From 526111923cc379944a65f88174907ea16e447444 Mon Sep 17 00:00:00 2001 From: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Date: Thu, 20 Feb 2020 01:19:59 -0800 Subject: [PATCH 01/22] Refactor Controls to default to MouseFilterMode.Ignore --- Content.Client/Chat/ChatBox.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Content.Client/Chat/ChatBox.cs b/Content.Client/Chat/ChatBox.cs index 3ad087d1ae..87bbebba1b 100644 --- a/Content.Client/Chat/ChatBox.cs +++ b/Content.Client/Chat/ChatBox.cs @@ -43,6 +43,7 @@ namespace Content.Client.Chat AnchorLeft = 1.0f; AnchorRight = 1.0f;*/ + MouseFilter = MouseFilterMode.Stop; var outerVBox = new VBoxContainer(); From 4bdb45731adbf930189a3a6369e37ddd36bf5aea Mon Sep 17 00:00:00 2001 From: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Date: Thu, 20 Feb 2020 01:21:23 -0800 Subject: [PATCH 02/22] Clean up MouseFilterMode.Ignore from Controls --- Content.Client/Chat/ChatManager.cs | 7 ++----- Content.Client/Chat/SpeechBubble.cs | 5 +---- .../Components/Storage/ClientStorageComponent.cs | 7 +++---- Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs | 7 +------ Content.Client/UserInterface/CharacterSetupGui.cs | 2 -- Content.Client/UserInterface/GameHud.cs | 7 +------ Content.Client/UserInterface/HandsGui.cs | 6 +----- Content.Client/UserInterface/ItemSlotButton.cs | 2 -- Content.Client/UserInterface/StatusEffectsUI.cs | 3 +-- 9 files changed, 10 insertions(+), 36 deletions(-) diff --git a/Content.Client/Chat/ChatManager.cs b/Content.Client/Chat/ChatManager.cs index e0ee549fbd..a2a3e04ae7 100644 --- a/Content.Client/Chat/ChatManager.cs +++ b/Content.Client/Chat/ChatManager.cs @@ -1,4 +1,4 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Content.Client.Interfaces.Chat; using Content.Shared.Chat; using Robust.Client.Console; @@ -81,10 +81,7 @@ namespace Content.Client.Chat { _netManager.RegisterNetMessage(MsgChatMessage.NAME, _onChatMessage); - _speechBubbleRoot = new LayoutContainer - { - MouseFilter = Control.MouseFilterMode.Ignore - }; + _speechBubbleRoot = new LayoutContainer(); LayoutContainer.SetAnchorPreset(_speechBubbleRoot, LayoutContainer.LayoutPreset.Wide); _userInterfaceManager.StateRoot.AddChild(_speechBubbleRoot); _speechBubbleRoot.SetPositionFirst(); diff --git a/Content.Client/Chat/SpeechBubble.cs b/Content.Client/Chat/SpeechBubble.cs index 01453c12f0..2766ab1b0b 100644 --- a/Content.Client/Chat/SpeechBubble.cs +++ b/Content.Client/Chat/SpeechBubble.cs @@ -1,4 +1,4 @@ -using Content.Client.Interfaces.Chat; +using Content.Client.Interfaces.Chat; using Robust.Client.Interfaces.Graphics.ClientEye; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; @@ -44,14 +44,12 @@ namespace Content.Client.Chat _senderEntity = senderEntity; _eyeManager = eyeManager; - MouseFilter = MouseFilterMode.Ignore; // Use text clipping so new messages don't overlap old ones being pushed up. RectClipContent = true; var label = new RichTextLabel { MaxWidth = 256, - MouseFilter = MouseFilterMode.Ignore }; label.SetMessage(text); @@ -59,7 +57,6 @@ namespace Content.Client.Chat { StyleClasses = { "tooltipBox" }, Children = { label }, - MouseFilter = MouseFilterMode.Ignore, ModulateSelfOverride = Color.White.WithAlpha(0.75f) }; diff --git a/Content.Client/GameObjects/Components/Storage/ClientStorageComponent.cs b/Content.Client/GameObjects/Components/Storage/ClientStorageComponent.cs index a1491a0a7a..f66c6c7751 100644 --- a/Content.Client/GameObjects/Components/Storage/ClientStorageComponent.cs +++ b/Content.Client/GameObjects/Components/Storage/ClientStorageComponent.cs @@ -242,23 +242,22 @@ namespace Content.Client.GameObjects.Components.Storage }; AddChild(ActualButton); - var hBoxContainer = new HBoxContainer {MouseFilter = MouseFilterMode.Ignore}; + var hBoxContainer = new HBoxContainer(); EntitySpriteView = new SpriteView { - CustomMinimumSize = new Vector2(32.0f, 32.0f), MouseFilter = MouseFilterMode.Ignore + CustomMinimumSize = new Vector2(32.0f, 32.0f) }; EntityName = new Label { SizeFlagsVertical = SizeFlags.ShrinkCenter, Text = "Backpack", - MouseFilter = MouseFilterMode.Ignore }; hBoxContainer.AddChild(EntitySpriteView); hBoxContainer.AddChild(EntityName); EntityControl = new Control { - SizeFlagsHorizontal = SizeFlags.FillExpand, MouseFilter = MouseFilterMode.Ignore + SizeFlagsHorizontal = SizeFlags.FillExpand }; EntitySize = new Label { diff --git a/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs b/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs index 53b350bdd0..30b8238d20 100644 --- a/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs +++ b/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs @@ -345,14 +345,12 @@ namespace Content.Client.UserInterface.Cargo var hBox = new HBoxContainer { - SizeFlagsHorizontal = SizeFlags.FillExpand, - MouseFilter = MouseFilterMode.Ignore + SizeFlagsHorizontal = SizeFlags.FillExpand }; Icon = new TextureRect { CustomMinimumSize = new Vector2(32.0f, 32.0f), - MouseFilter = MouseFilterMode.Ignore, RectClipContent = true }; hBox.AddChild(Icon); @@ -366,7 +364,6 @@ namespace Content.Client.UserInterface.Cargo var panel = new PanelContainer { PanelOverride = new StyleBoxFlat { BackgroundColor = new Color(37, 37, 42) }, - MouseFilter = MouseFilterMode.Ignore }; PointCost = new Label { @@ -396,13 +393,11 @@ namespace Content.Client.UserInterface.Cargo var hBox = new HBoxContainer { SizeFlagsHorizontal = SizeFlags.FillExpand, - MouseFilter = MouseFilterMode.Ignore }; Icon = new TextureRect { CustomMinimumSize = new Vector2(32.0f, 32.0f), - MouseFilter = MouseFilterMode.Ignore, RectClipContent = true }; hBox.AddChild(Icon); diff --git a/Content.Client/UserInterface/CharacterSetupGui.cs b/Content.Client/UserInterface/CharacterSetupGui.cs index ca738faeb3..910df07ad4 100644 --- a/Content.Client/UserInterface/CharacterSetupGui.cs +++ b/Content.Client/UserInterface/CharacterSetupGui.cs @@ -231,7 +231,6 @@ namespace Content.Client.UserInterface { Sprite = _previewDummy.GetComponent(), Scale = (2, 2), - MouseFilter = MouseFilterMode.Ignore, OverrideDirection = Direction.South }; @@ -264,7 +263,6 @@ namespace Content.Client.UserInterface var internalHBox = new HBoxContainer { SizeFlagsHorizontal = SizeFlags.FillExpand, - MouseFilter = MouseFilterMode.Ignore, SeparationOverride = 0, Children = { diff --git a/Content.Client/UserInterface/GameHud.cs b/Content.Client/UserInterface/GameHud.cs index 7367a82caa..fdfd3e624c 100644 --- a/Content.Client/UserInterface/GameHud.cs +++ b/Content.Client/UserInterface/GameHud.cs @@ -107,7 +107,7 @@ namespace Content.Client.UserInterface public void Initialize() { - RootControl = new LayoutContainer {MouseFilter = Control.MouseFilterMode.Ignore}; + RootControl = new LayoutContainer(); LayoutContainer.SetAnchorPreset(RootControl, LayoutContainer.LayoutPreset.Wide); var escapeTexture = _resourceCache.GetTexture("/Textures/UserInterface/hamburger.svg.96dpi.png"); @@ -237,7 +237,6 @@ namespace Content.Client.UserInterface HandsContainer = new MarginContainer { - MouseFilter = MouseFilterMode.Ignore, SizeFlagsVertical = Control.SizeFlags.ShrinkEnd }; @@ -353,13 +352,11 @@ namespace Content.Client.UserInterface AddChild(new MarginContainer { - MouseFilter = MouseFilterMode.Ignore, MarginTopOverride = 4, Children = { new VBoxContainer { - MouseFilter = MouseFilterMode.Ignore, Children = { (_textureRect = new TextureRect @@ -367,7 +364,6 @@ namespace Content.Client.UserInterface Texture = texture, SizeFlagsHorizontal = SizeFlags.ShrinkCenter, SizeFlagsVertical = SizeFlags.Expand | SizeFlags.ShrinkCenter, - MouseFilter = MouseFilterMode.Ignore, ModulateSelfOverride = ColorNormal, CustomMinimumSize = (0, 32), Stretch = TextureRect.StretchMode.KeepCentered @@ -376,7 +372,6 @@ namespace Content.Client.UserInterface { Text = keyName, SizeFlagsHorizontal = SizeFlags.ShrinkCenter, - MouseFilter = MouseFilterMode.Ignore, ModulateSelfOverride = ColorNormal, StyleClasses = {StyleClassLabelTopButton} }) diff --git a/Content.Client/UserInterface/HandsGui.cs b/Content.Client/UserInterface/HandsGui.cs index 0f66d323a3..2356d7e24e 100644 --- a/Content.Client/UserInterface/HandsGui.cs +++ b/Content.Client/UserInterface/HandsGui.cs @@ -39,8 +39,6 @@ namespace Content.Client.UserInterface { IoCManager.InjectDependencies(this); - MouseFilter = MouseFilterMode.Ignore; - var textureHandLeft = _resourceCache.GetTexture("/Textures/UserInterface/Inventory/hand_l.png"); var textureHandRight = _resourceCache.GetTexture("/Textures/UserInterface/Inventory/hand_r.png"); var textureHandActive = _resourceCache.GetTexture("/Textures/UserInterface/Inventory/hand_active.png"); @@ -54,8 +52,7 @@ namespace Content.Client.UserInterface var hBox = new HBoxContainer { SeparationOverride = 0, - Children = {_rightStatusPanel, _rightButton, _leftButton, _leftStatusPanel}, - MouseFilter = MouseFilterMode.Ignore + Children = {_rightStatusPanel, _rightButton, _leftButton, _leftStatusPanel} }; AddChild(hBox); @@ -68,7 +65,6 @@ namespace Content.Client.UserInterface // Active hand _leftButton.AddChild(ActiveHandRect = new TextureRect { - MouseFilter = MouseFilterMode.Ignore, Texture = textureHandActive, TextureScale = (2, 2) }); diff --git a/Content.Client/UserInterface/ItemSlotButton.cs b/Content.Client/UserInterface/ItemSlotButton.cs index a6b0e0fa49..f27583f737 100644 --- a/Content.Client/UserInterface/ItemSlotButton.cs +++ b/Content.Client/UserInterface/ItemSlotButton.cs @@ -31,7 +31,6 @@ namespace Content.Client.GameObjects AddChild(SpriteView = new SpriteView { - MouseFilter = MouseFilterMode.Ignore, Scale = (2, 2), OverrideDirection = Direction.South }); @@ -52,7 +51,6 @@ namespace Content.Client.GameObjects { SizeFlagsHorizontal = SizeFlags.ShrinkCenter, SizeFlagsVertical = SizeFlags.ShrinkCenter, - MouseFilter = MouseFilterMode.Ignore, Stretch = TextureRect.StretchMode.KeepCentered, TextureScale = (2, 2), Visible = false, diff --git a/Content.Client/UserInterface/StatusEffectsUI.cs b/Content.Client/UserInterface/StatusEffectsUI.cs index 2e09c01a2f..e6f0fc044f 100644 --- a/Content.Client/UserInterface/StatusEffectsUI.cs +++ b/Content.Client/UserInterface/StatusEffectsUI.cs @@ -1,4 +1,4 @@ -using Robust.Client.UserInterface; +using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; namespace Content.Client.UserInterface @@ -14,7 +14,6 @@ namespace Content.Client.UserInterface public StatusEffectsUI() { _vBox = new VBoxContainer(); - MouseFilter = Control.MouseFilterMode.Ignore; AddChild(_vBox); LayoutContainer.SetGrowHorizontal(this, LayoutContainer.GrowDirection.Begin); From 14f6cbb84525882b87b4cba2297eb222fa225e6b Mon Sep 17 00:00:00 2001 From: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Date: Tue, 25 Feb 2020 16:52:18 -0800 Subject: [PATCH 03/22] Refactor ContainerButtons to use a StyleClass for formatting instead of typeof --- Content.Client/UserInterface/NanoStyle.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Content.Client/UserInterface/NanoStyle.cs b/Content.Client/UserInterface/NanoStyle.cs index bd5bd73a60..97cdd91310 100644 --- a/Content.Client/UserInterface/NanoStyle.cs +++ b/Content.Client/UserInterface/NanoStyle.cs @@ -307,19 +307,19 @@ namespace Content.Client.UserInterface }), // Regular buttons! - new StyleRule(new SelectorElement(typeof(Button), null, null, new[] {ContainerButton.StylePseudoClassNormal}), new[] + new StyleRule(new SelectorElement(typeof(ContainerButton), new[] { ContainerButton.StyleClassButton }, null, new[] {ContainerButton.StylePseudoClassNormal}), new[] { new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonNormal), }), - new StyleRule(new SelectorElement(typeof(Button), null, null, new[] {ContainerButton.StylePseudoClassHover}), new[] + new StyleRule(new SelectorElement(typeof(ContainerButton), new[] { ContainerButton.StyleClassButton }, null, new[] {ContainerButton.StylePseudoClassHover}), new[] { new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonHover), }), - new StyleRule(new SelectorElement(typeof(Button), null, null, new[] {ContainerButton.StylePseudoClassPressed}), new[] + new StyleRule(new SelectorElement(typeof(ContainerButton), new[] { ContainerButton.StyleClassButton }, null, new[] {ContainerButton.StylePseudoClassPressed}), new[] { new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonPressed), }), - new StyleRule(new SelectorElement(typeof(Button), null, null, new[] {ContainerButton.StylePseudoClassDisabled}), new[] + new StyleRule(new SelectorElement(typeof(ContainerButton), new[] { ContainerButton.StyleClassButton }, null, new[] {ContainerButton.StylePseudoClassDisabled}), new[] { new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonDisabled), }), From 3edfdb8763ba2b5a00daf6d43142d41960060b33 Mon Sep 17 00:00:00 2001 From: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Date: Tue, 25 Feb 2020 17:03:46 -0800 Subject: [PATCH 04/22] Refactor CharacterSetupButton into a ContainerButton --- .../UserInterface/CharacterSetupGui.cs | 21 ++++++++----------- 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/Content.Client/UserInterface/CharacterSetupGui.cs b/Content.Client/UserInterface/CharacterSetupGui.cs index 910df07ad4..3f4291deeb 100644 --- a/Content.Client/UserInterface/CharacterSetupGui.cs +++ b/Content.Client/UserInterface/CharacterSetupGui.cs @@ -141,6 +141,7 @@ namespace Content.Client.UserInterface { preferencesManager.CreateCharacter(HumanoidCharacterProfile.Default()); UpdateUI(); + args.Event.Handle(); }; hBox.AddChild(new PanelContainer @@ -179,13 +180,14 @@ namespace Content.Client.UserInterface _charactersVBox.AddChild(characterPickerButton); var characterIndexCopy = characterIndex; - characterPickerButton.ActualButton.OnPressed += args => + characterPickerButton.OnPressed += args => { _humanoidProfileEditor.Profile = (HumanoidCharacterProfile) character; _humanoidProfileEditor.CharacterSlot = characterIndexCopy; _humanoidProfileEditor.UpdateControls(); _preferencesManager.SelectCharacter(character); UpdateUI(); + args.Event.Handle(); }; characterIndex++; } @@ -195,9 +197,8 @@ namespace Content.Client.UserInterface _charactersVBox.AddChild(_createNewCharacterButton); } - private class CharacterPickerButton : Control + private class CharacterPickerButton : ContainerButton { - public readonly Button ActualButton; private IEntity _previewDummy; public CharacterPickerButton( @@ -206,6 +207,10 @@ namespace Content.Client.UserInterface ButtonGroup group, ICharacterProfile profile) { + AddStyleClass(StyleClassButton); + ToggleMode = true; + Group = group; + _previewDummy = entityManager.SpawnEntity("HumanMob_Dummy", MapCoordinates.Nullspace); _previewDummy.GetComponent().UpdateFromProfile(profile); var humanoid = profile as HumanoidCharacterProfile; @@ -216,16 +221,8 @@ namespace Content.Client.UserInterface var isSelectedCharacter = profile == preferencesManager.Preferences.SelectedCharacter; - ActualButton = new Button - { - SizeFlagsHorizontal = SizeFlags.FillExpand, - SizeFlagsVertical = SizeFlags.FillExpand, - ToggleMode = true, - Group = group - }; if (isSelectedCharacter) - ActualButton.Pressed = true; - AddChild(ActualButton); + Pressed = true; var view = new SpriteView { From 8174fdd54b88bc74c40cd7e48f4995304b8b0dfb Mon Sep 17 00:00:00 2001 From: ShadowCommander <10494922+ShadowCommander@users.noreply.github.com> Date: Tue, 10 Mar 2020 19:42:55 -0700 Subject: [PATCH 05/22] Update submodule --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index 0a306514a2..e0cdfeec54 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 0a306514a2c927d3e19f2f6fcec9eee64b488ce4 +Subproject commit e0cdfeec548c695f7eea8af48cc768b8f7ada139 From 020c74a9cb19474d98b4d00008954f2ba496958a Mon Sep 17 00:00:00 2001 From: PrPleGoo Date: Sun, 15 Mar 2020 10:46:09 +0100 Subject: [PATCH 06/22] Changed Item_Base CollisionMask to 0 (#785) --- Resources/Prototypes/Entities/items/item_base.yml | 2 +- RobustToolbox | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Resources/Prototypes/Entities/items/item_base.yml b/Resources/Prototypes/Entities/items/item_base.yml index ce56ba084c..efc42621d6 100644 --- a/Resources/Prototypes/Entities/items/item_base.yml +++ b/Resources/Prototypes/Entities/items/item_base.yml @@ -11,7 +11,7 @@ shapes: - !type:PhysShapeAabb bounds: "-0.25,-0.25,0.25,0.25" - mask: 26 + mask: 0 layer: 32 IsScrapingFloor: true - type: Physics diff --git a/RobustToolbox b/RobustToolbox index 0a306514a2..54dfe82459 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 0a306514a2c927d3e19f2f6fcec9eee64b488ce4 +Subproject commit 54dfe82459b009acd1732a1a01cc517e4bdca19b From a1357a1ff33f0731d4add14a5ac612b69209dda8 Mon Sep 17 00:00:00 2001 From: Decappi Date: Sun, 15 Mar 2020 17:55:20 +0100 Subject: [PATCH 07/22] #391 Done Lathe animations (#774) * Draft PR, do not merge * Lathe now uses animations. Timing is still wrong, code is very wet, repetitions and unused layers are there. * Removed (unneeded?) PowerDeviceVisualizer from the lathe Refactored & Renamed code and variables Renamed animation names * WIP protolathe animation * Working protolathe animation. I still don't like the solution though. --- .../Components/Doors/AirlockVisualizer2D.cs | 1 - .../Components/Power/AutolatheVisualizer2D.cs | 107 ++++++++++++++++++ .../Power/ProtolatheVisualizer2D.cs | 104 +++++++++++++++++ .../Components/Research/LatheComponent.cs | 55 ++++++++- .../Components/Power/SharedLatheComponent.cs | 14 +++ .../Power/SharedPowerDeviceComponent.cs | 1 + .../Prototypes/Entities/buildings/lathe.yml | 12 +- ...ng => autolathe_inserting_glass_plate.png} | Bin ...ng => autolathe_inserting_metal_plate.png} | Bin .../Buildings/autolathe.rsi/meta.json | 74 ++++++------ .../Textures/Buildings/research.rsi/meta.json | 4 +- ...otolathe_n.png => protolathe_building.png} | Bin .../{protolathe_t.png => protolathe_open.png} | Bin 13 files changed, 325 insertions(+), 47 deletions(-) create mode 100644 Content.Client/GameObjects/Components/Power/AutolatheVisualizer2D.cs create mode 100644 Content.Client/GameObjects/Components/Power/ProtolatheVisualizer2D.cs create mode 100644 Content.Shared/GameObjects/Components/Power/SharedLatheComponent.cs rename Resources/Textures/Buildings/autolathe.rsi/{autolathe_r.png => autolathe_inserting_glass_plate.png} (100%) rename Resources/Textures/Buildings/autolathe.rsi/{autolathe_inserting.png => autolathe_inserting_metal_plate.png} (100%) rename Resources/Textures/Buildings/research.rsi/{protolathe_n.png => protolathe_building.png} (100%) rename Resources/Textures/Buildings/research.rsi/{protolathe_t.png => protolathe_open.png} (100%) diff --git a/Content.Client/GameObjects/Components/Doors/AirlockVisualizer2D.cs b/Content.Client/GameObjects/Components/Doors/AirlockVisualizer2D.cs index 03f0af16c5..04597fc3f9 100644 --- a/Content.Client/GameObjects/Components/Doors/AirlockVisualizer2D.cs +++ b/Content.Client/GameObjects/Components/Doors/AirlockVisualizer2D.cs @@ -120,7 +120,6 @@ namespace Content.Client.GameObjects.Components.Doors { animPlayer.Play(OpenAnimation, AnimationKey); } - break; case DoorVisualState.Open: sprite.LayerSetState(DoorVisualLayers.Base, "open"); diff --git a/Content.Client/GameObjects/Components/Power/AutolatheVisualizer2D.cs b/Content.Client/GameObjects/Components/Power/AutolatheVisualizer2D.cs new file mode 100644 index 0000000000..6ad061678b --- /dev/null +++ b/Content.Client/GameObjects/Components/Power/AutolatheVisualizer2D.cs @@ -0,0 +1,107 @@ +using System; +using Content.Shared.GameObjects.Components.Power; +using Robust.Client.Animations; +using Robust.Client.GameObjects; +using Robust.Client.GameObjects.Components.Animations; +using Robust.Client.Interfaces.GameObjects.Components; +using Robust.Shared.Interfaces.GameObjects; +using YamlDotNet.RepresentationModel; + +namespace Content.Client.GameObjects.Components.Power +{ + public class AutolatheVisualizer2D : AppearanceVisualizer + { + private const string AnimationKey = "autolathe_animation"; + + private Animation _buildingAnimation; + private Animation _insertingMetalAnimation; + private Animation _insertingGlassAnimation; + + public override void LoadData(YamlMappingNode node) + { + base.LoadData(node); + + _buildingAnimation = PopulateAnimation("autolathe_building", "autolathe_building_unlit", 0.5f); + _insertingMetalAnimation = PopulateAnimation("autolathe_inserting_metal_plate", "autolathe_inserting_unlit", 0.9f); + _insertingGlassAnimation = PopulateAnimation("autolathe_inserting_glass_plate", "autolathe_inserting_unlit", 0.9f); + } + + private Animation PopulateAnimation(string sprite, string spriteUnlit, float length) + { + var animation = new Animation {Length = TimeSpan.FromSeconds(length)}; + + var flick = new AnimationTrackSpriteFlick(); + animation.AnimationTracks.Add(flick); + flick.LayerKey = AutolatheVisualLayers.Base; + flick.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame(sprite, 0f)); + + var flickUnlit = new AnimationTrackSpriteFlick(); + animation.AnimationTracks.Add(flickUnlit); + flickUnlit.LayerKey = AutolatheVisualLayers.BaseUnlit; + flickUnlit.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame(spriteUnlit, 0f)); + + return animation; + } + + public override void InitializeEntity(IEntity entity) + { + if (!entity.HasComponent()) + { + entity.AddComponent(); + } + } + + public override void OnChangeData(AppearanceComponent component) + { + base.OnChangeData(component); + + var sprite = component.Owner.GetComponent(); + var animPlayer = component.Owner.GetComponent(); + if (!component.TryGetData(PowerDeviceVisuals.VisualState, out LatheVisualState state)) + { + state = LatheVisualState.Idle; + } + + switch (state) + { + case LatheVisualState.Idle: + if (animPlayer.HasRunningAnimation(AnimationKey)) + { + animPlayer.Stop(AnimationKey); + } + + sprite.LayerSetState(AutolatheVisualLayers.Base, "autolathe"); + sprite.LayerSetState(AutolatheVisualLayers.BaseUnlit, "autolathe_unlit"); + break; + case LatheVisualState.Producing: + if (!animPlayer.HasRunningAnimation(AnimationKey)) + { + animPlayer.Play(_buildingAnimation, AnimationKey); + } + break; + case LatheVisualState.InsertingMetal: + if (!animPlayer.HasRunningAnimation(AnimationKey)) + { + animPlayer.Play(_insertingMetalAnimation, AnimationKey); + } + break; + case LatheVisualState.InsertingGlass: + if (!animPlayer.HasRunningAnimation(AnimationKey)) + { + animPlayer.Play(_insertingGlassAnimation, AnimationKey); + } + break; + default: + throw new ArgumentOutOfRangeException(); + } + + var glowingPartsVisible = !(component.TryGetData(PowerDeviceVisuals.Powered, out bool powered) && !powered); + sprite.LayerSetVisible(AutolatheVisualLayers.BaseUnlit, glowingPartsVisible); + } + public enum AutolatheVisualLayers + { + Base, + BaseUnlit + } + } +} diff --git a/Content.Client/GameObjects/Components/Power/ProtolatheVisualizer2D.cs b/Content.Client/GameObjects/Components/Power/ProtolatheVisualizer2D.cs new file mode 100644 index 0000000000..4547c1668c --- /dev/null +++ b/Content.Client/GameObjects/Components/Power/ProtolatheVisualizer2D.cs @@ -0,0 +1,104 @@ +using System; +using Content.Shared.GameObjects.Components.Power; +using Robust.Client.Animations; +using Robust.Client.GameObjects; +using Robust.Client.GameObjects.Components.Animations; +using Robust.Client.Interfaces.GameObjects.Components; +using Robust.Shared.Interfaces.GameObjects; +using YamlDotNet.RepresentationModel; + +namespace Content.Client.GameObjects.Components.Power +{ + public class ProtolatheVisualizer2D : AppearanceVisualizer + { + private const string AnimationKey = "protolathe_animation"; + + private Animation _buildingAnimation; + private Animation _insertingMetalAnimation; + private Animation _insertingGlassAnimation; + + public override void LoadData(YamlMappingNode node) + { + base.LoadData(node); + + _buildingAnimation = PopulateAnimation("protolathe_building", 0.9f); + _insertingMetalAnimation = PopulateAnimation("protolathe_metal", 0.9f); + _insertingGlassAnimation = PopulateAnimation("protolathe_glass", 0.9f); + } + + private Animation PopulateAnimation(string sprite, float length) + { + var animation = new Animation {Length = TimeSpan.FromSeconds(length)}; + + var flick = new AnimationTrackSpriteFlick(); + animation.AnimationTracks.Add(flick); + flick.LayerKey = ProtolatheVisualLayers.AnimationLayer; + flick.KeyFrames.Add(new AnimationTrackSpriteFlick.KeyFrame(sprite, 0f)); + + return animation; + } + + public override void InitializeEntity(IEntity entity) + { + if (!entity.HasComponent()) + { + entity.AddComponent(); + } + } + + public override void OnChangeData(AppearanceComponent component) + { + base.OnChangeData(component); + + var sprite = component.Owner.GetComponent(); + var animPlayer = component.Owner.GetComponent(); + if (!component.TryGetData(PowerDeviceVisuals.VisualState, out LatheVisualState state)) + { + state = LatheVisualState.Idle; + } + sprite.LayerSetVisible(ProtolatheVisualLayers.AnimationLayer, true); + switch (state) + { + case LatheVisualState.Idle: + if (animPlayer.HasRunningAnimation(AnimationKey)) + { + animPlayer.Stop(AnimationKey); + } + + sprite.LayerSetState(ProtolatheVisualLayers.Base, "protolathe"); + sprite.LayerSetState(ProtolatheVisualLayers.BaseUnlit, "protolathe_unlit"); + sprite.LayerSetVisible(ProtolatheVisualLayers.AnimationLayer, false); + break; + case LatheVisualState.Producing: + if (!animPlayer.HasRunningAnimation(AnimationKey)) + { + animPlayer.Play(_buildingAnimation, AnimationKey); + } + break; + case LatheVisualState.InsertingMetal: + if (!animPlayer.HasRunningAnimation(AnimationKey)) + { + animPlayer.Play(_insertingMetalAnimation, AnimationKey); + } + break; + case LatheVisualState.InsertingGlass: + if (!animPlayer.HasRunningAnimation(AnimationKey)) + { + animPlayer.Play(_insertingGlassAnimation, AnimationKey); + } + break; + default: + throw new ArgumentOutOfRangeException(); + } + + var glowingPartsVisible = !(component.TryGetData(PowerDeviceVisuals.Powered, out bool powered) && !powered); + sprite.LayerSetVisible(ProtolatheVisualLayers.BaseUnlit, glowingPartsVisible); + } + public enum ProtolatheVisualLayers + { + Base, + BaseUnlit, + AnimationLayer + } + } +} diff --git a/Content.Server/GameObjects/Components/Research/LatheComponent.cs b/Content.Server/GameObjects/Components/Research/LatheComponent.cs index d08a471024..f1020eb091 100644 --- a/Content.Server/GameObjects/Components/Research/LatheComponent.cs +++ b/Content.Server/GameObjects/Components/Research/LatheComponent.cs @@ -1,18 +1,22 @@ // Only unused on .NET Core due to KeyValuePair.Deconstruct // ReSharper disable once RedundantUsingDirective + +using System; using Robust.Shared.Utility; using System.Collections.Generic; +using System.Linq; using Content.Server.GameObjects.Components.Power; using Content.Server.GameObjects.Components.Stack; using Content.Server.GameObjects.EntitySystems; using Content.Shared.GameObjects.Components.Materials; +using Content.Shared.GameObjects.Components.Power; using Content.Shared.GameObjects.Components.Research; using Content.Shared.Research; +using Robust.Server.GameObjects; using Robust.Server.GameObjects.Components.UserInterface; using Robust.Server.Interfaces.GameObjects; using Robust.Server.Interfaces.Player; using Robust.Shared.GameObjects; -using Robust.Shared.Map; using Robust.Shared.Timers; using Robust.Shared.ViewVariables; @@ -32,16 +36,28 @@ namespace Content.Server.GameObjects.Components.Research [ViewVariables] public bool Producing { get; private set; } = false; + private AppearanceComponent _appearance; + private LatheState _state = LatheState.Base; + + protected virtual LatheState State + { + get => _state; + set => _state = value; + } + private LatheRecipePrototype _producingRecipe = null; private PowerDeviceComponent _powerDevice; private bool Powered => _powerDevice.Powered; + private static readonly TimeSpan InsertionTime = TimeSpan.FromSeconds(0.9f); + public override void Initialize() { base.Initialize(); _userInterface = Owner.GetComponent().GetBoundUserInterface(LatheUiKey.Key); _userInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage; _powerDevice = Owner.GetComponent(); + _appearance = Owner.GetComponent(); } private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage message) @@ -100,12 +116,17 @@ namespace Content.Server.GameObjects.Components.Research _userInterface.SendMessage(new LatheProducingRecipeMessage(recipe.ID)); + State = LatheState.Producing; + SetAppearance(LatheVisualState.Producing); + Timer.Spawn(recipe.CompleteTime, () => { Producing = false; _producingRecipe = null; Owner.EntityManager.SpawnEntity(recipe.Result, Owner.Transform.GridPosition); _userInterface.SendMessage(new LatheStoppedProducingRecipeMessage()); + State = LatheState.Base; + SetAppearance(LatheVisualState.Idle); }); return true; @@ -125,7 +146,6 @@ namespace Content.Server.GameObjects.Components.Research return; } OpenUserInterface(actor.playerSession); - return; } bool IAttackBy.AttackBy(AttackByEventArgs eventArgs) { @@ -151,15 +171,37 @@ namespace Content.Server.GameObjects.Components.Research foreach (var mat in material.MaterialTypes.Values) { - storage.InsertMaterial(mat.ID, VolumePerSheet * multiplier); } + State = LatheState.Inserting; + switch (material.MaterialTypes.Values.First().Name) + { + case "Steel": + SetAppearance(LatheVisualState.InsertingMetal); + break; + case "Glass": + SetAppearance(LatheVisualState.InsertingGlass); + break; + } + + Timer.Spawn(InsertionTime, async () => + { + State = LatheState.Base; + SetAppearance(LatheVisualState.Idle); + }); + eventArgs.AttackWith.Delete(); return false; } + private void SetAppearance(LatheVisualState state) + { + if (_appearance != null || Owner.TryGetComponent(out _appearance)) + _appearance.SetData(PowerDeviceVisuals.VisualState, state); + } + private Queue GetIDQueue() { var queue = new Queue(); @@ -170,5 +212,12 @@ namespace Content.Server.GameObjects.Components.Research return queue; } + + protected enum LatheState + { + Base, + Inserting, + Producing + } } } diff --git a/Content.Shared/GameObjects/Components/Power/SharedLatheComponent.cs b/Content.Shared/GameObjects/Components/Power/SharedLatheComponent.cs new file mode 100644 index 0000000000..21ab0d43a0 --- /dev/null +++ b/Content.Shared/GameObjects/Components/Power/SharedLatheComponent.cs @@ -0,0 +1,14 @@ +using System; +using Robust.Shared.Serialization; + +namespace Content.Shared.GameObjects.Components.Power +{ + [Serializable, NetSerializable] + public enum LatheVisualState + { + Idle, + Producing, + InsertingMetal, + InsertingGlass + } +} diff --git a/Content.Shared/GameObjects/Components/Power/SharedPowerDeviceComponent.cs b/Content.Shared/GameObjects/Components/Power/SharedPowerDeviceComponent.cs index 2f050760f4..67ee873851 100644 --- a/Content.Shared/GameObjects/Components/Power/SharedPowerDeviceComponent.cs +++ b/Content.Shared/GameObjects/Components/Power/SharedPowerDeviceComponent.cs @@ -6,6 +6,7 @@ namespace Content.Shared.GameObjects.Components.Power [Serializable, NetSerializable] public enum PowerDeviceVisuals { + VisualState, Powered } } diff --git a/Resources/Prototypes/Entities/buildings/lathe.yml b/Resources/Prototypes/Entities/buildings/lathe.yml index f49b58f89e..67a52069f2 100644 --- a/Resources/Prototypes/Entities/buildings/lathe.yml +++ b/Resources/Prototypes/Entities/buildings/lathe.yml @@ -25,9 +25,10 @@ sprite: Buildings/autolathe.rsi layers: - state: autolathe + map: ["enum.AutolatheVisualLayers.Base"] - state: autolathe_unlit shader: unshaded - map: ["enum.PowerDeviceVisualLayers.Powered"] + map: ["enum.AutolatheVisualLayers.BaseUnlit"] - type: Icon sprite: Buildings/autolathe.rsi state: autolathe @@ -56,7 +57,7 @@ - Multitool - type: Appearance visuals: - - type: PowerDeviceVisualizer2D + - type: AutolatheVisualizer2D - type: entity parent: BaseLathe @@ -67,9 +68,12 @@ sprite: Buildings/research.rsi layers: - state: protolathe + map: ["enum.ProtolatheVisualLayers.Base"] - state: protolathe_unlit shader: unshaded - map: ["enum.PowerDeviceVisualLayers.Powered"] + map: ["enum.ProtolatheVisualLayers.BaseUnlit"] + - state: protolathe + map: ["enum.ProtolatheVisualLayers.AnimationLayer"] - type: Icon sprite: Buildings/research.rsi state: protolathe @@ -104,4 +108,4 @@ type: ResearchClientBoundUserInterface - type: Appearance visuals: - - type: PowerDeviceVisualizer2D + - type: ProtolatheVisualizer2D diff --git a/Resources/Textures/Buildings/autolathe.rsi/autolathe_r.png b/Resources/Textures/Buildings/autolathe.rsi/autolathe_inserting_glass_plate.png similarity index 100% rename from Resources/Textures/Buildings/autolathe.rsi/autolathe_r.png rename to Resources/Textures/Buildings/autolathe.rsi/autolathe_inserting_glass_plate.png diff --git a/Resources/Textures/Buildings/autolathe.rsi/autolathe_inserting.png b/Resources/Textures/Buildings/autolathe.rsi/autolathe_inserting_metal_plate.png similarity index 100% rename from Resources/Textures/Buildings/autolathe.rsi/autolathe_inserting.png rename to Resources/Textures/Buildings/autolathe.rsi/autolathe_inserting_metal_plate.png diff --git a/Resources/Textures/Buildings/autolathe.rsi/meta.json b/Resources/Textures/Buildings/autolathe.rsi/meta.json index 3bb1cccea4..9f868d6a0c 100644 --- a/Resources/Textures/Buildings/autolathe.rsi/meta.json +++ b/Resources/Textures/Buildings/autolathe.rsi/meta.json @@ -28,15 +28,15 @@ "directions": 1, "delays": [ [ - 0.15, - 0.15, - 0.15, - 0.15, - 0.15, - 0.15, - 0.15, - 0.15, - 0.15 + 0.055, + 0.055, + 0.055, + 0.055, + 0.055, + 0.055, + 0.055, + 0.055, + 0.055 ] ] }, @@ -45,20 +45,37 @@ "directions": 1, "delays": [ [ - 0.15, - 0.15, - 0.15, - 0.15, - 0.15, - 0.15, - 0.15, - 0.15, - 0.15 + 0.055, + 0.055, + 0.055, + 0.055, + 0.055, + 0.055, + 0.055, + 0.055, + 0.055 ] ] }, { - "name": "autolathe_inserting", + "name": "autolathe_inserting_metal_plate", + "directions": 1, + "delays": [ + [ + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1, + 0.1 + ] + ] + }, + { + "name": "autolathe_inserting_glass_plate", "directions": 1, "delays": [ [ @@ -99,23 +116,6 @@ 1.0 ] ] - }, - { - "name": "autolathe_r", - "directions": 1, - "delays": [ - [ - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1, - 0.1 - ] - ] } ] -} \ No newline at end of file +} diff --git a/Resources/Textures/Buildings/research.rsi/meta.json b/Resources/Textures/Buildings/research.rsi/meta.json index 6eacf5723e..c41bbc75d9 100644 --- a/Resources/Textures/Buildings/research.rsi/meta.json +++ b/Resources/Textures/Buildings/research.rsi/meta.json @@ -259,7 +259,7 @@ ] }, { - "name": "protolathe_n", + "name": "protolathe_building", "directions": 1, "delays": [ [ @@ -314,7 +314,7 @@ ] }, { - "name": "protolathe_t", + "name": "protolathe_open", "directions": 1, "delays": [ [ diff --git a/Resources/Textures/Buildings/research.rsi/protolathe_n.png b/Resources/Textures/Buildings/research.rsi/protolathe_building.png similarity index 100% rename from Resources/Textures/Buildings/research.rsi/protolathe_n.png rename to Resources/Textures/Buildings/research.rsi/protolathe_building.png diff --git a/Resources/Textures/Buildings/research.rsi/protolathe_t.png b/Resources/Textures/Buildings/research.rsi/protolathe_open.png similarity index 100% rename from Resources/Textures/Buildings/research.rsi/protolathe_t.png rename to Resources/Textures/Buildings/research.rsi/protolathe_open.png From d645b1470e483620e84bd4c332a870da52024687 Mon Sep 17 00:00:00 2001 From: JiimBob <44332255+JiimBob@users.noreply.github.com> Date: Sat, 21 Mar 2020 15:37:22 -0400 Subject: [PATCH 08/22] Added power checks Added power checks to: Reagent Dispenser Medical Scanner Lathes Research Console Vending Machines Added power device component to: chem dispenser prototype medical scanner prototype Fixes for #706 --- .../Chemistry/ReagentDispenserComponent.cs | 13 ++++ .../Medical/MedicalScannerComponent.cs | 10 ++++ .../Components/Research/LatheComponent.cs | 60 ++++++++++--------- .../Research/ResearchConsoleComponent.cs | 2 + .../VendingMachineComponent.cs | 5 ++ .../Entities/buildings/chem_dispenser.yml | 1 + .../Entities/buildings/medical_scanner.yml | 2 +- 7 files changed, 64 insertions(+), 29 deletions(-) diff --git a/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs b/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs index fa3a65e6c5..6fb12aa337 100644 --- a/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs +++ b/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs @@ -2,6 +2,7 @@ using System.Linq; using Content.Server.GameObjects.Components.Sound; using Content.Server.GameObjects.EntitySystems; +using Content.Server.GameObjects.Components.Power; using Content.Server.Interfaces; using Content.Server.Interfaces.GameObjects; using Content.Shared.Chemistry; @@ -46,6 +47,11 @@ namespace Content.Server.GameObjects.Components.Chemistry [ViewVariables] private SolutionComponent Solution => _beakerContainer.ContainedEntity.GetComponent(); + ///implementing PowerDeviceComponent + private PowerDeviceComponent _powerDevice; + private bool Powered => _powerDevice.Powered; + + /// /// Shows the serializer how to save/load this components yaml prototype. /// @@ -70,6 +76,7 @@ namespace Content.Server.GameObjects.Components.Chemistry _beakerContainer = ContainerManagerComponent.Ensure($"{Name}-reagentContainerContainer", Owner); + _powerDevice = Owner.GetComponent(); InitializeFromPrototype(); UpdateUserInterface(); @@ -159,6 +166,9 @@ namespace Content.Server.GameObjects.Components.Chemistry //Check if player can interact in their current state if (!ActionBlockerSystem.CanInteract(playerEntity) || !ActionBlockerSystem.CanUse(playerEntity)) return false; + //Check if device is powered + if (!Powered) + return false; return true; } @@ -251,6 +261,9 @@ namespace Content.Server.GameObjects.Components.Chemistry return; } + if (!Powered) + return; + var activeHandEntity = hands.GetActiveHand?.Owner; if (activeHandEntity == null) { diff --git a/Content.Server/GameObjects/Components/Medical/MedicalScannerComponent.cs b/Content.Server/GameObjects/Components/Medical/MedicalScannerComponent.cs index f27144bb0b..2ea653ff69 100644 --- a/Content.Server/GameObjects/Components/Medical/MedicalScannerComponent.cs +++ b/Content.Server/GameObjects/Components/Medical/MedicalScannerComponent.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using Content.Server.GameObjects.EntitySystems; using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Medical; +using Content.Server.GameObjects.Components.Power; using Robust.Server.GameObjects; using Robust.Server.GameObjects.Components.Container; using Robust.Server.GameObjects.Components.UserInterface; @@ -24,6 +25,10 @@ namespace Content.Server.GameObjects.Components.Medical private readonly Vector2 _ejectOffset = new Vector2(-0.5f, 0f); public bool IsOccupied => _bodyContainer.ContainedEntity != null; + ///implementing PowerDeviceComponent + private PowerDeviceComponent _powerDevice; + private bool Powered => _powerDevice.Powered; + public override void Initialize() { base.Initialize(); @@ -31,6 +36,7 @@ namespace Content.Server.GameObjects.Components.Medical _userInterface = Owner.GetComponent() .GetBoundUserInterface(MedicalScannerUiKey.Key); _bodyContainer = ContainerManagerComponent.Ensure($"{Name}-bodyContainer", Owner); + _powerDevice = Owner.GetComponent(); UpdateUserInterface(); } @@ -79,6 +85,8 @@ namespace Content.Server.GameObjects.Components.Medical private void UpdateUserInterface() { + if (!Powered) + return; var newState = GetUserInterfaceState(); _userInterface.SetState(newState); } @@ -112,6 +120,8 @@ namespace Content.Server.GameObjects.Components.Medical { return; } + if (!Powered) + return; _userInterface.Open(actor.playerSession); } diff --git a/Content.Server/GameObjects/Components/Research/LatheComponent.cs b/Content.Server/GameObjects/Components/Research/LatheComponent.cs index f1020eb091..f06967b592 100644 --- a/Content.Server/GameObjects/Components/Research/LatheComponent.cs +++ b/Content.Server/GameObjects/Components/Research/LatheComponent.cs @@ -62,38 +62,42 @@ namespace Content.Server.GameObjects.Components.Research private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage message) { - switch (message.Message) - { - case LatheQueueRecipeMessage msg: - _prototypeManager.TryIndex(msg.ID, out LatheRecipePrototype recipe); - if (recipe != null) - for (var i = 0; i < msg.Quantity; i++) - { - Queue.Enqueue(recipe); - _userInterface.SendMessage(new LatheFullQueueMessage(GetIDQueue())); - } - break; - case LatheSyncRequestMessage msg: - if (!Owner.TryGetComponent(out MaterialStorageComponent storage)) return; - _userInterface.SendMessage(new LatheFullQueueMessage(GetIDQueue())); - if (_producingRecipe != null) - _userInterface.SendMessage(new LatheProducingRecipeMessage(_producingRecipe.ID)); - break; + if (!Powered) + return; + switch (message.Message) + { + case LatheQueueRecipeMessage msg: + _prototypeManager.TryIndex(msg.ID, out LatheRecipePrototype recipe); + if (recipe != null) + for (var i = 0; i < msg.Quantity; i++) + { + Queue.Enqueue(recipe); + _userInterface.SendMessage(new LatheFullQueueMessage(GetIDQueue())); + } + break; + case LatheSyncRequestMessage msg: + if (!Owner.TryGetComponent(out MaterialStorageComponent storage)) return; + _userInterface.SendMessage(new LatheFullQueueMessage(GetIDQueue())); + if (_producingRecipe != null) + _userInterface.SendMessage(new LatheProducingRecipeMessage(_producingRecipe.ID)); + break; - case LatheServerSelectionMessage msg: - if (!Owner.TryGetComponent(out ResearchClientComponent researchClient)) return; - researchClient.OpenUserInterface(message.Session); - break; + case LatheServerSelectionMessage msg: + if (!Owner.TryGetComponent(out ResearchClientComponent researchClient)) return; + researchClient.OpenUserInterface(message.Session); + break; - case LatheServerSyncMessage msg: - if (!Owner.TryGetComponent(out TechnologyDatabaseComponent database) - || !Owner.TryGetComponent(out ProtolatheDatabaseComponent protoDatabase)) return; + case LatheServerSyncMessage msg: + if (!Owner.TryGetComponent(out TechnologyDatabaseComponent database) + || !Owner.TryGetComponent(out ProtolatheDatabaseComponent protoDatabase)) return; - if(database.SyncWithServer()) - protoDatabase.Sync(); + if (database.SyncWithServer()) + protoDatabase.Sync(); + + break; + } + - break; - } } internal bool Produce(LatheRecipePrototype recipe) diff --git a/Content.Server/GameObjects/Components/Research/ResearchConsoleComponent.cs b/Content.Server/GameObjects/Components/Research/ResearchConsoleComponent.cs index e3a2d4be72..9b10ad832a 100644 --- a/Content.Server/GameObjects/Components/Research/ResearchConsoleComponent.cs +++ b/Content.Server/GameObjects/Components/Research/ResearchConsoleComponent.cs @@ -46,6 +46,8 @@ namespace Content.Server.GameObjects.Components.Research private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage message) { if (!Owner.TryGetComponent(out TechnologyDatabaseComponent database)) return; + if (!Powered) + return; switch (message.Message) { diff --git a/Content.Server/GameObjects/Components/VendingMachines/VendingMachineComponent.cs b/Content.Server/GameObjects/Components/VendingMachines/VendingMachineComponent.cs index 2284d14596..1a9823d8ae 100644 --- a/Content.Server/GameObjects/Components/VendingMachines/VendingMachineComponent.cs +++ b/Content.Server/GameObjects/Components/VendingMachines/VendingMachineComponent.cs @@ -47,6 +47,8 @@ namespace Content.Server.GameObjects.Components.VendingMachines { return; } + if (!Powered) + return; var wires = Owner.GetComponent(); if (wires.IsPanelOpen) @@ -121,6 +123,9 @@ namespace Content.Server.GameObjects.Components.VendingMachines private void UserInterfaceOnOnReceiveMessage(ServerBoundUserInterfaceMessage serverMsg) { + if (!Powered) + return; + var message = serverMsg.Message; switch (message) { diff --git a/Resources/Prototypes/Entities/buildings/chem_dispenser.yml b/Resources/Prototypes/Entities/buildings/chem_dispenser.yml index da79842a68..a72263b277 100644 --- a/Resources/Prototypes/Entities/buildings/chem_dispenser.yml +++ b/Resources/Prototypes/Entities/buildings/chem_dispenser.yml @@ -10,6 +10,7 @@ texture: Buildings/chemicals.rsi/industrial_dispenser.png - type: ReagentDispenser pack: ChemDispenserStandardInventory + - type: PowerDevice - type: reagentDispenserInventory id: ChemDispenserStandardInventory diff --git a/Resources/Prototypes/Entities/buildings/medical_scanner.yml b/Resources/Prototypes/Entities/buildings/medical_scanner.yml index c583a1a12a..9ad614ce7b 100644 --- a/Resources/Prototypes/Entities/buildings/medical_scanner.yml +++ b/Resources/Prototypes/Entities/buildings/medical_scanner.yml @@ -11,7 +11,7 @@ map: ["enum.MedicalScannerVisualLayers.Machine"] - state: scanner_terminal_blue map: ["enum.MedicalScannerVisualLayers.Terminal"] - + - type: PowerDevice - type: Icon sprite: Buildings/medical_scanner.rsi state: scanner_open From 5536ef2d2b7bdd1f34e39e4647db4d4dbc1af4a8 Mon Sep 17 00:00:00 2001 From: JiimBob <44332255+JiimBob@users.noreply.github.com> Date: Sun, 22 Mar 2020 19:34:38 -0400 Subject: [PATCH 09/22] Update CargoConsoleComponent.cs --- .../Components/Cargo/CargoConsoleComponent.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs b/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs index b5e3fd4564..3b555c725f 100644 --- a/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs +++ b/Content.Server/GameObjects/Components/Cargo/CargoConsoleComponent.cs @@ -1,6 +1,7 @@ using Content.Server.Cargo; using Content.Server.GameObjects.EntitySystems; using Content.Shared.GameObjects.Components.Cargo; +using Content.Server.GameObjects.Components.Power; using Content.Shared.Prototypes.Cargo; using Robust.Server.GameObjects.Components.UserInterface; using Robust.Server.Interfaces.GameObjects; @@ -40,6 +41,9 @@ namespace Content.Server.GameObjects.Components.Cargo private bool _requestOnly = false; + private PowerDeviceComponent _powerDevice; + private bool Powered => _powerDevice.Powered; + public override void Initialize() { base.Initialize(); @@ -47,6 +51,7 @@ namespace Content.Server.GameObjects.Components.Cargo Orders = Owner.GetComponent(); _userInterface = Owner.GetComponent().GetBoundUserInterface(CargoConsoleUiKey.Key); _userInterface.OnReceiveMessage += UserInterfaceOnOnReceiveMessage; + _powerDevice = Owner.GetComponent(); _galacticBankManager.AddComponent(this); BankId = 0; } @@ -66,6 +71,8 @@ namespace Content.Server.GameObjects.Components.Cargo var message = serverMsg.Message; if (!Orders.ConnectedToDatabase) return; + if (!Powered) + return; switch (message) { case CargoConsoleAddOrderMessage msg: @@ -119,6 +126,8 @@ namespace Content.Server.GameObjects.Components.Cargo { return; } + if (!Powered) + return; _userInterface.Open(actor.playerSession); } From 8d1a019b860e3880cc7c91fcc766af8d8487847b Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 25 Mar 2020 02:24:40 +0100 Subject: [PATCH 10/22] Update submodule. --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index 54dfe82459..c4b9c1cc4e 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 54dfe82459b009acd1732a1a01cc517e4bdca19b +Subproject commit c4b9c1cc4ed66f78ef74450105963c251ed30f82 From fa27e44fd48c8ee3716a41af11d2d8c5c2d30bbd Mon Sep 17 00:00:00 2001 From: PrPleGoo Date: Wed, 25 Mar 2020 02:28:37 +0100 Subject: [PATCH 11/22] Sets drawdepth "Mobs" on the Human prototype (#788) * Update .gitignore * Revert "Update .gitignore" This reverts commit bea34f7f347ebb8795986e4d3be2b4348cfb4c3d. * human entities now get their DrawDepth set to Mobs --- Resources/Prototypes/Entities/mobs/human.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Resources/Prototypes/Entities/mobs/human.yml b/Resources/Prototypes/Entities/mobs/human.yml index d455a96e7a..50f789e8e0 100644 --- a/Resources/Prototypes/Entities/mobs/human.yml +++ b/Resources/Prototypes/Entities/mobs/human.yml @@ -26,7 +26,7 @@ - type: InteractionOutline - type: Sprite netsync: false - + drawdepth: Mobs layers: - map: ["enum.HumanoidVisualLayers.Chest"] color: "#e8b59b" From 42814fcfe762d23db20c50b78d07c2bdc3794516 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 25 Mar 2020 08:36:06 +0100 Subject: [PATCH 12/22] Update submodule --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index c4b9c1cc4e..a21bad1f1b 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit c4b9c1cc4ed66f78ef74450105963c251ed30f82 +Subproject commit a21bad1f1b423cd1d000eb6b69293c70614f9f15 From 65d1681cb3fb7a67bbb5e8615487fc667397fedf Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Wed, 25 Mar 2020 22:21:29 +0100 Subject: [PATCH 13/22] Fix error about game.diagonalmovement being registered multiple times. --- .../Components/Movement/PlayerInputMoverComponent.cs | 6 ------ Content.Server/GameObjects/EntitySystems/MoverSystem.cs | 5 +++++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Content.Server/GameObjects/Components/Movement/PlayerInputMoverComponent.cs b/Content.Server/GameObjects/Components/Movement/PlayerInputMoverComponent.cs index 26d056ac17..969b071bd8 100644 --- a/Content.Server/GameObjects/Components/Movement/PlayerInputMoverComponent.cs +++ b/Content.Server/GameObjects/Components/Movement/PlayerInputMoverComponent.cs @@ -104,12 +104,6 @@ namespace Content.Server.GameObjects.Components.Movement /// [ViewVariables] public bool DiagonalMovementEnabled => _configurationManager.GetCVar("game.diagonalmovement"); - public override void Initialize() - { - base.Initialize(); - _configurationManager.RegisterCVar("game.diagonalmovement", true, CVar.ARCHIVE); - } - /// public override void OnAdd() { diff --git a/Content.Server/GameObjects/EntitySystems/MoverSystem.cs b/Content.Server/GameObjects/EntitySystems/MoverSystem.cs index a2524b6204..5860ac4e35 100644 --- a/Content.Server/GameObjects/EntitySystems/MoverSystem.cs +++ b/Content.Server/GameObjects/EntitySystems/MoverSystem.cs @@ -11,10 +11,12 @@ using Robust.Server.GameObjects; using Robust.Server.GameObjects.EntitySystems; using Robust.Server.Interfaces.Player; using Robust.Server.Interfaces.Timing; +using Robust.Shared.Configuration; using Robust.Shared.GameObjects; using Robust.Shared.GameObjects.Components.Transform; using Robust.Shared.GameObjects.Systems; using Robust.Shared.Input; +using Robust.Shared.Interfaces.Configuration; using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects.Components; using Robust.Shared.Interfaces.Map; @@ -38,6 +40,7 @@ namespace Content.Server.GameObjects.EntitySystems [Dependency] private readonly ITileDefinitionManager _tileDefinitionManager; [Dependency] private readonly IMapManager _mapManager; [Dependency] private readonly IRobustRandom _robustRandom; + [Dependency] private readonly IConfigurationManager _configurationManager; #pragma warning restore 649 private AudioSystem _audioSystem; @@ -78,6 +81,8 @@ namespace Content.Server.GameObjects.EntitySystems SubscribeLocalEvent(PlayerDetached); _audioSystem = EntitySystemManager.GetEntitySystem(); + + _configurationManager.RegisterCVar("game.diagonalmovement", true, CVar.ARCHIVE); } private static void PlayerAttached(PlayerAttachSystemMessage ev) From 006d0685ac6ddb0f1c101d2fde6133c6ee692588 Mon Sep 17 00:00:00 2001 From: JiimBob <44332255+JiimBob@users.noreply.github.com> Date: Wed, 25 Mar 2020 19:58:59 -0400 Subject: [PATCH 14/22] LatheComponent indentation fix Corrected indentation for the switch case. --- .../Components/Research/LatheComponent.cs | 57 ++++++++++--------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/Content.Server/GameObjects/Components/Research/LatheComponent.cs b/Content.Server/GameObjects/Components/Research/LatheComponent.cs index f06967b592..b97cc3a7cb 100644 --- a/Content.Server/GameObjects/Components/Research/LatheComponent.cs +++ b/Content.Server/GameObjects/Components/Research/LatheComponent.cs @@ -64,38 +64,39 @@ namespace Content.Server.GameObjects.Components.Research { if (!Powered) return; - switch (message.Message) - { - case LatheQueueRecipeMessage msg: - _prototypeManager.TryIndex(msg.ID, out LatheRecipePrototype recipe); - if (recipe != null) - for (var i = 0; i < msg.Quantity; i++) - { - Queue.Enqueue(recipe); - _userInterface.SendMessage(new LatheFullQueueMessage(GetIDQueue())); - } - break; - case LatheSyncRequestMessage msg: - if (!Owner.TryGetComponent(out MaterialStorageComponent storage)) return; - _userInterface.SendMessage(new LatheFullQueueMessage(GetIDQueue())); - if (_producingRecipe != null) - _userInterface.SendMessage(new LatheProducingRecipeMessage(_producingRecipe.ID)); - break; - case LatheServerSelectionMessage msg: - if (!Owner.TryGetComponent(out ResearchClientComponent researchClient)) return; - researchClient.OpenUserInterface(message.Session); - break; + switch (message.Message) + { + case LatheQueueRecipeMessage msg: + _prototypeManager.TryIndex(msg.ID, out LatheRecipePrototype recipe); + if (recipe != null) + for (var i = 0; i < msg.Quantity; i++) + { + Queue.Enqueue(recipe); + _userInterface.SendMessage(new LatheFullQueueMessage(GetIDQueue())); + } + break; + case LatheSyncRequestMessage msg: + if (!Owner.TryGetComponent(out MaterialStorageComponent storage)) return; + _userInterface.SendMessage(new LatheFullQueueMessage(GetIDQueue())); + if (_producingRecipe != null) + _userInterface.SendMessage(new LatheProducingRecipeMessage(_producingRecipe.ID)); + break; - case LatheServerSyncMessage msg: - if (!Owner.TryGetComponent(out TechnologyDatabaseComponent database) - || !Owner.TryGetComponent(out ProtolatheDatabaseComponent protoDatabase)) return; + case LatheServerSelectionMessage msg: + if (!Owner.TryGetComponent(out ResearchClientComponent researchClient)) return; + researchClient.OpenUserInterface(message.Session); + break; - if (database.SyncWithServer()) - protoDatabase.Sync(); + case LatheServerSyncMessage msg: + if (!Owner.TryGetComponent(out TechnologyDatabaseComponent database) + || !Owner.TryGetComponent(out ProtolatheDatabaseComponent protoDatabase)) return; - break; - } + if (database.SyncWithServer()) + protoDatabase.Sync(); + + break; + } } From 3b06ec8126583cd0c0e59c2a6007cb9a33d0a2df Mon Sep 17 00:00:00 2001 From: Swept Date: Wed, 25 Mar 2020 23:16:38 -0700 Subject: [PATCH 15/22] Fixed pixel aspect ratio on SMES --- .../Textures/Buildings/smes.rsi/smes-oc0.png | Bin 162 -> 127 bytes .../Textures/Buildings/smes.rsi/smes-oc1.png | Bin 171 -> 134 bytes .../Textures/Buildings/smes.rsi/smes-oc2.png | Bin 171 -> 134 bytes .../Textures/Buildings/smes.rsi/smes-og1.png | Bin 146 -> 120 bytes .../Textures/Buildings/smes.rsi/smes-og2.png | Bin 181 -> 157 bytes .../Textures/Buildings/smes.rsi/smes-og3.png | Bin 198 -> 179 bytes .../Textures/Buildings/smes.rsi/smes-og4.png | Bin 230 -> 220 bytes .../Textures/Buildings/smes.rsi/smes-og5.png | Bin 255 -> 249 bytes .../Textures/Buildings/smes.rsi/smes-op0.png | Bin 146 -> 115 bytes .../Textures/Buildings/smes.rsi/smes-op1.png | Bin 192 -> 171 bytes .../Textures/Buildings/smes.rsi/smes-op2.png | Bin 146 -> 127 bytes 11 files changed, 0 insertions(+), 0 deletions(-) diff --git a/Resources/Textures/Buildings/smes.rsi/smes-oc0.png b/Resources/Textures/Buildings/smes.rsi/smes-oc0.png index 2a8a9cb961aa4fe32964442c33884b99de43533a..2dd8b598ef0d91a97f32cd06eeae71a4c1f78cf3 100644 GIT binary patch delta 105 zcmV-v0G9uv0e_GjV*qn{dh`GQ07gkfK~z|U?b4wQ03ZxR(F>bkIzm@rc9x+SECB-~ zsZ>5-|8adaI?+)1Ue86$59{>P!y$B5Ain4(=00000 LNkvXXu0mjfM{X$Y delta 141 zcmb2D~W-DfwRCPvbaTnfr){kzMb*(fp2O+!4OXu$B>A_$q5qQ9_*ia z^Z-fi^{A7=3^PEZKGnIY2C6zI@e#M2Sjm9y+(f+XwW1fY=MrD;LTi7}r{*77ar s-7)*WsAxW4L~~yN2T--a0|tgq-I7;t_$>w+&%ofx?&{~V&MBb@0LXJTTmS$7 diff --git a/Resources/Textures/Buildings/smes.rsi/smes-oc1.png b/Resources/Textures/Buildings/smes.rsi/smes-oc1.png index 66095d016b8ac1538c24a3c6459c2dc7b796448e..32bfb2c017f491741ce2b2f0a96a7af460a44912 100644 GIT binary patch delta 113 zcmZ3@*v2?PCW~Rw+`1M91_obG7srr{#7Wsl_R5$W z#&1p6>)J5_l_u!#y;QaI?6>TvhO57NRnOl&>59&wYmEOa><)a}R|izETq@-@f9#xj R7iIuC44$rjF6*2UngDs|ES3NO delta 151 zcmV;I0BHY)0jmL!9Df1Tnobe`000SaNLh1yZ~y`T0Dp%8HU&2y00018Nkl|eG zAJ*2Rr7mIt0D!^20I##CGWy|7Wsl_R5$W z#&1p6>)J5_l_u!#y;QaI?6>TvhO57NRnOl&>59&wYmEOa><)a}R|izETq@-@f9#xj R7iIuC44$rjF6*2UngDs|ES3NO delta 151 zcmV;I0BHY)0jmL!9Df1Tnobe`000SaNLh1&pa22@0Dp%8ZY)^~00018Nkl|eG zAJ*2Rr7mIt0D!^20I##CGWy|;28I+*7srr@*0+~7@-`UoxLlNPJIN%Hb3lXVs76l15vDZB z%L_C@Cmjl!Rqd;FKQhe01q9T*CnnZS@cwYp+GsP&bZKq2h`m1EZ&=N~3Dp$4rhPxH pX#ark-+p1efT?Q7{xzInpU*71hvhWd6!?-R3}fr9CtE{-7)hm#W|B0kis z9jwHB8YnNYF)g*=nT*>ov4C0PS51~X4dRi6V9i9kCU NJYD@<);T3K0RT}cHnRW# diff --git a/Resources/Textures/Buildings/smes.rsi/smes-og3.png b/Resources/Textures/Buildings/smes.rsi/smes-og3.png index 30ea3f0722405732cf8a06f99e210b9eddd15201..0716a2643b58848da832b73a5728f6b5652faea4 100644 GIT binary patch delta 159 zcmV;Q0AT;d0kZ*+9De|FdV2H#004SPL_t(oh3(U^4S*mNgyElMZ~zN8&`li5O>_ej z9YB{k8$;~0c+r^L*HCef8~|o!W@cs|OOas`xdbQn$m~bMwIB(dYrfwV-M~m&f;*;H z51^h5Y}CLCK$V93Ylv;2xim08YanhoeM({g000SaNLh1&-~a*u0Dp%8N3omc0001ZNklaGhj!I)`+8E6pVsVFjxUqTV2SFKSoA|Tg2#Lp)0C)b}=X*@dm&Fbpss* g3`kKxWC)A`0KS18{C3gB-v9sr07*qoM6N<$f=ZJ^vj6}9 diff --git a/Resources/Textures/Buildings/smes.rsi/smes-og4.png b/Resources/Textures/Buildings/smes.rsi/smes-og4.png index 6ea122e0f47c45a8a5d55e7f82c1794363435439..ce6b70e2f0c88e1ab3e0a7c1a298669c2dfd2d93 100644 GIT binary patch delta 200 zcmV;(05|{U0o(zQ9De|FdV2H#005&&L_t(oh3%3d4gx_8Mc<&&Bq-dVPzWT3z)etG z0mUu234{xfEDAMTfCP>Im|Zf88PTw&&$Oof%}c>?9LI4S$LX11x$JNs#jfAaUXPlY zfpK_RPId`M`7ysRHE?+j*ImCFzt5Jti%3K@NJ4G>zX6^28bJsfstlMNpe+$d%z+yK z({QBth_(h6nSpDa0lRRB4M?E2_V5E)XrQd$aR5FEJTN)pB9^TH0000eM({g000SaNLh1&&;SAe0Dp%8!hFb^0001(Nkl7CNPc$ z;wTse(1P$k2$P>1&j54c8SM2Dak+68gdXU@BwYslv z5u=BNnhvlO`KExxrN0B5FMT0d4^Z`f0Fm`9!K;;&BLDyZ M07*qoM6N<$f~S8~l>h($ diff --git a/Resources/Textures/Buildings/smes.rsi/smes-og5.png b/Resources/Textures/Buildings/smes.rsi/smes-og5.png index 63579e63abe6ec99aaa4222ee4a08df8887cce00..5b58c2358d1c1c78c3aaffd76e3beca32b49a30e 100644 GIT binary patch delta 229 zcmV%t9De|FdV2H#006*AL_t(oh3%A~3IahCMbA{RDwu4u$z-qy7STU3 z`3ok0!Q`JP7QrH{$+R|;pjE8bvM$?p!!V2RPI*)2z2VHA0mCp1!!V47aY4HYU+R1d z+Pl{96d{yXU%e@?f$^&~`>ju%&pzq_*4M5FvPpl*@xB2_R$hZ=igc}Y%1qqbb1~O0@ f>WKXl8vn`{AoM$)Y88Q+00000NkvXXu0mjf41Z)~ delta 235 zcmVeM({g000SaNLh1&-~a*u0Dp%8N3omc00027NklMsf_m z&@~E1!4L&!fZ5>;_S%4`ywJ=p2BvEnUXhubfwupr#03nqC}a)-kRurWk0ypuFbYP& z-~`ldb0D{!7#VI6qlJZ<_S?MSQh>3KFnpuG0~-D?!PzcE>Y=IwoG*PLSr1hmz)&~9 li4a)fsv#MCYc!7&0|3e=Edu1Ts#5>}002ovPDHLkV1oWLV0r)m diff --git a/Resources/Textures/Buildings/smes.rsi/smes-op0.png b/Resources/Textures/Buildings/smes.rsi/smes-op0.png index 7a6e915b535e57260aa6e1b980104f9f5947ebe1..50bdab855c144a43a240b8864018e4df5682e8ad 100644 GIT binary patch delta 93 zcmV-j0HXhr0dtTXR{(Q*dh`GQ06IxTK~z|U?ao0B03j5_(0ckF)(rm7!)1d5G9l?R z(1IjMk|bRgn85Vn>q~}ICIa)vI|FB;71t9s`DqfMQsd0DRS*p2Mw+ e_H;0F`f35~qY|KuLYGDW00000044HL_t(&f$h_=4Z|=DM9~kglalZXnZg@n7cFMH z%siLIt-A;k;Qt07j|UJWNs=T4w5vY9LNs%z;3v?Bz>-c9D09Of5JzmoEeyVgGDG+fv+OPls002ovPDHLk FV1nnnKLr2) delta 172 zcmV;d08{^~0l)!}9Df1Tnobe`000SaNLh1&@Bjh;0Dp%8I|{1J0001TNkl>t%1<_AdlB|=7%}mA&U=@PRJrGMPIq8jsOaLCOn87yz-R>9W1YraK^dzV($oPFc emut((7%B%S=n_)Pi&ql>0000 Date: Fri, 27 Mar 2020 00:32:24 -0400 Subject: [PATCH 16/22] Added entity integration testing Added integration test that spawns all non-abstract entities to see if anything breaks. --- Content.IntegrationTests/Tests/EntityTest.cs | 81 ++++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 Content.IntegrationTests/Tests/EntityTest.cs diff --git a/Content.IntegrationTests/Tests/EntityTest.cs b/Content.IntegrationTests/Tests/EntityTest.cs new file mode 100644 index 0000000000..be5f5c83c5 --- /dev/null +++ b/Content.IntegrationTests/Tests/EntityTest.cs @@ -0,0 +1,81 @@ +using NUnit.Framework; +using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Map; +using Robust.Shared.Map; +using Robust.Shared.Prototypes; +using System; +using System.Collections.Generic; +using System.Threading.Tasks; +using Robust.Shared.Log; +using Robust.Server.Interfaces.Maps; +using Robust.Server.Interfaces.Timing; + +namespace Content.IntegrationTests.Tests +{ + [TestFixture] + [TestOf(typeof(Robust.Shared.GameObjects.Entity))] + public class EntityTest : ContentIntegrationTest + { + [Test] + public async Task Test() + { + var server = StartServerDummyTicker(); + await server.WaitIdleAsync(); + var mapMan = server.ResolveDependency(); + var entityMan = server.ResolveDependency(); + var prototypeMan = server.ResolveDependency(); + var mapLoader = server.ResolveDependency(); + var pauseMan = server.ResolveDependency(); + var prototypes = new List(); + IMapGrid grid = default; + IEntity testEntity = null; + + //Build up test environment + server.Post(() => + { + var mapId = mapMan.CreateMap(); + pauseMan.AddUninitializedMap(mapId); + grid = mapLoader.LoadBlueprint(mapId, "Maps/stationstation.yml"); + }); + + server.Assert(() => + { + var testLocation = new GridCoordinates(new Robust.Shared.Maths.Vector2(0, 0), grid); + + //Generate list of non-abstract prototypes to test + foreach (var prototype in prototypeMan.EnumeratePrototypes()) + { + if (prototype.Abstract) + { + continue; + } + prototypes.Add(prototype); + } + + //Iterate list of prototypes to spawn + foreach (var prototype in prototypes) + { + try + { + Logger.LogS(LogLevel.Debug, "EntityTest", "Testing: " + prototype.Name); + testEntity = entityMan.SpawnEntity(prototype.ID, testLocation); + server.RunTicks(2); + Assert.That(testEntity.Initialized); + entityMan.DeleteEntity(testEntity.Uid); + } + + //Fail any exceptions thrown on spawn + catch (Exception e) + { + Logger.LogS(LogLevel.Error, "EntityTest", "Entity '" + testEntity.Name + "' threw: " + e.Message); + Assert.Fail(); + } + } + }); + + await server.WaitIdleAsync(); + } + + } +} From c282f12edf75a4db4a4896ffd496c59c691acb1f Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Mon, 30 Mar 2020 18:34:36 +0200 Subject: [PATCH 17/22] Update submodule. --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index a21bad1f1b..7d6bc63439 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit a21bad1f1b423cd1d000eb6b69293c70614f9f15 +Subproject commit 7d6bc63439382e8c265ff29ed504bd88d2126c52 From ebe5ffe33edf5de2cb9bfb4220102a0712fd4aeb Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Mon, 30 Mar 2020 18:34:57 +0200 Subject: [PATCH 18/22] Soundfont is a word. --- SpaceStation14.sln.DotSettings | 1 + 1 file changed, 1 insertion(+) diff --git a/SpaceStation14.sln.DotSettings b/SpaceStation14.sln.DotSettings index 582298cec4..ee76b7776b 100644 --- a/SpaceStation14.sln.DotSettings +++ b/SpaceStation14.sln.DotSettings @@ -52,5 +52,6 @@ True True True + True True True From ff36b2dcc7ce5f19490ba89477dce75030e4a31d Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Mon, 30 Mar 2020 18:36:58 +0200 Subject: [PATCH 19/22] Re-enable instruments with fallback when MIDI isn't available. --- .../Instruments/InstrumentComponent.cs | 70 ++++++--- Content.Client/Instruments/InstrumentMenu.cs | 38 ++++- .../Entities/buildings/instruments.yml | 140 +++++++++--------- 3 files changed, 152 insertions(+), 96 deletions(-) diff --git a/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs b/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs index 29511ceb4d..80fc60360c 100644 --- a/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs +++ b/Content.Client/GameObjects/Components/Instruments/InstrumentComponent.cs @@ -1,6 +1,7 @@ using System; using System.Collections.Generic; using Content.Shared.GameObjects.Components.Instruments; +using JetBrains.Annotations; using Robust.Shared.GameObjects; using Robust.Client.Audio.Midi; using Robust.Shared.Audio.Midi; @@ -28,6 +29,7 @@ namespace Content.Client.GameObjects.Components.Instruments [Dependency] private readonly IGameTiming _timing; #pragma warning restore 649 + [CanBeNull] private IMidiRenderer _renderer; private int _instrumentProgram = 1; @@ -42,8 +44,14 @@ namespace Content.Client.GameObjects.Components.Instruments [ViewVariables(VVAccess.ReadWrite)] public bool LoopMidi { - get => _renderer.LoopMidi; - set => _renderer.LoopMidi = value; + get => _renderer?.LoopMidi ?? false; + set + { + if (_renderer != null) + { + _renderer.LoopMidi = value; + } + } } /// @@ -53,9 +61,13 @@ namespace Content.Client.GameObjects.Components.Instruments public int InstrumentProgram { get => _instrumentProgram; - set { + set + { _instrumentProgram = value; - _renderer.MidiProgram = _instrumentProgram; + if (_renderer != null) + { + _renderer.MidiProgram = _instrumentProgram; + } } } @@ -63,22 +75,26 @@ namespace Content.Client.GameObjects.Components.Instruments /// Whether there's a midi song being played or not. /// [ViewVariables] - public bool IsMidiOpen => _renderer.Status == MidiRendererStatus.File; + public bool IsMidiOpen => _renderer?.Status == MidiRendererStatus.File; /// /// Whether the midi renderer is listening for midi input or not. /// [ViewVariables] - public bool IsInputOpen => _renderer.Status == MidiRendererStatus.Input; + public bool IsInputOpen => _renderer?.Status == MidiRendererStatus.Input; public override void Initialize() { base.Initialize(); IoCManager.InjectDependencies(this); _renderer = _midiManager.GetNewRenderer(); - _renderer.MidiProgram = _instrumentProgram; - _renderer.TrackingEntity = Owner; - _renderer.OnMidiPlayerFinished += () => { OnMidiPlaybackEnded?.Invoke(); }; + + if (_renderer != null) + { + _renderer.MidiProgram = _instrumentProgram; + _renderer.TrackingEntity = Owner; + _renderer.OnMidiPlayerFinished += () => { OnMidiPlaybackEnded?.Invoke(); }; + } } protected override void Shutdown() @@ -93,9 +109,16 @@ namespace Content.Client.GameObjects.Components.Instruments serializer.DataField(ref _instrumentProgram, "program", 1); } - public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null, IComponent component = null) + public override void HandleMessage(ComponentMessage message, INetChannel netChannel = null, + IComponent component = null) { base.HandleMessage(message, netChannel, component); + + if (_renderer == null) + { + return; + } + switch (message) { case InstrumentMidiEventMessage midiEventMessage: @@ -107,8 +130,8 @@ namespace Content.Client.GameObjects.Components.Instruments case InstrumentStopMidiMessage _: _renderer.StopAllNotes(); - if(IsInputOpen) CloseInput(); - if(IsMidiOpen) CloseMidi(); + if (IsInputOpen) CloseInput(); + if (IsMidiOpen) CloseMidi(); break; } } @@ -116,7 +139,7 @@ namespace Content.Client.GameObjects.Components.Instruments /// public bool OpenInput() { - if (_renderer.OpenInput()) + if (_renderer != null && _renderer.OpenInput()) { _renderer.OnMidiEvent += RendererOnMidiEvent; return true; @@ -128,28 +151,37 @@ namespace Content.Client.GameObjects.Components.Instruments /// public bool CloseInput() { - if (!_renderer.CloseInput()) return false; + if (_renderer == null || !_renderer.CloseInput()) + { + return false; + } + _renderer.OnMidiEvent -= RendererOnMidiEvent; return true; - } /// public bool OpenMidi(string filename) { - if (!_renderer.OpenMidi(filename)) return false; + if (_renderer == null || !_renderer.OpenMidi(filename)) + { + return false; + } + _renderer.OnMidiEvent += RendererOnMidiEvent; return true; - } /// public bool CloseMidi() { - if (!_renderer.CloseMidi()) return false; + if (_renderer == null || !_renderer.CloseMidi()) + { + return false; + } + _renderer.OnMidiEvent -= RendererOnMidiEvent; return true; - } /// diff --git a/Content.Client/Instruments/InstrumentMenu.cs b/Content.Client/Instruments/InstrumentMenu.cs index b0880fbb48..0fb39bde2e 100644 --- a/Content.Client/Instruments/InstrumentMenu.cs +++ b/Content.Client/Instruments/InstrumentMenu.cs @@ -1,10 +1,13 @@ using Content.Client.GameObjects.Components.Instruments; +using Content.Client.UserInterface; using Robust.Client.Audio.Midi; +using Robust.Client.Graphics.Drawing; using Robust.Client.Interfaces.UserInterface; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Shared.IoC; +using Robust.Shared.Localization; using Robust.Shared.Log; using Robust.Shared.Maths; @@ -27,7 +30,7 @@ namespace Content.Client.Instruments public InstrumentMenu(InstrumentBoundUserInterface owner) { IoCManager.InjectDependencies(this); - Title = "Instrument"; + Title = Loc.GetString("Instrument"); _owner = owner; @@ -55,7 +58,7 @@ namespace Content.Client.Instruments midiInputButton = new Button() { - Text = "MIDI Input", + Text = Loc.GetString("MIDI Input"), TextAlign = Label.AlignMode.Center, SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1, @@ -73,7 +76,7 @@ namespace Content.Client.Instruments var midiFileButton = new Button() { - Text = "Open File", + Text = Loc.GetString("Play MIDI File"), TextAlign = Label.AlignMode.Center, SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1, @@ -91,7 +94,7 @@ namespace Content.Client.Instruments midiLoopButton = new Button() { - Text = "Loop", + Text = Loc.GetString("Loop"), TextAlign = Label.AlignMode.Center, SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1, @@ -110,7 +113,7 @@ namespace Content.Client.Instruments midiStopButton = new Button() { - Text = "Stop", + Text = Loc.GetString("Stop"), TextAlign = Label.AlignMode.Center, SizeFlagsHorizontal = SizeFlags.FillExpand, SizeFlagsStretchRatio = 1, @@ -132,6 +135,26 @@ namespace Content.Client.Instruments margin.AddChild(vBox); + if (!_midiManager.IsAvailable) + { + margin.AddChild(new PanelContainer + { + MouseFilter = MouseFilterMode.Stop, + PanelOverride = new StyleBoxFlat {BackgroundColor = Color.Black.WithAlpha(0.90f)}, + Children = + { + new Label + { + Align = Label.AlignMode.Center, + SizeFlagsVertical = SizeFlags.ShrinkCenter, + SizeFlagsHorizontal = SizeFlags.ShrinkCenter, + StyleClasses = {NanoStyle.StyleClassLabelBig}, + Text = Loc.GetString("MIDI support is currently\nnot available on your platform.") + } + } + }); + } + Contents.AddChild(margin); } @@ -148,7 +171,8 @@ namespace Content.Client.Instruments private async void MidiFileButtonOnOnPressed(BaseButton.ButtonEventArgs obj) { - var filename = await _fileDialogManager.OpenFile(); + var filters = new FileDialogFilters(new FileDialogFilters.Group("mid", "midi")); + var filename = await _fileDialogManager.OpenFile(filters); if (filename == null) return; @@ -160,7 +184,7 @@ namespace Content.Client.Instruments if (!_owner.Instrument.OpenMidi(filename)) return; MidiPlaybackSetButtonsDisabled(false); - if(midiInputButton.Pressed) + if (midiInputButton.Pressed) midiInputButton.Pressed = false; } diff --git a/Resources/Prototypes/Entities/buildings/instruments.yml b/Resources/Prototypes/Entities/buildings/instruments.yml index ce8cc881b9..2c6edf0355 100644 --- a/Resources/Prototypes/Entities/buildings/instruments.yml +++ b/Resources/Prototypes/Entities/buildings/instruments.yml @@ -1,70 +1,70 @@ -# - type: entity -# name: BaseInstrument -# id: BaseInstrument -# abstract: true -# components: -# - type: Instrument -# handheld: false -# -# - type: Clickable -# - type: InteractionOutline -# -# - type: Collidable -# shapes: -# - !type:PhysShapeAabb -# layer: 31 -# -# - type: SnapGrid -# offset: Center -# -# - type: Damageable -# - type: Destructible -# thresholdvalue: 50 -# -# - type: UserInterface -# interfaces: -# - key: enum.InstrumentUiKey.Key -# type: InstrumentBoundUserInterface -# -# - type: entity -# name: Piano -# parent: BaseInstrument -# id: PianoInstrument -# description: Play Needles Piano Now. -# components: -# - type: Instrument -# program: 1 -# - type: Sprite -# sprite: Objects/Instruments/musician.rsi -# state: piano -# - type: Icon -# sprite: Objects/Instruments/musician.rsi -# state: piano -# -# - type: entity -# name: Minimoog -# parent: BaseInstrument -# id: MinimoogInstrument -# components: -# - type: Instrument -# program: 7 -# - type: Sprite -# sprite: Objects/Instruments/musician.rsi -# state: minimoog -# - type: Icon -# sprite: Objects/Instruments/musician.rsi -# state: minimoog -# -# - type: entity -# name: Xylophone -# parent: BaseInstrument -# id: XylophoneInstrument -# components: -# - type: Instrument -# program: 13 -# - type: Sprite -# sprite: Objects/Instruments/musician.rsi -# state: xylophone -# - type: Icon -# sprite: Objects/Instruments/musician.rsi -# state: xylophone + - type: entity + name: BaseInstrument + id: BaseInstrument + abstract: true + components: + - type: Instrument + handheld: false + + - type: Clickable + - type: InteractionOutline + + - type: Collidable + shapes: + - !type:PhysShapeAabb + layer: 31 + + - type: SnapGrid + offset: Center + + - type: Damageable + - type: Destructible + thresholdvalue: 50 + + - type: UserInterface + interfaces: + - key: enum.InstrumentUiKey.Key + type: InstrumentBoundUserInterface + + - type: entity + name: Piano + parent: BaseInstrument + id: PianoInstrument + description: Play Needles Piano Now. + components: + - type: Instrument + program: 1 + - type: Sprite + sprite: Objects/Instruments/musician.rsi + state: piano + - type: Icon + sprite: Objects/Instruments/musician.rsi + state: piano + + - type: entity + name: Minimoog + parent: BaseInstrument + id: MinimoogInstrument + components: + - type: Instrument + program: 7 + - type: Sprite + sprite: Objects/Instruments/musician.rsi + state: minimoog + - type: Icon + sprite: Objects/Instruments/musician.rsi + state: minimoog + + - type: entity + name: Xylophone + parent: BaseInstrument + id: XylophoneInstrument + components: + - type: Instrument + program: 13 + - type: Sprite + sprite: Objects/Instruments/musician.rsi + state: xylophone + - type: Icon + sprite: Objects/Instruments/musician.rsi + state: xylophone From 5edfa2db34b4f152b35115d1c1db7fb226bff9d6 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sat, 4 Apr 2020 15:10:51 +0200 Subject: [PATCH 20/22] Re-organize style sheets and add StyleSpace. --- Content.Client/ClientContentIoC.cs | 2 + Content.Client/EntryPoint.cs | 8 +- Content.Client/EscapeMenuOwner.cs | 1 - .../Actor/CharacterInfoComponent.cs | 3 +- .../Components/Chemistry/InjectorComponent.cs | 3 +- .../Chemistry/ReagentDispenserWindow.cs | 9 +- .../MagicMirrorBoundUserInterface.cs | 7 +- .../Components/Power/ApcBoundUserInterface.cs | 9 +- .../GameObjects/Components/StackComponent.cs | 3 +- .../BallisticMagazineWeaponComponent.cs | 3 +- .../GameObjects/Components/WelderComponent.cs | 3 +- Content.Client/Instruments/InstrumentMenu.cs | 4 +- .../UserInterface/Cargo/CargoConsoleMenu.cs | 15 +-- .../UserInterface/CharacterSetupGui.cs | 9 +- .../UserInterface/Controls/HighDivider.cs | 14 +++ .../UserInterface/ItemStatusPanel.cs | 3 +- Content.Client/UserInterface/LobbyGui.cs | 17 +-- Content.Client/UserInterface/NanoHeading.cs | 3 +- .../Stylesheets/IStylesheetManager.cs | 12 ++ .../UserInterface/Stylesheets/StyleBase.cs | 47 ++++++++ .../StyleNano.cs} | 43 +++---- .../UserInterface/Stylesheets/StyleSpace.cs | 107 ++++++++++++++++++ .../Stylesheets/StylesheetManager.cs | 26 +++++ 23 files changed, 279 insertions(+), 72 deletions(-) create mode 100644 Content.Client/UserInterface/Controls/HighDivider.cs create mode 100644 Content.Client/UserInterface/Stylesheets/IStylesheetManager.cs create mode 100644 Content.Client/UserInterface/Stylesheets/StyleBase.cs rename Content.Client/UserInterface/{NanoStyle.cs => Stylesheets/StyleNano.cs} (96%) create mode 100644 Content.Client/UserInterface/Stylesheets/StyleSpace.cs create mode 100644 Content.Client/UserInterface/Stylesheets/StylesheetManager.cs diff --git a/Content.Client/ClientContentIoC.cs b/Content.Client/ClientContentIoC.cs index 6a8e9ea10a..05dfbfa957 100644 --- a/Content.Client/ClientContentIoC.cs +++ b/Content.Client/ClientContentIoC.cs @@ -6,6 +6,7 @@ using Content.Client.Interfaces.Parallax; using Content.Client.Parallax; using Content.Client.Sandbox; using Content.Client.UserInterface; +using Content.Client.UserInterface.Stylesheets; using Content.Client.Utility; using Content.Shared.Interfaces; using Robust.Shared.IoC; @@ -27,6 +28,7 @@ namespace Content.Client IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); + IoCManager.Register(); } } } diff --git a/Content.Client/EntryPoint.cs b/Content.Client/EntryPoint.cs index 8eedfcc852..5077657039 100644 --- a/Content.Client/EntryPoint.cs +++ b/Content.Client/EntryPoint.cs @@ -1,4 +1,4 @@ -using System; +using System; using Content.Client.GameObjects.Components.Actor; using Content.Client.Input; using Content.Client.Interfaces; @@ -8,6 +8,7 @@ using Content.Client.Parallax; using Content.Client.Sandbox; using Content.Client.State; using Content.Client.UserInterface; +using Content.Client.UserInterface.Stylesheets; using Content.Shared.GameObjects.Components; using Content.Shared.GameObjects.Components.Cargo; using Content.Shared.GameObjects.Components.Chemistry; @@ -167,10 +168,7 @@ namespace Content.Client IoCManager.Resolve().LoadParallax(); IoCManager.Resolve().PlayerJoinedServer += SubscribePlayerAttachmentEvents; - - var stylesheet = new NanoStyle(); - - IoCManager.Resolve().Stylesheet = stylesheet.Stylesheet; + IoCManager.Resolve().Initialize(); IoCManager.InjectDependencies(this); diff --git a/Content.Client/EscapeMenuOwner.cs b/Content.Client/EscapeMenuOwner.cs index 519d6e0692..5cbd33c1d8 100644 --- a/Content.Client/EscapeMenuOwner.cs +++ b/Content.Client/EscapeMenuOwner.cs @@ -5,7 +5,6 @@ using Robust.Client.Interfaces.Input; using Robust.Client.Interfaces.Placement; using Robust.Client.Interfaces.ResourceManagement; using Robust.Client.Interfaces.State; -using Robust.Client.State.States; using Robust.Shared.Input; using Robust.Shared.Interfaces.Configuration; using Robust.Shared.Interfaces.Map; diff --git a/Content.Client/GameObjects/Components/Actor/CharacterInfoComponent.cs b/Content.Client/GameObjects/Components/Actor/CharacterInfoComponent.cs index 18b939d90b..dfb7e3c796 100644 --- a/Content.Client/GameObjects/Components/Actor/CharacterInfoComponent.cs +++ b/Content.Client/GameObjects/Components/Actor/CharacterInfoComponent.cs @@ -1,5 +1,6 @@ using Content.Client.GameObjects.Components.Mobs; using Content.Client.UserInterface; +using Content.Client.UserInterface.Stylesheets; using Robust.Client.Interfaces.GameObjects.Components; using Robust.Client.Interfaces.ResourceManagement; using Robust.Client.UserInterface; @@ -68,7 +69,7 @@ namespace Content.Client.GameObjects.Components.Actor (SubText = new Label { SizeFlagsVertical = SizeFlags.None, - StyleClasses = {NanoStyle.StyleClassLabelSubText} + StyleClasses = {StyleNano.StyleClassLabelSubText} }) } } diff --git a/Content.Client/GameObjects/Components/Chemistry/InjectorComponent.cs b/Content.Client/GameObjects/Components/Chemistry/InjectorComponent.cs index ab1bb415d1..bc064e32e6 100644 --- a/Content.Client/GameObjects/Components/Chemistry/InjectorComponent.cs +++ b/Content.Client/GameObjects/Components/Chemistry/InjectorComponent.cs @@ -1,4 +1,5 @@ using Content.Client.UserInterface; +using Content.Client.UserInterface.Stylesheets; using Content.Client.Utility; using Robust.Shared.Timing; using Content.Shared.GameObjects.Components.Chemistry; @@ -49,7 +50,7 @@ namespace Content.Client.GameObjects.Components.Chemistry public StatusControl(InjectorComponent parent) { _parent = parent; - _label = new RichTextLabel { StyleClasses = { NanoStyle.StyleClassItemStatus } }; + _label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } }; AddChild(_label); parent._uiUpdateNeeded = true; diff --git a/Content.Client/GameObjects/Components/Chemistry/ReagentDispenserWindow.cs b/Content.Client/GameObjects/Components/Chemistry/ReagentDispenserWindow.cs index d35b18346c..8461d0ac8b 100644 --- a/Content.Client/GameObjects/Components/Chemistry/ReagentDispenserWindow.cs +++ b/Content.Client/GameObjects/Components/Chemistry/ReagentDispenserWindow.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Content.Client.UserInterface; +using Content.Client.UserInterface.Stylesheets; using Content.Shared.Chemistry; using Content.Shared.GameObjects.Components.Chemistry; using Robust.Client.Graphics.Drawing; @@ -218,7 +219,7 @@ namespace Content.Client.GameObjects.Components.Chemistry new Label { Text = $"{state.BeakerCurrentVolume}/{state.BeakerMaxVolume}", - StyleClasses = {NanoStyle.StyleClassLabelSecondaryColor} + StyleClasses = {StyleNano.StyleClassLabelSecondaryColor} } } }); @@ -247,12 +248,12 @@ namespace Content.Client.GameObjects.Components.Chemistry new Label { Text = $"{name}: ", - StyleClasses = {NanoStyle.StyleClassPowerStateGood} + StyleClasses = {StyleNano.StyleClassPowerStateGood} }, new Label { Text = $"{reagent.Quantity}u", - StyleClasses = {NanoStyle.StyleClassPowerStateGood} + StyleClasses = {StyleNano.StyleClassPowerStateGood} } } }); @@ -267,7 +268,7 @@ namespace Content.Client.GameObjects.Components.Chemistry new Label { Text = $"{reagent.Quantity}u", - StyleClasses = {NanoStyle.StyleClassLabelSecondaryColor} + StyleClasses = {StyleNano.StyleClassLabelSecondaryColor} } } }); diff --git a/Content.Client/GameObjects/Components/MagicMirrorBoundUserInterface.cs b/Content.Client/GameObjects/Components/MagicMirrorBoundUserInterface.cs index 4c9245b9b3..d6fcca29fd 100644 --- a/Content.Client/GameObjects/Components/MagicMirrorBoundUserInterface.cs +++ b/Content.Client/GameObjects/Components/MagicMirrorBoundUserInterface.cs @@ -1,6 +1,7 @@ using System; using System.Linq; using Content.Client.UserInterface; +using Content.Client.UserInterface.Stylesheets; using Content.Shared.Preferences.Appearance; using JetBrains.Annotations; using Robust.Client.GameObjects.Components.UserInterface; @@ -126,9 +127,9 @@ namespace Content.Client.GameObjects.Components var vBox = new VBoxContainer(); AddChild(vBox); - vBox.AddChild(_colorSliderR = new ColorSlider(NanoStyle.StyleClassSliderRed)); - vBox.AddChild(_colorSliderG = new ColorSlider(NanoStyle.StyleClassSliderGreen)); - vBox.AddChild(_colorSliderB = new ColorSlider(NanoStyle.StyleClassSliderBlue)); + vBox.AddChild(_colorSliderR = new ColorSlider(StyleNano.StyleClassSliderRed)); + vBox.AddChild(_colorSliderG = new ColorSlider(StyleNano.StyleClassSliderGreen)); + vBox.AddChild(_colorSliderB = new ColorSlider(StyleNano.StyleClassSliderBlue)); Action colorValueChanged = ColorValueChanged; _colorSliderR.OnValueChanged += colorValueChanged; diff --git a/Content.Client/GameObjects/Components/Power/ApcBoundUserInterface.cs b/Content.Client/GameObjects/Components/Power/ApcBoundUserInterface.cs index 0abeb69183..0d89ecfddb 100644 --- a/Content.Client/GameObjects/Components/Power/ApcBoundUserInterface.cs +++ b/Content.Client/GameObjects/Components/Power/ApcBoundUserInterface.cs @@ -1,5 +1,6 @@ using System; using Content.Client.UserInterface; +using Content.Client.UserInterface.Stylesheets; using Content.Shared.GameObjects.Components.Power; using Robust.Client.GameObjects.Components.UserInterface; using Robust.Client.Graphics.Drawing; @@ -47,15 +48,15 @@ namespace Content.Client.GameObjects.Components.Power { case ApcExternalPowerState.None: _externalPowerStateLabel.Text = "None"; - _externalPowerStateLabel.SetOnlyStyleClass(NanoStyle.StyleClassPowerStateNone); + _externalPowerStateLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateNone); break; case ApcExternalPowerState.Low: _externalPowerStateLabel.Text = "Low"; - _externalPowerStateLabel.SetOnlyStyleClass(NanoStyle.StyleClassPowerStateLow); + _externalPowerStateLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateLow); break; case ApcExternalPowerState.Good: _externalPowerStateLabel.Text = "Good"; - _externalPowerStateLabel.SetOnlyStyleClass(NanoStyle.StyleClassPowerStateGood); + _externalPowerStateLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateGood); break; default: throw new ArgumentOutOfRangeException(); @@ -140,7 +141,7 @@ namespace Content.Client.GameObjects.Components.Power var externalStatus = new HBoxContainer(); var externalStatusLabel = new Label {Text = "External Power: "}; ExternalPowerStateLabel = new Label {Text = "Good"}; - ExternalPowerStateLabel.SetOnlyStyleClass(NanoStyle.StyleClassPowerStateGood); + ExternalPowerStateLabel.SetOnlyStyleClass(StyleNano.StyleClassPowerStateGood); externalStatus.AddChild(externalStatusLabel); externalStatus.AddChild(ExternalPowerStateLabel); rows.AddChild(externalStatus); diff --git a/Content.Client/GameObjects/Components/StackComponent.cs b/Content.Client/GameObjects/Components/StackComponent.cs index 717372091a..c24b1787a5 100644 --- a/Content.Client/GameObjects/Components/StackComponent.cs +++ b/Content.Client/GameObjects/Components/StackComponent.cs @@ -1,4 +1,5 @@ using Content.Client.UserInterface; +using Content.Client.UserInterface.Stylesheets; using Content.Client.Utility; using Content.Shared.GameObjects.Components; using Robust.Client.UserInterface; @@ -38,7 +39,7 @@ namespace Content.Client.GameObjects.Components public StatusControl(StackComponent parent) { _parent = parent; - _label = new RichTextLabel {StyleClasses = {NanoStyle.StyleClassItemStatus}}; + _label = new RichTextLabel {StyleClasses = {StyleNano.StyleClassItemStatus}}; AddChild(_label); parent._uiUpdateNeeded = true; diff --git a/Content.Client/GameObjects/Components/Weapons/Ranged/BallisticMagazineWeaponComponent.cs b/Content.Client/GameObjects/Components/Weapons/Ranged/BallisticMagazineWeaponComponent.cs index 1917dbcd65..d800e7cb5e 100644 --- a/Content.Client/GameObjects/Components/Weapons/Ranged/BallisticMagazineWeaponComponent.cs +++ b/Content.Client/GameObjects/Components/Weapons/Ranged/BallisticMagazineWeaponComponent.cs @@ -1,6 +1,7 @@ using System; using Content.Client.Animations; using Content.Client.UserInterface; +using Content.Client.UserInterface.Stylesheets; using Content.Client.Utility; using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components.Weapons.Ranged; @@ -174,7 +175,7 @@ namespace Content.Client.GameObjects.Components.Weapons.Ranged (_noMagazineLabel = new Label { Text = "No Magazine!", - StyleClasses = {NanoStyle.StyleClassItemStatus} + StyleClasses = {StyleNano.StyleClassItemStatus} }) } }, diff --git a/Content.Client/GameObjects/Components/WelderComponent.cs b/Content.Client/GameObjects/Components/WelderComponent.cs index dc7387b559..e5a64d5ccb 100644 --- a/Content.Client/GameObjects/Components/WelderComponent.cs +++ b/Content.Client/GameObjects/Components/WelderComponent.cs @@ -1,5 +1,6 @@ using System; using Content.Client.UserInterface; +using Content.Client.UserInterface.Stylesheets; using Content.Client.Utility; using Content.Shared.GameObjects; using Content.Shared.GameObjects.Components; @@ -46,7 +47,7 @@ namespace Content.Client.GameObjects.Components public StatusControl(WelderComponent parent) { _parent = parent; - _label = new RichTextLabel {StyleClasses = {NanoStyle.StyleClassItemStatus}}; + _label = new RichTextLabel {StyleClasses = {StyleNano.StyleClassItemStatus}}; AddChild(_label); parent._uiUpdateNeeded = true; diff --git a/Content.Client/Instruments/InstrumentMenu.cs b/Content.Client/Instruments/InstrumentMenu.cs index 0fb39bde2e..171263e811 100644 --- a/Content.Client/Instruments/InstrumentMenu.cs +++ b/Content.Client/Instruments/InstrumentMenu.cs @@ -1,5 +1,5 @@ using Content.Client.GameObjects.Components.Instruments; -using Content.Client.UserInterface; +using Content.Client.UserInterface.Stylesheets; using Robust.Client.Audio.Midi; using Robust.Client.Graphics.Drawing; using Robust.Client.Interfaces.UserInterface; @@ -148,7 +148,7 @@ namespace Content.Client.Instruments Align = Label.AlignMode.Center, SizeFlagsVertical = SizeFlags.ShrinkCenter, SizeFlagsHorizontal = SizeFlags.ShrinkCenter, - StyleClasses = {NanoStyle.StyleClassLabelBig}, + StyleClasses = {StyleNano.StyleClassLabelBig}, Text = Loc.GetString("MIDI support is currently\nnot available on your platform.") } } diff --git a/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs b/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs index 30b8238d20..9de68993e6 100644 --- a/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs +++ b/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs @@ -9,6 +9,7 @@ using Robust.Shared.Localization; using Robust.Shared.Maths; using System; using System.Collections.Generic; +using Content.Client.UserInterface.Stylesheets; namespace Content.Client.UserInterface.Cargo { @@ -57,7 +58,7 @@ namespace Content.Client.UserInterface.Cargo var accountName = new HBoxContainer(); var accountNameLabel = new Label { Text = _loc.GetString("Account Name: "), - StyleClasses = { NanoStyle.StyleClassLabelKeyText } + StyleClasses = { StyleNano.StyleClassLabelKeyText } }; _accountNameLabel = new Label { Text = "None" //Owner.Bank.Account.Name @@ -70,7 +71,7 @@ namespace Content.Client.UserInterface.Cargo var pointsLabel = new Label { Text = _loc.GetString("Points: "), - StyleClasses = { NanoStyle.StyleClassLabelKeyText } + StyleClasses = { StyleNano.StyleClassLabelKeyText } }; _pointsLabel = new Label { @@ -84,7 +85,7 @@ namespace Content.Client.UserInterface.Cargo var shuttleStatusLabel = new Label { Text = _loc.GetString("Shuttle Status: "), - StyleClasses = { NanoStyle.StyleClassLabelKeyText } + StyleClasses = { StyleNano.StyleClassLabelKeyText } }; _shuttleStatusLabel = new Label { @@ -410,13 +411,13 @@ namespace Content.Client.UserInterface.Cargo ProductName = new Label { SizeFlagsHorizontal = SizeFlags.FillExpand, - StyleClasses = { NanoStyle.StyleClassLabelSubText }, + StyleClasses = { StyleNano.StyleClassLabelSubText }, ClipText = true }; Description = new Label { SizeFlagsHorizontal = SizeFlags.FillExpand, - StyleClasses = { NanoStyle.StyleClassLabelSubText }, + StyleClasses = { StyleNano.StyleClassLabelSubText }, ClipText = true }; vBox.AddChild(ProductName); @@ -426,14 +427,14 @@ namespace Content.Client.UserInterface.Cargo Approve = new Button { Text = "Approve", - StyleClasses = { NanoStyle.StyleClassLabelSubText } + StyleClasses = { StyleNano.StyleClassLabelSubText } }; hBox.AddChild(Approve); Cancel = new Button { Text = "Cancel", - StyleClasses = { NanoStyle.StyleClassLabelSubText } + StyleClasses = { StyleNano.StyleClassLabelSubText } }; hBox.AddChild(Cancel); diff --git a/Content.Client/UserInterface/CharacterSetupGui.cs b/Content.Client/UserInterface/CharacterSetupGui.cs index 3f4291deeb..be82a1668d 100644 --- a/Content.Client/UserInterface/CharacterSetupGui.cs +++ b/Content.Client/UserInterface/CharacterSetupGui.cs @@ -1,6 +1,7 @@ using System.Linq; using Content.Client.GameObjects.Components.Mobs; using Content.Client.Interfaces; +using Content.Client.UserInterface.Stylesheets; using Content.Client.Utility; using Content.Shared.Jobs; using Content.Shared.Preferences; @@ -67,7 +68,7 @@ namespace Content.Client.UserInterface { SizeFlagsHorizontal = SizeFlags.Expand | SizeFlags.ShrinkEnd, Text = Loc.GetString("Save and close"), - StyleClasses = {NanoStyle.StyleClassButtonBig} + StyleClasses = {StyleNano.StyleClassButtonBig} }; var topHBox = new HBoxContainer @@ -83,7 +84,7 @@ namespace Content.Client.UserInterface new Label { Text = Loc.GetString("Character Setup"), - StyleClasses = {NanoStyle.StyleClassLabelHeadingBigger}, + StyleClasses = {StyleNano.StyleClassLabelHeadingBigger}, VAlign = Label.VAlignMode.Center, SizeFlagsHorizontal = SizeFlags.Expand | SizeFlags.ShrinkCenter } @@ -99,7 +100,7 @@ namespace Content.Client.UserInterface { PanelOverride = new StyleBoxFlat { - BackgroundColor = NanoStyle.NanoGold, + BackgroundColor = StyleNano.NanoGold, ContentMarginTopOverride = 2 } }); @@ -146,7 +147,7 @@ namespace Content.Client.UserInterface hBox.AddChild(new PanelContainer { - PanelOverride = new StyleBoxFlat {BackgroundColor = NanoStyle.NanoGold}, + PanelOverride = new StyleBoxFlat {BackgroundColor = StyleNano.NanoGold}, CustomMinimumSize = (2, 0) }); _humanoidProfileEditor = new HumanoidProfileEditor(preferencesManager, prototypeManager); diff --git a/Content.Client/UserInterface/Controls/HighDivider.cs b/Content.Client/UserInterface/Controls/HighDivider.cs new file mode 100644 index 0000000000..29bdaabaee --- /dev/null +++ b/Content.Client/UserInterface/Controls/HighDivider.cs @@ -0,0 +1,14 @@ +using Content.Client.UserInterface.Stylesheets; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; + +namespace Content.Client.UserInterface.Controls +{ + public sealed class HighDivider : Control + { + public HighDivider() + { + Children.Add(new PanelContainer {StyleClasses = {StyleBase.ClassHighDivider}}); + } + } +} diff --git a/Content.Client/UserInterface/ItemStatusPanel.cs b/Content.Client/UserInterface/ItemStatusPanel.cs index e53a1cd522..fe94573a17 100644 --- a/Content.Client/UserInterface/ItemStatusPanel.cs +++ b/Content.Client/UserInterface/ItemStatusPanel.cs @@ -1,5 +1,6 @@ using System.Collections.Generic; using Content.Client.GameObjects.Components; +using Content.Client.UserInterface.Stylesheets; using Content.Client.Utility; using Robust.Client.Graphics.Drawing; using Robust.Client.UserInterface; @@ -57,7 +58,7 @@ namespace Content.Client.UserInterface (_itemNameLabel = new Label { ClipText = true, - StyleClasses = {NanoStyle.StyleClassItemStatus} + StyleClasses = {StyleNano.StyleClassItemStatus} }) } } diff --git a/Content.Client/UserInterface/LobbyGui.cs b/Content.Client/UserInterface/LobbyGui.cs index 29624b8ced..4904eb6322 100644 --- a/Content.Client/UserInterface/LobbyGui.cs +++ b/Content.Client/UserInterface/LobbyGui.cs @@ -1,5 +1,6 @@ using Content.Client.Chat; using Content.Client.Interfaces; +using Content.Client.UserInterface.Stylesheets; using Content.Client.Utility; using Robust.Client.Graphics.Drawing; using Robust.Client.Interfaces.ResourceManagement; @@ -69,7 +70,7 @@ namespace Content.Client.UserInterface new Label { Text = Loc.GetString("Lobby"), - StyleClasses = {NanoStyle.StyleClassLabelHeadingBigger}, + StyleClasses = {StyleNano.StyleClassLabelHeadingBigger}, /*MarginBottom = 40, MarginLeft = 8,*/ VAlign = Label.VAlignMode.Center @@ -78,7 +79,7 @@ namespace Content.Client.UserInterface }, (ServerName = new Label { - StyleClasses = {NanoStyle.StyleClassLabelHeadingBigger}, + StyleClasses = {StyleNano.StyleClassLabelHeadingBigger}, /*MarginBottom = 40, GrowHorizontal = GrowDirection.Both,*/ VAlign = Label.VAlignMode.Center, @@ -88,7 +89,7 @@ namespace Content.Client.UserInterface { SizeFlagsHorizontal = SizeFlags.ShrinkEnd, Text = Loc.GetString("Leave"), - StyleClasses = {NanoStyle.StyleClassButtonBig}, + StyleClasses = {StyleNano.StyleClassButtonBig}, //GrowHorizontal = GrowDirection.Begin }) } @@ -100,7 +101,7 @@ namespace Content.Client.UserInterface { PanelOverride = new StyleBoxFlat { - BackgroundColor = NanoStyle.NanoGold, + BackgroundColor = StyleNano.NanoGold, ContentMarginTopOverride = 2 }, }); @@ -146,20 +147,20 @@ namespace Content.Client.UserInterface (ObserveButton = new Button { Text = Loc.GetString("Observe"), - StyleClasses = {NanoStyle.StyleClassButtonBig} + StyleClasses = {StyleNano.StyleClassButtonBig} }), (StartTime = new Label { SizeFlagsHorizontal = SizeFlags.FillExpand, Align = Label.AlignMode.Right, FontColorOverride = Color.DarkGray, - StyleClasses = {NanoStyle.StyleClassLabelBig} + StyleClasses = {StyleNano.StyleClassLabelBig} }), (ReadyButton = new Button { ToggleMode = true, Text = Loc.GetString("Ready Up"), - StyleClasses = {NanoStyle.StyleClassButtonBig} + StyleClasses = {StyleNano.StyleClassButtonBig} }), } } @@ -188,7 +189,7 @@ namespace Content.Client.UserInterface hBox.AddChild(new PanelContainer { - PanelOverride = new StyleBoxFlat {BackgroundColor = NanoStyle.NanoGold}, CustomMinimumSize = (2, 0) + PanelOverride = new StyleBoxFlat {BackgroundColor = StyleNano.NanoGold}, CustomMinimumSize = (2, 0) }); { diff --git a/Content.Client/UserInterface/NanoHeading.cs b/Content.Client/UserInterface/NanoHeading.cs index 30dde27fc5..d0ac77e9e7 100644 --- a/Content.Client/UserInterface/NanoHeading.cs +++ b/Content.Client/UserInterface/NanoHeading.cs @@ -1,3 +1,4 @@ +using Content.Client.UserInterface.Stylesheets; using Robust.Client.UserInterface.Controls; using Robust.Shared.Maths; @@ -14,7 +15,7 @@ namespace Content.Client.UserInterface { Children = {(_label = new Label { - StyleClasses = {NanoStyle.StyleClassLabelHeading} + StyleClasses = {StyleNano.StyleClassLabelHeading} })} }; AddChild(_panel); diff --git a/Content.Client/UserInterface/Stylesheets/IStylesheetManager.cs b/Content.Client/UserInterface/Stylesheets/IStylesheetManager.cs new file mode 100644 index 0000000000..2082ffb216 --- /dev/null +++ b/Content.Client/UserInterface/Stylesheets/IStylesheetManager.cs @@ -0,0 +1,12 @@ +using Robust.Client.UserInterface; + +namespace Content.Client.UserInterface.Stylesheets +{ + public interface IStylesheetManager + { + Stylesheet SheetNano { get; } + Stylesheet SheetSpace { get; } + + void Initialize(); + } +} diff --git a/Content.Client/UserInterface/Stylesheets/StyleBase.cs b/Content.Client/UserInterface/Stylesheets/StyleBase.cs new file mode 100644 index 0000000000..10562fad2f --- /dev/null +++ b/Content.Client/UserInterface/Stylesheets/StyleBase.cs @@ -0,0 +1,47 @@ +using Content.Client.Utility; +using Robust.Client.Graphics.Drawing; +using Robust.Client.Interfaces.ResourceManagement; +using Robust.Client.UserInterface; + +namespace Content.Client.UserInterface.Stylesheets +{ + public abstract class StyleBase + { + public const string ClassHighDivider = "HighDivider"; + public const string StyleClassLabelHeading = "LabelHeading"; + public const string StyleClassLabelSubText = "LabelSubText"; + + public abstract Stylesheet Stylesheet { get; } + + protected StyleRule[] BaseRules { get; } + + protected StyleBoxTexture BaseButton { get; } + + protected StyleBase(IResourceCache resCache) + { + var notoSans12 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 12); + + // Button styles. + var buttonTex = resCache.GetTexture("/Nano/button.svg.96dpi.png"); + BaseButton = new StyleBoxTexture + { + Texture = buttonTex, + }; + BaseButton.SetPatchMargin(StyleBox.Margin.All, 10); + BaseButton.SetPadding(StyleBox.Margin.All, 1); + BaseButton.SetContentMarginOverride(StyleBox.Margin.Vertical, 2); + BaseButton.SetContentMarginOverride(StyleBox.Margin.Horizontal, 14); + + BaseRules = new[] + { + // Default font. + new StyleRule( + new SelectorElement(null, null, null, null), + new[] + { + new StyleProperty("font", notoSans12), + }), + }; + } + } +} diff --git a/Content.Client/UserInterface/NanoStyle.cs b/Content.Client/UserInterface/Stylesheets/StyleNano.cs similarity index 96% rename from Content.Client/UserInterface/NanoStyle.cs rename to Content.Client/UserInterface/Stylesheets/StyleNano.cs index 97cdd91310..e182012a55 100644 --- a/Content.Client/UserInterface/NanoStyle.cs +++ b/Content.Client/UserInterface/Stylesheets/StyleNano.cs @@ -1,29 +1,29 @@ -using Content.Client.GameObjects.EntitySystems; +using System.Linq; +using Content.Client.GameObjects.EntitySystems; using Content.Client.Utility; using Robust.Client.Graphics.Drawing; using Robust.Client.Interfaces.ResourceManagement; using Robust.Client.UserInterface; using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; -using Robust.Shared.IoC; using Robust.Shared.Maths; -namespace Content.Client.UserInterface +namespace Content.Client.UserInterface.Stylesheets { - public sealed class NanoStyle + public sealed class StyleNano : StyleBase { public const string StyleClassSliderRed = "Red"; public const string StyleClassSliderGreen = "Green"; public const string StyleClassSliderBlue = "Blue"; - public const string StyleClassLabelHeading = "LabelHeading"; public const string StyleClassLabelHeadingBigger = "LabelHeadingBigger"; - public const string StyleClassLabelSubText = "LabelSubText"; public const string StyleClassLabelKeyText = "LabelKeyText"; public const string StyleClassLabelSecondaryColor = "LabelSecondaryColor"; public const string StyleClassLabelBig = "LabelBig"; public const string StyleClassButtonBig = "ButtonBig"; + public static readonly Color NanoGold = Color.FromHex("#A88B5E"); + public static readonly Color ButtonColorDefault = Color.FromHex("#464966"); public static readonly Color ButtonColorHovered = Color.FromHex("#575b7f"); public static readonly Color ButtonColorPressed = Color.FromHex("#3e6c45"); @@ -36,12 +36,10 @@ namespace Content.Client.UserInterface public const string StyleClassItemStatus = "ItemStatus"; - public Stylesheet Stylesheet { get; } + public override Stylesheet Stylesheet { get; } - public NanoStyle() + public StyleNano(IResourceCache resCache) : base(resCache) { - var resCache = IoCManager.Resolve(); - var notoSans8 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 8); var notoSans10 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 10); var notoSans12 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 12); var notoSansBold12 = resCache.GetFont("/Nano/NotoSans/NotoSans-Bold.ttf", 12); @@ -69,16 +67,10 @@ namespace Content.Client.UserInterface var textureInvertedTriangle = resCache.GetTexture("/Nano/inverted_triangle.svg.png"); // Button styles. - var buttonTex = resCache.GetTexture("/Nano/button.svg.96dpi.png"); - var buttonNormal = new StyleBoxTexture + var buttonNormal = new StyleBoxTexture(BaseButton) { - Texture = buttonTex, Modulate = ButtonColorDefault }; - buttonNormal.SetPatchMargin(StyleBox.Margin.All, 10); - buttonNormal.SetPadding(StyleBox.Margin.All, 1); - buttonNormal.SetContentMarginOverride(StyleBox.Margin.Vertical, 2); - buttonNormal.SetContentMarginOverride(StyleBox.Margin.Horizontal, 14); var buttonHover = new StyleBoxTexture(buttonNormal) { @@ -248,16 +240,8 @@ namespace Content.Client.UserInterface var sliderFillRed = new StyleBoxTexture(sliderFillBox) {Modulate = Color.Red}; var sliderFillBlue = new StyleBoxTexture(sliderFillBox) {Modulate = Color.Blue}; - Stylesheet = new Stylesheet(new[] + Stylesheet = new Stylesheet(BaseRules.Concat(new[] { - // Default font. - new StyleRule( - new SelectorElement(null, null, null, null), - new[] - { - new StyleProperty("font", notoSans12), - }), - // Window title. new StyleRule( new SelectorElement(typeof(Label), new[] {SS14Window.StyleClassWindowTitle}, null, null), @@ -721,7 +705,12 @@ namespace Content.Client.UserInterface { new StyleProperty(Label.StylePropertyAlignMode, Label.AlignMode.Center), }), - }); + + new StyleRule(new SelectorElement(typeof(PanelContainer), new []{ ClassHighDivider}, null, null), new [] + { + new StyleProperty(PanelContainer.StylePropertyPanel, new StyleBoxFlat { BackgroundColor = NanoGold, ContentMarginBottomOverride = 2, ContentMarginLeftOverride = 2}), + }) + }).ToList()); } } } diff --git a/Content.Client/UserInterface/Stylesheets/StyleSpace.cs b/Content.Client/UserInterface/Stylesheets/StyleSpace.cs new file mode 100644 index 0000000000..9e4b318c6c --- /dev/null +++ b/Content.Client/UserInterface/Stylesheets/StyleSpace.cs @@ -0,0 +1,107 @@ +using System.Linq; +using Content.Client.Utility; +using Robust.Client.Graphics.Drawing; +using Robust.Client.Interfaces.ResourceManagement; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Shared.Maths; + +namespace Content.Client.UserInterface.Stylesheets +{ + public class StyleSpace : StyleBase + { + public static readonly Color SpaceRed = Color.FromHex("#9b2236"); + + public static readonly Color ButtonColorDefault = Color.FromHex("#464966"); + public static readonly Color ButtonColorHovered = Color.FromHex("#575b7f"); + public static readonly Color ButtonColorPressed = Color.FromHex("#3e6c45"); + public static readonly Color ButtonColorDisabled = Color.FromHex("#30313c"); + + public override Stylesheet Stylesheet { get; } + + public StyleSpace(IResourceCache resCache) : base(resCache) + { + var notoSans10 = resCache.GetFont("/Nano/NotoSans/NotoSans-Regular.ttf", 10); + var notoSansBold16 = resCache.GetFont("/Nano/NotoSans/NotoSans-Bold.ttf", 16); + + // Button styles. + var buttonNormal = new StyleBoxTexture(BaseButton) + { + Modulate = ButtonColorDefault + }; + + var buttonHover = new StyleBoxTexture(buttonNormal) + { + Modulate = ButtonColorHovered + }; + + var buttonPressed = new StyleBoxTexture(buttonNormal) + { + Modulate = ButtonColorPressed + }; + + var buttonDisabled = new StyleBoxTexture(buttonNormal) + { + Modulate = ButtonColorDisabled + }; + + + Stylesheet = new Stylesheet(BaseRules.Concat(new StyleRule[] + { + // Big Label + new StyleRule(new SelectorElement(typeof(Label), new[] {StyleClassLabelHeading}, null, null), new[] + { + new StyleProperty(Label.StylePropertyFont, notoSansBold16), + new StyleProperty(Label.StylePropertyFontColor, SpaceRed), + }), + + // Small Label + new StyleRule(new SelectorElement(typeof(Label), new[] {StyleClassLabelSubText}, null, null), new[] + { + new StyleProperty(Label.StylePropertyFont, notoSans10), + new StyleProperty(Label.StylePropertyFontColor, Color.DarkGray), + }), + + new StyleRule(new SelectorElement(typeof(PanelContainer), new[] {ClassHighDivider}, null, null), new[] + { + new StyleProperty(PanelContainer.StylePropertyPanel, + new StyleBoxFlat + { + BackgroundColor = SpaceRed, ContentMarginBottomOverride = 2, ContentMarginLeftOverride = 2 + }), + }), + + // Regular buttons! + new StyleRule(new SelectorElement(typeof(ContainerButton), new[] { ContainerButton.StyleClassButton }, null, new[] {ContainerButton.StylePseudoClassNormal}), new[] + { + new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonNormal), + }), + new StyleRule(new SelectorElement(typeof(ContainerButton), new[] { ContainerButton.StyleClassButton }, null, new[] {ContainerButton.StylePseudoClassHover}), new[] + { + new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonHover), + }), + new StyleRule(new SelectorElement(typeof(ContainerButton), new[] { ContainerButton.StyleClassButton }, null, new[] {ContainerButton.StylePseudoClassPressed}), new[] + { + new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonPressed), + }), + new StyleRule(new SelectorElement(typeof(ContainerButton), new[] { ContainerButton.StyleClassButton }, null, new[] {ContainerButton.StylePseudoClassDisabled}), new[] + { + new StyleProperty(ContainerButton.StylePropertyStyleBox, buttonDisabled), + }), + + new StyleRule(new SelectorElement(typeof(Label), new[] { Button.StyleClassButton }, null, null), new[] + { + new StyleProperty(Label.StylePropertyAlignMode, Label.AlignMode.Center), + }), + + new StyleRule(new SelectorChild( + new SelectorElement(typeof(Button), null, null, new[] {ContainerButton.StylePseudoClassDisabled}), + new SelectorElement(typeof(Label), null, null, null)), + new[] + { + new StyleProperty("font-color", Color.FromHex("#E5E5E581")), + }), + }).ToList()); + } + } +} diff --git a/Content.Client/UserInterface/Stylesheets/StylesheetManager.cs b/Content.Client/UserInterface/Stylesheets/StylesheetManager.cs new file mode 100644 index 0000000000..49147d841e --- /dev/null +++ b/Content.Client/UserInterface/Stylesheets/StylesheetManager.cs @@ -0,0 +1,26 @@ +using Robust.Client.Interfaces.ResourceManagement; +using Robust.Client.Interfaces.UserInterface; +using Robust.Client.UserInterface; +using Robust.Shared.IoC; + +namespace Content.Client.UserInterface.Stylesheets +{ + public sealed class StylesheetManager : IStylesheetManager + { +#pragma warning disable 649 + [Dependency] private readonly IUserInterfaceManager _userInterfaceManager; + [Dependency] private readonly IResourceCache _resourceCache; +#pragma warning restore 649 + + public Stylesheet SheetNano { get; private set; } + public Stylesheet SheetSpace { get; private set; } + + public void Initialize() + { + SheetNano = new StyleNano(_resourceCache).Stylesheet; + SheetSpace = new StyleSpace(_resourceCache).Stylesheet; + + _userInterfaceManager.Stylesheet = SheetNano; + } + } +} From 264891ff86811339810f41fd75f5136d48bfbfd6 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sat, 4 Apr 2020 15:11:03 +0200 Subject: [PATCH 21/22] Update submodule. --- RobustToolbox | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RobustToolbox b/RobustToolbox index 7d6bc63439..ec52102d02 160000 --- a/RobustToolbox +++ b/RobustToolbox @@ -1 +1 @@ -Subproject commit 7d6bc63439382e8c265ff29ed504bd88d2126c52 +Subproject commit ec52102d0279281a00cc1c6811330a13ddaf975b From 45e9be43ef8f384f17c0059c03d1ab42813b0714 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sat, 4 Apr 2020 15:11:28 +0200 Subject: [PATCH 22/22] Content now owns main menu and launcher connecting. --- Content.Client/EntryPoint.cs | 16 +- Content.Client/State/LauncherConnecting.cs | 230 ++++++++++++++ Content.Client/State/MainMenu.cs | 329 +++++++++++++++++++++ 3 files changed, 573 insertions(+), 2 deletions(-) create mode 100644 Content.Client/State/LauncherConnecting.cs create mode 100644 Content.Client/State/MainMenu.cs diff --git a/Content.Client/EntryPoint.cs b/Content.Client/EntryPoint.cs index 5077657039..e1b50b11e8 100644 --- a/Content.Client/EntryPoint.cs +++ b/Content.Client/EntryPoint.cs @@ -1,4 +1,4 @@ -using System; +using System; using Content.Client.GameObjects.Components.Actor; using Content.Client.Input; using Content.Client.Interfaces; @@ -18,7 +18,7 @@ using Content.Shared.GameObjects.Components.VendingMachines; using Robust.Client.Interfaces; using Robust.Client.Interfaces.Graphics.Overlays; using Robust.Client.Interfaces.Input; -using Robust.Client.Interfaces.UserInterface; +using Robust.Client.Interfaces.State; using Robust.Client.Player; using Robust.Shared.ContentPack; using Robust.Shared.Interfaces.GameObjects; @@ -36,6 +36,8 @@ namespace Content.Client [Dependency] private readonly IPlayerManager _playerManager; [Dependency] private readonly IBaseClient _baseClient; [Dependency] private readonly IEscapeMenuOwner _escapeMenuOwner; + [Dependency] private readonly IGameController _gameController; + [Dependency] private readonly IStateManager _stateManager; #pragma warning restore 649 public override void Init() @@ -223,6 +225,16 @@ namespace Content.Client IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); IoCManager.Resolve().Initialize(); + + // Fire off into state dependent on launcher or not. + if (_gameController.LaunchState.FromLauncher) + { + _stateManager.RequestStateChange(); + } + else + { + _stateManager.RequestStateChange(); + } } public override void Update(ModUpdateLevel level, FrameEventArgs frameEventArgs) diff --git a/Content.Client/State/LauncherConnecting.cs b/Content.Client/State/LauncherConnecting.cs new file mode 100644 index 0000000000..df1af3c6dc --- /dev/null +++ b/Content.Client/State/LauncherConnecting.cs @@ -0,0 +1,230 @@ +using Content.Client.UserInterface.Controls; +using Content.Client.UserInterface.Stylesheets; +using Content.Client.Utility; +using Robust.Client.Graphics.Drawing; +using Robust.Client.Interfaces; +using Robust.Client.Interfaces.UserInterface; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Shared.Interfaces.Network; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Maths; +using static Content.Client.StaticIoC; + +namespace Content.Client.State +{ + public class LauncherConnecting : Robust.Client.State.State + { +#pragma warning disable 649 + [Dependency] private readonly IUserInterfaceManager _userInterfaceManager; + [Dependency] private readonly IStylesheetManager _stylesheetManager; + [Dependency] private readonly IClientNetManager _clientNetManager; + [Dependency] private readonly IGameController _gameController; +#pragma warning restore 649 + + private Control _control; + private Label _connectStatus; + + public override void Startup() + { + var panelTex = ResC.GetTexture("/Nano/button.svg.96dpi.png"); + var back = new StyleBoxTexture + { + Texture = panelTex, + Modulate = new Color(32, 32, 48), + }; + back.SetPatchMargin(StyleBox.Margin.All, 10); + + Button exitButton; + Label connectFailReason; + Control connectingStatus; + + var address = _gameController.LaunchState.Ss14Address ?? _gameController.LaunchState.ConnectAddress; + + _control = new Control + { + Stylesheet = _stylesheetManager.SheetSpace, + Children = + { + new PanelContainer + { + PanelOverride = back + }, + new VBoxContainer + { + SeparationOverride = 0, + CustomMinimumSize = (300, 200), + Children = + { + new HBoxContainer + { + Children = + { + new MarginContainer + { + MarginLeftOverride = 8, + Children = + { + new Label + { + Text = Loc.GetString("Space Station 14"), + StyleClasses = {StyleBase.StyleClassLabelHeading}, + VAlign = Label.VAlignMode.Center + }, + } + }, + + (exitButton = new Button + { + Text = Loc.GetString("Exit"), + SizeFlagsHorizontal = Control.SizeFlags.ShrinkEnd | Control.SizeFlags.Expand + }), + } + }, + + // Line + new HighDivider(), + + new MarginContainer + { + SizeFlagsVertical = Control.SizeFlags.FillExpand, + MarginLeftOverride = 4, + MarginRightOverride = 4, + MarginTopOverride = 4, + Children = + { + new VBoxContainer + { + SeparationOverride = 0, + Children = + { + new Control + { + Children = + { + (connectingStatus = new VBoxContainer + { + SeparationOverride = 0, + Children = + { + new Label + { + Text = Loc.GetString("Connecting to server..."), + Align = Label.AlignMode.Center, + }, + + (_connectStatus = new Label + { + StyleClasses = {StyleBase.StyleClassLabelSubText}, + Align = Label.AlignMode.Center, + }), + } + }), + (connectFailReason = new Label + { + Align = Label.AlignMode.Center + }) + } + }, + + // Padding. + new Control {CustomMinimumSize = (0, 8)}, + + new Label + { + Text = address, + StyleClasses = {StyleBase.StyleClassLabelSubText}, + SizeFlagsHorizontal = Control.SizeFlags.ShrinkCenter, + SizeFlagsVertical = + Control.SizeFlags.ShrinkEnd | Control.SizeFlags.Expand, + } + } + }, + } + }, + + // Line + new PanelContainer + { + PanelOverride = new StyleBoxFlat + { + BackgroundColor = Color.FromHex("#444"), + ContentMarginTopOverride = 2 + }, + }, + + new MarginContainer + { + MarginLeftOverride = 12, + MarginRightOverride = 4, + Children = + { + new HBoxContainer + { + SizeFlagsVertical = Control.SizeFlags.ShrinkEnd, + Children = + { + new Label + { + Text = Loc.GetString("Don't die!"), + StyleClasses = {StyleBase.StyleClassLabelSubText} + }, + new Label + { + Text = "ver 0.1", + SizeFlagsHorizontal = + Control.SizeFlags.Expand | Control.SizeFlags.ShrinkEnd, + StyleClasses = {StyleBase.StyleClassLabelSubText} + } + } + } + } + }, + } + }, + } + }; + + _userInterfaceManager.StateRoot.AddChild(_control); + + LayoutContainer.SetAnchorPreset(_control, LayoutContainer.LayoutPreset.Center); + LayoutContainer.SetGrowHorizontal(_control, LayoutContainer.GrowDirection.Both); + LayoutContainer.SetGrowVertical(_control, LayoutContainer.GrowDirection.Both); + + exitButton.OnPressed += args => + { + _gameController.Shutdown("Exit button pressed"); + }; + + _clientNetManager.ConnectFailed += (sender, args) => + { + connectFailReason.Text = Loc.GetString("Failed to connect to server:\n{0}", args.Reason); + connectingStatus.Visible = false; + connectFailReason.Visible = true; + }; + + _clientNetManager.ClientConnectStateChanged += ConnectStateChanged; + + ConnectStateChanged(_clientNetManager.ClientConnectState); + } + + private void ConnectStateChanged(ClientConnectionState state) + { + _connectStatus.Text = Loc.GetString(state switch + { + ClientConnectionState.NotConnecting => "Not connecting?", + ClientConnectionState.ResolvingHost => "Resolving server address...", + ClientConnectionState.EstablishingConnection => "Establishing initial connection...", + ClientConnectionState.Handshake => "Doing handshake...", + ClientConnectionState.Connected => "Synchronizing game state...", + _ => state.ToString() + }); + } + + public override void Shutdown() + { + _control.Dispose(); + } + } +} diff --git a/Content.Client/State/MainMenu.cs b/Content.Client/State/MainMenu.cs new file mode 100644 index 0000000000..1157e9907b --- /dev/null +++ b/Content.Client/State/MainMenu.cs @@ -0,0 +1,329 @@ +using System; +using System.Text.RegularExpressions; +using Robust.Client; +using Robust.Client.Interfaces; +using Robust.Client.Interfaces.ResourceManagement; +using Robust.Client.Interfaces.UserInterface; +using Robust.Client.ResourceManagement; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.Interfaces.Configuration; +using Robust.Shared.Interfaces.Network; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Log; +using Robust.Shared.Network; +using Robust.Shared.Utility; + +namespace Content.Client.State +{ + /// + /// Main menu screen that is the first screen to be displayed when the game starts. + /// + // Instantiated dynamically through the StateManager, Dependencies will be resolved. + public class MainScreen : Robust.Client.State.State + { + private const string PublicServerAddress = "server.spacestation14.io"; + +#pragma warning disable 649 + [Dependency] private readonly IBaseClient _client; + [Dependency] private readonly IClientNetManager _netManager; + [Dependency] private readonly IConfigurationManager _configurationManager; + [Dependency] private readonly IGameController _controllerProxy; + [Dependency] private readonly ILocalizationManager _loc; + [Dependency] private readonly IResourceCache _resourceCache; + [Dependency] private readonly IUserInterfaceManager userInterfaceManager; +#pragma warning restore 649 + + private MainMenuControl _mainMenuControl; + private OptionsMenu OptionsMenu; + private bool _isConnecting; + + // ReSharper disable once InconsistentNaming + private static readonly Regex IPv6Regex = new Regex(@"\[(.*:.*:.*)](?::(\d+))?"); + + /// + public override void Startup() + { + _mainMenuControl = new MainMenuControl(_resourceCache, _configurationManager); + userInterfaceManager.StateRoot.AddChild(_mainMenuControl); + + _mainMenuControl.QuitButton.OnPressed += QuitButtonPressed; + _mainMenuControl.OptionsButton.OnPressed += OptionsButtonPressed; + _mainMenuControl.DirectConnectButton.OnPressed += DirectConnectButtonPressed; + _mainMenuControl.JoinPublicServerButton.OnPressed += JoinPublicServerButtonPressed; + _mainMenuControl.AddressBox.OnTextEntered += AddressBoxEntered; + + _client.RunLevelChanged += RunLevelChanged; + + OptionsMenu = new OptionsMenu(_configurationManager); + } + + /// + public override void Shutdown() + { + _client.RunLevelChanged -= RunLevelChanged; + _netManager.ConnectFailed -= _onConnectFailed; + + _mainMenuControl.Dispose(); + OptionsMenu.Dispose(); + } + + private void QuitButtonPressed(BaseButton.ButtonEventArgs args) + { + _controllerProxy.Shutdown(); + } + + private void OptionsButtonPressed(BaseButton.ButtonEventArgs args) + { + OptionsMenu.OpenCentered(); + } + + private void DirectConnectButtonPressed(BaseButton.ButtonEventArgs args) + { + var input = _mainMenuControl.AddressBox; + TryConnect(input.Text); + } + + private void JoinPublicServerButtonPressed(BaseButton.ButtonEventArgs args) + { + TryConnect(PublicServerAddress); + } + + private void AddressBoxEntered(LineEdit.LineEditEventArgs args) + { + if (_isConnecting) + { + return; + } + + TryConnect(args.Text); + } + + private void TryConnect(string address) + { + var inputName = _mainMenuControl.UserNameBox.Text.Trim(); + var (nameValid, invalidReason) = UsernameHelpers.IsNameValid(inputName); + if (!nameValid) + { + invalidReason = _loc.GetString(invalidReason); + userInterfaceManager.Popup( + _loc.GetString("Invalid username:\n{0}", invalidReason), + _loc.GetString("Invalid Username")); + return; + } + + var configName = _configurationManager.GetCVar("player.name"); + if (_mainMenuControl.UserNameBox.Text != configName) + { + _configurationManager.SetCVar("player.name", inputName); + _configurationManager.SaveToFile(); + } + + _setConnectingState(true); + _netManager.ConnectFailed += _onConnectFailed; + try + { + ParseAddress(address, out var ip, out var port); + _client.ConnectToServer(ip, port); + } + catch (ArgumentException e) + { + userInterfaceManager.Popup($"Unable to connect: {e.Message}", "Connection error."); + Logger.Warning(e.ToString()); + _netManager.ConnectFailed -= _onConnectFailed; + } + } + + private void RunLevelChanged(object obj, RunLevelChangedEventArgs args) + { + if (args.NewLevel == ClientRunLevel.Initialize) + { + _setConnectingState(false); + _netManager.ConnectFailed -= _onConnectFailed; + } + } + + private void ParseAddress(string address, out string ip, out ushort port) + { + var match6 = IPv6Regex.Match(address); + if (match6 != Match.Empty) + { + ip = match6.Groups[1].Value; + if (!match6.Groups[2].Success) + { + port = _client.DefaultPort; + } + else if (!ushort.TryParse(match6.Groups[2].Value, out port)) + { + throw new ArgumentException("Not a valid port."); + } + + return; + } + + // See if the IP includes a port. + var split = address.Split(':'); + ip = address; + port = _client.DefaultPort; + if (split.Length > 2) + { + throw new ArgumentException("Not a valid Address."); + } + + // IP:port format. + if (split.Length == 2) + { + ip = split[0]; + if (!ushort.TryParse(split[1], out port)) + { + throw new ArgumentException("Not a valid port."); + } + } + } + + private void _onConnectFailed(object _, NetConnectFailArgs args) + { + userInterfaceManager.Popup($"Failed to connect:\n{args.Reason}"); + _netManager.ConnectFailed -= _onConnectFailed; + _setConnectingState(false); + } + + private void _setConnectingState(bool state) + { + _isConnecting = state; + _mainMenuControl.DirectConnectButton.Disabled = state; +#if FULL_RELEASE + _mainMenuControl.JoinPublicServerButton.Disabled = state; +#endif + } + + private sealed class MainMenuControl : Control + { + private readonly IResourceCache _resourceCache; + private readonly IConfigurationManager _configurationManager; + + public LineEdit UserNameBox { get; private set; } + public Button JoinPublicServerButton { get; private set; } + public LineEdit AddressBox { get; private set; } + public Button DirectConnectButton { get; private set; } + public Button OptionsButton { get; private set; } + public Button QuitButton { get; private set; } + public Label VersionLabel { get; private set; } + + public MainMenuControl(IResourceCache resCache, IConfigurationManager configMan) + { + _resourceCache = resCache; + _configurationManager = configMan; + + PerformLayout(); + } + + private void PerformLayout() + { + LayoutContainer.SetAnchorPreset(this, LayoutContainer.LayoutPreset.Wide); + + var layout = new LayoutContainer(); + AddChild(layout); + + var vBox = new VBoxContainer + { + StyleIdentifier = "mainMenuVBox" + }; + + layout.AddChild(vBox); + LayoutContainer.SetAnchorPreset(vBox, LayoutContainer.LayoutPreset.TopRight); + LayoutContainer.SetMarginRight(vBox, -25); + LayoutContainer.SetMarginTop(vBox, 30); + LayoutContainer.SetGrowHorizontal(vBox, LayoutContainer.GrowDirection.Begin); + + var logoTexture = _resourceCache.GetResource("/Textures/Logo/logo.png"); + var logo = new TextureRect + { + Texture = logoTexture, + Stretch = TextureRect.StretchMode.KeepCentered, + }; + vBox.AddChild(logo); + + var userNameHBox = new HBoxContainer {SeparationOverride = 4}; + vBox.AddChild(userNameHBox); + userNameHBox.AddChild(new Label {Text = "Username:"}); + + var currentUserName = _configurationManager.GetCVar("player.name"); + UserNameBox = new LineEdit + { + Text = currentUserName, PlaceHolder = "Username", + SizeFlagsHorizontal = SizeFlags.FillExpand + }; + + userNameHBox.AddChild(UserNameBox); + + JoinPublicServerButton = new Button + { + Text = "Join Public Server", + StyleIdentifier = "mainMenu", + TextAlign = Label.AlignMode.Center, +#if !FULL_RELEASE + Disabled = true, + ToolTip = "Cannot connect to public server with a debug build." +#endif + }; + + vBox.AddChild(JoinPublicServerButton); + + // Separator. + vBox.AddChild(new Control {CustomMinimumSize = (0, 2)}); + + AddressBox = new LineEdit + { + Text = "localhost", + PlaceHolder = "server address:port", + SizeFlagsHorizontal = SizeFlags.FillExpand + }; + + vBox.AddChild(AddressBox); + + DirectConnectButton = new Button + { + Text = "Direct Connect", + TextAlign = Label.AlignMode.Center, + StyleIdentifier = "mainMenu", + }; + + vBox.AddChild(DirectConnectButton); + + // Separator. + vBox.AddChild(new Control {CustomMinimumSize = (0, 2)}); + + OptionsButton = new Button + { + Text = "Options", + TextAlign = Label.AlignMode.Center, + StyleIdentifier = "mainMenu", + }; + + vBox.AddChild(OptionsButton); + + QuitButton = new Button + { + Text = "Quit", + TextAlign = Label.AlignMode.Center, + StyleIdentifier = "mainMenu", + }; + + vBox.AddChild(QuitButton); + + VersionLabel = new Label + { + Text = $"v0.1" + }; + + LayoutContainer.SetAnchorPreset(VersionLabel, LayoutContainer.LayoutPreset.BottomRight); + LayoutContainer.SetGrowHorizontal(VersionLabel, LayoutContainer.GrowDirection.Begin); + LayoutContainer.SetGrowVertical(VersionLabel, LayoutContainer.GrowDirection.Begin); + layout.AddChild(VersionLabel); + } + } + } +}