forked from mirror/openmw-tes3mp
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
|
namespace MWRender
|
||||||
{
|
{
|
||||||
|
|
||||||
const NpcAnimation::PartInfo NpcAnimation::sPartList[NpcAnimation::sPartListSize] = {
|
static NpcAnimation::PartBoneMap createPartListMap()
|
||||||
{ ESM::PRT_Head, "Head" },
|
{
|
||||||
{ ESM::PRT_Hair, "Head" },
|
NpcAnimation::PartBoneMap result;
|
||||||
{ ESM::PRT_Neck, "Neck" },
|
result.insert(std::make_pair(ESM::PRT_Head, "Head"));
|
||||||
{ ESM::PRT_Cuirass, "Chest" },
|
result.insert(std::make_pair(ESM::PRT_Hair, "Head"));
|
||||||
{ ESM::PRT_Groin, "Groin" },
|
result.insert(std::make_pair(ESM::PRT_Neck, "Neck"));
|
||||||
{ ESM::PRT_Skirt, "Groin" },
|
result.insert(std::make_pair(ESM::PRT_Cuirass, "Chest"));
|
||||||
{ ESM::PRT_RHand, "Right Hand" },
|
result.insert(std::make_pair(ESM::PRT_Groin, "Groin"));
|
||||||
{ ESM::PRT_LHand, "Left Hand" },
|
result.insert(std::make_pair(ESM::PRT_Skirt, "Groin"));
|
||||||
{ ESM::PRT_RWrist, "Right Wrist" },
|
result.insert(std::make_pair(ESM::PRT_RHand, "Right Hand"));
|
||||||
{ ESM::PRT_LWrist, "Left Wrist" },
|
result.insert(std::make_pair(ESM::PRT_LHand, "Left Hand"));
|
||||||
{ ESM::PRT_Shield, "Shield Bone" },
|
result.insert(std::make_pair(ESM::PRT_RWrist, "Right Wrist"));
|
||||||
{ ESM::PRT_RForearm, "Right Forearm" },
|
result.insert(std::make_pair(ESM::PRT_LWrist, "Left Wrist"));
|
||||||
{ ESM::PRT_LForearm, "Left Forearm" },
|
result.insert(std::make_pair(ESM::PRT_Shield, "Shield Bone"));
|
||||||
{ ESM::PRT_RUpperarm, "Right Upper Arm" },
|
result.insert(std::make_pair(ESM::PRT_RForearm, "Right Forearm"));
|
||||||
{ ESM::PRT_LUpperarm, "Left Upper Arm" },
|
result.insert(std::make_pair(ESM::PRT_LForearm, "Left Forearm"));
|
||||||
{ ESM::PRT_RFoot, "Right Foot" },
|
result.insert(std::make_pair(ESM::PRT_RUpperarm, "Right Upper Arm"));
|
||||||
{ ESM::PRT_LFoot, "Left Foot" },
|
result.insert(std::make_pair(ESM::PRT_LUpperarm, "Left Upper Arm"));
|
||||||
{ ESM::PRT_RAnkle, "Right Ankle" },
|
result.insert(std::make_pair(ESM::PRT_RFoot, "Right Foot"));
|
||||||
{ ESM::PRT_LAnkle, "Left Ankle" },
|
result.insert(std::make_pair(ESM::PRT_LFoot, "Left Foot"));
|
||||||
{ ESM::PRT_RKnee, "Right Knee" },
|
result.insert(std::make_pair(ESM::PRT_RAnkle, "Right Ankle"));
|
||||||
{ ESM::PRT_LKnee, "Left Knee" },
|
result.insert(std::make_pair(ESM::PRT_LAnkle, "Left Ankle"));
|
||||||
{ ESM::PRT_RLeg, "Right Upper Leg" },
|
result.insert(std::make_pair(ESM::PRT_RKnee, "Right Knee"));
|
||||||
{ ESM::PRT_LLeg, "Left Upper Leg" },
|
result.insert(std::make_pair(ESM::PRT_LKnee, "Left Knee"));
|
||||||
{ ESM::PRT_RPauldron, "Right Clavicle" },
|
result.insert(std::make_pair(ESM::PRT_RLeg, "Right Upper Leg"));
|
||||||
{ ESM::PRT_LPauldron, "Left Clavicle" },
|
result.insert(std::make_pair(ESM::PRT_LLeg, "Left Upper Leg"));
|
||||||
{ ESM::PRT_Weapon, "Weapon Bone" },
|
result.insert(std::make_pair(ESM::PRT_RPauldron, "Right Clavicle"));
|
||||||
{ ESM::PRT_Tail, "Tail" }
|
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()
|
NpcAnimation::~NpcAnimation()
|
||||||
{
|
{
|
||||||
Ogre::SceneManager *sceneMgr = mInsert->getCreator();
|
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]);
|
destroyObjectList(sceneMgr, mObjectParts[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,7 +86,7 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
|
||||||
{
|
{
|
||||||
mNpc = mPtr.get<ESM::NPC>()->mBase;
|
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
|
mPartslots[i] = -1; //each slot is empty
|
||||||
mPartPriorities[i] = 0;
|
mPartPriorities[i] = 0;
|
||||||
|
@ -168,8 +172,8 @@ void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode)
|
||||||
}
|
}
|
||||||
MWBase::Environment::get().getMechanicsManager()->forceStateUpdate(mPtr);
|
MWBase::Environment::get().getMechanicsManager()->forceStateUpdate(mPtr);
|
||||||
|
|
||||||
for(size_t i = 0;i < sPartListSize;i++)
|
for(size_t i = 0;i < ESM::PRT_Count;i++)
|
||||||
removeIndividualPart(i);
|
removeIndividualPart((ESM::PartReferenceType)i);
|
||||||
forceUpdate();
|
forceUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,14 +280,7 @@ void NpcAnimation::updateParts(bool forceupdate)
|
||||||
const ESM::Light *light = part.get<ESM::Light>()->mBase;
|
const ESM::Light *light = part.get<ESM::Light>()->mBase;
|
||||||
addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft,
|
addOrReplaceIndividualPart(ESM::PRT_Shield, MWWorld::InventoryStore::Slot_CarriedLeft,
|
||||||
1, "meshes\\"+light->mModel);
|
1, "meshes\\"+light->mModel);
|
||||||
for(size_t i = 0;i < sPartListSize;i++)
|
addExtraLight(mInsert->getCreator(), mObjectParts[ESM::PRT_Shield], light);
|
||||||
{
|
|
||||||
if(ESM::PRT_Shield == sPartList[i].type)
|
|
||||||
{
|
|
||||||
addExtraLight(mInsert->getCreator(), mObjectParts[i], light);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -386,7 +383,8 @@ void NpcAnimation::updateParts(bool forceupdate)
|
||||||
{
|
{
|
||||||
const ESM::BodyPart* bodypart = parts[part];
|
const ESM::BodyPart* bodypart = parts[part];
|
||||||
if(bodypart)
|
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);
|
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());
|
std::vector<Ogre::Controller<Ogre::Real> >::iterator ctrl(mObjectParts[i].mControllers.begin());
|
||||||
for(;ctrl != mObjectParts[i].mControllers.end();ctrl++)
|
for(;ctrl != mObjectParts[i].mControllers.end();ctrl++)
|
||||||
|
@ -457,22 +455,15 @@ Ogre::Vector3 NpcAnimation::runAnimation(float timepassed)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void NpcAnimation::removeIndividualPart(int type)
|
void NpcAnimation::removeIndividualPart(ESM::PartReferenceType type)
|
||||||
{
|
{
|
||||||
mPartPriorities[type] = 0;
|
mPartPriorities[type] = 0;
|
||||||
mPartslots[type] = -1;
|
mPartslots[type] = -1;
|
||||||
|
|
||||||
for(size_t i = 0;i < sPartListSize;i++)
|
destroyObjectList(mInsert->getCreator(), mObjectParts[type]);
|
||||||
{
|
|
||||||
if(type == sPartList[i].type)
|
|
||||||
{
|
|
||||||
destroyObjectList(mInsert->getCreator(), mObjectParts[i]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NpcAnimation::reserveIndividualPart(int type, int group, int priority)
|
void NpcAnimation::reserveIndividualPart(ESM::PartReferenceType type, int group, int priority)
|
||||||
{
|
{
|
||||||
if(priority > mPartPriorities[type])
|
if(priority > mPartPriorities[type])
|
||||||
{
|
{
|
||||||
|
@ -484,14 +475,14 @@ void NpcAnimation::reserveIndividualPart(int type, int group, int priority)
|
||||||
|
|
||||||
void NpcAnimation::removePartGroup(int group)
|
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)
|
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])
|
if(priority <= mPartPriorities[type])
|
||||||
return false;
|
return false;
|
||||||
|
@ -500,43 +491,36 @@ bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority,
|
||||||
mPartslots[type] = group;
|
mPartslots[type] = group;
|
||||||
mPartPriorities[type] = priority;
|
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);
|
Ogre::Bone *offset = skel->getBone("BoneOffset");
|
||||||
if(mObjectParts[i].mSkelBase && mObjectParts[i].mSkelBase->isParentTagPoint())
|
root->translate(offset->getPosition());
|
||||||
{
|
root->rotate(offset->getOrientation());
|
||||||
Ogre::Node *root = mObjectParts[i].mSkelBase->getParentNode();
|
// HACK: Why an extra -90 degree rotation?
|
||||||
Ogre::SkeletonInstance *skel = mObjectParts[i].mSkelBase->getSkeleton();
|
root->pitch(Ogre::Degree(-90.0f));
|
||||||
if(skel->hasBone("BoneOffset"))
|
root->scale(offset->getScale());
|
||||||
{
|
root->setInitialState();
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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)
|
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)
|
if(bodypart)
|
||||||
addOrReplaceIndividualPart(part->mPart, group, priority, "meshes\\"+bodypart->mModel);
|
addOrReplaceIndividualPart((ESM::PartReferenceType)part->mPart, group, priority, "meshes\\"+bodypart->mModel);
|
||||||
else
|
else
|
||||||
reserveIndividualPart(part->mPart, group, priority);
|
reserveIndividualPart((ESM::PartReferenceType)part->mPart, group, priority);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,25 +21,21 @@ namespace MWRender
|
||||||
class NpcAnimation : public Animation
|
class NpcAnimation : public Animation
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct PartInfo {
|
typedef std::map<ESM::PartReferenceType,std::string> PartBoneMap;
|
||||||
ESM::PartReferenceType type;
|
|
||||||
const char name[32];
|
|
||||||
};
|
|
||||||
|
|
||||||
enum ViewMode {
|
enum ViewMode {
|
||||||
VM_Normal,
|
VM_Normal,
|
||||||
VM_FirstPerson,
|
VM_FirstPerson,
|
||||||
VM_HeadOnly
|
VM_HeadOnly
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const size_t sPartListSize = 27;
|
static const PartBoneMap sPartList;
|
||||||
static const PartInfo sPartList[sPartListSize];
|
|
||||||
|
|
||||||
int mStateID;
|
int mStateID;
|
||||||
|
|
||||||
// Bounded Parts
|
// Bounded Parts
|
||||||
NifOgre::ObjectList mObjectParts[sPartListSize];
|
NifOgre::ObjectList mObjectParts[ESM::PRT_Count];
|
||||||
|
|
||||||
const ESM::NPC *mNpc;
|
const ESM::NPC *mNpc;
|
||||||
std::string mHeadModel;
|
std::string mHeadModel;
|
||||||
|
@ -66,17 +62,17 @@ private:
|
||||||
|
|
||||||
int mVisibilityFlags;
|
int mVisibilityFlags;
|
||||||
|
|
||||||
int mPartslots[sPartListSize]; //Each part slot is taken by clothing, armor, or is empty
|
int mPartslots[ESM::PRT_Count]; //Each part slot is taken by clothing, armor, or is empty
|
||||||
int mPartPriorities[sPartListSize];
|
int mPartPriorities[ESM::PRT_Count];
|
||||||
|
|
||||||
NifOgre::ObjectList insertBoundedPart(const std::string &model, int group, const std::string &bonename);
|
NifOgre::ObjectList insertBoundedPart(const std::string &model, int group, const std::string &bonename);
|
||||||
|
|
||||||
void updateParts(bool forceupdate = false);
|
void updateParts(bool forceupdate = false);
|
||||||
|
|
||||||
void removeIndividualPart(int type);
|
void removeIndividualPart(ESM::PartReferenceType type);
|
||||||
void reserveIndividualPart(int type, int group, int priority);
|
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 removePartGroup(int group);
|
||||||
void addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts);
|
void addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue