diff --git a/src/framework/CMakeLists.txt b/src/framework/CMakeLists.txt index 15c2cc34..ebc04b97 100644 --- a/src/framework/CMakeLists.txt +++ b/src/framework/CMakeLists.txt @@ -20,11 +20,10 @@ FIND_PACKAGE(Boost COMPONENTS system REQUIRED) IF(USE_OPENGL_ES2) FIND_PACKAGE(OpenGLES2 REQUIRED) FIND_PACKAGE(EGL REQUIRED) - SET(OPENGL_INCLUDE_DIR ${OPENGLES_INCLUDE_DIR} ${EGL_INCLUDE_DIR}) - SET(OPENGL_LIBRARIES ${OPENGLES_LIBRARY} ${EGL_LIBRARY}) ADD_DEFINITIONS(-DOPENGL_ES2) ELSE(USE_OPENGL_ES2) FIND_PACKAGE(OpenGL REQUIRED) + FIND_PACKAGE(GLEW REQUIRED) ENDIF(USE_OPENGL_ES2) FIND_PACKAGE(Lua REQUIRED) @@ -66,7 +65,9 @@ IF(USE_GCC47) ENDIF(USE_GCC47) IF(WIN32) - SET(framework_SOURCES ${framework_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/platform/win32window.cpp) + SET(framework_SOURCES ${framework_SOURCES} + ${CMAKE_CURRENT_LIST_DIR}/platform/win32window.cpp + ${CMAKE_CURRENT_LIST_DIR}/platform/win32crashhandler.cpp) SET(ADDITIONAL_LIBRARIES ws2_32 mswsock) IF(CMAKE_COMPILER_IS_GNUCXX) @@ -89,13 +90,17 @@ ELSE(WIN32) ADD_DEFINITIONS(-D_GLIBCXX__PTHREADS) ENDIF(USE_GCC47) SET(ADDITIONAL_LIBRARIES X11 dl) - SET(framework_SOURCES ${framework_SOURCES} ${CMAKE_CURRENT_LIST_DIR}/platform/x11window.cpp) + SET(framework_SOURCES ${framework_SOURCES} + ${CMAKE_CURRENT_LIST_DIR}/platform/x11window.cpp + ${CMAKE_CURRENT_LIST_DIR}/platform/unixcrashhandler.cpp) ENDIF(WIN32) INCLUDE_DIRECTORIES( ${Boost_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIR} + ${EGL_INCLUDE_DIR} + ${OPENGLES_INCLUDE_DIR} ${LUA_INCLUDE_DIR} ${PHYSFS_INCLUDE_DIR} ${GMP_INCLUDE_DIR} @@ -105,7 +110,9 @@ INCLUDE_DIRECTORIES( SET(framework_LIBRARIES ${Boost_LIBRARIES} + ${GLEW_LIBRARY} ${OPENGL_LIBRARIES} + ${OPENGLES_LIBRARY} ${LUA_LIBRARIES} ${PHYSFS_LIBRARY} ${GMP_LIBRARY} diff --git a/src/framework/application.cpp b/src/framework/application.cpp index 15af6960..6e214556 100644 --- a/src/framework/application.cpp +++ b/src/framework/application.cpp @@ -34,6 +34,7 @@ #include #include #include +#include Application *g_app = nullptr; @@ -72,6 +73,10 @@ void Application::init(const std::vector& args, int appFlags) signal(SIGTERM, exitSignalHandler); signal(SIGINT, exitSignalHandler); +#ifdef HANDLE_EXCEPTIONS + installCrashHandler(); +#endif + // initialize lua g_lua.init(); registerLuaFunctions(); diff --git a/src/framework/cmake/FindEGL.cmake b/src/framework/cmake/FindEGL.cmake index bcbec21e..2a3069d3 100644 --- a/src/framework/cmake/FindEGL.cmake +++ b/src/framework/cmake/FindEGL.cmake @@ -3,7 +3,7 @@ # EGL_INCLUDE_DIR - the EGL include directory # EGL_LIBRARY - the EGL library -FIND_PATH(EGL_INCLUDE_DIR egl.h PATH_SUFFIXES EGL) +FIND_PATH(EGL_INCLUDE_DIR NAMES EGL/egl.h) FIND_LIBRARY(EGL_LIBRARY NAMES EGL) INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(EGL DEFAULT_MSG EGL_LIBRARY EGL_INCLUDE_DIR) diff --git a/src/framework/cmake/FindGLEW.cmake b/src/framework/cmake/FindGLEW.cmake new file mode 100644 index 00000000..9e226c1c --- /dev/null +++ b/src/framework/cmake/FindGLEW.cmake @@ -0,0 +1,10 @@ +# Try to find the GLEW librairy +# GLEW_FOUND - system has GLEW +# GLEW_INCLUDE_DIR - the GLEW include directory +# GLEW_LIBRARY - the GLEW library + +FIND_PATH(GLEW_INCLUDE_DIR NAMES GL/glew.h) +FIND_LIBRARY(GLEW_LIBRARY NAMES libGLEW.a libglew32.a GLEW glew32) +INCLUDE(FindPackageHandleStandardArgs) +FIND_PACKAGE_HANDLE_STANDARD_ARGS(GLEW DEFAULT_MSG GLEW_LIBRARY GLEW_INCLUDE_DIR) +MARK_AS_ADVANCED(GLEW_LIBRARY GLEW_INCLUDE_DIR) \ No newline at end of file diff --git a/src/framework/cmake/FindOpenGLES2.cmake b/src/framework/cmake/FindOpenGLES2.cmake index 34afa737..09692766 100644 --- a/src/framework/cmake/FindOpenGLES2.cmake +++ b/src/framework/cmake/FindOpenGLES2.cmake @@ -3,7 +3,7 @@ # OPENGLES_INCLUDE_DIR - the OpenGLES include directory # OPENGLES_LIBRARY - the OpenGLES library -FIND_PATH(OPENGLES_INCLUDE_DIR gl2.h PATH_SUFFIXES GLES2) +FIND_PATH(OPENGLES_INCLUDE_DIR NAMES GLES2/gl2.h) FIND_LIBRARY(OPENGLES_LIBRARY NAMES GLESv2) INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(OpenGLES DEFAULT_MSG OPENGLES_LIBRARY OPENGLES_INCLUDE_DIR) diff --git a/src/framework/graphics/glutil.h b/src/framework/graphics/glutil.h index 344d6ee7..c5e16e4c 100644 --- a/src/framework/graphics/glutil.h +++ b/src/framework/graphics/glutil.h @@ -24,12 +24,13 @@ #ifndef GLUTIL_H #define GLUTIL_H -#define GL_GLEXT_PROTOTYPES - #ifndef OPENGL_ES2 -#include -#include +#define GLEW_STATIC +#include +//#include +//#include #else +#define GL_GLEXT_PROTOTYPES #include #include #endif diff --git a/src/framework/graphics/graphics.cpp b/src/framework/graphics/graphics.cpp index 8b8f7d90..ba46112f 100644 --- a/src/framework/graphics/graphics.cpp +++ b/src/framework/graphics/graphics.cpp @@ -30,6 +30,18 @@ Graphics g_graphics; void Graphics::init() { +#ifndef OPENGL_ES2 + // init GL extensions + GLenum err = glewInit(); + if(err != GLEW_OK) + logFatal("Unable to init GLEW: ", glewGetErrorString(err)); + if(!GLEW_ARB_vertex_program || !GLEW_ARB_vertex_shader || + !GLEW_ARB_fragment_program || !GLEW_ARB_fragment_shader || + !GLEW_ARB_framebuffer_object || + !GLEW_ARB_multitexture) + logFatal("Your video driver is not supported"); +#endif + glEnable(GL_BLEND); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); diff --git a/src/framework/platform/crashhandler.h b/src/framework/platform/crashhandler.h new file mode 100644 index 00000000..b8c96e15 --- /dev/null +++ b/src/framework/platform/crashhandler.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#ifndef CRASHHANDLER_H +#define CRASHHANDLER_H + +void installCrashHandler(); + +#endif diff --git a/src/framework/platform/crashhandler.cpp b/src/framework/platform/unixcrashhandler.cpp similarity index 95% rename from src/framework/platform/crashhandler.cpp rename to src/framework/platform/unixcrashhandler.cpp index b788a324..a0c798f4 100644 --- a/src/framework/platform/crashhandler.cpp +++ b/src/framework/platform/unixcrashhandler.cpp @@ -20,11 +20,10 @@ * THE SOFTWARE. */ - -#ifdef HANDLE_EXCEPTIONS - -#include +#include "crashhandler.h" +#include #include +#include #define MAX_BACKTRACE_DEPTH 128 #define DEMANGLE_BACKTRACE_SYMBOLS @@ -38,7 +37,7 @@ void crashHandler(int signum, siginfo_t* info, void* secret) char fileName[128]; time(&tnow); tm *ts = localtime(&tnow); - strftime(fileName, 128, (x11.appName + "-crash_-%d-%m-%Y_%H:%M:%S.txt").c_str(), ts); + strftime(fileName, 128, (g_app->getAppName() + "-crash_-%d-%m-%Y_%H:%M:%S.txt").c_str(), ts); std::stringstream ss; ss.flags(std::ios::hex | std::ios::showbase); @@ -103,10 +102,9 @@ void crashHandler(int signum, siginfo_t* info, void* secret) signal(SIGSEGV, SIG_DFL); signal(SIGFPE, SIG_DFL); } -#endif - -#ifdef HANDLE_EXCEPTIONS +void installCrashHandler() +{ struct sigaction sa; sa.sa_sigaction = &crashHandler; sigemptyset (&sa.sa_mask); @@ -115,4 +113,4 @@ void crashHandler(int signum, siginfo_t* info, void* secret) sigaction(SIGILL, &sa, NULL); // illegal instruction sigaction(SIGSEGV, &sa, NULL); // segmentation fault sigaction(SIGFPE, &sa, NULL); // floating-point exception -#endif \ No newline at end of file +} diff --git a/src/framework/platform/win32crashhandler.cpp b/src/framework/platform/win32crashhandler.cpp new file mode 100644 index 00000000..e34e4dc5 --- /dev/null +++ b/src/framework/platform/win32crashhandler.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2010-2011 OTClient + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ + +#include "crashhandler.h" +#include +#include +#include +#include + +typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)( + HANDLE hProcess, + DWORD ProcessId, + HANDLE hFile, + MINIDUMP_TYPE DumpType, + PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, + PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, + PMINIDUMP_CALLBACK_INFORMATION CallbackParam); + +LONG WINAPI crashHandler(EXCEPTION_POINTERS* exceptionPointers) +{ + logError("Application crashed"); + HMODULE hDbgHelp = LoadLibraryA("DBGHELP.DLL"); + char fileName[128]; + + if(hDbgHelp) { + MINIDUMPWRITEDUMP minuDumpWriteDump = (MINIDUMPWRITEDUMP)GetProcAddress(hDbgHelp, "MiniDumpWriteDump"); + + SYSTEMTIME systemTime; + GetSystemTime(&systemTime); + snprintf(fileName, 128, "%s_%02u-%02u-%04u_%02u-%02u-%02u.mdmp", g_app->getAppName().c_str(), + systemTime.wDay, systemTime.wMonth, systemTime.wYear, + systemTime.wHour, systemTime.wMinute, systemTime.wSecond); + + HANDLE hFile = CreateFileA(fileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if(hFile) { + MINIDUMP_EXCEPTION_INFORMATION exceptionInformation; + exceptionInformation.ClientPointers = FALSE; + exceptionInformation.ExceptionPointers = exceptionPointers; + exceptionInformation.ThreadId = GetCurrentThreadId(); + + HANDLE hProcess = GetCurrentProcess(); + DWORD ProcessId = GetProcessId(hProcess); + MINIDUMP_TYPE flags = (MINIDUMP_TYPE)(MiniDumpNormal); + + BOOL dumpResult = minuDumpWriteDump(hProcess, ProcessId, hFile, flags, &exceptionInformation, NULL, NULL); + if(!dumpResult){ + logError("Cannot generate minidump: ", GetLastError()); + CloseHandle(hFile); + DeleteFileA(fileName); + return EXCEPTION_CONTINUE_SEARCH; + } else { + logInfo("Crash minidump genarated on file ", fileName); + } + } else { + logError("Cannot create dump file: ", GetLastError()); + } + } else { + logError("Cannot create dump file: dbghlp.dll not found"); + } + return EXCEPTION_CONTINUE_SEARCH; +} + +void installCrashHandler() +{ + SetUnhandledExceptionFilter(crashHandler); +} diff --git a/src/framework/platform/win32window.cpp b/src/framework/platform/win32window.cpp index 9c52470e..f3960f08 100644 --- a/src/framework/platform/win32window.cpp +++ b/src/framework/platform/win32window.cpp @@ -20,777 +20,600 @@ * THE SOFTWARE. */ -// disabled for a while -#if 0 #include "win32window.h" -#include "platform.h" -#include "platformlistener.h" - -#include -#include -#include - +#include #include #include -LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); - -struct Win32PlatformPrivate { - HWND window; - HINSTANCE instance; - HDC hdc; - HGLRC hrc; - std::string appName; - int x, y; - int width, height; - int minWidth, minHeight; - bool focused, visible, maximized; - std::map keyMap; - PlatformListener* listener; - PlatformEvent platformEvent; -} win32; - -Platform g_platform; - -#ifdef HANDLE_EXCEPTIONS -#include - -typedef BOOL (WINAPI *MINIDUMPWRITEDUMP)( - HANDLE hProcess, - DWORD ProcessId, - HANDLE hFile, - MINIDUMP_TYPE DumpType, - PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam, - PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam, - PMINIDUMP_CALLBACK_INFORMATION CallbackParam); - -LONG WINAPI crashHandler(EXCEPTION_POINTERS* exceptionPointers) -{ - logError("Application crashed"); - HMODULE hDbgHelp = LoadLibraryA("DBGHELP.DLL"); - char fileName[128]; - - if(hDbgHelp) { - MINIDUMPWRITEDUMP minuDumpWriteDump = (MINIDUMPWRITEDUMP)GetProcAddress(hDbgHelp, "MiniDumpWriteDump"); - - SYSTEMTIME systemTime; - GetSystemTime(&systemTime); - snprintf(fileName, 128, "%s_%02u-%02u-%04u_%02u-%02u-%02u.mdmp", win32.appName.c_str(), - systemTime.wDay, systemTime.wMonth, systemTime.wYear, - systemTime.wHour, systemTime.wMinute, systemTime.wSecond); - - HANDLE hFile = CreateFileA(fileName, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); - if(hFile) { - MINIDUMP_EXCEPTION_INFORMATION exceptionInformation; - exceptionInformation.ClientPointers = FALSE; - exceptionInformation.ExceptionPointers = exceptionPointers; - exceptionInformation.ThreadId = GetCurrentThreadId(); - - HANDLE hProcess = GetCurrentProcess(); - DWORD ProcessId = GetProcessId(hProcess); - MINIDUMP_TYPE flags = (MINIDUMP_TYPE)(MiniDumpNormal); - - BOOL dumpResult = minuDumpWriteDump(hProcess, ProcessId, hFile, flags, &exceptionInformation, NULL, NULL); - if(!dumpResult){ - logError("Cannot generate minidump: ", GetLastError()); - CloseHandle(hFile); - DeleteFileA(fileName); - return EXCEPTION_CONTINUE_SEARCH; - } else { - logInfo("Crash minidump genarated on file ", fileName); - } - } else { - logError("Cannot create dump file: ", GetLastError()); - } - } else { - logError("Cannot create dump file: dbghlp.dll not found"); - } - return EXCEPTION_CONTINUE_SEARCH; -} -#endif - -void Platform::init(PlatformListener* platformListener, const char *appName) -{ - // install crash handler -#ifdef HANDLE_EXCEPTIONS - SetUnhandledExceptionFilter(crashHandler); -#endif - - // seend random numbers - std::srand(std::time(NULL)); - - win32.appName = appName; - win32.instance = GetModuleHandle(NULL); - win32.listener = platformListener; - win32.keyMap[VK_ESCAPE] = Fw::KeyEscape; - win32.keyMap[VK_TAB] = Fw::KeyTab; - win32.keyMap[VK_RETURN] = Fw::KeyReturn; - win32.keyMap[VK_BACK] = Fw::KeyBackspace; - win32.keyMap[VK_SPACE] = Fw::KeySpace; - - win32.keyMap[VK_PRIOR] = Fw::KeyPageUp; - win32.keyMap[VK_NEXT] = Fw::KeyPageDown; - win32.keyMap[VK_HOME] = Fw::KeyHome; - win32.keyMap[VK_END] = Fw::KeyEnd; - win32.keyMap[VK_INSERT] = Fw::KeyInsert; - win32.keyMap[VK_DELETE] = Fw::KeyDelete; - - win32.keyMap[VK_UP] = Fw::KeyUp; - win32.keyMap[VK_DOWN] = Fw::KeyDown; - win32.keyMap[VK_LEFT] = Fw::KeyLeft; - win32.keyMap[VK_RIGHT] = Fw::KeyRight; - - win32.keyMap[VK_NUMLOCK] = Fw::KeyNumLock; - win32.keyMap[VK_SCROLL] = Fw::KeyScrollLock; - win32.keyMap[VK_CAPITAL] = Fw::KeyCapsLock; - win32.keyMap[VK_SNAPSHOT] = Fw::KeyPrintScreen; - win32.keyMap[VK_PAUSE] = Fw::KeyPause; - - win32.keyMap[VK_LCONTROL] = Fw::KeyCtrl; - win32.keyMap[VK_RCONTROL] = Fw::KeyCtrl; - win32.keyMap[VK_LSHIFT] = Fw::KeyShift; - win32.keyMap[VK_RSHIFT] = Fw::KeyShift; - win32.keyMap[VK_LMENU] = Fw::KeyAlt; - win32.keyMap[VK_RMENU] = Fw::KeyAltGr; - win32.keyMap[VK_LWIN] = Fw::KeyMeta; - win32.keyMap[VK_RWIN] = Fw::KeyMeta; - win32.keyMap[VK_MENU] = Fw::KeyMenu; +WIN32Window::WIN32Window() +{ + m_window = 0; + m_instance = 0; + m_deviceContext = 0; + m_glContext = 0; + m_maximized = false; + + m_keyMap[VK_ESCAPE] = Fw::KeyEscape; + m_keyMap[VK_TAB] = Fw::KeyTab; + m_keyMap[VK_RETURN] = Fw::KeyReturn; + m_keyMap[VK_BACK] = Fw::KeyBackspace; + m_keyMap[VK_SPACE] = Fw::KeySpace; + + m_keyMap[VK_PRIOR] = Fw::KeyPageUp; + m_keyMap[VK_NEXT] = Fw::KeyPageDown; + m_keyMap[VK_HOME] = Fw::KeyHome; + m_keyMap[VK_END] = Fw::KeyEnd; + m_keyMap[VK_INSERT] = Fw::KeyInsert; + m_keyMap[VK_DELETE] = Fw::KeyDelete; + + m_keyMap[VK_UP] = Fw::KeyUp; + m_keyMap[VK_DOWN] = Fw::KeyDown; + m_keyMap[VK_LEFT] = Fw::KeyLeft; + m_keyMap[VK_RIGHT] = Fw::KeyRight; + + m_keyMap[VK_NUMLOCK] = Fw::KeyNumLock; + m_keyMap[VK_SCROLL] = Fw::KeyScrollLock; + m_keyMap[VK_CAPITAL] = Fw::KeyCapsLock; + m_keyMap[VK_SNAPSHOT] = Fw::KeyPrintScreen; + m_keyMap[VK_PAUSE] = Fw::KeyPause; + + m_keyMap[VK_LCONTROL] = Fw::KeyCtrl; + m_keyMap[VK_RCONTROL] = Fw::KeyCtrl; + m_keyMap[VK_LSHIFT] = Fw::KeyShift; + m_keyMap[VK_RSHIFT] = Fw::KeyShift; + m_keyMap[VK_LMENU] = Fw::KeyAlt; + m_keyMap[VK_RMENU] = Fw::KeyAltGr; + m_keyMap[VK_LWIN] = Fw::KeyMeta; + m_keyMap[VK_RWIN] = Fw::KeyMeta; + m_keyMap[VK_MENU] = Fw::KeyMenu; // ascii characters /* - win32.keyMap['!'] = Fw::KeyExclamation; - win32.keyMap['"'] = Fw::KeyQuote; - win32.keyMap['#'] = Fw::KeyNumberSign; - win32.keyMap['$'] = Fw::KeyDollar; - win32.keyMap['%'] = Fw::KeyPercent; - win32.keyMap['$'] = Fw::KeyAmpersand; - win32.keyMap['\''] = Fw::KeyApostrophe; - win32.keyMap['('] = Fw::KeyLeftParen; - win32.keyMap[')'] = Fw::KeyRightParen; - win32.keyMap['*'] = Fw::KeyAsterisk; - win32.keyMap['+'] = Fw::KeyPlus; - win32.keyMap['.'] = Fw::KeyComma; - win32.keyMap['-'] = Fw::KeyMinus; - win32.keyMap['.'] = Fw::KeyPeriod; - win32.keyMap['/'] = Fw::KeySlash; + m_keyMap['!'] = Fw::KeyExclamation; + m_keyMap['"'] = Fw::KeyQuote; + m_keyMap['#'] = Fw::KeyNumberSign; + m_keyMap['$'] = Fw::KeyDollar; + m_keyMap['%'] = Fw::KeyPercent; + m_keyMap['$'] = Fw::KeyAmpersand; + m_keyMap['\''] = Fw::KeyApostrophe; + m_keyMap['('] = Fw::KeyLeftParen; + m_keyMap[')'] = Fw::KeyRightParen; + m_keyMap['*'] = Fw::KeyAsterisk; + m_keyMap['+'] = Fw::KeyPlus; + m_keyMap['.'] = Fw::KeyComma; + m_keyMap['-'] = Fw::KeyMinus; + m_keyMap['.'] = Fw::KeyPeriod; + m_keyMap['/'] = Fw::KeySlash; */ - win32.keyMap['0'] = Fw::Key0; - win32.keyMap['1'] = Fw::Key1; - win32.keyMap['2'] = Fw::Key2; - win32.keyMap['3'] = Fw::Key3; - win32.keyMap['4'] = Fw::Key4; - win32.keyMap['5'] = Fw::Key5; - win32.keyMap['6'] = Fw::Key6; - win32.keyMap['7'] = Fw::Key7; - win32.keyMap['8'] = Fw::Key8; - win32.keyMap['9'] = Fw::Key9; + m_keyMap['0'] = Fw::Key0; + m_keyMap['1'] = Fw::Key1; + m_keyMap['2'] = Fw::Key2; + m_keyMap['3'] = Fw::Key3; + m_keyMap['4'] = Fw::Key4; + m_keyMap['5'] = Fw::Key5; + m_keyMap['6'] = Fw::Key6; + m_keyMap['7'] = Fw::Key7; + m_keyMap['8'] = Fw::Key8; + m_keyMap['9'] = Fw::Key9; /* - win32.keyMap[':'] = Fw::KeyColon; - win32.keyMap[';'] = Fw::KeySemicolon; - win32.keyMap['<'] = Fw::KeyLess; - win32.keyMap['='] = Fw::KeyEqual; - win32.keyMap['>'] = Fw::KeyGreater; - win32.keyMap['?'] = Fw::KeyQuestion; - win32.keyMap['@'] = Fw::KeyAtSign; + m_keyMap[':'] = Fw::KeyColon; + m_keyMap[';'] = Fw::KeySemicolon; + m_keyMap['<'] = Fw::KeyLess; + m_keyMap['='] = Fw::KeyEqual; + m_keyMap['>'] = Fw::KeyGreater; + m_keyMap['?'] = Fw::KeyQuestion; + m_keyMap['@'] = Fw::KeyAtSign; */ - win32.keyMap['A'] = Fw::KeyA; - win32.keyMap['B'] = Fw::KeyB; - win32.keyMap['C'] = Fw::KeyC; - win32.keyMap['D'] = Fw::KeyD; - win32.keyMap['E'] = Fw::KeyE; - win32.keyMap['F'] = Fw::KeyF; - win32.keyMap['G'] = Fw::KeyG; - win32.keyMap['H'] = Fw::KeyH; - win32.keyMap['I'] = Fw::KeyI; - win32.keyMap['J'] = Fw::KeyJ; - win32.keyMap['K'] = Fw::KeyK; - win32.keyMap['L'] = Fw::KeyL; - win32.keyMap['M'] = Fw::KeyM; - win32.keyMap['N'] = Fw::KeyN; - win32.keyMap['O'] = Fw::KeyO; - win32.keyMap['P'] = Fw::KeyP; - win32.keyMap['Q'] = Fw::KeyQ; - win32.keyMap['R'] = Fw::KeyR; - win32.keyMap['S'] = Fw::KeyS; - win32.keyMap['T'] = Fw::KeyT; - win32.keyMap['U'] = Fw::KeyU; - win32.keyMap['V'] = Fw::KeyV; - win32.keyMap['W'] = Fw::KeyW; - win32.keyMap['X'] = Fw::KeyX; - win32.keyMap['Y'] = Fw::KeyY; - win32.keyMap['Z'] = Fw::KeyZ; + m_keyMap['A'] = Fw::KeyA; + m_keyMap['B'] = Fw::KeyB; + m_keyMap['C'] = Fw::KeyC; + m_keyMap['D'] = Fw::KeyD; + m_keyMap['E'] = Fw::KeyE; + m_keyMap['F'] = Fw::KeyF; + m_keyMap['G'] = Fw::KeyG; + m_keyMap['H'] = Fw::KeyH; + m_keyMap['I'] = Fw::KeyI; + m_keyMap['J'] = Fw::KeyJ; + m_keyMap['K'] = Fw::KeyK; + m_keyMap['L'] = Fw::KeyL; + m_keyMap['M'] = Fw::KeyM; + m_keyMap['N'] = Fw::KeyN; + m_keyMap['O'] = Fw::KeyO; + m_keyMap['P'] = Fw::KeyP; + m_keyMap['Q'] = Fw::KeyQ; + m_keyMap['R'] = Fw::KeyR; + m_keyMap['S'] = Fw::KeyS; + m_keyMap['T'] = Fw::KeyT; + m_keyMap['U'] = Fw::KeyU; + m_keyMap['V'] = Fw::KeyV; + m_keyMap['W'] = Fw::KeyW; + m_keyMap['X'] = Fw::KeyX; + m_keyMap['Y'] = Fw::KeyY; + m_keyMap['Z'] = Fw::KeyZ; /* - win32.keyMap['['] = Fw::KeyLeftBracket; - win32.keyMap['\\'] = Fw::KeyBackslash; - win32.keyMap[']'] = Fw::KeyRightBracket; - win32.keyMap['^'] = Fw::KeyCaret; - win32.keyMap['_'] = Fw::KeyUnderscore; - win32.keyMap['`'] = Fw::KeyGrave; - win32.keyMap['{'] = Fw::KeyLeftCurly; - win32.keyMap['|'] = Fw::KeyBar; - win32.keyMap['}'] = Fw::KeyRightCurly; - win32.keyMap['~'] = Fw::KeyTilde; + m_keyMap['['] = Fw::KeyLeftBracket; + m_keyMap['\\'] = Fw::KeyBackslash; + m_keyMap[']'] = Fw::KeyRightBracket; + m_keyMap['^'] = Fw::KeyCaret; + m_keyMap['_'] = Fw::KeyUnderscore; + m_keyMap['`'] = Fw::KeyGrave; + m_keyMap['{'] = Fw::KeyLeftCurly; + m_keyMap['|'] = Fw::KeyBar; + m_keyMap['}'] = Fw::KeyRightCurly; + m_keyMap['~'] = Fw::KeyTilde; */ // keypad - win32.keyMap[VK_ADD] = Fw::KeyPlus; - win32.keyMap[VK_SUBTRACT] = Fw::KeyMinus; - win32.keyMap[VK_DECIMAL] = Fw::KeyPeriod; - win32.keyMap[VK_DIVIDE] = Fw::KeySlash; - win32.keyMap[VK_MULTIPLY] = Fw::KeyAsterisk; - win32.keyMap[VK_SEPARATOR] = Fw::KeyEnter; + m_keyMap[VK_ADD] = Fw::KeyPlus; + m_keyMap[VK_SUBTRACT] = Fw::KeyMinus; + m_keyMap[VK_DECIMAL] = Fw::KeyPeriod; + m_keyMap[VK_DIVIDE] = Fw::KeySlash; + m_keyMap[VK_MULTIPLY] = Fw::KeyAsterisk; + m_keyMap[VK_SEPARATOR] = Fw::KeyEnter; // keypad with numlock off - win32.keyMap[VK_NUMPAD0] = Fw::KeyNumpad0; - win32.keyMap[VK_NUMPAD1] = Fw::KeyNumpad1; - win32.keyMap[VK_NUMPAD2] = Fw::KeyNumpad2; - win32.keyMap[VK_NUMPAD3] = Fw::KeyNumpad3; - win32.keyMap[VK_NUMPAD4] = Fw::KeyNumpad4; - win32.keyMap[VK_NUMPAD5] = Fw::KeyNumpad5; - win32.keyMap[VK_NUMPAD6] = Fw::KeyNumpad6; - win32.keyMap[VK_NUMPAD7] = Fw::KeyNumpad7; - win32.keyMap[VK_NUMPAD8] = Fw::KeyNumpad8; - win32.keyMap[VK_NUMPAD9] = Fw::KeyNumpad9; - - win32.keyMap[VK_OEM_1] = Fw::KeySemicolon; - win32.keyMap[VK_OEM_2] = Fw::KeySlash; - win32.keyMap[VK_OEM_3] = Fw::KeyGrave; - win32.keyMap[VK_OEM_4] = Fw::KeyLeftBracket; - win32.keyMap[VK_OEM_5] = Fw::KeyBackslash; - win32.keyMap[VK_OEM_6] = Fw::KeyRightBracket; - win32.keyMap[VK_OEM_7] = Fw::KeyApostrophe; - win32.keyMap[VK_OEM_MINUS] = Fw::KeyMinus; - win32.keyMap[VK_OEM_PLUS] = Fw::KeyPlus; - win32.keyMap[VK_OEM_COMMA] = Fw::KeyComma; - win32.keyMap[VK_OEM_PERIOD] = Fw::KeyPeriod; - - win32.keyMap[VK_F1] = Fw::KeyF1; - win32.keyMap[VK_F2] = Fw::KeyF2; - win32.keyMap[VK_F3] = Fw::KeyF3; - win32.keyMap[VK_F4] = Fw::KeyF4; - win32.keyMap[VK_F5] = Fw::KeyF5; - win32.keyMap[VK_F6] = Fw::KeyF6; - win32.keyMap[VK_F7] = Fw::KeyF7; - win32.keyMap[VK_F8] = Fw::KeyF8; - win32.keyMap[VK_F9] = Fw::KeyF9; - win32.keyMap[VK_F10] = Fw::KeyF10; - win32.keyMap[VK_F11] = Fw::KeyF11; - win32.keyMap[VK_F12] = Fw::KeyF12; - - // win class - WNDCLASSA wc; - wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Size, And Own DC For Window. - wc.lpfnWndProc = (WNDPROC)WndProc; // WndProc Handles Messages - wc.cbClsExtra = 0; // No Extra Window Data - wc.cbWndExtra = 0; // No Extra Window Data - wc.hInstance = win32.instance; // Set The Instance - wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); // Load The Default Icon - wc.hCursor = LoadCursor(NULL, IDC_ARROW); // Load The Arrow Pointer - wc.hbrBackground = NULL; // No Background Required For GL - wc.lpszMenuName = NULL; // We Don't Want A Menu - wc.lpszClassName = win32.appName.c_str(); // Set The Class Name - - if(!RegisterClassA(&wc)) - logFatal("Failed to register the window class."); - - // force first tick - updateTicks(); -} + m_keyMap[VK_NUMPAD0] = Fw::KeyNumpad0; + m_keyMap[VK_NUMPAD1] = Fw::KeyNumpad1; + m_keyMap[VK_NUMPAD2] = Fw::KeyNumpad2; + m_keyMap[VK_NUMPAD3] = Fw::KeyNumpad3; + m_keyMap[VK_NUMPAD4] = Fw::KeyNumpad4; + m_keyMap[VK_NUMPAD5] = Fw::KeyNumpad5; + m_keyMap[VK_NUMPAD6] = Fw::KeyNumpad6; + m_keyMap[VK_NUMPAD7] = Fw::KeyNumpad7; + m_keyMap[VK_NUMPAD8] = Fw::KeyNumpad8; + m_keyMap[VK_NUMPAD9] = Fw::KeyNumpad9; + + m_keyMap[VK_OEM_1] = Fw::KeySemicolon; + m_keyMap[VK_OEM_2] = Fw::KeySlash; + m_keyMap[VK_OEM_3] = Fw::KeyGrave; + m_keyMap[VK_OEM_4] = Fw::KeyLeftBracket; + m_keyMap[VK_OEM_5] = Fw::KeyBackslash; + m_keyMap[VK_OEM_6] = Fw::KeyRightBracket; + m_keyMap[VK_OEM_7] = Fw::KeyApostrophe; + m_keyMap[VK_OEM_MINUS] = Fw::KeyMinus; + m_keyMap[VK_OEM_PLUS] = Fw::KeyPlus; + m_keyMap[VK_OEM_COMMA] = Fw::KeyComma; + m_keyMap[VK_OEM_PERIOD] = Fw::KeyPeriod; + + m_keyMap[VK_F1] = Fw::KeyF1; + m_keyMap[VK_F2] = Fw::KeyF2; + m_keyMap[VK_F3] = Fw::KeyF3; + m_keyMap[VK_F4] = Fw::KeyF4; + m_keyMap[VK_F5] = Fw::KeyF5; + m_keyMap[VK_F6] = Fw::KeyF6; + m_keyMap[VK_F7] = Fw::KeyF7; + m_keyMap[VK_F8] = Fw::KeyF8; + m_keyMap[VK_F9] = Fw::KeyF9; + m_keyMap[VK_F10] = Fw::KeyF10; + m_keyMap[VK_F11] = Fw::KeyF11; + m_keyMap[VK_F12] = Fw::KeyF12; +} + +void WIN32Window::init() +{ + m_instance = GetModuleHandle(NULL); + + internalRegisterWindowClass(); + internalCreateWindow(); + internalChooseGLVisual(); + internalCreateGLContext(); +} + +void WIN32Window::terminate() +{ + if(m_glContext) { + if(!wglMakeCurrent(NULL, NULL)) + logError("Release of dc and rc failed."); + if(!wglDeleteContext(m_glContext)) + logError("Release rendering context failed."); + m_glContext = NULL; + } -void Platform::terminate() -{ - if(win32.window) { - destroyWindow(); - win32.window = NULL; + if(m_deviceContext) { + if(!ReleaseDC(m_window, m_deviceContext)) + logError("Release device context failed."); + m_deviceContext = NULL; } - if(win32.instance) { - if(!UnregisterClassA(win32.appName.c_str(), win32.instance)) - logError("ERROR: Unregister class failed."); + if(m_window) { + if(!DestroyWindow(m_window)) + logError("ERROR: Destroy window failed."); + m_window = NULL; + } - win32.instance = NULL; + if(m_instance) { + if(!UnregisterClassA(g_app->getAppName().c_str(), m_instance)) + logError("UnregisterClassA failed"); + m_instance = NULL; } } -void Platform::poll() -{ - MSG msg; - if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { - TranslateMessage(&msg); - DispatchMessage(&msg); +struct WindowProcProxy { + static LRESULT CALLBACK call(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + WIN32Window *window = (WIN32Window*)&g_window; + return window->windowProc(hWnd, uMsg, wParam, lParam); } -} +}; -void Platform::updateTicks() +void WIN32Window::internalRegisterWindowClass() { - static ulong firstTick = 0; - if(!firstTick) - firstTick = GetTickCount(); - - m_lastTicks = (uint32_t)(GetTickCount() - firstTick); -} + WNDCLASSA wc; + wc.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; + wc.lpfnWndProc = (WNDPROC)WindowProcProxy::call; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = m_instance; + wc.hIcon = LoadIcon(NULL, IDI_WINLOGO); + wc.hCursor = LoadCursor(NULL, IDC_ARROW); + wc.hbrBackground = NULL; + wc.lpszMenuName = NULL; + wc.lpszClassName = g_app->getAppName().c_str(); -void Platform::sleep(ulong miliseconds) -{ - Sleep(miliseconds); + if(!RegisterClassA(&wc)) + logFatal("Failed to register the window class."); } -bool Platform::createWindow(int x, int y, int width, int height, int minWidth, int minHeight, bool maximized) +void WIN32Window::internalCreateWindow() { DWORD dwExStyle = WS_EX_APPWINDOW | WS_EX_WINDOWEDGE; DWORD dwStyle = WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN; - win32.x = x; - win32.y = y; - win32.width = width; - win32.height = height; - win32.minWidth = minWidth; - win32.minHeight = minHeight; - win32.maximized = maximized; - - RECT windowRect = {x, y, x + width, y + height}; + dump << m_size; + RECT windowRect = {m_pos.x, m_pos.y, m_pos.x + m_size.width(), m_pos.y + m_size.height()}; AdjustWindowRectEx(&windowRect, dwStyle, FALSE, dwExStyle); - win32.window = CreateWindowExA(dwExStyle, // Extended Style For The Window - win32.appName.c_str(), // Class Name - win32.appName.c_str(), // Window Title - dwStyle, // Required Window Style - windowRect.left, // Window X Position - windowRect.top, // Window Y Position - windowRect.right - windowRect.left, // Calculate Window Width - windowRect.bottom - windowRect.top, // Calculate Window Height - NULL, // No Parent Window - NULL, // No Menu - win32.instance, // Instance - NULL); - - if(!win32.window) { - terminate(); - logFatal("Window creation error."); - return false; - } - - uint pixelFormat; - static PIXELFORMATDESCRIPTOR pfd= // pfd Tells Windows How We Want Things To Be - { - sizeof(PIXELFORMATDESCRIPTOR), // Size Of This Pixel Format Descriptor - 1, // Version Number - PFD_DRAW_TO_WINDOW | // Format Must Support Window - PFD_SUPPORT_OPENGL | // Format Must Support OpenGL - PFD_DOUBLEBUFFER, // Must Support Double Buffering - PFD_TYPE_RGBA, // Request An RGBA Format - 32, // Select Our Color Depth - 0, 0, 0, 0, 0, 0, // Color Bits Ignored - 0, // No Alpha Buffer - 0, // Shift Bit Ignored - 0, // No Accumulation Buffer - 0, 0, 0, 0, // Accumulation Bits Ignored - 16, // 16Bit Z-Buffer (Depth Buffer) - 0, // No Stencil Buffer - 0, // No Auxiliary Buffer - PFD_MAIN_PLANE, // Main Drawing Layer - 0, // Reserved - 0, 0, 0 // Layer Masks Ignored - }; - - if(!(win32.hdc = GetDC(win32.window))) { - terminate(); - logFatal("Could not create OpenGL device context."); - return false; - } - - if(!(pixelFormat = ChoosePixelFormat(win32.hdc, &pfd))) { - terminate(); - logFatal("Could not find a suitable pixel format."); - return false; - } - - if(!SetPixelFormat(win32.hdc, pixelFormat, &pfd)) { - terminate(); - logFatal("Could not set the pixel format."); - return false; - } - - if(!(win32.hrc = wglCreateContext(win32.hdc))) { - terminate(); - logFatal("Could not create OpenGL rendering context."); - return false; - } - - if(!wglMakeCurrent(win32.hdc, win32.hrc)) { - terminate(); - logFatal("Can't activate the GL rendering context."); - return false; - } - - return true; -} - -void Platform::setWindowIcon(const std::string& pngIcon) -{ - apng_data apng; - std::stringstream fin; - g_resources.loadFile(pngIcon, fin); - if(load_apng(fin, &apng) == 0) { - if(apng.bpp != 4) { - logError("could not set app icon, icon image must have 4 channels"); - free_apng(&apng); - } - - int n = apng.width * apng.height; - std::vector iconData(n); - for(int i=0; i < n;++i) { - uint8 *pixel = (uint8*)&iconData[i]; - pixel[2] = *(apng.pdata + (i * 4) + 0); - pixel[1] = *(apng.pdata + (i * 4) + 1); - pixel[0] = *(apng.pdata + (i * 4) + 2); - pixel[3] = *(apng.pdata + (i * 4) + 3); - } - - HBITMAP hbmColor = CreateBitmap(apng.width, apng.height, 1, 32, &iconData[0]); - HBITMAP hbmMask = CreateCompatibleBitmap(GetDC(NULL), apng.width, apng.height); + m_window = CreateWindowExA(dwExStyle, + g_app->getAppName().c_str(), + NULL, + dwStyle, + windowRect.left, + windowRect.top, + windowRect.right - windowRect.left, + windowRect.bottom - windowRect.top, + NULL, + NULL, + m_instance, + NULL); - ICONINFO ii; - ii.fIcon = TRUE; - ii.hbmColor = hbmColor; - ii.hbmMask = hbmMask; - ii.xHotspot = 0; - ii.yHotspot = 0; + if(!m_window) + logFatal("Unable to create window"); - HICON icon = CreateIconIndirect(&ii); - DeleteObject(hbmMask); - DeleteObject(hbmColor); - - SendMessage(win32.window, WM_SETICON, ICON_SMALL, (LPARAM)icon); - SendMessage(win32.window, WM_SETICON, ICON_BIG, (LPARAM)icon); - - free_apng(&apng); - } else - logError("could not load app icon"); + m_deviceContext = GetDC(m_window); + if(!m_deviceContext) + logFatal("GetDC failed"); } -void Platform::destroyWindow() +void WIN32Window::internalChooseGLVisual() { - if(win32.hrc) { - if(!wglMakeCurrent(NULL, NULL)) - logError("Release of dc and rc failed."); - - if(!wglDeleteContext(win32.hrc)) - logError("Release rendering context failed."); - - win32.hrc = NULL; - } - - if(win32.hdc) { - if(!ReleaseDC(win32.window, win32.hdc)) - logError("Release device context failed."); - - win32.hdc = NULL; - } - - if(win32.window) { - if(!DestroyWindow(win32.window)) - logError("ERROR: Destroy window failed."); - - win32.window = NULL; - } -} + uint pixelFormat; + static PIXELFORMATDESCRIPTOR pfd = { sizeof(PIXELFORMATDESCRIPTOR), + 1, + PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER, + PFD_TYPE_RGBA, + 32, // Select Our Color Depth + 0, 0, 0, 0, 0, 0, // Color Bits Ignored + 0, // No Alpha Buffer + 0, // Shift Bit Ignored + 0, // No Accumulation Buffer + 0, 0, 0, 0, // Accumulation Bits Ignored + 16, // 16Bit Z-Buffer (Depth Buffer) + 0, // No Stencil Buffer + 0, // No Auxiliary Buffer + PFD_MAIN_PLANE, // Main Drawing Layer + 0, // Reserved + 0, 0, 0 }; // Layer Masks Ignored -void Platform::showWindow() -{ - if(win32.maximized) - ShowWindow(win32.window, SW_MAXIMIZE); - else - ShowWindow(win32.window, SW_SHOW); -} + pixelFormat = ChoosePixelFormat(m_deviceContext, &pfd); + if(!pixelFormat) + logFatal("Could not find a suitable pixel format"); -void Platform::hideWindow() -{ - ShowWindow(win32.window, SW_HIDE); + if(!SetPixelFormat(m_deviceContext, pixelFormat, &pfd)) + logFatal("Could not set the pixel format"); } -void Platform::setWindowTitle(const char *title) +void WIN32Window::internalCreateGLContext() { - SetWindowTextA(win32.window, title); -} + if(!(m_glContext = wglCreateContext(m_deviceContext))) + logFatal("Unable to create GL context"); -void *Platform::getExtensionProcAddress(const char *ext) -{ - return (void*)wglGetProcAddress(ext); + if(!wglMakeCurrent(m_deviceContext, m_glContext)) + logFatal("Unable to set GLX context on WIN32 window"); } -bool Platform::isExtensionSupported(const char *ext) +bool WIN32Window::isExtensionSupported(const char *ext) { typedef const char* _wglGetExtensionsStringARB(HDC hdc); _wglGetExtensionsStringARB *wglGetExtensionsStringARB = (_wglGetExtensionsStringARB*)getExtensionProcAddress("wglGetExtensionsStringARB"); if(wglGetExtensionsStringARB) { - const char *exts = wglGetExtensionsStringARB(win32.hdc); + const char *exts = wglGetExtensionsStringARB(m_deviceContext); if(strstr(exts, ext)) return true; } return false; } -const char *Platform::getClipboardText() -{ - const char *text = ""; - if(OpenClipboard(NULL)) { - text = (const char*)GetClipboardData(CF_TEXT); - CloseClipboard(); - } - return text; -} - -void Platform::setClipboardText(const char *text) -{ - int textLenght = strlen(text); - HANDLE hData = new HANDLE[textLenght + 1]; - memcpy(hData, text, textLenght + 1); - - if(OpenClipboard(NULL)) { - EmptyClipboard(); - SetClipboardData(CF_TEXT, hData); - CloseClipboard(); - } -} - -void Platform::hideMouseCursor() +void *WIN32Window::getExtensionProcAddress(const char *ext) { - ShowCursor(false); -} - -void Platform::showMouseCursor() -{ - ShowCursor(true); -} - -Point Platform::getMouseCursorPos() -{ - return win32.platformEvent.mousePos; -} - -void Platform::setVerticalSync(bool enable /*= true*/) -{ - typedef int (*glSwapIntervalProc)(int); - glSwapIntervalProc glSwapInterval = NULL; - - if(isExtensionSupported("WGL_EXT_swap_control")) - glSwapInterval = (glSwapIntervalProc)getExtensionProcAddress("wglSwapIntervalEXT"); - - if(glSwapInterval) - glSwapInterval(enable ? 1 : 0); -} - -void Platform::swapBuffers() -{ - SwapBuffers(win32.hdc); -} - -bool Platform::isWindowFocused() -{ - return win32.focused; -} - -bool Platform::isWindowVisible() -{ - return win32.visible; -} - -int Platform::getWindowX() -{ - return win32.x; -} - -int Platform::getWindowY() -{ - return win32.y; + return (void*)wglGetProcAddress(ext); } -int Platform::getWindowWidth() +void WIN32Window::move(const Point& pos) { - return win32.width; + MoveWindow(m_window, pos.x, pos.y, m_size.width(), m_size.height(), TRUE); } -int Platform::getWindowHeight() +void WIN32Window::resize(const Size& size) { - return win32.height; + MoveWindow(m_window, m_pos.x, m_pos.y, size.width(), size.height(), TRUE); } -int Platform::getDisplayWidth() +void WIN32Window::show() { - return GetSystemMetrics(SM_CXSCREEN); + if(m_maximized) + ShowWindow(m_window, SW_MAXIMIZE); + else + ShowWindow(m_window, SW_SHOW); } -int Platform::getDisplayHeight() +void WIN32Window::hide() { - return GetSystemMetrics(SM_CYSCREEN); + ShowWindow(m_window, SW_HIDE); } -bool Platform::isWindowMaximized() +void WIN32Window::maximize() { - return win32.maximized; + //TODO } -std::string Platform::getAppUserDir() +void WIN32Window::poll() { - std::stringstream sdir; - sdir << PHYSFS_getUserDir() << "/." << win32.appName << "/"; - if((mkdir(sdir.str().c_str()) != 0) && (errno != EEXIST)) - logError("Couldn't create directory for saving configuration file. (%s)", sdir.str().c_str()); - return sdir.str(); + MSG msg; + if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + TranslateMessage(&msg); + DispatchMessage(&msg); + } } -LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +LRESULT WIN32Window::windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - static int lastX, lastY; - PlatformEvent& platformEvent = win32.platformEvent; + m_inputEvent.type = Fw::NoInputEvent; + m_inputEvent.mouseButton = Fw::MouseNoButton; + m_inputEvent.keyCode = Fw::KeyUnknown; + m_inputEvent.keyText = ""; + m_inputEvent.mouseMoved = Point(); + m_inputEvent.wheelDirection = Fw::MouseNoWheel; switch(uMsg) { - case WM_ACTIVATE: - { - win32.focused = !(wParam == WA_INACTIVE); + case WM_ACTIVATE: { + m_focused = !(wParam == WA_INACTIVE); break; } - case WM_CHAR: - { + case WM_CHAR: { if(wParam >= 32 && wParam <= 255) { - platformEvent.type = EventKeyDown; - platformEvent.ctrl = HIWORD(GetKeyState(VK_CONTROL)) == 0 ? false : true; - platformEvent.alt = HIWORD(GetKeyState(VK_MENU)) == 0 ? false : true; - platformEvent.shift = HIWORD(GetKeyState(VK_SHIFT)) == 0 ? false : true; - platformEvent.keychar = wParam; - platformEvent.keycode = Fw::KeyUnknown; - win32.listener->onPlatformEvent(platformEvent); + m_inputEvent.type = Fw::KeyPressInputEvent; + if(HIWORD(GetKeyState(VK_CONTROL))) + m_inputEvent.keyboardModifiers |= Fw::KeyboardCtrlModifier; + if(HIWORD(GetKeyState(VK_MENU))) + m_inputEvent.keyboardModifiers |= Fw::KeyboardAltModifier; + if(HIWORD(GetKeyState(VK_SHIFT))) + m_inputEvent.keyboardModifiers |= Fw::KeyboardShiftModifier; + m_inputEvent.keyCode = Fw::KeyUnknown; + m_inputEvent.keyText = wParam; } break; } - case WM_CLOSE: - { - win32.listener->onClose(); - break; - } - case WM_GETMINMAXINFO: - { - MINMAXINFO *minMax = (MINMAXINFO*)lParam; - minMax->ptMinTrackSize.x = win32.minWidth; - minMax->ptMinTrackSize.y = win32.minHeight; + case WM_CLOSE: { + m_onClose(); break; } - case WM_KEYDOWN: - case WM_KEYUP: - { - if(win32.keyMap.find(wParam) != win32.keyMap.end()) { - platformEvent.type = uMsg == WM_KEYDOWN ? EventKeyDown : EventKeyUp; - platformEvent.ctrl = HIWORD(GetKeyState(VK_CONTROL)) == 0 ? false : true; - platformEvent.alt = HIWORD(GetKeyState(VK_MENU)) == 0 ? false : true; - platformEvent.shift = HIWORD(GetKeyState(VK_SHIFT)) == 0 ? false : true; - platformEvent.keycode = win32.keyMap[wParam]; - platformEvent.keychar = 0; + case WM_KEYDOWN: + case WM_KEYUP: { + if(m_keyMap.find(wParam) != m_keyMap.end()) { + m_inputEvent.type = (uMsg == WM_KEYDOWN) ? Fw::KeyPressInputEvent : Fw::KeyReleaseInputEvent; + if(HIWORD(GetKeyState(VK_CONTROL))) + m_inputEvent.keyboardModifiers |= Fw::KeyboardCtrlModifier; + if(HIWORD(GetKeyState(VK_MENU))) + m_inputEvent.keyboardModifiers |= Fw::KeyboardAltModifier; + if(HIWORD(GetKeyState(VK_SHIFT))) + m_inputEvent.keyboardModifiers |= Fw::KeyboardShiftModifier; + m_inputEvent.keyCode = m_keyMap[wParam]; } - win32.listener->onPlatformEvent(platformEvent); break; } - case WM_LBUTTONDOWN: - { - platformEvent.type = EventMouseLeftButtonDown; - win32.listener->onPlatformEvent(platformEvent); + case WM_LBUTTONDOWN: { + m_inputEvent.type = Fw::MousePressInputEvent; + m_inputEvent.mouseButton = Fw::MouseLeftButton; break; } - case WM_LBUTTONUP: - { - platformEvent.type = EventMouseLeftButtonUp; - win32.listener->onPlatformEvent(platformEvent); + case WM_LBUTTONUP: { + m_inputEvent.type = Fw::MouseReleaseInputEvent; + m_inputEvent.mouseButton = Fw::MouseLeftButton; break; } - case WM_MBUTTONDOWN: - { - platformEvent.type = EventMouseMiddleButtonDown; - win32.listener->onPlatformEvent(platformEvent); + case WM_MBUTTONDOWN: { + m_inputEvent.type = Fw::MousePressInputEvent; + m_inputEvent.mouseButton = Fw::MouseMidButton; break; } - case WM_MBUTTONUP: - { - platformEvent.type = EventMouseMiddleButtonUp; - win32.listener->onPlatformEvent(platformEvent); + case WM_MBUTTONUP: { + m_inputEvent.type = Fw::MouseReleaseInputEvent; + m_inputEvent.mouseButton = Fw::MouseMidButton; break; } - case WM_RBUTTONDOWN: - { - platformEvent.type = EventMouseRightButtonDown; - win32.listener->onPlatformEvent(platformEvent); + case WM_RBUTTONDOWN: { + m_inputEvent.type = Fw::MousePressInputEvent; + m_inputEvent.mouseButton = Fw::MouseRightButton; break; } - case WM_RBUTTONUP: - { - platformEvent.type = EventMouseRightButtonUp; - win32.listener->onPlatformEvent(platformEvent); + case WM_RBUTTONUP: { + m_inputEvent.type = Fw::MouseReleaseInputEvent; + m_inputEvent.mouseButton = Fw::MouseRightButton; break; } - case WM_MOUSEMOVE: - { - platformEvent.type = EventMouseMove; + case WM_MOUSEMOVE: { + m_inputEvent.type = Fw::MouseMoveInputEvent; Point newMousePos(LOWORD(lParam), HIWORD(lParam)); - platformEvent.mouseMoved = newMousePos - platformEvent.mousePos; - platformEvent.mousePos = newMousePos; - win32.listener->onPlatformEvent(platformEvent); + m_inputEvent.mouseMoved = newMousePos - m_inputEvent.mousePos; + m_inputEvent.mousePos = newMousePos; break; } - case WM_MOUSEWHEEL: - { - platformEvent.type = HIWORD(wParam) > 0 ? EventMouseWheelUp : EventMouseWheelDown; - win32.listener->onPlatformEvent(platformEvent); + case WM_MOUSEWHEEL: { + m_inputEvent.type = Fw::MouseWheelInputEvent; + m_inputEvent.mouseButton = Fw::MouseMidButton; + m_inputEvent.wheelDirection = HIWORD(wParam) > 0 ? Fw::MouseWheelUp : Fw::MouseWheelDown; break; } - case WM_MOVE: - { - lastX = win32.x; - lastY = win32.y; - win32.x = LOWORD(lParam); - win32.y = HIWORD(lParam); + case WM_MOVE: { + m_lastWindowPos = m_pos; + m_pos.x = LOWORD(lParam); + m_pos.y = HIWORD(lParam); break; } - case WM_SIZE: - { - switch(wParam) - { - case SIZE_MAXIMIZED: - win32.x = lastX; - win32.y = lastY; - win32.maximized = true; - break; - case SIZE_RESTORED: - win32.maximized = false; - break; + case WM_SIZE: { + switch(wParam) { + case SIZE_MAXIMIZED: + m_pos = m_lastWindowPos; + m_maximized = true; + break; + case SIZE_RESTORED: + m_maximized = false; + break; } - win32.visible = !(wParam == SIZE_MINIMIZED); + m_visible = !(wParam == SIZE_MINIMIZED); - if(!win32.maximized) { - win32.width = LOWORD(lParam); - win32.height = HIWORD(lParam); + if(!m_maximized) { + m_size.setWidth(LOWORD(lParam)); + m_size.setHeight(HIWORD(lParam)); } - win32.listener->onResize(Size(LOWORD(lParam), HIWORD(lParam))); + m_onResize(m_size); break; } - default: - { + default: return DefWindowProc(hWnd, uMsg, wParam, lParam); - } } + + if(m_inputEvent.type != Fw::NoInputEvent) + m_onInputEvent(m_inputEvent); + return 0; } -void Platform::displayFatalError(const std::string& message) +void WIN32Window::swapBuffers() +{ + SwapBuffers(m_deviceContext); +} + +void WIN32Window::showMouse() +{ + ShowCursor(true); +} + +void WIN32Window::hideMouse() +{ + ShowCursor(false); +} + +void WIN32Window::setTitle(const std::string& title) +{ + SetWindowTextA(m_window, title.c_str()); +} + +void WIN32Window::setMinimumSize(const Size& minimumSize) { - MessageBoxA(NULL, message.c_str(), "Fatal Error", MB_OK | MB_ICONERROR); + //TODO +} + +void WIN32Window::setFullscreen(bool fullscreen) +{ + //TODO +} + +void WIN32Window::setVerticalSync(bool enable) +{ + typedef int (*glSwapIntervalProc)(int); + glSwapIntervalProc glSwapInterval = NULL; + + if(isExtensionSupported("WGL_EXT_swap_control")) + glSwapInterval = (glSwapIntervalProc)getExtensionProcAddress("wglSwapIntervalEXT"); + + if(glSwapInterval) + glSwapInterval(enable ? 1 : 0); +} + +void WIN32Window::setIcon(const std::string& pngIcon) +{ + apng_data apng; + std::stringstream fin; + g_resources.loadFile(pngIcon, fin); + if(load_apng(fin, &apng) == 0) { + if(apng.bpp != 4) { + logError("could not set app icon, icon image must have 4 channels"); + free_apng(&apng); + } + + int n = apng.width * apng.height; + std::vector iconData(n); + for(int i=0; i < n;++i) { + uint8 *pixel = (uint8*)&iconData[i]; + pixel[2] = *(apng.pdata + (i * 4) + 0); + pixel[1] = *(apng.pdata + (i * 4) + 1); + pixel[0] = *(apng.pdata + (i * 4) + 2); + pixel[3] = *(apng.pdata + (i * 4) + 3); + } + + HBITMAP hbmColor = CreateBitmap(apng.width, apng.height, 1, 32, &iconData[0]); + HBITMAP hbmMask = CreateCompatibleBitmap(GetDC(NULL), apng.width, apng.height); + + ICONINFO ii; + ii.fIcon = TRUE; + ii.hbmColor = hbmColor; + ii.hbmMask = hbmMask; + ii.xHotspot = 0; + ii.yHotspot = 0; + + HICON icon = CreateIconIndirect(&ii); + DeleteObject(hbmMask); + DeleteObject(hbmColor); + + SendMessage(m_window, WM_SETICON, ICON_SMALL, (LPARAM)icon); + SendMessage(m_window, WM_SETICON, ICON_BIG, (LPARAM)icon); + + free_apng(&apng); + } else + logError("could not load app icon"); +} + +void WIN32Window::setClipboardText(const std::string& text) +{ + m_clipboardText = text; + if(OpenClipboard(NULL)) { + EmptyClipboard(); + SetClipboardData(CF_TEXT, (void*)&m_clipboardText[0]); + CloseClipboard(); + } +} + +Size WIN32Window::getDisplaySize() +{ + return Size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN)); +} + +std::string WIN32Window::getClipboardText() +{ + std::string text; + if(OpenClipboard(NULL)) { + text = (const char*)GetClipboardData(CF_TEXT); + CloseClipboard(); + } + return text; } -#endif diff --git a/src/framework/platform/win32window.h b/src/framework/platform/win32window.h index 366e3512..a843c7e6 100644 --- a/src/framework/platform/win32window.h +++ b/src/framework/platform/win32window.h @@ -25,9 +25,61 @@ #include "platformwindow.h" +#include + +struct WindowProcProxy; + class WIN32Window : public PlatformWindow { - //TODO + void internalCreateWindow(); + void internalRegisterWindowClass(); + + void internalChooseGLVisual(); + void internalCreateGLContext(); + + void *getExtensionProcAddress(const char *ext); + bool isExtensionSupported(const char *ext); + + LRESULT windowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + friend class WindowProcProxy; + +public: + WIN32Window(); + + void init(); + void terminate(); + + void move(const Point& pos); + void resize(const Size& size); + void show(); + void hide(); + void maximize(); + void poll(); + void swapBuffers(); + void showMouse(); + void hideMouse(); + + void setTitle(const std::string& title); + void setMinimumSize(const Size& minimumSize); + void setFullscreen(bool fullscreen); + void setVerticalSync(bool enable); + void setIcon(const std::string& iconFile); + void setClipboardText(const std::string& text); + + Size getDisplaySize(); + std::string getClipboardText(); + + bool isMaximized() { return m_maximized; } + +private: + HWND m_window; + HINSTANCE m_instance; + HDC m_deviceContext; + HGLRC m_glContext; + bool m_maximized; + Point m_lastWindowPos; + std::string m_clipboardText; + std::map m_keyMap; }; #endif diff --git a/src/framework/platform/x11window.cpp b/src/framework/platform/x11window.cpp index 467a3da1..ddd71d2f 100644 --- a/src/framework/platform/x11window.cpp +++ b/src/framework/platform/x11window.cpp @@ -26,9 +26,25 @@ X11Window::X11Window() { - m_cursor = None; + m_display = 0; m_visual = 0; + m_window = 0; + m_rootWindow = 0; m_colormap = 0; + m_cursor = 0; + m_xim = 0; + m_xic = 0; + m_screen = 0; + m_wmDelete = 0; + +#ifndef OPENGL_ES2 + m_glxContext = 0; +#else + m_eglConfig = 0; + m_eglContext = 0; + m_eglDisplay = 0; + m_eglSurface = 0; +#endif m_keyMap[XK_Escape] = Fw::KeyEscape; m_keyMap[XK_Tab] = Fw::KeyTab; @@ -193,23 +209,37 @@ void X11Window::init() void X11Window::terminate() { - XDestroyWindow(m_display, m_window); + if(m_window) { + XDestroyWindow(m_display, m_window); + m_window = 0; + } - if(m_colormap) + if(m_colormap) { XFreeColormap(m_display, m_colormap); + m_colormap = 0; + } internalDestroyGLContext(); - if(m_visual) + if(m_visual) { XFree(m_visual); + m_visual = 0; + } - if(m_xic) + if(m_xic) { XDestroyIC(m_xic); + m_xic = 0; + } - if(m_xim) + if(m_xim) { XCloseIM(m_xim); + m_xim = 0; + } - XCloseDisplay(m_display); + if(m_display) { + XCloseDisplay(m_display); + m_display = 0; + } m_visible = false; } @@ -380,12 +410,24 @@ void X11Window::internalCreateGLContext() void X11Window::internalDestroyGLContext() { #ifndef OPENGL_ES2 - glXMakeCurrent(m_display, None, NULL); - glXDestroyContext(m_display, m_glxContext); + if(m_glxContext) { + glXMakeCurrent(m_display, None, NULL); + glXDestroyContext(m_display, m_glxContext); + m_glxContext = 0; + } #else - eglDestroyContext(m_eglDisplay, m_eglContext); - eglDestroySurface(m_eglDisplay, m_eglSurface); - eglTerminate(m_eglDisplay); + if(m_eglDisplay) { + if(m_eglContext) { + eglDestroyContext(m_eglDisplay, m_eglContext); + m_eglContext = 0; + } + if(m_eglSurface) + eglDestroySurface(m_eglDisplay, m_eglSurface); + m_eglSurface = 0; + } + eglTerminate(m_eglDisplay); + m_eglDisplay = 0; + } #endif } diff --git a/src/otclient/core/map.cpp b/src/otclient/core/map.cpp index 2a6cc2fd..34ef385f 100644 --- a/src/otclient/core/map.cpp +++ b/src/otclient/core/map.cpp @@ -27,11 +27,13 @@ #include "item.h" #include "missile.h" #include "statictext.h" + #include #include #include #include #include + Map g_map; Map::Map() @@ -39,7 +41,6 @@ Map::Map() setVisibleSize(Size(MAP_VISIBLE_WIDTH, MAP_VISIBLE_HEIGHT)); } -PainterShaderProgramPtr program; void Map::draw(const Rect& rect) { if(!m_framebuffer) { @@ -47,10 +48,10 @@ void Map::draw(const Rect& rect) m_framebuffer = FrameBufferPtr(new FrameBuffer(fboSize)); - program = PainterShaderProgramPtr(new PainterShaderProgram); - program->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); - program->addShaderFromSourceFile(Shader::Fragment, "/game_shaders/map.frag"); - assert(program->link()); + m_shaderProgram = PainterShaderProgramPtr(new PainterShaderProgram); + m_shaderProgram->addShaderFromSourceCode(Shader::Vertex, glslMainWithTexCoordsVertexShader + glslPositionOnlyVertexShader); + m_shaderProgram->addShaderFromSourceFile(Shader::Fragment, "/game_shaders/map.frag"); + assert(m_shaderProgram->link()); } g_painter.setColor(Fw::white); @@ -95,7 +96,7 @@ void Map::draw(const Rect& rect) m_framebuffer->release(); - g_painter.setCustomProgram(program); + g_painter.setCustomProgram(m_shaderProgram); g_painter.setColor(Fw::white); m_framebuffer->draw(rect); g_painter.releaseCustomProgram(); diff --git a/src/otclient/core/map.h b/src/otclient/core/map.h index 8a3269dc..32c707e6 100644 --- a/src/otclient/core/map.h +++ b/src/otclient/core/map.h @@ -87,6 +87,7 @@ private: Point m_centralOffset, m_drawOffset; FrameBufferPtr m_framebuffer; + PainterShaderProgramPtr m_shaderProgram; }; extern Map g_map;