diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index c6864de36..c47ad066b 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -284,6 +284,9 @@ namespace MWBase virtual void setKeyFocusWidget (MyGUI::Widget* widget) = 0; virtual Loading::Listener* getLoadingScreen() = 0; + + /// Should the cursor be visible? + virtual bool getCursorVisible() = 0; }; } diff --git a/apps/openmw/mwgui/cursor.cpp b/apps/openmw/mwgui/cursor.cpp index c069eca15..9c64f94ca 100644 --- a/apps/openmw/mwgui/cursor.cpp +++ b/apps/openmw/mwgui/cursor.cpp @@ -73,57 +73,4 @@ namespace MWGui return mSize; } - // ---------------------------------------------------------------------------------------- - - Cursor::Cursor() - { - // hide mygui's pointer since we're rendering it ourselves (because mygui's pointer doesn't support rotation) - MyGUI::PointerManager::getInstance().setVisible(false); - - MyGUI::PointerManager::getInstance().eventChangeMousePointer += MyGUI::newDelegate(this, &Cursor::onCursorChange); - - mWidget = MyGUI::Gui::getInstance().createWidget("RotatingSkin",0,0,0,0,MyGUI::Align::Default,"Pointer",""); - - onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer()); - } - - Cursor::~Cursor() - { - } - - void Cursor::onCursorChange(const std::string &name) - { - ResourceImageSetPointerFix* imgSetPtr = dynamic_cast( - MyGUI::PointerManager::getInstance().getByName(name)); - assert(imgSetPtr != NULL); - - MyGUI::ResourceImageSet* imgSet = imgSetPtr->getImageSet(); - - std::string texture = imgSet->getIndexInfo(0,0).texture; - - mSize = imgSetPtr->getSize(); - mHotSpot = imgSetPtr->getHotSpot(); - - int rotation = imgSetPtr->getRotation(); - - mWidget->setImageTexture(texture); - MyGUI::ISubWidget* main = mWidget->getSubWidgetMain(); - MyGUI::RotatingSkin* rotatingSubskin = main->castType(); - rotatingSubskin->setCenter(MyGUI::IntPoint(mSize.width/2,mSize.height/2)); - rotatingSubskin->setAngle(Ogre::Degree(rotation).valueRadians()); - } - - void Cursor::update() - { - MyGUI::IntPoint position = MyGUI::InputManager::getInstance().getMousePosition(); - - mWidget->setPosition(position - mHotSpot); - mWidget->setSize(mSize); - } - - void Cursor::setVisible(bool visible) - { - mWidget->setVisible(visible); - } - } diff --git a/apps/openmw/mwgui/cursor.hpp b/apps/openmw/mwgui/cursor.hpp index badf82262..4e3eb9097 100644 --- a/apps/openmw/mwgui/cursor.hpp +++ b/apps/openmw/mwgui/cursor.hpp @@ -39,23 +39,6 @@ namespace MWGui int mRotation; // rotation in degrees }; - class Cursor - { - public: - Cursor(); - ~Cursor(); - void update (); - - void setVisible (bool visible); - - void onCursorChange (const std::string& name); - - private: - MyGUI::ImageBox* mWidget; - - MyGUI::IntSize mSize; - MyGUI::IntPoint mHotSpot; - }; } #endif diff --git a/apps/openmw/mwgui/messagebox.cpp b/apps/openmw/mwgui/messagebox.cpp index 48d7ec171..0a9ee0188 100644 --- a/apps/openmw/mwgui/messagebox.cpp +++ b/apps/openmw/mwgui/messagebox.cpp @@ -10,7 +10,6 @@ namespace MWGui MessageBoxManager::MessageBoxManager () { - // defines mMessageBoxSpeed = 0.1; mInterMessageBoxe = NULL; mStaticMessageBox = NULL; @@ -19,47 +18,26 @@ namespace MWGui void MessageBoxManager::onFrame (float frameDuration) { - std::vector::iterator it; - for(it = mTimers.begin(); it != mTimers.end();) + std::vector::iterator it; + for(it = mMessageBoxes.begin(); it != mMessageBoxes.end();) { - // if this messagebox is already deleted, remove the timer and move on - if (std::find(mMessageBoxes.begin(), mMessageBoxes.end(), it->messageBox) == mMessageBoxes.end()) - { - it = mTimers.erase(it); - continue; - } - - it->current += frameDuration; - if(it->current >= it->max) + (*it)->mCurrentTime += frameDuration; + if((*it)->mCurrentTime >= (*it)->mMaxTime && *it != mStaticMessageBox) { - it->messageBox->mMarkedToDelete = true; - - if(*mMessageBoxes.begin() == it->messageBox) // if this box is the last one - { - // collect all with mMarkedToDelete and delete them. - // and place the other messageboxes on the right position - int height = 0; - std::vector::iterator it2 = mMessageBoxes.begin(); - while(it2 != mMessageBoxes.end()) - { - if((*it2)->mMarkedToDelete) - { - delete (*it2); - it2 = mMessageBoxes.erase(it2); - } - else { - (*it2)->update(height); - height += (*it2)->getHeight(); - ++it2; - } - } - } - it = mTimers.erase(it); + delete *it; + it = mMessageBoxes.erase(it); } else - { ++it; - } + } + + float height = 0; + it = mMessageBoxes.begin(); + while(it != mMessageBoxes.end()) + { + (*it)->update(height); + height += (*it)->getHeight(); + ++it; } if(mInterMessageBoxe != NULL && mInterMessageBoxe->mMarkedToDelete) { @@ -74,14 +52,13 @@ namespace MWGui void MessageBoxManager::createMessageBox (const std::string& message, bool stat) { MessageBox *box = new MessageBox(*this, message); + box->mCurrentTime = 0; + box->mMaxTime = message.length()*mMessageBoxSpeed; if(stat) mStaticMessageBox = box; - else - removeMessageBox(message.length()*mMessageBoxSpeed, box); mMessageBoxes.push_back(box); - std::vector::iterator it; if(mMessageBoxes.size() > 3) { delete *mMessageBoxes.begin(); @@ -89,7 +66,7 @@ namespace MWGui } int height = 0; - for(it = mMessageBoxes.begin(); it != mMessageBoxes.end(); ++it) + for(std::vector::iterator it = mMessageBoxes.begin(); it != mMessageBoxes.end(); ++it) { (*it)->update(height); height += (*it)->getHeight(); @@ -119,15 +96,6 @@ namespace MWGui return mInterMessageBoxe != NULL; } - void MessageBoxManager::removeMessageBox (float time, MessageBox *msgbox) - { - MessageBoxManagerTimer timer; - timer.current = 0; - timer.max = time; - timer.messageBox = msgbox; - - mTimers.insert(mTimers.end(), timer); - } bool MessageBoxManager::removeMessageBox (MessageBox *msgbox) { @@ -169,12 +137,13 @@ namespace MWGui : Layout("openmw_messagebox.layout") , mMessageBoxManager(parMessageBoxManager) , mMessage(message) + , mCurrentTime(0) + , mMaxTime(0) { // defines mFixedWidth = 300; mBottomPadding = 20; mNextBoxPadding = 20; - mMarkedToDelete = false; getWidget(mMessageWidget, "message"); diff --git a/apps/openmw/mwgui/messagebox.hpp b/apps/openmw/mwgui/messagebox.hpp index 63840cfe2..ce3a85ab3 100644 --- a/apps/openmw/mwgui/messagebox.hpp +++ b/apps/openmw/mwgui/messagebox.hpp @@ -19,13 +19,6 @@ namespace MWGui class InteractiveMessageBox; class MessageBoxManager; class MessageBox; - - struct MessageBoxManagerTimer { - float current; - float max; - MessageBox *messageBox; - }; - class MessageBoxManager { public: @@ -36,7 +29,6 @@ namespace MWGui bool createInteractiveMessageBox (const std::string& message, const std::vector& buttons); bool isInteractiveMessageBox (); - void removeMessageBox (float time, MessageBox *msgbox); bool removeMessageBox (MessageBox *msgbox); void setMessageBoxSpeed (int speed); @@ -54,7 +46,6 @@ namespace MWGui std::vector mMessageBoxes; InteractiveMessageBox* mInterMessageBoxe; MessageBox* mStaticMessageBox; - std::vector mTimers; float mMessageBoxSpeed; int mLastButtonPressed; }; @@ -67,7 +58,8 @@ namespace MWGui int getHeight (); void update (int height); - bool mMarkedToDelete; + float mCurrentTime; + float mMaxTime; protected: MessageBoxManager& mMessageBoxManager; diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index b77d1a885..dc753a8fa 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -100,7 +100,6 @@ namespace MWGui , mRepair(NULL) , mCompanionWindow(NULL) , mTranslationDataStorage (translationDataStorage) - , mSoftwareCursor(NULL) , mCharGen(NULL) , mInputBlocker(NULL) , mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD")) @@ -128,7 +127,6 @@ namespace MWGui , mFPS(0.0f) , mTriangleCount(0) , mBatchCount(0) - , mUseHardwareCursors(Settings::Manager::getBool("hardware cursors", "GUI")) { // Set up the GUI system mGuiManager = new OEngine::GUI::MyGUIManager(mRendering->getWindow(), mRendering->getScene(), false, logpath); @@ -173,16 +171,19 @@ namespace MWGui mLoadingScreen->onResChange (w,h); //set up the hardware cursor manager - mSoftwareCursor = new Cursor(); mCursorManager = new SFO::SDLCursorManager(); MyGUI::PointerManager::getInstance().eventChangeMousePointer += MyGUI::newDelegate(this, &WindowManager::onCursorChange); MyGUI::InputManager::getInstance().eventChangeKeyFocus += MyGUI::newDelegate(this, &WindowManager::onKeyFocusChanged); - setUseHardwareCursors(mUseHardwareCursors); + mCursorManager->setEnabled(true); + onCursorChange(MyGUI::PointerManager::getInstance().getDefaultPointer()); - mCursorManager->cursorVisibilityChange(false); + SDL_ShowCursor(false); + + // hide mygui's pointer + MyGUI::PointerManager::getInstance().setVisible(false); } void WindowManager::initUI() @@ -313,7 +314,6 @@ namespace MWGui delete mMerchantRepair; delete mRepair; delete mSoulgemDialog; - delete mSoftwareCursor; delete mCursorManager; delete mRecharge; @@ -344,8 +344,6 @@ namespace MWGui mHud->setBatchCount(mBatchCount); mHud->update(); - - mSoftwareCursor->update(); } void WindowManager::updateVisible() @@ -879,21 +877,9 @@ namespace MWGui MWBase::Environment::get().getInputManager()->setDragDrop(dragDrop); } - void WindowManager::setUseHardwareCursors(bool use) - { - mCursorManager->setEnabled(use); - mSoftwareCursor->setVisible(!use && mCursorVisible); - } - void WindowManager::setCursorVisible(bool visible) { - if(mCursorVisible == visible) - return; - mCursorVisible = visible; - mCursorManager->cursorVisibilityChange(visible); - - mSoftwareCursor->setVisible(!mUseHardwareCursors && visible); } void WindowManager::onRetrieveTag(const MyGUI::UString& _tag, MyGUI::UString& _result) @@ -924,8 +910,6 @@ namespace MWGui mHud->setFpsLevel(Settings::Manager::getInt("fps", "HUD")); mToolTips->setDelay(Settings::Manager::getFloat("tooltip delay", "GUI")); - setUseHardwareCursors(Settings::Manager::getBool("hardware cursors", "GUI")); - for (Settings::CategorySettingVector::const_iterator it = changed.begin(); it != changed.end(); ++it) { @@ -977,8 +961,6 @@ namespace MWGui void WindowManager::onCursorChange(const std::string &name) { - mSoftwareCursor->onCursorChange(name); - if(!mCursorManager->cursorChanged(name)) return; //the cursor manager doesn't want any more info about this cursor //See if we can get the information we need out of the cursor resource @@ -1376,4 +1358,9 @@ namespace MWGui mRecharge->start(soulgem); } + bool WindowManager::getCursorVisible() + { + return mCursorVisible; + } + } diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 965c7d638..c5b6ff2be 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -278,6 +278,8 @@ namespace MWGui void onSoulgemDialogButtonPressed (int button); + virtual bool getCursorVisible(); + private: bool mConsoleOnlyScripts; @@ -369,9 +371,6 @@ namespace MWGui unsigned int mTriangleCount; unsigned int mBatchCount; - bool mUseHardwareCursors; - void setUseHardwareCursors(bool use); - /** * Called when MyGUI tries to retrieve a tag. This usually corresponds to a GMST string, * so this method will retrieve the GMST with the name \a _tag and place the result in \a _result diff --git a/apps/openmw/mwinput/inputmanagerimp.cpp b/apps/openmw/mwinput/inputmanagerimp.cpp index 9b50be7ca..6901bcdb9 100644 --- a/apps/openmw/mwinput/inputmanagerimp.cpp +++ b/apps/openmw/mwinput/inputmanagerimp.cpp @@ -264,6 +264,8 @@ namespace MWInput void InputManager::update(float dt, bool loading) { + mInputManager->setMouseVisible(MWBase::Environment::get().getWindowManager()->getCursorVisible()); + mInputManager->capture(loading); // inject some fake mouse movement to force updating MyGUI's widget states // this shouldn't do any harm since we're moving back to the original position afterwards diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index ec22c8d7f..b9a56e30c 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -211,7 +211,7 @@ namespace MWMechanics float currentDiff = creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::RestoreHealth+i)).mMagnitude - creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::DamageHealth+i)).mMagnitude - - creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::AbsorbHealth)).mMagnitude; + - creatureStats.getMagicEffects().get(EffectKey(ESM::MagicEffect::AbsorbHealth+i)).mMagnitude; stat.setCurrent(stat.getCurrent() + currentDiff * duration); creatureStats.setDynamic(i, stat); @@ -219,16 +219,34 @@ namespace MWMechanics // Apply damage ticks int damageEffects[] = { - ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison + ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison, + ESM::MagicEffect::SunDamage }; + DynamicStat health = creatureStats.getHealth(); for (unsigned int i=0; i health = creatureStats.getHealth(); - health.setCurrent(health.getCurrent() - magnitude * duration); - creatureStats.setHealth(health); + + if (damageEffects[i] == ESM::MagicEffect::SunDamage) + { + // isInCell shouldn't be needed, but updateActor called during game start + if (!ptr.isInCell() || !ptr.getCell()->isExterior()) + continue; + float time = MWBase::Environment::get().getWorld()->getTimeStamp().getHour(); + float timeDiff = std::min(7.f, std::max(0.f, std::abs(time - 13))); + float damageScale = 1.f - timeDiff / 7.f; + // When cloudy, the sun damage effect is halved + int weather = MWBase::Environment::get().getWorld()->getCurrentWeather(); + if (weather > 1) + damageScale *= 0.5; + health.setCurrent(health.getCurrent() - magnitude * duration * damageScale); + } + else + health.setCurrent(health.getCurrent() - magnitude * duration); + } + creatureStats.setHealth(health); } void Actors::calculateNpcStatModifiers (const MWWorld::Ptr& ptr) @@ -324,7 +342,7 @@ namespace MWMechanics } } - Actors::Actors() : mDuration (0) {} + Actors::Actors() {} void Actors::addActor (const MWWorld::Ptr& ptr) { @@ -377,14 +395,8 @@ namespace MWMechanics void Actors::update (float duration, bool paused) { - mDuration += duration; - - //if (mDuration>=0.25) if (!paused) { - float totalDuration = mDuration; - mDuration = 0; - for(PtrControllerMap::iterator iter(mActors.begin());iter != mActors.end();iter++) { const MWWorld::Class &cls = MWWorld::Class::get(iter->first); @@ -396,9 +408,9 @@ namespace MWMechanics if(iter->second->isDead()) iter->second->resurrect(); - updateActor(iter->first, totalDuration); + updateActor(iter->first, duration); if(iter->first.getTypeName() == typeid(ESM::NPC).name()) - updateNpc(iter->first, totalDuration, paused); + updateNpc(iter->first, duration, paused); if(!stats.isDead()) continue; diff --git a/apps/openmw/mwmechanics/actors.hpp b/apps/openmw/mwmechanics/actors.hpp index 01a96f199..b733c966b 100644 --- a/apps/openmw/mwmechanics/actors.hpp +++ b/apps/openmw/mwmechanics/actors.hpp @@ -30,8 +30,6 @@ namespace MWMechanics std::map mDeathCount; - float mDuration; - void updateNpc(const MWWorld::Ptr &ptr, float duration, bool paused); diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 859d8d699..9f7073d2a 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -157,7 +157,7 @@ namespace MWMechanics } } else - applyInstantEffect(mTarget, effectIt->mEffectID, magnitude); + applyInstantEffect(target, effectIt->mEffectID, magnitude); if (target.getClass().isActor() || magicEffect->mData.mFlags & ESM::MagicEffect::NoDuration) { diff --git a/apps/openmw/mwmechanics/spells.cpp b/apps/openmw/mwmechanics/spells.cpp index 5b18e2a3c..6e7ac6f31 100644 --- a/apps/openmw/mwmechanics/spells.cpp +++ b/apps/openmw/mwmechanics/spells.cpp @@ -66,7 +66,7 @@ namespace MWMechanics int i=0; for (std::vector::const_iterator it = spell->mEffects.mList.begin(); it != spell->mEffects.mList.end(); ++it) { - effects.add (*it, iter->second[i]); + effects.add (*it, it->mMagnMin + (it->mMagnMax - it->mMagnMin) * iter->second[i]); ++i; } } diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index b9818efbb..2cae30611 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -72,7 +72,6 @@ namespace MWRender mAnimation = new NpcAnimation(mCharacter, mNode, 0, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); - mAnimation->updateParts(); Ogre::Vector3 scale = mNode->getScale(); mCamera->setPosition(mPosition * scale); @@ -114,7 +113,6 @@ namespace MWRender delete mAnimation; mAnimation = new NpcAnimation(mCharacter, mNode, 0, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); - mAnimation->updateParts(); float scale=1.f; MWWorld::Class::get(mCharacter).adjustScale(mCharacter, scale); @@ -142,6 +140,9 @@ namespace MWRender void InventoryPreview::update(int sizeX, int sizeY) { + // TODO: can we avoid this. Vampire state needs to be updated. + mAnimation->rebuild(); + MWWorld::InventoryStore &inv = MWWorld::Class::get(mCharacter).getInventoryStore(mCharacter); MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); std::string groupname; @@ -176,11 +177,12 @@ namespace MWRender groupname = "inventoryhandtohand"; } - if(groupname != mCurrentAnimGroup) - { + // TODO see above + //if(groupname != mCurrentAnimGroup) + //{ mCurrentAnimGroup = groupname; mAnimation->play(mCurrentAnimGroup, 1, Animation::Group_All, false, 1.0f, "start", "stop", 0.0f, 0); - } + //} MWWorld::ContainerStoreIterator torch = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); if(torch != inv.end() && torch->getTypeName() == typeid(ESM::Light).name()) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index c71428941..093a40c8e 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -19,6 +19,42 @@ #include "renderconst.hpp" #include "camera.hpp" +namespace +{ + +std::string getVampireHead(const std::string& race, bool female) +{ + static std::map , const ESM::BodyPart* > sVampireMapping; + + std::pair thisCombination = std::make_pair(race, int(female)); + + if (sVampireMapping.find(thisCombination) == sVampireMapping.end()) + { + const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); + const MWWorld::Store &partStore = store.get(); + for(MWWorld::Store::iterator it = partStore.begin(); it != partStore.end(); ++it) + { + const ESM::BodyPart& bodypart = *it; + if (!bodypart.mData.mVampire) + continue; + if (bodypart.mData.mType != ESM::BodyPart::MT_Skin) + continue; + if (bodypart.mData.mPart != ESM::BodyPart::MP_Head) + continue; + if (female != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female)) + continue; + if (!Misc::StringUtils::ciEqual(bodypart.mRace, race)) + continue; + sVampireMapping[thisCombination] = &*it; + } + } + + assert(sVampireMapping[thisCombination]); + return "meshes\\" + sVampireMapping[thisCombination]->mModel; +} + +} + namespace MWRender { @@ -110,17 +146,22 @@ void NpcAnimation::updateNpcBase() const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore(); const ESM::Race *race = store.get().find(mNpc->mRace); - bool isWerewolf = MWWorld::Class::get(mPtr).getNpcStats(mPtr).isWerewolf(); + bool isWerewolf = mPtr.getClass().getNpcStats(mPtr).isWerewolf(); + bool vampire = mPtr.getClass().getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Vampirism).mMagnitude; - if(!isWerewolf) + if (isWerewolf) { - mHeadModel = "meshes\\" + store.get().find(mNpc->mHead)->mModel; - mHairModel = "meshes\\" + store.get().find(mNpc->mHair)->mModel; + mHeadModel = "meshes\\" + store.get().find("WerewolfHead")->mModel; + mHairModel = "meshes\\" + store.get().find("WerewolfHair")->mModel; } else { - mHeadModel = "meshes\\" + store.get().find("WerewolfHead")->mModel; - mHairModel = "meshes\\" + store.get().find("WerewolfHair")->mModel; + if (vampire) + mHeadModel = getVampireHead(mNpc->mRace, mNpc->mFlags & ESM::NPC::Female); + else + mHeadModel = "meshes\\" + store.get().find(mNpc->mHead)->mModel; + + mHairModel = "meshes\\" + store.get().find(mNpc->mHair)->mModel; } bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0; @@ -270,6 +311,8 @@ void NpcAnimation::updateParts() // Remember body parts so we only have to search through the store once for each race/gender/viewmode combination static std::map< std::pair,std::vector > sRaceMapping; + static std::map , std::vector > sVampireMapping; + static const int Flag_Female = 1<<0; static const int Flag_FirstPerson = 1<<1; diff --git a/extern/sdl4ogre/cursormanager.hpp b/extern/sdl4ogre/cursormanager.hpp index f45c5cdc2..35ec92a70 100644 --- a/extern/sdl4ogre/cursormanager.hpp +++ b/extern/sdl4ogre/cursormanager.hpp @@ -22,9 +22,6 @@ public: /// \brief Follow up a cursorChanged() call with enough info to create an cursor. virtual void receiveCursorInfo(const std::string &name, int rotDegrees, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y) = 0; - /// \brief Tell the manager when the cursor visibility changed - virtual void cursorVisibilityChange(bool visible) = 0; - /// \brief sets whether to actively manage cursors or not virtual void setEnabled(bool enabled) = 0; }; diff --git a/extern/sdl4ogre/sdlcursormanager.cpp b/extern/sdl4ogre/sdlcursormanager.cpp index d14a9ffa0..65fb7f98b 100644 --- a/extern/sdl4ogre/sdlcursormanager.cpp +++ b/extern/sdl4ogre/sdlcursormanager.cpp @@ -10,7 +10,6 @@ namespace SFO SDLCursorManager::SDLCursorManager() : mEnabled(false), - mCursorVisible(false), mInitialized(false) { } @@ -70,27 +69,7 @@ namespace SFO void SDLCursorManager::_setGUICursor(const std::string &name) { - if(mEnabled && mCursorVisible) - { - SDL_SetCursor(mCursorMap.find(name)->second); - _setCursorVisible(mCursorVisible); - } - } - - void SDLCursorManager::_setCursorVisible(bool visible) - { - if(!mEnabled) - return; - - SDL_ShowCursor(visible ? SDL_TRUE : SDL_FALSE); - } - - void SDLCursorManager::cursorVisibilityChange(bool visible) - { - mCursorVisible = visible; - - _setGUICursor(mCurrentCursor); - _setCursorVisible(visible); + SDL_SetCursor(mCursorMap.find(name)->second); } void SDLCursorManager::receiveCursorInfo(const std::string& name, int rotDegrees, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y) diff --git a/extern/sdl4ogre/sdlcursormanager.hpp b/extern/sdl4ogre/sdlcursormanager.hpp index 8940220d4..7ba69f013 100644 --- a/extern/sdl4ogre/sdlcursormanager.hpp +++ b/extern/sdl4ogre/sdlcursormanager.hpp @@ -19,14 +19,12 @@ namespace SFO virtual bool cursorChanged(const std::string &name); virtual void receiveCursorInfo(const std::string &name, int rotDegrees, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y); - virtual void cursorVisibilityChange(bool visible); private: void _createCursorFromResource(const std::string &name, int rotDegrees, Ogre::TexturePtr tex, Uint8 size_x, Uint8 size_y, Uint8 hotspot_x, Uint8 hotspot_y); void _putPixel(SDL_Surface *surface, int x, int y, Uint32 pixel); void _setGUICursor(const std::string& name); - void _setCursorVisible(bool visible); typedef std::map CursorMap; CursorMap mCursorMap; @@ -34,7 +32,6 @@ namespace SFO std::string mCurrentCursor; bool mEnabled; bool mInitialized; - bool mCursorVisible; }; } diff --git a/extern/sdl4ogre/sdlinputwrapper.cpp b/extern/sdl4ogre/sdlinputwrapper.cpp index 5c0eff1c0..9990e828a 100644 --- a/extern/sdl4ogre/sdlinputwrapper.cpp +++ b/extern/sdl4ogre/sdlinputwrapper.cpp @@ -23,7 +23,11 @@ namespace SFO mJoyListener(NULL), mKeyboardListener(NULL), mMouseListener(NULL), - mWindowListener(NULL) + mWindowListener(NULL), + mWindowHasFocus(true), + mWantGrab(false), + mWantRelative(false), + mWantMouseVisible(false) { _setupOISKeys(); } @@ -51,13 +55,16 @@ namespace SFO switch(evt.type) { case SDL_MOUSEMOTION: - //ignore this if it happened due to a warp + // Ignore this if it happened due to a warp if(!_handleWarpMotion(evt.motion)) { - mMouseListener->mouseMoved(_packageMouseMotion(evt)); + // If in relative mode, don't trigger events unless window has focus + if (!mWantRelative || mWindowHasFocus) + mMouseListener->mouseMoved(_packageMouseMotion(evt)); - //try to keep the mouse inside the window - _wrapMousePointer(evt.motion); + // Try to keep the mouse inside the window + if (mWindowHasFocus) + _wrapMousePointer(evt.motion); } break; case SDL_MOUSEWHEEL: @@ -118,11 +125,11 @@ namespace SFO switch (evt.window.event) { case SDL_WINDOWEVENT_ENTER: mMouseInWindow = true; + updateMouseSettings(); break; case SDL_WINDOWEVENT_LEAVE: mMouseInWindow = false; - SDL_SetWindowGrab(mSDLWindow, SDL_FALSE); - SDL_SetRelativeMouseMode(SDL_FALSE); + updateMouseSettings(); break; case SDL_WINDOWEVENT_SIZE_CHANGED: int w,h; @@ -149,10 +156,15 @@ namespace SFO break; case SDL_WINDOWEVENT_FOCUS_GAINED: + mWindowHasFocus = true; + updateMouseSettings(); if (mWindowListener) mWindowListener->windowFocusChange(true); + break; case SDL_WINDOWEVENT_FOCUS_LOST: + mWindowHasFocus = false; + updateMouseSettings(); if (mWindowListener) mWindowListener->windowFocusChange(false); break; @@ -193,25 +205,43 @@ namespace SFO /// \brief Locks the pointer to the window void InputWrapper::setGrabPointer(bool grab) { - mGrabPointer = grab && mMouseInWindow; - SDL_SetWindowGrab(mSDLWindow, grab && mMouseInWindow ? SDL_TRUE : SDL_FALSE); + mWantGrab = grab; + updateMouseSettings(); } /// \brief Set the mouse to relative positioning. Doesn't move the cursor /// and disables mouse acceleration. void InputWrapper::setMouseRelative(bool relative) { - if(mMouseRelative == relative && mMouseInWindow) + mWantRelative = relative; + updateMouseSettings(); + } + + void InputWrapper::setMouseVisible(bool visible) + { + mWantMouseVisible = visible; + updateMouseSettings(); + } + + void InputWrapper::updateMouseSettings() + { + mGrabPointer = mWantGrab && mMouseInWindow && mWindowHasFocus; + SDL_SetWindowGrab(mSDLWindow, mGrabPointer ? SDL_TRUE : SDL_FALSE); + + SDL_ShowCursor(mWantMouseVisible || !mWindowHasFocus); + + bool relative = mWantRelative && mMouseInWindow && mWindowHasFocus; + if(mMouseRelative == relative) return; - mMouseRelative = relative && mMouseInWindow; + mMouseRelative = relative; mWrapPointer = false; //eep, wrap the pointer manually if the input driver doesn't support //relative positioning natively - int success = SDL_SetRelativeMouseMode(relative && mMouseInWindow ? SDL_TRUE : SDL_FALSE); - if(relative && mMouseInWindow && success != 0) + int success = SDL_SetRelativeMouseMode(relative ? SDL_TRUE : SDL_FALSE); + if(relative && success != 0) mWrapPointer = true; //now remove all mouse events using the old setting from the queue diff --git a/extern/sdl4ogre/sdlinputwrapper.hpp b/extern/sdl4ogre/sdlinputwrapper.hpp index 1bd8947a0..ca57464e9 100644 --- a/extern/sdl4ogre/sdlinputwrapper.hpp +++ b/extern/sdl4ogre/sdlinputwrapper.hpp @@ -28,6 +28,7 @@ namespace SFO bool isModifierHeld(SDL_Keymod mod); bool isKeyDown(SDL_Scancode key); + void setMouseVisible (bool visible); void setMouseRelative(bool relative); bool getMouseRelative() { return mMouseRelative; } void setGrabPointer(bool grab); @@ -36,6 +37,8 @@ namespace SFO void warpMouse(int x, int y); + void updateMouseSettings(); + private: void handleWindowEvent(const SDL_Event& evt); @@ -57,14 +60,19 @@ namespace SFO Uint16 mWarpX; Uint16 mWarpY; bool mWarpCompensate; - bool mMouseRelative; bool mWrapPointer; + + bool mWantMouseVisible; + bool mWantGrab; + bool mWantRelative; bool mGrabPointer; + bool mMouseRelative; Sint32 mMouseZ; Sint32 mMouseX; Sint32 mMouseY; + bool mWindowHasFocus; bool mMouseInWindow; SDL_Window* mSDLWindow;