Merge origin/master: the D1 relay/operator line + input remap meet the glass layer
33 master commits in (relay TCP/UDP + PySide6 operator console, CONTROLS.MAP +XInput binding engine, camera seats, torso pitch aim, sign fixes, the 1995 manual, version stamping, 18-mech certification). Conflicts: .gitignore + CLAUDE.md router rows (combined). SEMANTIC RECONCILIATION (the one real overlap): masters btinput binding engine (ungated, CONTROLS.MAP) and the glass PadRIO (gated, bindings.txt) would both read the keyboard/pad in a glass+PAD session. btinput now joins the stand-down convention: BTInputPoll yields (and BTInputSuppressKey claims NOTHING, so authentic hotkeys flow) when an operational cockpit device owns the input path -- BTRIODevicePresent, BT_KEY_BRIDGE force-override honored, forced harness exempt. One input system per mode: btinput on pod/dev desktops, PadRIO on glass. The mechmppr/mech4 bridge merges composed clean (masters negate-once sign fix inside our device-gated bridge). The D1 relay keeps its own raw sockets by design (an alternative LAN wire; Steam and relay are separate modes). Verified post-merge: all 3 configs build; glass boots with [input] binding engine standing down + PadRIO owning input (30 ticks); pod forced-walk speedDemand=61.501 with btinput ACTIVE; 2-node loopback MP full 31/31 mission, 76/76 ticks. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -641,7 +641,13 @@ void
|
||||
{
|
||||
float key_throttle = gBTDrive.forced
|
||||
? gBTDrive.forcedThrottle : gBTDrive.throttle;
|
||||
float key_turn = gBTDrive.forced ? 0.0f : gBTDrive.turn;
|
||||
// PORT SIGN (user live-verified 2026-07-18: left arrow turned the
|
||||
// mech RIGHT): the sim's positive turnDemand is CCW (LEFT) -- math
|
||||
// convention, same as the torso twist. On the pod the RIO Ranger
|
||||
// owned the hardware sign; the desktop bridge must negate so that
|
||||
// input-right (positive) = turn RIGHT. Forced/BT_GOTO harness
|
||||
// demands are sim-frame already and stay un-negated.
|
||||
float key_turn = gBTDrive.forced ? 0.0f : -gBTDrive.turn;
|
||||
// Headless harness (forced mode only): BT_FORCE_TURN holds a steering
|
||||
// demand; BT_FORCE_SECONDS releases the forced throttle after n
|
||||
// sim-seconds while KEEPING the turn (the turn-in-place repro).
|
||||
@@ -760,6 +766,14 @@ void
|
||||
gBTModeCycle = 0;
|
||||
CycleControlModeNow();
|
||||
}
|
||||
// TORSO ELEVATION (pitch): the pod stick's Y axis -- every
|
||||
// control mode routes stickPosition.y into
|
||||
// Torso::SetAnalogElevationAxis below, so the bridge feeds
|
||||
// it in BOTH branches (keys R/F or a pad stick via btinput).
|
||||
{
|
||||
extern float gBTElevAxis;
|
||||
stickPosition.y = gBTElevAxis;
|
||||
}
|
||||
if (controlMode == BasicMode)
|
||||
{
|
||||
stickPosition.x = key_turn;
|
||||
@@ -767,7 +781,14 @@ void
|
||||
}
|
||||
else
|
||||
{
|
||||
stickPosition.x = gBTTwistAxis; // the torso axis
|
||||
// PORT SIGN: positive twist is CCW (left) like the turn;
|
||||
// negate so stick/E-key right = torso right (manual p8:
|
||||
// "pulling your joystick to the right torso twists your
|
||||
// 'Mech to the right"). The earlier "MadCat twist was
|
||||
// correct" call was based on the same misread screenshot
|
||||
// forensics as the turn -- the user's live left-arrow
|
||||
// test invalidated both.
|
||||
stickPosition.x = -gBTTwistAxis; // the torso axis
|
||||
pedalsPosition = key_turn; // A/D = the pedals
|
||||
// 'X' recenter pulse (2026-07-13): one-frame centerCommand
|
||||
// -> the sim arms recenterActive and Recenter (@004b6918)
|
||||
@@ -792,7 +813,8 @@ void
|
||||
}
|
||||
}
|
||||
}
|
||||
stickPosition.y = 0.0f;
|
||||
// (stickPosition.y no longer zeroed here -- the bridge above
|
||||
// feeds the elevation axis every bridged frame, 2026-07-18)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -863,6 +885,18 @@ void
|
||||
{
|
||||
torso->SetAnalogElevationAxis(stick_y); // raw torso+0x1f4 (500)
|
||||
torso->SetAnalogTwistAxis(0.0f); // raw torso+0x1f0
|
||||
if (getenv("BT_INPUT_LOG"))
|
||||
{
|
||||
static float s_eacc2 = 0.0f; s_eacc2 += time_slice;
|
||||
if (s_eacc2 >= 0.5f) { s_eacc2 = 0.0f;
|
||||
YawPitchRoll ypr;
|
||||
ypr = mech->localOrigin.angularPosition;
|
||||
DEBUG_STREAM << "[input] mppr elev in=" << stick_y
|
||||
<< " torsoElev=" << torso->CurrentElevation()
|
||||
<< " vel=" << torso->ElevationVelocity()
|
||||
<< " mechYaw=" << (Scalar)ypr.yaw
|
||||
<< "\n" << std::flush; }
|
||||
}
|
||||
}
|
||||
if (cockpit)
|
||||
{
|
||||
@@ -887,6 +921,8 @@ void
|
||||
//
|
||||
if (torso == 0 || !torso->GetHorizontalEnabled()) // raw torso+0x250 == 0
|
||||
{
|
||||
// (sign handled ONCE at the key bridge: positive sim twist/slew
|
||||
// = CCW/left; the bridge negates so input-right = right)
|
||||
if (cockpit) cockpit->SetFreeAimSlew(stick_x); // raw cockpit+0x28c
|
||||
}
|
||||
else
|
||||
@@ -894,6 +930,14 @@ void
|
||||
torso->SetAnalogTwistAxis(stick_x); // raw torso+0x1f0
|
||||
}
|
||||
if (torso) torso->SetAnalogElevationAxis(stick_y); // raw torso+0x1f4
|
||||
if (torso && getenv("BT_INPUT_LOG"))
|
||||
{
|
||||
static float s_tacc = 0.0f; s_tacc += time_slice;
|
||||
if (s_tacc >= 0.5f) { s_tacc = 0.0f;
|
||||
DEBUG_STREAM << "[input] twist in=" << stick_x
|
||||
<< " currentTwist=" << torso->CurrentTwist()
|
||||
<< "\n" << std::flush; }
|
||||
}
|
||||
|
||||
turnDemand = (pedal_3 == 0.0f) ? 0.0f : pedal_3;
|
||||
|
||||
@@ -914,7 +958,7 @@ void
|
||||
//
|
||||
if (torso == 0 || !torso->GetHorizontalEnabled())
|
||||
{
|
||||
if (cockpit) cockpit->SetFreeAimSlew(stick_x);
|
||||
if (cockpit) cockpit->SetFreeAimSlew(stick_x); // (sign at the bridge)
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user