From 566211e7532e1b30f3429b7c0f06198c4f9fdf50 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Fri, 3 Oct 2014 22:39:05 +0200 Subject: [PATCH 01/10] 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/10] 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/10] 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/10] 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 | 77 +++++++++++++++++++++----- apps/openmw/mwrender/npcanimation.hpp | 8 +-- apps/openmw/mwworld/inventorystore.cpp | 23 +++++--- apps/openmw/mwworld/inventorystore.hpp | 9 +-- 4 files changed, 85 insertions(+), 32 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,32 +930,79 @@ 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 (item.getTypeName() == typeid(ESM::Light).name()) + { + soundId = item.get()->mBase->mSound; + } - if (state == InventoryStoreListener::EQUIPPED) + if (!soundId.empty()) { - sndMgr->playSound3D(mPtr, soundId, 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, - MWBase::SoundManager::Play_Loop); + 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::UNEQUIPPED) + } + 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) { - sndMgr->stopSound3D(mPtr, soundId); + 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 fa65c8981a963224ed86480bb54fe16d3ea244e1 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 11 Oct 2014 21:05:12 +0200 Subject: [PATCH 05/10] 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()) + { + soundId = csi->get()->mBase->mSound; + } + mObjectParts[type] = std::make_pair(insertBoundedPart(mesh, group, sPartList.at(type), enchantedGlow, glowColor), soundId); + if (!soundId.empty()) { - Ogre::SkeletonInstance *skel = mObjectParts[type]->mSkelBase->getSkeleton(); - if(mObjectParts[type]->mSkelBase->isParentTagPoint()) + 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 3b9cfba03cef103ab02b11b3bbf76e4cd8e7a5ae Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 11 Oct 2014 22:21:59 +0200 Subject: [PATCH 06/10] 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 07/10] 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 b44ba84a8099779fce7312a26f95cd6cb3952c77 Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sat, 11 Oct 2014 23:18:09 +0200 Subject: [PATCH 08/10] 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 e1663de7cf2d9a788e4f14a9282b12cd3d99728f Mon Sep 17 00:00:00 2001 From: Lukasz Gromanowski Date: Sun, 12 Oct 2014 11:40:14 +0200 Subject: [PATCH 09/10] 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 | 31 +++++++++++++---------- apps/openmw/mwrender/npcanimation.hpp | 4 ++- apps/openmw/mwworld/class.cpp | 5 ++++ apps/openmw/mwworld/class.hpp | 3 +++ 7 files changed, 37 insertions(+), 17 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) + + if (!mSoundsDisabled) { - MWBase::Environment::get().getSoundManager()->playSound3D(mPtr, mSoundIds[type], 1.0f, 1.0f, MWBase::SoundManager::Play_TypeSfx, - MWBase::SoundManager::Play_Loop); + 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 10/10] 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; }; }