L4RIO.h splits the abstract cockpit-control surface (RIOBase: enums, the five analog Scalars, GetNextEvent/SetLamp, no-op serial ops, NEW IsOperational) out of the serial RIO (RIO : PCSerialPacket, RIOBase -- byte-for-byte behavior kept, ctor assigns as before); LBE4ControlsManager holds a RIOBase* and gains the gated L4CONTROLS=PAD factory arm (BT_GLASS; OFF build logs+ignores the token). NEW gated TUs: L4PADRIO (XInput+keyboard synthesize the surface; 3s hot-plug re-probe; focus-guarded keys; per-poll AnalogEvent heartbeat; lampState[] + static SetScreenButton/GetLampState for the panel) and L4PADBINDINGS (content\bindings.txt profile, self-documenting default written on first run; deflect/slew/set axis model; addresses validated against ButtonCount). Verified live (glass build, L4CONTROLS=PAD): bindings written+parsed 44/10/5, XInput pad detected, 121 streamed mappings install via stock PrimaryRIO path, 2157 frames clean. Pod build (gates OFF) compiles the split with zero behavioral delta. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
111 lines
2.8 KiB
C++
111 lines
2.8 KiB
C++
#pragma once
|
|
|
|
//###########################################################################
|
|
//
|
|
// L4PADRIO -- the hardware-less cockpit device (BT_GLASS only).
|
|
//
|
|
// PadRIO synthesizes the pod's abstract control surface (RIOBase: the five
|
|
// analog Scalars + button/keypad events + lamps) from an XInput controller
|
|
// and the PC keyboard, so the whole stock RIO path above the seam -- the
|
|
// LBE4ControlsManager push, MechRIOMapper, streamed .CTL mappings, lamp
|
|
// writes -- runs with no serial hardware. Selected at runtime with
|
|
// L4CONTROLS=PAD (the factory arm in L4CTRL.cpp).
|
|
//
|
|
// Input model (bindings: L4PADBINDINGS.h, content\bindings.txt):
|
|
// - keyboard keys emit button/keypad edge events and drive the analog
|
|
// channels (spring-stick deflect / throttle-lever slew / detent set)
|
|
// - XInput pad buttons emit button events; pad axes drive the channels
|
|
// directly (or as slew rates); hot-plug re-probe every ~3 s
|
|
// - on-screen cockpit buttons (the L4PADPANEL window, or any WndProc)
|
|
// inject through the static SetScreenButton() entry
|
|
// - lamps are recorded in lampState[] for the on-screen panel to render
|
|
//
|
|
// The keyboard is only read while a window of THIS process has focus.
|
|
// L4PADFLIP=1 inverts both stick axes.
|
|
//
|
|
//###########################################################################
|
|
|
|
#include "l4rio.h"
|
|
#include "l4padbindings.h"
|
|
|
|
class PadRIO :
|
|
public RIOBase
|
|
{
|
|
public:
|
|
PadRIO();
|
|
~PadRIO();
|
|
|
|
Logical
|
|
GetNextEvent(RIOEvent *destinationPointer);
|
|
|
|
void
|
|
SetLamp(int lampNumber, int state);
|
|
|
|
Logical
|
|
IsOperational() const
|
|
{ return True; }
|
|
|
|
//
|
|
// The on-screen panel / WndProc entries. Safe no-ops when no PadRIO
|
|
// is active (pod build never links this TU; a glass build without
|
|
// L4CONTROLS=PAD never constructs one). Same-thread use only: the
|
|
// panel WndProc runs on the app thread's message pump.
|
|
//
|
|
static Logical
|
|
IsActive();
|
|
static void
|
|
SetScreenButton(int unit, int pressed);
|
|
static int
|
|
GetLampState(int unit);
|
|
|
|
enum { LampCount = 128 };
|
|
|
|
protected:
|
|
void
|
|
Poll();
|
|
void
|
|
PushEvent(const RIOEvent &event);
|
|
void
|
|
EmitButton(int address, int pressed);
|
|
void
|
|
EmitKeypad(int unit, int key);
|
|
|
|
PadBindingProfile
|
|
bindings;
|
|
|
|
//
|
|
// Event queue (ring; drop-newest on overflow, logged).
|
|
//
|
|
enum { EventQueueSize = 128 };
|
|
RIOEvent
|
|
eventQueue[EventQueueSize];
|
|
int
|
|
eventHead, eventTail;
|
|
|
|
//
|
|
// Poll state.
|
|
//
|
|
unsigned long
|
|
lastPollMilliseconds;
|
|
unsigned long
|
|
lastPadProbeMilliseconds;
|
|
int
|
|
padIndex; // connected XInput slot, -1 = none
|
|
unsigned
|
|
previousPadButtons;
|
|
unsigned char
|
|
previousKeyHeld[192]; // per key BINDING (parallel to the profile)
|
|
float
|
|
channelValue[PadBindingProfile::ChannelCount];
|
|
float
|
|
channelReturnRate[PadBindingProfile::ChannelCount];
|
|
int
|
|
flipStickAxes; // L4PADFLIP
|
|
|
|
int
|
|
lampState[LampCount];
|
|
|
|
static PadRIO
|
|
*activeInstance;
|
|
};
|