unit uPOAObjects;

interface

uses
  uGlobal, uPOA, VectorTypes, VectorGeometry;

var
  POAS: array of TPOAObject;

  function POAAdd(Params: array of variant): variant; stdcall;
  function POAObjectAdd(Params: array of variant): variant; stdcall;
  function POAObjectID(Params: array of variant): variant; stdcall;
  function POAAnimate(Params: array of variant): variant; stdcall;
  function POAReset(Params: array of variant): variant; stdcall;
  function POATime(Params: array of variant): variant; stdcall;
  function POAFrameTime(Params: array of variant): variant; stdcall;
  function POAFrames(Params: array of variant): variant; stdcall;
  function POATransformAdd(Params: array of variant): variant; stdcall;
  function POAFrameAdd(Params: array of variant): variant; stdcall;

  function POAID(Params: array of variant): variant; stdcall;

  function POAPosition(Params: array of variant): variant; stdcall;
  function POAScale(Params: array of variant): variant; stdcall;
  function POARotation(Params: array of variant): variant; stdcall;
  function POAVisible(Params: array of variant): variant; stdcall;

  function POASave(Params: array of variant): variant; stdcall;
  function POALoad(Params: array of variant): variant; stdcall;

  function POAFrameStart(Params: array of variant): variant; stdcall;
  function POAFrameEnd(Params: array of variant): variant; stdcall;

implementation

function POAAdd(Params: array of variant): variant; stdcall;
begin
  SetLength(POAS, length(POAS)+1);
  POAS[length(POAS)-1]:=TPOAObject.Create;
  Result:=length(POAS)-1;
end;

function POAID(Params: array of variant): variant; stdcall;
begin
  Result:=POAS[integer(Params[0])].Root;
end;

function POAObjectAdd(Params: array of variant): variant; stdcall;
var
  Pos, Rot, Scl: TVector4f;
  V: TDoubleArray;
  X: integer;
begin
  V:=Params[2]; Pos:=VectorMake(v[0],v[1],v[2]);
  V:=Params[3]; Rot:=VectorMake(v[0],v[1],v[2]);
  V:=Params[4]; Scl:=VectorMake(v[0],v[1],v[2]);
  Result:=POAS[integer(Params[0])].AddObject(Params[1]);
  POAS[integer(Params[0])].Objects[integer(Result)].Position:=Pos;
  POAS[integer(Params[0])].Objects[integer(Result)].Rotation:=Rot;
  POAS[integer(Params[0])].Objects[integer(Result)].Scale:=Scl;
  SetLength(POAS[integer(Params[0])].Objects[integer(Result)].Params, 0);
  if length(Params)>5 then
  for x := 5 to length(Params) - 1 do
  begin
    SetLength(POAS[integer(Params[0])].Objects[integer(Result)].Params, length(POAS[integer(Params[0])].Objects[integer(Result)].Params)+1);
    POAS[integer(Params[0])].Objects[integer(Result)].Params[Length(POAS[integer(Params[0])].Objects[integer(Result)].Params)-1]:=Params[x];
  end;
end;

function POAObjectID(Params: array of variant): variant; stdcall;
begin
  Result:=POAS[integer(Params[0])].Objects[integer(Params[1])].ID;
end;

function POAAnimate(Params: array of variant): variant; stdcall;
begin
  POAS[integer(Params[0])].Animate(Params[1]);
end;

function POAReset(Params: array of variant): variant; stdcall;
begin
  POAS[integer(Params[0])].Reset;
end;

function POATime(Params: array of variant): variant; stdcall;
begin
  if length(Params)>1 then POAS[integer(Params[0])].Time:=Params[1];
  Result:=POAS[integer(Params[0])].Time;
end;

function POAFrameStart(Params: array of variant): variant; stdcall;
begin
  if length(Params)>1 then POAS[integer(Params[0])].StartFrame:=Params[1];
  Result:=POAS[integer(Params[0])].StartFrame;
end;

function POAFrameEnd(Params: array of variant): variant; stdcall;
begin
  if length(Params)>1 then POAS[integer(Params[0])].EndFrame:=Params[1];
  Result:=POAS[integer(Params[0])].EndFrame;
end;

function POAFrameTime(Params: array of variant): variant; stdcall;
begin
  if length(Params)>2 then
    if Params[2]>0 then
      POAS[integer(Params[0])].FrameTimes[integer(Params[1])]:=Params[2]
    else
      POAS[integer(Params[0])].FrameTimes[integer(Params[1])]:=1;
  Result:=POAS[integer(Params[0])].FrameTimes[integer(Params[1])];
