DEADSOFTWARE

gl: draw gui controls
authorDeaDDooMER <deaddoomer@deadsoftware.ru>
Sun, 12 Jun 2022 08:48:14 +0000 (11:48 +0300)
committerDeaDDooMER <deaddoomer@deadsoftware.ru>
Fri, 9 Jun 2023 08:43:43 +0000 (11:43 +0300)
src/game/Doom2DF.lpr
src/game/renders/opengl/r_common.pas [new file with mode: 0644]
src/game/renders/opengl/r_gui.pas [new file with mode: 0644]
src/game/renders/opengl/r_map.pas
src/game/renders/opengl/r_render.pas
src/game/renders/opengl/r_textures.pas

index ba700515606c038b292305dc5c2f8e03591ebd2f..5eb2229bbddc44ab96eb3019f47fc3da7bb31ab7 100644 (file)
@@ -203,6 +203,8 @@ uses
     r_draw in 'renders/opengl/r_draw.pas',
     r_map in 'renders/opengl/r_map.pas',
     r_fonts in 'renders/opengl/r_fonts.pas',
+    r_common in 'renders/opengl/r_common.pas',
+    r_gui in 'renders/opengl/r_gui.pas',
   {$ELSE}
     {$FATAL render driver not selected}
   {$ENDIF}
