Files
RP412/RP_L4/RPL4MPPR.cpp
T
CydandClaude Opus 5 05f993b9aa Picking a preset no longer blinds the mode lamps
The six PRESET switches down the map's right flank stored their lamps in
modeLamp[], which holds four. Indices 4 and 5 ran off the end into
presetLamp[0..1], so the whole thing stayed self-consistent by memory
layout and nobody noticed - but it overwrote the four control-mode lamps
made moments earlier, and BASIC/STANDARD/VETERAN/MASTER on the upper-right
MFD were never lit again. presetLamp[], meanwhile, went unused.

The preset pass now fills the array it was always meant to, and the lamp
work moves out of the switch handler into a virtual NotifyOfPresetChange
that PresetEnable announces itself. That closes the second gap in passing:
keyboard 1-6 changed the mappings without touching the lamps, leaving the
flank showing a preset that was no longer in force. Both routes now go
through one place. The lamp arrays are also cleared in the constructor -
only the mapping loops ever filled them, and NOMODES skips those.

Verified by dumping the commanded RIO lamp states out of the running game
(PadRIO, TEST.EGG, at rest in Basic mode). Before and after are identical
except lamp 0x33, BASIC, which goes from 14 dim to 3c lit. The preset
lamps are unchanged: they worked by accident, and now work by
construction.

docs/CONTROL-PRESETS.md is the research behind it. The presets are not a
map feature at all - each is a complete factory layout for the four
mappable stick buttons, one mode-mask bit apiece, with all 26 vehicles
carrying their own six-preset table in RPL4.RES for both the pod RIO and
the Thrustmaster.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-06 11:43:02 -05:00

2098 lines
49 KiB
C++

