unit uMainMenu;

interface

uses uStateManager;

var MainMenuScene : rState;

implementation

uses  QuadEngine,
      direct3d9,
      Windows,
      uQEHelp,
      uSMath,
      uConst,
      uVar,
      uStarsFon,
      uGame,
      uCommonGameTypes,
      uEnemies;

const
  ACCELERATION_STARS_TIME = 1.500;
  SHOW_APPNAME_TIME       = 2.000;
  HIDE_APPNAME_TIME       = 2.000;

var startTime : Double;

    accelStars: Boolean;

    GradientX   : Single;
    showAppName : Boolean;
    drawAppName : Boolean;
    hideAppName : Boolean;

    waitShips   : Boolean;
    goToGame    : Boolean;

    Ships : array [ 1 .. 4 ] of cEnemy_1;

procedure MainMenuInit( param: Pointer );
var eparam : rEnemyInitParam;
begin
  Ships[ 1 ] := cEnemy_1.Create;
  Ships[ 2 ] := cEnemy_1.Create;
  Ships[ 3 ] := cEnemy_1.Create;
  Ships[ 4 ] := cEnemy_1.Create;

  currentSpeed := Vec2f( -AppScrH * STARS_SPEED_COF, 0 );
  GradientX   := 0.0;
  showAppName := False;
  drawAppName := False;
  hideAppName := False;
  goToGame    := False;

  if param = nil then begin
    accelStars  := True;
    showAppName := False;
  end else begin
    accelStars  := False;
    showAppName := True;

    eparam.game := nil;
    eparam.moveType := 8;
    Ships[ 1 ].Init( @eparam );
    eparam.moveType := 9;
    Ships[ 2 ].Init( @eparam );
    eparam.moveType := 10;
    Ships[ 3 ].Init( @eparam );
    eparam.moveType := 11;
    Ships[ 4 ].Init( @eparam );
  end;

  startTime   := Timer.GetWholeTime;
end;

