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