diff --git a/Content.Client/GameObjects/Components/HUD/Inventory/ClientInventoryComponent.cs b/Content.Client/GameObjects/Components/HUD/Inventory/ClientInventoryComponent.cs index 655a37f7af..041f763cac 100644 --- a/Content.Client/GameObjects/Components/HUD/Inventory/ClientInventoryComponent.cs +++ b/Content.Client/GameObjects/Components/HUD/Inventory/ClientInventoryComponent.cs @@ -91,6 +91,14 @@ namespace Content.Client.GameObjects doneSlots.Add(slot); } + if (cast.HoverEntity != null) + { + var (slot, (entityUid, fits)) = cast.HoverEntity.Value; + var entity = Owner.EntityManager.GetEntity(entityUid); + + InterfaceController?.HoverInSlot(slot, entity, fits); + } + foreach (var slot in _slots.Keys.ToList()) { if (!doneSlots.Contains(slot)) @@ -171,6 +179,11 @@ namespace Content.Client.GameObjects SendNetworkMessage(equipmessage); } + public void SendHoverMessage(Slots slot) + { + SendNetworkMessage(new ClientInventoryMessage(slot, ClientInventoryUpdate.Hover)); + } + public void SendOpenStorageUIMessage(Slots slot) { SendNetworkMessage(new OpenSlotStorageUIMessage(slot)); diff --git a/Content.Client/GameObjects/Components/HUD/Inventory/HumanInventoryInterfaceController.cs b/Content.Client/GameObjects/Components/HUD/Inventory/HumanInventoryInterfaceController.cs index aeb779b0c0..01d94b822b 100644 --- a/Content.Client/GameObjects/Components/HUD/Inventory/HumanInventoryInterfaceController.cs +++ b/Content.Client/GameObjects/Components/HUD/Inventory/HumanInventoryInterfaceController.cs @@ -48,6 +48,7 @@ namespace Content.Client.GameObjects { button.OnPressed = (e) => AddToInventory(e, slot); button.OnStoragePressed = (e) => OpenStorage(e, slot); + button.OnHover = (e) => RequestItemHover(slot); _inventoryButtons.Add(slot, new List {button}); } @@ -58,7 +59,8 @@ namespace Content.Client.GameObjects variable = new ItemSlotButton(texture, storageTexture) { OnPressed = (e) => AddToInventory(e, slot), - OnStoragePressed = (e) => OpenStorage(e, slot) + OnStoragePressed = (e) => OpenStorage(e, slot), + OnHover = (e) => RequestItemHover(slot) }; _inventoryButtons[slot].Add(variable); } @@ -114,6 +116,21 @@ namespace Content.Client.GameObjects } } + public override void HoverInSlot(Slots slot, IEntity entity, bool fits) + { + base.HoverInSlot(slot, entity, fits); + + if (!_inventoryButtons.TryGetValue(slot, out var buttons)) + { + return; + } + + foreach (var button in buttons) + { + _itemSlotManager.HoverInSlot(button, entity, fits); + } + } + protected override void HandleInventoryKeybind(GUIBoundKeyEventArgs args, Slots slot) { if (!_inventoryButtons.TryGetValue(slot, out var buttons)) diff --git a/Content.Client/GameObjects/Components/HUD/Inventory/InventoryInterfaceController.cs b/Content.Client/GameObjects/Components/HUD/Inventory/InventoryInterfaceController.cs index 62237e09cf..091ca4d097 100644 --- a/Content.Client/GameObjects/Components/HUD/Inventory/InventoryInterfaceController.cs +++ b/Content.Client/GameObjects/Components/HUD/Inventory/InventoryInterfaceController.cs @@ -59,6 +59,10 @@ namespace Content.Client.GameObjects { } + public virtual void HoverInSlot(EquipmentSlotDefines.Slots slot, IEntity entity, bool fits) + { + } + public virtual void RemoveFromSlot(EquipmentSlotDefines.Slots slot) { } @@ -95,5 +99,10 @@ namespace Content.Client.GameObjects Owner.SendOpenStorageUIMessage(slot); } + + protected void RequestItemHover(EquipmentSlotDefines.Slots slot) + { + Owner.SendHoverMessage(slot); + } } } diff --git a/Content.Client/UserInterface/IItemSlotManager.cs b/Content.Client/UserInterface/IItemSlotManager.cs index 5e1d09365d..9c23325976 100644 --- a/Content.Client/UserInterface/IItemSlotManager.cs +++ b/Content.Client/UserInterface/IItemSlotManager.cs @@ -9,5 +9,6 @@ namespace Content.Client.UserInterface bool OnButtonPressed(GUIBoundKeyEventArgs args, IEntity item); void UpdateCooldown(ItemSlotButton cooldownTexture, IEntity entity); bool SetItemSlot(ItemSlotButton button, IEntity entity); + void HoverInSlot(ItemSlotButton button, IEntity entity, bool fits); } } diff --git a/Content.Client/UserInterface/ItemSlotButton.cs b/Content.Client/UserInterface/ItemSlotButton.cs index df70a8cdaa..cb68416c09 100644 --- a/Content.Client/UserInterface/ItemSlotButton.cs +++ b/Content.Client/UserInterface/ItemSlotButton.cs @@ -17,6 +17,10 @@ namespace Content.Client.UserInterface public Action OnPressed { get; set; } public Action OnStoragePressed { get; set; } + public Action OnHover { get; set; } + + public bool EntityHover { get; set; } = false; + public bool MouseIsHovering = false; public ItemSlotButton(Texture texture, Texture storageTexture) { @@ -56,6 +60,24 @@ namespace Content.Client.UserInterface StorageButton.OnPressed += OnStorageButtonPressed; + Button.OnMouseEntered += _ => + { + MouseIsHovering = true; + }; + Button.OnMouseEntered += OnButtonHover; + + Button.OnMouseExited += _ => + { + MouseIsHovering = false; + if (EntityHover) + { + SpriteView.Sprite?.Owner.Delete(); + EntityHover = false; + SpriteView.Sprite = null; + StorageButton.Visible = false; + } + }; + AddChild(CooldownDisplay = new CooldownGraphic { SizeFlagsHorizontal = SizeFlags.Fill, @@ -80,5 +102,10 @@ namespace Content.Client.UserInterface OnPressed?.Invoke(args.Event); } } + + private void OnButtonHover(GUIMouseHoverEventArgs args) + { + OnHover?.Invoke(args); + } } } diff --git a/Content.Client/UserInterface/ItemSlotManager.cs b/Content.Client/UserInterface/ItemSlotManager.cs index 5ddbc93fbc..3c0170af84 100644 --- a/Content.Client/UserInterface/ItemSlotManager.cs +++ b/Content.Client/UserInterface/ItemSlotManager.cs @@ -5,6 +5,7 @@ using Content.Client.GameObjects.EntitySystems; using Content.Client.Utility; using Content.Shared.GameObjects.Components.Items; using Content.Shared.Input; +using Robust.Client.GameObjects; using Robust.Client.GameObjects.EntitySystems; using Robust.Client.Graphics; using Robust.Client.Interfaces.GameObjects.Components; @@ -30,6 +31,7 @@ namespace Content.Client.UserInterface [Dependency] private readonly IGameTiming _gameTiming; [Dependency] private readonly IInputManager _inputManager; [Dependency] private readonly IEntitySystemManager _entitySystemManager; + [Dependency] private readonly IEntityManager _entityManager; [Dependency] private readonly IEyeManager _eyeManager; [Dependency] private readonly IMapManager _mapManager; #pragma warning restore 0649 @@ -45,6 +47,7 @@ namespace Content.Client.UserInterface { if (!entity.TryGetComponent(out ISpriteComponent sprite)) return false; + button.EntityHover = false; button.SpriteView.Sprite = sprite; button.StorageButton.Visible = entity.HasComponent(); } @@ -124,5 +127,31 @@ namespace Content.Client.UserInterface cooldownDisplay.Visible = false; } } + + public void HoverInSlot(ItemSlotButton button, IEntity entity, bool fits) + { + if (entity == null || !button.MouseIsHovering) + { + button.SpriteView.Sprite?.Owner.Delete(); + button.SpriteView.Sprite = null; + button.StorageButton.Visible = false; + return; + } + + if (!entity.HasComponent()) + { + return; + } + + // Set green / red overlay at 50% transparency + var hoverEntity = _entityManager.SpawnEntity("hoverentity", MapCoordinates.Nullspace); + var hoverSprite = hoverEntity.GetComponent(); + hoverSprite.CopyFrom(entity.GetComponent()); + hoverSprite.Color = fits ? new Color(0, 255, 0, 127) : new Color(255, 0, 0, 127); + + button.EntityHover = true; + button.SpriteView.Sprite = hoverSprite; + button.StorageButton.Visible = entity.HasComponent(); + } } } diff --git a/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs b/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs index 819d22bfd3..1c09c3bcf2 100644 --- a/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs +++ b/Content.Server/GameObjects/Components/GUI/InventoryComponent.cs @@ -36,6 +36,8 @@ namespace Content.Server.GameObjects [ViewVariables] private readonly Dictionary SlotContainers = new Dictionary(); + private KeyValuePair? HoverEntity; + public override void Initialize() { base.Initialize(); @@ -93,6 +95,11 @@ namespace Content.Server.GameObjects } public T GetSlotItem(Slots slot) where T : ItemComponent { + if (!SlotContainers.ContainsKey(slot)) + { + return null; + } + var containedEntity = SlotContainers[slot].ContainedEntity; if (containedEntity?.Deleted == true) { @@ -358,6 +365,20 @@ namespace Content.Server.GameObjects } break; } + case ClientInventoryUpdate.Hover: + { + var hands = Owner.GetComponent(); + var activeHand = hands.GetActiveHand; + if (activeHand != null && GetSlotItem(msg.Inventoryslot) == null) + { + var canEquip = CanEquip(msg.Inventoryslot, activeHand, out var reason); + HoverEntity = new KeyValuePair(msg.Inventoryslot, (activeHand.Owner.Uid, canEquip)); + + Dirty(); + } + + break; + } } } @@ -417,7 +438,11 @@ namespace Content.Server.GameObjects list.Add(new KeyValuePair(slot, container.ContainedEntity.Uid)); } } - return new InventoryComponentState(list); + + var hover = HoverEntity; + HoverEntity = null; + + return new InventoryComponentState(list, hover); } void IExAct.OnExplosion(ExplosionEventArgs eventArgs) diff --git a/Content.Shared/GameObjects/Components/Inventory/SharedInventoryComponent.cs b/Content.Shared/GameObjects/Components/Inventory/SharedInventoryComponent.cs index cf49d55e09..032385d0d4 100644 --- a/Content.Shared/GameObjects/Components/Inventory/SharedInventoryComponent.cs +++ b/Content.Shared/GameObjects/Components/Inventory/SharedInventoryComponent.cs @@ -51,10 +51,12 @@ namespace Content.Shared.GameObjects protected class InventoryComponentState : ComponentState { public List> Entities { get; } + public KeyValuePair? HoverEntity { get; } - public InventoryComponentState(List> entities) : base(ContentNetIDs.STORAGE) + public InventoryComponentState(List> entities, KeyValuePair? hoverEntity = null) : base(ContentNetIDs.STORAGE) { Entities = entities; + HoverEntity = hoverEntity; } } @@ -74,7 +76,8 @@ namespace Content.Shared.GameObjects public enum ClientInventoryUpdate { Equip = 0, - Use = 1 + Use = 1, + Hover = 2 } } diff --git a/Resources/Prototypes/Entities/Effects/Markers/hover_entity.yml b/Resources/Prototypes/Entities/Effects/Markers/hover_entity.yml new file mode 100644 index 0000000000..f3eb6bc998 --- /dev/null +++ b/Resources/Prototypes/Entities/Effects/Markers/hover_entity.yml @@ -0,0 +1,7 @@ +- type: entity + name: hover entity + id: hoverentity + components: + - type: Sprite + layers: + - shader: unshaded