1 /***********************************************************************
2 created:    21/7/2015
3 author:     Yaron Cohen-Tal
4 *************************************************************************/
5 /***************************************************************************
6 *   Copyright (C) 2004 - 2015 Paul D Turner & The CEGUI Development Team
7 *
8 *   Permission is hereby granted, free of charge, to any person obtaining
9 *   a copy of this software and associated documentation files (the
10 *   "Software"), to deal in the Software without restriction, including
11 *   without limitation the rights to use, copy, modify, merge, publish,
12 *   distribute, sublicense, and/or sell copies of the Software, and to
13 *   permit persons to whom the Software is furnished to do so, subject to
14 *   the following conditions:
15 *
16 *   The above copyright notice and this permission notice shall be
17 *   included in all copies or substantial portions of the Software.
18 *
19 *   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 *   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 *   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
22 *   IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23 *   OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24 *   ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25 *   OTHER DEALINGS IN THE SOFTWARE.
26 ***************************************************************************/
27 
28 #include "CEGuiGLFWSharedBase.h"
29 #include "SamplesFrameworkBase.h"
30 #include "CEGUI/CEGUI.h"
31 
32 //----------------------------------------------------------------------------//
33 GLFWwindow* CEGuiGLFWSharedBase::d_window = 0;
34 
35 //----------------------------------------------------------------------------//
run()36 void CEGuiGLFWSharedBase::run()
37 {
38     // Input callbacks of glfw for CEGUI
39     glfwSetKeyCallback(d_window, glfwKeyCallback);
40     glfwSetCharCallback(d_window, glfwCharCallback);
41     glfwSetMouseButtonCallback(d_window, glfwMouseButtonCallback);
42     glfwSetScrollCallback(d_window, glfwScrollCallback);
43     glfwSetCursorPosCallback(d_window, glfwCursorPosCallback);
44 
45     //Window callbacks
46     glfwSetWindowCloseCallback(d_window, glfwWindowCloseCallback);
47     glfwSetWindowSizeCallback(d_window, glfwWindowResizeCallback);
48     d_windowSized = false; //The resize callback is being called immediately after setting it in this version of glfw
49     glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
50 
51     // set starting time
52     d_frameTime = glfwGetTime();
53 
54     while (!d_sampleApp->isQuitting())
55     {
56         if (d_windowSized)
57         {
58             d_windowSized = false;
59             CEGUI::System::getSingleton().
60                 notifyDisplaySizeChanged(
61                 CEGUI::Sizef(static_cast<float>(d_newWindowWidth),
62                 static_cast<float>(d_newWindowHeight)));
63         }
64 
65         drawFrame();
66         glfwPollEvents();
67     }
68 
69 }
70 
71 //----------------------------------------------------------------------------//
endRendering()72 void CEGuiGLFWSharedBase::endRendering()
73 {
74     glfwSwapBuffers(d_window);
75 }
76 
77 //----------------------------------------------------------------------------//
createGLFWWindow()78 void CEGuiGLFWSharedBase::createGLFWWindow()
79 {
80     glfwWindowHint(GLFW_RED_BITS,   GLFW_DONT_CARE);
81     glfwWindowHint(GLFW_GREEN_BITS, GLFW_DONT_CARE);
82     glfwWindowHint(GLFW_BLUE_BITS,  GLFW_DONT_CARE);
83     glfwWindowHint(GLFW_ALPHA_BITS, 0);
84     if (!(d_window = glfwCreateWindow(s_defaultWindowWidth,
85             s_defaultWindowHeight, d_windowTitle, 0, 0)))
86     {
87         CEGUI_THROW(RendererException("Failed to open GLFW window."));
88         glfwTerminate();
89     }
90     glfwMakeContextCurrent (d_window);
91 }
92 
93 //----------------------------------------------------------------------------//
setGLFWAppConfiguration()94 void CEGuiGLFWSharedBase::setGLFWAppConfiguration()
95 {
96     //Deactivate VSYNC
97     glfwSwapInterval(0);
98 
99     // Disable the mouse position in Non_Debug mode
100 #ifndef DEBUG
101     glfwSetInputMode(d_window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
102 #endif
103     // Clear Errors by GLFW, even if Setup is correct.
104     glGetError();
105 }
106 
107 //----------------------------------------------------------------------------//
glfwWindowCloseCallback(GLFWwindow *)108 void CEGuiGLFWSharedBase::glfwWindowCloseCallback(GLFWwindow* /*window*/)
109 {
110     d_sampleApp->setQuitting(true);
111 }
112 
113 //----------------------------------------------------------------------------//
glfwWindowResizeCallback(GLFWwindow *,int width,int height)114 void CEGuiGLFWSharedBase::glfwWindowResizeCallback(GLFWwindow* /*window*/, int width, int height)
115 {
116     // We cache this in order to minimise calls to notifyDisplaySizeChanged,
117     // which happens in the main loop whenever d_windowSized is set to true.
118     d_windowSized = true;
119     d_newWindowWidth = width;
120     d_newWindowHeight = height;
121 }
122 
123 //----------------------------------------------------------------------------//
GlfwToCeguiKey(int glfwKey)124 CEGUI::Key::Scan CEGuiGLFWSharedBase::GlfwToCeguiKey(int glfwKey)
125 {
126     switch(glfwKey)
127     {
128     case GLFW_KEY_ESCAPE       : return CEGUI::Key::Escape;
129     case GLFW_KEY_F1           : return CEGUI::Key::F1;
130     case GLFW_KEY_F2           : return CEGUI::Key::F2;
131     case GLFW_KEY_F3           : return CEGUI::Key::F3;
132     case GLFW_KEY_F4           : return CEGUI::Key::F4;
133     case GLFW_KEY_F5           : return CEGUI::Key::F5;
134     case GLFW_KEY_F6           : return CEGUI::Key::F6;
135     case GLFW_KEY_F7           : return CEGUI::Key::F7;
136     case GLFW_KEY_F8           : return CEGUI::Key::F8;
137     case GLFW_KEY_F9           : return CEGUI::Key::F9;
138     case GLFW_KEY_F10          : return CEGUI::Key::F10;
139     case GLFW_KEY_F11          : return CEGUI::Key::F11;
140     case GLFW_KEY_F12          : return CEGUI::Key::F12;
141     case GLFW_KEY_F13          : return CEGUI::Key::F13;
142     case GLFW_KEY_F14          : return CEGUI::Key::F14;
143     case GLFW_KEY_F15          : return CEGUI::Key::F15;
144     case GLFW_KEY_UP           : return CEGUI::Key::ArrowUp;
145     case GLFW_KEY_DOWN         : return CEGUI::Key::ArrowDown;
146     case GLFW_KEY_LEFT         : return CEGUI::Key::ArrowLeft;
147     case GLFW_KEY_RIGHT        : return CEGUI::Key::ArrowRight;
148     case GLFW_KEY_LEFT_SHIFT   : return CEGUI::Key::LeftShift;
149     case GLFW_KEY_RIGHT_SHIFT  : return CEGUI::Key::RightShift;
150     case GLFW_KEY_LEFT_CONTROL : return CEGUI::Key::LeftControl;
151     case GLFW_KEY_RIGHT_CONTROL: return CEGUI::Key::RightControl;
152     case GLFW_KEY_LEFT_ALT     : return CEGUI::Key::LeftAlt;
153     case GLFW_KEY_RIGHT_ALT    : return CEGUI::Key::RightAlt;
154     case GLFW_KEY_TAB          : return CEGUI::Key::Tab;
155     case GLFW_KEY_ENTER        : return CEGUI::Key::Return;
156     case GLFW_KEY_BACKSPACE    : return CEGUI::Key::Backspace;
157     case GLFW_KEY_INSERT       : return CEGUI::Key::Insert;
158     case GLFW_KEY_DELETE       : return CEGUI::Key::Delete;
159     case GLFW_KEY_PAGE_UP      : return CEGUI::Key::PageUp;
160     case GLFW_KEY_PAGE_DOWN    : return CEGUI::Key::PageDown;
161     case GLFW_KEY_HOME         : return CEGUI::Key::Home;
162     case GLFW_KEY_END          : return CEGUI::Key::End;
163     case GLFW_KEY_KP_ENTER     : return CEGUI::Key::NumpadEnter;
164     default                    : return CEGUI::Key::Unknown;
165     }
166 }
167 
168 //----------------------------------------------------------------------------//
glfwKeyCallback(GLFWwindow *,int key,int,int action,int)169 void CEGuiGLFWSharedBase::glfwKeyCallback(GLFWwindow* /*window*/, int key,
170   int /*scancode*/, int action, int /*mods*/)
171 {
172     CEGUI::Key::Scan ceguiKey = GlfwToCeguiKey(key);
173 
174     if(action == GLFW_PRESS)
175         d_sampleApp->injectKeyDown(ceguiKey);
176     else if (action == GLFW_RELEASE)
177         d_sampleApp->injectKeyUp(ceguiKey);
178 }
179 
180 //----------------------------------------------------------------------------//
glfwCharCallback(GLFWwindow *,unsigned codepoint)181 void CEGuiGLFWSharedBase::glfwCharCallback
182   (GLFWwindow* /*window*/, unsigned codepoint)
183 {
184     d_sampleApp->injectChar(codepoint);
185 }
186 
187 //----------------------------------------------------------------------------//
glfwMouseButtonCallback(GLFWwindow *,int button,int action,int)188 void CEGuiGLFWSharedBase::glfwMouseButtonCallback
189   (GLFWwindow* /*window*/, int button, int action, int /*mods*/)
190 {
191     CEGUI::MouseButton ceguiMouseButton = GlfwToCeguiMouseButton(button);
192 
193     if (action == GLFW_PRESS)
194         d_sampleApp->injectMouseButtonDown(ceguiMouseButton);
195     else if (action == GLFW_RELEASE)
196         d_sampleApp->injectMouseButtonUp(ceguiMouseButton);
197 }
198 
199 //----------------------------------------------------------------------------//
glfwScrollCallback(GLFWwindow *,double,double yoffset)200 void CEGuiGLFWSharedBase::glfwScrollCallback
201   (GLFWwindow* /*window*/, double /*xoffset*/, double yoffset)
202 {
203     d_sampleApp->injectMouseWheelChange(static_cast<float>(yoffset/4));
204 }
205 
206 //----------------------------------------------------------------------------//
glfwCursorPosCallback(GLFWwindow *,double x,double y)207 void CEGuiGLFWSharedBase::glfwCursorPosCallback
208   (GLFWwindow* /*window*/, double x, double y)
209 {
210     if (!d_mouseDisableCalled)
211     {
212         // if cursor didn't leave the window nothing changes
213         d_sampleApp->injectMousePosition(static_cast<float>(x), static_cast<float>(y));
214     }
215     else
216     {
217         // if the cursor left the window, we need to use the saved position
218         // because glfw beams the cursor to the middle of the window if
219         // the cursor is disabled
220         d_sampleApp->injectMousePosition(static_cast<float>(d_oldMousePosX), static_cast<float>(d_oldMousePosY));
221         glfwSetCursorPos(d_window, d_oldMousePosX, d_oldMousePosY);
222         d_mouseDisableCalled = false;
223     }
224 
225 #ifndef DEBUG
226     if (x < 0 || y < 0
227         || x > d_newWindowWidth
228         || y > d_newWindowHeight)
229     {
230         // show cursor
231         glfwSetInputMode(d_window, GLFW_CURSOR, GLFW_CURSOR_NORMAL);
232 
233         // move the cursor to the position where it left the window
234         glfwSetCursorPos(d_window, x, y);
235 
236         // "note down" that the cursor left the window
237         d_mouseLeftWindow = true;
238     }
239     else
240     {
241         if (d_mouseLeftWindow)
242         {
243             // get cursor position to restore afterwards
244             glfwGetCursorPos(d_window, &d_oldMousePosX, &d_oldMousePosY);
245 
246             // we need to inject the previous cursor position because
247             // glfw moves the cursor to the centre of the render
248             // window if it gets disabled. therefore notify the
249             // next MousePosCallback invocation of the "mouse disabled" event.
250             d_mouseDisableCalled = true;
251 
252             // disable cursor
253             glfwSetInputMode(d_window, GLFW_CURSOR, GLFW_CURSOR_HIDDEN);
254 
255             // "note down" that the cursor is back in the render window
256             d_mouseLeftWindow = false;
257         }
258     }
259 #endif
260 }
261