aboutsummaryrefslogblamecommitdiffstats
path: root/src/Menu/UDisplay.pas
blob: 2b10b2c6a2e2f19c909a3538ed7e52ee1f225d96 (plain) (tree)























                           





                                                                                                











                                     
                  


                                 
                                                                                    




























                                    




                               

                             


                               


                                      
 
                             
 
                    
       
                                             
                                                                     
                                                                     

      





                                     
                                    




                                

                        

                        


                 
                            

                                                      

                          

                   


                                                      



                                                                             
                 


                                      
                                           
           


                                          


           

                                                   


          
                                                            



                         
                                                                    
                             
                                                                         


                              




                                                         


         

                                                
           
                             
          

                                              
           
                                                      
                             
             

                                                        
                                     

                                           
                             






                                                                                
                                                                         
                                  

                                          

                                                                                        
              


                             
 



                                 



                                          


                                                         

                                                           
             

                                      

            


                                             
                                  




                                                              






                                                           



                                                          



                                                                                   









                                  



                                                                               
                             

                                          
                          
                               





                                           
                          

                



                                                            

                                                           
             

    









                                  



                                                        






















































































                                                                                  
unit UDisplay;

interface

{$IFDEF FPC}
  {$MODE Delphi}
{$ENDIF}

{$I switches.inc}

uses
  ucommon,
  SDL,
  UMenu,
  gl,
  glu,
  SysUtils;

type
  TDisplay = class
    private
      //fade-to-black-hack
      BlackScreen: Boolean;

      FadeEnabled:  Boolean;  // true if fading is enabled
      FadeFailed: Boolean;    // true if fading is possible (enough memory, etc.)
      FadeState: integer;     // fading state, 0 means that the fade texture must be initialized
      LastFadeTime: Cardinal; // last fade update time

      FadeTex: array[1..2] of GLuint;

      FPSCounter    : Cardinal;
      LastFPS       : Cardinal;
      NextFPSSwap   : Cardinal;

      OSD_LastError : String;

      procedure DrawDebugInformation;
    public
      NextScreen   : PMenu;
      CurrentScreen : PMenu;

      //popup data
      NextScreenWithCheck: Pmenu;
      CheckOK  : Boolean;

      // FIXME: Fade is set to 0 in UMain and other files but not used here anymore.
      Fade     : Real;

      constructor Create;
      destructor  Destroy; override;

      procedure SaveScreenShot;

      function  Draw: Boolean;
  end;

var
  Display:          TDisplay;

implementation

uses
  UImage,
  TextGL,
  ULog,
  UMain,
  UTexture,
  UIni,
  UGraphic,
  UTime,
  UCommandLine;

constructor TDisplay.Create;
var
  i: integer;
begin
  inherited Create;

  //popup hack
  CheckOK             := False;
  NextScreen          := nil;
  NextScreenWithCheck := nil;
  BlackScreen         := False;

  // fade mod
  FadeState := 0;
  FadeEnabled := (Ini.ScreenFade = 1);
  FadeFailed:= false;

  glGenTextures(2, @FadeTex);

  for i := 1 to 2 do
  begin
    glBindTexture(GL_TEXTURE_2D, FadeTex[i]);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  end;

  //Set LastError for OSD to No Error
  OSD_LastError := 'No Errors';
end;

destructor TDisplay.Destroy;
begin
  glDeleteTextures(2, @FadeTex);    
  inherited Destroy;
end;

function TDisplay.Draw: Boolean;
var
  S: integer;
  FadeStateSquare: Real;
  currentTime: Cardinal;
  glError: glEnum;
