//DJXLights v1.1
unit DJXLights;

interface

uses
  Classes,
  SysUtils,
  Windows,
  DJXClasses,
  Direct3D9,
  D3DX9;

type
  TDJXLight = class;
  TDJXLightList = class;

  TDJXLight = class
  private
    m_DanJetX: Pointer;
    m_D3DLight: TD3DLight9;
    m_Enabled: boolean;
    m_Index: integer;
  protected
    procedure SetEnabled(Value: boolean);
  public
    constructor Create; 
    destructor Destroy; override;
    procedure Reset;
    property DanJetX: Pointer read m_DanJetX write m_DanJetX;
    property D3DLight: TD3DLight9 read m_D3DLight write m_D3DLight;
    property Enabled: boolean read m_Enabled write SetEnabled;
    property LightType: TD3DLightType read m_D3DLight._Type write m_D3DLight._Type;
    property DiffuseR: single read m_D3DLight.Diffuse.r write m_D3DLight.Diffuse.r;
    property DiffuseG: single read m_D3DLight.Diffuse.g write m_D3DLight.Diffuse.g;
    property DiffuseB: single read m_D3DLight.Diffuse.b write m_D3DLight.Diffuse.b;
    property SpecularR: single read m_D3DLight.Specular.r write m_D3DLight.Specular.r;
    property SpecularG: single read m_D3DLight.Specular.g write m_D3DLight.Specular.g;
    property SpecularB: single read m_D3DLight.Specular.b write m_D3DLight.Specular.b;
    property AmbientR: single read m_D3DLight.Ambient.r write m_D3DLight.Ambient.r;
    property AmbientG: single read m_D3DLight.Ambient.g write m_D3DLight.Ambient.g;
    property AmbientB: single read m_D3DLight.Ambient.b write m_D3DLight.Ambient.b;
    property PosX: single read m_D3DLight.Position.x write m_D3DLight.Position.x;
    property PosY: single read m_D3DLight.Position.y write m_D3DLight.Position.y;
    property PosZ: single read m_D3DLight.Position.z write m_D3DLight.Position.z;
    property DirX: single read m_D3DLight.Direction.x write m_D3DLight.Direction.x;
    property DirY: single read m_D3DLight.Direction.y write m_D3DLight.Direction.y;
    property DirZ: single read m_D3DLight.Direction.z write m_D3DLight.Direction.z;
    property Range: Single read m_D3DLight.Range write m_D3DLight.Range;
    property Falloff: Single read m_D3DLight.Falloff write m_D3DLight.Falloff;
    property AttenuationConstant: Single read m_D3DLight.Attenuation0 write m_D3DLight.Attenuation0;
    property AttenuationLinear: Single read m_D3DLight.Attenuation1 write m_D3DLight.Attenuation1;
    property AttenuationQuadratic: Single read m_D3DLight.Attenuation2 write m_D3DLight.Attenuation2;
    property SpotInner: Single read m_D3DLight.Theta write m_D3DLight.Theta;
    property SpotOutter: Single read m_D3DLight.Phi write m_D3DLight.Phi;
  end;

  TDJXLightList = class(TDJXComponent)
  protected
    m_Lights: array of TDJXLight;
    function getItem(Index: integer): TDJXLight;
    procedure setItem(Index: integer; Value: TDJXLight);
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    property DanJetX: Pointer read m_DanJetX write m_DanJetX;
    procedure Clear;
    function SetPointLight(
      posX, posY, posZ: double;
      DiffuseR, DiffuseG, DiffuseB: single
    ): TDJXLight; overload;
    function SetPointLight(
      posX, posY, posZ: double;
      DiffuseR, DiffuseG, DiffuseB: single;
      AmbientR, AmbientG, AmbientB: single;
      SpecularR, SpecularG, SpecularB: single;
      Range: single = 1000;
      falloff: single = 1;
      AttenuationConstant: single = 0.5
    ): TDJXLight; overload;
    function SetSpotLight(
      posX, posY, posZ: double;
      dirX, dirY, dirZ: double;
      DiffuseR, DiffuseG, DiffuseB: single
    ): TDJXLight; overload;
    function SetSpotLight(
      posX, posY, posZ: double;
      dirX, dirY, dirZ: double;
      DiffuseR, DiffuseG, DiffuseB: single;
      AmbientR, AmbientG, AmbientB: single;
      SpecularR, SpecularG, SpecularB: single;
      Range: single = 1000;
      falloff: single = 1;
      AttenuationConstant: single = 0.5;
      SpotInner: single = 0.5;
      SpotOutter: single = 1
    ): TDJXLight; overload;
    function SetDirLight(
      dirX, dirY, dirZ: double;
      DiffuseR, DiffuseG, DiffuseB: single
    ): TDJXLight; overload;
    function SetDirLight(
      dirX, dirY, dirZ: double;
      DiffuseR, DiffuseG, DiffuseB: single;
      AmbientR, AmbientG, AmbientB: single;
      SpecularR, SpecularG, SpecularB: single
    ): TDJXLight; overload;
    property Lights[Index: integer]:TDJXLight read getItem write setItem;
    function Add(Light: TDJXLight): integer;
    procedure Init(DanJetX: Pointer); override;
    procedure OnLostDevice; override;
    procedure OnResetDevice; override;
  published
  end;

