merge default into experimental3D experimental3D
authorkoda
Mon, 17 Jan 2011 01:43:10 +0100
branchexperimental3D
changeset 4844 20b81fafd236
parent 4818 202eef454354 (diff)
parent 4843 673f74c89687 (current diff)
child 4846 668602df25a6
child 4848 03aa62a64978
merge default into experimental3D
QTfrontend/gameuiconfig.cpp
QTfrontend/pages.cpp
hedgewars/uConsts.pas
hedgewars/uIO.pas
hedgewars/uVariables.pas
hedgewars/uWorld.pas
project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj
--- a/.hgignore	Sun Jan 16 13:53:32 2011 -0500
+++ b/.hgignore	Mon Jan 17 01:43:10 2011 +0100
@@ -32,5 +32,3 @@
 glob:*.orig
 glob:*.bak
 glob:*.rej
-glob:*.qm
-glob:share/hedgewars/Data/misc/hwengine.desktop
--- a/QTfrontend/game.cpp	Sun Jan 16 13:53:32 2011 -0500
+++ b/QTfrontend/game.cpp	Mon Jan 17 01:43:10 2011 +0100
@@ -300,6 +300,7 @@
     arguments << (config->isAltDamageEnabled() ? "1" : "0");
     arguments << config->netNick().toUtf8().toBase64();
     arguments << QString::number(config->translateQuality());
+    arguments << QString::number(config->stereoMode());
     arguments << tr("en.txt");
 
     return arguments;
--- a/QTfrontend/gameuiconfig.cpp	Sun Jan 16 13:53:32 2011 -0500
+++ b/QTfrontend/gameuiconfig.cpp	Mon Jan 17 01:43:10 2011 +0100
@@ -48,6 +48,7 @@
     Form->ui.pageOptions->CBFrontendFullscreen->setChecked(ffscr);
 
     Form->ui.pageOptions->SLQuality->setValue(value("video/quality", 5).toUInt());
+    Form->ui.pageOptions->CBStereoMode->setCurrentIndex(value("video/stereo", 0).toUInt());
     Form->ui.pageOptions->CBFrontendEffects->setChecked(frontendEffects);
     Form->ui.pageOptions->CBEnableSound->setChecked(value("audio/sound", true).toBool());
     Form->ui.pageOptions->CBEnableFrontendSound->setChecked(value("frontend/sound", true).toBool());
@@ -113,6 +114,7 @@
     setValue("video/fullscreen", vid_Fullscreen());
 
     setValue("video/quality", Form->ui.pageOptions->SLQuality->value());
+    setValue("video/stereo", stereoMode());
 
     setValue("frontend/effects", isFrontendEffects());
 
@@ -261,6 +263,11 @@
     return Form->ui.pageOptions->CBAltDamage->isChecked();
 }
 
+quint32 GameUIConfig::stereoMode() const
+{
+    return Form->ui.pageOptions->CBStereoMode->currentIndex();
+}
+
 bool GameUIConfig::appendDateTimeToRecordName()
 {
     return Form->ui.pageOptions->CBNameWithDate->isChecked();
--- a/QTfrontend/gameuiconfig.h	Sun Jan 16 13:53:32 2011 -0500
+++ b/QTfrontend/gameuiconfig.h	Mon Jan 17 01:43:10 2011 +0100
@@ -52,6 +52,7 @@
     bool isFrontendEffects() const;
     bool isFrontendFullscreen() const;
     void resizeToConfigValues();
+    quint32 stereoMode() const;
 
 #ifdef __APPLE__
 #ifdef SPARKLE_ENABLED
--- a/QTfrontend/pages.cpp	Sun Jan 16 13:53:32 2011 -0500
+++ b/QTfrontend/pages.cpp	Mon Jan 17 01:43:10 2011 +0100
@@ -669,6 +669,7 @@
 
             QVBoxLayout * GBAlayout = new QVBoxLayout(AGGroupBox);
             QHBoxLayout * GBAreslayout = new QHBoxLayout(0);
+            QHBoxLayout * GBAstereolayout = new QHBoxLayout(0);
             QHBoxLayout * GBAqualayout = new QHBoxLayout(0);
 
             CBFrontendFullscreen = new QCheckBox(AGGroupBox);
@@ -704,6 +705,7 @@
             CBFullscreen = new QCheckBox(AGGroupBox);
             CBFullscreen->setText(QCheckBox::tr("Fullscreen"));
             GBAlayout->addWidget(CBFullscreen);
+            connect(CBFullscreen, SIGNAL(stateChanged(int)), this, SLOT(setFullscreen(void)));
 
             QLabel * quality = new QLabel(AGGroupBox);
             quality->setText(QLabel::tr("Quality"));
@@ -717,6 +719,25 @@
             SLQuality->setFixedWidth(150);
             GBAqualayout->addWidget(SLQuality);
             GBAlayout->addLayout(GBAqualayout);
+            QLabel * stereo = new QLabel(AGGroupBox);
+            stereo->setText(QLabel::tr("Stereo rendering"));
+            GBAstereolayout->addWidget(stereo);
+
+            CBStereoMode = new QComboBox(AGGroupBox);
+            CBStereoMode->addItem(QComboBox::tr("Disabled"));
+            CBStereoMode->addItem(QComboBox::tr("Red/Cyan"));
+            CBStereoMode->addItem(QComboBox::tr("Cyan/Red"));
+            CBStereoMode->addItem(QComboBox::tr("Red/Blue"));
+            CBStereoMode->addItem(QComboBox::tr("Blue/Red"));
+            CBStereoMode->addItem(QComboBox::tr("Red/Green"));
+            CBStereoMode->addItem(QComboBox::tr("Green/Red"));
+            CBStereoMode->addItem(QComboBox::tr("Side-by-side"));
+            CBStereoMode->addItem(QComboBox::tr("Top-Bottom"));
+            CBStereoMode->addItem(QComboBox::tr("Wiggle"));
+            connect(CBStereoMode, SIGNAL(currentIndexChanged(int)), this, SLOT(forceFullscreen(int)));
+
+            GBAstereolayout->addWidget(CBStereoMode);
+            GBAlayout->addLayout(GBAstereolayout);
 
             hr = new QFrame(AGGroupBox);
             hr->setFrameStyle(QFrame::HLine);
@@ -781,8 +802,34 @@
     BtnBack->setFixedHeight(BtnSaveOptions->height());
     BtnBack->setFixedWidth(BtnBack->width()+2);
     BtnBack->setStyleSheet("QPushButton{margin: 22px 0 9px 2px;}");
+}
 
