unit iz_sprite;

interface
uses
  OpenGL,iz_types,iz_utils,iz_texture;

type
  izSpriteAnimation = record
    sID,
    eID,
    cID : word;
    delay : float;
    Time : float;
  end;

  izSprite = record
    Size,PatternSize : izSize_w;
    PatternXCount,
    PatternYCount : word;
    Animation : array of izSpriteAnimation;
    AnimationCount : word;
  end;

  izSpriteManager = class
    Items : array of izSprite;
    Count : uint;

    constructor Create();
    destructor Destroy();
    function Find() : int;
    function Add( Size,PatternSize : izSize_w) : int; //izzSprite;
    procedure Clear();
    function Add_Anim(id : word; sID, eID, cID : word; delay : float) : word;
    procedure Anim_Delete(id : word; AnimID : word);
    procedure Anim_Clear(id : word);
    procedure Anim_Update(id : word; AnimID : word; Time : float);
    procedure Draw_Full(id : word; PatternNumber : word; pos : izPosition_f; Angle : float);
    procedure Draw_Scale(id : word; PatternNumber : word; pos : izPosition_f; size : izSize_w; Angle : float);
    procedure Draw_Fast(id : word; pos : izPosition_f; Angle : float);
    procedure Draw_Alpha(id : uint; AnimID : word;  pos : izPosition_f; Angle : float);overload;
    procedure Draw_Alpha(id : uint; bFunc,bFunc2 : Cardinal; AnimID : word;  pos : izPosition_f; Angle : float);overload;
    procedure Draw_Alpha_Color(id : uint; bFunc,bFunc2 : Cardinal; AnimID : word; pos : izPosition_f; Angle : float; Color : izColor3f);
    procedure Draw_Alpha_Scale(id : uint; AnimID : word; pos : izPosition_f; size : izSize_w; Angle : float); overload;
    procedure Draw_Alpha_Scale(id : uint; bFunc,bFunc2 : Cardinal; AnimID : word; pos : izPosition_f; size : izSize_w; Angle : float); overload;
    procedure Draw_Anim(id : word; AnimID : word; pos : izPosition_f; Angle : float);
    procedure Draw_Anim_Scale(id : word; AnimID : word; pos : izPosition_f; size : izSize_w; Angle : float);
    procedure Draw_Anim_Scale_Alpha(id : word; AnimID : word; pos : izPosition_f; size : izSize_w; Angle : float);
    procedure Anim(id : word; AnimID : word; pos : izPosition_f; Angle : float; Time : float);
    procedure Draw_Anim_Alpha(id : word; AnimID : word; pos : izPosition_f; Angle : float); overload;
    procedure Draw_Anim_Alpha(id : word; bFunc,bFunc2 : Cardinal; AnimID : word; pos : izPosition_f; Angle : float);overload;
    procedure Draw_Anim_Alpha_Color(id : word; bFunc,bFunc2 : Cardinal; AnimID : word; pos : izPosition_f; Angle : float; Color : izColor3f);
  end;

implementation

constructor izSpriteManager.Create();
begin
   Count := 0;
   SetLength(Items,count);
end;

destructor izSpriteManager.Destroy();
begin
  Clear();
end;

function izSpriteManager.Find() : int;
var
  i : int;
begin
  Result := -1;
  for i := 0 to Count-1 do
    if Items[i].Size[0] = 0 then
    begin
      Result := i;
      break;
    end;
end;

function izSpriteManager.Add( Size,PatternSize : izSize_w) : int; //izzSprite;
var
  id : int;
begin
  id := Find();
  if id = -1 then
  begin
    id := Count;
    inc( Count );
    SetLength( Items, Count );
  end;
  Items[id].Size := Size;
  Items[id].PatternSize := PatternSize;
  Items[id].PatternXCount := Items[id].Size[0] div Items[id].PatternSize[0]-1;
  Items[id].PatternYCount := Items[id].Size[1] div Items[id].PatternSize[1]-1;

  Result := id; //@Items[id];
end;

procedure izSpriteManager.Clear();
begin
  Count := 0;
  SetLength( Items, Count ); 
end;

