Fix pinpointer flicker (#15452)

This commit is contained in:
Slava0135
2023-05-07 11:20:43 +03:00
committed by GitHub
parent 7b5ad3ca83
commit dce7741b9d
6 changed files with 322 additions and 417 deletions

View File

@@ -1,57 +1,60 @@
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;
namespace Content.Shared.Pinpointer
namespace Content.Shared.Pinpointer;
/// <summary>
/// Displays a sprite on the item that points towards the target component.
/// </summary>
[RegisterComponent, NetworkedComponent]
[AutoGenerateComponentState]
[Access(typeof(SharedPinpointerSystem))]
public sealed partial class PinpointerComponent : Component
{
// TODO: Type serializer oh god
[DataField("component")]
public string? Component;
[DataField("mediumDistance"), ViewVariables(VVAccess.ReadWrite)]
public float MediumDistance = 16f;
[DataField("closeDistance"), ViewVariables(VVAccess.ReadWrite)]
public float CloseDistance = 8f;
[DataField("reachedDistance"), ViewVariables(VVAccess.ReadWrite)]
public float ReachedDistance = 1f;
/// <summary>
/// Displays a sprite on the item that points towards the target component.
/// Pinpointer arrow precision in radians.
/// </summary>
[RegisterComponent]
[NetworkedComponent]
[Access(typeof(SharedPinpointerSystem))]
public sealed class PinpointerComponent : Component
{
// TODO: Type serializer oh god
[DataField("component")]
public string? Component;
[DataField("precision"), ViewVariables(VVAccess.ReadWrite)]
public double Precision = 0.09;
[DataField("mediumDistance")]
public float MediumDistance = 16f;
[ViewVariables]
public EntityUid? Target = null;
[DataField("closeDistance")]
public float CloseDistance = 8f;
[ViewVariables]
[AutoNetworkedField]
public bool IsActive = false;
[DataField("reachedDistance")]
public float ReachedDistance = 1f;
[ViewVariables]
[AutoNetworkedField]
public Angle ArrowAngle;
/// <summary>
/// Pinpointer arrow precision in radians.
/// </summary>
[DataField("precision")]
public double Precision = 0.09;
[ViewVariables]
[AutoNetworkedField]
public Distance DistanceToTarget = Distance.Unknown;
public EntityUid? Target = null;
public bool IsActive = false;
public Angle ArrowAngle;
public Distance DistanceToTarget = Distance.Unknown;
public bool HasTarget => DistanceToTarget != Distance.Unknown;
}
[Serializable, NetSerializable]
public sealed class PinpointerComponentState : ComponentState
{
public bool IsActive;
public Angle ArrowAngle;
public Distance DistanceToTarget;
}
[Serializable, NetSerializable]
public enum Distance : byte
{
Unknown,
Reached,
Close,
Medium,
Far
}
[ViewVariables]
public bool HasTarget => DistanceToTarget != Distance.Unknown;
}
[Serializable, NetSerializable]
public enum Distance : byte
{
Unknown,
Reached,
Close,
Medium,
Far
}

View File

@@ -1,86 +1,52 @@
using Robust.Shared.GameStates;
namespace Content.Shared.Pinpointer;
namespace Content.Shared.Pinpointer
public abstract class SharedPinpointerSystem : EntitySystem
{
public abstract class SharedPinpointerSystem : EntitySystem
/// <summary>
/// Manually set distance from pinpointer to target
/// </summary>
public void SetDistance(EntityUid uid, Distance distance, PinpointerComponent? pinpointer = null)
{
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<PinpointerComponent, ComponentGetState>(GetCompState);
}
if (!Resolve(uid, ref pinpointer))
return;
private void GetCompState(EntityUid uid, PinpointerComponent pinpointer, ref ComponentGetState args)
{
args.State = new PinpointerComponentState
{
IsActive = pinpointer.IsActive,
ArrowAngle = pinpointer.ArrowAngle,
DistanceToTarget = pinpointer.DistanceToTarget
};
}
if (distance == pinpointer.DistanceToTarget)
return;
/// <summary>
/// Manually set distance from pinpointer to target
/// </summary>
public void SetDistance(EntityUid uid, Distance distance, PinpointerComponent? pinpointer = null)
{
if (!Resolve(uid, ref pinpointer))
return;
pinpointer.DistanceToTarget = distance;
Dirty(pinpointer);
}
if (distance == pinpointer.DistanceToTarget)
return;
/// <summary>
/// Try to manually set pinpointer arrow direction.
/// If difference between current angle and new angle is smaller than
/// pinpointer precision, new value will be ignored and it will return false.
/// </summary>
public bool TrySetArrowAngle(EntityUid uid, Angle arrowAngle, PinpointerComponent? pinpointer = null)
{
if (!Resolve(uid, ref pinpointer))
return false;
pinpointer.DistanceToTarget = distance;
Dirty(pinpointer);
}
if (pinpointer.ArrowAngle.EqualsApprox(arrowAngle, pinpointer.Precision))
return false;
/// <summary>
/// Try to manually set pinpointer arrow direction.
/// If difference between current angle and new angle is smaller than
/// pinpointer precision, new value will be ignored and it will return false.
/// </summary>
public bool TrySetArrowAngle(EntityUid uid, Angle arrowAngle, PinpointerComponent? pinpointer = null)
{
if (!Resolve(uid, ref pinpointer))
return false;
pinpointer.ArrowAngle = arrowAngle;
Dirty(pinpointer);
if (pinpointer.ArrowAngle.EqualsApprox(arrowAngle, pinpointer.Precision))
return false;
return true;
}
pinpointer.ArrowAngle = arrowAngle;
Dirty(pinpointer);
/// <summary>
/// Activate/deactivate pinpointer screen. If it has target it will start tracking it.
/// </summary>
public void SetActive(EntityUid uid, bool isActive, PinpointerComponent? pinpointer = null)
{
if (!Resolve(uid, ref pinpointer))
return;
if (isActive == pinpointer.IsActive)
return;
return true;
}
/// <summary>
/// Activate/deactivate pinpointer screen. If it has target it will start tracking it.
/// </summary>
public void SetActive(EntityUid uid, bool isActive, PinpointerComponent? pinpointer = null)
{
if (!Resolve(uid, ref pinpointer))
return;
if (isActive == pinpointer.IsActive)
return;
pinpointer.IsActive = isActive;
Dirty(pinpointer);
}
/// <summary>
/// Toggle Pinpointer screen. If it has target it will start tracking it.
/// </summary>
/// <returns>True if pinpointer was activated, false otherwise</returns>
public bool TogglePinpointer(EntityUid uid, PinpointerComponent? pinpointer = null)
{
if (!Resolve(uid, ref pinpointer))
return false;
var isActive = !pinpointer.IsActive;
SetActive(uid, isActive, pinpointer);
return isActive;
}
pinpointer.IsActive = isActive;
Dirty(pinpointer);
}
}