diff --git a/Content.Client/Options/UI/Tabs/GraphicsTab.xaml b/Content.Client/Options/UI/Tabs/GraphicsTab.xaml index 3de59cf5dc..e3d45c19da 100644 --- a/Content.Client/Options/UI/Tabs/GraphicsTab.xaml +++ b/Content.Client/Options/UI/Tabs/GraphicsTab.xaml @@ -22,6 +22,7 @@ + diff --git a/Content.Client/Options/UI/Tabs/GraphicsTab.xaml.cs b/Content.Client/Options/UI/Tabs/GraphicsTab.xaml.cs index 9d7e500651..7a11885a89 100644 --- a/Content.Client/Options/UI/Tabs/GraphicsTab.xaml.cs +++ b/Content.Client/Options/UI/Tabs/GraphicsTab.xaml.cs @@ -103,6 +103,8 @@ namespace Content.Client.Options.UI.Tabs ShowHeldItemCheckBox.OnToggled += OnCheckBoxToggled; ShowCombatModeIndicatorsCheckBox.OnToggled += OnCheckBoxToggled; + OpaqueStorageWindowCheckBox.OnToggled += OnCheckBoxToggled; + ShowLoocAboveHeadCheckBox.OnToggled += OnCheckBoxToggled; ShowLoocAboveHeadCheckBox.OnToggled += OnCheckBoxToggled; FancySpeechBubblesCheckBox.OnToggled += OnCheckBoxToggled; FancyNameBackgroundsCheckBox.OnToggled += OnCheckBoxToggled; @@ -124,6 +126,7 @@ namespace Content.Client.Options.UI.Tabs FpsCounterCheckBox.Pressed = _cfg.GetCVar(CCVars.HudFpsCounterVisible); ShowHeldItemCheckBox.Pressed = _cfg.GetCVar(CCVars.HudHeldItemShow); ShowCombatModeIndicatorsCheckBox.Pressed = _cfg.GetCVar(CCVars.CombatModeIndicatorsPointShow); + OpaqueStorageWindowCheckBox.Pressed = _cfg.GetCVar(CCVars.OpaqueStorageWindow); ShowLoocAboveHeadCheckBox.Pressed = _cfg.GetCVar(CCVars.LoocAboveHeadShow); FancySpeechBubblesCheckBox.Pressed = _cfg.GetCVar(CCVars.ChatEnableFancyBubbles); FancyNameBackgroundsCheckBox.Pressed = _cfg.GetCVar(CCVars.ChatFancyNameBackground); @@ -174,6 +177,7 @@ namespace Content.Client.Options.UI.Tabs _cfg.SetCVar(CCVars.ParallaxLowQuality, ParallaxLowQualityCheckBox.Pressed); _cfg.SetCVar(CCVars.HudHeldItemShow, ShowHeldItemCheckBox.Pressed); _cfg.SetCVar(CCVars.CombatModeIndicatorsPointShow, ShowCombatModeIndicatorsCheckBox.Pressed); + _cfg.SetCVar(CCVars.OpaqueStorageWindow, OpaqueStorageWindowCheckBox.Pressed); _cfg.SetCVar(CCVars.LoocAboveHeadShow, ShowLoocAboveHeadCheckBox.Pressed); _cfg.SetCVar(CCVars.ChatEnableFancyBubbles, FancySpeechBubblesCheckBox.Pressed); _cfg.SetCVar(CCVars.ChatFancyNameBackground, FancyNameBackgroundsCheckBox.Pressed); @@ -214,6 +218,7 @@ namespace Content.Client.Options.UI.Tabs var isPLQSame = ParallaxLowQualityCheckBox.Pressed == _cfg.GetCVar(CCVars.ParallaxLowQuality); var isShowHeldItemSame = ShowHeldItemCheckBox.Pressed == _cfg.GetCVar(CCVars.HudHeldItemShow); var isCombatModeIndicatorsSame = ShowCombatModeIndicatorsCheckBox.Pressed == _cfg.GetCVar(CCVars.CombatModeIndicatorsPointShow); + var isOpaqueStorageWindow = OpaqueStorageWindowCheckBox.Pressed == _cfg.GetCVar(CCVars.OpaqueStorageWindow); var isLoocShowSame = ShowLoocAboveHeadCheckBox.Pressed == _cfg.GetCVar(CCVars.LoocAboveHeadShow); var isFancyChatSame = FancySpeechBubblesCheckBox.Pressed == _cfg.GetCVar(CCVars.ChatEnableFancyBubbles); var isFancyBackgroundSame = FancyNameBackgroundsCheckBox.Pressed == _cfg.GetCVar(CCVars.ChatFancyNameBackground); @@ -233,6 +238,7 @@ namespace Content.Client.Options.UI.Tabs isHudThemeSame && isShowHeldItemSame && isCombatModeIndicatorsSame && + isOpaqueStorageWindow && isLoocShowSame && isFancyChatSame && isFancyBackgroundSame && diff --git a/Content.Client/UserInterface/Systems/Storage/Controls/ItemGridPiece.cs b/Content.Client/UserInterface/Systems/Storage/Controls/ItemGridPiece.cs index 830d59bd90..e4f3506baa 100644 --- a/Content.Client/UserInterface/Systems/Storage/Controls/ItemGridPiece.cs +++ b/Content.Client/UserInterface/Systems/Storage/Controls/ItemGridPiece.cs @@ -1,9 +1,7 @@ -using System.Linq; using System.Numerics; using Content.Client.Items.Systems; using Content.Shared.Item; using Content.Shared.Storage; -using Content.Shared.Storage.EntitySystems; using Robust.Client.GameObjects; using Robust.Client.Graphics; using Robust.Client.UserInterface; @@ -12,8 +10,7 @@ namespace Content.Client.UserInterface.Systems.Storage.Controls; public sealed class ItemGridPiece : Control { - private readonly ItemSystem _itemSystem; - private readonly SpriteSystem _spriteSystem; + private readonly IEntityManager _entityManager; private readonly StorageUIController _storageController; private readonly List<(Texture, Vector2)> _texturesPositions = new(); @@ -49,8 +46,7 @@ public sealed class ItemGridPiece : Control { IoCManager.InjectDependencies(this); - _itemSystem = entityManager.System(); - _spriteSystem = entityManager.System(); + _entityManager = entityManager; _storageController = UserInterfaceManager.GetUIController(); Entity = entity.Owner; @@ -81,10 +77,17 @@ public sealed class ItemGridPiece : Control { base.Draw(handle); + // really just an "oh shit" catch. + if (!_entityManager.EntityExists(Entity)) + { + Dispose(); + return; + } + if (_storageController.IsDragging && _storageController.CurrentlyDragging == this) return; - var adjustedShape = _itemSystem.GetAdjustedItemShape((Entity, null), Location.Rotation, Vector2i.Zero); + var adjustedShape = _entityManager.System().GetAdjustedItemShape((Entity, null), Location.Rotation, Vector2i.Zero); var boundingGrid = adjustedShape.GetBoundingBox(); var size = _centerTexture!.Size * 2 * UIScale; @@ -130,7 +133,7 @@ public sealed class ItemGridPiece : Control var iconOffset = new Vector2((boundingGrid.Width + 1) * size.X , (boundingGrid.Height + 1) * size.Y); - _spriteSystem.ForceUpdate(Entity); + _entityManager.System().ForceUpdate(Entity); handle.DrawEntity(Entity, PixelPosition + iconOffset, Vector2.One * 2 * UIScale, diff --git a/Content.Client/UserInterface/Systems/Storage/Controls/StorageContainer.cs b/Content.Client/UserInterface/Systems/Storage/Controls/StorageContainer.cs index 12bce74352..ba19d2aa90 100644 --- a/Content.Client/UserInterface/Systems/Storage/Controls/StorageContainer.cs +++ b/Content.Client/UserInterface/Systems/Storage/Controls/StorageContainer.cs @@ -34,6 +34,10 @@ public sealed class StorageContainer : BaseWindow private Texture? _emptyTexture; private readonly string _blockedTexturePath = "Storage/tile_blocked"; private Texture? _blockedTexture; + private readonly string _emptyOpaqueTexturePath = "Storage/tile_empty_opaque"; + private Texture? _emptyOpaqueTexture; + private readonly string _blockedOpaqueTexturePath = "Storage/tile_blocked_opaque"; + private Texture? _blockedOpaqueTexture; private readonly string _exitTexturePath = "Storage/exit"; private Texture? _exitTexture; private readonly string _backTexturePath = "Storage/back"; @@ -109,6 +113,8 @@ public sealed class StorageContainer : BaseWindow _emptyTexture = Theme.ResolveTextureOrNull(_emptyTexturePath)?.Texture; _blockedTexture = Theme.ResolveTextureOrNull(_blockedTexturePath)?.Texture; + _emptyOpaqueTexture = Theme.ResolveTextureOrNull(_emptyOpaqueTexturePath)?.Texture; + _blockedOpaqueTexture = Theme.ResolveTextureOrNull(_blockedOpaqueTexturePath)?.Texture; _exitTexture = Theme.ResolveTextureOrNull(_exitTexturePath)?.Texture; _backTexture = Theme.ResolveTextureOrNull(_backTexturePath)?.Texture; _sidebarTopTexture = Theme.ResolveTextureOrNull(_sidebarTopTexturePath)?.Texture; @@ -124,35 +130,17 @@ public sealed class StorageContainer : BaseWindow if (entity == null) return; - BuildGridRepresentation(entity.Value); + BuildGridRepresentation(); } - private void BuildGridRepresentation(Entity entity) + private void BuildGridRepresentation() { - var comp = entity.Comp; - if (!comp.Grid.Any()) + if (!_entity.TryGetComponent(StorageEntity, out var comp) || !comp.Grid.Any()) return; var boundingGrid = comp.Grid.GetBoundingBox(); - _backgroundGrid.Children.Clear(); - _backgroundGrid.Rows = boundingGrid.Height + 1; - _backgroundGrid.Columns = boundingGrid.Width + 1; - for (var y = boundingGrid.Bottom; y <= boundingGrid.Top; y++) - { - for (var x = boundingGrid.Left; x <= boundingGrid.Right; x++) - { - var texture = comp.Grid.Contains(x, y) - ? _emptyTexture - : _blockedTexture; - - _backgroundGrid.AddChild(new TextureRect - { - Texture = texture, - TextureScale = new Vector2(2, 2) - }); - } - } + BuildBackground(); #region Sidebar _sidebar.Children.Clear(); @@ -209,6 +197,40 @@ public sealed class StorageContainer : BaseWindow BuildItemPieces(); } + public void BuildBackground() + { + if (!_entity.TryGetComponent(StorageEntity, out var comp) || !comp.Grid.Any()) + return; + + var boundingGrid = comp.Grid.GetBoundingBox(); + + var emptyTexture = _storageController.OpaqueStorageWindow + ? _emptyOpaqueTexture + : _emptyTexture; + var blockedTexture = _storageController.OpaqueStorageWindow + ? _blockedOpaqueTexture + : _blockedTexture; + + _backgroundGrid.Children.Clear(); + _backgroundGrid.Rows = boundingGrid.Height + 1; + _backgroundGrid.Columns = boundingGrid.Width + 1; + for (var y = boundingGrid.Bottom; y <= boundingGrid.Top; y++) + { + for (var x = boundingGrid.Left; x <= boundingGrid.Right; x++) + { + var texture = comp.Grid.Contains(x, y) + ? emptyTexture + : blockedTexture; + + _backgroundGrid.AddChild(new TextureRect + { + Texture = texture, + TextureScale = new Vector2(2, 2) + }); + } + } + } + public void BuildItemPieces() { if (!_entity.TryGetComponent(StorageEntity, out var storageComp)) @@ -320,7 +342,7 @@ public sealed class StorageContainer : BaseWindow origin, currentLocation.Rotation); - var validColor = usingInHand ? Color.Goldenrod : Color.Green; + var validColor = usingInHand ? Color.Goldenrod : Color.FromHex("#1E8000"); for (var y = itemBounding.Bottom; y <= itemBounding.Top; y++) { @@ -328,7 +350,7 @@ public sealed class StorageContainer : BaseWindow { if (TryGetBackgroundCell(x, y, out var cell) && itemShape.Contains(x, y)) { - cell.ModulateSelfOverride = validLocation ? validColor : Color.Red; + cell.ModulateSelfOverride = validLocation ? validColor : Color.FromHex("#B40046"); } } } diff --git a/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs b/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs index d3bbd826ba..a08dae1dd7 100644 --- a/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs +++ b/Content.Client/UserInterface/Systems/Storage/StorageUIController.cs @@ -38,6 +38,7 @@ public sealed class StorageUIController : UIController, IOnSystemChanged _menuDragHelper.IsDragging; public ItemGridPiece? CurrentlyDragging => _menuDragHelper.Dragged; @@ -52,6 +53,7 @@ public sealed class StorageUIController : UIController, IOnSystemChanged _ui.WindowRoot.Width || + _lastContainerPosition.Value.Y > _ui.WindowRoot.Height)) { _container.OpenCenteredAt(new Vector2(0.5f, 0.75f)); } @@ -88,8 +96,11 @@ public sealed class StorageUIController : UIController, IOnSystemChanged(_container.StorageEntity, out var comp)) + OnStorageOrderChanged((_container.StorageEntity.Value, comp)); + } + + private void OnOpaqueWindowChanged(bool obj) + { + if (OpaqueStorageWindow == obj) + return; + OpaqueStorageWindow = obj; + _container?.BuildBackground(); } /// One might ask, Hey Emo, why are you parsing raw keyboard input just to rotate a rectangle? @@ -321,7 +344,7 @@ public sealed class StorageUIController : UIController, IOnSystemChanged ToggleWalk = CVarDef.Create("control.toggle_walk", false, CVar.CLIENTONLY | CVar.ARCHIVE); + /* + * STORAGE + */ + /// /// Whether or not the storage UI is static and bound to the hotbar, or unbound and allowed to be dragged anywhere. /// public static readonly CVarDef StaticStorageUI = CVarDef.Create("control.static_storage_ui", true, CVar.CLIENTONLY | CVar.ARCHIVE); + /// + /// Whether or not the storage window uses a transparent or opaque sprite. + /// + public static readonly CVarDef OpaqueStorageWindow = + CVarDef.Create("control.opaque_storage_background", false, CVar.CLIENTONLY | CVar.ARCHIVE); + /* * UPDATE */ diff --git a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs index 2f6550bf2e..32ce24a971 100644 --- a/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs +++ b/Content.Shared/Storage/EntitySystems/SharedStorageSystem.cs @@ -407,7 +407,7 @@ public abstract class SharedStorageSystem : EntitySystem if (!_actionBlockerSystem.CanInteract(player, itemEnt) || !_sharedHandsSystem.IsHolding(player, itemEnt, out _)) return; - InsertAt((storageEnt, storageComp), (itemEnt, null), msg.Location, out _, player); + InsertAt((storageEnt, storageComp), (itemEnt, null), msg.Location, out _, player, stackAutomatically: false); } private void OnBoundUIOpen(EntityUid uid, StorageComponent storageComp, BoundUIOpenedEvent args) @@ -465,7 +465,7 @@ public abstract class SharedStorageSystem : EntitySystem if (args.Cancelled || args.Container.ID != StorageComponent.ContainerId) return; - if (!CanInsert(uid, args.EntityUid, out _, component, ignoreStacks: true)) + if (!CanInsert(uid, args.EntityUid, out _, component, ignoreStacks: true, includeContainerChecks: false)) args.Cancel(); } @@ -534,7 +534,8 @@ public abstract class SharedStorageSystem : EntitySystem StorageComponent? storageComp = null, ItemComponent? item = null, bool ignoreStacks = false, - bool ignoreLocation = false) + bool ignoreLocation = false, + bool includeContainerChecks = true) { if (!Resolve(uid, ref storageComp) || !Resolve(insertEnt, ref item, false)) { @@ -591,6 +592,12 @@ public abstract class SharedStorageSystem : EntitySystem } } + if (includeContainerChecks && !_containerSystem.CanInsert(insertEnt, storageComp.Container)) + { + reason = null; + return false; + } + reason = null; return true; } @@ -606,7 +613,8 @@ public abstract class SharedStorageSystem : EntitySystem ItemStorageLocation location, out EntityUid? stackedEntity, EntityUid? user = null, - bool playSound = true) + bool playSound = true, + bool stackAutomatically = true) { stackedEntity = null; if (!Resolve(uid, ref uid.Comp)) @@ -617,7 +625,21 @@ public abstract class SharedStorageSystem : EntitySystem uid.Comp.StoredItems[GetNetEntity(insertEnt)] = location; Dirty(uid, uid.Comp); - return Insert(uid, insertEnt, out stackedEntity, out _, user: user, storageComp: uid.Comp, playSound: playSound); + + if (Insert(uid, + insertEnt, + out stackedEntity, + out _, + user: user, + storageComp: uid.Comp, + playSound: playSound, + stackAutomatically: stackAutomatically)) + { + return true; + } + + uid.Comp.StoredItems.Remove(GetNetEntity(insertEnt)); + return false; } /// @@ -631,9 +653,10 @@ public abstract class SharedStorageSystem : EntitySystem out EntityUid? stackedEntity, EntityUid? user = null, StorageComponent? storageComp = null, - bool playSound = true) + bool playSound = true, + bool stackAutomatically = true) { - return Insert(uid, insertEnt, out stackedEntity, out _, user: user, storageComp: storageComp, playSound: playSound); + return Insert(uid, insertEnt, out stackedEntity, out _, user: user, storageComp: storageComp, playSound: playSound, stackAutomatically: stackAutomatically); } /// @@ -648,7 +671,8 @@ public abstract class SharedStorageSystem : EntitySystem out string? reason, EntityUid? user = null, StorageComponent? storageComp = null, - bool playSound = true) + bool playSound = true, + bool stackAutomatically = true) { stackedEntity = null; reason = null; @@ -665,7 +689,7 @@ public abstract class SharedStorageSystem : EntitySystem * For now we just treat items as always being the same size regardless of stack count. */ - if (!_stackQuery.TryGetComponent(insertEnt, out var insertStack)) + if (!stackAutomatically || !_stackQuery.TryGetComponent(insertEnt, out var insertStack)) { if (!_containerSystem.Insert(insertEnt, storageComp.Container)) return false; diff --git a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl index da9edc6f75..0b6a7df6f8 100644 --- a/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl +++ b/Resources/Locale/en-US/escape-menu/ui/options-menu.ftl @@ -29,6 +29,7 @@ ui-options-volume-percent = { TOSTRING($volume, "P0") } ui-options-show-held-item = Show held item next to cursor? ui-options-show-combat-mode-indicators = Show combat mode indicators with cursor? +ui-options-opaque-storage-window = Enable opaque storage window? ui-options-show-looc-on-head = Show LOOC chat above characters head? ui-options-fancy-speech = Show names in speech bubbles? ui-options-fancy-name-background = Add background to speech bubble names? diff --git a/Resources/Textures/Interface/Default/Storage/tile_blocked_opaque.png b/Resources/Textures/Interface/Default/Storage/tile_blocked_opaque.png new file mode 100644 index 0000000000..16a65e36db Binary files /dev/null and b/Resources/Textures/Interface/Default/Storage/tile_blocked_opaque.png differ diff --git a/Resources/Textures/Interface/Default/Storage/tile_empty_opaque.png b/Resources/Textures/Interface/Default/Storage/tile_empty_opaque.png new file mode 100644 index 0000000000..6a6eb055a7 Binary files /dev/null and b/Resources/Textures/Interface/Default/Storage/tile_empty_opaque.png differ