Archival snapshot of the Virtual World Entertainment Tesla cockpit software, 1994-1996: MUNGA engine and L4 pod layer source (Borland C++ 5.0), BT/RP game code, and game content (models, audio, maps, gauges, Division renderer data). Includes third-party libraries: Division dVS/DPL graphics, HMI SOS audio, WATTCP networking. Files are preserved byte-for-byte (.gitattributes disables all line-ending conversion). README.md documents the layout, target hardware, and toolchain. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2430 lines
60 KiB
C++
2430 lines
60 KiB
C++
//==========================================================================//
|
|
// File: controls.cc //
|
|
// Project: MUNGA Brick: Controls Manager //
|
|
// Contents: Interface specification for Controls //
|
|
//--------------------------------------------------------------------------//
|
|
// Date Who Modification //
|
|
// -------- --- ----------------------------------------------------------//
|
|
// 11/21/94 CPB Initial coding. //
|
|
//--------------------------------------------------------------------------//
|
|
// Copyright (C) 1994, Virtual World Entertainment, Inc. //
|
|
// All Rights reserved worldwide //
|
|
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL //
|
|
//==========================================================================//
|
|
|
|
#include <mungal4.hpp>
|
|
#pragma hdrstop
|
|
|
|
#if !defined(L4CTRL_HPP)
|
|
# include <l4ctrl.hpp>
|
|
#endif
|
|
|
|
#if !defined(L4KEYBD_HPP)
|
|
# include <l4keybd.hpp>
|
|
#endif
|
|
|
|
#if !defined(L4APP_HPP)
|
|
# include <l4app.hpp>
|
|
#endif
|
|
|
|
// #define LOCAL_TEST
|
|
|
|
#if defined(LOCAL_TEST)
|
|
# define Test_Tell(n) Tell(n << 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
|
|
|
|
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()
|
|
{
|
|
PC_Joystick_Mask = PCJ_Standard_Mask;
|
|
ExtendedValue.x = (Scalar) 0;
|
|
ExtendedValue.y = (Scalar) 0;
|
|
Check_Fpu();
|
|
}
|
|
|
|
OrdinaryJoystick::~OrdinaryJoystick()
|
|
{
|
|
Check_Fpu();
|
|
}
|
|
|
|
void OrdinaryJoystick::Update()
|
|
{
|
|
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()
|
|
{
|
|
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()
|
|
{
|
|
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();
|
|
}
|
|
|
|
ThrustMaster::ThrustMaster()
|
|
{
|
|
PC_Joystick_Mask = PCJ_TM_Mask;
|
|
ExtendedValue.x = (Scalar) 0;
|
|
ExtendedValue.y = (Scalar) 0;
|
|
hatMax = 0;
|
|
prevHatState = 0;
|
|
Check_Fpu();
|
|
}
|
|
|
|
ThrustMaster::~ThrustMaster()
|
|
{
|
|
Check_Fpu();
|
|
}
|
|
|
|
void ThrustMaster::Update()
|
|
{
|
|
int newButtons, changedButtons;
|
|
int hat;
|
|
|
|
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
|
|
//---------------------------------------------------
|
|
//
|
|
ButtonPressed = Joystick::NoButton;
|
|
ButtonReleased = Joystick::NoButton;
|
|
|
|
newButtons = (int) PC_Joystick_Buttons;
|
|
changedButtons = newButtons ^ oldButtons;
|
|
|
|
if (changedButtons)
|
|
{
|
|
if (changedButtons & PCJ_TM_Trigger)
|
|
{
|
|
if (newButtons & PCJ_TM_Trigger)
|
|
{
|
|
ButtonPressed |= Joystick::Trigger;
|
|
}
|
|
else
|
|
{
|
|
ButtonReleased |= Joystick::Trigger;
|
|
}
|
|
}
|
|
if (changedButtons & PCJ_TM_ThumbHigh)
|
|
{
|
|
if (newButtons & PCJ_TM_ThumbHigh)
|
|
{
|
|
ButtonPressed |= Joystick::Thumb3;
|
|
}
|
|
else
|
|
{
|
|
ButtonReleased |= Joystick::Thumb3;
|
|
}
|
|
}
|
|
if (changedButtons & PCJ_TM_ThumbMid)
|
|
{
|
|
if (newButtons & PCJ_TM_ThumbMid)
|
|
{
|
|
ButtonPressed |= Joystick::Thumb2;
|
|
}
|
|
else
|
|
{
|
|
ButtonReleased |= Joystick::Thumb2;
|
|
}
|
|
}
|
|
if (changedButtons & PCJ_TM_ThumbLow)
|
|
{
|
|
if (newButtons & PCJ_TM_ThumbLow)
|
|
{
|
|
ButtonPressed |= Joystick::Thumb1;
|
|
}
|
|
else
|
|
{
|
|
ButtonReleased |= Joystick::Thumb1;
|
|
}
|
|
}
|
|
oldButtons = newButtons;
|
|
}
|
|
//
|
|
//---------------------------------------------------
|
|
// Handle "hat" changes
|
|
//---------------------------------------------------
|
|
//
|
|
hat = PC_Joystick2_Raw_Y;
|
|
if (hatMax < hat) { hatMax = hat; }
|
|
if (hat > ((hatMax*7)>>3)) // Unpressed, near max.
|
|
{
|
|
newButtons = 0;
|
|
}
|
|
else if (hat > ((hatMax*5)>>3)) // HatLeft is about 3/4 max
|
|
{
|
|
newButtons = Joystick::HatLeft;
|
|
}
|
|
else if (hat > ((hatMax*3)>>3)) // HatDown is about 1/2 max
|
|
{
|
|
newButtons = Joystick::HatDown;
|
|
}
|
|
else if (hat > (hatMax>>3)) // HatRight is about 1/4 max
|
|
{
|
|
newButtons = Joystick::HatRight;
|
|
}
|
|
else // Must be hatUp (near zero)
|
|
{
|
|
newButtons = Joystick::HatUp;
|
|
}
|
|
if (newButtons != prevHatState)
|
|
{
|
|
ButtonReleased |= prevHatState;
|
|
ButtonPressed |= newButtons;
|
|
prevHatState = newButtons;
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
|
|
//#########################################################################
|
|
//########################## LBE4ControlsManager ##########################
|
|
//#########################################################################
|
|
|
|
//---------------------------------------------------------------------------
|
|
// Class derivation
|
|
//---------------------------------------------------------------------------
|
|
Derivation
|
|
LBE4ControlsManager::ClassDerivations(
|
|
ControlsManager::ClassDerivations,"L4ControlsManager");
|
|
|
|
//---------------------------------------------------------------------------
|
|
// 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::ClassDerivations,
|
|
LBE4ControlsManager::MessageHandlers
|
|
);
|
|
//
|
|
//############################################################################
|
|
// 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 = 0L;
|
|
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');
|
|
}
|
|
|
|
if (
|
|
(strcmpi(temp, "RIO") == 0)||
|
|
(strcmpi(temp, "RIO:COM1") == 0)
|
|
)
|
|
{
|
|
rioPointer = new RIO(RIO_COM1);
|
|
Check(rioPointer);
|
|
Register_Object(rioPointer);
|
|
flags.RIOExists = 1;
|
|
primaryControlType = LBE4ControlsManager::PrimaryRIO;
|
|
}
|
|
else if (strcmpi(temp, "RIO:COM2") == 0)
|
|
{
|
|
rioPointer = new RIO(RIO_COM2);
|
|
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 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();
|
|
Register_Object(joystickPointer);
|
|
primaryControlType = LBE4ControlsManager::PrimaryThrustMaster;
|
|
}
|
|
}
|
|
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; i<ScalarCount; ++i)
|
|
{
|
|
scalarGroup[i].ForceUpdate(&initial_scalar, mode_mask);
|
|
}
|
|
}
|
|
//--------------------------------------------------
|
|
// Initialize joystick group
|
|
//--------------------------------------------------
|
|
{
|
|
int
|
|
i;
|
|
ControlsJoystick
|
|
initial_stick;
|
|
|
|
initial_stick.x = 0.0;
|
|
initial_stick.y = 0.0;
|
|
|
|
for(i=0; i<JoystickCount; ++i)
|
|
{
|
|
joystickGroup[i].ForceUpdate(&initial_stick, mode_mask);
|
|
}
|
|
}
|
|
//--------------------------------------------------
|
|
// Initialize keyboard group
|
|
//--------------------------------------------------
|
|
{
|
|
int
|
|
i;
|
|
ControlsKey
|
|
initial_key = 0;
|
|
|
|
for(i=0; i<KeyboardCount; ++i)
|
|
{
|
|
keyboardGroup[i].ForceUpdate(&initial_key, mode_mask);
|
|
}
|
|
}
|
|
//--------------------------------------------------
|
|
// Initialize button control groups
|
|
//--------------------------------------------------
|
|
{
|
|
int
|
|
i;
|
|
ControlsButton
|
|
initial_button_value = 0;
|
|
|
|
for(i=0; i<ButtonCount; ++i)
|
|
{
|
|
buttonGroup[i].ForceUpdate(&initial_button_value, mode_mask);
|
|
buttonActivateModeMask[i] = mode_mask;
|
|
}
|
|
}
|
|
|
|
//--------------------------------------------------
|
|
// Initialize control mode
|
|
//--------------------------------------------------
|
|
l4ControlsMode = normalMode;
|
|
{
|
|
int i;
|
|
|
|
for(i=0; i<maxStringIDs; ++i)
|
|
{
|
|
temporaryStringID[i] = 0;
|
|
}
|
|
}
|
|
|
|
|
|
// stringManager.Add("A90", KeyboardPilot, this, BeginCalibrationMessageID, 0);
|
|
|
|
//
|
|
//-----------------------------------------
|
|
// Initialize the RIO stream spoofing stuff
|
|
//-----------------------------------------
|
|
//
|
|
rioStream = NULL;
|
|
streamStart = Now();
|
|
playbackMode = False;
|
|
streamEnabled = False;
|
|
|
|
previousJoystickX = (Scalar) 0;
|
|
previousJoystickY = (Scalar) 0;
|
|
previousThrottle = (Scalar) 0;
|
|
previousPedalLeft = (Scalar) 0;
|
|
previousPedalRight = (Scalar) 0;
|
|
//
|
|
//-------------------------------------
|
|
// See if we need to load in a RIO file
|
|
//-------------------------------------
|
|
//
|
|
CString
|
|
playback = L4Application::GetRIOPlaybackFileName();
|
|
if (playback && strlen(playback))
|
|
{
|
|
if (!flags.RIOExists)
|
|
{
|
|
DEBUG_STREAM << "RIO must be enabled by setenv!\n";
|
|
Exit(1);
|
|
}
|
|
LoadPlayback(playback);
|
|
playbackMode = True;
|
|
}
|
|
|
|
CString
|
|
record = L4Application::GetRIORecordingFileName();
|
|
if (record && strlen(record))
|
|
{
|
|
if (!flags.RIOExists)
|
|
{
|
|
DEBUG_STREAM << "RIO must be enabled by setenv!\n";
|
|
Exit(1);
|
|
}
|
|
|
|
RIOStreamEvent
|
|
*events = new RIOStreamEvent[RIO_SPOOL_SIZE];
|
|
Register_Pointer(events);
|
|
|
|
Verify(rioStream == NULL);
|
|
rioStream =
|
|
new MemoryStream(events, RIO_SPOOL_SIZE * sizeof(RIOStreamEvent));
|
|
Register_Object(rioStream);
|
|
}
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//############################################################################
|
|
// ~LBE4ControlsManager
|
|
//
|
|
// Destructor method
|
|
//############################################################################
|
|
//
|
|
LBE4ControlsManager::~LBE4ControlsManager()
|
|
{
|
|
Check(this);
|
|
|
|
//
|
|
//----------------------------------------
|
|
// If we are recording, save the recording
|
|
//----------------------------------------
|
|
//
|
|
if (IsRecording())
|
|
{
|
|
CString
|
|
record = L4Application::GetRIORecordingFileName();
|
|
SaveRecording(record);
|
|
}
|
|
|
|
if (rioStream)
|
|
{
|
|
Check(rioStream);
|
|
rioStream->Rewind();
|
|
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<ScalarCount; ++i)
|
|
{
|
|
Check(&scalarGroup[i]);
|
|
scalarGroup[i].Remove(mode_mask);
|
|
}
|
|
|
|
for(i=0; i<JoystickCount; ++i)
|
|
{
|
|
Check(&joystickGroup[i]);
|
|
joystickGroup[i].Remove(mode_mask);
|
|
}
|
|
|
|
for(i=0; i<KeyboardCount; ++i)
|
|
{
|
|
Check(&keyboardGroup[i]);
|
|
keyboardGroup[i].Remove(mode_mask);
|
|
}
|
|
|
|
for(i=0; i<ButtonCount; ++i)
|
|
{
|
|
Check(&buttonGroup[i]);
|
|
buttonGroup[i].Remove(mode_mask);
|
|
}
|
|
|
|
Check(&mouseGroup[0]);
|
|
mouseGroup[0].Remove(mode_mask);
|
|
Check_Fpu();
|
|
}
|
|
|
|
//
|
|
//############################################################################
|
|
// SetLamp
|
|
//
|
|
// Sets a specific lamp to the designated state
|
|
//############################################################################
|
|
//
|
|
|
|
void
|
|
LBE4ControlsManager::SetLamp(
|
|
int lamp_number,
|
|
int state
|
|
)
|
|
{
|
|
if (rioPointer != NULL)
|
|
{
|
|
Check(rioPointer);
|
|
Verify(lamp_number >= 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;
|
|
Logical new_RIO_values(False);
|
|
|
|
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;
|
|
|
|
if (application->GetApplicationState() == Application::RunningMission)
|
|
{
|
|
limit = 15.0; // 0.2
|
|
}
|
|
else
|
|
{
|
|
limit = 15.0;
|
|
}
|
|
|
|
if (first_time)
|
|
{
|
|
first_time = False;
|
|
}
|
|
else
|
|
{
|
|
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";
|
|
|
|
extern Logical
|
|
iThinkIRQIsOn;
|
|
|
|
extern int
|
|
pcspakCharactersSent;
|
|
|
|
|
|
DEBUG_STREAM <<
|
|
"iThinkIRQIsOn =" << iThinkIRQIsOn <<
|
|
", actual state =" << PCSPAKIRQState() <<
|
|
", characters sent =" << pcspakCharactersSent << "\n";
|
|
}
|
|
|
|
rioPointer->RequestAnalogUpdate();
|
|
lastRioRequest = Now();
|
|
}
|
|
//-------------------------
|
|
// 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(((long)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);
|
|
mousePointer->ReadCounters(&mouseValue.x, &mouseValue.y);
|
|
|
|
virtualJoystickX += mouseValue.x;
|
|
virtualJoystickY += mouseValue.y;
|
|
|
|
|
|
# define MAXEXTENT 2048 // 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;
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// 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)
|
|
{
|
|
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)
|
|
{
|
|
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
|
|
);
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// 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)
|
|
{
|
|
Check(&joystickGroup[LBE4ControlsManager::JoystickVirtual]);
|
|
joystickGroup[LBE4ControlsManager::JoystickVirtual].Update(
|
|
&virtual_joystick, mode_mask
|
|
);
|
|
}
|
|
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
// Update the PC keyboard mapping group
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
if (flags.keyboardExists)
|
|
{
|
|
keyValue = (ControlsKey) PC_Keyboard_Read();
|
|
if (keyValue)
|
|
{
|
|
Check(&keyboardGroup[KeyboardPC]);
|
|
keyboardGroup[KeyboardPC].ForceUpdate(&keyValue, mode_mask);
|
|
|
|
Check(&stringManager);
|
|
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::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::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;
|
|
i<k;
|
|
++i,++j
|
|
)
|
|
{
|
|
if (mousePointer->ButtonPressed(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" << 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; i<ELEMENTS(Control_IDs); ++i)
|
|
{
|
|
if (!stricmp(control_name, Control_IDs[i].controlName))
|
|
{
|
|
mapping->controlsGroup = 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; i<controls_count; ++i)
|
|
{
|
|
subsystem = player->GetSimulation(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<maxStringIDs; ++i)
|
|
{
|
|
if (temporaryStringID[i] != 0)
|
|
{
|
|
stringManager.Remove(temporaryStringID[i]);
|
|
}
|
|
}
|
|
|
|
SetLamp(LampPanic, RIO::solid+RIO::state1Off+RIO::state2Off);
|
|
Verify(heapcheck() != _HEAPCORRUPT);
|
|
}
|
|
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
void
|
|
LBE4ControlsManager::ManageControlsMode()
|
|
{
|
|
Check(this);
|
|
|
|
if (l4ControlsMode != normalMode)
|
|
{
|
|
if (Now() >= exitModeTime)
|
|
{
|
|
Receiver::Message
|
|
message(exitMessageID, sizeof(Receiver__Message));
|
|
|
|
Dispatch(&message);
|
|
}
|
|
}
|
|
}
|
|
|
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
//
|
|
Logical
|
|
LBE4ControlsManager::TestInstance() const
|
|
{
|
|
Verify(IsDerivedFrom(ClassDerivations));
|
|
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=" << hex << event << 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=" << hex << event << 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
|
|
|