Improved bodypart select fallback (fixes #2594)

pull/205/head^2
Andrei Kortunov 8 years ago
parent c2240e3af1
commit 4544caf7f3

@ -726,6 +726,19 @@ void NpcAnimation::removePartGroup(int group)
}
}
bool NpcAnimation::isFirstPersonPart(const ESM::BodyPart* bodypart)
{
return (bodypart->mId.size() >= 3)
&& bodypart->mId[bodypart->mId.size()-3] == '1'
&& bodypart->mId[bodypart->mId.size()-2] == 's'
&& bodypart->mId[bodypart->mId.size()-1] == 't';
}
bool NpcAnimation::isFemalePart(const ESM::BodyPart* bodypart)
{
return bodypart->mData.mFlags & ESM::BodyPart::BPF_Female;
}
bool NpcAnimation::addOrReplaceIndividualPart(ESM::PartReferenceType type, int group, int priority, const std::string &mesh, bool enchantedGlow, osg::Vec4f* glowColor)
{
if(priority <= mPartPriorities[type])
@ -1096,46 +1109,79 @@ const std::vector<const ESM::BodyPart *>& NpcAnimation::getBodyParts(const std::
if (!Misc::StringUtils::ciEqual(bodypart.mRace, race))
continue;
bool partFirstPerson = (bodypart.mId.size() >= 3)
&& bodypart.mId[bodypart.mId.size()-3] == '1'
&& bodypart.mId[bodypart.mId.size()-2] == 's'
&& bodypart.mId[bodypart.mId.size()-1] == 't';
if(partFirstPerson != (firstPerson))
bool partFirstPerson = isFirstPersonPart(&bodypart);
bool isHand = bodypart.mData.mPart == ESM::BodyPart::MP_Hand ||
bodypart.mData.mPart == ESM::BodyPart::MP_Wrist ||
bodypart.mData.mPart == ESM::BodyPart::MP_Forearm ||
bodypart.mData.mPart == ESM::BodyPart::MP_Upperarm;
bool isSameGender = isFemalePart(&bodypart) == female;
/* A fallback for the arms if 1st person is missing:
1. Try to use 3d person skin for same gender
2. Try to use 1st person skin for male, if female == true
3. Try to use 3d person skin for male, if female == true
A fallback in another cases: allow to use male bodyparts, if female == true
*/
if (firstPerson && isHand && !partFirstPerson)
{
if(firstPerson && (bodypart.mData.mPart == ESM::BodyPart::MP_Hand ||
bodypart.mData.mPart == ESM::BodyPart::MP_Wrist ||
bodypart.mData.mPart == ESM::BodyPart::MP_Forearm ||
bodypart.mData.mPart == ESM::BodyPart::MP_Upperarm))
// Allow 3rd person skins as a fallback for the arms if 1st person is missing
BodyPartMapType::const_iterator bIt = sBodyPartMap.lower_bound(BodyPartMapType::key_type(bodypart.mData.mPart));
while(bIt != sBodyPartMap.end() && bIt->first == bodypart.mData.mPart)
{
/* Allow 3rd person skins as a fallback for the arms if 1st person is missing. */
BodyPartMapType::const_iterator bIt = sBodyPartMap.lower_bound(BodyPartMapType::key_type(bodypart.mData.mPart));
while(bIt != sBodyPartMap.end() && bIt->first == bodypart.mData.mPart)
{
if(!parts[bIt->second])
parts[bIt->second] = &*it;
++bIt;
}
// If we have no fallback bodypart now and bodypart is for same gender (1)
if(!parts[bIt->second] && isSameGender)
parts[bIt->second] = &bodypart;
// If we have fallback bodypart for other gender and found fallback for current gender (1)
else if(isSameGender && isFemalePart(parts[bIt->second]) != female)
parts[bIt->second] = &bodypart;
// If we have no fallback bodypart and searching for female bodyparts (3)
else if(!parts[bIt->second] && female)
parts[bIt->second] = &bodypart;
++bIt;
}
continue;
}
if ((female) != (bodypart.mData.mFlags & ESM::BodyPart::BPF_Female))
// Don't allow to use podyparts for a different view
if (partFirstPerson != firstPerson)
continue;
if (female && !isFemalePart(&bodypart))
{
// Allow opposite gender's parts as fallback if parts for our gender are missing
// Allow male parts as fallback for females if female parts are missing
BodyPartMapType::const_iterator bIt = sBodyPartMap.lower_bound(BodyPartMapType::key_type(bodypart.mData.mPart));
while(bIt != sBodyPartMap.end() && bIt->first == bodypart.mData.mPart)
{
// If we have no fallback bodypart now
if(!parts[bIt->second])
parts[bIt->second] = &*it;
parts[bIt->second] = &bodypart;
// If we have 3d person fallback bodypart for hand and 1st person fallback found (2)
else if(isHand && !isFirstPersonPart(parts[bIt->second]) && partFirstPerson)
parts[bIt->second] = &bodypart;
++bIt;
}
continue;
}
// Don't allow to use podyparts for another gender
if (female != isFemalePart(&bodypart))
continue;
// Use properly found bodypart, replacing fallbacks
BodyPartMapType::const_iterator bIt = sBodyPartMap.lower_bound(BodyPartMapType::key_type(bodypart.mData.mPart));
while(bIt != sBodyPartMap.end() && bIt->first == bodypart.mData.mPart)
{
parts[bIt->second] = &*it;
parts[bIt->second] = &bodypart;
++bIt;
}
}

@ -90,6 +90,9 @@ private:
osg::ref_ptr<NeckController> mFirstPersonNeckController;
static bool isFirstPersonPart(const ESM::BodyPart* bodypart);
static bool isFemalePart(const ESM::BodyPart* bodypart);
protected:
virtual void addControllers();

Loading…
Cancel
Save