forked from chinosk/gkms-local
738 lines
26 KiB
C++
738 lines
26 KiB
C++
#include "baseCamera.hpp"
|
|
#include "camera.hpp"
|
|
#include <thread>
|
|
#include "Misc.hpp"
|
|
#include "../BaseDefine.h"
|
|
|
|
|
|
namespace GKCamera {
|
|
BaseCamera::Camera baseCamera{};
|
|
CameraMode cameraMode = CameraMode::FREE;
|
|
FirstPersonRoll firstPersonRoll = FirstPersonRoll::ENABLE_ROLL;
|
|
FollowModeY followModeY = FollowModeY::SMOOTH_Y;
|
|
|
|
UnityResolve::UnityType::Vector3 firstPersonPosOffset{0, 0.064f, 0.000f};
|
|
UnityResolve::UnityType::Vector3 followPosOffset{0, 0, 1.5};
|
|
UnityResolve::UnityType::Vector2 followLookAtOffset{0, 0};
|
|
float offsetMoveStep = 0.008;
|
|
int followCharaIndex = 0;
|
|
float l_sensitivity = 0.5f;
|
|
float r_sensitivity = 0.5f;
|
|
bool showToast = true;
|
|
GakumasLocal::Misc::CSEnum bodyPartsEnum("Head", 0xa);
|
|
|
|
// bool rMousePressFlg = false;
|
|
|
|
void SetCameraMode(CameraMode mode) {
|
|
cameraMode = mode;
|
|
}
|
|
|
|
CameraMode GetCameraMode() {
|
|
return cameraMode;
|
|
}
|
|
|
|
void SetFirstPersonRoll(FirstPersonRoll mode) {
|
|
firstPersonRoll = mode;
|
|
}
|
|
|
|
FirstPersonRoll GetFirstPersonRoll() {
|
|
return firstPersonRoll;
|
|
}
|
|
|
|
|
|
void reset_camera() {
|
|
followCharaIndex = 0;
|
|
firstPersonPosOffset = {0, 0.064f, 0.000f}; // f3: 0.008f
|
|
followPosOffset = {0, 0, 1.5};
|
|
followLookAtOffset = {0, 0};
|
|
baseCamera.reset();
|
|
}
|
|
|
|
void camera_forward() { // 向前
|
|
switch (cameraMode) {
|
|
case CameraMode::FREE: {
|
|
baseCamera.set_lon_move(0, LonMoveHState::LonMoveForward);
|
|
} break;
|
|
case CameraMode::FIRST_PERSON: {
|
|
firstPersonPosOffset.z += offsetMoveStep;
|
|
} break;
|
|
case CameraMode::FOLLOW: {
|
|
followPosOffset.z -= offsetMoveStep;
|
|
}
|
|
}
|
|
|
|
}
|
|
void camera_back(float multiplier = 1.0f) { // 后退
|
|
switch (cameraMode) {
|
|
case CameraMode::FREE: {
|
|
baseCamera.set_lon_move(180, LonMoveHState::LonMoveBack, multiplier);
|
|
} break;
|
|
case CameraMode::FIRST_PERSON: {
|
|
firstPersonPosOffset.z -= offsetMoveStep * multiplier;
|
|
} break;
|
|
case CameraMode::FOLLOW: {
|
|
followPosOffset.z += offsetMoveStep * multiplier;
|
|
}
|
|
}
|
|
}
|
|
void camera_left() { // 向左
|
|
switch (cameraMode) {
|
|
case CameraMode::FREE: {
|
|
baseCamera.set_lon_move(90);
|
|
} break;
|
|
case CameraMode::FOLLOW: {
|
|
// followPosOffset.x += 0.8;
|
|
followLookAtOffset.x += offsetMoveStep;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
|
|
}
|
|
void camera_right(float multiplier = 1.0f) { // 向右
|
|
switch (cameraMode) {
|
|
case CameraMode::FREE: {
|
|
baseCamera.set_lon_move(-90, LonMoveLeftAndRight, multiplier);
|
|
} break;
|
|
case CameraMode::FOLLOW: {
|
|
// followPosOffset.x -= 0.8;
|
|
followLookAtOffset.x -= offsetMoveStep * multiplier;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
void camera_down(float multiplier = 1.0f) { // 向下
|
|
switch (cameraMode) {
|
|
case CameraMode::FREE: {
|
|
float preStep = BaseCamera::moveStep / BaseCamera::smoothLevel * multiplier;
|
|
|
|
for (int i = 0; i < BaseCamera::smoothLevel; i++) {
|
|
baseCamera.pos.y -= preStep;
|
|
baseCamera.lookAt.y -= preStep;
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(BaseCamera::sleepTime));
|
|
}
|
|
} break;
|
|
case CameraMode::FIRST_PERSON: {
|
|
firstPersonPosOffset.y -= offsetMoveStep * multiplier;
|
|
} break;
|
|
case CameraMode::FOLLOW: {
|
|
// followPosOffset.y -= offsetMoveStep;
|
|
followLookAtOffset.y -= offsetMoveStep * multiplier;
|
|
}
|
|
}
|
|
}
|
|
|
|
void camera_up(float multiplier = 1.0f) { // 向上
|
|
switch (cameraMode) {
|
|
case CameraMode::FREE: {
|
|
float preStep = BaseCamera::moveStep / BaseCamera::smoothLevel * multiplier;
|
|
|
|
for (int i = 0; i < BaseCamera::smoothLevel; i++) {
|
|
baseCamera.pos.y += preStep;
|
|
baseCamera.lookAt.y += preStep;
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(BaseCamera::sleepTime));
|
|
}
|
|
} break;
|
|
case CameraMode::FIRST_PERSON: {
|
|
firstPersonPosOffset.y += offsetMoveStep * multiplier;
|
|
} break;
|
|
case CameraMode::FOLLOW: {
|
|
// followPosOffset.y += offsetMoveStep;
|
|
followLookAtOffset.y += offsetMoveStep * multiplier;
|
|
}
|
|
}
|
|
}
|
|
void cameraLookat_up(float mAngel, bool mouse = false) {
|
|
baseCamera.horizontalAngle += mAngel;
|
|
if (baseCamera.horizontalAngle >= 90) baseCamera.horizontalAngle = 89.99;
|
|
baseCamera.updateVertLook();
|
|
}
|
|
void cameraLookat_down(float mAngel, bool mouse = false) {
|
|
baseCamera.horizontalAngle -= mAngel;
|
|
if (baseCamera.horizontalAngle <= -90) baseCamera.horizontalAngle = -89.99;
|
|
baseCamera.updateVertLook();
|
|
}
|
|
void cameraLookat_left(float mAngel) {
|
|
baseCamera.verticalAngle += mAngel;
|
|
if (baseCamera.verticalAngle >= 360) baseCamera.verticalAngle = -360;
|
|
baseCamera.setHoriLook(baseCamera.verticalAngle);
|
|
}
|
|
void cameraLookat_right(float mAngel) {
|
|
baseCamera.verticalAngle -= mAngel;
|
|
if (baseCamera.verticalAngle <= -360) baseCamera.verticalAngle = 360;
|
|
baseCamera.setHoriLook(baseCamera.verticalAngle);
|
|
}
|
|
void changeCameraFOV(float value) {
|
|
baseCamera.fov += value;
|
|
}
|
|
|
|
void SwitchCameraMode() {
|
|
switch (cameraMode) {
|
|
case CameraMode::FREE: {
|
|
cameraMode = CameraMode::FOLLOW;
|
|
GakumasLocal::Log::Info("CameraMode: FOLLOW");
|
|
} break;
|
|
case CameraMode::FOLLOW: {
|
|
cameraMode = CameraMode::FIRST_PERSON;
|
|
GakumasLocal::Log::Info("CameraMode: FIRST_PERSON");
|
|
} break;
|
|
case CameraMode::FIRST_PERSON: {
|
|
cameraMode = CameraMode::FREE;
|
|
GakumasLocal::Log::Info("CameraMode: FREE");
|
|
|
|
} break;
|
|
}
|
|
}
|
|
|
|
void SwitchCameraSubMode() {
|
|
switch (cameraMode) {
|
|
case CameraMode::FIRST_PERSON: {
|
|
if (firstPersonRoll == FirstPersonRoll::ENABLE_ROLL) {
|
|
firstPersonRoll = FirstPersonRoll::DISABLE_ROLL;
|
|
GakumasLocal::Log::Info("FirstPersonRoll: DISABLE_ROLL");
|
|
}
|
|
else {
|
|
firstPersonRoll = FirstPersonRoll::ENABLE_ROLL;
|
|
GakumasLocal::Log::Info("FirstPersonRoll: ENABLE_ROLL");
|
|
}
|
|
} break;
|
|
|
|
case CameraMode::FOLLOW: {
|
|
if (followModeY == FollowModeY::APPLY_Y) {
|
|
followModeY = FollowModeY::SMOOTH_Y;
|
|
GakumasLocal::Log::Info("FollowModeY: SMOOTH_Y");
|
|
}
|
|
else {
|
|
followModeY = FollowModeY::APPLY_Y;
|
|
GakumasLocal::Log::Info("FollowModeY: APPLY_Y");
|
|
}
|
|
} break;
|
|
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
void OnLeftDown() {
|
|
if (cameraMode == CameraMode::FREE) return;
|
|
if (followCharaIndex >= 1) {
|
|
followCharaIndex--;
|
|
}
|
|
}
|
|
|
|
void OnRightDown() {
|
|
if (cameraMode == CameraMode::FREE) return;
|
|
followCharaIndex++;
|
|
}
|
|
|
|
void OnUpDown() {
|
|
if (cameraMode == CameraMode::FOLLOW) {
|
|
const auto currPart = bodyPartsEnum.Last();
|
|
GakumasLocal::Log::InfoFmt("Look at: %s (0x%x)", currPart.first.c_str(), currPart.second);
|
|
}
|
|
}
|
|
|
|
void OnDownDown() {
|
|
if (cameraMode == CameraMode::FOLLOW) {
|
|
const auto currPart = bodyPartsEnum.Next();
|
|
GakumasLocal::Log::InfoFmt("Look at: %s (0x%x)", currPart.first.c_str(), currPart.second);
|
|
}
|
|
}
|
|
|
|
void ChangeLiveFollowCameraOffsetY(const float value) {
|
|
if (cameraMode == CameraMode::FOLLOW) {
|
|
followPosOffset.y += value;
|
|
}
|
|
}
|
|
|
|
void ChangeLiveFollowCameraOffsetX(const float value) {
|
|
if (cameraMode == CameraMode::FOLLOW) {
|
|
followPosOffset.x += value;
|
|
}
|
|
}
|
|
|
|
void ShowToast(const char *text) {
|
|
if (showToast) {
|
|
GakumasLocal::Log::ShowToast(text);
|
|
}
|
|
}
|
|
|
|
void JLThumbRight(float value) {
|
|
camera_right(value * l_sensitivity * baseCamera.fov / 60);
|
|
}
|
|
|
|
void JLThumbDown(float value) {
|
|
camera_back(value * l_sensitivity * baseCamera.fov / 60);
|
|
}
|
|
|
|
void JRThumbRight(float value) {
|
|
cameraLookat_right(value * r_sensitivity * baseCamera.fov / 60);
|
|
ChangeLiveFollowCameraOffsetX(-1 * value * r_sensitivity * baseCamera.fov / 60);
|
|
}
|
|
|
|
void JRThumbDown(float value) {
|
|
cameraLookat_down(value * r_sensitivity * baseCamera.fov / 60);
|
|
ChangeLiveFollowCameraOffsetY(-0.1 * value * r_sensitivity * baseCamera.fov / 60);
|
|
}
|
|
|
|
void JDadUp(){
|
|
reset_camera();
|
|
ShowToast("Reset Camera");
|
|
}
|
|
|
|
void JDadDown(){
|
|
ShowToast("Notification off, click again to turn it on.");
|
|
showToast = !showToast;
|
|
}
|
|
|
|
void JDadLeft(){
|
|
l_sensitivity = 1.0f;
|
|
ShowToast("Reset Movement Sensitivity");
|
|
}
|
|
|
|
void JDadRight(){
|
|
r_sensitivity = 1.0f;
|
|
ShowToast("Reset Camera Sensitivity");
|
|
}
|
|
|
|
void JAKeyDown() {
|
|
if (cameraMode == CameraMode::FOLLOW) {
|
|
const auto currPart = bodyPartsEnum.Next();
|
|
if (showToast) {
|
|
GakumasLocal::Log::ShowToastFmt("Look at: %s (0x%x)", currPart.first.c_str(),
|
|
currPart.second);
|
|
}
|
|
} else {
|
|
r_sensitivity *= 0.8f;
|
|
}
|
|
}
|
|
|
|
void JBKeyDown() {
|
|
if (cameraMode == CameraMode::FOLLOW) {
|
|
const auto currPart = bodyPartsEnum.Last();
|
|
if (showToast) {
|
|
GakumasLocal::Log::ShowToastFmt("Look at: %s (0x%x)", currPart.first.c_str(),
|
|
currPart.second);
|
|
}
|
|
} else {
|
|
r_sensitivity *= 1.2f;
|
|
}
|
|
}
|
|
|
|
void JXKeyDown() {
|
|
if (cameraMode == CameraMode::FOLLOW) {
|
|
OnLeftDown();
|
|
if (showToast) {
|
|
GakumasLocal::Log::ShowToastFmt("Look at position: %d", followCharaIndex);
|
|
}
|
|
} else {
|
|
l_sensitivity *= 0.8f;
|
|
}
|
|
}
|
|
|
|
void JYKeyDown() {
|
|
if (cameraMode == CameraMode::FOLLOW) {
|
|
OnRightDown();
|
|
if (showToast) {
|
|
GakumasLocal::Log::ShowToastFmt("Look at position: %d", followCharaIndex);
|
|
}
|
|
} else {
|
|
l_sensitivity *= 1.2f;
|
|
}
|
|
}
|
|
|
|
void JSelectKeyDown() {
|
|
switch (cameraMode) {
|
|
case CameraMode::FREE: {
|
|
cameraMode = CameraMode::FOLLOW;
|
|
ShowToast("Follow Mode");
|
|
} break;
|
|
case CameraMode::FOLLOW: {
|
|
cameraMode = CameraMode::FIRST_PERSON;
|
|
ShowToast("First-person Mode");
|
|
} break;
|
|
case CameraMode::FIRST_PERSON: {
|
|
cameraMode = CameraMode::FREE;
|
|
ShowToast("Free Mode");
|
|
|
|
} break;
|
|
}
|
|
}
|
|
|
|
void JStartKeyDown() {
|
|
switch (cameraMode) {
|
|
case CameraMode::FIRST_PERSON: {
|
|
if (firstPersonRoll == FirstPersonRoll::ENABLE_ROLL) {
|
|
firstPersonRoll = FirstPersonRoll::DISABLE_ROLL;
|
|
ShowToast("Camera Horizontal Fixed");
|
|
}
|
|
else {
|
|
firstPersonRoll = FirstPersonRoll::ENABLE_ROLL;
|
|
ShowToast("Camera Horizontal Rollable");
|
|
}
|
|
} break;
|
|
|
|
case CameraMode::FOLLOW: {
|
|
if (followModeY == FollowModeY::APPLY_Y) {
|
|
followModeY = FollowModeY::SMOOTH_Y;
|
|
ShowToast("Smooth Lift");
|
|
}
|
|
else {
|
|
followModeY = FollowModeY::APPLY_Y;
|
|
ShowToast("Instant Lift");
|
|
}
|
|
} break;
|
|
|
|
default: break;
|
|
}
|
|
}
|
|
|
|
UnityResolve::UnityType::Vector3 CalcPositionFromLookAt(const UnityResolve::UnityType::Vector3& target,
|
|
const UnityResolve::UnityType::Vector3& offset) {
|
|
// offset: z 远近, y 高低, x角度
|
|
const float angleX = offset.x;
|
|
const float distanceZ = offset.z;
|
|
const float angleRad = angleX * (M_PI / 180.0f);
|
|
const float newX = target.x + distanceZ * std::sin(angleRad);
|
|
const float newZ = target.z + distanceZ * std::cos(angleRad);
|
|
const float newY = target.y + offset.y;
|
|
return UnityResolve::UnityType::Vector3(newX, newY, newZ);
|
|
}
|
|
|
|
float CheckNewY(const UnityResolve::UnityType::Vector3& targetPos, const bool recordY,
|
|
GakumasLocal::Misc::FixedSizeQueue<float>& recordsY) {
|
|
const auto currentY = targetPos.y;
|
|
static auto lastRetY = currentY;
|
|
|
|
if (followModeY == FollowModeY::APPLY_Y) {
|
|
lastRetY = currentY;
|
|
return currentY;
|
|
}
|
|
|
|
const auto currentAvg = recordsY.Average();
|
|
// GakumasLocal::Log::DebugFmt("currentY: %f, currentAvg: %f, diff: %f", currentY, currentAvg, abs(currentY - currentAvg));
|
|
|
|
if (recordY) {
|
|
recordsY.Push(currentY);
|
|
}
|
|
|
|
if (abs(currentY - currentAvg) < 0.02) {
|
|
return lastRetY;
|
|
}
|
|
|
|
const auto retAvg = recordsY.Average();
|
|
lastRetY = lastRetY + (retAvg - lastRetY) / 8;
|
|
return lastRetY;
|
|
}
|
|
|
|
UnityResolve::UnityType::Vector3 CalcFollowModeLookAt(const UnityResolve::UnityType::Vector3& targetPos,
|
|
const UnityResolve::UnityType::Vector3& posOffset,
|
|
const bool recordY) {
|
|
static GakumasLocal::Misc::FixedSizeQueue<float> recordsY(60);
|
|
|
|
const float angleX = posOffset.x;
|
|
const float angleRad = (angleX + (followPosOffset.z >= 0 ? 90.0f : -90.0f)) * (M_PI / 180.0f);
|
|
|
|
UnityResolve::UnityType::Vector3 newTargetPos = targetPos;
|
|
newTargetPos.y = CheckNewY(targetPos, recordY, recordsY);
|
|
|
|
const float offsetX = followLookAtOffset.x * sin(angleRad);
|
|
const float offsetZ = followLookAtOffset.x * cos(angleRad);
|
|
|
|
newTargetPos.x += offsetX;
|
|
newTargetPos.z += offsetZ;
|
|
newTargetPos.y += followLookAtOffset.y;
|
|
|
|
return newTargetPos;
|
|
}
|
|
|
|
UnityResolve::UnityType::Vector3 CalcFirstPersonPosition(const UnityResolve::UnityType::Vector3& position,
|
|
const UnityResolve::UnityType::Vector3& forward,
|
|
const UnityResolve::UnityType::Vector3& offset) {
|
|
using Vector3 = UnityResolve::UnityType::Vector3;
|
|
|
|
// 计算角色的右方向
|
|
Vector3 up(0, 1, 0); // Y轴方向
|
|
Vector3 right = forward.cross(up).Normalize();
|
|
Vector3 fwd = forward;
|
|
Vector3 pos = position;
|
|
|
|
// 计算角色的左方向
|
|
Vector3 left = right * -1.0f;
|
|
|
|
// 计算最终位置
|
|
Vector3 backwardOffset = fwd * -offset.z;
|
|
Vector3 leftOffset = left * offset.x;
|
|
|
|
Vector3 finalPosition = pos + backwardOffset + leftOffset;
|
|
finalPosition.y += offset.y;
|
|
|
|
return finalPosition;
|
|
|
|
}
|
|
|
|
struct CameraMoveState {
|
|
bool w = false;
|
|
bool s = false;
|
|
bool a = false;
|
|
bool d = false;
|
|
bool ctrl = false;
|
|
bool space = false;
|
|
bool up = false;
|
|
bool down = false;
|
|
bool left = false;
|
|
bool right = false;
|
|
bool q = false;
|
|
bool e = false;
|
|
bool i = false;
|
|
bool k = false;
|
|
bool j = false;
|
|
bool l = false;
|
|
float thumb_l_right = 0.0f;
|
|
float thumb_l_down = 0.0f;
|
|
bool thumb_l_button = false;
|
|
float thumb_r_right = 0.0f;
|
|
float thumb_r_down = 0.0f;
|
|
bool thumb_r_button = false;
|
|
bool dpad_up = false;
|
|
bool dpad_down = false;
|
|
bool dpad_left = false;
|
|
bool dpad_right = false;
|
|
bool a_button = false;
|
|
bool b_button = false;
|
|
bool x_button = false;
|
|
bool y_button = false;
|
|
bool lb_button = false;
|
|
float lt_button = 0.0f;
|
|
bool rb_button = false;
|
|
float rt_button = 0.0f;
|
|
bool select_button = false;
|
|
bool start_button = false;
|
|
bool share_button = false;
|
|
bool xbox_button = false;
|
|
bool threadRunning = false;
|
|
|
|
void resetAll() {
|
|
// 获取当前对象的指针并转换为 unsigned char* 类型
|
|
unsigned char* p = reinterpret_cast<unsigned char*>(this);
|
|
|
|
// 遍历对象的每个字节
|
|
for (size_t offset = 0; offset < sizeof(*this); ) {
|
|
if (offset + sizeof(bool) <= sizeof(*this) && reinterpret_cast<bool*>(p + offset) == reinterpret_cast<bool*>(this) + offset / sizeof(bool)) {
|
|
// 如果当前偏移量适用于 bool 类型,则将其设置为 false
|
|
*reinterpret_cast<bool*>(p + offset) = false;
|
|
offset += sizeof(bool);
|
|
} else if (offset + sizeof(float) <= sizeof(*this) && reinterpret_cast<float*>(p + offset) == reinterpret_cast<float*>(this) + offset / sizeof(float)) {
|
|
// 如果当前偏移量适用于 float 类型,则将其设置为 0.0
|
|
*reinterpret_cast<float*>(p + offset) = 0.0f;
|
|
offset += sizeof(float);
|
|
} else {
|
|
// 处理未定义的情况(例如混合类型数组或其他类型成员)
|
|
// 可以根据实际情况调整逻辑或添加更多类型检查
|
|
offset += 1; // 跳过一个字节
|
|
}
|
|
}
|
|
}
|
|
} cameraMoveState;
|
|
|
|
|
|
void cameraRawInputThread() {
|
|
using namespace BaseCamera;
|
|
|
|
std::thread([]() {
|
|
if (cameraMoveState.threadRunning) return;
|
|
cameraMoveState.threadRunning = true;
|
|
while (true) {
|
|
if (cameraMoveState.w) camera_forward();
|
|
if (cameraMoveState.s) camera_back();
|
|
if (cameraMoveState.a) camera_left();
|
|
if (cameraMoveState.d) camera_right();
|
|
if (cameraMoveState.ctrl) camera_down();
|
|
if (cameraMoveState.space) camera_up();
|
|
if (cameraMoveState.up) cameraLookat_up(moveAngel);
|
|
if (cameraMoveState.down) cameraLookat_down(moveAngel);
|
|
if (cameraMoveState.left) cameraLookat_left(moveAngel);
|
|
if (cameraMoveState.right) cameraLookat_right(moveAngel);
|
|
if (cameraMoveState.q) changeCameraFOV(0.5f);
|
|
if (cameraMoveState.e) changeCameraFOV(-0.5f);
|
|
if (cameraMoveState.i) ChangeLiveFollowCameraOffsetY(offsetMoveStep);
|
|
if (cameraMoveState.k) ChangeLiveFollowCameraOffsetY(-offsetMoveStep);
|
|
if (cameraMoveState.j) ChangeLiveFollowCameraOffsetX(0.8);
|
|
if (cameraMoveState.l) ChangeLiveFollowCameraOffsetX(-0.8);
|
|
// 手柄操作响应
|
|
// 左摇杆
|
|
if (std::abs(cameraMoveState.thumb_l_right) > 0.1f)
|
|
JLThumbRight(cameraMoveState.thumb_l_right);
|
|
if (std::abs(cameraMoveState.thumb_l_down) > 0.1f)
|
|
JLThumbDown(cameraMoveState.thumb_l_down);
|
|
// 右摇杆
|
|
if (std::abs(cameraMoveState.thumb_r_right) > 0.1f)
|
|
JRThumbRight(cameraMoveState.thumb_r_right);
|
|
if (std::abs(cameraMoveState.thumb_r_down) > 0.1f)
|
|
JRThumbDown(cameraMoveState.thumb_r_down);
|
|
// 左扳机
|
|
if (std::abs(cameraMoveState.lt_button) > 0.1f)
|
|
camera_down(cameraMoveState.lt_button * l_sensitivity * baseCamera.fov / 60);
|
|
// 右扳机
|
|
if (std::abs(cameraMoveState.rt_button) > 0.1f)
|
|
camera_up(cameraMoveState.rt_button * l_sensitivity * baseCamera.fov / 60);
|
|
// 左肩键
|
|
if (cameraMoveState.lb_button) changeCameraFOV(0.5f * r_sensitivity);
|
|
// 右肩键
|
|
if (cameraMoveState.rb_button) changeCameraFOV(-0.5f * r_sensitivity);
|
|
// 十字键
|
|
if (cameraMoveState.dpad_up) JDadUp();
|
|
// if (cameraMoveState.dpad_down) JDadDown();
|
|
if (cameraMoveState.dpad_left) JDadLeft();
|
|
if (cameraMoveState.dpad_right) JDadRight();
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
|
}
|
|
}).detach();
|
|
}
|
|
|
|
void on_cam_rawinput_keyboard(int message, int key) {
|
|
if (message == WM_KEYDOWN || message == WM_KEYUP) {
|
|
switch (key) {
|
|
case KEY_W:
|
|
cameraMoveState.w = message == WM_KEYDOWN; break;
|
|
case KEY_S:
|
|
cameraMoveState.s = message == WM_KEYDOWN; break;
|
|
case KEY_A:
|
|
cameraMoveState.a = message == WM_KEYDOWN; break;
|
|
case KEY_D:
|
|
cameraMoveState.d = message == WM_KEYDOWN; break;
|
|
case KEY_CTRL:
|
|
cameraMoveState.ctrl = message == WM_KEYDOWN; break;
|
|
case KEY_SPACE:
|
|
cameraMoveState.space = message == WM_KEYDOWN; break;
|
|
case KEY_UP: {
|
|
if (message == WM_KEYDOWN) {
|
|
OnUpDown();
|
|
}
|
|
cameraMoveState.up = message == WM_KEYDOWN;
|
|
} break;
|
|
case KEY_DOWN: {
|
|
if (message == WM_KEYDOWN) {
|
|
OnDownDown();
|
|
}
|
|
cameraMoveState.down = message == WM_KEYDOWN;
|
|
} break;
|
|
case KEY_LEFT: {
|
|
if (message == WM_KEYDOWN) {
|
|
OnLeftDown();
|
|
}
|
|
cameraMoveState.left = message == WM_KEYDOWN;
|
|
} break;
|
|
case KEY_RIGHT: {
|
|
if (message == WM_KEYDOWN) {
|
|
OnRightDown();
|
|
}
|
|
cameraMoveState.right = message == WM_KEYDOWN;
|
|
} break;
|
|
case KEY_Q:
|
|
cameraMoveState.q = message == WM_KEYDOWN; break;
|
|
case KEY_E:
|
|
cameraMoveState.e = message == WM_KEYDOWN; break;
|
|
case KEY_I:
|
|
cameraMoveState.i = message == WM_KEYDOWN; break;
|
|
case KEY_K:
|
|
cameraMoveState.k = message == WM_KEYDOWN; break;
|
|
case KEY_J:
|
|
cameraMoveState.j = message == WM_KEYDOWN; break;
|
|
case KEY_L:
|
|
cameraMoveState.l = message == WM_KEYDOWN; break;
|
|
case KEY_R: {
|
|
if (message == WM_KEYDOWN) reset_camera();
|
|
} break;
|
|
case KEY_F: if (message == WM_KEYDOWN) SwitchCameraMode(); break;
|
|
case KEY_V: if (message == WM_KEYDOWN) SwitchCameraSubMode(); break;
|
|
// 手柄操作响应
|
|
case BTN_A:
|
|
cameraMoveState.a_button = message == WM_KEYDOWN;
|
|
if (message == WM_KEYDOWN) JAKeyDown();
|
|
break;
|
|
case BTN_B:
|
|
cameraMoveState.b_button = message == WM_KEYDOWN;
|
|
if (message == WM_KEYDOWN) JBKeyDown();
|
|
break;
|
|
case BTN_X:
|
|
cameraMoveState.x_button = message == WM_KEYDOWN;
|
|
if (message == WM_KEYDOWN) JXKeyDown();
|
|
break;
|
|
case BTN_Y:
|
|
cameraMoveState.y_button = message == WM_KEYDOWN;
|
|
if (message == WM_KEYDOWN) JYKeyDown();
|
|
break;
|
|
case BTN_LB:
|
|
cameraMoveState.lb_button = message == WM_KEYDOWN;
|
|
break;
|
|
case BTN_RB:
|
|
cameraMoveState.rb_button = message == WM_KEYDOWN;
|
|
break;
|
|
case BTN_THUMBL:
|
|
cameraMoveState.thumb_l_button = message == WM_KEYDOWN;
|
|
break;
|
|
case BTN_THUMBR:
|
|
cameraMoveState.thumb_r_button = message == WM_KEYDOWN;
|
|
break;
|
|
case BTN_SELECT:
|
|
cameraMoveState.select_button = message == WM_KEYDOWN;
|
|
if (message == WM_KEYDOWN) JSelectKeyDown();
|
|
break;
|
|
case BTN_START:
|
|
cameraMoveState.start_button = message == WM_KEYDOWN;
|
|
if (message == WM_KEYDOWN) JStartKeyDown();
|
|
break;
|
|
case BTN_SHARE:
|
|
cameraMoveState.share_button = message == WM_KEYDOWN;
|
|
break;
|
|
case BTN_XBOX:
|
|
cameraMoveState.xbox_button = message == WM_KEYDOWN;
|
|
break;
|
|
|
|
default: break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
on_cam_rawinput_joystick(JoystickEvent event) {
|
|
int message = event.getMessage();
|
|
float leftStickX = event.getLeftStickX();
|
|
float leftStickY = event.getLeftStickY();
|
|
float rightStickX = event.getRightStickX();
|
|
float rightStickY = event.getRightStickY();
|
|
float leftTrigger = event.getLeftTrigger();
|
|
float rightTrigger = event.getRightTrigger();
|
|
float hatX = event.getHatX();
|
|
float hatY = event.getHatY();
|
|
|
|
cameraMoveState.thumb_l_right = (std::abs(leftStickX) > 0.1f) ? leftStickX : 0;
|
|
cameraMoveState.thumb_l_down = (std::abs(leftStickY) > 0.1f) ? leftStickY : 0;
|
|
cameraMoveState.thumb_r_right = (std::abs(rightStickX) > 0.1f) ? rightStickX : 0;
|
|
cameraMoveState.thumb_r_down = (std::abs(rightStickY) > 0.1f) ? rightStickY : 0;
|
|
cameraMoveState.lt_button = (std::abs(leftTrigger) > 0.1f) ? leftTrigger : 0;
|
|
cameraMoveState.rt_button = (std::abs(rightTrigger) > 0.1f) ? rightTrigger : 0;
|
|
cameraMoveState.dpad_up = hatY == -1.0f;
|
|
cameraMoveState.dpad_down = hatY == 1.0f;
|
|
cameraMoveState.dpad_left = hatX == -1.0f;
|
|
cameraMoveState.dpad_right = hatX == 1.0f;
|
|
|
|
if (cameraMoveState.dpad_down) {
|
|
JDadDown();
|
|
}
|
|
|
|
// GakumasLocal::Log::InfoFmt(
|
|
// "Motion event: action=%d, leftStickX=%.2f, leftStickY=%.2f, rightStickX=%.2f, rightStickY=%.2f, leftTrigger=%.2f, rightTrigger=%.2f, hatX=%.2f, hatY=%.2f",
|
|
// message, leftStickX, leftStickY, rightStickX, rightStickY, leftTrigger,
|
|
// rightTrigger, hatX, hatY);
|
|
}
|
|
|
|
void initCameraSettings() {
|
|
reset_camera();
|
|
cameraRawInputThread();
|
|
}
|
|
|
|
}
|