DEADSOFTWARE

gl: draw screen message
[d2df-sdl.git] / src / game / renders / opengl / r_render.pas
index 599fb4b9bd8973820777eb25c042daad2a244f46..6f52530d099f3299049facc31b2205483c382174 100644 (file)
@@ -242,14 +242,15 @@ implementation
   end;
 
   procedure r_Render_DrawText (const text: AnsiString; x, y: Integer; r, g, b, a: Byte; f: TGLFont; p: TBasePoint);
-    var w, h: Integer;
+    var xx, yy, w, h: Integer;
   begin
+    xx := x; yy := y;
     if p <> TBasePoint.BP_LEFTUP then
     begin
       r_Draw_GetTextSize(text, f, w, h);
-      r_Render_GetBasePoint(x, y, w, h, p, xy);
+      r_Render_GetBasePoint(x, y, w, h, p, xx, yy);
     end;
-    r_Draw_Text(text, xy, r, g, b, a, f);
+    r_Draw_Text(text, xx, yy, r, g, b, a, f);
   end;
 
   procedure r_Render_DrawTexture (img: TGLTexture; x, y, w, h: Integer; p: TBasePoint);
@@ -258,6 +259,79 @@ implementation
     r_Draw_TextureRepeat(img, x, y, w, h, false, 255, 255, 255, 255, false);
   end;
 
+  procedure r_Render_GetFormatTextSize (const text: AnsiString; f: TGLFont; out w, h: Integer);
+    var i, cw, ch, cln, curw, curh, maxw, maxh: Integer;
+  begin
+    curw := 0; curh := 0; maxw := 0; maxh := 0;
+    r_Draw_GetTextSize('W', f, cw, cln);
+    for i := 1 to Length(text) do
+    begin
+      case text[i] of
+        #10:
+        begin
+          maxw := MAX(maxw, curw);
+          curh := curh + cln;
+          curw := 0;
+        end;
+        #1, #2, #3, #4, #18, #19, #20, #21:
+        begin
+          // skip color modifiers
+        end;
+        otherwise
+        begin
+          r_Draw_GetTextSize(text[i], f, cw, ch);
+          maxh := MAX(maxh, curh + ch);
+          curw := curw + cw;
+        end;
+      end;
+    end;
+    w := MAX(maxw, curw);
+    h := MAX(maxh, curh);
+  end;
+
+  procedure r_Render_DrawFormatText (const text: AnsiString; x, y: Integer; a: Byte; f: TGLFont; p: TBasePoint);
+    const
+      colors: array [boolean, 0..5] of TRGB = (
+        ((R:$00; G:$00; B:$00), (R:$FF; G:$00; B:$00), (R:$00; G:$FF; B:$00), (R:$FF; G:$FF; B:$00), (R:$00; G:$00; B:$FF), (R:$FF; G:$FF; B:$FF)),
+        ((R:$00; G:$00; B:$00), (R:$7F; G:$00; B:$00), (R:$00; G:$7F; B:$00), (R:$FF; G:$7F; B:$00), (R:$00; G:$00; B:$7F), (R:$7F; G:$7F; B:$7F))
+      );
+    var
+      i, xx, yy, cx, cy, w, h, cw, ch, cln, color: Integer; dark: Boolean;
+  begin
+    xx := x; yy := y;
+    if p <> TBasePoint.BP_LEFTUP then
+    begin
+      r_Render_GetFormatTextSize(text, f, w, h);
+      r_Render_GetBasePoint(x, y, w, h, p, xx, yy);
+    end;
+    cx := xx; cy := yy; color := 5; dark := false;
+    r_Draw_GetTextSize('W', f, cw, cln);
+    for i := 1 to Length(text) do
+    begin
+      case text[i] of
+        #10:
+        begin
+          cx := xx;
+          INC(cy, cln);
+        end;
+        #1: color := 0;
+        #2: color := 5;
+        #3: dark := true;
+        #4: dark := false;
+        #18: color := 1;
+        #19: color := 2;
+        #20: color := 4;
+        #21: color := 3;
+        otherwise
+        begin
+          r_Draw_GetTextSize(text[i], f, cw, ch);
+          r_Draw_Text(text[i], cx, cy, colors[dark, color].R, colors[dark, color].G, colors[dark, color].B, a, f);
+          INC(cx, cw);
+        end;
+      end;
+    end;
+  end;
+
   procedure r_Render_DrawHUD (x, y: Integer; p: TPlayer);
     var t: TGLTexture; s: AnsiString;
   begin