implementation

uses
  DJX;

//DJXLightList BEGIN
constructor TDJXLightList.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);
end;
destructor TDJXLightList.Destroy;
var
  i: integer;
begin
  for i := 0 to high(m_Lights) do
  lights[i].Free;
  setLength(m_Lights, 0);
  inherited Destroy;
end;
procedure TDJXLightList.Init(DanJetX: Pointer);
begin
  inherited Init(DanJetX);
end;
procedure TDJXLightList.OnLostDevice;
begin

end;
procedure TDJXLightList.OnResetDevice;
var
  i: integer;
begin
  for i := 0 to high(m_Lights) do
  if m_Lights[i] <> nil then
  TDJXLight(m_Lights[i]).Reset;
end;
function TDJXLightList.SetPointLight(
      posX, posY, posZ: double;
      DiffuseR, DiffuseG, DiffuseB: single
    ): TDJXLight;
var
  light: TDJXLight;
begin
  light := TDJXLight.Create;
  ZeroMemory(@light.m_D3DLight, SizeOf(TD3DLight9));
  light.m_D3DLight._Type := D3DLIGHT_POINT;
  light.m_D3DLight.Diffuse.r := DiffuseR;
  light.m_D3DLight.Diffuse.g := DiffuseG;
  light.m_D3DLight.Diffuse.b := DiffuseB;
  light.m_D3DLight.Diffuse.a := 1;
  light.m_D3DLight.Specular.a := 1;
  light.m_D3DLight.Position := D3DXVector3(posX, posY, posZ);
  light.m_D3DLight.Range := 1000.0;
  light.m_D3DLight.Attenuation0 := 0.5;
  light.m_DanJetX := m_DanJetX;
  light.m_Enabled := false;
  light.m_Index := Add(light);
  TDanJetX(m_DanJetX).Device.SetLight(light.m_Index, light.m_D3DLight);
  TDanJetX(m_DanJetX).Device.LightEnable(light.m_Index, false);
  Result := light;
end;
function TDJXLightList.SetPointLight(
      posX, posY, posZ: double;
      DiffuseR, DiffuseG, DiffuseB: single;
      AmbientR, AmbientG, AmbientB: single;
      SpecularR, SpecularG, SpecularB: single;
      Range: single = 1000;
      falloff: single = 1;
      AttenuationConstant: single = 0.5
    ): TDJXLight;
var
  light: TDJXLight;
begin
  light := TDJXLight.Create;
  ZeroMemory(@light.m_D3DLight, SizeOf(TD3DLight9));
  light.m_D3DLight._Type := D3DLIGHT_POINT;
  light.m_D3DLight.Diffuse.r := DiffuseR;
  light.m_D3DLight.Diffuse.g := DiffuseG;
  light.m_D3DLight.Diffuse.b := DiffuseB;
  light.m_D3DLight.Diffuse.a := 1;
  light.m_D3DLight.Ambient.r := AmbientR;
  light.m_D3DLight.Ambient.g := AmbientG;
  light.m_D3DLight.Ambient.b := AmbientB;
  light.m_D3DLight.Specular.r := SpecularR;
  light.m_D3DLight.Specular.g := SpecularG;
  light.m_D3DLight.Specular.b := SpecularB;
  light.m_D3DLight.Specular.a := 1;
  light.m_D3DLight.Position := D3DXVector3(posX,posY,posZ);
  light.m_D3DLight.Range := Range;
  light.m_D3DLight.Attenuation0 := AttenuationConstant;
  light.m_DanJetX := m_DanJetX;
  light.m_Enabled := false;
  light.m_Index := add(light);
  TDanJetX(m_DanJetX).Device.SetLight(light.m_Index, light.m_D3DLight);
  TDanJetX(m_DanJetX).Device.LightEnable(light.m_Index, false);
  Result := light;