-//    BtnAssociateFiles = addButton("");
+void PageOptions::forceFullscreen(int index)
+{
+    if (index != 0) {
+        previousFullscreenValue = this->CBFullscreen->isChecked();
+        this->CBFullscreen->setChecked(true);
+        this->CBFullscreen->setEnabled(false);
+        previousQuality = this->SLQuality->value();
+        this->SLQuality->setValue(this->SLQuality->maximum());
+        this->SLQuality->setEnabled(false);
+    } else {
+        this->CBFullscreen->setChecked(previousFullscreenValue);
+        this->CBFullscreen->setEnabled(true);
+        this->SLQuality->setValue(previousQuality);
+        this->SLQuality->setEnabled(true);
+    }
+}
+
+void PageOptions::setFullscreen(void)
+{
+    int tmp = this->CBResolution->currentIndex();
+    if (this->CBFullscreen->isChecked())
+        this->CBResolution->setCurrentIndex(0);
+    else
+        this->CBResolution->setCurrentIndex(previousResolutionIndex);
+    previousResolutionIndex = tmp;
+    this->CBResolution->setEnabled(!this->CBFullscreen->isChecked());
 }
 
 PageNet::PageNet(QWidget* parent) : AbstractPage(parent)
--- a/QTfrontend/pages.h	Sun Jan 16 13:53:32 2011 -0500
+++ b/QTfrontend/pages.h	Mon Jan 17 01:43:10 2011 +0100
@@ -234,6 +234,7 @@
     QComboBox *CBTeamName;
     IconedGroupBox *AGGroupBox;
     QComboBox *CBResolution;
+    QComboBox *CBStereoMode;
     QCheckBox *CBEnableSound;
     QCheckBox *CBEnableFrontendSound;
     QCheckBox *CBEnableMusic;
@@ -254,6 +255,15 @@
     QLineEdit *editNetNick;
     QSlider *SLQuality;
     QCheckBox *CBFrontendEffects;
+
+private:
+    bool previousFullscreenValue;
+    int previousResolutionIndex;
+    int previousQuality;
+
+private slots:
+    void forceFullscreen(int index);
+    void setFullscreen(void);
 };
 
 class PageNet : public AbstractPage
--- a/hedgewars/ArgParsers.inc	Sun Jan 16 13:53:32 2011 -0500
+++ b/hedgewars/ArgParsers.inc	Mon Jan 17 01:43:10 2011 +0100
@@ -8,6 +8,7 @@
 end;
 
 procedure internalStartGameWithParameters();
+var tmp: LongInt;
 begin
     val(ParamStr(2), cScreenWidth);
     val(ParamStr(3), cScreenHeight);
@@ -23,7 +24,9 @@
     cAltDamage:= ParamStr(13) = '1';
     UserNick:= DecodeBase64(ParamStr(14));
     val(ParamStr(15), cReducedQuality);
-    cLocaleFName:= ParamStr(16)
+    val(ParamStr(16), tmp);
+    cStereoMode:= TStereoMode(max(0, min(ord(high(TStereoMode)), tmp)));
+    cLocaleFName:= ParamStr(17);
 end;
 
 procedure setVideo(screenWidth: LongInt; screenHeight: LongInt; bitsStr: LongInt);
--- a/hedgewars/hwengine.pas	Sun Jan 16 13:53:32 2011 -0500
+++ b/hedgewars/hwengine.pas	Mon Jan 17 01:43:10 2011 +0100
@@ -226,10 +226,12 @@
     cAltDamage:= gameArgs[8] = '1';
     val(gameArgs[9], rotationQt);
     recordFileName:= gameArgs[10];
+    cStereoMode:= smNone;
 {$ENDIF}
 
     cLogfileBase:= 'game';
     initEverything(true);
+
     WriteLnToConsole('Hedgewars ' + cVersionString + ' engine (network protocol: ' + inttostr(cNetProtoVersion) + ')');
 {$IFDEF DEBUGFILE}
     AddFileLog('Prefix: "' + PathPrefix +'"');
--- a/hedgewars/options.inc	Sun Jan 16 13:53:32 2011 -0500
+++ b/hedgewars/options.inc	Mon Jan 17 01:43:10 2011 +0100
@@ -32,6 +32,7 @@
   {$DEFINE SDL_MIXER_NEWER}
   {$DEFINE SDL_IMAGE_NEWER}
   {$DEFINE HWLIBRARY}
+  {$DEFINE S3D_DISABLED}
   {$DEFINE GLunit:=gles11}
 {$ENDIF}
 
@@ -41,3 +42,5 @@
   {  $DEFINE TRACEAIACTIONS}
   {  $DEFINE COUNTTICKS}
 {$ENDIF}
+
+//also available LUA_DISABLED
\ No newline at end of file
--- a/hedgewars/uChat.pas	Sun Jan 16 13:53:32 2011 -0500
+++ b/hedgewars/uChat.pas	Mon Jan 17 01:43:10 2011 +0100
@@ -29,10 +29,6 @@
 procedure DrawChat;
 procedure KeyPressChat(Key: Longword);
 
-var UserNick: shortstring = '';
-    ChatReady: boolean;
-    showAll: boolean;
-
 implementation
 uses SDLh, uKeys, uTypes, uVariables, uCommands, uUtils, uTextures, uRender, uIO;
 
@@ -52,6 +48,8 @@
     visibleCount: LongWord;
     InputStr: TChatLine;
     InputStrL: array[0..260] of char; // for full str + 4-byte utf-8 char
