Viewport improvements (#3765)
This commit is contained in:
committed by
GitHub
parent
8e2fc49357
commit
147a54c642
@@ -28,9 +28,9 @@ namespace Content.Client.Atmos
|
||||
_atmosDebugOverlaySystem = EntitySystem.Get<AtmosDebugOverlaySystem>();
|
||||
}
|
||||
|
||||
protected override void Draw(DrawingHandleBase handle, OverlaySpace overlay)
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
var drawHandle = (DrawingHandleWorld) handle;
|
||||
var drawHandle = args.WorldHandle;
|
||||
|
||||
var mapId = _eyeManager.CurrentMap;
|
||||
var eye = _eyeManager.CurrentEye;
|
||||
|
||||
@@ -25,9 +25,9 @@ namespace Content.Client.Atmos
|
||||
_gasTileOverlaySystem = EntitySystem.Get<GasTileOverlaySystem>();
|
||||
}
|
||||
|
||||
protected override void Draw(DrawingHandleBase handle, OverlaySpace overlay)
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
var drawHandle = (DrawingHandleWorld) handle;
|
||||
var drawHandle = args.WorldHandle;
|
||||
|
||||
var mapId = _eyeManager.CurrentMap;
|
||||
var eye = _eyeManager.CurrentEye;
|
||||
|
||||
@@ -47,6 +47,7 @@ namespace Content.Client
|
||||
IoCManager.Register<EuiManager, EuiManager>();
|
||||
IoCManager.Register<IVoteManager, VoteManager>();
|
||||
IoCManager.Register<ChangelogManager, ChangelogManager>();
|
||||
IoCManager.Register<ViewportManager, ViewportManager>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.State;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
@@ -100,6 +101,7 @@ namespace Content.Client
|
||||
IoCManager.Resolve<IStylesheetManager>().Initialize();
|
||||
IoCManager.Resolve<IScreenshotHook>().Initialize();
|
||||
IoCManager.Resolve<ChangelogManager>().Initialize();
|
||||
IoCManager.Resolve<ViewportManager>().Initialize();
|
||||
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
@@ -183,6 +185,9 @@ namespace Content.Client
|
||||
}
|
||||
};
|
||||
|
||||
// Disable engine-default viewport since we use our own custom viewport control.
|
||||
IoCManager.Resolve<IUserInterfaceManager>().MainViewport.Visible = false;
|
||||
|
||||
SwitchToDefaultState();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,28 +11,23 @@ namespace Content.Client.GameObjects.Components
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
private const float DefaultWidth = 1;
|
||||
private const string ShaderInRange = "SelectionOutlineInrange";
|
||||
private const string ShaderOutOfRange = "SelectionOutline";
|
||||
|
||||
public override string Name => "InteractionOutline";
|
||||
|
||||
private ShaderInstance? _selectionShaderInstance;
|
||||
private ShaderInstance? _selectionShaderInRangeInstance;
|
||||
private bool _inRange;
|
||||
private ShaderInstance? _shader;
|
||||
private int _lastRenderScale;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_selectionShaderInRangeInstance = _prototypeManager.Index<ShaderPrototype>(ShaderInRange).Instance();
|
||||
_selectionShaderInstance = _prototypeManager.Index<ShaderPrototype>(ShaderOutOfRange).Instance();
|
||||
}
|
||||
|
||||
public void OnMouseEnter(bool inInteractionRange)
|
||||
public void OnMouseEnter(bool inInteractionRange, int renderScale)
|
||||
{
|
||||
_lastRenderScale = renderScale;
|
||||
_inRange = inInteractionRange;
|
||||
if (Owner.TryGetComponent(out ISpriteComponent? sprite))
|
||||
{
|
||||
sprite.PostShader = inInteractionRange ? _selectionShaderInRangeInstance : _selectionShaderInstance;
|
||||
sprite.PostShader = MakeNewShader(inInteractionRange, renderScale);
|
||||
sprite.RenderOrder = Owner.EntityManager.CurrentTick.Value;
|
||||
}
|
||||
}
|
||||
@@ -44,14 +39,30 @@ namespace Content.Client.GameObjects.Components
|
||||
sprite.PostShader = null;
|
||||
sprite.RenderOrder = 0;
|
||||
}
|
||||
|
||||
_shader?.Dispose();
|
||||
_shader = null;
|
||||
}
|
||||
|
||||
public void UpdateInRange(bool inInteractionRange)
|
||||
public void UpdateInRange(bool inInteractionRange, int renderScale)
|
||||
{
|
||||
if (Owner.TryGetComponent(out ISpriteComponent? sprite))
|
||||
if (Owner.TryGetComponent(out ISpriteComponent? sprite)
|
||||
&& (inInteractionRange != _inRange || _lastRenderScale != renderScale))
|
||||
{
|
||||
sprite.PostShader = inInteractionRange ? _selectionShaderInRangeInstance : _selectionShaderInstance;
|
||||
_inRange = inInteractionRange;
|
||||
_lastRenderScale = renderScale;
|
||||
_shader = MakeNewShader(_inRange, _lastRenderScale);
|
||||
sprite.PostShader = _shader;
|
||||
}
|
||||
}
|
||||
|
||||
private ShaderInstance MakeNewShader(bool inRange, int renderScale)
|
||||
{
|
||||
var shaderName = inRange ? ShaderInRange : ShaderOutOfRange;
|
||||
|
||||
var instance = _prototypeManager.Index<ShaderPrototype>(shaderName).InstanceUnique();
|
||||
instance.SetParameter("outline_width", DefaultWidth * renderScale);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,17 +35,7 @@ namespace Content.Client.GameObjects.Components.Suspicion
|
||||
_font = new VectorFont(resourceCache.GetResource<FontResource>("/Fonts/NotoSans/NotoSans-Regular.ttf"), 10);
|
||||
}
|
||||
|
||||
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
|
||||
{
|
||||
switch (currentSpace)
|
||||
{
|
||||
case OverlaySpace.ScreenSpace:
|
||||
DrawScreen((DrawingHandleScreen) handle);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawScreen(DrawingHandleScreen screen)
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
var viewport = _eyeManager.GetWorldViewport();
|
||||
|
||||
@@ -91,8 +81,8 @@ namespace Content.Client.GameObjects.Components.Suspicion
|
||||
continue;
|
||||
}
|
||||
|
||||
var screenCoordinates = _eyeManager.WorldToScreen(physics.GetWorldAABB().TopLeft + (0, 0.5f));
|
||||
DrawString(screen, _font, screenCoordinates, _traitorText, Color.OrangeRed);
|
||||
var screenCoordinates = args.ViewportControl!.WorldToScreen(physics.GetWorldAABB().TopLeft + (0, 0.5f));
|
||||
DrawString(args.ScreenHandle, _font, screenCoordinates, _traitorText, Color.OrangeRed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -464,15 +464,15 @@ namespace Content.Client.GameObjects.EntitySystems.AI
|
||||
|
||||
#endregion
|
||||
|
||||
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (Modes == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
handle.UseShader(_shader);
|
||||
var screenHandle = (DrawingHandleScreen) handle;
|
||||
var screenHandle = args.ScreenHandle;
|
||||
screenHandle.UseShader(_shader);
|
||||
var viewport = _eyeManager.GetWorldViewport();
|
||||
|
||||
if ((Modes & PathfindingDebugMode.Route) != 0)
|
||||
|
||||
@@ -10,6 +10,7 @@ using Content.Shared;
|
||||
using Content.Shared.GameObjects.Verbs;
|
||||
using Content.Shared.Input;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.State;
|
||||
@@ -35,6 +36,7 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
|
||||
private readonly IContextMenuView _contextMenuView;
|
||||
private readonly VerbSystem _verbSystem;
|
||||
@@ -152,7 +154,14 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
{
|
||||
var inRange =
|
||||
localPlayer.InRangeUnobstructed(e.ContextEntity, ignoreInsideBlocker: true);
|
||||
e.OutlineComponent?.UpdateInRange(inRange);
|
||||
|
||||
// BUG: This assumes that the main viewport is the viewport that the context menu is active on.
|
||||
// This is not necessarily true but we currently have no way to find the viewport (reliably)
|
||||
// from the input event.
|
||||
//
|
||||
// This might be particularly important in the future with a more advanced mapping mode.
|
||||
var renderScale = _eyeManager.MainViewport.GetRenderScale();
|
||||
e.OutlineComponent?.UpdateInRange(inRange, renderScale);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +179,8 @@ namespace Content.Client.GameObjects.EntitySystems
|
||||
var localPlayer = _playerManager.LocalPlayer;
|
||||
if (localPlayer?.ControlledEntity == null) return;
|
||||
|
||||
e.OutlineComponent?.OnMouseEnter(localPlayer.InRangeUnobstructed(entity, ignoreInsideBlocker: true));
|
||||
var renderScale = _eyeManager.MainViewport.GetRenderScale();
|
||||
e.OutlineComponent?.OnMouseEnter(localPlayer.InRangeUnobstructed(entity, ignoreInsideBlocker: true), renderScale);
|
||||
if (e.SpriteComp != null)
|
||||
{
|
||||
e.SpriteComp.DrawDepth = (int) Shared.GameObjects.DrawDepth.HighlightedItems;
|
||||
|
||||
@@ -22,12 +22,14 @@ namespace Content.Client.Graphics.Overlays
|
||||
_shader = _prototypeManager.Index<ShaderPrototype>("CircleMask").Instance();
|
||||
}
|
||||
|
||||
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (!CritOverlay.LocalPlayerHasState(_playerManager, false, true))
|
||||
return;
|
||||
handle.UseShader(_shader);
|
||||
var worldHandle = (DrawingHandleWorld)handle;
|
||||
|
||||
|
||||
var worldHandle = args.WorldHandle;
|
||||
worldHandle.UseShader(_shader);
|
||||
var viewport = _eyeManager.GetWorldViewport();
|
||||
worldHandle.DrawRect(viewport, Color.White);
|
||||
}
|
||||
|
||||
@@ -22,10 +22,10 @@ namespace Content.Client.Graphics.Overlays
|
||||
_shader = _prototypeManager.Index<ShaderPrototype>("ColoredScreenBorder").Instance();
|
||||
}
|
||||
|
||||
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
handle.UseShader(_shader);
|
||||
var worldHandle = (DrawingHandleWorld)handle;
|
||||
var worldHandle = args.WorldHandle;
|
||||
worldHandle.UseShader(_shader);
|
||||
var viewport = _eyeManager.GetWorldViewport();
|
||||
worldHandle.DrawRect(viewport, Color.White);
|
||||
}
|
||||
|
||||
@@ -45,14 +45,14 @@ namespace Content.Client.Graphics.Overlays
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (!LocalPlayerHasState(_playerManager, true, false))
|
||||
return;
|
||||
|
||||
var worldHandle = (DrawingHandleWorld) handle;
|
||||
var worldHandle = args.WorldHandle;
|
||||
var viewport = _eyeManager.GetWorldViewport();
|
||||
handle.UseShader(_gradientCircleShader);
|
||||
worldHandle.UseShader(_gradientCircleShader);
|
||||
worldHandle.DrawRect(viewport, Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Content.Client.State;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.State;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
@@ -14,6 +16,7 @@ namespace Content.Client.Graphics.Overlays
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IClyde _displayManager = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly IStateManager _stateManager = default!;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.ScreenSpace;
|
||||
private readonly ShaderInstance _shader;
|
||||
@@ -29,29 +32,34 @@ namespace Content.Client.Graphics.Overlays
|
||||
|
||||
public void ReceiveFlash(double duration)
|
||||
{
|
||||
_displayManager.Screenshot(ScreenshotType.BeforeUI, image =>
|
||||
if (_stateManager.CurrentState is IMainViewportState state)
|
||||
{
|
||||
var rgba32Image = image.CloneAs<Rgba32>(Configuration.Default);
|
||||
_screenshotTexture = _displayManager.LoadTextureFromImage(rgba32Image);
|
||||
});
|
||||
state.Viewport.Viewport.Screenshot(image =>
|
||||
{
|
||||
var rgba32Image = image.CloneAs<Rgba32>(Configuration.Default);
|
||||
_screenshotTexture = _displayManager.LoadTextureFromImage(rgba32Image);
|
||||
});
|
||||
}
|
||||
|
||||
_startTime = _gameTiming.CurTime.TotalSeconds;
|
||||
_lastsFor = duration;
|
||||
}
|
||||
|
||||
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
var percentComplete = (float) ((_gameTiming.CurTime.TotalSeconds - _startTime) / _lastsFor);
|
||||
if (percentComplete >= 1.0f)
|
||||
return;
|
||||
handle.UseShader(_shader);
|
||||
_shader?.SetParameter("percentComplete", percentComplete);
|
||||
|
||||
var screenSpaceHandle = handle as DrawingHandleScreen;
|
||||
var screenSpaceHandle = args.ScreenHandle;
|
||||
screenSpaceHandle.UseShader(_shader);
|
||||
_shader.SetParameter("percentComplete", percentComplete);
|
||||
|
||||
var screenSize = UIBox2.FromDimensions((0, 0), _displayManager.ScreenSize);
|
||||
|
||||
if (_screenshotTexture != null)
|
||||
{
|
||||
screenSpaceHandle?.DrawTextureRect(_screenshotTexture, screenSize);
|
||||
screenSpaceHandle.DrawTextureRect(_screenshotTexture, screenSize);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ namespace Content.Client.Graphics.Overlays
|
||||
return _singularities.Count() > 0;
|
||||
}
|
||||
|
||||
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
SingularityQuery();
|
||||
|
||||
@@ -52,8 +52,8 @@ namespace Content.Client.Graphics.Overlays
|
||||
_shader?.SetParameter("intensity", LevelToIntensity(instance.Level));
|
||||
_shader?.SetParameter("falloff", LevelToFalloff(instance.Level));
|
||||
|
||||
handle.UseShader(_shader);
|
||||
var worldHandle = (DrawingHandleWorld) handle;
|
||||
var worldHandle = args.WorldHandle;
|
||||
worldHandle.UseShader(_shader);
|
||||
var viewport = _eyeManager.GetWorldViewport();
|
||||
worldHandle.DrawRect(viewport, Color.White);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using Content.Client.Interfaces.Parallax;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
@@ -18,7 +19,7 @@ namespace Content.Client.Parallax
|
||||
|
||||
private Texture? _parallaxTexture;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.ScreenSpaceBelowWorld;
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowWorld;
|
||||
private readonly ShaderInstance _shader;
|
||||
|
||||
public ParallaxOverlay()
|
||||
@@ -36,26 +37,36 @@ namespace Content.Client.Parallax
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (_parallaxTexture == null)
|
||||
if (_parallaxTexture == null || args.Viewport.Eye == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
handle.UseShader(_shader);
|
||||
var screenHandle = (DrawingHandleScreen) handle;
|
||||
var screenHandle = args.WorldHandle;
|
||||
screenHandle.UseShader(_shader);
|
||||
|
||||
var (sizeX, sizeY) = _parallaxTexture.Size;
|
||||
var (posX, posY) = _eyeManager.ScreenToMap(Vector2.Zero).Position;
|
||||
var (ox, oy) = (Vector2i) new Vector2(-posX / Slowness, posY / Slowness);
|
||||
ox = MathHelper.Mod(ox, sizeX);
|
||||
oy = MathHelper.Mod(oy, sizeY);
|
||||
var (sizeX, sizeY) = _parallaxTexture.Size / (float) EyeManager.PixelsPerMeter;
|
||||
var (posX, posY) = args.Viewport.Eye.Position;
|
||||
var o = new Vector2(posX * Slowness, posY * Slowness);
|
||||
|
||||
var (screenSizeX, screenSizeY) = _displayManager.ScreenSize;
|
||||
for (var x = -sizeX; x < screenSizeX; x += sizeX) {
|
||||
for (var y = -sizeY; y < screenSizeY; y += sizeY) {
|
||||
screenHandle.DrawTexture(_parallaxTexture, new Vector2(ox + x, oy + y));
|
||||
// Remove offset so we can floor.
|
||||
var (l, b) = args.WorldBounds.BottomLeft - o;
|
||||
|
||||
// Floor to background size.
|
||||
l = sizeX * MathF.Floor(l / sizeX);
|
||||
b = sizeY * MathF.Floor(b / sizeY);
|
||||
|
||||
// Re-offset.
|
||||
l += o.X;
|
||||
b += o.Y;
|
||||
|
||||
for (var x = l; x < args.WorldBounds.Right; x += sizeX)
|
||||
{
|
||||
for (var y = b; y < args.WorldBounds.Top; y += sizeY)
|
||||
{
|
||||
screenHandle.DrawTexture(_parallaxTexture, (x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Client.State;
|
||||
using Content.Shared.Input;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.State;
|
||||
using Robust.Shared.ContentPack;
|
||||
using Robust.Shared.Input.Binding;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Utility;
|
||||
using SixLabors.ImageSharp;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace Content.Client
|
||||
{
|
||||
@@ -20,24 +23,30 @@ namespace Content.Client
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
[Dependency] private readonly IClyde _clyde = default!;
|
||||
[Dependency] private readonly IResourceManager _resourceManager = default!;
|
||||
[Dependency] private readonly IStateManager _stateManager = default!;
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_inputManager.SetInputCommand(ContentKeyFunctions.TakeScreenshot, InputCmdHandler.FromDelegate(_ =>
|
||||
{
|
||||
Take(ScreenshotType.AfterUI);
|
||||
_clyde.Screenshot(ScreenshotType.Final, Take);
|
||||
}));
|
||||
|
||||
_inputManager.SetInputCommand(ContentKeyFunctions.TakeScreenshotNoUI, InputCmdHandler.FromDelegate(_ =>
|
||||
{
|
||||
Take(ScreenshotType.BeforeUI);
|
||||
if (_stateManager.CurrentState is IMainViewportState state)
|
||||
{
|
||||
state.Viewport.Viewport.Screenshot(Take);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.InfoS("screenshot", "Can't take no-UI screenshot: current state is not GameScreen");
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
private async void Take(ScreenshotType type)
|
||||
private async void Take<T>(Image<T> screenshot) where T : unmanaged, IPixel<T>
|
||||
{
|
||||
var screenshot = await _clyde.ScreenshotAsync(type);
|
||||
|
||||
var time = DateTime.Now.ToString("yyyy-M-dd_HH.mm.ss");
|
||||
|
||||
if (!_resourceManager.UserData.IsDir(BaseScreenshotPath))
|
||||
|
||||
@@ -6,6 +6,7 @@ using Content.Client.UserInterface;
|
||||
using Content.Client.Voting;
|
||||
using Content.Shared;
|
||||
using Content.Shared.Input;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
@@ -13,12 +14,16 @@ using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Input.Binding;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Client.State
|
||||
{
|
||||
public class GameScreen : GameScreenBase
|
||||
public class GameScreen : GameScreenBase, IMainViewportState
|
||||
{
|
||||
public static readonly Vector2i ViewportSize = (EyeManager.PixelsPerMeter * 21, EyeManager.PixelsPerMeter * 15);
|
||||
|
||||
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
|
||||
[Dependency] private readonly IGameHud _gameHud = default!;
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
@@ -26,6 +31,8 @@ namespace Content.Client.State
|
||||
[Dependency] private readonly IVoteManager _voteManager = default!;
|
||||
[Dependency] private readonly IConfigurationManager _configurationManager = default!;
|
||||
[Dependency] private readonly IClientAdminManager _adminManager = default!;
|
||||
[Dependency] private readonly IClyde _clyde = default!;
|
||||
[Dependency] private readonly IEyeManager _eyeManager = default!;
|
||||
|
||||
[ViewVariables] private ChatBox? _gameChat;
|
||||
private ConstructionMenuPresenter? _constructionMenu;
|
||||
@@ -33,15 +40,27 @@ namespace Content.Client.State
|
||||
private bool _oocEnabled;
|
||||
private bool _adminOocEnabled;
|
||||
|
||||
public MainViewport Viewport { get; private set; } = default!;
|
||||
|
||||
public override void Startup()
|
||||
{
|
||||
base.Startup();
|
||||
|
||||
_gameChat = new ChatBox();
|
||||
Viewport = new MainViewport
|
||||
{
|
||||
Viewport =
|
||||
{
|
||||
ViewportSize = ViewportSize
|
||||
}
|
||||
};
|
||||
|
||||
_userInterfaceManager.StateRoot.AddChild(Viewport);
|
||||
LayoutContainer.SetAnchorPreset(Viewport, LayoutContainer.LayoutPreset.Wide);
|
||||
Viewport.SetPositionFirst();
|
||||
|
||||
_userInterfaceManager.StateRoot.AddChild(_gameChat);
|
||||
LayoutContainer.SetAnchorAndMarginPreset(_gameChat, LayoutContainer.LayoutPreset.TopRight, margin: 10);
|
||||
LayoutContainer.SetAnchorAndMarginPreset(_gameChat, LayoutContainer.LayoutPreset.TopRight, margin: 10);
|
||||
LayoutContainer.SetMarginLeft(_gameChat, -475);
|
||||
LayoutContainer.SetMarginBottom(_gameChat, 235);
|
||||
|
||||
@@ -65,6 +84,8 @@ namespace Content.Client.State
|
||||
_adminManager.AdminStatusUpdated += OnAdminStatusUpdated;
|
||||
|
||||
SetupPresenters();
|
||||
|
||||
_eyeManager.MainViewport = Viewport.Viewport;
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
@@ -74,7 +95,10 @@ namespace Content.Client.State
|
||||
base.Shutdown();
|
||||
|
||||
_gameChat?.Dispose();
|
||||
Viewport.Dispose();
|
||||
_gameHud.RootControl.Orphan();
|
||||
// Clear viewport to some fallback, whatever.
|
||||
_eyeManager.MainViewport = _userInterfaceManager.MainViewport;
|
||||
|
||||
}
|
||||
|
||||
@@ -168,5 +192,12 @@ namespace Content.Client.State
|
||||
chat.Input.GrabKeyboardFocus();
|
||||
chat.Input.InsertAtCursor("]");
|
||||
}
|
||||
|
||||
public override void FrameUpdate(FrameEventArgs e)
|
||||
{
|
||||
base.FrameUpdate(e);
|
||||
|
||||
Viewport.Viewport.Eye = _eyeManager.CurrentEye;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,14 +2,15 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Linq;
|
||||
using Content.Client.GameObjects.Components;
|
||||
using Content.Client.UserInterface;
|
||||
using Content.Client.Utility;
|
||||
using Content.Shared;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.State;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Input;
|
||||
@@ -28,7 +29,6 @@ namespace Content.Client.State
|
||||
[Dependency] protected readonly IClientEntityManager EntityManager = default!;
|
||||
[Dependency] protected readonly IInputManager InputManager = default!;
|
||||
[Dependency] protected readonly IPlayerManager PlayerManager = default!;
|
||||
[Dependency] protected readonly IEyeManager EyeManager = default!;
|
||||
[Dependency] protected readonly IEntitySystemManager EntitySystemManager = default!;
|
||||
[Dependency] protected readonly IGameTiming Timing = default!;
|
||||
[Dependency] protected readonly IMapManager MapManager = default!;
|
||||
@@ -68,10 +68,18 @@ namespace Content.Client.State
|
||||
if (localPlayer == null)
|
||||
return;
|
||||
|
||||
var mousePosWorld = EyeManager.ScreenToMap(InputManager.MouseScreenPosition);
|
||||
var entityToClick = UserInterfaceManager.CurrentlyHovered != null
|
||||
? null
|
||||
: GetEntityUnderPosition(mousePosWorld);
|
||||
IEntity? entityToClick = null;
|
||||
var renderScale = 1;
|
||||
if (UserInterfaceManager.CurrentlyHovered is IViewportControl vp)
|
||||
{
|
||||
var mousePosWorld = vp.ScreenToMap(InputManager.MouseScreenPosition);
|
||||
entityToClick = GetEntityUnderPosition(mousePosWorld);
|
||||
|
||||
if (vp is ScalingViewport svp)
|
||||
{
|
||||
renderScale = svp.CurrentRenderScale;
|
||||
}
|
||||
}
|
||||
|
||||
var inRange = false;
|
||||
if (localPlayer.ControlledEntity != null && entityToClick != null)
|
||||
@@ -93,7 +101,7 @@ namespace Content.Client.State
|
||||
{
|
||||
if (entityToClick != null && entityToClick.TryGetComponent(out outline))
|
||||
{
|
||||
outline.UpdateInRange(inRange);
|
||||
outline.UpdateInRange(inRange, renderScale);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -109,7 +117,7 @@ namespace Content.Client.State
|
||||
|
||||
if (_lastHoveredEntity != null && _lastHoveredEntity.TryGetComponent(out outline))
|
||||
{
|
||||
outline.OnMouseEnter(inRange);
|
||||
outline.OnMouseEnter(inRange, renderScale);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,30 +214,36 @@ namespace Content.Client.State
|
||||
/// Converts a state change event from outside the simulation to inside the simulation.
|
||||
/// </summary>
|
||||
/// <param name="args">Event data values for a bound key state change.</param>
|
||||
private void OnKeyBindStateChanged(BoundKeyEventArgs args)
|
||||
private void OnKeyBindStateChanged(ViewportBoundKeyEventArgs args)
|
||||
{
|
||||
// If there is no InputSystem, then there is nothing to forward to, and nothing to do here.
|
||||
if(!EntitySystemManager.TryGetEntitySystem(out InputSystem inputSys))
|
||||
return;
|
||||
|
||||
var func = args.Function;
|
||||
var kArgs = args.KeyEventArgs;
|
||||
var func = kArgs.Function;
|
||||
var funcId = InputManager.NetworkBindMap.KeyFunctionID(func);
|
||||
|
||||
var mousePosWorld = EyeManager.ScreenToMap(args.PointerLocation);
|
||||
var entityToClick = GetEntityUnderPosition(mousePosWorld);
|
||||
EntityCoordinates coordinates = default;
|
||||
EntityUid entityToClick = default;
|
||||
if (args.Viewport is IViewportControl vp)
|
||||
{
|
||||
var mousePosWorld = vp.ScreenToMap(kArgs.PointerLocation.Position);
|
||||
entityToClick = GetEntityUnderPosition(mousePosWorld)?.Uid ?? EntityUid.Invalid;
|
||||
|
||||
var coordinates = MapManager.TryFindGridAt(mousePosWorld, out var grid) ? grid.MapToGrid(mousePosWorld) :
|
||||
EntityCoordinates.FromMap(EntityManager, MapManager, mousePosWorld);
|
||||
coordinates = MapManager.TryFindGridAt(mousePosWorld, out var grid) ? grid.MapToGrid(mousePosWorld) :
|
||||
EntityCoordinates.FromMap(EntityManager, MapManager, mousePosWorld);
|
||||
}
|
||||
|
||||
var message = new FullInputCmdMessage(Timing.CurTick, Timing.TickFraction, funcId, args.State,
|
||||
coordinates , args.PointerLocation,
|
||||
entityToClick?.Uid ?? EntityUid.Invalid);
|
||||
var message = new FullInputCmdMessage(Timing.CurTick, Timing.TickFraction, funcId, kArgs.State,
|
||||
coordinates , kArgs.PointerLocation,
|
||||
entityToClick);
|
||||
|
||||
// client side command handlers will always be sent the local player session.
|
||||
var session = PlayerManager.LocalPlayer?.Session;
|
||||
if (inputSys.HandleInputCommand(session, func, message))
|
||||
{
|
||||
args.Handle();
|
||||
kArgs.Handle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
15
Content.Client/State/IMainViewport.cs
Normal file
15
Content.Client/State/IMainViewport.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Content.Client.UserInterface;
|
||||
|
||||
namespace Content.Client.State
|
||||
{
|
||||
/// <summary>
|
||||
/// Client state that has a main viewport.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Used for taking no-UI screenshots (including things like flash overlay).
|
||||
/// </remarks>
|
||||
public interface IMainViewportState
|
||||
{
|
||||
public MainViewport Viewport { get; }
|
||||
}
|
||||
}
|
||||
@@ -1,251 +1,81 @@
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Client.UserInterface.Stylesheets;
|
||||
using Content.Client.Utility;
|
||||
using System;
|
||||
using Content.Client.UserInterface;
|
||||
using Robust.Client;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Network;
|
||||
using static Content.Client.StaticIoC;
|
||||
|
||||
namespace Content.Client.State
|
||||
{
|
||||
public class LauncherConnecting : Robust.Client.State.State
|
||||
{
|
||||
[Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
|
||||
[Dependency] private readonly IStylesheetManager _stylesheetManager = default!;
|
||||
[Dependency] private readonly IClientNetManager _clientNetManager = default!;
|
||||
[Dependency] private readonly IGameController _gameController = default!;
|
||||
[Dependency] private readonly IBaseClient _baseClient = default!;
|
||||
|
||||
private Control? _control;
|
||||
private Label? _connectStatus;
|
||||
private LauncherConnectingGui? _control;
|
||||
|
||||
private Control? _connectingStatus;
|
||||
private Control? _connectFail;
|
||||
private Label? _connectFailReason;
|
||||
private Control? _disconnected;
|
||||
private Page _currentPage;
|
||||
private string? _connectFailReason;
|
||||
|
||||
public string? Address => _gameController.LaunchState.Ss14Address ?? _gameController.LaunchState.ConnectAddress;
|
||||
|
||||
public string? ConnectFailReason
|
||||
{
|
||||
get => _connectFailReason;
|
||||
private set
|
||||
{
|
||||
_connectFailReason = value;
|
||||
ConnectFailReasonChanged?.Invoke(value);
|
||||
}
|
||||
}
|
||||
|
||||
public Page CurrentPage
|
||||
{
|
||||
get => _currentPage;
|
||||
private set
|
||||
{
|
||||
_currentPage = value;
|
||||
PageChanged?.Invoke(value);
|
||||
}
|
||||
}
|
||||
|
||||
public ClientConnectionState ConnectionState => _clientNetManager.ClientConnectState;
|
||||
|
||||
public event Action<Page>? PageChanged;
|
||||
public event Action<string?>? ConnectFailReasonChanged;
|
||||
public event Action<ClientConnectionState>? ConnectionStateChanged;
|
||||
|
||||
public override void Startup()
|
||||
{
|
||||
Button exitButton;
|
||||
Button reconnectButton;
|
||||
Button retryButton;
|
||||
|
||||
var address = _gameController.LaunchState.Ss14Address ?? _gameController.LaunchState.ConnectAddress;
|
||||
|
||||
_control = new Control
|
||||
{
|
||||
Stylesheet = _stylesheetManager.SheetSpace,
|
||||
Children =
|
||||
{
|
||||
new PanelContainer {StyleClasses = {StyleBase.ClassAngleRect}},
|
||||
new VBoxContainer
|
||||
{
|
||||
SeparationOverride = 0,
|
||||
MinSize = (300, 200),
|
||||
Children =
|
||||
{
|
||||
new HBoxContainer
|
||||
{
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
Margin = new Thickness(8, 0, 0, 0),
|
||||
Text = Loc.GetString("Space Station 14"),
|
||||
StyleClasses = {StyleBase.StyleClassLabelHeading},
|
||||
VAlign = Label.VAlignMode.Center
|
||||
},
|
||||
|
||||
(exitButton = new Button
|
||||
{
|
||||
Text = Loc.GetString("Exit"),
|
||||
HorizontalAlignment = Control.HAlignment.Right,
|
||||
HorizontalExpand = true,
|
||||
}),
|
||||
}
|
||||
},
|
||||
|
||||
// Line
|
||||
new HighDivider(),
|
||||
|
||||
new VBoxContainer
|
||||
{
|
||||
VerticalExpand = true,
|
||||
Margin = new Thickness(4, 4, 4, 0),
|
||||
SeparationOverride = 0,
|
||||
Children =
|
||||
{
|
||||
new Control
|
||||
{
|
||||
VerticalExpand = true,
|
||||
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,
|
||||
}),
|
||||
}
|
||||
}),
|
||||
(_connectFail = new VBoxContainer
|
||||
{
|
||||
Visible = false,
|
||||
SeparationOverride = 0,
|
||||
Children =
|
||||
{
|
||||
(_connectFailReason = new Label
|
||||
{
|
||||
Align = Label.AlignMode.Center
|
||||
}),
|
||||
|
||||
(retryButton = new Button
|
||||
{
|
||||
Text = "Retry",
|
||||
HorizontalAlignment = Control.HAlignment.Center,
|
||||
VerticalExpand = true,
|
||||
VerticalAlignment = Control.VAlignment.Bottom,
|
||||
})
|
||||
}
|
||||
}),
|
||||
|
||||
(_disconnected = new VBoxContainer
|
||||
{
|
||||
SeparationOverride = 0,
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
Text = "Disconnected from server:",
|
||||
Align = Label.AlignMode.Center
|
||||
},
|
||||
new Label
|
||||
{
|
||||
Text = _baseClient.LastDisconnectReason,
|
||||
Align = Label.AlignMode.Center
|
||||
},
|
||||
(reconnectButton = new Button
|
||||
{
|
||||
Text = "Reconnect",
|
||||
HorizontalAlignment = Control.HAlignment.Center,
|
||||
VerticalExpand = true,
|
||||
VerticalAlignment = Control.VAlignment.Bottom,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
// Padding.
|
||||
new Control {MinSize = (0, 8)},
|
||||
|
||||
new Label
|
||||
{
|
||||
Text = address,
|
||||
StyleClasses = {StyleBase.StyleClassLabelSubText},
|
||||
HorizontalAlignment = Control.HAlignment.Center
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Line
|
||||
new PanelContainer
|
||||
{
|
||||
PanelOverride = new StyleBoxFlat
|
||||
{
|
||||
BackgroundColor = Color.FromHex("#444"),
|
||||
ContentMarginTopOverride = 2
|
||||
},
|
||||
},
|
||||
new HBoxContainer
|
||||
{
|
||||
Margin = new Thickness(12, 0, 4, 0),
|
||||
VerticalAlignment = Control.VAlignment.Bottom,
|
||||
Children =
|
||||
{
|
||||
new Label
|
||||
{
|
||||
Text = Loc.GetString("Don't die!"),
|
||||
StyleClasses = {StyleBase.StyleClassLabelSubText}
|
||||
},
|
||||
new Label
|
||||
{
|
||||
Text = "ver 0.1",
|
||||
HorizontalExpand = true,
|
||||
HorizontalAlignment = Control.HAlignment.Right,
|
||||
StyleClasses = {StyleBase.StyleClassLabelSubText}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
};
|
||||
_control = new LauncherConnectingGui(this);
|
||||
|
||||
_userInterfaceManager.StateRoot.AddChild(_control);
|
||||
|
||||
LayoutContainer.SetAnchorPreset(_control, LayoutContainer.LayoutPreset.Center);
|
||||
LayoutContainer.SetGrowHorizontal(_control, LayoutContainer.GrowDirection.Both);
|
||||
LayoutContainer.SetGrowVertical(_control, LayoutContainer.GrowDirection.Both);
|
||||
|
||||
exitButton.OnPressed += _ =>
|
||||
{
|
||||
_gameController.Shutdown("Exit button pressed");
|
||||
};
|
||||
|
||||
void Retry(BaseButton.ButtonEventArgs args)
|
||||
{
|
||||
if (_gameController.LaunchState.ConnectEndpoint != null)
|
||||
{
|
||||
_baseClient.ConnectToServer(_gameController.LaunchState.ConnectEndpoint);
|
||||
SetActivePage(Page.Connecting);
|
||||
}
|
||||
}
|
||||
|
||||
reconnectButton.OnPressed += Retry;
|
||||
retryButton.OnPressed += Retry;
|
||||
|
||||
_clientNetManager.ConnectFailed += (_, args) =>
|
||||
{
|
||||
_connectFailReason.Text = Loc.GetString("Failed to connect to server:\n{0}", args.Reason);
|
||||
SetActivePage(Page.ConnectFailed);
|
||||
ConnectFailReason = args.Reason;
|
||||
CurrentPage = Page.ConnectFailed;
|
||||
};
|
||||
|
||||
_clientNetManager.ClientConnectStateChanged += ConnectStateChanged;
|
||||
_clientNetManager.ClientConnectStateChanged += state => ConnectionStateChanged?.Invoke(state);
|
||||
|
||||
SetActivePage(Page.Connecting);
|
||||
|
||||
ConnectStateChanged(_clientNetManager.ClientConnectState);
|
||||
CurrentPage = Page.Connecting;
|
||||
}
|
||||
|
||||
private void ConnectStateChanged(ClientConnectionState state)
|
||||
public void RetryConnect()
|
||||
{
|
||||
if (_connectStatus == null) return;
|
||||
|
||||
_connectStatus.Text = Loc.GetString(state switch
|
||||
if (_gameController.LaunchState.ConnectEndpoint != null)
|
||||
{
|
||||
ClientConnectionState.NotConnecting => "You should not be seeing this",
|
||||
ClientConnectionState.ResolvingHost => "Resolving server address...",
|
||||
ClientConnectionState.EstablishingConnection => "Establishing initial connection...",
|
||||
ClientConnectionState.Handshake => "Doing handshake...",
|
||||
ClientConnectionState.Connected => "Synchronizing game state...",
|
||||
_ => state.ToString()
|
||||
});
|
||||
_baseClient.ConnectToServer(_gameController.LaunchState.ConnectEndpoint);
|
||||
CurrentPage = Page.Connecting;
|
||||
}
|
||||
}
|
||||
|
||||
public void Exit()
|
||||
{
|
||||
_gameController.Shutdown("Exit button pressed");
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
@@ -255,17 +85,10 @@ namespace Content.Client.State
|
||||
|
||||
public void SetDisconnected()
|
||||
{
|
||||
SetActivePage(Page.Disconnected);
|
||||
CurrentPage = Page.Disconnected;
|
||||
}
|
||||
|
||||
private void SetActivePage(Page page)
|
||||
{
|
||||
if (_connectingStatus != null) _connectingStatus.Visible = page == Page.Connecting;
|
||||
if (_connectFail != null) _connectFail.Visible = page == Page.ConnectFailed;
|
||||
if (_disconnected != null) _disconnected.Visible = page == Page.Disconnected;
|
||||
}
|
||||
|
||||
private enum Page : byte
|
||||
public enum Page : byte
|
||||
{
|
||||
Connecting,
|
||||
ConnectFailed,
|
||||
|
||||
@@ -215,6 +215,8 @@ namespace Content.Client.State
|
||||
|
||||
LayoutContainer.SetAnchorPreset(this, LayoutContainer.LayoutPreset.Wide);
|
||||
|
||||
AddChild(new ParallaxControl());
|
||||
|
||||
var layout = new LayoutContainer();
|
||||
AddChild(layout);
|
||||
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace Content.Client.StationEvents
|
||||
_alphaRateOfChange[entity] = 1.0f / (float) (transitionTime - currentTime).TotalSeconds;
|
||||
}
|
||||
|
||||
protected override void Draw(DrawingHandleBase handle, OverlaySpace currentSpace)
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
// PVS should control the overlay pretty well so the overlay doesn't get instantiated unless we're near one...
|
||||
var playerEntity = _playerManager.LocalPlayer?.ControlledEntity;
|
||||
@@ -124,7 +124,7 @@ namespace Content.Client.StationEvents
|
||||
.EntityQuery<RadiationPulseComponent>(true)
|
||||
.ToList();
|
||||
|
||||
var screenHandle = (DrawingHandleScreen) handle;
|
||||
var screenHandle = args.ScreenHandle;
|
||||
var viewport = _eyeManager.GetWorldViewport();
|
||||
|
||||
foreach (var grid in _mapManager.FindGridsIntersecting(playerEntity.Transform.MapID, viewport))
|
||||
@@ -134,7 +134,7 @@ namespace Content.Client.StationEvents
|
||||
if (!pulse.Draw || grid.Index != pulse.Owner.Transform.GridID) continue;
|
||||
|
||||
// TODO: Check if viewport intersects circle
|
||||
var circlePosition = _eyeManager.WorldToScreen(pulse.Owner.Transform.WorldPosition);
|
||||
var circlePosition = args.ViewportControl!.WorldToScreen(pulse.Owner.Transform.WorldPosition);
|
||||
|
||||
// change to worldhandle when implemented
|
||||
screenHandle.DrawCircle(
|
||||
|
||||
@@ -29,11 +29,14 @@ namespace Content.Client.UserInterface
|
||||
public readonly Button CloseButton;
|
||||
public readonly Button SaveButton;
|
||||
|
||||
public CharacterSetupGui(IEntityManager entityManager,
|
||||
public CharacterSetupGui(
|
||||
IEntityManager entityManager,
|
||||
IResourceCache resourceCache,
|
||||
IClientPreferencesManager preferencesManager,
|
||||
IPrototypeManager prototypeManager)
|
||||
{
|
||||
AddChild(new ParallaxControl());
|
||||
|
||||
_entityManager = entityManager;
|
||||
_preferencesManager = preferencesManager;
|
||||
var margin = new Control
|
||||
|
||||
53
Content.Client/UserInterface/LauncherConnectingGui.xaml
Normal file
53
Content.Client/UserInterface/LauncherConnectingGui.xaml
Normal file
@@ -0,0 +1,53 @@
|
||||
<Control xmlns="https://spacestation14.io"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:cui="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
|
||||
xmlns:cuic="clr-namespace:Content.Client.UserInterface">
|
||||
<cuic:ParallaxControl />
|
||||
<Control HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
<PanelContainer StyleClasses="AngleRect" />
|
||||
<VBoxContainer MinSize="300 200">
|
||||
<HBoxContainer>
|
||||
<Label Margin="8 0 0 0" Text="{Loc 'connecting-title'}"
|
||||
StyleClasses="LabelHeading" VAlign="Center" />
|
||||
<Button Name="ExitButton" Text="{Loc 'connecting-exit'}"
|
||||
HorizontalAlignment="Right" HorizontalExpand="True" />
|
||||
</HBoxContainer>
|
||||
<cui:HighDivider />
|
||||
<VBoxContainer VerticalExpand="True" Margin="4 4 4 0">
|
||||
<Control VerticalExpand="True" Margin="0 0 0 8">
|
||||
<VBoxContainer Name="ConnectingStatus">
|
||||
<Label Text="{Loc 'connecting-in-progress'}" Align="Center" />
|
||||
<!-- Who the fuck named these cont- oh wait I did -->
|
||||
<Label Name="ConnectStatus" StyleClasses="LabelSubText" Align="Center" />
|
||||
</VBoxContainer>
|
||||
<VBoxContainer Name="ConnectFail" Visible="False">
|
||||
<Label Name="ConnectFailReason" Align="Center" />
|
||||
<Button Name="RetryButton" Text="{Loc 'connecting-retry'}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalExpand="True" VerticalAlignment="Bottom" />
|
||||
</VBoxContainer>
|
||||
<VBoxContainer Name="Disconnected">
|
||||
<Label Text="{Loc 'connecting-disconnected'}" Align="Center" />
|
||||
<Label Name="DisconnectReason" Align="Center" />
|
||||
<Button Name="ReconnectButton" Text="{Loc 'connecting-reconnect'}"
|
||||
HorizontalAlignment="Center"
|
||||
VerticalExpand="True" VerticalAlignment="Bottom" />
|
||||
</VBoxContainer>
|
||||
</Control>
|
||||
<Label Name="ConnectingAddress" StyleClasses="LabelSubText" HorizontalAlignment="Center" />
|
||||
</VBoxContainer>
|
||||
<PanelContainer>
|
||||
<PanelContainer.PanelOverride>
|
||||
<gfx:StyleBoxFlat BackgroundColor="#444" ContentMarginTopOverride="2" />
|
||||
</PanelContainer.PanelOverride>
|
||||
</PanelContainer>
|
||||
|
||||
<HBoxContainer Margin="12 0 4 0" VerticalAlignment="Bottom">
|
||||
<Label Text="{Loc 'connecting-tip'}" StyleClasses="LabelSubText" />
|
||||
<Label Text="{Loc 'connecting-version'}" StyleClasses="LabelSubText"
|
||||
HorizontalAlignment="Right" HorizontalExpand="True" />
|
||||
</HBoxContainer>
|
||||
</VBoxContainer>
|
||||
</Control>
|
||||
</Control>
|
||||
62
Content.Client/UserInterface/LauncherConnectingGui.xaml.cs
Normal file
62
Content.Client/UserInterface/LauncherConnectingGui.xaml.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using Content.Client.State;
|
||||
using Content.Client.UserInterface.Stylesheets;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Network;
|
||||
|
||||
namespace Content.Client.UserInterface
|
||||
{
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class LauncherConnectingGui : Control
|
||||
{
|
||||
private readonly LauncherConnecting _state;
|
||||
|
||||
public LauncherConnectingGui(LauncherConnecting state)
|
||||
{
|
||||
_state = state;
|
||||
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
LayoutContainer.SetAnchorPreset(this, LayoutContainer.LayoutPreset.Wide);
|
||||
|
||||
Stylesheet = IoCManager.Resolve<IStylesheetManager>().SheetSpace;
|
||||
|
||||
ReconnectButton.OnPressed += _ => _state.RetryConnect();
|
||||
RetryButton.OnPressed += _ => _state.RetryConnect();
|
||||
ExitButton.OnPressed += _ => _state.Exit();
|
||||
|
||||
var addr = state.Address;
|
||||
if (addr != null)
|
||||
ConnectingAddress.Text = addr;
|
||||
|
||||
state.PageChanged += OnPageChanged;
|
||||
state.ConnectFailReasonChanged += ConnectFailReasonChanged;
|
||||
state.ConnectionStateChanged += ConnectionStateChanged;
|
||||
|
||||
ConnectionStateChanged(state.ConnectionState);
|
||||
}
|
||||
|
||||
private void ConnectFailReasonChanged(string? reason)
|
||||
{
|
||||
ConnectFailReason.Text = reason == null
|
||||
? null
|
||||
: Loc.GetString("connecting-fail-reason", ("reason", reason));
|
||||
}
|
||||
|
||||
private void OnPageChanged(LauncherConnecting.Page page)
|
||||
{
|
||||
ConnectingStatus.Visible = page == LauncherConnecting.Page.Connecting;
|
||||
ConnectFail.Visible = page == LauncherConnecting.Page.ConnectFailed;
|
||||
Disconnected.Visible = page == LauncherConnecting.Page.Disconnected;
|
||||
}
|
||||
|
||||
private void ConnectionStateChanged(ClientConnectionState state)
|
||||
{
|
||||
ConnectStatus.Text = Loc.GetString($"connecting-state-{state}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,82 +7,88 @@
|
||||
xmlns:maths="clr-namespace:Robust.Shared.Maths;assembly=Robust.Shared.Maths"
|
||||
xmlns:voting="clr-namespace:Content.Client.Voting">
|
||||
|
||||
<!-- One day I'll code a Margin property for controls. -->
|
||||
<MarginContainer MarginBottomOverride="20" MarginLeftOverride="20" MarginRightOverride="20"
|
||||
MarginTopOverride="20">
|
||||
<PanelContainer StyleClasses="AngleRect" />
|
||||
<VBoxContainer>
|
||||
<!-- Top row -->
|
||||
<HBoxContainer MinSize="0 40">
|
||||
<MarginContainer MarginLeftOverride="8">
|
||||
<Label StyleClasses="LabelHeadingBigger" VAlign="Center" Text="{Loc 'Lobby'}" />
|
||||
</MarginContainer>
|
||||
<Label Name="CServerName" StyleClasses="LabelHeadingBigger" VAlign="Center" />
|
||||
<voting:VoteCallMenuButton Name="CCallVoteButton" StyleClasses="ButtonBig" />
|
||||
<Button Name="COptionsButton" StyleClasses="ButtonBig" Text="{Loc 'Options'}" />
|
||||
<Button Name="CLeaveButton" StyleClasses="ButtonBig" Text="{Loc 'Leave'}" />
|
||||
</HBoxContainer>
|
||||
<!-- Gold line -->
|
||||
<PanelContainer>
|
||||
<PanelContainer.PanelOverride>
|
||||
<gfx:StyleBoxFlat BackgroundColor="{x:Static style:StyleNano.NanoGold}"
|
||||
ContentMarginTopOverride="2" />
|
||||
</PanelContainer.PanelOverride>
|
||||
</PanelContainer>
|
||||
<!-- Middle section with the two vertical panels -->
|
||||
<HBoxContainer VerticalExpand="True">
|
||||
<!-- Left panel -->
|
||||
<VBoxContainer Name="CLeftPanelContainer" HorizontalExpand="True">
|
||||
<cui:StripeBack>
|
||||
<MarginContainer MarginLeftOverride="3" MarginRightOverride="3" MarginBottomOverride="3"
|
||||
MarginTopOverride="3">
|
||||
<HBoxContainer SeparationOverride="6">
|
||||
<Button Name="CObserveButton" Text="{Loc 'Observe'}" StyleClasses="ButtonBig" />
|
||||
<Label Name="CStartTime" Align="Right"
|
||||
FontColorOverride="{x:Static maths:Color.DarkGray}"
|
||||
StyleClasses="LabelBig" HorizontalExpand="True" />
|
||||
<Button Name="CReadyButton" ToggleMode="True" Text="{Loc 'Ready Up'}"
|
||||
StyleClasses="ButtonBig" />
|
||||
</HBoxContainer>
|
||||
</MarginContainer>
|
||||
</cui:StripeBack>
|
||||
<MarginContainer VerticalExpand="True" MarginLeftOverride="3" MarginRightOverride="3"
|
||||
MarginBottomOverride="3"
|
||||
MarginTopOverride="3">
|
||||
<chat:ChatBox Name="CChat" />
|
||||
<Control>
|
||||
<!-- Parallax background -->
|
||||
<cui:ParallaxControl />
|
||||
|
||||
<!-- One day I'll code a Margin property for controls. -->
|
||||
<MarginContainer MarginBottomOverride="20" MarginLeftOverride="20" MarginRightOverride="20"
|
||||
MarginTopOverride="20">
|
||||
<PanelContainer StyleClasses="AngleRect" />
|
||||
<VBoxContainer>
|
||||
<!-- Top row -->
|
||||
<HBoxContainer MinSize="0 40">
|
||||
<MarginContainer MarginLeftOverride="8">
|
||||
<Label StyleClasses="LabelHeadingBigger" VAlign="Center" Text="{Loc 'Lobby'}" />
|
||||
</MarginContainer>
|
||||
</VBoxContainer>
|
||||
<Label Name="CServerName" StyleClasses="LabelHeadingBigger" VAlign="Center" />
|
||||
<voting:VoteCallMenuButton Name="CCallVoteButton" StyleClasses="ButtonBig" />
|
||||
<Button Name="COptionsButton" StyleClasses="ButtonBig" Text="{Loc 'Options'}" />
|
||||
<Button Name="CLeaveButton" StyleClasses="ButtonBig" Text="{Loc 'Leave'}" />
|
||||
</HBoxContainer>
|
||||
<!-- Gold line -->
|
||||
<PanelContainer MinSize="2 0">
|
||||
<PanelContainer>
|
||||
<PanelContainer.PanelOverride>
|
||||
<gfx:StyleBoxFlat BackgroundColor="{x:Static style:StyleNano.NanoGold}" />
|
||||
<gfx:StyleBoxFlat BackgroundColor="{x:Static style:StyleNano.NanoGold}"
|
||||
ContentMarginTopOverride="2" />
|
||||
</PanelContainer.PanelOverride>
|
||||
</PanelContainer>
|
||||
<!-- Right panel -->
|
||||
<Control HorizontalExpand="True">
|
||||
<VBoxContainer>
|
||||
<!-- Player list -->
|
||||
<cui:NanoHeading Text="{Loc 'Online Players'}" />
|
||||
<MarginContainer VerticalExpand="True"
|
||||
MarginRightOverride="3" MarginLeftOverride="3"
|
||||
MarginBottomOverride="3" MarginTopOverride="3">
|
||||
<cui:LobbyPlayerList Name="COnlinePlayerList"
|
||||
HorizontalExpand="True"
|
||||
VerticalExpand="True" />
|
||||
</MarginContainer>
|
||||
<!-- Server info -->
|
||||
<cui:NanoHeading Text="{Loc 'Server Info'}" />
|
||||
<MarginContainer VerticalExpand="True"
|
||||
MarginRightOverride="3" MarginLeftOverride="3"
|
||||
MarginBottomOverride="2" MarginTopOverride="3">
|
||||
<cui:ServerInfo Name="CServerInfo" />
|
||||
<!-- Middle section with the two vertical panels -->
|
||||
<HBoxContainer VerticalExpand="True">
|
||||
<!-- Left panel -->
|
||||
<VBoxContainer Name="CLeftPanelContainer" HorizontalExpand="True">
|
||||
<cui:StripeBack>
|
||||
<MarginContainer MarginLeftOverride="3" MarginRightOverride="3" MarginBottomOverride="3"
|
||||
MarginTopOverride="3">
|
||||
<HBoxContainer SeparationOverride="6">
|
||||
<Button Name="CObserveButton" Text="{Loc 'Observe'}" StyleClasses="ButtonBig" />
|
||||
<Label Name="CStartTime" Align="Right"
|
||||
FontColorOverride="{x:Static maths:Color.DarkGray}"
|
||||
StyleClasses="LabelBig" HorizontalExpand="True" />
|
||||
<Button Name="CReadyButton" ToggleMode="True" Text="{Loc 'Ready Up'}"
|
||||
StyleClasses="ButtonBig" />
|
||||
</HBoxContainer>
|
||||
</MarginContainer>
|
||||
</cui:StripeBack>
|
||||
<MarginContainer VerticalExpand="True" MarginLeftOverride="3" MarginRightOverride="3"
|
||||
MarginBottomOverride="3"
|
||||
MarginTopOverride="3">
|
||||
<chat:ChatBox Name="CChat" />
|
||||
</MarginContainer>
|
||||
</VBoxContainer>
|
||||
<MarginContainer SizeFlagsHorizontal="ShrinkEnd" MarginTopOverride="8" MarginRightOverride="8">
|
||||
<VBoxContainer Name="CVoteContainer" />
|
||||
</MarginContainer>
|
||||
</Control>
|
||||
</HBoxContainer>
|
||||
</VBoxContainer>
|
||||
</MarginContainer>
|
||||
<!-- Gold line -->
|
||||
<PanelContainer MinSize="2 0">
|
||||
<PanelContainer.PanelOverride>
|
||||
<gfx:StyleBoxFlat BackgroundColor="{x:Static style:StyleNano.NanoGold}" />
|
||||
</PanelContainer.PanelOverride>
|
||||
</PanelContainer>
|
||||
<!-- Right panel -->
|
||||
<Control HorizontalExpand="True">
|
||||
<VBoxContainer>
|
||||
<!-- Player list -->
|
||||
<cui:NanoHeading Text="{Loc 'Online Players'}" />
|
||||
<MarginContainer VerticalExpand="True"
|
||||
MarginRightOverride="3" MarginLeftOverride="3"
|
||||
MarginBottomOverride="3" MarginTopOverride="3">
|
||||
<cui:LobbyPlayerList Name="COnlinePlayerList"
|
||||
HorizontalExpand="True"
|
||||
VerticalExpand="True" />
|
||||
</MarginContainer>
|
||||
<!-- Server info -->
|
||||
<cui:NanoHeading Text="{Loc 'Server Info'}" />
|
||||
<MarginContainer VerticalExpand="True"
|
||||
MarginRightOverride="3" MarginLeftOverride="3"
|
||||
MarginBottomOverride="2" MarginTopOverride="3">
|
||||
<cui:ServerInfo Name="CServerInfo" />
|
||||
</MarginContainer>
|
||||
</VBoxContainer>
|
||||
<MarginContainer SizeFlagsHorizontal="ShrinkEnd" MarginTopOverride="8" MarginRightOverride="8">
|
||||
<VBoxContainer Name="CVoteContainer" />
|
||||
</MarginContainer>
|
||||
</Control>
|
||||
</HBoxContainer>
|
||||
</VBoxContainer>
|
||||
</MarginContainer>
|
||||
|
||||
</Control>
|
||||
</Control>
|
||||
|
||||
153
Content.Client/UserInterface/MainViewport.cs
Normal file
153
Content.Client/UserInterface/MainViewport.cs
Normal file
@@ -0,0 +1,153 @@
|
||||
using System;
|
||||
using Content.Shared;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
|
||||
namespace Content.Client.UserInterface
|
||||
{
|
||||
/// <summary>
|
||||
/// Wrapper for <see cref="ScalingViewport"/> that listens to configuration variables.
|
||||
/// Also does NN-snapping within tolerances.
|
||||
/// </summary>
|
||||
public sealed class MainViewport : Control
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
[Dependency] private readonly ViewportManager _vpManager = default!;
|
||||
|
||||
public ScalingViewport Viewport { get; }
|
||||
|
||||
public MainViewport()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
Viewport = new ScalingViewport
|
||||
{
|
||||
AlwaysRender = true,
|
||||
RenderScaleMode = ScalingViewportRenderScaleMode.CeilInt,
|
||||
MouseFilter = MouseFilterMode.Stop
|
||||
};
|
||||
|
||||
AddChild(Viewport);
|
||||
}
|
||||
|
||||
protected override void EnteredTree()
|
||||
{
|
||||
base.EnteredTree();
|
||||
|
||||
_vpManager.AddViewport(this);
|
||||
}
|
||||
|
||||
protected override void ExitedTree()
|
||||
{
|
||||
base.ExitedTree();
|
||||
|
||||
_vpManager.RemoveViewport(this);
|
||||
}
|
||||
|
||||
public void UpdateCfg()
|
||||
{
|
||||
var stretch = _cfg.GetCVar(CCVars.ViewportStretch);
|
||||
var renderScaleUp = _cfg.GetCVar(CCVars.ViewportScaleRender);
|
||||
var fixedFactor = _cfg.GetCVar(CCVars.ViewportFixedScaleFactor);
|
||||
|
||||
if (stretch)
|
||||
{
|
||||
var snapFactor = CalcSnappingFactor();
|
||||
if (snapFactor == null)
|
||||
{
|
||||
// Did not find a snap, enable stretching.
|
||||
Viewport.FixedStretchSize = null;
|
||||
Viewport.StretchMode = ScalingViewportStretchMode.Bilinear;
|
||||
|
||||
if (renderScaleUp)
|
||||
{
|
||||
Viewport.RenderScaleMode = ScalingViewportRenderScaleMode.CeilInt;
|
||||
}
|
||||
else
|
||||
{
|
||||
Viewport.RenderScaleMode = ScalingViewportRenderScaleMode.Fixed;
|
||||
Viewport.FixedRenderScale = 1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Found snap, set fixed factor and run non-stretching code.
|
||||
fixedFactor = snapFactor.Value;
|
||||
}
|
||||
|
||||
Viewport.FixedStretchSize = Viewport.ViewportSize * fixedFactor;
|
||||
Viewport.StretchMode = ScalingViewportStretchMode.Nearest;
|
||||
|
||||
if (renderScaleUp)
|
||||
{
|
||||
Viewport.RenderScaleMode = ScalingViewportRenderScaleMode.Fixed;
|
||||
Viewport.FixedRenderScale = fixedFactor;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Snapping but forced to render scale at scale 1 so...
|
||||
// At least we can NN.
|
||||
Viewport.RenderScaleMode = ScalingViewportRenderScaleMode.Fixed;
|
||||
Viewport.FixedRenderScale = 1;
|
||||
}
|
||||
}
|
||||
|
||||
private int? CalcSnappingFactor()
|
||||
{
|
||||
// Margin tolerance is tolerance of "the window is too big"
|
||||
// where we add a margin to the viewport to make it fit.
|
||||
var cfgToleranceMargin = _cfg.GetCVar(CCVars.ViewportSnapToleranceMargin);
|
||||
// Clip tolerance is tolerance of "the window is too small"
|
||||
// where we are clipping the viewport to make it fit.
|
||||
var cfgToleranceClip = _cfg.GetCVar(CCVars.ViewportSnapToleranceClip);
|
||||
|
||||
// Calculate if the viewport, when rendered at an integer scale,
|
||||
// is close enough to the control size to enable "snapping" to NN,
|
||||
// potentially cutting a tiny bit off/leaving a margin.
|
||||
//
|
||||
// Idea here is that if you maximize the window at 1080p or 1440p
|
||||
// we are close enough to an integer scale (2x and 3x resp) that we should "snap" to it.
|
||||
|
||||
// Just do it iteratively.
|
||||
// I'm sure there's a smarter approach that needs one try with math but I'm dumb.
|
||||
for (var i = 1; i <= 10; i++)
|
||||
{
|
||||
var toleranceMargin = i * cfgToleranceMargin;
|
||||
var toleranceClip = i * cfgToleranceClip;
|
||||
var scaled = (Vector2) Viewport.ViewportSize * i;
|
||||
var (dx, dy) = PixelSize - scaled;
|
||||
|
||||
// The rule for which snap fits is that at LEAST one axis needs to be in the tolerance size wise.
|
||||
// One axis MAY be larger but not smaller than tolerance.
|
||||
// Obviously if it's too small it's bad, and if it's too big on both axis we should stretch up.
|
||||
if (Fits(dx) && Fits(dy) || Fits(dx) && Larger(dy) || Larger(dx) && Fits(dy))
|
||||
{
|
||||
// Found snap that fits.
|
||||
return i;
|
||||
}
|
||||
|
||||
bool Larger(float a)
|
||||
{
|
||||
return a > toleranceMargin;
|
||||
}
|
||||
|
||||
bool Fits(float a)
|
||||
{
|
||||
return a <= toleranceMargin && a >= -toleranceClip;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected override void Resized()
|
||||
{
|
||||
base.Resized();
|
||||
|
||||
UpdateCfg();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,10 @@
|
||||
using System;
|
||||
using Content.Client.GameObjects.Components.HUD.Inventory;
|
||||
using Content.Shared;
|
||||
using Content.Shared.Prototypes.HUD;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -39,6 +35,11 @@ namespace Content.Client.UserInterface
|
||||
private readonly OptionButton LightingPresetOption;
|
||||
private readonly OptionButton _uiScaleOption;
|
||||
private readonly OptionButton _hudThemeOption;
|
||||
private readonly CheckBox _viewportStretchCheckBox;
|
||||
private readonly CheckBox _viewportLowResCheckBox;
|
||||
private readonly Slider _viewportScaleSlider;
|
||||
private readonly Control _viewportScaleBox;
|
||||
private readonly Label _viewportScaleText;
|
||||
|
||||
public GraphicsControl(IConfigurationManager cfg, IPrototypeManager proMan)
|
||||
{
|
||||
@@ -121,12 +122,55 @@ namespace Content.Client.UserInterface
|
||||
}
|
||||
});
|
||||
|
||||
contents.AddChild(new Placeholder()
|
||||
_viewportStretchCheckBox = new CheckBox
|
||||
{
|
||||
VerticalExpand = true,
|
||||
PlaceholderText = Loc.GetString("ui-options-placeholder-viewport")
|
||||
Text = Loc.GetString("ui-options-vp-stretch")
|
||||
};
|
||||
|
||||
_viewportStretchCheckBox.OnToggled += _ =>
|
||||
{
|
||||
UpdateViewportScale();
|
||||
UpdateApplyButton();
|
||||
};
|
||||
|
||||
_viewportScaleSlider = new Slider
|
||||
{
|
||||
MinValue = 1,
|
||||
MaxValue = 5,
|
||||
Rounded = true,
|
||||
MinWidth = 200
|
||||
};
|
||||
|
||||
_viewportScaleSlider.OnValueChanged += _ =>
|
||||
{
|
||||
UpdateApplyButton();
|
||||
UpdateViewportScale();
|
||||
};
|
||||
|
||||
_viewportLowResCheckBox = new CheckBox { Text = Loc.GetString("ui-options-vp-low-res")};
|
||||
_viewportLowResCheckBox.OnToggled += OnCheckBoxToggled;
|
||||
|
||||
contents.AddChild(new HBoxContainer
|
||||
{
|
||||
Children =
|
||||
{
|
||||
_viewportStretchCheckBox,
|
||||
(_viewportScaleBox = new HBoxContainer
|
||||
{
|
||||
Children =
|
||||
{
|
||||
(_viewportScaleText = new Label
|
||||
{
|
||||
Margin = new Thickness(8, 0)
|
||||
}),
|
||||
_viewportScaleSlider,
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
contents.AddChild(_viewportLowResCheckBox);
|
||||
|
||||
vBox.AddChild(contents);
|
||||
|
||||
vBox.AddChild(new StripeBack
|
||||
@@ -145,6 +189,12 @@ namespace Content.Client.UserInterface
|
||||
LightingPresetOption.SelectId(GetConfigLightingQuality());
|
||||
_uiScaleOption.SelectId(GetConfigUIScalePreset(ConfigUIScale));
|
||||
_hudThemeOption.SelectId(_cfg.GetCVar(CCVars.HudTheme));
|
||||
_viewportScaleSlider.Value = _cfg.GetCVar(CCVars.ViewportFixedScaleFactor);
|
||||
_viewportStretchCheckBox.Pressed = _cfg.GetCVar(CCVars.ViewportStretch);
|
||||
_viewportLowResCheckBox.Pressed = !_cfg.GetCVar(CCVars.ViewportScaleRender);
|
||||
|
||||
UpdateViewportScale();
|
||||
UpdateApplyButton();
|
||||
|
||||
AddChild(vBox);
|
||||
}
|
||||
@@ -173,6 +223,9 @@ namespace Content.Client.UserInterface
|
||||
_cfg.SetCVar(CVars.DisplayWindowMode,
|
||||
(int) (FullscreenCheckBox.Pressed ? WindowMode.Fullscreen : WindowMode.Windowed));
|
||||
_cfg.SetCVar(CVars.DisplayUIScale, UIScaleOptions[_uiScaleOption.SelectedId]);
|
||||
_cfg.SetCVar(CCVars.ViewportStretch, _viewportStretchCheckBox.Pressed);
|
||||
_cfg.SetCVar(CCVars.ViewportFixedScaleFactor, (int) _viewportScaleSlider.Value);
|
||||
_cfg.SetCVar(CCVars.ViewportScaleRender, !_viewportLowResCheckBox.Pressed);
|
||||
_cfg.SaveToFile();
|
||||
UpdateApplyButton();
|
||||
}
|
||||
@@ -195,8 +248,18 @@ namespace Content.Client.UserInterface
|
||||
var isLightingQualitySame = LightingPresetOption.SelectedId == GetConfigLightingQuality();
|
||||
var isHudThemeSame = _hudThemeOption.SelectedId == _cfg.GetCVar(CCVars.HudTheme);
|
||||
var isUIScaleSame = MathHelper.CloseTo(UIScaleOptions[_uiScaleOption.SelectedId], ConfigUIScale);
|
||||
ApplyButton.Disabled = isVSyncSame && isFullscreenSame && isLightingQualitySame && isHudThemeSame &&
|
||||
isUIScaleSame;
|
||||
var isVPStretchSame = _viewportStretchCheckBox.Pressed == _cfg.GetCVar(CCVars.ViewportStretch);
|
||||
var isVPScaleSame = (int) _viewportScaleSlider.Value == _cfg.GetCVar(CCVars.ViewportFixedScaleFactor);
|
||||
var isVPResSame = _viewportLowResCheckBox.Pressed == !_cfg.GetCVar(CCVars.ViewportScaleRender);
|
||||
|
||||
ApplyButton.Disabled = isVSyncSame &&
|
||||
isFullscreenSame &&
|
||||
isLightingQualitySame &&
|
||||
isUIScaleSame &&
|
||||
isVPStretchSame &&
|
||||
isVPScaleSame &&
|
||||
isVPResSame &&
|
||||
isHudThemeSame;
|
||||
}
|
||||
|
||||
private bool ConfigIsFullscreen =>
|
||||
@@ -261,6 +324,12 @@ namespace Content.Client.UserInterface
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void UpdateViewportScale()
|
||||
{
|
||||
_viewportScaleBox.Visible = !_viewportStretchCheckBox.Pressed;
|
||||
_viewportScaleText.Text = Loc.GetString("ui-options-vp-scale", ("scale", _viewportScaleSlider.Value));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
47
Content.Client/UserInterface/ParallaxControl.cs
Normal file
47
Content.Client/UserInterface/ParallaxControl.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using Content.Client.Interfaces.Parallax;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Client.UserInterface
|
||||
{
|
||||
/// <summary>
|
||||
/// Renders the parallax background as a UI control.
|
||||
/// </summary>
|
||||
public sealed class ParallaxControl : Control
|
||||
{
|
||||
[Dependency] private readonly IParallaxManager _parallaxManager = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)] public Vector2i Offset { get; set; }
|
||||
|
||||
public ParallaxControl()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
Offset = (_random.Next(0, 1000), _random.Next(0, 1000));
|
||||
RectClipContent = true;
|
||||
}
|
||||
|
||||
protected override void Draw(DrawingHandleScreen handle)
|
||||
{
|
||||
var tex = _parallaxManager.ParallaxTexture;
|
||||
if (tex == null)
|
||||
return;
|
||||
|
||||
var size = tex.Size;
|
||||
var ourSize = PixelSize;
|
||||
|
||||
for (var x = -size.X + Offset.X; x < ourSize.X; x += size.X)
|
||||
{
|
||||
for (var y = -size.Y + Offset.Y; y < ourSize.Y; y += size.Y)
|
||||
{
|
||||
handle.DrawTexture(tex, (x, y));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
340
Content.Client/UserInterface/ScalingViewport.cs
Normal file
340
Content.Client/UserInterface/ScalingViewport.cs
Normal file
@@ -0,0 +1,340 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Maths;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.ViewVariables;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
|
||||
namespace Content.Client.UserInterface
|
||||
{
|
||||
/// <summary>
|
||||
/// Viewport control that has a fixed viewport size and scales it appropriately.
|
||||
/// </summary>
|
||||
public sealed class ScalingViewport : Control, IViewportControl
|
||||
{
|
||||
[Dependency] private readonly IClyde _clyde = default!;
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
|
||||
// Internal viewport creation is deferred.
|
||||
private IClydeViewport? _viewport;
|
||||
private IEye? _eye;
|
||||
private Vector2i _viewportSize;
|
||||
private int _curRenderScale;
|
||||
private ScalingViewportStretchMode _stretchMode = ScalingViewportStretchMode.Bilinear;
|
||||
private ScalingViewportRenderScaleMode _renderScaleMode = ScalingViewportRenderScaleMode.Fixed;
|
||||
private int _fixedRenderScale = 1;
|
||||
|
||||
private readonly List<CopyPixelsDelegate<Rgba32>> _queuedScreenshots = new();
|
||||
|
||||
public int CurrentRenderScale => _curRenderScale;
|
||||
|
||||
/// <summary>
|
||||
/// The eye to render.
|
||||
/// </summary>
|
||||
public IEye? Eye
|
||||
{
|
||||
get => _eye;
|
||||
set
|
||||
{
|
||||
_eye = value;
|
||||
|
||||
if (_viewport != null)
|
||||
_viewport.Eye = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The size, in unscaled pixels, of the internal viewport.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The actual viewport may have render scaling applied based on parameters.
|
||||
/// </remarks>
|
||||
public Vector2i ViewportSize
|
||||
{
|
||||
get => _viewportSize;
|
||||
set
|
||||
{
|
||||
_viewportSize = value;
|
||||
InvalidateViewport();
|
||||
}
|
||||
}
|
||||
|
||||
// Do not need to InvalidateViewport() since it doesn't affect viewport creation.
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)] public Vector2i? FixedStretchSize { get; set; }
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public ScalingViewportStretchMode StretchMode
|
||||
{
|
||||
get => _stretchMode;
|
||||
set
|
||||
{
|
||||
_stretchMode = value;
|
||||
InvalidateViewport();
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public ScalingViewportRenderScaleMode RenderScaleMode
|
||||
{
|
||||
get => _renderScaleMode;
|
||||
set
|
||||
{
|
||||
_renderScaleMode = value;
|
||||
InvalidateViewport();
|
||||
}
|
||||
}
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public int FixedRenderScale
|
||||
{
|
||||
get => _fixedRenderScale;
|
||||
set
|
||||
{
|
||||
_fixedRenderScale = value;
|
||||
InvalidateViewport();
|
||||
}
|
||||
}
|
||||
|
||||
public ScalingViewport()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
RectClipContent = true;
|
||||
}
|
||||
|
||||
protected override void KeyBindDown(GUIBoundKeyEventArgs args)
|
||||
{
|
||||
base.KeyBindDown(args);
|
||||
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
_inputManager.ViewportKeyEvent(this, args);
|
||||
}
|
||||
|
||||
protected override void KeyBindUp(GUIBoundKeyEventArgs args)
|
||||
{
|
||||
base.KeyBindUp(args);
|
||||
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
_inputManager.ViewportKeyEvent(this, args);
|
||||
}
|
||||
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
EnsureViewportCreated();
|
||||
}
|
||||
|
||||
protected override void Draw(DrawingHandleScreen handle)
|
||||
{
|
||||
DebugTools.AssertNotNull(_viewport);
|
||||
|
||||
_viewport!.Render();
|
||||
|
||||
if (_queuedScreenshots.Count != 0)
|
||||
{
|
||||
var callbacks = _queuedScreenshots.ToArray();
|
||||
|
||||
_viewport.RenderTarget.CopyPixelsToMemory<Rgba32>(image =>
|
||||
{
|
||||
foreach (var callback in callbacks)
|
||||
{
|
||||
callback(image);
|
||||
}
|
||||
});
|
||||
|
||||
_queuedScreenshots.Clear();
|
||||
}
|
||||
|
||||
var drawBox = GetDrawBox();
|
||||
var drawBoxGlobal = drawBox.Translated(GlobalPixelPosition);
|
||||
_viewport.RenderScreenOverlaysBelow(handle, this, drawBoxGlobal);
|
||||
handle.DrawTextureRect(_viewport.RenderTarget.Texture, drawBox);
|
||||
_viewport.RenderScreenOverlaysAbove(handle, this, drawBoxGlobal);
|
||||
}
|
||||
|
||||
public void Screenshot(CopyPixelsDelegate<Rgba32> callback)
|
||||
{
|
||||
_queuedScreenshots.Add(callback);
|
||||
}
|
||||
|
||||
// Draw box in pixel coords to draw the viewport at.
|
||||
private UIBox2i GetDrawBox()
|
||||
{
|
||||
DebugTools.AssertNotNull(_viewport);
|
||||
|
||||
var vpSize = _viewport!.Size;
|
||||
var ourSize = (Vector2) PixelSize;
|
||||
|
||||
if (FixedStretchSize == null)
|
||||
{
|
||||
var (ratioX, ratioY) = ourSize / vpSize;
|
||||
var ratio = Math.Min(ratioX, ratioY);
|
||||
|
||||
var size = vpSize * ratio;
|
||||
// Size
|
||||
var pos = (ourSize - size) / 2;
|
||||
|
||||
return (UIBox2i) UIBox2.FromDimensions(pos, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Center only, no scaling.
|
||||
var pos = (ourSize - FixedStretchSize.Value) / 2;
|
||||
return (UIBox2i) UIBox2.FromDimensions(pos, FixedStretchSize.Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void RegenerateViewport()
|
||||
{
|
||||
DebugTools.AssertNull(_viewport);
|
||||
|
||||
var vpSizeBase = ViewportSize;
|
||||
var ourSize = PixelSize;
|
||||
var (ratioX, ratioY) = ourSize / (Vector2) vpSizeBase;
|
||||
var ratio = Math.Min(ratioX, ratioY);
|
||||
var renderScale = 1;
|
||||
switch (_renderScaleMode)
|
||||
{
|
||||
case ScalingViewportRenderScaleMode.CeilInt:
|
||||
renderScale = (int) Math.Ceiling(ratio);
|
||||
break;
|
||||
case ScalingViewportRenderScaleMode.FloorInt:
|
||||
renderScale = (int) Math.Floor(ratio);
|
||||
break;
|
||||
case ScalingViewportRenderScaleMode.Fixed:
|
||||
renderScale = _fixedRenderScale;
|
||||
break;
|
||||
}
|
||||
|
||||
// Always has to be at least one to avoid passing 0,0 to the viewport constructor
|
||||
renderScale = Math.Max(1, renderScale);
|
||||
|
||||
_curRenderScale = renderScale;
|
||||
|
||||
_viewport = _clyde.CreateViewport(
|
||||
ViewportSize * renderScale,
|
||||
new TextureSampleParameters
|
||||
{
|
||||
Filter = StretchMode == ScalingViewportStretchMode.Bilinear,
|
||||
});
|
||||
|
||||
_viewport.RenderScale = (renderScale, renderScale);
|
||||
|
||||
_viewport.Eye = _eye;
|
||||
}
|
||||
|
||||
protected override void Resized()
|
||||
{
|
||||
base.Resized();
|
||||
|
||||
InvalidateViewport();
|
||||
}
|
||||
|
||||
private void InvalidateViewport()
|
||||
{
|
||||
_viewport?.Dispose();
|
||||
_viewport = null;
|
||||
}
|
||||
|
||||
public MapCoordinates ScreenToMap(Vector2 coords)
|
||||
{
|
||||
if (_eye == null)
|
||||
return default;
|
||||
|
||||
EnsureViewportCreated();
|
||||
|
||||
var matrix = Matrix3.Invert(LocalToScreenMatrix());
|
||||
|
||||
return _viewport!.LocalToWorld(matrix.Transform(coords));
|
||||
}
|
||||
|
||||
public Vector2 WorldToScreen(Vector2 map)
|
||||
{
|
||||
if (_eye == null)
|
||||
return default;
|
||||
|
||||
EnsureViewportCreated();
|
||||
|
||||
var vpLocal = _viewport!.WorldToLocal(map);
|
||||
|
||||
var matrix = LocalToScreenMatrix();
|
||||
|
||||
return matrix.Transform(vpLocal);
|
||||
}
|
||||
|
||||
private Matrix3 LocalToScreenMatrix()
|
||||
{
|
||||
DebugTools.AssertNotNull(_viewport);
|
||||
|
||||
var drawBox = GetDrawBox();
|
||||
var scaleFactor = drawBox.Size / (Vector2) _viewport!.Size;
|
||||
|
||||
if (scaleFactor == (0, 0))
|
||||
// Basically a nonsense scenario, at least make sure to return something that can be inverted.
|
||||
return Matrix3.Identity;
|
||||
|
||||
var scale = Matrix3.CreateScale(scaleFactor);
|
||||
var translate = Matrix3.CreateTranslation(GlobalPixelPosition + drawBox.TopLeft);
|
||||
|
||||
return scale * translate;
|
||||
}
|
||||
|
||||
private void EnsureViewportCreated()
|
||||
{
|
||||
if (_viewport == null)
|
||||
{
|
||||
RegenerateViewport();
|
||||
}
|
||||
|
||||
DebugTools.AssertNotNull(_viewport);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines how the viewport is stretched if it does not match the size of the control perfectly.
|
||||
/// </summary>
|
||||
public enum ScalingViewportStretchMode
|
||||
{
|
||||
/// <summary>
|
||||
/// Bilinear sampling is used.
|
||||
/// </summary>
|
||||
Bilinear = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Nearest neighbor sampling is used.
|
||||
/// </summary>
|
||||
Nearest,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Defines how the base render scale of the viewport is selected.
|
||||
/// </summary>
|
||||
public enum ScalingViewportRenderScaleMode
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="ScalingViewport.FixedRenderScale"/> is used.
|
||||
/// </summary>
|
||||
Fixed = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Floor to the closest integer scale possible.
|
||||
/// </summary>
|
||||
FloorInt,
|
||||
|
||||
/// <summary>
|
||||
/// Ceiling to the closest integer scale possible.
|
||||
/// </summary>
|
||||
CeilInt
|
||||
}
|
||||
}
|
||||
15
Content.Client/UserInterface/ViewportExt.cs
Normal file
15
Content.Client/UserInterface/ViewportExt.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
|
||||
namespace Content.Client.UserInterface
|
||||
{
|
||||
public static class ViewportExt
|
||||
{
|
||||
public static int GetRenderScale(this IViewportControl viewport)
|
||||
{
|
||||
if (viewport is ScalingViewport svp)
|
||||
return svp.CurrentRenderScale;
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
42
Content.Client/UserInterface/ViewportManager.cs
Normal file
42
Content.Client/UserInterface/ViewportManager.cs
Normal file
@@ -0,0 +1,42 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Client.UserInterface
|
||||
{
|
||||
/// <summary>
|
||||
/// Event proxy for <see cref="MainViewport"/> to listen to config events.
|
||||
/// </summary>
|
||||
// ReSharper disable once ClassNeverInstantiated.Global
|
||||
public sealed class ViewportManager
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfg = default!;
|
||||
|
||||
private readonly List<MainViewport> _viewports = new();
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
_cfg.OnValueChanged(CCVars.ViewportStretch, _ => UpdateCfg());
|
||||
_cfg.OnValueChanged(CCVars.ViewportSnapToleranceClip, _ => UpdateCfg());
|
||||
_cfg.OnValueChanged(CCVars.ViewportSnapToleranceMargin, _ => UpdateCfg());
|
||||
_cfg.OnValueChanged(CCVars.ViewportScaleRender, _ => UpdateCfg());
|
||||
_cfg.OnValueChanged(CCVars.ViewportFixedScaleFactor, _ => UpdateCfg());
|
||||
}
|
||||
|
||||
private void UpdateCfg()
|
||||
{
|
||||
_viewports.ForEach(v => v.UpdateCfg());
|
||||
}
|
||||
|
||||
public void AddViewport(MainViewport vp)
|
||||
{
|
||||
_viewports.Add(vp);
|
||||
}
|
||||
|
||||
public void RemoveViewport(MainViewport vp)
|
||||
{
|
||||
_viewports.Remove(vp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -318,5 +318,24 @@ namespace Content.Shared
|
||||
|
||||
public static readonly CVarDef<bool> BanHardwareIds =
|
||||
CVarDef.Create("ban.hardware_ids", false, CVar.SERVERONLY);
|
||||
/*
|
||||
* VIEWPORT
|
||||
*/
|
||||
|
||||
public static readonly CVarDef<bool> ViewportStretch =
|
||||
CVarDef.Create("viewport.stretch", true, CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||
|
||||
public static readonly CVarDef<int> ViewportFixedScaleFactor =
|
||||
CVarDef.Create("viewport.fixed_scale_factor", 2, CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||
|
||||
// This default is basically specifically chosen so fullscreen/maximized 1080p hits a 2x snap and does NN.
|
||||
public static readonly CVarDef<int> ViewportSnapToleranceMargin =
|
||||
CVarDef.Create("viewport.snap_tolerance_margin", 64, CVar.CLIENTONLY);
|
||||
|
||||
public static readonly CVarDef<int> ViewportSnapToleranceClip =
|
||||
CVarDef.Create("viewport.snap_tolerance_clip", 32, CVar.CLIENTONLY);
|
||||
|
||||
public static readonly CVarDef<bool> ViewportScaleRender =
|
||||
CVarDef.Create("viewport.scale_render", true, CVar.CLIENTONLY | CVar.ARCHIVE);
|
||||
}
|
||||
}
|
||||
|
||||
18
Resources/Locale/en-US/ui/connecting.ftl
Normal file
18
Resources/Locale/en-US/ui/connecting.ftl
Normal file
@@ -0,0 +1,18 @@
|
||||
### Connecting dialog when you start up the game
|
||||
|
||||
connecting-title = Space Station 14
|
||||
connecting-exit = Exit
|
||||
connecting-retry = Retry
|
||||
connecting-reconnect = Reconnect
|
||||
connecting-in-progress = Connecting to server...
|
||||
connecting-disconnected = Disconnected from server:
|
||||
connecting-tip = Don't die!
|
||||
connecting-version = ver 0.1
|
||||
connecting-fail-reason = Failed to connect to server:
|
||||
{ $reason }
|
||||
|
||||
connecting-state-NotConnecting = You should not be seeing this
|
||||
connecting-state-ResolvingHost = Resolving server address...
|
||||
connecting-state-EstablishingConnection = Establishing initial connection...
|
||||
connecting-state-Handshake = Doing handshake...
|
||||
connecting-state-Connected = Synchronizing game state...
|
||||
@@ -36,7 +36,9 @@ ui-options-hud-theme = HUD Theme:
|
||||
ui-options-hud-theme-default = Default
|
||||
ui-options-hud-theme-modernized = Modernized
|
||||
ui-options-hud-theme-classic = Classic
|
||||
ui-options-placeholder-viewport = Viewport settings
|
||||
ui-options-vp-stretch = Stretch viewport to fit game window?
|
||||
ui-options-vp-scale = Fixed viewport scale: x{ $scale }
|
||||
ui-options-vp-low-res = Low-resolution viewport?
|
||||
|
||||
## Controls menu
|
||||
ui-options-binds-reset-all = Reset ALL keybinds
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
- Disarm
|
||||
- HumanScream
|
||||
- type: Eye
|
||||
zoom: 0.5, 0.5
|
||||
- type: CameraRecoil
|
||||
- type: Examiner
|
||||
- type: HumanInventoryController
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
status: InAir
|
||||
- type: PlayerInputMover
|
||||
- type: Eye
|
||||
zoom: 0.5, 0.5
|
||||
drawFov: false
|
||||
- type: Input
|
||||
context: "ghost"
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
- HumanScream
|
||||
- Disarm
|
||||
- type: Eye
|
||||
zoom: 0.5, 0.5
|
||||
- type: CameraRecoil
|
||||
- type: Examiner
|
||||
- type: HumanInventoryController
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
- VoxScream
|
||||
- Disarm
|
||||
- type: Eye
|
||||
zoom: 0.5, 0.5
|
||||
- type: CameraRecoil
|
||||
- type: Examiner
|
||||
- type: HumanInventoryController
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
kind: source
|
||||
path: "/Textures/Shaders/outline.swsl"
|
||||
params:
|
||||
outline_width: 2
|
||||
outline_color: "#FF000055"
|
||||
|
||||
- type: shader
|
||||
@@ -11,5 +10,4 @@
|
||||
kind: source
|
||||
path: "/Textures/Shaders/outline.swsl"
|
||||
params:
|
||||
outline_width: 2
|
||||
outline_color: "#00FF0055"
|
||||
|
||||
Submodule RobustToolbox updated: ffa908bf27...c4946b8466
Reference in New Issue
Block a user