unit GMUtilite;

interface
      uses Windows,OpenGl,GMVars,SysUtils,Math ;


procedure SaveOptions(Filename:string);
procedure Enable2d(A:boolean);
procedure glBlend(ID: Byte);
procedure VBL2(vsync : TVSyncMode);
procedure FreeSystemFont2D(font: DWORD); stdcall;
function GetTimer: integer;
function ExtractFileDir(const FileName: string): string;
function CreateSystemFont2D(AD:hDC;Face: PChar; W, H: integer): DWORD; stdcall;
procedure SText2D(font: DWORD; const str: string; X, Y, color: integer; Alpha : byte); stdcall;
procedure DrawRectangle2D(X, Y:Single; Width, Height:Single; Color:integer; Alpha : byte=255;Angle:integer=0; Fill : boolean = false;Center:boolean=false);
function IntToStr(x: integer): string;
function StrToInt(const S: string): Integer;
procedure DrawTextureBox(x,y:Single;Width,Height:Single;textId:cardinal;Angle:Integer=0;Center:boolean=false;Color:Integer=$FFFFFF;Alpha:Byte=255;flipx:Boolean=False;flipy:Boolean=False);
procedure ReadOptions(Name:string);

Function Range( Number:Integer ; LowerLimit:Integer = 0; UpperLimit:Integer = 255):Integer;
function Distance(a,b:Tpoint): integer;


procedure DrawTextureBoxIJ(x,y,w,h:single;
                           textId:cardinal;
                           color: integer;
                           Alpha : byte;
                           center:boolean=false;
                           angle:integer=0;
                           sprx:Integer=-1;
                           spry:Integer=-1);

function PointInRect(X,Y:Single;Rx,RY,Rw,Rh:Single):Boolean;

implementation
 uses IniFile,IDX_sound;


procedure DrawTextureBoxIJ(x,y,w,h:single;
                         textId:cardinal;
                         color: integer;
                         Alpha : byte;
                         center:boolean=false;
                         angle:integer=0;
                         sprx:Integer=-1;
                         spry:Integer=-1);
var
rx,ry,dx,dy:single;
spx:array[0..3]of Single;
spy:array[0..3]of Single;
begin
 if Alpha<>255 then
  glEnable(GL_BLEND);
 glcolor4ub(GetRValue(Color),GetGValue(Color),GetBValue(Color),Alpha);

  glEnable( GL_TEXTURE_2D );
  glPushMatrix();
  glTranslatef(X,Y,0);
  if Angle<>0 then glrotatef(Angle,0,0,1);
  glBindTexture(GL_TEXTURE_2D, textId); // use floor

  spx[0]:=0;
  spx[1]:=1;
  spx[2]:=1;
  spx[3]:=0;

  spy[0]:=1;
  spy[1]:=1;
  spy[2]:=0;
  spy[3]:=0;

  if (sprx>-1)and(spry>-1) then
  begin
//    spx:=sprx*0.25; //(1/128)*32=0.25;
//    spy:=spry*0.25;
//    spw:=0.25;
//    sph:=0.25;
//    sph1:=1-(spy+sph);
//    sph2:=1-(spy);

       dx:=sprx*0.25;
       dy:=spry*0.125;

      spx[0]:=dx;
      spx[1]:=dx+0.25;
      spx[2]:=dx+0.25;
      spx[3]:=dx;

      spy[0]:=1-(dy); //1-(dy+0.25)
      spy[1]:=1-(dy);
      spy[2]:=1-(dy+0.125);
      spy[3]:=1-(dy+0.125);