procedure MainMenuDraw;
begin
  Quad.BeginRender;
    Quad.RenderToTexture( True, 0 );
      Quad.Rectangle( 0, 0, AppScrW, AppScrH,
                      GetARGB( 255, 0, 0, 0 ), GetARGB( 255, 0, 0, 0 ),
                      GetARGB( 255, 0, 52, 104 ), GetARGB( 255, 0, 52, 104 ) );
      Quad.SetBlendMode( qbmSrcAlpha );
      DrawAllStars;
    Quad.RenderToTexture( False, 0 );

    Quad.SetBlendMode( qbmNone );
    Quad.RenderToTexture( True, 1 );
      StarsBloomShader.SetShaderState( UseShaders );
        ScreenBuf_0.Draw( 0, 0, $FFFFFFFF );
      StarsBloomShader.SetShaderState( False );
    Quad.RenderToTexture( False, 1 );

    Quad.RenderToTexture( True, 2 );
      ScreenBuf_1.Draw( 0, 0, $FFFFFFFF );
      if showAppName or drawAppName then begin
        Quad.RenderToTexture( True, 0 );
          Quad.Clear( $00FFFFFF );
          Quad.SetBlendMode( qbmSrcAlpha );

          Font_2.TextOutCentered( AppScrW * 0.5, AppScrH * 0.065, 1, GameNameString, $FFFFFFFF );
          Font_1.TextOutCentered( AppScrW * 0.5, AppScrH * 0.9, 1, MenuNewGameString, $FFFFFFFF );

          if showAppName or hideAppName then begin
            Quad.SetBlendMode( qbmSrcAlphaMul );
            if showAppName then begin
              Quad.Rectangle( GradientX, 0, GradientX + AppScrW, AppScrH, $FF000000 );
              Quad.Rectangle( GradientX + AppScrW, 0, GradientX + 1.2 * AppScrW, AppScrH,
                              GetARGB( 255, 0, 0, 0 ), GetARGB( 0, 0, 0, 0 ),
                              GetARGB( 255, 0, 0, 0 ), GetARGB( 0, 0, 0, 0 ) );
            end;
            if hideAppName then begin
              Quad.Rectangle( GradientX, 0, GradientX + 0.2 * AppScrW, AppScrH,
                              GetARGB( 0, 0, 0, 0 ), GetARGB( 255, 0, 0, 0 ),
                              GetARGB( 0, 0, 0, 0 ), GetARGB( 255, 0, 0, 0 ) );
              Quad.Rectangle( GradientX + 0.2 * AppScrW, 0, GradientX + 1.2 * AppScrW, AppScrH, $FF000000 );
            end;
          end;
        Quad.RenderToTexture( False, 0 );
      end;
    Quad.RenderToTexture( False, 2 );

    Quad.RenderToTexture( True, 6 );
      Quad.Clear( 0 );
      if not accelStars then begin
        Quad.SetTextureFiltering( D3DTEXF_POINT );
          Quad.SetBlendMode( qbmSrcAlpha );
          if Assigned( Ships[ 1 ] ) then Ships[ 1 ].Draw( 1 );
          if Assigned( Ships[ 2 ] ) then Ships[ 2 ].Draw( 1 );
          if Assigned( Ships[ 3 ] ) then Ships[ 3 ].Draw( 1 );
          if Assigned( Ships[ 4 ] ) then Ships[ 4 ].Draw( 1 );
          Quad.SetBlendMode( qbmSrcAlphaAdd );
          if Assigned( Ships[ 1 ] ) then Ships[ 1 ].Draw( 2 );
          if Assigned( Ships[ 2 ] ) then Ships[ 2 ].Draw( 2 );
          if Assigned( Ships[ 3 ] ) then Ships[ 3 ].Draw( 2 );
          if Assigned( Ships[ 4 ] ) then Ships[ 4 ].Draw( 2 );
        Quad.SetTextureFiltering( D3DTEXF_LINEAR );
      end;
    Quad.RenderToTexture( False, 6 );

        Quad.SetBlendMode( qbmSrcAlpha );
    Quad.RenderToTexture( True, 3 );
      Quad.Clear( $FF000000 );
      BloomShader.SetShaderState( UseShaders );
        ScreenBuf_3.Draw( 0, 0, $FFFFFFFF );
      BloomShader.SetShaderState( False );
    Quad.RenderToTexture( False, 3 );

    Quad.RenderToTexture( True, 4 );
      Quad.Clear( $FF000000 );
      BlurHShader.SetShaderState( UseShaders );
        BloomBuf_1.DrawMap( 0, 0, AppScrW, AppScrH, 0, 0, 1, 1, $FFFFFFFF );
      BlurHShader.SetShaderState( False );
    Quad.RenderToTexture( False, 4 );

    Quad.RenderToTexture( True, 5 );
      Quad.Clear( $FF000000 );
      BlurVShader.SetShaderState( UseShaders );
        BloomBuf_2.DrawMap( 0, 0, AppScrW, AppScrH, 0, 0, 1, 1, $FFFFFFFF );
      BlurVShader.SetShaderState( False );
    Quad.RenderToTexture( False, 5 );

    Quad.RenderToTexture( True, 1 );
      Quad.SetBlendMode( qbmSrcAlpha );
      ScreenBuf_2.Draw( 0, 0, $FFFFFFFF );
      ScreenBuf_3.Draw( 0, 0, $FFFFFFFF );
      if UseShaders then begin
        Quad.SetBlendMode( qbmSrcAlphaAdd );
        BloomBuf_3.DrawMap( 0, 0, AppScrW, AppScrH, 0, 0, 1, 1, $FFFFFFFF );
      end;
      Quad.SetBlendMode( qbmSrcAlpha );
      if showAppName or drawAppName then begin
        ScreenBuf_0.Draw( 0, 0, $FFFFFFFF );
      end;
    Quad.RenderToTexture( False, 1 );

    OldTVShader.SetShaderState( UseShaders );
      ScreenBuf_1.Draw( 0, 0, $FFFFFFFF );
    OldTVShader.SetShaderState( False );
  Quad.EndRender;
end;

procedure MainMenuUpdate( dt: Double; currentTime: Double );
var tbol  : Boolean;
    param : rEnemyInitParam;
