/* ----------------------------------------------------------------------------- This source file is part of OGRE (Object-oriented Graphics Rendering Engine) For the latest info, see http://www.ogre3d.org/ Copyright (c) 2000-2005 The OGRE Team Also see acknowledgements in Readme.html You may use this sample code for anything you like, it is not covered by the LGPL like the rest of the engine. ----------------------------------------------------------------------------- */ #include "OgreColladaManager.h" #include "OgreColladaScene.h" #include "ColladaDemo.h" #include "UIHandler.h" #include "OgreConfigFile.h" #include "OgreException.h" #include "OgreRoot.h" #include "OgreTextureManager.h" #include "OgreCamera.h" #include "OgreRenderWindow.h" #include "OgreMeshManager.h" #include "OgreSkeletonManager.h" #include "OgreMaterialManager.h" #include "OgreCEGUIRenderer.h" #include "OgreCEGUIResourceProvider.h" #include #include #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 #define WIN32_LEAN_AND_MEAN #include "windows.h" #endif #define DEFAULT_CAMERA_NAME "DefaultCamera" //----------------------------------------------------------------------------- // sub-class for ListboxTextItem that auto-sets the selection brush // image. //----------------------------------------------------------------------------- class MyListItem : public CEGUI::ListboxTextItem { public: MyListItem(const CEGUI::String& text, CEGUI::uint id) : CEGUI::ListboxTextItem(text, id) { setSelectionBrushImage("TaharezLook", "MultiListSelectionBrush"); } }; //----------------------------------------------------------------------------- // ColladaDemo Methods //----------------------------------------------------------------------------- ColladaDemo::~ColladaDemo() { delete mGUISystem; delete mGUIRenderer; delete mFrameListener; // get rid of the shared pointers before shutting down ogre or exceptions occure delete mRoot; } //-------------------------------------------------------------------------- void ColladaDemo::go() { if (!setup()) return; mRoot->startRendering(); } //-------------------------------------------------------------------------- bool ColladaDemo::setup() { bool setupCompleted = false; mRoot = new Ogre::Root(); setupResources(); if (configure()) { mSceneMgr = mRoot->createSceneManager(Ogre::ST_GENERIC, "ExampleSMInstance"); createDefaultCamera(); createViewports(); // Set default mipmap level (NB some APIs ignore this) Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5); Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups(); if (setupGUI()) { // Set default ambient light level mSceneMgr->setAmbientLight(Ogre::ColourValue(0.3, 0.3, 0.3)); createFrameListener(); // load some GUI stuff for demo. initDemoEventWiring(); updateAvailableCameras(); setupCompleted = true; } } return setupCompleted; } //-------------------------------------------------------------------------- bool ColladaDemo::configure() { // Show the configuration dialog and initialise the system if(mRoot->showConfigDialog()) { // If returned true, user clicked OK so initialise // Here we choose to let the system create a default rendering window by passing 'true' mWindow = mRoot->initialise(true); return true; } else { return false; } } //-------------------------------------------------------------------------- void ColladaDemo::createDefaultCamera() { // Create the default camera to be used if the dae document does not provide one mActiveCamera = mSceneMgr->createCamera(DEFAULT_CAMERA_NAME); // Default Position it at 500 in Z direction mActiveCamera->setPosition(Ogre::Vector3(0,100,500)); // Look back along -Z mActiveCamera->lookAt(Ogre::Vector3(0,0,-100)); mActiveCamera->setNearClipDistance(1); } //-------------------------------------------------------------------------- void ColladaDemo::createViewports() { // Create one viewport, entire window Ogre::Viewport* vp = mWindow->addViewport(mActiveCamera); vp->setBackgroundColour(Ogre::ColourValue(0,0,0)); // Alter the camera aspect ratio to match the viewport mActiveCamera->setAspectRatio( Ogre::Real(vp->getActualWidth()) / Ogre::Real(vp->getActualHeight())); } //-------------------------------------------------------------------------- void ColladaDemo::setupResources() { // Load resource paths from config file Ogre::ConfigFile cf; #if OGRE_PLATFORM == OGRE_PLATFORM_APPLE Ogre::String mResourcePath; mResourcePath = bundlePath() + "/Contents/Resources/"; cf.load(mResourcePath + "resources.cfg"); #else cf.load("resources.cfg"); #endif // Go through all sections & settings in the file Ogre::ConfigFile::SectionIterator seci = cf.getSectionIterator(); Ogre::String secName, typeName, archName; while (seci.hasMoreElements()) { secName = seci.peekNextKey(); Ogre::ConfigFile::SettingsMultiMap *settings = seci.getNext(); Ogre::ConfigFile::SettingsMultiMap::iterator i; for (i = settings->begin(); i != settings->end(); ++i) { typeName = i->first; archName = i->second; Ogre::ResourceGroupManager::getSingleton().addResourceLocation( archName, typeName, secName); } } Ogre::LogManager::getSingleton().logMessage( "Resource directories setup" ); } //-------------------------------------------------------------------------- bool ColladaDemo::setupGUI() { bool setupGUICompleted = false; // setup GUI system try { mGUIRenderer = new CEGUI::OgreCEGUIRenderer(mWindow, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, mSceneMgr); // load scheme and set up defaults mGUISystem = new CEGUI::System(mGUIRenderer,(CEGUI::OgreCEGUIResourceProvider *)0, (CEGUI::XMLParser *)0, (CEGUI::ScriptModule *)0, (CEGUI::utf8*)"ColladaDemoCegui.config"); CEGUI::System::getSingleton().setDefaultMouseCursor("TaharezLook", "MouseArrow"); setupGUICompleted = true; } catch(...) { Ogre::LogManager::getSingleton().logMessage("failed to setup the GUI so shutting down..."); } return setupGUICompleted; } //-------------------------------------------------------------------------- void ColladaDemo::updateDaeFileList() { using namespace CEGUI; Combobox* cbobox = (Combobox*)WindowManager::getSingleton().getWindow("DaeCombos"); cbobox->resetList(); Ogre::StringVectorPtr daeStringVector = Ogre::ResourceGroupManager::getSingleton().findResourceNames( Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "*.dae" ); std::vector::iterator daeFileNameIterator = daeStringVector->begin(); while ( daeFileNameIterator != daeStringVector->end() ) { cbobox->addItem(new MyListItem( (*daeFileNameIterator).c_str(), 0 )); ++daeFileNameIterator; } } //-------------------------------------------------------------------------- void ColladaDemo::initDemoEventWiring() { using namespace CEGUI; WindowManager::getSingleton().getWindow("ExitDemoBtn")-> subscribeEvent(PushButton::EventClicked, CEGUI::Event::Subscriber(&ColladaDemo::handleQuit, this)); WindowManager::getSingleton().getWindow("DaeCombos")-> subscribeEvent(Combobox::EventListSelectionAccepted, CEGUI::Event::Subscriber(&ColladaDemo::handleDaeComboChanged, this)); WindowManager::getSingleton().getWindow("DaeCombos")-> subscribeEvent(Combobox::EventDropListDisplayed, CEGUI::Event::Subscriber(&ColladaDemo::handleUpdateList, this)); WindowManager::getSingleton().getWindow("CameraCombos")-> subscribeEvent(Combobox::EventListSelectionAccepted, CEGUI::Event::Subscriber(&ColladaDemo::handleCameraComboChanged, this)); WindowManager::getSingleton().getWindow("AutoReloadCB")-> subscribeEvent(Checkbox::EventCheckStateChanged, CEGUI::Event::Subscriber(&ColladaDemo::handleAutoReloadChanged, this)); Window* wndw = WindowManager::getSingleton().getWindow("root"); wndw->subscribeEvent(Window::EventMouseMove, CEGUI::Event::Subscriber(&UIHandler::handleMouseMove, mFrameListener)); wndw->subscribeEvent(Window::EventMouseButtonUp, CEGUI::Event::Subscriber(&UIHandler::handleMouseButtonUp, mFrameListener)); wndw->subscribeEvent(Window::EventMouseButtonDown, CEGUI::Event::Subscriber(&UIHandler::handleMouseButtonDown, mFrameListener)); wndw->subscribeEvent(Window::EventMouseWheel, CEGUI::Event::Subscriber(&UIHandler::handleMouseWheelEvent, mFrameListener)); wndw->subscribeEvent(Window::EventKeyDown, CEGUI::Event::Subscriber(&UIHandler::handleKeyDownEvent, mFrameListener )); wndw->subscribeEvent(Window::EventKeyUp, CEGUI::Event::Subscriber(&UIHandler::handleKeyUpEvent, mFrameListener )); showLoadingWindow(false); } //-------------------------------------------------------------------------- void ColladaDemo::doErrorBox(const char* text) { using namespace CEGUI; WindowManager& winMgr = WindowManager::getSingleton(); Window* root = winMgr.getWindow("root_wnd"); FrameWindow* errbox; try { errbox = (FrameWindow*)winMgr.getWindow("ErrorBox"); } catch(UnknownObjectException x) { #if 0 // create frame window for box FrameWindow* fwnd = (FrameWindow*)winMgr.createWindow("TaharezLook/FrameWindow", "ErrorBox"); root->addChildWindow(fwnd); // fwnd->setPosition(Point(0.25, 0.25f)); // fwnd->setMaximumSize(Size(1.0f, 1.0f)); fwnd->setSize(Size(0.5f, 0.5f)); fwnd->setText("CEGUI Demo - Error!"); fwnd->setDragMovingEnabled(false); fwnd->setSizingEnabled(false); fwnd->setAlwaysOnTop(true); fwnd->setCloseButtonEnabled(false); // create error text message StaticText* msg = (StaticText*)winMgr.createWindow("TaharezLook/StaticText", "ErrorBox/Message"); fwnd->addChildWindow(msg); msg->setPosition(Point(0.1f, 0.1f)); msg->setSize(Size(0.8f, 0.5f)); msg->setVerticalFormatting(StaticText::VertCentred); msg->setHorizontalFormatting(StaticText::HorzCentred); msg->setBackgroundEnabled(false); msg->setFrameEnabled(false); // create ok button PushButton* btn = (PushButton*)winMgr.createWindow("TaharezLook/Button", "ErrorBox/OkButton"); fwnd->addChildWindow(btn); btn->setPosition(Point(0.3f, 0.80f)); btn->setSize(Size(0.4f, 0.1f)); btn->setText("Okay!"); // subscribe event btn->subscribeEvent(PushButton::EventClicked, CEGUI::Event::Subscriber(&ColladaDemo::handleErrorBox, this )); errbox = fwnd; #endif } errbox->getChild("ErrorBox/Message")->setText(text); errbox->show(); errbox->activate(); } //-------------------------------------------------------------------------- void ColladaDemo::viewColladaDocument(const Ogre::String& daeFileName) { Ogre::LogManager::getSingleton().logMessage("ColladaDocument - import started"); try { Ogre::ColladaDocumentPtr daeDoc = Ogre::ColladaManager::getSingleton().load(daeFileName, mSceneMgr); // build up scene fully if document was loaded if (!daeDoc.isNull()) { Ogre::ColladaSceneNode* node = daeDoc->getScene(); if (node) { daeDoc->getScene()->createOgreInstance(NULL); Ogre::LogManager::getSingleton().logMessage("ColladaDocument - import finished"); } else { Ogre::LogManager::getSingleton().logMessage("ColladaDocument - import failed"); } } } catch(...) { Ogre::LogManager::getSingleton().logMessage("ColladaDocument - failed to load"); } // reset last update time so file update checking starts all over again if enabled mLastUpdateTime = 0; } //-------------------------------------------------------------------------- bool ColladaDemo::checkActiveFileUpdated() { // get time stamp of file which will be used for auto reload feature // Note: this will fail if the file was obtained from a zip archive // Note2: we cheat here and only allow files loaded from ..\..\media\dae path to auto reload Ogre::String filename = "..\\..\\media\\dae\\" + mActiveDaeFileName; bool fileUpdated = false; struct stat tagStat; int ret = stat(filename.c_str(), &tagStat); // only check update if file was accessible if (ret == 0) { if (tagStat.st_mtime != mLastUpdateTime) { // file is updated only if this not the first time checking fileUpdated = mLastUpdateTime != 0; mLastUpdateTime = tagStat.st_mtime; } } return fileUpdated; } //-------------------------------------------------------------------------- bool ColladaDemo::handleQuit(const CEGUI::EventArgs& e) { mRoot->queueEndRendering(); return true; } //-------------------------------------------------------------------------- bool ColladaDemo::handleDaeComboChanged(const CEGUI::EventArgs& e) { using namespace CEGUI; // get the selected mesh filename from the combo box CEGUI::ListboxItem* item = ((Combobox*)((const WindowEventArgs&)e).window)->getSelectedItem(); mActiveDaeFileName = item->getText().c_str(); loadActiveDae(); return true; } //-------------------------------------------------------------------------- bool ColladaDemo::handleCameraComboChanged(const CEGUI::EventArgs& e) { using namespace CEGUI; // get the selected mesh filename from the combo box CEGUI::ListboxItem* item = ((Combobox*)((const WindowEventArgs&)e).window)->getSelectedItem(); // view the selected document setActiveCamera(item->getText().c_str()); return true; } //-------------------------------------------------------------------------- bool ColladaDemo::handleAutoReloadChanged(const CEGUI::EventArgs& e) { using namespace CEGUI; mAutoReload = ((Checkbox*)((const WindowEventArgs&)e).window)->isSelected(); return true; } //-------------------------------------------------------------------------- void ColladaDemo::updateAvailableCameras() { using namespace CEGUI; Combobox* cbobox = (Combobox*)WindowManager::getSingleton().getWindow("CameraCombos"); cbobox->resetList(); // find first non default camera and make it active Ogre::String activeCameraName; Ogre::SceneManager::CameraIterator cameras = mSceneMgr->getCameraIterator(); while (cameras.hasMoreElements()) { Ogre::Camera* camera = cameras.getNext(); cbobox->addItem(new MyListItem( camera->getName().c_str(), 0 )); // make the first non default camera the active camera if (activeCameraName.empty() && (camera->getName() != DEFAULT_CAMERA_NAME)) { activeCameraName = camera->getName(); } } // if no dae camera was found then use the default camera if (activeCameraName.empty()) activeCameraName = DEFAULT_CAMERA_NAME; // make camera item visible Editbox* eb = static_cast(WindowManager::getSingleton().getWindow(cbobox->getName() + "__auto_editbox__")); eb->setText(activeCameraName.c_str()); setActiveCamera(activeCameraName); } //-------------------------------------------------------------------------- void ColladaDemo::setActiveCamera(const Ogre::String& cameraName) { assert(mSceneMgr); assert(mWindow); // get the camera by name from the scenemanager and tell the first viewport of the // current render window to use it. try { mActiveCamera = mSceneMgr->getCamera(cameraName); mWindow->getViewport(0)->setCamera(mActiveCamera); } catch (Ogre::Exception& e) { Ogre::LogManager::getSingleton().logMessage("ColladaDemo::setActiveCamera(\"" + cameraName + ") failed: " + e.getFullDescription()); } } //-------------------------------------------------------------------------- bool ColladaDemo::handleErrorBox(const CEGUI::EventArgs& e) { CEGUI::WindowManager::getSingleton().getWindow((CEGUI::utf8*)"ErrorBox")->hide(); return true; } bool ColladaDemo::handleUpdateList(const CEGUI::EventArgs& e) { updateDaeFileList(); return true; } //-------------------------------------------------------------------------- void ColladaDemo::createFrameListener() { mFrameListener= new UIHandler(this); mRoot->addFrameListener(mFrameListener); } //-------------------------------------------------------------------------- void ColladaDemo::clearScene() { using namespace Ogre; try { mWindow->removeAllViewports(); mSceneMgr->destroyAllCameras(); if( mSceneMgr ) { mSceneMgr->clearScene(); } MeshManager::getSingleton().removeAll(); SkeletonManager::getSingleton().removeAll(); ColladaManager::getSingleton().removeAll(); MaterialManager::getSingleton().removeAll(); createDefaultCamera(); createViewports(); } catch (Ogre::Exception& e) { Ogre::LogManager::getSingleton().logMessage("Clear Scene failed: " + e.getFullDescription()); } } //-------------------------------------------------------------------------- void ColladaDemo::loadActiveDae() { // que the loading so that Loading window can get a chance to be rendered if (!mLoadQued) { showLoadingWindow(true); mLoadQued = true; mLastFrameNumber = mRoot->getCurrentFrameNumber(); } // perform loading and view if load was qued and rendering has advanced to the next frame else if (mRoot->getCurrentFrameNumber() > mLastFrameNumber) { // erase current scene clearScene(); // view the selected document viewColladaDocument(mActiveDaeFileName); updateAvailableCameras(); showLoadingWindow(false); mLoadQued = false; } } //-------------------------------------------------------------------------- void ColladaDemo::updateAutoReload(float time) { if (mLoadQued) { loadActiveDae(); } if (mAutoReload) { mElapsedTime += time; if (mElapsedTime > 1.0) { mElapsedTime = 0.0; if (!mActiveDaeFileName.empty()) { if (checkActiveFileUpdated()) { loadActiveDae(); } } } } } //-------------------------------------------------------------------------- void ColladaDemo::showLoadingWindow(const bool show) { if (!mLoadingWindow) { mLoadingWindow = CEGUI::WindowManager::getSingleton().getWindow("ColladaDemo/LoadWin"); } mLoadingWindow->setVisible(show); } //-------------------------------------------------------------------------- #ifdef __cplusplus extern "C" { #endif #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT ) #else int main(int argc, char *argv[]) #endif { // Create application object ColladaDemo app; // SET_TERM_HANDLER; try { app.go(); } catch( Ogre::Exception& e ) { #if OGRE_PLATFORM == OGRE_PLATFORM_WIN32 MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL); #else std::cerr << "An exception has occured: " << e.getFullDescription().c_str() << std::endl; #endif } return 0; } #ifdef __cplusplus } #endif