Extensions introduced in Castle Game Engine related to the time.
See also documentation of supported nodes of the Time component and X3D specification of the Time component.
Contents:
These feature are available since Castle Game Engine 6.5 and view3dscene 3.19.0.
As an extension, we add a fractionIncreasing
field to
the TimeSensor
node:
TimeSensor { ... SFBool [in,out] fractionIncreasing TRUE }
When FALSE
, the animation runs backwards.
It's very simple: after calculating the fraction
value,
following the X3D specification, we do fraction := 1 - fraction
.
And then we send fraction
through the TimeSensor.fraction_changed
event.
If your interpolators react nicely to the TimeSensor.fraction_changed
then the animation will run backwards.
See a description how
TimeSensor and interpolators are typically connected to implement animation.
Note that everything else works as usual, regardless of
the fractionIncreasing
value. In particular,
TimeSensor.elapsedTime
and TimeSensor.time
output events are always generated with increasing values
(trying to force them to go backward would make weird results).
TimeSensor { ... SFBool [] detectAffectedFields TRUE }
In short: This field should remain TRUE
(the default value) for time sensor nodes that represent animations that Castle Game Engine can run at any moment (e.g. using TCastleSceneCore.PlayAnimation).
This allows the CGE TCastleSceneCore.ResetAnimationState
to work correctly. In turn, this means that TCastleSceneCore.PlayAnimation
works always correctly, with and without animation blending (cross-fading).
Details:
When this is TRUE
, the engine will detect the fields affected by the animation defined by this TimeSensor
node. This "detection" looks what interpolators and triggers are affected by this TimeSensor. To be precise:
TimeSensor fraction_changed
may be routed to interpolator/sequencer (X3DInterpolatorNode
, X3DSequencerNode
) input set_fraction
. Then the interpolator value_changed
must be routed to the field we call "affected".
TimeSensor isActive
may be routed to trigger ValueTrigger.trigger
or IntegerTrigger.set_boolean
or TimeTrigger.set_boolean
. Then the trigger output (ValueTrigger
has many outputs), IntegerTrigger.triggerValue
, TimeTrigger.triggerTime
must be routed to the field we call "affected".
The values assigned to detected fields will be recorded, for the entire lifetime of this scene.
The detected "affected fields" will be used:
The TCastleSceneCore.ResetAnimatedFields
sets all the fields affected by any animation to their initial (detected at loading) state.
The TCastleSceneCore.PlayAnimation
sets all the fields affected by any animation (except the new animation) to their initial (detected at loading) state.
This is important e.g. if your animation "walk" only moves the model's legs (and doesn't modify model's hands), but some other animation moves hands. Then when doing "walk" we also make sure to put the hands in the original (not animated) position. This is useful, because previous animation could be e.g. "wave_hand" and you don't want the hand to be permanently raised up during "walk" animation cycle.
Note that if you want to play multiple animations simulteneously, you can use TTimeSensorNode.Start
instead of TCastleSceneCore.PlayAnimation
. See simultaneous_animations_one_scene example . In this case, the "affected fields" do not matter, starting an animation using TTimeSensorNode.Start
doesn't reset any fields.
Set the detectAffectedFields
field to FALSE
when this detection would be useless and time-consuming. This applies to time sensors which are not supposed to be used with TCastleSceneCore.PlayAnimation
. Saving the state of "affected" fields may take time (if they are e.g. MFVec3f fields with lots of data) and may change memory management (if they are e.g. SFNode or MFNode fields).