diff --git a/LEGO1/lego/legoomni/include/legonavcontroller.h b/LEGO1/lego/legoomni/include/legonavcontroller.h index 5401f971..37e4fbd7 100644 --- a/LEGO1/lego/legoomni/include/legonavcontroller.h +++ b/LEGO1/lego/legoomni/include/legonavcontroller.h @@ -124,6 +124,7 @@ class LegoNavController : public MxCore { protected: friend class Extensions::ThirdPersonCamera::OrbitCamera; + friend class Extensions::ThirdPersonCamera::Controller; float CalculateNewVel(float p_targetVel, float p_currentVel, float p_accel, float p_time); float CalculateNewTargetVel(int p_pos, int p_center, float p_max); diff --git a/extensions/include/extensions/fwd.h b/extensions/include/extensions/fwd.h index e78bead5..aed06b0a 100644 --- a/extensions/include/extensions/fwd.h +++ b/extensions/include/extensions/fwd.h @@ -11,6 +11,7 @@ class CharacterCloner; } namespace ThirdPersonCamera { +class Controller; class OrbitCamera; } } // namespace Extensions diff --git a/extensions/include/extensions/thirdpersoncamera/controller.h b/extensions/include/extensions/thirdpersoncamera/controller.h index a1901160..602f2655 100644 --- a/extensions/include/extensions/thirdpersoncamera/controller.h +++ b/extensions/include/extensions/thirdpersoncamera/controller.h @@ -74,6 +74,19 @@ class Controller { bool ConsumeAutoDisable() { return m_input.ConsumeAutoDisable(); } bool ConsumeAutoEnable() { return m_input.ConsumeAutoEnable(); } + bool IsLeftButtonHeld() const { return m_input.IsLeftButtonHeld(); } + bool IsLmbForwardEngaged() const { return m_lmbForwardEngaged; } + void SetLmbForwardEngaged(bool p_engaged) { m_lmbForwardEngaged = p_engaged; } + + MxBool HandleFirstPersonForward( + LegoNavController* p_nav, + const Vector3& p_curPos, + const Vector3& p_curDir, + Vector3& p_newPos, + Vector3& p_newDir, + float p_deltaTime + ); + float GetOrbitDistance() const { return m_orbit.GetOrbitDistance(); } void SetOrbitDistance(float p_distance) { m_orbit.SetOrbitDistance(p_distance); } void ResetTouchState() { m_input.ResetTouchState(); } @@ -106,6 +119,7 @@ class Controller { bool m_enabled; bool m_active; bool m_pendingWorldTransition; + bool m_lmbForwardEngaged; LegoROI* m_playerROI; }; diff --git a/extensions/include/extensions/thirdpersoncamera/inputhandler.h b/extensions/include/extensions/thirdpersoncamera/inputhandler.h index 8ecd1746..7b4e07d7 100644 --- a/extensions/include/extensions/thirdpersoncamera/inputhandler.h +++ b/extensions/include/extensions/thirdpersoncamera/inputhandler.h @@ -21,6 +21,8 @@ class InputHandler { int GetTouchCount() const { return m_touch.count; } SDL_FingerID GetFingerID(int p_idx) const { return m_touch.id[p_idx]; } + bool IsLeftButtonHeld() const { return m_leftButtonHeld; } + bool ConsumeAutoDisable(); bool ConsumeAutoEnable(); @@ -43,6 +45,7 @@ class InputHandler { bool m_wantsAutoDisable; bool m_wantsAutoEnable; bool m_rightButtonHeld; + bool m_leftButtonHeld; float m_savedMouseX; float m_savedMouseY; }; diff --git a/extensions/include/extensions/thirdpersoncamera/orbitcamera.h b/extensions/include/extensions/thirdpersoncamera/orbitcamera.h index e60b1351..36599deb 100644 --- a/extensions/include/extensions/thirdpersoncamera/orbitcamera.h +++ b/extensions/include/extensions/thirdpersoncamera/orbitcamera.h @@ -36,7 +36,8 @@ class OrbitCamera { Vector3& p_newPos, Vector3& p_newDir, float p_deltaTime, - bool p_isInMultiPartEmote + bool p_isInMultiPartEmote, + bool p_lmbHeld ); void AdjustYaw(float p_delta) { m_absoluteYaw += p_delta; } diff --git a/extensions/src/thirdpersoncamera.cpp b/extensions/src/thirdpersoncamera.cpp index cfb926c6..70aac3f1 100644 --- a/extensions/src/thirdpersoncamera.cpp +++ b/extensions/src/thirdpersoncamera.cpp @@ -119,8 +119,15 @@ void ThirdPersonCameraExt::OnSDLEvent(SDL_Event* p_event) s_camera->HandleSDLEventImpl(p_event); + if (p_event->type == SDL_EVENT_MOUSE_BUTTON_UP && p_event->button.button == SDL_BUTTON_LEFT) { + s_camera->SetLmbForwardEngaged(false); + } + if (s_camera->ConsumeAutoDisable()) { s_camera->Disable(/*p_preserveTouch=*/true); + if (s_camera->IsLeftButtonHeld()) { + s_camera->SetLmbForwardEngaged(true); + } } else if (s_camera->ConsumeAutoEnable()) { // Clear the movement system's touch state for camera-owned fingers only, @@ -145,6 +152,9 @@ void ThirdPersonCameraExt::OnSDLEvent(SDL_Event* p_event) s_camera->SetOrbitDistance(ThirdPersonCamera::Controller::MIN_DISTANCE); s_camera->Enable(); + if (s_camera->IsLeftButtonHeld()) { + s_camera->SetLmbForwardEngaged(true); + } } } @@ -202,6 +212,9 @@ MxBool ThirdPersonCameraExt::HandleNavOverride( } if (!s_camera->IsActive()) { + if (s_camera->IsLmbForwardEngaged()) { + return s_camera->HandleFirstPersonForward(p_nav, p_curPos, p_curDir, p_newPos, p_newDir, p_deltaTime); + } return FALSE; } diff --git a/extensions/src/thirdpersoncamera/controller.cpp b/extensions/src/thirdpersoncamera/controller.cpp index 878e5def..a7a912ad 100644 --- a/extensions/src/thirdpersoncamera/controller.cpp +++ b/extensions/src/thirdpersoncamera/controller.cpp @@ -30,7 +30,7 @@ using namespace Extensions::ThirdPersonCamera; Controller::Controller() : m_animator(CharacterAnimatorConfig{/*.saveEmoteTransform=*/true, /*.propSuffix=*/0}), m_enabled(false), - m_active(false), m_pendingWorldTransition(false), m_playerROI(nullptr) + m_active(false), m_pendingWorldTransition(false), m_lmbForwardEngaged(false), m_playerROI(nullptr) { } @@ -59,6 +59,7 @@ void Controller::Deactivate() m_active = false; m_pendingWorldTransition = false; + m_lmbForwardEngaged = false; m_animator.StopROISounds(); m_animator.StopClickAnimation(); m_display.DestroyDisplayClone(); @@ -365,7 +366,8 @@ MxBool Controller::HandleCameraRelativeMovement( p_newPos, p_newDir, p_deltaTime, - m_animator.IsInMultiPartEmote() + m_animator.IsInMultiPartEmote(), + m_input.IsLeftButtonHeld() ); } @@ -374,6 +376,31 @@ void Controller::HandleSDLEventImpl(SDL_Event* p_event) m_input.HandleSDLEvent(p_event, m_orbit, m_active); } +MxBool Controller::HandleFirstPersonForward( + LegoNavController* p_nav, + const Vector3& p_curPos, + const Vector3& p_curDir, + Vector3& p_newPos, + Vector3& p_newDir, + float p_deltaTime +) +{ + float accel = p_nav->m_maxLinearAccel; + p_nav->m_linearVel += accel * p_deltaTime; + if (p_nav->m_linearVel > p_nav->m_maxLinearVel) { + p_nav->m_linearVel = p_nav->m_maxLinearVel; + } + + float speed = p_nav->m_linearVel * p_deltaTime; + p_newPos[0] = p_curPos[0] + p_curDir[0] * speed; + p_newPos[1] = p_curPos[1] + p_curDir[1] * speed; + p_newPos[2] = p_curPos[2] + p_curDir[2] * speed; + p_newDir = p_curDir; + + p_nav->m_rotationalVel = 0.0f; + return TRUE; +} + void Controller::ReinitForCharacter() { if (!GameState() || IsRestrictedArea(GameState()->m_currentArea)) { diff --git a/extensions/src/thirdpersoncamera/inputhandler.cpp b/extensions/src/thirdpersoncamera/inputhandler.cpp index e2288715..376c04bc 100644 --- a/extensions/src/thirdpersoncamera/inputhandler.cpp +++ b/extensions/src/thirdpersoncamera/inputhandler.cpp @@ -8,8 +8,8 @@ using namespace Extensions::ThirdPersonCamera; InputHandler::InputHandler() - : m_touch{}, m_wantsAutoDisable(false), m_wantsAutoEnable(false), m_rightButtonHeld(false), m_savedMouseX(0.0f), - m_savedMouseY(0.0f) + : m_touch{}, m_wantsAutoDisable(false), m_wantsAutoEnable(false), m_rightButtonHeld(false), + m_leftButtonHeld(false), m_savedMouseX(0.0f), m_savedMouseY(0.0f) { } @@ -116,21 +116,23 @@ void InputHandler::HandleSDLEvent(SDL_Event* p_event, OrbitCamera& p_orbit, bool case SDL_EVENT_MOUSE_BUTTON_UP: { if (p_event->button.button == SDL_BUTTON_RIGHT) { m_rightButtonHeld = p_event->button.down; - if (!p_active) { - break; - } SDL_Window* window = SDL_GetWindowFromID(p_event->button.windowID); if (window) { if (m_rightButtonHeld) { - SDL_GetMouseState(&m_savedMouseX, &m_savedMouseY); - SDL_SetWindowRelativeMouseMode(window, true); + if (p_active) { + SDL_GetMouseState(&m_savedMouseX, &m_savedMouseY); + SDL_SetWindowRelativeMouseMode(window, true); + } } - else { + else if (SDL_GetWindowRelativeMouseMode(window)) { SDL_SetWindowRelativeMouseMode(window, false); SDL_WarpMouseInWindow(window, m_savedMouseX, m_savedMouseY); } } } + else if (p_event->button.button == SDL_BUTTON_LEFT) { + m_leftButtonHeld = p_event->button.down; + } break; } diff --git a/extensions/src/thirdpersoncamera/orbitcamera.cpp b/extensions/src/thirdpersoncamera/orbitcamera.cpp index 80cdc75e..2bfc649c 100644 --- a/extensions/src/thirdpersoncamera/orbitcamera.cpp +++ b/extensions/src/thirdpersoncamera/orbitcamera.cpp @@ -147,7 +147,8 @@ MxBool OrbitCamera::HandleCameraRelativeMovement( Vector3& p_newPos, Vector3& p_newDir, float p_deltaTime, - bool p_isInMultiPartEmote + bool p_isInMultiPartEmote, + bool p_lmbHeld ) { LegoInputManager* inputManager = InputManager(); @@ -180,8 +181,12 @@ MxBool OrbitCamera::HandleCameraRelativeMovement( moveDirX += camRightX; moveDirZ += camRightZ; } + if (p_lmbHeld) { + moveDirX += camForwardX; + moveDirZ += camForwardZ; + } - if (keyFlags == 0 && inputManager) { + if (keyFlags == 0 && !p_lmbHeld && inputManager) { MxU32 joystickX, joystickY, povPosition; if (inputManager->GetJoystickState(&joystickX, &joystickY, &povPosition) == SUCCESS) { float jx = (joystickX - 50.0f) / 50.0f;