@@ -315,22 +389,23 @@ implementation
     r_Render_DrawTexture(hudbg, x, y, w, h, TBasePoint.BP_LEFTUP);
 
     if p <> nil then
+    begin
       r_Render_DrawHUD(x + w - 196 + 2, y, p);
+      if p.Spectator then
+      begin
+        r_Render_DrawText(_lc[I_PLAYER_SPECT], x + 4, y + 242, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
+        r_Render_DrawText(_lc[I_PLAYER_SPECT2], x + 4, y + 258, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
+        r_Render_DrawText(_lc[I_PLAYER_SPECT1], x + 4, y + 274, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
+        if p.NoRespawn then
+          r_Render_DrawText(_lc[I_PLAYER_SPECT1S], x + 4, y + 290, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
+      end;
+    end;
 
     if gShowPing and g_Game_IsClient then
     begin
       s := _lc[I_GAME_PING_HUD] + IntToStr(NetPeer.lastRoundTripTime) + _lc[I_NET_SLIST_PING_MS];
       r_Render_DrawText(s, x + 4, y + 242, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
     end;
-
-    if p.Spectator then
-    begin
-      r_Render_DrawText(_lc[I_PLAYER_SPECT], x + 4, y + 242, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
-      r_Render_DrawText(_lc[I_PLAYER_SPECT2], x + 4, y + 258, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
-      r_Render_DrawText(_lc[I_PLAYER_SPECT1], x + 4, y + 274, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
-      if p.NoRespawn then
-        r_Render_DrawText(_lc[I_PLAYER_SPECT1S], x + 4, y + 290, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
-    end;
   end;
 
   procedure r_Render_DrawStatsView (x, y, w, h: Integer; p: TPlayer);
@@ -435,6 +510,15 @@ implementation
     r_Draw_SetRect(l, t, r, b);
   end;
 
+  procedure r_Render_DrawMapView (x, y, w, h, camx, camy: Integer);
+    var l, t, r, b: Integer;
+  begin
+    r_Draw_GetRect(l, t, r, b);
+    r_Draw_SetRect(x, y, x + w, y + h);
+    r_Map_Draw(x, y, w, h, camx, camy, nil);
+    r_Draw_SetRect(l, t, r, b);
+  end;
+
   procedure r_Render_DrawPlayerView (x, y, w, h: Integer; p: TPlayer);
     var l, t, r, b: Integer;
   begin
@@ -484,9 +568,7 @@ implementation
     begin
       r_Draw_FillRect(16, motdh, gScreenWidth - 16, gScreenHeight - 44, 64, 64, 64, 110);
       r_Draw_Rect(16, motdh, gScreenWidth - 16, gScreenHeight - 44, 255, 127, 0, 255);
-      msg := Parse2(slMOTD, #10);
-      for i := 0 to High(msg) do
-        r_Render_DrawText(msg[i], 20, motdh + 3 + ch * i, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
+      r_Render_DrawFormatText(slMOTD, 20, motdh + 3 + ch * i, 255, stdfont, TBasePoint.BP_LEFTUP);
     end;
 
     if not slReadUrgent and (slUrgent <> '') then
@@ -496,9 +578,7 @@ implementation
       r_Draw_Rect(scrx - 256, scry - 60, scrx + 256, scry + 60, 255, 127, 0, 255);
       r_Draw_FillRect(scrx - 256, scry - 40, scrx + 256, scry - 40, 255, 127, 0, 255);
       r_Render_DrawText(_lc[I_NET_SLIST_URGENT], scrx, scry - 58, 255, 255, 255, 255, stdfont, TBasePoint.BP_UP);
-      msg := Parse2(slUrgent, #10);
-      for i := 0 to High(msg) do
-        r_Render_DrawText(msg[i], scrx - 253, scry - 38 + ch * i, 255, 255, 255, 255, stdfont, TBasePoint.BP_LEFTUP);
+      r_Render_DrawFormatText(slUrgent, scrx - 253, scry - 38 + ch * i, 255, stdfont, TBasePoint.BP_LEFTUP);
       r_Render_DrawText(_lc[I_NET_SLIST_URGENT_CONT], scrx, scry + 41, 255, 255, 255, 255, stdfont, TBasePoint.BP_UP);
       r_Draw_FillRect(scrx - 256, scry + 40, scrx + 256, scry + 40, 255, 127, 0, 255);
     end
@@ -873,7 +953,110 @@ implementation
     end;
   end;
 
+  procedure r_Render_DrawValueOf (a, b, x, y: Integer; f: TGLFont);
+    var wa, wb, ch: Integer; sa, sb: AnsiString;
+  begin
+    sa := IntToStr(a);
+    sb := IntToStr(b);
+    r_Draw_GetTextSize(sa, f, wa, ch);
+    r_Draw_GetTextSize(sa + ' / ', f, wb, ch);
+    r_Render_DrawText(sa, x, y, 255, 0, 0, 255, f, TBasePoint.BP_LEFTUP);
+    r_Render_DrawText(' / ', x + wa, y, 255, 255, 255, 255, f, TBasePoint.BP_LEFTUP);
+    r_Render_DrawText(sb, x + wb, y, 255, 0, 0, 255, f, TBasePoint.BP_LEFTUP);
+  end;
+
+  procedure r_Render_DrawSinglStatsPlayer (player, x, y, w1: Integer);
+    var time, kpm: Single;
+  begin
+    r_Render_DrawText(_lc[I_MENU_INTER_KILLS], x, y, 255, 255, 255, 255, menufont, TBasePoint.BP_LEFTUP);
+    r_Render_DrawValueOf(SingleStat.PlayerStat[player].Kills, gTotalMonsters, x + w1, y, MenuFont);
+    r_Render_DrawText(_lc[I_MENU_INTER_KPM], x, y + 32, 255, 255, 255, 255, menufont, TBasePoint.BP_LEFTUP);
+    time := SingleStat.GameTime / 1000;
+    kpm := SingleStat.PlayerStat[player].Kills;
+    if time > 0 then kpm := kpm / time * 60;
+    r_Render_DrawText(Format('%.1f', [kpm]), x + w1, y + 32, 255, 0, 0, 255, menufont, TBasePoint.BP_LEFTUP);
+    r_Render_DrawText(_lc[I_MENU_INTER_SECRETS], x, y + 64, 255, 255, 255, 255, menufont, TBasePoint.BP_LEFTUP);
+    r_Render_DrawValueOf(SingleStat.PlayerStat[player].Secrets, SingleStat.TotalSecrets, x + w1, y + 64, MenuFont);
+  end;
+
+  procedure r_Render_DrawSingleStats;
+    var xx, wa, wb, ww, ch: Integer; s: AnsiString;
+  begin
+    r_Render_DrawText(_lc[I_MENU_INTER_LEVEL_COMPLETE], gScreenWidth div 2, 32, 255, 255, 255, 255, menufont, TBasePoint.BP_UP);
+
+    r_Draw_GetTextSize(_lc[I_MENU_INTER_KPM] + '  ', menufont, wa, ch);
+    r_Draw_GetTextSize(' 9999.9', menufont, wb, ch);
+    ww := wa + wb;
+    xx := gScreenWidth div 2 - ww div 2;
+
+    s := r_Render_TimeToStr(SingleStat.GameTime);
+    r_Render_DrawText(_lc[I_MENU_INTER_TIME], xx, 80, 255, 255, 255, 255, menufont, TBasePoint.BP_LEFTUP);
+    r_Render_DrawText(s, xx + wa, 80, 255, 0, 0, 255, menufont, TBasePoint.BP_LEFTUP);
+
+    if SingleStat.TwoPlayers then
+    begin
+      r_Render_DrawText(_lc[I_MENU_PLAYER_1], gScreenWidth div 2, 128, 255, 255, 255, 255, menufont, TBasePoint.BP_UP);
+      r_Render_DrawSinglStatsPlayer(0, xx, 176, wa);
+      r_Render_DrawText(_lc[I_MENU_PLAYER_2], gScreenWidth div 2, 288, 255, 255, 255, 255, menufont, TBasePoint.BP_UP);
+      r_Render_DrawSinglStatsPlayer(1, xx, 336, wa);
+    end
+    else
+    begin
+      r_Render_DrawSinglStatsPlayer(0, xx, 128, wa);
+    end;
+  end;
+
+  procedure r_Render_DrawSpectHud;
+    var xoff: Integer; s: AnsiString;
+
+    procedure AddText (s1, s2: AnsiString);
+      var w1, w2, ww, ch: Integer;
+    begin
+      r_Draw_GetTextSize(s1, stdfont, w1, ch);
+      r_Draw_GetTextSize(s2, stdfont, w2, ch);
+      ww := MAX(w1, w2);
+      r_Render_DrawText(s1, xoff + ww div 2, gScreenHeight - ch, 255, 255, 255, 255, stdfont, TBasePoint.BP_DOWN);
+      r_Render_DrawText(s2, xoff + ww div 2, gScreenHeight - ch, 255, 255, 255, 255, stdfont, TBasePoint.BP_UP);
+      xoff := xoff + ww + 16;
+    end;
+
+  begin
+    xoff := 0;
+    case gSpectMode of
+      SPECT_STATS:   s := 'MODE: Stats';
+      SPECT_MAPVIEW: s := 'MODE: Observe Map';
+      SPECT_PLAYERS: s := 'MODE: Watch Players';
+      otherwise      s := 'MODE: ' + IntToStr(gSpectMode);
+    end;
+    AddText(s, '< jump >');
+    if gSpectMode = SPECT_STATS then
+      AddText('Autoview', '< fire >');
+    if gSpectMode = SPECT_MAPVIEW then
+      AddText('[-] Step ' + IntToStr(gSpectStep) + ' [+]', '<prev weap> <next weap>');
+    if gSpectMode = SPECT_PLAYERS then
+    begin
+      AddText('Player 1', '<left/right>');
+      if gSpectViewTwo then
+        AddText('Player 2', '<prev w/next w>');
+      AddText('2x View', '<up/down>');
+    end;
+  end;
+
+  function GetActivePlayer_ByID (id: Integer): TPlayer;
+    var i, len: Integer; p: TPlayer;
+  begin
+    p := nil;
+    if (id >= 0) and (gPlayers <> nil) then
+    begin
+      i := 0; len := Length(gPlayers);
+      while (i < len) and ((IsActivePlayer(gPlayers[i]) = false) or (gPlayers[i].UID <> id)) do INC(i);
+      if i < len then p := gPlayers[i];
+    end;
+    result := p;
+  end;
+
   procedure r_Render_Draw;
+    var p1, p2: TPlayer;
   begin
     if gExit = EXIT_QUIT then
       exit;
@@ -889,27 +1072,77 @@ implementation
 
     //e_LogWritefln('r_render_draw: %sx%s', [gScreenWidth, gScreenHeight]);
 
+    p1 := nil;
+    p2 := nil;
+    if gGameOn or (gState = STATE_FOLD) then
+    begin
+      if (gPlayer1 <> nil) and (gPlayer2 <> nil) then
+      begin
+        if gRevertPlayers then
+        begin
+          p1 := gPlayer2;
+          p2 := gPlayer1;
+        end
+        else
+        begin
+          p1 := gPlayer1;
+          p2 := gPlayer2;
+        end;
+      end
+      else if gPlayer1 <> nil then
+      begin
+        p1 := gPlayer1;
+      end
+      else if gPlayer2 <> nil then
+      begin
+        p1 := gPlayer2;
+      end;
+      if (gSpectMode = SPECT_PLAYERS) and (gPlayers <> nil) then
+      begin
+        p1 := GetActivePlayer_ByID(gSpectPID1);
+        if p1 = nil then
+          p1 := GetActivePlayer_ByID(GetActivePlayerID_Next());
+        if gSpectViewTwo then
+        begin
+          p2 := GetActivePlayer_ByID(gSpectPID2);
+          if p2 = nil then
+            p2 := GetActivePlayer_ByID(GetActivePlayerID_Next());
+        end;
+      end;
+    end;
+
     if gGameOn or ((gState in [STATE_FOLD]) and (EndingGameCounter < 255)) then
     begin
-      // TODO setup sectator mode
       // TODO setup player hear point
 
-      if (gPlayer1 <> nil) and (gPlayer2 <> nil) then
-       begin
-        r_Render_DrawPlayerView(0, 0, gScreenWidth, gScreenHeight div 2 - 2, gPlayer1);
-        r_Render_DrawPlayerView(0, gScreenHeight div 2 + 2, gScreenWidth, gScreenHeight div 2, gPlayer2);
+      if gSpectMode = SPECT_MAPVIEW then
+      begin
+        r_Render_DrawMapView(0, 0, gScreenWidth, gScreenHeight, gSpectX + gScreenWidth div 2, gSpectY + gScreenHeight div 2);
       end
-      else
+      else if (p1 <> nil) and (p2 <> nil) then
       begin
-        r_Render_DrawPlayerView(0, 0, gScreenWidth, gScreenHeight, gPlayer1);
+        r_Render_DrawPlayerView(0, 0, gScreenWidth, gScreenHeight div 2 - 2, p1);
+        r_Render_DrawPlayerView(0, gScreenHeight div 2 + 2, gScreenWidth, gScreenHeight div 2, p2);
+      end
+      else if p1 <> nil then
+      begin
+        r_Render_DrawPlayerView(0, 0, gScreenWidth, gScreenHeight, p1);
+      end
+      else if p2 <> nil then
+      begin
+        r_Render_DrawPlayerView(0, 0, gScreenWidth, gScreenHeight, p2);
       end;
 
       // TODO draw holmes inspector
 
-      // TODO draw messages
+      if MessageText <> '' then
+        r_Render_DrawFormatText(MessageText, (gScreenWidth - 196) div 2, gScreenHeight div 2, 255, menufont, TBasePoint.BP_CENTER);
+
       if IsDrawStat or (gSpectMode = SPECT_STATS) then
         r_Render_DrawStats;
-      // TODO draw spectator hud
+
+      if gSpectHUD and (gChatShow = false) and (gSpectMode <> SPECT_NONE) and (gSpectAuto = false) then
+        r_Render_DrawSpectHud;
     end;
 
     if gPauseMain and gGameOn {$IFDEF ENABLE_MENU}and (g_ActiveWindow = nil){$ENDIF} then
@@ -953,7 +1186,7 @@ implementation
           else
           begin
             r_Render_DrawBackground(GameWad + ':TEXTURES/INTER');
-            // TODO darw single stats
+            r_Render_DrawSingleStats;
             {$IFDEF ENABLE_MENU}
               if g_ActiveWindow <> nil then
                 r_Draw_FillRect(0, 0, gScreenWidth - 1, gScreenHeight - 1, 0, 0, 0, 105);