Fixed Merge

This commit is contained in:
Michel Fedde 2021-03-22 13:20:59 +01:00
commit bb030f588b
65 changed files with 917 additions and 1427 deletions

View file

@ -6,12 +6,24 @@ using SM.Base.Scene;
namespace SM.Base.Window
{
/// <summary>
/// A context that gets send when a window want to update the scene.
/// </summary>
public struct UpdateContext
{
/// <summary>
/// The window what triggered the updated.
/// </summary>
public IGenericWindow Window;
/// <summary>
/// A current update delta time. Equivalent to <see cref="SMRenderer.DefaultDeltatime"/>.
/// </summary>
public float Deltatime => SMRenderer.DefaultDeltatime.DeltaTime;
/// <summary>
/// The scene that gets updated.
/// </summary>
public GenericScene Scene;
}
}

View file

@ -3,6 +3,7 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing.Text;
using System.Threading;
using System.Windows.Forms;
using OpenTK;
@ -18,58 +19,105 @@ using Mouse = SM.Base.Controls.Mouse;
namespace SM.Base.Window
{
/// <summary>
/// This provides the main entry, by executing the window.
/// </summary>
public class GLWindow : GameWindow, IGenericWindow
{
private Vector2 _flagWindowPos;
private Vector2 _flagWindowSize;
private Thread _fixedUpdateThread;
private WindowFlags _windowFlags;
public WindowFlags WindowFlags;
private DisplayResolution _normalResolution;
private DisplayResolution _fullscreenResolution;
/// <inheritdoc />
public bool Loading { get; private set; } = true;
/// <inheritdoc />
public float AspectRatio { get; set; }
/// <inheritdoc />
public GenericCamera ViewportCamera { get; set; }
/// <inheritdoc />
public bool ForceViewportCamera { get; set; }
/// <inheritdoc />
public bool DrawWhileUnfocused { get; set; } = true;
/// <inheritdoc />
public bool UpdateWhileUnfocused { get; set; } = false;
/// <inheritdoc />
public Vector2 WindowSize { get; set; }
/// <inheritdoc />
public ISetup AppliedSetup { get; private set; }
/// <inheritdoc />
public new event Action<IGenericWindow> Resize;
/// <inheritdoc />
public new event Action<IGenericWindow> Load;
/// <inheritdoc />
public GenericScene CurrentScene { get; private set; }
/// <inheritdoc />
public RenderPipeline CurrentRenderPipeline { get; private set; }
/// <summary>
/// Gets/Sets the current window flag.
/// </summary>
public WindowFlags WindowFlags
{
get => _windowFlags;
set
{
if (_windowFlags != value)
{
WindowFlags oldV = _windowFlags;
_windowFlags = value;
ChangeWindowFlag(value, oldV);
}
}
}
/// <summary>
/// Loads the window with default values.
/// <para>Width: 1280px; Height: 720px; Title: Generic OpenGL Title; WindowFlag: Window</para>
/// </summary>
public GLWindow() : this(1280, 720, "Generic OpenGL Title", WindowFlags.Window)
{
}
/// <summary>
/// Loads the window with custom values.
/// </summary>
/// <param name="width"></param>
/// <param name="height"></param>
/// <param name="title"></param>
/// <param name="flags"></param>
/// <param name="vSync"></param>
public GLWindow(int width, int height, string title, WindowFlags flags, VSyncMode vSync = VSyncMode.On) :
base(width, height, default, title, (GameWindowFlags) flags, DisplayDevice.Default,
base(width, height, default, title, GameWindowFlags.Default, DisplayDevice.Default,
GLSettings.ForcedVersion.MajorVersion, GLSettings.ForcedVersion.MinorVersion,
GraphicsContextFlags.Default)
{
VSync = vSync;
_flagWindowSize = new Vector2(width, height);
WindowFlags = flags;
ChangeWindowFlag(flags);
FocusedChanged += GLWindow_FocusedChanged;
_normalResolution = _fullscreenResolution = DisplayDevice.Default.SelectResolution(DisplayDevice.Default.Width, DisplayDevice.Default.Height, DisplayDevice.Default.BitsPerPixel, DisplayDevice.Default.RefreshRate);
}
public bool Loading { get; private set; } = true;
public float AspectRatio { get; set; }
public GenericCamera ViewportCamera { get; set; }
public bool ForceViewportCamera { get; set; }
public bool DrawWhileUnfocused { get; set; } = true;
public bool UpdateWhileUnfocused { get; set; } = false;
public Vector2 WindowSize { get; set; }
public ISetup AppliedSetup { get; private set; }
public new event Action<IGenericWindow> Resize;
public new event Action<IGenericWindow> Load;
public GenericScene CurrentScene { get; private set; }
public RenderPipeline CurrentRenderPipeline { get; private set; }
public void TriggerLoad()
{
Load?.Invoke(this);
}
public void TriggerResize()
{
Resize?.Invoke(this);
}
/// <summary>
/// A event that gets executed when the window is done loading.
/// </summary>
public event Action<IGenericWindow> Loaded;
/// <inheritdoc />
protected override void OnLoad(EventArgs e)
{
WindowCode.Load(this);
@ -78,14 +126,13 @@ namespace SM.Base.Window
base.OnLoad(e);
}
/// <inheritdoc />
protected override void OnResize(EventArgs e)
{
base.OnResize(e);
WindowCode.Resize(this);
if (WindowFlags == WindowFlags.Window) _flagWindowSize = WindowSize;
if (Loading)
{
Loading = false;
@ -94,6 +141,7 @@ namespace SM.Base.Window
}
}
/// <inheritdoc />
protected override void OnUpdateFrame(FrameEventArgs e)
{
if (!Focused && !UpdateWhileUnfocused) return;
@ -104,6 +152,7 @@ namespace SM.Base.Window
}
/// <inheritdoc />
protected override void OnRenderFrame(FrameEventArgs e)
{
base.OnRenderFrame(e);
@ -115,23 +164,40 @@ namespace SM.Base.Window
GLDebugging.CheckGLErrors();
}
/// <inheritdoc />
protected override void OnMouseMove(MouseMoveEventArgs e)
{
base.OnMouseMove(e);
Mouse.MouseMoveEvent(e, this);
}
/// <inheritdoc />
public void TriggerLoad()
{
Load?.Invoke(this);
}
/// <inheritdoc />
public void TriggerResize()
{
Resize?.Invoke(this);
}
/// <inheritdoc />
public void Update(UpdateContext context)
{
}
/// <inheritdoc />
public void ApplySetup(ISetup setup)
{
AppliedSetup = setup;
setup.Applied(this);
}
/// <inheritdoc />
public void SetScene(GenericScene scene)
{
if (Loading)
@ -144,6 +210,7 @@ namespace SM.Base.Window
CurrentScene = scene;
}
/// <inheritdoc />
public void SetRenderPipeline(RenderPipeline renderPipeline)
{
if (Loading)
@ -156,34 +223,23 @@ namespace SM.Base.Window
CurrentRenderPipeline = renderPipeline;
}
public void ChangeWindowFlag(WindowFlags newFlag)
/// <summary>
/// Changes the resolution in fullscreen mode.
/// <para>Can be executed before changing to fullscreen, but with no effect until changed.</para>
/// </summary>
/// <param name="resolution">The resolution you get from <see cref="DisplayDevice.AvailableResolutions"/> or <see cref="DisplayDevice.SelectResolution"/></param>
public void ChangeFullscreenResolution(DisplayResolution resolution)
{
WindowFlags = newFlag;
_fullscreenResolution = resolution;
switch (newFlag)
{
case WindowFlags.Window:
Width = (int) _flagWindowSize.X;
Height = (int) _flagWindowSize.Y;
WindowBorder = WindowBorder.Resizable;
break;
case WindowFlags.BorderlessWindow:
WindowBorder = WindowBorder.Hidden;
X = Screen.PrimaryScreen.Bounds.Left;
Y = Screen.PrimaryScreen.Bounds.Top;
Width = Screen.PrimaryScreen.Bounds.Width;
Height = Screen.PrimaryScreen.Bounds.Height;
break;
case WindowFlags.ExclusiveFullscreen:
break;
default:
throw new ArgumentOutOfRangeException(nameof(newFlag), newFlag, null);
}
if (_windowFlags == WindowFlags.ExclusiveFullscreen) ApplyFullscreenResolution();
}
/// <summary>
/// Starts the fixed update loop.
/// <para>Need to get executed before <see cref="IFixedScriptable"/> can be used.</para>
/// </summary>
/// <param name="updatesPerSecond"></param>
public void RunFixedUpdate(float updatesPerSecond)
{
Deltatime.FixedUpdateDelta = 1 / (float)updatesPerSecond;
@ -208,5 +264,76 @@ namespace SM.Base.Window
Thread.Sleep(waitTime);
}
}
private void GLWindow_FocusedChanged(object sender, EventArgs e)
{
if (_windowFlags == WindowFlags.ExclusiveFullscreen)
{
if (!Focused)
{
DisplayDevice.Default.ChangeResolution(_normalResolution);
WindowState = WindowState.Minimized;
}
else
{
ApplyFullscreenResolution();
}
}
}
private void ChangeWindowFlag(WindowFlags newFlag, WindowFlags oldFlag)
{
if (oldFlag == WindowFlags.Window)
{
_flagWindowSize = WindowSize;
_flagWindowPos = new Vector2(X, Y);
}
switch (newFlag)
{
case WindowFlags.Window:
DisplayDevice.Default.ChangeResolution(_normalResolution);
WindowState = WindowState.Normal;
Width = (int)_flagWindowSize.X;
Height = (int)_flagWindowSize.Y;
X = (int) _flagWindowPos.X;
Y = (int) _flagWindowPos.Y;
WindowBorder = WindowBorder.Resizable;
break;
case WindowFlags.BorderlessWindow:
DisplayDevice.Default.ChangeResolution(_normalResolution);
WindowState = WindowState.Maximized;
WindowBorder = WindowBorder.Hidden;
X = Screen.PrimaryScreen.Bounds.Left;
Y = Screen.PrimaryScreen.Bounds.Top;
Width = Screen.PrimaryScreen.Bounds.Width;
Height = Screen.PrimaryScreen.Bounds.Height;
break;
case WindowFlags.ExclusiveFullscreen:
WindowState = WindowState.Fullscreen;
ApplyFullscreenResolution();
break;
default:
throw new ArgumentOutOfRangeException(nameof(newFlag), newFlag, null);
}
}
private void ApplyFullscreenResolution()
{
DisplayDevice.Default.ChangeResolution(_fullscreenResolution);
Width = _fullscreenResolution.Width;
Height = _fullscreenResolution.Height;
}
}
}

