#include "mungal4.h" #pragma hdrstop #include "l4padrio.h" #include "l4ctrl.h" #include "l4keybd.h" #include "l4app.h" #include "l4dinput.h" #include "..\munga\appmgr.h" #include "dxutils.h" // #define LOCAL_TEST #if defined(LOCAL_TEST) # define Test_Tell(n) Tell(n << std::flush); #else # define Test_Tell(n) #endif static const char *initFileName = "JOYSTICK.INI"; #define RIO_SPOOL_SIZE 12000 //########################################################################### //########################### Button type table ############################# //########################################################################### #define DARKBTN (char) 0 #define AUTOBTN (char) 1 #define MAPBTN (char) 2 #define DI_TRIGGER 0 #define DI_THUMB1 2 #define DI_THUMB2 1 #define DI_THUMB3 3 #define DI_THROTTLE 10 static char buttonType[LBE4ControlsManager::ButtonCount] = { AUTOBTN, // ButtonAuxLowerLeft8=0x00 AUTOBTN, // ButtonAuxLowerLeft7 AUTOBTN, // ButtonAuxLowerLeft6, AUTOBTN, // ButtonAuxLowerLeft5, AUTOBTN, // ButtonAuxLowerLeft4, AUTOBTN, // ButtonAuxLowerLeft3, AUTOBTN, // ButtonAuxLowerLeft2, AUTOBTN, // ButtonAuxLowerLeft1, AUTOBTN, // ButtonAuxLowerRight8=0x08 AUTOBTN, // ButtonAuxLowerRight7, AUTOBTN, // ButtonAuxLowerRight6, AUTOBTN, // ButtonAuxLowerRight5, AUTOBTN, // ButtonAuxLowerRight4, AUTOBTN, // ButtonAuxLowerRight3, AUTOBTN, // ButtonAuxLowerRight2, AUTOBTN, // ButtonAuxLowerRight1, AUTOBTN, // ButtonSecondary1=0x10 AUTOBTN, // ButtonSecondary2, AUTOBTN, // ButtonSecondary3, AUTOBTN, // ButtonSecondary4, AUTOBTN, // ButtonSecondary5, AUTOBTN, // ButtonSecondary6, DARKBTN, // DARKBTN, // AUTOBTN, // ButtonSecondary7=0x18 AUTOBTN, // ButtonSecondary8, AUTOBTN, // ButtonSecondary9, AUTOBTN, // ButtonSecondary10, AUTOBTN, // ButtonSecondary11, AUTOBTN, // ButtonSecondary12, DARKBTN, // DARKBTN, // AUTOBTN, // ButtonAuxUpperCenter8=0x20 AUTOBTN, // ButtonAuxUpperCenter7, AUTOBTN, // ButtonAuxUpperCenter6, AUTOBTN, // ButtonAuxUpperCenter5, AUTOBTN, // ButtonAuxUpperCenter4, AUTOBTN, // ButtonAuxUpperCenter3, AUTOBTN, // ButtonAuxUpperCenter2, AUTOBTN, // ButtonAuxUpperCenter1, AUTOBTN, // ButtonAuxUpperLeft8=0x28 AUTOBTN, // ButtonAuxUpperLeft7, AUTOBTN, // ButtonAuxUpperLeft6, AUTOBTN, // ButtonAuxUpperLeft5, AUTOBTN, // ButtonAuxUpperLeft4, AUTOBTN, // ButtonAuxUpperLeft3, AUTOBTN, // ButtonAuxUpperLeft2, AUTOBTN, // ButtonAuxUpperLeft1, AUTOBTN, // ButtonAuxUpperRight8=0x30 AUTOBTN, // ButtonAuxUpperRight7, AUTOBTN, // ButtonAuxUpperRight6, AUTOBTN, // ButtonAuxUpperRight5, AUTOBTN, // ButtonAuxUpperRight4, AUTOBTN, // ButtonAuxUpperRight3, AUTOBTN, // ButtonAuxUpperRight2, AUTOBTN, // ButtonAuxUpperRight1, AUTOBTN, // ButtonPanic=0x38, DARKBTN, // DARKBTN, // DARKBTN, // DARKBTN, // ButtonDoor=0x3C, DARKBTN, // DARKBTN, // DARKBTN, // ButtonThrottle1=0x3F, MAPBTN, // ButtonJoystickTrigger=0x40 MAPBTN, // ButtonJoystickHatDown=0x41 MAPBTN, // ButtonJoystickHatUp=0x42 MAPBTN, // ButtonJoystickHatRight=0x43 MAPBTN, // ButtonJoystickHatLeft=0x44 MAPBTN, // ButtonJoystickPinky=0x45 MAPBTN, // ButtonJoystickThumbLow=0x46 MAPBTN // ButtonJoystickThumbHigh=0x47 }; //########################################################################### //############################ Joystick classes ############################# //########################################################################### Joystick::Joystick() { NotationFile init(initFileName); channel[0] = new FilterChannel( &init, FilterChannel::joystickXName, 10,20,30 // bogus values in case file didn't previously exist ); Check(channel[0]); channel[1] = new FilterChannel( &init, FilterChannel::joystickYName, 10,20,30 // bogus values in case file didn't previously exist ); Check(channel[1]); ButtonReleased = Joystick::NoButton; ButtonPressed = Joystick::NoButton; Check_Fpu(); } Joystick::~Joystick() { Check(this); NotationFile init(initFileName); //------------------------------------------- // Save DOS timestamp //------------------------------------------- time_t dos_time; time(&dos_time); init.SetEntry("operator", "time", ctime(&dos_time)); for(int i=0; i<2; ++i) { Check(channel[i]); delete channel[i]; channel[i] = NULL; } Check_Fpu(); } void Joystick::BeginAlignment() { Check(this); for(int i=0; i<2; ++i) { Check(channel[i]); channel[i]->BeginAlignment(); } Check_Fpu(); } void Joystick::EndAlignment() { Check(this); //------------------------------------------------------------ // If channel was never adjusted, synthesize reasonable values //------------------------------------------------------------ NotationFile init(initFileName); EndAndSaveAlignment(&init); Check_Fpu(); } void Joystick::EndAndSaveAlignment(NotationFile *init_file) { Check(this); Check(init_file); for(int i=0; i<2; ++i) { Check(channel[i]); channel[i]->EndAlignment(init_file); } Check_Fpu(); } void Joystick::Update() { Fail("Joystick::Update should not be called!\n"); } void Joystick::SetDeadBand(Scalar dead_band) { Check(this); for(int i=0; i<2; ++i) { Check(channel[i]); channel[i]->SetDeadBand(dead_band); } Check_Fpu(); } OrdinaryJoystick::OrdinaryJoystick() { //STUBBED: JOYSTICK RB 1/14/07 //PC_Joystick_Mask = PCJ_Standard_Mask; //ExtendedValue.x = (Scalar) 0; //ExtendedValue.y = (Scalar) 0; //Check_Fpu(); } OrdinaryJoystick::~OrdinaryJoystick() { Check_Fpu(); } void OrdinaryJoystick::Update() { //STUBBED: JOYSTICK RB 1/14/07 //int newButtons, changedButtons; //Check(this); //// ////--------------------------------------------------- //// Update analog values ////--------------------------------------------------- //// //PC_Joystick_Update(); //Check(channel[0]); //Value.x = channel[0]->Update(PC_Joystick1_Raw_X); //Check(channel[1]); //Value.y = channel[1]->Update(PC_Joystick1_Raw_Y); //// ////--------------------------------------------------- //// Handle button changes ////--------------------------------------------------- //// //newButtons = (int) PC_Joystick_Buttons; //changedButtons = newButtons ^ oldButtons; //ButtonPressed = Joystick::NoButton; //ButtonReleased = Joystick::NoButton; //if (changedButtons) //{ // if (changedButtons & PCJ_Standard_Button1) // { // if (newButtons & PCJ_Standard_Button1) // { // ButtonPressed |= Joystick::Trigger; // } // else // { // ButtonReleased |= Joystick::Trigger; // } // } // if (changedButtons & PCJ_Standard_Button2) // { // if (newButtons & PCJ_Standard_Button2) // { // ButtonPressed |= Joystick::Thumb3; // } // else // { // ButtonReleased |= Joystick::Thumb3; // } // } //} //oldButtons = newButtons; //Check_Fpu(); } Logical Joystick::TestInstance() const { return True; } FlightStickPro::FlightStickPro() { //STUBBED: JOYSTICK RB 1/14/07 //NotationFile // init(initFileName); //throttle = new FilterChannel( // &init, // FilterChannel::throttleName, // 10,30 // bogus values in case file doesn't exist //); //Check(throttle); //PC_Joystick_Mask = PCJ_FSP_Mask; //ExtendedValue.x = (Scalar) 0; //Check_Fpu(); } FlightStickPro::~FlightStickPro() { Check(this); NotationFile init(initFileName); //------------------------------------------- // Save DOS timestamp //------------------------------------------- time_t dos_time; time(&dos_time); init.SetEntry("operator", "time", ctime(&dos_time)); Check(throttle); delete throttle; throttle = NULL; Check_Fpu(); } void FlightStickPro::Update() { //STUBBED: JOYSTICK RB 1/14/07 //int newButtons; //Check(this); //// ////--------------------------------------------------- //// Update analog values ////--------------------------------------------------- //// //PC_Joystick_Update(); //Check(channel[0]); //Value.x = channel[0]->Update(PC_Joystick1_Raw_X); //Check(channel[1]); //Value.y = channel[1]->Update(PC_Joystick1_Raw_Y); //// Note inverted direction (below) for throttle //Check(throttle); //ExtendedValue.y = 1.0 - throttle->Update(PC_Joystick2_Raw_Y); //// ////--------------------------------------------------- //// Handle button changes ////--------------------------------------------------- //// //newButtons = int (PC_Joystick_Buttons); //ButtonPressed = Joystick::NoButton; //ButtonReleased = Joystick::NoButton; //if (newButtons != oldButtons) //{ // switch(oldButtons) // { // case PCJ_FSP_Up: ButtonReleased = Joystick::HatUp; break; // case PCJ_FSP_Down: ButtonReleased = Joystick::HatDown; break; // case PCJ_FSP_Left: ButtonReleased = Joystick::HatLeft; break; // case PCJ_FSP_Right: ButtonReleased = Joystick::HatRight; break; // case PCJ_FSP_Trigger: ButtonReleased = Joystick::Trigger; break; // case PCJ_FSP_LButton: ButtonReleased = Joystick::Thumb3; break; // case PCJ_FSP_RButton: ButtonReleased = Joystick::Thumb1; break; // case PCJ_FSP_CButton: ButtonReleased = Joystick::Thumb2; break; // } // switch(newButtons) // { // case PCJ_FSP_Up: ButtonPressed = Joystick::HatUp; break; // case PCJ_FSP_Down: ButtonPressed = Joystick::HatDown; break; // case PCJ_FSP_Left: ButtonPressed = Joystick::HatLeft; break; // case PCJ_FSP_Right: ButtonPressed = Joystick::HatRight; break; // case PCJ_FSP_Trigger: ButtonPressed = Joystick::Trigger; break; // case PCJ_FSP_LButton: ButtonPressed = Joystick::Thumb3; break; // case PCJ_FSP_RButton: ButtonPressed = Joystick::Thumb1; break; // case PCJ_FSP_CButton: ButtonPressed = Joystick::Thumb2; break; // } // oldButtons = newButtons; //} //Check_Fpu(); } void FlightStickPro::BeginAlignment() { Check(this); Check(throttle); throttle->BeginAlignment(); Joystick::BeginAlignment(); Check_Fpu(); } void FlightStickPro::EndAlignment() { Check(this); NotationFile init(initFileName); Check(throttle); throttle->EndAlignment(&init); Joystick::EndAndSaveAlignment(&init); Check_Fpu(); } BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext) { ThrustMaster *joystick = (ThrustMaster*)pContext; if (FAILED(joystick->mDI->CreateDevice(pdidInstance->guidInstance, &joystick->mJoystick, NULL))) return DIENUM_CONTINUE; return DIENUM_STOP; } BOOL CALLBACK EnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) { ThrustMaster *joystick = (ThrustMaster*)pvRef; DIPROPRANGE diprg; diprg.diph.dwSize = sizeof(DIPROPRANGE); diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); diprg.diph.dwHow = DIPH_BYID; diprg.diph.dwObj = lpddoi->dwType; diprg.lMax = diprg.lMax = 0; if (lpddoi->guidType == GUID_XAxis) { if (SUCCEEDED(joystick->mJoystick->GetProperty(DIPROP_RANGE, &diprg.diph))) { joystick->xAxisMin = diprg.lMin; joystick->xAxisMax = diprg.lMax; } } else if (lpddoi->guidType == GUID_YAxis) { if (SUCCEEDED(joystick->mJoystick->GetProperty(DIPROP_RANGE, &diprg.diph))) { joystick->yAxisMin = diprg.lMin; joystick->yAxisMax = diprg.lMax; } } else if (lpddoi->guidType == GUID_ZAxis) { if (SUCCEEDED(joystick->mJoystick->GetProperty(DIPROP_RANGE, &diprg.diph))) { joystick->zAxisMin = diprg.lMin; joystick->zAxisMax = diprg.lMax; } } else if (lpddoi->guidType == GUID_RxAxis) { } else if (lpddoi->guidType == GUID_RyAxis) { } else if (lpddoi->guidType == GUID_RzAxis) { if (SUCCEEDED(joystick->mJoystick->GetProperty(DIPROP_RANGE, &diprg.diph))) { joystick->rzAxisMin = diprg.lMin; joystick->rzAxisMax = diprg.lMax; } } else if (lpddoi->guidType == GUID_Slider) { if (SUCCEEDED(joystick->mJoystick->GetProperty(DIPROP_RANGE, &diprg.diph))) { joystick->zAxisMin = diprg.lMin; joystick->zAxisMax = diprg.lMax; } } return DIENUM_CONTINUE; } ThrustMaster::ThrustMaster(HINSTANCE hInstance, HWND hWnd) { //STUBBED: JOYSTICK RB 1/14/07 ExtendedValue.x = (Scalar) 0; ExtendedValue.y = (Scalar) 0; hatMax = 0; prevHatState = 0; mDI = NULL; mJoystick = NULL; if (SUCCEEDED(DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&mDI, NULL))) { mDI->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, this, DIEDFL_ATTACHEDONLY); if (mJoystick) if (SUCCEEDED(mJoystick->SetDataFormat(&c_dfDIJoystick2))) if (SUCCEEDED(mJoystick->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND))) if (SUCCEEDED(mJoystick->EnumObjects(EnumAxesCallback, this, DIDFT_AXIS))) return; } if (mDI) { mDI->Release(); mDI = NULL; } if (mJoystick) { mJoystick->Release(); mJoystick = NULL; } } ThrustMaster::~ThrustMaster() { Check_Fpu(); } bool ThrustMaster::Poll() { HRESULT hr; if (mJoystick) { V( mJoystick->Poll() ); if (FAILED(hr)) { V( mJoystick->Acquire() ); while (hr == DIERR_INPUTLOST) V( mJoystick->Acquire() ); return false; } V( mJoystick->GetDeviceState(sizeof(DIJOYSTATE2), &mJoystate) ); if (FAILED(hr)) return false; } return true; } void ThrustMaster::Update() { if (!Poll()) return; // //--------------------------------------------------- // Update analog values //--------------------------------------------------- // Value.x = ((Scalar)(mJoystate.lX - xAxisMin) / (Scalar)(xAxisMax - xAxisMin)) * 2.0f - 1.0f; Value.y = ((Scalar)(mJoystate.lY - yAxisMin) / (Scalar)(yAxisMax - yAxisMin)) * 2.0f - 1.0f; LONG z = (mJoystate.lZ == 0 ? mJoystate.rglSlider[0] : mJoystate.lZ); ExtendedValue.y = 1.0f - (Scalar)(z - zAxisMin) / (Scalar)(zAxisMax - zAxisMin); // full left rotation = 0, center rotation = 1/2 range, full right = full range LONG rot = (Scalar)(mJoystate.lRz - rzAxisMin); Scalar half = (Scalar)(rzAxisMax - rzAxisMin) / 2.0f; Rotation.x = (Scalar)0; Rotation.y = (Scalar)0; if (rot <= half) Rotation.x = ((half - rot) / half) * 470.0; else Rotation.y = ((rot - half) / half) * 470.0; // //--------------------------------------------------- // Handle button changes //--------------------------------------------------- // ButtonPressed = Joystick::NoButton; ButtonReleased = Joystick::NoButton; int newButtons = 0; if (mJoystate.rgbButtons[DI_TRIGGER]) newButtons |= Joystick::Trigger; if (mJoystate.rgbButtons[DI_THUMB1]) newButtons |= Joystick::Thumb1; if (mJoystate.rgbButtons[DI_THUMB2]) newButtons |= Joystick::Thumb2; if (mJoystate.rgbButtons[DI_THUMB3]) newButtons |= Joystick::Thumb3; if (mJoystate.rgbButtons[DI_THROTTLE]) newButtons |= Joystick::Throttle; if (mJoystate.rgdwPOV[0] == 0) newButtons |= Joystick::HatUp; if (mJoystate.rgdwPOV[0] == 9000) newButtons |= Joystick::HatRight; if (mJoystate.rgdwPOV[0] == 18000) newButtons |= Joystick::HatDown; if (mJoystate.rgdwPOV[0] == 27000) newButtons |= Joystick::HatLeft; ButtonPressed = (oldButtons ^ newButtons) & newButtons; ButtonReleased = (oldButtons ^ newButtons) & oldButtons; oldButtons = newButtons; } //######################################################################### //########################## LBE4ControlsManager ########################## //######################################################################### //--------------------------------------------------------------------------- // Class derivation //--------------------------------------------------------------------------- Derivation* LBE4ControlsManager::GetClassDerivations() { static Derivation classDerivations(ControlsManager::GetClassDerivations(), "L4ControlsManager"); return &classDerivations; } //--------------------------------------------------------------------------- // Message support //--------------------------------------------------------------------------- //const Receiver::HandlerEntry // LBE4ControlsManager::MessageHandlerEntries[]= //{ // MESSAGE_ENTRY(LBE4ControlsManager,BeginCalibration), // MESSAGE_ENTRY(LBE4ControlsManager,EndCalibration) //}; // //Receiver::MessageHandlerSet // LBE4ControlsManager::MessageHandlers( // ELEMENTS(LBE4ControlsManager::MessageHandlerEntries), // LBE4ControlsManager::MessageHandlerEntries, // ControlsManager::MessageHandlers // ); //--------------------------------------------------------------------------- // Shared data //--------------------------------------------------------------------------- LBE4ControlsManager::SharedData LBE4ControlsManager::DefaultData( LBE4ControlsManager::GetClassDerivations(), LBE4ControlsManager::GetMessageHandlers() ); // //############################################################################ // LBE4ControlsManager // // Creator method //---------------------------------------------------------------------------- // Enter: virtualDataPtr //############################################################################ // LBE4ControlsManager::LBE4ControlsManager(): ControlsManager(L4ControlsManagerClassID, DefaultData) { Check_Pointer(this); // //------------------------------------------------------------------------- // configure //------------------------------------------------------------------------- // flags.mouseExists = 0; flags.keyboardExists = 0; flags.joystickExists = 0; flags.RIOExists = 0; virtualJoystickX = 0; virtualJoystickY = 0; lastJoystickUpdate = 0.0f; joystickType = LBE4ControlsManager::none; mousePointer = NULL; joystickPointer = NULL; rioPointer = NULL; lastRioRequest = 0L; primaryControlType = LBE4ControlsManager::None; char *controlString = getenv("L4CONTROLS"); if (controlString != NULL) { // //------------------------------------------------- // parse environment variable, build configuration //------------------------------------------------- // char temp[128]; char *dest; char c; int noMore(0); do { // // Get the next token // Can't use strtok(), because RIO::RIO uses it, // and it's not re-entrant. // dest = temp; if (noMore) { *dest = '\0'; } else { do { switch(c=*controlString++) { case '\0': case '\n': noMore = 1; // deliberately falls through into next case case ',': case ';': c = '\0'; // deliberately falls through into default case default: *dest++=c; break; } } while (c != '\0'); } //Win32 Serial support: ADB 06/30/07 if(strncmp(temp, "RIO", 3) == 0) { if(strncmp(temp, "RIO:COM", 7) == 0) { int l = strlen(temp+4) + 5; char* comm = new char[l]; strcpy(comm, "\\\\.\\"); strcpy(comm+4, temp+4); rioPointer = new RIO(comm);//temp + 4); Check(rioPointer); Register_Object(rioPointer); flags.RIOExists = 1; primaryControlType = LBE4ControlsManager::PrimaryRIO; delete comm; } else { rioPointer = new RIO("COM1"); Check(rioPointer); Register_Object(rioPointer); flags.RIOExists = 1; primaryControlType = LBE4ControlsManager::PrimaryRIO; } } else if (strcmpi(temp, "KEYBOARD") == 0) { flags.keyboardExists = 1; } else if (strcmpi(temp, "MOUSE") == 0) { if (!flags.mouseExists) { flags.mouseExists = 1; mousePointer = new Mouse; Check(mousePointer); Register_Object(mousePointer); if (mousePointer->Errors) { Unregister_Object(mousePointer); delete mousePointer; mousePointer = NULL; flags.mouseExists = 0; } else { primaryControlType = LBE4ControlsManager::PrimaryThrustMaster; } } } else if (strcmpi(temp, "JOYSTICK") == 0) { flags.joystickExists = 1; joystickType = LBE4ControlsManager::ordinary; joystickPointer = new OrdinaryJoystick(); Register_Object(joystickPointer); primaryControlType = LBE4ControlsManager::PrimaryGenericJoystick; } else if (strcmpi(temp, "FLIGHTSTICKPRO") == 0) { flags.joystickExists = 1; joystickType = LBE4ControlsManager::flightstickPro; joystickPointer = new FlightStickPro(); Register_Object(joystickPointer); primaryControlType = LBE4ControlsManager::PrimaryFlightStickPro; } else if (strcmpi(temp, "THRUSTMASTER") == 0) { flags.joystickExists = 1; joystickType = LBE4ControlsManager::thrustMaster; joystickPointer = new ThrustMaster(ApplicationManager::GetCurrentManager()->GetHInstance(), ApplicationManager::GetCurrentManager()->GetHWnd()); Register_Object(joystickPointer); primaryControlType = LBE4ControlsManager::PrimaryThrustMaster; } else if (strcmpi(temp, "DIJOYSTICK") == 0) { joystickPointer = new DIJoystick(ApplicationManager::GetCurrentManager()->GetHInstance(), ApplicationManager::GetCurrentManager()->GetHWnd()); if (((DIJoystick*)joystickPointer)->IsValid()) { flags.joystickExists = 1; joystickType = LBE4ControlsManager::directInputJoystick; Register_Object(joystickPointer); primaryControlType = LBE4ControlsManager::PrimaryThrustMaster; } else { delete joystickPointer; joystickPointer = NULL; } } else if (strcmpi(temp, "PAD") == 0) { //------------------------------------------------------ // Cockpit-less play: PadRIO speaks the RIO control // surface from an XInput pad + the PC keyboard, so the // full RIO mapper/lamp/button path runs unchanged. //------------------------------------------------------ rioPointer = new PadRIO(); Check(rioPointer); Register_Object(rioPointer); flags.RIOExists = 1; primaryControlType = LBE4ControlsManager::PrimaryRIO; } } while (temp[0] != '\0'); } //-------------------------------------------------- // Clear all lamps (and reset analog I/O) //-------------------------------------------------- if (rioPointer != NULL) { Check(rioPointer); rioPointer->GeneralReset(); } //-------------------------------------------------- // Get mode mask for updating //-------------------------------------------------- Check(application); Check(application->GetModeManager()); ModeMask mode_mask = application->GetModeManager()->GetModeMask(); //-------------------------------------------------- // Initialize scalar group //-------------------------------------------------- { int i; ControlsScalar initial_scalar = 0.0; for(i=0; iRewind(); RIOStreamEvent *start = (RIOStreamEvent*)rioStream->GetPointer(); Unregister_Object(rioStream); delete rioStream; Unregister_Pointer(start); delete[] start; rioStream = NULL; streamEnabled = False; } //-------------------------------------------------- // Delete mouse //-------------------------------------------------- if (mousePointer != NULL) { Check(mousePointer); Unregister_Object(mousePointer); delete mousePointer; mousePointer = NULL; } //-------------------------------------------------- // Delete joystick //-------------------------------------------------- if (joystickPointer != NULL) { Check(joystickPointer); Unregister_Object(joystickPointer); delete joystickPointer; joystickPointer = NULL; } //-------------------------------------------------- // Delete string manager temporary groups //-------------------------------------------------- ExitControlsMode(); //-------------------------------------------------- // Delete RIO AFTER buttons! // ...the 'autoManager' button class sends // lamp commands when deleted. //-------------------------------------------------- if (rioPointer != NULL) { Check(rioPointer); Unregister_Object(rioPointer); delete rioPointer; rioPointer = NULL; } Check_Fpu(); } // //############################################################################# // LocalShutdown //############################################################################# // void LBE4ControlsManager::LocalShutdown() { Check_Pointer(this); if (rioPointer != NULL) { Check(rioPointer); Unregister_Object(rioPointer); delete rioPointer; rioPointer = NULL; } ControlsManager::LocalShutdown(); Check_Fpu(); } // //############################################################################ // Remove // // Remove all controlsInstance records bearing the given ID //############################################################################ // void LBE4ControlsManager::Remove(ModeMask mode_mask) { int i; Check(this); for(i=0; i= 0); Verify(lamp_number < LBE4ControlsManager::LampCount); rioPointer->SetLamp(lamp_number, (RIO::LampState) state); } Check_Fpu(); } // //############################################################################ // Execute // // Execution method //############################################################################ // void LBE4ControlsManager::Execute() { ControlsJoystick virtual_joystick; ControlsKey keyValue; ControlsMouse mouseValue; static Scalar mouseWheel = 0.0; Logical new_RIO_values(False); Logical mouseMoved = false; Logical mouseWheelMoved = false; static int oldX = 0; static int oldY = 0; Check(this); //-------------------------------------------------- // Get mode mask for updating //-------------------------------------------------- Check(application); Check(application->GetModeManager()); ModeMask mode_mask = application->GetModeManager()->GetModeMask(); //------------------------------------------------------------------------- // Process operator control mode //------------------------------------------------------------------------- // ManageControlsMode(); //------------------------------------------------------------------------- // Process RIO //------------------------------------------------------------------------- if (flags.RIOExists) { Check(rioPointer); RIO::RIOEvent rio_event; // //------------------------------------ // Request analog update // (held down to 5 Hz unless reply // is received: reply allows another // request to be sent next invocation) //------------------------------------ // if (!playbackMode) { //Scalar // delta_t(Now() - lastRioRequest); //Scalar // limit; //static Logical // first_time = True; //ADB 10/01/07 static DWORD last_check = GetTickCount(); DWORD limit = 15000; if(application->GetApplicationState() == Application::RunningMission) { //Posible Bug: ADB 03/30/07 //limit = 15.0; // 0.2 limit = 50;//reduced to improve responsiveness } //else //{ // //limit = 15.0; // limit = 15000; //} //if (first_time) //{ // first_time = False; //} //else { DWORD this_check = GetTickCount(); //if(this_check - last_check >= 1000) //DEBUG_STREAM << "No Request in " << (this_check - last_check) << "ms." << std::endl << std::flush; if((this_check - last_check) >= limit) //if (delta_t >= limit) // 5 Hz minimum rate, in case of no reply { //------------------------- // Debugging aid //------------------------- //long time_in_ticks; //time_in_ticks = lastRioRequest; //if (time_in_ticks != 0L) //{ // DEBUG_STREAM << "LBE4ControlsManager::Execute, lost RIO analog request\n"; //STUBBED: JOYSTICK RB 1/14/07 /*extern Logical iThinkIRQIsOn; extern int pcspakCharactersSent; DEBUG_STREAM << "iThinkIRQIsOn =" << iThinkIRQIsOn << ", actual state =" << PCSPAKIRQState() << ", characters sent =" << pcspakCharactersSent << "\n";*/ //} rioPointer->RequestAnalogUpdate(); //lastRioRequest = Now(); last_check = this_check; } //------------------------- // Debugging aid //------------------------- //else if (delta_t < 0.0) //{ // DEBUG_STREAM << // "LBE4ControlsManager::Execute, delta_t went negative (" << // delta_t << ")\n"; // rioPointer->RequestAnalogUpdate(); // lastRioRequest = Now(); //} } } // //------------------------------------ // Process events //------------------------------------ // while (GetNextRIOEvent(&rio_event)) { ProcessRIOEvent(rio_event, &new_RIO_values); } } // //------------------------------------------------------------------------- // Read physical joystick inputs, filter the values //------------------------------------------------------------------------- // if (flags.joystickExists) { Scalar delta_t = (Scalar)Now() - lastJoystickUpdate; if (delta_t > .05) { Check(joystickPointer); joystickPointer->Update(); joystickPointer->Value.x = -joystickPointer->Value.x; // HACK!!! lastJoystickUpdate = Now(); } } // //------------------------------------------------------------------------- // Read physical mouse inputs, generate virtual joystick values //------------------------------------------------------------------------- // if (flags.mouseExists) { Check(mousePointer); //OLD WAY: mousePointer->ReadCounters(&mouseValue.x, &mouseValue.y); //NEW WAY /*MSG msg; if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if (msg.message == WM_MOUSEMOVE) { mouseMoved = true; GetMessage(&msg, NULL, 0, 0); int x = (msg.lParam & 0xFFFF); int y = (msg.lParam & 0xFFFF0000) >> 16; mouseValue.x = x - oldX; mouseValue.y = y - oldY; oldX = x; oldY = y; virtualJoystickX += mouseValue.x; virtualJoystickY += mouseValue.y; #define MAXEXTENT 400 // This is a guess. We'll have to try it and see. if (virtualJoystickX > MAXEXTENT) { virtualJoystickX = MAXEXTENT; } if (virtualJoystickX < -MAXEXTENT) { virtualJoystickX = -MAXEXTENT; } virtual_joystick.x = (Scalar) virtualJoystickX / (Scalar) MAXEXTENT; if (virtualJoystickY > MAXEXTENT) { virtualJoystickY = MAXEXTENT; } if (virtualJoystickY < -MAXEXTENT) { virtualJoystickY = -MAXEXTENT; } virtual_joystick.y = (Scalar) virtualJoystickY / (Scalar) MAXEXTENT; }*/ //else if (msg.message == 0x020A /*WM_MOUSEWHEEL*/) /*{ #define MAXEXTENT 1200.0f // Just a guess mouseWheelMoved = true; GetMessage(&msg, NULL, 0, 0); //mouseWheel = (signed int)((msg.wParam & 0xFFFF0000) >> 16) * 1.0f; int delta = (mouseWheel * MAXEXTENT) + ((short)HIWORD(msg.wParam)); if (delta > MAXEXTENT) delta = MAXEXTENT; if (delta < 0.0f) delta = 0.0f; mouseWheel = delta / MAXEXTENT; } }*/ } // //------------------------------------------------------------------------- // Update the scalar mapping groups using the analog values //------------------------------------------------------------------------- // if (flags.RIOExists && new_RIO_values) { Check(rioPointer); Check(&scalarGroup[LBE4ControlsManager::ScalarThrottle]); scalarGroup[LBE4ControlsManager::ScalarThrottle].Update( &rioPointer->Throttle, mode_mask ); Check(&scalarGroup[LBE4ControlsManager::ScalarLeftPedal]); scalarGroup[LBE4ControlsManager::ScalarLeftPedal].Update( &rioPointer->LeftPedal, mode_mask ); Check(&scalarGroup[LBE4ControlsManager::ScalarRightPedal]); scalarGroup[LBE4ControlsManager::ScalarRightPedal].Update( &rioPointer->RightPedal, mode_mask ); Check(&scalarGroup[LBE4ControlsManager::ScalarJoystickX]); scalarGroup[LBE4ControlsManager::ScalarJoystickX].Update( &rioPointer->JoystickX, mode_mask ); Check(&scalarGroup[LBE4ControlsManager::ScalarJoystickY]); scalarGroup[LBE4ControlsManager::ScalarJoystickY].Update( &rioPointer->JoystickY, mode_mask ); } else if (flags.joystickExists) { scalarGroup[LBE4ControlsManager::ScalarLeftPedal].Update( &joystickPointer->Rotation.x, mode_mask ); scalarGroup[LBE4ControlsManager::ScalarRightPedal].Update( &joystickPointer->Rotation.y, mode_mask ); Check(&scalarGroup[LBE4ControlsManager::ScalarThrottle]); scalarGroup[LBE4ControlsManager::ScalarThrottle].Update( &joystickPointer->ExtendedValue.y, mode_mask ); Check(&scalarGroup[LBE4ControlsManager::ScalarJoystickX]); scalarGroup[LBE4ControlsManager::ScalarJoystickX].Update( &joystickPointer->Value.x, mode_mask ); Check(&scalarGroup[LBE4ControlsManager::ScalarJoystickY]); scalarGroup[LBE4ControlsManager::ScalarJoystickY].Update( &joystickPointer->Value.y, mode_mask ); } if (flags.mouseExists) { if (mouseMoved) { Check(&scalarGroup[LBE4ControlsManager::ScalarMouseX]); scalarGroup[LBE4ControlsManager::ScalarMouseX].Update( &virtual_joystick.x, mode_mask ); Check(&scalarGroup[LBE4ControlsManager::ScalarMouseY]); scalarGroup[LBE4ControlsManager::ScalarMouseY].Update( &virtual_joystick.y, mode_mask ); } else { Scalar clear = 0; scalarGroup[LBE4ControlsManager::ScalarMouseX].Update(&clear, mode_mask); scalarGroup[LBE4ControlsManager::ScalarMouseY].Update(&clear, mode_mask); } if (mouseWheelMoved) { scalarGroup[LBE4ControlsManager::ScalarThrottle].Update( &mouseWheel, mode_mask ); } } // //------------------------------------------------------------------------- // Update the joystick mapping groups using the analog values //------------------------------------------------------------------------- // if (flags.RIOExists && new_RIO_values) { Check(rioPointer); ControlsJoystick stick; stick.x = rioPointer->JoystickX; stick.y = rioPointer->JoystickY; Check(&joystickGroup[LBE4ControlsManager::JoystickPhysical]); joystickGroup[LBE4ControlsManager::JoystickPhysical].Update( &stick, mode_mask ); } else if (flags.joystickExists) { Check(&joystickGroup[LBE4ControlsManager::JoystickPhysical]); joystickGroup[LBE4ControlsManager::JoystickPhysical].Update( &joystickPointer->Value, mode_mask ); } if (flags.mouseExists && mouseMoved) { Check(&joystickGroup[LBE4ControlsManager::JoystickVirtual]); /*joystickGroup[LBE4ControlsManager::JoystickVirtual].Update( &virtual_joystick, mode_mask );*/ joystickGroup[LBE4ControlsManager::JoystickPhysical].Update( &virtual_joystick, mode_mask ); } // //------------------------------------------------------------------------- // Update the PC keyboard mapping group //------------------------------------------------------------------------- // if (flags.keyboardExists) { //RB 1/20/07 //keyValue = (ControlsKey) PC_Keyboard_Read(); MSG msg; if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) { if (msg.message == WM_SYSKEYUP || msg.message == WM_KEYUP || msg.message == WM_CHAR) { GetMessage(&msg, NULL, 0, 0); TranslateMessage(&msg); keyValue = (msg.wParam & VK_MASK); if (msg.message == WM_SYSKEYUP) keyValue |= ALT_BIT; keyboardGroup[KeyboardPC].ForceUpdate(&keyValue, mode_mask); stringManager.Update(KeyboardPC, keyValue); } } } // //------------------------------------------------------------------------- // Update the button mapping groups //------------------------------------------------------------------------- // // //-------------------------- // Joystick buttons //-------------------------- // if (flags.joystickExists) { int i; ControlsButton b; Check(joystickPointer); i = joystickPointer->ButtonReleased; if(i != Joystick::NoButton) { if (i & Joystick::Trigger) { b = - ButtonJoystickTrigger - 1; buttonGroup[ButtonJoystickTrigger].Update(&b, mode_mask); } if (i & Joystick::Thumb1) { b = - ButtonJoystickPinky - 1; buttonGroup[ButtonJoystickPinky].Update(&b, mode_mask); } if (i & Joystick::Thumb2) { b = - ButtonJoystickThumbLow - 1; buttonGroup[ButtonJoystickThumbLow].Update(&b, mode_mask); } if (i & Joystick::Thumb3) { b = - ButtonJoystickThumbHigh - 1; buttonGroup[ButtonJoystickThumbHigh].Update(&b, mode_mask); } if (i & Joystick::Throttle) { b = - ButtonThrottle1 - 1; buttonGroup[ButtonThrottle1].Update(&b, mode_mask); } if (i & Joystick::HatUp) { b = - ButtonJoystickHatUp - 1; buttonGroup[ButtonJoystickHatUp].Update(&b, mode_mask); } if (i & Joystick::HatDown) { b = - ButtonJoystickHatDown - 1; buttonGroup[ButtonJoystickHatDown].Update(&b, mode_mask); } if (i & Joystick::HatLeft) { b = - ButtonJoystickHatLeft - 1; buttonGroup[ButtonJoystickHatLeft].Update(&b, mode_mask); } if (i & Joystick::HatRight) { b = - ButtonJoystickHatRight - 1; buttonGroup[ButtonJoystickHatRight].Update(&b, mode_mask); } } i = joystickPointer->ButtonPressed; if(i != Joystick::NoButton) { if (i & Joystick::Trigger) { b = ButtonJoystickTrigger + 1; buttonGroup[ButtonJoystickTrigger].Update(&b, mode_mask); } if (i & Joystick::Thumb1) { b = ButtonJoystickPinky + 1; buttonGroup[ButtonJoystickPinky].Update(&b, mode_mask); } if (i & Joystick::Thumb2) { b = ButtonJoystickThumbLow + 1; buttonGroup[ButtonJoystickThumbLow].Update(&b, mode_mask); } if (i & Joystick::Thumb3) { b = ButtonJoystickThumbHigh + 1; buttonGroup[ButtonJoystickThumbHigh].Update(&b, mode_mask); } if (i & Joystick::Throttle) { b = ButtonThrottle1 - 1; buttonGroup[ButtonThrottle1].Update(&b, mode_mask); } if (i & Joystick::HatUp) { b = ButtonJoystickHatUp + 1; buttonGroup[ButtonJoystickHatUp].Update(&b, mode_mask); } if (i & Joystick::HatDown) { b = ButtonJoystickHatDown + 1; buttonGroup[ButtonJoystickHatDown].Update(&b, mode_mask); } if (i & Joystick::HatLeft) { b = ButtonJoystickHatLeft + 1; buttonGroup[ButtonJoystickHatLeft].Update(&b, mode_mask); } if (i & Joystick::HatRight) { b = ButtonJoystickHatRight + 1; buttonGroup[ButtonJoystickHatRight].Update(&b, mode_mask); } } } // //-------------------------- // Mouse buttons //-------------------------- // if (flags.mouseExists) { int i, j, k; ControlsButton b; k = mousePointer->ButtonCount; for(i=0, j=LBE4ControlsManager::ButtonMouseLeft; iButtonPressed(i)) { b = (ControlsButton) (j+1); buttonGroup[j].Update(&b, mode_mask); } if (mousePointer->ButtonReleased(i)) { b = (ControlsButton) (-j-1); buttonGroup[j].Update(&b, mode_mask); } } // //------------------------------------------------------------------------- // Update the mouse mapping group //------------------------------------------------------------------------- // mouseGroup[0].Update(&mouseValue, mode_mask); } // Tell("LBE4ControlsManager::Execute ends\n" << std::flush); Check_Fpu(); } // //############################################################################ // BeginAlignJoystick // // Start alignment process for joystick and analog inputs //############################################################################ // void LBE4ControlsManager::BeginAlignJoystick() { Check(this); if (flags.joystickExists) { Check(joystickPointer); joystickPointer->BeginAlignment(); } Check_Fpu(); } // //############################################################################ // EndAlignJoystick // // End alignment process for joystick and analog inputs //############################################################################ // void LBE4ControlsManager::EndAlignJoystick() { Check(this); if (flags.RIOExists) { Check(rioPointer); rioPointer->ForceCenterJoystick(); } if (flags.joystickExists) { Check(joystickPointer); joystickPointer->EndAlignment(); } Check_Fpu(); } void LBE4ControlsManager::CenterRIOJoystick() { Check(this); if (flags.RIOExists) { Check(rioPointer); rioPointer->ForceCenterJoystick(); } Check_Fpu(); } void LBE4ControlsManager::SetJoystickDeadBand(Scalar dead_band) { Check(this); if (flags.RIOExists) { Check(rioPointer); rioPointer->SetJoystickDeadBand(dead_band); } if (flags.joystickExists) { Check(joystickPointer); joystickPointer->SetDeadBand(dead_band); } Check_Fpu(); } void LBE4ControlsManager::SetThrottleDeadBand(Scalar dead_band) { Check(this); if (flags.RIOExists) { Check(rioPointer); rioPointer->SetThrottleDeadBand(dead_band); } Check_Fpu(); } void LBE4ControlsManager::SetPedalsDeadBand(Scalar dead_band) { Check(this); if (flags.RIOExists) { Check(rioPointer); rioPointer->SetPedalsDeadBand(dead_band); } Check_Fpu(); } const char* LBE4ControlsManager::GetLampName(int lamp_number) { const char *lamp_name[] = { "AuxLowerRight8", "AuxLowerRight7", "AuxLowerRight6", "AuxLowerRight5", "AuxLowerRight4", "AuxLowerRight3", "AuxLowerRight2", "AuxLowerRight1", "AuxLowerLeft8", "AuxLowerLeft7", "AuxLowerLeft6", "AuxLowerLeft5", "AuxLowerLeft4", "AuxLowerLeft3", "AuxLowerLeft2", "AuxLowerLeft1", "Secondary1", //=0x10 "Secondary2", "Secondary3", "Secondary4", "Secondary5", "Secondary6", "TeslaRelay3", "undefined_0x17", "Secondary7", //=0x18 "Secondary8", "Secondary9", "Secondary10", "Secondary11", "Secondary12", "TeslaRelay1", "TeslaRelay2", "AuxUpperCenter8", //=0x20 "AuxUpperCenter7", "AuxUpperCenter6", "AuxUpperCenter5", "AuxUpperCenter4", "AuxUpperCenter3", "AuxUpperCenter2", "AuxUpperCenter1", "AuxUpperLeft8", //=0x28 "AuxUpperLeft7", "AuxUpperLeft6", "AuxUpperLeft5", "AuxUpperLeft4", "AuxUpperLeft3", "AuxUpperLeft2", "AuxUpperLeft1", "AuxUpperRight8", //=0x30 "AuxUpperRight7", "AuxUpperRight6", "AuxUpperRight5", "AuxUpperRight4", "AuxUpperRight3", "AuxUpperRight2", "AuxUpperRight1", "PanicButton", //=0x38 "IcomAmpEnableRelay",//=0x39 "IcomIncRelay", //=0x3A "IcomPTTRelay", //=0x03B "IcomDecRelay", //=0x3C "undefined_0x3D", //=0x3D unimplemented convenience lamp "FloorEntry" //=0x3E }; if (lamp_number >= LampCount) { return "overrange"; } else if (lamp_number < 0) { return "underrange"; } else { return lamp_name[lamp_number]; } } #define ID_ENTRY(name,group)\ { #name , LBE4ControlsManager::##group, LBE4ControlsManager::##name } struct { const char* controlName; Enumeration controlsGroup, controlsElement; } Control_IDs[]= { //----------------------------------------------- // Throttle //----------------------------------------------- ID_ENTRY(ScalarThrottle,ScalarGroup), ID_ENTRY(ButtonThrottle1,ButtonGroup), //----------------------------------------------- // Pedals //----------------------------------------------- ID_ENTRY(ScalarLeftPedal,ScalarGroup), ID_ENTRY(ScalarRightPedal,ScalarGroup), //----------------------------------------------- // Joystick //----------------------------------------------- ID_ENTRY(JoystickPhysical,JoystickGroup), ID_ENTRY(ButtonJoystickHatUp,ButtonGroup), ID_ENTRY(ButtonJoystickHatDown,ButtonGroup), ID_ENTRY(ButtonJoystickHatLeft,ButtonGroup), ID_ENTRY(ButtonJoystickHatRight,ButtonGroup), ID_ENTRY(ButtonJoystickTrigger,ButtonGroup), ID_ENTRY(ButtonJoystickThumbHigh,ButtonGroup), ID_ENTRY(ButtonJoystickThumbLow,ButtonGroup), ID_ENTRY(ButtonJoystickPinky,ButtonGroup), //----------------------------------------------- // Secondary buttons //----------------------------------------------- ID_ENTRY(ButtonSecondary1,ButtonGroup), ID_ENTRY(ButtonSecondary2,ButtonGroup), ID_ENTRY(ButtonSecondary3,ButtonGroup), ID_ENTRY(ButtonSecondary4,ButtonGroup), ID_ENTRY(ButtonSecondary5,ButtonGroup), ID_ENTRY(ButtonSecondary6,ButtonGroup), ID_ENTRY(ButtonSecondary7,ButtonGroup), ID_ENTRY(ButtonSecondary8,ButtonGroup), ID_ENTRY(ButtonSecondary9,ButtonGroup), ID_ENTRY(ButtonSecondary10,ButtonGroup), ID_ENTRY(ButtonSecondary11,ButtonGroup), ID_ENTRY(ButtonSecondary12,ButtonGroup), //----------------------------------------------- // Upper left auxiliary //----------------------------------------------- ID_ENTRY(ButtonAuxUpperLeft8,ButtonGroup), ID_ENTRY(ButtonAuxUpperLeft7,ButtonGroup), ID_ENTRY(ButtonAuxUpperLeft6,ButtonGroup), ID_ENTRY(ButtonAuxUpperLeft5,ButtonGroup), ID_ENTRY(ButtonAuxUpperLeft4,ButtonGroup), ID_ENTRY(ButtonAuxUpperLeft3,ButtonGroup), ID_ENTRY(ButtonAuxUpperLeft2,ButtonGroup), ID_ENTRY(ButtonAuxUpperLeft1,ButtonGroup), //----------------------------------------------- // Center auxiliary //----------------------------------------------- ID_ENTRY(ButtonAuxUpperCenter8,ButtonGroup), ID_ENTRY(ButtonAuxUpperCenter7,ButtonGroup), ID_ENTRY(ButtonAuxUpperCenter6,ButtonGroup), ID_ENTRY(ButtonAuxUpperCenter5,ButtonGroup), ID_ENTRY(ButtonAuxUpperCenter4,ButtonGroup), ID_ENTRY(ButtonAuxUpperCenter3,ButtonGroup), ID_ENTRY(ButtonAuxUpperCenter2,ButtonGroup), ID_ENTRY(ButtonAuxUpperCenter1,ButtonGroup), //----------------------------------------------- // Upper right auxiliary //----------------------------------------------- ID_ENTRY(ButtonAuxUpperRight8,ButtonGroup), ID_ENTRY(ButtonAuxUpperRight7,ButtonGroup), ID_ENTRY(ButtonAuxUpperRight6,ButtonGroup), ID_ENTRY(ButtonAuxUpperRight5,ButtonGroup), ID_ENTRY(ButtonAuxUpperRight4,ButtonGroup), ID_ENTRY(ButtonAuxUpperRight3,ButtonGroup), ID_ENTRY(ButtonAuxUpperRight2,ButtonGroup), ID_ENTRY(ButtonAuxUpperRight1,ButtonGroup), //----------------------------------------------- // Lower left auxiliary //----------------------------------------------- ID_ENTRY(ButtonAuxLowerLeft8,ButtonGroup), ID_ENTRY(ButtonAuxLowerLeft7,ButtonGroup), ID_ENTRY(ButtonAuxLowerLeft6,ButtonGroup), ID_ENTRY(ButtonAuxLowerLeft5,ButtonGroup), ID_ENTRY(ButtonAuxLowerLeft4,ButtonGroup), ID_ENTRY(ButtonAuxLowerLeft3,ButtonGroup), ID_ENTRY(ButtonAuxLowerLeft2,ButtonGroup), ID_ENTRY(ButtonAuxLowerLeft1,ButtonGroup), //----------------------------------------------- // Lower right auxiliary //----------------------------------------------- ID_ENTRY(ButtonAuxLowerRight8,ButtonGroup), ID_ENTRY(ButtonAuxLowerRight7,ButtonGroup), ID_ENTRY(ButtonAuxLowerRight6,ButtonGroup), ID_ENTRY(ButtonAuxLowerRight5,ButtonGroup), ID_ENTRY(ButtonAuxLowerRight4,ButtonGroup), ID_ENTRY(ButtonAuxLowerRight3,ButtonGroup), ID_ENTRY(ButtonAuxLowerRight2,ButtonGroup), ID_ENTRY(ButtonAuxLowerRight1,ButtonGroup), //----------------------------------------------- // Miscellaneous buttons //----------------------------------------------- ID_ENTRY(ButtonPanic,ButtonGroup), ID_ENTRY(ButtonDoor,ButtonGroup) }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // int LBE4ControlsManager::SetControlMappingID( const char *control_name, ControlsMapping *mapping ) { Check_Pointer(control_name); Check_Pointer(mapping); int i; for (i=0; icontrolsGroup = Control_IDs[i].controlsGroup; mapping->controlsElement = Control_IDs[i].controlsElement; break; } } Check_Fpu(); return i < ELEMENTS(Control_IDs); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Lamp * LBE4ControlsManager::MakeLinkedLamp( int element, ModeMask mode_mask ) { Check(this); Check(application); if (application->GetGaugeRenderer() == NULL) { return NULL; } else { Check(application->GetGaugeRenderer()); //------------------------------------------ // Create the lamp //------------------------------------------ L4LampManager *lamp_manager = (L4LampManager *) application-> GetGaugeRenderer()->GetLampManager(); Check(lamp_manager); Lamp *lamp = new L4Lamp( element, mode_mask, lamp_manager ); Register_Object(lamp); //------------------------------------------ // Add button mapping to lamp //------------------------------------------ buttonGroup[element].Add( mode_mask, &((L4Lamp *)lamp)->automaticValue, lamp ); Check_Fpu(); return lamp; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void LBE4ControlsManager::CreateStreamedMappings( Entity *player, const int *control_mappings ) { Check(this); Check_Pointer(control_mappings); int controls_count = *control_mappings; ++control_mappings; ControlsMapping *mapping = (ControlsMapping*)control_mappings; Simulation *subsystem; void *attribute; for (int i=0; iGetSimulation(mapping->subsystemID); Verify(subsystem); // //--------------------------- // Handle the direct mappings //--------------------------- // int element = mapping->controlsElement; ModeMask mode_mask = mapping->modeMask; if (mapping->mappingType == ControlsMapping::DirectMapping) { attribute = subsystem->GetAttributePointer(mapping->attributeID); switch (mapping->controlsGroup) { case ScalarGroup: scalarGroup[element].Add( mode_mask, (ControlsScalar*)attribute, subsystem ); break; case JoystickGroup: joystickGroup[element].Add( mode_mask, (ControlsJoystick*)attribute, subsystem ); break; case ButtonGroup: //---------------------------------------------- // Add button //---------------------------------------------- buttonGroup[element].Add( mode_mask, (ControlsButton*)attribute, subsystem ); //---------------------------------------------- // Create associated lamp //---------------------------------------------- if(buttonType[element] == AUTOBTN) { # if DEBUG_LEVEL > 0 Lamp * lamp = # endif MakeLinkedLamp(element, mode_mask); # if DEBUG_LEVEL > 0 if (lamp != NULL) { Check(lamp); } # endif } break; default: Fail("Unknown mapping group!\n"); break; } } // //-------------------------------------------------- // Otherwise, it is an event mapping, so set that up //-------------------------------------------------- // else if (mapping->mappingType == ControlsMapping::EventMapping) { Receiver::MessageID msg_id = mapping->messageID; switch (mapping->controlsGroup) { case ScalarGroup: scalarGroup[element].Add(mode_mask,subsystem,msg_id,subsystem); break; case JoystickGroup: joystickGroup[element].Add(mode_mask,subsystem,msg_id,subsystem); break; case ButtonGroup: //---------------------------------------------- // Add button //---------------------------------------------- buttonGroup[element].Add( mode_mask, subsystem, msg_id, subsystem ); //---------------------------------------------- // Create associated lamp //---------------------------------------------- if(buttonType[element] == AUTOBTN) { # if DEBUG_LEVEL > 0 Lamp * lamp = # endif MakeLinkedLamp(element, mode_mask); # if DEBUG_LEVEL > 0 if (lamp != NULL) { Check(lamp); } # endif } break; default: Fail("Unknown mapping group!\n"); break; } } else { Fail("Unknown mapping type!\n"); } mapping = (ControlsMapping*)((char*)mapping + sizeof(ControlsMapping)); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void LBE4ControlsManager::EnterControlsMode( L4ControlsMode new_mode, Scalar time_until_exit, Receiver::MessageID message_on_exit ) { Check(this); l4ControlsMode = new_mode; exitModeTime = ((Scalar) Now()) + time_until_exit; exitMessageID = message_on_exit; SetLamp(LampPanic, RIO::flashFast+RIO::state1Off+RIO::state2Bright); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void LBE4ControlsManager::ExitControlsMode() { Check(this); l4ControlsMode = normalMode; int i; for(i=0; i= exitModeTime) { Receiver::Message message(exitMessageID, sizeof(Receiver__Message)); Dispatch(&message); } } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical LBE4ControlsManager::TestInstance() const { Verify(IsDerivedFrom(*GetClassDerivations())); return ControlsManager::TestInstance(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical LBE4ControlsManager::AnalogHasChanged() { Check(this); Logical result = False; if (rioPointer != NULL) { Check(rioPointer); result = (rioPointer->Throttle != previousThrottle); result |= (rioPointer->LeftPedal != previousPedalLeft); result |= (rioPointer->RightPedal != previousPedalRight); result |= (rioPointer->JoystickX != previousJoystickX); result |= (rioPointer->JoystickY != previousJoystickY); if (result) { previousThrottle = rioPointer->Throttle; previousPedalLeft = rioPointer->LeftPedal; previousPedalRight = rioPointer->RightPedal; previousJoystickX = rioPointer->JoystickX; previousJoystickY = rioPointer->JoystickY; } } Check_Fpu(); return result; } Logical LBE4ControlsManager::GetNextRIOEvent(RIO::RIOEvent *rio_event) { // //------------------------------------------------- // If we aren't in playback mode, read the real RIO //------------------------------------------------- // if (!playbackMode) { Logical result = rioPointer->GetNextEvent(rio_event); //---------------------------------------------------------------------- // If the RIO stream exists, and a rio event was added, // store this event in the rioStream //---------------------------------------------------------------------- if (result && streamEnabled) { Check(rioStream); if (rioStream->GetBytesRemaining() >= sizeof(RIOStreamEvent)) { Check(rioStream); RIOStreamEvent *event = (RIOStreamEvent*)rioStream->GetPointer(); Check_Pointer(event); event->timeStamp.ticks = Now().ticks - streamStart.ticks; if (rio_event->Type == RIO::AnalogEvent) { if (AnalogHasChanged()) { DEBUG_STREAM << "AnalogEvent at" << event->timeStamp.ticks << "\n"; DEBUG_STREAM << "Pointer=" << std::hex << event << std::dec << "\n"; //---------------------------- // Set the event type //---------------------------- event->eventType = analog; //---------------------------- // Get the analog state //---------------------------- event->data.analog.throttle = rioPointer->Throttle; event->data.analog.pedalLeft = rioPointer->LeftPedal; event->data.analog.pedalRight = rioPointer->RightPedal; event->data.analog.joystickX = rioPointer->JoystickX; event->data.analog.joystickY = rioPointer->JoystickY; //---------------------------- // Save the event //---------------------------- rioStream->AdvancePointer(sizeof(RIOStreamEvent)); } } else { DEBUG_STREAM << "DigitalEvent at" << event->timeStamp.ticks << "\n"; DEBUG_STREAM << "Pointer=" << std::hex << event << std::dec << "\n"; //---------------------------- // Set the event type //---------------------------- event->eventType = digital; //---------------------------- // Save the event //---------------------------- event->data.rioEvent = *rio_event; rioStream->AdvancePointer(sizeof(RIOStreamEvent)); } } } return result; } // //---------------------------------------------------------------------- // Otherwise, we are in playback mode, so get the next record out of the // memory block //---------------------------------------------------------------------- // else if (streamEnabled) { Check(rioStream); if (rioStream->GetBytesRemaining() >= sizeof(RIOStreamEvent)) { RIOStreamEvent *event = (RIOStreamEvent*)rioStream->GetPointer(); Check_Pointer(event); Time now; now.ticks = Now().ticks - streamStart.ticks; if (event->timeStamp.ticks <= now.ticks) { DEBUG_STREAM << "Event timestamp=" << event->timeStamp.ticks << "\n"; switch(event->eventType) { case analog: DEBUG_STREAM << "AnalogEvent\n"; //---------------------------- // Send event type ONLY //---------------------------- rio_event->Type = RIO::AnalogEvent; //---------------------------- // Restore the analog state //---------------------------- rioPointer->Throttle = event->data.analog.throttle; rioPointer->LeftPedal = event->data.analog.pedalLeft; rioPointer->RightPedal = event->data.analog.pedalRight; rioPointer->JoystickX = event->data.analog.joystickX; rioPointer->JoystickY = event->data.analog.joystickY; break; case digital: DEBUG_STREAM << "DigitalEvent\n"; //---------------------------- // Send the entire event //---------------------------- *rio_event = event->data.rioEvent; break; } rioStream->AdvancePointer(sizeof(RIOStreamEvent)); return True; } } } return False; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void LBE4ControlsManager::ProcessRIOEvent( RIO::RIOEvent &rio_event, Logical *new_RIO_values ) { //-------------------------------------------------- // Get mode mask for updating //-------------------------------------------------- Check(application); Check(application->GetModeManager()); ModeMask mode_mask = application->GetModeManager()->GetModeMask(); ControlsButton temp; switch(rio_event.Type) { case RIO::ButtonPressedEvent: Verify(rio_event.Data.Unit >= 0); Verify(rio_event.Data.Unit < ButtonCount); temp = rio_event.Data.Unit + 1; Check(&buttonGroup[rio_event.Data.Unit]); buttonGroup[rio_event.Data.Unit].Update(&temp, mode_mask); //---------------------------------------- // Save 'pressed' mode mask for 'release' //---------------------------------------- buttonActivateModeMask[rio_event.Data.Unit] = mode_mask; break; case RIO::ButtonReleasedEvent: Verify(rio_event.Data.Unit >= 0); Verify(rio_event.Data.Unit < ButtonCount); temp = -rio_event.Data.Unit - 1; Check(&buttonGroup[rio_event.Data.Unit]); //---------------------------------------- // Use 'pressed' mode mask for 'release' //---------------------------------------- buttonGroup[rio_event.Data.Unit].Update( &temp, buttonActivateModeMask[rio_event.Data.Unit] ); break; case RIO::KeyEvent: { Verify(rio_event.Data.Keyboard.Unit >= 0); Verify(rio_event.Data.Keyboard.Unit < KeyboardCount); //-------------------------------------- // Convert key to ASCII //-------------------------------------- ControlsKey new_key = rio_event.Data.Keyboard.Key; if (new_key <= 9) { new_key += '0'; } else { new_key += 'A'-10; } Test_Tell( "LBE4ControlsManager::Execute, new_key=" << (int) new_key << "\n" ); Check(&keyboardGroup[rio_event.Data.Keyboard.Unit]); keyboardGroup[rio_event.Data.Keyboard.Unit]. ForceUpdate(&new_key, mode_mask); Check(&stringManager); stringManager.Update( rio_event.Data.Keyboard.Unit, new_key ); } break; case RIO::AnalogEvent: lastRioRequest = 0L; // force another RIO update request *new_RIO_values = True; break; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void LBE4ControlsManager::SaveRecording(const char* file_name) { Check(this); Check_Pointer(file_name); Check(rioStream); FileStream output(file_name, True); size_t length = rioStream->GetBytesUsed(); if (length) { rioStream->Rewind(); output << length; output << *rioStream; } } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void LBE4ControlsManager::LoadPlayback(const char* file_name) { Check(this); Check_Pointer(file_name); FileStream input(file_name); Verify(input.IsFileOpened()); // //------------------------------- // Figure out how big the file is //------------------------------- // size_t spool_size = 0; input >> spool_size; Verify(spool_size); Verify(spool_size <= RIO_SPOOL_SIZE * sizeof(RIOStreamEvent)); RIOStreamEvent *events = new RIOStreamEvent[RIO_SPOOL_SIZE]; Register_Pointer(events); Verify(rioStream == NULL); rioStream = new MemoryStream(events, spool_size); Register_Object(rioStream); input.ReadBytes(events, spool_size); } #if defined(TEST_CLASS) # include "l4ctrl.tcp" #endif