begin
  Result := True;

  glClearColor(1, 1, 1 , 0);
  glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);

  for S := 1 to Screens do
  begin
    ScreenAct := S;

    //if Screens = 1 then ScreenX := 0;
    //if (Screens = 2) and (S = 1) then ScreenX := -1;
    //if (Screens = 2) and (S = 2) then ScreenX := 1;
    ScreenX := 0;

    glViewPort((S-1) * ScreenW div Screens, 0, ScreenW div Screens, ScreenH);

    // popup hack
    // check was successful... move on
    if CheckOK then
    begin
      if assigned(NextScreenWithCheck) then
      begin
        NextScreen := NextScreenWithCheck;
        NextScreenWithCheck := nil;
        CheckOk := False;
      end
      else
      begin
        // on end of game fade to black before exit
        BlackScreen := True;
      end;
    end;

    if (not assigned(NextScreen)) and (not BlackScreen) then
    begin
      CurrentScreen.Draw;

      //popup mod
      if (ScreenPopupError <> nil) and ScreenPopupError.Visible then
        ScreenPopupError.Draw
      else if (ScreenPopupCheck <> nil) and ScreenPopupCheck.Visible then
        ScreenPopupCheck.Draw;

      // fade mod
      FadeState := 0;
      if ((Ini.ScreenFade = 1) and (not FadeFailed)) then
        FadeEnabled := True
      else if (Ini.ScreenFade = 0) then
        FadeEnabled := False;
    end
    else
    begin
      // disable fading if initialization failed
      if (FadeEnabled and FadeFailed) then
      begin
        FadeEnabled := False;
      end;
      
      if (FadeEnabled and not FadeFailed) then
      begin
        //Create Fading texture if we're just starting
        if FadeState = 0 then
        begin
          // save old viewport and resize to fit texture
          glPushAttrib(GL_VIEWPORT_BIT);
          glViewPort(0, 0, 512, 512);

          // draw screen that will be faded
          CurrentScreen.Draw;

          // clear OpenGL errors, otherwise fading might be disabled due to some
          // older errors in previous OpenGL calls.
          glGetError();

          // copy screen to texture
          glBindTexture(GL_TEXTURE_2D, FadeTex[S]);
          glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, 512, 512, 0);
          glError := glGetError();
          if (glError <> GL_NO_ERROR) then
          begin
            FadeFailed := true;
            Log.LogWarn('Fading disabled: ' + gluErrorString(glError), 'TDisplay.Draw');
          end;

          // restore viewport
          glPopAttrib();

          // blackscreen-hack
          if not BlackScreen then
            NextScreen.onShow;

          // update fade state
          LastFadeTime := SDL_GetTicks();
          if (S = 2) or (Screens = 1) then
            FadeState := FadeState + 1;
        end; // end texture creation in first fading step

        //do some time-based fading
        currentTime := SDL_GetTicks();
        if (currentTime > LastFadeTime+30) and (S = 1) then
        begin
          FadeState := FadeState + 4;
          LastFadeTime := currentTime;
        end;

        // blackscreen-hack
        if not BlackScreen then
          NextScreen.Draw // draw next screen
        else if ScreenAct = 1 then
        begin
          glClearColor(0, 0, 0 , 0);
          glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
        end;

        // and draw old screen over it... slowly fading out

        FadeStateSquare := (FadeState*FadeState)/10000;

        glBindTexture(GL_TEXTURE_2D, FadeTex[S]);
        glColor4f(1, 1, 1, 1-FadeStateSquare);

        glEnable(GL_TEXTURE_2D);
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
        glEnable(GL_BLEND);
        glBegin(GL_QUADS);
          glTexCoord2f(0+FadeStateSquare, 0+FadeStateSquare); glVertex2f(0,   600);
          glTexCoord2f(0+FadeStateSquare, 1-FadeStateSquare); glVertex2f(0,   0);
          glTexCoord2f(1-FadeStateSquare, 1-FadeStateSquare); glVertex2f(800, 0);
          glTexCoord2f(1-FadeStateSquare, 0+FadeStateSquare); glVertex2f(800, 600);
        glEnd;
        glDisable(GL_BLEND);
        glDisable(GL_TEXTURE_2D);
      end
      // blackscreen hack
      else if not BlackScreen then
      begin
        NextScreen.OnShow;
      end;

      if ((FadeState > 40) or (not FadeEnabled) or FadeFailed) and (S = 1) then
      begin
        // fade out complete...
        FadeState := 0;
        CurrentScreen.onHide;
        CurrentScreen.ShowFinish := False;
        CurrentScreen := NextScreen;
        NextScreen := nil;
        if not BlackScreen then
        begin
          CurrentScreen.onShowFinish;
          CurrentScreen.ShowFinish := true;
        end
        else
        begin
          Result := False;
          Break;
        end;
      end;
    end; // if

    //Draw OSD only on first Screen if Debug Mode is enabled
    if ((Ini.Debug = 1) or (Params.Debug)) and (S = 1) then
      DrawDebugInformation;      
  end; // for
