unit _render;
//----------------------------------------------------------------------------------------------------------------------
// Alex 'Shirson' Nevskiy 2012-08
//----------------------------------------------------------------------------------------------------------------------
interface

uses _var, _scd, exgine, openGL, SysUtils;

type
  TGUI = record
    Ch : byte;
    FG : byte;
    BG : byte;
  end;

const
  TotalW=80;
  TotalH=25;
  CharW=10;
  CharH=14;


  // Colors
  colBlack =    0; //    (#000000) 	000000 	0
  colBlue =     1; //    (#0000AA) 	000001 	1
  colGreen =    2; //    (#00AA00) 	000010 	2
  colCyan =     3; //    (#00AAAA) 	000011 	3
  colRed =      4; //    (#AA0000) 	000100 	4
  colMagenta =  5; //    (#AA00AA) 	000101 	5
  colBrown =    6; //    (#AA5500) 	010100 	20
  colDarkGray =   7; //  (#555555) 	111000 	56 // Switched for seamless filtering
  colLightGray =  8; //  (#AAAAAA) 	000111 	7  //
  colLightBlue =  9; //  (#5555FF) 	111001 	57
  colLightGreen = 10;//   A (#55FF55) 	111010 	58
  colLightCyan =  11;//   B (#55FFFF) 	111011 	59
  colLightRed =   12;//   C (#FF5555) 	111100 	60
  colLightMagenta = 13;// D (#FF55FF) 	111101 	61
  colLightYellow =14; //  E (#FFFF55) 	111110 	62
  colWhite =      15; //  F (#FFFFFF) 	111111 	63
  colAlpha =      16;

  clWallHit=colRed;
  clBlood=colRed;  


  chBack = 131;

  chFace = 1;
  chFaceI= 2;
  chLife = 3;
  chArmor= 4;
  chShotLine=7;
  chUp =14;
  chDown=15;
  chPortal=19;

  chStar8=28;
  chCorpse=37;
  chEnemy=65; //97

  FGMark='/';
  BGMark='\';
var
  GUIMatrix : array[0..TotalW-1, 0..TotalH-1] of TGUI;
  FontTex : TTexture;
//  arColor:array [0..15, 0..2] of byte=(($00, $00, $00), ($00, $00, $AA), ($00, $AA, $00), ($00, $AA, $AA),
//                                       ($AA, $00, $00), ($AA, $00, $AA), ($AA, $55, $00), ($AA, $AA, $AA),
//                                       ($55, $55, $55), ($55, $55, $FF), ($55, $FF, $55), ($55, $FF, $FF),
//                                       ($FF, $55, $55), ($FF, $55, $FF), ($FF, $FF, $55), ($FF, $FF, $FF));
  arColor:array [0..15, 0..2] of byte=(($00, $00, $00), ($00, $00, $AA), ($00, $AA, $00), ($00, $AA, $AA),
                                       ($AA, $00, $00), ($AA, $00, $AA), ($AA, $55, $00), ($55, $55, $55),
                                       ($AA, $AA, $AA), ($55, $55, $FF), ($55, $FF, $55), ($55, $FF, $FF),
                                       ($FF, $55, $55), ($FF, $55, $FF), ($FF, $FF, $55), ($FF, $FF, $FF));


procedure RenderGUI;
procedure PrintString(s: string; GUI_X, GUI_Y:integer; FG, BG:byte); overload;
procedure PrintString(s: string; GUI_X, GUI_Y:integer; FG:byte); overload;
procedure PrintString(s: string; GUI_X, GUI_Y:integer; FG:byte; IgnoredChar:Char); overload;

procedure PrintColoredString(s: string; GUI_X, GUI_Y:integer; IgnoreBG: boolean; GhostString:boolean); overload;
procedure PrintColoredString(s: string; GUI_X, GUI_Y:integer; IgnoredChar: Char); overload;

procedure FillBG(x0, y0, x1, y1:integer; BG:byte); overload;
procedure FillBG(x0, y0, Count: integer; BG:byte); overload;

function ColorFilter(BaseColor, FilterColor: byte):byte;
function IfThenElseColor(Logic:boolean; ifTrue, ifFalse:byte):byte;

procedure DrawScrollV(GUI_X, GUI_Y, Size, Current, Total:integer);

function ReplaceSymbol(s:string):string;


implementation
uses LevelSys;

//----------------------------------------------------------------------------------------------------------------------

function IfThenElseColor(Logic:boolean; ifTrue, ifFalse:byte):byte;
begin
  if Logic then result:=ifTrue else result:=ifFalse;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure FillBG(x0,y0,x1,y1:integer; BG:byte); overload;
var x,y: integer;
begin
  for x:=x0 to x1 do
    for y:=y0 to y1 do
    GUIMatrix[x,y].BG:=BG;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure FillBG(x0, y0, Count:integer; BG:byte); overload;