diff --git a/src/game/renders/opengl/r_common.pas b/src/game/renders/opengl/r_common.pas
new file mode 100644 (file)
index 0000000..ba934c5
--- /dev/null
@@ -0,0 +1,59 @@
+(* Copyright (C)  Doom 2D: Forever Developers
+ *
+ * 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, version 3 of the License ONLY.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *)
+{$INCLUDE ../../../shared/a_modes.inc}
+unit r_common;
+
+interface
+
+  uses r_textures;
+
+  var
+    stdfont: TGLFont;
+    smallfont: TGLFont;
+    menufont: TGLFont;
+
+  procedure r_Common_Load;
+  procedure r_Common_Free;
+
+implementation
+
+  uses e_log, r_fonts, g_options;
+
+  function r_Common_LoadFont (const name: AnsiString): TGLFont;
+    var info: TFontInfo; skiphack: Integer;
+  begin
+    result := nil;
+    if name = 'STD' then skiphack := 144 else skiphack := 0;
+    if r_Font_LoadInfoFromFile(GameWad + ':FONTS/' + name + 'TXT', info) then
+      result := r_Textures_LoadFontFromFile(GameWad + ':FONTS/' + name + 'FONT', info, skiphack, true);
+    if result = nil then
+      e_logwritefln('failed to load font %s', [name]);
+  end;
+
+  procedure r_Common_Load;
+  begin
+    stdfont := r_Common_LoadFont('STD');
+    smallfont := r_Common_LoadFont('SMALL');
+    menufont := r_Common_LoadFont('MENU');
+  end;
+
+  procedure r_Common_Free;
+  begin
+    menufont.Free;
+    smallfont.Free;
+    stdfont.Free;
+  end;
+
+end.
diff --git a/src/game/renders/opengl/r_gui.pas b/src/game/renders/opengl/r_gui.pas
new file mode 100644 (file)
index 0000000..7016db9
--- /dev/null
@@ -0,0 +1,598 @@
+(* Copyright (C)  Doom 2D: Forever Developers
+ *
+ * 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, version 3 of the License ONLY.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ *)
+{$INCLUDE ../../../shared/a_modes.inc}
+unit r_gui;
+
+interface
+
+  uses g_gui;
+
+  procedure r_GUI_Load;
+  procedure r_GUI_Free;
+
+  procedure r_GUI_GetSize (ctrl: TGUIControl; out w, h: Integer);
+  procedure r_GUI_GetLogoSize (out w, h: Integer);
+  procedure r_GUI_GetMaxFontSize (BigFont: Boolean; out w, h: Integer);
+  procedure r_GUI_GetStringSize (BigFont: Boolean; str: String; out w, h: Integer);
+
+  procedure r_GUI_Draw_Window (win: TGUIWindow);
+
+implementation
+
+  uses
+    Classes, Math, SysUtils,
+    MAPDEF, utils,
+    g_basic, g_base, e_input, g_options,
+    r_draw, r_textures, r_common, r_map,
+    g_game, g_menu
+  ;
+
+  const
+    EDIT_CURSORLEN = 10;
+
+  type
+    THereTexture = record
+      name: AnsiString;
+      id: TGLTexture;
+    end;
+
+  var
+    Box: Array [0..8] of TGLTexture;
+    MarkerID: array [Boolean] of TGLTexture;
+    ScrollLeft, ScrollRight, ScrollMiddle, ScrollMarker: TGLTexture;
+    EditLeft, EditRight, EditMiddle: TGLTexture;
+    BScrollUp, BScrollDown: array [Boolean] of TGLTexture;
+    BScrollMiddle: TGLTexture;
+
+    Font: array [boolean] of TGLFont; (* Small[FALSE] / Big[TRUE] *)
+    LogoTex: TGLTexture;
+    nopic: TGLTexture;
+
+    Background: THereTexture;
+    ImageControl: THereTexture;
+
+  procedure r_GUI_FreeThis (var here: THereTexture);
+  begin
+    here.name := '';
+    if here.id <> nil then
+      here.id.Free;
+    here.id := nil;
+  end;
+
+  function r_GUI_LoadThis (const name: AnsiString; var here: THereTexture): Boolean;
+  begin
+    r_GUI_FreeThis(here);
+    if (name <> '') and (here.name <> name) then
+      here.id := r_Textures_LoadFromFile(name);
+    result := here.id <> nil;
+  end;
+
+  procedure r_GUI_Load;
+    var i: Integer;
+  begin
+    Font[FALSE] := smallfont;
+    Font[TRUE] := menufont;
+
+    MarkerID[FALSE] := r_Textures_LoadFromFile(GameWad + ':TEXTURES/MARKER1');
+    MarkerID[TRUE] := r_Textures_LoadFromFile(GameWad + ':TEXTURES/MARKER2');
+
+    for i := 0 to 8 do
+      Box[i] := r_Textures_LoadFromFile(GameWad + ':TEXTURES/BOX' + IntToStr(i + 1));
+
+    ScrollLeft := r_Textures_LoadFromFile(GameWad + ':TEXTURES/SLEFT');
+    ScrollRight := r_Textures_LoadFromFile(GameWad + ':TEXTURES/SRIGHT');
+    ScrollMiddle := r_Textures_LoadFromFile(GameWad + ':TEXTURES/SMIDDLE');
+    ScrollMarker := r_Textures_LoadFromFile(GameWad + ':TEXTURES/SMARKER');
+
+    EditLeft := r_Textures_LoadFromFile(GameWad + ':TEXTURES/ELEFT');
+    EditRight := r_Textures_LoadFromFile(GameWad + ':TEXTURES/ERIGHT');
+    EditMiddle := r_Textures_LoadFromFile(GameWad + ':TEXTURES/EMIDDLE');
+
+    BScrollUp[true] := r_Textures_LoadFromFile(GameWad + ':TEXTURES/SCROLLUPA');
+    BScrollUp[false] := r_Textures_LoadFromFile(GameWad + ':TEXTURES/SCROLLUPU');
+    BScrollDown[true] := r_Textures_LoadFromFile(GameWad + ':TEXTURES/SCROLLDOWNA');
+    BScrollDown[false] := r_Textures_LoadFromFile(GameWad + ':TEXTURES/SCROLLDOWNU');
+    BScrollMiddle := r_Textures_LoadFromFile(GameWad + ':TEXTURES/SCROLLMIDDLE');
+
+    LogoTex := r_Textures_LoadFromFile(GameWad + ':TEXTURES/MAINLOGO');
+    nopic := r_Textures_LoadFromFile(GameWad + ':TEXTURES/NOPIC');
+  end;
+
+  procedure r_GUI_Free;
+    var i: Integer;
+  begin
+    Font[FALSE] := nil;
+    Font[TRUE] := nil;
+
+    MarkerID[FALSE].Free;
+    MarkerID[TRUE].Free;
+
+    for i := 0 to 8 do
+      Box[i].Free;
+
+    ScrollLeft.Free;
+    ScrollRight.Free;
+    ScrollMiddle.Free;
+    ScrollMarker.Free;
+
+    EditLeft.Free;
+    EditRight.Free;
+    EditMiddle.Free;
+
+    BScrollUp[true].Free;
+    BScrollUp[false].Free;
+    BScrollDown[true].Free;
+    BScrollDown[false].Free;
+    BScrollMiddle.Free;
+
+    LogoTex.Free;
+    nopic.Free;
+
+    r_GUI_FreeThis(Background);
+    r_GUI_FreeThis(ImageControl);
+  end;
+
+  procedure r_GUI_GetMaxFontSize (BigFont: Boolean; out w, h: Integer);
+    var f: TGLFont;
+  begin
+    f := Font[BigFont];
+    w := f.GetMaxWidth();
+    h := f.GetMaxHeight();
+  end;
+
+  procedure r_GUI_GetStringSize (BigFont: Boolean; str: String; out w, h: Integer);
+  begin
+    r_Draw_GetTextSize(str, Font[BigFont], w, h);
+  end;
+
+  procedure r_GUI_GetLogoSize (out w, h: Integer);
+  begin
+    w := 0; h := 0;
+    if LogoTex <> nil then
+    begin
+      w := LogoTex.width;
+      h := LogoTex.height;
+    end;
+  end;
+
+  procedure r_GUI_GetSize_TextButton (ctrl: TGUITextButton; out w, h: Integer);
+  begin
+    r_Draw_GetTextSize(ctrl.Caption, Font[ctrl.BigFont], w, h);
+  end;
+
+  procedure r_GUI_GetSize_Label (ctrl: TGUILabel; out w, h: Integer);
+    var f: TGLFont;
+  begin
+    f := Font[ctrl.BigFont];
+    r_Draw_GetTextSize(ctrl.Text, f, w, h);
+    if ctrl.FixedLength <> 0 then
+      w := f.GetMaxWidth() * ctrl.FixedLength;
+  end;
+
+  procedure r_GUI_GetSize_Switch (ctrl: TGUISwitch; out w, h: Integer);
+    var i: Integer;
+  begin
+    w := 0; h := 0;
+    if ctrl.Items <> nil then
+      for i := 0 to High(ctrl.Items) do
+        r_Draw_GetTextSize(ctrl.Items[i], Font[ctrl.BigFont], w, h);
+  end;
+
+  procedure r_GUI_GetSize_KeyRead (ctrl: TGUIKeyRead; out w, h: Integer);
+    var i, ww, hh: Integer; f: TGLFont;
+  begin
+    w := 0; h := 0; // ??? h always 0
+    f := Font[ctrl.BigFont];
+    for i := 0 to 255 do
+    begin
+      r_Draw_GetTextSize(e_KeyNames[i], f, ww, hh);
+      w := MAX(w, ww);
+    end;
+    r_Draw_GetTextSize(KEYREAD_QUERY, f, ww, hh);
+    w := MAX(w, ww);
+    r_Draw_GetTextSize(KEYREAD_CLEAR, f, ww, hh);
+    w := MAX(w, ww);
+  end;
+
+  procedure r_GUI_GetSize (ctrl: TGUIControl; out w, h: Integer);
+  begin
+    w := 0;
+    h := 0;
+    if ctrl is TGUITextButton then
+      r_GUI_GetSize_TextButton(ctrl as TGUITextButton, w, h)
+    else if ctrl is TGUILabel then
+      r_GUI_GetSize_Label(ctrl as TGUILabel, w, h)
+    else if ctrl is TGUIScroll then
+      w := 16 + ((ctrl as TGUIScroll).Max + 1) * 8 // ??? but h = 0
+    else if ctrl is TGUISwitch then
+      r_GUI_GetSize_Switch(ctrl as TGUISwitch, w, h)
+    else if ctrl is TGUIEdit then
+      w := 16 + (ctrl as TGUIEdit).Width * 16 // ??? but h = 0
+    else if ctrl is TGUIKeyRead then
+      r_GUI_GetSize_KeyRead(ctrl as TGUIKeyRead, w, h)
+    else if ctrl is TGUIKeyRead2 then
+      w := (ctrl as TGUIKeyRead2).MaxKeyNameWdt * 2 + 8 + 8 + 16 // ??? but h = 0
+    else if ctrl is TGUIListBox then
+    begin
+      w := 8 + ((ctrl as TGUIListBox).Width + 1) * 16; // recheck w & h
+      h := 8 + (ctrl as TGUIListBox).Height * 16;
+    end
+    else if ctrl is TGUIMemo then
+    begin
+      w := 8 + ((ctrl as TGUIMemo).Width + 1) * 16;
+      h := 8 + (ctrl as TGUIMemo).Height * 16;
+    end
+    else
+    begin
+      w := ctrl.GetWidth();
+      h := ctrl.GetHeight();
+    end;
+  end;
+
+  procedure r_GUI_Draw_Control (ctrl: TGUIControl); forward;
+
+  procedure r_GUI_Draw_TextButton (ctrl: TGUITextButton);
+  begin
+    r_Draw_Text(ctrl.Caption, ctrl.x, ctrl.y, ctrl.Color.R, ctrl.Color.G, ctrl.Color.B, 255, Font[ctrl.BigFont]);
+  end;
+
+  procedure r_GUI_Draw_Label (ctrl: TGUILabel);
+    var w, h: Integer; f: TGLFont;
+  begin
+    f := Font[ctrl.BigFont];
+    if ctrl.RightAlign then
+    begin
+      r_Draw_GetTextSize(ctrl.Text, f, w, h);
+      r_Draw_Text(ctrl.Text, ctrl.X + ctrl.CMaxWidth - w, ctrl.Y, ctrl.Color.R, ctrl.Color.G, ctrl.Color.B, 255, f);
+    end
+    else
+      r_Draw_Text(ctrl.Text, ctrl.X, ctrl.Y, ctrl.Color.R, ctrl.Color.G, ctrl.Color.B, 255, f);
+  end;
+
+  procedure r_GUI_Draw_Scroll (ctrl: TGUIScroll);
+  begin
+    r_Draw_Texture(ScrollLeft, ctrl.X, ctrl.Y, ScrollLeft.width, ScrollLeft.height, false, 255, 255, 255, 255, false);
+    r_Draw_TextureRepeat(ScrollMiddle, ctrl.X + 8 + 0 * 8, ctrl.Y, 8 + ctrl.Max * 8, ScrollMiddle.height, false, 255, 255, 255, 255, false);
+    r_Draw_Texture(ScrollRight, ctrl.X + 8 + (ctrl.Max + 1) * 8, ctrl.Y, ScrollRight.width, ScrollRight.height, false, 255, 255, 255, 255, false);
+    r_Draw_Texture(ScrollMarker, ctrl.X + 8 + ctrl.Value * 8, ctrl.Y, ScrollMarker.width, ScrollMarker.height, false, 255, 255, 255, 255, false);
+  end;
+
+  procedure r_GUI_Draw_Switch (ctrl: TGUISwitch);
+  begin
+    r_Draw_Text(ctrl.Items[ctrl.ItemIndex], ctrl.X, ctrl.Y, ctrl.Color.R, ctrl.Color.G, ctrl.Color.B, 255, Font[ctrl.BigFont]);
+  end;
+
+  procedure r_GUI_Draw_Edit (ctrl: TGUIEdit);
+    var w, h: Integer; r, g, b: Byte; f: TGLFont;
+  begin
+    r_Draw_Texture(EditLeft, ctrl.X, ctrl.Y, EditLeft.width, EditLeft.height, false, 255, 255, 255, 255, false);
+    r_Draw_TextureRepeat(EditMiddle, ctrl.X + 8, ctrl.Y, 8 + (ctrl.Width - 1) * 16, EditMiddle.height, false, 255, 255, 255, 255, false);
+    r_Draw_Texture(EditRight, ctrl.X + 8 + ctrl.Width * 16, ctrl.Y, EditRight.width, EditRight.height, false, 255, 255, 255, 255, false);
+    r := ctrl.Color.R;
+    g := ctrl.Color.G;
+    b := ctrl.Color.B;
+    if ctrl.Invalid and (ctrl.Window.ActiveControl <> ctrl) then
+    begin
+      r := 128;
+      g := 128;
+      b := 128;
+    end;
+    f := Font[ctrl.BigFont];
+    r_Draw_Text(ctrl.Text, ctrl.X + 8, ctrl.Y, r, g, b, 255, f);
+    if ctrl.Window.ActiveControl = ctrl then
+    begin
+      r_Draw_GetTextSize(Copy(ctrl.Text, 1, ctrl.CaretPos), f, w, h);
+      r_Draw_FillRect(ctrl.X + 8 + w, ctrl.Y + h - 4, ctrl.X + 8 + w + EDIT_CURSORLEN, ctrl.Y + h - 2, 200, 0, 0, 255);
+    end;
+  end;
+
+  procedure r_GUI_Draw_KeyRead (ctrl: TGUIKeyRead);
+    var k: AnsiString;
+  begin
+    if ctrl.IsQuery then
+      k := KEYREAD_QUERY
+    else if ctrl.Key <> 0 then
+      k := e_KeyNames[ctrl.Key]
+    else
+      k := KEYREAD_CLEAR;
+    r_Draw_Text(k, ctrl.X, ctrl.Y, ctrl.Color.R, ctrl.Color.G, ctrl.Color.B, 255, Font[ctrl.BigFont]);
+  end;
+
+  procedure r_GUI_Draw_KeyRead2 (ctrl: TGUIKeyRead2);
+
+    procedure drawText (idx: Integer);
+      var x, y: Integer; r, g, b: Byte; kk: DWORD; str: AnsiString;
+    begin
+      if idx = 0 then kk := ctrl.Key0 else kk := ctrl.Key1;
+      y := ctrl.Y;
+      if idx = 0 then x := ctrl.X + 8 else x := ctrl.X + 8 + ctrl.MaxKeyNameWdt + 16;
+      r := 255; g := 0; b := 0;
+      if ctrl.KeyIdx = idx then
+      begin
+        r := 255; g := 255; b := 255;
+      end;
+      if ctrl.IsQuery and (ctrl.KeyIdx = idx) then
+        str := KEYREAD_QUERY
+      else if kk <> 0 then
+        str := e_KeyNames[kk]
+      else
+        str := KEYREAD_CLEAR;
+      r_Draw_Text(str, x, y, r, g, b, 255, Font[ctrl.BigFont]);
+    end;
+
+  begin
+    drawText(0);
+    drawText(1);
+  end;
+
+  procedure DrawBox (x, y, w, h: Integer);
+  begin
+    r_Draw_Texture(Box[0], x, y, 4, 4, false, 255, 255, 255, 255, false);
+    r_Draw_TextureRepeat(Box[1], x + 4, y, w * 16, 4, false, 255, 255, 255, 255, false);
+    r_Draw_Texture(Box[2], x + 4 + w * 16, y, 4, 4, false, 255, 255, 255, 255, false);
+
+    r_Draw_TextureRepeat(Box[3], x, y + 4, 4, h * 16, false, 255, 255, 255, 255, false);
+    r_Draw_TextureRepeat(Box[4], x + 4, y + 4, w * 16, h * 16, false, 255, 255, 255, 255, false);
+    r_Draw_TextureRepeat(Box[5], x + 4 + w * 16, y + 4, 4, h * 16, false, 255, 255, 255, 255, false);
+
+    r_Draw_Texture(Box[6], x, y + 4 + h * 16, 4, 4, false, 255, 255, 255, 255, false);
+    r_Draw_TextureRepeat(Box[7], x + 4, y + 4 + h * 16, w * 16, 4, false, 255, 255, 255, 255, false);
+    r_Draw_Texture(Box[8], x + 4 + w * 16, y + 4 + h * 16, 4, 4, false, 255, 255, 255, 255, false);
+  end;
+
+  procedure r_GUI_Draw_ModelView (ctrl: TGUIModelView);
+  begin
+    DrawBox(ctrl.X, ctrl.Y, 4, 4);
+    if ctrl.Model <> nil then
+      r_Map_DrawPlayerModel(ctrl.Model, ctrl.X + 4, ctrl.Y + 4, 255);
+  end;
+
+  procedure r_GUI_Draw_MapPreview (ctrl: TGUIMapPreview);
+    var a: Integer; r, g, b: Byte;
+  begin
+    DrawBox(ctrl.X, ctrl.Y, MAPPREVIEW_WIDTH, MAPPREVIEW_HEIGHT);
+    if (ctrl.MapSize.X <= 0) or (ctrl.MapSize.Y <= 0) then
+      Exit;
+    r_Draw_FillRect(ctrl.X + 4, ctrl.Y + 4, ctrl.X + 4 + Trunc(ctrl.MapSize.X / ctrl.Scale), ctrl.Y + 4 + Trunc(ctrl.MapSize.Y / ctrl.Scale), 32, 32, 32, 255);
+    if ctrl.MapData <> nil then
+      for a := 0 to High(ctrl.MapData) do
+        with ctrl.MapData[a] do
+        begin
+          if X1 > MAPPREVIEW_WIDTH * 16 then Continue;
+          if Y1 > MAPPREVIEW_HEIGHT * 16 then Continue;
+          if X2 < 0 then Continue;
+          if Y2 < 0 then Continue;
+          if X2 > MAPPREVIEW_WIDTH * 16 then X2 := MAPPREVIEW_WIDTH * 16;
+          if Y2 > MAPPREVIEW_HEIGHT * 16 then Y2 := MAPPREVIEW_HEIGHT * 16;
+          if X1 < 0 then X1 := 0;
+          if Y1 < 0 then Y1 := 0;
+          case PanelType of
+            PANEL_WALL:
+            begin
+              r := 255; g := 255; b := 255;
+            end;
+            PANEL_CLOSEDOOR:
+            begin
+              r := 255; g := 255; b := 0;
+            end;
+            PANEL_WATER:
+            begin
+              r := 0; g := 0; b := 192;
+            end;
+            PANEL_ACID1:
+            begin
+              r := 0; g := 176; b := 0;
+            end;
+            PANEL_ACID2:
+            begin
+              r := 176; g := 0; b := 0;
+            end;
+          else
+            r := 128; g := 128; b := 128;
+          end;
+          if ((X2 - X1) > 0) and ((Y2 - Y1) > 0) then
+            r_Draw_FillRect(ctrl.X + 4 + X1, ctrl.Y + 4 + Y1, ctrl.X + 4 + X2, ctrl.Y + 4 + Y2, r, g, b, 255);
+      end;
+  end;
+
+  procedure r_GUI_Draw_Image (ctrl: TGUIImage);
+    var pic: TGLTexture;
+  begin
+    pic := nopic;
+    if ctrl.ImageRes <> '' then
+      if r_GUI_LoadThis(ctrl.ImageRes, ImageControl) then
+        pic := ImageControl.id;
+    if pic <> nil then
+      r_Draw_Texture(pic, ctrl.x, ctrl.y, pic.width, pic.height, false, 255, 255, 255, 255, false);
+  end;
+
+  procedure DrawScroll(x, y, h: Integer; Up, Down: Boolean);
+    var t: TGLTexture;
+  begin
+    if h >= 3 then
+    begin
+      t := BScrollUp[Up];
+      r_Draw_Texture(t, x, y, t.width, t.height, false, 255, 255, 255, 255, false);
+      t := BScrollDown[Down];
+      r_Draw_Texture(t, x, y + (h - 1) * 16, t.width, t.height, false, 255, 255, 255, 255, false);
+      t := BScrollMiddle;
+      r_Draw_TextureRepeat(t, x, y + 16, t.width, (h - 2) * 16, false, 255, 255, 255, 255, false);
+    end;
+  end;
+
+  procedure r_GUI_Draw_ListBox (ctrl: TGUIListBox); // + TGUIFileListBox
+    var a, w2, h2: Integer; s: string; col: TRGB; f: TGLFont;
+  begin
+    if ctrl.DrawBack then
+      DrawBox(ctrl.X, ctrl.Y, ctrl.Width + 1, ctrl.Height);
+    if ctrl.DrawScrollBar then
+      DrawScroll(ctrl.X + 4 + ctrl.Width * 16, ctrl.Y + 4, ctrl.Height, (ctrl.StartLine > 0) and (ctrl.Items <> nil), (ctrl.StartLine + ctrl.Height - 1 < High(ctrl.Items)) and (ctrl.Items <> nil));
+    if ctrl.Items <> nil then
+    begin
+      f := Font[ctrl.BigFont];
+      for a := ctrl.StartLine to Min(High(ctrl.Items), ctrl.StartLine + ctrl.Height - 1) do
+      begin
+        s := ctrl.Items[a];
+        r_Draw_GetTextSize(s, f, w2, h2);
+        while (Length(s) > 0) and (w2 > ctrl.Width * 16) do
+        begin
+          SetLength(s, Length(s) - 1);
+          r_Draw_GetTextSize(s, f, w2, h2);
+        end;
+        if a = ctrl.ItemIndex then col := ctrl.ActiveColor else col := ctrl.UnActiveColor;
+        r_Draw_Text(s, ctrl.X + 4, ctrl.Y + 4 + (a - ctrl.StartLine) * 16, col.r, col.g, col.b, 255, f);
+      end;
+    end;
+  end;
+
+  procedure r_GUI_Draw_Memo (ctrl: TGUIMemo);
+    var i: Integer;
+  begin
+    if ctrl.DrawBack then
+      DrawBox(ctrl.X, ctrl.Y, ctrl.Width + 1, ctrl.Height);
+    if ctrl.DrawScrollBar then
+      DrawScroll(ctrl.X + 4 + ctrl.Width * 16, ctrl.Y + 4, ctrl.Height, (ctrl.StartLine > 0) and (ctrl.Lines <> nil), (ctrl.StartLine + ctrl.Height - 1 < High(ctrl.Lines)) and (ctrl.Lines <> nil));
+    if ctrl.Lines <> nil then
+      for i := ctrl.StartLine to Min(High(ctrl.Lines), ctrl.StartLine + ctrl.Height - 1) do
+        r_Draw_Text(ctrl.Lines[i], ctrl.X + 4, ctrl.Y + 4 + (i - ctrl.StartLine) * 16, ctrl.Color.R, ctrl.Color.G, ctrl.Color.B, 255, Font[ctrl.BigFont]);
+  end;
+
+  procedure r_GUI_Draw_MainMenu (ctrl: TGUIMainMenu);
+    var i, w, h: Integer; ID: TGLTexture;
+  begin
+    if ctrl.Header <> nil then
+    begin
+      r_GUI_Draw_Label(ctrl.Header)
+    end
+    else if LogoTex <> nil then
+    begin
+      r_GUI_GetLogoSize(w, h);
+      r_Draw_Texture(LogoTex, ((gScreenWidth div 2) - (w div 2)), ctrl.Buttons[0].Y - ctrl.Buttons[0].GetHeight - h, w, h, false, 255, 255, 255, 255, false);
+    end;
+    if ctrl.Buttons <> nil then
+    begin
+      for i := 0 to High(ctrl.Buttons) do
+        if ctrl.Buttons[i] <> nil then
+          r_GUI_Draw_TextButton(ctrl.Buttons[i]);
+      if ctrl.Index <> -1 then
+      begin
+        ID := MarkerID[ctrl.Counter DIV MAINMENU_MARKERDELAY MOD 2 <> 0];
+        r_Draw_Texture(ID, ctrl.Buttons[ctrl.Index].X - 48, ctrl.Buttons[ctrl.Index].Y, ID.width, ID.height, false, 255, 255, 255, 255, false);
+      end
+    end;
+  end;
+
+  procedure r_GUI_Draw_Menu (ctrl: TGUIMenu);
+    var a, locx, locy: Integer; f: TGLFont;
+  begin
+    if ctrl.Header <> nil then
+      r_GUI_Draw_Label(ctrl.Header);
+    if ctrl.Items <> nil then
+    begin
+      for a := 0 to High(ctrl.Items) do
+      begin
+        if ctrl.Items[a].Text <> nil then
+          r_GUI_Draw_Control(ctrl.Items[a].Text);
+        if ctrl.Items[a].Control <> nil then
+          r_GUI_Draw_Control(ctrl.Items[a].Control);
+      end;
+    end;
+    if (ctrl.Index <> -1) and (ctrl.Counter > MENU_MARKERDELAY div 2) then
+    begin
+      locx := 0;
+      locy := 0;
+      if ctrl.Items[ctrl.Index].Text <> nil then
+      begin
+        locx := ctrl.Items[ctrl.Index].Text.X;
+        locy := ctrl.Items[ctrl.Index].Text.Y;
+        //HACK!
+        if ctrl.Items[ctrl.Index].Text.RightAlign then
+        begin
+          locx := locx + ctrl.Items[ctrl.Index].Text.CMaxWidth - ctrl.Items[ctrl.Index].Text.GetWidth;
+        end;
+      end
+      else if ctrl.Items[ctrl.Index].Control <> nil then
+      begin
+        locx := ctrl.Items[ctrl.Index].Control.X;
+        locy := ctrl.Items[ctrl.Index].Control.Y;
+      end;
+      f := Font[ctrl.BigFont];
+      locx := locx - f.GetMaxWidth();
+      r_Draw_Text(#16, locx, locy, 255, 0, 0, 255, f);
+    end;
+  end;
+
+  procedure r_GUI_Draw_Control (ctrl: TGUIControl);
+  begin
+    if ctrl is TGUITextButton then
+      r_GUI_Draw_TextButton(TGUITextButton(ctrl))
+    else if ctrl is TGUILabel then
+      r_GUI_Draw_Label(TGUILabel(ctrl))
+    else if ctrl is TGUIScroll then
+      r_GUI_Draw_Scroll(TGUIScroll(ctrl))
+    else if ctrl is TGUISwitch then
+      r_GUI_Draw_Switch(TGUISwitch(ctrl))
+    else if ctrl is TGUIEdit then
+      r_GUI_Draw_Edit(TGUIEdit(ctrl))
+    else if ctrl is TGUIKeyRead then
+      r_GUI_Draw_KeyRead(TGUIKeyRead(ctrl))
+    else if ctrl is TGUIKeyRead2 then
+      r_GUI_Draw_KeyRead2(TGUIKeyRead2(ctrl))
+    else if ctrl is TGUIModelView then
+      r_GUI_Draw_ModelView(TGUIModelView(ctrl))
+    else if ctrl is TGUIMapPreview then
+      r_GUI_Draw_MapPreview(TGUIMapPreview(ctrl))
+    else if ctrl is TGUIImage then
+      r_GUI_Draw_Image(TGUIImage(ctrl))
+    else if ctrl is TGUIListBox then
+      r_GUI_Draw_ListBox(TGUIListBox(ctrl)) // + TGUIFileListBox
+    else if ctrl is TGUIMemo then
+      r_GUI_Draw_Memo(TGUIMemo(ctrl))
+    else if ctrl is TGUIMainMenu then
+      r_GUI_Draw_MainMenu(TGUIMainMenu(ctrl))
+    else if ctrl is TGUIMenu then
+      r_GUI_Draw_Menu(TGUIMenu(ctrl))
+    else
+      Assert(False)
+  end;
+
+  procedure r_GUI_Draw_Window (win: TGUIWindow);
+    var i, tw, th: Integer;
+  begin
+    // Here goes code duplication from g_game.pas:DrawMenuBackground()
+    if win.BackTexture <> '' then
+      if r_GUI_LoadThis(win.BackTexture, Background) then
+      begin
+        r_Draw_FillRect(0, 0, gScreenWidth - 1, gScreenHeight - 1, 0, 0, 0, 255);
+        tw := Background.id.width;
+        th := Background.id.height;
+        if tw = th then
+          tw := round(tw * 1.333 * (gScreenHeight / th))
+        else
+          tw := trunc(tw * (gScreenHeight / th));
+        r_Draw_Texture(Background.id, (gScreenWidth - tw) div 2, 0, tw, gScreenHeight, false, 255, 255, 255, 255, false);
+      end
+      else
+        r_Draw_FillRect(0, 0, gScreenWidth - 1, gScreenHeight - 1, 127, 127, 127, 255);
+
+    // small hack here
+    if win.Name = 'AuthorsMenu' then
+      r_Draw_FillRect(0, 0, gScreenWidth - 1, gScreenHeight - 1, 0, 0, 0, 105);
+    for i := 0 to High(win.Childs) do
+      if win.Childs[i] <> nil then
+        r_GUI_Draw_Control(win.Childs[i]);
+  end;
+
+end.
index 11be032553b5fe48717cb92f1dfc25730b3fe871..4f0621d452ac7f9abfde5904ecd0e3b48e94a13f 100644 (file)
@@ -17,7 +17,7 @@ unit r_map;
 
 interface
 
-  uses g_base, g_player; // TRectWH, TPlayer
+  uses g_base, g_player, g_playermodel; // TRectWH, TPlayer, TPlayerModel
 
   procedure r_Map_Initialize;
   procedure r_Map_Finalize;
@@ -34,6 +34,10 @@ interface
 {$IFDEF ENABLE_GIBS}
   function r_Map_GetGibSize (m, i: Integer): TRectWH;
 {$ENDIF}
+{$IFDEF ENABLE_MENU}
+  procedure r_Map_DrawPlayerModel (pm: TPlayerModel; x, y: Integer; alpha: Byte);
+{$ENDIF}
+
 
   procedure r_Map_Update;
 
@@ -51,7 +55,7 @@ implementation
     e_log,
     binheap, MAPDEF, utils,
     g_options, g_textures, g_basic, g_phys,
-    g_game, g_map, g_panel, g_items, g_monsters, g_playermodel, g_weapons,
+    g_game, g_map, g_panel, g_items, g_monsters, g_weapons,
     {$IFDEF ENABLE_CORPSES}
       g_corpses,
     {$ENDIF}
@@ -1221,7 +1225,6 @@ implementation
   end;
 
   procedure r_Map_DrawScreenEffects (x, y, w, h: Integer; p: TPlayer);
-    var i: Integer;
   begin
     if p <> nil then
     begin
index be9192d8a0a8e0aeec87ba210fea2f61d9745f88..6e9b96c8a813d6a7abbc1bee72a90c6db064399a 100644 (file)
@@ -74,6 +74,9 @@ implementation
     {$ELSE}
       GL, GLEXT,
     {$ENDIF}
+    {$IFDEF ENABLE_MENU}
+      r_gui,
+    {$ENDIF}
     {$IFDEF ENABLE_SYSTEM}
       g_system,
     {$ENDIF}
@@ -81,7 +84,7 @@ implementation
     e_log, utils,
     g_game, g_options, g_console, g_player, g_weapons, g_language,
     g_net,
-    r_draw, r_textures, r_fonts, r_map
+    r_draw, r_textures, r_fonts, r_common, r_map
   ;
 
   type
@@ -94,10 +97,6 @@ implementation
   var
     menuBG: TGLTexture;
 
-    stdfont: TGLFont;
-    smallfont: TGLFont;
-    menufont: TGLFont;
-
     hud, hudbg: TGLTexture;
     hudhp: array [Boolean] of TGLTexture;
     hudap: TGLTexture;
@@ -116,27 +115,14 @@ implementation
     r_Map_FreeTextures;
   end;
 
-  function r_Render_LoadFont (const name: AnsiString): TGLFont;
-    var info: TFontInfo; skiphack: Integer;
-  begin
-    result := nil;
-    if name = 'STD' then skiphack := 144 else skiphack := 0;
-    if r_Font_LoadInfoFromFile(GameWad + ':FONTS/' + name + 'TXT', info) then
-      result := r_Textures_LoadFontFromFile(GameWad + ':FONTS/' + name + 'FONT', info, skiphack, true);
-    if result = nil then
-      e_logwritefln('failed to load font %s', [name]);
-  end;
-
   procedure r_Render_Load;
     const
       WeapName: array [0..WP_LAST] of AnsiString = ('KASTET', 'SAW', 'PISTOL', 'SHOTGUN1', 'SHOTGUN2', 'MGUN', 'RLAUNCHER', 'PGUN', 'BFG', 'SPULEMET', 'FLAMETHROWER');
     var
       i: Integer;
   begin
+    r_Common_Load;
     menuBG := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/TITLE');
-    stdfont := r_Render_LoadFont('STD');
-    smallfont := r_Render_LoadFont('SMALL');
-    menufont := r_Render_LoadFont('MENU');
     hud :=  r_Textures_LoadFromFile(GameWAD + ':TEXTURES/HUD');
     hudbg :=  r_Textures_LoadFromFile(GameWAD + ':TEXTURES/HUDBG');
     hudhp[false] := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/MED2');
@@ -150,11 +136,17 @@ implementation
     hudair := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/AIRBAR');
     hudjet := r_Textures_LoadFromFile(GameWAD + ':TEXTURES/JETBAR');
     r_Map_Load;
+    {$IFDEF ENABLE_MENU}
+      r_GUI_Load;
+    {$ENDIF}
   end;
 
   procedure r_Render_Free;
     var i: Integer;
   begin
+    {$IFDEF ENABLE_MENU}
+      r_GUI_Free;
+    {$ENDIF}
     r_Map_Free;
     hudjet.Free;
     hudair.Free;
@@ -172,10 +164,8 @@ implementation
     hudhp[false].Free;
     hudbg.Free;
     hud.Free;
-    menufont.Free;
-    smallfont.Free;
-    stdfont.Free;
     menuBG.Free;
+    r_Common_Free;
   end;
 
 {$IFDEF ENABLE_SYSTEM}
@@ -407,7 +397,9 @@ implementation
     {$IFDEF ENABLE_MENU}
       if g_ActiveWindow <> nil then
       begin
-        // TODO draw menu widgets
+        if gGameOn then
+          r_Draw_FillRect(0, 0, gScreenWidth - 1, gScreenHeight - 1, 0, 0, 0, 105);
+        r_GUI_Draw_Window(g_ActiveWindow);
       end;
     {$ENDIF}
 
@@ -470,22 +462,22 @@ implementation
 {$IFDEF ENABLE_MENU}
   procedure r_Render_GetControlSize (ctrl: TGUIControl; out w, h: Integer);
   begin
-    w := 0; h := 0;
+    r_GUI_GetSize(ctrl, w, h);
   end;
 
   procedure r_Render_GetLogoSize (out w, h: Integer);
   begin
-    w := 0; h := 0;
+    r_GUI_GetLogoSize(w, h);
   end;
 
   procedure r_Render_GetMaxFontSize (BigFont: Boolean; out w, h: Integer);
   begin
-    w := 0; h := 0;
+    r_GUI_GetMaxFontSize(BigFont, w, h);
   end;
 
   procedure r_Render_GetStringSize (BigFont: Boolean; str: String; out w, h: Integer);
   begin
-    w := 0; h := 0;
+    r_GUI_GetStringSize(BigFont, str, w, h);
   end;
 {$ENDIF}
 
index b51afd2e964bfbd9a76e2edddc8cf4641a43e97f..8df881acebef45500174bfb4790c7daddc8e0873 100644 (file)
@@ -111,6 +111,7 @@ interface
         destructor Destroy; override;
         function GetChar (c: AnsiChar): TGLTexture;
         function GetWidth (c: AnsiChar): Integer;
+        function GetMaxWidth (): Integer;
         function GetMaxHeight (): Integer;
         function GetSpace (): Integer;
     end;
@@ -780,6 +781,13 @@ implementation
       result := self.info.w;
   end;
 
+  function TGLFont.GetMaxWidth (): Integer;
+  begin
+    result := self.info.w;
+    if self.info.kern < 0 then
+      result := result + self.info.kern;
+  end;
+
   function TGLFont.GetMaxHeight (): Integer;
   begin
     result := self.info.h;