end;

function POAFrames(Params: array of variant): variant; stdcall;
begin
  if length(Params)>1 then POAS[integer(Params[0])].SetFramesCount(Params[1]);
  Result:=length(POAS[integer(Params[0])].Frames);
end;

function POATransformAdd(Params: array of variant): variant; stdcall;
var
  Pos, Rot, Scl: TVector4f;
  V: TDoubleArray;
begin
  V:=Params[3]; Pos:=VectorMake(v[0],v[1],v[2]);
  V:=Params[4]; Rot:=VectorMake(v[0],v[1],v[2],0);
  V:=Params[5]; Scl:=VectorMake(v[0],v[1],v[2],0);
  Result:=POAS[integer(Params[0])].AddTransform(Params[1],Params[2],Pos, Rot, Scl);
end;

function POAFrameAdd(Params: array of variant): variant; stdcall;
var
  Pos, Rot, Scl: TVector4f;
  V: TDoubleArray;
  A: Array of Variant;
  x: integer;
  T: array of TGLTransform;
begin
  SetLength(T, length(Params)-1);
  for x := 1 to length(Params) - 1 do
  begin
    A:=Params[x];
    V:=A[1]; Pos:=VectorMake(v[0],v[1],v[2]);
    V:=A[2]; Rot:=VectorMake(v[0],v[1],v[2]);
    V:=A[3]; Scl:=VectorMake(v[0],v[1],v[2]);
    t[x-1].ObjID:=A[0];
    t[x-1].Position:=Pos;
    t[x-1].Rotation:=Rot;
    t[x-1].Scale:=Scl;
  end;
  Result:=POAS[integer(Params[0])].AddFrame(T);
end;

function POAVisible(Params: array of variant): variant; stdcall;
var
  I: integer;
begin
  for I := 0 to length(POAS[integer(params[0])].Objects) - 1 do
    call('glObjectVisible', [POAS[integer(params[0])].Objects[i].ID, params[1]]);
end;

function POAPosition(Params: array of variant): variant; stdcall;
begin
  POAS[integer(params[0])].Position[0]:=params[1];
  POAS[integer(params[0])].Position[1]:=params[2];
  POAS[integer(params[0])].Position[2]:=params[3];
  call('glPosition', [POAS[integer(params[0])].Root, POAS[integer(params[0])].Position[0], POAS[integer(params[0])].Position[1], POAS[integer(params[0])].Position[2]]);
end;

function POAScale(Params: array of variant): variant; stdcall;
begin
  POAS[integer(params[0])].Scale[0]:=params[1];
  POAS[integer(params[0])].Scale[1]:=params[2];
  POAS[integer(params[0])].Scale[2]:=params[3];
  call('glScale', [POAS[integer(params[0])].Root, POAS[integer(params[0])].Scale[0], POAS[integer(params[0])].Scale[1], POAS[integer(params[0])].Scale[2]]);
end;

function POARotation(Params: array of variant): variant; stdcall;
begin
  POAS[integer(params[0])].Rotation[0]:=params[1];
  POAS[integer(params[0])].Rotation[1]:=params[2];
  POAS[integer(params[0])].Rotation[2]:=params[3];
  call('glRotation', [POAS[integer(params[0])].Root, POAS[integer(params[0])].Rotation[0], POAS[integer(params[0])].Rotation[1], POAS[integer(params[0])].Rotation[2]]);
end;


//==============================================================================

function POASave(Params: array of variant): variant; stdcall;
var
  F: File of Double;
  P: TPOAObject;

  I, II: integer;
  D, OP: Double;
