mirror of
https://github.com/isledecomp/isle-portable.git
synced 2026-05-02 02:23:56 +00:00
Add LMB forward movement to third person camera
When LMB is held in 3rd person mode, the character walks forward in the camera's facing direction. Works simultaneously with RMB camera rotation. Transitions between 1st and 3rd person are seamless while holding LMB. Also fixes RMB mouse cursor not reappearing when releasing after a 3rd-to-1st person transition. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
982957ee5e
commit
138cbcf6a3
@ -124,6 +124,7 @@ class LegoNavController : public MxCore {
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend class Extensions::ThirdPersonCamera::OrbitCamera;
|
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 CalculateNewVel(float p_targetVel, float p_currentVel, float p_accel, float p_time);
|
||||||
float CalculateNewTargetVel(int p_pos, int p_center, float p_max);
|
float CalculateNewTargetVel(int p_pos, int p_center, float p_max);
|
||||||
|
|||||||
@ -11,6 +11,7 @@ class CharacterCloner;
|
|||||||
}
|
}
|
||||||
namespace ThirdPersonCamera
|
namespace ThirdPersonCamera
|
||||||
{
|
{
|
||||||
|
class Controller;
|
||||||
class OrbitCamera;
|
class OrbitCamera;
|
||||||
}
|
}
|
||||||
} // namespace Extensions
|
} // namespace Extensions
|
||||||
|
|||||||
@ -74,6 +74,19 @@ class Controller {
|
|||||||
bool ConsumeAutoDisable() { return m_input.ConsumeAutoDisable(); }
|
bool ConsumeAutoDisable() { return m_input.ConsumeAutoDisable(); }
|
||||||
bool ConsumeAutoEnable() { return m_input.ConsumeAutoEnable(); }
|
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(); }
|
float GetOrbitDistance() const { return m_orbit.GetOrbitDistance(); }
|
||||||
void SetOrbitDistance(float p_distance) { m_orbit.SetOrbitDistance(p_distance); }
|
void SetOrbitDistance(float p_distance) { m_orbit.SetOrbitDistance(p_distance); }
|
||||||
void ResetTouchState() { m_input.ResetTouchState(); }
|
void ResetTouchState() { m_input.ResetTouchState(); }
|
||||||
@ -106,6 +119,7 @@ class Controller {
|
|||||||
bool m_enabled;
|
bool m_enabled;
|
||||||
bool m_active;
|
bool m_active;
|
||||||
bool m_pendingWorldTransition;
|
bool m_pendingWorldTransition;
|
||||||
|
bool m_lmbForwardEngaged;
|
||||||
LegoROI* m_playerROI;
|
LegoROI* m_playerROI;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -21,6 +21,8 @@ class InputHandler {
|
|||||||
int GetTouchCount() const { return m_touch.count; }
|
int GetTouchCount() const { return m_touch.count; }
|
||||||
SDL_FingerID GetFingerID(int p_idx) const { return m_touch.id[p_idx]; }
|
SDL_FingerID GetFingerID(int p_idx) const { return m_touch.id[p_idx]; }
|
||||||
|
|
||||||
|
bool IsLeftButtonHeld() const { return m_leftButtonHeld; }
|
||||||
|
|
||||||
bool ConsumeAutoDisable();
|
bool ConsumeAutoDisable();
|
||||||
bool ConsumeAutoEnable();
|
bool ConsumeAutoEnable();
|
||||||
|
|
||||||
@ -43,6 +45,7 @@ class InputHandler {
|
|||||||
bool m_wantsAutoDisable;
|
bool m_wantsAutoDisable;
|
||||||
bool m_wantsAutoEnable;
|
bool m_wantsAutoEnable;
|
||||||
bool m_rightButtonHeld;
|
bool m_rightButtonHeld;
|
||||||
|
bool m_leftButtonHeld;
|
||||||
float m_savedMouseX;
|
float m_savedMouseX;
|
||||||
float m_savedMouseY;
|
float m_savedMouseY;
|
||||||
};
|
};
|
||||||
|
|||||||
@ -36,7 +36,8 @@ class OrbitCamera {
|
|||||||
Vector3& p_newPos,
|
Vector3& p_newPos,
|
||||||
Vector3& p_newDir,
|
Vector3& p_newDir,
|
||||||
float p_deltaTime,
|
float p_deltaTime,
|
||||||
bool p_isInMultiPartEmote
|
bool p_isInMultiPartEmote,
|
||||||
|
bool p_lmbHeld
|
||||||
);
|
);
|
||||||
|
|
||||||
void AdjustYaw(float p_delta) { m_absoluteYaw += p_delta; }
|
void AdjustYaw(float p_delta) { m_absoluteYaw += p_delta; }
|
||||||
|
|||||||
@ -119,8 +119,15 @@ void ThirdPersonCameraExt::OnSDLEvent(SDL_Event* p_event)
|
|||||||
|
|
||||||
s_camera->HandleSDLEventImpl(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()) {
|
if (s_camera->ConsumeAutoDisable()) {
|
||||||
s_camera->Disable(/*p_preserveTouch=*/true);
|
s_camera->Disable(/*p_preserveTouch=*/true);
|
||||||
|
if (s_camera->IsLeftButtonHeld()) {
|
||||||
|
s_camera->SetLmbForwardEngaged(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else if (s_camera->ConsumeAutoEnable()) {
|
else if (s_camera->ConsumeAutoEnable()) {
|
||||||
// Clear the movement system's touch state for camera-owned fingers only,
|
// 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->SetOrbitDistance(ThirdPersonCamera::Controller::MIN_DISTANCE);
|
||||||
s_camera->Enable();
|
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->IsActive()) {
|
||||||
|
if (s_camera->IsLmbForwardEngaged()) {
|
||||||
|
return s_camera->HandleFirstPersonForward(p_nav, p_curPos, p_curDir, p_newPos, p_newDir, p_deltaTime);
|
||||||
|
}
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,7 +30,7 @@ using namespace Extensions::ThirdPersonCamera;
|
|||||||
|
|
||||||
Controller::Controller()
|
Controller::Controller()
|
||||||
: m_animator(CharacterAnimatorConfig{/*.saveEmoteTransform=*/true, /*.propSuffix=*/0}), m_enabled(false),
|
: 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_active = false;
|
||||||
m_pendingWorldTransition = false;
|
m_pendingWorldTransition = false;
|
||||||
|
m_lmbForwardEngaged = false;
|
||||||
m_animator.StopROISounds();
|
m_animator.StopROISounds();
|
||||||
m_animator.StopClickAnimation();
|
m_animator.StopClickAnimation();
|
||||||
m_display.DestroyDisplayClone();
|
m_display.DestroyDisplayClone();
|
||||||
@ -365,7 +366,8 @@ MxBool Controller::HandleCameraRelativeMovement(
|
|||||||
p_newPos,
|
p_newPos,
|
||||||
p_newDir,
|
p_newDir,
|
||||||
p_deltaTime,
|
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);
|
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()
|
void Controller::ReinitForCharacter()
|
||||||
{
|
{
|
||||||
if (!GameState() || IsRestrictedArea(GameState()->m_currentArea)) {
|
if (!GameState() || IsRestrictedArea(GameState()->m_currentArea)) {
|
||||||
|
|||||||
@ -8,8 +8,8 @@
|
|||||||
using namespace Extensions::ThirdPersonCamera;
|
using namespace Extensions::ThirdPersonCamera;
|
||||||
|
|
||||||
InputHandler::InputHandler()
|
InputHandler::InputHandler()
|
||||||
: m_touch{}, m_wantsAutoDisable(false), m_wantsAutoEnable(false), m_rightButtonHeld(false), m_savedMouseX(0.0f),
|
: m_touch{}, m_wantsAutoDisable(false), m_wantsAutoEnable(false), m_rightButtonHeld(false),
|
||||||
m_savedMouseY(0.0f)
|
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: {
|
case SDL_EVENT_MOUSE_BUTTON_UP: {
|
||||||
if (p_event->button.button == SDL_BUTTON_RIGHT) {
|
if (p_event->button.button == SDL_BUTTON_RIGHT) {
|
||||||
m_rightButtonHeld = p_event->button.down;
|
m_rightButtonHeld = p_event->button.down;
|
||||||
if (!p_active) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
SDL_Window* window = SDL_GetWindowFromID(p_event->button.windowID);
|
SDL_Window* window = SDL_GetWindowFromID(p_event->button.windowID);
|
||||||
if (window) {
|
if (window) {
|
||||||
if (m_rightButtonHeld) {
|
if (m_rightButtonHeld) {
|
||||||
|
if (p_active) {
|
||||||
SDL_GetMouseState(&m_savedMouseX, &m_savedMouseY);
|
SDL_GetMouseState(&m_savedMouseX, &m_savedMouseY);
|
||||||
SDL_SetWindowRelativeMouseMode(window, true);
|
SDL_SetWindowRelativeMouseMode(window, true);
|
||||||
}
|
}
|
||||||
else {
|
}
|
||||||
|
else if (SDL_GetWindowRelativeMouseMode(window)) {
|
||||||
SDL_SetWindowRelativeMouseMode(window, false);
|
SDL_SetWindowRelativeMouseMode(window, false);
|
||||||
SDL_WarpMouseInWindow(window, m_savedMouseX, m_savedMouseY);
|
SDL_WarpMouseInWindow(window, m_savedMouseX, m_savedMouseY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (p_event->button.button == SDL_BUTTON_LEFT) {
|
||||||
|
m_leftButtonHeld = p_event->button.down;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -147,7 +147,8 @@ MxBool OrbitCamera::HandleCameraRelativeMovement(
|
|||||||
Vector3& p_newPos,
|
Vector3& p_newPos,
|
||||||
Vector3& p_newDir,
|
Vector3& p_newDir,
|
||||||
float p_deltaTime,
|
float p_deltaTime,
|
||||||
bool p_isInMultiPartEmote
|
bool p_isInMultiPartEmote,
|
||||||
|
bool p_lmbHeld
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
LegoInputManager* inputManager = InputManager();
|
LegoInputManager* inputManager = InputManager();
|
||||||
@ -180,8 +181,12 @@ MxBool OrbitCamera::HandleCameraRelativeMovement(
|
|||||||
moveDirX += camRightX;
|
moveDirX += camRightX;
|
||||||
moveDirZ += camRightZ;
|
moveDirZ += camRightZ;
|
||||||
}
|
}
|
||||||
|
if (p_lmbHeld) {
|
||||||
|
moveDirX += camForwardX;
|
||||||
|
moveDirZ += camForwardZ;
|
||||||
|
}
|
||||||
|
|
||||||
if (keyFlags == 0 && inputManager) {
|
if (keyFlags == 0 && !p_lmbHeld && inputManager) {
|
||||||
MxU32 joystickX, joystickY, povPosition;
|
MxU32 joystickX, joystickY, povPosition;
|
||||||
if (inputManager->GetJoystickState(&joystickX, &joystickY, &povPosition) == SUCCESS) {
|
if (inputManager->GetJoystickState(&joystickX, &joystickY, &povPosition) == SUCCESS) {
|
||||||
float jx = (joystickX - 50.0f) / 50.0f;
|
float jx = (joystickX - 50.0f) / 50.0f;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user