Class TPlayAnimationParameters

Unit

Declaration

type TPlayAnimationParameters = class(TObject)

Description

Parameters to use when playing animation, see TCastleSceneCore.PlayAnimation.

Design note: This is a class, not e.g. an advanced record. This way is has always sensible defaults. You will usually create and quickly destroy it around the TCastleSceneCore.PlayAnimation call. Don't worry, time of creation/destruction of it really doesn't matter in practice, thanks to fast FPC memory allocator.

Hierarchy

  • TObject
  • TPlayAnimationParameters

Overview

Fields

Public Name: string;
Public Loop: boolean;
Public Forward: boolean;
Public StopNotification: TStopAnimationEvent;
Public TransitionDuration: TFloatTime;
Public InitialTime: TFloatTime;

Methods

Public constructor Create;

Description

Fields

Public Name: string;

Animation name. You have to set at least this field, otherwise calling TCastleSceneCore.PlayAnimation with this is useless.

Public Loop: boolean;

Should we play in a loop, default False which means to play just once.

Public Forward: boolean;

Does animation play forward, default True.

Public StopNotification: TStopAnimationEvent;

Notification when the animation finished playing, which happens if the animation was non-looping and it reached the end, or another animation was started by TCastleSceneCore.PlayAnimation.

This will never fire if the animation did not exist (TCastleSceneCore.PlayAnimation returned False). It also may never fire if the scene was destroyed or rebuilt (TCastleSceneCore.ChangedAll) during the animation playing.

Listening on this notification is usually simpler and more reliable then explicitly adding a notification to TTimeSensorNode.EventIsActive, e.g. by CurrentAnimation.EventIsActive.AddNotification. It avoids corner cases when PlayAnimation restarts playing the current animation. This notification will happen when the animation that you caused (by the call to TCastleSceneCore.PlayAnimation) stops, not at other times.

Example usage:

{ Example of using TPlayAnimationParameters.StopNotification.

  Play animation by pressing Space.

  There are 3 cases when the animation stops in this application:

  - if you press S,
  - if you just wait for animation to finish,
    since we leave TPlayAnimationParameters.Loop = false.
    (it's a short attack animation).
  - note that the animation also stops when another animation is run.
    (the OnStopNotification in this case is not called immediately
    when Scene.PlayAnimation for new animation is called,
    the actual animation change happens in nearest update).

  Regardless of why the animation stopped, AnimationStopped method is called. }

{$ifdef MSWINDOWS} {$apptype GUI} {$endif}

uses SysUtils,
  CastleWindow, CastleSceneCore, CastleScene, CastleViewport, CastleCameras,
  CastleVectors, CastleUIState, CastleUIControls, CastleControls, X3DNodes,
  CastleKeysMouse, CastleColors, CastleNotifications;

{ TStateMain ----------------------------------------------------------------- }

type
  TStateMain = class(TUIState)
  strict private
    Viewport: TCastleViewport;
    Scene: TCastleScene;
    Notifications: TCastleNotifications;
    procedure AnimationStopped(const AScene: TCastleSceneCore; const Animation: TTimeSensorNode);
  public
    procedure Start; override;
    function Press(const Event: TInputPressRelease): Boolean; override;
  end;

procedure TStateMain.Start;
begin
  inherited;

  Viewport := TCastleViewport.Create(FreeAtStop);
  Viewport.FullSize := true;
  Viewport.AutoCamera := true;
  Viewport.InsertBack(TCastleExamineNavigation.Create(Application));
  InsertFront(Viewport);

  Scene := TCastleScene.Create(FreeAtStop);
  Scene.Load('castle-data:/knight.gltf');
  Viewport.Items.Add(Scene);
  Viewport.Items.MainScene := Scene;

  Notifications := TCastleNotifications.Create(FreeAtStop);
  Notifications.Timeout := 2;
  Notifications.Fade := 0.25;
  Notifications.Color := Yellow;
  Notifications.FontSize := 30;
  Notifications.Anchor(vpTop, -10);
  Notifications.Anchor(hpMiddle);
  Notifications.TextAlignment := hpMiddle;
  Viewport.InsertFront(Notifications);
end;

function TStateMain.Press(const Event: TInputPressRelease): Boolean;
var
  PlayAnimationParams: TPlayAnimationParameters;
begin
  Result := inherited;
  if Result then Exit;

  if Event.IsKey(keySpace) then
  begin
    PlayAnimationParams := TPlayAnimationParameters.Create;
    try
      PlayAnimationParams.Name := 'Attack';
      PlayAnimationParams.StopNotification := {$ifdef FPC}@{$endif} AnimationStopped;
      Scene.PlayAnimation(PlayAnimationParams);
    finally FreeAndNil(PlayAnimationParams) end;

    Notifications.Show('Playing animation...');
  end;

  if Event.IsKey(keyS) then
    Scene.StopAnimation;
end;

procedure TStateMain.AnimationStopped(const AScene: TCastleSceneCore; const Animation: TTimeSensorNode);
begin
  Notifications.Show('Stopped.');
end;

{ application initialization ------------------------------------------------- }

var
  Window: TCastleWindow;
  StateMain: TStateMain;
begin
  Window := TCastleWindow.Create(Application);
  Window.Open;
  Application.MainWindow := Window;

  StateMain := TStateMain.Create(Application);
  TUIState.Current := StateMain;

  Application.Run;
end.

Public TransitionDuration: TFloatTime;

Time, in seconds, when this animation fades-in (and the previous animation, if any, fades-out). See https://castle-engine.io/wp/2018/03/21/animation-blending/

Public InitialTime: TFloatTime;

Start new animation at given moment in animation. Allows to start animation from the middle, not necessarily from the start.

Note that animation blending (TransitionDuration) starts from the moment you called the PlayAnimation, i.e. from InitialTime, not from 0. In other words, animation will enter smoothly (cross-fade), regardless of InitialTime.

Methods

Public constructor Create;
 

Generated by PasDoc 0.16.0.