unit Unit1;

{$mode objfpc}{$H+}
{$define TRY_DOWNLOAD}
interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs,
  LCLIntf, LCLType, ExtCtrls, Menus, ComCtrls,
  X3DNodes, X3DLoad,
  {$ifndef VER3_0} OpenSSLSockets, {$endif}
  CastleDownload, CastleParameters, CastleClassUtils, CastleImages,
  CastleControl, CastleSceneCore, CastleVectors, CastleScene, CastleViewport,
  CastleNotifications, CastleUIControls, CastleTransform, CastleLCLUtils,
  CastleKeysMouse, CastleLog, CastleTimeUtils;

type

  { TForm1 }

  TForm1 = class(TForm)
    CastleControlBase1: TCastleControlBase;
    MainMenu1: TMainMenu;
    MenuItem1: TMenuItem;
    FileOpen: TMenuItem;
    OpenDialog1: TOpenDialog;
    Panel1: TPanel;
    ProgressBar1: TProgressBar;
    Timer1: TTimer;
    procedure CastleControlBase1Press(Sender: TObject;
    const Event: TInputPressRelease);
    procedure CastleControlBase1Update(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure FileOpenClick(Sender: TObject);
    procedure SetFullScreen(FullScreenState: Boolean);
    procedure Timer1Timer(Sender: TObject);
  private
    Viewport: TCastleViewport;
    Scene: TCastleScene;
    stateNotifications: TCastleNotifications;
    infoNotifications: TCastleNotifications;
    frame: Integer;
    start_ticks: Int64;
    procedure LoadScene(filename: String);
  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.SetFullScreen(FullScreenState: Boolean);
begin
  if FullScreenState then
    ShowWindow(Handle, SW_SHOWFULLSCREEN)
  else
    ShowWindow(Handle, SW_SHOWNORMAL);
end;

procedure TForm1.CastleControlBase1Press(Sender: TObject;
  const Event: TInputPressRelease);
var
  TopMostScene: TCastleTransform;
begin
  if not (stateNotifications = nil) then
  begin
    if Event.IsMouseButton(mbLeft) then
    begin
      if Viewport.MouseRayHit <> nil then
        TopMostScene := Viewport.MouseRayHit.First.Item
      else
        TopMostScene := nil;

      if TopMostScene <> nil then
        stateNotifications.Show('Clicked on scene ' + IntToStr(TopMostScene.Tag))
      else
        stateNotifications.Show('Clicked on empty space')
    end;
  end;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var
  prog: Integer;
begin
  prog := (((CastleGetTickCount64 - start_ticks) div 1000) mod ProgressBar1.Max);
  ProgressBar1.Position := prog;
end;

procedure TForm1.CastleControlBase1Update(Sender: TObject);
var
  fps: TFloatTime;
begin
  WritelnLog('Update time : '+ IntToStr(CastleGetTickCount64 - start_ticks));
  if not (infoNotifications = nil) then
  begin
    fps := CastleControlBase1.Fps.RealFps;
    infoNotifications.Show('Frame ' + IntToStr(frame) + ' : time ' + ', fps ' + FormatFloat('#0.00', fps));
    inc(frame);
  end;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  SetFullScreen(False);
  Application.ProcessMessages;
end;

procedure TForm1.FileOpenClick(Sender: TObject);
var
  filename: String;
begin
  if OpenDialog1.Execute then
  begin
    filename := OpenDialog1.Filename;
    LoadScene(filename);
  end;
end;

procedure TForm1.LoadScene(filename: String);
begin
  if not (Scene = nil) then
    begin
      Scene.Free;
      Scene := nil;
    end;

  CastleControlBase1.Enabled:=False;

  Viewport := TCastleViewport.Create(Application);
  Viewport.FullSize := true;
  Viewport.AutoCamera := true; // instead of this, you could do "Viewport.Camera.SetView(...)"
  Viewport.AutoNavigation := true; // instead of this, you could do "Viewport.Navigation := ..."

  stateNotifications := TCastleNotifications.Create(Application);
  stateNotifications.Anchor(hpLeft, 10);
  stateNotifications.Anchor(vpBottom, 10);

  infoNotifications := TCastleNotifications.Create(Application);
  infoNotifications.Anchor(hpRight, -10);
  infoNotifications.Anchor(vpBottom, 10);

  CastleControlBase1.Controls.InsertFront(Viewport);
  CastleControlBase1.Controls.InsertFront(stateNotifications);
  CastleControlBase1.Controls.InsertFront(infoNotifications);

  Scene := TCastleScene.Create(Application);
  Scene.Spatial := [ssRendering, ssDynamicCollisions];
  Scene.ProcessEvents := true;

  Scene.Load(filename);
  Scene.Tag := 1;
  Viewport.Items.Add(Scene);

  Viewport.Items.MainScene := Scene;

  CastleControlBase1.Enabled:=True;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Form1.Width := 1280;
  Form1.Height := 800;
  Form1.Caption := 'view3d';
  frame := 0;
  start_ticks := CastleGetTickCount64;
  InitializeLog;
  LoadScene('assets/scene.gltf');
end;

end.

