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";
|
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 _viewPortChanged;
|
||||||
|
|
||||||
private bool _visible;
|
private bool _visible;
|
||||||
|
|
||||||
private RenderTargetGroup _renderTarget ~ _?.ReleaseRef();
|
private RenderTargetGroup _renderTarget ~ _?.ReleaseRef();
|
||||||
|
|
||||||
public float2 ViewportSize => (float2)_oldViewportSize;
|
public float2 AvailableViewportSize => _availableViewportSize;
|
||||||
|
public float2 RenderedViewportSize => _renderedViewportSize;
|
||||||
|
|
||||||
// Occurs when the viewport is resized.
|
// Occurs when the viewport is resized.
|
||||||
public Event<EventHandler<float2>> ViewportSizeChanged ~ _.Dispose();
|
public Event<EventHandler<float2>> ViewportSizeChanged ~ _.Dispose();
|
||||||
// Occurs when an entity was clicked.
|
// Occurs when an entity was clicked.
|
||||||
@@ -71,19 +74,23 @@ namespace GlitchyEditor.EditWindows
|
|||||||
|
|
||||||
_hasFocus = ImGui.IsWindowFocused();
|
_hasFocus = ImGui.IsWindowFocused();
|
||||||
|
|
||||||
|
ShowMenuBar();
|
||||||
|
|
||||||
if(_renderTarget != null)
|
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();
|
ImGui.End();
|
||||||
|
|
||||||
if(_oldViewportSize != viewportSize)
|
SetAvailableViewportSize((float2)viewportSize);
|
||||||
{
|
|
||||||
ViewportSizeChanged.Invoke(this, (float2)viewportSize);
|
|
||||||
_viewPortChanged = true;
|
|
||||||
_oldViewportSize = viewportSize;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides the ImGui Drop target and handles dropped payload.
|
/// Provides the ImGui Drop target and handles dropped payload.
|
||||||
@@ -102,5 +109,175 @@ namespace GlitchyEditor.EditWindows
|
|||||||
ImGui.EndDragDropTarget();
|
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[](
|
ColorTargetDescriptions = TargetDescription[](
|
||||||
.(.R8G8B8A8_UNorm))
|
.(.R8G8B8A8_UNorm))
|
||||||
});
|
});
|
||||||
_editorViewportTarget.[Friend]Identifier = "Game Viewport Target";
|
_gameViewportTarget.[Friend]Identifier = "Game Viewport Target";
|
||||||
|
|
||||||
_editorIcons = new EditorIcons("Resources/Textures/EditorIcons.dds", .(64, 64));
|
_editorIcons = new EditorIcons("Resources/Textures/EditorIcons.dds", .(64, 64));
|
||||||
_editorIcons.SamplerState = SamplerStateManager.AnisotropicClamp;
|
_editorIcons.SamplerState = SamplerStateManager.AnisotropicClamp;
|
||||||
@@ -460,8 +460,8 @@ namespace GlitchyEditor
|
|||||||
{
|
{
|
||||||
_gameSceneRenderer.Scene = _activeScene;
|
_gameSceneRenderer.Scene = _activeScene;
|
||||||
|
|
||||||
_activeScene.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.ViewportSize.X, (uint32)_editor.GameViewportWindow.ViewportSize.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);
|
RenderCommand.Clear(_gameViewportTarget, .Color | .Depth, .(0.2f, 0.2f, 0.2f), 1.0f, 0);
|
||||||
_gameSceneRenderer.RenderRuntime(gameTime, _gameViewportTarget);
|
_gameSceneRenderer.RenderRuntime(gameTime, _gameViewportTarget);
|
||||||
@@ -960,10 +960,10 @@ namespace GlitchyEditor
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Update the viewport size because if the game windows size changed in
|
* 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).
|
* 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)
|
if (Application.Instance.Settings.EditorSettings.SwitchToEditorOnStop)
|
||||||
|
|||||||
@@ -864,4 +864,75 @@ static
|
|||||||
// transpose und determinante für Matrizen
|
// transpose und determinante für Matrizen
|
||||||
|
|
||||||
// sin, cos, tan, asin, acos, atan, atan2, cosh, sinh, tanh
|
// 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