DEADSOFTWARE

hashtable cosmetix; holmes scissoring fixes
[d2df-sdl.git] / src / game / g_holmes.inc
index e3dd3804062e387e50ab515390ce367d26031214..c053b4c73e8eb7b246bf9470fc055a808b0b6434 100644 (file)
@@ -1,32 +1,49 @@
+(* 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, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * 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/>.
+ *)
 // ////////////////////////////////////////////////////////////////////////// //
 // cursor (hi, Death Track!)
+const curTexWidth = 32;
+const curTexHeight = 32;
 const curWidth = 17;
 const curHeight = 23;
 
 const cursorImg: array[0..curWidth*curHeight-1] of Byte = (
-  0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-  0,0,3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
-  1,0,3,2,2,0,0,0,0,0,0,0,0,0,0,0,0,
-  1,1,3,3,2,2,0,0,0,0,0,0,0,0,0,0,0,
-  1,1,3,3,4,2,2,0,0,0,0,0,0,0,0,0,0,
-  1,1,3,3,4,4,2,2,0,0,0,0,0,0,0,0,0,
-  1,1,3,3,4,4,4,2,2,0,0,0,0,0,0,0,0,
-  1,1,3,3,4,4,4,4,2,2,0,0,0,0,0,0,0,
-  1,1,3,3,4,4,4,5,6,2,2,0,0,0,0,0,0,
-  1,1,3,3,4,4,5,6,7,5,2,2,0,0,0,0,0,
-  1,1,3,3,4,5,6,7,5,4,5,2,2,0,0,0,0,
-  1,1,3,3,5,6,7,5,4,5,6,7,2,2,0,0,0,
-  1,1,3,3,6,7,5,4,5,6,7,7,7,2,2,0,0,
-  1,1,3,3,7,5,4,5,6,7,7,7,7,7,2,2,0,
-  1,1,3,3,5,4,5,6,8,8,8,8,8,8,8,8,2,
-  1,1,3,3,4,5,6,3,8,8,8,8,8,8,8,8,8,
-  1,1,3,3,5,6,3,3,1,1,1,1,1,1,1,0,0,
-  1,1,3,3,6,3,3,1,1,1,1,1,1,1,1,0,0,
-  1,1,3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,
-  1,1,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,
-  1,1,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,
-  1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-  1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+  2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  3,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  3,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  3,3,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  3,3,4,2,2,0,0,0,0,0,0,0,0,0,0,0,0,
+  3,3,4,4,2,2,0,0,0,0,0,0,0,0,0,0,0,
+  3,3,4,4,4,2,2,0,0,0,0,0,0,0,0,0,0,
+  3,3,4,4,4,4,2,2,0,0,0,0,0,0,0,0,0,
+  3,3,4,4,4,5,6,2,2,0,0,0,0,0,0,0,0,
+  3,3,4,4,5,6,7,5,2,2,0,0,0,0,0,0,0,
+  3,3,4,5,6,7,5,4,5,2,2,0,0,0,0,0,0,
+  3,3,5,6,7,5,4,5,6,7,2,2,0,0,0,0,0,
+  3,3,6,7,5,4,5,6,7,7,7,2,2,0,0,0,0,
+  3,3,7,5,4,5,6,7,7,7,7,7,2,2,0,0,0,
+  3,3,5,4,5,6,8,8,8,8,8,8,8,8,2,0,0,
+  3,3,4,5,6,3,8,8,8,8,8,8,8,8,8,0,0,
+  3,3,5,6,3,3,0,0,0,0,0,0,0,0,0,0,0,
+  3,3,6,3,3,0,0,0,0,0,0,0,0,0,0,0,0,
+  3,3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  3,3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  3,3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
 );
 const cursorPal: array[0..9*4-1] of Byte = (
     0,  0,  0,  0,
@@ -52,18 +69,44 @@ var
 begin
   if (curtexid <> 0) then exit; //begin glDeleteTextures(1, @curtexid); curtexid := 0; end;
 
-  GetMem(tex, curWidth*curHeight*4);
+  GetMem(tex, curTexWidth*curTexHeight*4);
+  FillChar(tex^, curTexWidth*curTexHeight*4, 0);
 
-  tpp := tex;
+  // draw shadow
+  for y := 0 to curHeight-1 do
+  begin
+    for x := 0 to curWidth-1 do
+    begin
+      if (cursorImg[y*curWidth+x] <> 0) then
+      begin
+        c := 1*4;
+        tpp := tex+((y+1)*(curTexWidth*4)+(x+3)*4);
+        tpp^ := cursorPal[c+0]; Inc(tpp);
+        tpp^ := cursorPal[c+1]; Inc(tpp);
+        tpp^ := cursorPal[c+2]; Inc(tpp);
+        tpp^ := cursorPal[c+3]; Inc(tpp);
+        tpp^ := cursorPal[c+0]; Inc(tpp);
+        tpp^ := cursorPal[c+1]; Inc(tpp);
+        tpp^ := cursorPal[c+2]; Inc(tpp);
+        tpp^ := cursorPal[c+3]; Inc(tpp);
+      end;
+    end;
+  end;
+
+  // draw cursor
   for y := 0 to curHeight-1 do
   begin
     for x := 0 to curWidth-1 do
     begin
       c := cursorImg[y*curWidth+x]*4;
-      tpp^ := cursorPal[c+0]; Inc(tpp);
-      tpp^ := cursorPal[c+1]; Inc(tpp);
-      tpp^ := cursorPal[c+2]; Inc(tpp);
-      tpp^ := cursorPal[c+3]; Inc(tpp);
+      if (c <> 0) then
+      begin
+        tpp := tex+(y*(curTexWidth*4)+x*4);
+        tpp^ := cursorPal[c+0]; Inc(tpp);
+        tpp^ := cursorPal[c+1]; Inc(tpp);
+        tpp^ := cursorPal[c+2]; Inc(tpp);
+        tpp^ := cursorPal[c+3]; Inc(tpp);
+      end;
     end;
   end;
 
@@ -79,7 +122,7 @@ begin
   //GLfloat[4] bclr = 0.0;
   //glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, bclr.ptr);
 
-  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, curWidth, curHeight, 0, GL_RGBA{gltt}, GL_UNSIGNED_BYTE, tex);
+  glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, curTexWidth, curTexHeight, 0, GL_RGBA{gltt}, GL_UNSIGNED_BYTE, tex);
   glFlush();
 
   //FreeMem(tex);
