mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-05 17:41:32 +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 Animation::runAnimation(float timepassed)
|
||||||
{
|
{
|
||||||
Ogre::Vector3 movement = Ogre::Vector3::ZERO;
|
Ogre::Vector3 movement(0.0f);
|
||||||
|
|
||||||
timepassed *= mAnimSpeedMult;
|
timepassed *= mAnimSpeedMult;
|
||||||
while(mCurrentAnim && mPlaying)
|
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));
|
skelnames.push_back("meshes\\"+Misc::StringUtils::lowerCase(mNpc->mModel));
|
||||||
setAnimationSources(skelnames);
|
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)
|
void NpcAnimation::updateParts(bool forceupdate)
|
||||||
|
@ -254,13 +287,18 @@ void NpcAnimation::updateParts(bool forceupdate)
|
||||||
reserveIndividualPart(slotlist[i].reserveParts[res], slotlist[i].slot, prio);
|
reserveIndividualPart(slotlist[i].reserveParts[res], slotlist[i].slot, prio);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mPartPriorities[ESM::PRT_Head] < 1)
|
if(mViewMode != VM_FirstPerson)
|
||||||
addOrReplaceIndividualPart(ESM::PRT_Head, -1,1, mHeadModel);
|
{
|
||||||
if(mPartPriorities[ESM::PRT_Hair] < 1 && mPartPriorities[ESM::PRT_Head] <= 1)
|
if(mPartPriorities[ESM::PRT_Head] < 1)
|
||||||
addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1, mHairModel);
|
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)
|
if(mViewMode == VM_HeadOnly)
|
||||||
return;
|
return;
|
||||||
|
/* FIXME: Remove this once we figure out how to show what in first-person */
|
||||||
|
if(mViewMode == VM_FirstPerson)
|
||||||
|
return;
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
ESM::PartReferenceType type;
|
ESM::PartReferenceType type;
|
||||||
|
@ -288,6 +326,7 @@ void NpcAnimation::updateParts(bool forceupdate)
|
||||||
{ ESM::PRT_Tail, { "tail", "" } }
|
{ ESM::PRT_Tail, { "tail", "" } }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const char *ext = (mViewMode == VM_FirstPerson) ? ".1st" : "";
|
||||||
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
const MWWorld::ESMStore &store = MWBase::Environment::get().getWorld()->getStore();
|
||||||
for(size_t i = 0;i < sizeof(PartTypeList)/sizeof(PartTypeList[0]);i++)
|
for(size_t i = 0;i < sizeof(PartTypeList)/sizeof(PartTypeList[0]);i++)
|
||||||
{
|
{
|
||||||
|
@ -298,14 +337,14 @@ void NpcAnimation::updateParts(bool forceupdate)
|
||||||
|
|
||||||
if(!mNpc->isMale())
|
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)
|
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)
|
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)
|
if(part == 0)
|
||||||
part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[1]);
|
part = partStore.search(mBodyPrefix + "_m_" + PartTypeList[i].name[1]+ext);
|
||||||
|
|
||||||
if(part)
|
if(part)
|
||||||
addOrReplaceIndividualPart(PartTypeList[i].type, -1,1, "meshes\\"+part->mModel);
|
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)
|
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++)
|
for(std::size_t i = 0; i < parts.size(); i++)
|
||||||
{
|
{
|
||||||
const ESM::PartReference &part = parts[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;
|
const ESM::BodyPart *bodypart = 0;
|
||||||
if(!mNpc->isMale())
|
if(!mNpc->isMale())
|
||||||
bodypart = partStore.search(part.mFemale);
|
bodypart = partStore.search(part.mFemale+ext);
|
||||||
if(!bodypart)
|
if(!bodypart)
|
||||||
bodypart = partStore.search(part.mMale);
|
bodypart = partStore.search(part.mMale+ext);
|
||||||
|
|
||||||
if(bodypart)
|
if(bodypart)
|
||||||
addOrReplaceIndividualPart(part.mPart, group, priority, "meshes\\"+bodypart->mModel);
|
addOrReplaceIndividualPart(part.mPart, group, priority, "meshes\\"+bodypart->mModel);
|
||||||
|
|
|
@ -28,6 +28,7 @@ struct PartInfo {
|
||||||
|
|
||||||
enum ViewMode {
|
enum ViewMode {
|
||||||
VM_Normal,
|
VM_Normal,
|
||||||
|
VM_FirstPerson,
|
||||||
VM_HeadOnly
|
VM_HeadOnly
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -84,6 +85,8 @@ public:
|
||||||
|
|
||||||
virtual Ogre::Vector3 runAnimation(float timepassed);
|
virtual Ogre::Vector3 runAnimation(float timepassed);
|
||||||
|
|
||||||
|
void setViewMode(ViewMode viewMode);
|
||||||
|
|
||||||
void forceUpdate()
|
void forceUpdate()
|
||||||
{ updateParts(true); }
|
{ updateParts(true); }
|
||||||
};
|
};
|
||||||
|
|
|
@ -124,8 +124,6 @@ namespace MWRender
|
||||||
MWBase::Environment::get().getWindowManager ()->showCrosshair
|
MWBase::Environment::get().getWindowManager ()->showCrosshair
|
||||||
(!MWBase::Environment::get().getWindowManager ()->isGuiMode () && (mFirstPersonView && !mVanity.enabled && !mPreviewMode));
|
(!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) {
|
if (mFirstPersonView && !mVanity.enabled) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -139,6 +137,8 @@ namespace MWRender
|
||||||
void Player::toggleViewMode()
|
void Player::toggleViewMode()
|
||||||
{
|
{
|
||||||
mFirstPersonView = !mFirstPersonView;
|
mFirstPersonView = !mFirstPersonView;
|
||||||
|
mAnimation->setViewMode((mVanity.enabled || mPreviewMode || !mFirstPersonView) ?
|
||||||
|
NpcAnimation::VM_Normal : NpcAnimation::VM_FirstPerson);
|
||||||
if (mFirstPersonView) {
|
if (mFirstPersonView) {
|
||||||
mCamera->setPosition(0.f, 0.f, 0.f);
|
mCamera->setPosition(0.f, 0.f, 0.f);
|
||||||
setLowHeight(false);
|
setLowHeight(false);
|
||||||
|
@ -168,6 +168,9 @@ namespace MWRender
|
||||||
mVanity.enabled = enable;
|
mVanity.enabled = enable;
|
||||||
mVanity.forced = force && enable;
|
mVanity.forced = force && enable;
|
||||||
|
|
||||||
|
mAnimation->setViewMode((mVanity.enabled || mPreviewMode || !mFirstPersonView) ?
|
||||||
|
NpcAnimation::VM_Normal : NpcAnimation::VM_FirstPerson);
|
||||||
|
|
||||||
float offset = mPreviewCam.offset;
|
float offset = mPreviewCam.offset;
|
||||||
Ogre::Vector3 rot(0.f, 0.f, 0.f);
|
Ogre::Vector3 rot(0.f, 0.f, 0.f);
|
||||||
if (mVanity.enabled) {
|
if (mVanity.enabled) {
|
||||||
|
@ -194,6 +197,8 @@ namespace MWRender
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mPreviewMode = enable;
|
mPreviewMode = enable;
|
||||||
|
mAnimation->setViewMode((mVanity.enabled || mPreviewMode || !mFirstPersonView) ?
|
||||||
|
NpcAnimation::VM_Normal : NpcAnimation::VM_FirstPerson);
|
||||||
float offset = mCamera->getPosition().z;
|
float offset = mCamera->getPosition().z;
|
||||||
if (mPreviewMode) {
|
if (mPreviewMode) {
|
||||||
mMainCam.offset = offset;
|
mMainCam.offset = offset;
|
||||||
|
@ -305,7 +310,8 @@ namespace MWRender
|
||||||
delete mAnimation;
|
delete mAnimation;
|
||||||
mAnimation = anim;
|
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)
|
void Player::setHeight(float height)
|
||||||
|
|
Loading…
Reference in a new issue