+    ChatReady: boolean;
+    showAll: boolean;
 
 const colors: array[#1..#5] of TSDL_Color = (
     (r:$FF; g:$FF; b:$FF; unused:$FF), // chat message [White]
@@ -373,7 +371,6 @@
 
 procedure freeModule;
 begin
-    UserNick:= '';
 end;
 
 end.
--- a/hedgewars/uConsts.pas	Sun Jan 16 13:53:32 2011 -0500
+++ b/hedgewars/uConsts.pas	Mon Jan 17 01:43:10 2011 +0100
@@ -23,15 +23,11 @@
 
 uses    SDLh, uFloat, GLunit;
 
-
 {$INCLUDE "config.inc"}
 
-// typed const is a variable despite const qualifier
-// in freepascal you may actually use var for the same purpose
-
 const
     sfMax = 1000;
-    cDefaultParamNum = 16;
+    cDefaultParamNum = 17;
 
     // message constants
     errmsgCreateSurface   = 'Error creating SDL surface';
--- a/hedgewars/uIO.pas	Sun Jan 16 13:53:32 2011 -0500
+++ b/hedgewars/uIO.pas	Mon Jan 17 01:43:10 2011 +0100
@@ -22,9 +22,6 @@
 interface
 uses SDLh, uTypes;
 
-var ipcPort: Word = 0;
-    hiTicks: Word;
-
 procedure initModule;
 procedure freeModule;
 
@@ -431,7 +428,6 @@
 
 procedure freeModule;
 begin
-    ipcPort:= 0;
 end;
 
 end.
--- a/hedgewars/uMisc.pas	Sun Jan 16 13:53:32 2011 -0500
+++ b/hedgewars/uMisc.pas	Mon Jan 17 01:43:10 2011 +0100
@@ -23,7 +23,6 @@
 
 uses    SDLh, uConsts, GLunit, uTypes;
 
-
 procedure movecursor(dx, dy: LongInt);
 function  doSurfaceConversion(tmpsurf: PSDL_Surface): PSDL_Surface;
 procedure MakeScreenshot(filename: shortstring);
--- a/hedgewars/uStore.pas	Sun Jan 16 13:53:32 2011 -0500
+++ b/hedgewars/uStore.pas	Mon Jan 17 01:43:10 2011 +0100
@@ -378,6 +378,17 @@
     SDL_FreeSurface(MissionIcons);
     FreeTexture(ropeIconTex);
     FreeTexture(HHTexture);
+{$IFNDEF S3D_DISABLED}
+    if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then
+    begin
+        glDeleteTextures(1, @texl);
+        glDeleteRenderbuffersEXT(1, @depthl);
+        glDeleteFramebuffersEXT(1, @framel);
+        glDeleteTextures(1, @texr);
+        glDeleteRenderbuffersEXT(1, @depthr);
+        glDeleteFramebuffersEXT(1, @framer)
+    end
+{$ENDIF}
 end;
 
 
@@ -434,10 +445,10 @@
 {$ELSE}
     glLoadExtension:= glext_LoadExtension(extension);
 {$IFDEF DEBUGFILE}
-    if not glLoadExtension then
-        AddFileLog('OpenGL - "' + extension + '" failed to load')
+    if glLoadExtension then
+        AddFileLog('OpenGL - "' + extension + '" loaded')
     else
-        AddFileLog('OpenGL - "' + extension + '" loaded');
+        AddFileLog('OpenGL - "' + extension + '" failed to load');
 {$ENDIF}
 {$ENDIF}
 end;
@@ -495,16 +506,57 @@
 {$ENDIF}
     end;
 
-{$IFNDEF IPHONEOS}
+{$IFDEF IPHONEOS}
+    cGPUVendor:= gvApple;
+{$ELSE}
     if StrPos(Str2PChar(vendor), Str2PChar('nvidia')) <> nil then
         cGPUVendor:= gvNVIDIA
     else if StrPos(Str2PChar(vendor), Str2PChar('intel')) <> nil then
         cGPUVendor:= gvATI
     else if StrPos(Str2PChar(vendor), Str2PChar('ati')) <> nil then
         cGPUVendor:= gvIntel;
+{$ENDIF}
 //SupportNPOTT:= glLoadExtension('GL_ARB_texture_non_power_of_two');
-{$ELSE}
-    cGPUVendor:= gvApple;
+{$IFNDEF S3D_DISABLED}
+    if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) or (cStereoMode = smAFR) then
+    begin
+        // prepare left and right frame buffers and associated textures
+        if glLoadExtension('GL_EXT_framebuffer_object') then
+        begin
+            // left
+            glGenFramebuffersEXT(1, @framel);
+            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framel);
+            glGenRenderbuffersEXT(1, @depthl);
+            glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthl);
+            glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, cScreenWidth, cScreenHeight);
+            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthl);
+            glGenTextures(1, @texl);
+            glBindTexture(GL_TEXTURE_2D, texl);
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,  cScreenWidth, cScreenHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texl, 0);
+
+            // right
+            glGenFramebuffersEXT(1, @framer);
+            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framer);
+            glGenRenderbuffersEXT(1, @depthr);
+            glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depthr);
+            glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, cScreenWidth, cScreenHeight);
+            glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, depthr);
+            glGenTextures(1, @texr);
+            glBindTexture(GL_TEXTURE_2D, texr);
+            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,  cScreenWidth, cScreenHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, nil);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, texr, 0);
+
+            // reset
+            glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0)
+        end
+        else
+            cStereoMode:= smNone;
+    end;
 {$ENDIF}
 
 {$IFDEF DEBUGFILE}
--- a/hedgewars/uTypes.pas	Sun Jan 16 13:53:32 2011 -0500
+++ b/hedgewars/uTypes.pas	Mon Jan 17 01:43:10 2011 +0100
@@ -5,6 +5,9 @@
 
 uses SDLh, uFloat, GLunit, uConsts, Math;
 
+// NOTE: typed const is a variable despite const qualifier
+// in freepascal you may actually use var for the same purpose
+
 type
     HwColor4f = record
         r, g, b, a: byte
@@ -128,6 +131,9 @@
 
     TWave = (waveRollup, waveSad, waveWave, waveHurrah, waveLemonade, waveShrug, waveJuggle);
 
+    TRenderMode = (rmDefault, rmLeftEye, rmRightEye);
+    TStereoMode = (smNone, smRedCyan, smCyanRed, smRedBlue, smBlueRed, smRedGreen, smGreenRed, smHorizontal, smVertical, smAFR);
+
     THHFont = record
             Handle: PTTF_Font;
             Height: LongInt;
--- a/hedgewars/uVariables.pas	Sun Jan 16 13:53:32 2011 -0500
+++ b/hedgewars/uVariables.pas	Mon Jan 17 01:43:10 2011 +0100
@@ -10,7 +10,7 @@
     cScreenWidth    : LongInt     = 1024;
     cScreenHeight   : LongInt     = 768;
     cBits           : LongInt     = 32;
