Files
RP412/RP_L4/RPL4MPPR.cpp
T
CydandClaude Opus 5 769407ca24 The mode lamps follow the mode
Selecting NOV, STD, VET or EXP on the Upper Right MFD lit nothing and
dimmed nothing. Two separate faults had to line up for that.

SetControlsMode announced the change as
L4VTVControlsMapper::NotifyOfControlModeChange - explicitly qualified,
which suppresses the virtual call and lands on the base class no-op. The
code that drives the four lamps is VTVRIOMapper's override, so a mode
change never reached it. Its neighbour has always gone out unqualified
from VTVControlsMapper::SetConfigurationState, which is why the
configuration lamps behaved and these did not.

previousControlMode is the lamp the next change dims, and nothing wrote
it after construction set it to -1. Even once the call arrived, the dim
step would have matched nothing and the panel would have accumulated
lamps rather than following the selection.

The one call that did dispatch is the one in VTVRIOMapper's own
constructor, where the vtable is already the derived one - which is why
NOV lit at the start and then nothing ever moved.

B / S / V / M are gone from the Thrustmaster mapper's key handler. The
driving mode is a panel decision, four buttons carrying the lamps that
say which one you are in, and a bare letter key changing it behind the
player's back is not that. It reads worse in 4.12 than it ever did in
the pod: the whole letter board is the MFD banks now, so on that path
those four letters would have fired their bank button and silently
changed the driving mode as well.

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

2119 lines
50 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
//----------------------------------------
//
// Unqualified, so the platform's override is the one that runs. The
// RIO carries the four mode lamps on the Upper Right MFD and lights
// them from here (VTVRIOMapper::NotifyOfControlModeChange); naming
// the class suppressed the virtual call and landed on the base's
// no-op instead, so the lamps never followed the mode the pilot had
// just selected. Its neighbour has always gone out this way - see
// VTVControlsMapper::SetConfigurationState.
//
if (previous_mode != controlMode)
{
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
//-------------------------------------------------------
//
// B / S / V / M used to drop straight into Basic, Standard,
// Veteran and Master here. The driving mode is a panel
// decision - the four buttons on the Upper Right MFD, with the
// lamps that say which one you are in - and a bare letter key
// changing it behind the player's back is not that. Worse in
// 4.12 than it ever was in the pod: the whole letter board is
// the MFD banks now, so those four letters are buttons in their
// own right and would have fired twice.
//
// Nothing replaces them. Press the mode you want.
//
//-------------------------------------------------------
// 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);
}
}
//----------------------------------
// Remember what is lit
//----------------------------------
//
// previousControlMode is the lamp the NEXT change dims, and nothing
// used to write it after construction set it to -1. Every mode
// therefore lit its own lamp against a dim that matched nothing, and
// the panel accumulated lamps instead of following the selection.
//
previousControlMode = controlMode;
//-----------------------------------
// 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());
}