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