function izSpriteManager.Add_Anim(id : word; sID, eID, cID : word; delay : float) : word;
begin
  Result := Items[id].AnimationCount;
  inc(Items[id].AnimationCount);
  SetLength(Items[id].Animation, Items[id].AnimationCount);

  Items[id].Animation[Result].sID := sID;
  Items[id].Animation[Result].eID := eID;
  Items[id].Animation[Result].cID := cID;
  Items[id].Animation[Result].delay := delay;
  Items[id].Animation[Result].Time := 0.0;
end;

procedure izSpriteManager.Anim_Delete(id : word; AnimID : word );
begin
  Items[id].Animation[AnimID].delay := 0.0;
end;

procedure izSpriteManager.Anim_Clear(id : word);
begin
  Items[id].AnimationCount := 0;
  SetLength(Items[id].Animation, Items[id].AnimationCount);
end;

procedure izSpriteManager.Anim_Update(id : word; AnimID : word; Time : float);
begin
  Items[id].Animation[AnimID].Time := Items[id].Animation[AnimID].Time+Time;
  if Items[id].Animation[AnimID].Time >= Items[id].Animation[AnimID].delay then
  begin
    Items[id].Animation[AnimID].Time := Items[id].Animation[AnimID].Time-Items[id].Animation[AnimID].delay;
    inc( Items[id].Animation[AnimID].cID );
    if Items[id].Animation[AnimID].cID > Items[id].Animation[AnimID].eID then
      Items[id].Animation[AnimID].cID := Items[id].Animation[AnimID].sID;
  end;
end;

procedure izSpriteManager.Draw_Full(id : word; PatternNumber : word; pos : izPosition_f; Angle : float);
var
  PatternX, PatternY : word;
  PW,PH,W,H : float;
begin
  // Вычисляем координаты спрайта
  PatternY := Items[id].PatternYCount - PatternNumber div (Items[id].PatternXCount+1);
  PatternX := PatternNumber mod (Items[id].PatternXCount+1);
  PW := Items[id].PatternSize[0]/Items[id].Size[0];
  PH := Items[id].PatternSize[1]/Items[id].Size[1];
  W  := Items[id].PatternSize[0]/2;
  H  := Items[id].PatternSize[1]/2;


  // Рисуем спрайт
  glEnable(GL_TEXTURE_2D);
  glPushMatrix();
  glTranslatef( pos[0], pos[1], 0.0 );
  glRotatef( Angle, 0.0, 0.0, 1.0 );
  glBegin( GL_QUADS );
    glTexCoord2f( PW*PatternX, PH*(PatternY) );
    glVertex2f( -W, H );
    glTexCoord2f( PW*(PatternX+1), PH*(PatternY) );
    glVertex2f( W, H );
    glTexCoord2f( PW*(PatternX+1), PH*(PatternY+1) );
    glVertex2f( W, -H );
    glTexCoord2f( PW*(PatternX), PH*(PatternY+1) );
    glVertex2f( -W, -H );
  glEnd();
  glPopMatrix();
  glDisable(GL_TEXTURE_2D);
end;

procedure izSpriteManager.Draw_Scale(id : word; PatternNumber : word; pos : izPosition_f; size : izSize_w; Angle : float);
var
  PatternX, PatternY : word;
  PW,PH,W,H : float;
begin
  // Вычисляем координаты спрайта
  PatternY := Items[id].PatternYCount - PatternNumber div (Items[id].PatternXCount+1);
  PatternX := PatternNumber mod (Items[id].PatternXCount+1);
  PW := Items[id].PatternSize[0]/Items[id].Size[0];
  PH := Items[id].PatternSize[1]/Items[id].Size[1];
  W  := Size[0]/2;
  H  := Size[1]/2;

  // Рисуем спрайт
  glEnable(GL_TEXTURE_2D);
  glPushMatrix();
  glTranslatef( pos[0], pos[1], 0.0 );
  glRotatef( Angle, 0.0, 0.0, 1.0 );
  glBegin( GL_QUADS );
    glTexCoord2f( PW*PatternX, PH*(PatternY) );
    glVertex2f( -W, H );
    glTexCoord2f( PW*(PatternX+1), PH*(PatternY) );
    glVertex2f( W, H );
    glTexCoord2f( PW*(PatternX+1), PH*(PatternY+1) );
    glVertex2f( W, -H );
    glTexCoord2f( PW*(PatternX), PH*(PatternY+1) );
    glVertex2f( -W, -H );
  glEnd();
  glPopMatrix();
  glDisable(GL_TEXTURE_2D);
end;

