From 3febec4aa44ccfc7231abe0df2176e095d78336b Mon Sep 17 00:00:00 2001 From: Inusaito Sayori Date: Wed, 14 May 2014 02:23:55 -0400 Subject: [PATCH] Merge up CtrlAltStudio and Alchemy for XBox360 support Can't seem to get scrollies working in cursor mode, odd.. need to look into that. I need to figure out if inverted Y axis is just for me on my Dual Shock 3, though it seems to work usually... if this is the case I might flip it in the code. More work needs to be done to get ctrl/alt/shift support from CAS, too. I just wanted to get today's work out of the way and wrapped up, so here it is. --- indra/newview/llviewerjoystick.cpp | 318 +++++++++++++++++++++++------ indra/newview/llviewerjoystick.h | 5 + 2 files changed, 261 insertions(+), 62 deletions(-) diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp index 438611162..420ac9944 100644 --- a/indra/newview/llviewerjoystick.cpp +++ b/indra/newview/llviewerjoystick.cpp @@ -40,6 +40,7 @@ #include "llagentcamera.h" #include "llfocusmgr.h" +#include // ---------------------------------------------------------------------------- // Constants @@ -57,6 +58,28 @@ const F32 MIN_AFK_TIME = 2.f; F32 LLViewerJoystick::sLastDelta[] = {0,0,0,0,0,0,0}; F32 LLViewerJoystick::sDelta[] = {0,0,0,0,0,0,0}; +// Note: Save the type of controller +enum EControllerType { NONE, SPACE_NAV, XBOX, UNKNOWN }; +static EControllerType sType = NONE; + +// Control cursor instead of avatar? +bool sControlCursor = false; + +enum XBoxKeys +{ + XBOX_A_KEY = 0, + XBOX_B_KEY, + XBOX_X_KEY, + XBOX_Y_KEY, + XBOX_L_BUMP_KEY, + XBOX_R_BUMP_KEY, + XBOX_BACK_KEY, + XBOX_START_KEY, + XBOX_L_STICK_CLICK, + XBOX_R_STICK_CLICK +}; +// + // These constants specify the maximum absolute value coming in from the device. // HACK ALERT! the value of MAX_JOYSTICK_INPUT_VALUE is not arbitrary as it // should be. It has to be equal to 3000 because the SpaceNavigator on Windows @@ -240,9 +263,11 @@ void LLViewerJoystick::init(bool autoenable) if (mDriverState == JDS_INITIALIZED) { + sControlCursor = false; // A Joystick device is plugged in if (isLikeSpaceNavigator()) { + sType = SPACE_NAV; // It's a space navigator, we have defaults for it. if (gSavedSettings.getString("JoystickInitialized") != "SpaceNavigator") { @@ -251,19 +276,39 @@ void LLViewerJoystick::init(bool autoenable) gSavedSettings.setString("JoystickInitialized", "SpaceNavigator"); } } + else if (isJoystickInitialized() && getDescription().find("Xbox") != std::string::npos) + { + sType = XBOX; + // It's an Xbox controller, we have defaults for it. + if (gSavedSettings.getString("JoystickInitialized") != "XboxController") + { + // Only set the defaults if we haven't already (in case they were overridden) + setSNDefaults(); + gSavedSettings.setString("JoystickInitialized", "XboxController"); + } + } else { - // It's not a Space Navigator + // It's not a Space Navigator or 360 controller + sType = UNKNOWN; gSavedSettings.setString("JoystickInitialized", "UnknownDevice"); } } else { // No device connected, don't change any settings + sType = NONE; } llinfos << "ndof: mDriverState=" << mDriverState << "; mNdofDev=" << mNdofDev << "; libinit=" << libinit << llendl; + + // + if (mDriverState == JDS_INITIALIZED) + { + llinfos << "Joystick = " << getDescription() << llendl; + } + // #endif } @@ -449,6 +494,60 @@ void LLViewerJoystick::agentYaw(F32 yaw_inc) } } +S32 linear_ramp(const F32& inc, const F32& prev_inc) +{ + // Start out linear for fine control but then ramp up more quickly for faster movement. + F32 nudge = inc > F_APPROXIMATELY_ZERO ? 1.f : -1.f; + F32 linear = inc + prev_inc; + F32 square = 0.f; + if (abs(linear) > 0.2f) + { + square = linear + (0.2f * -nudge); + square *= abs(square); + } + + return nudge + linear * 25.f + square * 300.f; +} + +void LLViewerJoystick::cursorSlide(F32 inc) +{ + static F32 prev_inc = 0.f; // Smooth a little. + if (!is_approx_zero(inc)) + { + S32 x, y; + LLUI::getMousePositionScreen(&x, &y); + x = llclamp(x + linear_ramp(inc, prev_inc), 0, gViewerWindow->getWindowWidthRaw()); + LLUI::setMousePositionScreen(x, y); + } + prev_inc = inc; +} + +void LLViewerJoystick::cursorPush(F32 inc) +{ + static F32 prev_inc = 0.f; // Smooth a little. + if (!is_approx_zero(0.001)) + { + S32 x, y; + LLUI::getMousePositionScreen(&x, &y); + y = llclamp(y + linear_ramp(inc, prev_inc), 0, gViewerWindow->getWindowHeightRaw()); + LLUI::setMousePositionScreen(x, y); + } + prev_inc = inc; +} + +void LLViewerJoystick::cursorZoom(F32 inc) +{ + if (!is_approx_zero(inc)) + { + static U8 count = 0; + if (count == 3) // Slow down the zoom in/out. + { + gViewerWindow->handleScrollWheel(inc > F_APPROXIMATELY_ZERO ? 1 : -1); + count = 0; + } + } +} + // ----------------------------------------------------------------------------- void LLViewerJoystick::resetDeltas(S32 axis[]) { @@ -607,21 +706,24 @@ void LLViewerJoystick::moveAvatar(bool reset) gSavedSettings.getS32("JoystickAxis5") }; - if (reset || mResetFlag) + if (!sControlCursor) { - resetDeltas(axis); - if (reset) + if (reset || mResetFlag) { - // Note: moving the agent triggers agent camera mode; - // don't do this every time we set mResetFlag (e.g. because we gained focus) - gAgent.moveAt(0, true); + resetDeltas(axis); + if (reset) + { + // Note: moving the agent triggers agent camera mode; + // don't do this every time we set mResetFlag (e.g. because we gained focus) + gAgent.moveAt(0, true); + } + return; } - return; } bool is_zero = true; - if (mBtn[1] == 1) + if (mBtn[sType == XBOX ? XBOX_L_STICK_CLICK : 1] == 1) { agentJump(); is_zero = false; @@ -737,7 +839,15 @@ void LLViewerJoystick::moveAvatar(bool reset) } sDelta[RX_I] += (cur_delta[RX_I] - sDelta[RX_I]) * time * feather; sDelta[RY_I] += (cur_delta[RY_I] - sDelta[RY_I]) * time * feather; - + + if (sControlCursor) + { + cursorSlide(sDelta[X_I]); // left / right + cursorPush(sDelta[Z_I]); // up / down + cursorZoom(sDelta[RX_I]); // mousewheel + return; + } + handleRun((F32) sqrt(sDelta[Z_I]*sDelta[Z_I] + sDelta[X_I]*sDelta[X_I])); // Allow forward/backward movement some priority @@ -1006,6 +1116,8 @@ bool LLViewerJoystick::toggleFlycam() return true; } +bool toggleCursor() { sControlCursor = !sControlCursor; return true; } + void LLViewerJoystick::scanJoystick() { if (mDriverState != JDS_INITIALIZED || !gSavedSettings.getBOOL("JoystickEnabled")) @@ -1021,20 +1133,86 @@ void LLViewerJoystick::scanJoystick() updateStatus(); static long toggle_flycam = 0; + static bool toggle_cursor = false; - if (mBtn[0] == 1) - { - if (mBtn[0] != toggle_flycam) + // Xbox 360 support + if (sType == XBOX) + { + // Special command keys ... + // - Back = toggle flycam + if (mBtn[XBOX_BACK_KEY] == 1) { - toggle_flycam = toggleFlycam() ? 1 : 0; + if (!toggle_flycam) toggle_flycam = toggleFlycam(); + } + else + { + toggle_flycam = false; + } + + // - Start = toggle cursor/camera control + if (mBtn[XBOX_START_KEY] == 1) + { + if (!toggle_cursor) toggle_cursor = toggleCursor(); + } + else + { + toggle_cursor = false; + } + + // Toggle mouselook ... + static bool right_stick_click_down = false; + if (!!mBtn[XBOX_R_STICK_CLICK] != right_stick_click_down) + { + if (right_stick_click_down = mBtn[XBOX_R_STICK_CLICK]) // Note: Setting, not comparing. + gAgentCamera.cameraMouselook() ? gAgentCamera.changeCameraToDefault() : gAgentCamera.changeCameraToMouselook(); + } + + MASK mask = gKeyboard->currentMask(TRUE); + // Esc + static bool esc_down = false; + if (!!mBtn[XBOX_Y_KEY] != esc_down) + { + esc_down = mBtn[XBOX_Y_KEY]; + (gKeyboard->*(esc_down ? &LLKeyboard::handleTranslatedKeyDown : &LLKeyboard::handleTranslatedKeyDown))(KEY_ESCAPE, mask); + } + + // Mouse clicks ... + LLCoordGL coord; + LLUI::getMousePositionScreen(&coord.mX, &coord.mY); + static bool m1_down = false; + static F32 last_m1 = 0; + if (!!mBtn[XBOX_L_BUMP_KEY] != m1_down) + { + m1_down = mBtn[XBOX_L_BUMP_KEY]; + (gViewerWindow->*(m1_down ? &LLViewerWindow::handleMouseDown : &LLViewerWindow::handleMouseUp))(gViewerWindow->getWindow(), coord, mask); + if (m1_down && gFrameTimeSeconds-last_m1 == 0.5f) + gViewerWindow->handleDoubleClick(gViewerWindow->getWindow(), coord, mask); + last_m1 = gFrameTimeSeconds; + } + static bool m2_down = false; + if (!!mBtn[XBOX_R_BUMP_KEY] != m2_down) + { + m2_down = mBtn[XBOX_R_BUMP_KEY]; + (gViewerWindow->*(m2_down ? &LLViewerWindow::handleRightMouseDown : &LLViewerWindow::handleRightMouseUp))(gViewerWindow->getWindow(), coord, mask); } } else + // { - toggle_flycam = 0; + if (mBtn[0] == 1) + { + if (mBtn[0] != toggle_flycam) + { + toggle_flycam = toggleFlycam() ? 1 : 0; + } + } + else + { + toggle_flycam = 0; + } } - if (!mOverrideCamera && !(LLToolMgr::getInstance()->inBuildMode() && gSavedSettings.getBOOL("JoystickBuildEnabled"))) + if (sControlCursor || (!mOverrideCamera && !(LLToolMgr::getInstance()->inBuildMode() && gSavedSettings.getBOOL("JoystickBuildEnabled")))) { moveAvatar(); } @@ -1049,6 +1227,11 @@ std::string LLViewerJoystick::getDescription() { res = ll_safe_string(mNdofDev->product); } + + // + // Tidy up description of Xbox controllers. + res = boost::regex_replace(res, boost::regex("^Controller \\((.*)\\)$", boost::regex::perl), "$1"); + // #endif return res; } @@ -1081,61 +1264,72 @@ void LLViewerJoystick::setSNDefaults() #endif //gViewerWindow->alertXml("CacheWillClear"); - llinfos << "restoring SpaceNavigator defaults..." << llendl; + const bool xbox = sType == XBOX; + llinfos << "restoring " << (xbox ? "Xbox Controller" : "SpaceNavigator") << " defaults..." << llendl; + + /* + Axis 0: Left Thumbstick Horizontal + Axis 1: Left Thumbstick Vertical + Axis 2: Left and Right triggers (Analog) + Axis 3: Right Thumbstick Horizontal + Axis 4: Left Thumbstick Vertical + Axis 5: Unused + Syntax/Format: + Debug setting InternalMapping,Jostick Axis (see above) */ gSavedSettings.setS32("JoystickAxis0", 1); // z (at) gSavedSettings.setS32("JoystickAxis1", 0); // x (slide) - gSavedSettings.setS32("JoystickAxis2", 2); // y (up) - gSavedSettings.setS32("JoystickAxis3", 4); // pitch - gSavedSettings.setS32("JoystickAxis4", 3); // roll - gSavedSettings.setS32("JoystickAxis5", 5); // yaw + gSavedSettings.setS32("JoystickAxis2", xbox ? -1 : 2); // y (up) + gSavedSettings.setS32("JoystickAxis3", xbox ? 2 : 4); // roll + gSavedSettings.setS32("JoystickAxis4", xbox ? 4 : 3); // pitch + gSavedSettings.setS32("JoystickAxis5", xbox ? 3 : 5); // yaw gSavedSettings.setS32("JoystickAxis6", -1); - gSavedSettings.setBOOL("Cursor3D", is_3d_cursor); + gSavedSettings.setBOOL("Cursor3D", !xbox && is_3d_cursor); gSavedSettings.setBOOL("AutoLeveling", true); gSavedSettings.setBOOL("ZoomDirect", false); - gSavedSettings.setF32("AvatarAxisScale0", 1.f * platformScaleAvXZ); - gSavedSettings.setF32("AvatarAxisScale1", 1.f * platformScaleAvXZ); - gSavedSettings.setF32("AvatarAxisScale2", 1.f); - gSavedSettings.setF32("AvatarAxisScale4", .1f * platformScale); - gSavedSettings.setF32("AvatarAxisScale5", .1f * platformScale); - gSavedSettings.setF32("AvatarAxisScale3", 0.f * platformScale); - gSavedSettings.setF32("BuildAxisScale1", .3f * platformScale); - gSavedSettings.setF32("BuildAxisScale2", .3f * platformScale); - gSavedSettings.setF32("BuildAxisScale0", .3f * platformScale); - gSavedSettings.setF32("BuildAxisScale4", .3f * platformScale); - gSavedSettings.setF32("BuildAxisScale5", .3f * platformScale); - gSavedSettings.setF32("BuildAxisScale3", .3f * platformScale); - gSavedSettings.setF32("FlycamAxisScale1", 2.f * platformScale); - gSavedSettings.setF32("FlycamAxisScale2", 2.f * platformScale); - gSavedSettings.setF32("FlycamAxisScale0", 2.1f * platformScale); - gSavedSettings.setF32("FlycamAxisScale4", .1f * platformScale); - gSavedSettings.setF32("FlycamAxisScale5", .15f * platformScale); - gSavedSettings.setF32("FlycamAxisScale3", 0.f * platformScale); - gSavedSettings.setF32("FlycamAxisScale6", 0.f * platformScale); + gSavedSettings.setF32("AvatarAxisScale0", (xbox ? 0.43f : 1.f) * platformScaleAvXZ); + gSavedSettings.setF32("AvatarAxisScale1", (xbox ? 0.43f : 1.f) * platformScaleAvXZ); + gSavedSettings.setF32("AvatarAxisScale2", xbox ? 0.43f : 1.f); + gSavedSettings.setF32("AvatarAxisScale4", (xbox ? 4.f : .1f) * platformScale); + gSavedSettings.setF32("AvatarAxisScale5", (xbox ? 4.f : .1f) * platformScale); + gSavedSettings.setF32("AvatarAxisScale3", (xbox ? 4.f : 0.f) * platformScale); + gSavedSettings.setF32("BuildAxisScale1", (xbox ? 0.8f : .3f) * platformScale); + gSavedSettings.setF32("BuildAxisScale2", (xbox ? 0.8f : .3f) * platformScale); + gSavedSettings.setF32("BuildAxisScale0", (xbox ? 1.6f : .3f) * platformScale); + gSavedSettings.setF32("BuildAxisScale4", (xbox ? 1.f : .3f) * platformScale); + gSavedSettings.setF32("BuildAxisScale5", (xbox ? 2.f : .3f) * platformScale); + gSavedSettings.setF32("BuildAxisScale3", (xbox ? 1.f : .3f) * platformScale); + gSavedSettings.setF32("FlycamAxisScale1", (xbox ? 4.f : 2.f) * platformScale); + gSavedSettings.setF32("FlycamAxisScale2", (xbox ? 4.f : 2.f) * platformScale); + gSavedSettings.setF32("FlycamAxisScale0", (xbox ? 25.f : 2.1f) * platformScale); // Z Scale + gSavedSettings.setF32("FlycamAxisScale4", (xbox ? 4.f : .1f) * platformScale); + gSavedSettings.setF32("FlycamAxisScale5", (xbox ? 4.f : .15f) * platformScale); + gSavedSettings.setF32("FlycamAxisScale3", (xbox ? 4.f : 0.f) * platformScale); + gSavedSettings.setF32("FlycamAxisScale6", (xbox ? 4.f : 0.f) * platformScale); - gSavedSettings.setF32("AvatarAxisDeadZone0", .1f); - gSavedSettings.setF32("AvatarAxisDeadZone1", .1f); - gSavedSettings.setF32("AvatarAxisDeadZone2", .1f); - gSavedSettings.setF32("AvatarAxisDeadZone3", 1.f); - gSavedSettings.setF32("AvatarAxisDeadZone4", .02f); - gSavedSettings.setF32("AvatarAxisDeadZone5", .01f); - gSavedSettings.setF32("BuildAxisDeadZone0", .01f); - gSavedSettings.setF32("BuildAxisDeadZone1", .01f); - gSavedSettings.setF32("BuildAxisDeadZone2", .01f); - gSavedSettings.setF32("BuildAxisDeadZone3", .01f); - gSavedSettings.setF32("BuildAxisDeadZone4", .01f); - gSavedSettings.setF32("BuildAxisDeadZone5", .01f); - gSavedSettings.setF32("FlycamAxisDeadZone0", .01f); - gSavedSettings.setF32("FlycamAxisDeadZone1", .01f); - gSavedSettings.setF32("FlycamAxisDeadZone2", .01f); - gSavedSettings.setF32("FlycamAxisDeadZone3", .01f); - gSavedSettings.setF32("FlycamAxisDeadZone4", .01f); - gSavedSettings.setF32("FlycamAxisDeadZone5", .01f); - gSavedSettings.setF32("FlycamAxisDeadZone6", 1.f); + gSavedSettings.setF32("AvatarAxisDeadZone0", xbox ? .2f : .1f); + gSavedSettings.setF32("AvatarAxisDeadZone1", xbox ? .2f : .1f); + gSavedSettings.setF32("AvatarAxisDeadZone2", xbox ? .2f : .1f); + gSavedSettings.setF32("AvatarAxisDeadZone3", xbox ? .2f : 1.f); + gSavedSettings.setF32("AvatarAxisDeadZone4", xbox ? .2f : .02f); + gSavedSettings.setF32("AvatarAxisDeadZone5", xbox ? .2f : .01f); + gSavedSettings.setF32("BuildAxisDeadZone0", xbox ? .02f : .01f); + gSavedSettings.setF32("BuildAxisDeadZone1", xbox ? .02f : .01f); + gSavedSettings.setF32("BuildAxisDeadZone2", xbox ? .02f : .01f); + gSavedSettings.setF32("BuildAxisDeadZone3", xbox ? .02f : .01f); + gSavedSettings.setF32("BuildAxisDeadZone4", xbox ? .02f : .01f); + gSavedSettings.setF32("BuildAxisDeadZone5", xbox ? .02f : .01f); + gSavedSettings.setF32("FlycamAxisDeadZone0", xbox ? .2f : .01f); + gSavedSettings.setF32("FlycamAxisDeadZone1", xbox ? .2f : .01f); + gSavedSettings.setF32("FlycamAxisDeadZone2", xbox ? .2f : .01f); + gSavedSettings.setF32("FlycamAxisDeadZone3", xbox ? .1f : .01f); + gSavedSettings.setF32("FlycamAxisDeadZone4", xbox ? .25f : .01f); + gSavedSettings.setF32("FlycamAxisDeadZone5", xbox ? .25f : .01f); + gSavedSettings.setF32("FlycamAxisDeadZone6", xbox ? .2f : 1.f); - gSavedSettings.setF32("AvatarFeathering", 6.f); + gSavedSettings.setF32("AvatarFeathering", xbox ? 3.f : 6.f); gSavedSettings.setF32("BuildFeathering", 12.f); - gSavedSettings.setF32("FlycamFeathering", 5.f); + gSavedSettings.setF32("FlycamFeathering", xbox ? 1.f : 5.f); } diff --git a/indra/newview/llviewerjoystick.h b/indra/newview/llviewerjoystick.h index 431d614c1..308f52bc6 100644 --- a/indra/newview/llviewerjoystick.h +++ b/indra/newview/llviewerjoystick.h @@ -79,6 +79,11 @@ protected: void agentPitch(F32 pitch_inc); void agentYaw(F32 yaw_inc); void agentJump(); + // + void cursorSlide(F32 inc); + void cursorPush(F32 inc); + void cursorZoom(F32 inc); + // void resetDeltas(S32 axis[]); #if LIB_NDOF static NDOF_HotPlugResult HotPlugAddCallback(NDOF_Device *dev);