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