mirror of
https://github.com/Facepunch/sbox-public.git
synced 2025-12-23 22:48:07 -05:00
Play mode: re-add game view resolution/ratio dropdown functionality
This commit is contained in:
@@ -24,6 +24,8 @@ public partial class SceneViewWidget
|
||||
|
||||
_gameViewport = _viewports.FirstOrDefault().Value;
|
||||
_gameViewport.StartPlay();
|
||||
|
||||
_viewportTools.UpdateViewportFromCookie();
|
||||
}
|
||||
|
||||
[Event( "scene.stop" )]
|
||||
@@ -65,10 +67,44 @@ public partial class SceneViewWidget
|
||||
_sidePanel?.Visible = CurrentView != ViewMode.Game;
|
||||
}
|
||||
|
||||
// The first viewport is our target for now - we could probably do something smarter
|
||||
// in future, like using the last focused viewport
|
||||
public SceneViewportWidget GetGameTarget()
|
||||
{
|
||||
return _gameViewport;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the game viewport to free sizing mode
|
||||
/// </summary>
|
||||
public void SetFreeSize()
|
||||
{
|
||||
var viewport = GetGameTarget();
|
||||
if ( viewport.IsValid() )
|
||||
{
|
||||
viewport.SetDefaultSize();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the game viewport to a specific aspect ratio
|
||||
/// </summary>
|
||||
public void SetForceAspect( float aspect )
|
||||
{
|
||||
var viewport = GetGameTarget();
|
||||
if ( viewport.IsValid() )
|
||||
{
|
||||
viewport.SetAspectRatio( aspect );
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the game viewport to a specific resolution
|
||||
/// </summary>
|
||||
public void SetForceResolution( Vector2 resolution )
|
||||
{
|
||||
var viewport = GetGameTarget();
|
||||
if ( viewport.IsValid() )
|
||||
{
|
||||
viewport.SetResolution( resolution );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,7 +263,9 @@ public partial class SceneViewWidget : Widget
|
||||
}
|
||||
default:
|
||||
case ViewportLayoutMode.One:
|
||||
Layout.AddStretchCell();
|
||||
viewportLayout.Add( CreateViewport() );
|
||||
Layout.AddStretchCell();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ public partial class SceneViewportWidget
|
||||
Renderer.Camera = _activeCamera;
|
||||
Renderer.EnableEngineOverlays = false;
|
||||
ViewportOptions.Visible = true;
|
||||
SetDefaultSize();
|
||||
}
|
||||
|
||||
public void EjectGameCamera()
|
||||
@@ -40,6 +41,7 @@ public partial class SceneViewportWidget
|
||||
Renderer.Camera = _activeCamera;
|
||||
Renderer.EnableEngineOverlays = false;
|
||||
ViewportOptions.Visible = true;
|
||||
SetDefaultSize();
|
||||
}
|
||||
|
||||
public void PossesGameCamera()
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
namespace Editor;
|
||||
|
||||
public partial class SceneViewportWidget
|
||||
{
|
||||
Vector2? ForcedSize { get; set; }
|
||||
float? ForcedAspectRatio { get; set; }
|
||||
|
||||
//
|
||||
// Qt constraint -- unsets FixedSize when set to this value
|
||||
//
|
||||
const float QT_MAX_SIZE = (1 << 24) - 1;
|
||||
|
||||
/// <summary>
|
||||
/// Set the forced size to defaults (free size)
|
||||
/// </summary>
|
||||
public void SetDefaultSize()
|
||||
{
|
||||
ForcedSize = null;
|
||||
ForcedAspectRatio = null;
|
||||
|
||||
MinimumSize = Vector2.Zero;
|
||||
MaximumSize = QT_MAX_SIZE;
|
||||
FixedSize = QT_MAX_SIZE;
|
||||
|
||||
SetSizeMode( SizeMode.CanGrow, SizeMode.CanGrow );
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the viewport to a specific aspect ratio
|
||||
/// </summary>
|
||||
/// <param name="aspectRatio"></param>
|
||||
public void SetAspectRatio( float aspectRatio )
|
||||
{
|
||||
ForcedAspectRatio = aspectRatio;
|
||||
ForcedSize = null;
|
||||
|
||||
UpdateSizeConstraints();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Tries to set the viewport to a specific resolution
|
||||
/// </summary>
|
||||
/// <param name="resolution"></param>
|
||||
public void SetResolution( Vector2 resolution )
|
||||
{
|
||||
ForcedSize = resolution;
|
||||
ForcedAspectRatio = null;
|
||||
|
||||
UpdateSizeConstraints();
|
||||
}
|
||||
|
||||
private void UpdateSizeConstraints()
|
||||
{
|
||||
if ( ForcedSize.HasValue )
|
||||
{
|
||||
var size = ForcedSize.Value;
|
||||
|
||||
// For fixed resolution, use exact size constraints
|
||||
MaximumSize = size;
|
||||
FixedSize = size;
|
||||
}
|
||||
else
|
||||
{
|
||||
// For aspect ratio mode or free, don't lock the size - let it be dynamic
|
||||
MaximumSize = new Vector2( QT_MAX_SIZE, QT_MAX_SIZE );
|
||||
FixedSize = QT_MAX_SIZE;
|
||||
}
|
||||
|
||||
Layout.SizeConstraint = SizeConstraint.SetDefaultConstraint;
|
||||
SetSizeMode( SizeMode.Expand, SizeMode.Expand );
|
||||
|
||||
UpdateGeometry();
|
||||
AdjustSize();
|
||||
}
|
||||
|
||||
protected override Vector2 SizeHint()
|
||||
{
|
||||
// Exact size, easy
|
||||
if ( ForcedSize.HasValue )
|
||||
{
|
||||
return ForcedSize.Value;
|
||||
}
|
||||
|
||||
// Free
|
||||
if ( !ForcedAspectRatio.HasValue )
|
||||
{
|
||||
return base.SizeHint();
|
||||
}
|
||||
|
||||
// Dynamically calculate size based on current parent size
|
||||
var parentSize = Parent?.Size ?? base.SizeHint();
|
||||
var parentAspect = parentSize.x / parentSize.y;
|
||||
var aspectRatio = ForcedAspectRatio.Value;
|
||||
|
||||
if ( aspectRatio > parentAspect )
|
||||
{
|
||||
// Fit to width
|
||||
return new Vector2( parentSize.x, parentSize.x / aspectRatio );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fit to height
|
||||
return new Vector2( parentSize.y * aspectRatio, parentSize.y );
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,9 @@ partial class ViewportTools
|
||||
private Label FrameRateLabel;
|
||||
private ResolutionModeButton ResolutionComboBox;
|
||||
|
||||
/// <inheritdoc cref="ResolutionModeButton.UpdateViewportFromCookie"/>
|
||||
public void UpdateViewportFromCookie() => ResolutionComboBox.UpdateViewportFromCookie();
|
||||
|
||||
private void BuildToolbarGame( Layout layout )
|
||||
{
|
||||
{
|
||||
@@ -66,8 +69,7 @@ partial class ViewportTools
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
internal class ResolutionModeButton : Button
|
||||
class ResolutionModeButton : Button
|
||||
{
|
||||
private int _selectedIndex = 0;
|
||||
private List<Option> _options;
|
||||
@@ -76,8 +78,16 @@ internal class ResolutionModeButton : Button
|
||||
|
||||
private SceneViewWidget _sceneViewWidget;
|
||||
|
||||
static string EditorDisplayMode
|
||||
{
|
||||
get => ProjectCookie.Get( "EditorDisplayMode", "Free Size" );
|
||||
set => ProjectCookie.Set( "EditorDisplayMode", value );
|
||||
}
|
||||
|
||||
public ResolutionModeButton( SceneViewWidget sceneViewWidget ) : base( null )
|
||||
{
|
||||
_sceneViewWidget = sceneViewWidget;
|
||||
|
||||
SetStyles( $"padding-left: 32px; padding-right: 32px; font-family: '{Theme.DefaultFont}'; padding-top: 6px; padding-bottom: 6px;" );
|
||||
FixedWidth = 210;
|
||||
FixedHeight = Theme.RowHeight + 6;
|
||||
@@ -86,48 +96,45 @@ internal class ResolutionModeButton : Button
|
||||
UpdateButtonText();
|
||||
|
||||
Clicked = Click;
|
||||
|
||||
_sceneViewWidget = sceneViewWidget;
|
||||
}
|
||||
|
||||
private void InitializeOptions()
|
||||
{
|
||||
var view = _sceneViewWidget;
|
||||
_options =
|
||||
[
|
||||
new Option( "Free Size", "fit_screen", () => SetFreeSize() ),
|
||||
new Option( "16:9 Aspect", "aspect_ratio", () => SetForceAspect( 16.0f / 9.0f ) ),
|
||||
new Option( "21:9 Aspect", "aspect_ratio", () => SetForceAspect( 21.0f / 9.0f ) ),
|
||||
new Option( "4:3 Aspect", "aspect_ratio", () => SetForceAspect( 4.0f / 3.0f ) ),
|
||||
new Option( "9:16 Aspect", "aspect_ratio", () => SetForceAspect( 9.0f / 16.0f ) ),
|
||||
new Option( "Steam Deck", "stay_current_landscape", () => SetForceResolution( new( 1280, 800 ) ) ),
|
||||
new Option( "720p", "laptop_windows", () => SetForceResolution( new( 1280, 720 ) ) ),
|
||||
new Option( "1080p", "desktop_windows", () => SetForceResolution( new( 1920, 1080 ) ) ),
|
||||
new Option( "Free Size", "fit_screen", () => view.SetFreeSize() ),
|
||||
new Option( "16:9 Aspect", "aspect_ratio", () => view.SetForceAspect( 16.0f / 9.0f ) ),
|
||||
new Option( "21:9 Aspect", "aspect_ratio", () => view.SetForceAspect( 21.0f / 9.0f ) ),
|
||||
new Option( "4:3 Aspect", "aspect_ratio", () => view.SetForceAspect( 4.0f / 3.0f ) ),
|
||||
new Option( "9:16 Aspect", "aspect_ratio", () => view.SetForceAspect( 9.0f / 16.0f ) ),
|
||||
new Option( "Steam Deck", "stay_current_landscape", () => view.SetForceResolution( new( 1280, 800 ) ) ),
|
||||
new Option( "720p", "laptop_windows", () => view.SetForceResolution( new( 1280, 720 ) ) ),
|
||||
new Option( "1080p", "desktop_windows", () => view.SetForceResolution( new( 1920, 1080 ) ) ),
|
||||
];
|
||||
}
|
||||
|
||||
void SetForceAspect( float aspect )
|
||||
/// <summary>
|
||||
/// Updates the viewport from the <see cref="EditorDisplayMode"/> cookie
|
||||
/// </summary>
|
||||
public void UpdateViewportFromCookie()
|
||||
{
|
||||
var viewport = _sceneViewWidget.GetGameTarget();
|
||||
// viewport.SetForceAspect( aspect );
|
||||
var storedMode = EditorDisplayMode;
|
||||
var option = _options.FirstOrDefault( o => o.Text == storedMode );
|
||||
|
||||
UpdateButtonText();
|
||||
if ( option != null )
|
||||
{
|
||||
_selectedIndex = _options.IndexOf( option );
|
||||
option.Triggered?.Invoke();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Fallback to first option if not found
|
||||
_selectedIndex = 0;
|
||||
_options[0].Triggered?.Invoke();
|
||||
}
|
||||
}
|
||||
|
||||
void SetFreeSize()
|
||||
{
|
||||
var viewport = _sceneViewWidget.GetGameTarget();
|
||||
// viewport.SetFreeSize();
|
||||
|
||||
UpdateButtonText();
|
||||
}
|
||||
|
||||
void SetForceResolution( Vector2 res )
|
||||
{
|
||||
var viewport = _sceneViewWidget.GetGameTarget();
|
||||
// viewport.SetForceResolution( res );
|
||||
|
||||
UpdateButtonText();
|
||||
}
|
||||
|
||||
public string GetSizeString()
|
||||
{
|
||||
@@ -159,6 +166,7 @@ internal class ResolutionModeButton : Button
|
||||
|
||||
menu.AddOption( option.Text, option.Icon, () =>
|
||||
{
|
||||
EditorDisplayMode = option.Text;
|
||||
_selectedIndex = index;
|
||||
option.Triggered?.Invoke();
|
||||
} );
|
||||
|
||||
Reference in New Issue
Block a user