Resolves RadiationCollectorVisualizer is Obsolete (#13905)

This commit is contained in:
TemporalOroboros
2023-05-18 11:03:30 -07:00
committed by GitHub
parent f43683e3b9
commit ed1b9bde83
5 changed files with 178 additions and 108 deletions

View File

@@ -0,0 +1,62 @@
using Content.Shared.Singularity.Components;
using Robust.Client.Animations;
namespace Content.Client.Singularity.Visualizers;
/// <summary>
/// The component used to reflect the state of a radiation collector in its appearance.
/// </summary>
[RegisterComponent]
[Access(typeof(RadiationCollectorSystem))]
public sealed class RadiationCollectorComponent : Component
{
/// <summary>
/// The key used to index the (de)activation animations played when turning a radiation collector on/off.
/// </summary>
[ViewVariables]
public const string AnimationKey = "radiationcollector_animation";
/// <summary>
/// The current visual state of the radiation collector.
/// </summary>
[ViewVariables]
public RadiationCollectorVisualState CurrentState = RadiationCollectorVisualState.Deactive;
/// <summary>
/// The RSI state used for the main sprite layer (<see cref="RadiationCollectorVisualLayers.Main"/>) when the radiation collector is active.
/// </summary>
[DataField("activeState")]
[ViewVariables(VVAccess.ReadWrite)]
public string ActiveState = "ca_on";
/// <summary>
/// The RSI state used for the main sprite layer (<see cref="RadiationCollectorVisualLayers.Main"/>) when the radiation collector is inactive.
/// </summary>
[DataField("inactiveState")]
[ViewVariables(VVAccess.ReadWrite)]
public string InactiveState = "ca_off";
/// <summary>
/// Used to build the <value cref="ActivateAnimation">activation animation</value> when the component is initialized.
/// </summary>
[DataField("activatingState")]
public string ActivatingState = "ca_active";
/// <summary>
/// Used to build the <see cref="DeactiveAnimation">deactivation animation</see> when the component is initialized.
/// </summary>
[DataField("deactivatingState")]
public string DeactivatingState = "ca_deactive";
/// <summary>
/// The animation used when turning on the radiation collector.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public Animation ActivateAnimation = default!;
/// <summary>
/// The animation used when turning off the radiation collector.
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public Animation DeactiveAnimation = default!;
}

View File

@@ -0,0 +1,109 @@
using System;
using Content.Shared.Singularity.Components;
using Robust.Client.Animations;
using Robust.Client.GameObjects;
namespace Content.Client.Singularity.Visualizers;
public sealed class RadiationCollectorSystem : VisualizerSystem<RadiationCollectorComponent>
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<RadiationCollectorComponent, ComponentInit>(OnComponentInit);
SubscribeLocalEvent<RadiationCollectorComponent, AnimationCompletedEvent>(OnAnimationCompleted);
}
private void OnComponentInit(EntityUid uid, RadiationCollectorComponent comp, ComponentInit args)
{
comp.ActivateAnimation = new Animation {
Length = TimeSpan.FromSeconds(0.8f),
AnimationTracks = {
new AnimationTrackSpriteFlick() {
LayerKey = RadiationCollectorVisualLayers.Main,
KeyFrames = {new AnimationTrackSpriteFlick.KeyFrame(comp.ActivatingState, 0f)}
}, // TODO: Make this play a sound when activating a radiation collector.
}
};
comp.DeactiveAnimation = new Animation {
Length = TimeSpan.FromSeconds(0.8f),
AnimationTracks = {
new AnimationTrackSpriteFlick() {
LayerKey = RadiationCollectorVisualLayers.Main,
KeyFrames = {new AnimationTrackSpriteFlick.KeyFrame(comp.DeactivatingState, 0f)}
}, // TODO: Make this play a sound when deactivating a radiation collector.
}
};
}
private void UpdateVisuals(EntityUid uid, RadiationCollectorVisualState state, RadiationCollectorComponent comp, SpriteComponent sprite, AnimationPlayerComponent? animPlayer = null)
{
if (state == comp.CurrentState)
return;
if (!Resolve(uid, ref animPlayer))
return;
if (AnimationSystem.HasRunningAnimation(uid, animPlayer, RadiationCollectorComponent.AnimationKey))
return;
var targetState = (RadiationCollectorVisualState) (state & RadiationCollectorVisualState.Active);
var destinationState = (RadiationCollectorVisualState) (comp.CurrentState & RadiationCollectorVisualState.Active);
if (targetState != destinationState) // If where we're going is not where we want to be then we must go there next.
targetState = (RadiationCollectorVisualState) (targetState | RadiationCollectorVisualState.Deactivating); // Convert to transition state.
comp.CurrentState = state;
switch (targetState)
{
case RadiationCollectorVisualState.Activating:
AnimationSystem.Play(uid, animPlayer, comp.ActivateAnimation, RadiationCollectorComponent.AnimationKey);
break;
case RadiationCollectorVisualState.Deactivating:
AnimationSystem.Play(uid, animPlayer, comp.DeactiveAnimation, RadiationCollectorComponent.AnimationKey);
break;
case RadiationCollectorVisualState.Active:
sprite.LayerSetState(RadiationCollectorVisualLayers.Main, comp.ActiveState);
break;
case RadiationCollectorVisualState.Deactive:
sprite.LayerSetState(RadiationCollectorVisualLayers.Main, comp.InactiveState);
break;
}
}
private void OnAnimationCompleted(EntityUid uid, RadiationCollectorComponent comp, AnimationCompletedEvent args)
{
if (args.Key != RadiationCollectorComponent.AnimationKey)
return;
if (!TryComp<SpriteComponent>(uid, out var sprite))
return;
if (!TryComp<AnimationPlayerComponent>(uid, out var animPlayer))
return; // Why doesn't AnimationCompletedEvent propagate the AnimationPlayerComponent? No idea, but it's in engine so I'm not touching it.
if (!AppearanceSystem.TryGetData<RadiationCollectorVisualState>(uid, RadiationCollectorVisuals.VisualState, out var state))
state = comp.CurrentState;
// Convert to terminal state.
var targetState = (RadiationCollectorVisualState) (state & RadiationCollectorVisualState.Active);
UpdateVisuals(uid, targetState, comp, sprite, animPlayer);
}
protected override void OnAppearanceChange(EntityUid uid, RadiationCollectorComponent comp, ref AppearanceChangeEvent args)
{
if (args.Sprite == null)
return;
if (!TryComp<AnimationPlayerComponent>(uid, out var animPlayer))
return;
if (!AppearanceSystem.TryGetData<RadiationCollectorVisualState>(uid, RadiationCollectorVisuals.VisualState, out var state, args.Component))
state = RadiationCollectorVisualState.Deactive;
UpdateVisuals(uid, state, comp, args.Sprite, animPlayer);
}
}
public enum RadiationCollectorVisualLayers : byte
{
Main
}