View file

@ -10,39 +10,106 @@ using SM.OGL.Framebuffer;
namespace SM.Base.Window
{
/// <summary>
/// This interface sets ground functions for windows.
/// </summary>
public interface IGenericWindow : IFramebufferWindow
{
/// <summary>
/// If true, the window is currently loading.
/// </summary>
bool Loading { get; }
/// <summary>
/// Holds the aspect ratio of the window.
/// </summary>
float AspectRatio { get; set; }
/// <summary>
/// The viewport camera is used, when no camera is found in the scene.
/// </summary>
GenericCamera ViewportCamera { get; set; }
/// <summary>
/// Turning this to true, will force the window to render in the viewport camera.
/// </summary>
bool ForceViewportCamera { get; set; }
/// <summary>
/// Turning this to false will not allow drawing while the window is not in focus.
/// </summary>
bool DrawWhileUnfocused { get; set; }
/// <summary>
/// Turning this to false will not allow updating while the window is not in focus.
/// </summary>
bool UpdateWhileUnfocused { get; set; }
/// <summary>
/// Contains the window size.
/// </summary>
Vector2 WindowSize { get; set; }
/// <summary>
/// The rectangle the window is using.
/// </summary>
Rectangle ClientRectangle { get; }
/// <summary>
/// The setup that was applied to the window.
/// </summary>
ISetup AppliedSetup { get; }
/// <summary>
/// The scene that is currently used.
/// </summary>
GenericScene CurrentScene { get; }
/// <summary>
/// The render pipeline that is currently used.
/// </summary>
RenderPipeline CurrentRenderPipeline { get; }
/// <summary>
/// An event, when the window resizes.
/// </summary>
event Action<IGenericWindow> Resize;
/// <summary>
/// An event, when the window is loading.
/// </summary>
event Action<IGenericWindow> Load;
/// <summary>
/// This gets executed, when the window should update something.
/// </summary>
/// <param name="context">The context of the update.</param>
void Update(UpdateContext context);
/// <summary>
/// This applies a setup to the window.
/// </summary>
/// <param name="setup"></param>
void ApplySetup(ISetup setup);
/// <summary>
/// This sets a scene for the window to use.
/// </summary>
/// <param name="scene"></param>
void SetScene(GenericScene scene);
/// <summary>
/// This sets a render pipeline, from where the scene gets rendered.
/// </summary>
/// <param name="renderPipeline"></param>
void SetRenderPipeline(RenderPipeline renderPipeline);
/// <summary>
/// This triggeres the <see cref="Load"/> event.
/// </summary>
void TriggerLoad();
/// <summary>
/// This triggeres the <see cref="Resize"/> event.
/// </summary>
void TriggerResize();
/// <summary>
/// This closes the window.
/// </summary>
void Close();
}
}

View file

@ -53,9 +53,10 @@ namespace SM.Base.Window
/// <inheritdoc/>
public virtual void Initialization()
{
MainFramebuffer.Name = GetType().Name + ".MainFramebuffer";
if (MainFramebuffer != null) Framebuffers.Add(MainFramebuffer);
if (MainFramebuffer != null) {
Framebuffers.Add(MainFramebuffer);
MainFramebuffer.Name = GetType().Name + ".MainFramebuffer";
}
DefaultShader ??= SMRenderer.DefaultMaterialShader;
}

View file

@ -93,6 +93,7 @@ namespace SM.Base.Window
internal static void Render(IGenericWindow window, float deltatime)
{
if (window.CurrentScene == null) return;
if (window.CurrentRenderPipeline == null) window.SetRenderPipeline(SMRenderer.DefaultRenderPipeline);
SMRenderer.CurrentFrame++;