#include "rp.h" #pragma hdrstop #include "vtvmppr.h" #include "vtvpwr.h" #include "..\munga\icom.h" #include "..\munga\app.h" #include "rpplayer.h" #include "vtv.h" //############################################################################# // Shared Data Support // VTVControlsMapper::SharedData VTVControlsMapper::DefaultData( VTVControlsMapper::GetClassDerivations(), VTVControlsMapper::GetMessageHandlers(), VTVControlsMapper::GetAttributeIndex(), VTVControlsMapper::StateCount ); Derivation* VTVControlsMapper::GetClassDerivations() { static Derivation classDerivations(VTVSubsystem::GetClassDerivations(), "VTVControlsMapper"); return &classDerivations; } //############################################################################# // Messaging Support // const Receiver::HandlerEntry VTVControlsMapper::MessageHandlerEntries[]= { MESSAGE_ENTRY(VTVControlsMapper, ConfigureControls), MESSAGE_ENTRY(VTVControlsMapper, ConfigureSideSlipMappables), MESSAGE_ENTRY(VTVControlsMapper, ChooseSideSlip), MESSAGE_ENTRY(VTVControlsMapper, ConfigureLiftCutMappables), MESSAGE_ENTRY(VTVControlsMapper, ChooseLiftCut), MESSAGE_ENTRY(VTVControlsMapper, ConfigureHornMappables), MESSAGE_ENTRY(VTVControlsMapper, ChooseHorn), MESSAGE_ENTRY(VTVControlsMapper, ActivateHorn), MESSAGE_ENTRY(VTVControlsMapper, ConfigurePTTMappables), MESSAGE_ENTRY(VTVControlsMapper, ChoosePTT), MESSAGE_ENTRY(VTVControlsMapper, ActivatePTT), MESSAGE_ENTRY(VTVControlsMapper, ToggleReticle) }; Receiver::MessageHandlerSet& VTVControlsMapper::GetMessageHandlers() { static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(VTVControlsMapper::MessageHandlerEntries), VTVControlsMapper::MessageHandlerEntries, VTVSubsystem::GetMessageHandlers()); return messageHandlers; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::ConfigureControlsMessageHandler( #if DEBUG_LEVEL>0 ReceiverDataMessageOf *message #else ReceiverDataMessageOf * #endif ) { Check(this); Check(message); #if 0 THIS STUFF IS BASICALLY OBSOLETE // //------------------------ // Get the control manager //------------------------ // Check(application); ControlsManager *control = application->GetControlsManager(); Check(control); // //---------------------------------------------------------------------- // If the config button was pressed, set all hardwired buttons to config // mode, otherwise set them all back to active mode, and clear out any // temporary mappings to the mappable buttons //---------------------------------------------------------------------- // if (message->dataContents > 0) { if (GetSimulationState() == ConfigurationState) { control->SetHardwiredButtonsFilter(ActiveFilter, 0); control->StopMappableButtonsConfigure( ConfigurationFilter, mustMatch, mayMatch ); SetSimulationState(DefaultState); } else { if (controlMode != BasicMode) { control->SetHardwiredButtonsFilter(ConfigurationFilter, 0); SetSimulationState(ConfigurationState); } } } #endif Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::ConfigureSideSlipMappablesMessageHandler( ReceiverDataMessageOf *message ) { Check(this); Check(message); //--------------------------------------------------------------------- // If the hardwired button was pressed, process presses of the mappable // buttons, otherwise it was released, so erase any temporary mappings //--------------------------------------------------------------------- if (message->dataContents > 0) { EnterConfiguration( &sideSlip, // direct target this, // receiver (Receiver::MessageID) 0, // activation message ID (none here) ChooseSideSlipMessageID // configuration message ID ); } else { ExitConfiguration(); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::ChooseSideSlipMessageHandler( ReceiverDataMessageOf *message ) { Check(this); Check(message); if (message->dataContents > 0) { AddOrErase(message->dataContents, &sideSlip); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::ConfigureLiftCutMappablesMessageHandler( ReceiverDataMessageOf *message ) { Check(this); Check(message); // //--------------------------------------------------------------------- // If the hardwired button was pressed, process presses of the mappable // buttons, otherwise it was released, so erase any temporary mappings //--------------------------------------------------------------------- // if (message->dataContents > 0) { EnterConfiguration( &liftCut, // direct target this, // receiver (Receiver::MessageID) 0, // activation message ID (none here) ChooseLiftCutMessageID // configuration message ID ); } else { ExitConfiguration(); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::ChooseLiftCutMessageHandler( ReceiverDataMessageOf *message ) { Check(this); Check(message); if (message->dataContents > 0) { AddOrErase(message->dataContents, &liftCut); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::ConfigureHornMappablesMessageHandler( ReceiverDataMessageOf *message ) { Check(this); Check(message); // //--------------------------------------------------------------------- // If the hardwired button was pressed, process presses of the mappable // buttons, otherwise it was released, so erase any temporary mappings //--------------------------------------------------------------------- // if (message->dataContents > 0) { EnterConfiguration( NULL, // direct target (none here) this, // receiver ActivateHornMessageID, // activation message ID ChooseHornMessageID // configuration message ID ); } else { ExitConfiguration(); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::ChooseHornMessageHandler( ReceiverDataMessageOf *message ) { Check(this); Check(message); if (message->dataContents > 0) { AddOrErase(message->dataContents, this, ActivateHornMessageID); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::ActivateHornMessageHandler( ReceiverDataMessageOf *message ) { Check(this); Check(message); hornBlast = message->dataContents; // hornBlast = (hornBlast == -1) ? 1 : -1; // HACK - ECH 7/31/95 - Propagate horn blast Check(GetEntity()); GetEntity()->hornBlast = hornBlast; GetEntity()->ForceUpdate(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::ConfigurePTTMappablesMessageHandler( ReceiverDataMessageOf *message ) { Check(this); Check(message); // //--------------------------------------------------------------------- // If the hardwired button was pressed, process presses of the mappable // buttons, otherwise it was released, so erase any temporary mappings //--------------------------------------------------------------------- // if (message->dataContents > 0) { EnterConfiguration( NULL, // direct target (none here) this, // receiver ActivatePTTMessageID, // activation message ID ChoosePTTMessageID // configuration message ID ); } else { ExitConfiguration(); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::ChoosePTTMessageHandler( ReceiverDataMessageOf *message ) { Check(this); Check(message); if (message->dataContents > 0) { AddOrErase(message->dataContents, &pttStatus); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::ActivatePTTMessageHandler( ReceiverDataMessageOf *message ) { Check(this); Check(message); pttStatus = message->dataContents; } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::ToggleReticleMessageHandler( ReceiverDataMessageOf *message ) { Check(this); Check(message); if (message->dataContents > 0) { VTV* vtv = GetEntity(); Check(vtv); Reticle *reticle = &vtv->targetReticle; Check(reticle); reticle->reticleState = (Reticle::ReticleState)(reticle->reticleState^Reticle::ReticleOn); } } //############################################################################# // Attribute Support // const VTVControlsMapper::IndexEntry VTVControlsMapper::AttributePointers[]= { ATTRIBUTE_ENTRY(VTVControlsMapper, StickPosition, stickPosition), ATTRIBUTE_ENTRY(VTVControlsMapper, ThrottlePosition, throttlePosition), ATTRIBUTE_ENTRY(VTVControlsMapper, PedalsPosition, pedalsPosition), ATTRIBUTE_ENTRY(VTVControlsMapper, ReverseThrust, reverseThrust), ATTRIBUTE_ENTRY(VTVControlsMapper, LiftCut, liftCut), ATTRIBUTE_ENTRY(VTVControlsMapper, SideSlip, sideSlip), ATTRIBUTE_ENTRY(VTVControlsMapper, PowerDemand, powerDemand), ATTRIBUTE_ENTRY( VTVControlsMapper, AngularVelocityDemand, angularVelocityDemand ), ATTRIBUTE_ENTRY(VTVControlsMapper, BrakeLights, brakeLights), ATTRIBUTE_ENTRY(VTVControlsMapper, LookLeft, lookLeft), ATTRIBUTE_ENTRY(VTVControlsMapper, LookRight, lookRight), ATTRIBUTE_ENTRY(VTVControlsMapper, LookBehind, lookBehind), ATTRIBUTE_ENTRY(VTVControlsMapper, LookUp, lookUp), ATTRIBUTE_ENTRY(VTVControlsMapper, ControlMode, controlMode), ATTRIBUTE_ENTRY(VTVControlsMapper, HornBlast, hornBlast), ATTRIBUTE_ENTRY(VTVControlsMapper, MustMatch, mustMatch), ATTRIBUTE_ENTRY(VTVControlsMapper, ReverseThrustEngaged,reverseThrustEngaged), // ECH 8/3/95 - HACK - deal with thrust ATTRIBUTE_ENTRY(VTVControlsMapper, LiftCutEngaged, liftCutEngaged), ATTRIBUTE_ENTRY(VTVControlsMapper, PTTStatus, pttStatus) }; VTVControlsMapper::AttributeIndexSet& VTVControlsMapper::GetAttributeIndex() { static VTVControlsMapper::AttributeIndexSet attributeIndex(ELEMENTS(VTVControlsMapper::AttributePointers), VTVControlsMapper::AttributePointers, VTVSubsystem::GetAttributeIndex() ); return attributeIndex; } //############################################################################# // Model Support // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::InterpretControls(Scalar) { Scalar demand; Check(this); VTV* vtv = GetEntity(); Check(vtv); VTVPower *power_system = Cast_Object(VTVPower*, vtv->GetSubsystem(VTV::PowerSubsystem)); // //---------------------------------------------- // Make sure the control inputs are within range //---------------------------------------------- // Verify(throttlePosition >= 0.0f && throttlePosition <= 1.0f); Verify(stickPosition.x >= -1.0f && stickPosition.x <= 1.0f); Verify(stickPosition.y >= -1.0f && stickPosition.y <= 1.0f); Verify(pedalsPosition >= -1.0f && pedalsPosition <= 1.0f); // //---------------------------------------------------------------- // Figure out the proper control model to use based upon the speed //---------------------------------------------------------------- // Scalar lateral_power = power_system->maxAccelerationOutput * ZIPPY; powerDemand = Vector3D::Identity; int slow_mode = fabs(vtv->localVelocity.linearMotion.z) < lateral_power / vtv->maxYawVelocity; Check_Fpu(); angularVelocityDemand = Vector3D::Identity; Scalar kick_turn = (reverseThrust>0) ? throttlePosition : -throttlePosition; powerDemand.z = kick_turn; Logical no_steal = False; liftCutEngaged = False; reverseThrustEngaged = False; // //---------------------------------------------------- // If we are in basic mode, do that autothrottle thing //---------------------------------------------------- // if (controlMode == BasicMode) { Scalar desired_speed = powerDemand.z * power_system->maxAccelerationOutput / vtv->negativeLinearDragCoefficients.z; Check_Fpu(); Scalar reverse = (reverseThrust>0) ? 1.0f : -1.0f; // //----------------------------------------------------------------------- // If we have no boosters on, and we are going too fast, and the stick is // not pushed near full forward, change the throttle setting //----------------------------------------------------------------------- // if ( !vtv->BoosterOn() && throttlePosition < 0.1f && desired_speed > vtv->localVelocity.linearMotion.z ) { no_steal = True; powerDemand.z = -reverse; // ECH 8/3/95 - HACK - deal with thrust Scalar temp = Abs(vtv->localVelocity.linearMotion.z) / 60.0f; Clamp(temp, 0.0f, 1.0f); powerDemand.z *= pow(temp, 0.5f); } // //-------------------------------------------------------- // If we are sliding against the engines, go to full power //-------------------------------------------------------- // else if (vtv->localVelocity.linearMotion.z * reverse < 0.0f) { no_steal = True; // ECH 8/3/95 - HACK - deal with thrust if (throttlePosition < 0.1f) { Scalar temp = Abs(vtv->localVelocity.linearMotion.z) / 60.0f; Clamp(temp, 0.0f, 1.0f); powerDemand.z *= pow(temp, 0.5f); } } } brakeLights = (powerDemand.z * vtv->localVelocity.linearMotion.z) < 0.0f; // //-------------------------------------------------------------------------- // If we are in slow mode, match the lateral power to the turn rate, giving // it priority over thrust, so that we will be able to turn a perfect circle //-------------------------------------------------------------------------- // if (slow_mode && sideSlip < 1 && controlMode < MasterMode) { angularVelocityDemand.y += stickPosition.x * vtv->maxYawVelocity; powerDemand.x = -vtv->maxYawVelocity * fabs(vtv->localVelocity.linearMotion.z) * stickPosition.x / lateral_power; Check_Fpu(); if (reverseThrust>0 && vtv->localVelocity.linearMotion.z > 0.0f) { powerDemand.x = -powerDemand.x; } demand = powerDemand.x*powerDemand.x + powerDemand.z*powerDemand.z; Check_Fpu(); if (demand>1.0f) { if (powerDemand.z > 0.0f) { powerDemand.z = Sqrt(1.0f - powerDemand.x*powerDemand.x); } else { powerDemand.z = -Sqrt(1.0f - powerDemand.x*powerDemand.x); } } Check_Fpu(); } // //------------------------------------------------------------------------- // If we aren't in slow mode, match the turning rate to the power setting // on the stick, sharing power equally between forward and sideways demands //------------------------------------------------------------------------- // else { powerDemand.x = -stickPosition.x; demand = powerDemand.x*powerDemand.x + powerDemand.z*powerDemand.z; Check_Fpu(); // //----------------------------------------------------------------------- // If we are asking for more power than is available, steal from anything // but braking so we can turn quicker if we are in a wimp mode //----------------------------------------------------------------------- // if (demand>1.0f) { if (controlMode < MasterMode && powerDemand.z < 0.0f && !no_steal) { powerDemand.z = -Sqrt(1.0f - powerDemand.x*powerDemand.x); Check_Fpu(); } else { demand = Sqrt(demand); powerDemand.x /= demand; powerDemand.z /= demand; Check_Fpu(); } } } // //------------------------------------------------------------------------- // The amount of power required for height as requested by the stick should // range between 1m height and the service ceiling //------------------------------------------------------------------------- // JointSubsystem *joint_subsystem = vtv->GetJointSubsystem(); Check(joint_subsystem); Verify(joint_subsystem->GetJointCount()); // //------------------------------------------------------------------------ // If the lift cut button is on, go ahead and put all the power on X and Z. // In basic mode, if the height is greater than 5m and the stick is pushed // mostly forward //------------------------------------------------------------------------ // if ( liftCut > 0 || controlMode < VeteranMode && stickPosition.y <= -0.8f && vtv->heightAboveTerrain >= 5.0f ) { powerDemand.y = vtv->powerDive; if (powerDemand.y) { Scalar reduction = Sqrt(1.0f - powerDemand.y*powerDemand.y); powerDemand.x *= reduction; powerDemand.z *= reduction; } liftCutEngaged = True; } // //------------------------------------------------------------------------ // Otherwise, give altitude everything it wants, and split the rest up for // X and Z //------------------------------------------------------------------------ // else { if (!vtv->groundEffectDomainSquared) { if (vtv->heightAboveTerrain >= 2.0f) { powerDemand.y = 0.0f; liftCutEngaged = True; } else { demand = power_system->maxAccelerationOutput + joint_subsystem->GetJointCount() * vtv->groundEffectRange; powerDemand.y = vtv->GetEnvironment()->gravityConstant/demand; } } else if (controlMode > StandardMode) { demand = power_system->maxAccelerationOutput + joint_subsystem->GetJointCount() * (vtv->groundEffectRange / (1.0f + vtv->groundEffectDomainSquared)); Check_Fpu(); demand = vtv->GetEnvironment()->gravityConstant/demand; powerDemand.y = 0.5f * ((1.0f - demand) * stickPosition.y + (1.0f + demand)); Max_Clamp(powerDemand.y, 1.0f); Check_Fpu(); } else { Scalar seek_height = vtv->heightAboveTerrain; Scalar height_clamp = 30.0f; Max_Clamp(seek_height, height_clamp); if (stickPosition.y < 0.0f) { seek_height = ::Lerp(seek_height, 1.0f, -stickPosition.y); } else { seek_height = ::Lerp(seek_height, height_clamp, stickPosition.y); } demand = power_system->maxAccelerationOutput + joint_subsystem->GetJointCount() * ( vtv->groundEffectRange / ( 1.0f + vtv->groundEffectDomainSquared*seek_height*seek_height ) ); Check_Fpu(); powerDemand.y = vtv->GetEnvironment()->gravityConstant/demand; if (controlMode == BasicMode) { Max_Clamp(powerDemand.y, 0.85f); } else { Max_Clamp(powerDemand.y, 1.0f); } Check_Fpu(); } demand = Sqrt(1.0f - powerDemand.y*powerDemand.y); powerDemand.x *= demand; powerDemand.z *= demand; } // //---------------------------------------------------------- // Apply the rudders, and simulate a kick turn in basic mode //---------------------------------------------------------- // if (controlMode == BasicMode) { Scalar temp = stickPosition.x * stickPosition.x; temp *= stickPosition.x; angularVelocityDemand.y += temp * vtv->maxYawVelocity; } else if (pedalsPosition < 0.0f) { angularVelocityDemand.y -= vtv->maxYawVelocity * pedalsPosition*pedalsPosition; } else { angularVelocityDemand.y += vtv->maxYawVelocity * pedalsPosition*pedalsPosition; } // //------------------------------------------------------------------------- // If we are not is slow mode, apply yaw to the craft to sufficient to make // it turn a perfect circle, then clamp to maximum velocity //------------------------------------------------------------------------- // if (!slow_mode && controlMode < MasterMode && sideSlip < 1) { angularVelocityDemand.y += -powerDemand.x * ZIPPY * power_system->maxAccelerationOutput / fabs(vtv->localVelocity.linearMotion.z); Check_Fpu(); if (reverseThrust>0 && vtv->localVelocity.linearMotion.z > 0.0f) { powerDemand.x = -powerDemand.x; } } Clamp( angularVelocityDemand.y, -vtv->maxYawVelocity, vtv->maxYawVelocity ); // //---------------------------------------- // Turn the eyepoint the direction we want //---------------------------------------- // vtv->eyepointRotation = EulerAngles::Identity; if (lookLeft > 0) { vtv->eyepointRotation.yaw = 0.3f * PI; } else if (lookRight > 0) { vtv->eyepointRotation.yaw = -0.3f * PI; } else if (lookBehind > 0) { vtv->eyepointRotation.yaw = PI; } else if (lookUp > 0) { vtv->eyepointRotation.pitch = PI / 8.0f; } // ECH - HACK - deal with thrust and lift cut averageOfForwardThrustDemand.Add(powerDemand.z); forwardThrustDemand = averageOfForwardThrustDemand.CalculateAverage(); switch (controlMode) { case BasicMode: // Lift cut has been set, see above // Reverse thrust if demand over 0.15 reverseThrustEngaged = (forwardThrustDemand > 0.15f); break; case StandardMode: // Lift cut has been set, see above // Reverse thrust based on button reverseThrustEngaged = (reverseThrust > 0); break; case VeteranMode: case MasterMode: // Lift cut based on button // Reverse thrust based on button liftCutEngaged = (liftCut > 0); reverseThrustEngaged = (reverseThrust > 0); break; } Check(GetEntity()); if (GetEntity()->GetSimulationState() == VTV::BurningState) { liftCutEngaged = False; reverseThrustEngaged = False; } // //---------------------------------------------------------------- // Send PTT status to intercom //---------------------------------------------------------------- // if (pttStatus != previousPTTStatus) { previousPTTStatus = pttStatus; Player *player_pointer = vtv->GetPlayerLink(); Check(player_pointer); Icom *intercom = player_pointer->GetIntercom(); Check(intercom); intercom->SetPTTStatus((Logical) pttStatus > 0); } Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::CreateTemporaryEventMappings( Receiver */*receiver*/, Receiver::MessageID /*config_message_id*/ ) { Fail("Unhandled mapping!\n"); } void VTVControlsMapper::RemoveTemporaryEventMappings() { Fail("Unhandled mapping!\n"); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::AddOrErase( unsigned int, Receiver *, Receiver::MessageID ) { Fail("Unhandled mapping!\n"); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::AddOrErase( unsigned int, ControlsButton * ) { Fail("Unhandled mapping!\n"); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // void VTVControlsMapper::SetConfigurationState(Logical enter_config) { Check(this); if (enter_config) { if (GetSimulationState() != ConfigurationState) { SetSimulationState(ConfigurationState); NotifyOfConfigurationModeChange(enter_config); } } else { if (GetSimulationState() == ConfigurationState) { SetSimulationState(DefaultState); NotifyOfConfigurationModeChange(enter_config); } } Check_Fpu(); } void VTVControlsMapper::NotifyOfControlModeChange(int /*new_mode*/) { Check(this); // defaults to no-operation: intended to be processed by // platform-specific derived class Check_Fpu(); } void VTVControlsMapper::NotifyOfConfigurationModeChange(Logical /*new_state*/) { Check(this); // defaults to no-operation: intended to be processed by // platform-specific derived class Check_Fpu(); } //############################################################################# // Construction and Destruction // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // VTVControlsMapper::VTVControlsMapper( VTV *owner, int subsystem_ID, SubsystemResource *subsystem_resource, SharedData &shared_data ): VTVSubsystem( owner, subsystem_ID, subsystem_resource, shared_data ), averageOfForwardThrustDemand(4) // ECH 8/3/95 - HACK - To deal with reverse thrust { if (owner->GetInstance() == VTV::MasterInstance && owner->IsDynamic()) { SetPerformance(&VTVControlsMapper::InterpretControls); } stickPosition.x = 0.0f; stickPosition.y = 0.0f; throttlePosition = 0.0f; pedalsPosition = 0.0f; reverseThrust = 0; liftCut = 0; sideSlip = 0; powerDemand = Vector3D::Identity; angularVelocityDemand = Vector3D::Identity; brakeLights = 0; lookLeft = 0; lookRight = 0; lookBehind = 0; lookUp = 0; hornBlast = 0; controlMode = BasicMode; forwardThrustDemand = 0.0f; liftCutEngaged = False; reverseThrustEngaged = False; pttStatus = 0; previousPTTStatus = 0; Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // VTVControlsMapper::~VTVControlsMapper() { Check(this); Check_Fpu(); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // Logical VTVControlsMapper::TestInstance() const { return IsDerivedFrom(*GetClassDerivations()); }