Resolve PoweredLightVisualizer is Obsolete (#13891)
This commit is contained in:
@@ -1,131 +0,0 @@
|
|||||||
using Content.Shared.Light;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Robust.Client.Animations;
|
|
||||||
using Robust.Client.GameObjects;
|
|
||||||
using Robust.Shared.Animations;
|
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Robust.Shared.Random;
|
|
||||||
|
|
||||||
namespace Content.Client.Light.Visualizers
|
|
||||||
{
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class PoweredLightVisualizer : AppearanceVisualizer
|
|
||||||
{
|
|
||||||
[DataField("minBlinkingTime")] private float _minBlinkingTime = 0.5f;
|
|
||||||
[DataField("maxBlinkingTime")] private float _maxBlinkingTime = 2;
|
|
||||||
[DataField("blinkingSound")] private SoundSpecifier? _blinkingSound = default;
|
|
||||||
|
|
||||||
private bool _wasBlinking;
|
|
||||||
|
|
||||||
private Action<string>? _blinkingCallback;
|
|
||||||
|
|
||||||
[Obsolete("Subscribe to AppearanceChangeEvent instead.")]
|
|
||||||
public override void OnChangeData(AppearanceComponent component)
|
|
||||||
{
|
|
||||||
base.OnChangeData(component);
|
|
||||||
|
|
||||||
var entities = IoCManager.Resolve<IEntityManager>();
|
|
||||||
if (!entities.TryGetComponent(component.Owner, out SpriteComponent? sprite)) return;
|
|
||||||
if (!component.TryGetData(PoweredLightVisuals.BulbState, out PoweredLightState state)) return;
|
|
||||||
|
|
||||||
switch (state)
|
|
||||||
{
|
|
||||||
case PoweredLightState.Empty:
|
|
||||||
sprite.LayerSetState(PoweredLightLayers.Base, "empty");
|
|
||||||
ToggleBlinkingAnimation(component, false);
|
|
||||||
break;
|
|
||||||
case PoweredLightState.Off:
|
|
||||||
sprite.LayerSetState(PoweredLightLayers.Base, "off");
|
|
||||||
ToggleBlinkingAnimation(component, false);
|
|
||||||
break;
|
|
||||||
case PoweredLightState.On:
|
|
||||||
if (component.TryGetData(PoweredLightVisuals.Blinking, out bool isBlinking))
|
|
||||||
ToggleBlinkingAnimation(component, isBlinking);
|
|
||||||
if (!isBlinking)
|
|
||||||
{
|
|
||||||
sprite.LayerSetState(PoweredLightLayers.Base, "on");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PoweredLightState.Broken:
|
|
||||||
sprite.LayerSetState(PoweredLightLayers.Base, "broken");
|
|
||||||
ToggleBlinkingAnimation(component, false);
|
|
||||||
break;
|
|
||||||
case PoweredLightState.Burned:
|
|
||||||
sprite.LayerSetState(PoweredLightLayers.Base, "burn");
|
|
||||||
ToggleBlinkingAnimation(component, false);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private void ToggleBlinkingAnimation(AppearanceComponent component, bool isBlinking)
|
|
||||||
{
|
|
||||||
if (isBlinking == _wasBlinking)
|
|
||||||
return;
|
|
||||||
_wasBlinking = isBlinking;
|
|
||||||
|
|
||||||
component.Owner.EnsureComponent(out AnimationPlayerComponent animationPlayer);
|
|
||||||
|
|
||||||
if (isBlinking)
|
|
||||||
{
|
|
||||||
_blinkingCallback = (animName) => animationPlayer.Play(BlinkingAnimation(), "blinking");
|
|
||||||
animationPlayer.AnimationCompleted += _blinkingCallback;
|
|
||||||
animationPlayer.Play(BlinkingAnimation(), "blinking");
|
|
||||||
}
|
|
||||||
else if (animationPlayer.HasRunningAnimation("blinking"))
|
|
||||||
{
|
|
||||||
if (_blinkingCallback != null)
|
|
||||||
animationPlayer.AnimationCompleted -= _blinkingCallback;
|
|
||||||
animationPlayer.Stop("blinking");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Animation BlinkingAnimation()
|
|
||||||
{
|
|
||||||
var random = IoCManager.Resolve<IRobustRandom>();
|
|
||||||
var randomTime = random.NextFloat() *
|
|
||||||
(_maxBlinkingTime - _minBlinkingTime) + _minBlinkingTime;
|
|
||||||
|
|
||||||
var blinkingAnim = new Animation()
|
|
||||||
{
|
|
||||||
Length = TimeSpan.FromSeconds(randomTime),
|
|
||||||
AnimationTracks =
|
|
||||||
{
|
|
||||||
new AnimationTrackComponentProperty
|
|
||||||
{
|
|
||||||
ComponentType = typeof(PointLightComponent),
|
|
||||||
InterpolationMode = AnimationInterpolationMode.Nearest,
|
|
||||||
Property = nameof(PointLightComponent.Enabled),
|
|
||||||
KeyFrames =
|
|
||||||
{
|
|
||||||
new AnimationTrackProperty.KeyFrame(false, 0),
|
|
||||||
new AnimationTrackProperty.KeyFrame(true, 1)
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new AnimationTrackSpriteFlick()
|
|
||||||
{
|
|
||||||
LayerKey = PoweredLightLayers.Base,
|
|
||||||
KeyFrames =
|
|
||||||
{
|
|
||||||
new AnimationTrackSpriteFlick.KeyFrame("off", 0),
|
|
||||||
new AnimationTrackSpriteFlick.KeyFrame("on", 0.5f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (_blinkingSound != null)
|
|
||||||
{
|
|
||||||
blinkingAnim.AnimationTracks.Add(new AnimationTrackPlaySound()
|
|
||||||
{
|
|
||||||
KeyFrames =
|
|
||||||
{
|
|
||||||
new AnimationTrackPlaySound.KeyFrame(_blinkingSound.GetSound(), 0.5f)
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return blinkingAnim;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
125
Content.Client/Light/Visualizers/PoweredLightVisualizerSystem.cs
Normal file
125
Content.Client/Light/Visualizers/PoweredLightVisualizerSystem.cs
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
using Content.Shared.Light;
|
||||||
|
using Robust.Client.Animations;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Shared.Animations;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
namespace Content.Client.Light.Visualizers;
|
||||||
|
|
||||||
|
public sealed class PoweredLightVisualizerSystem : VisualizerSystem<PoweredLightVisualsComponent>
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<PoweredLightVisualsComponent, AnimationCompletedEvent>(OnAnimationCompleted);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnAppearanceChange(EntityUid uid, PoweredLightVisualsComponent comp, ref AppearanceChangeEvent args)
|
||||||
|
{
|
||||||
|
if (args.Sprite == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!AppearanceSystem.TryGetData<PoweredLightState>(uid, PoweredLightVisuals.BulbState, out var state, args.Component))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (comp.SpriteStateMap.TryGetValue(state, out var spriteState))
|
||||||
|
args.Sprite.LayerSetState(PoweredLightLayers.Base, spriteState);
|
||||||
|
|
||||||
|
SetBlinkingAnimation(
|
||||||
|
uid,
|
||||||
|
state == PoweredLightState.On
|
||||||
|
&& (AppearanceSystem.TryGetData<bool>(uid, PoweredLightVisuals.Blinking, out var isBlinking, args.Component) && isBlinking),
|
||||||
|
comp
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Loops the blinking animation until the light should stop blinking.
|
||||||
|
/// </summary>
|
||||||
|
private void OnAnimationCompleted(EntityUid uid, PoweredLightVisualsComponent comp, AnimationCompletedEvent args)
|
||||||
|
{
|
||||||
|
if (args.Key != PoweredLightVisualsComponent.BlinkingAnimationKey)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!comp.IsBlinking)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AnimationSystem.Play(uid, Comp<AnimationPlayerComponent>(uid), BlinkingAnimation(comp), PoweredLightVisualsComponent.BlinkingAnimationKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets whether or not the given light should be blinking.
|
||||||
|
/// Triggers or clears the blinking animation of the state changes.
|
||||||
|
/// </summary>
|
||||||
|
private void SetBlinkingAnimation(EntityUid uid, bool shouldBeBlinking, PoweredLightVisualsComponent comp)
|
||||||
|
{
|
||||||
|
if (shouldBeBlinking == comp.IsBlinking)
|
||||||
|
return;
|
||||||
|
|
||||||
|
comp.IsBlinking = shouldBeBlinking;
|
||||||
|
|
||||||
|
var animationPlayer = EnsureComp<AnimationPlayerComponent>(uid);
|
||||||
|
if (shouldBeBlinking)
|
||||||
|
{
|
||||||
|
AnimationSystem.Play(uid, animationPlayer, BlinkingAnimation(comp), PoweredLightVisualsComponent.BlinkingAnimationKey);
|
||||||
|
}
|
||||||
|
else if (AnimationSystem.HasRunningAnimation(uid, animationPlayer, PoweredLightVisualsComponent.BlinkingAnimationKey))
|
||||||
|
{
|
||||||
|
AnimationSystem.Stop(uid, animationPlayer, PoweredLightVisualsComponent.BlinkingAnimationKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generates a blinking animation.
|
||||||
|
/// Essentially just flashes the light off and on over a random time interval.
|
||||||
|
/// The resulting animation is looped indefinitely until the comp is set to stop blinking.
|
||||||
|
/// </summary>
|
||||||
|
private Animation BlinkingAnimation(PoweredLightVisualsComponent comp)
|
||||||
|
{
|
||||||
|
var randomTime = MathHelper.Lerp(comp.MinBlinkingAnimationCycleTime, comp.MaxBlinkingAnimationCycleTime, _random.NextFloat());
|
||||||
|
var blinkingAnim = new Animation()
|
||||||
|
{
|
||||||
|
Length = TimeSpan.FromSeconds(randomTime),
|
||||||
|
AnimationTracks =
|
||||||
|
{
|
||||||
|
new AnimationTrackComponentProperty
|
||||||
|
{
|
||||||
|
ComponentType = typeof(PointLightComponent),
|
||||||
|
InterpolationMode = AnimationInterpolationMode.Nearest,
|
||||||
|
Property = nameof(PointLightComponent.Enabled),
|
||||||
|
KeyFrames =
|
||||||
|
{
|
||||||
|
new AnimationTrackProperty.KeyFrame(false, 0),
|
||||||
|
new AnimationTrackProperty.KeyFrame(true, 1)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new AnimationTrackSpriteFlick()
|
||||||
|
{
|
||||||
|
LayerKey = PoweredLightLayers.Base,
|
||||||
|
KeyFrames =
|
||||||
|
{
|
||||||
|
new AnimationTrackSpriteFlick.KeyFrame(comp.SpriteStateMap[PoweredLightState.Off], 0),
|
||||||
|
new AnimationTrackSpriteFlick.KeyFrame(comp.SpriteStateMap[PoweredLightState.On], 0.5f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (comp.BlinkingSound != null)
|
||||||
|
{
|
||||||
|
var sound = _audio.GetSound(comp.BlinkingSound);
|
||||||
|
blinkingAnim.AnimationTracks.Add(new AnimationTrackPlaySound()
|
||||||
|
{
|
||||||
|
KeyFrames =
|
||||||
|
{
|
||||||
|
new AnimationTrackPlaySound.KeyFrame(sound, 0.5f)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return blinkingAnim;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
using Content.Shared.Light;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
|
||||||
|
namespace Content.Client.Light.Visualizers;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
[Access(typeof(PoweredLightVisualizerSystem))]
|
||||||
|
public sealed class PoweredLightVisualsComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A map of the sprite states used by this visualizer indexed by the light state they correspond to.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("spriteStateMap")]
|
||||||
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
|
public readonly Dictionary<PoweredLightState, string> SpriteStateMap = new()
|
||||||
|
{
|
||||||
|
[PoweredLightState.Empty] = "empty",
|
||||||
|
[PoweredLightState.Off] = "off",
|
||||||
|
[PoweredLightState.On] = "on",
|
||||||
|
[PoweredLightState.Broken] = "broken",
|
||||||
|
[PoweredLightState.Burned] = "burn",
|
||||||
|
};
|
||||||
|
|
||||||
|
#region Blinking
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The id used to track the blinking animation for lights.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadOnly)]
|
||||||
|
public const string BlinkingAnimationKey = "poweredlight_blinking";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The minimum length of the base blinking animation (one on-off-on cycle) in seconds.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("minBlinkingTime")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float MinBlinkingAnimationCycleTime = 0.5f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum length of the base blinking animation (one on-off-on cycle) in seconds.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("maxBlinkingTime")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float MaxBlinkingAnimationCycleTime = 2;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The sound that plays when the blinking animation cycles.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("blinkingSound")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public SoundSpecifier? BlinkingSound = default;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether or not this light is currently blinking.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public bool IsBlinking;
|
||||||
|
|
||||||
|
#endregion Blinking
|
||||||
|
}
|
||||||
@@ -90,10 +90,9 @@
|
|||||||
receiveFrequencyId: SmartLight
|
receiveFrequencyId: SmartLight
|
||||||
- type: ApcNetworkConnection
|
- type: ApcNetworkConnection
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
visuals:
|
- type: PoweredLightVisuals
|
||||||
- type: PoweredLightVisualizer
|
blinkingSound:
|
||||||
blinkingSound:
|
path: "/Audio/Machines/light_tube_on.ogg"
|
||||||
path: "/Audio/Machines/light_tube_on.ogg"
|
|
||||||
- type: SignalReceiver
|
- type: SignalReceiver
|
||||||
inputs:
|
inputs:
|
||||||
On: []
|
On: []
|
||||||
@@ -263,8 +262,7 @@
|
|||||||
receiveFrequencyId: SmartLight
|
receiveFrequencyId: SmartLight
|
||||||
- type: ApcNetworkConnection
|
- type: ApcNetworkConnection
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
visuals:
|
- type: PoweredLightVisuals
|
||||||
- type: PoweredLightVisualizer
|
|
||||||
- type: SignalReceiver
|
- type: SignalReceiver
|
||||||
inputs:
|
inputs:
|
||||||
On: []
|
On: []
|
||||||
|
|||||||
@@ -91,10 +91,9 @@
|
|||||||
graph: LightFixture
|
graph: LightFixture
|
||||||
node: groundLight
|
node: groundLight
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
visuals:
|
- type: PoweredLightVisuals
|
||||||
- type: PoweredLightVisualizer
|
blinkingSound:
|
||||||
blinkingSound:
|
path: "/Audio/Machines/light_tube_on.ogg"
|
||||||
path: "/Audio/Machines/light_tube_on.ogg"
|
|
||||||
- type: SignalReceiver
|
- type: SignalReceiver
|
||||||
inputs:
|
inputs:
|
||||||
On: []
|
On: []
|
||||||
|
|||||||
Reference in New Issue
Block a user