| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389 |
- using System;
- using System.Diagnostics;
- using System.Runtime.InteropServices;
- using ImGuiNET;
- using OpenTK.Windowing.Common;
- using OpenTK.Windowing.Desktop;
- using OpenTK.Windowing.GraphicsLibraryFramework;
- using ErrorCode = OpenTK.Windowing.GraphicsLibraryFramework.ErrorCode;
- using Vector2 = System.Numerics.Vector2;
- // ReSharper disable PossibleNullReferenceException
- namespace Pow3r
- {
- internal sealed unsafe partial class Program
- {
- private Renderer _renderer = Renderer.Veldrid;
- [UnmanagedCallersOnly]
- private static byte* GetClipboardTextCallback(void* userData)
- {
- return GLFW.GetClipboardStringRaw((Window*) userData);
- }
- [UnmanagedCallersOnly]
- private static void SetClipboardTextCallback(void* userData, byte* text)
- {
- GLFW.SetClipboardStringRaw((Window*) userData, text);
- }
- private static readonly GLFWCallbacks.ErrorCallback ErrorCallback = GlfwErrorCallback;
- private static void GlfwErrorCallback(ErrorCode error, string description)
- {
- Console.WriteLine($"{error}: {description}");
- }
- private bool[] _mouseJustPressed = new bool[5];
- private bool _fullscreen;
- private int _monitorIdx;
- private bool _vsync = true;
- private GameWindow _window;
- private readonly Stopwatch _stopwatch = new();
- private readonly Cursor*[] _cursors = new Cursor*[9];
- private readonly float[] _frameTimings = new float[180];
- private int _frameTimeIdx = 0;
- private int _tps = 60;
- private void Run(string[] args)
- {
- for (var i = 0; i < args.Length; i++)
- {
- if (args[i] == "--renderer")
- {
- _renderer = Enum.Parse<Renderer>(args[++i]);
- }
- else if (args[i] == "--veldrid")
- {
- _vdRenderer = Enum.Parse<VeldridRenderer>(args[++i]);
- }
- else if (args[i] == "--fullscreen")
- {
- _fullscreen = true;
- }
- else if (args[i] == "--monitor-idx")
- {
- _monitorIdx = int.Parse(args[++i]);
- }
- else if (args[i] == "--no-vsync")
- {
- _vsync = false;
- }
- else if (args[i] == "--help")
- {
- Console.WriteLine("--renderer <Veldrid|OpenGL>");
- Console.WriteLine("--veldrid <Vulkan|OpenGL|D3D11>");
- Console.WriteLine("--no-vsync");
- Console.WriteLine("--fullscreen");
- Console.WriteLine("--monitor-idx");
- Console.WriteLine("--help");
- return;
- }
- else
- {
- Console.WriteLine($"unknown arg \"{args[i]}\"");
- return;
- }
- }
- Console.WriteLine($"Renderer: {_renderer}");
- if (_renderer == Renderer.Veldrid)
- Console.WriteLine($"Veldrid API: {_vdRenderer}");
- Console.WriteLine($"Fullscreen: {_fullscreen}");
- Console.WriteLine($"VSync: {_vsync}");
- //NativeLibrary.Load("nvapi64.dll");
- GLFW.Init();
- GLFW.SetErrorCallback(ErrorCallback);
- // var sw = Stopwatch.StartNew();
- GLFW.WindowHint(WindowHintBool.SrgbCapable, true);
- var windowSettings = new NativeWindowSettings
- {
- Size = (1280, 720),
- WindowState = WindowState.Maximized,
- StartVisible = false,
- Title = "Pow3r"
- };
- var openGLBased = _renderer == Renderer.OpenGL ||
- (_renderer == Renderer.Veldrid && _vdRenderer == VeldridRenderer.OpenGL);
- if (openGLBased)
- {
- windowSettings.API = ContextAPI.OpenGL;
- if (_renderer == Renderer.Veldrid)
- {
- windowSettings.Profile = ContextProfile.Core;
- windowSettings.APIVersion = new Version(4, 6);
- windowSettings.Flags = ContextFlags.ForwardCompatible;
- }
- else
- {
- windowSettings.Profile = ContextProfile.Any;
- windowSettings.APIVersion = new Version(1, 5);
- }
- #if DEBUG
- windowSettings.Flags |= ContextFlags.Debug;
- #endif
- }
- else
- {
- windowSettings.API = ContextAPI.NoAPI;
- }
- _window = new GameWindow(GameWindowSettings.Default, windowSettings);
- // Console.WriteLine(sw.ElapsedMilliseconds);
- if (_fullscreen)
- {
- var monitors = GLFW.GetMonitors();
- var monitor = monitors[_monitorIdx];
- var monitorMode = GLFW.GetVideoMode(monitor);
- GLFW.SetWindowMonitor(
- _window.WindowPtr,
- monitor,
- 0, 0,
- monitorMode->Width,
- monitorMode->Height,
- monitorMode->RefreshRate);
- }
- if (openGLBased)
- {
- _window.VSync = _vsync ? VSyncMode.On : VSyncMode.Off;
- }
- var context = ImGui.CreateContext();
- ImGui.SetCurrentContext(context);
- ImGui.StyleColorsDark();
- var io = ImGui.GetIO();
- io.Fonts.AddFontDefault();
- delegate* unmanaged<void*, byte*> getClipboardCallback = &GetClipboardTextCallback;
- io.GetClipboardTextFn = (IntPtr) getClipboardCallback;
- delegate* unmanaged<void*, byte*, void> setClipboardCallback = &SetClipboardTextCallback;
- io.GetClipboardTextFn = (IntPtr) setClipboardCallback;
- io.ClipboardUserData = (IntPtr) _window.WindowPtr;
- io.BackendFlags |= ImGuiBackendFlags.RendererHasVtxOffset;
- io.BackendFlags |= ImGuiBackendFlags.HasSetMousePos;
- io.BackendFlags |= ImGuiBackendFlags.HasMouseCursors;
- io.KeyMap[(int) ImGuiKey.Tab] = (int) Keys.Tab;
- io.KeyMap[(int) ImGuiKey.LeftArrow] = (int) Keys.Left;
- io.KeyMap[(int) ImGuiKey.RightArrow] = (int) Keys.Right;
- io.KeyMap[(int) ImGuiKey.UpArrow] = (int) Keys.Up;
- io.KeyMap[(int) ImGuiKey.DownArrow] = (int) Keys.Down;
- io.KeyMap[(int) ImGuiKey.PageUp] = (int) Keys.PageUp;
- io.KeyMap[(int) ImGuiKey.PageDown] = (int) Keys.PageDown;
- io.KeyMap[(int) ImGuiKey.Home] = (int) Keys.Home;
- io.KeyMap[(int) ImGuiKey.End] = (int) Keys.End;
- io.KeyMap[(int) ImGuiKey.Delete] = (int) Keys.Delete;
- io.KeyMap[(int) ImGuiKey.Backspace] = (int) Keys.Backspace;
- io.KeyMap[(int) ImGuiKey.Enter] = (int) Keys.Enter;
- io.KeyMap[(int) ImGuiKey.Escape] = (int) Keys.Escape;
- io.KeyMap[(int) ImGuiKey.A] = (int) Keys.A;
- io.KeyMap[(int) ImGuiKey.C] = (int) Keys.C;
- io.KeyMap[(int) ImGuiKey.V] = (int) Keys.V;
- io.KeyMap[(int) ImGuiKey.X] = (int) Keys.X;
- io.KeyMap[(int) ImGuiKey.Y] = (int) Keys.Y;
- io.KeyMap[(int) ImGuiKey.Z] = (int) Keys.Z;
- _cursors[(int) ImGuiMouseCursor.Arrow] = GLFW.CreateStandardCursor(CursorShape.Arrow);
- _cursors[(int) ImGuiMouseCursor.TextInput] = GLFW.CreateStandardCursor(CursorShape.IBeam);
- _cursors[(int) ImGuiMouseCursor.ResizeNS] = GLFW.CreateStandardCursor(CursorShape.VResize);
- _cursors[(int) ImGuiMouseCursor.ResizeEW] = GLFW.CreateStandardCursor(CursorShape.HResize);
- _cursors[(int) ImGuiMouseCursor.Hand] = GLFW.CreateStandardCursor(CursorShape.Hand);
- _cursors[(int) ImGuiMouseCursor.ResizeAll] = GLFW.CreateStandardCursor(CursorShape.Arrow);
- _cursors[(int) ImGuiMouseCursor.ResizeNESW] = GLFW.CreateStandardCursor(CursorShape.Arrow);
- _cursors[(int) ImGuiMouseCursor.ResizeNWSE] = GLFW.CreateStandardCursor(CursorShape.Arrow);
- _cursors[(int) ImGuiMouseCursor.NotAllowed] = GLFW.CreateStandardCursor(CursorShape.Arrow);
- InitRenderer();
- _window.MouseDown += OnMouseDown;
- _window.TextInput += WindowOnTextInput;
- _window.MouseWheel += WindowOnMouseWheel;
- _window.KeyDown += args => KeyCallback(args, true);
- _window.KeyUp += args => KeyCallback(args, false);
- _stopwatch.Start();
- LoadFromDisk();
- _window.IsVisible = true;
- var lastTick = TimeSpan.Zero;
- var lastFrame = TimeSpan.Zero;
- var curTime = TimeSpan.Zero;
- while (!GLFW.WindowShouldClose(_window.WindowPtr))
- {
- NativeWindow.ProcessWindowEvents(false);
- var tickSpan = TimeSpan.FromSeconds(1f / _tps);
- while (curTime - lastTick > tickSpan)
- {
- lastTick += tickSpan;
- Tick((float) tickSpan.TotalSeconds);
- }
- _frameTimeIdx = (_frameTimeIdx + 1) % _frameTimings.Length;
- var dt = curTime - lastFrame;
- lastFrame = curTime;
- _frameTimings[_frameTimeIdx] = (float) dt.TotalMilliseconds;
- FrameUpdate((float) dt.TotalSeconds);
- Render();
- curTime = _stopwatch.Elapsed;
- }
- SaveToDisk();
- }
- private static void KeyCallback(KeyboardKeyEventArgs obj, bool down)
- {
- var io = ImGui.GetIO();
- if (obj.Key ==Keys.Unknown)
- return;
- var keyInt = (int) obj.Key;
- io.KeysDown[keyInt] = down;
- io.KeyCtrl = io.KeysDown[(int) Keys.LeftControl] || io.KeysDown[(int) Keys.RightControl];
- io.KeyShift = io.KeysDown[(int) Keys.LeftShift] || io.KeysDown[(int) Keys.RightShift];
- io.KeyAlt = io.KeysDown[(int) Keys.LeftAlt] || io.KeysDown[(int) Keys.RightAlt];
- }
- private static void WindowOnMouseWheel(MouseWheelEventArgs obj)
- {
- var io = ImGui.GetIO();
- io.MouseWheelH += obj.OffsetX;
- io.MouseWheel += obj.OffsetY;
- }
- private static void WindowOnTextInput(TextInputEventArgs obj)
- {
- var io = ImGui.GetIO();
- io.AddInputCharacter((uint) obj.Unicode);
- }
- private void OnMouseDown(MouseButtonEventArgs obj)
- {
- var button = (int) obj.Button;
- if (obj.IsPressed && button < _mouseJustPressed.Length)
- _mouseJustPressed[button] = true;
- }
- private void FrameUpdate(float dt)
- {
- //var sw = Stopwatch.StartNew();
- var io = ImGui.GetIO();
- GLFW.GetFramebufferSize(_window.WindowPtr, out var fbW, out var fbH);
- GLFW.GetWindowSize(_window.WindowPtr, out var wW, out var wH);
- io.DisplaySize = new Vector2(wW, wH);
- io.DisplayFramebufferScale = new Vector2(fbW / (float) wW, fbH / (float) wH);
- io.DeltaTime = dt;
- UpdateMouseState(io);
- UpdateCursorState(io);
- //Console.WriteLine($"INPUT: {sw.Elapsed.TotalMilliseconds}");
- ImGui.NewFrame();
- DoUI(dt);
- }
- private void UpdateCursorState(ImGuiIOPtr io)
- {
- var cursor = ImGui.GetMouseCursor();
- if (cursor == ImGuiMouseCursor.None)
- {
- GLFW.SetInputMode(_window.WindowPtr, CursorStateAttribute.Cursor, CursorModeValue.CursorHidden);
- }
- else
- {
- GLFW.SetCursor(_window.WindowPtr, _cursors[(int) cursor]);
- GLFW.SetInputMode(_window.WindowPtr, CursorStateAttribute.Cursor, CursorModeValue.CursorNormal);
- }
- }
- private void UpdateMouseState(ImGuiIOPtr io)
- {
- for (var i = 0; i < io.MouseDown.Count; i++)
- {
- io.MouseDown[i] = _mouseJustPressed[i] ||
- GLFW.GetMouseButton(_window.WindowPtr, (MouseButton) i) == InputAction.Press;
- _mouseJustPressed[i] = false;
- }
- var oldMousePos = io.MousePos;
- io.MousePos = new Vector2(float.PositiveInfinity, float.PositiveInfinity);
- var focused = _window.IsFocused;
- if (focused)
- {
- if (io.WantSetMousePos)
- {
- GLFW.SetCursorPos(_window.WindowPtr, oldMousePos.X, oldMousePos.Y);
- }
- else
- {
- GLFW.GetCursorPos(_window.WindowPtr, out var x, out var y);
- io.MousePos = new Vector2((float) x, (float) y);
- }
- }
- }
- private void InitRenderer()
- {
- switch (_renderer)
- {
- case Renderer.OpenGL:
- InitOpenGL();
- break;
- case Renderer.Veldrid:
- InitVeldrid();
- break;
- }
- }
- private void Render()
- {
- ImGui.Render();
- switch (_renderer)
- {
- case Renderer.OpenGL:
- RenderOpenGL();
- break;
- case Renderer.Veldrid:
- RenderVeldrid();
- break;
- }
- }
- private static void Main(string[] args)
- {
- new Program().Run(args);
- }
- public enum Renderer
- {
- OpenGL,
- Veldrid
- }
- }
- }
|