mirror of
https://github.com/TES3MP/openmw-tes3mp.git
synced 2025-02-01 22:15:33 +00:00
Add a first-person view mode to NpcAnimation
And use it instead of showing/hiding the player.
This commit is contained in:
parent
029d565727
commit
a700c50e84
4 changed files with 65 additions and 16 deletions
|
@ -476,7 +476,7 @@ void Animation::play(const std::string &groupname, const std::string &start, con
|
|||
|
||||
Ogre::Vector3 Animation::runAnimation(float timepassed)
|
||||
{
|
||||
Ogre::Vector3 movement = Ogre::Vector3::ZERO;
|
||||
Ogre::Vector3 movement(0.0f);
|
||||
|
||||
timepassed *= mAnimSpeedMult;
|
||||
while(mCurrentAnim && mPlaying)
|
||||
|
|
|
@ -130,7 +130,40 @@ NpcAnimation::NpcAnimation(const MWWorld::Ptr& ptr, Ogre::SceneNode* node, MWWor
|
|||
skelnames.push_back("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel));
|
||||
setAnimationSources(skelnames);
|
||||
|
||||
updateParts(true);
|
||||
forceUpdate();
|
||||
}
|
||||
|
||||
void NpcAnimation::setViewMode(NpcAnimation::ViewMode viewMode)
|
||||
{
|
||||
assert(viewMode != VM_HeadOnly);
|
||||
mViewMode = viewMode;
|
||||
|
||||
/* FIXME: Enable this once first-person animations work. */
|
||||
#if 0
|
||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||
const ESM::Race *race = store.get<ESM::Race>().find(mNpc->mRace);
|
||||
|
||||
bool isBeast = (race->mData.mFlags & ESM::Race::Beast) != 0;
|
||||
std::string smodel = (!isBeast ? "meshes\\base_anim.nif" : "meshes\\base_animkna.nif");
|
||||
|
||||
std::vector<std::string> skelnames(1, smodel);
|
||||
if(!mNpc->isMale() && !isBeast)
|
||||
skelnames.push_back("meshes\\base_anim_female.nif");
|
||||
else if(mBodyPrefix.find("argonian") != std::string::npos)
|
||||
skelnames.push_back("meshes\\argonian_swimkna.nif");
|
||||
if(mNpc->mModel.length() > 0)
|
||||
skelnames.push_back("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel));
|
||||
if(mViewMode == VM_FirstPerson)
|
||||
{
|
||||
smodel = (!isBeast ? "meshes\\base_anim.1st.nif" : "meshes\\base_animkna.1st.nif");
|
||||
skelnames.push_back(smodel);
|
||||
}
|
||||
setAnimationSources(skelnames);
|
||||
#endif
|
||||
|
||||
for(size_t i = 0;i < sPartListSize;i++)
|
||||
removeIndividualPart(i);
|
||||
forceUpdate();
|
||||
}
|
||||
|
||||
void NpcAnimation::updateParts(bool forceupdate)
|
||||
|
@ -254,13 +287,18 @@ void NpcAnimation::updateParts(bool forceupdate)
|
|||
reserveIndividualPart(slotlist[i].reserveParts[res], slotlist[i].slot, prio);
|
||||
}
|
||||
|
||||
if(mPartPriorities[ESM::PRT_Head] < 1)
|
||||
addOrReplaceIndividualPart(ESM::PRT_Head, -1,1, mHeadModel);
|
||||
if(mPartPriorities[ESM::PRT_Hair] < 1 && mPartPriorities[ESM::PRT_Head] <= 1)
|
||||
addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1, mHairModel);
|
||||
|
||||
if(mViewMode != VM_FirstPerson)
|
||||
{
|
||||
if(mPartPriorities[ESM::PRT_Head] < 1)
|
||||
addOrReplaceIndividualPart(ESM::PRT_Head, -1,1, mHeadModel);
|
||||
if(mPartPriorities[ESM::PRT_Hair] < 1 && mPartPriorities[ESM::PRT_Head] <= 1)
|
||||
addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1, mHairModel);
|
||||
}
|
||||
if(mViewMode == VM_HeadOnly)
|
||||
return;
|
||||
/* FIXME: Remove this once we figure out how to show what in first-person */
|
||||
if(mViewMode == VM_FirstPerson)
|
||||
return;
|
||||
|
||||
static const struct {
|
||||
ESM::PartReferenceType type;
|
||||
|
@ -288,6 +326,7 @@ void NpcAnimation::updateParts(bool forceupdate)
|
|||
{ ESM::PRT_Tail, { "tail", "" } }
|
||||
};
|
||||
|
||||
const char *ext = (mViewMode == VM_FirstPerson) ? ".1st" : "";
|
||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||
for(size_t i = 0;i < sizeof(PartTypeList)/sizeof(PartTypeList[0]);i++)
|
||||
{
|
||||
|
@ -298,14 +337,14 @@ void NpcAnimation::updateParts(bool forceupdate)
|
|||
|
||||
if(!mNpc->isMale())
|
||||
{
|
||||
part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[0]);
|
||||
part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[0]+ext);
|
||||
if(part == 0)
|
||||
part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[1]);
|
||||
part = partStore.search(mBodyPrefix + "_f_" + PartTypeList[i].name[1]+ext);
|
||||
}
|
||||
if(part == 0)
|
||||
part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[0]);
|
||||
part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[0]+ext);
|
||||
if(part == 0)
|
||||
part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[1]);
|
||||
part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[1]+ext);
|
||||
|
||||
if(part)
|
||||
addOrReplaceIndividualPart(PartTypeList[i].type, -1,1, "meshes\\"+part->mModel);
|
||||
|
@ -431,6 +470,7 @@ bool NpcAnimation::addOrReplaceIndividualPart(int type, int group, int priority,
|
|||
|
||||
void NpcAnimation::addPartGroup(int group, int priority, const std::vector<ESM::PartReference> &parts)
|
||||
{
|
||||
const char *ext = (mViewMode == VM_FirstPerson) ? ".1st" : "";
|
||||
for(std::size_t i = 0; i < parts.size(); i++)
|
||||
{
|
||||
const ESM::PartReference &part = parts[i];
|
||||
|
@ -440,9 +480,9 @@ void NpcAnimation::addPartGroup(int group, int priority, const std::vector<ESM::
|
|||
|
||||
const ESM::BodyPart *bodypart = 0;
|
||||
if(!mNpc->isMale())
|
||||
bodypart = partStore.search(part.mFemale);
|
||||
bodypart = partStore.search(part.mFemale+ext);
|
||||
if(!bodypart)
|
||||
bodypart = partStore.search(part.mMale);
|
||||
bodypart = partStore.search(part.mMale+ext);
|
||||
|
||||
if(bodypart)
|
||||
addOrReplaceIndividualPart(part.mPart, group, priority, "meshes\\"+bodypart->mModel);
|
||||
|
|
|
@ -28,6 +28,7 @@ struct PartInfo {
|
|||
|
||||
enum ViewMode {
|
||||
VM_Normal,
|
||||
VM_FirstPerson,
|
||||
VM_HeadOnly
|
||||
};
|
||||
|
||||
|
@ -84,6 +85,8 @@ public:
|
|||
|
||||
virtual Ogre::Vector3 runAnimation(float timepassed);
|
||||
|
||||
void setViewMode(ViewMode viewMode);
|
||||
|
||||
void forceUpdate()
|
||||
{ updateParts(true); }
|
||||
};
|
||||
|
|
|
@ -124,8 +124,6 @@ namespace MWRender
|
|||
MWBase::Environment::get().getWindowManager ()->showCrosshair
|
||||
(!MWBase::Environment::get().getWindowManager ()->isGuiMode () && (mFirstPersonView && !mVanity.enabled && !mPreviewMode));
|
||||
|
||||
/// \fixme We shouldn't hide the whole model, just certain components of the character (head, chest, feet, etc)
|
||||
mPlayerNode->setVisible(mVanity.enabled || mPreviewMode || !mFirstPersonView);
|
||||
if (mFirstPersonView && !mVanity.enabled) {
|
||||
return;
|
||||
}
|
||||
|
@ -139,6 +137,8 @@ namespace MWRender
|
|||
void Player::toggleViewMode()
|
||||
{
|
||||
mFirstPersonView = !mFirstPersonView;
|
||||
mAnimation->setViewMode((mVanity.enabled || mPreviewMode || !mFirstPersonView) ?
|
||||
NpcAnimation::VM_Normal : NpcAnimation::VM_FirstPerson);
|
||||
if (mFirstPersonView) {
|
||||
mCamera->setPosition(0.f, 0.f, 0.f);
|
||||
setLowHeight(false);
|
||||
|
@ -168,6 +168,9 @@ namespace MWRender
|
|||
mVanity.enabled = enable;
|
||||
mVanity.forced = force && enable;
|
||||
|
||||
mAnimation->setViewMode((mVanity.enabled || mPreviewMode || !mFirstPersonView) ?
|
||||
NpcAnimation::VM_Normal : NpcAnimation::VM_FirstPerson);
|
||||
|
||||
float offset = mPreviewCam.offset;
|
||||
Ogre::Vector3 rot(0.f, 0.f, 0.f);
|
||||
if (mVanity.enabled) {
|
||||
|
@ -194,6 +197,8 @@ namespace MWRender
|
|||
return;
|
||||
}
|
||||
mPreviewMode = enable;
|
||||
mAnimation->setViewMode((mVanity.enabled || mPreviewMode || !mFirstPersonView) ?
|
||||
NpcAnimation::VM_Normal : NpcAnimation::VM_FirstPerson);
|
||||
float offset = mCamera->getPosition().z;
|
||||
if (mPreviewMode) {
|
||||
mMainCam.offset = offset;
|
||||
|
@ -305,7 +310,8 @@ namespace MWRender
|
|||
delete mAnimation;
|
||||
mAnimation = anim;
|
||||
|
||||
mPlayerNode->setVisible(mVanity.enabled || mPreviewMode || !mFirstPersonView);
|
||||
mAnimation->setViewMode((mVanity.enabled || mPreviewMode || !mFirstPersonView) ?
|
||||
NpcAnimation::VM_Normal : NpcAnimation::VM_FirstPerson);
|
||||
}
|
||||
|
||||
void Player::setHeight(float height)
|
||||
|
|
Loading…
Reference in a new issue