@@ -95,14 +138,14 @@ begin
   glEnable(GL_TEXTURE_2D);
   // color and opacity
   glColor4f(1, 1, 1, 0.9);
-  Dec(msX, 2);
+  //Dec(msX, 2);
   glBegin(GL_QUADS);
     glTexCoord2f(0.0, 0.0); glVertex2i(msX, msY); // top-left
-    glTexCoord2f(1.0, 0.0); glVertex2i(msX+curWidth, msY); // top-right
-    glTexCoord2f(1.0, 1.0); glVertex2i(msX+curWidth, msY+curHeight); // bottom-right
-    glTexCoord2f(0.0, 1.0); glVertex2i(msX, msY+curHeight); // bottom-left
+    glTexCoord2f(1.0, 0.0); glVertex2i(msX+curTexWidth, msY); // top-right
+    glTexCoord2f(1.0, 1.0); glVertex2i(msX+curTexWidth, msY+curTexHeight); // bottom-right
+    glTexCoord2f(0.0, 1.0); glVertex2i(msX, msY+curTexHeight); // bottom-left
   glEnd();
-  Inc(msX, 2);
+  //Inc(msX, 2);
   glDisable(GL_BLEND);
   glDisable(GL_TEXTURE_2D);
   glColor4f(1, 1, 1, 1);
@@ -110,6 +153,34 @@ begin
 end;
 
 
