From 8984d8f8ee3efcccea658ac84ccbaa4a21e89e3e Mon Sep 17 00:00:00 2001 From: Chris Robinson Date: Mon, 5 Aug 2013 18:59:55 -0700 Subject: [PATCH] Use a map to simplify NPC part referencing --- apps/openmw/mwrender/npcanimation.cpp | 166 ++++++++++++-------------- apps/openmw/mwrender/npcanimation.hpp | 30 ++--- 2 files changed, 88 insertions(+), 108 deletions(-) diff --git a/apps/openmw/mwrender/npcanimation.cpp b/apps/openmw/mwrender/npcanimation.cpp index 6611b3694..2d3cea12f 100644 --- a/apps/openmw/mwrender/npcanimation.cpp +++ b/apps/openmw/mwrender/npcanimation.cpp @@ -20,40 +20,44 @@ namespace MWRender { -const NpcAnimation::PartInfo NpcAnimation::sPartList[NpcAnimation::sPartListSize] = { - { ESM::PRT_Head, "Head" }, - { ESM::PRT_Hair, "Head" }, - { ESM::PRT_Neck, "Neck" }, - { ESM::PRT_Cuirass, "Chest" }, - { ESM::PRT_Groin, "Groin" }, - { ESM::PRT_Skirt, "Groin" }, - { ESM::PRT_RHand, "Right Hand" }, - { ESM::PRT_LHand, "Left Hand" }, - { ESM::PRT_RWrist, "Right Wrist" }, - { ESM::PRT_LWrist, "Left Wrist" }, - { ESM::PRT_Shield, "Shield Bone" }, - { ESM::PRT_RForearm, "Right Forearm" }, - { ESM::PRT_LForearm, "Left Forearm" }, - { ESM::PRT_RUpperarm, "Right Upper Arm" }, - { ESM::PRT_LUpperarm, "Left Upper Arm" }, - { ESM::PRT_RFoot, "Right Foot" }, - { ESM::PRT_LFoot, "Left Foot" }, - { ESM::PRT_RAnkle, "Right Ankle" }, - { ESM::PRT_LAnkle, "Left Ankle" }, - { ESM::PRT_RKnee, "Right Knee" }, - { ESM::PRT_LKnee, "Left Knee" }, - { ESM::PRT_RLeg, "Right Upper Leg" }, - { ESM::PRT_LLeg, "Left Upper Leg" }, - { ESM::PRT_RPauldron, "Right Clavicle" }, - { ESM::PRT_LPauldron, "Left Clavicle" }, - { ESM::PRT_Weapon, "Weapon Bone" }, - { ESM::PRT_Tail, "Tail" } -}; +static NpcAnimation::PartBoneMap createPartListMap() +{ + NpcAnimation::PartBoneMap result; + result.insert(std::make_pair(ESM::PRT_Head, "Head")); + result.insert(std::make_pair(ESM::PRT_Hair, "Head")); + result.insert(std::make_pair(ESM::PRT_Neck, "Neck")); + result.insert(std::make_pair(ESM::PRT_Cuirass, "Chest")); + result.insert(std::make_pair(ESM::PRT_Groin, "Groin")); + result.insert(std::make_pair(ESM::PRT_Skirt, "Groin")); + result.insert(std::make_pair(ESM::PRT_RHand, "Right Hand")); + result.insert(std::make_pair(ESM::PRT_LHand, "Left Hand")); + result.insert(std::make_pair(ESM::PRT_RWrist, "Right Wrist")); + result.insert(std::make_pair(ESM::PRT_LWrist, "Left Wrist")); + result.insert(std::make_pair(ESM::PRT_Shield, "Shield Bone")); + result.insert(std::make_pair(ESM::PRT_RForearm, "Right Forearm")); + result.insert(std::make_pair(ESM::PRT_LForearm, "Left Forearm")); + result.insert(std::make_pair(ESM::PRT_RUpperarm, "Right Upper Arm")); + result.insert(std::make_pair(ESM::PRT_LUpperarm, "Left Upper Arm")); + result.insert(std::make_pair(ESM::PRT_RFoot, "Right Foot")); + result.insert(std::make_pair(ESM::PRT_LFoot, "Left Foot")); + result.insert(std::make_pair(ESM::PRT_RAnkle, "Right Ankle")); + result.insert(std::make_pair(ESM::PRT_LAnkle, "Left Ankle")); + result.insert(std::make_pair(ESM::PRT_RKnee, "Right Knee")); + result.insert(std::make_pair(ESM::PRT_LKnee, "Left Knee")); + result.insert(std::make_pair(ESM::PRT_RLeg, "Right Upper Leg")); + result.insert(std::make_pair(ESM::PRT_LLeg, "Left Upper Leg")); + result.insert(std::make_pair(ESM::PRT_RPauldron, "Right Clavicle")); + result.insert(std::make_pair(ESM::PRT_LPauldron, "Left Clavicle")); + result.insert(std::make_pair(ESM::PRT_Weapon, "Weapon Bone")); + result.insert(std::make_pair(ESM::PRT_Tail, "Tail")); + return result; +} +const NpcAnimation::PartBoneMap NpcAnimation::sPartList = createPartListMap(); NpcAnimation::~NpcAnimation() { Ogre::SceneManager *sceneMgr = mInsert->getCreator(); - for(size_t i = 0;i < sPartListSize;i++) + for(size_t i = 0;i < ESM::PRT_Count;i++) destroyObjectList(sceneMgr, mObjectParts[i]); } @@ -82,7 +86,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor { mNpc = mPtr.get()->mBase; - for(size_t i = 0;i < sPartListSize;i++) + for(size_t i = 0;i < ESM::PRT_Count;i++) { mPartslots[i] = -1; //each slot is empty mPartPriorities[i] = 0; @@ -168,8 +172,8 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode) } MWBase::Environment::get().getMechanicsManager()->forceStateUpdate(mPtr); - for(size_t i = 0;i < sPartListSize;i++) - removeIndividualPart(i); + for(size_t i = 0;i < ESM::PRT_Count;i++) + removeIndividualPart((ESM::PartReferenceType)i); forceUpdate(); } @@ -276,14 +280,7 @@ void NpcAnimation::updateParts(bool forceupdate) const ESM::Light *light = part.get()->mBase; addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft, 1, "meshes\\"+light->mModel); - for(size_t i = 0;i < sPartListSize;i++) - { - if(ESM::PRT_Shield == sPartList[i].type) - { - addExtraLight(mInsert->getCreator(), mObjectParts[i], light); - break; - } - } + addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield], light); } } @@ -386,7 +383,8 @@ void NpcAnimation::updateParts(bool forceupdate) { const ESM::BodyPart* bodypart = parts[part]; if(bodypart) - addOrReplaceIndividualPart(part, -1,1, "meshes\\"+bodypart->mModel); + addOrReplaceIndividualPart((ESM::PartReferenceType)part, -1, 1, + "meshes\\"+bodypart->mModel); } } } @@ -442,7 +440,7 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) node->pitch(Ogre::Radian(pitch*0.75f), Ogre::Node::TS_WORLD); } - for(size_t i = 0;i < sPartListSize;i++) + for(size_t i = 0;i < ESM::PRT_Count;i++) { std::vector >::iterator ctrl(mObjectParts[i].mControllers.begin()); for(;ctrl != mObjectParts[i].mControllers.end();ctrl++) @@ -457,22 +455,15 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed) return ret; } -void NpcAnimation::removeIndividualPart(int type) +void NpcAnimation::removeIndividualPart(ESM::PartReferenceType type) { mPartPriorities[type] = 0; mPartslots[type] = -1; - for(size_t i = 0;i < sPartListSize;i++) - { - if(type == sPartList[i].type) - { - destroyObjectList(mInsert->getCreator(), mObjectParts[i]); - break; - } - } + destroyObjectList(mInsert->getCreator(), mObjectParts[type]); } -void NpcAnimation::reserveIndividualPart(int type, int group, int priority) +void NpcAnimation::reserveIndividualPart(ESM::PartReferenceType type, int group, int priority) { if(priority > mPartPriorities[type]) { @@ -484,14 +475,14 @@ void NpcAnimation::reserveIndividualPart(int type, int group, int priority) void NpcAnimation::removePartGroup(int group) { - for(int i = 0; i < 27; i++) + for(int i = 0; i < ESM::PRT_Count; i++) { if(mPartslots[i] == group) - removeIndividualPart(i); + removeIndividualPart((ESM::PartReferenceType)i); } } -bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, const std::string &mesh) +bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int group, int priority, const std::string &mesh) { if(priority <= mPartPriorities[type]) return false; @@ -500,43 +491,36 @@ bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority, mPartslots[type] = group; mPartPriorities[type] = priority; - for(size_t i = 0;i < sPartListSize;i++) + mObjectParts[type] = insertBoundedPart(mesh, group, sPartList.at(type)); + if(mObjectParts[type].mSkelBase && mObjectParts[type].mSkelBase->isParentTagPoint()) { - if(type == sPartList[i].type) + Ogre::Node *root = mObjectParts[type].mSkelBase->getParentNode(); + Ogre::SkeletonInstance *skel = mObjectParts[type].mSkelBase->getSkeleton(); + if(skel->hasBone("BoneOffset")) { - mObjectParts[i] = insertBoundedPart(mesh, group, sPartList[i].name); - if(mObjectParts[i].mSkelBase && mObjectParts[i].mSkelBase->isParentTagPoint()) - { - Ogre::Node *root = mObjectParts[i].mSkelBase->getParentNode(); - Ogre::SkeletonInstance *skel = mObjectParts[i].mSkelBase->getSkeleton(); - if(skel->hasBone("BoneOffset")) - { - Ogre::Bone *offset = skel->getBone("BoneOffset"); - root->translate(offset->getPosition()); - root->rotate(offset->getOrientation()); - // HACK: Why an extra -90 degree rotation? - root->pitch(Ogre::Degree(-90.0f)); - root->scale(offset->getScale()); - root->setInitialState(); - } - } - - // TODO: - // type == ESM::PRT_Head should get an animation source based on the current output of - // the actor's 'say' sound (0 = silent, 1 = loud?). - // type == ESM::PRT_Weapon should get an animation source based on the current offset - // of the weapon attack animation (from its beginning, or start marker?) - std::vector >::iterator ctrl(mObjectParts[i].mControllers.begin()); - for(;ctrl != mObjectParts[i].mControllers.end();ctrl++) - { - if(ctrl->getSource().isNull()) - ctrl->setSource(mNullAnimationValuePtr); - } - - break; + Ogre::Bone *offset = skel->getBone("BoneOffset"); + root->translate(offset->getPosition()); + root->rotate(offset->getOrientation()); + // HACK: Why an extra -90 degree rotation? + root->pitch(Ogre::Degree(-90.0f)); + root->scale(offset->getScale()); + root->setInitialState(); } } - return true; + + // TODO: + // type == ESM::PRT_Head should get an animation source based on the current output of + // the actor's 'say' sound (0 = silent, 1 = loud?). + // type == ESM::PRT_Weapon should get an animation source based on the current offset + // of the weapon attack animation (from its beginning, or start marker?) + std::vector >::iterator ctrl(mObjectParts[type].mControllers.begin()); + for(;ctrl != mObjectParts[type].mControllers.end();ctrl++) + { + if(ctrl->getSource().isNull()) + ctrl->setSource(mNullAnimationValuePtr); + } + + return true; } void NpcAnimation::addPartGroup(int group, int priority, const std::vector &parts) @@ -577,9 +561,9 @@ void NpcAnimation::addPartGroup(int group, int priority, const std::vectormPart, group, priority, "meshes\\"+bodypart->mModel); + addOrReplaceIndividualPart((ESM::PartReferenceType)part->mPart, group, priority, "meshes\\"+bodypart->mModel); else - reserveIndividualPart(part->mPart, group, priority); + reserveIndividualPart((ESM::PartReferenceType)part->mPart, group, priority); } } diff --git a/apps/openmw/mwrender/npcanimation.hpp b/apps/openmw/mwrender/npcanimation.hpp index e72fa56ed..aa51ffbe9 100644 --- a/apps/openmw/mwrender/npcanimation.hpp +++ b/apps/openmw/mwrender/npcanimation.hpp @@ -21,25 +21,21 @@ namespace MWRender class NpcAnimation : public Animation { public: -struct PartInfo { - ESM::PartReferenceType type; - const char name[32]; -}; + typedef std::map PartBoneMap; -enum ViewMode { - VM_Normal, - VM_FirstPerson, - VM_HeadOnly -}; + enum ViewMode { + VM_Normal, + VM_FirstPerson, + VM_HeadOnly + }; private: - static const size_t sPartListSize = 27; - static const PartInfo sPartList[sPartListSize]; + static const PartBoneMap sPartList; int mStateID; // Bounded Parts - NifOgre::ObjectList mObjectParts[sPartListSize]; + NifOgre::ObjectList mObjectParts[ESM::PRT_Count]; const ESM::NPC *mNpc; std::string mHeadModel; @@ -66,17 +62,17 @@ private: int mVisibilityFlags; - int mPartslots[sPartListSize]; //Each part slot is taken by clothing, armor, or is empty - int mPartPriorities[sPartListSize]; + int mPartslots[ESM::PRT_Count]; //Each part slot is taken by clothing, armor, or is empty + int mPartPriorities[ESM::PRT_Count]; NifOgre::ObjectList insertBoundedPart(const std::string &model, int group, const std::string &bonename); void updateParts(bool forceupdate = false); - void removeIndividualPart(int type); - void reserveIndividualPart(int type, int group, int priority); + void removeIndividualPart(ESM::PartReferenceType type); + void reserveIndividualPart(ESM::PartReferenceType type, int group, int priority); - bool addOrReplaceIndividualPart(int type, int group, int priority, const std::string &mesh); + bool addOrReplaceIndividualPart(ESM::PartReferenceType type, int group, int priority, const std::string &mesh); void removePartGroup(int group); void addPartGroup(int group, int priority, const std::vector &parts);