SleepIsDeath/gameSource/gameNoMain.cpp

2261 lines
63 KiB
C++

/*
* Modification History
*
* 2008-September-11 Jason Rohrer
* Created. Copied from Cultivation.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
// let SDL override our main function with SDLMain
#include <SDL/SDL_main.h>
// must do this before SDL include to prevent WinMain linker errors on win32
int mainFunction( int inArgCount, char **inArgs );
int mainBLOCKED( int inArgCount, char **inArgs ) {
return mainFunction( inArgCount, inArgs );
}
#include <SDL/SDL.h>
#include "minorGems/graphics/openGL/ScreenGL.h"
#include "minorGems/graphics/openGL/SceneHandlerGL.h"
#include "minorGems/graphics/Color.h"
#include "minorGems/graphics/openGL/gui/GUIPanelGL.h"
#include "minorGems/graphics/openGL/gui/GUITranslatorGL.h"
#include "minorGems/graphics/openGL/gui/TextGL.h"
#include "minorGems/graphics/openGL/gui/LabelGL.h"
#include "minorGems/graphics/openGL/gui/TextFieldGL.h"
#include "minorGems/graphics/openGL/gui/SliderGL.h"
#include "minorGems/system/Time.h"
#include "minorGems/system/Thread.h"
#include "minorGems/io/file/File.h"
#include "minorGems/network/HostAddress.h"
#include "minorGems/network/upnp/portMapping.h"
#include "minorGems/util/SettingsManager.h"
#include "minorGems/util/TranslationManager.h"
#include "minorGems/util/stringUtils.h"
#include "minorGems/util/SimpleVector.h"
#include "minorGems/util/log/AppLog.h"
#include "minorGems/util/log/FileLog.h"
#include "common.h"
#include "HighlightLabelGL.h"
#include "Connection.h"
#include "GameHalf.h"
#include "PlayerGame.h"
#include "ControllerGame.h"
#include "musicPlayer.h"
#include "Song.h"
#include "DemoCodeChecker.h"
// from musicPlayer.cpp
extern char noteToggles[PARTS][S][N][N];
extern int partLengths[PARTS];
// some settings
// size of game image
int gameWidth = 320;
int gameHeight = 240;
// size of screen for fullscreen mode
int screenWidth = 640;
int screenHeight = 480;
char hardToQuitMode = false;
double musicTrackFadeLevel = 1.0;
char autoJoinMode = false;
char autoHostMode = false;
// ^ and & keys to slow down and speed up for testing
char enableSlowdownKeys = false;
//char enableSlowdownKeys = true;
// is demo mode on? If so, it checks server to see if it is still allowed
// to run.
char demoMode = false;
int demoCodeLength = 10;
DemoCodeChecker *codeChecker = NULL;
// track old code checkers so that we can destroy them after they unblock
SimpleVector<DemoCodeChecker *> oldCodeCheckers;
// these are shared by other modules as extern
Connection *connection = NULL;
TextGL *largeText = NULL;
TextGL *largeTextFixed = NULL;
char *addressString = NULL;
// should we try UPNP search (blocks) on next redraw?
char tryUPNP = false;
char tryUPNPClose = false;
char upnpPortOpen = false;
// track old clients so that we can destroy them after they unblock
SimpleVector<Connection *> oldConnections;
GameHalf *game = NULL;
char isControllerGame = false;
char loadingDrawnOnce = false;
class GameSceneHandler :
public SceneHandlerGL, public MouseHandlerGL, public KeyboardHandlerGL,
public RedrawListenerGL, public ActionListener {
public:
/**
* Constructs a sceen handler.
*
* @param inScreen the screen to interact with.
* Must be destroyed by caller after this class is destroyed.
*/
GameSceneHandler( ScreenGL *inScreen );
virtual ~GameSceneHandler();
/**
* Executes necessary init code that reads from files.
*
* Must be called before using a newly-constructed GameSceneHandler.
*
* This call assumes that the needed files are in the current working
* directory.
*/
void initFromFiles();
ScreenGL *mScreen;
// implements the SceneHandlerGL interface
virtual void drawScene();
// implements the MouseHandlerGL interface
virtual void mouseMoved( int inX, int inY );
virtual void mouseDragged( int inX, int inY );
virtual void mousePressed( int inX, int inY );
virtual void mouseReleased( int inX, int inY );
// implements the KeyboardHandlerGL interface
virtual char isFocused() {
// always focused
return true;
}
virtual void keyPressed( unsigned char inKey, int inX, int inY );
virtual void specialKeyPressed( int inKey, int inX, int inY );
virtual void keyReleased( unsigned char inKey, int inX, int inY );
virtual void specialKeyReleased( int inKey, int inX, int inY );
// implements the RedrawListener interface
virtual void fireRedraw();
// implements the ActionListener interface
virtual void actionPerformed( GUIComponent *inTarget );
protected:
// sets the string on a label and re-centers it
void setLabelString( LabelGL *inLabel,
char *inTranslationString,
double inScaleFactor = 1.0 );
// creates a centerd label at a particular height
HighlightLabelGL *createLabel( double inGuiY,
char *inTranslationString,
TextGL *inText = NULL );
// the time that the last frame was drawn
unsigned long mLastFrameSeconds;
unsigned long mLastFrameMilliseconds;
// our current frame rate
unsigned long mFrameMillisecondDelta;
int mStartTimeSeconds;
char mPaused;
double mMaxFrameRate;
char mPrintFrameRate;
unsigned long mNumFrames;
unsigned long mFrameBatchSize;
unsigned long mFrameBatchStartTimeSeconds;
unsigned long mFrameBatchStartTimeMilliseconds;
Color mBackgroundColor;
// for game selection display
char mGUIVisible;
GUIPanelGL *mMainPanel;
GUITranslatorGL *mMainPanelGuiTranslator;
TextGL *mTextGL;
TextGL *mTextGLFixedWidth;
GUIPanelGL *mCurrentPanel;
GUIPanelGL *mWriteFailedPanel;
HighlightLabelGL *mWriteFailedLabel;
GUIPanelGL *mDemoCodePanel;
HighlightLabelGL *mEnterDemoCodeLabel;
TextFieldGL *mEnterDemoCodeField;
GUIPanelGL *mTitlePanel;
HighlightLabelGL *mTitleLabel;
GUIPanelGL *mVolumePanel;
HighlightLabelGL *mVolumeLabel;
HighlightLabelGL *mVolumeDoneLabel;
SliderGL *mVolumeSlider;
// avoid abrupt volume changes that cause clicks
double mVolumeTarget;
GUIPanelGL *mSelectPanel;
HighlightLabelGL *mControlLocalLabel;
HighlightLabelGL *mControlRemoteLabel;
HighlightLabelGL *mJoinAsPlayerLabel;
// track as array to make toggling easier
HighlightLabelGL *mSelectLabels[3];
int mSelectHighlightIndex;
GUIPanelGL *mWaitPlayerPanel;
HighlightLabelGL *mWaitPlayerMessageLabel;
HighlightLabelGL *mWaitPlayerLabel;
HighlightLabelGL *mAddressLabel;
HighlightLabelGL *mDoNotWaitTipLabel;
GUIPanelGL *mUPNPPanel;
HighlightLabelGL *mUPNPLabel;
GUIPanelGL *mJoinControllerPanel;
HighlightLabelGL *mEnterAddressLabel;
TextFieldGL *mEnterAddressField;
GUIPanelGL *mLoadingPanel;
HighlightLabelGL *mLoadingLabel;
};
GameSceneHandler *sceneHandler;
ScreenGL *screen;
GUITranslatorGL *guiTranslator;
// how many pixels wide is each game pixel drawn as?
int pixelZoomFactor;
int maxAddressLength = 15;
// function that destroys object when exit is called.
// exit is the only way to stop the loop in ScreenGL
void cleanUpAtExit() {
AppLog::info( "exiting\n" );
if( game != NULL ) {
delete game;
}
delete sceneHandler;
delete screen;
if( codeChecker != NULL ) {
delete codeChecker;
}
for( int i=0; i<oldCodeCheckers.size(); i++ ) {
delete *( oldCodeCheckers.getElement( i ) );
}
if( connection != NULL ) {
delete connection;
}
for( int i=0; i<oldConnections.size(); i++ ) {
delete *( oldConnections.getElement( i ) );
}
if( addressString != NULL ) {
delete [] addressString;
}
stopMusic();
SDL_Quit();
}
#include "StringTree.h"
int mainFunction( int inNumArgs, char **inArgs ) {
/*
// test tree
StringTree *tree = new StringTree();
// use strings as values, too
char *apple = "apple";
tree->insert( "apple", (void*)apple );
//tree->insert( "dapper", (void*)"dapper" );
//tree->insert( "relapse", (void*)"relapse" );
tree->insert( "apron", (void*)"apron" );
char* aaron = "aaron";
tree->insert( "aaron", (void*)aaron );
tree->insert( "no", (void*)"no" );
tree->insert( "dodo", (void*)"dodo" );
tree->insert( "dodomanofdodo", (void*)"dodomanofdodo" );
tree->insert( "dad", (void*)"dad" );
tree->remove( "aaron", aaron );
tree->remove( "apple", apple );
char *searchString = "a";
int numMatches = tree->countMatches( searchString );
char **results = new char*[numMatches];
for( int j=0; j<numMatches; j++ ) {
printf( "Skipping %d gives:\n", j );
int numGotten = tree->getMatches( searchString, j, 2,
(void **)results );
for( int i=0; i<numGotten; i++ ) {
printf( "Test result: %s\n", results[i] );
}
}
delete [] results;
delete tree;
*/
// check result below, after opening log, so we can log failure
int sdlResult = SDL_Init( SDL_INIT_VIDEO | SDL_INIT_NOPARACHUTE );
// do this mac check after initing SDL,
// since it causes various Mac frameworks to be loaded (which can
// change the current working directory out from under us)
#ifdef __mac__
// make sure working directory is the same as the directory
// that the app resides in
// this is especially important on the mac platform, which
// doesn't set a proper working directory for double-clicked
// app bundles
// arg 0 is the path to the app executable
char *appDirectoryPath = stringDuplicate( inArgs[0] );
char *appNamePointer = strstr( appDirectoryPath,
"SleepIsDeath.app" );
if( appNamePointer != NULL ) {
// terminate full app path to get parent directory
appNamePointer[0] = '\0';
chdir( appDirectoryPath );
}
delete [] appDirectoryPath;
#endif
AppLog::setLog( new FileLog( "log.txt" ) );
AppLog::setLoggingLevel( Log::DETAIL_LEVEL );
AppLog::info( "New game starting up" );
if( sdlResult < 0 ) {
AppLog::getLog()->logPrintf(
Log::CRITICAL_ERROR_LEVEL,
"Couldn't initialize SDL: %s\n", SDL_GetError() );
return 0;
}
// read screen size from settings
char widthFound = false;
int readWidth = SettingsManager::getIntSetting( "screenWidth",
&widthFound );
char heightFound = false;
int readHeight = SettingsManager::getIntSetting( "screenHeight",
&heightFound );
if( widthFound && heightFound ) {
// override hard-coded defaults
screenWidth = readWidth;
screenHeight = readHeight;
}
AppLog::getLog()->logPrintf(
Log::INFO_LEVEL,
"Screen dimensions for fullscreen mode: %dx%d\n",
screenWidth, screenHeight );
char fullscreenFound = false;
int readFullscreen = SettingsManager::getIntSetting( "fullscreen",
&fullscreenFound );
char fullscreen = true;
if( readFullscreen == 0 ) {
fullscreen = false;
}
screen =
new ScreenGL( screenWidth, screenHeight, fullscreen,
"SleepIsDeath", NULL, NULL, NULL );
// may change if specified resolution is not supported
screenWidth = screen->getWidth();
screenHeight = screen->getHeight();
SDL_EnableKeyRepeat( SDL_DEFAULT_REPEAT_DELAY,
SDL_DEFAULT_REPEAT_INTERVAL );
pixelZoomFactor = screenWidth / gameWidth;
if( pixelZoomFactor * gameHeight > screenHeight ) {
// screen too short
pixelZoomFactor = screenHeight / gameHeight;
}
screen->setImageSize( pixelZoomFactor * gameWidth,
pixelZoomFactor * gameHeight );
//SDL_ShowCursor( SDL_DISABLE );
sceneHandler = new GameSceneHandler( screen );
// also do file-dependent part of init for GameSceneHandler here
// actually, constructor is file dependent anyway.
sceneHandler->initFromFiles();
// hard to quit mode?
char hardToQuitFound = false;
int readHardToQuit = SettingsManager::getIntSetting( "hardToQuitMode",
&hardToQuitFound );
if( readHardToQuit == 1 ) {
hardToQuitMode = true;
}
// auto-join mode?
char autoJoinFound = false;
int readAutoJoin = SettingsManager::getIntSetting( "autoJoin",
&autoJoinFound );
if( readAutoJoin == 1 ) {
autoJoinMode = true;
}
// auto-host mode?
char autoHostFound = false;
int readAutoHost = SettingsManager::getIntSetting( "autoHost",
&autoHostFound );
if( readAutoHost == 1 ) {
autoHostMode = true;
}
if( autoJoinMode && autoHostMode ) {
// only allow one
AppLog::info(
"Both autoJoin and autoHost set... defaulting to neither" );
autoJoinMode = false;
autoHostMode = false;
}
setMusicLoudness( 0.5 );
startMusic();
// register cleanup function, since screen->start() will never return
atexit( cleanUpAtExit );
screen->switchTo2DMode();
//glLineWidth( pixelZoomFactor );
screen->start();
return 0;
}
GameSceneHandler::GameSceneHandler( ScreenGL *inScreen )
: mScreen( inScreen ),
mFrameMillisecondDelta( 0 ),
mStartTimeSeconds( time( NULL ) ),
mPaused( false ),
mMaxFrameRate( 30 ),
mPrintFrameRate( false ),
mNumFrames( 0 ), mFrameBatchSize( 100 ),
mFrameBatchStartTimeSeconds( time( NULL ) ),
mFrameBatchStartTimeMilliseconds( 0 ),
mBackgroundColor( 0, 0, 0, 1 ) {
mVolumeTarget = 0.5;
glClearColor( mBackgroundColor.r,
mBackgroundColor.g,
mBackgroundColor.b,
mBackgroundColor.a );
// set external pointer so it can be used in calls below
sceneHandler = this;
mScreen->addMouseHandler( this );
mScreen->addKeyboardHandler( this );
mScreen->addSceneHandler( this );
mScreen->addRedrawListener( this );
Time::getCurrentTime( &mLastFrameSeconds, &mLastFrameMilliseconds );
// set up main UI
mMainPanel = new GUIPanelGL( 0, 0, gameWidth, gameWidth,
new Color( 0,
0,
0, 1.0 ) );
mMainPanelGuiTranslator = new GUITranslatorGL( mMainPanel, mScreen,
gameWidth );
guiTranslator = mMainPanelGuiTranslator;
mScreen->addSceneHandler( mMainPanelGuiTranslator );
mScreen->addKeyboardHandler( mMainPanelGuiTranslator );
mScreen->addMouseHandler( mMainPanelGuiTranslator );
mGUIVisible = true;
// construct sub-panels, but only add the first one
mWriteFailedPanel = new GUIPanelGL( 0, 0, gameWidth, gameWidth,
new Color( 0,
0,
0, 1.0 ) );
mDemoCodePanel = new GUIPanelGL( 0, 0, gameWidth, gameWidth,
new Color( 0,
0,
0, 1.0 ) );
mTitlePanel = new GUIPanelGL( 0, 0, gameWidth, gameWidth,
new Color( 0,
0,
0, 1.0 ) );
mVolumePanel = new GUIPanelGL( 0, 0, gameWidth, gameWidth,
new Color( 0,
0,
0, 1.0 ) );
mSelectPanel = new GUIPanelGL( 0, 0, gameWidth, gameWidth,
new Color( 0,
0,
0, 1.0 ) );
mWaitPlayerPanel = new GUIPanelGL( 0, 0, gameWidth, gameWidth,
new Color( 0,
0,
0, 1.0 ) );
mUPNPPanel = new GUIPanelGL( 0, 0, gameWidth, gameWidth,
new Color( 0,
0,
0, 1.0 ) );
mJoinControllerPanel = new GUIPanelGL( 0, 0, gameWidth, gameWidth,
new Color( 0,
0,
0, 1.0 ) );
mLoadingPanel = new GUIPanelGL( 0, 0, gameWidth, gameWidth,
new Color( 0,
0,
0, 1.0 ) );
// make sure we can write to our main folder
FILE *testFile = fopen( "testWrite.txt", "w" );
if( testFile == NULL ) {
// failed
mMainPanel->add( mWriteFailedPanel );
mCurrentPanel = mWriteFailedPanel;
}
else {
fclose( testFile );
remove( "testWrite.txt" );
if( demoMode ) {
mMainPanel->add( mDemoCodePanel );
mCurrentPanel = mDemoCodePanel;
}
else {
mMainPanel->add( mTitlePanel );
mCurrentPanel = mTitlePanel;
}
}
}
GameSceneHandler::~GameSceneHandler() {
mScreen->removeMouseHandler( this );
mScreen->removeSceneHandler( this );
mScreen->removeRedrawListener( this );
// remove before deleting, since we're not sure which one is still
// added
mMainPanel->remove( mWriteFailedPanel );
mMainPanel->remove( mDemoCodePanel );
mMainPanel->remove( mTitlePanel );
mMainPanel->remove( mVolumePanel );
mMainPanel->remove( mSelectPanel );
mMainPanel->remove( mWaitPlayerPanel );
mMainPanel->remove( mUPNPPanel );
mMainPanel->remove( mJoinControllerPanel );
mMainPanel->remove( mLoadingPanel );
delete mWriteFailedPanel;
delete mDemoCodePanel;
delete mTitlePanel;
delete mVolumePanel;
delete mSelectPanel;
delete mWaitPlayerPanel;
delete mUPNPPanel;
delete mJoinControllerPanel;
delete mLoadingPanel;
// this will recursively delete all of our selector GUI components
delete mMainPanelGuiTranslator;
delete mTextGL;
delete mTextGLFixedWidth;
}
void GameSceneHandler::setLabelString( LabelGL *inLabel,
char *inTranslationString,
double inScaleFactor ) {
char *labelString =
(char *)TranslationManager::translate( (char*)inTranslationString );
inLabel->setText( labelString );
TextGL *text = inLabel->getTextGL();
// 1:1 aspect ratio
// we know font is 8 pixels wide/tall
double height = inScaleFactor * 8;
double width = height * strlen( labelString );
double actualDrawWidth =
height * text->measureTextWidth( labelString );
/*
// round to an integer number of pixels
actualDrawWidth =
round( actualDrawWidth * screenImageWidth )
/
screenImageWidth;
*/
double centerW = gameWidth / 2;
//0.5 * (double)( mScreen->getImageWidth() ) / screenImageHeight;
double guiY = inLabel->getAnchorY();
double labelX = centerW - 0.5 * actualDrawWidth;
/*
// round to an integer number of pixels
labelX =
round( labelX * screenImageWidth )
/
screenImageWidth;
guiY =
round( guiY * screenImageWidth )
/
screenImageWidth;
*/
inLabel->setPosition( labelX,
guiY,
width,
height );
}
HighlightLabelGL *GameSceneHandler::createLabel( double inGuiY,
char *inTranslationString,
TextGL *inText ) {
if( inText == NULL ) {
inText = mTextGL;
}
HighlightLabelGL *returnLabel =
new HighlightLabelGL( 0, inGuiY, 0, 0, "", inText );
setLabelString( returnLabel, inTranslationString );
return returnLabel;
}
void GameSceneHandler::initFromFiles() {
// translation language
File languageNameFile( NULL, "language.txt" );
if( languageNameFile.exists() ) {
char *languageNameText = languageNameFile.readFileContents();
SimpleVector<char *> *tokens = tokenizeString( languageNameText );
int numTokens = tokens->size();
// first token is name
if( numTokens > 0 ) {
char *languageName = *( tokens->getElement( 0 ) );
TranslationManager::setLanguage( languageName );
}
else {
// default
// TranslationManager already defaults to English, but
// it looks for the language files at runtime before we have set
// the current working directory.
// Thus, we specify the default again here so that it looks
// for its language files again.
TranslationManager::setLanguage( "English" );
}
delete [] languageNameText;
for( int t=0; t<numTokens; t++ ) {
delete [] *( tokens->getElement( t ) );
}
delete tokens;
}
// load text font
Image *fontImage = readTGA( "font8.tga" );
if( fontImage == NULL ) {
// default
// blank font
fontImage = new Image( 256, 256, 4, true );
}
mTextGL = new TextGL( fontImage,
// use alpha
true,
// variable character width
false,
// extra space around each character, one pixel
0.125,
// space is 4 pixels wide (out of 8)
0.5 );
largeText = mTextGL;
mTextGLFixedWidth = new TextGL( fontImage,
// use alpha
true,
// fixed character width
true,
// extra space around each character
0,
// space is full char width
1.0 );
largeTextFixed = mTextGLFixedWidth;
delete fontImage;
// now build gui panels based on labels, which depend on textGL
mWriteFailedLabel = createLabel( 160, "writeFailed" );
// increase scale
setLabelString( mWriteFailedLabel, "writeFailed" );
mWriteFailedPanel->add( mWriteFailedLabel );
mEnterDemoCodeLabel = createLabel( 175, "enterDemoCode" );
mDemoCodePanel->add( mEnterDemoCodeLabel );
// 1:1 aspect ratio
// we know font is 8 pixels wide/tall
double height = 8;
double width = height * demoCodeLength;
double centerW = gameWidth / 2;
char *defaultCode =
SettingsManager::getStringSetting( "demoCode" );
char *fieldDefault = "";
if( defaultCode != NULL ) {
fieldDefault = defaultCode;
}
mEnterDemoCodeField = new TextFieldGL( centerW - 0.5 * width,
145,
width,
height,
1,
fieldDefault,
mTextGLFixedWidth,
new Color( 0.75, 0.75, 0.75 ),
new Color( 0.75, 0.75, 0.75 ),
new Color( 0.15, 0.15, 0.15 ),
new Color( 0.75, 0.75, 0.75 ),
demoCodeLength,
true );
mDemoCodePanel->add( mEnterDemoCodeField );
if( demoMode ) {
mEnterDemoCodeField->setEnabled( true );
mEnterDemoCodeField->setFocus( true );
mEnterDemoCodeField->lockFocus( true );
}
if( defaultCode != NULL ) {
mEnterDemoCodeField->setCursorPosition( strlen( defaultCode ) );
if( demoMode ) {
// don't destroy this
char *enteredCode = mEnterDemoCodeField->getText();
if( strlen( enteredCode ) > 0 ) {
// run with this code
// disable further input
mEnterDemoCodeField->setEnabled( false );
mEnterDemoCodeField->setFocus( false );
mEnterDemoCodeField->lockFocus( false );
setLabelString( mEnterDemoCodeLabel,
"checkingCode" );
// start
codeChecker = new DemoCodeChecker( enteredCode );
}
}
delete [] defaultCode;
}
mTitleLabel = createLabel( 160, "title" );
// increase scale
setLabelString( mTitleLabel, "title" );
mTitlePanel->add( mTitleLabel );
mVolumeLabel = createLabel( 160, "volume" );
// increase scale
setLabelString( mVolumeLabel, "volume" );
mVolumePanel->add( mVolumeLabel );
mVolumeDoneLabel = createLabel( 48, "volumeDone" );
// increase scale
setLabelString( mVolumeDoneLabel, "volumeDone" );
mVolumePanel->add( mVolumeDoneLabel );
Color thumbColor( .5, .5, .5, .5 );
Color borderColor( .35, .35, .35, .35 );
mVolumeSlider = new SliderGL( 160 - 24, 104,
48, 12,
NULL, 0,
new Color( 0, 0, 0, 1 ),
new Color( 1, 0.5, 0, 1 ),
thumbColor.copy(),
borderColor.copy(),
1, 4, 1 );
mVolumePanel->add( mVolumeSlider );
// volume starts in middle
// avoid round-off errors
mVolumeSlider->setThumbPosition( (int)(0.5 * 96) / 96.0 );
mVolumeSlider->addActionListener( this );
mSelectLabels[0] =
mControlLocalLabel = createLabel( 190, "control_local" );
mSelectLabels[1] =
mControlRemoteLabel = createLabel( 160, "control_remote" );
mSelectLabels[2] =
mJoinAsPlayerLabel = createLabel( 130, "joinAsPlayer" );
mSelectPanel->add( mControlLocalLabel );
mSelectPanel->add( mControlRemoteLabel );
mSelectPanel->add( mJoinAsPlayerLabel );
mSelectLabels[0]->setHighlight( true );
mSelectHighlightIndex = 0;
mWaitPlayerMessageLabel = createLabel( 205, "" );
mWaitPlayerLabel = createLabel( 175, "waitingForPlayer" );
HostAddress *local = HostAddress::getNumericalLocalAddress();
if( local != NULL ) {
addressString = stringDuplicate( local->mAddressString );
delete local;
}
else {
addressString = stringDuplicate( "???.???.???.???" );
}
mAddressLabel = createLabel( 145, addressString,
mTextGLFixedWidth );
mDoNotWaitTipLabel = createLabel( 115, "doNotWaitTip" );
mWaitPlayerPanel->add( mWaitPlayerMessageLabel );
mWaitPlayerPanel->add( mWaitPlayerLabel );
mWaitPlayerPanel->add( mAddressLabel );
mWaitPlayerPanel->add( mDoNotWaitTipLabel );
mUPNPLabel = createLabel( 160, "upnpTrying" );
mUPNPPanel->add( mUPNPLabel );
mEnterAddressLabel = createLabel( 175, "enterAddress" );
mJoinControllerPanel->add( mEnterAddressLabel );
mLoadingLabel = createLabel( 160, "loading" );
mLoadingPanel->add( mLoadingLabel );
// 1:1 aspect ratio
// we know font is 8 pixels wide/tall
height = 8;
width = height * maxAddressLength;
centerW = gameWidth / 2;
char *defaultAddress =
SettingsManager::getStringSetting( "defaultServerAddress" );
fieldDefault = "";
if( defaultAddress != NULL ) {
fieldDefault = defaultAddress;
}
mEnterAddressField = new TextFieldGL( centerW - 0.5 * width,
145,
width,
height,
1,
fieldDefault,
mTextGLFixedWidth,
new Color( 0.75, 0.75, 0.75 ),
new Color( 0.75, 0.75, 0.75 ),
new Color( 0.15, 0.15, 0.15 ),
new Color( 0.75, 0.75, 0.75 ),
maxAddressLength,
true );
mEnterAddressField->setCursorPosition( strlen( fieldDefault ) );
mJoinControllerPanel->add( mEnterAddressField );
if( defaultAddress != NULL ) {
delete [] defaultAddress;
}
}
void GameSceneHandler::drawScene() {
/*
glClearColor( mBackgroundColor->r,
mBackgroundColor->g,
mBackgroundColor->b,
mBackgroundColor->a );
*/
glDisable( GL_TEXTURE_2D );
glDisable( GL_CULL_FACE );
glDisable( GL_DEPTH_TEST );
/*
// sky
glColor4d( 0.75, 0.75, 0.75, 1.0 );
glBegin( GL_QUADS ); {
glVertex2d( -1, 1 );
glVertex2d( 1, 1 );
glVertex2d( 1, -1 );
glVertex2d( -1, -1 );
}
glEnd();
*/
}
void GameSceneHandler::mouseMoved( int inX, int inY ) {
}
void GameSceneHandler::mouseDragged( int inX, int inY ) {
}
void GameSceneHandler::mousePressed( int inX, int inY ) {
}
void GameSceneHandler::mouseReleased( int inX, int inY ) {
// actually, WHY do we let people mouse-click from title?
// rest of menu system is all keyboard-driven
// this sets up a false expectation that the mouse will do something
// in the menus
/*
if( mGUIVisible ) {
if( mMainPanel->contains( mTitlePanel ) ) {
mMainPanel->remove( mCurrentPanel );
mMainPanel->add( mVolumePanel );
mCurrentPanel = mVolumePanel;
// test sounds on
for( int i=0; i<N; i++ ) {
noteToggles[i][i] = true;
}
restartMusic();
}
return;
}
*/
}
void GameSceneHandler::fireRedraw() {
if( mPaused ) {
// ignore redraw event
// sleep to avoid wasting CPU cycles
Thread::staticSleep( 1000 );
// also ignore time that passes while paused
Time::getCurrentTime( &mLastFrameSeconds, &mLastFrameMilliseconds );
return;
}
// deal with frame timing issues
unsigned long lastMillisecondDelta = mFrameMillisecondDelta;
// how many milliseconds have passed since the last frame
mFrameMillisecondDelta =
Time::getMillisecondsSince( mLastFrameSeconds,
mLastFrameMilliseconds );
// lock down to mMaxFrameRate frames per second
unsigned long minFrameTime = (unsigned long)( 1000 / mMaxFrameRate );
if( mFrameMillisecondDelta < minFrameTime ) {
unsigned long timeToSleep = minFrameTime - mFrameMillisecondDelta;
Thread::staticSleep( timeToSleep );
// get new frame second delta, including sleep time
mFrameMillisecondDelta =
Time::getMillisecondsSince( mLastFrameSeconds,
mLastFrameMilliseconds );
}
// avoid huge position "jumps" if we have a very large delay during a frame
// (possibly caused by something going on in the background)
// This will favor a slight visual slow down, but this is better than
// a disorienting jump
// skip this check if we are just starting up
if( lastMillisecondDelta != 0 ) {
if( mFrameMillisecondDelta > 6 * lastMillisecondDelta ) {
// limit: this frame represents at most twice the jump of the last
// frame
// printf( "Limiting time jump (requested=%lu ms, last=%lu ms)\n",
// mFrameMillisecondDelta, lastMillisecondDelta );
if( mFrameMillisecondDelta > 10000 ) {
AppLog::warning(
"Time between frames more than 10 seconds:\n" );
// way too big... investigate
AppLog::getLog()->logPrintf(
Log::WARNING_LEVEL,
"Last time = %lu s, %lu ms\n",
mLastFrameSeconds, mLastFrameMilliseconds );
Time::getCurrentTime( &mLastFrameSeconds,
&mLastFrameMilliseconds );
AppLog::getLog()->logPrintf(
Log::WARNING_LEVEL,
"current time = %lu s, %lu ms\n",
mLastFrameSeconds, mLastFrameMilliseconds );
}
mFrameMillisecondDelta = 2 * lastMillisecondDelta;
}
}
// record the time that this frame was drawn
Time::getCurrentTime( &mLastFrameSeconds, &mLastFrameMilliseconds );
// for use with non-constant time-per-frame
// this game is constant time-per-frame
// double frameSecondsDelta = (double)mFrameMillisecondDelta / 1000.0;
mNumFrames ++;
if( mPrintFrameRate ) {
if( mNumFrames % mFrameBatchSize == 0 ) {
// finished a batch
unsigned long timeDelta =
Time::getMillisecondsSince( mFrameBatchStartTimeSeconds,
mFrameBatchStartTimeMilliseconds );
double frameRate =
1000 * (double)mFrameBatchSize / (double)timeDelta;
AppLog::getLog()->logPrintf(
Log::DETAIL_LEVEL,
"Frame rate = %f frames/second\n", frameRate );
mFrameBatchStartTimeSeconds = mLastFrameSeconds;
mFrameBatchStartTimeMilliseconds = mLastFrameMilliseconds;
}
}
// process old connections to clear pending ops and destroy them
for( int i=0; i<oldConnections.size(); i++ ) {
Connection *c = *( oldConnections.getElement( i ) );
if( c->step() == false ) {
// done
AppLog::info( "Destroying old connection.\n" );
delete c;
oldConnections.deleteElement( i );
i--;
}
}
// should we start a game?
if( mMainPanel->contains( mLoadingPanel ) ) {
if( loadingDrawnOnce ) {
// loading panel drawn at least once
if( isControllerGame ) {
game = new ControllerGame( mScreen );
}
else {
// back to default sounds (in case we're Player in a
// v13 game)
setDefaultMusicSounds();
game = new PlayerGame( mScreen );
isControllerGame = false;
}
if( mGUIVisible ) {
// hide menu gui to start the game
mMainPanel->remove( mCurrentPanel );
mCurrentPanel = NULL;
mScreen->removeSceneHandler( mMainPanelGuiTranslator );
mScreen->removeKeyboardHandler( mMainPanelGuiTranslator );
mScreen->removeMouseHandler( mMainPanelGuiTranslator );
mGUIVisible = false;
// add game handlers instead
mScreen->addSceneHandler( game );
mScreen->addKeyboardHandler( game );
mScreen->addMouseHandler( game );
mScreen->addRedrawListener( game );
game->setScreen( screen );
}
}
else {
loadingDrawnOnce = true;
}
}
if( connection != NULL ) {
if( ! connection->isError() ) {
char workLeft = connection->step();
if( connection->isConnected() && game == NULL ) {
if( mMainPanel->contains( mJoinControllerPanel ) ) {
mMainPanel->remove( mJoinControllerPanel );
mMainPanel->add( mLoadingPanel );
mCurrentPanel = mLoadingPanel;
loadingDrawnOnce = false;
isControllerGame = false;
}
else if( mMainPanel->contains( mWaitPlayerPanel ) ) {
mMainPanel->remove( mWaitPlayerPanel );
mMainPanel->add( mLoadingPanel );
mCurrentPanel = mLoadingPanel;
loadingDrawnOnce = false;
isControllerGame = true;
}
// we construct the game outside the check for a connection
// (based on presence of loading panel) so that same
// construction code can be used even if player hits G
// to start w/out a connection
/*
if( mMainPanel->contains( mJoinControllerPanel ) ) {
// got connection as player
// back to default sounds (in case we're Player in a
// v13 game)
setDefaultMusicSounds();
game = new PlayerGame( mScreen );
isControllerGame = false;
}
else if( mMainPanel->contains( mWaitPlayerPanel ) ) {
// got connection as controller
game = new ControllerGame( mScreen );
isControllerGame = true;
}
*/
// if connected, keep stepping until no network work left
while( workLeft ) {
workLeft = connection->step();
}
}
}
else {
AppLog::getLog()->logPrintf(
Log::INFO_LEVEL,
"Connection failed: %s\n", connection->getErrorString() );
oldConnections.push_back( connection );
connection = NULL;
if( mMainPanel->contains( mJoinControllerPanel ) ) {
// re-enable input
mEnterAddressField->setEnabled( true );
mEnterAddressField->setFocus( true );
mEnterAddressField->lockFocus( true );
setLabelString( mEnterAddressLabel,
"joiningFailed" );
}
}
}
else {
// no connection... is a Controller game already running?
if( game != NULL && isControllerGame ) {
// are any old connections (which might block hosting on port)
// still waiting to be destroyed?
if( oldConnections.size() == 0 ) {
// clear to start a new one
AppLog::info(
"Trying to receive a new Player connection...\n" );
// start a server
connection = new Connection();
game->resetTimer();
}
}
}
// process old codeCheckers to clear pending ops and destroy them
for( int i=0; i<oldCodeCheckers.size(); i++ ) {
DemoCodeChecker *c = *( oldCodeCheckers.getElement( i ) );
if( c->step() == false ) {
// done
AppLog::info( "Destroying old codeChecker.\n" );
delete c;
oldCodeCheckers.deleteElement( i );
i--;
}
}
if( codeChecker != NULL ) {
if( codeChecker->isError() ) {
if( mMainPanel->contains( mDemoCodePanel ) ) {
// re-enable input
mEnterDemoCodeField->setEnabled( true );
mEnterDemoCodeField->setFocus( true );
mEnterDemoCodeField->lockFocus( true );
char *message = codeChecker->getErrorString();
setLabelString( mEnterDemoCodeLabel, message );
}
oldCodeCheckers.push_back( codeChecker );
codeChecker = NULL;
}
else {
char checkerWorkLeft = codeChecker->step();
if( ! checkerWorkLeft
&& ! codeChecker->isError()
&& codeChecker->codePermitted() ) {
// will have error if not permitted, which is handled above
oldCodeCheckers.push_back( codeChecker );
codeChecker = NULL;
if( mMainPanel->contains( mDemoCodePanel ) ) {
// move on to title
mMainPanel->remove( mCurrentPanel );
mMainPanel->add( mTitlePanel );
mCurrentPanel = mTitlePanel;
}
}
}
}
if( game != NULL ) {
game->step();
if( game->isQuitting() ) {
// back out and restore menu gui
if( !mGUIVisible ) {
mScreen->addSceneHandler( mMainPanelGuiTranslator );
mScreen->addKeyboardHandler( mMainPanelGuiTranslator );
mScreen->addMouseHandler( mMainPanelGuiTranslator );
mGUIVisible = true;
mScreen->removeSceneHandler( game );
mScreen->removeKeyboardHandler( game );
mScreen->removeMouseHandler( game );
mScreen->removeRedrawListener( game );
}
delete game;
game = NULL;
if( connection != NULL ) {
oldConnections.push_back( connection );
connection = NULL;
}
// clear music
for( int si=0; si<PARTS; si++ ) {
for( int s=0; s<S; s++ ) {
for( int i=0; i<N; i++ ) {
for( int j=0; j<N; j++ ) {
noteToggles[si][s][i][j] = false;
}
}
}
}
if( !upnpPortOpen ) {
// right back to game selection menu
mMainPanel->add( mSelectPanel );
mCurrentPanel = mSelectPanel;
}
else {
// close UPNP port first
mMainPanel->add( mUPNPPanel );
mCurrentPanel = mUPNPPanel;
setLabelString( mUPNPLabel, "upnpCloseTrying" );
// wait for it to draw once before blocking
tryUPNPClose = false;
}
}
}
// gradually adjust loudness toward target to avoid clicks
double trueVolume = getMusicLoudness();
if( mVolumeTarget != trueVolume ) {
double newTrueVolume = trueVolume;
if( mVolumeTarget > trueVolume ) {
newTrueVolume += 0.06;
if( newTrueVolume > mVolumeTarget ) {
newTrueVolume = mVolumeTarget;
}
}
if( mVolumeTarget < trueVolume ) {
newTrueVolume -= 0.06;
if( newTrueVolume < mVolumeTarget ) {
newTrueVolume = mVolumeTarget;
}
}
setMusicLoudness( newTrueVolume );
}
// handle auto-starts here
if( autoHostMode && ! mMainPanel->contains( mWaitPlayerPanel ) ) {
// done, don't re-trigger if player backs out of it
autoHostMode = false;
mEnterAddressField->setFocus( false );
mEnterAddressField->lockFocus( false );
mEnterAddressField->setEnabled( false );
setLabelString( mWaitPlayerLabel, "waitingForPlayer" );
// start as server
connection = new Connection();
mMainPanel->remove( mCurrentPanel );
mMainPanel->add( mWaitPlayerPanel );
mCurrentPanel = mWaitPlayerPanel;
}
if( autoJoinMode && ! mMainPanel->contains( mJoinControllerPanel ) ) {
// done, don't re-trigger if player backs out of it
autoJoinMode = false;
char *enteredAddress = mEnterAddressField->getText();
if( strlen( enteredAddress ) > 0 ) {
// disable further input
mEnterAddressField->setFocus( false );
mEnterAddressField->lockFocus( false );
mEnterAddressField->setEnabled( false );
setLabelString( mEnterAddressLabel,
"joiningController" );
// start as client
connection = new Connection( enteredAddress );
mMainPanel->remove( mCurrentPanel );
mMainPanel->add( mJoinControllerPanel );
mCurrentPanel = mJoinControllerPanel;
}
}
if( mMainPanel->contains( mUPNPPanel ) && !tryUPNP && !upnpPortOpen ) {
// try blocking op on next frame, so that panel can draw at least once
tryUPNP = true;
}
else if( tryUPNP ) {
tryUPNP = false;
char *externalIP;
int result = mapPort( Connection::getPort(), "Sleep Is Death",
2000,
&externalIP );
if( result == 1 ) {
upnpPortOpen = true;
if( externalIP != NULL ) {
setLabelString( mAddressLabel, externalIP );
delete [] addressString;
addressString = externalIP;
}
}
mMainPanel->remove( mCurrentPanel );
mMainPanel->add( mWaitPlayerPanel );
mCurrentPanel = mWaitPlayerPanel;
mEnterAddressField->setFocus( false );
mEnterAddressField->lockFocus( false );
mEnterAddressField->setEnabled( false );
setLabelString( mWaitPlayerLabel, "waitingForPlayer" );
// start as server
connection = new Connection();
if( result == 1 ) {
setLabelString( mWaitPlayerMessageLabel, "upnpSuccess" );
}
else {
setLabelString( mWaitPlayerMessageLabel, "upnpFailure" );
}
}
if( mMainPanel->contains( mUPNPPanel ) && upnpPortOpen && !tryUPNPClose ) {
// try blocking op on next frame, so that panel can draw at least once
tryUPNPClose = true;
}
else if( tryUPNPClose ) {
tryUPNPClose = false;
int result = unmapPort( Connection::getPort(), 2000 );
if( result == 1 ) {
upnpPortOpen = false;
}
if( game == NULL ) {
// not in the middle of a game, back out to select panel
mMainPanel->remove( mCurrentPanel );
mMainPanel->add( mSelectPanel );
mCurrentPanel = mSelectPanel;
// back to local address
HostAddress *local = HostAddress::getNumericalLocalAddress();
if( local != NULL ) {
delete [] addressString;
addressString = stringDuplicate( local->mAddressString );
setLabelString( mAddressLabel, addressString );
delete local;
}
}
else {
// quitting, but we just closed the UPNP port first
exit( 0 );
}
}
}
static unsigned char lastKeyPressed = '\0';
void GameSceneHandler::keyPressed(
unsigned char inKey, int inX, int inY ) {
if( enableSlowdownKeys ) {
if( inKey == '^' ) {
// slow
mMaxFrameRate = 2;
}
if( inKey == '&' ) {
// normal
mMaxFrameRate = 30;
}
}
if( mGUIVisible ) {
if( mMainPanel->contains( mTitlePanel ) ||
mMainPanel->contains( mVolumePanel ) ) {
if( !hardToQuitMode ) {
// q or escape
if( inKey == 'q' || inKey == 'Q' || inKey == 27 ) {
exit( 0 );
}
}
else {
// # followed by ESC
if( lastKeyPressed == '#' && inKey == 27 ) {
exit( 0 );
}
lastKeyPressed = inKey;
}
if( inKey != 'q' && inKey != 'Q' && inKey != 27 && inKey != '#' ) {
// any other key advances to next screen
if( mMainPanel->contains( mTitlePanel ) ) {
mMainPanel->remove( mCurrentPanel );
mMainPanel->add( mVolumePanel );
mCurrentPanel = mVolumePanel;
// test sounds on
// emulate old 1-grid test run (rising tones)
for( int i=0; i<N-1; i++ ) {
noteToggles[i/5][0][i%5][i] = true;
}
// last note at top
noteToggles[2][0][5][15] = true;
partLengths[0] = 1;
partLengths[1] = 1;
partLengths[2] = 1;
restartMusic();
}
else if( mMainPanel->contains( mVolumePanel ) ) {
mMainPanel->remove( mCurrentPanel );
mMainPanel->add( mSelectPanel );
mCurrentPanel = mSelectPanel;
// test sounds off
for( int i=0; i<N-1; i++ ) {
noteToggles[i/5][0][i%5][i] = false;
}
noteToggles[2][0][5][15] = false;
partLengths[0] = 0;
partLengths[1] = 0;
partLengths[2] = 0;
}
}
}
else if( mMainPanel->contains( mSelectPanel ) ) {
if( !hardToQuitMode ) {
// q or escape
if( inKey == 'q' || inKey == 'Q' || inKey == 27 ) {
exit( 0 );
}
}
else {
// # followed by ESC
if( lastKeyPressed == '#' && inKey == 27 ) {
exit( 0 );
}
lastKeyPressed = inKey;
}
if( inKey != 'q' && inKey != 'Q' && inKey != 27 && inKey != '#' ) {
// any other key press triggers selection
GUIPanelGL *panelToShow = NULL;
switch( mSelectHighlightIndex ) {
case 0:
panelToShow = mWaitPlayerPanel;
mEnterAddressField->setFocus( false );
mEnterAddressField->lockFocus( false );
mEnterAddressField->setEnabled( false );
setLabelString( mWaitPlayerLabel, "waitingForPlayer" );
setLabelString( mWaitPlayerMessageLabel, "" );
// start as server
connection = new Connection();
break;
case 1:
mEnterAddressField->setFocus( false );
mEnterAddressField->lockFocus( false );
mEnterAddressField->setEnabled( false );
if( upnpPortOpen ) {
// already open, maybe from failed close before?
panelToShow = mWaitPlayerPanel;
setLabelString( mWaitPlayerLabel,
"waitingForPlayer" );
setLabelString( mWaitPlayerMessageLabel, "" );
// start as server
connection = new Connection();
}
else {
// open it
panelToShow = mUPNPPanel;
setLabelString( mUPNPLabel, "upnpTrying" );
// wait until panel draws at least once
tryUPNP = false;
}
break;
case 2:
panelToShow = mJoinControllerPanel;
setLabelString( mEnterAddressLabel, "enterAddress" );
mEnterAddressField->setFocus( true );
mEnterAddressField->lockFocus( true );
mEnterAddressField->setEnabled( true );
// don't pass this key press through to field
mEnterAddressField->ignoreNextKey();
break;
}
if( panelToShow != NULL ) {
mMainPanel->remove( mSelectPanel );
mMainPanel->add( panelToShow );
mCurrentPanel = panelToShow;
}
}
}
else {
if( mMainPanel->contains( mWriteFailedPanel ) ) {
if( inKey == 'q' || inKey == 'Q' || inKey == 27 ) {
// q or escape
exit( 0 );
}
}
if( mMainPanel->contains( mDemoCodePanel ) ) {
// look for enter
if( inKey == 13 && mEnterDemoCodeField->isFocused() ) {
// don't destroy this
char *enteredCode = mEnterDemoCodeField->getText();
if( strlen( enteredCode ) > 0 ) {
// disable further input
mEnterDemoCodeField->setEnabled( false );
mEnterDemoCodeField->setFocus( false );
mEnterDemoCodeField->lockFocus( false );
setLabelString( mEnterDemoCodeLabel,
"checkingCode" );
// save this for next time
SettingsManager::setSetting( "demoCode",
enteredCode );
// start
codeChecker = new DemoCodeChecker( enteredCode );
}
}
else if( inKey == 'q' || inKey == 'Q' || inKey == 27 ) {
// q or escape
exit( 0 );
}
}
if( mMainPanel->contains( mJoinControllerPanel ) ) {
// look for enter
if( inKey == 13 && mEnterAddressField->isFocused() ) {
// don't destroy this
char *enteredAddress = mEnterAddressField->getText();
if( strlen( enteredAddress ) > 0 ) {
// disable further input
mEnterAddressField->setFocus( false );
mEnterAddressField->lockFocus( false );
mEnterAddressField->setEnabled( false );
setLabelString( mEnterAddressLabel,
"joiningController" );
// start as client
connection = new Connection( enteredAddress );
}
}
}
if( mMainPanel->contains( mWaitPlayerPanel ) ) {
// look for "g" to go ahaead
if( inKey == 'g' || inKey == 'G' ) {
mMainPanel->remove( mCurrentPanel );
mMainPanel->add( mLoadingPanel );
mCurrentPanel = mLoadingPanel;
isControllerGame = true;
loadingDrawnOnce = false;
/*
game = new ControllerGame( mScreen );
isControllerGame = true;
// hide menu gui to start the game
mMainPanel->remove( mCurrentPanel );
mCurrentPanel = NULL;
mScreen->removeSceneHandler( mMainPanelGuiTranslator );
mScreen->removeKeyboardHandler( mMainPanelGuiTranslator );
mGUIVisible = false;
// add game handlers instead
mScreen->addSceneHandler( game );
mScreen->addKeyboardHandler( game );
mScreen->addMouseHandler( game );
mScreen->addRedrawListener( game );
game->setScreen( screen );
*/
}
}
// q or escape pressed in any sub-panel
if( inKey == 'q' || inKey == 'Q' || inKey == 27 ) {
// back up
// wait for this connection to finish before destroying it
if( connection != NULL ) {
oldConnections.push_back( connection );
connection = NULL;
}
mMainPanel->remove( mCurrentPanel );
if( upnpPortOpen && mCurrentPanel == mWaitPlayerPanel ) {
// close upnp port first
AppLog::info( "Setting upnp panel\n" );
mMainPanel->add( mUPNPPanel );
mCurrentPanel = mUPNPPanel;
setLabelString( mUPNPLabel, "upnpCloseTrying" );
// show upnp panel at least once before blocking
tryUPNPClose = false;
}
else {
mMainPanel->add( mSelectPanel );
mCurrentPanel = mSelectPanel;
}
}
}
}
/*
// q or escape
if( inKey == 'q' || inKey == 'Q' || inKey == 27 ) {
if( !showingQuitQuestion ) {
oldStatusText = stringDuplicate( mStatusLabel->getText() );
showingQuitQuestion = true;
setLabelString( mStatusLabel, "quitQuestion" );
}
}
// answer to quit question?
else if( showingQuitQuestion && ( inKey == 'y' || inKey == 'Y' ) ) {
delete [] oldStatusText;
oldStatusText = NULL;
exit( 0 );
}
else if( showingQuitQuestion && ( inKey == 'n' || inKey == 'N' ) ) {
setLabelString( mStatusLabel, oldStatusText );
delete [] oldStatusText;
oldStatusText = NULL;
showingQuitQuestion = false;
}
*/
}
void GameSceneHandler::keyReleased(
unsigned char inKey, int inX, int inY ) {
}
void GameSceneHandler::specialKeyPressed(
int inKey, int inX, int inY ) {
/*
// keep key states for later, whether we act on them now or not
switch( inKey ) {
case MG_KEY_LEFT:
mLeftKeyDown = true;
break;
case MG_KEY_RIGHT:
mRightKeyDown = true;
break;
}
*/
switch( inKey ) {
case MG_KEY_UP:
if( mGUIVisible &&
mMainPanel->contains( mSelectPanel ) ) {
mSelectLabels[ mSelectHighlightIndex ]->setHighlight( false );
mSelectHighlightIndex --;
if( mSelectHighlightIndex < 0 ) {
mSelectHighlightIndex = 2;
}
mSelectLabels[ mSelectHighlightIndex ]->setHighlight( true );
}
break;
case MG_KEY_DOWN:
if( mGUIVisible &&
mMainPanel->contains( mSelectPanel ) ) {
mSelectLabels[ mSelectHighlightIndex ]->setHighlight( false );
mSelectHighlightIndex ++;
if( mSelectHighlightIndex > 2 ) {
mSelectHighlightIndex = 0;
}
mSelectLabels[ mSelectHighlightIndex ]->setHighlight( true );
}
break;
}
}
void GameSceneHandler::specialKeyReleased(
int inKey, int inX, int inY ) {
/*
// keep key states for later, whether we act on them now or not
switch( inKey ) {
case MG_KEY_LEFT:
mLeftKeyDown = false;
break;
case MG_KEY_RIGHT:
mRightKeyDown = false;
break;
}
*/
}
void GameSceneHandler::actionPerformed( GUIComponent *inTarget ) {
if( inTarget == mVolumeSlider ) {
mVolumeTarget = mVolumeSlider->getThumbPosition();
}
}