+// ////////////////////////////////////////////////////////////////////////// //
+type
+  TScissorSave = record
+  public
+    wassc: Boolean;
+    scxywh: packed array[0..3] of GLint;
+
+  public
+    procedure save (enableScissoring: Boolean);
+    procedure restore ();
+  end;
+
+procedure TScissorSave.save (enableScissoring: Boolean);
+begin
+  wassc := (glIsEnabled(GL_SCISSOR_TEST) <> 0);
+  if wassc then glGetIntegerv(GL_SCISSOR_BOX, @scxywh[0]) else glGetIntegerv(GL_VIEWPORT, @scxywh[0]);
+  //conwritefln('(%d,%d)-(%d,%d)', [scxywh[0], scxywh[1], scxywh[2], scxywh[3]]);
+  if enableScissoring then glEnable(GL_SCISSOR_TEST);
+end;
+
+
+procedure TScissorSave.restore ();
+begin
+  glScissor(scxywh[0], scxywh[1], scxywh[2], scxywh[3]);
+  if wassc then glEnable(GL_SCISSOR_TEST) else glDisable(GL_SCISSOR_TEST);
+end;
+
+
 // ////////////////////////////////////////////////////////////////////////// //
 // fonts
 const kgiFont6: array[0..256*8-1] of Byte  = (
@@ -385,12 +456,23 @@ var
 procedure createFonts ();
 begin
   if (font6texid = 0) then font6texid := createFontTexture(kgiFont6, kgiFont6PropWidth, false);
-  if (font8texid = 0) then font8texid := createFontTexture(kgiFont8, kgiFont8PropWidth, true);
-  if (prfont6texid = 0) then prfont6texid := createFontTexture(kgiFont6, kgiFont6PropWidth, false);
+  if (font8texid = 0) then font8texid := createFontTexture(kgiFont8, kgiFont8PropWidth, false);
+  if (prfont6texid = 0) then prfont6texid := createFontTexture(kgiFont6, kgiFont6PropWidth, true);
   if (prfont8texid = 0) then prfont8texid := createFontTexture(kgiFont8, kgiFont8PropWidth, true);
 end;
 
 
+// ////////////////////////////////////////////////////////////////////////// //
+procedure normRGBA (var r, g, b, a: Integer); inline;
+begin
+  if (a < 0) then a := 0 else if (a > 255) then a := 255;
+  if (r < 0) then r := 0 else if (r > 255) then r := 255;
+  if (g < 0) then g := 0 else if (g > 255) then g := 255;
+  if (b < 0) then b := 0 else if (b > 255) then b := 255;
+end;
+
+
+// ////////////////////////////////////////////////////////////////////////// //
 function textWidth6 (const s: AnsiString): Integer;
 var
   f: Integer;
@@ -419,13 +501,19 @@ var
 begin
   result := 0;
   if (Length(s) = 0) then exit;
-  if (a < 0) then a := 0 else if (a > 255) then a := 255;
-  if (r < 0) then r := 0 else if (r > 255) then r := 255;
-  if (g < 0) then g := 0 else if (g > 255) then g := 255;
-  if (b < 0) then b := 0 else if (b > 255) then b := 255;
+  normRGBA(r, g, b, a);
 
-  glEnable(GL_BLEND);
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  if (a < 255) then
+  begin
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  end
+  else
+  begin
+    glDisable(GL_BLEND);
+  end;
+  glEnable(GL_ALPHA_TEST);
+  glAlphaFunc(GL_NOTEQUAL, 0.0);
   glEnable(GL_TEXTURE_2D);
   // color and opacity
   glColor4f(r/255.0, g/255.0, b/255.0, a/255.0);
@@ -454,6 +542,7 @@ begin
     end;
   end;
 
+  glDisable(GL_ALPHA_TEST);
   glDisable(GL_BLEND);
   glDisable(GL_TEXTURE_2D);
   glColor4f(1, 1, 1, 1);
@@ -463,31 +552,8 @@ end;
 
 // ////////////////////////////////////////////////////////////////////////// //
 procedure drawLine (x1, y1, x2, y2: Integer; r, g, b: Integer; a: Integer=255);
-
-  procedure lcor (var x1, y1, x2, y2: Integer);
-  begin
-    if (y2 < y1) then
-    begin
-      x1 := x1 xor x2;
-      x2 := x1 xor x2;
-      x1 := x1 xor x2;
-
-      y1 := y1 xor y2;
-      y2 := y1 xor y2;
-      y1 := y1 xor y2;
-    end;
-
-    if (x1 < x2) then Inc(X2) else Inc(x1);
-    Inc(y2);
-  end;
-
 begin
-  lcor(x1, y1, x2, y2);
-
-  if (a < 0) then a := 0 else if (a > 255) then a := 255;
-  if (r < 0) then r := 0 else if (r > 255) then r := 255;
-  if (g < 0) then g := 0 else if (g > 255) then g := 255;
-  if (b < 0) then b := 0 else if (b > 255) then b := 255;
+  normRGBA(r, g, b, a);
 
   if (a < 255) then
   begin
@@ -501,60 +567,118 @@ begin
 
   glDisable(GL_TEXTURE_2D);
   glColor4f(r/255.0, g/255.0, b/255.0, a/255.0);
+
   glLineWidth(1);
+  glPointSize(1);
 
   glBegin(GL_LINES);
-    glVertex2i(x1, y1);
-    glVertex2i(x2, y2);
+    glVertex2f(x1+0.37, y1+0.37);
+    glVertex2f(x2+0.37, y2+0.37);
   glEnd();
 
+  if (x1 <> x2) or (y1 <> y2) then
+  begin
+    glBegin(GL_POINTS);
+      glVertex2f(x2+0.37, y2+0.37);
+    glEnd();
+  end;
+
   glColor4f(1, 1, 1, 1);
   glDisable(GL_BLEND);
 end;
 
 
-// ////////////////////////////////////////////////////////////////////////// //
-procedure shadeRect (x, y, w, h: Integer; a: Integer);
+procedure drawRect (x, y, w, h: Integer; r, g, b: Integer; a: Integer=255);
 begin
+  if (w < 0) or (h < 0) then exit;
+  normRGBA(r, g, b, a);
+  if (a < 255) then
+  begin
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  end
+  else
+  begin
+    glDisable(GL_BLEND);
+  end;
+  glDisable(GL_TEXTURE_2D);
+  glLineWidth(1);
+  glDisable(GL_LINE_SMOOTH);
+  glDisable(GL_POLYGON_SMOOTH);
+  glColor4f(r/255.0, g/255.0, b/255.0, a/255.0);
+  if (w = 1) and (h = 1) then
+  begin
+    glBegin(GL_POINTS);
+      glVertex2f(x+0.37, y+0.37);
+    glEnd();
+  end
+  else
+  begin
+    glBegin(GL_LINES);
+      glVertex2i(x, y); glVertex2i(x+w, y); // top
+      glVertex2i(x, y+h-1); glVertex2i(x+w, y+h-1); // bottom
+      glVertex2f(x+0.37, y+1); glVertex2f(x+0.37, y+h-1); // left
+      glVertex2f(x+w-1+0.37, y+1); glVertex2f(x+w-1+0.37, y+h-1); // right
+    glEnd();
+  end;
+  //glRect(x, y, x+w, y+h);
+  glColor4f(1, 1, 1, 1);
+  glDisable(GL_BLEND);
+end;
+
+
+procedure drawRectUI (x, y, w, h: Integer; r, g, b: Integer; a: Integer=255);
+begin
+  drawRect(x, y, w, h, r, g, b, a);
+end;
+
+
+procedure darkenRect (x, y, w, h: Integer; a: Integer);
+begin
+  if (w < 0) or (h < 0) then exit;
   if (a < 0) then a := 0;
   if (a > 255) then a := 255;
   glEnable(GL_BLEND);
-  glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR);
-  //glBlendFunc(GL_ONE, GL_DST_COLOR);
-  //glBlendEquation(GL_FUNC_SUBTRACT);
+  glBlendFunc(GL_ZERO, GL_SRC_ALPHA);
+  glDisable(GL_LINE_SMOOTH);
+  glDisable(GL_POLYGON_SMOOTH);
   glDisable(GL_TEXTURE_2D);