//      spx[0]:=dx;
//      spx[1]:=dx+0.25;
//      spx[2]:=dx+0.25;
//      spx[3]:=dx;
//
//      spy[0]:=(dy); //1-(dy+0.25)
//      spy[1]:=(dy);
//      spy[2]:=(dy+0.125);
//      spy[3]:=(dy+0.125);

  end;

 glBegin(GL_QUADS);
 if center then
  begin
          Rx:=W/2;
          Ry:=H/2;
      glTexCoord2f(spx[0],spy[0]);  glVertex2f(-rx,-ry);
      glTexCoord2f(spx[1],spy[1]);  glVertex2f(rx,-ry);
      glTexCoord2f(spx[2],spy[2]);  glVertex2f(rx,ry);
      glTexCoord2f(spx[3],spy[3]);  glVertex2f(-rx,ry);
   end
   else
   begin
      glTexCoord2f(spx[0],spy[0]);  glVertex2f(0, 0);
      glTexCoord2f(spx[1],spy[1]);  glVertex2f(0+w,0);
      glTexCoord2f(spx[2],spy[2]);  glVertex2f(0+w, 0+h);
      glTexCoord2f(spx[3],spy[3]);  glVertex2f(0,0+h);
   end;

  glEnd();
  glPopMatrix();
  if Alpha<>255 then glDisable(GL_BLEND);
  glDisable( GL_TEXTURE_2D );
end;


function Distance(a,b:Tpoint): integer;
begin
  result := sqr(a.x-b.x) + sqr(a.y-b.y);
end;


function convert(s:real):real;
begin
result:= s * (pi / 180);
end;


Function Range( Number:Integer ; LowerLimit:Integer = 0; UpperLimit:Integer = 255):Integer;
begin
    If Number > UpperLimit Then begin Range := UpperLimit; Exit; end;
    If Number < LowerLimit Then Range := LowerLimit Else Range := Number;
End;






function ReadValueFromIniFile(Filename, Section, Key, Default: string):string; stdcall;
var ini : TIniFile;
begin
  result:='';
  if fileexists(Filename) then
  begin
    ini:=TIniFile.Create(Filename);
    result:=ini.GetIniSectionKeyValue(Section,Key);

    if result='-1' then result:=Default;
    ini.Free;
  end
  else
    result:=Default;

end;

function PointInRect(X,Y:Single;Rx,RY,Rw,Rh:Single):Boolean;
begin
  Result := ( X > RX ) and ( X < RX + RW ) and
            ( Y > RY ) and ( Y < RY + RH );
end;


procedure SaveOptions(Filename:string);
var
  ini : TIniFile;
begin

  if fileexists(Filename) then
  begin
    ini:=TIniFile.Create(Filename);

    if playingmusic then
     ini.SetIniSectionKeyValue('Media','PlayMusic','1')
    else
     ini.SetIniSectionKeyValue('Media','PlayMusic','0');

    if playingsound then
     ini.SetIniSectionKeyValue('Media','PlaySound','1')
    else
     ini.SetIniSectionKeyValue('Media','PlaySound','0');

     ini.SaveToFile;

    ini.Free;
  end


end;


procedure ReadOptions(Name:string);
var
  ini : TIniFile;
  S:string;
  Loading:boolean;
  i,j,k,Myk:integer;
begin

 SCRW   :=strtoint(ReadValueFromIniFile(Name,'Screen','Width','800'));
 SCRH   :=strtoint(ReadValueFromIniFile(Name,'Screen','Height','600'));
 SCRBit :=strtoint(ReadValueFromIniFile(Name,'Screen','Bit','32'));
 SCRHZ  :=strtoint(ReadValueFromIniFile(Name,'Screen','Herz','60'));

 s:=ReadValueFromIniFile(Name,'Screen','Sync','1');
 if s='1' then Sync:=true else Sync:=false;

 s:=ReadValueFromIniFile(Name,'Screen','FullScreen','0');
 if s='1' then FullScreen:=true else FullScreen:=false;

 s:=ReadValueFromIniFile(Name,'Screen','CenterScreen','1');
 if s='1' then CenterScreen:=true else CenterScreen:=false;

 s:=ReadValueFromIniFile(Name,'Media','PlayMusic','0');
 if s='1' then playingmusic:=true else playingmusic:=false;

 s:=ReadValueFromIniFile(Name,'Media','PlaySound','0');
 if s='1' then playingsound:=true else playingsound:=false;

 SCR2W:=SCRW div 2;
 SCR2H:=SCRH div 2;;

end;

