Initial revision
This commit is contained in:
597
source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
Normal file
597
source/gameengine/GamePlayer/ghost/GPG_ghost.cpp
Normal file
@@ -0,0 +1,597 @@
|
||||
/**
|
||||
* $Id$
|
||||
*
|
||||
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version. The Blender
|
||||
* Foundation also sells licenses for use in proprietary software under
|
||||
* the Blender License. See http://www.blender.org/BL/ for information
|
||||
* about this.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*
|
||||
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
||||
* All rights reserved.
|
||||
*
|
||||
* The Original Code is: all of this file.
|
||||
*
|
||||
* Contributor(s): none yet.
|
||||
*
|
||||
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
||||
* Start up of the Blender Player on GHOST.
|
||||
*/
|
||||
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef __alpha__
|
||||
#include <signal.h>
|
||||
#endif /* __alpha__ */
|
||||
#endif /* __linux__ */
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Can't use Carbon right now because of double defined type ID (In Carbon.h and DNA_ID.h, sigh)
|
||||
//#include <Carbon/Carbon.h>
|
||||
//#include <CFBundle.h>
|
||||
#endif // __APPLE__
|
||||
#include "GEN_messaging.h"
|
||||
#include "KX_KetsjiEngine.h"
|
||||
|
||||
/**********************************
|
||||
* Begin Blender include block
|
||||
**********************************/
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif // __cplusplus
|
||||
|
||||
#include "BLI_blenlib.h"
|
||||
#include "DNA_scene_types.h"
|
||||
#include "BLO_readfile.h"
|
||||
|
||||
int GHOST_HACK_getFirstFile(char buf[]);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
/**********************************
|
||||
* End Blender include block
|
||||
**********************************/
|
||||
|
||||
#include "SYS_System.h"
|
||||
#include "GPG_Application.h"
|
||||
#include "GPC_PolygonMaterial.h"
|
||||
|
||||
#include "GHOST_ISystem.h"
|
||||
#include "RAS_IRasterizer.h"
|
||||
|
||||
#include "BKE_main.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#ifdef NDEBUG
|
||||
#include <windows.h>
|
||||
#include <wincon.h>
|
||||
#endif // NDEBUG
|
||||
#endif // WIN32
|
||||
|
||||
const int kMinWindowWidth = 100;
|
||||
const int kMinWindowHeight = 100;
|
||||
|
||||
void usage(char* program)
|
||||
{
|
||||
char * consoleoption;
|
||||
#ifdef _WIN32
|
||||
consoleoption = "-c ";
|
||||
#else
|
||||
consoleoption = "";
|
||||
#endif
|
||||
|
||||
printf("usage: %s [-p l t w h] [-f fw fh fb ff] %s[-g gamengineoptions] "
|
||||
"-s stereomode filename.blend\n", program, consoleoption);
|
||||
printf(" -p: specify window position\n");
|
||||
printf(" l = window left coordinate\n");
|
||||
printf(" t = window top coordinate\n");
|
||||
printf(" w = window width\n");
|
||||
printf(" h = window height\n");
|
||||
printf(" -f: start game in full screen mode\n");
|
||||
printf(" fw = full screen mode pixel width\n");
|
||||
printf(" fh = full screen mode pixel height\n");
|
||||
printf(" fb = full screen mode bits per pixel\n");
|
||||
printf(" ff = full screen mode frequency\n");
|
||||
printf(" -s: start player in stereo\n");
|
||||
printf(" stereomode = hwpageflip or syncdoubling depending on the type of stereo you want\n");
|
||||
#ifdef _WIN32
|
||||
printf(" -c: keep console window open\n");
|
||||
#endif
|
||||
printf("\n");
|
||||
printf("example: %s -p 10 10 320 200 -g noaudio c:\\loadtest.blend\n", program);
|
||||
}
|
||||
|
||||
char *get_filename(int argc, char **argv) {
|
||||
#ifdef __APPLE__
|
||||
/* On Mac we park the game file (called game.blend) in the application bundle.
|
||||
* The executable is located in the bundle as well.
|
||||
* Therefore, we can locate the game relative to the executable.
|
||||
*/
|
||||
int srclen = ::strlen(argv[0]);
|
||||
int len = 0;
|
||||
char *filename = NULL;
|
||||
|
||||
if (argc > 1) {
|
||||
if (BLI_exists(argv[argc-1])) {
|
||||
len = ::strlen(argv[argc-1]);
|
||||
filename = new char [len + 1];
|
||||
::strcpy(filename, argv[argc-1]);
|
||||
return(filename);
|
||||
}
|
||||
if (::strncmp(argv[argc-1], "-psn_", 5)==0) {
|
||||
static char firstfilebuf[512];
|
||||
if (GHOST_HACK_getFirstFile(firstfilebuf)) {
|
||||
len = ::strlen(firstfilebuf);
|
||||
filename = new char [len + 1];
|
||||
::strcpy(filename, firstfilebuf);
|
||||
return(filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
srclen -= ::strlen("MacOS/blenderplayer");
|
||||
if (srclen > 0) {
|
||||
len = srclen + ::strlen("Resources/game.blend");
|
||||
filename = new char [len + 1];
|
||||
::strcpy(filename, argv[0]);
|
||||
::strcpy(filename + srclen, "Resources/game.blend");
|
||||
//::printf("looking for file: %s\n", filename);
|
||||
|
||||
if (BLI_exists(filename)) {
|
||||
return (filename);
|
||||
}
|
||||
}
|
||||
|
||||
return(NULL);
|
||||
#else
|
||||
return (argc>1)?argv[argc-1]:NULL;
|
||||
#endif // !_APPLE
|
||||
}
|
||||
|
||||
BlendFileData *load_game_data(char *progname, char *filename) {
|
||||
BlendReadError error;
|
||||
BlendFileData *bfd;
|
||||
|
||||
/* try to load ourself, will only work if we are a runtime */
|
||||
bfd= BLO_read_from_file(progname, &error);
|
||||
|
||||
if (!bfd) {
|
||||
if (filename) {
|
||||
bfd= BLO_read_from_file(filename, &error);
|
||||
}
|
||||
}
|
||||
|
||||
if (bfd && bfd->type == BLENFILETYPE_BLEND) {
|
||||
BLO_blendfiledata_free(bfd);
|
||||
bfd = NULL;
|
||||
error = BRE_NOT_A_PUBFILE;
|
||||
}
|
||||
|
||||
if (!bfd) {
|
||||
if (filename) {
|
||||
printf("Loading %s failed: %s\n", filename, BLO_bre_as_string(error));
|
||||
}
|
||||
}
|
||||
|
||||
return bfd;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
int i;
|
||||
bool error = false;
|
||||
SYS_SystemHandle syshandle = SYS_GetSystem();
|
||||
bool fullScreen = false;
|
||||
bool fullScreenParFound = false;
|
||||
bool windowParFound = false;
|
||||
bool closeConsole = true;
|
||||
int stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
|
||||
bool stereoWindow = false;
|
||||
bool stereoParFound = false;
|
||||
int windowLeft = 100;
|
||||
int windowTop = 100;
|
||||
int windowWidth = 640;
|
||||
int windowHeight = 480;
|
||||
int fullScreenWidth = 640;
|
||||
int fullScreenHeight= 480;
|
||||
int fullScreenBpp = 16;
|
||||
int fullScreenFrequency = 60;
|
||||
|
||||
#ifdef __linux__
|
||||
#ifdef __alpha__
|
||||
signal (SIGFPE, SIG_IGN);
|
||||
#endif /* __alpha__ */
|
||||
#endif /* __linux__ */
|
||||
|
||||
#ifdef __APPLE__
|
||||
// Can't use Carbon right now because of double defined type ID (In Carbon.h and DNA_ID.h, sigh)
|
||||
/*
|
||||
IBNibRef nibRef;
|
||||
WindowRef window;
|
||||
OSStatus err;
|
||||
|
||||
// Create a Nib reference passing the name of the nib file (without the .nib extension)
|
||||
// CreateNibReference only searches into the application bundle.
|
||||
err = ::CreateNibReference(CFSTR("main"), &nibRef);
|
||||
if (err) return -1;
|
||||
|
||||
// Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar
|
||||
// object. This name is set in InterfaceBuilder when the nib is created.
|
||||
err = ::SetMenuBarFromNib(nibRef, CFSTR("MenuBar"));
|
||||
if (err) return -1;
|
||||
|
||||
// We don't need the nib reference anymore.
|
||||
::DisposeNibReference(nibRef);
|
||||
*/
|
||||
#endif // __APPLE__
|
||||
|
||||
GEN_init_messaging_system();
|
||||
|
||||
// Parse command line options
|
||||
#ifndef NDEBUG
|
||||
printf("argv[0] = '%s'\n", argv[0]);
|
||||
#endif
|
||||
for (i = 1; (i < argc) && !error; i++)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
printf("argv[%d] = '%s'\n", i, argv[i]);
|
||||
#endif
|
||||
|
||||
if (argv[i][0] == '-')
|
||||
{
|
||||
switch (argv[i][1])
|
||||
{
|
||||
case 'g':
|
||||
// Parse game options
|
||||
{
|
||||
i++;
|
||||
if (i < argc)
|
||||
{
|
||||
char* paramname = argv[i];
|
||||
// Check for single value versus assignment
|
||||
if (i+1 < argc && (*(argv[i+1]) == '='))
|
||||
{
|
||||
i++;
|
||||
if (i + 1 < argc)
|
||||
{
|
||||
i++;
|
||||
// Assignment
|
||||
SYS_WriteCommandLineString(syshandle, paramname, argv[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = true;
|
||||
printf("error: argument assignment %s without value.\n", paramname);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SYS_WriteCommandLineInt(syshandle, argv[i], 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'p':
|
||||
// Parse window position and size options
|
||||
if (argv[i][2] == 0) {
|
||||
i++;
|
||||
if ((i + 4) < argc)
|
||||
{
|
||||
windowLeft = atoi(argv[i++]);
|
||||
windowTop = atoi(argv[i++]);
|
||||
windowWidth = atoi(argv[i++]);
|
||||
windowHeight = atoi(argv[i]);
|
||||
windowParFound = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = true;
|
||||
printf("error: too few options for window argument.\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
// Parse window position and size options
|
||||
{
|
||||
fullScreen = true;
|
||||
i++;
|
||||
if ((i + 4) < argc)
|
||||
{
|
||||
fullScreenWidth = atoi(argv[i++]);
|
||||
fullScreenHeight = atoi(argv[i++]);
|
||||
fullScreenBpp = atoi(argv[i++]);
|
||||
fullScreenFrequency = atoi(argv[i]);
|
||||
fullScreenParFound = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = true;
|
||||
printf("error: too few options for fullscreen argument.\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
i++;
|
||||
closeConsole = false;
|
||||
break;
|
||||
case 's': // stereo
|
||||
i++;
|
||||
if ((i + 1) < argc)
|
||||
{
|
||||
if(!strcmp(argv[i], "nostereo")) // ok, redundant but clear
|
||||
stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
|
||||
|
||||
// only the hardware pageflip method needs a stereo window
|
||||
if(!strcmp(argv[i], "hwpageflip")) {
|
||||
stereomode = RAS_IRasterizer::RAS_STEREO_QUADBUFFERED;
|
||||
stereoWindow = true;
|
||||
}
|
||||
if(!strcmp(argv[i], "syncdoubling"))
|
||||
stereomode = RAS_IRasterizer::RAS_STEREO_ABOVEBELOW;
|
||||
#if 0
|
||||
// future stuff
|
||||
if(strcmp(argv[i], "stencil")
|
||||
stereomode = RAS_STEREO_STENCIL;
|
||||
#endif
|
||||
|
||||
i++;
|
||||
stereoParFound = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = true;
|
||||
printf("error: too few options for stereo argument.\n");
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
if ((windowWidth < kMinWindowWidth) || (windowHeight < kMinWindowHeight))
|
||||
{
|
||||
error = true;
|
||||
printf("error: window size too small.\n");
|
||||
}
|
||||
|
||||
if (error)
|
||||
{
|
||||
usage(argv[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
//SYS_WriteCommandLineInt(syshandle, "show_framerate", 1);
|
||||
SYS_WriteCommandLineInt(syshandle, "nomipmap", 1);
|
||||
//fullScreen = false; // Can't use full screen
|
||||
#endif
|
||||
if (SYS_GetCommandLineInt(syshandle, "nomipmap", 0))
|
||||
{
|
||||
GPC_PolygonMaterial::SetMipMappingEnabled(0);
|
||||
}
|
||||
|
||||
// Create the system
|
||||
if (GHOST_ISystem::createSystem() == GHOST_kSuccess)
|
||||
{
|
||||
GHOST_ISystem* system = GHOST_ISystem::getSystem();
|
||||
assertd(system);
|
||||
|
||||
// process first batch of events. If the user
|
||||
// drops a file on top off the blenderplayer icon, we
|
||||
// recieve an event with the filename
|
||||
|
||||
system->processEvents(0);
|
||||
|
||||
// this bracket is needed for app (see below) to get out
|
||||
// of scope before GHOST_ISystem::disposeSystem() is called.
|
||||
{
|
||||
int exitcode = KX_EXIT_REQUEST_NO_REQUEST;
|
||||
STR_String exitstring = "";
|
||||
GPG_Application app(system, NULL, exitstring);
|
||||
bool firstTimeRunning = true;
|
||||
|
||||
do
|
||||
{
|
||||
// Read the Blender file
|
||||
char *filename = get_filename(argc, argv);
|
||||
char *titlename;
|
||||
char pathname[160];
|
||||
BlendFileData *bfd;
|
||||
|
||||
// if we got an exitcode 3 (KX_EXIT_REQUEST_START_OTHER_GAME) load a different file
|
||||
if (exitcode == KX_EXIT_REQUEST_START_OTHER_GAME)
|
||||
{
|
||||
char basedpath[160];
|
||||
|
||||
// base the actuator filename with respect
|
||||
// to the original file working directory
|
||||
strcpy(basedpath, exitstring.Ptr());
|
||||
BLI_convertstringcode(basedpath, pathname, 0);
|
||||
|
||||
bfd = load_game_data(NULL, basedpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
bfd = load_game_data(argv[0], filename);
|
||||
}
|
||||
|
||||
//::printf("game data loaded from %s\n", filename);
|
||||
|
||||
if (!bfd) {
|
||||
usage(argv[0]);
|
||||
error = true;
|
||||
exitcode = KX_EXIT_REQUEST_QUIT_GAME;
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef WIN32
|
||||
#ifdef NDEBUG
|
||||
if (closeConsole)
|
||||
{
|
||||
::FreeConsole(); // Close a console window
|
||||
}
|
||||
#endif // NDEBUG
|
||||
#endif // WIN32
|
||||
Main *maggie = bfd->main;
|
||||
Scene *scene = bfd->curscene;
|
||||
strcpy (pathname, maggie->name);
|
||||
char *startscenename = scene->id.name + 2;
|
||||
|
||||
titlename = maggie->name;
|
||||
|
||||
// Check whether the game should be displayed full-screen
|
||||
if ((!fullScreenParFound) && (!windowParFound))
|
||||
{
|
||||
// Only use file settings when command line did not override
|
||||
if (scene->r.fullscreen) {
|
||||
//printf("fullscreen option found in Blender file\n");
|
||||
fullScreen = true;
|
||||
fullScreenWidth= scene->r.xplay;
|
||||
fullScreenHeight= scene->r.yplay;
|
||||
fullScreenFrequency= scene->r.freqplay;
|
||||
fullScreenBpp = scene->r.depth;
|
||||
}
|
||||
else
|
||||
{
|
||||
fullScreen = false;
|
||||
windowWidth = scene->r.xplay;
|
||||
windowHeight = scene->r.yplay;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Check whether the game should be displayed in stereo
|
||||
if (!stereoParFound)
|
||||
{
|
||||
if(scene->r.stereomode == RAS_IRasterizer::RAS_STEREO_NOSTEREO) // ok, redundant but clear
|
||||
stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
|
||||
|
||||
// only the hardware pageflip method needs a stereo window
|
||||
if(scene->r.stereomode == RAS_IRasterizer::RAS_STEREO_QUADBUFFERED) {
|
||||
stereomode = RAS_IRasterizer::RAS_STEREO_QUADBUFFERED;
|
||||
stereoWindow = true;
|
||||
}
|
||||
if(scene->r.stereomode == RAS_IRasterizer::RAS_STEREO_ABOVEBELOW)
|
||||
stereomode = RAS_IRasterizer::RAS_STEREO_ABOVEBELOW;
|
||||
#if 0
|
||||
// future stuff
|
||||
if(scene->r.stereomode == RAS_IRasterizer::RAS_STEREO_STENCIL)
|
||||
stereomode = RAS_STEREO_STENCIL;
|
||||
#endif
|
||||
}
|
||||
|
||||
// GPG_Application app (system, maggie, startscenename);
|
||||
app.SetGameEngineData(maggie, startscenename);
|
||||
|
||||
if (firstTimeRunning)
|
||||
{
|
||||
firstTimeRunning = false;
|
||||
|
||||
if (fullScreen)
|
||||
{
|
||||
app.startFullScreen(fullScreenWidth, fullScreenHeight, fullScreenBpp, fullScreenFrequency,
|
||||
stereoWindow, stereomode);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef __APPLE__
|
||||
// on Mac's we'll show the executable name instead of the 'game.blend' name
|
||||
char tempname[1024], *appstring;
|
||||
::strcpy(tempname, titlename);
|
||||
|
||||
appstring = strstr(tempname, ".app/");
|
||||
if (appstring) {
|
||||
appstring[2] = 0;
|
||||
titlename = &tempname[0];
|
||||
}
|
||||
#endif
|
||||
// Strip the path so that we have the name of the game file
|
||||
STR_String path = titlename;
|
||||
#ifndef WIN32
|
||||
vector<STR_String> parts = path.Explode('/');
|
||||
#else // WIN32
|
||||
vector<STR_String> parts = path.Explode('\\');
|
||||
#endif // WIN32
|
||||
STR_String title;
|
||||
if (parts.size())
|
||||
{
|
||||
title = parts[parts.size()-1];
|
||||
parts = title.Explode('.');
|
||||
if (parts.size() > 1)
|
||||
{
|
||||
title = parts[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
title = "blenderplayer";
|
||||
}
|
||||
app.startWindow(title, windowLeft, windowTop, windowWidth, windowHeight,
|
||||
stereoWindow, stereomode);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
app.StartGameEngine(stereomode);
|
||||
exitcode = KX_EXIT_REQUEST_NO_REQUEST;
|
||||
}
|
||||
|
||||
// Add the application as event consumer
|
||||
system->addEventConsumer(&app);
|
||||
|
||||
// Enter main loop
|
||||
bool run = true;
|
||||
while (run)
|
||||
{
|
||||
system->processEvents(true);
|
||||
system->dispatchEvents();
|
||||
if (exitcode = app.getExitRequested())
|
||||
{
|
||||
run = false;
|
||||
exitstring = app.getExitString();
|
||||
}
|
||||
}
|
||||
app.StopGameEngine();
|
||||
BLO_blendfiledata_free(bfd);
|
||||
|
||||
#ifdef __APPLE__
|
||||
if (filename) {
|
||||
delete [] filename;
|
||||
}
|
||||
#endif // __APPLE__
|
||||
}
|
||||
} while (exitcode == KX_EXIT_REQUEST_RESTART_GAME || exitcode == KX_EXIT_REQUEST_START_OTHER_GAME);
|
||||
}
|
||||
// Dispose the system
|
||||
GHOST_ISystem::disposeSystem();
|
||||
} else {
|
||||
error = true;
|
||||
printf("error: couldn't create a system.\n");
|
||||
}
|
||||
}
|
||||
|
||||
return error ? -1 : 0;
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user