end;
function TDJXLightList.SetSpotLight(
      posX, posY, posZ: double;
      dirX, dirY, dirZ: double;
      DiffuseR, DiffuseG, DiffuseB: single
    ): TDJXLight;
var
  light: TDJXLight;
begin
  light := TDJXLight.Create;
  ZeroMemory(@light.m_D3DLight, SizeOf(TD3DLight9));
  light.m_D3DLight._Type := D3DLIGHT_SPOT;
  light.m_D3DLight.Diffuse.r := DiffuseR;
  light.m_D3DLight.Diffuse.g := DiffuseG;
  light.m_D3DLight.Diffuse.b := DiffuseB;
  light.m_D3DLight.Diffuse.a := 1;
  light.m_D3DLight.Specular.a := 1;
  light.m_D3DLight.Position := D3DXVector3(posX, posY, posZ);
  light.m_D3DLight.Direction := D3DXVector3(dirX, dirY, dirZ);
  light.m_D3DLight.Theta := 0.5;
  light.m_D3DLight.Phi := 1;
  light.m_D3DLight.Falloff := 1.0;
  light.m_D3DLight.Range := 1000.0;
  light.m_D3DLight.Attenuation0 := 0.5;
  light.m_DanJetX := m_DanJetX;
  light.m_Enabled := false;
  light.m_Index := Add(light);
  TDanJetX(m_DanJetX).Device.SetLight(light.m_Index, light.m_D3DLight);
  TDanJetX(m_DanJetX).Device.LightEnable(light.m_Index, false);
  Result := light;
end;
function TDJXLightList.SetSpotLight(
      posX, posY, posZ: double;
      dirX, dirY, dirZ: double;
      DiffuseR, DiffuseG, DiffuseB: single;
      AmbientR, AmbientG, AmbientB: single;
      SpecularR, SpecularG, SpecularB: single;
      Range: single = 1000;
      falloff: single = 1;
      AttenuationConstant: single = 0.5;
      SpotInner: single = 0.5;
      SpotOutter: single = 1
    ): TDJXLight;
var
  light: TDJXLight;
begin
  light := TDJXLight.Create;
  ZeroMemory(@light.m_D3DLight, SizeOf(TD3DLight9));
  light.m_D3DLight._Type := D3DLIGHT_SPOT;
  light.m_D3DLight.Diffuse.r := DiffuseR;
  light.m_D3DLight.Diffuse.g := DiffuseG;
  light.m_D3DLight.Diffuse.b := DiffuseB;
  light.m_D3DLight.Diffuse.a := 1;
  light.m_D3DLight.Ambient.r := AmbientR;
  light.m_D3DLight.Ambient.g := AmbientG;
  light.m_D3DLight.Ambient.b := AmbientB;
  light.m_D3DLight.Specular.r := SpecularR;
  light.m_D3DLight.Specular.g := SpecularG;
  light.m_D3DLight.Specular.b := SpecularB;
  light.m_D3DLight.Specular.a := 1;
  light.m_D3DLight.Position := D3DXVector3(posX, posY, posZ);
  light.m_D3DLight.Direction := D3DXVector3(dirX, dirY, dirZ);
  light.m_D3DLight.Theta := SpotInner;
  light.m_D3DLight.Phi := SpotOutter;
  light.m_D3DLight.Falloff := Falloff;
  light.m_D3DLight.Range := Range;
  light.m_D3DLight.Attenuation0 := AttenuationConstant;
  light.m_DanJetX := m_DanJetX;
  light.m_Enabled := false;
  light.m_Index := Add(light);
  TDanJetX(m_DanJetX).Device.SetLight(light.m_Index, light.m_D3DLight);
  TDanJetX(m_DanJetX).Device.LightEnable(light.m_Index,false);
  Result := light;
end;
function TDJXLightList.SetDirLight(
      dirX, dirY, dirZ: double;
      DiffuseR, DiffuseG, DiffuseB: single
    ): TDJXLight;