begin
  P:=POAS[integer(params[0])];

  AssignFile(F, Params[1]);
  Rewrite(f);

  Write(F, P.Position[0]); Write(F, P.Position[1]); Write(F, P.Position[2]);
  Write(F, P.Rotation[0]); Write(F, P.Rotation[1]); Write(F, P.Rotation[2]);
  Write(F, P.Scale[0]); Write(F, P.Scale[1]); Write(F, P.Scale[2]); 

  D:=length(P.Objects);  Write(F, D);
  for I := 0 to length(P.Objects) - 1 do
  begin
    D:=integer(P.Objects[i].ObjType);  Write(F, D);
    Write(F, P.Objects[i].Position[0]); Write(F, P.Objects[i].Position[1]); Write(F, P.Objects[i].Position[2]);
    Write(F, P.Objects[i].Rotation[0]); Write(F, P.Objects[i].Rotation[1]); Write(F, P.Objects[i].Rotation[2]);
    Write(F, P.Objects[i].Scale[0]); Write(F, P.Objects[i].Scale[1]); Write(F, P.Objects[i].Scale[2]);

    D:=length(P.Objects[i].Params);  Write(F, D);
    for II := 0 to length(P.Objects[i].Params) - 1 do
    begin
      D:=P.Objects[i].Params[II];  Write(F, D);
    end;

    D:=call('glObjectParent',[P.Objects[i].ID]);
    OP:=-1;
    if D<>P.Root then
    for II := 0 to length(P.Objects) - 1 do
      if D=P.Objects[II].ID then
      begin
        OP:=II;
        Break;
      end;
    Write(F, OP);
  end;

  D:=length(P.Frames);  Write(F, D);
  for I := 0 to length(P.Frames) - 1 do
  begin
    Write(F, P.FrameTimes[I]);
    D:=length(P.Frames[i]);  Write(F, D);
    for II := 0 to length(P.Frames[i]) - 1 do
    begin
      D:=P.Frames[I, II].ObjID;  Write(F, D);
      Write(F, P.Frames[I, II].Position[0]); Write(F, P.Frames[I, II].Position[1]); Write(F, P.Frames[I, II].Position[2]);
      Write(F, P.Frames[I, II].Rotation[0]); Write(F, P.Frames[I, II].Rotation[1]); Write(F, P.Frames[I, II].Rotation[2]);
      Write(F, P.Frames[I, II].Scale[0]); Write(F, P.Frames[I, II].Scale[1]); Write(F, P.Frames[I, II].Scale[2]);
    end;
  end;

  CloseFile(f);
end;

function POALoad(Params: array of variant): variant; stdcall;
var
  F: File of Single;
  P: TPOAObject;

  I, II: integer;
  D: Single;
begin
  P:=POAS[integer(params[0])];

  AssignFile(F, Params[1]);
  Reset(f);

  Read(F, P.Position[0]); Read(F, P.Position[1]); Read(F, P.Position[2]);
  Read(F, P.Rotation[0]); Read(F, P.Rotation[1]); Read(F, P.Rotation[2]);
  Read(F, P.Scale[0]); Read(F, P.Scale[1]); Read(F, P.Scale[2]);

  Read(F, D);  I:=round(D);
  for I := 0 to I - 1 do
  begin
    Read(F, D); P.AddObject(TGLObjectType(round(D)));
    Read(F, P.Objects[i].Position[0]); Read(F, P.Objects[i].Position[1]); Read(F, P.Objects[i].Position[2]);
    Read(F, P.Objects[i].Rotation[0]); Read(F, P.Objects[i].Rotation[1]); Read(F, P.Objects[i].Rotation[2]);
    Read(F, P.Objects[i].Scale[0]); Read(F, P.Objects[i].Scale[1]); Read(F, P.Objects[i].Scale[2]);

    Read(F, D); SetLength(P.Objects[i].Params, round(D));
    for II := 0 to length(P.Objects[i].Params) - 1 do
    begin
      Read(F, D); P.Objects[i].Params[II]:=D;  
    end;

    Read(F, D);
    if D<>-1 then call('glObjectParent', [P.Objects[i].ID, round(D)]);
  end;

  Read(F, D);  SetLength(P.Frames, round(D)); SetLength(P.FrameTimes, round(D));
  for I := 0 to length(P.Frames) - 1 do
  begin
    Read(F, P.FrameTimes[I]);
    Read(F, D);  SetLength(P.Frames[I], round(D));
    for II := 0 to length(P.Frames[i]) - 1 do
    begin
      Read(F, D); P.Frames[I, II].ObjID:=round(D);
      Read(F, P.Frames[I, II].Position[0]); Read(F, P.Frames[I, II].Position[1]); Read(F, P.Frames[I, II].Position[2]);
      Read(F, P.Frames[I, II].Rotation[0]); Read(F, P.Frames[I, II].Rotation[1]); Read(F, P.Frames[I, II].Rotation[2]);
      Read(F, P.Frames[I, II].Scale[0]); Read(F, P.Frames[I, II].Scale[1]); Read(F, P.Frames[I, II].Scale[2]);
    end;
  end;

  CloseFile(f);

  P.Reset;
end;

end.
