NLS Engine  v0.1
The Next Logical Step in game engine design.
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Defines
win32.cpp
Go to the documentation of this file.
00001 
00009 #include "win32.h"
00010 #include <shlobj.h>
00011 
00012 // Standard Includes
00013 
00014 // Library Includes
00015 #include "d3dx9.h"
00016 
00017 // Local Includes
00018 #include "../sharedbase/MessageRouter.h"
00019 #include "../sharedbase/PropertyMap.h"
00020 #include "../sharedbase/Envelope.h"
00021 #include "../sharedbase/EventLogger.h"
00022 
00023 // Static class member initialization
00024 
00025 void win32::Make(PropertyMap* gprops, MessageRouter* msgrouter) {
00026   if (!OSInterface::HasOS()) {
00027     OSInterface::SetOS(OSInterfaceSPTR(new win32(gprops, msgrouter)));
00028   }
00029 }
00030 
00031 // Class methods in the order they are defined within the class header
00032 
00033 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00034 boost::any win32::CreateGUIWindow( int width, int height, std::string title, WINDOW_FLAGS flags ) {
00035   ShowWindow( GetConsoleWindow(), SW_HIDE ); // We don't need to show the console
00036 
00037   HWND hwnd;
00038   WNDCLASSEX wc = { 0 };
00039   wc.lpszClassName = "GameWindow";
00040   wc.cbSize = sizeof(wc);
00041   wc.style = CS_HREDRAW | CS_VREDRAW;
00042   wc.lpfnWndProc = win32::Proc;
00043   wc.hInstance = GetModuleHandle(NULL);
00044   wc.hbrBackground = (HBRUSH)(CTLCOLOR_DLG + 1);
00045   wc.hCursor = LoadCursor(NULL, IDC_ARROW);
00046   wc.cbWndExtra = sizeof(long*);
00047 
00048   RegisterClassEx(&wc);
00049 
00050   hwnd = CreateWindowEx(NULL, wc.lpszClassName, title.c_str(), WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | /*WS_THICKFRAME | WS_MAXIMIZEBOX |*/ WS_MINIMIZEBOX | CS_HREDRAW, 10, 10, width, height, NULL, NULL, wc.hInstance, NULL);
00051   if (!hwnd) {
00052     return 0;
00053   }
00054   UpdateWindow(hwnd);
00055   
00056   if (flags & WINDOW_INNER_SIZE) {
00057     RECT rect;
00058     rect.top = 0;
00059     rect.bottom = height;
00060     rect.left = 0;
00061     rect.right = width;
00062     AdjustWindowRectEx(&rect, WS_CAPTION | WS_SYSMENU | WS_THICKFRAME| WS_MINIMIZEBOX | WS_MAXIMIZEBOX, false, 0);
00063     MoveWindow(hwnd, 0, 0, rect.right + abs(rect.left), rect.bottom + abs(rect.top), true);
00064   }
00065   
00066   ShowWindow(hwnd, SW_NORMAL);
00067 
00068   SetWindowLongPtr(hwnd, GWLP_USERDATA, reinterpret_cast<long>(this->msgrouter));
00069 
00070   this->handle = hwnd;
00071 
00072   std::shared_ptr<Subscriber> squit(new Subscriber(boost::bind(&win32::Quit, this, _1)));
00073   this->msgrouter->Subscribe(CORE_MESSAGE::QUIT, squit);
00074 
00075   return hwnd;
00076 }
00077 
00078 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00079 void win32::ShowInfo(std::string text, std::string caption) {
00080   MessageBox(nullptr, text.c_str(), caption.c_str(), MB_OK | MB_ICONINFORMATION);
00081 }
00082 
00083 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00084 void win32::ShowWarning(std::string text, std::string caption) {
00085   MessageBox(nullptr, text.c_str(), caption.c_str(), MB_OK | MB_ICONWARNING);
00086 }
00087 
00088 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00089 void win32::ShowError(std::string text, std::string caption) {
00090   MessageBox(nullptr, text.c_str(), caption.c_str(), MB_OK | MB_ICONERROR);
00091 }
00092 
00093 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00094 void win32::RouteMessages() {
00095   MSG msg;
00096   while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0) {
00097     if (msg.message == WM_QUIT) {
00098       break;
00099     }
00100     TranslateMessage(&msg);
00101     DispatchMessage(&msg);
00102   }
00103   Sleep(1);
00104 }
00105 
00106 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00107 D3DXVECTOR2 GetMousePos(HWND hwnd, LPARAM lParam) {
00108   RECT client_rect; // client area rectangle 
00109   POINT client_UL; // client upper left corner 
00110   POINT client_LR; // client lower right corner
00111   POINTS client_mouse; // mouse position in client area
00112   
00113   D3DXVECTOR2 mouse_pos;
00114   
00115   // Capture mouse input.
00116   //SetCapture(hwnd);
00117   
00118   // Retrieve the screen coordinates of the client area, and convert them into client coordinates.
00119   GetClientRect(hwnd, &client_rect);
00120   client_UL.x = client_rect.left;
00121   client_UL.y = client_rect.top;
00122   
00123   // Add one to the right and bottom sides, because the coordinates retrieved by GetClientRect do not include the far left and lowermost pixels.
00124   client_LR.x = client_rect.right + 1; 
00125   client_LR.y = client_rect.bottom + 1; 
00126   ClientToScreen(hwnd, &client_UL); 
00127   ClientToScreen(hwnd, &client_LR);
00128   
00129   // Copy the client coordinates of the client area to the client_rect structure.
00130   // Confine the mouse cursor to the client area by passing the client_rect structure to the ClipCursor function. 
00131   //SetRect(&client_rect, client_UL.x, client_UL.y, client_LR.x, client_LR.y); 
00132   //ClipCursor(&client_rect);
00133   
00134   client_mouse = MAKEPOINTS(lParam);
00135   
00136   // Convert the mouse position into the correct coordinate system:
00137   // <0.0, 0.0> is at the upper-left of the client area,
00138   // <1.0, -1.0/aspect_ratio> is the lower-right of the client area.
00139   float client_width = float(client_LR.x - client_UL.x);
00140   mouse_pos.x = float(client_mouse.x) / client_width;
00141   mouse_pos.y = float(-client_mouse.y) / client_width; // Yes, the divisor here is correct: the Y is divided by the client width - this matches the Graphics coordinate system.
00142   
00143   return mouse_pos;
00144 }
00145 
00146 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00147 LRESULT CALLBACK win32::Proc(HWND hwnd, UINT msg, WPARAM w, LPARAM l) {
00148   bool def = true; // Whether or not to call the default window procedure
00149   
00150   
00151   switch (msg) {
00152     case WM_KEYDOWN:
00153     case WM_KEYUP:
00154     case WM_KEYLAST:
00155     {
00156       EnvelopeSPTR e(new Envelope);
00157       e->msgid = 9002;
00158       e->AddData(msg);
00159       e->AddData(w);
00160       e->AddData(l);
00161       reinterpret_cast<MessageRouter*>(GetWindowLongPtr(hwnd, GWLP_USERDATA))->SendSP(e);
00162     }
00163     break;
00164     case WM_LBUTTONUP:
00165     case WM_MBUTTONUP:
00166     case WM_RBUTTONUP:
00167     case WM_XBUTTONUP:
00168     case WM_LBUTTONDOWN:
00169     case WM_MBUTTONDOWN:
00170     case WM_RBUTTONDOWN:
00171     case WM_XBUTTONDOWN:
00172     {
00173       D3DXVECTOR2 mouse_pos = GetMousePos(hwnd, l);
00174       
00175       EnvelopeSPTR e(new Envelope);
00176       e->msgid = 9003;
00177       e->AddData(msg);
00178       e->AddData(w);
00179       e->AddData(mouse_pos.x);
00180       e->AddData(mouse_pos.y);
00181       reinterpret_cast<MessageRouter*>(GetWindowLongPtr(hwnd, GWLP_USERDATA))->SendSP(e);
00182     }
00183     break;
00184     case WM_MOUSEMOVE:
00185     {
00186       D3DXVECTOR2 mouse_pos = GetMousePos(hwnd, l);
00187       
00188       EnvelopeSPTR e(new Envelope);
00189       e->msgid = 9010;
00190       e->AddData(msg);
00191       e->AddData(w);
00192       e->AddData(mouse_pos.x);
00193       e->AddData(mouse_pos.y);
00194       reinterpret_cast<MessageRouter*>(GetWindowLongPtr(hwnd, GWLP_USERDATA))->SendSP(e);
00195     }
00196     break;
00197     case WM_MOUSEWHEEL:
00198     case WM_MOUSEHWHEEL:
00199     {
00200       D3DXVECTOR2 mouse_pos = GetMousePos(hwnd, l);
00201       
00202       EnvelopeSPTR e(new Envelope);
00203       e->msgid = 9011;
00204       e->AddData(msg);
00205       e->AddData(w);
00206       e->AddData(mouse_pos.x);
00207       e->AddData(mouse_pos.y);
00208       reinterpret_cast<MessageRouter*>(GetWindowLongPtr(hwnd, GWLP_USERDATA))->SendSP(e);
00209     }
00210     break;
00211     case WM_CREATE:
00212     break;
00213     case WM_DESTROY:
00214     case WM_CLOSE:
00215     {
00216       def = false;
00217       
00218       EnvelopeSPTR e(new Envelope);
00219       e->msgid = 9001;
00220       e->AddData(msg);
00221       e->AddData(w);
00222       e->AddData(l);
00223       reinterpret_cast<MessageRouter*>(GetWindowLongPtr(hwnd, GWLP_USERDATA))->SendSP(e);
00224     }
00225     break;
00226     default:
00227     break;
00228   }
00229   
00230   return (def ? DefWindowProc(hwnd, msg, w, l) : 0);
00231 }
00232 
00233 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00234 std::string win32::GetPath(DIRS::TYPE dir_id) {
00235   int csidl;
00236   
00237   switch (dir_id) {
00238     case DIRS::USER:
00239       csidl = CSIDL_APPDATA;
00240     break;
00241     case DIRS::DOCUMENTS:
00242       csidl = CSIDL_MYDOCUMENTS;
00243     break;
00244     case DIRS::PICTURES:
00245       csidl = CSIDL_MYPICTURES;
00246     break;
00247     case DIRS::MUSIC:
00248       csidl = CSIDL_MYMUSIC;
00249     break;
00250     case DIRS::VIDEO:
00251       csidl = CSIDL_MYVIDEO;
00252     break;
00253     case DIRS::DESKTOP:
00254       csidl = CSIDL_DESKTOPDIRECTORY;
00255     break;
00256     default:
00257       return "";
00258     break;
00259   }
00260   
00261   char path[MAX_PATH];
00262   if (SUCCEEDED(SHGetFolderPath(this->handle, csidl, nullptr, 0, path))) {
00263     return path;
00264   }
00265   else {
00266     return "";
00267   }
00268 }
00269 
00270 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00271 void win32::SetupTimer() {
00272   LARGE_INTEGER tps;
00273   QueryPerformanceFrequency(&tps);
00274   this->freq = 1.0f / (double)tps.QuadPart; // Determine the amount of counts per second
00275   QueryPerformanceCounter(&this->count); // Get the starting count
00276 }
00277 
00278 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00279 double win32::GetElapsedTime() {
00280   LARGE_INTEGER old = this->count;
00281   QueryPerformanceCounter(&this->count); // Get the current count.
00282   this->elapsed = (this->count.QuadPart - old.QuadPart) * this->freq; // Find the difference of the ticks and multiply it by the counts per second. Elapsed is measured in seconds.
00283   return this->elapsed;
00284 }
00285 
00286 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
00287 void win32::Quit(EnvelopeSPTR e) {
00288   DestroyWindow(this->handle);
00289 }