var
  light: TDJXLight;
begin
  light := TDJXLight.Create;
  ZeroMemory(@light.m_D3DLight, SizeOf(TD3DLight9));
  light.m_D3DLight._Type := D3DLIGHT_DIRECTIONAL;
  light.m_D3DLight.Diffuse.r := DiffuseR;
  light.m_D3DLight.Diffuse.g := DiffuseG;
  light.m_D3DLight.Diffuse.b := DiffuseB;
  light.m_D3DLight.Diffuse.a := 1;
  light.m_D3DLight.Specular.a := 1;
  light.m_D3DLight.Direction := D3DXVector3(DirX, DirY, DirZ);
  light.m_DanJetX := m_DanJetX;
  light.m_Enabled := false;
  light.m_Index := Add(light);
  TDanJetX(m_DanJetX).Device.SetLight(light.m_Index, light.m_D3DLight);
  TDanJetX(m_DanJetX).Device.LightEnable(light.m_Index,false);
  Result := light;
end;
function TDJXLightList.SetDirLight(
      dirX, dirY, dirZ: double;
      DiffuseR, DiffuseG, DiffuseB: single;
      AmbientR, AmbientG, AmbientB: single;
      SpecularR, SpecularG, SpecularB: single
    ): TDJXLight;
var
  light: TDJXLight;
begin
  light := TDJXLight.Create;
  ZeroMemory(@light.m_D3DLight, SizeOf(TD3DLight9));
  light.m_D3DLight._Type := D3DLIGHT_DIRECTIONAL;
  light.m_D3DLight.Diffuse.r := DiffuseR;
  light.m_D3DLight.Diffuse.g := DiffuseG;
  light.m_D3DLight.Diffuse.b := DiffuseB;
  light.m_D3DLight.Diffuse.a := 1;
  light.m_D3DLight.Ambient.r := AmbientR;
  light.m_D3DLight.Ambient.g := AmbientG;
  light.m_D3DLight.Ambient.b := AmbientB;
  light.m_D3DLight.Specular.r := SpecularR;
  light.m_D3DLight.Specular.g := SpecularG;
  light.m_D3DLight.Specular.b := SpecularB;
  light.m_D3DLight.Specular.a := 1;
  light.m_D3DLight.Direction := D3DXVector3(DirX,DirY,DirZ);
  light.m_DanJetX := m_DanJetX;
  light.m_Enabled := false;
  light.m_Index := Add(light);
  TDanJetX(m_DanJetX).Device.SetLight(light.m_Index, light.m_D3DLight);
  TDanJetX(m_DanJetX).Device.LightEnable(light.m_Index,false);
  Result := light;
end;
function TDJXLightList.Add(Light: TDJXLight): integer;
var
  i: integer;
begin
  i := 0;
  while (i < length(m_Lights)) and (m_Lights[i] <> nil) do
  inc(i);
  if i >= length(m_Lights) then
  setLength(m_Lights, length(m_Lights) + 1);
  m_Lights[i] := Light;
  Result := i;
end;
function TDJXLightList.getItem(Index: integer): TDJXLight;
begin
  result := m_Lights[Index];
end;
procedure TDJXLightList.setItem(Index: integer; Value: TDJXLight);
begin
  m_Lights[Index] := Value;
  m_Lights[Index].m_Index := Index;
end;
procedure TDJXLightList.Clear;
var
  i: integer;
begin
  for i := 0 to length(m_Lights) - 1 do
  begin
    m_Lights[i].Enabled := false;
    FreeAndNil(m_Lights[i]);
  end;
  setLength(m_Lights, 0);
end;
//TDJXLightList END

//TDJXLight BEGIN
constructor TDJXLight.Create;
begin
  inherited Create;
end;
destructor TDJXLight.Destroy;
begin
  Enabled := false;
  inherited destroy;
end;
procedure TDJXLight.SetEnabled(Value: boolean);
begin
  m_Enabled := Value;
  if TDanJetX(m_DanJetX).Device <> nil then
  TDanJetX(m_DanJetX).Device.LightEnable(m_Index, m_Enabled);
end;
procedure TDJXLight.Reset;
begin
  TDanJetX(m_DanJetX).Device.SetLight(m_Index, m_D3DLight);
  TDanJetX(m_DanJetX).Device.LightEnable(m_Index, m_Enabled);
end;
//TDJXLight END

end.
