forked from teamnwah/openmw-tes3coop
		
	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(mViewMode != VM_FirstPerson)
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
        if(mPartPriorities[ESM::PRT_Head] < 1)
 | 
					        if(mPartPriorities[ESM::PRT_Head] < 1)
 | 
				
			||||||
            addOrReplaceIndividualPart(ESM::PRT_Head, -1,1, mHeadModel);
 | 
					            addOrReplaceIndividualPart(ESM::PRT_Head, -1,1, mHeadModel);
 | 
				
			||||||
        if(mPartPriorities[ESM::PRT_Hair] < 1 && mPartPriorities[ESM::PRT_Head] <= 1)
 | 
					        if(mPartPriorities[ESM::PRT_Hair] < 1 && mPartPriorities[ESM::PRT_Head] <= 1)
 | 
				
			||||||
            addOrReplaceIndividualPart(ESM::PRT_Hair, -1,1, mHairModel);
 | 
					            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