Use a map to simplify NPC part referencing

actorid
Chris Robinson 12 years ago
parent e976bb16c5
commit 8984d8f8ee

@ -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…
Cancel
Save