procedure DrawTextureBox(x,y:Single;Width,Height:Single;textId:cardinal;Angle:Integer=0;Center:boolean=false;Color:Integer=$FFFFFF;Alpha:Byte=255;flipx:Boolean=False;flipy:Boolean=False);
var
  Rx,Ry:real;
  flp:array[0..3] of TPoint;
begin
  glcolor4ub(GetRValue(Color),GetGValue(Color),GetBValue(Color),Alpha);
  if Alpha<>255 then glEnable(GL_BLEND);
  glEnable( GL_TEXTURE_2D );
  glPushMatrix();
  glTranslatef(X,Y,0);
  if Angle<>0 then glrotatef(Angle,0,0,1);
                glBindTexture(GL_TEXTURE_2D, textId); // use floor
                glBegin(GL_QUADS);

     flp[0].x:=0; flp[0].y:=1;
     flp[1].x:=1; flp[1].y:=1;
     flp[2].x:=1; flp[2].y:=0;
     flp[3].x:=0; flp[3].y:=0;

     if flipy then
     begin
      flp[0].x:=0; flp[0].y:=0;
      flp[1].x:=1; flp[1].y:=0;
      flp[2].x:=1; flp[2].y:=1;
      flp[3].x:=0; flp[3].y:=1;
     end;

                if Center then
                  begin
                      Rx:=Width/2;
                      Ry:=Height/2;
                   glTexCoord2f(flp[0].x,flp[0].y); glVertex2f(-rx,-ry);
                   glTexCoord2f(flp[1].x,flp[1].y); glVertex2f(rx,-ry);
                   glTexCoord2f(flp[2].x,flp[2].y); glVertex2f(rx,ry);
                   glTexCoord2f(flp[3].x,flp[3].y); glVertex2f(-rx,ry);
                 end
                 else
                 begin
                   glTexCoord2f(flp[0].x,flp[0].y); glVertex2f(0,0);
                   glTexCoord2f(flp[1].x,flp[1].y); glVertex2f(0+Width,0);
                   glTexCoord2f(flp[2].x,flp[2].y); glVertex2f(0+Width,0+Height);
                   glTexCoord2f(flp[3].x,flp[3].y); glVertex2f(0,0+Height);
                 end;


//		glTexCoord2f(0,1);  glVertex2f(0, 0);
//		glTexCoord2f(1,1);  glVertex2f(0+w,0);
//		glTexCoord2f(1,0);  glVertex2f(0+w, 0+h);
//		glTexCoord2f(0,0);  glVertex2f(0,0+h);
	        glEnd();
  glPopMatrix();
  glDisable( GL_TEXTURE_2D );

if Alpha<>255 then glDisable(GL_BLEND);
end;


// целое в строку
function IntToStr(x: integer): string;
begin
Str(x, Result);
end;

function StrToInt(const S: string): Integer;
var
  E: Integer;
begin
  Val(S, Result, E);
end;


procedure DrawRectangle2D(X, Y:Single; Width, Height:Single; Color:integer; Alpha : byte=255;Angle:integer=0; Fill : boolean = false;Center:boolean=false);
var
Rx,Ry:real;
begin

glPushMatrix;

glTranslatef(X,Y,0);

if Angle<>0 then glrotatef(Angle,0,0,1);
if Alpha<>255 then glEnable(GL_BLEND);

 if fill then
 begin

  glcolor4ub(GetRValue(Color),GetGValue(Color),GetBValue(Color),Alpha);
   glBegin(GL_QUADS);
  if center then
  begin
      Rx:=Width/2;
      Ry:=Height/2;
    glVertex2f(-rx,-ry);
    glVertex2f(rx,-ry);
    glVertex2f(rx,ry);
    glVertex2f(-rx,ry);
 end
 else
 begin
    glVertex2f(0,0);
    glVertex2f(0+Width,0);
    glVertex2f(0+Width,0+Height);
    glVertex2f(0,0+Height);
 end;

   glEnd;

 end else
 begin

  glcolor4ub(GetRValue(Color),GetGValue(Color),GetBValue(Color),Alpha);
   glBegin(GL_LINE_STRIP);
     if center then
  begin
      Rx:=Width/2;
      Ry:=Height/2;

    glVertex2f(-rx,-ry);
    glVertex2f(rx,-ry);
    glVertex2f(rx,ry);
    glVertex2f(-rx,ry);
    glVertex2f(-rx,-ry);
   end
   else
   begin

    glVertex2f(0,0);
    glVertex2f(0+Width,0);
    glVertex2f(0+Width,0+Height);
    glVertex2f(0,0+Height);
    glVertex2f(0,0-1);

   end;

   glEnd;

 end;
 glPopMatrix;

