unit SolidParticle;

interface       

uses
  _Geometry,   
  Frost.Forms, 
  Frost.Renderers,
  Frost.Engine,
  Frost.GL,
  Frost.Utils,
  OpenGL;

const
  MAX_PARTS = 500;

type
TParticle = class(TComponent)
  const MAX_LIFE_TIME = 0.5;
  protected 
    class var FMesh: TMesh;   
    class var FMaterial: TMaterial;
  protected
    FActive: Boolean;
    FLife,
    FMaxLife: Single;
    FScale: Single;          
    FVelocity: TVector3;
    FRenderer: TMeshRenderer;
  public
    class procedure Init();
    class procedure Emit(Position: TVector3; Velocity: TVector3; Life: Single; Scale: Single = 0.5);
    procedure Hide;
    procedure OnStart(); override;
    procedure OnUpdate(const Delta: Double); override;
    procedure OnDestroy(); override;
    property Active: Boolean read FActive write FActive;
  end;

var
  Parts: array [0..MAX_PARTS] of TParticle;

implementation

uses
  WorldScene;

{$REGION 'SolidParticle'}
class procedure TParticle.Init;
var
  i: Word;
begin
  for i := 0 to MAX_PARTS do
    Parts[i] :=  TParticle.Create(TGameObject.Create(nil));
end;

class procedure TParticle.Emit(Position: TVector3; Velocity: TVector3; Life: Single; Scale: Single = 0.5);
var          
  i: Word;
begin
  for i := 0 to MAX_PARTS do
    if (not Parts[i].FActive) then
    begin
      Parts[i].FActive := True;
      Parts[i].FRenderer.Enable := True;
      Parts[i].GameObject.LocalPosition := Position;
      Parts[i].FLife := Life;
      Parts[i].FMaxLife := Life;
      Parts[i].GameObject.LocalScale := VECTOR3_ZERO;
      Parts[i].FScale := Scale;
      Parts[i].FVelocity := Velocity;
      break;
    end;
end;

procedure TParticle.Hide;
begin
  FLife := 0.01;
  FRenderer.Enable := false;
end;

procedure TParticle.OnStart;
begin
  if FMesh = nil then
  begin
    FMesh := TMesh.CreateSphere(1, 3);
    FMaterial := TColorMaterial.Create(Vector3(0.1,0.1,0.1));
  end;
  FActive := false;
  GameObject.LocalPosition := Vector3(0, 0, -100);
  FRenderer := TMeshRenderer.CreateMeshRenderer(FMesh, FMaterial);
  GameObject.AddComponent(FRenderer);
end;

procedure TParticle.OnUpdate(const Delta: Double);
var
  Scale: Single;
begin
  if (FActive) then
  begin
    GameObject.LocalPosition := GameObject.LocalPosition + FVelocity * Delta;
    if (FLife > FMaxLife * 0.5) then
      Scale := 1 - ((-FLife + FMaxLife) / FMaxLife) * 2
    else
      Scale := 1 - ((FLife) / FMaxLife) * 2;
    GameObject.LocalScale := VECTOR3_ONE * FScale * (1 - Scale * Scale);
    if (FLife > 0) then
      FLife := FLife - Delta;
    if (FLife <= 0) then
    begin
      FActive := false;
      FRenderer.Enable := false;
    end;
  end;
end;

procedure TParticle.OnDestroy;
begin

end;
{$ENDREGION}


end.
