Sordie.co.uk

libsassy/libSassy.SceneGraph.pas

Raw

{(
 )) libSassy.SceneGraph
((    SceneGraph type nested object library
 ))
((  Copyright  Sordie Aranka Solomon-Smith 2015-2016
 ))
((  This work is made available under the terms of the Creative Commons
 )) Attribution-NonCommercial-ShareAlike 3.0 Unported license
((  http://creativecommons.org/licenses/by-nc-sa/3.0/
 )}

unit libSassy.SceneGraph;

interface

uses
  libSassy.Interfaces,
  libSassy.Arrays;

type
  TSceneMethodRef = reference to function(const Delta: Extended): Boolean;

{$REGION 'TSceneNode'}
  TSceneNode = class abstract(TInterface)
  private
    fEnabled: Boolean;
  public
    procedure PushState; virtual;
    procedure PopState;  virtual;

    function Process(const Delta: Extended): Boolean; virtual;

    function Render(const Delta: Extended): Boolean; virtual;

    property Enabled: Boolean read fEnabled write fEnabled;
  end;
{$ENDREGION}

{$REGION 'TSceneGraph'}
  TSceneGraph = class(TSceneNode)
  private
    fNodes: TArray<TSceneNode>;
  public
    constructor Create;
    destructor  Destroy; override;

    function Process(const Delta: Extended): Boolean; override;

    procedure Add(const Node: TSceneNode); inline;

    procedure Clear; inline;

    property Nodes: TArray<TSceneNode> read fNodes;
  end;
{$ENDREGION}

{$REGION 'TSceneMethod'}
  TSceneMethod = class(TSceneNode)
  private
    fMethod: TSceneMethodRef;
  public
    function Render(const Delta: Extended): Boolean; override;

    property Method: TSceneMethodRef read fMethod write fMethod;
  end;
{$ENDREGION}

implementation

{$REGION 'TSceneNode'}
procedure TSceneNode.PushState;
begin
  {}
end;

procedure TSceneNode.PopState;
begin
  {}
end;

function TSceneNode.Process;
begin
  if not fEnabled then exit(True);

  PushState;

  Result := Render(Delta);

  PopState;
end;

function TSceneNode.Render;
begin
  Result := True;
end;
{$ENDREGION}

{$REGION 'TSceneGraph'}
constructor TSceneGraph.Create;
begin
  inherited;

  fNodes   := TArray<TSceneNode>.Create;
  fEnabled := True;
end;

destructor TSceneGraph.Destroy;
begin
  fNodes.Free;

  inherited;
end;

function TSceneGraph.Process;
var
  Node: TSceneNode;
begin
  if not fEnabled then exit(True);

  PushState;

  if Render(Delta) then
  begin
    Result := True;

    for Node in fNodes do
      if not Node.Process(Delta) then
      begin
        Result := False;
        break;
      end;
  end
  else Result := False;

  PopState;
end;

procedure TSceneGraph.Add;
begin
  fNodes.Add(Node);
end;

procedure TSceneGraph.Clear;
begin
  fNodes.Clear;
end;
{$ENDREGION}

{$REGION 'TSceneMethod'}
function TSceneMethod.Render;
begin
  if Assigned(fMethod) then
    Result := fMethod(Delta)
  else
    Result := True;
end;
{$ENDREGION}

end.