if Alpha<>255 then glDisable(GL_BLEND);
end;

procedure SText2D(font: DWORD; const str: string; X, Y, color: integer; Alpha : byte); stdcall;
begin
glPushMatrix();

if Alpha<>255 then
  glEnable(GL_BLEND);
 glcolor4ub(GetRValue(Color),GetGValue(Color),GetBValue(Color),Alpha);
 glRasterPos2f(X, Y);
 glListBase(font);
 glCallLists(Length(str), GL_UNSIGNED_BYTE, PChar(str));
if Alpha<>255 then
  glDisable(GL_BLEND);
glPopMatrix();
end;



function CreateSystemFont2D(AD:hDC;Face: PChar; W, H: integer): DWORD; stdcall;
var
 font : HFONT;
begin
Result := glGenLists(256);
font := CreateFont(H, W, 0, 0, 0, 0, 0, 0,RUSSIAN_CHARSET, OUT_TT_PRECIS, CLIP_DEFAULT_PRECIS,
                   ANTIALIASED_QUALITY, FW_BOLD {or FF_DONTCARE or DEFAULT_PITCH}, Face);
SelectObject(AD, font);
wglUseFontBitmaps(AD, 0, 256, Result);
DeleteObject(font);
end;


function ExtractFileDir(const FileName: string): string;
var
  I: Integer;
begin
  I := LastDelimiter(PathDelim + DriveDelim,Filename);
  if (I > 1) and (FileName[I] = PathDelim) and
    (((FileName[I - 1] <> PathDelim) and (FileName[I-1] <> DriveDelim)) or
    (ByteType(FileName, I-1) = mbTrailByte)) then Dec(I);
  while (ByteType(FileName, I-1) = mbTrailByte) and (I > 0) do Dec(I);
  Result := Copy(FileName, 1, I);
end;


function GetTimer: integer;
var
T : LARGE_INTEGER;
F : LARGE_INTEGER;
begin
QueryPerformanceFrequency(Int64(F));
QueryPerformanceCounter(Int64(T));
result := round(1000 * T.QuadPart / F.QuadPart);
end;



procedure FreeSystemFont2D(font: DWORD); stdcall;
begin
glDeleteLists(font, 256);
end;


procedure VBL2(vsync : TVSyncMode);
var
   i : Integer;
begin
   if WGL_EXT_swap_control then
   begin
      i := wglGetSwapIntervalEXT;
      case VSync of
         vsmSync    : if i<>1 then wglSwapIntervalEXT(1);
         vsmNoSync  : if i<>0 then wglSwapIntervalEXT(0);
      else
         Assert(False);
      end;
   end;

end;


// Прочие функции //
procedure glBlend(ID: Byte);
begin
if ID = 0 then
 glDisable(GL_BLEND)
else
 begin
 glEnable(GL_BLEND);
  case ID of
   1 : glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
   2 : glBlendFunc(GL_SRC_ALPHA, GL_ONE);
   3 : glBlendFunc(GL_ZERO, GL_SRC_COLOR);
  end;
 end;
end;

procedure Enable2d(A:boolean);
begin
 if A then
 begin
  glDisable(GL_DEPTH_TEST);
  glMatrixMode(GL_PROJECTION);
  glPushMatrix;
  glLoadIdentity;
  gluOrtho2D(0,SCRW,SCRH,0);
  glMatrixMode(GL_MODELVIEW);
  glPushMatrix;
  glLoadIdentity;
 end
 else
 begin
   glPopMatrix;
  glMatrixMode(GL_PROJECTION);
  glPopMatrix;
  glMatrixMode(GL_MODELVIEW);
  glEnable(GL_DEPTH_TEST);
 end;

 end;



end.
