1 /** 2 Copyright: Copyright (c) 2015-2016 Andrey Penechko. 3 License: $(WEB boost.org/LICENSE_1_0.txt, Boost License 1.0). 4 Authors: Andrey Penechko. 5 */ 6 7 module voxelman.gui.plugin; 8 9 import std.experimental.logger; 10 import std.string : format; 11 import dlib.math.vector; 12 13 import anchovy.fpshelper; 14 import anchovy.glfwwindow; 15 import anchovy.input; 16 import anchovy.irenderer; 17 import anchovy.iwindow; 18 import anchovy.oglrenderer; 19 20 import tharsis.prof : Zone; 21 22 import pluginlib; 23 import voxelman.imgui_glfw; 24 25 import voxelman.core.config; 26 import voxelman.core.events; 27 import voxelman.storage.chunk; 28 import voxelman.storage.coordinates; 29 import voxelman.storage.utils; 30 31 import voxelman.eventdispatcher.plugin; 32 import voxelman.config.configmanager; 33 34 35 struct ClosePressedEvent { 36 import tharsis.prof : Profiler; 37 Profiler profiler; 38 bool continuePropagation = true; 39 } 40 41 shared static this() 42 { 43 pluginRegistry.regClientPlugin(new GuiPlugin); 44 } 45 46 final class GuiPlugin : IPlugin 47 { 48 private: 49 EventDispatcherPlugin evDispatcher; 50 ConfigOption resolution; 51 ConfigOption maxFpsOpt; 52 53 public: 54 IWindow window; 55 IRenderer renderer; 56 FpsHelper fpsHelper; 57 ImguiState igState; 58 59 mixin IdAndSemverFrom!(voxelman.gui.plugininfo); 60 61 override void registerResources(IResourceManagerRegistry resmanRegistry) 62 { 63 auto config = resmanRegistry.getResourceManager!ConfigManager; 64 resolution = config.registerOption!(uint[])("resolution", [1280, 720]); 65 maxFpsOpt = config.registerOption!uint("max_fps", true); 66 } 67 68 override void preInit() 69 { 70 initLibs(); 71 72 window = new GlfwWindow(); 73 window.init(uvec2(resolution.get!(uint[])), "Voxelman client"); 74 renderer = new OglRenderer(window); 75 igState.init((cast(GlfwWindow)window).handle); 76 77 fpsHelper.maxFps = maxFpsOpt.get!uint; 78 if (fpsHelper.maxFps == 0) fpsHelper.limitFps = false; 79 80 // Bind events 81 window.windowResized.connect(&windowResized); 82 window.closePressed.connect(&closePressed); 83 84 window.keyPressed.connect(&igState.onKeyPressed); 85 window.keyReleased.connect(&igState.onKeyReleased); 86 window.charEntered.connect(&igState.charCallback); 87 window.mousePressed.connect(&igState.onMousePressed); 88 window.mouseReleased.connect(&igState.onMouseReleased); 89 window.wheelScrolled.connect((dvec2 s) => igState.scrollCallback(s.y)); 90 } 91 92 void initLibs() 93 { 94 import derelict.glfw3.glfw3; 95 import derelict.opengl3.gl3; 96 import derelict.imgui.imgui; 97 import voxelman.utils.libloader; 98 99 DerelictGL3.load(); 100 DerelictGLFW3.load([getLibName(BUILD_TO_ROOT_PATH, "glfw3")]); 101 DerelictImgui.load(getLibName(BUILD_TO_ROOT_PATH, "cimgui")); 102 } 103 104 override void init(IPluginManager pluginman) 105 { 106 evDispatcher = pluginman.getPlugin!EventDispatcherPlugin; 107 evDispatcher.subscribeToEvent(&onPreUpdateEvent); 108 evDispatcher.subscribeToEvent(&onRender3Event); 109 evDispatcher.subscribeToEvent(&onGameStopEvent); 110 } 111 112 void onPreUpdateEvent(ref PreUpdateEvent event) 113 { 114 Zone drawSceneZone = Zone(event.profiler, "updateGui"); 115 window.processEvents(); 116 fpsHelper.update(event.deltaTime); 117 igState.newFrame(); 118 } 119 120 void onRender3Event(ref Render3Event event) 121 { 122 Zone drawSceneZone = Zone(event.profiler, "drawGui"); 123 igState.render(); 124 } 125 126 void onGameStopEvent(ref GameStopEvent stopEvent) 127 { 128 window.releaseWindow; 129 igState.shutdown(); 130 } 131 132 private void windowResized(uvec2 newSize) 133 { 134 evDispatcher.postEvent(WindowResizedEvent(newSize)); 135 } 136 137 private void closePressed() 138 { 139 evDispatcher.postEvent(ClosePressedEvent()); 140 } 141 }