-    //ipcPort is in uIO
+    ipcPort         : Word        = 0;
     cFullScreen     : boolean     = false;
     isSoundEnabled  : boolean     = true;
     isMusicEnabled  : boolean     = false;
@@ -21,10 +21,11 @@
     cShowFPS        : boolean     = false;
     cAltDamage      : boolean     = true;
     cReducedQuality : LongWord    = rqNone;
-    //userNick is in uChat
+    UserNick        : shortstring = '';
     recordFileName  : shortstring = '';
     cReadyDelay     : Longword    = 5000;
     cLogfileBase    : shortstring = 'debug';
+    cStereoMode     : TStereoMode = smNone;
 //////////////////////////
 
     alsoShutdownFrontend: boolean = false;
@@ -145,6 +146,8 @@
     WorldDx: LongInt;
     WorldDy: LongInt;
 
+    hiTicks: Word;
+
 const
     cHHFileName = 'Hedgehog';
     cCHFileName = 'Crosshair';
@@ -2079,6 +2082,9 @@
     cntTicks: LongWord;
 {$ENDIF}
     cOffsetY: LongInt;
+    AFRToggle: Boolean;
+    bAFRRight: Boolean;
+
 
     PixelFormat: PSDL_PixelFormat;
     SDLPrimSurface: PSDL_Surface;
@@ -2093,7 +2099,11 @@
     ProgrTex: PTexture;
     MissionIcons: PSDL_Surface;
     ropeIconTex: PTexture;
+    // orientation of the viewport
     rotationQt: GLfloat;
+    // stereoscopic framebuffer and textures
+    framel, framer, depthl, depthr: GLuint;
+    texl, texr: GLuint;
 
 
     VisualGearsList: PVisualGear;
@@ -2274,7 +2284,7 @@
     SDLwindow       := nil;
 {$ENDIF}
 
-    // those values still aren't perfect
+    // those values still are not perfect
     cLeftScreenBorder:= round(-cMinZoomLevel * cScreenWidth);
     cRightScreenBorder:= round(cMinZoomLevel * cScreenWidth + LAND_WIDTH);
     cScreenSpace:= cRightScreenBorder - cLeftScreenBorder;
@@ -2297,20 +2307,21 @@
     cScreenWidth    := 1024;
     cScreenHeight   := 768;
     cBits           := 32;
-    //ipcPort is in uIO
+    ipcPort         := 0;
     cFullScreen     := false;
     isSoundEnabled  := true;
     isMusicEnabled  := false;
     cLocaleFName    := 'en.txt';
     cInitVolume     := 100;
     cTimerInterval  := 8;
-    PathPrefix := './';
+    PathPrefix      := './';
     cShowFPS        := false;
     cAltDamage      := true;
     cReducedQuality := rqNone;
-    //userNick is in uChat
+    UserNick        := '';
     recordFileName  := '';
     cReadyDelay     := 5000;
+    cStereoMode     := smNone;
 end;
 
 end.
--- a/hedgewars/uVisualGears.pas	Sun Jan 16 13:53:32 2011 -0500
+++ b/hedgewars/uVisualGears.pas	Mon Jan 17 01:43:10 2011 +0100
@@ -392,6 +392,7 @@
 begin
 Gear:= VisualGearsList;
 case Layer of
+    // this level is very distant in the background when stereo
     0: while Gear <> nil do
         begin
         if Gear^.Tint <> $FFFFFFFF then Tint(Gear^.Tint);
@@ -414,6 +415,7 @@
         if Gear^.Tint <> $FFFFFFFF then Tint($FF,$FF,$FF,$FF);
         Gear:= Gear^.NextGear
         end;
+    // this level is on the land one when stereo
     1: while Gear <> nil do
         begin
         tinted:= false;
@@ -422,30 +424,60 @@
             vgtSmokeTrace: if Gear^.State < 8 then DrawSprite(sprSmokeTrace, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.State);
             vgtEvilTrace: if Gear^.State < 8 then DrawSprite(sprEvilTrace, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.State);
             vgtLineTrail: DrawLine(Gear^.X, Gear^.Y, Gear^.dX, Gear^.dY, 1.0, $FF, min(Gear^.Timer, $C0), min(Gear^.Timer, $80), min(Gear^.Timer, $FF));
-            vgtSpeechBubble: if (Gear^.Tex <> nil) and (((Gear^.State = 0) and (Gear^.Hedgehog^.Team <> CurrentTeam)) or (Gear^.State = 1)) then 
-                    begin
-                    tinted:= true;
-                    Tint($FF, $FF, $FF,  $66);
-                    DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex)
-                    end
         end;
             if (cReducedQuality and rqAntiBoom) = 0 then
                 case Gear^.Kind of
                     vgtSmoke: DrawSprite(sprSmoke, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame);
                     vgtSmokeWhite: DrawSprite(sprSmokeWhite, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame);
                     vgtDust: DrawSprite(sprDust, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame);
-                    vgtFeather: begin
-                            if Gear^.FrameTicks < 255 then
-                                begin
-                                Tint($FF, $FF, $FF, Gear^.FrameTicks);
-                                tinted:= true
-                                end;
-                            DrawRotatedF(sprFeather, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
-                            end;
+                    vgtFire: if (Gear^.State and gstTmpFlag) = 0 then
+                                 DrawSprite(sprFlame, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy, (RealTicks shr 6 + Gear^.Frame) mod 8)
+                             else
+                                 DrawTextureF(SpritesData[sprFlame].Texture, Gear^.FrameTicks / 900, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, (RealTicks shr 7 + Gear^.Frame) mod 8, 1, 16, 16);
+                    vgtSplash: if SuddenDeathDmg then
+                                   DrawSprite(sprSDSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37))
+                               else
+                                   DrawSprite(sprSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37));
+                    vgtDroplet: if SuddenDeathDmg then
+                                    DrawSprite(sprSDDroplet, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame)
+                                else
+                                    DrawSprite(sprDroplet, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame);
+                    vgtChunk: DrawRotatedF(sprChunk, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
                  end;
         if (Gear^.Tint <> $FFFFFFFF) or tinted then Tint($FF,$FF,$FF,$FF);
         Gear:= Gear^.NextGear
         end;
+    // this level is on the screen plane when stereo (depth = 0)
+    3: while Gear <> nil do
+        begin
+        tinted:= false;
+        if Gear^.Tint <> $FFFFFFFF then Tint(Gear^.Tint);
+        case Gear^.Kind of
+            vgtSpeechBubble: begin
+                           if (Gear^.Tex <> nil) and (((Gear^.State = 0) and (Gear^.Hedgehog^.Team <> CurrentTeam)) or (Gear^.State = 1)) then
+                           begin
+                               tinted:= true;
+                               Tint($FF, $FF, $FF,  $66);
+                               DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex)
+                           end
+                           else if (Gear^.Tex <> nil) and (((Gear^.State = 0) and (Gear^.Hedgehog^.Team = CurrentTeam)) or (Gear^.State = 2)) then
+                               DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex);
+                       end;
+            vgtSmallDamageTag: DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex);
+            vgtHealthTag: if Gear^.Tex <> nil then DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex);
+            vgtHealth: begin
+                       tinted:= true;
+                       case Gear^.Frame div 10 of
+                           0:Tint(0, $FF, 0, round(Gear^.FrameTicks * $FF / 1000));
+                           1:Tint($FF, 0, 0, round(Gear^.FrameTicks * $FF / 1000));
+                       end;
+                       DrawSprite(sprHealth, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, 0);
+                       end;
+        end;
+        if (Gear^.Tint <> $FFFFFFFF) or tinted then Tint($FF,$FF,$FF,$FF);
+        Gear:= Gear^.NextGear
+       end;
+    // this level is outside the screen when stereo
     2: while Gear <> nil do
         begin
         tinted:= false;