begin
  if accelStars then begin
    currentSpeed := Vec2f( -AppScrH * STARS_SPEED_COF * ( currentTime - startTime ) / ACCELERATION_STARS_TIME, 0 );
    if currentTime - startTime >= ACCELERATION_STARS_TIME then begin
      accelStars    := False;

      param.game := nil;
      param.moveType := 8;
      Ships[ 1 ].Init( @param );
      param.moveType := 9;
      Ships[ 2 ].Init( @param );
      param.moveType := 10;
      Ships[ 3 ].Init( @param );
      param.moveType := 11;
      Ships[ 4 ].Init( @param );

      showAppName   := True;
      currentSpeed  := Vec2f( -AppScrH * STARS_SPEED_COF, 0 );
      startTime     := currentTime;
    end;
  end;

  if showAppName then begin
    GradientX := -1.2 * AppScrW * ( currentTime - startTime ) / SHOW_APPNAME_TIME;
    if currentTime - startTime >= SHOW_APPNAME_TIME then begin
      showAppName := False;
      drawAppName := True;
      startTime   := currentTime;
    end;
  end;

  if hideAppName then begin
    GradientX := AppScrW - 1.2 * AppScrW * ( currentTime - startTime ) / HIDE_APPNAME_TIME;
    if currentTime - startTime >= HIDE_APPNAME_TIME then begin
      hideAppName := False;
      drawAppName := False;
      //goToGame    := True;
      waitShips   := True;
      startTime   := currentTime;
    end;
  end;

  if Assigned( Ships[ 1 ] ) then Ships[ 1 ].Update( dt, currentTime );
  if Assigned( Ships[ 2 ] ) then Ships[ 2 ].Update( dt, currentTime );
  if Assigned( Ships[ 3 ] ) then Ships[ 3 ].Update( dt, currentTime );
  if Assigned( Ships[ 4 ] ) then Ships[ 4 ].Update( dt, currentTime );

  if waitShips then begin
    EnterCriticalSection( Section_EnemyDel );
      if Assigned( Ships[ 1 ] ) then begin
        if Ships[ 1 ].CollideVsRect( Rect( Vec2f( -100, -100 ), AppScrResf + Vec2f( 100, 100 ) ) ) then begin
          tbol := True;
        end else begin
          Ships[ 1 ].Free;
          Ships[ 1 ] := nil;
          tbol := False;
        end;
      end else tbol := False;
      if Assigned( Ships[ 2 ] ) then begin
        if Ships[ 2 ].CollideVsRect( Rect( Vec2f( -100, -100 ), AppScrResf + Vec2f( 100, 100 ) ) ) then begin
          tbol := True;
        end else begin
          Ships[ 2 ].Free;
          Ships[ 2 ] := nil;
          tbol := tbol or False;
        end;
      end else tbol := tbol or False;
      if Assigned( Ships[ 3 ] ) then begin
        if Ships[ 3 ].CollideVsRect( Rect( Vec2f( -100, -100 ), AppScrResf + Vec2f( 100, 100 ) ) ) then begin
          tbol := True;
        end else begin
          Ships[ 3 ].Free;
          Ships[ 3 ] := nil;
          tbol := tbol or False;
        end;
      end else tbol := tbol or False;
      if Assigned( Ships[ 4 ] ) then begin
        if Ships[ 4 ].CollideVsRect( Rect( Vec2f( -100, -100 ), AppScrResf + Vec2f( 100, 100 ) ) ) then begin
          tbol := True;
        end else begin
          Ships[ 4 ].Free;
          Ships[ 4 ] := nil;
          tbol := tbol or False;
        end;
      end else tbol := tbol or False;
    LeaveCriticalSection( Section_EnemyDel );
    if not tbol then begin
      waitShips := False;
      goToGame  := True;
    end;
  end;

  UpdateAllStars( dt, False );

  if goToGame then begin
    StateManager.Push( @GameScene );
    StateManager.MakeInit;
  end;
end;

procedure MainMenuUpdateFrames( dt: Double; currentTime: Double );
begin
  UpdateAllFrames( dt );

  EnterCriticalSection( Section_EnemyDel );
    if Assigned( Ships[ 1 ] ) then Ships[ 1 ].UpdateFrame( dt, currentTime );
    if Assigned( Ships[ 2 ] ) then Ships[ 2 ].UpdateFrame( dt, currentTime );
    if Assigned( Ships[ 3 ] ) then Ships[ 3 ].UpdateFrame( dt, currentTime );
    if Assigned( Ships[ 4 ] ) then Ships[ 4 ].UpdateFrame( dt, currentTime );
  LeaveCriticalSection( Section_EnemyDel );
end;

procedure MainMenuFree;
begin

end;

procedure MainMenuKeyDown( key: Byte );
begin

end;

procedure MainMenuKeyUp( key: Byte );
begin
  if key = K_SPACE then begin
    if drawAppName and not hideAppName then begin
      hideAppName := True;
      startTime   := Timer.GetWholeTime;
    end;
  end;
end;

initialization
  MainMenuScene.Name    := 'MainMenu Scene';
  MainMenuScene.onInit  := @MainMenuInit;
  MainMenuScene.onDraw  := @MainMenuDraw;
  SetLength( MainMenuScene.onTimer, 2 );
  MainMenuScene.onTimer[ 0 ]  := @MainMenuUpdate;
  MainMenuScene.onTimer[ 1 ]  := @MainMenuUpdateFrames;
  MainMenuScene.onKill        := @MainMenuFree;
  MainMenuScene.onKeyDown     := @MainMenuKeyDown;
  MainMenuScene.onUpdate      := nil;
  MainMenuScene.onActivate    := nil;
  MainMenuScene.onKeyUp       := @MainMenuKeyUp;
  MainMenuScene.onKeyChar     := nil;
  MainMenuScene.onMouseDown   := nil;
  MainMenuScene.onMouseUp     := nil;
  MainMenuScene.onMouseMove   := nil;
end.