var x: integer;
begin
  for x:=x0 to x0+Count-1 do
    GUIMatrix[x,y0].BG:=BG;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure PrintString(s: string; GUI_X, GUI_Y:integer; FG, BG:byte); overload;
var x:byte;
begin
  if Length(s)=0 then exit;
  for x:=1 to Length(s) do
  begin
    GUIMatrix[GUI_X + x - 1, GUI_Y].Ch:=byte(s[x]);
    GUIMatrix[GUI_X + x - 1, GUI_Y].FG:=FG;
    GUIMatrix[GUI_X + x - 1, GUI_Y].BG:=BG;
  end;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure PrintString(s: string; GUI_X, GUI_Y:integer; FG:byte); overload;
var x:byte;
begin
  if Length(s)=0 then exit;
  for x:=1 to Length(s) do
  begin
    GUIMatrix[GUI_X + x - 1, GUI_Y].Ch:=byte(s[x]);
    GUIMatrix[GUI_X + x - 1, GUI_Y].FG:=FG;
  end;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure PrintString(s: string; GUI_X, GUI_Y:integer; FG:byte; IgnoredChar:Char); overload;
var x:byte;
begin
  if Length(s)=0 then exit;
  for x:=1 to Length(s) do
  begin
    if s[x]<>IgnoredChar then
    begin
      GUIMatrix[GUI_X + x - 1, GUI_Y].Ch:=byte(s[x]);
      GUIMatrix[GUI_X + x - 1, GUI_Y].FG:=FG;
    end;
  end;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure PrintColoredString(s: string; GUI_X, GUI_Y:integer; IgnoreBG: boolean; GhostString:boolean); overload;
var x, CharIdx, FG, BG:byte;
//    isToPrint:byte;
    Ch:Char;
begin
  FG:=colWhite; BG:=colBlack;
  if Length(s)=0 then exit;
  x:=GUI_X; CharIdx:=1;
  repeat
    Ch:=s[CharIDx];
    case Ch of
      FGMark: if s[CharIDx+1]='$' then begin FG:=strtoint(copy(s,CharIdx+1,2));  inc(CharIdx,2); end;// FG:=strtoint('$'+s[CharIDx+1]);
      BGMark: if s[CharIDx+1]='$' then begin BG:=strtoint(copy(s,CharIdx+1,2));  inc(CharIdx,2); end; //BG:=strtoint('$'+s[CharIDx+1]);
         ' ': inc(x);
      else
      begin
        if not GhostString then
          GUIMatrix[x, GUI_Y].Ch:=byte(Ch);
        GUIMatrix[x, GUI_Y].FG:=FG;
        if not IgnoreBG then GUIMatrix[x, GUI_Y].BG:=BG;
        inc(x);
      end;
    end;
    inc(CharIdx);
  until CharIdx>Length(s);
end;

//----------------------------------------------------------------------------------------------------------------------

procedure PrintColoredString(s: string; GUI_X, GUI_Y:integer; IgnoredChar: Char); overload;
var x, CharIdx, FG:byte;
  //, BG:byte;
//    isToPrint:byte;
    Ch:Char;
begin
  FG:=colWhite; //BG:=colBlack;
  if Length(s)=0 then exit;
  x:=GUI_X; CharIdx:=1;
  repeat
    Ch:=s[CharIDx];
    case Ch of
      FGMark: if s[CharIDx+1]='$' then begin FG:=strtoint(copy(s,CharIdx+1,2));  inc(CharIdx,2); end;// FG:=strtoint('$'+s[CharIDx+1]);
      //BGMark: if s[CharIDx+1]='$' then begin BG:=strtoint(copy(s,CharIdx+1,2));  inc(CharIdx,2); end; //BG:=strtoint('$'+s[CharIDx+1]);
         ' ': inc(x);
    else
      begin
        if Ch<>IgnoredChar then
        begin
          GUIMatrix[x, GUI_Y].Ch:=byte(Ch);
          GUIMatrix[x, GUI_Y].FG:=FG;
          //GUIMatrix[x, GUI_Y].BG:=BG;
        end;
        inc(x);
      end;
    end;
    inc(CharIdx);
  until CharIdx>Length(s);
end;

//----------------------------------------------------------------------------------------------------------------------

procedure DrawColor(clIndex:integer);
const
  R=0;
  G=1;
  B=2;
  A=255;
begin
  glColor4ub(arColor[clIndex, R], arColor[clIndex, G], arColor[clIndex, B], A);
end;

//----------------------------------------------------------------------------------------------------------------------

procedure DrawGUI;
const prp = 16/256;

var row, col : single;
    x,y:integer;

    ///////////////////////////////////////
    procedure RawDraw(Ch:Byte);
    begin
      col:=Ch mod 16;
      row:=Ch div 16;

      row:=row/16;
      col:=col/16;

      glBegin(GL_QUADS);
        glTexCoord2d(col,         row);       glVertex2f( 0, 0);
        glTexCoord2d(col + prp,   row);       glVertex2f(16, 0);
        glTexCoord2d(col + prp,   row + prp); glVertex2f(16, 16);
        glTexCoord2d(col,         row + prp); glVertex2f( 0, 16);
      glEnd;
    end;
    ///////////////////////////////////////

