1 /*!
2 @file
3 @author Albert Semenov
4 @date 05/2009
5 */
6
7
8 #include "Precompiled.h"
9 #include <d3dx9.h>
10 #include "BaseManager.h"
11 #include <MyGUI_DirectXPlatform.h>
12
13 #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
14 # include <windows.h>
15 # include <winuser.h>
16 #endif
17
18 // имя класса окна
19 const char* WND_CLASS_NAME = "MyGUI_Demo_window";
20
DXWndProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam)21 LRESULT CALLBACK DXWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
22 {
23 switch (uMsg)
24 {
25 case WM_CREATE:
26 {
27 SetWindowLongPtr(hWnd, GWLP_USERDATA, (LONG_PTR)((LPCREATESTRUCT)lParam)->lpCreateParams);
28 break;
29 }
30
31 case WM_SIZE:
32 {
33 if (wParam != SIZE_MINIMIZED)
34 {
35 base::BaseManager* baseManager = (base::BaseManager*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
36 if (baseManager)
37 baseManager->_windowResized();
38 }
39 break;
40 }
41
42 case WM_CLOSE:
43 {
44 base::BaseManager* baseManager = (base::BaseManager*)GetWindowLongPtr(hWnd, GWLP_USERDATA);
45 if (baseManager)
46 baseManager->quit();
47 }
48
49 case WM_DESTROY:
50 {
51 PostQuitMessage(0);
52 break;
53 }
54
55 default:
56 {
57 return DefWindowProc(hWnd, uMsg, wParam, lParam);
58 }
59 }
60 return 0;
61 }
62
63 namespace base
64 {
65
66 D3DPRESENT_PARAMETERS mD3dpp;
67
BaseManager()68 BaseManager::BaseManager() :
69 mGUI(nullptr),
70 mPlatform(nullptr),
71 hWnd(0),
72 mD3d(nullptr),
73 mDevice(nullptr),
74 hInstance(nullptr),
75 mExit(false),
76 mResourceFileName("MyGUI_Core.xml"),
77 mIsDeviceLost(false)
78 {
79 }
80
_windowResized()81 void BaseManager::_windowResized()
82 {
83 RECT rect = { 0, 0, 0, 0 };
84 GetClientRect(hWnd, &rect);
85 int width = rect.right - rect.left;
86 int height = rect.bottom - rect.top;
87
88 resizeRender(width, height);
89
90 if (mPlatform)
91 MyGUI::RenderManager::getInstance().setViewSize(width, height);
92
93 setInputViewSize(width, height);
94 }
95
create(int _width,int _height)96 bool BaseManager::create(int _width, int _height)
97 {
98 const unsigned int width = _width;
99 const unsigned int height = _height;
100 bool windowed = true;
101
102 // регистрируем класс окна
103 WNDCLASS wc =
104 {
105 0, (WNDPROC)DXWndProc, 0, 0, GetModuleHandle(nullptr), LoadIcon(nullptr, MAKEINTRESOURCE(1001)),
106 LoadCursor(nullptr, IDC_ARROW), (HBRUSH)GetStockObject(BLACK_BRUSH), nullptr, TEXT(WND_CLASS_NAME),
107 };
108 RegisterClass(&wc);
109
110 // создаем главное окно
111 hWnd = CreateWindow(wc.lpszClassName, TEXT("Direct3D9 Render Window"), WS_POPUP,
112 0, 0, 0, 0, GetDesktopWindow(), nullptr, wc.hInstance, this);
113 if (!hWnd)
114 {
115 //OutException("fatal error!", "failed create window");
116 return false;
117 }
118
119 #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
120 char buf[MAX_PATH];
121 ::GetModuleFileNameA(0, (LPCH)&buf, MAX_PATH);
122 HINSTANCE instance = ::GetModuleHandleA(buf);
123 HICON hIconSmall = static_cast<HICON>(LoadImage(instance, MAKEINTRESOURCE(1001), IMAGE_ICON, 32, 32, LR_DEFAULTSIZE));
124 HICON hIconBig = static_cast<HICON>(LoadImage(instance, MAKEINTRESOURCE(1001), IMAGE_ICON, 256, 256, LR_DEFAULTSIZE));
125 if (hIconSmall)
126 ::SendMessageA(hWnd, WM_SETICON, 0, (LPARAM)hIconSmall);
127 if (hIconBig)
128 ::SendMessageA(hWnd, WM_SETICON, 1, (LPARAM)hIconBig);
129 #endif
130
131 hInstance = wc.hInstance;
132
133 windowAdjustSettings(hWnd, width, height, !windowed);
134
135 createRender(width, height, windowed);
136
137 createGui();
138
139 createInput((size_t)hWnd);
140
141 createPointerManager((size_t)hWnd);
142
143 // this needs to be called before createScene() since some demos require
144 // screen size to properly position the widgets
145 _windowResized();
146
147 createScene();
148
149 return true;
150 }
151
run()152 void BaseManager::run()
153 {
154 MSG msg;
155 while (true)
156 {
157 while (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
158 {
159 TranslateMessage(&msg);
160 DispatchMessage(&msg);
161 }
162 if (mExit)
163 break;
164 else if (msg.message == WM_QUIT)
165 break;
166
167 captureInput();
168 drawOneFrame();
169
170 if (GetActiveWindow() != hWnd)
171 ::Sleep(50);
172 }
173 }
174
destroy()175 void BaseManager::destroy()
176 {
177 destroyScene();
178
179 destroyPointerManager();
180
181 destroyInput();
182
183 destroyGui();
184
185 destroyRender();
186
187 if (hWnd)
188 {
189 DestroyWindow(hWnd);
190 hWnd = 0;
191 }
192
193 UnregisterClass(WND_CLASS_NAME, hInstance);
194 }
195
setupResources()196 void BaseManager::setupResources()
197 {
198 MyGUI::xml::Document doc;
199
200 if (!doc.open(std::string("resources.xml")))
201 doc.getLastError();
202
203 MyGUI::xml::ElementPtr root = doc.getRoot();
204 if (root == nullptr || root->getName() != "Paths")
205 return;
206
207 MyGUI::xml::ElementEnumerator node = root->getElementEnumerator();
208 while (node.next())
209 {
210 if (node->getName() == "Path")
211 {
212 if (node->findAttribute("root") != "")
213 {
214 bool rootAttribute = MyGUI::utility::parseBool(node->findAttribute("root"));
215 if (rootAttribute)
216 mRootMedia = node->getContent();
217 }
218 addResourceLocation(node->getContent(), false);
219 }
220 }
221
222 addResourceLocation(getRootMedia() + "/Common/Base");
223 }
224
createGui()225 void BaseManager::createGui()
226 {
227 mPlatform = new MyGUI::DirectXPlatform();
228 mPlatform->initialise(mDevice);
229
230 setupResources();
231
232 mGUI = new MyGUI::Gui();
233 mGUI->initialise(mResourceFileName);
234 }
235
destroyGui()236 void BaseManager::destroyGui()
237 {
238 if (mGUI)
239 {
240 mGUI->shutdown();
241 delete mGUI;
242 mGUI = nullptr;
243 }
244
245 if (mPlatform)
246 {
247 mPlatform->shutdown();
248 delete mPlatform;
249 mPlatform = nullptr;
250 }
251 }
252
getWindowHandle()253 size_t BaseManager::getWindowHandle()
254 {
255 return (size_t)hWnd;
256 }
257
setWindowMaximized(bool _value)258 void BaseManager::setWindowMaximized(bool _value)
259 {
260 #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
261 if (_value)
262 {
263 size_t handle = getWindowHandle();
264 ::ShowWindow((HWND)handle, SW_SHOWMAXIMIZED);
265 }
266 #endif
267 }
268
getWindowMaximized()269 bool BaseManager::getWindowMaximized()
270 {
271 bool result = false;
272 #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
273 size_t handle = getWindowHandle();
274 result = ::IsZoomed((HWND)handle) != 0;
275 #endif
276 return result;
277 }
278
setWindowCoord(const MyGUI::IntCoord & _value)279 void BaseManager::setWindowCoord(const MyGUI::IntCoord& _value)
280 {
281 #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
282 if (_value.empty())
283 return;
284
285 MyGUI::IntCoord coord = _value;
286 if (coord.left < 0)
287 coord.left = 0;
288 if (coord.top < 0)
289 coord.top = 0;
290 if (coord.width < 640)
291 coord.width = 640;
292 if (coord.height < 480)
293 coord.height = 480;
294 if (coord.width > GetSystemMetrics(SM_CXSCREEN))
295 coord.width = GetSystemMetrics(SM_CXSCREEN);
296 if (coord.height > GetSystemMetrics(SM_CYSCREEN))
297 coord.height = GetSystemMetrics(SM_CYSCREEN);
298 if (coord.right() > GetSystemMetrics(SM_CXSCREEN))
299 coord.left = GetSystemMetrics(SM_CXSCREEN) - coord.width;
300 if (coord.bottom() > GetSystemMetrics(SM_CYSCREEN))
301 coord.top = GetSystemMetrics(SM_CYSCREEN) - coord.height;
302
303 size_t handle = getWindowHandle();
304 ::MoveWindow((HWND)handle, coord.left, coord.top, coord.width, coord.height, true);
305 #endif
306 }
307
getWindowCoord()308 MyGUI::IntCoord BaseManager::getWindowCoord()
309 {
310 MyGUI::IntCoord result;
311 #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
312 size_t handle = getWindowHandle();
313 ::RECT rect;
314 ::GetWindowRect((HWND)handle, &rect);
315 result.left = rect.left;
316 result.top = rect.top;
317 result.width = rect.right - rect.left;
318 result.height = rect.bottom - rect.top;
319 #endif
320 return result;
321 }
322
setWindowCaption(const std::wstring & _text)323 void BaseManager::setWindowCaption(const std::wstring& _text)
324 {
325 SetWindowTextW(hWnd, _text.c_str());
326 }
327
prepare()328 void BaseManager::prepare()
329 {
330 }
331
addResourceLocation(const std::string & _name,bool _recursive)332 void BaseManager::addResourceLocation(const std::string& _name, bool _recursive)
333 {
334 mPlatform->getDataManagerPtr()->addResourceLocation(_name, _recursive);
335 }
336
windowAdjustSettings(HWND hWnd,int width,int height,bool fullScreen)337 void BaseManager::windowAdjustSettings(HWND hWnd, int width, int height, bool fullScreen)
338 {
339 // стиль окна
340 HWND hwndAfter = 0;
341 unsigned long style = 0;
342 unsigned long style_ex = 0;
343
344 RECT rc = { 0, 0, width, height };
345
346 if (fullScreen)
347 {
348 style = WS_POPUP | WS_VISIBLE;
349 style_ex = GetWindowLongPtr(hWnd, GWL_EXSTYLE) | (WS_EX_TOPMOST);
350 hwndAfter = HWND_TOPMOST;
351 }
352 else
353 {
354 style = WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SYSMENU | WS_THICKFRAME;
355 style_ex = GetWindowLongPtr(hWnd, GWL_EXSTYLE) & (~WS_EX_TOPMOST);
356 hwndAfter = HWND_NOTOPMOST;
357 AdjustWindowRect(&rc, style, false);
358 }
359
360 SetWindowLongPtr(hWnd, GWL_STYLE, style);
361 SetWindowLongPtr(hWnd, GWL_EXSTYLE, style_ex);
362
363 int desk_width = GetSystemMetrics(SM_CXSCREEN);
364 int desk_height = GetSystemMetrics(SM_CYSCREEN);
365
366 int w = rc.right - rc.left;
367 int h = rc.bottom - rc.top;
368 int x = fullScreen ? 0 : (desk_width - w) / 2;
369 int y = fullScreen ? 0 : (desk_height - h) / 2;
370
371 SetWindowPos(hWnd, hwndAfter, x, y, w, h, SWP_FRAMECHANGED | SWP_SHOWWINDOW);
372 }
373
injectMouseMove(int _absx,int _absy,int _absz)374 void BaseManager::injectMouseMove(int _absx, int _absy, int _absz)
375 {
376 if (!mGUI)
377 return;
378
379 MyGUI::InputManager::getInstance().injectMouseMove(_absx, _absy, _absz);
380 }
381
injectMousePress(int _absx,int _absy,MyGUI::MouseButton _id)382 void BaseManager::injectMousePress(int _absx, int _absy, MyGUI::MouseButton _id)
383 {
384 if (!mGUI)
385 return;
386
387 MyGUI::InputManager::getInstance().injectMousePress(_absx, _absy, _id);
388 }
389
injectMouseRelease(int _absx,int _absy,MyGUI::MouseButton _id)390 void BaseManager::injectMouseRelease(int _absx, int _absy, MyGUI::MouseButton _id)
391 {
392 if (!mGUI)
393 return;
394
395 MyGUI::InputManager::getInstance().injectMouseRelease(_absx, _absy, _id);
396 }
397
injectKeyPress(MyGUI::KeyCode _key,MyGUI::Char _text)398 void BaseManager::injectKeyPress(MyGUI::KeyCode _key, MyGUI::Char _text)
399 {
400 if (!mGUI)
401 return;
402
403 if (_key == MyGUI::KeyCode::Escape)
404 {
405 mExit = true;
406 return;
407 }
408
409 MyGUI::InputManager::getInstance().injectKeyPress(_key, _text);
410 }
411
injectKeyRelease(MyGUI::KeyCode _key)412 void BaseManager::injectKeyRelease(MyGUI::KeyCode _key)
413 {
414 if (!mGUI)
415 return;
416
417 MyGUI::InputManager::getInstance().injectKeyRelease(_key);
418 }
419
resizeRender(int _width,int _height)420 void BaseManager::resizeRender(int _width, int _height)
421 {
422 if (mDevice != nullptr)
423 {
424 if (mPlatform != nullptr)
425 mPlatform->getRenderManagerPtr()->deviceLost();
426
427 mD3dpp.BackBufferWidth = _width;
428 mD3dpp.BackBufferHeight = _height;
429 HRESULT hr = mDevice->Reset(&mD3dpp);
430
431 if (hr == D3DERR_INVALIDCALL)
432 {
433 MessageBox( nullptr, "Call to Reset() failed with D3DERR_INVALIDCALL! ",
434 "ERROR", MB_OK | MB_ICONEXCLAMATION );
435 }
436
437 if (mPlatform != nullptr)
438 mPlatform->getRenderManagerPtr()->deviceRestore();
439 }
440 }
441
createRender(int _width,int _height,bool _windowed)442 bool BaseManager::createRender(int _width, int _height, bool _windowed)
443 {
444 // инициализация direct3d
445 mD3d = Direct3DCreate9(D3D_SDK_VERSION);
446
447 D3DDISPLAYMODE d3ddm;
448 mD3d->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &d3ddm);
449
450 memset(&mD3dpp, 0, sizeof(mD3dpp));
451 mD3dpp.AutoDepthStencilFormat = D3DFMT_D16;
452 mD3dpp.EnableAutoDepthStencil = TRUE;
453 mD3dpp.BackBufferCount = 1;
454 mD3dpp.BackBufferFormat = d3ddm.Format;
455 mD3dpp.BackBufferWidth = _width;
456 mD3dpp.BackBufferHeight = _height;
457 mD3dpp.hDeviceWindow = hWnd;
458 mD3dpp.SwapEffect = D3DSWAPEFFECT_FLIP;
459 mD3dpp.Windowed = _windowed;
460
461 if (FAILED(mD3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
462 D3DCREATE_HARDWARE_VERTEXPROCESSING, &mD3dpp, &mDevice)))
463 {
464 //OutException("fatal error!", "failed create d3d9 mDevice");
465 return false;
466 }
467 return true;
468 }
469
470 bool mIsDeviceLost = false;
471
drawOneFrame()472 void BaseManager::drawOneFrame()
473 {
474 if (mIsDeviceLost)
475 {
476 Sleep( 100 );
477
478 HRESULT hr;
479 if (FAILED(hr = mDevice->TestCooperativeLevel()))
480 {
481 if (hr == D3DERR_DEVICELOST)
482 return;
483
484 if (hr == D3DERR_DEVICENOTRESET)
485 {
486 if (mPlatform != nullptr)
487 mPlatform->getRenderManagerPtr()->deviceLost();
488
489 hr = mDevice->Reset( &mD3dpp );
490
491 if (FAILED(hr))
492 return;
493
494 if (mPlatform != nullptr)
495 mPlatform->getRenderManagerPtr()->deviceRestore();
496 }
497
498 return;
499 }
500
501 mIsDeviceLost = false;
502 }
503
504 if (SUCCEEDED(mDevice->BeginScene()))
505 {
506 mDevice->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x001589FF, 1.0f, 0);
507 mPlatform->getRenderManagerPtr()->drawOneFrame();
508 mDevice->EndScene();
509 }
510
511 if (mDevice->Present(nullptr, nullptr, 0, nullptr) == D3DERR_DEVICELOST)
512 mIsDeviceLost = true;
513 }
514
destroyRender()515 void BaseManager::destroyRender()
516 {
517 if (mDevice)
518 {
519 mDevice->Release();
520 mDevice = 0;
521 }
522 if (mD3d)
523 {
524 mD3d->Release();
525 mD3d = 0;
526 }
527 }
528
quit()529 void BaseManager::quit()
530 {
531 mExit = true;
532 }
533
getRootMedia()534 const std::string& BaseManager::getRootMedia()
535 {
536 return mRootMedia;
537 }
538
setResourceFilename(const std::string & _flename)539 void BaseManager::setResourceFilename(const std::string& _flename)
540 {
541 mResourceFileName = _flename;
542 }
543
544 } // namespace base
545