procedure izSpriteManager.Draw_Fast(id : word; pos : izPosition_f; Angle : float);
begin
  Draw_Full(id,0,pos,0);
end;

procedure izSpriteManager.Draw_Alpha(id : uint; AnimID : word;  pos : izPosition_f; Angle : float);
begin
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  Draw_Full(id,AnimID,pos,Angle);
  glDisable(GL_BLEND);
end;

procedure izSpriteManager.Draw_Alpha(id : uint; bFunc,bFunc2 : Cardinal; AnimID : word;  pos : izPosition_f; Angle : float);
begin
  glEnable(GL_BLEND);
  glBlendFunc(bFunc, bFunc2);
  Draw_Full(id,AnimID,pos,Angle);
  glDisable(GL_BLEND);
end;

procedure izSpriteManager.Draw_Alpha_Color(id : uint; bFunc,bFunc2 : Cardinal; AnimID : word; pos : izPosition_f; Angle : float; Color : izColor3f);
begin
  glEnable(GL_BLEND);
  glBlendFunc(bFunc,bFunc2);
  glPushAttrib(GL_CURRENT_BIT);
  glColor3fv(@Color);
  Draw_Full(id,AnimID,pos,Angle);
  glPopAttrib();
  glDisable(GL_BLEND);
end;

procedure izSpriteManager.Draw_Alpha_Scale(id : uint; AnimID : word; pos : izPosition_f; size : izSize_w; Angle : float);
begin
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  Draw_Scale(id,AnimID,pos,size,Angle);
  glDisable(GL_BLEND);
end;

procedure izSpriteManager.Draw_Alpha_Scale(id : uint; bFunc,bFunc2 : Cardinal; AnimID : word; pos : izPosition_f; size : izSize_w; Angle : float);
begin
  glEnable(GL_BLEND);
  glBlendFunc(bFunc,bFunc2);
  Draw_Scale(id,AnimID,pos,size,Angle);
  glDisable(GL_BLEND);
end;

procedure izSpriteManager.Draw_Anim(id : word; AnimID : word; pos : izPosition_f; Angle : float);
var
  PatternNumber : word;
begin
  PatternNumber := Items[id].Animation[AnimID].cID;
  Draw_Full(id, PatternNumber, pos, Angle);
end;

procedure izSpriteManager.Draw_Anim_Scale(id : word; AnimID : word; pos : izPosition_f; size : izSize_w; Angle : float);
var
  PatternNumber : word;
begin
  PatternNumber := Items[id].Animation[AnimID].cID;
  Draw_Scale(id, PatternNumber, pos, size, Angle);
end;

procedure izSpriteManager.Draw_Anim_Scale_Alpha(id : word; AnimID : word; pos : izPosition_f; size : izSize_w; Angle : float);
var
  PatternNumber : word;
begin
  PatternNumber := Items[id].Animation[AnimID].cID;
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  Draw_Scale(id, PatternNumber, pos, size, Angle);
  glDisable(GL_BLEND);
end;

procedure izSpriteManager.Anim(id : word; AnimID : word; pos : izPosition_f; Angle : float; Time : float);
begin
  Anim_Update(id, AnimID, Time);
  Draw_Anim(id, AnimID, pos, Angle);
end;

procedure izSpriteManager.Draw_Anim_Alpha(id : word; bFunc,bFunc2 : Cardinal; AnimID : word; pos : izPosition_f; Angle : float);
begin
  glEnable(GL_BLEND);
  glBlendFunc(bFunc,bFunc2);
  Draw_Anim(id,AnimID,pos,Angle);
  glDisable(GL_BLEND);
end;

procedure izSpriteManager.Draw_Anim_Alpha(id : word; AnimID : word; pos : izPosition_f; Angle : float);
begin
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
  Draw_Anim(id,AnimID,pos,Angle);
  glDisable(GL_BLEND);
end;

procedure izSpriteManager.Draw_Anim_Alpha_Color(id : word; bFunc,bFunc2 : Cardinal; AnimID : word; pos : izPosition_f; Angle : float; Color : izColor3f);
begin
  glPushAttrib(GL_CURRENT_BIT);
  glEnable(GL_BLEND);
  glBlendFunc(bFunc,bFunc2);
  glColor3fv(@Color);
  Draw_Anim(id,AnimID,pos,Angle);
  glDisable(GL_BLEND);
  glPopAttrib(); 
end;

end.