@@ -462,10 +494,6 @@
             case Gear^.Kind of
                 vgtExplPart: DrawSprite(sprExplPart, round(Gear^.X) + WorldDx - 16, round(Gear^.Y) + WorldDy - 16, 7 - Gear^.Frame);
                 vgtExplPart2: DrawSprite(sprExplPart2, round(Gear^.X) + WorldDx - 16, round(Gear^.Y) + WorldDy - 16, 7 - Gear^.Frame);
-                vgtFire: if (Gear^.State and gstTmpFlag) = 0 then
-                             DrawSprite(sprFlame, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy, (RealTicks shr 6 + Gear^.Frame) mod 8)
-                         else
-                             DrawTextureF(SpritesData[sprFlame].Texture, Gear^.FrameTicks / 900, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, (RealTicks shr 7 + Gear^.Frame) mod 8, 1, 16, 16);
                 vgtBubble: DrawSprite(sprBubbles, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame);//(RealTicks div 64 + Gear^.Frame) mod 8);
                 vgtSteam: DrawSprite(sprSmokeWhite, round(Gear^.X) + WorldDx - 11, round(Gear^.Y) + WorldDy - 11, 7 - Gear^.Frame);
                 vgtAmmo: begin
@@ -474,14 +502,6 @@
                         DrawTextureF(ropeIconTex, Gear^.scale, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 0, 1, 32, 32);
                         DrawTextureF(SpritesData[sprAMAmmos].Texture, Gear^.scale * 0.90, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame - 1, 1, 32, 32);
                         end;
-                vgtHealth:  begin
-                            tinted:= true;
-                            case Gear^.Frame div 10 of
-                                0:Tint(0, $FF, 0, round(Gear^.FrameTicks * $FF / 1000));
-                                1:Tint($FF, 0, 0, round(Gear^.FrameTicks * $FF / 1000));
-                            end;
-                            DrawSprite(sprHealth, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, 0);
-                            end;
                 vgtShell: begin
                             if Gear^.FrameTicks < $FF then
                                 begin