begin
  glPushAttrib(GL_ENABLE_BIT);
  glDisable(GL_DEPTH_TEST);
  glDisable(GL_CULL_FACE);
  glDisable(GL_LIGHTING);
  glEnable(GL_ALPHA_TEST);
  glEnable(GL_TEXTURE_2D);
  glAlphaFunc(GL_GEQUAL, 1/255);
  ogl.Blend(BT_SUB);
  tex.Enable(FontTex, 0);
  glPushMatrix;
  for x:=0 to TotalW-1 do
  begin
    glPopMatrix;
    glPushMatrix;
    glTranslatef(x * CharW, 0, 0);
    for y:=0 to TotalH-1 do
    begin
      if (GUIMatrix[x, y].FG<>0) or (GUIMatrix[x, y].BG<>0) then
      begin
        DrawColor(GUIMatrix[x, y].BG);
        RawDraw(chBack);
        DrawColor(GUIMatrix[x, y].FG);
        RawDraw(byte(GUIMatrix[x, y].Ch));
      end;
      glTranslatef(0, CharH, 0);
    end;
  end;
  glPopMatrix;
  glPopAttrib;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure RenderGUI;
begin
  //PrintString('0123456789', 0, 0, 15, 0);
  //PrintColoredString('012ŽA3456789', 0, 1);
  DrawColor(colWhite);
  DrawGUI;                     
  //StringOut(inttostr(ogl.fps), 70, 1, 15, 0);
//  for row:=0 to 15 do
//    for col:=0 to 15 do
//      CharOut(char(col+row*16), col, row, 15, 0);
//  exit;
//  for col:=0 to TotalW-1 do
//    for row:=0 to TotalH-1 do
//    begin
//    if (GUIMatrix[col, row].FG<>0) or (GUIMatrix[col, row].BG<>0) then
//      CharOut(GUIMatrix[col, row].Ch, col, row, GUIMatrix[col, row].FG, GUIMatrix[col, row].BG);
//      //ogl.TextOut(DebugFont, col * CharW, Row * CharH, GUIMatrix[col, row].Ch);
//    end;

  //CharOut(' ',GameInput.MouseX, GameInput.MouseY, 0, 3);
  //CharOut('@',79,24,15,4);
end;

//----------------------------------------------------------------------------------------------------------------------

function ColorFilter(BaseColor, FilterColor: byte):byte;
begin
  result:=BaseColor;
  if FilterColor=16 then exit;

  if FilterColor>=8 then
    case BaseColor of
      1..7 : result:=FilterColor-8;
      8..15: result:=FilterColor;
    end
  else
    case BaseColor of
      0..7 : result:=0;
      8..15: result:=FilterColor;
    end;
end;

//----------------------------------------------------------------------------------------------------------------------

procedure DrawScrollV(GUI_X, GUI_Y, Size, Current, Total:integer);
var Scrl:integer;
    Idx:integer;
    FG:byte;
begin
  Scrl:=trunc((Size-2) * Current /Total)+1;
  for Idx:=GUI_Y+1 to GUI_Y+Size-2 do
  begin
    if Scrl = Idx then
      FG:=colLightGray
    else
      FG:=colDarkGray;
    PrintString(char(blWall-1), GUI_X, idx, FG);
    PrintString(char(chUp), GUI_X, GUI_Y, colLightGray);
    PrintString(char(chDown), GUI_X, GUI_Y+Size-1, colLightGray);
  end;
end;

//----------------------------------------------------------------------------------------------------------------------

function ReplaceSymbol(s:string):string;
begin
  s:=StringReplace(s,'%Life%', char(chLife), [rfReplaceAll, rfIgnoreCase]);
  s:=StringReplace(s,'%Armor%', char(chArmor), [rfReplaceAll, rfIgnoreCase]);
  s:=StringReplace(s,'%Face%', char(chFace), [rfReplaceAll, rfIgnoreCase]);
  s:=StringReplace(s,'%FaceI%', char(chFaceI), [rfReplaceAll, rfIgnoreCase]);
  s:=StringReplace(s,'%Portal%', char(chPortal), [rfReplaceAll, rfIgnoreCase]);
  s:=StringReplace(s,'%Up%', char(22), [rfReplaceAll, rfIgnoreCase]);
  s:=StringReplace(s,'%Down%', char(23), [rfReplaceAll, rfIgnoreCase]);
  s:=StringReplace(s,'%Right%', char(24), [rfReplaceAll, rfIgnoreCase]);
  s:=StringReplace(s,'%Left%', char(25), [rfReplaceAll, rfIgnoreCase]);
  result:=s;
end;

//----------------------------------------------------------------------------------------------------------------------

end.



