1 /*!
2 	@file
3 	@author		Albert Semenov
4 	@date		08/2008
5 */
6 
7 #include "Precompiled.h"
8 #include "BaseManager.h"
9 #include <MyGUI_OgrePlatform.h>
10 
11 #if (OGRE_VERSION >= ((1 << 16) | (10 << 8) | 0))
12 #include <OgreBitesConfigDialog.h>
13 #endif
14 
15 #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
16 #	include <windows.h>
17 #elif MYGUI_PLATFORM == MYGUI_PLATFORM_LINUX
18 #	include <X11/Xlib.h>
19 #	include <X11/Xutil.h>
20 #	include <X11/Xatom.h>
21 #endif
22 
23 namespace base
24 {
25 
26 #if MYGUI_PLATFORM == MYGUI_PLATFORM_APPLE
27 #include <CoreFoundation/CoreFoundation.h>
28 	// This function will locate the path to our application on OS X,
29 	// unlike windows you can not rely on the curent working directory
30 	// for locating your configuration files and resources.
macBundlePath()31 	std::string macBundlePath()
32 	{
33 		char path[1024];
34 		CFBundleRef mainBundle = CFBundleGetMainBundle();
35 		assert(mainBundle);
36 		CFURLRef mainBundleURL = CFBundleCopyBundleURL(mainBundle);
37 		assert(mainBundleURL);
38 		CFStringRef cfStringRef = CFURLCopyFileSystemPath( mainBundleURL, kCFURLPOSIXPathStyle);
39 		assert(cfStringRef);
40 		CFStringGetCString(cfStringRef, path, 1024, kCFStringEncodingASCII);
41 		CFRelease(mainBundleURL);
42 		CFRelease(cfStringRef);
43 		return std::string(path);
44 	}
45 #endif
46 
BaseManager()47 	BaseManager::BaseManager() :
48 		mGUI(nullptr),
49 		mPlatform(nullptr),
50 		mRoot(nullptr),
51 		mCamera(nullptr),
52 		mSceneManager(nullptr),
53 		mWindow(nullptr),
54 		mExit(false),
55 		mPluginCfgName("plugins.cfg"),
56 		mResourceXMLName("resources.xml"),
57 		mResourceFileName("MyGUI_Core.xml")
58 	{
59 		#if MYGUI_PLATFORM == MYGUI_PLATFORM_APPLE
60 			mResourcePath = macBundlePath() + "/Contents/Resources/";
61 		#else
62 			mResourcePath = "";
63 		#endif
64 	}
65 
create(int _width,int _height)66 	bool BaseManager::create(int _width, int _height)
67 	{
68 		Ogre::String pluginsPath;
69 
70 		#ifndef OGRE_STATIC_LIB
71 			pluginsPath = mResourcePath + mPluginCfgName;
72 		#endif
73 
74 		mRoot = new Ogre::Root(pluginsPath, mResourcePath + "ogre.cfg", mResourcePath + "Ogre.log");
75 
76 		setupResources();
77 
78 		// попробуем завестись на дефолтных
79 		if (!mRoot->restoreConfig())
80 		{
81 			// ничего не получилось, покажем диалог
82 			#if (OGRE_VERSION >= ((1 << 16) | (10 << 8) | 0))
83 			if (!mRoot->showConfigDialog(OgreBites::getNativeConfigDialog())) return false;
84 			#else
85 			if (!mRoot->showConfigDialog()) return false;
86 			#endif
87 		}
88 
89 		#if (OGRE_VERSION >= ((1 << 16) | (11 << 8) | 0)) && MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
90 		Ogre::NameValuePairList miscParams;
91 		mWindow = mRoot->initialise(false);
92 		miscParams["windowProc"] = Ogre::StringConverter::toString((size_t)Ogre::WindowEventUtilities::_WndProc);
93 		mWindow = Ogre::Root::getSingleton().createRenderWindow("MyGUI Demo", 800, 600, false, &miscParams);
94 		Ogre::WindowEventUtilities::_addRenderWindow(mWindow);
95 		#else
96 		mWindow = mRoot->initialise(true);
97 		#endif
98 
99 		// вытаскиваем дискриптор окна
100 		size_t handle = getWindowHandle();
101 
102 	#if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
103 		char buf[MAX_PATH];
104 		::GetModuleFileNameA(0, (LPCH)&buf, MAX_PATH);
105 		HINSTANCE instance = ::GetModuleHandleA(buf);
106 		HICON hIconSmall = static_cast<HICON>(LoadImage(instance, MAKEINTRESOURCE(1001), IMAGE_ICON, 32, 32, LR_DEFAULTSIZE));
107 		HICON hIconBig = static_cast<HICON>(LoadImage(instance, MAKEINTRESOURCE(1001), IMAGE_ICON, 256, 256, LR_DEFAULTSIZE));
108 		if (hIconSmall)
109 			::SendMessageA((HWND)handle, WM_SETICON, 0, (LPARAM)hIconSmall);
110 		if (hIconBig)
111 			::SendMessageA((HWND)handle, WM_SETICON, 1, (LPARAM)hIconBig);
112 	#endif
113 
114 		mSceneManager = mRoot->createSceneManager(Ogre::ST_GENERIC, "BaseSceneManager");
115 
116 		mCamera = mSceneManager->createCamera("BaseCamera");
117 		mCamera->setNearClipDistance(5);
118 		mCamera->setPosition(400, 400, 400);
119 		mCamera->lookAt(0, 150, 0);
120 
121 		// Create one viewport, entire window
122 		Ogre::Viewport* vp = mWindow->addViewport(mCamera);
123 		// Alter the camera aspect ratio to match the viewport
124 		mCamera->setAspectRatio((float)vp->getActualWidth() / (float)vp->getActualHeight());
125 
126 		// Set default mipmap level (NB some APIs ignore this)
127 		Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
128 
129 		mSceneManager->setAmbientLight(Ogre::ColourValue::White);
130 		Ogre::Light* light = mSceneManager->createLight("MainLight");
131 		light->setType(Ogre::Light::LT_DIRECTIONAL);
132 		Ogre::Vector3 vec(-0.3f, -0.3f, -0.3f);
133 		vec.normalise();
134 		light->setDirection(vec);
135 
136 		// Load resources
137 		Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
138 
139 		mRoot->addFrameListener(this);
140 		Ogre::WindowEventUtilities::addWindowEventListener(mWindow, this);
141 
142 		createGui();
143 
144 		createInput(handle);
145 
146 		createPointerManager(handle);
147 
148 		// this needs to be called before createScene() since some demos require
149 		// screen size to properly position the widgets
150 		windowResized(mWindow);
151 
152 		createScene();
153 
154 		return true;
155 	}
156 
run()157 	void BaseManager::run()
158 	{
159 		// инициализируем все рендер таргеты
160 		mRoot->getRenderSystem()->_initRenderTargets();
161 
162 		// крутимся бесконечно
163 		while (true)
164 		{
165 			Ogre::WindowEventUtilities::messagePump();
166 
167 			if (mWindow->isActive() == false)
168 			{
169 				mWindow->setActive(true);
170 #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
171 				::Sleep(50);
172 #endif
173 			}
174 			if (!mRoot->renderOneFrame())
175 				break;
176 
177 // выставляем слип, чтобы другие потоки не стопорились
178 #if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
179 			::Sleep(0);
180 #endif
181 
182 		};
183 	}
184 
destroy()185 	void BaseManager::destroy()
186 	{
187 		destroyScene();
188 
189 		destroyPointerManager();
190 
191 		destroyInput();
192 
193 		destroyGui();
194 
195 		// очищаем сцену
196 		if (mSceneManager)
197 		{
198 			mSceneManager->clearScene();
199 			mSceneManager->destroyAllCameras();
200 			mSceneManager = nullptr;
201 			mCamera = nullptr;
202 		}
203 
204 		if (mWindow)
205 		{
206 			mWindow->destroy();
207 			mWindow = nullptr;
208 		}
209 
210 		if (mRoot)
211 		{
212 			Ogre::RenderWindow* window = mRoot->getAutoCreatedWindow();
213 			if (window)
214 				window->removeAllViewports();
215 			delete mRoot;
216 			mRoot = nullptr;
217 		}
218 	}
219 
createGui()220 	void BaseManager::createGui()
221 	{
222 		mPlatform = new MyGUI::OgrePlatform();
223 		mPlatform->initialise(mWindow, mSceneManager, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME);
224 		mGUI = new MyGUI::Gui();
225 		mGUI->initialise(mResourceFileName);
226 	}
227 
destroyGui()228 	void BaseManager::destroyGui()
229 	{
230 		if (mGUI)
231 		{
232 			mGUI->shutdown();
233 			delete mGUI;
234 			mGUI = nullptr;
235 		}
236 
237 		if (mPlatform)
238 		{
239 			mPlatform->shutdown();
240 			delete mPlatform;
241 			mPlatform = nullptr;
242 		}
243 	}
244 
setWindowMaximized(bool _value)245     void BaseManager::setWindowMaximized(bool _value)
246 	{
247 	#if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
248 		if (_value)
249 		{
250 			size_t handle = getWindowHandle();
251 			::ShowWindow((HWND)handle, SW_SHOWMAXIMIZED);
252 		}
253 	#endif
254 	}
255 
getWindowMaximized()256     bool BaseManager::getWindowMaximized()
257 	{
258 		bool result = false;
259 	#if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
260 		size_t handle = getWindowHandle();
261 		result = ::IsZoomed((HWND)handle) != 0;
262 	#endif
263 		return result;
264 	}
265 
setWindowCoord(const MyGUI::IntCoord & _value)266 	void BaseManager::setWindowCoord(const MyGUI::IntCoord& _value)
267 	{
268 	#if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
269 		if (_value.empty())
270 			return;
271 
272 		MyGUI::IntCoord coord = _value;
273 		if (coord.left < 0)
274 			coord.left = 0;
275 		if (coord.top < 0)
276 			coord.top = 0;
277 		if (coord.width < 640)
278 			coord.width = 640;
279 		if (coord.height < 480)
280 			coord.height = 480;
281 		if (coord.width > GetSystemMetrics(SM_CXSCREEN))
282 			coord.width = GetSystemMetrics(SM_CXSCREEN);
283 		if (coord.height > GetSystemMetrics(SM_CYSCREEN))
284 			coord.height = GetSystemMetrics(SM_CYSCREEN);
285 		if (coord.right() > GetSystemMetrics(SM_CXSCREEN))
286 			coord.left = GetSystemMetrics(SM_CXSCREEN) - coord.width;
287 		if (coord.bottom() > GetSystemMetrics(SM_CYSCREEN))
288 			coord.top = GetSystemMetrics(SM_CYSCREEN) - coord.height;
289 
290 		size_t handle = getWindowHandle();
291 		::MoveWindow((HWND)handle, coord.left, coord.top, coord.width, coord.height, true);
292 	#endif
293 	}
294 
getWindowCoord()295 	MyGUI::IntCoord BaseManager::getWindowCoord()
296 	{
297 		MyGUI::IntCoord result;
298 	#if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
299 		size_t handle = getWindowHandle();
300 		::RECT rect;
301 		::GetWindowRect((HWND)handle, &rect);
302 		result.left = rect.left;
303 		result.top = rect.top;
304 		result.width = rect.right - rect.left;
305 		result.height = rect.bottom - rect.top;
306 	#endif
307 		return result;
308 	}
309 
setupResources()310 	void BaseManager::setupResources()
311 	{
312 		MyGUI::xml::Document doc;
313 
314 		if (!doc.open(mResourceXMLName))
315 			doc.getLastError();
316 
317 		MyGUI::xml::ElementPtr root = doc.getRoot();
318 		if (root == nullptr || root->getName() != "Paths")
319 			return;
320 
321 		MyGUI::xml::ElementEnumerator node = root->getElementEnumerator();
322 		while (node.next())
323 		{
324 			if (node->getName() == "Path")
325 			{
326 				if (node->findAttribute("root") != "")
327 				{
328 					bool rootAttribute = MyGUI::utility::parseBool(node->findAttribute("root"));
329 					if (rootAttribute)
330 						mRootMedia = node->getContent();
331 				}
332 				addResourceLocation(node->getContent());
333 			}
334 		}
335 
336 		addResourceLocation(getRootMedia() + "/Common/Base");
337 	}
338 
frameStarted(const Ogre::FrameEvent & evt)339 	bool BaseManager::frameStarted(const Ogre::FrameEvent& evt)
340 	{
341 		if (mExit)
342 			return false;
343 
344 		if (!mGUI)
345 			return true;
346 
347 		captureInput();
348 
349 		return true;
350 	}
351 
frameEnded(const Ogre::FrameEvent & evt)352 	bool BaseManager::frameEnded(const Ogre::FrameEvent& evt)
353 	{
354 		return true;
355 	}
356 
windowResized(Ogre::RenderWindow * _rw)357 	void BaseManager::windowResized(Ogre::RenderWindow* _rw)
358 	{
359 		int width = (int)_rw->getWidth();
360 		int height = (int)_rw->getHeight();
361 
362 		if (mPlatform)
363 			MyGUI::RenderManager::getInstance().setViewSize(width, height);
364 
365 		// при удалении окна может вызываться этот метод
366 		if (mCamera)
367 		{
368 			mCamera->setAspectRatio((float)width / (float)height);
369 
370 			setInputViewSize(width, height);
371 		}
372 	}
373 
windowClosed(Ogre::RenderWindow * _rw)374 	void BaseManager::windowClosed(Ogre::RenderWindow* _rw)
375 	{
376 		mExit = true;
377 		destroyInput();
378 	}
379 
getWindowHandle()380 	size_t BaseManager::getWindowHandle()
381 	{
382 		size_t handle = 0;
383 		mWindow->getCustomAttribute("WINDOW", &handle);
384 		return handle;
385 	}
386 
setWindowCaption(const std::wstring & _text)387 	void BaseManager::setWindowCaption(const std::wstring& _text)
388 	{
389 	#if MYGUI_PLATFORM == MYGUI_PLATFORM_WIN32
390 		::SetWindowTextW((HWND)getWindowHandle(), _text.c_str());
391 	#elif MYGUI_PLATFORM == MYGUI_PLATFORM_LINUX
392 		Display* xDisplay = nullptr;
393 		unsigned long windowHandle = 0;
394 		mWindow->getCustomAttribute("XDISPLAY", &xDisplay);
395 		mWindow->getCustomAttribute("WINDOW", &windowHandle);
396 		Window win = (Window)windowHandle;
397 
398 		XTextProperty windowName;
399 		windowName.value    = (unsigned char *)(MyGUI::UString(_text).asUTF8_c_str());
400 		windowName.encoding = XA_STRING;
401 		windowName.format   = 8;
402 		windowName.nitems   = strlen((char *)(windowName.value));
403 		XSetWMName(xDisplay, win, &windowName);
404 	#endif
405 	}
406 
prepare()407 	void BaseManager::prepare()
408 	{
409 	}
410 
addResourceLocation(const std::string & _name,const std::string & _group,const std::string & _type,bool _recursive)411 	void BaseManager::addResourceLocation(const std::string& _name, const std::string& _group, const std::string& _type, bool _recursive)
412 	{
413 		#if MYGUI_PLATFORM == MYGUI_PLATFORM_APPLE
414 			// OS X does not set the working directory relative to the app, In order to make things portable on OS X we need to provide the loading with it's own bundle path location
415 			Ogre::ResourceGroupManager::getSingleton().addResourceLocation(Ogre::String(macBundlePath() + "/" + _name), _type, _group, _recursive);
416 		#else
417 			Ogre::ResourceGroupManager::getSingleton().addResourceLocation(_name, _type, _group, _recursive);
418 		#endif
419 	}
420 
addResourceLocation(const std::string & _name,bool _recursive)421 	void BaseManager::addResourceLocation(const std::string& _name, bool _recursive)
422 	{
423 		addResourceLocation(_name, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "FileSystem", false);
424 	}
425 
injectMouseMove(int _absx,int _absy,int _absz)426 	void BaseManager::injectMouseMove(int _absx, int _absy, int _absz)
427 	{
428 		if (!mGUI)
429 			return;
430 
431 		MyGUI::InputManager::getInstance().injectMouseMove(_absx, _absy, _absz);
432 	}
433 
injectMousePress(int _absx,int _absy,MyGUI::MouseButton _id)434 	void BaseManager::injectMousePress(int _absx, int _absy, MyGUI::MouseButton _id)
435 	{
436 		if (!mGUI)
437 			return;
438 
439 		MyGUI::InputManager::getInstance().injectMousePress(_absx, _absy, _id);
440 	}
441 
injectMouseRelease(int _absx,int _absy,MyGUI::MouseButton _id)442 	void BaseManager::injectMouseRelease(int _absx, int _absy, MyGUI::MouseButton _id)
443 	{
444 		if (!mGUI)
445 			return;
446 
447 		MyGUI::InputManager::getInstance().injectMouseRelease(_absx, _absy, _id);
448 	}
449 
injectKeyPress(MyGUI::KeyCode _key,MyGUI::Char _text)450 	void BaseManager::injectKeyPress(MyGUI::KeyCode _key, MyGUI::Char _text)
451 	{
452 		if (!mGUI)
453 			return;
454 
455 		if (_key == MyGUI::KeyCode::Escape)
456 		{
457 			mExit = true;
458 			return;
459 		}
460 		else if (_key == MyGUI::KeyCode::SysRq)
461 		{
462 			makeScreenShot();
463 			return;
464 		}
465 
466 		// change polygon mode
467 		// TODO: polygon mode require changes in platform
468 		else if (_key == MyGUI::KeyCode::F5)
469 		{
470 			getCamera()->setPolygonMode(Ogre::PM_SOLID);
471 		}
472 		else if (_key == MyGUI::KeyCode::F6)
473 		{
474 			getCamera()->setPolygonMode(Ogre::PM_WIREFRAME);
475 		}
476 		else if (_key == MyGUI::KeyCode::F7)
477 		{
478 			getCamera()->setPolygonMode(Ogre::PM_POINTS);
479 		}
480 #if OGRE_VERSION >= MYGUI_DEFINE_VERSION(1, 7, 0) && OGRE_NO_VIEWPORT_ORIENTATIONMODE == 0
481 		else if (_key == MyGUI::KeyCode::F1)
482 		{
483 			mWindow->getViewport(0)->setOrientationMode(Ogre::OR_DEGREE_0, false);
484 			mPlatform->getRenderManagerPtr()->setRenderWindow(mWindow);
485 		}
486 		else if (_key == MyGUI::KeyCode::F2)
487 		{
488 			mWindow->getViewport(0)->setOrientationMode(Ogre::OR_DEGREE_90, false);
489 			mPlatform->getRenderManagerPtr()->setRenderWindow(mWindow);
490 		}
491 		else if (_key == MyGUI::KeyCode::F3)
492 		{
493 			mWindow->getViewport(0)->setOrientationMode(Ogre::OR_DEGREE_180, false);
494 			mPlatform->getRenderManagerPtr()->setRenderWindow(mWindow);
495 		}
496 		else if (_key == MyGUI::KeyCode::F4)
497 		{
498 			mWindow->getViewport(0)->setOrientationMode(Ogre::OR_DEGREE_270, false);
499 			mPlatform->getRenderManagerPtr()->setRenderWindow(mWindow);
500 		}
501 #endif
502 
503 		MyGUI::InputManager::getInstance().injectKeyPress(_key, _text);
504 	}
505 
injectKeyRelease(MyGUI::KeyCode _key)506 	void BaseManager::injectKeyRelease(MyGUI::KeyCode _key)
507 	{
508 		if (!mGUI)
509 			return;
510 
511 		MyGUI::InputManager::getInstance().injectKeyRelease(_key);
512 	}
513 
quit()514 	void BaseManager::quit()
515 	{
516 		mExit = true;
517 	}
518 
getRootMedia()519 	const std::string& BaseManager::getRootMedia()
520 	{
521 		return mRootMedia;
522 	}
523 
setResourceFilename(const std::string & _flename)524 	void BaseManager::setResourceFilename(const std::string& _flename)
525 	{
526 		mResourceFileName = _flename;
527 	}
528 
getSceneManager()529 	Ogre::SceneManager* BaseManager::getSceneManager()
530 	{
531 		return mSceneManager;
532 	}
533 
getCamera()534 	Ogre::Camera* BaseManager::getCamera()
535 	{
536 		return mCamera;
537 	}
538 
makeScreenShot()539 	void BaseManager::makeScreenShot()
540 	{
541 		std::ifstream stream;
542 		std::string file;
543 		do
544 		{
545 			stream.close();
546 			static size_t num = 0;
547 			const size_t max_shot = 100;
548 			if (num == max_shot)
549 			{
550 				MYGUI_LOG(Info, "The limit of screenshots is exceeded : " << max_shot);
551 				return;
552 			}
553 			file = MyGUI::utility::toString("screenshot_", ++num, ".png");
554 			stream.open(file.c_str());
555 		}
556 		while (stream.is_open());
557 		mWindow->writeContentsToFile(file);
558 	}
559 
getStatistic()560 	MyGUI::MapString BaseManager::getStatistic()
561 	{
562 		MyGUI::MapString result;
563 
564 		try
565 		{
566 			const Ogre::RenderTarget::FrameStats& stats = mWindow->getStatistics();
567 			result["FPS"] = MyGUI::utility::toString(stats.lastFPS);
568 			result["triangle"] = MyGUI::utility::toString(stats.triangleCount);
569 			result["batch"] = MyGUI::utility::toString(stats.batchCount);
570 			result["batch gui"] = MyGUI::utility::toString(MyGUI::OgreRenderManager::getInstance().getBatchCount());
571 		}
572 		catch (...)
573 		{
574 			MYGUI_LOG(Warning, "Error get statistics");
575 		}
576 
577 		return result;
578 	}
579 
580 } // namespace base
581