using System.Numerics;
+using Content.Client.Sprite;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Utility;
private EntityQuery<ClickableComponent> _clickableQuery;
private EntityQuery<TransformComponent> _xformQuery;
+ private EntityQuery<FadingSpriteComponent> _fadingSpriteQuery;
public override void Initialize()
{
base.Initialize();
_clickableQuery = GetEntityQuery<ClickableComponent>();
_xformQuery = GetEntityQuery<TransformComponent>();
+ _fadingSpriteQuery = GetEntityQuery<FadingSpriteComponent>();
}
/// <summary>
/// The draw depth for the sprite that captured the click.
/// </param>
/// <returns>True if the click worked, false otherwise.</returns>
- public bool CheckClick(Entity<ClickableComponent?, SpriteComponent, TransformComponent?> entity, Vector2 worldPos, IEye eye, out int drawDepth, out uint renderOrder, out float bottom)
+ public bool CheckClick(Entity<ClickableComponent?, SpriteComponent, TransformComponent?, FadingSpriteComponent?> entity, Vector2 worldPos, IEye eye, bool excludeFaded, out int drawDepth, out uint renderOrder, out float bottom)
{
if (!_clickableQuery.Resolve(entity.Owner, ref entity.Comp1, false))
{
return false;
}
+ if (excludeFaded && _fadingSpriteQuery.Resolve(entity.Owner, ref entity.Comp4, false))
+ {
+ drawDepth = default;
+ renderOrder = default;
+ bottom = default;
+ return false;
+ }
+
var sprite = entity.Comp2;
var transform = entity.Comp3;
return first.IsValid() ? first : null;
}
- public IEnumerable<EntityUid> GetClickableEntities(EntityCoordinates coordinates)
+ public IEnumerable<EntityUid> GetClickableEntities(EntityCoordinates coordinates, bool excludeFaded = true)
{
var transformSystem = _entitySystemManager.GetEntitySystem<SharedTransformSystem>();
- return GetClickableEntities(transformSystem.ToMapCoordinates(coordinates));
+ return GetClickableEntities(transformSystem.ToMapCoordinates(coordinates), excludeFaded);
}
- public IEnumerable<EntityUid> GetClickableEntities(MapCoordinates coordinates)
+ public IEnumerable<EntityUid> GetClickableEntities(MapCoordinates coordinates, bool excludeFaded = true)
{
- return GetClickableEntities(coordinates, _eyeManager.CurrentEye);
+ return GetClickableEntities(coordinates, _eyeManager.CurrentEye, excludeFaded);
}
- public IEnumerable<EntityUid> GetClickableEntities(MapCoordinates coordinates, IEye? eye)
+ public IEnumerable<EntityUid> GetClickableEntities(MapCoordinates coordinates, IEye? eye, bool excludeFaded = true)
{
/*
* TODO:
foreach (var entity in entities)
{
if (clickQuery.TryGetComponent(entity.Uid, out var component) &&
- clickables.CheckClick((entity.Uid, component, entity.Component, entity.Transform), coordinates.Position, eye, out var drawDepthClicked, out var renderOrder, out var bottom))
+ clickables.CheckClick((entity.Uid, component, entity.Component, entity.Transform), coordinates.Position, eye, excludeFaded, out var drawDepthClicked, out var renderOrder, out var bottom))
{
foundEntities.Add((entity.Uid, drawDepthClicked, renderOrder, bottom));
}
+using System.Numerics;
using Content.Client.Gameplay;
using Content.Shared.Sprite;
using Robust.Client.GameObjects;
+using Robust.Client.Input;
using Robust.Client.Player;
using Robust.Client.State;
+using Robust.Client.UserInterface.CustomControls;
+using Robust.Client.UserInterface;
+using Robust.Shared.Map;
+using Robust.Shared.Physics.Systems;
using Robust.Shared.Physics;
namespace Content.Client.Sprite;
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IStateManager _stateManager = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
+ [Dependency] private readonly IUserInterfaceManager _uiManager = default!;
+ [Dependency] private readonly IInputManager _inputManager = default!;
+ [Dependency] private readonly SharedPhysicsSystem _physics = default!;
private readonly HashSet<FadingSpriteComponent> _comps = new();
private EntityQuery<SpriteFadeComponent> _fadeQuery;
private EntityQuery<FadingSpriteComponent> _fadingQuery;
+ /// <summary>
+ /// Radius of the mouse point for the intersection test
+ /// </summary>
+ private static Vector2 MouseRadius = new Vector2(10f * float.Epsilon, 10f * float.Epsilon);
+
private const float TargetAlpha = 0.4f;
private const float ChangeRate = 1f;
sprite.Color = sprite.Color.WithAlpha(component.OriginalAlpha);
}
- public override void FrameUpdate(float frameTime)
+ /// <summary>
+ /// Adds sprites to the fade set, and brings their alpha downwards
+ /// </summary>
+ private void FadeIn(float change)
{
- base.FrameUpdate(frameTime);
-
var player = _playerManager.LocalEntity;
- var change = ChangeRate * frameTime;
+ // ExcludeBoundingBox is set if we don't want to fade this sprite within the collision bounding boxes for the given POI
+ var pointsOfInterest = new List<(MapCoordinates Point, bool ExcludeBoundingBox)>();
- if (TryComp(player, out TransformComponent? playerXform) &&
- _stateManager.CurrentState is GameplayState state &&
- _spriteQuery.TryGetComponent(player, out var playerSprite))
+ if (_uiManager.CurrentlyHovered is IViewportControl vp
+ && _inputManager.MouseScreenPosition.IsValid)
{
- var mapPos = _transform.GetMapCoordinates(_playerManager.LocalEntity!.Value, xform: playerXform);
-
- // Also want to handle large entities even if they may not be clickable.
- foreach (var ent in state.GetClickableEntities(mapPos))
- {
- if (ent == player ||
- !_fadeQuery.HasComponent(ent) ||
- !_spriteQuery.TryGetComponent(ent, out var sprite) ||
- sprite.DrawDepth < playerSprite.DrawDepth)
- {
- continue;
- }
-
- if (!_fadingQuery.TryComp(ent, out var fading))
- {
- fading = AddComp<FadingSpriteComponent>(ent);
- fading.OriginalAlpha = sprite.Color.A;
- }
+ pointsOfInterest.Add((vp.PixelToMap(_inputManager.MouseScreenPosition.Position), true));
+ }
- _comps.Add(fading);
- var newColor = Math.Max(sprite.Color.A - change, TargetAlpha);
+ if (TryComp(player, out TransformComponent? playerXform))
+ {
+ pointsOfInterest.Add((_transform.GetMapCoordinates(_playerManager.LocalEntity!.Value, xform: playerXform), false));
+ }
- if (!sprite.Color.A.Equals(newColor))
+ if (_stateManager.CurrentState is GameplayState state && _spriteQuery.TryGetComponent(player, out var playerSprite))
+ {
+ foreach (var (mapPos, excludeBB) in pointsOfInterest)
+ {
+ // Also want to handle large entities even if they may not be clickable.
+ foreach (var ent in state.GetClickableEntities(mapPos, excludeFaded: false))
{
- sprite.Color = sprite.Color.WithAlpha(newColor);
+ if (ent == player ||
+ !_fadeQuery.HasComponent(ent) ||
+ !_spriteQuery.TryGetComponent(ent, out var sprite) ||
+ sprite.DrawDepth < playerSprite.DrawDepth)
+ {
+ continue;
+ }
+
+ if (excludeBB)
+ {
+ var test = new Box2Rotated(mapPos.Position - MouseRadius, mapPos.Position + MouseRadius);
+ var collided = false;
+ foreach (var fixture in _physics.GetCollidingEntities(mapPos.MapId, test))
+ {
+ if (fixture.Owner == ent)
+ {
+ collided = true;
+ break;
+ }
+ }
+ if (collided)
+ {
+ break;
+ }
+ }
+
+ if (!_fadingQuery.TryComp(ent, out var fading))
+ {
+ fading = AddComp<FadingSpriteComponent>(ent);
+ fading.OriginalAlpha = sprite.Color.A;
+ }
+
+ _comps.Add(fading);
+ var newColor = Math.Max(sprite.Color.A - change, TargetAlpha);
+
+ if (!sprite.Color.A.Equals(newColor))
+ {
+ sprite.Color = sprite.Color.WithAlpha(newColor);
+ }
}
}
}
+ }
+ /// <summary>
+ /// Bring sprites back up to their original alpha if they aren't in the fade set, and removes their fade component when done
+ /// </summary>
+ private void FadeOut(float change)
+ {
var query = AllEntityQuery<FadingSpriteComponent>();
while (query.MoveNext(out var uid, out var comp))
{
RemCompDeferred<FadingSpriteComponent>(uid);
}
}
+ }
+
+ public override void FrameUpdate(float frameTime)
+ {
+ base.FrameUpdate(frameTime);
+
+ var change = ChangeRate * frameTime;
+
+ FadeIn(change);
+ FadeOut(change);
_comps.Clear();
}