View File

@@ -1,100 +0,0 @@
using System;
using Content.Shared.Singularity.Components;
using JetBrains.Annotations;
using Robust.Client.Animations;
using Robust.Client.GameObjects;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Serialization;
namespace Content.Client.Singularity.Visualizers
{
[UsedImplicitly]
public sealed class RadiationCollectorVisualizer : AppearanceVisualizer, ISerializationHooks
{
private const string AnimationKey = "radiationcollector_animation";
private Animation ActivateAnimation = default!;
private Animation DeactiveAnimation = default!;
void ISerializationHooks.AfterDeserialization()
{
ActivateAnimation = new Animation {Length = TimeSpan.FromSeconds(0.8f)};
{
var flick = new AnimationTrackSpriteFlick();
ActivateAnimation.AnimationTracks.Add(flick);
flick.LayerKey = RadiationCollectorVisualLayers.Main;
flick.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame("ca_active", 0f));
/*var sound = new AnimationTrackPlaySound();
CloseAnimation.AnimationTracks.Add(sound);
sound.KeyFrames.Add(new AnimationTrackPlaySound.KeyFrame(closeSound, 0));*/
}
DeactiveAnimation = new Animation {Length = TimeSpan.FromSeconds(0.8f)};
{
var flick = new AnimationTrackSpriteFlick();
DeactiveAnimation.AnimationTracks.Add(flick);
flick.LayerKey = RadiationCollectorVisualLayers.Main;
flick.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame("ca_deactive", 0f));
/*var sound = new AnimationTrackPlaySound();
CloseAnimation.AnimationTracks.Add(sound);
sound.KeyFrames.Add(new AnimationTrackPlaySound.KeyFrame(closeSound, 0));*/
}
}
[Obsolete("Subscribe to your component being initialised instead.")]
public override void InitializeEntity(EntityUid entity)
{
IoCManager.Resolve<IEntityManager>().EnsureComponent<AnimationPlayerComponent>(entity);
}
[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 (!entities.TryGetComponent(component.Owner, out AnimationPlayerComponent? animPlayer)) return;
if (!component.TryGetData(RadiationCollectorVisuals.VisualState, out RadiationCollectorVisualState state))
{
state = RadiationCollectorVisualState.Deactive;
}
switch (state)
{
case RadiationCollectorVisualState.Active:
sprite.LayerSetState(RadiationCollectorVisualLayers.Main, "ca_on");
break;
case RadiationCollectorVisualState.Activating:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(ActivateAnimation, AnimationKey);
animPlayer.AnimationCompleted += _ =>
component.SetData(RadiationCollectorVisuals.VisualState,
RadiationCollectorVisualState.Active);
}
break;
case RadiationCollectorVisualState.Deactivating:
if (!animPlayer.HasRunningAnimation(AnimationKey))
{
animPlayer.Play(DeactiveAnimation, AnimationKey);
animPlayer.AnimationCompleted += _ =>
component.SetData(RadiationCollectorVisuals.VisualState,
RadiationCollectorVisualState.Deactive);
}
break;
case RadiationCollectorVisualState.Deactive:
sprite.LayerSetState(RadiationCollectorVisualLayers.Main, "ca_off");
break;
}
}
}
public enum RadiationCollectorVisualLayers : byte
{
Main
}
}

View File

@@ -11,9 +11,9 @@ namespace Content.Shared.Singularity.Components
[NetSerializable, Serializable] [NetSerializable, Serializable]
public enum RadiationCollectorVisualState public enum RadiationCollectorVisualState
{ {
Active, Active = (1<<0),
Activating, Activating = (1<<1) | Active,
Deactivating, Deactivating = (1<<1),
Deactive Deactive = 0
} }
} }

View File

@@ -28,11 +28,10 @@
netsync: false netsync: false
snapCardinals: true snapCardinals: true
layers: layers:
- state: ca_on - state: ca_off
map: ["enum.RadiationCollectorVisualLayers.Main"] map: ["enum.RadiationCollectorVisualLayers.Main"]
- type: Appearance - type: Appearance
visuals: - type: AnimationPlayer
- type: RadiationCollectorVisualizer
- type: NodeContainer - type: NodeContainer
examinable: true examinable: true
nodes: nodes: