diff --git a/Content.Client/Buckle/BuckleVisualizer.cs b/Content.Client/Buckle/BuckleVisualizer.cs deleted file mode 100644 index 0be425f45d..0000000000 --- a/Content.Client/Buckle/BuckleVisualizer.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System; -using Content.Shared.Buckle.Components; -using JetBrains.Annotations; -using Robust.Client.Animations; -using Robust.Client.GameObjects; -using Robust.Shared.Animations; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Maths; - -namespace Content.Client.Buckle -{ - [UsedImplicitly] - public sealed class BuckleVisualizer : AppearanceVisualizer - { - [Obsolete("Subscribe to AppearanceChangeEvent instead.")] - public override void OnChangeData(AppearanceComponent component) - { - if (!component.TryGetData(BuckleVisuals.Buckled, out var buckled) || - !buckled) - { - return; - } - - if (!component.TryGetData(StrapVisuals.RotationAngle, out var angle)) - { - return; - } - - SetRotation(component, Angle.FromDegrees(angle)); - } - - private void SetRotation(AppearanceComponent component, Angle rotation) - { - var sprite = IoCManager.Resolve().GetComponent(component.Owner); - - if (!IoCManager.Resolve().TryGetComponent(sprite.Owner, out AnimationPlayerComponent? animation)) - { - sprite.Rotation = rotation; - return; - } - - if (animation.HasRunningAnimation("rotate")) - { - animation.Stop("rotate"); - } - - animation.Play(new Animation - { - Length = TimeSpan.FromSeconds(0.125), - AnimationTracks = - { - new AnimationTrackComponentProperty - { - ComponentType = typeof(ISpriteComponent), - Property = nameof(ISpriteComponent.Rotation), - InterpolationMode = AnimationInterpolationMode.Linear, - KeyFrames = - { - new AnimationTrackProperty.KeyFrame(sprite.Rotation, 0), - new AnimationTrackProperty.KeyFrame(rotation, 0.125f) - } - } - } - }, "rotate"); - } - } -} diff --git a/Content.Client/Buckle/BuckleVisualizerSystem.cs b/Content.Client/Buckle/BuckleVisualizerSystem.cs new file mode 100644 index 0000000000..f5531ced44 --- /dev/null +++ b/Content.Client/Buckle/BuckleVisualizerSystem.cs @@ -0,0 +1,23 @@ +using Content.Shared.Buckle.Components; +using Content.Client.Rotation; +using Robust.Client.GameObjects; + +namespace Content.Client.Buckle; + +public sealed class BuckleVisualizer : VisualizerSystem +{ + protected override void OnAppearanceChange(EntityUid uid, BuckleComponent component, ref AppearanceChangeEvent args) + { + if (!args.Component.TryGetData(StrapVisuals.RotationAngle, out var angle) || + !args.Component.TryGetData(BuckleVisuals.Buckled, out var buckled) || + !buckled || + args.Sprite == null) + { + return; + } + + EntityManager.System() + .AnimateSpriteRotation(args.Sprite, Angle.FromDegrees(angle), 0.125f); + } +} + diff --git a/Content.Client/Rotation/RotationVisualizer.cs b/Content.Client/Rotation/RotationVisualizer.cs deleted file mode 100644 index 6bddf2e10f..0000000000 --- a/Content.Client/Rotation/RotationVisualizer.cs +++ /dev/null @@ -1,76 +0,0 @@ -using System; -using Content.Shared.Rotation; -using JetBrains.Annotations; -using Robust.Client.Animations; -using Robust.Client.GameObjects; -using Robust.Shared.Animations; -using Robust.Shared.GameObjects; -using Robust.Shared.IoC; -using Robust.Shared.Maths; - -namespace Content.Client.Rotation -{ - [UsedImplicitly] - public sealed class RotationVisualizer : AppearanceVisualizer - { - [Obsolete("Subscribe to AppearanceChangeEvent instead.")] - public override void OnChangeData(AppearanceComponent component) - { - base.OnChangeData(component); - - // if TryGet fails, state defaults to RotationState.Vertical. - component.TryGetData(RotationVisuals.RotationState, out var state); - - switch (state) - { - case RotationState.Vertical: - SetRotation(component, 0); - break; - case RotationState.Horizontal: - SetRotation(component, Angle.FromDegrees(90)); - break; - } - } - - private void SetRotation(AppearanceComponent component, Angle rotation) - { - var entMan = IoCManager.Resolve(); - var sprite = entMan.GetComponent(component.Owner); - - if (sprite.Rotation.Equals(rotation)) - { - return; - } - - if (!entMan.TryGetComponent(sprite.Owner, out AnimationPlayerComponent? animation)) - { - sprite.Rotation = rotation; - return; - } - - if (animation.HasRunningAnimation("rotate")) - { - animation.Stop("rotate"); - } - - animation.Play(new Animation - { - Length = TimeSpan.FromSeconds(0.125), - AnimationTracks = - { - new AnimationTrackComponentProperty - { - ComponentType = typeof(ISpriteComponent), - Property = nameof(ISpriteComponent.Rotation), - InterpolationMode = AnimationInterpolationMode.Linear, - KeyFrames = - { - new AnimationTrackProperty.KeyFrame(sprite.Rotation, 0), - new AnimationTrackProperty.KeyFrame(rotation, 0.125f) - } - } - } - }, "rotate"); - } - } -} diff --git a/Content.Client/Rotation/RotationVisualizerSystem.cs b/Content.Client/Rotation/RotationVisualizerSystem.cs new file mode 100644 index 0000000000..d67ca67615 --- /dev/null +++ b/Content.Client/Rotation/RotationVisualizerSystem.cs @@ -0,0 +1,73 @@ +using Robust.Client.GameObjects; +using Robust.Client.Animations; +using Content.Shared.Rotation; +using Robust.Shared.Animations; + +namespace Content.Client.Rotation; + +public sealed class RotationVisualizerSystem : VisualizerSystem +{ + protected override void OnAppearanceChange(EntityUid uid, RotationVisualsComponent component, ref AppearanceChangeEvent args) + { + base.OnAppearanceChange(uid, component, ref args); + + if (args.Sprite != null) + { + // if TryGetData fails, state defaults to RotationState.Vertical. + args.Component.TryGetData(RotationVisuals.RotationState, out var state); + + switch (state) + { + case RotationState.Vertical: + AnimateSpriteRotation(args.Sprite, component.VerticalRotation, component.AnimationTime); + break; + case RotationState.Horizontal: + AnimateSpriteRotation(args.Sprite, component.HorizontalRotation, component.AnimationTime); + break; + } + } + } + + /// + /// Rotates a sprite between two animated keyframes given a certain time. + /// + public void AnimateSpriteRotation(SpriteComponent sprite, Angle rotation, float animationTime) + { + var entMan = IoCManager.Resolve(); + + if (sprite.Rotation.Equals(rotation)) + { + return; + } + + if (!entMan.TryGetComponent(sprite.Owner, out AnimationPlayerComponent? animation)) + { + sprite.Rotation = rotation; + return; + } + + if (animation.HasRunningAnimation("rotate")) + { + animation.Stop("rotate"); + } + + animation.Play(new Animation + { + Length = TimeSpan.FromSeconds(animationTime), + AnimationTracks = + { + new AnimationTrackComponentProperty + { + ComponentType = typeof(ISpriteComponent), + Property = nameof(ISpriteComponent.Rotation), + InterpolationMode = AnimationInterpolationMode.Linear, + KeyFrames = + { + new AnimationTrackProperty.KeyFrame(sprite.Rotation, 0), + new AnimationTrackProperty.KeyFrame(rotation, animationTime) + } + } + } + }, "rotate"); + } +} diff --git a/Content.Client/Rotation/RotationVisualsComponent.cs b/Content.Client/Rotation/RotationVisualsComponent.cs new file mode 100644 index 0000000000..ee7fc6a7cc --- /dev/null +++ b/Content.Client/Rotation/RotationVisualsComponent.cs @@ -0,0 +1,14 @@ +namespace Content.Client.Rotation; + +[RegisterComponent] +public sealed class RotationVisualsComponent : Component +{ + [ViewVariables(VVAccess.ReadWrite)] + public Angle VerticalRotation = 0; + + [ViewVariables(VVAccess.ReadWrite)] + public Angle HorizontalRotation = Angle.FromDegrees(90); + + [ViewVariables(VVAccess.ReadWrite)] + public float AnimationTime = 0.125f; +} diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml index 45625cae98..2e3ceae3a8 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/simplemob.yml @@ -127,8 +127,7 @@ groups: Brute: 5 - type: Appearance - visuals: - - type: BuckleVisualizer + - type: RotationVisuals - type: FireVisuals sprite: Mobs/Effects/onfire.rsi normalState: Generic_mob_burning diff --git a/Resources/Prototypes/Entities/Mobs/Species/base.yml b/Resources/Prototypes/Entities/Mobs/Species/base.yml index 9665486e79..74383554a9 100644 --- a/Resources/Prototypes/Entities/Mobs/Species/base.yml +++ b/Resources/Prototypes/Entities/Mobs/Species/base.yml @@ -225,10 +225,9 @@ sprite: Mobs/Effects/burn_damage.rsi - type: Appearance visuals: - - type: RotationVisualizer - - type: BuckleVisualizer - type: CreamPiedVisualizer state: creampie_human + - type: RotationVisuals - type: FireVisuals sprite: Mobs/Effects/onfire.rsi normalState: Generic_mob_burning @@ -368,6 +367,7 @@ - type: Body prototype: Human requiredLegs: 2 + - type: Appearance - type: Damageable damageContainer: Biological - type: MobState @@ -375,9 +375,6 @@ 0: Alive 100: Critical 200: Dead - - type: Appearance - visuals: - - type: RotationVisualizer - type: UserInterface interfaces: - key: enum.HumanoidMarkingModifierKey.Key # sure, this can go here too