mirror of
https://github.com/wega-team/ss14-wega.git
synced 2026-06-09 10:06:49 +02:00
226 lines
7.8 KiB
C#
226 lines
7.8 KiB
C#
using System.Numerics;
|
|
using Content.Shared.Input;
|
|
using Content.Shared.Posing;
|
|
using Robust.Client.GameObjects;
|
|
using Robust.Client.Input;
|
|
using Robust.Client.Player;
|
|
|
|
namespace Content.Client.Posing;
|
|
|
|
public sealed partial class PosingSystem : SharedPosingSystem
|
|
{
|
|
[Dependency] private IInputManager _input = default!;
|
|
[Dependency] private IPlayerManager _playerManager = default!;
|
|
[Dependency] private SpriteSystem _sprite = default!;
|
|
|
|
private readonly Dictionary<EntityUid, (
|
|
Vector2 Offset,
|
|
Angle Angle,
|
|
Vector2 TargetOffset,
|
|
Angle TargetAngle,
|
|
float LerpTime,
|
|
bool IsReturning
|
|
)> _interpolationState = new();
|
|
|
|
public override void Initialize()
|
|
{
|
|
base.Initialize();
|
|
|
|
SubscribeLocalEvent<PosingComponent, ComponentRemove>(OnComponentRemove);
|
|
SubscribeLocalEvent<PosingComponent, AfterAutoHandleStateEvent>(OnAfterHandleState);
|
|
|
|
var posing = _input.Contexts.New("posing", "common");
|
|
posing.AddFunction(ContentKeyFunctions.TogglePosing);
|
|
posing.AddFunction(ContentKeyFunctions.PosingOffsetUp);
|
|
posing.AddFunction(ContentKeyFunctions.PosingOffsetDown);
|
|
posing.AddFunction(ContentKeyFunctions.PosingOffsetLeft);
|
|
posing.AddFunction(ContentKeyFunctions.PosingOffsetRight);
|
|
posing.AddFunction(ContentKeyFunctions.PosingRotatePositive);
|
|
posing.AddFunction(ContentKeyFunctions.PosingRotateNegative);
|
|
}
|
|
|
|
public override void FrameUpdate(float frameTime)
|
|
{
|
|
base.FrameUpdate(frameTime);
|
|
|
|
var query = EntityQueryEnumerator<PosingComponent>();
|
|
while (query.MoveNext(out var uid, out var posing))
|
|
{
|
|
if (posing.Posing)
|
|
{
|
|
if (!_interpolationState.TryGetValue(uid, out var state))
|
|
{
|
|
state = (
|
|
posing.CurrentOffset,
|
|
posing.CurrentAngle,
|
|
posing.CurrentOffset,
|
|
posing.CurrentAngle,
|
|
0f,
|
|
false
|
|
);
|
|
_interpolationState[uid] = state;
|
|
}
|
|
|
|
if (state.IsReturning)
|
|
{
|
|
state = (
|
|
posing.CurrentOffset,
|
|
posing.CurrentAngle,
|
|
posing.CurrentOffset,
|
|
posing.CurrentAngle,
|
|
0f,
|
|
false
|
|
);
|
|
}
|
|
|
|
if (state.TargetOffset != posing.CurrentOffset || state.TargetAngle != posing.CurrentAngle)
|
|
{
|
|
state.TargetOffset = posing.CurrentOffset;
|
|
state.TargetAngle = posing.CurrentAngle;
|
|
state.LerpTime = 0f;
|
|
}
|
|
|
|
state.LerpTime += frameTime;
|
|
var t = Math.Min(1f, state.LerpTime / 0.15f);
|
|
|
|
var newOffset = Vector2.Lerp(state.Offset, state.TargetOffset, t);
|
|
var newAngle = Angle.FromDegrees(
|
|
MathHelper.Lerp(state.Angle.Degrees, state.TargetAngle.Degrees, t)
|
|
);
|
|
|
|
if (t >= 1f)
|
|
{
|
|
state.Offset = state.TargetOffset;
|
|
state.Angle = state.TargetAngle;
|
|
}
|
|
else
|
|
{
|
|
state.Offset = newOffset;
|
|
state.Angle = newAngle;
|
|
}
|
|
|
|
_sprite.SetOffset(uid, posing.DefaultOffset + state.Offset);
|
|
_sprite.SetRotation(uid, state.Angle);
|
|
|
|
_interpolationState[uid] = state;
|
|
}
|
|
else
|
|
{
|
|
if (_interpolationState.TryGetValue(uid, out var state))
|
|
{
|
|
if (!state.IsReturning)
|
|
{
|
|
state.IsReturning = true;
|
|
state.LerpTime = 0f;
|
|
state.TargetOffset = Vector2.Zero;
|
|
state.TargetAngle = Angle.Zero;
|
|
}
|
|
|
|
state.LerpTime += frameTime;
|
|
var t = Math.Min(1f, state.LerpTime / 0.2f);
|
|
|
|
var newOffset = Vector2.Lerp(state.Offset, state.TargetOffset, t);
|
|
var newAngle = Angle.FromDegrees(
|
|
MathHelper.Lerp(state.Angle.Degrees, state.TargetAngle.Degrees, t)
|
|
);
|
|
|
|
if (t >= 1f)
|
|
{
|
|
_interpolationState.Remove(uid);
|
|
_sprite.SetOffset(uid, posing.DefaultOffset);
|
|
_sprite.SetRotation(uid, Angle.FromDegrees(posing.DefaultAngle));
|
|
}
|
|
else
|
|
{
|
|
state.Offset = newOffset;
|
|
state.Angle = newAngle;
|
|
_interpolationState[uid] = state;
|
|
_sprite.SetOffset(uid, posing.DefaultOffset + state.Offset);
|
|
_sprite.SetRotation(uid, state.Angle);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public override void Shutdown()
|
|
{
|
|
base.Shutdown();
|
|
_input.Contexts.Remove("posing");
|
|
_interpolationState.Clear();
|
|
}
|
|
|
|
protected override void TogglePosing(Entity<PosingComponent?> entity)
|
|
{
|
|
base.TogglePosing(entity);
|
|
|
|
if (!Resolve(entity, ref entity.Comp, false))
|
|
return;
|
|
|
|
_input.Contexts.SetActiveContext(entity.Comp.Posing ? "posing" : entity.Comp.DefaultInputContext);
|
|
|
|
if (entity.Comp.Posing)
|
|
{
|
|
_interpolationState[entity.Owner] = (
|
|
entity.Comp.CurrentOffset,
|
|
entity.Comp.CurrentAngle,
|
|
entity.Comp.CurrentOffset,
|
|
entity.Comp.CurrentAngle,
|
|
0f, false
|
|
);
|
|
_sprite.SetOffset(entity.Owner, entity.Comp.DefaultOffset + entity.Comp.CurrentOffset);
|
|
_sprite.SetRotation(entity.Owner, entity.Comp.CurrentAngle);
|
|
}
|
|
else
|
|
{
|
|
if (_interpolationState.TryGetValue(entity.Owner, out var state))
|
|
{
|
|
state.IsReturning = true;
|
|
state.LerpTime = 0f;
|
|
state.TargetOffset = Vector2.Zero;
|
|
state.TargetAngle = Angle.Zero;
|
|
_interpolationState[entity.Owner] = state;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void OnComponentRemove(EntityUid uid, PosingComponent component, ComponentRemove args)
|
|
{
|
|
_interpolationState.Remove(uid);
|
|
}
|
|
|
|
private void OnAfterHandleState(EntityUid uid, PosingComponent component, ref AfterAutoHandleStateEvent args)
|
|
{
|
|
if (_playerManager.LocalEntity == uid)
|
|
return;
|
|
|
|
if (component.Posing && _interpolationState.TryGetValue(uid, out var state))
|
|
{
|
|
state.TargetOffset = component.CurrentOffset;
|
|
state.TargetAngle = component.CurrentAngle;
|
|
state.LerpTime = 0f;
|
|
state.IsReturning = false;
|
|
_interpolationState[uid] = state;
|
|
}
|
|
else if (component.Posing && !_interpolationState.ContainsKey(uid))
|
|
{
|
|
_interpolationState[uid] = (
|
|
component.CurrentOffset,
|
|
component.CurrentAngle,
|
|
component.CurrentOffset,
|
|
component.CurrentAngle,
|
|
0f, false
|
|
);
|
|
}
|
|
else if (!component.Posing && _interpolationState.ContainsKey(uid) && !_interpolationState[uid].IsReturning)
|
|
{
|
|
var returnState = _interpolationState[uid];
|
|
returnState.IsReturning = true;
|
|
returnState.LerpTime = 0f;
|
|
returnState.TargetOffset = Vector2.Zero;
|
|
returnState.TargetAngle = Angle.Zero;
|
|
_interpolationState[uid] = returnState;
|
|
}
|
|
}
|
|
}
|