From: TemporalOroboros Date: Thu, 16 Feb 2023 04:10:41 +0000 (-0800) Subject: Resolve PoweredLightVisualizer is Obsolete (#13891) X-Git-Url: https://git.smokeofanarchy.ru/gitweb.cgi?a=commitdiff_plain;h=6b381f73042bb23e472c832283fbeba981a4a571;p=space-station-14.git Resolve PoweredLightVisualizer is Obsolete (#13891) --- diff --git a/Content.Client/Light/Visualizers/PoweredLightVisualizer.cs b/Content.Client/Light/Visualizers/PoweredLightVisualizer.cs deleted file mode 100644 index cc40dd27be..0000000000 --- a/Content.Client/Light/Visualizers/PoweredLightVisualizer.cs +++ /dev/null @@ -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? _blinkingCallback; - - [Obsolete("Subscribe to AppearanceChangeEvent instead.")] - public override void OnChangeData(AppearanceComponent component) - { - base.OnChangeData(component); - - var entities = IoCManager.Resolve(); - 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(); - 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; - } - } -} diff --git a/Content.Client/Light/Visualizers/PoweredLightVisualizerSystem.cs b/Content.Client/Light/Visualizers/PoweredLightVisualizerSystem.cs new file mode 100644 index 0000000000..62af358c40 --- /dev/null +++ b/Content.Client/Light/Visualizers/PoweredLightVisualizerSystem.cs @@ -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 +{ + [Dependency] private readonly IRobustRandom _random = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnAnimationCompleted); + } + + protected override void OnAppearanceChange(EntityUid uid, PoweredLightVisualsComponent comp, ref AppearanceChangeEvent args) + { + if (args.Sprite == null) + return; + + if (!AppearanceSystem.TryGetData(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(uid, PoweredLightVisuals.Blinking, out var isBlinking, args.Component) && isBlinking), + comp + ); + } + + /// + /// Loops the blinking animation until the light should stop blinking. + /// + private void OnAnimationCompleted(EntityUid uid, PoweredLightVisualsComponent comp, AnimationCompletedEvent args) + { + if (args.Key != PoweredLightVisualsComponent.BlinkingAnimationKey) + return; + + if(!comp.IsBlinking) + return; + + AnimationSystem.Play(uid, Comp(uid), BlinkingAnimation(comp), PoweredLightVisualsComponent.BlinkingAnimationKey); + } + + /// + /// Sets whether or not the given light should be blinking. + /// Triggers or clears the blinking animation of the state changes. + /// + private void SetBlinkingAnimation(EntityUid uid, bool shouldBeBlinking, PoweredLightVisualsComponent comp) + { + if (shouldBeBlinking == comp.IsBlinking) + return; + + comp.IsBlinking = shouldBeBlinking; + + var animationPlayer = EnsureComp(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); + } + } + + /// + /// 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. + /// + 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; + } +} diff --git a/Content.Client/Light/Visualizers/PoweredLightVisualsComponent.cs b/Content.Client/Light/Visualizers/PoweredLightVisualsComponent.cs new file mode 100644 index 0000000000..6a1b4d713d --- /dev/null +++ b/Content.Client/Light/Visualizers/PoweredLightVisualsComponent.cs @@ -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 +{ + /// + /// A map of the sprite states used by this visualizer indexed by the light state they correspond to. + /// + [DataField("spriteStateMap")] + [ViewVariables(VVAccess.ReadOnly)] + public readonly Dictionary SpriteStateMap = new() + { + [PoweredLightState.Empty] = "empty", + [PoweredLightState.Off] = "off", + [PoweredLightState.On] = "on", + [PoweredLightState.Broken] = "broken", + [PoweredLightState.Burned] = "burn", + }; + + #region Blinking + + /// + /// The id used to track the blinking animation for lights. + /// + [ViewVariables(VVAccess.ReadOnly)] + public const string BlinkingAnimationKey = "poweredlight_blinking"; + + /// + /// The minimum length of the base blinking animation (one on-off-on cycle) in seconds. + /// + [DataField("minBlinkingTime")] + [ViewVariables(VVAccess.ReadWrite)] + public float MinBlinkingAnimationCycleTime = 0.5f; + + /// + /// The maximum length of the base blinking animation (one on-off-on cycle) in seconds. + /// + [DataField("maxBlinkingTime")] + [ViewVariables(VVAccess.ReadWrite)] + public float MaxBlinkingAnimationCycleTime = 2; + + /// + /// The sound that plays when the blinking animation cycles. + /// + [DataField("blinkingSound")] + [ViewVariables(VVAccess.ReadWrite)] + public SoundSpecifier? BlinkingSound = default; + + /// + /// Whether or not this light is currently blinking. + /// + [ViewVariables(VVAccess.ReadWrite)] + public bool IsBlinking; + + #endregion Blinking +} diff --git a/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml b/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml index baa2d7362a..6d5c038811 100644 --- a/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml +++ b/Resources/Prototypes/Entities/Structures/Lighting/base_lighting.yml @@ -90,10 +90,9 @@ receiveFrequencyId: SmartLight - type: ApcNetworkConnection - type: Appearance - visuals: - - type: PoweredLightVisualizer - blinkingSound: - path: "/Audio/Machines/light_tube_on.ogg" + - type: PoweredLightVisuals + blinkingSound: + path: "/Audio/Machines/light_tube_on.ogg" - type: SignalReceiver inputs: On: [] @@ -263,8 +262,7 @@ receiveFrequencyId: SmartLight - type: ApcNetworkConnection - type: Appearance - visuals: - - type: PoweredLightVisualizer + - type: PoweredLightVisuals - type: SignalReceiver inputs: On: [] diff --git a/Resources/Prototypes/Entities/Structures/Lighting/ground_lighting.yml b/Resources/Prototypes/Entities/Structures/Lighting/ground_lighting.yml index 3f8bbc0f99..5c506cc802 100644 --- a/Resources/Prototypes/Entities/Structures/Lighting/ground_lighting.yml +++ b/Resources/Prototypes/Entities/Structures/Lighting/ground_lighting.yml @@ -91,10 +91,9 @@ graph: LightFixture node: groundLight - type: Appearance - visuals: - - type: PoweredLightVisualizer - blinkingSound: - path: "/Audio/Machines/light_tube_on.ogg" + - type: PoweredLightVisuals + blinkingSound: + path: "/Audio/Machines/light_tube_on.ogg" - type: SignalReceiver inputs: On: []