static void LoadGameDll(string BasePath) { BasePath = Path.Combine(BasePath, "Game.dll"); Assembly GameAssembly = Reflect.LoadAssembly(BasePath); Type[] GameImplementations = Reflect.GetAllImplementationsOf(GameAssembly, typeof(LibTechGame)).ToArray(); if (GameImplementations.Length == 0) { GConsole.WriteLine("No game implementations found in " + BasePath); Environment.Exit(0); } else if (GameImplementations.Length > 1) { GConsole.WriteLine("Too many game implementations in " + BasePath); Environment.Exit(0); } AppDomain.CurrentDomain.AssemblyResolve += (S, E) => TryLoadAssembly(E.Name, BasePath); Importers.RegisterAll(GameAssembly); Game = (LibTechGame)Activator.CreateInstance(GameImplementations[0]); Game.Load(); }
static void RunGame() { InitConsole(); FileWatcher.Init("content"); Importers.RegisterAll(Reflect.GetExeAssembly()); Engine.GUI = new libGUI(); Engine.Window = new RenderWindow(Engine.WindowWidth, Engine.WindowHeight, "libTech", Engine.WindowResizable); Engine.Window.OnMouseMove += Engine.GUI.OnMouseMove; Engine.Window.OnKey += OnKey; Engine.Window.OnChar += Engine.GUI.OnChar; Engine.GUI.Init(Engine.Window, new ShaderProgram(new ShaderStage(ShaderType.VertexShader, "content/shaders/gui.vert"), new ShaderStage(ShaderType.FragmentShader, "content/shaders/gui.frag"))); GConsole.Init(); GConsole.WriteLine("Running {0}", RenderAPI.Renderer, RenderAPI.Version); GConsole.Color = FishGfx.Color.Orange; foreach (var DllName in FailedToLoadDLLs) { GConsole.WriteLine("Failed to load '{0}'", DllName); } GConsole.Color = FishGfx.Color.White; // Graphics init Gfx.ShadersDirectory = "content/shaders"; //Gfx.Line3D = DefaultShaders.Line3D; //Gfx.Point3D = DefaultShaders.Point3D; //Gfx.Default3D = DefaultShaders.DefaultColor3D; // Camera init Engine.Camera2D = new Camera(); Engine.Camera2D.SetOrthogonal(0, 0, Engine.Window.WindowWidth, Engine.Window.WindowHeight); Engine.Camera3D = new Camera(); Engine.Camera3D.SetPerspective(Engine.Window.WindowWidth, Engine.Window.WindowHeight); LoadGameDll(Engine.GamePath); float Dt = 0; while (!Engine.Window.ShouldClose) { Update(Dt); Draw(Dt); Thread.Sleep(0); } }
static void LoadGameDll(string BasePath) { string GameDllPath = Path.Combine(BasePath, "Game.dll"); Assembly GameAssembly = Assembly.GetExecutingAssembly(); bool LoadImporters = false; if (File.Exists(GameDllPath)) { GameAssembly = Reflect.LoadAssembly(GameDllPath); LoadImporters = true; } Type[] GameImplementations = Reflect.GetAllImplementationsOf(GameAssembly, typeof(LibTechGame)).ToArray(); if (GameImplementations.Length == 0) { GConsole.WriteLine("No game implementations found in " + GameDllPath); Environment.Exit(0); } else if (GameImplementations.Length > 1) { GConsole.WriteLine("Too many game implementations in " + GameDllPath); Environment.Exit(0); } AppDomain.CurrentDomain.AssemblyResolve += (S, E) => TryLoadAssembly(E.Name, GameDllPath); if (LoadImporters) { Importers.RegisterAll(GameAssembly); } Entity.LoadAllTypes(); Engine.Game = (LibTechGame)Activator.CreateInstance(GameImplementations[0]); Engine.Game.Load(); }
static void RunGame() { TimeStopwatch = Stopwatch.StartNew(); InitConsole(); Engine.VFS = new VirtualFileSystem(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)); Engine.VFS.Mount("/content/", "./content"); Engine.VFS.Mount("/materials/", "C:/Program Files (x86)/Steam/steamapps/common/GarrysMod/garrysmod/addons/quake_3_gmod_160207505/materials"); string[] SourceGameDirs = Engine.SourceGameDirs.Value.Split(new[] { ',', ';' }, StringSplitOptions.RemoveEmptyEntries).Where(Pth => Directory.Exists(Pth)).ToArray(); if (SourceGameDirs.Length > 0) { foreach (var GameDir in SourceGameDirs) { Engine.VFS.GetSourceProvider().AddRoot(GameDir); } } if (Directory.Exists(Path.Combine(Engine.GamePath, "content"))) { Engine.VFS.Mount("/content/", Path.Combine(Engine.GamePath, "content")); } List <string> ZipResources = new List <string>(); ZipResources.AddRange(Engine.VFS.GetFiles("/content/").Where(P => Path.GetExtension(P) == ".pk3" || Path.GetExtension(P) == ".zip")); foreach (var ZipResource in ZipResources) { Engine.VFS.MountArchive("/content/", ZipResource); } FileWatcher.Init("content"); Importers.RegisterAll(Reflect.GetExeAssembly()); Engine.GUI = new NuklearGUI(); Engine.Window = new RenderWindow(Engine.WindowWidth, Engine.WindowHeight, "libTech", Engine.WindowResizable); Engine.Window.OnMouseMove += Engine.GUI.OnMouseMove; Engine.Window.OnKey += OnKey; Engine.Window.OnChar += Engine.GUI.OnChar; RenderDoc.Init(); GConsole.Init(); GConsole.WriteLine("Running {0}", RenderAPI.Renderer, RenderAPI.Version); string ExtensionsFile = "extensions.txt"; if (File.Exists(ExtensionsFile)) { File.Delete(ExtensionsFile); } File.WriteAllLines(ExtensionsFile, RenderAPI.Extensions); EngineRenderer.Init(); Engine.GUI.Init(Engine.Window, new ShaderProgram(new ShaderStage(ShaderType.VertexShader, "content/shaders/gui.vert"), new ShaderStage(ShaderType.FragmentShader, "content/shaders/gui.frag"))); Engine.UI = new libGUI(Engine.Window); DbgDraw.Init(); Lua.Init(); GConsole.Color = Color.Orange; foreach (var DllName in FailedToLoadDLLs) { GConsole.WriteLine("Failed to load '{0}'", DllName); } GConsole.Color = Color.White; // Graphics init Gfx.ShadersDirectory = "content/shaders"; //Gfx.Line3D = DefaultShaders.Line3D; //Gfx.Point3D = DefaultShaders.Point3D; //Gfx.Default3D = DefaultShaders.DefaultColor3D; // Camera init Engine.Camera2D = new Camera(); Engine.Camera2D.SetOrthogonal(0, 0, Engine.Window.WindowWidth, Engine.Window.WindowHeight); Engine.Camera3D = new Camera(); Engine.Camera3D.SetPerspective(Engine.Window.WindowWidth, Engine.Window.WindowHeight, FarPlane: 16000); LoadGameDll(Engine.GamePath); Stopwatch SWatch = Stopwatch.StartNew(); int MaxFPS = Engine.MaxFPS; if (MaxFPS <= 0) { MaxFPS = 900; } float FrameCap = 1.0f / MaxFPS; float Dt = 1.0f / 60.0f; while (!Engine.Window.ShouldClose) { Engine.FrameTime.Push(Dt); Update(Dt); EngineRenderer.Draw(Dt); // TODO: Move frame cap somewhere else while ((SWatch.ElapsedMilliseconds / 1000.0f) < FrameCap) { Thread.Sleep(0); } Dt = SWatch.ElapsedMilliseconds / 1000.0f; SWatch.Restart(); } }
static void LoadContent() { string GameDllPath = Path.Combine(CVar.GetString("game"), "Game.dll"); if (!File.Exists(GameDllPath)) { FatalError("File not found: {0}", GameDllPath); } Assembly GameAssembly = Reflect.LoadAssembly(GameDllPath); Importers.RegisterAll(GameAssembly); Type[] GameImplementations = Reflect.GetAllImplementationsOf(GameAssembly, typeof(LibTechGame)).ToArray(); if (GameImplementations.Length == 0) { FatalError("Could not find game implementation in {0}", GameDllPath); } if (GameImplementations.Length > 1) { FatalError("Found too many game implementations in {0}", GameDllPath); } Game = (LibTechGame)Activator.CreateInstance(GameImplementations[0]); Game.Load(); RenderDevice = new RenderDevice(ShaderProgram.GUI, Width, Height); NuklearAPI.Init(RenderDevice); NuklearAPI.SetClipboardCallback((Txt) => { if (string.IsNullOrEmpty(Txt)) { return; } Glfw.SetClipboardString(Window, Txt); }, () => { string Str = Glfw.GetClipboardString(Window); if (Str == null) { Str = ""; } return(Str); }); Glfw.SetCursorPosCallback(Window, (Wnd, X, Y) => { RenderDevice.OnMouseMove((int)X, (int)Y); }); Glfw.SetMouseButtonCallback(Window, (Wnd, Button, State, Mods) => { NuklearEvent.MouseButton NkButton; bool IsDown = State == Glfw.InputState.Press ? true : false; if (!(State == Glfw.InputState.Press || State == Glfw.InputState.Release)) { return; } if (Button == Glfw.MouseButton.ButtonLeft) { NkButton = NuklearEvent.MouseButton.Left; } else if (Button == Glfw.MouseButton.ButtonMiddle) { NkButton = NuklearEvent.MouseButton.Middle; } else if (Button == Glfw.MouseButton.ButtonRight) { NkButton = NuklearEvent.MouseButton.Right; } else { return; } RenderDevice.OnMouseButton(NkButton, (int)MousePos.X, (int)MousePos.Y, IsDown); }); Glfw.SetScrollCallback(Window, (Wnd, X, Y) => { RenderDevice.OnScroll((float)X, (float)Y); }); Glfw.SetCharCallback(Window, (Wnd, Chr) => { RenderDevice.OnText(((char)Chr).ToString()); }); Glfw.SetKeyCallback(Window, (Wnd, KCode, SCode, State, Mods) => { if (KCode == Glfw.KeyCode.F1 && State == Glfw.InputState.Press) { GConsole.Open = true; } NkKeys K = ConvertToNkKey(KCode, Mods); if (K != NkKeys.None) { RenderDevice.OnKey(K, State == Glfw.InputState.Press); if (State == Glfw.InputState.Repeat) { RenderDevice.OnKey(K, true); } } }); Glfw.SetDropCallback(Window, (Wnd, Cnt, Paths) => { DragDropPaths = Paths; }); }
static void Main(string[] args) { CVar.InitMode = true; CVar.Register("game", "basegame", CVarType.Replicated | CVarType.Init, (This, Old, New) => This.Value = Path.GetFullPath((string)New)); CVar.Register("width", 1366, CVarType.Archive); CVar.Register("height", 768, CVarType.Archive); CVar.Register("borderless", false, CVarType.Archive); CVar.Register("resizable", false, CVarType.Archive); CVar.Register("gl_doublebuffer", true, CVarType.Archive); CVar.Register("gl_samples", 8, CVarType.Archive); CVar.Register("gl_forwardcompat", true, CVarType.Archive | CVarType.Init | CVarType.Unsafe); CVar.Register("gl_major", 4, CVarType.Archive | CVarType.Init | CVarType.Unsafe); CVar.Register("gl_minor", 5, CVarType.Archive | CVarType.Init | CVarType.Unsafe); // Parse all arguments and set CVars foreach (var Arg in ArgumentParser.All) { switch (Arg.Key) { case "console": GConsole.Open = true; break; default: { CVar CVar = CVar.Find(Arg.Key); if (CVar != null) { CVar.Value = Arg.Value.LastOrDefault(); } else { CVar.Register(Arg.Key, Arg.Value.LastOrDefault()); } break; } } } CVar.InitMode = false; foreach (var CVar in CVar.GetAll()) { GConsole.WriteLine(CVar); } FileWatcher.Init("content"); Importers.RegisterAll(Reflect.GetExeAssembly()); CreateContext(); InitPhysics(); LoadContent(); Stopwatch SWatch = Stopwatch.StartNew(); float Target = 1.0f / 120; float Dt = Target; TextureTarget Tgt = TextureTarget.Texture2dMultisample; if (CVar.GetInt("gl_samples") == 0) { Tgt = TextureTarget.Texture2d; } Texture ColorTex = new Texture(Width, Height, Tgt, 1, InternalFormat.Rgb16f); Texture DepthTex = new Texture(Width, Height, Tgt, 1, InternalFormat.Depth24Stencil8); Framebuffer FB = new Framebuffer(); FB.AttachColorTexture(ColorTex); FB.AttachDepthTexture(DepthTex); Texture SkyboxCubeMap = new Texture(1024, 1024, TextureTarget.TextureCubeMap, 1, InternalFormat.Srgb8Alpha8); SkyboxCubeMap.SetFilter(Gl.LINEAR, Gl.LINEAR); SkyboxCubeMap.SubImage3D(Image.FromFile("content/textures/skybox/interstellar/front.png"), Z: Texture.FRONT); SkyboxCubeMap.SubImage3D(Image.FromFile("content/textures/skybox/interstellar/back.png"), Z: Texture.BACK); SkyboxCubeMap.SubImage3D(Image.FromFile("content/textures/skybox/interstellar/left.png"), Z: Texture.LEFT); SkyboxCubeMap.SubImage3D(Image.FromFile("content/textures/skybox/interstellar/right.png"), Z: Texture.RIGHT); SkyboxCubeMap.SubImage3D(Image.FromFile("content/textures/skybox/interstellar/top.png"), Z: Texture.TOP); SkyboxCubeMap.SubImage3D(Image.FromFile("content/textures/skybox/interstellar/bottom.png"), Z: Texture.BOTTOM); //FB.Clear(new Vector4(1, 0, 0, 1)); Model SkyboxCube = Importers.Load <Model>("content/models/cube.obj"); SkyboxCube.Scale = new Vector3(2); SkyboxCube.Meshes[0].Material.Shader = ShaderProgram.Skybox; SkyboxCube.Meshes[0].Material.Diffuse = SkyboxCubeMap; //bool DoDebug = true; while (!Glfw.WindowShouldClose(Window)) { /*if (Khronos.KhronosApi.LogEnabled) { * Khronos.KhronosApi.LogCommand("END FRAME", null, null); * Khronos.KhronosApi.LogEnabled = false; * } * * if (DoDebug) { * DoDebug = false; * Khronos.KhronosApi.LogEnabled = true; * Khronos.KhronosApi.LogCommand("BEGIN FRAME", null, null); * }*/ Update(Dt); Gl.Clear(ClearBufferMask.DepthBufferBit | ClearBufferMask.ColorBufferBit | ClearBufferMask.StencilBufferBit); FB.Bind(); { Gl.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit); SetupState(); Gl.Disable(EnableCap.CullFace); Gl.DepthMask(false); SkyboxCube.Position = Camera.ActiveCamera?.Position ?? Vector3.Zero; SkyboxCube.Draw(); Gl.DepthMask(true); DrawScene(Dt); } FB.Unbind(); // Swap to GUI camera Gl.Disable(EnableCap.DepthTest); Gl.Disable(EnableCap.CullFace); Camera.ActiveCamera = Camera.GUICamera; Immediate.UseShaders(() => { if (ColorTex.Multisampled) { Immediate.TriangleShader = ShaderProgram.PostMultisample; Immediate.TriangleShader.Uniform2f("TexSize", new Vector2(ColorTex.Width, ColorTex.Height)); } else { Immediate.TriangleShader = ShaderProgram.Post; } Immediate.TriangleShader.Uniform1f("Exposure", 1.0f); Gl.Enable(EnableCap.FramebufferSrgb); Immediate.Texture2D(Vector2.Zero, ColorTex, UVInvertY: true); Gl.Disable(EnableCap.FramebufferSrgb); }); DrawGUI(Dt); Glfw.SwapBuffers(Window); // Cap at Target framerate while ((float)SWatch.ElapsedMilliseconds / 1000 < Target) { ; } Dt = (float)SWatch.ElapsedMilliseconds / 1000; FPS = (int)(1.0f / Dt); SWatch.Restart(); } Environment.Exit(0); }