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 RectInRect(Rect1,Rect2:TRect):Boolean;
//procedure Draw2D_Line( const X1, Y1, X2, Y2 : Single; const Color : DWORD; const Alpha : Byte; const FX : DWORD );stdcall;
 function distance_dbl(x1,y1,x2,y2: double): double;
 function PointInCircle(X,Y:Single;Cx,Cy,Cr:Single):boolean;
 function PointInRect(X,Y:Single;Rx,RY,Rw,Rh:Single):Boolean;

 procedure DrawCircle(cx,cy,r:single;
                     Color:Integer=$FFFFFF;
                     Alpha:Byte=255;
                     num_segments:integer=26;
                     fill:boolean=false);
 procedure DrawLine( ax, ay, bx, by, width:single; r,g,b,a:byte );
 function convert(s:real):real;

implementation
 uses IniFile,IDX_sound;



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


 
procedure DrawCircle(cx,cy,r:single;
                     Color:Integer=$FFFFFF;
                     Alpha:Byte=255;
                     num_segments:integer=26;
                     fill:boolean=false);
var
i:integer;
theta,x,y:single;
begin

glPushMatrix;
if Alpha<>255 then glEnable(GL_BLEND);

if fill=false then glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );

glColor4ub(
            (   Color and $FF              ),
            ( ( Color and $FF00   ) shr 8  ),
            ( ( Color and $FF0000 ) shr 16 ),
                Alpha
         );

glBegin( GL_POLYGON );

	for i:= 0 to num_segments do
	begin
		theta:= (2.0 * 3.1415926 * i) / (num_segments);//get the current angle

		x := r * cos(theta);//calculate the x component
		y := r * sin(theta);//calculate the y component

		glVertex2f(x + cx, y + cy);//output vertex

	end;
	glEnd();

if fill=false then  glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );

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

procedure DrawLine( ax, ay, bx, by, width:single; r,g,b,a:byte );
begin
    glDisable(GL_TEXTURE_2D);
    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glColor4ub( r, g, b, a);

    glLineWidth(width);
    glBegin(GL_LINES);
    glVertex2f( ax, ay);
    glVertex2f( bx, by);
    glEnd();

    glDisable(GL_BLEND);
    glEnable(GL_TEXTURE_2D);
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;

function PointInCircle(X,Y:Single;Cx,Cy,Cr:Single):boolean;
begin
  Result := sqr( Cx - X ) + sqr( Cy - Y ) < sqr( Cr );
end;


 function distance_dbl(x1,y1,x2,y2: double): double;
begin
  result:=Sqrt(Sqr(x1-x2)+Sqr(y1-y2));
end;


function RectInRect(Rect1,Rect2:TRect):Boolean;
begin
   Result := ( Rect1.Left + Rect1.Right >= Rect2.Left ) and ( Rect1.Left <= Rect2.Left + Rect2.Right ) and
            ( Rect1.Top + Rect1.Bottom >= Rect2.Top ) and ( Rect1.Top <= Rect2.Top + Rect2.Bottom );
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;

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;


	        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.
