123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797 |
- /*
- Copyright (C) 2009-2011 id Software LLC, a ZeniMax Media company.
- Copyright (C) 2009 Id Software, Inc.
-
- 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.
-
- 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.
-
- */
- #include "../doomiphone.h"
- playState_t playState;
- #define OWNER_AUTOMAP (void *)0x123
- int iphoneFrameNum;
- int levelLoadFrameNum;
- boolean iphoneTimeDemo;
- char timeDemoResultString[80];
- int timeDemoFrames;
- int timeDemoStart;
- // set to 1 when app is exiting to cause game thread to do a save game,
- // which would not be safe to do from the event thread
- volatile int saveOnExitState;
- // console mode
- int consoleActive;
- // current touches latched from the system touches
- int numTouches;
- int touches[5][2]; // [0] = x, [1] = y in landscape mode, raster order with y = 0 at top
- // so we can detect button releases
- int numPrevTouches;
- int prevTouches[5][2];
- float tilt; // -1.0 to 1.0
- float tiltPitch;
- #define MAX_TILT_HISTORY 64
- float tiltHistory[MAX_TILT_HISTORY][4];
- int tiltHistoryNum;
- // pressing on the weapon brings up the weaponSelect overlay
- boolean drawWeaponSelect;
- int weaponSelected = -1;
- pkTexture_t *arialFontTexture;
- logTime_t loggedTimes[MAX_LOGGED_TIMES]; // indexed by iphoneFrameNum
- int gameSocket;
- int gameID;
- int playerID;
- int packetSequence; // for logging dropped packets and estimating latency
- netFail_t netGameFailure; // set by asyncThread
- netPlayer_t netPlayers[MAXPLAYERS];
- netPeer_t netServer;
- sem_t * ticSemaphore;
- // set after each game tic if a usable line is in front of the player
- boolean autoUseActive;
- boolean respawnActive;
- // if we haven't processed a game tic in a half second, draw the net problem icon
- int lastGameProcessedTime;
- // this flag lets us give a shotgun and some ammo after the player has respawned
- boolean addGear;
- extern bool inBackgroundProcess;
- /*
- =================================================================================
-
- Touch Handling
-
- With multiple draggable controls on screen, it is important to track touches
- as continuous events, rather than discrete points, because we want to allow
- a finger to start on a dragable control, but still function when it has
- been dragged outside the original hot area, and not trigger anything else
- as it wanders around.
-
- I considered a Down / Dragged / Released interface, but especially with
- threading, it was better to keep them as a set of structures that could
- be looked at at different points in the game loop.
-
- if touch goes down on a dragable control, it will be owned by that control until it
- is released, even if it is dragged outside the original bounds.
-
- If we support pinch for anything, a single control will own multiple touches.
-
- Touches that aren't owned by a dragable control are free-roaming, and can hit buttons.
-
- =================================================================================
- */
- /*
-
- Does not claim ownership or play any sounds.
- The touch can be dragged in if it isn't owned by
- another control.
-
- */
- touch_t *TouchInBounds( int x, int y, int w, int h ) {
- for ( int i = 0 ; i < MAX_TOUCHES ; i++ ) {
- touch_t *t = &gameTouches[i];
- if ( t->controlOwner ) {
- continue; // already claimed
- }
- if ( !t->down ) {
- continue; // not pressed
- }
- if ( t->x >= x && t->x < x + w
- && t->y >= y && t->y < y + h ) {
- return t;
- }
- }
- return NULL;
- }
- // even a touch claimed by another control will count (fire button)
- touch_t *AnyTouchInBounds( int x, int y, int w, int h ) {
- for ( int i = 0 ; i < MAX_TOUCHES ; i++ ) {
- touch_t *t = &gameTouches[i];
- if ( !t->down ) {
- continue; // not pressed
- }
- if ( t->x >= x && t->x < x + w
- && t->y >= y && t->y < y + h ) {
- return t;
- }
- }
- return NULL;
- }
- touch_t *UpdateHudTouch( ibutton_t *hud ) {
- if ( hud->buttonFlags & ( BF_IGNORE | BF_HUDBUTTON ) ) {
- // hud element isn't active
- return NULL;
- }
-
- if ( !hud->touch ) {
- // see if a free touch was just made in, or dragged into the bounds
- // make the active boxes twice as large as the drawing bounds
- int x = hud->x - ( hud->drawWidth >> 1 );
- int y = hud->y - ( hud->drawHeight >> 1 );
- int w = hud->drawWidth << 1;
- int h = hud->drawHeight << 1;
-
- hud->touch = TouchInBounds( x, y, w, h );
- if ( hud->touch ) {
- // claim this touch so it won't activate anything else
- hud->touch->controlOwner = hud;
- if ( touchClick->value ) {
- Sound_StartLocalSoundAtVolume( "iphone/controller_down_01_SILENCE.wav", touchClick->value );
- }
- // save the initial touch position for auto-centering stcks
- hud->downX = hud->touch->x;
- hud->downY = hud->touch->y;
-
- // Clamp it so that you are guaranteed to have a full range of motion.
- // This means that a touch at the edge of the screen won't center it,
- // but will instead cause immediate movement. This prevents the main
- // drawback of the centering controls -- if you pressed down too close
- // to the side, you wouldn't have full mobility that direction.
- int w = hud->drawWidth / 2;
- int h = hud->drawHeight / 2;
- if ( hud->downX < w ) {
- hud->downX = w;
- }
- if ( hud->downX + w > displaywidth ) {
- hud->downX = displaywidth - w;
- }
- if ( hud->downY < h ) {
- hud->downY = h;
- }
- if ( hud->downY > displayheight - h ) {
- hud->downY = displayheight - h;
- }
- }
- }
-
- if ( hud->touch ) {
- // see if the touch was released
- if ( !hud->touch->down ) {
- if ( touchClick->value ) {
- Sound_StartLocalSoundAtVolume( "iphone/controller_up_01_SILENCE.wav", touchClick->value );
- }
- hud->touch = NULL;
- }
- }
- return hud->touch;
- }
- void SetButtonPics( ibutton_t *button, const char *picBase, const char *title, int x, int y ) {
- button->texture = PK_FindTexture( picBase );
- button->scale = 1.0f;
- button->title = title;
- button->x = x * ((float)displaywidth) / 480.0f;
- button->y = y * ((float)displayheight) / 320.0f;
-
- float xRatio = ((float)displaywidth) / 480.0f;
- float yRatio = ((float)displayheight) / 320.0f;
-
- float themin = MIN( xRatio, yRatio );
-
- button->drawWidth = button->texture->textureData->srcWidth * themin;
- button->drawHeight = button->texture->textureData->srcHeight * themin;
- }
- void SetButtonPicsAndSizes( ibutton_t *button, const char *picBase, const char *title, int x, int y, int w, int h ) {
- SetButtonPics( button, picBase, title, x, y );
-
-
- float xRatio = ((float)displaywidth) / 480.0f;
- float yRatio = ((float)displayheight) / 320.0f;
-
- float themin = MIN( xRatio, yRatio );
-
- button->drawWidth = w * themin;
- button->drawHeight = h * themin;
- }
- /*
- ==================
- HandleButton
-
- Plays enter / exit / action sounds, returns true if the
- touch was released inside the bounds.
-
- Touches can slide onto a button, they aren't required
- to tap initially inside it.
-
- Main menu buttons and the small in-game buttons are
- done with this. Because these handle both drawing and
- decision making, there is a frame of latency involved
- versus splitting the decision making and drawing.
-
- Returns true if the button should perform its action.
- ==================
- */
- float buttonScaleStep = 0.01f;
- float buttonScaleMin = 0.95f;
- boolean HandleButton( ibutton_t *button ) {
- if ( button->buttonFlags & BF_IGNORE ) {
- return false;
- }
-
-
- // Hack
- button->drawHeight = button->drawWidth;
-
- if ( ( button->buttonFlags & BF_TRANSPARENT ) && !button->touch ) {
- // draw half-transparent
- glColor4f( 1, 1, 1, 0.5 );
- } else if ( button->buttonFlags & BF_DIMMED ) {
- // draw half-bright
- glColor4f( 0.5, 0.5, 0.5, 1 );
- } else {
- glColor4f( 1, 1, 1, 1 );
- }
-
- if ( button->touch && !button->touch->down ) {
- button->touch->controlOwner = NULL;
- button->touch = NULL;
- }
-
- bool released = false;
- if ( !(button->buttonFlags & BF_INACTIVE) ) {
- if ( button->touch ) {
- // see if the touch was dragged outside the button bounds
- if ( button->touch->x < button->x || button->touch->x >= button->x + button->drawWidth
- || button->touch->y < button->y || button->touch->y >= button->y + button->drawHeight ) {
- // dragged outside, don't trigger on release now
- if ( button->buttonFlags & BF_SMALL_CLICK ) {
- Sound_StartLocalSoundAtVolume( "iphone/controller_up_01_SILENCE.wav", touchClick->value );
- } else {
- Sound_StartLocalSound( "iphone/baborted_01.wav" );
- }
- button->touch->controlOwner = NULL;
- button->touch = NULL;
- button->pressed = false;
- }
- }
- if ( !button->touch ) {
- if ( button->pressed ) {
- // released inside the button, so do the action
- if ( button->buttonFlags & BF_SMALL_CLICK ) {
- Sound_StartLocalSoundAtVolume( "iphone/controller_up_01_SILENCE.wav", touchClick->value );
- } else {
- Sound_StartLocalSound( "iphone/baction_01.wav" );
- }
- button->pressed = false;
- released = true;
- }
- }
-
- // see if a new touch went down or moved into the button
- if ( !released && !button->touch ) {
- button->twoFingerPress = false;
-
- for ( int i = 0 ; i < MAX_TOUCHES ; i++ ) {
- touch_t *t = &gameTouches[i];
- if ( t->controlOwner ) {
- continue; // already claimed
- }
- if ( !t->down ) {
- continue;
- }
- if ( t->x >= button->x && t->x < button->x + button->drawWidth
- && t->y >= button->y && t->y < button->y + button->drawHeight ) {
- if ( button->buttonFlags & BF_SMALL_CLICK ) {
- Sound_StartLocalSoundAtVolume( "iphone/controller_down_01_SILENCE.wav", touchClick->value );
- } else {
- Sound_StartLocalSound( "iphone/bdown_01.wav" );
- }
- button->touch = t;
- button->pressed = true;
- t->controlOwner = &button;
- break;
- }
- }
- }
- }
-
- // animate scale
- if ( button->frameNum != iphoneFrameNum - 1 ) {
- button->scale = 1.0f; // just came back to a menu
- }
- button->frameNum = iphoneFrameNum;
-
- if ( button->touch && button->touch->down ) {
- // check for a two-finger touch for alternate modes
- for ( int i = 0 ; i < MAX_TOUCHES ; i++ ) {
- touch_t *t = &gameTouches[i];
- if ( t->controlOwner ) {
- continue; // already claimed
- }
- if ( t == button->touch ) {
- continue; // the primary touch
- }
- if ( !t->down ) {
- continue;
- }
- if ( t->x >= button->x && t->x < button->x + button->drawWidth
- && t->y >= button->y && t->y < button->y + button->drawHeight ) {
- button->twoFingerPress = true;
- break;
- }
- }
-
- // adjust the animated scale
- button->scale -= buttonScaleStep;
- if ( button->scale < buttonScaleMin ) {
- button->scale = buttonScaleMin;
- }
- } else {
- button->scale += buttonScaleStep;
- if ( button->scale > 1.0f ) {
- button->scale = 1.0f;
- }
- }
-
- if ( button->buttonFlags & BF_GLOW ) {
- // cycle through double-bright
- float f = 0.75 + 0.25 * sin( 3.14159 * 2 * ( iphoneFrameNum & 31 ) / 32.0 );
-
- glColor4f( f, f, f, 1 );
- glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE );
- glTexEnvf( GL_TEXTURE_ENV, GL_RGB_SCALE, 2.0 );
- }
- PK_StretchTexture( button->texture, button->x+button->drawWidth/2 - button->drawWidth/2 * button->scale,
- button->y + button->drawHeight/2 - button->drawHeight/2 * button->scale,
- button->drawWidth * button->scale, button->drawHeight * button->scale );
- if ( button->buttonFlags & BF_GLOW ) {
- glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
- glColor4f( 1, 1, 1, 1 );
- }
-
- if ( button->title ) {
- float length = StringFontWidth( button->title ) * 0.75;
- float x = button->x + button->drawWidth/2 - length/2;
- // don't push the text off the edge of the screen
- if ( x < 0 ) {
- x = 0;
- } else if ( x + length > displaywidth ) {
- x = displaywidth - length;
- }
- float y;
- float textScale = 0.75;
- if ( button->buttonFlags & BF_CENTERTEXT ) {
- glColor4f( 1, 1, 1, 1 ); // !@# remove when we get a button background that doesn't need dimming
- y = button->y + button->drawHeight / 2 + 8;
- textScale *= button->scale; // animate text scale when centered
- } else {
- y = button->y + button->drawHeight + 16;
- }
- iphoneDrawText( x, y, textScale, button->title );
- }
-
- glColor4f( 1, 1, 1, 1 );
-
- return released;
- }
- //=========================================================================
- typedef struct {
- unsigned short x0, y0, x1, y1;
- float xoff, yoff, xadvance;
- } GlyphRect;
- #include "arialGlyphRects.h" // precalculated offsets in the font image
- float StringFontWidth( const char *str ) {
- float len = 0;
- while ( *str ) {
- int i = *str;
- if ( i >= ' ' && i < 128 ) {
- len += glyphRects[i-32].xadvance;
- }
- str++;
- }
- return len;
- }
- /*
- ==================
- iphoneDrawText
-
- Returns the width in pixels
- ==================
- */
- float iphoneDrawText( float x, float y, float scale, const char *str ) {
-
- float fx = x;
- float fy = y;
- PK_BindTexture( arialFontTexture );
- glBegin( GL_QUADS );
-
- while ( *str ) {
- int i = *str;
- if ( i >= ' ' && i < 128 ) {
- GlyphRect *glyph = &glyphRects[i-32];
-
- // the glyphRects don't include the shadow outline
- float x0 = ( glyph->x0 - 1 ) / 256.0;
- float y0 = ( glyph->y0 - 1 ) / 256.0;
- float x1 = ( glyph->x1 + 2 ) / 256.0;
- float y1 = ( glyph->y1 + 2 ) / 256.0;
-
- float width = ( x1 - x0 ) * 256 * scale;
- float height = ( y1 - y0 ) * 256 * scale;
-
- float xoff = ( glyph->xoff - 1 ) * scale;
- float yoff = ( glyph->yoff - 1 ) * scale;
-
- glTexCoord2f( x0, y0 );
- glVertex2f( fx + xoff, fy + yoff );
-
- glTexCoord2f( x1, y0 );
- glVertex2f( fx + xoff + width, fy + yoff );
-
- glTexCoord2f( x1, y1 );
- glVertex2f( fx + xoff + width, fy + yoff + height );
-
- glTexCoord2f( x0, y1 );
- glVertex2f( fx + xoff, fy + yoff + height );
- // with our default texture, the difference is negligable
- fx += glyph->xadvance * scale;
- // fx += ceil(glyph->xadvance); // with the outline, ceil is probably the right thing
- }
- str++;
- }
-
- glEnd();
-
- return fx - x;
- }
- /*
- ==================
- iphoneCenterText
-
- Returns the width in pixels
- ==================
- */
- float iphoneCenterText( float x, float y, float scale, const char *str ) {
- float l = StringFontWidth( str );
-
- x *= ((float)displaywidth) / 480.0f;
- y *= ((float)displayheight) / 320.0f;
-
- x -= l * scale * 0.5;
-
- return iphoneDrawText( x, y, scale, str );
- }
- /*
- ==================
- TouchDown
-
- Checks all touches against a square
- ==================
- */
- int TouchDown( int x, int y, int w, int h ) {
- int i;
- for ( i = 0 ; i < numTouches ; i++ ) {
- if ( touches[i][0] >= x && touches[i][1] >= y
- && touches[i][0] < x + w && touches[i][1] < y + h ) {
- return 1;
- }
- }
- return 0;
- }
- /*
- ==================
- TouchPressed
-
- Requires that the touch be inside the bounds, and that it didn't seem to be
- dragged in from out of the bounds in the previous frame.
- ==================
- */
- int TouchPressed( int x, int y, int w, int h ) {
-
- x *= ((float)displaywidth) / 480.0f;
- y *= ((float)displayheight) / 320.0f;
- w *= ((float)displaywidth) / 480.0f;
- h *= ((float)displayheight) / 320.0f;
-
- for ( int i = 0 ; i < MAX_TOUCHES ; i++ ) {
- touch_t *t = &gameTouches[i];
- if ( !t->down ) {
- continue;
- }
- if ( t->controlOwner ) {
- continue;
- }
- if ( t->stateCount != 1 ) {
- // not just pressed
- continue;
- }
-
- if ( t->x < x || t->x >= x + w
- || t->y < y || t->y >= y + h ) {
- continue;
- }
- // just pressed this frame
- return 1;
- }
- return 0;
- }
- /*
- ==================
- TouchReleased
-
- Perform an action when released in the box.
- If not down this frame, but down the previous frame, it is released
- ==================
- */
- int TouchReleased( int x, int y, int w, int h ) {
- #if 0
- // only check when the touch count just went down by one
- if ( numTouches != numPrevTouches - 1 ) {
- return 0;
- }
- int i;
- int downPrev = 0;
- int downNow = 0;
-
- for ( i = 0 ; i < numPrevTouches ; i++ ) {
- if ( prevTouches[i][0] >= x && prevTouches[i][1] >= y
- && prevTouches[i][0] < x + w && prevTouches[i][1] < y + h ) {
- downPrev = 1;
- break;
- }
- }
-
- // see if not down this frame
- for ( i = 0 ; i < numTouches ; i++ ) {
- if ( touches[i][0] >= x && touches[i][1] >= y
- && touches[i][0] < x + w && touches[i][1] < y + h ) {
- downNow = 1;
- break;
- }
- }
-
- if ( !downPrev ) {
- if ( downNow ) {
- Sound_StartLocalSound( "iphone/bdown_01.wav" );
- }
- // wasn't down the previous frame
- return 0;
- }
-
- if ( downNow ) {
- // still down
- return 0;
- }
-
- if ( numTouches == numPrevTouches ) {
- // finger dragged off
- Sound_StartLocalSound( "iphone/baborted_01.wav" );
- return 0;
- }
-
- // released
- Sound_StartLocalSound( "iphone/baction_01.wav" );
- return 1;
- #else
- for ( int i = 0 ; i < MAX_TOUCHES ; i++ ) {
- touch_t *t = &gameTouches[i];
- if ( t->down ) {
- continue; // still pressed
- }
- if ( t->x >= x && t->x < x + w
- && t->y >= y && t->y < y + h ) {
- if ( t->stateCount <= 1 ) {
- // just released
- Sound_StartLocalSound( "iphone/baction_01.wav" );
- return 1;
- }
- }
- }
- return 0;
- #endif
- }
- /*
- ==================
- iphoneRotateForLandscape
-
- ==================
- */
- int iphoneRotateForLandscape() {
- if ( revLand->value ) {
- // reverse landscape mode
- glRotatef( -90, 0, 0, 1 );
- return true;
- } else {
- glRotatef( 90, 0, 0, 1 );
- }
- return false;
- }
- /*
- ==================
- iphoneSet2D
-
- ==================
- */
- void iphoneSet2D( void ) {
- // note that GL thinks the iphone is always
- // in portrait mode as far as the framebuffer
- // is concerned.
- glViewport( 0,0, displayheight, displaywidth );
- glMatrixMode( GL_MODELVIEW );
- glLoadIdentity();
- glEnable( GL_TEXTURE_2D );
- glDisable( GL_DEPTH_TEST );
- glDisable( GL_SCISSOR_TEST );
- glDisable( GL_FOG );
- glDisable( GL_CULL_FACE );
- glEnable( GL_BLEND );
- glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
- glDisable( GL_ALPHA_TEST );
- glColor4f( 1,1,1,1 );
- glMatrixMode( GL_PROJECTION );
- glLoadIdentity();
- // now get into the landscape we want
- iphoneRotateForLandscape();
- glOrthof( 0, displaywidth, displayheight, 0, -99999, 99999 );
- }
- void iphoneCheckForLandscapeReverse() {
- static int reverseCount;
-
- // if we stay significantly negative for half a second, flip orientation
- if ( tiltPitch < -0.35 ) {
- if ( ++reverseCount > 10 ) {
- Cvar_SetValue( revLand->name, !revLand->value );
- SysIPhoneSetUIKitOrientation( revLand->value );
- }
- } else {
- reverseCount = 0;
- }
- }
- void iphoneTiltEvent( float *tilts ) {
- int i;
- int j;
- int c;
- float sum[3];
- static float prevTime;
- // we probably should mutex this, but I doubt it causes any problems
-
- if ( revLand->value ) {
- tilts[1] = -tilts[1];
- tilts[0] = -tilts[0];
- }
- c = tiltAverages->value;
- if ( c < 1 ) {
- c = 1;
- } else if ( c > MAX_TILT_HISTORY ) {
- c = MAX_TILT_HISTORY;
- }
-
- // acc[0] - [2] are accelerometer values, ax[3] is the timestamp
- for ( i = 0 ; i < 3 ; i++ ) {
- tiltHistory[tiltHistoryNum&(MAX_TILT_HISTORY-1)][i] = tilts[i];
- sum[i] = 0;
- for ( j = 0 ; j < c ; j++ ) {
- sum[i] += tiltHistory[(tiltHistoryNum-j)&(MAX_TILT_HISTORY-1)][i];
- }
- sum[i] /= c;
- }
- // save the timestamp for analysis and tap detection
- tiltHistory[tiltHistoryNum&(MAX_TILT_HISTORY-1)][3] = tilts[3] - prevTime;
- prevTime = tilts[3];
- tiltHistoryNum++;
-
- tilt = sum[1];
- tiltPitch = sum[0];
- // Com_Printf( "%4.2f %4.2f %4.2f\n", tilts[0], tilts[1], tilts[2] );
- }
- void ShowTilt() {
- int i;
- int axis = (int)showTilt->value - 1;
- color4_t fillColor = { 255, 0, 0, 255 };
- color4_t whiteColor = { 255, 255, 255, 255 };
- color4_t nowColor = { 0, 255, 0, 255 };
- float x;
-
- if ( axis < 0 || axis > 2 ) {
- return;
- }
- for ( i = 0 ; i < MAX_TILT_HISTORY ; i++ ) {
- x = tiltHistory[(tiltHistoryNum-1-i)&(MAX_TILT_HISTORY-1)][axis] * ( 10 / 0.018168604 );
- if ( x < 0 ) {
- R_Draw_Fill( 240 + x, i*4, -x, 4, fillColor );
- } else if ( x > 0 ) {
- R_Draw_Fill( 240, i*4, x, 4, fillColor );
- }
- }
- x = tilt * ( 10 / 0.018168604 );
- if ( x < 0 ) {
- R_Draw_Fill( 240 + x, i*4, -x, 4, nowColor );
- } else if ( x > 0 ) {
- R_Draw_Fill( 240, i*4, x, 4, nowColor );
- }
- R_Draw_Fill( 240, 0, 1, MAX_TILT_HISTORY*4, whiteColor );
- }
- void ShowTime() {
- if ( !showTime->value ) {
- return;
- }
- color4_t sleepColor = { 255, 0, 0, 255 };
- color4_t activeColor = { 0, 255, 0, 255 };
- color4_t swapColor = { 0, 0, 255, 255 };
- color4_t ticColor = { 255, 255, 255, 255 };
-
- for ( int i = 1 ; i < 30 ; i++ ) {
- logTime_t *lt = &loggedTimes[(iphoneFrameNum - i ) & (MAX_LOGGED_TIMES-1)];
- int sleepTime = ( lt->afterSleep - lt->enterFrame ) >> 7;
- int activeTime = ( lt->beforeSwap - lt->afterSleep ) >> 7;
- int swapTime = ( lt->afterSwap - lt->beforeSwap ) >> 7;
- R_Draw_Fill( 0, i * 4, activeTime, 2, activeColor );
- R_Draw_Fill( activeTime, i * 4, swapTime, 2, swapColor );
- R_Draw_Fill( activeTime + swapTime, i * 4, sleepTime, 2, sleepColor );
-
- R_Draw_Fill( 480 - lt->numGameTics * 10, i * 4, lt->numGameTics * 10, 2, ticColor );
- R_Draw_Fill( 480 - lt->numPingTics * 10, i * 4+2, lt->numPingTics * 10, 2, swapColor );
- }
- }
- /*
- ==================
- iphoneHighlightPicWhenTouched
- Draw transparent except when touched
- =================
- */
- void iphoneHighlightPicWhenTouched( pkTexture_t *texture, int x, int y, int w, int h ) {
- if ( TouchDown( x, y, w, h ) ) {
- glColor4f(1,1,1,1);
- } else {
- glColor4f(1,1,1,0.5);
- }
- PK_StretchTexture( texture, x, y, w, h );
- glColor4f(1,1,1,1);
- }
- /*
- ==================
- iphoneSetNotifyText
-
- Notify text is a single centered line for "got a key", "found a secret", etc
- ==================
- */
- char notifyText[128];
- int notifyFrameNum;
- void iphoneSetNotifyText( const char *str, ... ) {
- va_list argptr;
- if ( !messages->value ) {
- // option to disable all the message prints
- return;
- }
- va_start( argptr, str );
- (void)vsnprintf( notifyText, sizeof( notifyText )-1, str, argptr );
- va_end( argptr );
- notifyFrameNum = iphoneFrameNum;
- }
- void iphoneDrawNotifyText() {
- if ( notifyFrameNum == 0 ) {
- return;
- }
- // display for three seconds, then fade over 0.3
- float f = iphoneFrameNum - notifyFrameNum - 80;
- if ( f < 0 ) {
- f = 1.0;
- } else {
- f = 1.0 - f * 0.1f;
- if ( f < 0 ) {
- notifyFrameNum = 0;
- return;
- }
- }
-
- glColor4f( 1, 1, 1, f );
- iphoneCenterText( 240, 16, 0.75, notifyText );
- glColor4f( 1, 1, 1, 1 );
- }
- /*
- ==================
- Rotor control
-
- ==================
- */
- void iphoneDrawRotorControl( ibutton_t *hud ) {
- if ( hud->buttonFlags & BF_IGNORE ) {
- return;
- }
- pkTexture_t *tex = hud->texture;
- PK_BindTexture( tex );
- float cx = hud->x + hud->drawWidth / 2;
- float cy = hud->y + hud->drawHeight / 2;
- float as = sin( hud->drawState );
- float ac = cos( hud->drawState );
- float sz = hud->drawWidth / 2;
-
- float xv[2] = { sz*ac, sz*as };
- float yv[2] = { -sz*as, sz*ac };
-
- glColor4f( 1, 1, 1, 1 );
-
- glBegin( GL_TRIANGLE_STRIP );
-
- glTexCoord2f( 0.0f, 0.0f ); glVertex2f( cx - xv[0] - yv[0], cy - xv[1] - yv[1] );
- glTexCoord2f( tex->textureData->maxS, 0.0f ); glVertex2f( cx + xv[0] - yv[0], cy + xv[1] - yv[1] );
- glTexCoord2f( 0.0f, tex->textureData->maxT ); glVertex2f( cx - xv[0] + yv[0], cy - xv[1] + yv[1] );
- glTexCoord2f( tex->textureData->maxS, tex->textureData->maxT ); glVertex2f( cx + xv[0] + yv[0], cy + xv[1] + yv[1] );
-
- glEnd();
- }
- //===================================================================================
- void iphoneDrawHudControl( ibutton_t *hud ) {
- if ( hud->buttonFlags & BF_IGNORE ) {
- return;
- }
- if ( !hud->texture ) {
- return;
- }
- if ( hud->drawAsLimit ) {
- // green tint when at maximum displacement
- glColor4f(0.5,1,0.5,1);
- } else if ( hud->touch || ( hud->buttonFlags & BF_DRAW_ACTIVE ) ) {
- // red tint when active
- glColor4f(1,0.5,0.5,1);
- } else {
- glColor4f(1,1,1,1);
- }
- if ( hud->scale <= 0 ) {
- hud->scale = 1.0f;
- }
- float w = hud->drawWidth * hud->scale;
- float h = hud->drawHeight * hud->scale;
- float x = hud->x + ( hud->drawWidth - w ) * 0.5f;
- float y = hud->y + ( hud->drawHeight - w ) * 0.5f;
-
- if ( centerSticks->value && hud->touch ) {
- // reposiition the control after each touch
- x = hud->touch->x - w*0.5f;
- y = hud->touch->y - h*0.5f;
- }
- PK_StretchTexture( hud->texture, x, y, w, h );
- glColor4f(1,1,1,1);
- }
- bool NewTextButton( ibutton_t *b, const char *title, int x, int y, int w, int h ) {
- if ( !b->texture ) {
- const char *pic = (w>128 ? "iphone/long_string_box.tga" : "iphone/short_string_box.tga" );
- SetButtonPicsAndSizes( b, pic, "", x, y, w, h );
- b->buttonFlags = BF_DIMMED | BF_CENTERTEXT;
- }
- b->title = title;
- return HandleButton( b );
- }
- /*
- =====================================================================
-
- Smart USE test -- determine if there is a usable line within range
- of the player. This is done by the main thread after running a game tic,
- the async thread just checks the flag, because calling the traverse
- functions is not thread safe.
-
- =====================================================================
- */
- static boolean usableInRange;
- boolean PTR_UseTestTraverse (intercept_t* in)
- {
- if (!in->d.line->special)
- {
- P_LineOpening (in->d.line);
- if (openrange <= 0)
- {
- // can't use through a wall
- return false;
- }
-
- // not a special line, but keep checking
-
- return true;
- }
-
- player_t* player = &players[consoleplayer];
- int side = 0;
- if (P_PointOnLineSide (player->mo->x, player->mo->y, in->d.line) == 1)
- side = 1;
- // e6y
- // b.m. side test was broken in boom201
- if ((demoplayback ? (demover != 201) : (compatibility_level != boom_201_compatibility)))
- if (side) //jff 6/1/98 fix inadvertent deletion of side test
- return false;
- if ( in->d.line->special == 76 ) {
- // The button that opens the final door at E1M6 has a trigger line
- // right in front of it, which causes the use button to go down without
- // doing anything, and it gets held down as you close to the actual
- // button, so it doesn't get activated. You could turn to face the wall
- // to get the use button up, then turn back towards the button, but it
- // feels totally broken. The correct solution would be to return false
- // for all line specials that won't actually be player-usable, but I can't
- // tell if that is a simple range or a huge scattered list. For now, this
- // hack to ignore this particular line type solves the problem. We'll
- // see if other levels have similar issues...
- return false;
- }
- if ( in->d.line->special == 88 ) { // yellow door above plat on E1M6
- return false;
- }
-
-
- // this is a reasonable target for use
- usableInRange = true;
-
- //WAS can't use for than one special line in a row
- //jff 3/21/98 NOW multiple use allowed with enabling line flag
-
- return (!demo_compatibility && (in->d.line->flags&ML_PASSUSE))?
- true : false;
- }
- boolean P_TestUseLines()
- {
- int angle;
- fixed_t x1;
- fixed_t y1;
- fixed_t x2;
- fixed_t y2;
-
- player_t* player = &players[consoleplayer];
- if ( !player->mo ) {
- return false; // at intermission
- }
- angle = player->mo->angle >> ANGLETOFINESHIFT;
-
- x1 = player->mo->x;
- y1 = player->mo->y;
- x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle];
- y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle];
-
- // itterate over the lines and run the callback function
- usableInRange = false;
- P_PathTraverse ( x1, y1, x2, y2, PT_ADDLINES, PTR_UseTestTraverse );
- return usableInRange;
- }
- //=====================================================================
- /*
- ==================
- AutomapControls
-
- This is strictly client-side, done in the game thread instead of the async thread
- ==================
- */
- void AutomapControls() {
- //------------------------
- // automap controls
- //------------------------
- extern fixed_t m_x, m_y; // LL x,y window location on the map (map coords)
- extern fixed_t m_x2, m_y2; // UR x,y window location on the map (map coords)
-
- // width/height of window on map (map coords)
- extern fixed_t m_w;
- extern fixed_t m_h;
-
- // used by MTOF to scale from map-to-frame-buffer coords
- extern fixed_t scale_mtof;
- // used by FTOM to scale from frame-buffer-to-map coords (=1/scale_mtof)
- extern fixed_t scale_ftom;
-
- extern fixed_t min_scale_mtof; // used to tell when to stop zooming out
- extern fixed_t max_scale_mtof; // used to tell when to stop zooming in
-
- static int prevX = -1, prevY = -1;
-
- // any touch not down in another control will
- // drag-scroll and be claimed by the automap
- int touchCount = 0;
- touch_t *mapTouch[MAX_TOUCHES];
- for ( int i = 0 ; i < MAX_TOUCHES ; i++ ) {
- touch_t *t = &gameTouches[i];
- if ( t->down ) {
- if ( t->controlOwner == NULL || t->controlOwner == OWNER_AUTOMAP ) {
- // claim it so dragging onto another control won't
- // cause it to activate
- t->controlOwner = OWNER_AUTOMAP;
- mapTouch[touchCount] = t;
- touchCount++;
- }
- }
- }
- if ( touchCount != 1 ) {
- prevX = -1;
- }
- static int pinching;
- if ( touchCount != 2 ) {
- pinching = 0;
- }
- if ( touchCount == 1 ) {
- // adjust the automap values, assume square aspect ratio
- touch_t *t = mapTouch[0];
- // drag position
- if ( prevX == -1 ) {
- prevX = t->x;
- prevY = t->y;
- }
- m_x -= ( t->x - prevX ) * (float)m_w / displaywidth;
- m_y += ( t->y - prevY ) * (float)m_w / displaywidth;
- m_x2 = m_x + m_w;
- m_y2 = m_y + m_h;
-
- prevX = t->x;
- prevY = t->y;
- } else if ( touchCount == 2 ) {
- // pinch scale
- touch_t *t1 = mapTouch[0];
- touch_t *t2 = mapTouch[1];
- static float baseDist;
- static float baseMtoF;
- static int basem_w;
- static int basem_h;
- float dist = sqrt( (t2->x-t1->x)*(t2->x-t1->x)+(t2->y-t1->y)*(t2->y-t1->y) );
- if ( !pinching ) {
- pinching = 1;
- baseDist = dist;
- baseMtoF = scale_mtof;
- basem_w = m_w;
- basem_h = m_h;
- }
- scale_mtof = baseMtoF * dist / baseDist;
- if ( scale_mtof < min_scale_mtof ) {
- scale_mtof = min_scale_mtof;
- dist = (float)min_scale_mtof * baseDist / baseMtoF;
- } else if ( scale_mtof > max_scale_mtof ) {
- scale_mtof = max_scale_mtof;
- dist = (float)max_scale_mtof * baseDist / baseMtoF;
- }
- scale_ftom = FixedDiv(FRACUNIT, scale_mtof);
-
- float midx = (t2->x+t1->x)*0.5;
- float midy = (t2->y+t1->y)*0.5;
- float midxDoom = m_x + m_w * midx / displaywidth;
- float midyDoom = m_y + m_w * midy / displaywidth;
- m_w = basem_w * baseDist / dist;
- m_h = basem_h * baseDist / dist;
- m_x = midxDoom - m_w * midx / displaywidth;
- m_y = midyDoom - m_w * midy / displaywidth;
- m_x2 = m_x + m_w;
- m_y2 = m_y + m_h;
- }
-
- }
- void SwapBuffersAndTouches() {
- // debug graphs
- ShowTilt();
- ShowTime();
- ShowNet();
- ShowSound();
-
- pthread_mutex_lock( &eventMutex );
- for ( int i = 0 ; i < MAX_TOUCHES ; i++ ) {
- if ( sysTouches[i].down && gameTouches[i].down ) {
- sysTouches[i].controlOwner = gameTouches[i].controlOwner;
- }
- }
- pthread_mutex_unlock( &eventMutex );
- loggedTimes[iphoneFrameNum&(MAX_LOGGED_TIMES-1)].beforeSwap = SysIphoneMicroseconds();
- SysIPhoneSwapBuffers();
- int now = SysIphoneMicroseconds();
- loggedTimes[iphoneFrameNum&(MAX_LOGGED_TIMES-1)].afterSwap = now;
- }
- float weaponSelectDrawScale = 1.25f;
- void DrawWeapon(int weaponlump, int x, int y, int w, int h, int lightlevel)
- {
- GLTexture *gltexture;
- float fU1,fU2,fV1,fV2;
- int x1,y1,x2,y2;
-
- if( displaywidth >= 960 ) {
- weaponSelectDrawScale = 1.25f;
- } else {
- weaponSelectDrawScale = 0.75f;
- }
-
- x *= ((float)displaywidth) / 480.0f;
- y *= ((float)displayheight) / 320.0f;
- w *= ((float)displaywidth) / 480.0f;
- h *= ((float)displayheight) / 320.0f;
-
- // force doom to rebind, since we have changed the active GL_TEXTURE_2D
- last_gltexture = NULL;
-
- gltexture=gld_RegisterPatch(firstspritelump+weaponlump, CR_DEFAULT);
- if (!gltexture)
- return;
- float scaledWidth = gltexture->width * weaponSelectDrawScale;
- float scaledHeight = gltexture->height * weaponSelectDrawScale;
-
- // pin the middle bottom of the patch to the middle bottom of
- // the draw rectangle, then let everything else scale as needed
- fU1=0;
- fV1=0;
- fU2=(float)gltexture->width/(float)gltexture->tex_width;
- fV2=(float)gltexture->height/(float)gltexture->tex_height;
- x1=x+(w-scaledWidth)*0.5;
- x2=x1 + scaledWidth;
- y1=y+h-scaledHeight;
- y2=y+h;;
-
- gld_BindPatch(gltexture, CR_DEFAULT);
-
- glColor4f( lightlevel, lightlevel, lightlevel, 1 );
-
- glBegin(GL_TRIANGLE_STRIP);
- glTexCoord2f(fU1, fV1); glVertex2f((float)(x1),(float)(y1));
- glTexCoord2f(fU1, fV2); glVertex2f((float)(x1),(float)(y2));
- glTexCoord2f(fU2, fV1); glVertex2f((float)(x2),(float)(y1));
- glTexCoord2f(fU2, fV2); glVertex2f((float)(x2),(float)(y2));
- glEnd();
- glColor4f(1.0f,1.0f,1.0f,1.0f);
- }
- /*
- ==================
- DrawWeaponSelect
-
- ==================
- */
- static const char *weaponNames[9] = {
- "fist",
- "pistol",
- "shotgun",
- "chaingun",
- "rockets",
- "plasma",
- "BFG",
- "chainsaw",
- "dblshotgun"
- };
- int weaponSprites[9] = {
- SPR_PUNG,
- SPR_PISG,
- SPR_SHTG,
- SPR_CHGG,
- SPR_MISG,
- SPR_PLSG,
- SPR_BFGG,
- SPR_SAWG,
- SPR_SHT2
- };
- void DrawWeaponSelect() {
- player_t *player = &players[consoleplayer];
-
- for ( int i = wp_fist ; i <= wp_supershotgun ; i++ ) {
- int bx = i % 3;
- int by = i / 3;
- color4_t color = { 0, 0, 255, 200 };
- color4_t textColor = { 255, 255, 255, 255 };
- boolean selectable = false;
- int ammo = -1;
- switch ( i ) {
- case wp_pistol: ammo = player->ammo[am_clip]; break;
- case wp_shotgun: ammo = player->ammo[am_shell]; break;
- case wp_chaingun: ammo = player->ammo[am_clip]; break;
- case wp_missile: ammo = player->ammo[am_misl]; break;
- case wp_plasma: ammo = player->ammo[wp_plasma]; break;
- case wp_bfg: ammo = player->ammo[wp_plasma]; if ( ammo < 40 ) ammo = 0; break;
- case wp_supershotgun: ammo = player->ammo[wp_plasma]; if ( ammo < 2 ) ammo = 0; break;
- }
- if ( !player->weaponowned[i] ) {
- // don't have the weapon
- color[0] = color[1] = color[2] = 50;
- textColor[3] = 128;
- } else {
- // selectable
- color[0] = 255; color[1] = 255; color[2] = 255; color[3] = 255;
- selectable = true;
-
- if ( ammo == 0 ) {
- // have it, but out of ammo
- color[0] = 255; color[1] = color[2] = 0;
- textColor[3] = 128;
- }
- }
-
- int x = bx * 160 + 20;
- int y = by * 88;
- int w = 120;
- int h = 80;
-
- float nx = x * ((float)displaywidth) / 480.0f;
- float ny = y * ((float)displayheight) / 320.0f;
- float nw = w * ((float)displaywidth) / 480.0f;
- float nh = h * ((float)displayheight) / 320.0f;
-
- if ( selectable && TouchDown( nx, ny, nw, nh ) ) {
- color[0] = 128;
- color[1] = color[2] = 128;
- color[3] = 200;
- }
-
- glColor4ubv( color );
-
-
- PK_StretchTexture( PK_FindTexture( "iphone/multi_backdrop.tga" ), nx, ny, nw, nh );
- // R_Draw_Blend( x, y, w, h, color );
-
- glColor4ubv( textColor );
- iphoneCenterText( x + w/2, y+16, 0.75, weaponNames[i] );
- // draw the weapon sprite full color if available or black if not
-
- spritedef_t *sprdef = &sprites[weaponSprites[i]];
- if ( sprdef->spriteframes ) { // restricted wads won't have all weapons
- spriteframe_t *sprframe = &sprdef->spriteframes[0];
- DrawWeapon( sprframe->lump[0] , x, y - 2, w, h, player->weaponowned[i] );
-
- if ( selectable && TouchReleased( nx, ny, nw, nh ) ) {
- drawWeaponSelect = false;
- weaponSelected = i;
- }
- }
- }
- }
- /*
- ==================
- iphoneFrame
-
- This is continuously called by the game thread main loop, any sleeping
- is done explicitly. If the game isn't holding 30hz, it will be running
- flat out with no sleeping at all.
- ==================
- */
- void iphoneFrame() {
- iphoneFrameNum++;
- loggedTimes[iphoneFrameNum&(MAX_LOGGED_TIMES-1)].numGameTics = 0;
- loggedTimes[iphoneFrameNum&(MAX_LOGGED_TIMES-1)].afterSleep =
- loggedTimes[iphoneFrameNum&(MAX_LOGGED_TIMES-1)].enterFrame = SysIphoneMicroseconds();
- //-------------------------------------------------
- // grabs the console command under mutex.
- //-------------------------------------------------
- pthread_mutex_lock( &eventMutex );
- // execute a console command if one was typed
- if ( consoleCommand[0] ) {
- // send it a character at a time to the classic dooom cheat processing
- // for idkfa, idclev, etc
- for ( int i = 0 ; consoleCommand[i] != 0 ; i++ ) {
- M_FindCheats( consoleCommand[i] );
- }
-
- // send it to the new concole command processing
- Com_Printf( "%s\n", consoleCommand );
- Cmd_ExecuteString( consoleCommand );
- consoleCommand[0] = 0;
- }
-
- pthread_mutex_unlock( &eventMutex );
-
- // move touches to prevTouches (old style use, remove...)
- numPrevTouches = numTouches;
- memcpy( prevTouches, touches, sizeof( prevTouches ) );
-
- // process old style touches
- numTouches = 0;
- for ( int i = 0 ; i < MAX_TOUCHES ; i++ ) {
- touch_t *t = &gameTouches[i];
- if ( t->down ) {
- touches[numTouches][0] = t->x;
- touches[numTouches][1] = t->y;
- numTouches++;
- }
- }
- // check for flipping the phone orientation
- iphoneCheckForLandscapeReverse();
-
- // go to the next demo if needed
- if ( advancedemo ) {
- if ( iphoneTimeDemo && timeDemoStart ) {
- // go back to the menu after a timedemo
- menuState = IPM_MAIN;
- timeDemoStart = 0;
- return;
- }
- static int demoState;
- players[consoleplayer].playerstate = PST_LIVE; /* not reborn */
- advancedemo = usergame = paused = false;
- gameaction = ga_nothing;
- gamestate = GS_DEMOSCREEN;
- static const char *demoNames[4] = { "demo1", "demo2", "demo3", "demo4" };
- G_DeferedPlayDemo( demoNames[demoState] );
- if ( ++demoState == 4 ) {
- demoState = 0;
- }
- }
- if ( saveOnExitState == 1 ) {
- printf( "SaveOnExitState == 1\n" );
- if ( !netgame && !demoplayback && usergame && gamestate == GS_LEVEL ) {
- G_SaveGame( 0, "quicksave" );
- G_DoSaveGame(true);
- }
- saveOnExitState = 2;
- return;
- }
- if ( saveOnExitState == 2 ) {
- // the app is exiting
- return;
- }
-
- //--------------------------------------------------------------------------------------
- // game tic processing
- //--------------------------------------------------------------------------------------
- boolean runGame = false;
-
- if( inBackgroundProcess ) {
- return;
- }
-
- if ( menuState == IPM_GAME ) {
- // don't run the game when in the menus
- runGame = true;
- }
- if ( automapmode & am_active ) {
- // Unlike PC Doom, don't run time when in the automap, since
- // drawing the controls clutters the screen too much.
- runGame = false;
- }
- if ( netgame ) {
- // even when in the menus or automap, the tics must be processed if it is a net game
- runGame = true;
- }
-
- if ( netGameFailure ) {
- // consistancy failure or interruption
- runGame = false;
- }
-
- // since we don't allow movement control in the automap,
- // don't advance time.
- if ( runGame ) {
- int stopTic;
-
- // block until the AsyncTic() has said we can run at least one frame,
- // unless we are doing a flat-out timedemo run
- if ( iphoneTimeDemo ) {
- stopTic = gametic+1;
- maketic = stopTic+1;
- } else {
-
- loggedTimes[iphoneFrameNum&(MAX_LOGGED_TIMES-1)].afterSleep = SysIphoneMicroseconds();
- if ( localGameID == gameID ) {
- loggedTimes[iphoneFrameNum&(MAX_LOGGED_TIMES-1)].numPingTics = netPlayers[1].peer.currentPingTics;
- } else {
- loggedTimes[iphoneFrameNum&(MAX_LOGGED_TIMES-1)].numPingTics = netServer.currentPingTics;
- }
-
- // On the server, we always want to execute all available tics.
- // For a remote client, that would also give the minimum lag, but things are much
- // smoother if they instead try to leave one buffer tic, unless that would
- // leave the frame without running a single gametic.
- stopTic = maketic;
- if ( consoleplayer != 0 ) {
- // we are a client, so try to leave a buffer frame
- stopTic = maketic - 1;
- if ( gametic == stopTic ) {
- stopTic++;
- }
- }
- }
-
- //---------------------------------
- // run game tics
- //---------------------------------
- while( gametic < stopTic ) {
- // run the gametic with all the player and monster logic
- // this will extract netcmds[player][gametic%BACKUPTICS] for each player
- // Com_Printf( "gametic %i\n", gametic );
- G_Ticker();
- // if we just respawned with add-gear, give items now
- if ( addGear ) {
- players[0].weaponowned[wp_shotgun] = true;
- players[0].ammo[am_shell] = 20;
- players[0].pendingweapon = wp_shotgun;
- addGear = false;
- }
-
- // show the network trouble icon if we haven't run a game tic in a long time
- lastGameProcessedTime = SysIphoneMilliseconds();
-
- // see if there is a usable line in front of the player right now,
- // which can be picked up by the asyncTic
- autoUseActive = P_TestUseLines();
-
- // generate the checksum for consistency failure testing
- P_Checksum(gametic);
-
- // on to the next tic
- loggedTimes[iphoneFrameNum&(MAX_LOGGED_TIMES-1)].numGameTics++;
- gametic++;
-
- // this probably doesn't need to be tic-synced, but it doesn't hurt
- if (players[displayplayer].mo) {
- // move positional sounds and free up channels that have completed
- S_UpdateSounds(players[displayplayer].mo);
- }
- }
- }
-
- if ( consoleActive ) {
- iphoneSet2D();
- // FIXME: actually draw a console...
- // Console_Draw();
- SwapBuffersAndTouches();
- return;
- }
- if ( menuState != IPM_GAME ) {
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- iphoneSet2D();
- iphoneDrawMenus();
- SwapBuffersAndTouches();
-
- return;
- }
-
- //------------------
- // any touch release during demo playback goes to main menu
- //------------------
- if ( !usergame && !iphoneTimeDemo ) {
- if ( numTouches == 0 && numPrevTouches == 1 ) {
- menuState = IPM_MAIN;
- }
- }
-
- if( inBackgroundProcess ) {
- return;
- }
-
- // Draw the game screen. This can also be called by the pacifier update
- // during level loading.
- iphoneDrawScreen();
-
- // If we just loaded a level, do the texture precaching after we
- // have drawn and displayed the first frame, so the user has
- // something to look at while it is loading.
- if ( iphoneFrameNum == levelLoadFrameNum + 1 ) {
- int start = SysIphoneMilliseconds();
- gld_Precache();
- int end = SysIphoneMilliseconds();
- Com_Printf( "%3.1f seconds to gld_Precache()\n", (end-start)*0.001f );
- timeDemoStart = end;
- timeDemoFrames = 0;
- }
- }
- int pacifierCycle;
- int pacifierTime;
- void iphonePacifierUpdate() {
- // Only update a few times a second so it doesn't actually make it
- // take longer to load.
- int now = SysIphoneMilliseconds();
- if ( now < pacifierTime + 200 ) {
- return;
- }
- pacifierTime = now;
- pacifierCycle = ( pacifierCycle + 1 ) & 7;
- iphoneDrawScreen();
- }
- /*
- ==================
- iphoneDrawScreen
-
- Called by the main loop and also during pacifier update when preloading textures
- ==================
- */
- void iphoneDrawScreen() {
- // tell the classic code about turning the status bar on or off
- if ( statusBar->modified ) {
- statusBar->modified = false;
-
- if ( statusBar->value ) {
- R_SetViewSize( 10 );
- } else {
- R_SetViewSize( 11 );
- }
- }
- //------------------------------------------------
- // Update display with current state.
- //------------------------------------------------
- // force doom to rebind, since we have changed the active GL_TEXTURE_2D
- last_gltexture = NULL;
-
- D_Display();
- iphoneSet2D();
- //-----------------------------------
- // draw 2D overlays for game screen
- //-----------------------------------
- if ( automapmode & am_active ) {
- if ( HandleButton( &huds.map ) ) {
- AM_Stop();
- }
- if ( !netgame ) { // no save game option during net play
- static ibutton_t btnSave;
- if ( NewTextButton( &btnSave, "SAVE", 480-64, 0, 64, 32 ) ) {
- G_SaveGame( 0, "ManualSave" );
- G_DoSaveGame(true);
- AM_Stop();
- }
- }
- // update scroll and zoom after the buttons have potentially claimed a touch
- AutomapControls();
- } else if ( iphoneFrameNum == levelLoadFrameNum + 1 ) {
- // don't draw hud elements during the precache
-
- // draw rotating pacifier icon
- PK_BindTexture( PK_FindTexture( "iphone/loading.tga" ) );
- glColor4f( 1, 1, 1, 1 );
- float cx = 240 * ((float)displaywidth) / 480.0f;
- float cy = 160 * ((float)displayheight) / 320.0f;
- float as = sin( pacifierCycle * M_PI / 4 );
- float ac = cos( pacifierCycle * M_PI / 4 );
- float sz = 64;
-
- float xv[2] = { sz*ac, sz*as };
- float yv[2] = { -sz*as, sz*ac };
-
- glBegin( GL_TRIANGLE_STRIP );
-
- glTexCoord2f( 0, 0 ); glVertex2f( cx - xv[0] - yv[0], cy - xv[1] - yv[1] );
- glTexCoord2f( 1, 0 ); glVertex2f( cx + xv[0] - yv[0], cy + xv[1] - yv[1] );
- glTexCoord2f( 0, 1 ); glVertex2f( cx - xv[0] + yv[0], cy - xv[1] + yv[1] );
- glTexCoord2f( 1, 1 ); glVertex2f( cx + xv[0] + yv[0], cy + xv[1] + yv[1] );
-
- glEnd();
- } else {
- // normal gameplay
- if ( gamestate == GS_FINALE ) {
- // leave the main menu button on the screen so they can start the
- // next episode
- if ( HandleButton( &huds.menu ) ) {
- iphonePauseMusic();
- menuState = IPM_MAIN;
- }
- } else if ( !menuactive && !demoplayback && usergame && gamestate == GS_LEVEL ) {
- if ( players[consoleplayer].playerstate == PST_DEAD ) {
- // when dead, only show the main menu con and the
- // respawn / load game icons
- if ( HandleButton( &huds.menu ) ) {
- iphonePauseMusic();
- menuState = IPM_MAIN;
- }
- if ( !deathmatch && !netgame ) {
- static ibutton_t btnSaved;
- static ibutton_t btnRespawn;
- static ibutton_t btnGear;
-
- if ( !btnSaved.texture ) {
- // initial setup
- SetButtonPicsAndSizes( &btnSaved, "iphone/load_saved.tga", "Saved game", 240 - 48 - 96 - 48, 80, 96, 96 );
- SetButtonPicsAndSizes( &btnRespawn, "iphone/respawn.tga", "Restart", 240 - 48, 80, 96, 96 );
- SetButtonPicsAndSizes( &btnGear, "iphone/respawn_gear.tga", "Add gear", 240 + 48 + 48, 80, 96, 96 );
- }
-
- if ( HandleButton( &btnSaved ) ) {
- StartSaveGame();
- }
- if ( HandleButton( &btnRespawn ) ) {
- players[consoleplayer].playerstate = PST_REBORN;
- }
- if ( HandleButton( &btnGear ) ) {
- players[consoleplayer].playerstate = PST_REBORN;
- addGear = true;
- }
- } else {
- static ibutton_t btnNetRespawn;
- if ( !btnNetRespawn.texture ) {
- // initial setup
- SetButtonPicsAndSizes( &btnNetRespawn, "iphone/respawn.tga", "Respawn", 240 - 96/2, 90, 96, 96 );
- }
- if ( HandleButton( &btnNetRespawn ) ) {
- // this will cause the next command sent to include a use action,
- // then clear this flag
- respawnActive = true;
- }
- }
- } else if ( drawWeaponSelect ) {
- DrawWeaponSelect();
- } else {
- if ( drawControls->value ) {
- iphoneDrawHudControl( &huds.forwardStick );
- iphoneDrawHudControl( &huds.sideStick );
- iphoneDrawHudControl( &huds.turnStick );
- iphoneDrawRotorControl( &huds.turnRotor );
- // iphoneDrawHudControl( &huds.fire );
- }
-
- if ( HandleButton( &huds.menu ) ) {
- iphonePauseMusic();
- menuState = IPM_MAIN;
- }
- if ( HandleButton( &huds.map ) ) {
- AM_Start();
- }
- if ( HandleButton( &huds.fire ) ) {
- }
-
- if ( netgame ) {
- #if 0
- static ibutton_t btnPlayer;
- if ( NewTextButton( &btnPlayer, "PLAYER", 0, 48, 100, 32 ) ) {
- displayplayer ^= 1;
- }
-
- static ibutton_t btnNet;
- if ( NewTextButton( &btnNet, "NET", 240-32, 0, 80, 32 ) ) {
- showNet->value = !showNet->value;
- }
- static ibutton_t btnThrottle;
- const char *title = throttle->value ? "Throttle:ON" : "Throttle:OFF";
- if ( NewTextButton( &btnThrottle, title, 0, 0, 128, 32 ) ) {
- throttle->value = !throttle->value;
- }
- #endif
- }
- #if 0
- static ibutton_t btnSpeeds;
- if ( NewTextButton( &btnSpeeds, "SPEEDS", 240-32, 0, 80, 32 ) ) {
- showTime->value = !showTime->value;
- }
- static ibutton_t btnTest;
- if ( NewTextButton( &btnTest, "TEST", 0, 48, 70, 32 ) ) {
- testNewRenderer = !testNewRenderer;
- }
- #endif
- }
- // notify text last, so it is always on top and legible
- iphoneDrawNotifyText();
-
- // not getting network tics
- if ( SysIphoneMilliseconds() - lastGameProcessedTime > 500 ) {
- PK_StretchTexture( PK_FindTexture("iphone/multiplay.tga"), 240 - 96/2, 90, 96, 96 );
- }
-
- // draw the little graph in the upper right corner
- if ( netgame ) {
- ShowMiniNet();
- }
- }
- }
-
- // update timedemo display
- if ( iphoneTimeDemo ) {
- if ( iphoneFrameNum > levelLoadFrameNum + 1 ) {
- timeDemoFrames++;
- float fps = timeDemoFrames * 1000.0f / ( SysIphoneMilliseconds() - timeDemoStart );
- sprintf( timeDemoResultString, "%5.1f fps", fps );
- } else {
- strcpy( timeDemoResultString, "TIMEDEMO" );
- }
- iphoneCenterText( 240, 80, 0.75, timeDemoResultString );
- }
-
- // time how long the GPU takes to render the entire frame
- if ( glfinish->value ) {
- int start = SysIphoneMicroseconds();
- glFinish();
- int end = SysIphoneMicroseconds();
- Com_Printf( "%4.1f msec for glFinish()\n", ( end - start ) * 0.001f );
- }
-
- SwapBuffersAndTouches();
- }
|