#include "Library/Play/Camera/CameraVerticalAbsorber.h" #include #include "Library/Camera/CameraPoser.h" #include "Library/Camera/CameraPoserFunction.h" #include "Library/Camera/CameraStartInfo.h" #include "Library/Math/MathUtil.h" #include "Library/Nerve/NerveSetupUtil.h" #include "Library/Nerve/NerveUtil.h" #include "Library/Screen/ScreenFunction.h" #include "Library/Yaml/ByamlUtil.h" namespace { using namespace al; NERVE_IMPL(CameraVerticalAbsorber, FollowGround); NERVE_IMPL(CameraVerticalAbsorber, FollowAbsolute); NERVE_IMPL_(CameraVerticalAbsorber, FollowClimbPoleNoInterp, FollowClimbPole); NERVE_IMPL_(CameraVerticalAbsorber, FollowSlow, Follow); NERVE_IMPL(CameraVerticalAbsorber, Absorb); NERVE_IMPL(CameraVerticalAbsorber, Follow); NERVE_IMPL(CameraVerticalAbsorber, FollowClimbPole); NERVES_MAKE_STRUCT(CameraVerticalAbsorber, FollowGround, FollowAbsolute, FollowClimbPoleNoInterp, FollowSlow, Absorb, Follow, FollowClimbPole); } // namespace namespace al { CameraVerticalAbsorber::CameraVerticalAbsorber(const CameraPoser* cameraParent, bool isCameraPosAbsorb) : NerveExecutor("カメラの縦パン"), mCameraPoser(cameraParent), mIsNoCameraPosAbsorb(isCameraPosAbsorb) { initNerve(&NrvCameraVerticalAbsorber.FollowGround); } void CameraVerticalAbsorber::load(const ByamlIter& iter) { ByamlIter verticalAbsorbIter; if (!iter.tryGetIterByKey(&verticalAbsorbIter, "VerticalAbsorb")) return; tryGetByamlF32(&mAbsorbScreenPosUp, verticalAbsorbIter, "AbsorbScreenPosUp"); tryGetByamlF32(&mAbsorbScreenPosDown, verticalAbsorbIter, "AbsorbScreenPosDown"); tryGetByamlF32(&mHighJumpJudgeSpeedV, verticalAbsorbIter, "HighJumpJudgeSpeedV"); ByamlIter advanceAbsorbUpIter; if (verticalAbsorbIter.tryGetIterByKey(&advanceAbsorbUpIter, "AdvanceAbsorbUp")) { mIsAdvanceAbsorbUp = true; mAdvanceAbsorbScreenPosUp = getByamlKeyFloat(advanceAbsorbUpIter, "AdvanceAbsorbScreenPosUp"); } } void CameraVerticalAbsorber::start(const sead::Vector3f& pos, const CameraStartInfo& info) { alCameraPoserFunction::calcTargetFront(&mPrevTargetFront, mCameraPoser); mAbsorbVec = {0.0f, 0.0f, 0.0f}; mPrevTargetTrans.set(pos); if (!isValid() || alCameraPoserFunction::isPlayerTypeNotTouchGround(mCameraPoser)) return setNerve(this, &NrvCameraVerticalAbsorber.FollowAbsolute); if (alCameraPoserFunction::isTargetClimbPole(mCameraPoser)) return setNerve(this, &NrvCameraVerticalAbsorber.FollowClimbPoleNoInterp); if (alCameraPoserFunction::isTargetGrabCeil(mCameraPoser)) return setNerve(this, &NrvCameraVerticalAbsorber.FollowSlow); if (!info._25 || alCameraPoserFunction::isTargetCollideGround(mCameraPoser)) return setNerve(this, &NrvCameraVerticalAbsorber.FollowGround); mPrevTargetTrans.set(alCameraPoserFunction::getPreLookAtPos(mCameraPoser)); const CameraPoser* poser = mCameraPoser; sead::Vector3f gravity = {0.0f, 0.0f, 0.0f}; alCameraPoserFunction::calcTargetGravity(&gravity, poser); mAbsorbVec = pos - mPrevTargetTrans; parallelizeVec(&mAbsorbVec, gravity, mAbsorbVec); setNerve(this, &NrvCameraVerticalAbsorber.Absorb); } bool CameraVerticalAbsorber::isValid() const { return !_1aa && !mIsInvalidated; } inline void updateAbsorbVec(sead::Vector3f* absorbVec, const CameraPoser* poser, const sead::Vector3f& prevTrans) { sead::Vector3f gravity = {0.0f, 0.0f, 0.0f}; alCameraPoserFunction::calcTargetGravity(&gravity, poser); *absorbVec = poser->getTargetTrans() - prevTrans; parallelizeVec(absorbVec, gravity, *absorbVec); } void CameraVerticalAbsorber::update() { if (mIsStopUpdate) return; updateAbsorbVec(&mAbsorbVec, mCameraPoser, mPrevTargetTrans); mLookAtCamera.setPos(mCameraPoser->getPosition()); mLookAtCamera.setAt(mCameraPoser->getTargetTrans()); mLookAtCamera.setUp(mCameraPoser->getCameraUp()); mLookAtCamera.normalizeUp(); makeLookAtCamera(&mLookAtCamera); mLookAtCamera.updateViewMatrix(); mProjection.set(alCameraPoserFunction::getNear(mCameraPoser), alCameraPoserFunction::getFar(mCameraPoser), sead::Mathf::deg2rad(mCameraPoser->getFovyDegree()), alCameraPoserFunction::getAspect(mCameraPoser)); alCameraPoserFunction::calcTargetFront(&mTargetFront, mCameraPoser); if (!isNerve(this, &NrvCameraVerticalAbsorber.FollowGround) && alCameraPoserFunction::isTargetCollideGround(mCameraPoser)) setNerve(this, &NrvCameraVerticalAbsorber.FollowGround); if (!isNerve(this, &NrvCameraVerticalAbsorber.FollowAbsolute) && alCameraPoserFunction::isPlayerTypeNotTouchGround(mCameraPoser)) setNerve(this, &NrvCameraVerticalAbsorber.FollowAbsolute); updateNerve(); sead::Vector3f offset = {0.0f, 0.0f, 0.0f}; if (mIsKeepInFrame) { sead::Vector3f offsetTrans = {0.0f, 0.0f, 0.0f}; alCameraPoserFunction::calcTargetTransWithOffset(&offsetTrans, mCameraPoser); alCameraPoserFunction::calcOffsetCameraKeepInFrameV( &offset, &mLookAtCamera, offsetTrans, mCameraPoser, mKeepInFrameOffsetUp, alCameraPoserFunction::isPlayerTypeHighJump(mCameraPoser) ? 300.0f : mKeepInFrameOffsetDown); mAbsorbVec -= offset; } mPrevTargetTrans.set(mCameraPoser->getTargetTrans() - mAbsorbVec); mPrevTargetFront.set(mTargetFront); } void CameraVerticalAbsorber::makeLookAtCamera(sead::LookAtCamera* lookAtCamera) const { if (!isValid()) return; lookAtCamera->setAt(lookAtCamera->getAt() - mAbsorbVec); if (!mIsNoCameraPosAbsorb) lookAtCamera->setPos(lookAtCamera->getPos() - mAbsorbVec); } void CameraVerticalAbsorber::liberateAbsorb() { if (isNerve(this, &NrvCameraVerticalAbsorber.Absorb)) setNerve(this, &NrvCameraVerticalAbsorber.Follow); } bool CameraVerticalAbsorber::isAbsorbing() const { return isValid() && isNerve(this, &NrvCameraVerticalAbsorber.Absorb); } void CameraVerticalAbsorber::invalidate() { mIsInvalidated = true; if (!isNerve(this, &NrvCameraVerticalAbsorber.FollowAbsolute)) setNerve(this, &NrvCameraVerticalAbsorber.FollowAbsolute); } void CameraVerticalAbsorber::tryResetAbsorbVecIfInCollision(const sead::Vector3f& pos) { if (!alCameraPoserFunction::checkFirstCameraCollisionArrow(nullptr, nullptr, mCameraPoser, pos + mAbsorbVec, -mAbsorbVec)) return; mAbsorbVec = {0.0f, 0.0f, 0.0f}; if (alCameraPoserFunction::isTargetCollideGround(mCameraPoser)) setNerve(this, &NrvCameraVerticalAbsorber.FollowGround); else setNerve(this, &NrvCameraVerticalAbsorber.Follow); } void CameraVerticalAbsorber::exeFollowAbsolute() { mAbsorbVec *= 0.8f; } } // namespace al