mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Allow custom resolutions for game window
This commit is contained in:
@@ -13,14 +13,17 @@ namespace GlitchyEditor.EditWindows
|
||||
{
|
||||
public const String s_WindowTitle = "Game";
|
||||
|
||||
private ImGui.Vec2 _oldViewportSize = .(100, 100);
|
||||
private float2 _availableViewportSize = .(100, 100);
|
||||
private float2 _renderedViewportSize = .(100, 100);
|
||||
private bool _viewPortChanged;
|
||||
|
||||
private bool _visible;
|
||||
|
||||
private RenderTargetGroup _renderTarget ~ _?.ReleaseRef();
|
||||
|
||||
public float2 ViewportSize => (float2)_oldViewportSize;
|
||||
public float2 AvailableViewportSize => _availableViewportSize;
|
||||
public float2 RenderedViewportSize => _renderedViewportSize;
|
||||
|
||||
// Occurs when the viewport is resized.
|
||||
public Event<EventHandler<float2>> ViewportSizeChanged ~ _.Dispose();
|
||||
// Occurs when an entity was clicked.
|
||||
@@ -71,19 +74,23 @@ namespace GlitchyEditor.EditWindows
|
||||
|
||||
_hasFocus = ImGui.IsWindowFocused();
|
||||
|
||||
ShowMenuBar();
|
||||
|
||||
if(_renderTarget != null)
|
||||
{
|
||||
ImGui.Image(_renderTarget.GetViewBinding(0), viewportSize);
|
||||
float2 scalingFactor = CalculateFitScalingFactor(_availableViewportSize, _renderedViewportSize);
|
||||
|
||||
float2 previewResolution = scalingFactor * _renderedViewportSize;
|
||||
|
||||
float2 position = max(0.0f, _availableViewportSize / 2.0f - previewResolution / 2.0f) + (float2)ImGui.GetCursorPos();
|
||||
ImGui.SetCursorPos((ImGui.Vec2)position);
|
||||
|
||||
ImGui.Image(_renderTarget.GetViewBinding(0), (ImGui.Vec2)previewResolution);
|
||||
}
|
||||
|
||||
ImGui.End();
|
||||
|
||||
if(_oldViewportSize != viewportSize)
|
||||
{
|
||||
ViewportSizeChanged.Invoke(this, (float2)viewportSize);
|
||||
_viewPortChanged = true;
|
||||
_oldViewportSize = viewportSize;
|
||||
}
|
||||
SetAvailableViewportSize((float2)viewportSize);
|
||||
}
|
||||
|
||||
/// Provides the ImGui Drop target and handles dropped payload.
|
||||
@@ -102,5 +109,175 @@ namespace GlitchyEditor.EditWindows
|
||||
ImGui.EndDragDropTarget();
|
||||
}
|
||||
}
|
||||
|
||||
private void SetAvailableViewportSize(float2 viewportSize)
|
||||
{
|
||||
if(any(_availableViewportSize != viewportSize))
|
||||
{
|
||||
_availableViewportSize = viewportSize;
|
||||
|
||||
UpdateCustomResolution();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateCustomResolution()
|
||||
{
|
||||
float2 newRenderViewport = _renderedViewportSize;
|
||||
|
||||
switch (resolutionMode)
|
||||
{
|
||||
case .Window:
|
||||
newRenderViewport = _availableViewportSize;
|
||||
case .CustomAspect:
|
||||
float scalingFactor = CalculateFitScalingFactor(_availableViewportSize, _customAspectRatio);
|
||||
newRenderViewport = max(ceil(_customAspectRatio * scalingFactor), 16);
|
||||
case .CustomResolution:
|
||||
newRenderViewport = _customResolution;
|
||||
case .SixteenToNine:
|
||||
case .FullHd:
|
||||
newRenderViewport = .(1920, 1080);
|
||||
case .WQHD:
|
||||
newRenderViewport = .(2560, 1440);
|
||||
case .UltraHd:
|
||||
newRenderViewport = .(3840, 2160);
|
||||
}
|
||||
|
||||
if (any(newRenderViewport != _renderedViewportSize))
|
||||
{
|
||||
_viewPortChanged = true;
|
||||
_renderedViewportSize = newRenderViewport;
|
||||
ViewportSizeChanged.Invoke(this, (float2)_renderedViewportSize);
|
||||
}
|
||||
}
|
||||
|
||||
private float CalculateFitScalingFactor(float2 outerBox, float2 innerBox)
|
||||
{
|
||||
float outerAspectRatio = outerBox.X / outerBox.Y;
|
||||
float innerAspectRatio = innerBox.X / innerBox.Y;
|
||||
|
||||
float scalingFactor;
|
||||
|
||||
// If our target shape is wider than our viewport shape, we have to fit in x-direction
|
||||
// otherwise fit in y-direction
|
||||
if (innerAspectRatio > outerAspectRatio)
|
||||
{
|
||||
scalingFactor = outerBox.X / innerBox.X;
|
||||
}
|
||||
else
|
||||
{
|
||||
scalingFactor = outerBox.Y / innerBox.Y;
|
||||
}
|
||||
|
||||
return scalingFactor;
|
||||
}
|
||||
|
||||
private enum ResolutionMode
|
||||
{
|
||||
case Window;
|
||||
case CustomAspect;
|
||||
case CustomResolution;
|
||||
case SixteenToNine;
|
||||
case FullHd;
|
||||
case WQHD;
|
||||
case UltraHd;
|
||||
|
||||
public StringView GetPreviewName()
|
||||
{
|
||||
switch (this)
|
||||
{
|
||||
case .Window:
|
||||
return "Window";
|
||||
case .CustomAspect:
|
||||
return "Custom Aspect Ratio";
|
||||
case .CustomResolution:
|
||||
return "Custom Resolution";
|
||||
case .SixteenToNine:
|
||||
return "16:9";
|
||||
case .FullHd:
|
||||
return "1080p (Full HD)";
|
||||
case .WQHD:
|
||||
return "1440p (WQHD)";
|
||||
case .UltraHd:
|
||||
return "2160p (4k)";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private float2 _customAspectRatio = .(16, 9);
|
||||
private float2 _customResolution = .(-1, -1);
|
||||
|
||||
ResolutionMode resolutionMode = .Window;
|
||||
|
||||
private void ShowMenuBar()
|
||||
{
|
||||
if (ImGui.BeginMenuBar())
|
||||
{
|
||||
ImGui.TextUnformatted("Resolution: ");
|
||||
if (ImGui.BeginCombo("##resolution", resolutionMode.GetPreviewName().ToScopeCStr!(), .WidthFitPreview))
|
||||
{
|
||||
for (ResolutionMode mode in Enum.EnumValuesEnumerator<ResolutionMode>())
|
||||
{
|
||||
if (ImGui.Selectable(mode.GetPreviewName().ToScopeCStr!(), mode == resolutionMode))
|
||||
{
|
||||
resolutionMode = mode;
|
||||
|
||||
if (mode == .CustomResolution && any(_customResolution == -1))
|
||||
{
|
||||
_customResolution = _availableViewportSize;
|
||||
}
|
||||
|
||||
UpdateCustomResolution();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui.EndCombo();
|
||||
}
|
||||
|
||||
float itemWidth = ImGui.CalcTextSize("5.1234").x;
|
||||
ImGui.PushItemWidth(itemWidth);
|
||||
|
||||
if (resolutionMode == .CustomAspect)
|
||||
{
|
||||
if (ImGui.DragFloat("##aspectX", &_customAspectRatio.X, 1, 1.0f, 16384.0f, format: "%.4g"))
|
||||
{
|
||||
UpdateCustomResolution();
|
||||
}
|
||||
if (ImGui.DragFloat("##aspectY", &_customAspectRatio.Y, 1, 1.0f, 16384.0f, format: "%.4g"))
|
||||
{
|
||||
UpdateCustomResolution();
|
||||
}
|
||||
|
||||
ImGui.TextUnformatted(scope $"({_renderedViewportSize.X}px x {_renderedViewportSize.Y}px)");
|
||||
}
|
||||
else if (resolutionMode == .CustomResolution)
|
||||
{
|
||||
int32 resX = (int32)_customResolution.X;
|
||||
if (ImGui.DragInt("##resolutionX", &resX, 1, 1))
|
||||
{
|
||||
_customResolution.X = resX;
|
||||
UpdateCustomResolution();
|
||||
|
||||
}
|
||||
int32 resY = (int32)_customResolution.Y;
|
||||
if (ImGui.DragInt("##resolutionY", &resY, 1, 1))
|
||||
{
|
||||
_customResolution.Y = resY;
|
||||
UpdateCustomResolution();
|
||||
}
|
||||
|
||||
int gcd = gcd((int)_customResolution.X, (int)_customResolution.Y);
|
||||
|
||||
ImGui.TextUnformatted(scope $"({_customResolution.X / gcd}:{_customResolution.Y / gcd})");
|
||||
}
|
||||
else
|
||||
{
|
||||
ImGui.TextUnformatted(scope $"({_renderedViewportSize.X}px x {_renderedViewportSize.Y}px)");
|
||||
}
|
||||
|
||||
ImGui.PopItemWidth();
|
||||
|
||||
ImGui.EndMenuBar();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -365,7 +365,7 @@ namespace GlitchyEditor
|
||||
ColorTargetDescriptions = TargetDescription[](
|
||||
.(.R8G8B8A8_UNorm))
|
||||
});
|
||||
_editorViewportTarget.[Friend]Identifier = "Game Viewport Target";
|
||||
_gameViewportTarget.[Friend]Identifier = "Game Viewport Target";
|
||||
|
||||
_editorIcons = new EditorIcons("Resources/Textures/EditorIcons.dds", .(64, 64));
|
||||
_editorIcons.SamplerState = SamplerStateManager.AnisotropicClamp;
|
||||
@@ -460,8 +460,8 @@ namespace GlitchyEditor
|
||||
{
|
||||
_gameSceneRenderer.Scene = _activeScene;
|
||||
|
||||
_activeScene.SetViewportSize((uint32)_editor.GameViewportWindow.ViewportSize.X, (uint32)_editor.GameViewportWindow.ViewportSize.Y);
|
||||
_gameSceneRenderer.SetViewportSize((uint32)_editor.GameViewportWindow.ViewportSize.X, (uint32)_editor.GameViewportWindow.ViewportSize.Y);
|
||||
_activeScene.SetViewportSize((uint32)_editor.GameViewportWindow.RenderedViewportSize.X, (uint32)_editor.GameViewportWindow.RenderedViewportSize.Y);
|
||||
_gameSceneRenderer.SetViewportSize((uint32)_editor.GameViewportWindow.RenderedViewportSize.X, (uint32)_editor.GameViewportWindow.RenderedViewportSize.Y);
|
||||
|
||||
RenderCommand.Clear(_gameViewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
|
||||
_gameSceneRenderer.RenderRuntime(gameTime, _gameViewportTarget);
|
||||
@@ -960,10 +960,10 @@ namespace GlitchyEditor
|
||||
{
|
||||
/*
|
||||
* Update the viewport size because if the game windows size changed in
|
||||
* "Game"-mode the updated aspect-rations will reset once we go back
|
||||
* "Game"-mode the updated aspect-ratios will reset once we go back
|
||||
* into "Editor"-mode (because Game-Mode works on a copy of the scene).
|
||||
*/
|
||||
GameViewportSizeChanged(null, _editor.GameViewportWindow.ViewportSize);
|
||||
GameViewportSizeChanged(null, _editor.GameViewportWindow.RenderedViewportSize);
|
||||
}
|
||||
|
||||
if (Application.Instance.Settings.EditorSettings.SwitchToEditorOnStop)
|
||||
|
||||
@@ -864,4 +864,75 @@ static
|
||||
// transpose und determinante für Matrizen
|
||||
|
||||
// sin, cos, tan, asin, acos, atan, atan2, cosh, sinh, tanh
|
||||
|
||||
#region Fancy Stuff
|
||||
|
||||
/// @brief Calculates the greates common divisor (greates common factor) of two unsgined integer a and b.
|
||||
/// Based on https://en.wikipedia.org/wiki/Binary_GCD_algorithm
|
||||
public static uint64 gcd(uint64 u, uint64 v)
|
||||
{
|
||||
if (u == 0)
|
||||
return v;
|
||||
if (v == 0)
|
||||
return u;
|
||||
|
||||
var u, v;
|
||||
|
||||
// Essentially we want to know how many trailing zeros a and b have.
|
||||
// TODO: If we have an efficient algorithm for that, this might become a lot faster.
|
||||
uint64 trailingZerosU = 0;
|
||||
while ((u % 2) == 0)
|
||||
{
|
||||
u >>= 1;
|
||||
trailingZerosU++;
|
||||
}
|
||||
|
||||
uint64 trailingZerosV = 0;
|
||||
while ((v % 2) == 0)
|
||||
{
|
||||
v >>= 1;
|
||||
trailingZerosV++;
|
||||
}
|
||||
|
||||
uint64 k = Math.Min(trailingZerosU, trailingZerosV);
|
||||
|
||||
while (true)
|
||||
{
|
||||
Log.EngineLogger.AssertDebug(u % 2 == 1, "a should be odd");
|
||||
Log.EngineLogger.AssertDebug(v % 2 == 1, "b should be odd");
|
||||
|
||||
if (u > v)
|
||||
{
|
||||
(u, v) = (v, u);
|
||||
}
|
||||
|
||||
v -= u;
|
||||
// b is now even
|
||||
|
||||
if (v == 0)
|
||||
{
|
||||
return u << k;
|
||||
}
|
||||
|
||||
// Make v odd again
|
||||
while ((v % 2) == 0)
|
||||
{
|
||||
v >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// @brief Calculates the greates common divisor (greates common factor) of two signed integer a and b.
|
||||
/// Based on https://en.wikipedia.org/wiki/Binary_GCD_algorithm
|
||||
public static int64 gcd(int64 u, int64 v)
|
||||
{
|
||||
return (int64)gcd((uint64)Math.Abs(u), (uint64)Math.Abs(v));
|
||||
}
|
||||
|
||||
public static this()
|
||||
{
|
||||
int64 i = (int64)gcd(38, 123);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
Reference in New Issue
Block a user