mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-29 01:41:38 +00:00
Use a map to simplify NPC part referencing
This commit is contained in:
parent
e976bb16c5
commit
8984d8f8ee
2 changed files with 88 additions and 108 deletions
|
@ -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<ESM::NPC>()->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<ESM::Light>()->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<Ogre::Controller<Ogre::Real> >::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<Ogre::Controller<Ogre::Real> >::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<Ogre::Controller<Ogre::Real> >::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<ESM::PartReference> &parts)
|
||||
|
@ -577,9 +561,9 @@ void NpcAnimation::addPartGroup(int group, int priority, const std::vector<ESM::
|
|||
}
|
||||
|
||||
if(bodypart)
|
||||
addOrReplaceIndividualPart(part->mPart, 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,25 +21,21 @@ namespace MWRender
|
|||
class NpcAnimation : public Animation
|
||||
{
|
||||
public:
|
||||
struct PartInfo {
|
||||
ESM::PartReferenceType type;
|
||||
const char name[32];
|
||||
};
|
||||
typedef std::map<ESM::PartReferenceType,std::string> 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<ESM::PartReference> &parts);
|
||||
|
||||
|
|
Loading…
Reference in a new issue