From 566211e7532e1b30f3429b7c0f06198c4f9fdf50 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Fri, 3 Oct 2014 22:39:05 +0200 Subject: [PATCH 01/32] Issue #1887: Equipped items do not emit sounds Added playing of sounds for equipped items (at this moment only for lights). Signed-off-by: Lukasz Gromanowski --- apps/openmw/mwworld/actionequip.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 50da1e5e5..165a8e192 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -3,6 +3,7 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" +#include "../mwbase/soundmanager.hpp" #include @@ -85,5 +86,18 @@ namespace MWWorld invStore.equip(*slot, it, actor); } } + + std::string sound; + + if (object.getTypeName() == typeid(ESM::Light).name()) + { + sound = object.get()->mBase->mSound; + } + if (!sound.empty()) + { + MWBase::Environment::get().getSoundManager()->playSound(sound, 1.0f, 1.0f, + MWBase::SoundManager::Play_TypeSfx, + MWBase::SoundManager::Play_Loop); + } } } From 6a89b67cb1bc22cdd092c81d7a5805ac9def05cb Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 4 Oct 2014 13:34:36 +0200 Subject: [PATCH 02/32] Revert "Issue #1887: Equipped items do not emit sounds" This reverts commit 566211e7532e1b30f3429b7c0f06198c4f9fdf50. --- apps/openmw/mwworld/actionequip.cpp | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/apps/openmw/mwworld/actionequip.cpp b/apps/openmw/mwworld/actionequip.cpp index 165a8e192..50da1e5e5 100644 --- a/apps/openmw/mwworld/actionequip.cpp +++ b/apps/openmw/mwworld/actionequip.cpp @@ -3,7 +3,6 @@ #include "../mwbase/environment.hpp" #include "../mwbase/world.hpp" #include "../mwbase/windowmanager.hpp" -#include "../mwbase/soundmanager.hpp" #include @@ -86,18 +85,5 @@ namespace MWWorld invStore.equip(*slot, it, actor); } } - - std::string sound; - - if (object.getTypeName() == typeid(ESM::Light).name()) - { - sound = object.get()->mBase->mSound; - } - if (!sound.empty()) - { - MWBase::Environment::get().getSoundManager()->playSound(sound, 1.0f, 1.0f, - MWBase::SoundManager::Play_TypeSfx, - MWBase::SoundManager::Play_Loop); - } } } From e566e4abf2a41a2e45e6833f0104ea7804a58e9c Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 4 Oct 2014 16:47:29 +0200 Subject: [PATCH 03/32] Issue #1887: Equipped items do not emit sounds Added playing of sounds for equipped items (at this moment only for lights). Signed-off-by: Lukasz Gromanowski --- apps/openmw/mwrender/npcanimation.cpp | 28 ++++++++++++++++++++++++++ apps/openmw/mwrender/npcanimation.hpp | 4 ++++ apps/openmw/mwworld/inventorystore.cpp | 13 ++++++------ apps/openmw/mwworld/inventorystore.hpp | 12 +++++++++-- 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 9e93bd314..abf2264af 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -928,4 +928,32 @@ void NpcAnimation::applyAlpha(float alpha, Ogre::Entity *ent, NifOgre::ObjectSce } } +void NpcAnimation::equipmentChanged (const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state) +{ + if (actor.getRefData().getHandle() == "player" && !item.isEmpty()) + { + std::string soundId; + + if (item.getTypeName() == typeid(ESM::Light).name()) + { + soundId = item.get()->mBase->mSound; + } + + if (!soundId.empty()) + { + MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); + + if (state == InventoryStoreListener::EQUIPPED) + { + sndMgr->playSound3D(mPtr, soundId, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, + MWBase::SoundManager::Play_Loop); + } + else if (state == InventoryStoreListener::UNEQUIPPED) + { + sndMgr->stopSound3D(mPtr, soundId); + } + } + } +} + } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 979210591..a6e927fce 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -114,6 +114,10 @@ private: void applyAlpha(float alpha, Ogre::Entity* ent, NifOgre::ObjectScenePtr scene); + /** + * Implementation of MWWorld::InventoryStoreListener equipmentChanged method + */ + void equipmentChanged (const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state); public: /** * @param ptr diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index f515f1efb..49db0025a 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -146,7 +146,8 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite flagAsModified(); - fireEquipmentChangedEvent(); + fireEquipmentChangedEvent(actor, *iterator, InventoryStoreListener::EQUIPPED); + updateMagicEffects(actor); } @@ -157,7 +158,7 @@ void MWWorld::InventoryStore::unequipAll(const MWWorld::Ptr& actor) for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) unequipSlot(slot, actor); mUpdatesEnabled = true; - fireEquipmentChangedEvent(); + fireEquipmentChangedEvent(actor, MWWorld::Ptr(), InventoryStoreListener::ALL_UNEQUIPPED); updateMagicEffects(actor); } @@ -286,7 +287,7 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) if (changed) { mSlots.swap (slots_); - fireEquipmentChangedEvent(); + fireEquipmentChangedEvent(actor, MWWorld::Ptr(), InventoryStoreListener::AUTOEQUIPPED); updateMagicEffects(actor); flagAsModified(); } @@ -519,7 +520,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipSlot(int slot, c } } - fireEquipmentChangedEvent(); + fireEquipmentChangedEvent(actor, *it, InventoryStoreListener::UNEQUIPPED); updateMagicEffects(actor); return retval; @@ -546,12 +547,12 @@ void MWWorld::InventoryStore::setListener(InventoryStoreListener *listener, cons updateMagicEffects(actor); } -void MWWorld::InventoryStore::fireEquipmentChangedEvent() +void MWWorld::InventoryStore::fireEquipmentChangedEvent(const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state) { if (!mUpdatesEnabled) return; if (mListener) - mListener->equipmentChanged(); + mListener->equipmentChanged(actor, item, state); } void MWWorld::InventoryStore::visitEffectSources(MWMechanics::EffectSourceVisitor &visitor) diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index 41caae4e5..475f810af 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -20,10 +20,18 @@ namespace MWWorld class InventoryStoreListener { public: + enum State + { + EQUIPPED, + AUTOEQUIPPED, + UNEQUIPPED, + ALL_UNEQUIPPED + }; + /** * Fired when items are equipped or unequipped */ - virtual void equipmentChanged () {} + virtual void equipmentChanged (const MWWorld::Ptr& /*actor*/, const MWWorld::Ptr& /*item*/, State /*state*/) {} /** * @param effect @@ -109,7 +117,7 @@ namespace MWWorld void updateMagicEffects(const Ptr& actor); void updateRechargingItems(); - void fireEquipmentChangedEvent(); + void fireEquipmentChangedEvent(const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state); virtual int getSlot (const MWWorld::LiveCellRefBase& ref) const; ///< Return inventory slot that \a ref is in or -1 (if \a ref is not in a slot). From bcb38c3eba9a2233dbd1df02acc2dfeeac5011ae Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 4 Oct 2014 22:27:23 +0200 Subject: [PATCH 04/32] Issue #1887: Equipped items do not emit sounds Added handling of autoEquip and unequipAll cases. Signed-off-by: Lukasz Gromanowski --- apps/openmw/mwrender/npcanimation.cpp | 79 +++++++++++++++++++++----- apps/openmw/mwrender/npcanimation.hpp | 8 +-- apps/openmw/mwworld/inventorystore.cpp | 23 +++++--- apps/openmw/mwworld/inventorystore.hpp | 9 +-- 4 files changed, 86 insertions(+), 33 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index abf2264af..6e8640377 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -186,7 +186,9 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v mShowCarriedLeft(true), mFirstPersonOffset(0.f, 0.f, 0.f), mAlpha(1.f), - mNpcType(Type_Normal) + mNpcType(Type_Normal), + mUnequipping(false), + mFirstEquip(true) { mNpc = mPtr.get()->mBase; @@ -928,31 +930,78 @@ void NpcAnimation::applyAlpha(float alpha, Ogre::Entity *ent, NifOgre::ObjectSce } } -void NpcAnimation::equipmentChanged (const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state) +void NpcAnimation::equipmentChanged(const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state) { - if (actor.getRefData().getHandle() == "player" && !item.isEmpty()) + if (actor.getRefData().getHandle() == "player") { std::string soundId; - if (item.getTypeName() == typeid(ESM::Light).name()) - { - soundId = item.get()->mBase->mSound; - } + MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); - if (!soundId.empty()) + if (state == InventoryStoreListener::EQUIP + || state == InventoryStoreListener::UNEQUIP) { - MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); - - if (state == InventoryStoreListener::EQUIPPED) + if (item.getTypeName() == typeid(ESM::Light).name()) { - sndMgr->playSound3D(mPtr, soundId, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, - MWBase::SoundManager::Play_Loop); + soundId = item.get()->mBase->mSound; } - else if (state == InventoryStoreListener::UNEQUIPPED) + + if (!soundId.empty()) { - sndMgr->stopSound3D(mPtr, soundId); + if (state == InventoryStoreListener::EQUIP) + { + sndMgr->playSound3D(mPtr, soundId, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, + MWBase::SoundManager::Play_Loop); + } + else + { + sndMgr->stopSound3D(mPtr, soundId); + } } } + else if (state == InventoryStoreListener::AUTOEQUIP) + { + const MWWorld::Class &cls = mPtr.getClass(); + MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr); + for (int i = MWWorld::InventoryStore::Slot_Helmet; i < MWWorld::InventoryStore::Slots; ++i) + { + MWWorld::ContainerStoreIterator store = inv.getSlot(i); + + if (store != inv.end() && store->getTypeName() == typeid(ESM::Light).name()) + { + soundId = store->get()->mBase->mSound; + } + + if (!soundId.empty()) + { + sndMgr->playSound3D(mPtr, soundId, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, + MWBase::SoundManager::Play_Loop); + } + } + } + } + + /** + * AUTOEQUIP is triggered just after setting listener (ie. when game is loaded from savegame), + * but not all things are initialized yet, so we have to check it (mFirstEquip variable) + * and skip one call to updateParts() method. + * + * Also call to updateParts() method will be called only once if inventory.unequipAll() + * was called (mUnequipping == true). + */ + if (state == InventoryStoreListener::UNEQUIPALL_BEGIN) + mUnequipping = true; + else if (state == InventoryStoreListener::UNEQUIPALL_END) + mUnequipping = false; + + if (!mUnequipping && !mFirstEquip) + { + updateParts(); + } + + if (mFirstEquip && state == InventoryStoreListener::AUTOEQUIP) + { + mFirstEquip = false; } } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index a6e927fce..83f85abe0 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -51,7 +51,7 @@ public: class NpcAnimation : public Animation, public WeaponAnimation, public MWWorld::InventoryStoreListener { public: - virtual void equipmentChanged() { updateParts(); } + virtual void equipmentChanged(const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state); virtual void permanentEffectAdded(const ESM::MagicEffect *magicEffect, bool isNew, bool playSound); public: @@ -97,6 +97,8 @@ private: Ogre::SharedPtr mWeaponAnimationTime; float mAlpha; + bool mUnequipping; + bool mFirstEquip; void updateNpcBase(); @@ -114,10 +116,6 @@ private: void applyAlpha(float alpha, Ogre::Entity* ent, NifOgre::ObjectScenePtr scene); - /** - * Implementation of MWWorld::InventoryStoreListener equipmentChanged method - */ - void equipmentChanged (const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state); public: /** * @param ptr diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index 49db0025a..db58af32a 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -146,19 +146,18 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite flagAsModified(); - fireEquipmentChangedEvent(actor, *iterator, InventoryStoreListener::EQUIPPED); + fireEquipmentChangedEvent(actor, *iterator, InventoryStoreListener::EQUIP); updateMagicEffects(actor); } void MWWorld::InventoryStore::unequipAll(const MWWorld::Ptr& actor) { - // Only *one* change event should be fired - mUpdatesEnabled = false; + fireEquipmentChangedEvent(actor, MWWorld::Ptr(), InventoryStoreListener::UNEQUIPALL_BEGIN); for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) unequipSlot(slot, actor); - mUpdatesEnabled = true; - fireEquipmentChangedEvent(actor, MWWorld::Ptr(), InventoryStoreListener::ALL_UNEQUIPPED); + + fireEquipmentChangedEvent(actor, MWWorld::Ptr(), InventoryStoreListener::UNEQUIPALL_END); updateMagicEffects(actor); } @@ -277,17 +276,19 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) bool changed = false; for (std::size_t i=0; iequipmentChanged(actor, MWWorld::Ptr(), InventoryStoreListener::AUTOEQUIP); + } } void MWWorld::InventoryStore::fireEquipmentChangedEvent(const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state) diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index 475f810af..fb6d2919b 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -22,10 +22,11 @@ namespace MWWorld public: enum State { - EQUIPPED, - AUTOEQUIPPED, - UNEQUIPPED, - ALL_UNEQUIPPED + EQUIP, + AUTOEQUIP, + UNEQUIP, + UNEQUIPALL_BEGIN, + UNEQUIPALL_END }; /** From de2cb8926a551cb9c4f7366f09011dc24a44d491 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Sun, 5 Oct 2014 17:53:50 +0200 Subject: [PATCH 05/32] Feature #1697: Queue fade operations, implement hit fader & werewolf overlay --- apps/openmw/mwbase/windowmanager.hpp | 3 + apps/openmw/mwclass/npc.cpp | 3 + apps/openmw/mwgui/screenfader.cpp | 190 ++++++++++++++++--------- apps/openmw/mwgui/screenfader.hpp | 54 +++++-- apps/openmw/mwgui/windowmanagerimp.cpp | 41 +++++- apps/openmw/mwgui/windowmanagerimp.hpp | 7 + apps/openmw/mwworld/worldimp.cpp | 2 + files/settings-default.cfg | 3 + 8 files changed, 219 insertions(+), 84 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index 58fa221e6..c2b02452a 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -338,6 +338,9 @@ namespace MWBase /// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading. virtual void setScreenFactor (float factor) = 0; + virtual void activateHitOverlay() = 0; + virtual void setWerewolfOverlay(bool set) = 0; + virtual void toggleDebugWindow() = 0; }; } diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 5d5b8a689..b4c1ad13a 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -778,6 +778,9 @@ namespace MWClass sndMgr->playSound3D(ptr, "Health Damage", 1.0f, 1.0f); float health = getCreatureStats(ptr).getHealth().getCurrent() - damage; setActorHealth(ptr, health, attacker); + + if (ptr.getRefData().getHandle() == "player") + MWBase::Environment::get().getWindowManager()->activateHitOverlay(); } else { diff --git a/apps/openmw/mwgui/screenfader.cpp b/apps/openmw/mwgui/screenfader.cpp index c27737285..1adfdef05 100644 --- a/apps/openmw/mwgui/screenfader.cpp +++ b/apps/openmw/mwgui/screenfader.cpp @@ -3,43 +3,86 @@ namespace MWGui { - ScreenFader::ScreenFader() + FadeOp::FadeOp(ScreenFader * fader, float time, float targetAlpha) + : mFader(fader), + mRemainingTime(time), + mTargetTime(time), + mTargetAlpha(targetAlpha), + mStartAlpha(0.f), + mRunning(false) + { + } + + bool FadeOp::isRunning() + { + return mRunning; + } + + void FadeOp::start() + { + if (mRunning) + return; + + mRemainingTime = mTargetTime; + mStartAlpha = mFader->getCurrentAlpha(); + mRunning = true; + } + + void FadeOp::update(float dt) + { + if (!mRunning) + return; + + if (mRemainingTime <= 0 || mStartAlpha == mTargetAlpha) + { + finish(); + return; + } + + float currentAlpha = mFader->getCurrentAlpha(); + if (mStartAlpha > mTargetAlpha) + { + currentAlpha -= dt/mTargetTime * (mStartAlpha-mTargetAlpha); + if (currentAlpha < mTargetAlpha) + currentAlpha = mTargetAlpha; + } + else + { + currentAlpha += dt/mTargetTime * (mTargetAlpha-mStartAlpha); + if (currentAlpha > mTargetAlpha) + currentAlpha = mTargetAlpha; + } + + mFader->notifyAlphaChanged(currentAlpha); + + mRemainingTime -= dt; + } + + void FadeOp::finish() + { + mRunning = false; + mFader->notifyOperationFinished(); + } + + ScreenFader::ScreenFader(const std::string & texturePath) : WindowBase("openmw_screen_fader.layout") - , mMode(FadingMode_In) - , mRemainingTime(0.f) - , mTargetTime(0.f) - , mTargetAlpha(0.f) , mCurrentAlpha(0.f) - , mStartAlpha(0.f) , mFactor(1.f) + , mRepeat(false) { mMainWidget->setSize(MyGUI::RenderManager::getInstance().getViewSize()); - + mMainWidget->setProperty("ImageTexture", texturePath); setVisible(false); } void ScreenFader::update(float dt) { - if (mRemainingTime > 0) + if (!mQueue.empty()) { - if (mMode == FadingMode_In) - { - mCurrentAlpha -= dt/mTargetTime * (mStartAlpha-mTargetAlpha); - if (mCurrentAlpha < mTargetAlpha) mCurrentAlpha = mTargetAlpha; - } - else if (mMode == FadingMode_Out) - { - mCurrentAlpha += dt/mTargetTime * (mTargetAlpha-mStartAlpha); - if (mCurrentAlpha > mTargetAlpha) mCurrentAlpha = mTargetAlpha; - } - - mRemainingTime -= dt; + if (!mQueue.front()->isRunning()) + mQueue.front()->start(); + mQueue.front()->update(dt); } - - if (1.f-((1.f-mCurrentAlpha) * mFactor) == 0.f) - mMainWidget->setVisible(false); - else - applyAlpha(); } void ScreenFader::applyAlpha() @@ -50,57 +93,17 @@ namespace MWGui void ScreenFader::fadeIn(float time) { - if (time<0.f) return; - if (time==0.f) - { - mCurrentAlpha = 0.f; - applyAlpha(); - return; - } - - mStartAlpha = mCurrentAlpha; - mTargetAlpha = 0.f; - mMode = FadingMode_In; - mTargetTime = time; - mRemainingTime = time; + queue(time, 0.f); } void ScreenFader::fadeOut(const float time) { - if (time<0.f) return; - if (time==0.f) - { - mCurrentAlpha = 1.f; - applyAlpha(); - return; - } - - mStartAlpha = mCurrentAlpha; - mTargetAlpha = 1.f; - mMode = FadingMode_Out; - mTargetTime = time; - mRemainingTime = time; + queue(time, 1.f); } void ScreenFader::fadeTo(const int percent, const float time) { - if (time<0.f) return; - if (time==0.f) - { - mCurrentAlpha = percent/100.f; - applyAlpha(); - return; - } - - mStartAlpha = mCurrentAlpha; - mTargetAlpha = percent/100.f; - - if (mTargetAlpha == mStartAlpha) return; - else if (mTargetAlpha > mStartAlpha) mMode = FadingMode_Out; - else mMode = FadingMode_In; - - mTargetTime = time; - mRemainingTime = time; + queue(time, percent/100.f); } void ScreenFader::setFactor(float factor) @@ -108,4 +111,55 @@ namespace MWGui mFactor = factor; } + void ScreenFader::setRepeat(bool repeat) + { + mRepeat = repeat; + } + + void ScreenFader::queue(float time, float targetAlpha) + { + if (time < 0.f) + return; + + if (time == 0.f) + { + mCurrentAlpha = targetAlpha; + applyAlpha(); + return; + } + + mQueue.push_back(FadeOp::Ptr(new FadeOp(this, time, targetAlpha))); + } + + void ScreenFader::clearQueue() + { + mQueue.clear(); + } + + void ScreenFader::notifyAlphaChanged(float alpha) + { + if (mCurrentAlpha == alpha) + return; + + mCurrentAlpha = alpha; + + if (1.f-((1.f-mCurrentAlpha) * mFactor) == 0.f) + mMainWidget->setVisible(false); + else + applyAlpha(); + } + + void ScreenFader::notifyOperationFinished() + { + FadeOp::Ptr op = mQueue.front(); + mQueue.pop_front(); + + if (mRepeat) + mQueue.push_back(op); + } + + float ScreenFader::getCurrentAlpha() + { + return mCurrentAlpha; + } } diff --git a/apps/openmw/mwgui/screenfader.hpp b/apps/openmw/mwgui/screenfader.hpp index 975006a85..07b6992ba 100644 --- a/apps/openmw/mwgui/screenfader.hpp +++ b/apps/openmw/mwgui/screenfader.hpp @@ -1,15 +1,42 @@ #ifndef OPENMW_MWGUI_SCREENFADER_H #define OPENMW_MWGUI_SCREENFADER_H +#include + +#include + #include "windowbase.hpp" namespace MWGui { + class ScreenFader; + + class FadeOp + { + public: + typedef boost::shared_ptr Ptr; + + FadeOp(ScreenFader * fader, float time, float targetAlpha); + + bool isRunning(); + + void start(); + void update(float dt); + void finish(); + + private: + ScreenFader * mFader; + float mRemainingTime; + float mTargetTime; + float mTargetAlpha; + float mStartAlpha; + bool mRunning; + }; class ScreenFader : public WindowBase { public: - ScreenFader(); + ScreenFader(const std::string & texturePath); void update(float dt); @@ -18,27 +45,24 @@ namespace MWGui void fadeTo(const int percent, const float time); void setFactor (float factor); + void setRepeat(bool repeat); + + void queue(float time, float targetAlpha); + void clearQueue(); + + void notifyAlphaChanged(float alpha); + void notifyOperationFinished(); + float getCurrentAlpha(); private: - enum FadingMode - { - FadingMode_In, - FadingMode_Out - }; - void applyAlpha(); - FadingMode mMode; - - float mRemainingTime; - float mTargetTime; - float mTargetAlpha; float mCurrentAlpha; - float mStartAlpha; - float mFactor; - }; + bool mRepeat; // repeat queued operations without removing them + std::deque mQueue; + }; } #endif diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 16295d3a5..ba880ddc9 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -120,6 +120,8 @@ namespace MWGui , mCompanionWindow(NULL) , mVideoBackground(NULL) , mVideoWidget(NULL) + , mHitFader(NULL) + , mWerewolfFader(NULL) , mScreenFader(NULL) , mDebugWindow(NULL) , mTranslationDataStorage (translationDataStorage) @@ -127,6 +129,8 @@ namespace MWGui , mInputBlocker(NULL) , mCrosshairEnabled(Settings::Manager::getBool ("crosshair", "HUD")) , mSubtitlesEnabled(Settings::Manager::getBool ("subtitles", "GUI")) + , mHitFaderEnabled(Settings::Manager::getBool ("hit fader", "GUI")) + , mWerewolfOverlayEnabled(Settings::Manager::getBool ("werewolf overlay", "GUI")) , mHudEnabled(true) , mGuiEnabled(true) , mCursorVisible(true) @@ -267,7 +271,11 @@ namespace MWGui mSoulgemDialog = new SoulgemDialog(mMessageBoxManager); mCompanionWindow = new CompanionWindow(mDragAndDrop, mMessageBoxManager); trackWindow(mCompanionWindow, "companion"); - mScreenFader = new ScreenFader(); + + mWerewolfFader = new ScreenFader("textures\\werewolfoverlay.dds"); + mHitFader = new ScreenFader("textures\\player_hit_01.dds"); + mScreenFader = new ScreenFader("black.png"); + mDebugWindow = new DebugWindow(); mInputBlocker = MyGUI::Gui::getInstance().createWidget("",0,0,w,h,MyGUI::Align::Stretch,"Overlay"); @@ -359,6 +367,8 @@ namespace MWGui delete mCursorManager; delete mRecharge; delete mCompanionWindow; + delete mHitFader; + delete mWerewolfFader; delete mScreenFader; delete mDebugWindow; @@ -862,6 +872,8 @@ namespace MWGui mConsole->checkReferenceAvailable(); mCompanionWindow->onFrame(); + mHitFader->update(frameDuration); + mWerewolfFader->update(frameDuration); mScreenFader->update(frameDuration); mDebugWindow->onFrame(frameDuration); @@ -1450,7 +1462,10 @@ namespace MWGui const MWWorld::Ptr player = MWBase::Environment::get().getWorld()->getPlayerPtr(); if (player.getClass().getNpcStats(player).isWerewolf()) + { + setWerewolfOverlay(true); forceHide((GuiWindow)(MWGui::GW_Inventory | MWGui::GW_Magic)); + } } // Remove this method for MyGUI 3.2.2 @@ -1718,16 +1733,19 @@ namespace MWGui void WindowManager::fadeScreenIn(const float time) { + mScreenFader->clearQueue(); mScreenFader->fadeIn(time); } void WindowManager::fadeScreenOut(const float time) { + mScreenFader->clearQueue(); mScreenFader->fadeOut(time); } void WindowManager::fadeScreenTo(const int percent, const float time) { + mScreenFader->clearQueue(); mScreenFader->fadeTo(percent, time); } @@ -1736,6 +1754,27 @@ namespace MWGui mScreenFader->setFactor(factor); } + void WindowManager::activateHitOverlay() + { + if (!mHitFaderEnabled) + return; + + mHitFader->clearQueue(); + mHitFader->fadeTo(50, 0.2f); + mHitFader->fadeTo(0, 0.2f); + } + + void WindowManager::setWerewolfOverlay(bool set) + { + if (mWerewolfOverlayEnabled) + return; + + if (set) + mWerewolfFader->fadeOut(1.0f); + else + mWerewolfFader->fadeIn(1.0f); + } + void WindowManager::onClipboardChanged(const std::string &_type, const std::string &_data) { if (_type == "Text") diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 1dae77641..7be0c1165 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -334,6 +334,9 @@ namespace MWGui /// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading. virtual void setScreenFactor (float factor); + virtual void activateHitOverlay(); + virtual void setWerewolfOverlay(bool set); + virtual void toggleDebugWindow(); private: @@ -388,6 +391,8 @@ namespace MWGui CompanionWindow* mCompanionWindow; MyGUI::ImageBox* mVideoBackground; VideoWidget* mVideoWidget; + ScreenFader* mWerewolfFader; + ScreenFader* mHitFader; ScreenFader* mScreenFader; DebugWindow* mDebugWindow; @@ -400,6 +405,8 @@ namespace MWGui bool mCrosshairEnabled; bool mSubtitlesEnabled; + bool mHitFaderEnabled; + bool mWerewolfOverlayEnabled; bool mHudEnabled; bool mGuiEnabled; bool mCursorVisible; diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 28a44d3ba..a905820f8 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2352,6 +2352,8 @@ namespace MWWorld windowManager->unsetForceHide(MWGui::GW_Magic); } + windowManager->setWerewolfOverlay(werewolf); + // Witnesses of the player's transformation will make them a globally known werewolf std::vector closeActors; MWBase::Environment::get().getMechanicsManager()->getActorsInRange(Ogre::Vector3(actor.getRefData().getPosition().pos), diff --git a/files/settings-default.cfg b/files/settings-default.cfg index 06d999189..12b52d3db 100644 --- a/files/settings-default.cfg +++ b/files/settings-default.cfg @@ -41,6 +41,9 @@ tooltip delay = 0 subtitles = false +hit fader = true +werewolf overlay = true + [General] # Camera field of view field of view = 55 From e1799cbcf4da9a0846d46e9a1af48592c0418932 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Sun, 5 Oct 2014 19:53:36 +0200 Subject: [PATCH 06/32] Fix a typo in condition --- apps/openmw/mwgui/windowmanagerimp.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index ba880ddc9..786115464 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1766,7 +1766,7 @@ namespace MWGui void WindowManager::setWerewolfOverlay(bool set) { - if (mWerewolfOverlayEnabled) + if (!mWerewolfOverlayEnabled) return; if (set) From b6abfb0145cb76f664da794473811a00093d6d98 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Mon, 6 Oct 2014 18:31:02 +0200 Subject: [PATCH 07/32] Do not display hit fader if the player wasn't damaged --- apps/openmw/mwclass/npc.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index ec1b89642..3276f15e9 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -775,12 +775,13 @@ namespace MWClass damage = scaleDamage(damage, attacker, ptr); if(damage > 0.0f) + { sndMgr->playSound3D(ptr, "Health Damage", 1.0f, 1.0f); + if (ptr.getRefData().getHandle() == "player") + MWBase::Environment::get().getWindowManager()->activateHitOverlay(); + } float health = getCreatureStats(ptr).getHealth().getCurrent() - damage; setActorHealth(ptr, health, attacker); - - if (ptr.getRefData().getHandle() == "player") - MWBase::Environment::get().getWindowManager()->activateHitOverlay(); } else { From 4086bc4848b1079af306779ee668578ccd102495 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Mon, 6 Oct 2014 18:33:41 +0200 Subject: [PATCH 08/32] Do not spawn blood vfx on player if hit fader is enabled --- apps/openmw/mwworld/worldimp.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 69651a630..b112c812a 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2936,6 +2936,9 @@ namespace MWWorld void World::spawnBloodEffect(const Ptr &ptr, const Vector3 &worldPosition) { + if (ptr.getRefData().getHandle() == "player" && Settings::Manager::getBool("hit fader", "GUI")) + return; + int type = ptr.getClass().getBloodTexture(ptr); std::string texture; switch (type) From 0e19c3fdeb3e117c8932c78754772769766e1029 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Mon, 6 Oct 2014 18:48:22 +0200 Subject: [PATCH 09/32] Silence werewolves' footstep sounds when they are running with their claws sheathed --- apps/openmw/mwclass/npc.cpp | 50 +++++++++++++------------------------ 1 file changed, 17 insertions(+), 33 deletions(-) diff --git a/apps/openmw/mwclass/npc.cpp b/apps/openmw/mwclass/npc.cpp index 3276f15e9..d3f86c03b 100644 --- a/apps/openmw/mwclass/npc.cpp +++ b/apps/openmw/mwclass/npc.cpp @@ -24,6 +24,7 @@ #include "../mwmechanics/combat.hpp" #include "../mwmechanics/autocalcspell.hpp" #include "../mwmechanics/difficultyscaling.hpp" +#include "../mwmechanics/character.hpp" #include "../mwworld/ptr.hpp" #include "../mwworld/actiontalk.hpp" @@ -1220,60 +1221,43 @@ namespace MWClass std::string Npc::getSoundIdFromSndGen(const MWWorld::Ptr &ptr, const std::string &name) const { - if(name == "left") + if(name == "left" || name == "right") { MWBase::World *world = MWBase::Environment::get().getWorld(); Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); if(world->isSwimming(ptr)) - return "Swim Left"; + return (name == "left") ? "Swim Left" : "Swim Right"; if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) - return "FootWaterLeft"; + return (name == "left") ? "FootWaterLeft" : "FootWaterRight"; if(world->isOnGround(ptr)) { + if (ptr.getClass().getNpcStats(ptr).isWerewolf() + && ptr.getClass().getCreatureStats(ptr).getStance(MWMechanics::CreatureStats::Stance_Run)) + { + MWMechanics::WeaponType weaponType = MWMechanics::WeapType_None; + MWMechanics::getActiveWeapon(ptr.getClass().getCreatureStats(ptr), ptr.getClass().getInventoryStore(ptr), &weaponType); + if (weaponType == MWMechanics::WeapType_None) + return ""; + } + MWWorld::InventoryStore &inv = Npc::getInventoryStore(ptr); MWWorld::ContainerStoreIterator boots = inv.getSlot(MWWorld::InventoryStore::Slot_Boots); if(boots == inv.end() || boots->getTypeName() != typeid(ESM::Armor).name()) - return "FootBareLeft"; + return (name == "left") ? "FootBareLeft" : "FootBareRight"; switch(boots->getClass().getEquipmentSkill(*boots)) { case ESM::Skill::LightArmor: - return "FootLightLeft"; + return (name == "left") ? "FootLightLeft" : "FootLightRight"; case ESM::Skill::MediumArmor: - return "FootMedLeft"; + return (name == "left") ? "FootMedLeft" : "FootMedRight"; case ESM::Skill::HeavyArmor: - return "FootHeavyLeft"; + return (name == "left") ? "FootHeavyLeft" : "FootHeavyRight"; } } return ""; } - if(name == "right") - { - MWBase::World *world = MWBase::Environment::get().getWorld(); - Ogre::Vector3 pos(ptr.getRefData().getPosition().pos); - if(world->isSwimming(ptr)) - return "Swim Right"; - if(world->isUnderwater(ptr.getCell(), pos) || world->isWalkingOnWater(ptr)) - return "FootWaterRight"; - if(world->isOnGround(ptr)) - { - MWWorld::InventoryStore &inv = Npc::getInventoryStore(ptr); - MWWorld::ContainerStoreIterator boots = inv.getSlot(MWWorld::InventoryStore::Slot_Boots); - if(boots == inv.end() || boots->getTypeName() != typeid(ESM::Armor).name()) - return "FootBareRight"; - switch(boots->getClass().getEquipmentSkill(*boots)) - { - case ESM::Skill::LightArmor: - return "FootLightRight"; - case ESM::Skill::MediumArmor: - return "FootMedRight"; - case ESM::Skill::HeavyArmor: - return "FootHeavyRight"; - } - } - return ""; - } if(name == "land") { MWBase::World *world = MWBase::Environment::get().getWorld(); From d1dc9951d498631478afe778f4f361ad59db2e56 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Mon, 6 Oct 2014 20:24:53 +0200 Subject: [PATCH 10/32] Do not display werewolf overlay in third person --- apps/openmw/mwgui/windowmanagerimp.cpp | 7 +++---- apps/openmw/mwrender/renderingmanager.cpp | 4 ++++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 786115464..2479f699b 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1559,6 +1559,8 @@ namespace MWGui mForceHidden = GW_None; + setWerewolfOverlay(false); + mGuiModes.clear(); MWBase::Environment::get().getInputManager()->changeInputMode(false); updateVisible(); @@ -1769,10 +1771,7 @@ namespace MWGui if (!mWerewolfOverlayEnabled) return; - if (set) - mWerewolfFader->fadeOut(1.0f); - else - mWerewolfFader->fadeIn(1.0f); + mWerewolfFader->notifyAlphaChanged(set ? 1.0f : 0.0f); } void WindowManager::onClipboardChanged(const std::string &_type, const std::string &_data) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index 4fbc55089..a3a30e7c7 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -36,6 +36,7 @@ #include "../mwbase/statemanager.hpp" #include "../mwmechanics/creaturestats.hpp" +#include "../mwmechanics/npcstats.hpp" #include "../mwworld/ptr.hpp" @@ -346,6 +347,9 @@ void RenderingManager::update (float duration, bool paused) MWBase::Environment::get().getWindowManager()->setScreenFactor(std::max(0.f, 1.f-(blind / 100.f))); setAmbientMode(); + if (player.getClass().getNpcStats(player).isWerewolf()) + MWBase::Environment::get().getWindowManager()->setWerewolfOverlay(mCamera->isFirstPerson()); + // player position MWWorld::RefData &data = player.getRefData(); Ogre::Vector3 playerPos(data.getPosition().pos); From 964e42ab02712706ea9b328674d944d2581548a0 Mon Sep 17 00:00:00 2001 From: sylar Date: Sat, 11 Oct 2014 21:21:23 +0400 Subject: [PATCH 11/32] fixes errors in connecting Sdl and Ogre for nvidia tegra3 and in theory for other devices based on android --- extern/sdl4ogre/sdlwindowhelper.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/extern/sdl4ogre/sdlwindowhelper.cpp b/extern/sdl4ogre/sdlwindowhelper.cpp index e040b8868..44993947f 100644 --- a/extern/sdl4ogre/sdlwindowhelper.cpp +++ b/extern/sdl4ogre/sdlwindowhelper.cpp @@ -27,7 +27,6 @@ SDLWindowHelper::SDLWindowHelper (SDL_Window* window, int w, int h, throw std::runtime_error("Couldn't get WM Info!"); Ogre::String winHandle; - Ogre::String winHandleSurface; switch (wmInfo.subsystem) { @@ -46,8 +45,6 @@ SDLWindowHelper::SDLWindowHelper (SDL_Window* window, int w, int h, #elif ANDROID case SDL_SYSWM_ANDROID: winHandle = Ogre::StringConverter::toString((unsigned long)wmInfo.info.android.window); - winHandleSurface = Ogre::StringConverter::toString((unsigned long)wmInfo.info.android.surface); - break; #else case SDL_SYSWM_X11: @@ -63,7 +60,8 @@ SDLWindowHelper::SDLWindowHelper (SDL_Window* window, int w, int h, /// to work properly. On Linux/X11 it causes an occasional GLXBadDrawable error. #ifdef ANDROID - params.insert(std::make_pair("externalSurface", winHandleSurface)); + SDL_GLContext context= SDL_GL_CreateContext(window); + params.insert(std::make_pair("currentGLContext","True")); #endif params.insert(std::make_pair("externalWindowHandle", winHandle)); From fa65c8981a963224ed86480bb54fe16d3ea244e1 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 11 Oct 2014 21:05:12 +0200 Subject: [PATCH 12/32] Issue #1887: Equipped items do not emit sounds Played sound items are based on parts not inserted items. Signed-off-by: Lukasz Gromanowski --- apps/openmw/mwrender/npcanimation.cpp | 165 +++++++++---------------- apps/openmw/mwrender/npcanimation.hpp | 8 +- apps/openmw/mwworld/inventorystore.cpp | 23 ++-- apps/openmw/mwworld/inventorystore.hpp | 13 +- 4 files changed, 73 insertions(+), 136 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 6e8640377..0b1dcc270 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -173,7 +173,7 @@ const NpcAnimation::PartBoneMap NpcAnimation::sPartList = createPartListMap(); NpcAnimation::~NpcAnimation() { if (!mListenerDisabled) - mPtr.getClass().getInventoryStore(mPtr).setListener(NULL, mPtr); + mInv.setListener(NULL, mPtr); } @@ -188,7 +188,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v mAlpha(1.f), mNpcType(Type_Normal), mUnequipping(false), - mFirstEquip(true) + mFirstEquip(true), + mInv(ptr.getClass().getInventoryStore(ptr)) { mNpc = mPtr.get()->mBase; @@ -202,7 +203,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v } if (!disableListener) - mPtr.getClass().getInventoryStore(mPtr).setListener(this, mPtr); + mInv.setListener(this, mPtr); updateNpcBase(); } @@ -299,7 +300,6 @@ void NpcAnimation::updateParts() { mAlpha = 1.f; const MWWorld::Class &cls = mPtr.getClass(); - MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr); NpcType curType = Type_Normal; if (cls.getCreatureStats(mPtr).getMagicEffects().get(ESM::MagicEffect::Vampirism).getMagnitude() > 0) @@ -338,11 +338,11 @@ void NpcAnimation::updateParts() for(size_t i = 0;i < slotlistsize && mViewMode != VM_HeadOnly;i++) { - MWWorld::ContainerStoreIterator store = inv.getSlot(slotlist[i].mSlot); + MWWorld::ContainerStoreIterator store = mInv.getSlot(slotlist[i].mSlot); removePartGroup(slotlist[i].mSlot); - if(store == inv.end()) + if(store == mInv.end()) continue; if(slotlist[i].mSlot == MWWorld::InventoryStore::Slot_Helmet) @@ -395,14 +395,14 @@ void NpcAnimation::updateParts() if(mPartPriorities[ESM::PRT_Shield] < 1) { - MWWorld::ContainerStoreIterator store = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); + MWWorld::ContainerStoreIterator store = mInv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); MWWorld::Ptr part; - if(store != inv.end() && (part=*store).getTypeName() == typeid(ESM::Light).name()) + if(store != mInv.end() && (part=*store).getTypeName() == typeid(ESM::Light).name()) { const ESM::Light *light = part.get()->mBase; addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1, "meshes\\"+light->mModel); - addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield], light); + addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield].first, light); } } @@ -606,13 +606,13 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) for(size_t i = 0;i < ESM::PRT_Count;i++) { - if (mObjectParts[i].isNull()) + if (mObjectParts[i].first.isNull()) continue; - std::vector >::iterator ctrl(mObjectParts[i]->mControllers.begin()); - for(;ctrl != mObjectParts[i]->mControllers.end();++ctrl) + std::vector >::iterator ctrl(mObjectParts[i].first->mControllers.begin()); + for(;ctrl != mObjectParts[i].first->mControllers.end();++ctrl) ctrl->update(); - Ogre::Entity *ent = mObjectParts[i]->mSkelBase; + Ogre::Entity *ent = mObjectParts[i].first->mSkelBase; if(!ent) continue; updateSkeletonInstance(baseinst, ent->getSkeleton()); ent->getAllAnimationStates()->_notifyDirty(); @@ -626,7 +626,12 @@ void NpcAnimation::removeIndividualPart(ESM::PartReferenceType type) mPartPriorities[type] = 0; mPartslots[type] = -1; - mObjectParts[type].setNull(); + mObjectParts[type].first.setNull(); + if (!mObjectParts[type].second.empty()) + { + MWBase::Environment::get().getSoundManager()->stopSound3D(mPtr, mObjectParts[type].second); + mObjectParts[type].second.clear(); + } } void NpcAnimation::reserveIndividualPart(ESM::PartReferenceType type, int group, int priority) @@ -657,13 +662,25 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g mPartslots[type] = group; mPartPriorities[type] = priority; - mObjectParts[type] = insertBoundedPart(mesh, group, sPartList.at(type), enchantedGlow, glowColor); - if(mObjectParts[type]->mSkelBase) + std::string soundId; + MWWorld::ContainerStoreIterator csi = mInv.getSlot(group < 0 ? MWWorld::InventoryStore::Slot_Helmet : group); + if (csi != mInv.end() && csi->getTypeName() == typeid(ESM::Light).name()) { - Ogre::SkeletonInstance *skel = mObjectParts[type]->mSkelBase->getSkeleton(); - if(mObjectParts[type]->mSkelBase->isParentTagPoint()) + soundId = csi->get()->mBase->mSound; + } + mObjectParts[type] = std::make_pair(insertBoundedPart(mesh, group, sPartList.at(type), enchantedGlow, glowColor), soundId); + if (!soundId.empty()) + { + MWBase::Environment::get().getSoundManager()->playSound3D(mPtr, soundId, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, + MWBase::SoundManager::Play_Loop); + } + + if(mObjectParts[type].first->mSkelBase) + { + Ogre::SkeletonInstance *skel = mObjectParts[type].first->mSkelBase->getSkeleton(); + if(mObjectParts[type].first->mSkelBase->isParentTagPoint()) { - Ogre::Node *root = mObjectParts[type]->mSkelBase->getParentNode(); + Ogre::Node *root = mObjectParts[type].first->mSkelBase->getParentNode(); if(skel->hasBone("BoneOffset")) { Ogre::Bone *offset = skel->getBone("BoneOffset"); @@ -682,8 +699,8 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g updateSkeletonInstance(mSkelBase->getSkeleton(), skel); } - std::vector >::iterator ctrl(mObjectParts[type]->mControllers.begin()); - for(;ctrl != mObjectParts[type]->mControllers.end();++ctrl) + std::vector >::iterator ctrl(mObjectParts[type].first->mControllers.begin()); + for(;ctrl != mObjectParts[type].first->mControllers.end();++ctrl) { if(ctrl->getSource().isNull()) { @@ -692,7 +709,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g if (type == ESM::PRT_Head) { ctrl->setSource(mHeadAnimationTime); - const NifOgre::TextKeyMap& keys = mObjectParts[type]->mTextKeys; + const NifOgre::TextKeyMap& keys = mObjectParts[type].first->mTextKeys; for (NifOgre::TextKeyMap::const_iterator it = keys.begin(); it != keys.end(); ++it) { if (Misc::StringUtils::ciEqual(it->second, "talk: start")) @@ -762,9 +779,8 @@ void NpcAnimation::showWeapons(bool showWeapon) mShowWeapons = showWeapon; if(showWeapon) { - MWWorld::InventoryStore &inv = mPtr.getClass().getInventoryStore(mPtr); - MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); - if(weapon != inv.end()) + MWWorld::ContainerStoreIterator weapon = mInv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + if(weapon != mInv.end()) { Ogre::Vector3 glowColor = getEnchantmentColor(*weapon); std::string mesh = weapon->getClass().getModel(*weapon); @@ -775,8 +791,8 @@ void NpcAnimation::showWeapons(bool showWeapon) if (weapon->getTypeName() == typeid(ESM::Weapon).name() && weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) { - MWWorld::ContainerStoreIterator ammo = inv.getSlot(MWWorld::InventoryStore::Slot_Ammunition); - if (ammo != inv.end() && ammo->get()->mBase->mData.mType == ESM::Weapon::Bolt) + MWWorld::ContainerStoreIterator ammo = mInv.getSlot(MWWorld::InventoryStore::Slot_Ammunition); + if (ammo != mInv.end() && ammo->get()->mBase->mData.mType == ESM::Weapon::Bolt) attachArrow(); else mAmmunition.setNull(); @@ -795,10 +811,9 @@ void NpcAnimation::showWeapons(bool showWeapon) void NpcAnimation::showCarriedLeft(bool show) { mShowCarriedLeft = show; - MWWorld::InventoryStore &inv = mPtr.getClass().getInventoryStore(mPtr); - MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); - if(show && iter != inv.end()) + MWWorld::ContainerStoreIterator iter = mInv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); + if(show && iter != mInv.end()) { Ogre::Vector3 glowColor = getEnchantmentColor(*iter); std::string mesh = iter->getClass().getModel(*iter); @@ -806,7 +821,7 @@ void NpcAnimation::showCarriedLeft(bool show) mesh, !iter->getClass().getEnchantment(*iter).empty(), &glowColor)) { if (iter->getTypeName() == typeid(ESM::Light).name()) - addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield], iter->get()->mBase); + addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield].first, iter->get()->mBase); } } else @@ -869,14 +884,14 @@ void NpcAnimation::setAlpha(float alpha) for (int i=0; imEntities.size(); ++j) + for (unsigned int j=0; jmEntities.size(); ++j) { - Ogre::Entity* ent = mObjectParts[i]->mEntities[j]; - if (ent != mObjectParts[i]->mSkelBase) - applyAlpha(alpha, ent, mObjectParts[i]); + Ogre::Entity* ent = mObjectParts[i].first->mEntities[j]; + if (ent != mObjectParts[i].first->mSkelBase) + applyAlpha(alpha, ent, mObjectParts[i].first); } } } @@ -891,9 +906,9 @@ void NpcAnimation::preRender(Ogre::Camera *camera) Animation::preRender(camera); for (int i=0; irotateBillboardNodes(camera); + mObjectParts[i].first->rotateBillboardNodes(camera); } } @@ -930,79 +945,9 @@ void NpcAnimation::applyAlpha(float alpha, Ogre::Entity *ent, NifOgre::ObjectSce } } -void NpcAnimation::equipmentChanged(const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state) +void NpcAnimation::equipmentChanged() { - if (actor.getRefData().getHandle() == "player") - { - std::string soundId; - - MWBase::SoundManager *sndMgr = MWBase::Environment::get().getSoundManager(); - - if (state == InventoryStoreListener::EQUIP - || state == InventoryStoreListener::UNEQUIP) - { - if (item.getTypeName() == typeid(ESM::Light).name()) - { - soundId = item.get()->mBase->mSound; - } - - if (!soundId.empty()) - { - if (state == InventoryStoreListener::EQUIP) - { - sndMgr->playSound3D(mPtr, soundId, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, - MWBase::SoundManager::Play_Loop); - } - else - { - sndMgr->stopSound3D(mPtr, soundId); - } - } - } - else if (state == InventoryStoreListener::AUTOEQUIP) - { - const MWWorld::Class &cls = mPtr.getClass(); - MWWorld::InventoryStore &inv = cls.getInventoryStore(mPtr); - for (int i = MWWorld::InventoryStore::Slot_Helmet; i < MWWorld::InventoryStore::Slots; ++i) - { - MWWorld::ContainerStoreIterator store = inv.getSlot(i); - - if (store != inv.end() && store->getTypeName() == typeid(ESM::Light).name()) - { - soundId = store->get()->mBase->mSound; - } - - if (!soundId.empty()) - { - sndMgr->playSound3D(mPtr, soundId, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, - MWBase::SoundManager::Play_Loop); - } - } - } - } - - /** - * AUTOEQUIP is triggered just after setting listener (ie. when game is loaded from savegame), - * but not all things are initialized yet, so we have to check it (mFirstEquip variable) - * and skip one call to updateParts() method. - * - * Also call to updateParts() method will be called only once if inventory.unequipAll() - * was called (mUnequipping == true). - */ - if (state == InventoryStoreListener::UNEQUIPALL_BEGIN) - mUnequipping = true; - else if (state == InventoryStoreListener::UNEQUIPALL_END) - mUnequipping = false; - - if (!mUnequipping && !mFirstEquip) - { - updateParts(); - } - - if (mFirstEquip && state == InventoryStoreListener::AUTOEQUIP) - { - mFirstEquip = false; - } + updateParts(); } } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 83f85abe0..827859b04 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -51,7 +51,7 @@ public: class NpcAnimation : public Animation, public WeaponAnimation, public MWWorld::InventoryStoreListener { public: - virtual void equipmentChanged(const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state); + virtual void equipmentChanged(); virtual void permanentEffectAdded(const ESM::MagicEffect *magicEffect, bool isNew, bool playSound); public: @@ -69,7 +69,7 @@ private: bool mListenerDisabled; // Bounded Parts - NifOgre::ObjectScenePtr mObjectParts[ESM::PRT_Count]; + std::pair mObjectParts[ESM::PRT_Count]; const ESM::NPC *mNpc; std::string mHeadModel; @@ -100,6 +100,8 @@ private: bool mUnequipping; bool mFirstEquip; + MWWorld::InventoryStore& mInv; + void updateNpcBase(); NifOgre::ObjectScenePtr insertBoundedPart(const std::string &model, int group, const std::string &bonename, @@ -148,7 +150,7 @@ public: virtual void releaseArrow(); // WeaponAnimation - virtual NifOgre::ObjectScenePtr getWeapon() { return mObjectParts[ESM::PRT_Weapon]; } + virtual NifOgre::ObjectScenePtr getWeapon() { return mObjectParts[ESM::PRT_Weapon].first; } virtual void showWeapon(bool show) { showWeapons(show); } virtual void configureAddedObject(NifOgre::ObjectScenePtr object, MWWorld::Ptr ptr, int slot); diff --git a/apps/openmw/mwworld/inventorystore.cpp b/apps/openmw/mwworld/inventorystore.cpp index db58af32a..2988066e0 100644 --- a/apps/openmw/mwworld/inventorystore.cpp +++ b/apps/openmw/mwworld/inventorystore.cpp @@ -146,18 +146,20 @@ void MWWorld::InventoryStore::equip (int slot, const ContainerStoreIterator& ite flagAsModified(); - fireEquipmentChangedEvent(actor, *iterator, InventoryStoreListener::EQUIP); + fireEquipmentChangedEvent(); updateMagicEffects(actor); } void MWWorld::InventoryStore::unequipAll(const MWWorld::Ptr& actor) { - fireEquipmentChangedEvent(actor, MWWorld::Ptr(), InventoryStoreListener::UNEQUIPALL_BEGIN); + mUpdatesEnabled = false; for (int slot=0; slot < MWWorld::InventoryStore::Slots; ++slot) unequipSlot(slot, actor); - fireEquipmentChangedEvent(actor, MWWorld::Ptr(), InventoryStoreListener::UNEQUIPALL_END); + mUpdatesEnabled = true; + + fireEquipmentChangedEvent(); updateMagicEffects(actor); } @@ -203,8 +205,9 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) if (!Misc::StringUtils::ciEqual(test.getCellRef().getOwner(), actor.getCellRef().getRefId()) && (actor.getClass().getScript(actor).empty() || !actor.getRefData().getLocals().getIntVar(actor.getClass().getScript(actor), "companion"))) + { continue; - + } int testSkill = test.getClass().getEquipmentSkill (test); std::pair, bool> itemsSlots = @@ -288,7 +291,7 @@ void MWWorld::InventoryStore::autoEquip (const MWWorld::Ptr& actor) if (changed) { mSlots.swap (slots_); - fireEquipmentChangedEvent(actor, MWWorld::Ptr(), InventoryStoreListener::AUTOEQUIP); + fireEquipmentChangedEvent(); updateMagicEffects(actor); flagAsModified(); } @@ -521,7 +524,7 @@ MWWorld::ContainerStoreIterator MWWorld::InventoryStore::unequipSlot(int slot, c } } - fireEquipmentChangedEvent(actor, *it, InventoryStoreListener::UNEQUIP); + fireEquipmentChangedEvent(); updateMagicEffects(actor); return retval; @@ -546,18 +549,14 @@ void MWWorld::InventoryStore::setListener(InventoryStoreListener *listener, cons { mListener = listener; updateMagicEffects(actor); - if (mListener != NULL) - { - mListener->equipmentChanged(actor, MWWorld::Ptr(), InventoryStoreListener::AUTOEQUIP); - } } -void MWWorld::InventoryStore::fireEquipmentChangedEvent(const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state) +void MWWorld::InventoryStore::fireEquipmentChangedEvent() { if (!mUpdatesEnabled) return; if (mListener) - mListener->equipmentChanged(actor, item, state); + mListener->equipmentChanged(); } void MWWorld::InventoryStore::visitEffectSources(MWMechanics::EffectSourceVisitor &visitor) diff --git a/apps/openmw/mwworld/inventorystore.hpp b/apps/openmw/mwworld/inventorystore.hpp index fb6d2919b..41caae4e5 100644 --- a/apps/openmw/mwworld/inventorystore.hpp +++ b/apps/openmw/mwworld/inventorystore.hpp @@ -20,19 +20,10 @@ namespace MWWorld class InventoryStoreListener { public: - enum State - { - EQUIP, - AUTOEQUIP, - UNEQUIP, - UNEQUIPALL_BEGIN, - UNEQUIPALL_END - }; - /** * Fired when items are equipped or unequipped */ - virtual void equipmentChanged (const MWWorld::Ptr& /*actor*/, const MWWorld::Ptr& /*item*/, State /*state*/) {} + virtual void equipmentChanged () {} /** * @param effect @@ -118,7 +109,7 @@ namespace MWWorld void updateMagicEffects(const Ptr& actor); void updateRechargingItems(); - void fireEquipmentChangedEvent(const MWWorld::Ptr& actor, const MWWorld::Ptr& item, InventoryStoreListener::State state); + void fireEquipmentChangedEvent(); virtual int getSlot (const MWWorld::LiveCellRefBase& ref) const; ///< Return inventory slot that \a ref is in or -1 (if \a ref is not in a slot). From 0ae604990e9a446ce852828363276915f4941f70 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Sat, 11 Oct 2014 22:21:48 +0200 Subject: [PATCH 13/32] Implement continuous damage indication (Fixes #1970) --- apps/openmw/mwbase/windowmanager.hpp | 2 +- apps/openmw/mwgui/screenfader.cpp | 5 +++++ apps/openmw/mwgui/screenfader.hpp | 1 + apps/openmw/mwgui/windowmanagerimp.cpp | 9 ++++++--- apps/openmw/mwgui/windowmanagerimp.hpp | 2 +- apps/openmw/mwmechanics/actors.cpp | 24 ++++++++++++++++++------ apps/openmw/mwworld/worldimp.cpp | 22 ++++++++++++++++++++++ 7 files changed, 54 insertions(+), 11 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index c2b02452a..adffa9903 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -338,7 +338,7 @@ namespace MWBase /// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading. virtual void setScreenFactor (float factor) = 0; - virtual void activateHitOverlay() = 0; + virtual void activateHitOverlay(bool interrupt=true) = 0; virtual void setWerewolfOverlay(bool set) = 0; virtual void toggleDebugWindow() = 0; diff --git a/apps/openmw/mwgui/screenfader.cpp b/apps/openmw/mwgui/screenfader.cpp index 1adfdef05..c616a8338 100644 --- a/apps/openmw/mwgui/screenfader.cpp +++ b/apps/openmw/mwgui/screenfader.cpp @@ -131,6 +131,11 @@ namespace MWGui mQueue.push_back(FadeOp::Ptr(new FadeOp(this, time, targetAlpha))); } + bool ScreenFader::isEmpty() + { + return mQueue.empty(); + } + void ScreenFader::clearQueue() { mQueue.clear(); diff --git a/apps/openmw/mwgui/screenfader.hpp b/apps/openmw/mwgui/screenfader.hpp index 07b6992ba..8c393bf92 100644 --- a/apps/openmw/mwgui/screenfader.hpp +++ b/apps/openmw/mwgui/screenfader.hpp @@ -48,6 +48,7 @@ namespace MWGui void setRepeat(bool repeat); void queue(float time, float targetAlpha); + bool isEmpty(); void clearQueue(); void notifyAlphaChanged(float alpha); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 2479f699b..0bc36cf4f 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -1756,14 +1756,17 @@ namespace MWGui mScreenFader->setFactor(factor); } - void WindowManager::activateHitOverlay() + void WindowManager::activateHitOverlay(bool interrupt) { if (!mHitFaderEnabled) return; + if (!interrupt && !mHitFader->isEmpty()) + return; + mHitFader->clearQueue(); - mHitFader->fadeTo(50, 0.2f); - mHitFader->fadeTo(0, 0.2f); + mHitFader->fadeTo(100, 0.0f); + mHitFader->fadeTo(0, 0.5f); } void WindowManager::setWerewolfOverlay(bool set) diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index e3bc7781f..088f6c6e9 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -333,7 +333,7 @@ namespace MWGui /// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading. virtual void setScreenFactor (float factor); - virtual void activateHitOverlay(); + virtual void activateHitOverlay(bool interrupt); virtual void setWerewolfOverlay(bool set); virtual void toggleDebugWindow(); diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index da6aec0be..71f9edfde 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -592,6 +592,7 @@ namespace MWMechanics }; DynamicStat health = creatureStats.getHealth(); + bool receivedMagicDamage = false; for (unsigned int i=0; i 1) damageScale *= fMagicSunBlockedMult; health.setCurrent(health.getCurrent() - magnitude * duration * damageScale); + + if (magnitude * damageScale > 0.0f) + receivedMagicDamage = true; } else + { health.setCurrent(health.getCurrent() - magnitude * duration); + if (magnitude > 0.0f) + receivedMagicDamage = true; + } } + + if (receivedMagicDamage && ptr.getRefData().getHandle() == "player") + MWBase::Environment::get().getWindowManager()->activateHitOverlay(false); + creatureStats.setHealth(health); if (!wasDead && creatureStats.isDead()) @@ -875,13 +887,13 @@ namespace MWMechanics static const float fSuffocationDamage = world->getStore().get().find("fSuffocationDamage")->getFloat(); ptr.getClass().setActorHealth(ptr, stats.getHealth().getCurrent() - fSuffocationDamage*duration); - // Play a drowning sound as necessary for the player + // Play a drowning sound + MWBase::SoundManager *sndmgr = MWBase::Environment::get().getSoundManager(); + if(!sndmgr->getSoundPlaying(ptr, "drown")) + sndmgr->playSound3D(ptr, "drown", 1.0f, 1.0f); + if(ptr == world->getPlayerPtr()) - { - MWBase::SoundManager *sndmgr = MWBase::Environment::get().getSoundManager(); - if(!sndmgr->getSoundPlaying(MWWorld::Ptr(), "drown")) - sndmgr->playSound("drown", 1.0f, 1.0f); - } + MWBase::Environment::get().getWindowManager()->activateHitOverlay(false); } } else diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index b112c812a..92e240d7a 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2087,9 +2087,20 @@ namespace MWWorld continue; MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor); + if (stats.isDead()) + continue; MWMechanics::DynamicStat health = stats.getHealth(); health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration()); stats.setHealth(health); + + if (healthPerSecond > 0.0f) + { + if (actor.getRefData().getHandle() == "player") + MWBase::Environment::get().getWindowManager()->activateHitOverlay(false); + + if (!MWBase::Environment::get().getSoundManager()->getSoundPlaying(actor, "Health Damage")) + MWBase::Environment::get().getSoundManager()->playSound3D(actor, "Health Damage", 1.0f, 1.0f); + } } } @@ -2104,9 +2115,20 @@ namespace MWWorld continue; MWMechanics::CreatureStats& stats = actor.getClass().getCreatureStats(actor); + if (stats.isDead()) + continue; MWMechanics::DynamicStat health = stats.getHealth(); health.setCurrent(health.getCurrent()-healthPerSecond*MWBase::Environment::get().getFrameDuration()); stats.setHealth(health); + + if (healthPerSecond > 0.0f) + { + if (actor.getRefData().getHandle() == "player") + MWBase::Environment::get().getWindowManager()->activateHitOverlay(false); + + if (!MWBase::Environment::get().getSoundManager()->getSoundPlaying(actor, "Health Damage")) + MWBase::Environment::get().getSoundManager()->playSound3D(actor, "Health Damage", 1.0f, 1.0f); + } } } From 3b9cfba03cef103ab02b11b3bbf76e4cd8e7a5ae Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 11 Oct 2014 22:21:59 +0200 Subject: [PATCH 14/32] Issue #1887: Equipped items do not emit sounds Sounds are played only when actors draw state is equal to MWMechanics::DrawState_Nothing Signed-off-by: Lukasz Gromanowski --- apps/openmw/mwrender/npcanimation.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 0b1dcc270..37e9e14ad 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -664,12 +664,13 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g std::string soundId; MWWorld::ContainerStoreIterator csi = mInv.getSlot(group < 0 ? MWWorld::InventoryStore::Slot_Helmet : group); + if (csi != mInv.end() && csi->getTypeName() == typeid(ESM::Light).name()) { soundId = csi->get()->mBase->mSound; } mObjectParts[type] = std::make_pair(insertBoundedPart(mesh, group, sPartList.at(type), enchantedGlow, glowColor), soundId); - if (!soundId.empty()) + if (!soundId.empty() && mPtr.getClass().getCreatureStats(mPtr).getDrawState() == MWMechanics::DrawState_Nothing) { MWBase::Environment::get().getSoundManager()->playSound3D(mPtr, soundId, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop); From 1a0c3dc6cf56db66fdb6964b3e14b975b6dfd02f Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 11 Oct 2014 22:33:11 +0200 Subject: [PATCH 15/32] Issue #1887: Equipped items do not emit sounds Removed unused mUnequipping and mFirstEquip member variables. Signed-off-by: Lukasz Gromanowski --- apps/openmw/mwrender/npcanimation.cpp | 3 --- apps/openmw/mwrender/npcanimation.hpp | 3 --- 2 files changed, 6 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 37e9e14ad..be48e387a 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -187,8 +187,6 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v mFirstPersonOffset(0.f, 0.f, 0.f), mAlpha(1.f), mNpcType(Type_Normal), - mUnequipping(false), - mFirstEquip(true), mInv(ptr.getClass().getInventoryStore(ptr)) { mNpc = mPtr.get()->mBase; @@ -664,7 +662,6 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g std::string soundId; MWWorld::ContainerStoreIterator csi = mInv.getSlot(group < 0 ? MWWorld::InventoryStore::Slot_Helmet : group); - if (csi != mInv.end() && csi->getTypeName() == typeid(ESM::Light).name()) { soundId = csi->get()->mBase->mSound; diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 827859b04..45481b837 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -97,9 +97,6 @@ private: Ogre::SharedPtr mWeaponAnimationTime; float mAlpha; - bool mUnequipping; - bool mFirstEquip; - MWWorld::InventoryStore& mInv; void updateNpcBase(); From 2162a9e1b93848321e486adbac944930e0c8174c Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Sat, 11 Oct 2014 23:09:20 +0200 Subject: [PATCH 16/32] Fall back to player_hit_01.dds if bm_player_hit_01.dds is not available --- apps/openmw/mwgui/screenfader.cpp | 7 ++++++- apps/openmw/mwgui/screenfader.hpp | 2 ++ apps/openmw/mwgui/windowmanagerimp.cpp | 6 +++++- 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwgui/screenfader.cpp b/apps/openmw/mwgui/screenfader.cpp index c616a8338..f2b3fa6af 100644 --- a/apps/openmw/mwgui/screenfader.cpp +++ b/apps/openmw/mwgui/screenfader.cpp @@ -71,10 +71,15 @@ namespace MWGui , mRepeat(false) { mMainWidget->setSize(MyGUI::RenderManager::getInstance().getViewSize()); - mMainWidget->setProperty("ImageTexture", texturePath); + setTexture(texturePath); setVisible(false); } + void ScreenFader::setTexture(const std::string & texturePath) + { + mMainWidget->setProperty("ImageTexture", texturePath); + } + void ScreenFader::update(float dt) { if (!mQueue.empty()) diff --git a/apps/openmw/mwgui/screenfader.hpp b/apps/openmw/mwgui/screenfader.hpp index 8c393bf92..402554555 100644 --- a/apps/openmw/mwgui/screenfader.hpp +++ b/apps/openmw/mwgui/screenfader.hpp @@ -38,6 +38,8 @@ namespace MWGui public: ScreenFader(const std::string & texturePath); + void setTexture(const std::string & texturePath); + void update(float dt); void fadeIn(const float time); diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 0bc36cf4f..2970c9b1d 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -273,7 +273,11 @@ namespace MWGui trackWindow(mCompanionWindow, "companion"); mWerewolfFader = new ScreenFader("textures\\werewolfoverlay.dds"); - mHitFader = new ScreenFader("textures\\player_hit_01.dds"); + mHitFader = new ScreenFader("textures\\bm_player_hit_01.dds"); + // fall back to player_hit_01.dds if bm_player_hit_01.dds is not available + // TODO: check if non-BM versions actually use player_hit_01.dds + if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup("textures\\bm_player_hit_01.dds")) + mHitFader->setTexture("textures\\player_hit_01.dds"); mScreenFader = new ScreenFader("black.png"); mDebugWindow = new DebugWindow(); From b44ba84a8099779fce7312a26f95cd6cb3952c77 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 11 Oct 2014 23:18:09 +0200 Subject: [PATCH 17/32] Issue #1887: Equipped items do not emit sounds Use separate arrays for sound ids and object parts. Restored getting inventoryStore via getInventoryStore() call (removed mInv introduced in previous commit). Signed-off-by: Lukasz Gromanowski --- apps/openmw/mwrender/npcanimation.cpp | 93 ++++++++++++++------------- apps/openmw/mwrender/npcanimation.hpp | 6 +- 2 files changed, 50 insertions(+), 49 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index be48e387a..52144df04 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -173,7 +173,7 @@ const NpcAnimation::PartBoneMap NpcAnimation::sPartList = createPartListMap(); NpcAnimation::~NpcAnimation() { if (!mListenerDisabled) - mInv.setListener(NULL, mPtr); + mPtr.getClass().getInventoryStore(mPtr).setListener(NULL, mPtr); } @@ -186,8 +186,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v mShowCarriedLeft(true), mFirstPersonOffset(0.f, 0.f, 0.f), mAlpha(1.f), - mNpcType(Type_Normal), - mInv(ptr.getClass().getInventoryStore(ptr)) + mNpcType(Type_Normal) { mNpc = mPtr.get()->mBase; @@ -201,7 +200,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v } if (!disableListener) - mInv.setListener(this, mPtr); + mPtr.getClass().getInventoryStore(mPtr).setListener(this, mPtr); updateNpcBase(); } @@ -334,13 +333,14 @@ void NpcAnimation::updateParts() }; static const size_t slotlistsize = sizeof(slotlist)/sizeof(slotlist[0]); + MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); for(size_t i = 0;i < slotlistsize && mViewMode != VM_HeadOnly;i++) { - MWWorld::ContainerStoreIterator store = mInv.getSlot(slotlist[i].mSlot); + MWWorld::ContainerStoreIterator store = inv.getSlot(slotlist[i].mSlot); removePartGroup(slotlist[i].mSlot); - if(store == mInv.end()) + if(store == inv.end()) continue; if(slotlist[i].mSlot == MWWorld::InventoryStore::Slot_Helmet) @@ -393,14 +393,14 @@ void NpcAnimation::updateParts() if(mPartPriorities[ESM::PRT_Shield] < 1) { - MWWorld::ContainerStoreIterator store = mInv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); + MWWorld::ContainerStoreIterator store = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); MWWorld::Ptr part; - if(store != mInv.end() && (part=*store).getTypeName() == typeid(ESM::Light).name()) + if(store != inv.end() && (part=*store).getTypeName() == typeid(ESM::Light).name()) { const ESM::Light *light = part.get()->mBase; addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1, "meshes\\"+light->mModel); - addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield].first, light); + addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield], light); } } @@ -604,13 +604,13 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) for(size_t i = 0;i < ESM::PRT_Count;i++) { - if (mObjectParts[i].first.isNull()) + if (mObjectParts[i].isNull()) continue; - std::vector >::iterator ctrl(mObjectParts[i].first->mControllers.begin()); - for(;ctrl != mObjectParts[i].first->mControllers.end();++ctrl) + std::vector >::iterator ctrl(mObjectParts[i]->mControllers.begin()); + for(;ctrl != mObjectParts[i]->mControllers.end();++ctrl) ctrl->update(); - Ogre::Entity *ent = mObjectParts[i].first->mSkelBase; + Ogre::Entity *ent = mObjectParts[i]->mSkelBase; if(!ent) continue; updateSkeletonInstance(baseinst, ent->getSkeleton()); ent->getAllAnimationStates()->_notifyDirty(); @@ -624,11 +624,11 @@ void NpcAnimation::removeIndividualPart(ESM::PartReferenceType type) mPartPriorities[type] = 0; mPartslots[type] = -1; - mObjectParts[type].first.setNull(); - if (!mObjectParts[type].second.empty()) + mObjectParts[type].setNull(); + if (!mSoundIds[type].empty()) { - MWBase::Environment::get().getSoundManager()->stopSound3D(mPtr, mObjectParts[type].second); - mObjectParts[type].second.clear(); + MWBase::Environment::get().getSoundManager()->stopSound3D(mPtr, mSoundIds[type]); + mSoundIds[type].clear(); } } @@ -660,25 +660,25 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g mPartslots[type] = group; mPartPriorities[type] = priority; - std::string soundId; - MWWorld::ContainerStoreIterator csi = mInv.getSlot(group < 0 ? MWWorld::InventoryStore::Slot_Helmet : group); - if (csi != mInv.end() && csi->getTypeName() == typeid(ESM::Light).name()) + MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); + MWWorld::ContainerStoreIterator csi = inv.getSlot(group < 0 ? MWWorld::InventoryStore::Slot_Helmet : group); + if (csi != inv.end() && csi->getTypeName() == typeid(ESM::Light).name()) { - soundId = csi->get()->mBase->mSound; + mSoundIds[type] = csi->get()->mBase->mSound; } - mObjectParts[type] = std::make_pair(insertBoundedPart(mesh, group, sPartList.at(type), enchantedGlow, glowColor), soundId); - if (!soundId.empty() && mPtr.getClass().getCreatureStats(mPtr).getDrawState() == MWMechanics::DrawState_Nothing) + mObjectParts[type] = insertBoundedPart(mesh, group, sPartList.at(type), enchantedGlow, glowColor); + if (!mSoundIds[type].empty() && mPtr.getClass().getCreatureStats(mPtr).getDrawState() == MWMechanics::DrawState_Nothing) { - MWBase::Environment::get().getSoundManager()->playSound3D(mPtr, soundId, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, + MWBase::Environment::get().getSoundManager()->playSound3D(mPtr, mSoundIds[type], 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, MWBase::SoundManager::Play_Loop); } - if(mObjectParts[type].first->mSkelBase) + if(mObjectParts[type]->mSkelBase) { - Ogre::SkeletonInstance *skel = mObjectParts[type].first->mSkelBase->getSkeleton(); - if(mObjectParts[type].first->mSkelBase->isParentTagPoint()) + Ogre::SkeletonInstance *skel = mObjectParts[type]->mSkelBase->getSkeleton(); + if(mObjectParts[type]->mSkelBase->isParentTagPoint()) { - Ogre::Node *root = mObjectParts[type].first->mSkelBase->getParentNode(); + Ogre::Node *root = mObjectParts[type]->mSkelBase->getParentNode(); if(skel->hasBone("BoneOffset")) { Ogre::Bone *offset = skel->getBone("BoneOffset"); @@ -697,8 +697,8 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g updateSkeletonInstance(mSkelBase->getSkeleton(), skel); } - std::vector >::iterator ctrl(mObjectParts[type].first->mControllers.begin()); - for(;ctrl != mObjectParts[type].first->mControllers.end();++ctrl) + std::vector >::iterator ctrl(mObjectParts[type]->mControllers.begin()); + for(;ctrl != mObjectParts[type]->mControllers.end();++ctrl) { if(ctrl->getSource().isNull()) { @@ -707,7 +707,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g if (type == ESM::PRT_Head) { ctrl->setSource(mHeadAnimationTime); - const NifOgre::TextKeyMap& keys = mObjectParts[type].first->mTextKeys; + const NifOgre::TextKeyMap& keys = mObjectParts[type]->mTextKeys; for (NifOgre::TextKeyMap::const_iterator it = keys.begin(); it != keys.end(); ++it) { if (Misc::StringUtils::ciEqual(it->second, "talk: start")) @@ -777,8 +777,9 @@ void NpcAnimation::showWeapons(bool showWeapon) mShowWeapons = showWeapon; if(showWeapon) { - MWWorld::ContainerStoreIterator weapon = mInv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); - if(weapon != mInv.end()) + MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); + MWWorld::ContainerStoreIterator weapon = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedRight); + if(weapon != inv.end()) { Ogre::Vector3 glowColor = getEnchantmentColor(*weapon); std::string mesh = weapon->getClass().getModel(*weapon); @@ -789,8 +790,8 @@ void NpcAnimation::showWeapons(bool showWeapon) if (weapon->getTypeName() == typeid(ESM::Weapon).name() && weapon->get()->mBase->mData.mType == ESM::Weapon::MarksmanCrossbow) { - MWWorld::ContainerStoreIterator ammo = mInv.getSlot(MWWorld::InventoryStore::Slot_Ammunition); - if (ammo != mInv.end() && ammo->get()->mBase->mData.mType == ESM::Weapon::Bolt) + MWWorld::ContainerStoreIterator ammo = inv.getSlot(MWWorld::InventoryStore::Slot_Ammunition); + if (ammo != inv.end() && ammo->get()->mBase->mData.mType == ESM::Weapon::Bolt) attachArrow(); else mAmmunition.setNull(); @@ -809,9 +810,9 @@ void NpcAnimation::showWeapons(bool showWeapon) void NpcAnimation::showCarriedLeft(bool show) { mShowCarriedLeft = show; - - MWWorld::ContainerStoreIterator iter = mInv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); - if(show && iter != mInv.end()) + MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); + MWWorld::ContainerStoreIterator iter = inv.getSlot(MWWorld::InventoryStore::Slot_CarriedLeft); + if(show && iter != inv.end()) { Ogre::Vector3 glowColor = getEnchantmentColor(*iter); std::string mesh = iter->getClass().getModel(*iter); @@ -819,7 +820,7 @@ void NpcAnimation::showCarriedLeft(bool show) mesh, !iter->getClass().getEnchantment(*iter).empty(), &glowColor)) { if (iter->getTypeName() == typeid(ESM::Light).name()) - addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield].first, iter->get()->mBase); + addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield], iter->get()->mBase); } } else @@ -882,14 +883,14 @@ void NpcAnimation::setAlpha(float alpha) for (int i=0; imEntities.size(); ++j) + for (unsigned int j=0; jmEntities.size(); ++j) { - Ogre::Entity* ent = mObjectParts[i].first->mEntities[j]; - if (ent != mObjectParts[i].first->mSkelBase) - applyAlpha(alpha, ent, mObjectParts[i].first); + Ogre::Entity* ent = mObjectParts[i]->mEntities[j]; + if (ent != mObjectParts[i]->mSkelBase) + applyAlpha(alpha, ent, mObjectParts[i]); } } } @@ -904,9 +905,9 @@ void NpcAnimation::preRender(Ogre::Camera *camera) Animation::preRender(camera); for (int i=0; irotateBillboardNodes(camera); + mObjectParts[i]->rotateBillboardNodes(camera); } } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index 45481b837..b5119b2ad 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -69,7 +69,8 @@ private: bool mListenerDisabled; // Bounded Parts - std::pair mObjectParts[ESM::PRT_Count]; + NifOgre::ObjectScenePtr mObjectParts[ESM::PRT_Count]; + std::string mSoundIds[ESM::PRT_Count]; const ESM::NPC *mNpc; std::string mHeadModel; @@ -97,7 +98,6 @@ private: Ogre::SharedPtr mWeaponAnimationTime; float mAlpha; - MWWorld::InventoryStore& mInv; void updateNpcBase(); @@ -147,7 +147,7 @@ public: virtual void releaseArrow(); // WeaponAnimation - virtual NifOgre::ObjectScenePtr getWeapon() { return mObjectParts[ESM::PRT_Weapon].first; } + virtual NifOgre::ObjectScenePtr getWeapon() { return mObjectParts[ESM::PRT_Weapon]; } virtual void showWeapon(bool show) { showWeapons(show); } virtual void configureAddedObject(NifOgre::ObjectScenePtr object, MWWorld::Ptr ptr, int slot); From a5e972aeb5c1a591ff2a07d2e1ed17d726d9f3e7 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Sun, 12 Oct 2014 00:13:24 +0200 Subject: [PATCH 18/32] Make collision events available on every frame (thanks, scrawl), make hurtStandingActor and hurtCollidingActor no-op in guimode --- apps/openmw/mwworld/physicssystem.cpp | 8 ++++---- apps/openmw/mwworld/worldimp.cpp | 6 ++++++ 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwworld/physicssystem.cpp b/apps/openmw/mwworld/physicssystem.cpp index ad0f5bea5..aba120baa 100644 --- a/apps/openmw/mwworld/physicssystem.cpp +++ b/apps/openmw/mwworld/physicssystem.cpp @@ -829,15 +829,15 @@ namespace MWWorld const PtrVelocityList& PhysicsSystem::applyQueuedMovement(float dt) { - // Collision events are only tracked for a single frame, so reset first - mCollisions.clear(); - mStandingCollisions.clear(); - mMovementResults.clear(); mTimeAccum += dt; if(mTimeAccum >= 1.0f/60.0f) { + // Collision events should be available on every frame + mCollisions.clear(); + mStandingCollisions.clear(); + const MWBase::World *world = MWBase::Environment::get().getWorld(); PtrVelocityList::iterator iter = mMovementQueue.begin(); for(;iter != mMovementQueue.end();++iter) diff --git a/apps/openmw/mwworld/worldimp.cpp b/apps/openmw/mwworld/worldimp.cpp index 92e240d7a..383641d2d 100644 --- a/apps/openmw/mwworld/worldimp.cpp +++ b/apps/openmw/mwworld/worldimp.cpp @@ -2078,6 +2078,9 @@ namespace MWWorld void World::hurtStandingActors(const Ptr &object, float healthPerSecond) { + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + return; + std::vector actors; mPhysics->getActorsStandingOn(object, actors); for (std::vector::iterator it = actors.begin(); it != actors.end(); ++it) @@ -2106,6 +2109,9 @@ namespace MWWorld void World::hurtCollidingActors(const Ptr &object, float healthPerSecond) { + if (MWBase::Environment::get().getWindowManager()->isGuiMode()) + return; + std::vector actors; mPhysics->getActorsCollidingWith(object, actors); for (std::vector::iterator it = actors.begin(); it != actors.end(); ++it) From 8dd95fd77e2e31c91844c08a8c100b7a90c0b59d Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Sun, 12 Oct 2014 00:40:31 +0200 Subject: [PATCH 19/32] Construct hit fader with correct texture right away to prevent mygui warning --- apps/openmw/mwgui/windowmanagerimp.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 2970c9b1d..7560f8738 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -273,11 +273,12 @@ namespace MWGui trackWindow(mCompanionWindow, "companion"); mWerewolfFader = new ScreenFader("textures\\werewolfoverlay.dds"); - mHitFader = new ScreenFader("textures\\bm_player_hit_01.dds"); + std::string hitFaderTexture = "textures\\bm_player_hit_01.dds"; // fall back to player_hit_01.dds if bm_player_hit_01.dds is not available // TODO: check if non-BM versions actually use player_hit_01.dds - if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup("textures\\bm_player_hit_01.dds")) - mHitFader->setTexture("textures\\player_hit_01.dds"); + if(!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(hitFaderTexture)) + hitFaderTexture = "textures\\player_hit_01.dds"; + mHitFader = new ScreenFader(hitFaderTexture); mScreenFader = new ScreenFader("black.png"); mDebugWindow = new DebugWindow(); From ad253059b1fa53e70b3d6c045f002ada9adce569 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Sun, 12 Oct 2014 01:15:40 +0200 Subject: [PATCH 20/32] Hit indicator for absorb/damage health effect --- apps/openmw/mwmechanics/actors.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 71f9edfde..9b66f7afb 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -585,6 +585,12 @@ namespace MWMechanics } } + bool receivedMagicDamage = false; + + if (creatureStats.getMagicEffects().get(ESM::MagicEffect::DamageHealth).getMagnitude() > 0.0f + || creatureStats.getMagicEffects().get(ESM::MagicEffect::AbsorbHealth).getMagnitude() > 0.0f) + receivedMagicDamage = true; + // Apply damage ticks int damageEffects[] = { ESM::MagicEffect::FireDamage, ESM::MagicEffect::ShockDamage, ESM::MagicEffect::FrostDamage, ESM::MagicEffect::Poison, @@ -592,7 +598,6 @@ namespace MWMechanics }; DynamicStat health = creatureStats.getHealth(); - bool receivedMagicDamage = false; for (unsigned int i=0; i Date: Sun, 12 Oct 2014 11:28:56 +0200 Subject: [PATCH 21/32] added make target for doxygen: make doc, make doc_pages --- CMakeLists.txt | 17 ++++++++++++++++- docs/{Doxyfile => Doxyfile.in} | 10 +++++----- docs/{DoxyfilePages => DoxyfilePages.in} | 10 +++++----- 3 files changed, 26 insertions(+), 11 deletions(-) rename docs/{Doxyfile => Doxyfile.in} (99%) rename docs/{DoxyfilePages => DoxyfilePages.in} (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 542ea3e94..6725ec64b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -60,7 +60,7 @@ endif (ANDROID) # doxygen main page -configure_file ("${OpenMW_SOURCE_DIR}/docs/mainpage.hpp.cmake" "${OpenMW_SOURCE_DIR}/docs/mainpage.hpp") +configure_file ("${OpenMW_SOURCE_DIR}/docs/mainpage.hpp.cmake" "${OpenMW_BINARY_DIR}/docs/mainpage.hpp") option(MYGUI_STATIC "Link static build of Mygui into the binaries" FALSE) option(OGRE_STATIC "Link static build of Ogre and Ogre Plugins into the binaries" FALSE) @@ -836,3 +836,18 @@ if (APPLE) include(CPack) endif (APPLE) +# Doxygen Target -- simply run 'make doc' or 'make doc_pages' +find_package(Doxygen) +if(DOXYGEN_FOUND) + configure_file(${OpenMW_SOURCE_DIR}/docs/Doxyfile.in ${OpenMW_BINARY_DIR}/docs/Doxyfile @ONLY) + configure_file(${OpenMW_SOURCE_DIR}/docs/DoxyfilePages.in ${OpenMW_BINARY_DIR}/docs/DoxyfilePages @ONLY) + add_custom_target(doc + ${DOXYGEN_EXECUTABLE} ${OpenMW_BINARY_DIR}/docs/Doxyfile + WORKING_DIRECTORY ${OpenMW_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen (from Doxyfile)" VERBATIM) + add_custom_target(doc_pages + ${DOXYGEN_EXECUTABLE} ${OpenMW_BINARY_DIR}/docs/DoxyfilePages + WORKING_DIRECTORY ${OpenMW_BINARY_DIR} + COMMENT "Generating API documentation with Doxygen (from DoxyfilePages)" VERBATIM) +endif(DOXYGEN_FOUND) + diff --git a/docs/Doxyfile b/docs/Doxyfile.in similarity index 99% rename from docs/Doxyfile rename to docs/Doxyfile.in index a74fc7b0a..b5022ca8a 100644 --- a/docs/Doxyfile +++ b/docs/Doxyfile.in @@ -58,7 +58,7 @@ PROJECT_LOGO = # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = Doxygen +OUTPUT_DIRECTORY = @OpenMW_SOURCE_DIR@/docs/Doxygen # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and @@ -764,10 +764,10 @@ WARN_LOGFILE = # spaces. # Note: If this tag is empty the current directory is searched. -INPUT = apps \ - components \ - libs \ - docs +INPUT = @OpenMW_SOURCE_DIR@/apps \ + @OpenMW_SOURCE_DIR@/components \ + @OpenMW_SOURCE_DIR@/libs \ + @OpenMW_BINARY_DIR@/docs # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/docs/DoxyfilePages b/docs/DoxyfilePages.in similarity index 99% rename from docs/DoxyfilePages rename to docs/DoxyfilePages.in index dca9d7a12..cb9dc37d6 100644 --- a/docs/DoxyfilePages +++ b/docs/DoxyfilePages.in @@ -38,7 +38,7 @@ PROJECT_NUMBER = # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. -OUTPUT_DIRECTORY = ../doxygen +OUTPUT_DIRECTORY = @OpenMW_SOURCE_DIR@/doxygen # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output @@ -573,10 +573,10 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = apps \ - components \ - libs \ - docs +INPUT = @OpenMW_SOURCE_DIR@/apps \ + @OpenMW_SOURCE_DIR@/components \ + @OpenMW_SOURCE_DIR@/libs \ + @OpenMW_BINARY_DIR@/docs # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is From e1663de7cf2d9a788e4f14a9282b12cd3d99728f Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sun, 12 Oct 2014 11:40:14 +0200 Subject: [PATCH 22/32] Fixes #1887: Equipped items do not emit sounds Added getSound() method to MWClass class and implementation into Light class. Also added additional bool parameter responsible for enabling/disabling of playing items sounds into NpcAnimation class constructor. Signed-off-by: Lukasz Gromanowski --- apps/openmw/mwclass/light.cpp | 5 ++++ apps/openmw/mwclass/light.hpp | 2 ++ apps/openmw/mwrender/characterpreview.cpp | 4 +-- apps/openmw/mwrender/npcanimation.cpp | 33 ++++++++++++----------- apps/openmw/mwrender/npcanimation.hpp | 4 ++- apps/openmw/mwworld/class.cpp | 5 ++++ apps/openmw/mwworld/class.hpp | 3 +++ 7 files changed, 38 insertions(+), 18 deletions(-) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index eabebc72a..b1bbbcf73 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -297,4 +297,9 @@ namespace MWClass state2.mTime = dynamic_cast (*ptr.getRefData().getCustomData()).mTime; } + + const std::string& Light::getSound(const MWWorld::Ptr& ptr) const + { + return ptr.get()->mBase->mSound; + } } diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 584039336..467bfade8 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -82,6 +82,8 @@ namespace MWClass virtual void writeAdditionalState (const MWWorld::Ptr& ptr, ESM::ObjectState& state) const; ///< Write additional state from \a ptr into \a state. + + virtual const std::string& getSound(const MWWorld::Ptr& ptr) const; }; } diff --git a/apps/openmw/mwrender/characterpreview.cpp b/apps/openmw/mwrender/characterpreview.cpp index 1630e4005..d9c953133 100644 --- a/apps/openmw/mwrender/characterpreview.cpp +++ b/apps/openmw/mwrender/characterpreview.cpp @@ -85,7 +85,7 @@ namespace MWRender mNode = renderRoot->createChildSceneNode(); mAnimation = new NpcAnimation(mCharacter, mNode, - 0, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); + 0, true, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); Ogre::Vector3 scale = mNode->getScale(); mCamera->setPosition(mPosition * scale); @@ -118,7 +118,7 @@ namespace MWRender assert(mAnimation); delete mAnimation; mAnimation = new NpcAnimation(mCharacter, mNode, - 0, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); + 0, true, true, (renderHeadOnly() ? NpcAnimation::VM_HeadOnly : NpcAnimation::VM_Normal)); float scale=1.f; mCharacter.getClass().adjustScale(mCharacter, scale); diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 52144df04..67be5916c 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -177,7 +177,7 @@ NpcAnimation::~NpcAnimation() } -NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int visibilityFlags, bool disableListener, ViewMode viewMode) +NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int visibilityFlags, bool disableListener, bool disableSounds, ViewMode viewMode) : Animation(ptr, node), mVisibilityFlags(visibilityFlags), mListenerDisabled(disableListener), @@ -186,7 +186,8 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int v mShowCarriedLeft(true), mFirstPersonOffset(0.f, 0.f, 0.f), mAlpha(1.f), - mNpcType(Type_Normal) + mNpcType(Type_Normal), + mSoundsDisabled(disableSounds) { mNpc = mPtr.get()->mBase; @@ -625,7 +626,7 @@ void NpcAnimation::removeIndividualPart(ESM::PartReferenceType type) mPartslots[type] = -1; mObjectParts[type].setNull(); - if (!mSoundIds[type].empty()) + if (!mSoundIds[type].empty() && !mSoundsDisabled) { MWBase::Environment::get().getSoundManager()->stopSound3D(mPtr, mSoundIds[type]); mSoundIds[type].clear(); @@ -659,20 +660,22 @@ bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int g removeIndividualPart(type); mPartslots[type] = group; mPartPriorities[type] = priority; - - MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); - MWWorld::ContainerStoreIterator csi = inv.getSlot(group < 0 ? MWWorld::InventoryStore::Slot_Helmet : group); - if (csi != inv.end() && csi->getTypeName() == typeid(ESM::Light).name()) - { - mSoundIds[type] = csi->get()->mBase->mSound; - } mObjectParts[type] = insertBoundedPart(mesh, group, sPartList.at(type), enchantedGlow, glowColor); - if (!mSoundIds[type].empty() && mPtr.getClass().getCreatureStats(mPtr).getDrawState() == MWMechanics::DrawState_Nothing) - { - MWBase::Environment::get().getSoundManager()->playSound3D(mPtr, mSoundIds[type], 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, - MWBase::SoundManager::Play_Loop); - } + if (!mSoundsDisabled) + { + MWWorld::InventoryStore& inv = mPtr.getClass().getInventoryStore(mPtr); + MWWorld::ContainerStoreIterator csi = inv.getSlot(group < 0 ? MWWorld::InventoryStore::Slot_Helmet : group); + if (csi != inv.end()) + { + mSoundIds[type] = csi->getClass().getSound(*csi); + if (!mSoundIds[type].empty()) + { + MWBase::Environment::get().getSoundManager()->playSound3D(mPtr, mSoundIds[type], 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, + MWBase::SoundManager::Play_Loop); + } + } + } if(mObjectParts[type]->mSkelBase) { Ogre::SkeletonInstance *skel = mObjectParts[type]->mSkelBase->getSkeleton(); diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index b5119b2ad..ee62fce9c 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -98,6 +98,7 @@ private: Ogre::SharedPtr mWeaponAnimationTime; float mAlpha; + bool mSoundsDisabled; void updateNpcBase(); @@ -124,10 +125,11 @@ public: * one listener at a time, so you shouldn't do this if creating several NpcAnimations * for the same Ptr, eg preview dolls for the player. * Those need to be manually rendered anyway. + * @param disableSounds Same as \a disableListener but for playing items sounds * @param viewMode */ NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, int visibilityFlags, bool disableListener = false, - ViewMode viewMode=VM_Normal); + bool disableSounds = false, ViewMode viewMode=VM_Normal); virtual ~NpcAnimation(); virtual void enableHeadAnimation(bool enable); diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index ebe08dc44..981b6bfba 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -420,4 +420,9 @@ namespace MWWorld { throw std::runtime_error("this is not a door"); } + + const std::string& Class::getSound(const MWWorld::Ptr&) const + { + return std::string(); + } } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 8ac39eaa9..2bfd6e8e4 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -336,6 +336,9 @@ namespace MWWorld virtual void respawn (const MWWorld::Ptr& ptr) const {} virtual void restock (const MWWorld::Ptr& ptr) const {} + + /// Returns sound id + virtual const std::string& getSound(const MWWorld::Ptr& ptr) const; }; } From a6a3eca930e198de4d2d2a11eca1466a3ef527ea Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sun, 12 Oct 2014 13:38:41 +0200 Subject: [PATCH 23/32] Fixes #1887: Equipped items do not emit sounds Corrected wrong return type of Class::getSound() method. Signed-off-by: Lukasz Gromanowski --- apps/openmw/mwclass/light.cpp | 2 +- apps/openmw/mwclass/light.hpp | 2 +- apps/openmw/mwworld/class.cpp | 2 +- apps/openmw/mwworld/class.hpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/apps/openmw/mwclass/light.cpp b/apps/openmw/mwclass/light.cpp index b1bbbcf73..7b2d7e132 100644 --- a/apps/openmw/mwclass/light.cpp +++ b/apps/openmw/mwclass/light.cpp @@ -298,7 +298,7 @@ namespace MWClass state2.mTime = dynamic_cast (*ptr.getRefData().getCustomData()).mTime; } - const std::string& Light::getSound(const MWWorld::Ptr& ptr) const + std::string Light::getSound(const MWWorld::Ptr& ptr) const { return ptr.get()->mBase->mSound; } diff --git a/apps/openmw/mwclass/light.hpp b/apps/openmw/mwclass/light.hpp index 467bfade8..a3b841261 100644 --- a/apps/openmw/mwclass/light.hpp +++ b/apps/openmw/mwclass/light.hpp @@ -83,7 +83,7 @@ namespace MWClass const; ///< Write additional state from \a ptr into \a state. - virtual const std::string& getSound(const MWWorld::Ptr& ptr) const; + virtual std::string getSound(const MWWorld::Ptr& ptr) const; }; } diff --git a/apps/openmw/mwworld/class.cpp b/apps/openmw/mwworld/class.cpp index 981b6bfba..31e1a926a 100644 --- a/apps/openmw/mwworld/class.cpp +++ b/apps/openmw/mwworld/class.cpp @@ -421,7 +421,7 @@ namespace MWWorld throw std::runtime_error("this is not a door"); } - const std::string& Class::getSound(const MWWorld::Ptr&) const + std::string Class::getSound(const MWWorld::Ptr&) const { return std::string(); } diff --git a/apps/openmw/mwworld/class.hpp b/apps/openmw/mwworld/class.hpp index 2bfd6e8e4..053eb5133 100644 --- a/apps/openmw/mwworld/class.hpp +++ b/apps/openmw/mwworld/class.hpp @@ -338,7 +338,7 @@ namespace MWWorld virtual void restock (const MWWorld::Ptr& ptr) const {} /// Returns sound id - virtual const std::string& getSound(const MWWorld::Ptr& ptr) const; + virtual std::string getSound(const MWWorld::Ptr& ptr) const; }; } From 8cb09e89ede693741f8b5667b4f9c8846fbfab26 Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 9 Oct 2014 01:39:35 +0200 Subject: [PATCH 24/32] Make spells cast by scripts always succeed (Fixes #1993) --- apps/openmw/mwmechanics/spellcasting.cpp | 3 ++- apps/openmw/mwmechanics/spellcasting.hpp | 1 + apps/openmw/mwscript/miscextensions.cpp | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/apps/openmw/mwmechanics/spellcasting.cpp b/apps/openmw/mwmechanics/spellcasting.cpp index 35432e979..d33bb6ad1 100644 --- a/apps/openmw/mwmechanics/spellcasting.cpp +++ b/apps/openmw/mwmechanics/spellcasting.cpp @@ -292,6 +292,7 @@ namespace MWMechanics , mTarget(target) , mStack(false) , mHitPosition(0,0,0) + , mAlwaysSucceed(false) { } @@ -761,7 +762,7 @@ namespace MWMechanics int school = 0; - if (mCaster.getClass().isActor()) + if (mCaster.getClass().isActor() && !mAlwaysSucceed) { school = getSpellSchool(spell, mCaster); diff --git a/apps/openmw/mwmechanics/spellcasting.hpp b/apps/openmw/mwmechanics/spellcasting.hpp index c01fede37..395ae043b 100644 --- a/apps/openmw/mwmechanics/spellcasting.hpp +++ b/apps/openmw/mwmechanics/spellcasting.hpp @@ -68,6 +68,7 @@ namespace MWMechanics std::string mId; // ID of spell, potion, item etc std::string mSourceName; // Display name for spell, potion, etc Ogre::Vector3 mHitPosition; // Used for spawning area orb + bool mAlwaysSucceed; // Always succeed spells casted by NPCs/creatures regardless of their chance (default: false) public: CastSpell(const MWWorld::Ptr& caster, const MWWorld::Ptr& target); diff --git a/apps/openmw/mwscript/miscextensions.cpp b/apps/openmw/mwscript/miscextensions.cpp index ef879a95a..0de8f3b91 100644 --- a/apps/openmw/mwscript/miscextensions.cpp +++ b/apps/openmw/mwscript/miscextensions.cpp @@ -854,6 +854,7 @@ namespace MWScript MWMechanics::CastSpell cast(ptr, target); cast.mHitPosition = Ogre::Vector3(target.getRefData().getPosition().pos); + cast.mAlwaysSucceed = true; cast.cast(spell); } }; @@ -871,6 +872,7 @@ namespace MWScript MWMechanics::CastSpell cast(ptr, ptr); cast.mHitPosition = Ogre::Vector3(ptr.getRefData().getPosition().pos); + cast.mAlwaysSucceed = true; cast.cast(spell); } }; From 9323f962118007fff610fcff807ddc2f096df5da Mon Sep 17 00:00:00 2001 From: scrawl Date: Thu, 9 Oct 2014 17:19:35 +0200 Subject: [PATCH 25/32] Move terrainstorage to opencs_units_noqt --- apps/opencs/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/opencs/CMakeLists.txt b/apps/opencs/CMakeLists.txt index 8c29b221d..0d8e3d009 100644 --- a/apps/opencs/CMakeLists.txt +++ b/apps/opencs/CMakeLists.txt @@ -77,12 +77,12 @@ opencs_units (view/widget opencs_units (view/render scenewidget worldspacewidget pagedworldspacewidget unpagedworldspacewidget - previewwidget terrainstorage + previewwidget ) opencs_units_noqt (view/render navigation navigation1st navigationfree navigationorbit lighting lightingday lightingnight - lightingbright object cell + lightingbright object cell terrainstorage ) opencs_hdrs_noqt (view/render From d51daf5875a003b4653460f6951d61d736198538 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 12 Oct 2014 17:17:52 +0200 Subject: [PATCH 26/32] Fix AI not using F_Always spells, for example "vampire touch" --- apps/openmw/mwmechanics/aicombataction.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/apps/openmw/mwmechanics/aicombataction.cpp b/apps/openmw/mwmechanics/aicombataction.cpp index 152854af9..cc8279b1e 100644 --- a/apps/openmw/mwmechanics/aicombataction.cpp +++ b/apps/openmw/mwmechanics/aicombataction.cpp @@ -166,10 +166,18 @@ namespace MWMechanics { const CreatureStats& stats = actor.getClass().getCreatureStats(actor); - // Never casting racial spells (ST_Power and F_Always) - if (spell->mData.mType != ESM::Spell::ST_Spell || spell->mData.mFlags & ESM::Spell::F_Always) + if (spell->mData.mType != ESM::Spell::ST_Spell) return 0.f; + // Don't make use of racial bonus spells, like MW. Can be made optional later + if (actor.getClass().isNpc()) + { + std::string raceid = actor.get()->mBase->mRace; + const ESM::Race* race = MWBase::Environment::get().getWorld()->getStore().get().find(raceid); + if (race->mPowers.exists(spell->mId)) + return 0.f; + } + if (spell->mData.mCost > stats.getMagicka().getCurrent()) return 0.f; From 772c66eedf09e9eb8a5f349cf95c1bce27579074 Mon Sep 17 00:00:00 2001 From: vocollapse Date: Sun, 12 Oct 2014 18:30:39 +0200 Subject: [PATCH 27/32] Changed Doxygen file extensions to .cmake for consistency. Also changed output directories for doxygen. --- CMakeLists.txt | 20 +++++++++++++------ docs/{Doxyfile.in => Doxyfile.cmake} | 4 ++-- .../{DoxyfilePages.in => DoxyfilePages.cmake} | 4 ++-- 3 files changed, 18 insertions(+), 10 deletions(-) rename docs/{Doxyfile.in => Doxyfile.cmake} (99%) rename docs/{DoxyfilePages.in => DoxyfilePages.cmake} (99%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6725ec64b..2feb2aeac 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -837,17 +837,25 @@ if (APPLE) endif (APPLE) # Doxygen Target -- simply run 'make doc' or 'make doc_pages' +# output directory for 'make doc' is "${OpenMW_BINARY_DIR}/docs/Doxygen" +# output directory for 'make doc_pages' is "${DOXYGEN_PAGES_OUTPUT_DIR}" if defined +# or "${OpenMW_BINARY_DIR}/docs/Pages" otherwise find_package(Doxygen) -if(DOXYGEN_FOUND) - configure_file(${OpenMW_SOURCE_DIR}/docs/Doxyfile.in ${OpenMW_BINARY_DIR}/docs/Doxyfile @ONLY) - configure_file(${OpenMW_SOURCE_DIR}/docs/DoxyfilePages.in ${OpenMW_BINARY_DIR}/docs/DoxyfilePages @ONLY) +if (DOXYGEN_FOUND) + # determine output directory for doc_pages + if (NOT DEFINED DOXYGEN_PAGES_OUTPUT_DIR) + set(DOXYGEN_PAGES_OUTPUT_DIR "${OpenMW_BINARY_DIR}/docs/Pages") + endif () + configure_file(${OpenMW_SOURCE_DIR}/docs/Doxyfile.cmake ${OpenMW_BINARY_DIR}/docs/Doxyfile @ONLY) + configure_file(${OpenMW_SOURCE_DIR}/docs/DoxyfilePages.cmake ${OpenMW_BINARY_DIR}/docs/DoxyfilePages @ONLY) add_custom_target(doc ${DOXYGEN_EXECUTABLE} ${OpenMW_BINARY_DIR}/docs/Doxyfile WORKING_DIRECTORY ${OpenMW_BINARY_DIR} - COMMENT "Generating API documentation with Doxygen (from Doxyfile)" VERBATIM) + COMMENT "Generating Doxygen documentation at ${OpenMW_BINARY_DIR}/docs/Doxygen" + VERBATIM) add_custom_target(doc_pages ${DOXYGEN_EXECUTABLE} ${OpenMW_BINARY_DIR}/docs/DoxyfilePages WORKING_DIRECTORY ${OpenMW_BINARY_DIR} - COMMENT "Generating API documentation with Doxygen (from DoxyfilePages)" VERBATIM) -endif(DOXYGEN_FOUND) + COMMENT "Generating documentation for the github-pages at ${DOXYGEN_PAGES_OUTPUT_DIR}" VERBATIM) +endif () diff --git a/docs/Doxyfile.in b/docs/Doxyfile.cmake similarity index 99% rename from docs/Doxyfile.in rename to docs/Doxyfile.cmake index b5022ca8a..38ad84165 100644 --- a/docs/Doxyfile.in +++ b/docs/Doxyfile.cmake @@ -58,7 +58,7 @@ PROJECT_LOGO = # entered, it will be relative to the location where doxygen was started. If # left blank the current directory will be used. -OUTPUT_DIRECTORY = @OpenMW_SOURCE_DIR@/docs/Doxygen +OUTPUT_DIRECTORY = @OpenMW_BINARY_DIR@/docs/Doxygen # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and @@ -767,7 +767,7 @@ WARN_LOGFILE = INPUT = @OpenMW_SOURCE_DIR@/apps \ @OpenMW_SOURCE_DIR@/components \ @OpenMW_SOURCE_DIR@/libs \ - @OpenMW_BINARY_DIR@/docs + @OpenMW_BINARY_DIR@/docs/mainpage.hpp # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses diff --git a/docs/DoxyfilePages.in b/docs/DoxyfilePages.cmake similarity index 99% rename from docs/DoxyfilePages.in rename to docs/DoxyfilePages.cmake index cb9dc37d6..d50a043d6 100644 --- a/docs/DoxyfilePages.in +++ b/docs/DoxyfilePages.cmake @@ -38,7 +38,7 @@ PROJECT_NUMBER = # If a relative path is entered, it will be relative to the location # where doxygen was started. If left blank the current directory will be used. -OUTPUT_DIRECTORY = @OpenMW_SOURCE_DIR@/doxygen +OUTPUT_DIRECTORY = @DOXYGEN_PAGES_OUTPUT_DIR@ # If the CREATE_SUBDIRS tag is set to YES, then doxygen will create # 4096 sub-directories (in 2 levels) under the output directory of each output @@ -576,7 +576,7 @@ WARN_LOGFILE = INPUT = @OpenMW_SOURCE_DIR@/apps \ @OpenMW_SOURCE_DIR@/components \ @OpenMW_SOURCE_DIR@/libs \ - @OpenMW_BINARY_DIR@/docs + @OpenMW_BINARY_DIR@/docs/mainpage.hpp # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is From 9edcc332ec4e0f579b26a01529b26c079081b060 Mon Sep 17 00:00:00 2001 From: scrawl Date: Sun, 12 Oct 2014 18:35:15 +0200 Subject: [PATCH 28/32] Don't remove player's sounds when unloading a cell --- apps/openmw/mwsound/soundmanagerimp.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/apps/openmw/mwsound/soundmanagerimp.cpp b/apps/openmw/mwsound/soundmanagerimp.cpp index 812e49a64..781bfb5d5 100644 --- a/apps/openmw/mwsound/soundmanagerimp.cpp +++ b/apps/openmw/mwsound/soundmanagerimp.cpp @@ -454,6 +454,7 @@ namespace MWSound while(snditer != mActiveSounds.end()) { if(snditer->second.first != MWWorld::Ptr() && + snditer->second.first.getCellRef().getRefId() != "player" && snditer->second.first.getCell() == cell) { snditer->first->stop(); From 8d6f953185b169c029cff62410ddc0a0b6e28da3 Mon Sep 17 00:00:00 2001 From: Marc Zinnschlag Date: Sun, 12 Oct 2014 18:53:40 +0200 Subject: [PATCH 29/32] updated credits file --- credits.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/credits.txt b/credits.txt index ab83b93be..225bba194 100644 --- a/credits.txt +++ b/credits.txt @@ -94,6 +94,7 @@ Thomas Luppi (Digmaster) Tom Mason (wheybags) Torben Leif Carrington (TorbenC) Vincent Heuken +vocollapse Packagers: Alexander Olofsson (Ace) - Windows From 8456741eaa0e5dc79abf25394b968ec6e8571766 Mon Sep 17 00:00:00 2001 From: MiroslavR Date: Sun, 12 Oct 2014 19:06:40 +0200 Subject: [PATCH 30/32] Fix blindness and create a separate fader for it --- apps/openmw/mwbase/windowmanager.hpp | 4 ++-- apps/openmw/mwgui/screenfader.cpp | 5 +++-- apps/openmw/mwgui/windowmanagerimp.cpp | 15 +++++++++------ apps/openmw/mwgui/windowmanagerimp.hpp | 5 +++-- apps/openmw/mwrender/renderingmanager.cpp | 2 +- 5 files changed, 18 insertions(+), 13 deletions(-) diff --git a/apps/openmw/mwbase/windowmanager.hpp b/apps/openmw/mwbase/windowmanager.hpp index adffa9903..bfc4f3b33 100644 --- a/apps/openmw/mwbase/windowmanager.hpp +++ b/apps/openmw/mwbase/windowmanager.hpp @@ -335,8 +335,8 @@ namespace MWBase virtual void fadeScreenOut(const float time) = 0; /// Fade the screen to a specified percentage of black, over \a time seconds virtual void fadeScreenTo(const int percent, const float time) = 0; - /// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading. - virtual void setScreenFactor (float factor) = 0; + /// Darken the screen to a specified percentage + virtual void setBlindness(const int percent) = 0; virtual void activateHitOverlay(bool interrupt=true) = 0; virtual void setWerewolfOverlay(bool set) = 0; diff --git a/apps/openmw/mwgui/screenfader.cpp b/apps/openmw/mwgui/screenfader.cpp index f2b3fa6af..a0421ec28 100644 --- a/apps/openmw/mwgui/screenfader.cpp +++ b/apps/openmw/mwgui/screenfader.cpp @@ -98,12 +98,12 @@ namespace MWGui void ScreenFader::fadeIn(float time) { - queue(time, 0.f); + queue(time, 1.f); } void ScreenFader::fadeOut(const float time) { - queue(time, 1.f); + queue(time, 0.f); } void ScreenFader::fadeTo(const int percent, const float time) @@ -114,6 +114,7 @@ namespace MWGui void ScreenFader::setFactor(float factor) { mFactor = factor; + applyAlpha(); } void ScreenFader::setRepeat(bool repeat) diff --git a/apps/openmw/mwgui/windowmanagerimp.cpp b/apps/openmw/mwgui/windowmanagerimp.cpp index 7560f8738..5a1b0b417 100644 --- a/apps/openmw/mwgui/windowmanagerimp.cpp +++ b/apps/openmw/mwgui/windowmanagerimp.cpp @@ -120,8 +120,9 @@ namespace MWGui , mCompanionWindow(NULL) , mVideoBackground(NULL) , mVideoWidget(NULL) - , mHitFader(NULL) , mWerewolfFader(NULL) + , mBlindnessFader(NULL) + , mHitFader(NULL) , mScreenFader(NULL) , mDebugWindow(NULL) , mTranslationDataStorage (translationDataStorage) @@ -273,6 +274,7 @@ namespace MWGui trackWindow(mCompanionWindow, "companion"); mWerewolfFader = new ScreenFader("textures\\werewolfoverlay.dds"); + mBlindnessFader = new ScreenFader("black.png"); std::string hitFaderTexture = "textures\\bm_player_hit_01.dds"; // fall back to player_hit_01.dds if bm_player_hit_01.dds is not available // TODO: check if non-BM versions actually use player_hit_01.dds @@ -877,8 +879,9 @@ namespace MWGui mConsole->checkReferenceAvailable(); mCompanionWindow->onFrame(); - mHitFader->update(frameDuration); mWerewolfFader->update(frameDuration); + mBlindnessFader->update(frameDuration); + mHitFader->update(frameDuration); mScreenFader->update(frameDuration); mDebugWindow->onFrame(frameDuration); @@ -1741,13 +1744,13 @@ namespace MWGui void WindowManager::fadeScreenIn(const float time) { mScreenFader->clearQueue(); - mScreenFader->fadeIn(time); + mScreenFader->fadeOut(time); } void WindowManager::fadeScreenOut(const float time) { mScreenFader->clearQueue(); - mScreenFader->fadeOut(time); + mScreenFader->fadeIn(time); } void WindowManager::fadeScreenTo(const int percent, const float time) @@ -1756,9 +1759,9 @@ namespace MWGui mScreenFader->fadeTo(percent, time); } - void WindowManager::setScreenFactor(float factor) + void WindowManager::setBlindness(const int percent) { - mScreenFader->setFactor(factor); + mBlindnessFader->notifyAlphaChanged(percent / 100.f); } void WindowManager::activateHitOverlay(bool interrupt) diff --git a/apps/openmw/mwgui/windowmanagerimp.hpp b/apps/openmw/mwgui/windowmanagerimp.hpp index 088f6c6e9..aa5bd0fc9 100644 --- a/apps/openmw/mwgui/windowmanagerimp.hpp +++ b/apps/openmw/mwgui/windowmanagerimp.hpp @@ -330,8 +330,8 @@ namespace MWGui virtual void fadeScreenOut(const float time); /// Fade the screen to a specified percentage of black, over \a time seconds virtual void fadeScreenTo(const int percent, const float time); - /// Darken the screen by \a factor (1.0 = no darkening). Works independently from screen fading. - virtual void setScreenFactor (float factor); + /// Darken the screen to a specified percentage + virtual void setBlindness(const int percent); virtual void activateHitOverlay(bool interrupt); virtual void setWerewolfOverlay(bool set); @@ -391,6 +391,7 @@ namespace MWGui MyGUI::ImageBox* mVideoBackground; VideoWidget* mVideoWidget; ScreenFader* mWerewolfFader; + ScreenFader* mBlindnessFader; ScreenFader* mHitFader; ScreenFader* mScreenFader; DebugWindow* mDebugWindow; diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index ae8bb3b2d..47ab4b13d 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -347,7 +347,7 @@ void RenderingManager::update (float duration, bool paused) MWWorld::Ptr player = world->getPlayerPtr(); int blind = player.getClass().getCreatureStats(player).getMagicEffects().get(ESM::MagicEffect::Blind).getMagnitude(); - MWBase::Environment::get().getWindowManager()->setScreenFactor(std::max(0.f, 1.f-(blind / 100.f))); + MWBase::Environment::get().getWindowManager()->setBlindness(std::max(0, std::min(100, blind))); setAmbientMode(); if (player.getClass().getNpcStats(player).isWerewolf()) From 4d62541b62d7fe7cd420aecee9d68547f5b2a2aa Mon Sep 17 00:00:00 2001 From: Thoronador Date: Sun, 12 Oct 2014 23:26:03 +0200 Subject: [PATCH 31/32] fix usage of numeric_limits static functions min() and max() Functions min() and max() of std::numeric_limits are static and can therefore be accessed via class name and :: operator. --- apps/openmw/mwgui/dialogue.cpp | 2 +- apps/openmw/mwmechanics/actors.cpp | 2 +- apps/openmw/mwrender/renderingmanager.cpp | 2 +- apps/openmw/mwscript/cellextensions.cpp | 2 +- apps/openmw/mwscript/interpretercontext.cpp | 2 +- apps/openmw/mwsound/loudness.cpp | 2 +- apps/openmw/mwworld/scene.cpp | 8 ++++---- components/esmterrain/storage.cpp | 4 ++-- components/widgets/numericeditbox.hpp | 4 ++-- 9 files changed, 14 insertions(+), 14 deletions(-) diff --git a/apps/openmw/mwgui/dialogue.cpp b/apps/openmw/mwgui/dialogue.cpp index 196e7d8c7..6526b200f 100644 --- a/apps/openmw/mwgui/dialogue.cpp +++ b/apps/openmw/mwgui/dialogue.cpp @@ -507,7 +507,7 @@ namespace MWGui mScrollBar->setVisible(true); } - BookTypesetter::Ptr typesetter = BookTypesetter::create (mHistory->getWidth(), std::numeric_limits().max()); + BookTypesetter::Ptr typesetter = BookTypesetter::create (mHistory->getWidth(), std::numeric_limits::max()); for (std::vector::iterator it = mHistoryContents.begin(); it != mHistoryContents.end(); ++it) (*it)->write(typesetter, &mKeywordSearch, mTopicLinks); diff --git a/apps/openmw/mwmechanics/actors.cpp b/apps/openmw/mwmechanics/actors.cpp index 9b66f7afb..a31e64dd3 100644 --- a/apps/openmw/mwmechanics/actors.cpp +++ b/apps/openmw/mwmechanics/actors.cpp @@ -220,7 +220,7 @@ namespace MWMechanics // Use the smallest soulgem that is large enough to hold the soul MWWorld::ContainerStore& container = caster.getClass().getContainerStore(caster); MWWorld::ContainerStoreIterator gem = container.end(); - float gemCapacity = std::numeric_limits().max(); + float gemCapacity = std::numeric_limits::max(); std::string soulgemFilter = "misc_soulgem"; // no other way to check for soulgems? :/ for (MWWorld::ContainerStoreIterator it = container.begin(MWWorld::ContainerStore::Type_Miscellaneous); it != container.end(); ++it) diff --git a/apps/openmw/mwrender/renderingmanager.cpp b/apps/openmw/mwrender/renderingmanager.cpp index ae8bb3b2d..414e13cf6 100644 --- a/apps/openmw/mwrender/renderingmanager.cpp +++ b/apps/openmw/mwrender/renderingmanager.cpp @@ -515,7 +515,7 @@ void RenderingManager::configureFog(const float density, const Ogre::ColourValue if (density == 0) { mFogStart = 0; - mFogEnd = std::numeric_limits().max(); + mFogEnd = std::numeric_limits::max(); mRendering.getCamera()->setFarClipDistance (max); } else diff --git a/apps/openmw/mwscript/cellextensions.cpp b/apps/openmw/mwscript/cellextensions.cpp index 94d734029..a568b7943 100644 --- a/apps/openmw/mwscript/cellextensions.cpp +++ b/apps/openmw/mwscript/cellextensions.cpp @@ -153,7 +153,7 @@ namespace MWScript if (cell->getCell()->hasWater()) runtime.push (cell->getWaterLevel()); else - runtime.push (-std::numeric_limits().max()); + runtime.push (-std::numeric_limits::max()); } }; diff --git a/apps/openmw/mwscript/interpretercontext.cpp b/apps/openmw/mwscript/interpretercontext.cpp index c43a010b4..cb02a6c97 100644 --- a/apps/openmw/mwscript/interpretercontext.cpp +++ b/apps/openmw/mwscript/interpretercontext.cpp @@ -438,7 +438,7 @@ namespace MWScript // If the objects are in different worldspaces, return a large value (just like vanilla) if (ref.getCell()->getCell()->getCellId().mWorldspace != ref2.getCell()->getCell()->getCellId().mWorldspace) - return std::numeric_limits().max(); + return std::numeric_limits::max(); double diff[3]; diff --git a/apps/openmw/mwsound/loudness.cpp b/apps/openmw/mwsound/loudness.cpp index ebe3bf1ec..c64913b1f 100644 --- a/apps/openmw/mwsound/loudness.cpp +++ b/apps/openmw/mwsound/loudness.cpp @@ -29,7 +29,7 @@ namespace MWSound else if (type == SampleType_Int16) { value = *reinterpret_cast(&data[sample*advance]); - value /= float(std::numeric_limits().max()); + value /= float(std::numeric_limits::max()); } else if (type == SampleType_Float32) { diff --git a/apps/openmw/mwworld/scene.cpp b/apps/openmw/mwworld/scene.cpp index 66c9f5b71..6f18a6ef3 100644 --- a/apps/openmw/mwworld/scene.cpp +++ b/apps/openmw/mwworld/scene.cpp @@ -124,10 +124,10 @@ namespace MWWorld void Scene::getGridCenter(int &cellX, int &cellY) { - int maxX = std::numeric_limits().min(); - int maxY = std::numeric_limits().min(); - int minX = std::numeric_limits().max(); - int minY = std::numeric_limits().max(); + int maxX = std::numeric_limits::min(); + int maxY = std::numeric_limits::min(); + int minX = std::numeric_limits::max(); + int minY = std::numeric_limits::max(); CellStoreCollection::iterator iter = mActiveCells.begin(); while (iter!=mActiveCells.end()) { diff --git a/components/esmterrain/storage.cpp b/components/esmterrain/storage.cpp index c4152533e..3c76cc3b4 100644 --- a/components/esmterrain/storage.cpp +++ b/components/esmterrain/storage.cpp @@ -34,8 +34,8 @@ namespace ESMTerrain if (!land) return false; - min = std::numeric_limits().max(); - max = -std::numeric_limits().max(); + min = std::numeric_limits::max(); + max = -std::numeric_limits::max(); for (int row=0; row().min()), - mMaxValue(std::numeric_limits().max()) + : mValue(0), mMinValue(std::numeric_limits::min()), + mMaxValue(std::numeric_limits::max()) {} void initialiseOverride(); From 46496a35a12ccdc2eb82fcfbc2c88be84bce4b99 Mon Sep 17 00:00:00 2001 From: Thoronador Date: Sun, 12 Oct 2014 23:42:44 +0200 Subject: [PATCH 32/32] fix uninitialized pointer variable in CSVDoc::SubView class --- apps/opencs/view/doc/subview.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/opencs/view/doc/subview.cpp b/apps/opencs/view/doc/subview.cpp index be03f91a5..ab4325cfc 100644 --- a/apps/opencs/view/doc/subview.cpp +++ b/apps/opencs/view/doc/subview.cpp @@ -2,7 +2,8 @@ #include "view.hpp" -CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id) : mUniversalId (id) +CSVDoc::SubView::SubView (const CSMWorld::UniversalId& id) + : mUniversalId (id), mParent (NULL) { /// \todo add a button to the title bar that clones this sub view