diff --git a/apps/openmw/engine.cpp b/apps/openmw/engine.cpp index d33e5300e..3647f8ccb 100644 --- a/apps/openmw/engine.cpp +++ b/apps/openmw/engine.cpp @@ -137,6 +137,7 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) } // update GUI + MWBase::Environment::get().getWindowManager()->onFrame(frametime); if (MWBase::Environment::get().getStateManager()->getState()!= MWBase::StateManager::State_NoGame) { @@ -145,7 +146,6 @@ bool OMW::Engine::frameRenderingQueued (const Ogre::FrameEvent& evt) MWBase::Environment::get().getWorld()->getTriangleBatchCount(tri, batch); MWBase::Environment::get().getWindowManager()->wmUpdateFps(window->getLastFPS(), tri, batch); - MWBase::Environment::get().getWindowManager()->onFrame(frametime); MWBase::Environment::get().getWindowManager()->update(); } } diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index fd45ec859..ef4549268 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -50,9 +50,9 @@ namespace MWClass void Light::insertObjectRendering (const MWWorld::Ptr& ptr, MWRender::RenderingInterface& renderingInterface) const { const std::string model = getModel(ptr); - if(!model.empty()) { - renderingInterface.getObjects().insertModel(ptr, model); - } + + // Insert even if model is empty, so that the light is added + renderingInterface.getObjects().insertModel(ptr, model); } void Light::insertObject(const MWWorld::Ptr& ptr, MWWorld::PhysicsSystem& physics) const diff --git a/apps/openmw/mwgui/console.cpp b/apps/openmw/mwgui/console.cpp index db87d0a59..2ae4d6ed1 100644 --- a/apps/openmw/mwgui/console.cpp +++ b/apps/openmw/mwgui/console.cpp @@ -61,7 +61,7 @@ namespace MWGui } catch (const std::exception& error) { - printError (std::string ("An exception has been thrown: ") + error.what()); + printError (std::string ("Error: ") + error.what()); } return false; @@ -195,7 +195,7 @@ namespace MWGui } catch (const std::exception& error) { - printError (std::string ("An exception has been thrown: ") + error.what()); + printError (std::string ("Error: ") + error.what()); } } } diff --git a/apps/openmw/mwgui/mainmenu.cpp b/apps/openmw/mwgui/mainmenu.cpp index bafd04311..53ce8f488 100644 --- a/apps/openmw/mwgui/mainmenu.cpp +++ b/apps/openmw/mwgui/mainmenu.cpp @@ -1,5 +1,7 @@ #include "mainmenu.hpp" +#include + #include #include "../mwbase/environment.hpp" @@ -16,6 +18,7 @@ #include "confirmationdialog.hpp" #include "imagebutton.hpp" #include "backgroundimage.hpp" +#include "videowidget.hpp" namespace MWGui { @@ -25,6 +28,7 @@ namespace MWGui , mButtonBox(0), mWidth (w), mHeight (h) , mSaveGameDialog(NULL) , mBackground(NULL) + , mVideo(NULL) { getWidget(mVersionText, "VersionText"); std::stringstream sstream; @@ -42,6 +46,8 @@ namespace MWGui std::string output = sstream.str(); mVersionText->setCaption(output); + mHasAnimatedMenu = (Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup("video\\menu_background.bik")); + updateMenu(); } @@ -134,14 +140,66 @@ namespace MWGui void MainMenu::showBackground(bool show) { - if (show && !mBackground) + if (mVideo && !show) + { + MyGUI::Gui::getInstance().destroyWidget(mVideo); + mVideo = NULL; + } + if (mBackground && !show) { - mBackground = MyGUI::Gui::getInstance().createWidgetReal("ImageBox", 0,0,1,1, - MyGUI::Align::Stretch, "Menu"); - mBackground->setBackgroundImage("textures\\menu_morrowind.dds"); + MyGUI::Gui::getInstance().destroyWidget(mBackground); + mBackground = NULL; } - if (mBackground) - mBackground->setVisible(show); + + if (!show) + return; + + if (mHasAnimatedMenu) + { + if (!mVideo) + { + // Use black background to correct aspect ratio + mVideoBackground = MyGUI::Gui::getInstance().createWidgetReal("ImageBox", 0,0,1,1, + MyGUI::Align::Default, "Menu"); + mVideoBackground->setImageTexture("black.png"); + + mVideo = mVideoBackground->createWidget("ImageBox", 0,0,1,1, + MyGUI::Align::Stretch, "Menu"); + + mVideo->playVideo("video\\menu_background.bik", false); + } + + MyGUI::IntSize viewSize = MyGUI::RenderManager::getInstance().getViewSize(); + int screenWidth = viewSize.width; + int screenHeight = viewSize.height; + mVideoBackground->setSize(screenWidth, screenHeight); + + double imageaspect = static_cast(mVideo->getVideoWidth())/mVideo->getVideoHeight(); + + int leftPadding = std::max(0.0, (screenWidth - screenHeight * imageaspect) / 2); + int topPadding = std::max(0.0, (screenHeight - screenWidth / imageaspect) / 2); + + mVideo->setCoord(leftPadding, topPadding, + screenWidth - leftPadding*2, screenHeight - topPadding*2); + + mVideo->setVisible(true); + } + else + { + if (!mBackground) + { + mBackground = MyGUI::Gui::getInstance().createWidgetReal("ImageBox", 0,0,1,1, + MyGUI::Align::Stretch, "Menu"); + mBackground->setBackgroundImage("textures\\menu_morrowind.dds"); + } + mBackground->setVisible(true); + } + } + + void MainMenu::update(float dt) + { + if (mVideo) + mVideo->update(); } void MainMenu::updateMenu() @@ -229,7 +287,7 @@ namespace MWGui if (state == MWBase::StateManager::State_NoGame) { // Align with the background image - int bottomPadding=48; + int bottomPadding=24; mButtonBox->setCoord (mWidth/2 - maxwidth/2, mHeight - curH - bottomPadding, maxwidth, curH); } else diff --git a/apps/openmw/mwgui/mainmenu.hpp b/apps/openmw/mwgui/mainmenu.hpp index c27442536..ccd8df4b0 100644 --- a/apps/openmw/mwgui/mainmenu.hpp +++ b/apps/openmw/mwgui/mainmenu.hpp @@ -9,12 +9,15 @@ namespace MWGui class ImageButton; class BackgroundImage; class SaveGameDialog; + class VideoWidget; class MainMenu : public OEngine::GUI::Layout { int mWidth; int mHeight; + bool mHasAnimatedMenu; + public: MainMenu(int w, int h); @@ -24,6 +27,8 @@ namespace MWGui virtual void setVisible (bool visible); + void update(float dt); + private: MyGUI::Widget* mButtonBox; @@ -31,6 +36,9 @@ namespace MWGui BackgroundImage* mBackground; + MyGUI::ImageBox* mVideoBackground; + VideoWidget* mVideo; // For animated main menus + std::map mButtons; void onButtonClicked (MyGUI::Widget* sender); diff --git a/apps/openmw/mwgui/savegamedialog.cpp b/apps/openmw/mwgui/savegamedialog.cpp index b36baf87b..348b7c1df 100644 --- a/apps/openmw/mwgui/savegamedialog.cpp +++ b/apps/openmw/mwgui/savegamedialog.cpp @@ -134,9 +134,12 @@ namespace MWGui else { // Find the localised name for this class from the store - const ESM::Class* class_ = MWBase::Environment::get().getWorld()->getStore().get().find( + const ESM::Class* class_ = MWBase::Environment::get().getWorld()->getStore().get().search( it->getSignature().mPlayerClassId); - className = class_->mName; + if (class_) + className = class_->mName; + else + className = "?"; // From an older savegame format that did not support custom classes properly. } title << " (Level " << it->getSignature().mPlayerLevel << " " << className << ")"; diff --git a/apps/openmw/mwgui/settingswindow.cpp b/apps/openmw/mwgui/settingswindow.cpp index 4730a7295..749616490 100644 --- a/apps/openmw/mwgui/settingswindow.cpp +++ b/apps/openmw/mwgui/settingswindow.cpp @@ -73,17 +73,6 @@ namespace return (Ogre::Root::getSingleton ().getRenderSystem ()->getName ().find("OpenGL") != std::string::npos) ? "glsl" : "hlsl"; } - bool cgAvailable () - { - Ogre::Root::PluginInstanceList list = Ogre::Root::getSingleton ().getInstalledPlugins (); - for (Ogre::Root::PluginInstanceList::const_iterator it = list.begin(); it != list.end(); ++it) - { - if ((*it)->getName() == "Cg Program Manager") - return true; - } - return false; - } - const char* checkButtonType = "CheckButton"; const char* sliderType = "Slider"; @@ -366,12 +355,7 @@ namespace MWGui void SettingsWindow::onShaderModeToggled(MyGUI::Widget* _sender) { std::string val = static_cast(_sender)->getCaption(); - if (val == "cg") - { - val = hlslGlsl(); - } - else if (cgAvailable ()) - val = "cg"; + val = hlslGlsl(); static_cast(_sender)->setCaption(val); diff --git a/apps/openmw/mwgui/statswindow.cpp b/apps/openmw/mwgui/statswindow.cpp index 6ae44e314..246ade7bf 100644 --- a/apps/openmw/mwgui/statswindow.cpp +++ b/apps/openmw/mwgui/statswindow.cpp @@ -454,20 +454,30 @@ namespace MWGui if (!mFactions.empty()) { - // Add a line separator if there are items above - if (!mSkillWidgets.empty()) - addSeparator(coord1, coord2); - MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); const MWMechanics::NpcStats &PCstats = player.getClass().getNpcStats(player); const std::set &expelled = PCstats.getExpelled(); - addGroup(MWBase::Environment::get().getWindowManager()->getGameSettingString("sFaction", "Faction"), coord1, coord2); + bool firstFaction=true; FactionList::const_iterator end = mFactions.end(); for (FactionList::const_iterator it = mFactions.begin(); it != end; ++it) { const ESM::Faction *faction = store.get().find(it->first); + if (faction->mData.mIsHidden == 1) + continue; + + if (firstFaction) + { + // Add a line separator if there are items above + if (!mSkillWidgets.empty()) + addSeparator(coord1, coord2); + + addGroup(MWBase::Environment::get().getWindowManager()->getGameSettingString("sFaction", "Faction"), coord1, coord2); + + firstFaction = false; + } + MyGUI::Widget* w = addItem(faction->mName, coord1, coord2); std::string text; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index b931cd370..4de3028ed 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -803,6 +803,8 @@ namespace MWGui mToolTips->onFrame(frameDuration); + mMenu->update(frameDuration); + if (MWBase::Environment::get().getStateManager()->getState()== MWBase::StateManager::State_NoGame) return; diff --git a/apps/openmw/mwrender/animation.cpp b/apps/openmw/mwrender/animation.cpp index a2f901b26..9ed4cb6d3 100644 --- a/apps/openmw/mwrender/animation.cpp +++ b/apps/openmw/mwrender/animation.cpp @@ -1257,22 +1257,30 @@ Ogre::Vector3 Animation::getEnchantmentColor(MWWorld::Ptr item) ObjectAnimation::ObjectAnimation(const MWWorld::Ptr& ptr, const std::string &model) : Animation(ptr, ptr.getRefData().getBaseNode()) { - setObjectRoot(model, false); - - Ogre::Vector3 extents = getWorldBounds().getSize(); - float size = std::max(std::max(extents.x, extents.y), extents.z); - - bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && - Settings::Manager::getBool("limit small object distance", "Viewing distance"); - // do not fade out doors. that will cause holes and look stupid - if(ptr.getTypeName().find("Door") != std::string::npos) - small = false; - - float dist = small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0.0f; - Ogre::Vector3 col = getEnchantmentColor(ptr); - setRenderProperties(mObjectRoot, (mPtr.getTypeName() == typeid(ESM::Static).name()) ? - (small ? RV_StaticsSmall : RV_Statics) : RV_Misc, - RQG_Main, RQG_Alpha, dist, !ptr.getClass().getEnchantment(ptr).empty(), &col); + if (!model.empty()) + { + setObjectRoot(model, false); + + Ogre::Vector3 extents = getWorldBounds().getSize(); + float size = std::max(std::max(extents.x, extents.y), extents.z); + + bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && + Settings::Manager::getBool("limit small object distance", "Viewing distance"); + // do not fade out doors. that will cause holes and look stupid + if(ptr.getTypeName().find("Door") != std::string::npos) + small = false; + + float dist = small ? Settings::Manager::getInt("small object distance", "Viewing distance") : 0.0f; + Ogre::Vector3 col = getEnchantmentColor(ptr); + setRenderProperties(mObjectRoot, (mPtr.getTypeName() == typeid(ESM::Static).name()) ? + (small ? RV_StaticsSmall : RV_Statics) : RV_Misc, + RQG_Main, RQG_Alpha, dist, !ptr.getClass().getEnchantment(ptr).empty(), &col); + } + else + { + // No model given. Create an object root anyway, so that lights can be added to it if needed. + mObjectRoot = NifOgre::ObjectScenePtr (new NifOgre::ObjectScene(mInsert->getCreator())); + } } void ObjectAnimation::addLight(const ESM::Light *light) diff --git a/apps/openmw/mwrender/objects.cpp b/apps/openmw/mwrender/objects.cpp index 3101100f2..7953a3117 100644 --- a/apps/openmw/mwrender/objects.cpp +++ b/apps/openmw/mwrender/objects.cpp @@ -79,79 +79,82 @@ void Objects::insertModel(const MWWorld::Ptr &ptr, const std::string &mesh) std::auto_ptr anim(new ObjectAnimation(ptr, mesh)); - Ogre::AxisAlignedBox bounds = anim->getWorldBounds(); - Ogre::Vector3 extents = bounds.getSize(); - extents *= ptr.getRefData().getBaseNode()->getScale(); - float size = std::max(std::max(extents.x, extents.y), extents.z); - - bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && - Settings::Manager::getBool("limit small object distance", "Viewing distance"); - // do not fade out doors. that will cause holes and look stupid - if(ptr.getTypeName().find("Door") != std::string::npos) - small = false; - - if (mBounds.find(ptr.getCell()) == mBounds.end()) - mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL; - mBounds[ptr.getCell()].merge(bounds); - if(ptr.getTypeName() == typeid(ESM::Light).name()) anim->addLight(ptr.get()->mBase); - if(ptr.getTypeName() == typeid(ESM::Static).name() && - Settings::Manager::getBool("use static geometry", "Objects") && - anim->canBatch()) + if (!mesh.empty()) { - Ogre::StaticGeometry* sg = 0; - - if (small) + Ogre::AxisAlignedBox bounds = anim->getWorldBounds(); + Ogre::Vector3 extents = bounds.getSize(); + extents *= ptr.getRefData().getBaseNode()->getScale(); + float size = std::max(std::max(extents.x, extents.y), extents.z); + + bool small = (size < Settings::Manager::getInt("small object size", "Viewing distance")) && + Settings::Manager::getBool("limit small object distance", "Viewing distance"); + // do not fade out doors. that will cause holes and look stupid + if(ptr.getTypeName().find("Door") != std::string::npos) + small = false; + + if (mBounds.find(ptr.getCell()) == mBounds.end()) + mBounds[ptr.getCell()] = Ogre::AxisAlignedBox::BOX_NULL; + mBounds[ptr.getCell()].merge(bounds); + + if(ptr.getTypeName() == typeid(ESM::Static).name() && + Settings::Manager::getBool("use static geometry", "Objects") && + anim->canBatch()) { - if(mStaticGeometrySmall.find(ptr.getCell()) == mStaticGeometrySmall.end()) - { - uniqueID = uniqueID+1; - sg = mRenderer.getScene()->createStaticGeometry("sg" + Ogre::StringConverter::toString(uniqueID)); - sg->setOrigin(ptr.getRefData().getBaseNode()->getPosition()); - mStaticGeometrySmall[ptr.getCell()] = sg; + Ogre::StaticGeometry* sg = 0; - sg->setRenderingDistance(Settings::Manager::getInt("small object distance", "Viewing distance")); + if (small) + { + if(mStaticGeometrySmall.find(ptr.getCell()) == mStaticGeometrySmall.end()) + { + uniqueID = uniqueID+1; + sg = mRenderer.getScene()->createStaticGeometry("sg" + Ogre::StringConverter::toString(uniqueID)); + sg->setOrigin(ptr.getRefData().getBaseNode()->getPosition()); + mStaticGeometrySmall[ptr.getCell()] = sg; + + sg->setRenderingDistance(Settings::Manager::getInt("small object distance", "Viewing distance")); + } + else + sg = mStaticGeometrySmall[ptr.getCell()]; } else - sg = mStaticGeometrySmall[ptr.getCell()]; - } - else - { - if(mStaticGeometry.find(ptr.getCell()) == mStaticGeometry.end()) { - uniqueID = uniqueID+1; - sg = mRenderer.getScene()->createStaticGeometry("sg" + Ogre::StringConverter::toString(uniqueID)); - sg->setOrigin(ptr.getRefData().getBaseNode()->getPosition()); - mStaticGeometry[ptr.getCell()] = sg; + if(mStaticGeometry.find(ptr.getCell()) == mStaticGeometry.end()) + { + uniqueID = uniqueID+1; + sg = mRenderer.getScene()->createStaticGeometry("sg" + Ogre::StringConverter::toString(uniqueID)); + sg->setOrigin(ptr.getRefData().getBaseNode()->getPosition()); + mStaticGeometry[ptr.getCell()] = sg; + } + else + sg = mStaticGeometry[ptr.getCell()]; } - else - sg = mStaticGeometry[ptr.getCell()]; - } - // This specifies the size of a single batch region. - // If it is set too high: - // - there will be problems choosing the correct lights - // - the culling will be more inefficient - // If it is set too low: - // - there will be too many batches. - if(ptr.getCell()->isExterior()) - sg->setRegionDimensions(Ogre::Vector3(2048,2048,2048)); - else - sg->setRegionDimensions(Ogre::Vector3(1024,1024,1024)); + // This specifies the size of a single batch region. + // If it is set too high: + // - there will be problems choosing the correct lights + // - the culling will be more inefficient + // If it is set too low: + // - there will be too many batches. + if(ptr.getCell()->isExterior()) + sg->setRegionDimensions(Ogre::Vector3(2048,2048,2048)); + else + sg->setRegionDimensions(Ogre::Vector3(1024,1024,1024)); - sg->setVisibilityFlags(small ? RV_StaticsSmall : RV_Statics); + sg->setVisibilityFlags(small ? RV_StaticsSmall : RV_Statics); - sg->setCastShadows(true); + sg->setCastShadows(true); - sg->setRenderQueueGroup(RQG_Main); + sg->setRenderQueueGroup(RQG_Main); - anim->fillBatch(sg); - /* TODO: We could hold on to this and just detach it from the scene graph, so if the Ptr - * ever needs to modify we can reattach it and rebuild the StaticGeometry object without - * it. Would require associating the Ptr with the StaticGeometry. */ - anim.reset(); + anim->fillBatch(sg); + /* TODO: We could hold on to this and just detach it from the scene graph, so if the Ptr + * ever needs to modify we can reattach it and rebuild the StaticGeometry object without + * it. Would require associating the Ptr with the StaticGeometry. */ + anim.reset(); + } } if(anim.get() != NULL) diff --git a/apps/openmw/mwworld/fallback.cpp b/apps/openmw/mwworld/fallback.cpp index 569a6b50c..c0b21b2ef 100644 --- a/apps/openmw/mwworld/fallback.cpp +++ b/apps/openmw/mwworld/fallback.cpp @@ -41,8 +41,9 @@ namespace MWWorld unsigned int j=0; for(unsigned int i=0;i(ret[0])/255.f,boost::lexical_cast(ret[1])/255.f,boost::lexical_cast(ret[2])/255.f); } } diff --git a/apps/openmw/mwworld/store.hpp b/apps/openmw/mwworld/store.hpp index 0f8ab8682..1dfb2f976 100644 --- a/apps/openmw/mwworld/store.hpp +++ b/apps/openmw/mwworld/store.hpp @@ -685,12 +685,14 @@ namespace MWWorld typedef std::map::iterator IntIterator; //std::sort(mInt.begin(), mInt.end(), RecordCmp()); + mSharedInt.clear(); mSharedInt.reserve(mInt.size()); for (IntIterator it = mInt.begin(); it != mInt.end(); ++it) { mSharedInt.push_back(&(it->second)); } //std::sort(mExt.begin(), mExt.end(), ExtCmp()); + mSharedExt.clear(); mSharedExt.reserve(mExt.size()); for (ExtIterator it = mExt.begin(); it != mExt.end(); ++it) { mSharedExt.push_back(&(it->second)); diff --git a/components/esm/loadnpc.hpp b/components/esm/loadnpc.hpp index 08f678b45..fd3e45bdc 100644 --- a/components/esm/loadnpc.hpp +++ b/components/esm/loadnpc.hpp @@ -82,7 +82,7 @@ struct NPC char mSkills[Skill::Length]; char mReputation; - short mHealth, mMana, mFatigue; + unsigned short mHealth, mMana, mFatigue; char mDisposition, mFactionID, mRank; char mUnknown; int mGold; diff --git a/extern/oics/ICSInputControlSystem_mouse.cpp b/extern/oics/ICSInputControlSystem_mouse.cpp index be18ebbc0..fb1100528 100644 --- a/extern/oics/ICSInputControlSystem_mouse.cpp +++ b/extern/oics/ICSInputControlSystem_mouse.cpp @@ -333,11 +333,6 @@ namespace ICS } } } - else if(mDetectingBindingListener) - { - mDetectingBindingListener->mouseButtonBindingDetected(this, - mDetectingBindingControl, btn, mDetectingBindingDirection); - } } } @@ -345,11 +340,19 @@ namespace ICS { if(mActive) { - ControlsButtonBinderMapType::const_iterator it = mControlsMouseButtonBinderMap.find((int)btn); - if(it != mControlsMouseButtonBinderMap.end()) - { - it->second.control->setChangingDirection(Control::STOP); - } + if (!mDetectingBindingControl) + { + ControlsButtonBinderMapType::const_iterator it = mControlsMouseButtonBinderMap.find((int)btn); + if(it != mControlsMouseButtonBinderMap.end()) + { + it->second.control->setChangingDirection(Control::STOP); + } + } + else if(mDetectingBindingListener) + { + mDetectingBindingListener->mouseButtonBindingDetected(this, + mDetectingBindingControl, btn, mDetectingBindingDirection); + } } }