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 }