-  glColor4f(0.0, 0.0, a/255.0, 1.0);
+  glColor4f(0.0, 0.0, 0.0, a/255.0);
   glBegin(GL_QUADS);
     glVertex2i(x, y);
     glVertex2i(x+w, y);
     glVertex2i(x+w, y+h);
     glVertex2i(x, y+h);
   glEnd();
+  //glRect(x, y, x+w, y+h);
   glColor4f(1, 1, 1, 1);
   glDisable(GL_BLEND);
   //glBlendEquation(GL_FUNC_ADD);
 end;
 
 
-// ////////////////////////////////////////////////////////////////////////// //
 procedure fillRect (x, y, w, h: Integer; r, g, b: Integer; a: Integer=255);
 begin
-  if (a < 0) then a := 0;
-  if (a > 255) then a := 255;
-  if (r < 0) then r := 0 else if (r > 255) then r := 255;
-  if (g < 0) then g := 0 else if (g > 255) then g := 255;
-  if (b < 0) then b := 0 else if (b > 255) then b := 255;
-  glEnable(GL_BLEND);
-  //glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-  //glBlendFunc(GL_SRC_ALPHA, GL_DST_ALPHA);
-  glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+  if (w < 0) or (h < 0) then exit;
+  normRGBA(r, g, b, a);
+  if (a < 255) then
+  begin
+    glEnable(GL_BLEND);
+    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  end
+  else
+  begin
+    glDisable(GL_BLEND);
+  end;
+  glDisable(GL_LINE_SMOOTH);
+  glDisable(GL_POLYGON_SMOOTH);
   glDisable(GL_TEXTURE_2D);
   glColor4f(r/255.0, g/255.0, b/255.0, a/255.0);
   glBegin(GL_QUADS);