end;

procedure TDisplay.SaveScreenShot;
var
  Num:        integer;
  FileName:   string;
  ScreenData: PChar;
  Surface:    PSDL_Surface;
  Success:    boolean;
  Align:      integer;
  RowSize:    integer;
begin
  // Exit if Screenshot-path does not exist or read-only
  if (ScreenshotsPath = '') then
    Exit;

  for Num := 1 to 9999 do
  begin
    FileName := IntToStr(Num);
    while Length(FileName) < 4 do
      FileName := '0' + FileName;
    FileName := ScreenshotsPath + 'screenshot' + FileName + '.png';
    if not FileExists(FileName) then
      break
  end;

  // we must take the row-alignment (4byte by default) into account
  glGetIntegerv(GL_PACK_ALIGNMENT, @Align);
  // calc aligned row-size
  RowSize := ((ScreenW*3 + (Align-1)) div Align) * Align;

  GetMem(ScreenData, RowSize * ScreenH);
  glReadPixels(0, 0, ScreenW, ScreenH, GL_RGB, GL_UNSIGNED_BYTE, ScreenData);
  Surface := SDL_CreateRGBSurfaceFrom(
      ScreenData, ScreenW, ScreenH, 24, RowSize,
      $0000FF, $00FF00, $FF0000, 0);

  //Success := WriteJPGImage(FileName, Surface, 95);
  //Success := WriteBMPImage(FileName, Surface);
  Success := WritePNGImage(FileName, Surface);
  if Success then
    ScreenPopupError.ShowPopup('Screenshot saved: ' + ExtractFileName(FileName))
  else
    ScreenPopupError.ShowPopup('Screenshot failed');

  SDL_FreeSurface(Surface);
  FreeMem(ScreenData);
end;

//------------
// DrawDebugInformation - Procedure draw FPS and some other Informations on Screen
//------------
procedure TDisplay.DrawDebugInformation;
var Ticks: Cardinal;
begin
  //Some White Background for information
  glEnable(GL_BLEND);
  glDisable(GL_TEXTURE_2D);
  glColor4f(1, 1, 1, 0.5);
  glBegin(GL_QUADS);
    glVertex2f(690, 44);
    glVertex2f(690, 0);
    glVertex2f(800, 0);
    glVertex2f(800, 44);
  glEnd;
  glDisable(GL_BLEND);

  //Set Font Specs
  SetFontStyle(0);
  SetFontSize(7);
  SetFontItalic(False);
  glColor4f(0, 0, 0, 1);

  //Calculate FPS
  Ticks := SDL_GetTicks();
  if (Ticks >= NextFPSSwap) then
  begin
    LastFPS := FPSCounter * 4;
    FPSCounter := 0;
    NextFPSSwap := Ticks + 250;
  end;

  Inc(FPSCounter);

  //Draw Text

  //FPS
  SetFontPos(695, 0);
  glPrint (PChar('FPS: ' + InttoStr(LastFPS)));

  //RSpeed
  SetFontPos(695, 13);
  glPrint (PChar('RSpeed: ' + InttoStr(Round(1000 * TimeMid))));

  //LastError
  SetFontPos(695, 26);
  glColor4f(1, 0, 0, 1);
  glPrint (PChar(OSD_LastError));

  glColor4f(1, 1, 1, 1);
end;

end.