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