#include "rpl4.h"
#pragma hdrstop
#include "..\rp\chute.h"
#include "rpl4mppr.h"
#include "rpl4grnd.h"
#include "rpl4app.h"
#include "rpl4mode.h"
#include "..\munga_l4\l4ctrl.h"
#include "..\munga_l4\l4keybd.h"
#include "..\rp\booster.h"
#include "..\rp\vtv.h"
#include "..\munga\appmsg.h"
L4Lamp *
CreateControlledLamp(
int lamp_number,
ModeMask mode_mask=RPL4ModeManager::ModeAlwaysActive
)
{
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);
L4Lamp
*lamp = new L4Lamp(
lamp_number,
mode_mask,
lamp_manager
);
Register_Object(lamp);
lamp->SetAutomaticOperation(False);
Check_Fpu();
return lamp;
}
}
//-----------------------------------------------------------------------
void
MakeButtonLampEvent(
LBE4ControlsManager *controls,
int button_number,
Receiver *receiver,
Receiver::MessageID message_id,
Plug *dependant,
ModeMask mode_mask = RPL4ModeManager::ModeAlwaysActive
)
{
Check(controls);
Check(receiver);
Check(dependant);
controls->buttonGroup[button_number].Add(
mode_mask,
receiver,
message_id,
dependant
);
controls->MakeLinkedLamp(button_number, mode_mask);
}
void
MakeButtonLampEventPair(
LBE4ControlsManager *controls,
int button_number1,
int button_number2,
Receiver *receiver,
Receiver::MessageID message_id,
Plug *dependant,
ModeMask mode_mask = RPL4ModeManager::ModeAlwaysActive
)
{
MakeButtonLampEvent(
controls,
button_number1,
receiver,
message_id,
dependant,
mode_mask
);
MakeButtonLampEvent(
controls,
button_number2,
receiver,
message_id,
dependant,
mode_mask
);
}
//-----------------------------------------------------------------------
void
MakeButtonLampDirect(
LBE4ControlsManager *controls,
int button_number,
ControlsButton *direct_target,
Plug *dependent,
ModeMask mode_mask = RPL4ModeManager::ModeAlwaysActive
)
{
Check(controls);
controls->buttonGroup[button_number].Add(
mode_mask,
direct_target,
dependent
);
controls->MakeLinkedLamp(button_number, mode_mask);
}
void
MakeButtonLampDirectPair(
LBE4ControlsManager *controls,
int button_number1,
int button_number2,
ControlsButton *direct_target,
Plug *dependent,
ModeMask mode_mask = RPL4ModeManager::ModeAlwaysActive
)
{
MakeButtonLampDirect(
controls,
button_number1,
direct_target,
dependent,
mode_mask
);
MakeButtonLampDirect(
controls,
button_number2,
direct_target,
dependent,
mode_mask
);
}
//-----------------------------------------------------------------------
void
CreateDirectSystemMapping(
LBE4ControlsManager *controls,
int button_number,
ControlsButton *direct_target,
Receiver *receiver,
Receiver::MessageID configure_message_id
)
{
Check(controls);
Check(receiver);
//-------------------------------------------------
// When not configuring, press button to activate
//-------------------------------------------------
MakeButtonLampDirect(
controls,
button_number,
direct_target,
receiver,
RPL4ModeManager::ModeNonConfig
);
//-------------------------------------------------
// When configuring, the same button allows mapping
//-------------------------------------------------
MakeButtonLampEvent(
controls,
button_number,
receiver,
configure_message_id,
receiver,
RPL4ModeManager::ModeConfigReady
);
}
void
CreateDirectSystemMappingPair(
LBE4ControlsManager *controls,
int button_number1,
int button_number2,
ControlsButton *direct_target,
Receiver *receiver,
Receiver::MessageID configure_message_id
)
{
Check(controls);
Check(receiver);
CreateDirectSystemMapping(
controls,
button_number1,
direct_target,
receiver,
configure_message_id
);
CreateDirectSystemMapping(
controls,
button_number2,
direct_target,
receiver,
configure_message_id
);
}
//-----------------------------------------------------------------------
void
CreateEventSystemMapping(
LBE4ControlsManager *controls,
int button_number,
Receiver *receiver,
Receiver::MessageID active_message_id,
Receiver::MessageID configure_message_id
)
{
Check(controls);
Check(receiver);
//-------------------------------------------------
// When not configuring, press button to activate
//-------------------------------------------------
MakeButtonLampEvent(
controls,
button_number,
receiver,
active_message_id,
receiver,
RPL4ModeManager::ModeNonConfig
);
//-------------------------------------------------
// When configuring, the same button allows mapping
//-------------------------------------------------
MakeButtonLampEvent(
controls,
button_number,
receiver,
configure_message_id,
receiver,
RPL4ModeManager::ModeConfigReady
);
}
void
CreateEventSystemMappingPair(
LBE4ControlsManager *controls,
int button_number1,
int button_number2,
Receiver *receiver,
Receiver::MessageID active_message_id,
Receiver::MessageID configure_message_id
)
{
CreateEventSystemMapping(
controls,
button_number1,
receiver,
active_message_id,
configure_message_id
);
CreateEventSystemMapping(
controls,
button_number2,
receiver,
active_message_id,
configure_message_id
);
}
//#############################################################################
//########################### L4VTVControlsMapper ##############################
//#############################################################################
//#############################################################################
// Shared Data Support
//
L4VTVControlsMapper::SharedData
L4VTVControlsMapper::DefaultData(
L4VTVControlsMapper::GetClassDerivations(),
L4VTVControlsMapper::GetMessageHandlers(),
L4VTVControlsMapper::GetAttributeIndex(),
L4VTVControlsMapper::StateCount
);
Derivation* L4VTVControlsMapper::GetClassDerivations()
{ static Derivation classDerivations(VTVControlsMapper::GetClassDerivations(), "L4VTVControlsMapper");
return &classDerivations;
}
//#############################################################################
// Messaging Support
//
const Receiver::HandlerEntry
L4VTVControlsMapper::MessageHandlerEntries[]=
{
MESSAGE_ENTRY(L4VTVControlsMapper, Keypress)
};
Receiver::MessageHandlerSet& L4VTVControlsMapper::GetMessageHandlers()
{
static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(L4VTVControlsMapper::MessageHandlerEntries), L4VTVControlsMapper::MessageHandlerEntries, VTVControlsMapper::GetMessageHandlers());
return messageHandlers;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
L4VTVControlsMapper::KeypressMessageHandler(
ReceiverDataMessageOf<ControlsKey> *message
)
{
Check(this);
Check(message);
switch (message->dataContents)
{
case PCK_F11:
{
Check(application);
GaugeRenderer
*renderer = application->GetGaugeRenderer();
if (renderer != NULL)
{
Check(renderer);
renderer->ProfileReport();
}
}
break;
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
L4VTVControlsMapper::SetControlsMode(int new_mode)
{
Check(this);
//-------------------------------------------
// Get mode manager
//-------------------------------------------
Check(application);
RPL4ModeManager
*mode_manager = Cast_Object(
RPL4ModeManager*,
application->GetModeManager()
);
Check(mode_manager);
int
previous_mode = controlMode;
//-------------------------------------------
// Change modes
//-------------------------------------------
switch (new_mode)
{
case BasicMode:
//--------------------------------------
// If we aren't already in basic mode,
// switch us there
//--------------------------------------
if (controlMode != BasicMode)
{
controlMode = BasicMode;
mode_manager->AddModeMask(RPL4ModeManager::ModeBasic);
mode_manager->RemoveModeMask(RPL4ModeManager::ModeStandard);
//----------------------------------------
// Ensure configuring is turned off
//----------------------------------------
if (GetSimulationState() == ConfigurationState)
{
mode_manager->AddModeMask(RPL4ModeManager::ModeNonConfig);
mode_manager->RemoveModeMask(RPL4ModeManager::ModeConfiguring);
SetSimulationState(DefaultState);
}
}
break;
case StandardMode:
//---------------------------------------
// If we aren't already in standard mode,
// switch us there
//---------------------------------------
if (controlMode != StandardMode)
{
controlMode = StandardMode;
mode_manager->AddModeMask(RPL4ModeManager::ModeStandard);
mode_manager->RemoveModeMask(RPL4ModeManager::ModeBasic);
}
break;
case VeteranMode:
//---------------------------------------
// If we aren't already in veteran mode,
// switch us there
//---------------------------------------
if (controlMode != VeteranMode)
{
controlMode = VeteranMode;
mode_manager->AddModeMask(RPL4ModeManager::ModeStandard);
mode_manager->RemoveModeMask(RPL4ModeManager::ModeBasic);
}
break;
case MasterMode:
//---------------------------------------
// If we aren't already in master mode,
// switch us there
//---------------------------------------
if (controlMode != MasterMode)
{
controlMode = MasterMode;
mode_manager->AddModeMask(RPL4ModeManager::ModeStandard);
mode_manager->RemoveModeMask(RPL4ModeManager::ModeBasic);
}
break;
default:
Tell(
"L4VTVControlsMapper::SetControlsMode(" << new_mode <<
")\n"
);
Fail("out of range");
break;
}
//----------------------------------------
// Notify of mode change
//----------------------------------------
if (previous_mode != controlMode)
{
L4VTVControlsMapper::NotifyOfControlModeChange(controlMode);
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
L4VTVControlsMapper::SetConfigurationMode(Logical new_state)
{
Check(this);
//-------------------------------------------
// Call ancestral method
//-------------------------------------------
VTVControlsMapper::SetConfigurationState(new_state);
//-------------------------------------------
// Get mode manager
//-------------------------------------------
Check(application);
RPL4ModeManager
*mode_manager = Cast_Object(
RPL4ModeManager*,
application->GetModeManager()
);
Check(mode_manager);
//-------------------------------------------
// Modify mode
//-------------------------------------------
if (GetSimulationState() == ConfigurationState)
{
mode_manager->RemoveModeMask(RPL4ModeManager::ModeAllNonConfig);
// Note: this removes ALL presets as well
mode_manager->AddModeMask(RPL4ModeManager::ModeConfigReady);
}
else
{
mode_manager->RemoveModeMask(RPL4ModeManager::ModeConfigReady);
mode_manager->AddModeMask(RPL4ModeManager::ModeNonConfig);
mode_manager->AddModeMask(previousPresetModeMask);
}
Check_Fpu();
}
//#############################################################################
// Platform-specific updates
//
void
L4VTVControlsMapper::NotifyOfControlModeChange(int new_mode)
{
Check(this);
// The gauges are controlled directly by modes, so we do nothing here.
//-----------------------------------
// Invoke ancestral method
//-----------------------------------
VTVControlsMapper::NotifyOfControlModeChange(new_mode);
Check_Fpu();
}
void
L4VTVControlsMapper::NotifyOfConfigurationModeChange(Logical new_state)
{
Check(this);
// The gauges are controlled directly by modes, so we do nothing here.
//-----------------------------------
// Invoke ancestral method
//-----------------------------------
VTVControlsMapper::NotifyOfConfigurationModeChange(new_state);
Check_Fpu();
}
//#############################################################################
// Construction and Destruction Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
L4VTVControlsMapper::L4VTVControlsMapper(
VTV *player_vehicle,
int subsystem_ID,
SubsystemResource *subsystem_resource,
SharedData &shared_data
):
VTVControlsMapper(
player_vehicle,
subsystem_ID,
subsystem_resource,
shared_data
)
{
Check(application);
RPL4ModeManager
*mode_manager = Cast_Object(
RPL4ModeManager*,
application->GetModeManager()
);
Check(mode_manager);
//------------------------------------------
// Initialize presets
//------------------------------------------
previousPresetModeMask = RPL4ModeManager::ModePreset1;
previousPresetNumber = 0;
mode_manager->AddModeMask(previousPresetModeMask);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
L4VTVControlsMapper::~L4VTVControlsMapper()
{
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
L4VTVControlsMapper::TestInstance() const
{
return IsDerivedFrom(*GetClassDerivations());
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
L4VTVControlsMapper::CreateTemporaryEventMappings(
Receiver *receiver,
Receiver::MessageID config_message_id
)
{
Check(this);
Check(receiver);
Check(application);
LBE4ControlsManager
*controls_mgr = Cast_Object(
LBE4ControlsManager *,
application->GetControlsManager()
);
Check(controls_mgr);
//------------------------------------------------
// Create temporary mappings for configuration
//------------------------------------------------
for(
int i=LBE4ControlsManager::FirstMappableButton;
i<=LBE4ControlsManager::LastMappableButton;
++i
)
{
//---------------------------------
// Skip past hat switches
//---------------------------------
if (i == LBE4ControlsManager::ButtonJoystickHatDown)
{
i = LBE4ControlsManager::ButtonJoystickPinky;
}
controls_mgr->buttonGroup[i].Add(
RPL4ModeManager::ModeConfigReady,
receiver,
config_message_id,
receiver
);
}
Check_Fpu();
}
void
L4VTVControlsMapper::RemoveTemporaryEventMappings()
{
Check(this);
Check(application);
LBE4ControlsManager
*controls_mgr = Cast_Object(
LBE4ControlsManager *,
application->GetControlsManager()
);
Check(controls_mgr);
//------------------------------------------------
// Remove temporary mappings
//------------------------------------------------
for(
int i=LBE4ControlsManager::FirstMappableButton;
i<=LBE4ControlsManager::LastMappableButton;
++i
)
{
//---------------------------------
// Skip past hat switches
//---------------------------------
if (i == LBE4ControlsManager::ButtonJoystickHatDown)
{
i = LBE4ControlsManager::ButtonJoystickPinky;
}
controls_mgr->buttonGroup[i].Remove(RPL4ModeManager::ModeConfigReady);
}
Check_Fpu();
}
void
L4VTVControlsMapper::AddOrErase(
unsigned int /*button_ID*/,
Receiver */*target*/,
Receiver::MessageID /*message_ID*/
)
{
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
L4VTVControlsMapper::AddOrErase(
unsigned int /*button_ID*/,
ControlsButton */*destination*/
)
{
Check_Fpu();
}
void
L4VTVControlsMapper::PresetEnable(int preset_number)
{
Check(this);
static ModeMask
mode_table[presetCount] =
{
RPL4ModeManager::ModePreset1,
RPL4ModeManager::ModePreset2,
RPL4ModeManager::ModePreset3,
RPL4ModeManager::ModePreset4,
RPL4ModeManager::ModePreset5,
RPL4ModeManager::ModePreset6
};
mustMatch = preset_number; // HACK - for backward watcher compatibility
if (preset_number != previousPresetNumber)
{
Check(application);
RPL4ModeManager
*mode_manager = Cast_Object(
RPL4ModeManager*,
application->GetModeManager()
);
Check(mode_manager);
//-----------------------------------
// Disable the old presets
//-----------------------------------
mode_manager->RemoveModeMask(previousPresetModeMask);
//-----------------------------------
// Enable the new presets
//-----------------------------------
if (preset_number >= 0)
{
Verify(preset_number < presetCount);
previousPresetModeMask = mode_table[preset_number];
mode_manager->AddModeMask(previousPresetModeMask);
}
//-----------------------------------
// Move the lamps with the mappings.
// Doing it here rather than in the
// switch handler keeps the keyboard
// presets (1-6) in step as well.
//-----------------------------------
NotifyOfPresetChange(previousPresetNumber, preset_number);
//-----------------------------------
// Save the new preset number
//-----------------------------------
previousPresetNumber = preset_number;
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
L4VTVControlsMapper::NotifyOfPresetChange(
int /*old_preset*/,
int /*new_preset*/
)
{
Check(this);
// The base mapper has no preset lamps to move.
Check_Fpu();
}
//#############################################################################
//########################### ThrustmasterMapper ##############################
//#############################################################################
//#############################################################################
// Shared Data Support
//
VTVThrustmasterMapper::SharedData
VTVThrustmasterMapper::DefaultData(
VTVThrustmasterMapper::GetClassDerivations(),
VTVThrustmasterMapper::MessageHandlers,
VTVThrustmasterMapper::GetAttributeIndex(),
VTVThrustmasterMapper::StateCount
);
Derivation* VTVThrustmasterMapper::GetClassDerivations()
{ static Derivation classDerivations(L4VTVControlsMapper::GetClassDerivations(), "VTVThrustmasterMapper");
return &classDerivations;
}
//#############################################################################
// Messaging Support
//
const Receiver::HandlerEntry
VTVThrustmasterMapper::MessageHandlerEntries[]=
{
MESSAGE_ENTRY(VTVThrustmasterMapper, Keypress)
};
Receiver::MessageHandlerSet
VTVThrustmasterMapper::MessageHandlers(
ELEMENTS(VTVThrustmasterMapper::MessageHandlerEntries),
VTVThrustmasterMapper::MessageHandlerEntries,
L4VTVControlsMapper::GetMessageHandlers()
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
VTVThrustmasterMapper::KeypressMessageHandler(
ReceiverDataMessageOf<ControlsKey> *message
)
{
Check(this);
Check(message);
LBE4ControlsManager
*controls =
Cast_Object(LBE4ControlsManager*,application->GetControlsManager());
Check(controls);
switch (message->dataContents)
{
//-------------------------------------------------------
// Joystick
//-------------------------------------------------------
case PCK_F1:
Tell("Aligning Joystick...\n");
controls->BeginAlignJoystick();
GetEntity()->SetSimulationState(VTV::StasisState);
break;
case PCK_F2:
Tell("Joystick Aligned...\n");
controls->EndAlignJoystick();
GetEntity()->SetSimulationState(VTV::DefaultState);
break;
case PCK_F12:
//-------------------------------------------------------
// Exit
//-------------------------------------------------------
Check(application);
if (
application->GetApplicationState() != Application::EndingMission
&& application->GetApplicationState() != Application::StoppingMission
)
{
DEBUG_STREAM << "Keystroke invoking mission stop...\n" << std::flush;
Exit_Code = 1;
Application::StopMissionMessage message(Exit_Code);
application->Dispatch(&message);
}
break;
//-------------------------------------------------------
// Control eyepoint views
//-------------------------------------------------------
case PCK_UP: // look forward
lookLeft = -1;
lookRight = -1;
lookBehind = -1;
lookUp = -1;
break;
case PCK_LEFT: // look left
lookLeft = 1;
lookRight = -1;
lookBehind = -1;
lookUp = -1;
break;
case PCK_RIGHT: // look right
lookLeft = -1;
lookRight = 1;
lookBehind = -1;
lookUp = -1;
break;
case PCK_DOWN: // look behind
lookLeft = -1;
lookRight = -1;
lookBehind = 1;
lookUp = -1;
break;
case PCK_CTL_UP: // look up
lookLeft = -1;
lookRight = -1;
lookBehind = -1;
lookUp = 1;
break;
//-------------------------------------------------------
// Set driving modes
//-------------------------------------------------------
case 'b':
case 'B': SetControlsMode(BasicMode); break;
case 's':
case 'S': SetControlsMode(StandardMode); break;
case 'v':
case 'V': SetControlsMode(VeteranMode); break;
case 'm':
case 'M': SetControlsMode(MasterMode); break;
//-------------------------------------------------------
// Configuration stuff
//-------------------------------------------------------
case 'c':
case 'C':
//------------------------------
// Not allowed in 'basic' mode
//------------------------------
if (controlMode != BasicMode)
{
static Logical
config_state = False;
//----------------------------
// Invert configuration state
//----------------------------
config_state ^= True;
//----------------------------
// Send message to base class
//----------------------------
SetConfigurationMode(config_state);
}
break;
//-------------------------------------------------------
// Map scale stuff
//-------------------------------------------------------
case '<':
case ',':
{
ReceiverDataMessageOf<ControlsButton>
config_msg(
VTV::ZoomInMessageID,
sizeof(ReceiverDataMessageOf<ControlsButton>),
1
);
GetEntity()->Dispatch(&config_msg);
break;
}
case '>':
case '.':
{
ReceiverDataMessageOf<ControlsButton>
config_msg(
VTV::ZoomOutMessageID,
sizeof(ReceiverDataMessageOf<ControlsButton>),
1
);
GetEntity()->Dispatch(&config_msg);
break;
}
case 'h':
case 'H':
//-------------------------------------------------------
// Horn blast
//-------------------------------------------------------
{
static ControlsButton horn_state=1;
ReceiverDataMessageOf<ControlsButton>
config_msg(
ActivateHornMessageID,
sizeof(ReceiverDataMessageOf<ControlsButton>),
horn_state
);
Dispatch(&config_msg);
horn_state = -horn_state;
break;
}
case 'z':
case 'Z':
//---------------------------------------------------------
// Chute
//---------------------------------------------------------
{
ReceiverDataMessageOf<ControlsButton>
config_msg(
Chute::ActivateMessageID,
sizeof(ReceiverDataMessageOf<ControlsButton>),
1
);
for (int i=0; i < GetEntity()->GetSubsystemCount(); i++)
{
Subsystem *sub = GetEntity()->GetSubsystem(i);
if (sub && sub->GetClassID() == VTV::ChuteClassID)
{
sub->Dispatch(&config_msg);
break;
}
}
break;
}
case 'w':
case 'W':
//---------------------------------------------------------
// Booster
//---------------------------------------------------------
{
ReceiverDataMessageOf<ControlsButton>
config_msg(
Booster::ActivateMessageID,
sizeof(ReceiverDataMessageOf<ControlsButton>),
1
);
for (int i=0; i < GetEntity()->GetSubsystemCount(); i++)
{
Subsystem *sub = GetEntity()->GetSubsystem(i);
if (sub && sub->GetClassID() == VTV::BoosterClassID)
{
sub->Dispatch(&config_msg);
break;
}
}
break;
}
case 'd':
case 'D':
//---------------------------------------------------------
// Demopack
//---------------------------------------------------------
{
/*for (int i=0; i < GetEntity()->GetSubsystemCount(); i++)
{
Subsystem *sub = GetEntity()->GetSubsystem(i);
if (sub && sub->GetClassID() == VTV::DemolitionPackDropperClassID)
{
((DemolitionPackDropper*)sub)->Fire();
break;
}
}*/
}
case 'r':
case 'R':
//-------------------------------------------------------
// Toggle reticle
//-------------------------------------------------------
{
ReceiverDataMessageOf<ControlsButton>
config_msg(
ToggleReticleMessageID,
sizeof(ReceiverDataMessageOf<ControlsButton>),
1
);
Dispatch(&config_msg);
break;
}
//-------------------------------------------------------
// Trigger presets
//-------------------------------------------------------
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
PresetEnable(message->dataContents - '1');
break;
//-------------------------------------------------------
// Suspend/resume
//-------------------------------------------------------
case '[':
{
Check(application);
Enumeration
state = application->GetApplicationState();
if (
state != Application::EndingMission &&
state != Application::StoppingMission &&
state != Application::SuspendingMission
)
{
DEBUG_STREAM << "Keystroke invoking mission suspend...\n" << std::flush;
Application::SuspendMissionMessage message;
application->Dispatch(&message);
}
}
break;
case ']':
Check(application);
if (
application->GetApplicationState() == Application::SuspendingMission
)
{
DEBUG_STREAM << "Keystroke invoking mission resume...\n" << std::flush;
Application::ResumeMissionMessage message;
application->Dispatch(&message);
}
break;
default:
L4VTVControlsMapper::KeypressMessageHandler(message);
break;
}
Check_Fpu();
}
//#############################################################################
// Model Support
//
void
VTVThrustmasterMapper::InterpretControls(Scalar time_slice)
{
//
//----------------------------------------
// Use the hat buttons to set the throttle
//----------------------------------------
//
LBE4ControlsManager
*controls = Cast_Object(
LBE4ControlsManager*,
application->GetControlsManager()
);
Check(controls);
throttlePosition = controls->scalarGroup[LBE4ControlsManager::ScalarThrottle].previousValue;
/*if (throttleUp > 0)
{
throttlePosition = 1.0f;
reverseThrust = 0;
}
else if (throttleDown > 0)
{
throttlePosition = 1.0f;
reverseThrust = 1;
}
else
{
throttlePosition = 0.0f;
reverseThrust = 0;
}*/
//
//----------------------------------------
// Sum the pedal inputs
//----------------------------------------
//
pedalsPosition = leftPedal - rightPedal;
VTVControlsMapper::InterpretControls(time_slice);
Check_Fpu();
}
//#############################################################################
// Construction and Destruction Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
VTVThrustmasterMapper::VTVThrustmasterMapper(
VTV *player_vehicle,
int subsystem_ID,
SubsystemResource *subsystem_resource
):
L4VTVControlsMapper(
player_vehicle,
subsystem_ID,
subsystem_resource,
DefaultData
)
{
SetPerformance(&VTVThrustmasterMapper::InterpretControls);
leftPedal = 0.0f;
rightPedal = 0.0f;
LBE4ControlsManager
*controls =
Cast_Object(LBE4ControlsManager*,application->GetControlsManager());
Check(controls);
controls
->joystickGroup[LBE4ControlsManager::JoystickPhysical]
.Add(RPL4ModeManager::ModeAlwaysActive, &stickPosition, this);
//
//--------------
// Pedal mapping
//--------------
//
controls
->scalarGroup[LBE4ControlsManager::ScalarLeftPedal]
.Add(RPL4ModeManager::ModeAlwaysActive, &leftPedal, this);
controls
->scalarGroup[LBE4ControlsManager::ScalarRightPedal]
.Add(RPL4ModeManager::ModeAlwaysActive, &rightPedal, this);
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickHatRight]
.Add(RPL4ModeManager::ModeAlwaysActive, &lookRight, this);
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickHatLeft]
.Add(RPL4ModeManager::ModeAlwaysActive, &lookLeft, this);
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickHatUp]
.Add(RPL4ModeManager::ModeAlwaysActive, &lookUp, this);
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickHatDown]
.Add(RPL4ModeManager::ModeAlwaysActive, &lookBehind, this);
controls
->buttonGroup[LBE4ControlsManager::ButtonThrottle1]
.Add(RPL4ModeManager::ModeAlwaysActive, &reverseThrust, this);
controls
->keyboardGroup[LBE4ControlsManager::KeyboardPC]
.Add(RPL4ModeManager::ModeAlwaysActive, this, KeypressMessageID, this);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
VTVThrustmasterMapper::~VTVThrustmasterMapper()
{
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
VTVThrustmasterMapper::TestInstance() const
{
return IsDerivedFrom(*GetClassDerivations());
}
//#############################################################################
//################################ RIOMapper ##################################
//#############################################################################
//#############################################################################
// Shared Data Support
//
VTVRIOMapper::SharedData
VTVRIOMapper::DefaultData(
VTVRIOMapper::GetClassDerivations(),
VTVRIOMapper::MessageHandlers,
VTVRIOMapper::GetAttributeIndex(),
VTVRIOMapper::StateCount
);
Derivation* VTVRIOMapper::GetClassDerivations()
{ static Derivation classDerivations(L4VTVControlsMapper::GetClassDerivations(), "VTVRIOMapper");
return &classDerivations;
}
//#############################################################################
// Messaging Support
//
const Receiver::HandlerEntry
VTVRIOMapper::MessageHandlerEntries[]=
{
MESSAGE_ENTRY(VTVRIOMapper, Keypress),
MESSAGE_ENTRY(VTVRIOMapper, SwitchMode),
MESSAGE_ENTRY(VTVRIOMapper, SelectPreset),
MESSAGE_ENTRY(VTVRIOMapper, CenterJoystick),
MESSAGE_ENTRY(VTVRIOMapper, ConfigureControls)
};
Receiver::MessageHandlerSet
VTVRIOMapper::MessageHandlers(
ELEMENTS(VTVRIOMapper::MessageHandlerEntries),
VTVRIOMapper::MessageHandlerEntries,
L4VTVControlsMapper::GetMessageHandlers()
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
VTVRIOMapper::KeypressMessageHandler(
ReceiverDataMessageOf<ControlsKey> *message
)
{
Check(this);
Check(message);
switch (message->dataContents)
{
case PCK_F1:
{
Check(application);
LBE4ControlsManager *controls = Cast_Object(
LBE4ControlsManager*,
application->GetControlsManager()
);
Check(controls);
Tell("Centered RIO Joystick\n");
controls->CenterRIOJoystick();
}
break;
case PCK_F12:
Check(application);
if (
application->GetApplicationState() != Application::EndingMission
&& application->GetApplicationState() != Application::StoppingMission
)
{
DEBUG_STREAM << "Keystroke invoking mission stop...\n" << std::flush;
Exit_Code = 1;
Application::StopMissionMessage message(Exit_Code);
application->Dispatch(&message);
}
break;
case 'W':
case 'w':
{
ReceiverDataMessageOf<ControlsButton>
config_msg(
Booster::ActivateMessageID,
sizeof(ReceiverDataMessageOf<ControlsButton>),
1
);
for (int i=0; i < GetEntity()->GetSubsystemCount(); i++)
{
Subsystem *sub = GetEntity()->GetSubsystem(i);
if (sub && sub->GetClassID() == VTV::BoosterClassID)
{
sub->Dispatch(&config_msg);
break;
}
}
break;
}
break;
//-------------------------------------------------------
// Control eyepoint views
//-------------------------------------------------------
case PCK_UP: // look forward
lookLeft = -1;
lookRight = -1;
lookBehind = -1;
lookUp = -1;
break;
case PCK_LEFT: // look left
lookLeft = 1;
lookRight = -1;
lookBehind = -1;
lookUp = -1;
break;
case PCK_RIGHT: // look right
lookLeft = -1;
lookRight = 1;
lookBehind = -1;
lookUp = -1;
break;
case PCK_DOWN: // look behind
lookLeft = -1;
lookRight = -1;
lookBehind = 1;
lookUp = -1;
break;
case PCK_CTL_UP: // look up
lookLeft = -1;
lookRight = -1;
lookBehind = -1;
lookUp = 1;
break;
default:
L4VTVControlsMapper::KeypressMessageHandler(message);
break;
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
VTVRIOMapper::SwitchModeMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
)
{
Check(this);
//-------------------------------------------
// Switch on 'press' only (ignore release)
//-------------------------------------------
if (message->dataContents > 0)
{
//----------------------------------
// Pick the selected mode
//----------------------------------
switch (message->dataContents - 1)
{
case LBE4ControlsManager::ButtonAuxUpperRight5:
SetControlsMode(BasicMode);
break;
case LBE4ControlsManager::ButtonAuxUpperRight6:
SetControlsMode(StandardMode);
break;
case LBE4ControlsManager::ButtonAuxUpperRight7:
SetControlsMode(VeteranMode);
break;
case LBE4ControlsManager::ButtonAuxUpperRight8:
SetControlsMode(MasterMode);
break;
}
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
VTVRIOMapper::SelectPresetMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
)
{
Check(this);
//-------------------------------------------
// Switch on 'press' only (ignore release)
//-------------------------------------------
if (message->dataContents > 0)
{
//-----------------------------------
// Choose a new preset. PresetEnable
// ignores a repeat of the lit switch
// and moves the lamps itself.
//-----------------------------------
PresetEnable(
(message->dataContents - 1) - LBE4ControlsManager::ButtonSecondary7
);
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
VTVRIOMapper::CenterJoystickMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
)
{
Check(this);
if (message->dataContents > 0)
{
Check(application);
LBE4ControlsManager
*controls = (LBE4ControlsManager *) application->GetControlsManager();
Check(controls);
controls->CenterRIOJoystick();
}
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
VTVRIOMapper::ConfigureControlsMessageHandler(
ReceiverDataMessageOf<ControlsButton> *message
)
{
Check(this);
//-------------------------------------------------------------
// Allow the VTVControlsMapper to process the message
//-------------------------------------------------------------
// OBSOLETE
// VTVControlsMapper::ConfigureControlsMessageHandler(message);
//-------------------------------------------
// Switch on 'press' only (ignore release)
//-------------------------------------------
if (message->dataContents > 0)
{
//-------------------------------------------
// Modify mode
//-------------------------------------------
if (GetSimulationState() == ConfigurationState)
{
SetConfigurationMode(False);
}
else
{
SetConfigurationMode(True);
}
}
Check_Fpu();
}
//#############################################################################
// Model Support
//
void
VTVRIOMapper::InterpretControls(Scalar time_slice)
{
//
//----------------------------------------
// Reverse if throttle button held in
//----------------------------------------
//
if (throttleReverse > 0)
{
reverseThrust = 1;
throttleReverse = 0;
}
else if (throttleReverse < 0)
{
reverseThrust = 0;
throttleReverse = 0;
}
//
//----------------------------------------
// Sum the pedal inputs
//----------------------------------------
//
pedalsPosition = leftPedal - rightPedal;
VTVControlsMapper::InterpretControls(time_slice);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
VTVRIOMapper::AddOrErase(
unsigned int button_ID,
Receiver *target,
Receiver::MessageID message_ID
)
{
Check(this);
Check(target);
Check(application);
LBE4ControlsManager *controls =
Cast_Object(LBE4ControlsManager*,application->GetControlsManager());
Check(controls);
controls->buttonGroup[button_ID-1]
.AddOrErase(previousPresetModeMask, target, message_ID, this);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
void
VTVRIOMapper::AddOrErase(
unsigned int button_ID,
ControlsButton *destination
)
{
Check(this);
Check_Pointer(destination);
Check(application);
LBE4ControlsManager *controls =
Cast_Object(LBE4ControlsManager*,application->GetControlsManager());
Check(controls);
controls->buttonGroup[button_ID-1]
.AddOrErase(previousPresetModeMask, destination, this);
Check_Fpu();
}
//#############################################################################
// Platform-specific updates
//
void
VTVRIOMapper::NotifyOfControlModeChange(int new_mode)
{
Check(this);
int
lamp_number;
//----------------------------------
// Set the old mode button to 'dim'
//----------------------------------
switch (previousControlMode)
{
case BasicMode: lamp_number = 0; break;
case StandardMode: lamp_number = 1; break;
case VeteranMode: lamp_number = 2; break;
case MasterMode: lamp_number = 3; break;
default: lamp_number = -1; break;
}
if (lamp_number >= 0)
{
Verify(lamp_number < modeLampCount);
if (modeLamp[lamp_number] != NULL)
{
Check(modeLamp[lamp_number]);
modeLamp[lamp_number]->SetState(L4Lamp::LampStateDim);
}
}
//----------------------------------
// Pick the selected mode
//----------------------------------
switch (controlMode)
{
case BasicMode: lamp_number = 0; break;
case StandardMode: lamp_number = 1; break;
case VeteranMode: lamp_number = 2; break;
case MasterMode: lamp_number = 3; break;
default: lamp_number = -1; break;
}
if (lamp_number >= 0)
{
Verify(lamp_number < modeLampCount);
if (modeLamp[lamp_number] != NULL)
{
Check(modeLamp[lamp_number]);
modeLamp[lamp_number]->SetState(L4Lamp::LampStateOn);
}
}
//-----------------------------------
// Invoke ancestral method
//-----------------------------------
L4VTVControlsMapper::NotifyOfControlModeChange(new_mode);
Check_Fpu();
}
void
VTVRIOMapper::NotifyOfConfigurationModeChange(Logical new_state)
{
Check(this);
for(int i=0; i<configLampCount; ++i)
{
if (configLamp[i] != NULL)
{
Check(configLamp[i]);
configLamp[i]->SetAlertState(new_state);
}
}
//-----------------------------------
// Invoke ancestral method
//-----------------------------------
L4VTVControlsMapper::NotifyOfConfigurationModeChange(new_state);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// The six amber switches down the map's right flank. Called by PresetEnable,
// so the lamps follow the mappings no matter what asked for the change.
//
void
VTVRIOMapper::NotifyOfPresetChange(int old_preset, int new_preset)
{
Check(this);
//----------------------------------
// Set the old preset lamp to 'dim'
//----------------------------------
if (old_preset >= 0)
{
Verify(old_preset < presetCount);
if (presetLamp[old_preset] != NULL)
{
Check(presetLamp[old_preset]);
presetLamp[old_preset]->SetState(L4Lamp::LampStateDim);
}
}
//----------------------------------
// Set the new preset lamp to 'on'
//----------------------------------
if (new_preset >= 0)
{
Verify(new_preset < presetCount);
if (presetLamp[new_preset] != NULL)
{
Check(presetLamp[new_preset]);
presetLamp[new_preset]->SetState(L4Lamp::LampStateOn);
}
}
Check_Fpu();
}
//#############################################################################
// Construction and Destruction Support
//
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
VTVRIOMapper::VTVRIOMapper(
VTV *player_vehicle,
int subsystem_ID,
SubsystemResource *subsystem_resource
):
L4VTVControlsMapper(
player_vehicle,
subsystem_ID,
subsystem_resource,
DefaultData
)
{
SetPerformance(&VTVRIOMapper::InterpretControls);
throttleUp = 0;
throttleDown = 0;
throttleReverse = 0;
leftPedal = 0.0f;
rightPedal = 0.0f;
//------------------------------------------------
// There are no lamps until the mapping blocks
// below make them - and under NOMODES they never
// do, so the notify methods must see NULLs.
//------------------------------------------------
{
int
i;
for(i=0; i<configLampCount; ++i) configLamp[i] = NULL;
for(i=0; i<modeLampCount; ++i) modeLamp[i] = NULL;
for(i=0; i<presetCount; ++i) presetLamp[i] = NULL;
}
Check(application);
LBE4ControlsManager
*controls = Cast_Object(
LBE4ControlsManager*,
application->GetControlsManager()
);
Check(controls);
VTV
*vtv = GetEntity();
Check(vtv);
//
//------------------
// Throttle mappings
//------------------
//
controls
->scalarGroup[LBE4ControlsManager::ScalarThrottle]
.Add(RPL4ModeManager::ModeAlwaysActive, &throttlePosition, this);
controls
->buttonGroup[LBE4ControlsManager::ButtonThrottle1]
.Add(RPL4ModeManager::ModeAlwaysActive, &reverseThrust, this);
//
//------------------
// Joystick mappings
//------------------
//
controls
->joystickGroup[LBE4ControlsManager::JoystickPhysical]
.Add(RPL4ModeManager::ModeAlwaysActive, &stickPosition, this);
//
//------------------
// Eyepoint mappings
//------------------
//
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickHatLeft]
.Add(RPL4ModeManager::ModeAlwaysActive, &lookLeft, this);
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickHatRight]
.Add(RPL4ModeManager::ModeAlwaysActive, &lookRight, this);
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickHatUp]
.Add(RPL4ModeManager::ModeAlwaysActive, &lookUp, this);
controls
->buttonGroup[LBE4ControlsManager::ButtonJoystickHatDown]
.Add(RPL4ModeManager::ModeAlwaysActive, &lookBehind, this);
//
//--------------
// Pedal mapping
//--------------
//
controls
->scalarGroup[LBE4ControlsManager::ScalarLeftPedal]
.Add(RPL4ModeManager::ModeAlwaysActive, &leftPedal, this);
controls
->scalarGroup[LBE4ControlsManager::ScalarRightPedal]
.Add(RPL4ModeManager::ModeAlwaysActive, &rightPedal, this);
//
//-----------------
// Keyboard mapping
//-----------------
//
controls
->keyboardGroup[LBE4ControlsManager::KeyboardPC]
.Add(RPL4ModeManager::ModeAlwaysActive, this, KeypressMessageID, this);
//----------------------------------------------------------------
// Configuration mapping
//----------------------------------------------------------------
// Lamps explicitly controlled by ConfigureControlsMessageHandler
configLamp[0] = CreateControlledLamp(
LBE4ControlsManager::ButtonAuxUpperRight1,
RPL4ModeManager::ModeStandard
);
configLamp[1] = CreateControlledLamp(
LBE4ControlsManager::ButtonAuxUpperRight2,
RPL4ModeManager::ModeStandard
);
if (!getenv("NOMODES"))
{
int
i;
for(i=0; i<configLampCount; ++i)
{
if (configLamp[i] != NULL)
{
Check(configLamp[i]);
configLamp[i]->SetState(L4Lamp::LampStateDim);
}
}
controls
->buttonGroup[LBE4ControlsManager::ButtonAuxUpperRight1]
.Add(
RPL4ModeManager::ModeStandard,
this,
ConfigureControlsMessageID, this
);
controls
->buttonGroup[LBE4ControlsManager::ButtonAuxUpperRight2]
.Add(
RPL4ModeManager::ModeStandard,
this,
ConfigureControlsMessageID, this
);
}
//----------------------------------------------------------------
// Joystick centering
//----------------------------------------------------------------
MakeButtonLampEventPair(
controls,
LBE4ControlsManager::ButtonAuxUpperRight3,
LBE4ControlsManager::ButtonAuxUpperRight4,
this,
CenterJoystickMessageID,
this
);
//----------------------------------------------------------------
// Secondary mappings
//----------------------------------------------------------------
MakeButtonLampEvent(
controls,
LBE4ControlsManager::ButtonSecondary1,
vtv,
VTV::ZoomInMessageID,
this
);
MakeButtonLampEvent(
controls,
LBE4ControlsManager::ButtonSecondary2,
vtv,
VTV::ZoomOutMessageID,
this
);
MakeButtonLampEvent(
controls,
LBE4ControlsManager::ButtonSecondary3,
this,
ToggleReticleMessageID,
this
);
MakeButtonLampEvent(
controls,
LBE4ControlsManager::ButtonSecondary4,
this,
ActivateHornMessageID,
this
);
//----------------------------------------------------------------
// Mode mapping
//----------------------------------------------------------------
previousControlMode = -1;
if (!getenv("NOMODES"))
{
int
i;
static int
button_number[modeLampCount] =
{
LBE4ControlsManager::ButtonAuxUpperRight5,
LBE4ControlsManager::ButtonAuxUpperRight6,
LBE4ControlsManager::ButtonAuxUpperRight7,
LBE4ControlsManager::ButtonAuxUpperRight8
};
for(i=0; i<modeLampCount; ++i)
{
controls->buttonGroup[button_number[i]].Add(
RPL4ModeManager::ModeAlwaysActive,
this,
SwitchModeMessageID,
this
);
//----------------------------------------------
// These lamps are explicitly controlled by
// VTVRIOMapper::NotifyOfControlModeChange
//----------------------------------------------
modeLamp[i] = CreateControlledLamp(button_number[i]);
if (modeLamp[i] != NULL)
{
Check(modeLamp[i]);
}
}
}
//----------------------------------------------------------------
// Preset mapping
//----------------------------------------------------------------
if (!getenv("NOMODES"))
{
int
i;
static int
button_number[presetCount] =
{
LBE4ControlsManager::ButtonSecondary7,
LBE4ControlsManager::ButtonSecondary8,
LBE4ControlsManager::ButtonSecondary9,
LBE4ControlsManager::ButtonSecondary10,
LBE4ControlsManager::ButtonSecondary11,
LBE4ControlsManager::ButtonSecondary12
};
for(i=0; i<presetCount; ++i)
{
controls->buttonGroup[button_number[i]].Add(
RPL4ModeManager::ModeAlwaysActive,
this,
SelectPresetMessageID,
this
);
// These lamps are explicitly controlled by NotifyOfPresetChange.
// They are six, and they are NOT the four mode lamps above.
presetLamp[i] = CreateControlledLamp(button_number[i]);
if (presetLamp[i] != NULL)
{
Check(presetLamp[i]);
presetLamp[i]->SetState(
(i==0)? L4Lamp::LampStateOn : L4Lamp::LampStateDim
);
}
}
NotifyOfControlModeChange(BasicMode);
}
//----------------------------------------------------------------
// liftcut mapping
//----------------------------------------------------------------
CreateDirectSystemMappingPair(
controls,
LBE4ControlsManager::ButtonAuxUpperLeft1,
LBE4ControlsManager::ButtonAuxUpperLeft2,
&liftCut,
this,
ConfigureLiftCutMappablesMessageID
);
//----------------------------------------------------------------
// sideslip mapping
//----------------------------------------------------------------
CreateDirectSystemMappingPair(
controls,
LBE4ControlsManager::ButtonAuxUpperLeft3,
LBE4ControlsManager::ButtonAuxUpperLeft4,
&sideSlip,
this,
ConfigureSideSlipMappablesMessageID
);
//----------------------------------------------------------------
// intercom PTT mapping
//----------------------------------------------------------------
CreateEventSystemMappingPair(
controls,
LBE4ControlsManager::ButtonAuxUpperLeft5,
LBE4ControlsManager::ButtonAuxUpperLeft6,
this,
ActivatePTTMessageID,
ConfigurePTTMappablesMessageID
);
//----------------------------------------------------------------
// horn mapping
//----------------------------------------------------------------
CreateEventSystemMappingPair(
controls,
LBE4ControlsManager::ButtonAuxUpperLeft7,
LBE4ControlsManager::ButtonAuxUpperLeft8,
this,
ActivateHornMessageID,
ConfigureHornMappablesMessageID
);
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
VTVRIOMapper::~VTVRIOMapper()
{
Check(this);
// HACK - gaugeRenderer::ShutdownImplementation() removes all lamps.
// When this destructor gets called, the lamps have (usually) already
// been deleted. The fix is to have all lamp operations go through
// the lamp manager, referring to the lamp by ID and modeMask...then,
// when a request is made for a nonexistent lamp, the request is ignored.
#if 0
int
i;
//-----------------------------------------------
// First check to see if the lamp manager exists.
// If it doesn't, then the lamps have either
// not been created or else have already
// been deleted.
//-----------------------------------------------
Check(application);
if (application->GetGaugeRenderer() != NULL)
{
Check(application->GetGaugeRenderer());
if (application->GetGaugeRenderer()->GetLampManager() != NULL)
{
Check(application->GetGaugeRenderer()->GetLampManager());
//--------------------------------------------
// Delete controlled lamp objects
//--------------------------------------------
for(i=0; i<configLampCount; ++i)
{
if (configLamp[i] != NULL)
{
Unregister_Object(configLamp[i]);
delete configLamp[i];
configLamp[i] = NULL;
}
}
for(i=0; i<modeLampCount; ++i)
{
if (modeLamp[i] != NULL)
{
Unregister_Object(modeLamp[i]);
delete modeLamp[i];
modeLamp[i] = NULL;
}
}
for(i=0; i<presetCount; ++i)
{
if (presetLamp[i] != NULL)
{
Unregister_Object(presetLamp[i]);
delete presetLamp[i];
presetLamp[i] = NULL;
}
}
}
}
#endif
Check_Fpu();
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
Logical
VTVRIOMapper::TestInstance() const
{
return IsDerivedFrom(*GetClassDerivations());
}