@@ -490,7 +510,15 @@
                                 end;
                             DrawRotatedF(sprShell, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
                             end;
-                  vgtEgg: begin
+                vgtFeather: begin
+                            if Gear^.FrameTicks < 255 then
+                                begin
+                                Tint($FF, $FF, $FF, Gear^.FrameTicks);
+                                tinted:= true
+                                end;
+                            DrawRotatedF(sprFeather, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
+                          end;
+                vgtEgg: begin
                             if Gear^.FrameTicks < $FF then
                                 begin
                                 Tint($FF, $FF, $FF, Gear^.FrameTicks);
@@ -498,14 +526,6 @@
                                 end;
                             DrawRotatedF(sprEgg, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
                             end;
-                 vgtSplash: if SuddenDeathDmg then
-                                DrawSprite(sprSDSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37))
-                            else
-                                DrawSprite(sprSplash, round(Gear^.X) + WorldDx - 40, round(Gear^.Y) + WorldDy - 58, 19 - (Gear^.FrameTicks div 37));
-                vgtDroplet: if SuddenDeathDmg then
-                                DrawSprite(sprSDDroplet, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame)
-                            else
-                                DrawSprite(sprDroplet, round(Gear^.X) + WorldDx - 8, round(Gear^.Y) + WorldDy - 8, Gear^.Frame);
                vgtBeeTrace: begin
                             if Gear^.FrameTicks < $FF then
                                 Tint($FF, $FF, $FF, Gear^.FrameTicks div 2)
@@ -519,14 +539,10 @@
                             Tint($FF, $FF, $FF, round(Gear^.alpha * $FF));
                             DrawRotatedTextureF(SpritesData[sprSmokeRing].Texture, Gear^.scale, 0, 0, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, 0, 1, 200, 200, Gear^.Angle);
                             end;
-                vgtChunk: DrawRotatedF(sprChunk, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
                  vgtNote: DrawRotatedF(sprNote, round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Frame, 1, Gear^.Angle);
                 vgtBulletHit: DrawRotatedF(sprBulletHit, round(Gear^.X) + WorldDx - 0, round(Gear^.Y) + WorldDy - 0, 7 - (Gear^.FrameTicks div 50), 1, Gear^.Angle);
             end;
         case Gear^.Kind of
-            vgtSmallDamageTag: DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex);
-            vgtSpeechBubble: if (Gear^.Tex <> nil) and (((Gear^.State = 0) and (Gear^.Hedgehog^.Team = CurrentTeam)) or (Gear^.State = 2)) then DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex);
-            vgtHealthTag: if Gear^.Tex <> nil then DrawCentered(round(Gear^.X) + WorldDx, round(Gear^.Y) + WorldDy, Gear^.Tex);
             vgtCircle:  if gear^.Angle = 1 then 
                             begin
                             tmp:= Gear^.State / 100;
--- a/hedgewars/uWorld.pas	Sun Jan 16 13:53:32 2011 -0500
+++ b/hedgewars/uWorld.pas	Mon Jan 17 01:43:10 2011 +0100
@@ -27,6 +27,7 @@
 
 procedure InitWorld;
 procedure DrawWorld(Lag: LongInt);
+procedure DrawWorldStereo(Lag: LongInt; RM: TRenderMode);
 procedure ShowMission(caption, subcaption, text: ansistring; icon, time : LongInt);
 procedure HideMission;
 procedure ShakeCamera(amount: LongWord);
@@ -63,6 +64,14 @@
     amSel: TAmmoType = amNothing;
     missionTex: PTexture;
     missionTimer: LongInt;
+    stereoDepth: GLfloat = 0;
+
+const cStereo_Sky           = 0.0500;
+      cStereo_Horizon       = 0.0250;
+      cStereo_Water_distant = 0.0125;
+      cStereo_Land          = 0.0075;
+      cStereo_Water_near    = 0.0025;
+      cStereo_Outside       = 0.0400;
 
 procedure InitWorld;
 var i, t: LongInt;
@@ -555,13 +564,6 @@
 
 
 procedure DrawWorld(Lag: LongInt);
-var i, t: LongInt;
-    r: TSDL_Rect;
-    tdx, tdy: Double;
-    s: string[15];
-    highlight: Boolean;
-    offsetX, offsetY, ScreenBottom: LongInt;
-    VertexBuffer: array [0..3] of TVertex2f;
 begin
     if not isPaused then
     begin
@@ -590,6 +592,160 @@
     if not isPaused then
         MoveCamera;
 
+    if cStereoMode = smNone then
+        begin
+        glClear(GL_COLOR_BUFFER_BIT);
+        DrawWorldStereo(Lag, rmDefault)
+        end
+{$IFNDEF S3D_DISABLED}
+    else if (cStereoMode = smAFR) then
+        begin
+        AFRToggle:= not AFRToggle;
+        glClear(GL_COLOR_BUFFER_BIT);
+        if AFRToggle then
+            DrawWorldStereo(Lag, rmLeftEye)
+        else
+            DrawWorldStereo(Lag, rmRightEye)
+        end
+    else if (cStereoMode = smHorizontal) or (cStereoMode = smVertical) then
+        begin
+        // create left fb
+        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framel);
+        glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+        DrawWorldStereo(Lag, rmLeftEye);
+
+        // create right fb
+        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, framer);
+        glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+        DrawWorldStereo(0, rmRightEye);
+
+        // detatch drawing from fbs
+        glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
+        glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+        SetScale(cDefaultZoomLevel);
+
+        // draw left frame
+        glBindTexture(GL_TEXTURE_2D, texl);
+        glBegin(GL_QUADS);
+            if cStereoMode = smHorizontal then
+                begin
+                glTexCoord2f(0.0, 0.0);
+                glVertex2d(cScreenWidth / -2, cScreenHeight);
+                glTexCoord2f(1.0, 0.0);
+                glVertex2d(0, cScreenHeight);
+                glTexCoord2f(1.0, 1.0);
+                glVertex2d(0, 0);
+                glTexCoord2f(0.0, 1.0);
+                glVertex2d(cScreenWidth / -2, 0);
+                end
+            else
+                begin
+                glTexCoord2f(0.0, 0.0);
+                glVertex2d(cScreenWidth / -2, cScreenHeight / 2);
+                glTexCoord2f(1.0, 0.0);
+                glVertex2d(cScreenWidth / 2, cScreenHeight / 2);
+                glTexCoord2f(1.0, 1.0);
+                glVertex2d(cScreenWidth / 2, 0);
+                glTexCoord2f(0.0, 1.0);
+                glVertex2d(cScreenWidth / -2, 0);
+                end;
+        glEnd();
+
+        // draw right frame
+        glBindTexture(GL_TEXTURE_2D, texr);
+        glBegin(GL_QUADS);
+            if cStereoMode = smHorizontal then
+                begin
+                glTexCoord2f(0.0, 0.0);
+                glVertex2d(0, cScreenHeight);
+                glTexCoord2f(1.0, 0.0);
+                glVertex2d(cScreenWidth / 2, cScreenHeight);
+                glTexCoord2f(1.0, 1.0);
+                glVertex2d(cScreenWidth / 2, 0);
+                glTexCoord2f(0.0, 1.0);
+                glVertex2d(0, 0);
+                end
+            else
+                begin
+                glTexCoord2f(0.0, 0.0);
+                glVertex2d(cScreenWidth / -2, cScreenHeight);
+                glTexCoord2f(1.0, 0.0);
+                glVertex2d(cScreenWidth / 2, cScreenHeight);
+                glTexCoord2f(1.0, 1.0);
+                glVertex2d(cScreenWidth / 2, cScreenHeight / 2);
+                glTexCoord2f(0.0, 1.0);
+                glVertex2d(cScreenWidth / -2, cScreenHeight / 2);
+                end;
+        glEnd();
+        SetScale(zoom);
+        end
+    else
+        begin
+        // clear scene
+        glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
+        glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
+        // draw left eye in red channel only
+        if cStereoMode = smGreenRed then
+            glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE)
+        else if cStereoMode = smBlueRed then
+            glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE)
+        else if cStereoMode = smCyanRed then
+            glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE)
+        else
+            glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
+        DrawWorldStereo(Lag, rmLeftEye);
+        // draw right eye in selected channel(s) only
+        if cStereoMode = smRedGreen then
+            glColorMask(GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE)
+        else if cStereoMode = smRedBlue then
+            glColorMask(GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE)
+        else if cStereoMode = smRedCyan then
+            glColorMask(GL_FALSE, GL_TRUE, GL_TRUE, GL_TRUE)
+        else
+            glColorMask(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE);
+        DrawWorldStereo(Lag, rmRightEye);
+        end
+{$ENDIF}
+end;
+
+procedure ChangeDepth(rm: TRenderMode; d: GLfloat);
+begin
+{$IFDEF S3D_DISABLED}
+    exit;
+{$ELSE}
+    d:= d / 5;
+    if rm = rmDefault then exit
+    else if rm = rmLeftEye then d:= -d;
+    stereoDepth:= stereoDepth + d;
+    glMatrixMode(GL_PROJECTION);
+    glTranslatef(d, 0, 0);
+    glMatrixMode(GL_MODELVIEW);
+{$ENDIF}
+end;
+ 
+procedure ResetDepth(rm: TRenderMode);
+begin
+{$IFDEF S3D_DISABLED}
+    exit;
+{$ELSE}
+    if rm = rmDefault then exit;
+    glMatrixMode(GL_PROJECTION);
+    glTranslatef(-stereoDepth, 0, 0);
+    glMatrixMode(GL_MODELVIEW);
+    stereoDepth:= 0;
+{$ENDIF}
+end;
+ 
+procedure DrawWorldStereo(Lag: LongInt; RM: TRenderMode);
+var i, t: LongInt;
+    r: TSDL_Rect;
+    tdx, tdy: Double;
+    grp: TCapGroup;
+    s: string[15];
+    highlight: Boolean;
+    offset, offsetX, offsetY, screenBottom: LongInt;
+    VertexBuffer: array [0..3] of TVertex2f;
+begin
     if (cReducedQuality and rqNoBackground) = 0 then
     begin
         // Offsets relative to camera - spare them to wimpier cpus, no bg or flakes for them anyway
