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(); 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/ClientContentIoC.cs b/Content.Client/ClientContentIoC.cs index 24f1738d00..690de5c18a 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.Chemistry; using Content.Shared.Interfaces; @@ -29,6 +30,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..e1b50b11e8 100644 --- a/Content.Client/EntryPoint.cs +++ b/Content.Client/EntryPoint.cs @@ -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; @@ -17,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; @@ -35,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() @@ -167,10 +170,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); @@ -225,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/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 1d1a7f5dcb..272a67d964 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; @@ -50,7 +51,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 e9c8903de3..997b487560 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/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/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/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/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.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/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/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 b0880fbb48..171263e811 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.Stylesheets; 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 = {StyleNano.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/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); + } + } + } +} diff --git a/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs b/Content.Client/UserInterface/Cargo/CargoConsoleMenu.cs index 53b350bdd0..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 { @@ -345,14 +346,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 +365,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 +394,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); @@ -415,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); @@ -431,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 ca738faeb3..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 } }); @@ -141,11 +142,12 @@ namespace Content.Client.UserInterface { preferencesManager.CreateCharacter(HumanoidCharacterProfile.Default()); UpdateUI(); + args.Event.Handle(); }; hBox.AddChild(new PanelContainer { - PanelOverride = new StyleBoxFlat {BackgroundColor = NanoStyle.NanoGold}, + PanelOverride = new StyleBoxFlat {BackgroundColor = StyleNano.NanoGold}, CustomMinimumSize = (2, 0) }); _humanoidProfileEditor = new HumanoidProfileEditor(preferencesManager, prototypeManager); @@ -179,13 +181,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 +198,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 +208,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,22 +222,13 @@ 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 { Sprite = _previewDummy.GetComponent(), Scale = (2, 2), - MouseFilter = MouseFilterMode.Ignore, OverrideDirection = Direction.South }; @@ -264,7 +261,6 @@ namespace Content.Client.UserInterface var internalHBox = new HBoxContainer { SizeFlagsHorizontal = SizeFlags.FillExpand, - MouseFilter = MouseFilterMode.Ignore, SeparationOverride = 0, Children = { 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/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/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/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); 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 94% rename from Content.Client/UserInterface/NanoStyle.cs rename to Content.Client/UserInterface/Stylesheets/StyleNano.cs index bd5bd73a60..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), @@ -307,19 +291,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), }), @@ -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; + } + } +} 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(); + } + + } +} 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); } diff --git a/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs b/Content.Server/GameObjects/Components/Chemistry/ReagentDispenserComponent.cs index 78d22c0f65..a24cd3078a 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/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/Components/Research/LatheComponent.cs b/Content.Server/GameObjects/Components/Research/LatheComponent.cs index d08a471024..b97cc3a7cb 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,20 +36,35 @@ 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) { + if (!Powered) + return; + switch (message.Message) { case LatheQueueRecipeMessage msg: @@ -71,13 +90,15 @@ namespace Content.Server.GameObjects.Components.Research case LatheServerSyncMessage msg: if (!Owner.TryGetComponent(out TechnologyDatabaseComponent database) - || !Owner.TryGetComponent(out ProtolatheDatabaseComponent protoDatabase)) return; + || !Owner.TryGetComponent(out ProtolatheDatabaseComponent protoDatabase)) return; - if(database.SyncWithServer()) + if (database.SyncWithServer()) protoDatabase.Sync(); break; } + + } internal bool Produce(LatheRecipePrototype recipe) @@ -100,12 +121,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 +151,6 @@ namespace Content.Server.GameObjects.Components.Research return; } OpenUserInterface(actor.playerSession); - return; } bool IAttackBy.AttackBy(AttackByEventArgs eventArgs) { @@ -151,15 +176,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 +217,12 @@ namespace Content.Server.GameObjects.Components.Research return queue; } + + protected enum LatheState + { + Base, + Inserting, + Producing + } } } 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/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) 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/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/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 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/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 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/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" 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 diff --git a/Resources/Textures/Buildings/smes.rsi/smes-oc0.png b/Resources/Textures/Buildings/smes.rsi/smes-oc0.png index 2a8a9cb961..2dd8b598ef 100644 Binary files a/Resources/Textures/Buildings/smes.rsi/smes-oc0.png and b/Resources/Textures/Buildings/smes.rsi/smes-oc0.png differ diff --git a/Resources/Textures/Buildings/smes.rsi/smes-oc1.png b/Resources/Textures/Buildings/smes.rsi/smes-oc1.png index 66095d016b..32bfb2c017 100644 Binary files a/Resources/Textures/Buildings/smes.rsi/smes-oc1.png and b/Resources/Textures/Buildings/smes.rsi/smes-oc1.png differ diff --git a/Resources/Textures/Buildings/smes.rsi/smes-oc2.png b/Resources/Textures/Buildings/smes.rsi/smes-oc2.png index 2b39f4a827..32bfb2c017 100644 Binary files a/Resources/Textures/Buildings/smes.rsi/smes-oc2.png and b/Resources/Textures/Buildings/smes.rsi/smes-oc2.png differ diff --git a/Resources/Textures/Buildings/smes.rsi/smes-og1.png b/Resources/Textures/Buildings/smes.rsi/smes-og1.png index 741ed22138..de43a4325e 100644 Binary files a/Resources/Textures/Buildings/smes.rsi/smes-og1.png and b/Resources/Textures/Buildings/smes.rsi/smes-og1.png differ diff --git a/Resources/Textures/Buildings/smes.rsi/smes-og2.png b/Resources/Textures/Buildings/smes.rsi/smes-og2.png index 0db9f1a6ef..fe80c8d645 100644 Binary files a/Resources/Textures/Buildings/smes.rsi/smes-og2.png and b/Resources/Textures/Buildings/smes.rsi/smes-og2.png differ diff --git a/Resources/Textures/Buildings/smes.rsi/smes-og3.png b/Resources/Textures/Buildings/smes.rsi/smes-og3.png index 30ea3f0722..0716a2643b 100644 Binary files a/Resources/Textures/Buildings/smes.rsi/smes-og3.png and b/Resources/Textures/Buildings/smes.rsi/smes-og3.png differ diff --git a/Resources/Textures/Buildings/smes.rsi/smes-og4.png b/Resources/Textures/Buildings/smes.rsi/smes-og4.png index 6ea122e0f4..ce6b70e2f0 100644 Binary files a/Resources/Textures/Buildings/smes.rsi/smes-og4.png and b/Resources/Textures/Buildings/smes.rsi/smes-og4.png differ diff --git a/Resources/Textures/Buildings/smes.rsi/smes-og5.png b/Resources/Textures/Buildings/smes.rsi/smes-og5.png index 63579e63ab..5b58c2358d 100644 Binary files a/Resources/Textures/Buildings/smes.rsi/smes-og5.png and b/Resources/Textures/Buildings/smes.rsi/smes-og5.png differ diff --git a/Resources/Textures/Buildings/smes.rsi/smes-op0.png b/Resources/Textures/Buildings/smes.rsi/smes-op0.png index 7a6e915b53..50bdab855c 100644 Binary files a/Resources/Textures/Buildings/smes.rsi/smes-op0.png and b/Resources/Textures/Buildings/smes.rsi/smes-op0.png differ diff --git a/Resources/Textures/Buildings/smes.rsi/smes-op1.png b/Resources/Textures/Buildings/smes.rsi/smes-op1.png index b98f33d5c6..ec45e860a8 100644 Binary files a/Resources/Textures/Buildings/smes.rsi/smes-op1.png and b/Resources/Textures/Buildings/smes.rsi/smes-op1.png differ diff --git a/Resources/Textures/Buildings/smes.rsi/smes-op2.png b/Resources/Textures/Buildings/smes.rsi/smes-op2.png index 55ce2f53f5..eb2e2ff6ff 100644 Binary files a/Resources/Textures/Buildings/smes.rsi/smes-op2.png and b/Resources/Textures/Buildings/smes.rsi/smes-op2.png differ 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