using System; using System.IO; using OpenTK; using OpenTK.Graphics; using OpenTK.Graphics.OpenGL4; using OpenTK.Input; using SM.Base.Contexts; using SM.Base.Objects.Static; using SM.Base.Scene; using SM.Base.Time; using SM.OGL; using SM.OGL.Shaders; using SM.Utility; namespace SM.Base { /// /// The base window. /// public abstract class GenericWindow : GameWindow { private bool _loading = false; /// /// This tells you the current world scale. /// protected Vector2 _worldScale = Vector2.Zero; /// /// This tells you the current aspect ratio of this window. /// public float Aspect { get; private set; } = 0f; /// protected GenericWindow() : base(1280, 720, GraphicsMode.Default, "Generic OGL Title", GameWindowFlags.Default, DisplayDevice.Default, 0, 0, GraphicsContextFlags.Default, null, true) { } /// protected override void OnLoad(EventArgs e) { GLSystem.INIT_SYSTEM(); Log.Write("#", ConsoleColor.Cyan, "----------------------", "--- OpenGL Loading ---", "----------------------------------", $"--- {"DeviceVersion",14}: {GLSystem.DeviceVersion,-10} ---", $"--- {"ForcedVersion",14}: {GLSystem.ForcedVersion,-10} ---", $"--- {"ShadingVersion",14}: {GLSystem.ShadingVersion,-10} ---", $"--- {"Debugging",14}: {GLSystem.Debugging,-10} ---", $"----------------------------------"); base.OnLoad(e); _loading = true; } /// protected override void OnResize(EventArgs e) { base.OnResize(e); Aspect = (float)Width / Height; _worldScale = new Vector2(Width, Height); SetWorldScale(); GL.Viewport(ClientRectangle); if (_loading) { _loading = false; OnLoaded(); } } /// /// This is triggered after all the window-loading has been done. /// protected virtual void OnLoaded() { } /// /// Sets the world scale. /// protected virtual void SetWorldScale() { } /// protected override void OnUpdateFrame(FrameEventArgs e) { base.OnUpdateFrame(e); Deltatime.UpdateDelta = (float)e.Time; UpdateContext context = new UpdateContext() { KeyboardState = Keyboard.GetState(), MouseState = Mouse.GetState() }; Stopwatch.PerformTicks(context); } /// /// Grabs the cursor and make sure it doesn't leave the window. /// /// If true, it makes the cursor invisible. public void GrabCursor(bool makeItInvisible = true) { CursorGrabbed = true; CursorVisible = !makeItInvisible; } /// /// Ungrabs the cursor. /// public void UngrabCursor() { CursorGrabbed = false; if (!CursorVisible) CursorVisible = true; } } /// /// The base window. /// /// The scene type /// The camera type public abstract class GenericWindow : GenericWindow where TScene : GenericScene, new() where TCamera : GenericCamera, new() { /// /// The viewport camera. /// public TCamera ViewportCamera { get; } /// /// This forces the render to use the viewport camera. /// public bool ForceViewportCamera { get; set; } = false; /// /// The current scene. /// public TScene CurrentScene { get; private set; } /// /// Controls how a scene is rendered. /// public RenderPipeline RenderPipeline { get; private set; } /// protected GenericWindow() { ViewportCamera = new TCamera(); } /// protected override void OnRenderFrame(FrameEventArgs e) { Deltatime.RenderDelta = (float)e.Time; DrawContext drawContext = new DrawContext() { World = ViewportCamera.World, View = ViewportCamera.CalculateViewMatrix(), Instances = new[] { new Instance {ModelMatrix = Matrix4.Identity, TexturePosition = Vector2.Zero, TextureScale = Vector2.One } }, Mesh = Plate.Object, ForceViewport = ForceViewportCamera, WorldScale = _worldScale }; base.OnRenderFrame(e); RenderPipeline.Render(ref drawContext, CurrentScene); SwapBuffers(); GLDebugging.CheckGLErrors(); } /// protected override void OnResize(EventArgs e) { base.OnResize(e); ViewportCamera.RecalculateWorld(_worldScale, Aspect); RenderPipeline.Resize(); } /// /// Sets the scene. /// /// public virtual void SetScene(TScene scene) { CurrentScene = scene; scene.Activate(); } /// /// Defines the render pipeline. /// /// public void SetRenderPipeline(RenderPipeline pipeline) { RenderPipeline = pipeline; pipeline.Activate(this); } } }