@@ -601,8 +757,10 @@
             HorizontOffset:= HorizontOffset + ((ScreenBottom-SkyOffset) div 20);
 
         // background
+        ChangeDepth(RM, cStereo_Sky);
         if SuddenDeathDmg then Tint(SDTint, SDTint, SDTint, $FF);
         DrawRepeated(sprSky, sprSkyL, sprSkyR, (WorldDx + LAND_WIDTH div 2) * 3 div 8, SkyOffset);
+        ChangeDepth(RM, -cStereo_Horizon);
         DrawRepeated(sprHorizont, sprHorizontL, sprHorizontR, (WorldDx + LAND_WIDTH div 2) * 3 div 5, HorizontOffset);
         if SuddenDeathDmg then Tint($FF, $FF, $FF, $FF);
     end;
@@ -612,15 +770,20 @@
     if (cReducedQuality and rq2DWater) = 0 then
     begin
         // Waves
-        DrawWater(255, SkyOffset);
+        DrawWater(255, SkyOffset); 
+        ChangeDepth(RM, -cStereo_Water_distant);
         DrawWaves( 1,  0 - WorldDx div 32, - cWaveHeight + offsetY div 35, 64);
+        ChangeDepth(RM, -cStereo_Water_distant);
         DrawWaves( -1,  25 + WorldDx div 25, - cWaveHeight + offsetY div 38, 48);
+        ChangeDepth(RM, -cStereo_Water_distant);
         DrawWaves( 1,  75 - WorldDx div 19, - cWaveHeight + offsetY div 45, 32);
+        ChangeDepth(RM, -cStereo_Water_distant);
         DrawWaves(-1, 100 + WorldDx div 14, - cWaveHeight + offsetY div 70, 24);
     end
     else
         DrawWaves(-1, 100, - (cWaveHeight + (cWaveHeight shr 1)), 0);
 
+    changeDepth(RM, cStereo_Land);
     DrawLand(WorldDx, WorldDy);
 
     DrawWater(255, 0);
@@ -648,37 +811,47 @@
         end;
 
     DrawVisualGears(1);
-
     DrawGears;
 
-    DrawVisualGears(2);
-
     if SuddenDeathDmg then
         DrawWater(cSDWaterOpacity, 0)
     else
         DrawWater(cWaterOpacity, 0);
 
     // Waves
+    ChangeDepth(RM, cStereo_Water_near);
     DrawWaves( 1, 25 - WorldDx div 9, - cWaveHeight, 12);
 
     if (cReducedQuality and rq2DWater) = 0 then
     begin
         //DrawWater(cWaterOpacity, - offsetY div 40);
+        ChangeDepth(RM, cStereo_Water_near);
         DrawWaves(-1, 50 + WorldDx div 6, - cWaveHeight - offsetY div 40, 8);
         if SuddenDeathDmg then
             DrawWater(cSDWaterOpacity, - offsetY div 20)
         else
             DrawWater(cWaterOpacity, - offsetY div 20);
+        ChangeDepth(RM, cStereo_Water_near);
         DrawWaves( 1, 75 - WorldDx div 4, - cWaveHeight - offsetY div 20, 2);
         if SuddenDeathDmg then
             DrawWater(cSDWaterOpacity, - offsetY div 10)
         else
             DrawWater(cWaterOpacity, - offsetY div 10);
+        ChangeDepth(RM, cStereo_Water_near);
         DrawWaves( -1, 25 + WorldDx div 3, - cWaveHeight - offsetY div 10, 0);
     end
     else
         DrawWaves(-1, 50, - (cWaveHeight shr 1), 0);
 
+// everything after this ChangeDepth will be drawn outside the screen
+// note: negative parallax gears should last very little for a smooth stereo effect
+    ChangeDepth(RM, cStereo_Outside);
+    DrawVisualGears(2);
+
+// everything after this ResetDepth will be drawn at screen level (depth = 0)
+// note: everything that needs to be readable should be on this level
+    ResetDepth(RM);
+    DrawVisualGears(3);
 
 {$WARNINGS OFF}
 // Target
@@ -697,7 +870,6 @@
 // this scale is used to keep the various widgets at the same dimension at all zoom levels
 SetScale(cDefaultZoomLevel);
 
-
 // Turn time
 {$IFDEF IPHONEOS}
 offsetX:= cScreenHeight - 13;
@@ -750,7 +922,7 @@
       r.h:= HealthTex^.h;
       DrawFromRect(14, cScreenHeight + DrawHealthY, @r, HealthTex);
 
-      // draw health bar's right border
+      // draw health bars right border
       inc(r.x, cTeamHealthWidth + 2);
       r.w:= 3;
       DrawFromRect(TeamHealthBarWidth + 16, cScreenHeight + DrawHealthY, @r, HealthTex);
@@ -825,8 +997,10 @@
 if isCursorVisible and bShowAmmoMenu then
    DrawSprite(sprArrow, CursorPoint.X, cScreenHeight - CursorPoint.Y, (RealTicks shr 6) mod 8);
 
+// Chat
 DrawChat;
 
+// confirmation caption
 if fastUntilLag then DrawCentered(0, (cScreenHeight shr 1), SyncTexture);
 if isPaused then DrawCentered(0, (cScreenHeight shr 1), PauseTexture);
 if not isFirstFrame and (missionTimer <> 0) or isPaused or fastUntilLag or (GameState = gsConfirm) then
