Skip to content

Commit

Permalink
Merge remote-tracking branch 'wizard/master'
Browse files Browse the repository at this point in the history
  • Loading branch information
Rxup committed Feb 28, 2024
2 parents 931e534 + 1c015d1 commit 5377414
Show file tree
Hide file tree
Showing 169 changed files with 554 additions and 668 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public sealed partial class SpawnExplosionWindow : DefaultWindow
[Dependency] private readonly IPlayerManager _playerManager = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntityManager _entMan = default!;
private SharedTransformSystem? _xformSystem = null;


private readonly SpawnExplosionEui _eui;
Expand Down Expand Up @@ -103,13 +102,9 @@ private void SetLocation()
if (!_entMan.TryGetComponent(_playerManager.LocalEntity, out TransformComponent? transform))
return;

_xformSystem ??= _entMan.SystemOrNull<SharedTransformSystem>();
if (_xformSystem is null)
return;

_pausePreview = true;
MapOptions.Select(_mapData.IndexOf(transform.MapID));
(MapX.Value, MapY.Value) = _xformSystem.GetWorldPosition(transform);
(MapX.Value, MapY.Value) = transform.MapPosition.Position;
_pausePreview = false;

UpdatePreview();
Expand Down
10 changes: 3 additions & 7 deletions Content.Client/Atmos/Overlays/GasTileOverlay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ public sealed class GasTileOverlay : Overlay
{
private readonly IEntityManager _entManager;
private readonly IMapManager _mapManager;
private readonly SharedTransformSystem _xformSystem;

public override OverlaySpace Space => OverlaySpace.WorldSpaceEntities;
private readonly ShaderInstance _shader;
Expand Down Expand Up @@ -52,7 +51,6 @@ public GasTileOverlay(GasTileOverlaySystem system, IEntityManager entManager, IR
{
_entManager = entManager;
_mapManager = IoCManager.Resolve<IMapManager>();
_xformSystem = _entManager.System<SharedTransformSystem>();
_shader = protoMan.Index<ShaderPrototype>("unshaded").Instance();
ZIndex = GasOverlayZIndex;

Expand Down Expand Up @@ -158,8 +156,7 @@ protected override void Draw(in OverlayDrawArgs args)
_fireFrameCounter,
_shader,
overlayQuery,
xformQuery,
_xformSystem);
xformQuery);

var mapUid = _mapManager.GetMapEntityId(args.MapId);

Expand Down Expand Up @@ -197,16 +194,15 @@ protected override void Draw(in OverlayDrawArgs args)
int[] fireFrameCounter,
ShaderInstance shader,
EntityQuery<GasTileOverlayComponent> overlayQuery,
EntityQuery<TransformComponent> xformQuery,
SharedTransformSystem xformSystem) state) =>
EntityQuery<TransformComponent> xformQuery) state) =>
{
if (!state.overlayQuery.TryGetComponent(uid, out var comp) ||
!state.xformQuery.TryGetComponent(uid, out var gridXform))
{
return true;
}

var (_, _, worldMatrix, invMatrix) = state.xformSystem.GetWorldPositionRotationMatrixWithInv(gridXform);
var (_, _, worldMatrix, invMatrix) = gridXform.GetWorldPositionRotationMatrixWithInv();
state.drawHandle.SetTransform(worldMatrix);
var floatBounds = invMatrix.TransformBox(in state.WorldBounds).Enlarged(grid.TileSize);
var localBounds = new Box2i(
Expand Down
2 changes: 1 addition & 1 deletion Content.Client/CardboardBox/CardboardBoxSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ private void OnBoxEffect(PlayBoxEffectMessage msg)
if (!xformQuery.TryGetComponent(source, out var xform))
return;

var sourcePos = _transform.GetMapCoordinates((source, xform));
var sourcePos = _transform.GetMapCoordinates(source, xform);

//Any mob that can move should be surprised?
//God mind rework needs to come faster so it can just check for mind
Expand Down
4 changes: 1 addition & 3 deletions Content.Client/Chat/UI/SpeechBubble.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ public abstract class SpeechBubble : Control
{
[Dependency] private readonly IEyeManager _eyeManager = default!;
[Dependency] private readonly IEntityManager _entityManager = default!;
[Dependency] private readonly SharedTransformSystem _xformSystem = default!;
[Dependency] protected readonly IConfigurationManager ConfigManager = default!;

public enum SpeechType : byte
Expand Down Expand Up @@ -83,7 +82,6 @@ public static SpeechBubble CreateSpeechBubble(SpeechType type, ChatMessage messa
public SpeechBubble(ChatMessage message, EntityUid senderEntity, string speechStyleClass, Color? fontColor = null)
{
IoCManager.InjectDependencies(this);
_xformSystem = _entityManager.System<SharedTransformSystem>();
_senderEntity = senderEntity;

// Use text clipping so new messages don't overlap old ones being pushed up.
Expand Down Expand Up @@ -142,7 +140,7 @@ protected override void FrameUpdate(FrameEventArgs args)
}

var offset = (-_eyeManager.CurrentEye.Rotation).ToWorldVec() * -EntityVerticalOffset;
var worldPos = _xformSystem.GetWorldPosition(xform) + offset;
var worldPos = xform.WorldPosition + offset;

var lowerCenter = _eyeManager.WorldToScreen(worldPos) / UIScale;
var screenPos = lowerCenter - new Vector2(ContentSize.X / 2, ContentSize.Y + _verticalOffsetAchieved);
Expand Down
162 changes: 140 additions & 22 deletions Content.Client/Clickable/ClickableComponent.cs
Original file line number Diff line number Diff line change
@@ -1,27 +1,145 @@
namespace Content.Client.Clickable;
using System.Numerics;
using Robust.Client.GameObjects;
using Robust.Client.Graphics;
using Robust.Client.Utility;
using Robust.Shared.Graphics;
using static Robust.Client.GameObjects.SpriteComponent;
using Direction = Robust.Shared.Maths.Direction;

/// <summary>
/// Makes it possible to click the associated entity.
/// </summary>
[RegisterComponent]
public sealed partial class ClickableComponent : Component
namespace Content.Client.Clickable
{
/// <summary>
/// A set of AABBs used as an approximate check for whether a click could hit this entity.
/// </summary>
[DataField("bounds")]
public DirBoundData? Bounds;

/// <summary>
/// A set of AABBs associated with the cardinal directions used for approximate click intersection calculations.
/// </summary>
[DataDefinition]
public sealed partial class DirBoundData
[RegisterComponent]
public sealed partial class ClickableComponent : Component
{
[DataField("all")] public Box2 All;
[DataField("north")] public Box2 North;
[DataField("south")] public Box2 South;
[DataField("east")] public Box2 East;
[DataField("west")] public Box2 West;
[Dependency] private readonly IClickMapManager _clickMapManager = default!;

[DataField("bounds")] public DirBoundData? Bounds;

/// <summary>
/// Used to check whether a click worked. Will first check if the click falls inside of some explicit bounding
/// boxes (see <see cref="Bounds"/>). If that fails, attempts to use automatically generated click maps.
/// </summary>
/// <param name="worldPos">The world position that was clicked.</param>
/// <param name="drawDepth">
/// The draw depth for the sprite that captured the click.
/// </param>
/// <returns>True if the click worked, false otherwise.</returns>
public bool CheckClick(SpriteComponent sprite, TransformComponent transform, EntityQuery<TransformComponent> xformQuery, Vector2 worldPos, IEye eye, out int drawDepth, out uint renderOrder, out float bottom)
{
if (!sprite.Visible)
{
drawDepth = default;
renderOrder = default;
bottom = default;
return false;
}

drawDepth = sprite.DrawDepth;
renderOrder = sprite.RenderOrder;
var (spritePos, spriteRot) = transform.GetWorldPositionRotation(xformQuery);
var spriteBB = sprite.CalculateRotatedBoundingBox(spritePos, spriteRot, eye.Rotation);
bottom = Matrix3.CreateRotation(eye.Rotation).TransformBox(spriteBB).Bottom;

var invSpriteMatrix = Matrix3.Invert(sprite.GetLocalMatrix());

// This should have been the rotation of the sprite relative to the screen, but this is not the case with no-rot or directional sprites.
var relativeRotation = (spriteRot + eye.Rotation).Reduced().FlipPositive();

Angle cardinalSnapping = sprite.SnapCardinals ? relativeRotation.GetCardinalDir().ToAngle() : Angle.Zero;

// First we get `localPos`, the clicked location in the sprite-coordinate frame.
var entityXform = Matrix3.CreateInverseTransform(transform.WorldPosition, sprite.NoRotation ? -eye.Rotation : spriteRot - cardinalSnapping);
var localPos = invSpriteMatrix.Transform(entityXform.Transform(worldPos));

// Check explicitly defined click-able bounds
if (CheckDirBound(sprite, relativeRotation, localPos))
return true;

// Next check each individual sprite layer using automatically computed click maps.
foreach (var spriteLayer in sprite.AllLayers)
{
if (!spriteLayer.Visible || spriteLayer is not Layer layer)
continue;

// Check the layer's texture, if it has one
if (layer.Texture != null)
{
// Convert to image coordinates
var imagePos = (Vector2i) (localPos * EyeManager.PixelsPerMeter * new Vector2(1, -1) + layer.Texture.Size / 2f);

if (_clickMapManager.IsOccluding(layer.Texture, imagePos))
return true;
}

// Either we weren't clicking on the texture, or there wasn't one. In which case: check the RSI next
if (layer.ActualRsi is not { } rsi || !rsi.TryGetState(layer.State, out var rsiState))
continue;

var dir = Layer.GetDirection(rsiState.RsiDirections, relativeRotation);

// convert to layer-local coordinates
layer.GetLayerDrawMatrix(dir, out var matrix);
var inverseMatrix = Matrix3.Invert(matrix);
var layerLocal = inverseMatrix.Transform(localPos);

// Convert to image coordinates
var layerImagePos = (Vector2i) (layerLocal * EyeManager.PixelsPerMeter * new Vector2(1, -1) + rsiState.Size / 2f);

// Next, to get the right click map we need the "direction" of this layer that is actually being used to draw the sprite on the screen.
// This **can** differ from the dir defined before, but can also just be the same.
if (sprite.EnableDirectionOverride)
dir = sprite.DirectionOverride.Convert(rsiState.RsiDirections);
dir = dir.OffsetRsiDir(layer.DirOffset);

if (_clickMapManager.IsOccluding(layer.ActualRsi!, layer.State, dir, layer.AnimationFrame, layerImagePos))
return true;
}

drawDepth = default;
renderOrder = default;
bottom = default;
return false;
}

public bool CheckDirBound(SpriteComponent sprite, Angle relativeRotation, Vector2 localPos)
{
if (Bounds == null)
return false;

// These explicit bounds only work for either 1 or 4 directional sprites.

// This would be the orientation of a 4-directional sprite.
var direction = relativeRotation.GetCardinalDir();

var modLocalPos = sprite.NoRotation
? localPos
: direction.ToAngle().RotateVec(localPos);

// First, check the bounding box that is valid for all orientations
if (Bounds.All.Contains(modLocalPos))
return true;

// Next, get and check the appropriate bounding box for the current sprite orientation
var boundsForDir = (sprite.EnableDirectionOverride ? sprite.DirectionOverride : direction) switch
{
Direction.East => Bounds.East,
Direction.North => Bounds.North,
Direction.South => Bounds.South,
Direction.West => Bounds.West,
_ => throw new InvalidOperationException()
};

return boundsForDir.Contains(modLocalPos);
}

[DataDefinition]
public sealed partial class DirBoundData
{
[DataField("all")] public Box2 All;
[DataField("north")] public Box2 North;
[DataField("south")] public Box2 South;
[DataField("east")] public Box2 East;
[DataField("west")] public Box2 West;
}
}
}
Loading

0 comments on commit 5377414

Please sign in to comment.