-    glVertex2i(x, y);
-    glVertex2i(x+w, y);
-    glVertex2i(x+w, y+h);
-    glVertex2i(x, y+h);
+    glVertex2f(x, y);
+    glVertex2f(x+w, y);
+    glVertex2f(x+w, y+h);
+    glVertex2f(x, y+h);
   glEnd();
   glColor4f(1, 1, 1, 1);
   glDisable(GL_BLEND);
@@ -578,14 +702,14 @@ end;
 
 function drawText6Prop (x, y: Integer; const s: AnsiString; r, g, b: Integer; a: Integer=255): Integer;
 begin
-  if (font6texid = 0) then createFonts();
-  result := drawTextInternal(6, x, y, s, r, g, b, a, font6texid, kgiFont6PropWidth, true);
+  if (prfont6texid = 0) then createFonts();
+  result := drawTextInternal(6, x, y, s, r, g, b, a, prfont6texid, kgiFont6PropWidth, true);
 end;
 
 function drawText8Prop (x, y: Integer; const s: AnsiString; r, g, b: Integer; a: Integer=255): Integer;
 begin
-  if (font8texid = 0) then createFonts();
-  result := drawTextInternal(8, x, y, s, r, g, b, a, font8texid, kgiFont8PropWidth, true);
+  if (prfont8texid = 0) then createFonts();
+  result := drawTextInternal(8, x, y, s, r, g, b, a, prfont8texid, kgiFont8PropWidth, true);
 end;
 
 
@@ -609,16 +733,16 @@ end;
 
 function drawText6PropXC (x, y: Integer; const s: AnsiString; r, g, b: Integer; a: Integer=255): Integer;
 begin
-  if (font6texid = 0) then createFonts();
+  if (prfont6texid = 0) then createFonts();
   x -= textWidth6(s) div 2;
-  result := drawTextInternal(6, x, y, s, r, g, b, a, font6texid, kgiFont6PropWidth, true);
+  result := drawTextInternal(6, x, y, s, r, g, b, a, prfont6texid, kgiFont6PropWidth, true);
 end;
 
 function drawText8PropXC (x, y: Integer; const s: AnsiString; r, g, b: Integer; a: Integer=255): Integer;
 begin
-  if (font8texid = 0) then createFonts();
+  if (prfont8texid = 0) then createFonts();
   x -= textWidth8(s) div 2;
-  result := drawTextInternal(8, x, y, s, r, g, b, a, font8texid, kgiFont8PropWidth, true);
+  result := drawTextInternal(8, x, y, s, r, g, b, a, prfont8texid, kgiFont8PropWidth, true);
 end;