@@ -844,58 +1018,63 @@
 offsetX:= 10;
 {$ENDIF}
 offsetY:= cOffsetY;
-inc(Frames);
+if (RM = rmDefault) or (RM = rmRightEye) then
+begin
+    inc(Frames);
 
-if cShowFPS or (GameType = gmtDemo) then inc(CountTicks, Lag);
-if (GameType = gmtDemo) and (CountTicks >= 1000) then
-   begin
-   i:=GameTicks div 1000;
-   t:= i mod 60;
-   s:= inttostr(t);
-   if t < 10 then s:= '0' + s;
-   i:= i div 60;
-   t:= i mod 60;
-   s:= inttostr(t) + ':' + s;
-   if t < 10 then s:= '0' + s;
-   s:= inttostr(i div 60) + ':' + s;
-
-   if timeTexture <> nil then
-        FreeTexture(timeTexture);
-    timeTexture:= nil;
-
-   tmpSurface:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar(s), cWhiteColorChannels);
-   tmpSurface:= doSurfaceConversion(tmpSurface);
-   timeTexture:= Surface2Tex(tmpSurface, false);
-   SDL_FreeSurface(tmpSurface)
-   end;
+    if cShowFPS or (GameType = gmtDemo) then
+        inc(CountTicks, Lag);
+    if (GameType = gmtDemo) and (CountTicks >= 1000) then
+    begin
+        i:=GameTicks div 1000;
+        t:= i mod 60;
+        s:= inttostr(t);
+        if t < 10 then s:= '0' + s;
+        i:= i div 60;
+        t:= i mod 60;
+        s:= inttostr(t) + ':' + s;
+        if t < 10 then s:= '0' + s;
+        s:= inttostr(i div 60) + ':' + s;
+   
+        if timeTexture <> nil then
+            FreeTexture(timeTexture);
+        timeTexture:= nil;
+    
+        tmpSurface:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar(s), cWhiteColorChannels);
+        tmpSurface:= doSurfaceConversion(tmpSurface);
+        timeTexture:= Surface2Tex(tmpSurface, false);
+        SDL_FreeSurface(tmpSurface)
+    end;
 
-if timeTexture <> nil then
-   DrawTexture((cScreenWidth shr 1) - 20 - timeTexture^.w - offsetY, offsetX + timeTexture^.h+5, timeTexture);
+    if timeTexture <> nil then
+        DrawTexture((cScreenWidth shr 1) - 20 - timeTexture^.w - offsetY, offsetX + timeTexture^.h+5, timeTexture);
 
-if cShowFPS then
-   begin
-   if CountTicks >= 1000 then
-      begin
-      FPS:= Frames;
-      Frames:= 0;
-      CountTicks:= 0;
-      s:= inttostr(FPS) + ' fps';
-      if fpsTexture <> nil then
-        FreeTexture(fpsTexture);
-    fpsTexture:= nil;
-      tmpSurface:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar(s), cWhiteColorChannels);
-      tmpSurface:= doSurfaceConversion(tmpSurface);
-      fpsTexture:= Surface2Tex(tmpSurface, false);
-      SDL_FreeSurface(tmpSurface)
-      end;
-   if fpsTexture <> nil then
-      DrawTexture((cScreenWidth shr 1) - 60 - offsetY, offsetX, fpsTexture);
-   end;
+    if cShowFPS then
+    begin
+        if CountTicks >= 1000 then
+        begin
+            FPS:= Frames;
+            Frames:= 0;
+            CountTicks:= 0;
+            s:= inttostr(FPS) + ' fps';
+            if fpsTexture <> nil then
+                FreeTexture(fpsTexture);
+            fpsTexture:= nil;
+            tmpSurface:= TTF_RenderUTF8_Blended(Fontz[fnt16].Handle, Str2PChar(s), cWhiteColorChannels);
+            tmpSurface:= doSurfaceConversion(tmpSurface);
+            fpsTexture:= Surface2Tex(tmpSurface, false);
+            SDL_FreeSurface(tmpSurface)
+        end;
+        if fpsTexture <> nil then
+            DrawTexture((cScreenWidth shr 1) - 60 - offsetY, offsetX, fpsTexture);
+    end;
 
-if CountTicks >= 1000 then CountTicks:= 0;
+    if CountTicks >= 1000 then CountTicks:= 0;
 
-// lag warning (?)
-inc(SoundTimerTicks, Lag);
+    // lag warning (?)
+    inc(SoundTimerTicks, Lag);
+end;
+
 if SoundTimerTicks >= 50 then
    begin
    SoundTimerTicks:= 0;
--- a/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj	Sun Jan 16 13:53:32 2011 -0500
+++ b/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj	Mon Jan 17 01:43:10 2011 +0100
@@ -934,7 +934,7 @@
 		61798934114AB25F00BA94A9 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
 		6179898B114AB3FA00BA94A9 /* SDL_mixer.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SDL_mixer.xcodeproj; path = "../../../Library/SDL-1.3/SDL_mixer/Xcode-iPhoneOS/SDL_mixer.xcodeproj"; sourceTree = SOURCE_ROOT; };
 		61798A0B114AB65600BA94A9 /* SDL_ttf.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = SDL_ttf.xcodeproj; path = "../../../Library/SDL-1.3/SDL_ttf/Xcode-iPhoneOS/SDL_ttf.xcodeproj"; sourceTree = SOURCE_ROOT; };
-		61798A5E114AE08600BA94A9 /* Data */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Data; sourceTree = "<group>"; };
+		61798A5E114AE08600BA94A9 /* Data */ = {isa = PBXFileReference; lastKnownFileType = folder; name = Data; path = ../../../trunk/project_files/HedgewarsMobile/Data; sourceTree = "<group>"; };
 		6183D83C11E2BCE200A88903 /* Default-ipad-Landscape.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Default-ipad-Landscape.png"; path = "Resources/Icons/Default-ipad-Landscape.png"; sourceTree = "<group>"; };
 		6183D83D11E2BCE200A88903 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = Default.png; path = Resources/Icons/Default.png; sourceTree = "<group>"; };
 		61842B23122B619D0096E335 /* HelpPageInGameViewController-iPad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "HelpPageInGameViewController-iPad.xib"; path = "../Resources/HelpPageInGameViewController-iPad.xib"; sourceTree = "<group>"; };