2022-11-16 20:22:11 +01:00
using System.Linq ;
2023-09-04 06:31:10 +01:00
using Content.Shared.Light.Components ;
2020-12-08 11:56:10 +01:00
using JetBrains.Annotations ;
2020-09-13 14:23:52 +02:00
using Robust.Client.Animations ;
2020-09-03 16:02:40 -04:00
using Robust.Client.GameObjects ;
using Robust.Shared.Animations ;
2021-02-11 01:13:03 -08:00
using Robust.Shared.Random ;
2020-09-13 14:23:52 +02:00
using Robust.Shared.Serialization ;
2020-09-03 16:02:40 -04:00
2021-06-09 22:19:39 +02:00
namespace Content.Client.Light.Components
2020-09-03 16:02:40 -04:00
{
#region LIGHT_BEHAVIOURS
/// <summary>
/// Base class for all light behaviours to derive from.
/// This AnimationTrack derivative does not rely on keyframes since it often needs to have a randomized duration.
/// </summary>
[Serializable]
2021-03-05 01:08:38 +01:00
[ImplicitDataDefinitionForInheritors]
2023-08-22 18:14:33 -07:00
public abstract partial class LightBehaviourAnimationTrack : AnimationTrackProperty
2020-09-03 16:02:40 -04:00
{
2021-12-08 12:09:43 +01:00
protected IEntityManager _entMan = default ! ;
2021-09-01 13:23:52 +02:00
protected IRobustRandom _random = default ! ;
2021-03-10 14:48:29 +01:00
2022-11-16 20:22:11 +01:00
[DataField("id")] public string ID { get ; set ; } = string . Empty ;
2021-03-05 01:08:38 +01:00
[DataField("property")]
2023-09-18 05:57:49 +12:00
public virtual string Property { get ; protected set ; } = nameof ( PointLightComponent . AnimatedRadius ) ;
2021-03-05 01:08:38 +01:00
2022-11-16 20:22:11 +01:00
[DataField("isLooped")] public bool IsLooped { get ; set ; }
2021-03-05 01:08:38 +01:00
2022-11-16 20:22:11 +01:00
[DataField("enabled")] public bool Enabled { get ; set ; }
2021-03-05 01:08:38 +01:00
2022-11-16 20:22:11 +01:00
[DataField("startValue")] public float StartValue { get ; set ; } = 0f ;
2021-03-05 01:08:38 +01:00
2022-11-16 20:22:11 +01:00
[DataField("endValue")] public float EndValue { get ; set ; } = 2f ;
2021-03-05 01:08:38 +01:00
2022-11-16 20:22:11 +01:00
[DataField("minDuration")] public float MinDuration { get ; set ; } = - 1f ;
2021-03-05 01:08:38 +01:00
2022-11-16 20:22:11 +01:00
[DataField("maxDuration")] public float MaxDuration { get ; set ; } = 2f ;
2021-03-05 01:08:38 +01:00
2022-11-16 20:22:11 +01:00
[DataField("interpolate")] public AnimationInterpolationMode InterpolateMode { get ; set ; } = AnimationInterpolationMode . Linear ;
2020-09-03 16:02:40 -04:00
[ViewVariables] protected float MaxTime { get ; set ; }
private float _maxTime = default ;
2021-12-05 18:09:01 +01:00
private EntityUid _parent = default ! ;
2020-09-06 17:16:08 +02:00
2021-12-08 12:09:43 +01:00
public void Initialize ( EntityUid parent , IRobustRandom random , IEntityManager entMan )
2020-09-03 16:02:40 -04:00
{
2021-09-01 13:23:52 +02:00
_random = random ;
2021-12-08 12:09:43 +01:00
_entMan = entMan ;
2021-03-10 14:48:29 +01:00
_parent = parent ;
2020-09-03 16:02:40 -04:00
2021-12-08 12:09:43 +01:00
if ( Enabled & & _entMan . TryGetComponent ( _parent , out PointLightComponent ? light ) )
2020-09-03 16:02:40 -04:00
{
2023-09-11 19:18:06 +10:00
_entMan . System < PointLightSystem > ( ) . SetEnabled ( _parent , true , light ) ;
2020-09-03 16:02:40 -04:00
}
OnInitialize ( ) ;
}
public void UpdatePlaybackValues ( Animation owner )
{
2021-12-08 12:09:43 +01:00
if ( _entMan . TryGetComponent ( _parent , out PointLightComponent ? light ) )
2021-03-10 14:48:29 +01:00
{
2023-09-11 19:18:06 +10:00
_entMan . System < PointLightSystem > ( ) . SetEnabled ( _parent , true , light ) ;
2021-03-10 14:48:29 +01:00
}
2020-09-03 16:02:40 -04:00
if ( MinDuration > 0 )
{
2021-05-28 00:56:06 -07:00
MaxTime = ( float ) _random . NextDouble ( ) * ( MaxDuration - MinDuration ) + MinDuration ;
2020-09-03 16:02:40 -04:00
}
else
{
MaxTime = MaxDuration ;
}
2020-09-06 17:16:08 +02:00
owner . Length = TimeSpan . FromSeconds ( MaxTime ) ;
2020-09-03 16:02:40 -04:00
}
public override ( int KeyFrameIndex , float FramePlayingTime ) InitPlayback ( )
{
OnStart ( ) ;
return ( - 1 , _maxTime ) ;
}
protected void ApplyProperty ( object value )
{
if ( Property = = null )
{
throw new InvalidOperationException ( "Property parameter is null! Check the prototype!" ) ;
}
2021-12-08 12:09:43 +01:00
if ( _entMan . TryGetComponent ( _parent , out PointLightComponent ? light ) )
2020-09-03 16:02:40 -04:00
{
2021-03-10 14:48:29 +01:00
AnimationHelper . SetAnimatableProperty ( light , Property , value ) ;
2020-09-03 16:02:40 -04:00
}
}
protected override void ApplyProperty ( object context , object value )
{
ApplyProperty ( value ) ;
}
public virtual void OnInitialize ( ) { }
public virtual void OnStart ( ) { }
}
/// <summary>
/// A light behaviour that alternates between StartValue and EndValue
/// </summary>
2020-12-08 11:56:10 +01:00
[UsedImplicitly]
2023-08-22 18:14:33 -07:00
public sealed partial class PulseBehaviour : LightBehaviourAnimationTrack
2020-09-03 16:02:40 -04:00
{
public override ( int KeyFrameIndex , float FramePlayingTime ) AdvancePlayback (
object context , int prevKeyFrameIndex , float prevPlayingTime , float frameTime )
{
var playingTime = prevPlayingTime + frameTime ;
var interpolateValue = playingTime / MaxTime ;
2023-09-18 05:57:49 +12:00
if ( Property = = nameof ( PointLightComponent . AnimatedEnable ) ) // special case for boolean
2020-09-03 16:02:40 -04:00
{
2021-12-05 18:09:01 +01:00
ApplyProperty ( interpolateValue < 0.5f ) ;
2020-09-03 16:02:40 -04:00
return ( - 1 , playingTime ) ;
}
if ( interpolateValue < 0.5f )
{
switch ( InterpolateMode )
{
case AnimationInterpolationMode . Linear :
ApplyProperty ( InterpolateLinear ( StartValue , EndValue , interpolateValue * 2f ) ) ;
break ;
case AnimationInterpolationMode . Cubic :
ApplyProperty ( InterpolateCubic ( EndValue , StartValue , EndValue , StartValue , interpolateValue * 2f ) ) ;
break ;
default :
case AnimationInterpolationMode . Nearest :
ApplyProperty ( StartValue ) ;
break ;
}
}
else
{
switch ( InterpolateMode )
{
case AnimationInterpolationMode . Linear :
ApplyProperty ( InterpolateLinear ( EndValue , StartValue , ( interpolateValue - 0.5f ) * 2f ) ) ;
break ;
case AnimationInterpolationMode . Cubic :
ApplyProperty ( InterpolateCubic ( StartValue , EndValue , StartValue , EndValue , ( interpolateValue - 0.5f ) * 2f ) ) ;
break ;
default :
case AnimationInterpolationMode . Nearest :
ApplyProperty ( EndValue ) ;
break ;
}
}
return ( - 1 , playingTime ) ;
}
}
/// <summary>
/// A light behaviour that interpolates from StartValue to EndValue
/// </summary>
2020-12-08 11:56:10 +01:00
[UsedImplicitly]
2023-08-22 18:14:33 -07:00
public sealed partial class FadeBehaviour : LightBehaviourAnimationTrack
2020-09-03 16:02:40 -04:00
{
2022-10-19 20:34:36 +02:00
/// <summary>
/// Automatically reverse the animation when EndValue is reached. In this particular case, MaxTime specifies the
/// time of the full animation, including the reverse interpolation.
/// </summary>
[DataField("reverseWhenFinished")]
public bool ReverseWhenFinished { get ; set ; }
2020-09-03 16:02:40 -04:00
public override ( int KeyFrameIndex , float FramePlayingTime ) AdvancePlayback (
object context , int prevKeyFrameIndex , float prevPlayingTime , float frameTime )
{
var playingTime = prevPlayingTime + frameTime ;
var interpolateValue = playingTime / MaxTime ;
2023-09-18 05:57:49 +12:00
if ( Property = = nameof ( PointLightComponent . AnimatedEnable ) ) // special case for boolean
2020-09-03 16:02:40 -04:00
{
2021-12-05 18:09:01 +01:00
ApplyProperty ( interpolateValue < EndValue ) ;
2020-09-03 16:02:40 -04:00
return ( - 1 , playingTime ) ;
}
2022-10-19 20:34:36 +02:00
// From 0 to MaxTime/2, we go from StartValue to EndValue. From MaxTime/2 to MaxTime, we reverse this interpolation.
if ( ReverseWhenFinished )
{
if ( interpolateValue < 0.5f )
{
ApplyInterpolation ( StartValue , EndValue , interpolateValue * 2 ) ;
}
else
{
ApplyInterpolation ( EndValue , StartValue , ( interpolateValue - 0.5f ) * 2 ) ;
}
}
else
{
ApplyInterpolation ( StartValue , EndValue , interpolateValue ) ;
}
return ( - 1 , playingTime ) ;
}
private void ApplyInterpolation ( float start , float end , float interpolateValue )
{
2020-09-03 16:02:40 -04:00
switch ( InterpolateMode )
{
case AnimationInterpolationMode . Linear :
2022-10-19 20:34:36 +02:00
ApplyProperty ( InterpolateLinear ( start , end , interpolateValue ) ) ;
2020-09-03 16:02:40 -04:00
break ;
case AnimationInterpolationMode . Cubic :
2022-10-19 20:34:36 +02:00
ApplyProperty ( InterpolateCubic ( end , start , end , start , interpolateValue ) ) ;
2020-09-03 16:02:40 -04:00
break ;
default :
case AnimationInterpolationMode . Nearest :
2022-10-19 20:34:36 +02:00
ApplyProperty ( interpolateValue < 0.5f ? start : end ) ;
2020-09-03 16:02:40 -04:00
break ;
}
}
}
/// <summary>
/// A light behaviour that interpolates using random values chosen between StartValue and EndValue.
/// </summary>
2020-12-08 11:56:10 +01:00
[UsedImplicitly]
2023-08-22 18:14:33 -07:00
public sealed partial class RandomizeBehaviour : LightBehaviourAnimationTrack
2020-09-03 16:02:40 -04:00
{
2021-05-28 00:56:06 -07:00
private float _randomValue1 ;
private float _randomValue2 ;
private float _randomValue3 ;
private float _randomValue4 ;
2020-09-03 16:02:40 -04:00
public override void OnInitialize ( )
{
2021-05-28 00:56:06 -07:00
_randomValue1 = ( float ) InterpolateLinear ( StartValue , EndValue , ( float ) _random . NextDouble ( ) ) ;
_randomValue2 = ( float ) InterpolateLinear ( StartValue , EndValue , ( float ) _random . NextDouble ( ) ) ;
_randomValue3 = ( float ) InterpolateLinear ( StartValue , EndValue , ( float ) _random . NextDouble ( ) ) ;
2020-09-03 16:02:40 -04:00
}
public override void OnStart ( )
{
2023-09-18 05:57:49 +12:00
if ( Property = = nameof ( PointLightComponent . AnimatedEnable ) ) // special case for boolean, we randomize it
2020-09-03 16:02:40 -04:00
{
2021-05-28 00:56:06 -07:00
ApplyProperty ( _random . NextDouble ( ) < 0.5 ) ;
2020-09-03 16:02:40 -04:00
return ;
}
if ( InterpolateMode = = AnimationInterpolationMode . Cubic )
{
_randomValue1 = _randomValue2 ;
_randomValue2 = _randomValue3 ;
}
_randomValue3 = _randomValue4 ;
2021-05-28 00:56:06 -07:00
_randomValue4 = ( float ) InterpolateLinear ( StartValue , EndValue , ( float ) _random . NextDouble ( ) ) ;
2020-09-03 16:02:40 -04:00
}
public override ( int KeyFrameIndex , float FramePlayingTime ) AdvancePlayback (
object context , int prevKeyFrameIndex , float prevPlayingTime , float frameTime )
{
var playingTime = prevPlayingTime + frameTime ;
var interpolateValue = playingTime / MaxTime ;
2023-09-18 05:57:49 +12:00
if ( Property = = nameof ( PointLightComponent . AnimatedEnable ) )
2020-09-03 16:02:40 -04:00
{
return ( - 1 , playingTime ) ;
}
switch ( InterpolateMode )
{
case AnimationInterpolationMode . Linear :
ApplyProperty ( InterpolateLinear ( _randomValue3 , _randomValue4 , interpolateValue ) ) ;
break ;
case AnimationInterpolationMode . Cubic :
2021-12-05 18:09:01 +01:00
ApplyProperty ( InterpolateCubic ( _randomValue1 , _randomValue2 , _randomValue3 , _randomValue4 , interpolateValue ) ) ;
2020-09-03 16:02:40 -04:00
break ;
default :
case AnimationInterpolationMode . Nearest :
ApplyProperty ( interpolateValue < 0.5f ? _randomValue3 : _randomValue4 ) ;
break ;
}
return ( - 1 , playingTime ) ;
}
}
/// <summary>
/// A light behaviour that cycles through a list of colors.
/// </summary>
2020-12-08 11:56:10 +01:00
[UsedImplicitly]
2021-03-05 01:08:38 +01:00
[DataDefinition]
2023-08-22 18:14:33 -07:00
public sealed partial class ColorCycleBehaviour : LightBehaviourAnimationTrack , ISerializationHooks
2020-09-03 16:02:40 -04:00
{
2021-03-05 01:08:38 +01:00
[DataField("property")]
2023-09-18 05:57:49 +12:00
public override string Property { get ; protected set ; } = nameof ( PointLightComponent . Color ) ;
2021-03-05 01:08:38 +01:00
[DataField("colors")] public List < Color > ColorsToCycle { get ; set ; } = new ( ) ;
2020-09-03 16:02:40 -04:00
2021-03-05 01:08:38 +01:00
private int _colorIndex ;
2020-09-03 16:02:40 -04:00
public override void OnStart ( )
{
_colorIndex + + ;
if ( _colorIndex > ColorsToCycle . Count - 1 )
{
_colorIndex = 0 ;
}
}
public override ( int KeyFrameIndex , float FramePlayingTime ) AdvancePlayback (
object context , int prevKeyFrameIndex , float prevPlayingTime , float frameTime )
{
var playingTime = prevPlayingTime + frameTime ;
var interpolateValue = playingTime / MaxTime ;
switch ( InterpolateMode )
{
case AnimationInterpolationMode . Linear :
ApplyProperty ( InterpolateLinear ( ColorsToCycle [ ( _colorIndex - 1 ) % ColorsToCycle . Count ] ,
ColorsToCycle [ _colorIndex ] ,
interpolateValue ) ) ;
break ;
case AnimationInterpolationMode . Cubic :
ApplyProperty ( InterpolateCubic ( ColorsToCycle [ _colorIndex ] ,
ColorsToCycle [ ( _colorIndex + 1 ) % ColorsToCycle . Count ] ,
ColorsToCycle [ ( _colorIndex + 2 ) % ColorsToCycle . Count ] ,
ColorsToCycle [ ( _colorIndex + 3 ) % ColorsToCycle . Count ] ,
interpolateValue ) ) ;
break ;
default :
case AnimationInterpolationMode . Nearest :
ApplyProperty ( ColorsToCycle [ _colorIndex ] ) ;
break ;
}
return ( - 1 , playingTime ) ;
}
2021-03-05 01:08:38 +01:00
void ISerializationHooks . AfterDeserialization ( )
2020-09-03 16:02:40 -04:00
{
if ( ColorsToCycle . Count < 2 )
{
throw new InvalidOperationException ( $"{nameof(ColorCycleBehaviour)} has less than 2 colors to cycle" ) ;
}
}
}
#endregion
/// <summary>
/// A component which applies a specific behaviour to a PointLightComponent on its owner.
/// </summary>
[RegisterComponent]
2023-08-22 18:14:33 -07:00
public sealed partial class LightBehaviourComponent : SharedLightBehaviourComponent , ISerializationHooks
2020-09-03 16:02:40 -04:00
{
2021-12-08 12:09:43 +01:00
[Dependency] private readonly IEntityManager _entMan = default ! ;
[Dependency] private readonly IRobustRandom _random = default ! ;
2020-09-03 16:02:40 -04:00
private const string KeyPrefix = nameof ( LightBehaviourComponent ) ;
2022-02-16 00:23:23 -07:00
public sealed class AnimationContainer
2020-09-03 16:02:40 -04:00
{
public AnimationContainer ( int key , Animation animation , LightBehaviourAnimationTrack track )
{
Key = key ;
Animation = animation ;
LightBehaviour = track ;
}
public string FullKey = > KeyPrefix + Key ;
public int Key { get ; set ; }
public Animation Animation { get ; set ; }
public LightBehaviourAnimationTrack LightBehaviour { get ; set ; }
}
2021-03-05 01:08:38 +01:00
[ViewVariables(VVAccess.ReadOnly)]
[DataField("behaviours")]
2023-08-22 18:14:33 -07:00
public List < LightBehaviourAnimationTrack > Behaviours = new ( ) ;
2021-03-05 01:08:38 +01:00
2020-09-03 16:02:40 -04:00
[ViewVariables(VVAccess.ReadOnly)]
2023-07-23 16:11:13 +10:00
public readonly List < AnimationContainer > Animations = new ( ) ;
2020-09-03 16:02:40 -04:00
2022-10-19 20:34:36 +02:00
[ViewVariables(VVAccess.ReadOnly)]
private Dictionary < string , object > _originalPropertyValues = new ( ) ;
2021-03-05 01:08:38 +01:00
void ISerializationHooks . AfterDeserialization ( )
{
var key = 0 ;
foreach ( var behaviour in Behaviours )
{
var animation = new Animation ( )
{
2021-03-10 14:48:29 +01:00
AnimationTracks = { behaviour }
2021-03-05 01:08:38 +01:00
} ;
2023-07-23 16:11:13 +10:00
Animations . Add ( new AnimationContainer ( key , animation , behaviour ) ) ;
2021-03-05 01:08:38 +01:00
key + + ;
}
}
2020-09-03 16:02:40 -04:00
/// <summary>
/// If we disable all the light behaviours we want to be able to revert the light to its original state.
/// </summary>
2023-10-19 12:34:31 -07:00
private void CopyLightSettings ( EntityUid uid , string property )
2020-09-03 16:02:40 -04:00
{
2023-10-19 12:34:31 -07:00
if ( _entMan . TryGetComponent ( uid , out PointLightComponent ? light ) )
2020-09-03 16:02:40 -04:00
{
2022-10-19 20:34:36 +02:00
var propertyValue = AnimationHelper . GetAnimatableProperty ( light , property ) ;
if ( propertyValue ! = null )
{
_originalPropertyValues . Add ( property , propertyValue ) ;
}
2020-09-03 16:02:40 -04:00
}
else
{
2023-10-19 12:34:31 -07:00
Logger . Warning ( $"{_entMan.GetComponent<MetaDataComponent>(uid).EntityName} has a {nameof(LightBehaviourComponent)} but it has no {nameof(PointLightComponent)}! Check the prototype!" ) ;
2020-09-03 16:02:40 -04:00
}
}
/// <summary>
/// Start animating a light behaviour with the specified ID. If the specified ID is empty, it will start animating all light behaviour entries.
/// If specified light behaviours are already animating, calling this does nothing.
/// Multiple light behaviours can have the same ID.
/// </summary>
public void StartLightBehaviour ( string id = "" )
{
2023-10-14 10:28:06 -07:00
var uid = Owner ;
if ( ! _entMan . TryGetComponent ( uid , out AnimationPlayerComponent ? animation ) )
2021-03-10 14:48:29 +01:00
{
return ;
}
2023-10-14 10:28:06 -07:00
var animations = _entMan . System < AnimationPlayerSystem > ( ) ;
2023-07-23 16:11:13 +10:00
foreach ( var container in Animations )
2020-09-03 16:02:40 -04:00
{
if ( container . LightBehaviour . ID = = id | | id = = string . Empty )
{
2023-10-14 10:28:06 -07:00
if ( ! animations . HasRunningAnimation ( uid , animation , KeyPrefix + container . Key ) )
2020-09-03 16:02:40 -04:00
{
2023-10-19 12:34:31 -07:00
CopyLightSettings ( uid , container . LightBehaviour . Property ) ;
2020-09-03 16:02:40 -04:00
container . LightBehaviour . UpdatePlaybackValues ( container . Animation ) ;
2023-10-14 10:28:06 -07:00
animations . Play ( uid , animation , container . Animation , KeyPrefix + container . Key ) ;
2020-09-03 16:02:40 -04:00
}
}
}
}
/// <summary>
/// If any light behaviour with the specified ID is animating, then stop it.
/// If no ID is specified then all light behaviours will be stopped.
/// Multiple light behaviours can have the same ID.
/// </summary>
/// <param name="id"></param>
/// <param name="removeBehaviour">Should the behaviour(s) also be removed permanently?</param>
/// <param name="resetToOriginalSettings">Should the light have its original settings applied?</param>
public void StopLightBehaviour ( string id = "" , bool removeBehaviour = false , bool resetToOriginalSettings = false )
{
2023-10-14 10:28:06 -07:00
var uid = Owner ;
if ( ! _entMan . TryGetComponent ( uid , out AnimationPlayerComponent ? animation ) )
2021-03-10 14:48:29 +01:00
{
return ;
}
2020-09-03 16:02:40 -04:00
var toRemove = new List < AnimationContainer > ( ) ;
2023-10-14 10:28:06 -07:00
var animations = _entMan . System < AnimationPlayerSystem > ( ) ;
2020-09-03 16:02:40 -04:00
2023-07-23 16:11:13 +10:00
foreach ( var container in Animations )
2020-09-03 16:02:40 -04:00
{
if ( container . LightBehaviour . ID = = id | | id = = string . Empty )
{
2023-10-14 10:28:06 -07:00
if ( animations . HasRunningAnimation ( uid , animation , KeyPrefix + container . Key ) )
2020-09-03 16:02:40 -04:00
{
2023-10-14 10:28:06 -07:00
animations . Stop ( uid , animation , KeyPrefix + container . Key ) ;
2020-09-03 16:02:40 -04:00
}
if ( removeBehaviour )
{
toRemove . Add ( container ) ;
}
}
}
foreach ( var container in toRemove )
{
2023-07-23 16:11:13 +10:00
Animations . Remove ( container ) ;
2020-09-03 16:02:40 -04:00
}
2023-10-14 10:28:06 -07:00
if ( resetToOriginalSettings & & _entMan . TryGetComponent ( uid , out PointLightComponent ? light ) )
2020-09-03 16:02:40 -04:00
{
2022-10-19 20:34:36 +02:00
foreach ( var ( property , value ) in _originalPropertyValues )
{
AnimationHelper . SetAnimatableProperty ( light , property , value ) ;
}
}
_originalPropertyValues . Clear ( ) ;
}
/// <summary>
/// Checks if at least one behaviour is running.
/// </summary>
/// <returns>Whether at least one behaviour is running, false if none is.</returns>
public bool HasRunningBehaviours ( )
{
2023-10-14 10:28:06 -07:00
var uid = Owner ;
if ( ! _entMan . TryGetComponent ( uid , out AnimationPlayerComponent ? animation ) )
2022-10-19 20:34:36 +02:00
{
return false ;
2020-09-03 16:02:40 -04:00
}
2022-10-19 20:34:36 +02:00
2023-10-14 10:28:06 -07:00
var animations = _entMan . System < AnimationPlayerSystem > ( ) ;
return Animations . Any ( container = > animations . HasRunningAnimation ( uid , animation , KeyPrefix + container . Key ) ) ;
2020-09-03 16:02:40 -04:00
}
/// <summary>
/// Add a new light behaviour to the component and start it immediately unless otherwise specified.
/// </summary>
public void AddNewLightBehaviour ( LightBehaviourAnimationTrack behaviour , bool playImmediately = true )
{
2021-03-10 14:48:29 +01:00
var key = 0 ;
2020-09-03 16:02:40 -04:00
2023-07-23 16:11:13 +10:00
while ( Animations . Any ( x = > x . Key = = key ) )
2020-09-03 16:02:40 -04:00
{
key + + ;
}
var animation = new Animation ( )
{
2021-03-10 14:48:29 +01:00
AnimationTracks = { behaviour }
2020-09-03 16:02:40 -04:00
} ;
2021-12-08 12:09:43 +01:00
behaviour . Initialize ( Owner , _random , _entMan ) ;
2021-03-10 14:48:29 +01:00
2020-09-03 16:02:40 -04:00
var container = new AnimationContainer ( key , animation , behaviour ) ;
2023-07-23 16:11:13 +10:00
Animations . Add ( container ) ;
2020-09-03 16:02:40 -04:00
if ( playImmediately )
{
StartLightBehaviour ( behaviour . ID ) ;
}
}
}
}