Merge branch 'next' of http://git.gitorious.org/fg/flightgear into next
This commit is contained in:
commit
8cf024bf5c
33 changed files with 2750 additions and 429 deletions
173
package/Win32-Inno/FlightGear-devel.iss
Normal file
173
package/Win32-Inno/FlightGear-devel.iss
Normal file
|
@ -0,0 +1,173 @@
|
|||
; Script generated by the Inno Setup Script Wizard.
|
||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||
;
|
||||
; This script creates an installable FlightGear package for Win32 using the
|
||||
; "Inno Setup" package builder. Inno Setup is free (but probably not open
|
||||
; source?.) The official web site for this package building software is:
|
||||
;
|
||||
; http://www.jrsoftware.org/isinfo.php
|
||||
;
|
||||
; Note: the files must appear in the X: drive.
|
||||
; You can do this with the command below:
|
||||
;
|
||||
; subst X: path_to_files
|
||||
;
|
||||
; For example:
|
||||
;
|
||||
; C:\> subst X: F:\Path\to\FlightGear\root
|
||||
; C:\> subst X: F:\
|
||||
; C:\> subst X: E:\Package\FlightGear-YYYYMMDD
|
||||
; C:\> subst X: /d
|
||||
;
|
||||
|
||||
#define FGVER "v20110228"
|
||||
|
||||
[Setup]
|
||||
AppId=FlightGear {#FGVER}
|
||||
AppName=FlightGear {#FGVER}
|
||||
AppPublisher=The FlightGear Team
|
||||
OutputBaseFilename=Setup FlightGear {#FGVER}
|
||||
AppVerName=FlightGear {#FGVER}
|
||||
AppPublisherURL=http://www.flightgear.org
|
||||
AppSupportURL=http://www.flightgear.org
|
||||
AppUpdatesURL=http://www.flightgear.org
|
||||
DefaultDirName={pf}\FlightGear {#FGVER}
|
||||
DefaultGroupName=FlightGear {#FGVER}
|
||||
LicenseFile=X:\data\COPYING
|
||||
Uninstallable=yes
|
||||
SetupIconFile=x:\flightgear.ico
|
||||
VersionInfoVersion=2.0.0.0
|
||||
WizardImageFile=X:\setupimg.bmp
|
||||
WizardImageStretch=No
|
||||
WizardSmallImageFile=X:\setupsmall.bmp
|
||||
VersionInfoCompany=The FlightGear Team
|
||||
UninstallDisplayIcon={app}\bin\Win32\fgrun.exe
|
||||
|
||||
[Tasks]
|
||||
; NOTE: The following entry contains English phrases ("Create a desktop icon" and "Additional icons"). You are free to translate them into another language if required.
|
||||
Name: "desktopicon"; Description: "Create a &desktop icon"; GroupDescription: "Additional icons:"
|
||||
Name: "insoal"; Description: "Install OpenAL (the sound engine)"
|
||||
|
||||
[Files]
|
||||
; NOTE: run subst X: F:\ (or whatever path the expanded tree resides at)
|
||||
Source: "X:\*.txt"; DestDir: "{app}"; Flags: ignoreversion
|
||||
Source: "X:\bin\Win32\*.*"; DestDir: "{app}\bin\Win32"; Flags: ignoreversion recursesubdirs
|
||||
Source: "X:\bin\vcredist_x86.exe"; DestDir: "{app}\bin"; Flags: ignoreversion
|
||||
Source: "X:\bin\oalinst.exe"; DestDir: "{app}\bin"; Flags: ignoreversion
|
||||
Source: "X:\data\*.*"; DestDir: "{app}\data"; Flags: ignoreversion recursesubdirs
|
||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||
|
||||
[Dirs]
|
||||
; Make the user installable scenery directory
|
||||
Name: "{app}\scenery"; Permissions: everyone-modify
|
||||
Name: "{code:TerrasyncDir}"; Permissions: everyone-modify
|
||||
|
||||
[Icons]
|
||||
Name: "{group}\FlightGear {#FGVER}"; Filename: "{app}\bin\Win32\fgrun.exe"; WorkingDir: "{app}";
|
||||
; Name: "{group}\FlightGear"; Filename: "{app}\bin\Win32\fgfs.exe"; Parameters: "--fg-root=."; WorkingDir: "{app}";
|
||||
Name: "{group}\FlightGear Manual"; Filename: "{app}\data\Docs\getstart.pdf"
|
||||
Name: "{group}\FlightGear Documentation"; Filename: "{app}\data\Docs\index.html"
|
||||
Name: "{group}\Flightgear Wiki"; Filename: "http://wiki.flightgear.org"
|
||||
Name: "{userdesktop}\FlightGear {#FGVER}"; Filename: "{app}\bin\Win32\fgrun.exe"; WorkingDir: "{app}"; Tasks: desktopicon
|
||||
|
||||
Name: "{group}\Tools\Install & Uninstall Scenery"; Filename: "{app}\bin\Win32\fgadmin.exe"; WorkingDir: "{app}";
|
||||
Name: "{group}\Tools\TerraSync"; Filename: "{app}\bin\Win32\terrasync.exe"; Parameters: "-S -p 5505 -d ""{app}\terrasync"""; WorkingDir: "{app}";
|
||||
Name: "{group}\Tools\Uninstall FlightGear {#FGVER}"; Filename: "{uninstallexe}"
|
||||
|
||||
Name: "{group}\Tools\js_demo"; Filename: "{app}\bin\Win32\js_demo.exe"
|
||||
Name: "{group}\Tools\fgjs"; Filename: "cmd"; Parameters: "/k fgjs.exe ""--fg-root={app}\data"""; WorkingDir: "{app}\bin\Win32";
|
||||
Name: "{group}\Tools\GPSsmooth"; Filename: "cmd"; Parameters: "/k ""{app}\bin\Win32\GPSsmooth.exe"" -h"; WorkingDir: "{app}\bin\Win32";
|
||||
Name: "{group}\Tools\UGsmooth"; Filename: "cmd"; Parameters: "/k ""{app}\bin\Win32\UGsmooth.exe"" -h"; WorkingDir: "{app}\bin\Win32";
|
||||
Name: "{group}\Tools\MIDSsmooth"; Filename: "cmd"; Parameters: "/k ""{app}\bin\Win32\MIDSsmooth.exe"" -h"; WorkingDir: "{app}\bin\Win32";
|
||||
Name: "{group}\Tools\metar"; Filename: "cmd"; Parameters: "/k ""{app}\bin\Win32\metar.exe"" -h"; WorkingDir: "{app}\bin\Win32";
|
||||
Name: "{group}\Tools\yasim"; Filename: "cmd"; Parameters: "/k ""{app}\bin\Win32\yasim.exe"" -h"; WorkingDir: "{app}\bin\Win32";
|
||||
|
||||
Name: "{group}\Tools\Explore Documentation Folder"; Filename: "{app}\data\Docs"
|
||||
|
||||
; For running flightgear directly
|
||||
; Name: "{userdesktop}\FlightGear {#FGVER}"; Filename: "{app}\bin\Win32\fgfs.exe"; Parameters: "--fg-root=."; WorkingDir: "{app}"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\bin\vcredist_x86.exe"; WorkingDir: "{app}"; Parameters: "/qb!"; Description: "Installing Flightgear prerequisites"
|
||||
|
||||
; Put installation directory into the fgrun.prefs
|
||||
filename: "{app}\bin\Win32\fgrun.exe"; WorkingDir: "{app}\bin\Win32"; Parameters: "--silent ""--fg-exe={app}\bin\Win32\fgfs.exe"" ""--ts-exe={app}\bin\Win32\terrasync.exe"" ""--fg-root={app}\data"" ""--fg-scenery={app}\data\Scenery;{app}\scenery;{code:TerrasyncDir}"" --ts-dir=3"
|
||||
|
||||
; Put installation and source directories into the fgadmin.prefs
|
||||
filename: "{app}\bin\Win32\fgadmin.exe"; WorkingDir: "{app}\bin\Win32"; Parameters: "--silent ""--install-source={src}\..\Scenery"" ""--scenery-dest={app}\scenery"""
|
||||
Filename: "{app}\bin\oalinst.exe"; WorkingDir: "{app}"; Description: "Installing OpenAL"; Tasks: insoal
|
||||
;Filename: "{app}\bin\Win32\fgrun.exe"; WorkingDir: "{app}"; Description: "Launch FlightGear"; Flags: postinstall skipifsilent
|
||||
|
||||
[Registry]
|
||||
Root: HKLM; Subkey: "Software\flightgear.org {#FGVER}"; ValueType: string; ValueName: "TerrasyncDir"; ValueData: "{code:TerrasyncDir}"
|
||||
|
||||
[Code]
|
||||
var
|
||||
TerrasyncDirPage: TInputDirWizardPage;
|
||||
|
||||
procedure URLLabelOnClick(Sender: TObject);
|
||||
var
|
||||
ErrorCode: Integer;
|
||||
begin
|
||||
ShellExec('open', 'http://www.flightgear.org', '', '', SW_SHOWNORMAL, ewNoWait, ErrorCode);
|
||||
end;
|
||||
|
||||
procedure CreateURLLabel(ParentForm: TSetupForm; CancelButton: TNewButton);
|
||||
var
|
||||
URLLabel: TNewStaticText;
|
||||
begin
|
||||
URLLabel := TNewStaticText.Create(ParentForm);
|
||||
URLLabel.Caption := 'www.flightgear.org';
|
||||
URLLabel.Cursor := crHand;
|
||||
URLLabel.OnClick := @URLLabelOnClick;
|
||||
URLLabel.Parent := ParentForm;
|
||||
{ Alter Font *after* setting Parent so the correct defaults are inherited first }
|
||||
URLLabel.Font.Style := URLLabel.Font.Style + [fsUnderline];
|
||||
URLLabel.Font.Color := clBlue;
|
||||
URLLabel.Top := CancelButton.Top + CancelButton.Height - URLLabel.Height - 2;
|
||||
URLLabel.Left := ScaleX(20);
|
||||
end;
|
||||
|
||||
procedure InitializeWizard();
|
||||
begin
|
||||
TerrasyncDirPage := CreateInputDirPage(wpSelectDir,
|
||||
'Select Terrasync Directory', 'Where should scenery downloaded by Terrasync be put?',
|
||||
'Select the folder in which Terrasync would download additional scenery, then click Next.',
|
||||
False, 'Terrasync Folder');
|
||||
TerrasyncDirPage.Add('');
|
||||
|
||||
CreateURLLabel(WizardForm, WizardForm.CancelButton);
|
||||
end;
|
||||
|
||||
function NextButtonClick(CurPageID: Integer): Boolean;
|
||||
begin
|
||||
if CurPageID = wpSelectDir then begin
|
||||
TerrasyncDirPage.Values[0] := GetPreviousData( 'TerrasyncDir', ExpandConstant('{reg:HKLM\Software\flightgear.org,TerrasyncDir|{app}\terrasync}') );
|
||||
end;
|
||||
Result := True;
|
||||
end;
|
||||
|
||||
function TerrasyncDir(Param: String): String;
|
||||
begin
|
||||
Result := TerrasyncDirPage.Values[0];
|
||||
end;
|
||||
|
||||
procedure RegisterPreviousData(PreviousDataKey: Integer);
|
||||
begin
|
||||
{ Store the settings so we can restore them next time }
|
||||
SetPreviousData(PreviousDataKey, 'TerrasyncDir', TerrasyncDirPage.Values[0]);
|
||||
end;
|
||||
|
||||
function UpdateReadyMemo(Space, NewLine, MemoUserInfoInfo, MemoDirInfo, MemoTypeInfo, MemoComponentsInfo, MemoGroupInfo, MemoTasksInfo: String): String;
|
||||
var
|
||||
S: String;
|
||||
begin
|
||||
S := '';
|
||||
S := S + MemoDirInfo + NewLine + NewLine;
|
||||
S := S + 'Terrasync folder:' + NewLine;
|
||||
S := S + Space + TerrasyncDirPage.Values[0] + NewLine + NewLine;
|
||||
S := S + MemoGroupInfo + NewLine + NewLine;
|
||||
S := S + MemoTasksInfo + NewLine + NewLine;
|
||||
|
||||
Result := S;
|
||||
end;
|
|
@ -1819,6 +1819,10 @@
|
|||
<File
|
||||
RelativePath="..\..\src\instrumentation\wxradar.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\instrumentation\tcas.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\autopilot\xmlauto.hxx"
|
||||
|
@ -3566,6 +3570,10 @@
|
|||
RelativePath="..\..\src\instrumentation\wxradar.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\instrumentation\tcas.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\src\autopilot\xmlauto.cxx"
|
||||
>
|
||||
|
|
|
@ -3784,6 +3784,14 @@
|
|||
<File
|
||||
RelativePath="..\..\..\src\Instrumentation\wxradar.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Instrumentation\tcas.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Instrumentation\tcas.hxx"
|
||||
>
|
||||
</File>
|
||||
<Filter
|
||||
Name="Lib_HUD"
|
||||
|
|
|
@ -332,6 +332,7 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
|
|||
use_perf_vs = false;
|
||||
tgt_vs = (curr->crossat - altitude_ft) / (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr)
|
||||
/ 6076.0 / speed*60.0);
|
||||
checkTcas();
|
||||
tgt_altitude_ft = curr->crossat;
|
||||
} else {
|
||||
use_perf_vs = true;
|
||||
|
@ -343,6 +344,32 @@ void FGAIAircraft::ProcessFlightPlan( double dt, time_t now ) {
|
|||
}
|
||||
}
|
||||
|
||||
void FGAIAircraft::checkTcas(void)
|
||||
{
|
||||
if (props->getIntValue("tcas/threat-level",0)==3)
|
||||
{
|
||||
int RASense = props->getIntValue("tcas/ra-sense",0);
|
||||
if ((RASense>0)&&(tgt_vs<4000))
|
||||
// upward RA: climb!
|
||||
tgt_vs = 4000;
|
||||
else
|
||||
if (RASense<0)
|
||||
{
|
||||
// downward RA: descend!
|
||||
if (altitude_ft < 1000)
|
||||
{
|
||||
// too low: level off
|
||||
if (tgt_vs>0)
|
||||
tgt_vs = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tgt_vs >- 4000)
|
||||
tgt_vs = -4000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FGAIAircraft::initializeFlightPlan() {
|
||||
}
|
||||
|
@ -603,6 +630,7 @@ void FGAIAircraft::handleFirstWaypoint() {
|
|||
tgt_vs = (curr->crossat - prev->altitude)
|
||||
/ (fp->getDistanceToGo(pos.getLatitudeDeg(), pos.getLongitudeDeg(), curr)
|
||||
/ 6076.0 / prev->speed*60.0);
|
||||
checkTcas();
|
||||
tgt_altitude_ft = curr->crossat;
|
||||
} else {
|
||||
use_perf_vs = true;
|
||||
|
@ -1025,6 +1053,7 @@ void FGAIAircraft::updateVerticalSpeedTarget() {
|
|||
}
|
||||
} //else
|
||||
// tgt_vs = 0.0;
|
||||
checkTcas();
|
||||
}
|
||||
|
||||
void FGAIAircraft::updatePitchAngleTarget() {
|
||||
|
@ -1183,4 +1212,4 @@ time_t FGAIAircraft::checkForArrivalTime(string wptName) {
|
|||
cerr << "Checking arrival time: ete " << ete << ". Time to go : " << secondsToGo << ". Track length = " << tracklength << endl;
|
||||
}
|
||||
return (ete - secondsToGo); // Positive when we're too slow...
|
||||
}
|
||||
}
|
||||
|
|
|
@ -94,6 +94,7 @@ public:
|
|||
inline double airspeed() const { return props->getFloatValue("velocities/airspeed-kt");};
|
||||
std::string atGate();
|
||||
|
||||
void checkTcas();
|
||||
|
||||
protected:
|
||||
void Run(double dt);
|
||||
|
|
|
@ -39,11 +39,11 @@ FGAIMultiplayer::FGAIMultiplayer() : FGAIBase(otMultiplayer) {
|
|||
mTimeOffsetSet = false;
|
||||
mAllowExtrapolation = true;
|
||||
mLagAdjustSystemSpeed = 10;
|
||||
|
||||
mLastTimestamp = 0;
|
||||
aip.getSceneGraph()->setNodeMask(~SG_NODEMASK_TERRAIN_BIT);
|
||||
lastUpdateTime = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
FGAIMultiplayer::~FGAIMultiplayer() {
|
||||
}
|
||||
|
@ -417,8 +417,21 @@ void FGAIMultiplayer::update(double dt)
|
|||
|
||||
// extract the position
|
||||
pos = SGGeod::fromCart(ecPos);
|
||||
double recent_alt_ft = altitude_ft;
|
||||
altitude_ft = pos.getElevationFt();
|
||||
|
||||
// expose a valid vertical speed
|
||||
if (lastUpdateTime != 0)
|
||||
{
|
||||
double dT = curtime - lastUpdateTime;
|
||||
double Weighting=1;
|
||||
if (dt < 1.0)
|
||||
Weighting = dt;
|
||||
// simple smoothing over 1 second
|
||||
vs = (1.0-Weighting)*vs + Weighting * (altitude_ft - recent_alt_ft) / dT * 60;
|
||||
}
|
||||
lastUpdateTime = curtime;
|
||||
|
||||
// The quaternion rotating from the earth centered frame to the
|
||||
// horizontal local frame
|
||||
SGQuatf qEc2Hl = SGQuatf::fromLonLatRad((float)pos.getLongitudeRad(),
|
||||
|
|
|
@ -78,6 +78,8 @@ private:
|
|||
double mTimeOffset;
|
||||
bool mTimeOffsetSet;
|
||||
|
||||
double lastUpdateTime;
|
||||
|
||||
/// Properties which are for now exposed for testing
|
||||
bool mAllowExtrapolation;
|
||||
double mLagAdjustSystemSpeed;
|
||||
|
|
|
@ -428,7 +428,7 @@ void FGAIWingman::Join(double dt) {
|
|||
//double approx_angle = atan2(daltM, range);
|
||||
double frm_spd = 50; // formation speed
|
||||
double join_rnge = 1000.0;
|
||||
double recip_parent_hdg = calcRecipBearingDeg(parent_hdg);
|
||||
// double recip_parent_hdg = calcRecipBearingDeg(parent_hdg);
|
||||
int turn = SGMiscd::sign(rel_brg);// turn direction: 1 = right, -1 = left
|
||||
|
||||
if (range <= join_rnge && (hdg >= hdg_l_lim || hdg <= hdg_r_lim)){
|
||||
|
|
|
@ -162,8 +162,8 @@ double FGClouds::buildCloud(SGPropertyNode *cloud_def_root, SGPropertyNode *box_
|
|||
double bottom_shade = cld_def->getDoubleValue("bottom-shade", 1.0);
|
||||
string texture = cld_def->getStringValue("texture", "cu.png");
|
||||
|
||||
SGNewCloud *cld =
|
||||
new SGNewCloud(type,
|
||||
SGNewCloud cld =
|
||||
SGNewCloud(type,
|
||||
texture_root,
|
||||
texture,
|
||||
min_width,
|
||||
|
@ -178,7 +178,7 @@ double FGClouds::buildCloud(SGPropertyNode *cloud_def_root, SGPropertyNode *box_
|
|||
num_sprites,
|
||||
num_textures_x,
|
||||
num_textures_y);
|
||||
layer->addCloud(newpos, cld);
|
||||
layer->addCloud(newpos, cld.genCloud());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,6 +69,7 @@ LiveMetarProperties::LiveMetarProperties( SGPropertyNode_ptr rootNode ) :
|
|||
|
||||
LiveMetarProperties::~LiveMetarProperties()
|
||||
{
|
||||
_tiedProperties.Untie();
|
||||
}
|
||||
|
||||
void LiveMetarProperties::update( double dt )
|
||||
|
@ -106,7 +107,7 @@ protected:
|
|||
bool _enabled;
|
||||
bool __enabled;
|
||||
simgear::TiedPropertyList _tiedProperties;
|
||||
; typedef std::vector<LiveMetarProperties_ptr> MetarPropertiesList;
|
||||
typedef std::vector<LiveMetarProperties_ptr> MetarPropertiesList;
|
||||
MetarPropertiesList _metarProperties;
|
||||
};
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@
|
|||
#define _REALWX_CTRL_HXX
|
||||
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
namespace Environment {
|
||||
class RealWxController : public SGSubsystem
|
||||
{
|
||||
|
|
|
@ -68,6 +68,11 @@ TankProperties::~TankProperties()
|
|||
{
|
||||
}
|
||||
|
||||
void TankProperties::unbind()
|
||||
{
|
||||
_tiedProperties.Untie();
|
||||
}
|
||||
|
||||
double TankProperties::getContent_kg() const
|
||||
{
|
||||
return _content_kg;
|
||||
|
@ -286,4 +291,10 @@ double TankPropertiesList::getTotalContent_norm() const
|
|||
return capacity > SGLimitsd::min() ? content / capacity : 0.0;
|
||||
}
|
||||
|
||||
|
||||
void TankPropertiesList::unbind()
|
||||
{
|
||||
for( const_iterator it = begin(); it != end(); ++it ) {
|
||||
(*it)->unbind();
|
||||
}
|
||||
_tiedProperties.Untie();
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ public:
|
|||
TankProperties( const TankProperties & );
|
||||
const TankProperties & operator = ( const TankProperties & );
|
||||
|
||||
void unbind();
|
||||
|
||||
double getContent_kg() const;
|
||||
void setContent_kg( double value );
|
||||
|
||||
|
@ -98,6 +100,8 @@ public:
|
|||
double getTotalContent_m3() const;
|
||||
double getTotalContent_norm() const;
|
||||
|
||||
void unbind();
|
||||
|
||||
private:
|
||||
simgear::TiedPropertyList _tiedProperties;
|
||||
};
|
||||
|
|
|
@ -102,6 +102,7 @@ void FDMShell::bind()
|
|||
void FDMShell::unbind()
|
||||
{
|
||||
if( _impl ) _impl->unbind();
|
||||
_tankProperties.unbind();
|
||||
}
|
||||
|
||||
void FDMShell::update(double dt)
|
||||
|
|
|
@ -83,7 +83,7 @@ public:
|
|||
--destIndex;
|
||||
}
|
||||
|
||||
int currentWpIndex = currentWaypoint();
|
||||
unsigned int currentWpIndex = currentWaypoint();
|
||||
WayptRef w(_rm->removeWayptAtIndex(srcIndex));
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "wpt:" << w->ident());
|
||||
_rm->insertWayptAtIndex(w, destIndex);
|
||||
|
|
|
@ -31,6 +31,7 @@ set(SOURCES
|
|||
rnav_waypt_controller.cxx
|
||||
slip_skid_ball.cxx
|
||||
tacan.cxx
|
||||
tcas.cxx
|
||||
transponder.cxx
|
||||
turn_indicator.cxx
|
||||
vertical_speed_indicator.cxx
|
||||
|
|
|
@ -33,6 +33,7 @@ libInstrumentation_a_SOURCES = \
|
|||
render_area_2d.cxx render_area_2d.hxx \
|
||||
groundradar.cxx groundradar.hxx \
|
||||
agradar.cxx agradar.hxx rad_alt.cxx rad_alt.hxx \
|
||||
rnav_waypt_controller.cxx rnav_waypt_controller.hxx
|
||||
rnav_waypt_controller.cxx rnav_waypt_controller.hxx \
|
||||
tcas.cxx tcas.hxx
|
||||
|
||||
INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/src -I$(top_builddir)/src
|
||||
|
|
|
@ -33,6 +33,7 @@
|
|||
#include <map>
|
||||
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <Navaids/positioned.hxx>
|
||||
|
||||
class SGTime;
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
#include "groundradar.hxx"
|
||||
#include "agradar.hxx"
|
||||
#include "rad_alt.hxx"
|
||||
#include "tcas.hxx"
|
||||
|
||||
FGInstrumentMgr::FGInstrumentMgr () :
|
||||
_explicitGps(false)
|
||||
|
@ -223,6 +224,9 @@ bool FGInstrumentMgr::build (SGPropertyNode* config_props)
|
|||
} else if ( name == "radar-altimeter" ) {
|
||||
set_subsystem( id, new radAlt( node ),1);
|
||||
|
||||
} else if ( name == "tcas" ) {
|
||||
set_subsystem( id, new TCAS( node ) );
|
||||
|
||||
} else {
|
||||
SG_LOG( SG_ALL, SG_ALERT, "Unknown top level section: "
|
||||
<< name );
|
||||
|
|
|
@ -210,17 +210,6 @@ MK_VIII::PropertiesHandler::init ()
|
|||
mk_node(vs) = fgGetNode("/velocities/vertical-speed-fps", true);
|
||||
}
|
||||
|
||||
void
|
||||
MK_VIII::PropertiesHandler::unbind ()
|
||||
{
|
||||
vector<SGPropertyNode_ptr>::iterator iter;
|
||||
|
||||
for (iter = tied_properties.begin(); iter != tied_properties.end(); iter++)
|
||||
(*iter)->untie();
|
||||
|
||||
tied_properties.clear();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// PowerHandler ///////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1858,7 +1847,8 @@ MK_VIII::IOHandler::tie_input (SGPropertyNode *node,
|
|||
bool *input,
|
||||
bool *feed)
|
||||
{
|
||||
mk->properties_handler.tie(node, (string("inputs/discretes/") + name).c_str(), RawValueMethodsData<MK_VIII::IOHandler, bool, bool *>(*this, input, &MK_VIII::IOHandler::get_discrete_input, &MK_VIII::IOHandler::set_discrete_input));
|
||||
mk->properties_handler.tie(node, (string("inputs/discretes/") + name).c_str(),
|
||||
FGVoicePlayer::RawValueMethodsData<MK_VIII::IOHandler, bool, bool *>(*this, input, &MK_VIII::IOHandler::get_discrete_input, &MK_VIII::IOHandler::set_discrete_input));
|
||||
if (feed)
|
||||
mk->properties_handler.tie(node, (string("input-feeders/discretes/") + name).c_str(), SGRawValuePointer<bool>(feed));
|
||||
}
|
||||
|
@ -2144,11 +2134,22 @@ MK_VIII::IOHandler::set_present_status (bool value)
|
|||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// VoicePlayer ////////////////////////////////////////////////////////////////
|
||||
// FGVoicePlayer //////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
MK_VIII::VoicePlayer::Speaker::bind (SGPropertyNode *node)
|
||||
FGVoicePlayer::PropertiesHandler::unbind ()
|
||||
{
|
||||
vector<SGPropertyNode_ptr>::iterator iter;
|
||||
|
||||
for (iter = tied_properties.begin(); iter != tied_properties.end(); iter++)
|
||||
(*iter)->untie();
|
||||
|
||||
tied_properties.clear();
|
||||
}
|
||||
|
||||
void
|
||||
FGVoicePlayer::Speaker::bind (SGPropertyNode *node)
|
||||
{
|
||||
// uses xmlsound property names
|
||||
tie(node, "volume", &volume);
|
||||
|
@ -2156,7 +2157,7 @@ MK_VIII::VoicePlayer::Speaker::bind (SGPropertyNode *node)
|
|||
}
|
||||
|
||||
void
|
||||
MK_VIII::VoicePlayer::Speaker::update_configuration ()
|
||||
FGVoicePlayer::Speaker::update_configuration ()
|
||||
{
|
||||
map< string, SGSharedPtr<SGSoundSample> >::iterator iter;
|
||||
for (iter = player->samples.begin(); iter != player->samples.end(); iter++)
|
||||
|
@ -2170,7 +2171,7 @@ MK_VIII::VoicePlayer::Speaker::update_configuration ()
|
|||
player->voice->volume_changed();
|
||||
}
|
||||
|
||||
MK_VIII::VoicePlayer::Voice::~Voice ()
|
||||
FGVoicePlayer::Voice::~Voice ()
|
||||
{
|
||||
for (iter = elements.begin(); iter != elements.end(); iter++)
|
||||
delete *iter; // we owned the element
|
||||
|
@ -2178,7 +2179,7 @@ MK_VIII::VoicePlayer::Voice::~Voice ()
|
|||
}
|
||||
|
||||
void
|
||||
MK_VIII::VoicePlayer::Voice::play ()
|
||||
FGVoicePlayer::Voice::play ()
|
||||
{
|
||||
iter = elements.begin();
|
||||
element = *iter;
|
||||
|
@ -2187,7 +2188,7 @@ MK_VIII::VoicePlayer::Voice::play ()
|
|||
}
|
||||
|
||||
void
|
||||
MK_VIII::VoicePlayer::Voice::stop (bool now)
|
||||
FGVoicePlayer::Voice::stop (bool now)
|
||||
{
|
||||
if (element)
|
||||
{
|
||||
|
@ -2202,21 +2203,21 @@ MK_VIII::VoicePlayer::Voice::stop (bool now)
|
|||
}
|
||||
|
||||
void
|
||||
MK_VIII::VoicePlayer::Voice::set_volume (float _volume)
|
||||
FGVoicePlayer::Voice::set_volume (float _volume)
|
||||
{
|
||||
volume = _volume;
|
||||
volume_changed();
|
||||
}
|
||||
|
||||
void
|
||||
MK_VIII::VoicePlayer::Voice::volume_changed ()
|
||||
FGVoicePlayer::Voice::volume_changed ()
|
||||
{
|
||||
if (element)
|
||||
element->set_volume(get_volume());
|
||||
}
|
||||
|
||||
void
|
||||
MK_VIII::VoicePlayer::Voice::update ()
|
||||
FGVoicePlayer::Voice::update ()
|
||||
{
|
||||
if (element)
|
||||
{
|
||||
|
@ -2233,7 +2234,7 @@ MK_VIII::VoicePlayer::Voice::update ()
|
|||
}
|
||||
}
|
||||
|
||||
MK_VIII::VoicePlayer::~VoicePlayer ()
|
||||
FGVoicePlayer::~FGVoicePlayer ()
|
||||
{
|
||||
vector<Voice *>::iterator iter1;
|
||||
for (iter1 = _voices.begin(); iter1 != _voices.end(); iter1++)
|
||||
|
@ -2243,85 +2244,80 @@ MK_VIII::VoicePlayer::~VoicePlayer ()
|
|||
}
|
||||
|
||||
void
|
||||
MK_VIII::VoicePlayer::init ()
|
||||
FGVoicePlayer::bind (SGPropertyNode *node, const char* default_dir_prefix)
|
||||
{
|
||||
#define STDPAUSE 0.75 // [SPEC] 6.4.4: "the standard 0.75 second delay"
|
||||
dir_prefix = node->getStringValue("voice/file-prefix", default_dir_prefix);
|
||||
speaker.bind(node);
|
||||
}
|
||||
|
||||
void
|
||||
FGVoicePlayer::init ()
|
||||
{
|
||||
SGSoundMgr *smgr = globals->get_soundmgr();
|
||||
_sgr = smgr->find("avionics", true);
|
||||
_sgr->tie_to_listener();
|
||||
|
||||
make_voice(&voices.application_data_base_failed, "application-data-base-failed");
|
||||
make_voice(&voices.bank_angle, "bank-angle");
|
||||
make_voice(&voices.bank_angle_bank_angle, "bank-angle", "bank-angle");
|
||||
make_voice(&voices.bank_angle_bank_angle_3, "bank-angle", "bank-angle", 3.0);
|
||||
make_voice(&voices.bank_angle_inop, "bank-angle-inop");
|
||||
make_voice(&voices.bank_angle_pause_bank_angle, "bank-angle", STDPAUSE, "bank-angle");
|
||||
make_voice(&voices.bank_angle_pause_bank_angle_3, "bank-angle", STDPAUSE, "bank-angle", 3.0);
|
||||
make_voice(&voices.callouts_inop, "callouts-inop");
|
||||
make_voice(&voices.configuration_type_invalid, "configuration-type-invalid");
|
||||
make_voice(&voices.dont_sink, "dont-sink");
|
||||
make_voice(&voices.dont_sink_pause_dont_sink, "dont-sink", STDPAUSE, "dont-sink");
|
||||
make_voice(&voices.five_hundred_above, "500-above");
|
||||
make_voice(&voices.glideslope, "glideslope");
|
||||
make_voice(&voices.glideslope_inop, "glideslope-inop");
|
||||
make_voice(&voices.gpws_inop, "gpws-inop");
|
||||
make_voice(&voices.hard_glideslope, "glideslope", "glideslope", 3.0);
|
||||
make_voice(&voices.minimums, "minimums");
|
||||
make_voice(&voices.minimums_minimums, "minimums", "minimums");
|
||||
make_voice(&voices.pull_up, "pull-up");
|
||||
make_voice(&voices.sink_rate, "sink-rate");
|
||||
make_voice(&voices.sink_rate_pause_sink_rate, "sink-rate", STDPAUSE, "sink-rate");
|
||||
make_voice(&voices.soft_glideslope, new Voice::SampleElement(get_sample("glideslope"), modify_amplitude(1.0, -6)));
|
||||
make_voice(&voices.terrain, "terrain");
|
||||
make_voice(&voices.terrain_pause_terrain, "terrain", STDPAUSE, "terrain");
|
||||
make_voice(&voices.too_low_flaps, "too-low-flaps");
|
||||
make_voice(&voices.too_low_gear, "too-low-gear");
|
||||
make_voice(&voices.too_low_terrain, "too-low-terrain");
|
||||
|
||||
for (unsigned i = 0; i < n_altitude_callouts; i++)
|
||||
{
|
||||
std::ostringstream name;
|
||||
name << "altitude-" << mk->mode6_handler.altitude_callout_definitions[i];
|
||||
make_voice(&voices.altitude_callouts[i], name.str().c_str());
|
||||
}
|
||||
|
||||
speaker.update_configuration();
|
||||
}
|
||||
|
||||
SGSoundSample *
|
||||
MK_VIII::VoicePlayer::get_sample (const char *name)
|
||||
void
|
||||
FGVoicePlayer::pause()
|
||||
{
|
||||
std::ostringstream refname;
|
||||
refname << mk->name << "[" << mk->num << "]" << "/" << name;
|
||||
if (paused)
|
||||
return;
|
||||
|
||||
SGSoundSample *sample = _sgr->find(refname.str());
|
||||
paused = true;
|
||||
if (voice)
|
||||
{
|
||||
voice->stop(true);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
FGVoicePlayer::resume()
|
||||
{
|
||||
if (!paused)
|
||||
return;
|
||||
paused = false;
|
||||
if (voice)
|
||||
{
|
||||
voice->play();
|
||||
}
|
||||
}
|
||||
|
||||
SGSoundSample *
|
||||
FGVoicePlayer::get_sample (const char *name)
|
||||
{
|
||||
string refname;
|
||||
refname = dev_name + "/" + dir_prefix + name;
|
||||
|
||||
SGSoundSample *sample = _sgr->find(refname);
|
||||
if (! sample)
|
||||
{
|
||||
string filename = "Sounds/mk-viii/" + string(name) + ".wav";
|
||||
string filename = dir_prefix + string(name) + ".wav";
|
||||
try
|
||||
{
|
||||
sample = new SGSoundSample(filename.c_str(), SGPath());
|
||||
}
|
||||
catch (const sg_exception &e)
|
||||
{
|
||||
SG_LOG(SG_INSTR, SG_ALERT, "Error loading MK VIII sound sample \"" + filename + "\": " + e.getFormattedMessage());
|
||||
SG_LOG(SG_INSTR, SG_ALERT, "Error loading sound sample \"" + filename + "\": " + e.getFormattedMessage());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
_sgr->add(sample, refname.str());
|
||||
samples[refname.str()] = sample;
|
||||
_sgr->add(sample, refname);
|
||||
samples[refname] = sample;
|
||||
}
|
||||
|
||||
return sample;
|
||||
}
|
||||
|
||||
void
|
||||
MK_VIII::VoicePlayer::play (Voice *_voice, unsigned int flags)
|
||||
FGVoicePlayer::play (Voice *_voice, unsigned int flags)
|
||||
{
|
||||
if (!_voice)
|
||||
return;
|
||||
if (test_bits(flags, PLAY_NOW) || ! voice || voice->element->silence)
|
||||
if (test_bits(flags, PLAY_NOW) || ! voice ||
|
||||
(voice->element && voice->element->silence))
|
||||
{
|
||||
if (voice)
|
||||
voice->stop(true);
|
||||
|
@ -2332,7 +2328,8 @@ MK_VIII::VoicePlayer::play (Voice *_voice, unsigned int flags)
|
|||
next_voice = NULL;
|
||||
next_looped = false;
|
||||
|
||||
voice->play();
|
||||
if (!paused)
|
||||
voice->play();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -2342,7 +2339,7 @@ MK_VIII::VoicePlayer::play (Voice *_voice, unsigned int flags)
|
|||
}
|
||||
|
||||
void
|
||||
MK_VIII::VoicePlayer::stop (unsigned int flags)
|
||||
FGVoicePlayer::stop (unsigned int flags)
|
||||
{
|
||||
if (voice)
|
||||
{
|
||||
|
@ -2356,7 +2353,7 @@ MK_VIII::VoicePlayer::stop (unsigned int flags)
|
|||
}
|
||||
|
||||
void
|
||||
MK_VIII::VoicePlayer::set_volume (float _volume)
|
||||
FGVoicePlayer::set_volume (float _volume)
|
||||
{
|
||||
volume = _volume;
|
||||
if (voice)
|
||||
|
@ -2364,7 +2361,7 @@ MK_VIII::VoicePlayer::set_volume (float _volume)
|
|||
}
|
||||
|
||||
void
|
||||
MK_VIII::VoicePlayer::update ()
|
||||
FGVoicePlayer::update ()
|
||||
{
|
||||
if (voice)
|
||||
{
|
||||
|
@ -2396,6 +2393,53 @@ MK_VIII::VoicePlayer::update ()
|
|||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// MK_VIII::VoicePlayer ///////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
MK_VIII::VoicePlayer::init ()
|
||||
{
|
||||
FGVoicePlayer::init();
|
||||
|
||||
#define STDPAUSE 0.75 // [SPEC] 6.4.4: "the standard 0.75 second delay"
|
||||
make_voice(&voices.application_data_base_failed, "application-data-base-failed");
|
||||
make_voice(&voices.bank_angle, "bank-angle");
|
||||
make_voice(&voices.bank_angle_bank_angle, "bank-angle", "bank-angle");
|
||||
make_voice(&voices.bank_angle_bank_angle_3, "bank-angle", "bank-angle", 3.0);
|
||||
make_voice(&voices.bank_angle_inop, "bank-angle-inop");
|
||||
make_voice(&voices.bank_angle_pause_bank_angle, "bank-angle", STDPAUSE, "bank-angle");
|
||||
make_voice(&voices.bank_angle_pause_bank_angle_3, "bank-angle", STDPAUSE, "bank-angle", 3.0);
|
||||
make_voice(&voices.callouts_inop, "callouts-inop");
|
||||
make_voice(&voices.configuration_type_invalid, "configuration-type-invalid");
|
||||
make_voice(&voices.dont_sink, "dont-sink");
|
||||
make_voice(&voices.dont_sink_pause_dont_sink, "dont-sink", STDPAUSE, "dont-sink");
|
||||
make_voice(&voices.five_hundred_above, "500-above");
|
||||
make_voice(&voices.glideslope, "glideslope");
|
||||
make_voice(&voices.glideslope_inop, "glideslope-inop");
|
||||
make_voice(&voices.gpws_inop, "gpws-inop");
|
||||
make_voice(&voices.hard_glideslope, "glideslope", "glideslope", 3.0);
|
||||
make_voice(&voices.minimums, "minimums");
|
||||
make_voice(&voices.minimums_minimums, "minimums", "minimums");
|
||||
make_voice(&voices.pull_up, "pull-up");
|
||||
make_voice(&voices.sink_rate, "sink-rate");
|
||||
make_voice(&voices.sink_rate_pause_sink_rate, "sink-rate", STDPAUSE, "sink-rate");
|
||||
make_voice(&voices.soft_glideslope, new Voice::SampleElement(get_sample("glideslope"), modify_amplitude(1.0, -6)));
|
||||
make_voice(&voices.terrain, "terrain");
|
||||
make_voice(&voices.terrain_pause_terrain, "terrain", STDPAUSE, "terrain");
|
||||
make_voice(&voices.too_low_flaps, "too-low-flaps");
|
||||
make_voice(&voices.too_low_gear, "too-low-gear");
|
||||
make_voice(&voices.too_low_terrain, "too-low-terrain");
|
||||
|
||||
for (unsigned i = 0; i < n_altitude_callouts; i++)
|
||||
{
|
||||
std::ostringstream name;
|
||||
name << "altitude-" << MK_VIII::Mode6Handler::altitude_callout_definitions[i];
|
||||
make_voice(&voices.altitude_callouts[i], name.str().c_str());
|
||||
}
|
||||
speaker.update_configuration();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// SelfTestHandler ////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -4949,7 +4993,7 @@ MK_VIII::bind ()
|
|||
configuration_module.bind(node);
|
||||
power_handler.bind(node);
|
||||
io_handler.bind(node);
|
||||
voice_player.bind(node);
|
||||
voice_player.bind(node, "Sounds/mk-viii/");
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -47,6 +47,295 @@ class SGSampleGroup;
|
|||
# pragma warning( disable: 4355 )
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// FGVoicePlayer /////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class FGVoicePlayer
|
||||
{
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// MK::RawValueMethodsData /////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class C, class VT, class DT>
|
||||
class RawValueMethodsData : public SGRawValue<VT>
|
||||
{
|
||||
public:
|
||||
typedef VT (C::*getter_t) (DT) const;
|
||||
typedef void (C::*setter_t) (DT, VT);
|
||||
|
||||
RawValueMethodsData (C &obj, DT data, getter_t getter = 0, setter_t setter = 0)
|
||||
: _obj(obj), _data(data), _getter(getter), _setter(setter) {}
|
||||
|
||||
virtual VT getValue () const
|
||||
{
|
||||
if (_getter)
|
||||
return (_obj.*_getter)(_data);
|
||||
else
|
||||
return SGRawValue<VT>::DefaultValue();
|
||||
}
|
||||
virtual bool setValue (VT value)
|
||||
{
|
||||
if (_setter)
|
||||
{
|
||||
(_obj.*_setter)(_data, value);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
virtual SGRawValue<VT> *clone () const
|
||||
{
|
||||
return new RawValueMethodsData<C,VT,DT>(_obj, _data, _getter, _setter);
|
||||
}
|
||||
|
||||
private:
|
||||
C &_obj;
|
||||
DT _data;
|
||||
getter_t _getter;
|
||||
setter_t _setter;
|
||||
};
|
||||
|
||||
class PropertiesHandler
|
||||
{
|
||||
public:
|
||||
vector<SGPropertyNode_ptr> tied_properties;
|
||||
|
||||
template <class T>
|
||||
inline void tie (SGPropertyNode *node, const SGRawValue<T> &raw_value)
|
||||
{
|
||||
node->tie(raw_value);
|
||||
tied_properties.push_back(node);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void tie (SGPropertyNode *node,
|
||||
const char *relative_path,
|
||||
const SGRawValue<T> &raw_value)
|
||||
{
|
||||
tie(node->getNode(relative_path, true), raw_value);
|
||||
}
|
||||
|
||||
PropertiesHandler() {};
|
||||
|
||||
void unbind ();
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// FGVoicePlayer::Voice ////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Voice
|
||||
{
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// FGVoicePlayer::Voice::Element ////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Element
|
||||
{
|
||||
public:
|
||||
bool silence;
|
||||
|
||||
virtual inline void play (float volume) {}
|
||||
virtual inline void stop () {}
|
||||
virtual bool is_playing () = 0;
|
||||
virtual inline void set_volume (float volume) {}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// FGVoicePlayer::Voice::SampleElement ///////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class SampleElement : public Element
|
||||
{
|
||||
SGSharedPtr<SGSoundSample> _sample;
|
||||
float _volume;
|
||||
|
||||
public:
|
||||
inline SampleElement (SGSharedPtr<SGSoundSample> sample, float volume = 1.0)
|
||||
: _sample(sample), _volume(volume) { silence = false; }
|
||||
|
||||
virtual inline void play (float volume) { if (_sample && (volume > 0.05)) { set_volume(volume); _sample->play_once(); } }
|
||||
virtual inline void stop () { if (_sample) _sample->stop(); }
|
||||
virtual inline bool is_playing () { return _sample ? _sample->is_playing() : false; }
|
||||
virtual inline void set_volume (float volume) { if (_sample) _sample->set_volume(volume * _volume); }
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// FGVoicePlayer::Voice::SilenceElement //////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class SilenceElement : public Element
|
||||
{
|
||||
double _duration;
|
||||
double start_time;
|
||||
|
||||
public:
|
||||
inline SilenceElement (double duration)
|
||||
: _duration(duration) { silence = true; }
|
||||
|
||||
virtual inline void play (float volume) { start_time = globals->get_sim_time_sec(); }
|
||||
virtual inline bool is_playing () { return globals->get_sim_time_sec() - start_time < _duration; }
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// FGVoicePlayer::Voice (continued) //////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Element *element;
|
||||
|
||||
inline Voice (FGVoicePlayer *_player)
|
||||
: element(NULL), player(_player), volume(1.0) {}
|
||||
|
||||
~Voice ();
|
||||
|
||||
inline void append (Element *_element) { elements.push_back(_element); }
|
||||
|
||||
void play ();
|
||||
void stop (bool now);
|
||||
void set_volume (float _volume);
|
||||
void volume_changed ();
|
||||
void update ();
|
||||
|
||||
private:
|
||||
FGVoicePlayer *player;
|
||||
|
||||
float volume;
|
||||
|
||||
vector<Element *> elements;
|
||||
vector<Element *>::iterator iter;
|
||||
|
||||
inline float get_volume () const { return player->volume * player->speaker.volume * volume; }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// FGVoicePlayer (continued) ///////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct
|
||||
{
|
||||
float volume;
|
||||
} conf;
|
||||
|
||||
float volume;
|
||||
|
||||
Voice *voice;
|
||||
Voice *next_voice;
|
||||
bool paused;
|
||||
string dev_name;
|
||||
string dir_prefix;
|
||||
|
||||
inline FGVoicePlayer (PropertiesHandler* properties_handler, string _dev_name)
|
||||
: volume(1.0), voice(NULL), next_voice(NULL), paused(false),
|
||||
dev_name(_dev_name), dir_prefix(""),
|
||||
speaker(this,properties_handler) {}
|
||||
|
||||
~FGVoicePlayer ();
|
||||
|
||||
void init ();
|
||||
void pause();
|
||||
void resume();
|
||||
bool is_playing() { return (voice!=NULL);}
|
||||
|
||||
enum
|
||||
{
|
||||
PLAY_NOW = 1 << 0,
|
||||
PLAY_LOOPED = 1 << 1
|
||||
};
|
||||
void play (Voice *_voice, unsigned int flags = 0);
|
||||
|
||||
enum
|
||||
{
|
||||
STOP_NOW = 1 << 0
|
||||
};
|
||||
void stop (unsigned int flags = 0);
|
||||
|
||||
void set_volume (float _volume);
|
||||
void update ();
|
||||
|
||||
void bind (SGPropertyNode *node, const char* default_dir_prefix);
|
||||
|
||||
public:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// FGVoicePlayer::Speaker //////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Speaker
|
||||
{
|
||||
FGVoicePlayer *player;
|
||||
PropertiesHandler* properties_handler;
|
||||
|
||||
double pitch;
|
||||
|
||||
template <class T>
|
||||
inline void tie (SGPropertyNode *node, const char *name, T *ptr)
|
||||
{
|
||||
properties_handler->tie
|
||||
(node, (string("speaker/") + name).c_str(),
|
||||
RawValueMethodsData<FGVoicePlayer::Speaker,T,T*>
|
||||
(*this, ptr,
|
||||
&FGVoicePlayer::Speaker::get_property,
|
||||
&FGVoicePlayer::Speaker::set_property));
|
||||
}
|
||||
|
||||
public:
|
||||
template <class T>
|
||||
inline void set_property (T *ptr, T value) { *ptr = value; update_configuration(); }
|
||||
|
||||
template <class T>
|
||||
inline T get_property (T *ptr) const { return *ptr; }
|
||||
|
||||
float volume;
|
||||
|
||||
inline Speaker (FGVoicePlayer *_player,PropertiesHandler* _properties_handler)
|
||||
: player(_player),
|
||||
properties_handler(_properties_handler),
|
||||
pitch(1),
|
||||
volume(1)
|
||||
{
|
||||
}
|
||||
|
||||
void bind (SGPropertyNode *node);
|
||||
void update_configuration ();
|
||||
};
|
||||
|
||||
protected:
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// FGVoicePlayer (continued) ///////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
SGSharedPtr<SGSampleGroup> _sgr;
|
||||
Speaker speaker;
|
||||
|
||||
map< string, SGSharedPtr<SGSoundSample> > samples;
|
||||
vector<Voice *> _voices;
|
||||
|
||||
bool looped;
|
||||
bool next_looped;
|
||||
|
||||
SGSoundSample *get_sample (const char *name);
|
||||
|
||||
inline void append (Voice *voice, Voice::Element *element) { voice->append(element); }
|
||||
inline void append (Voice *voice, const char *sample_name) { voice->append(new Voice::SampleElement(get_sample(sample_name))); }
|
||||
inline void append (Voice *voice, double silence) { voice->append(new Voice::SilenceElement(silence)); }
|
||||
|
||||
inline void make_voice (Voice **voice) { *voice = new Voice(this); _voices.push_back(*voice); }
|
||||
|
||||
template <class T1>
|
||||
inline void make_voice (Voice **voice, T1 e1) { make_voice(voice); append(*voice, e1); }
|
||||
template <class T1, class T2>
|
||||
inline void make_voice (Voice **voice, T1 e1, T2 e2) { make_voice(voice, e1); append(*voice, e2); }
|
||||
template <class T1, class T2, class T3>
|
||||
inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3) { make_voice(voice, e1, e2); append(*voice, e3); }
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3, T4 e4) { make_voice(voice, e1, e2, e3); append(*voice, e4); }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// MK_VIII ////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -56,49 +345,6 @@ class MK_VIII : public SGSubsystem
|
|||
// keep in sync with Mode6Handler::altitude_callout_definitions[]
|
||||
static const unsigned n_altitude_callouts = 11;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// MK_VIII::RawValueMethodsData /////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
template <class C, class VT, class DT>
|
||||
class RawValueMethodsData : public SGRawValue<VT>
|
||||
{
|
||||
public:
|
||||
typedef VT (C::*getter_t) (DT) const;
|
||||
typedef void (C::*setter_t) (DT, VT);
|
||||
|
||||
RawValueMethodsData (C &obj, DT data, getter_t getter = 0, setter_t setter = 0)
|
||||
: _obj(obj), _data(data), _getter(getter), _setter(setter) {}
|
||||
|
||||
virtual VT getValue () const
|
||||
{
|
||||
if (_getter)
|
||||
return (_obj.*_getter)(_data);
|
||||
else
|
||||
return SGRawValue<VT>::DefaultValue();
|
||||
}
|
||||
virtual bool setValue (VT value)
|
||||
{
|
||||
if (_setter)
|
||||
{
|
||||
(_obj.*_setter)(_data, value);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
virtual SGRawValue<VT> *clone () const
|
||||
{
|
||||
return new RawValueMethodsData<C,VT,DT>(_obj, _data, _getter, _setter);
|
||||
}
|
||||
|
||||
private:
|
||||
C &_obj;
|
||||
DT _data;
|
||||
getter_t _getter;
|
||||
setter_t _setter;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// MK_VIII::Parameter ///////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -184,12 +430,10 @@ class MK_VIII : public SGSubsystem
|
|||
// MK_VIII::PropertiesHandler ///////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class PropertiesHandler
|
||||
class PropertiesHandler : public FGVoicePlayer::PropertiesHandler
|
||||
{
|
||||
MK_VIII *mk;
|
||||
|
||||
vector<SGPropertyNode_ptr> tied_properties;
|
||||
|
||||
public:
|
||||
struct
|
||||
{
|
||||
|
@ -225,27 +469,11 @@ class MK_VIII : public SGSubsystem
|
|||
} external_properties;
|
||||
|
||||
inline PropertiesHandler (MK_VIII *device)
|
||||
: mk(device) {}
|
||||
: FGVoicePlayer::PropertiesHandler(), mk(device) {}
|
||||
|
||||
template <class T>
|
||||
inline void tie (SGPropertyNode *node, const SGRawValue<T> &raw_value)
|
||||
{
|
||||
node->tie(raw_value);
|
||||
tied_properties.push_back(node);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline void tie (SGPropertyNode *node,
|
||||
const char *relative_path,
|
||||
const SGRawValue<T> &raw_value)
|
||||
{
|
||||
tie(node->getNode(relative_path, true), raw_value);
|
||||
}
|
||||
|
||||
PropertiesHandler() {};
|
||||
PropertiesHandler() : FGVoicePlayer::PropertiesHandler() {}
|
||||
|
||||
void init ();
|
||||
void unbind ();
|
||||
};
|
||||
|
||||
public:
|
||||
|
@ -716,250 +944,49 @@ public:
|
|||
|
||||
bool *get_lamp_output (Lamp lamp);
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// MK_VIII::VoicePlayer /////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class VoicePlayer
|
||||
|
||||
class VoicePlayer : public FGVoicePlayer
|
||||
{
|
||||
public:
|
||||
VoicePlayer (MK_VIII *device) :
|
||||
FGVoicePlayer(&device->properties_handler, "mk-viii")
|
||||
{}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// MK_VIII::VoicePlayer::Voice ////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
~VoicePlayer() {}
|
||||
void init ();
|
||||
|
||||
class Voice
|
||||
{
|
||||
public:
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// MK_VIII::VoicePlayer::Voice::Element ////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Element
|
||||
struct
|
||||
{
|
||||
public:
|
||||
bool silence;
|
||||
|
||||
virtual inline void play (float volume) {}
|
||||
virtual inline void stop () {}
|
||||
virtual bool is_playing () = 0;
|
||||
virtual inline void set_volume (float volume) {}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// MK_VIII::VoicePlayer::Voice::SampleElement ///////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class SampleElement : public Element
|
||||
{
|
||||
SGSharedPtr<SGSoundSample> _sample;
|
||||
float _volume;
|
||||
|
||||
public:
|
||||
inline SampleElement (SGSharedPtr<SGSoundSample> sample, float volume = 1.0)
|
||||
: _sample(sample), _volume(volume) { silence = false; }
|
||||
|
||||
virtual inline void play (float volume) { if (_sample && (volume > 0.05)) { set_volume(volume); _sample->play_once(); } }
|
||||
virtual inline void stop () { if (_sample) _sample->stop(); }
|
||||
virtual inline bool is_playing () { return _sample ? _sample->is_playing() : false; }
|
||||
virtual inline void set_volume (float volume) { if (_sample) _sample->set_volume(volume * _volume); }
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// MK_VIII::VoicePlayer::Voice::SilenceElement //////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class SilenceElement : public Element
|
||||
{
|
||||
double _duration;
|
||||
double start_time;
|
||||
|
||||
public:
|
||||
inline SilenceElement (double duration)
|
||||
: _duration(duration) { silence = true; }
|
||||
|
||||
virtual inline void play (float volume) { start_time = globals->get_sim_time_sec(); }
|
||||
virtual inline bool is_playing () { return globals->get_sim_time_sec() - start_time < _duration; }
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
// MK_VIII::VoicePlayer::Voice (continued) //////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Element *element;
|
||||
|
||||
inline Voice (VoicePlayer *_player)
|
||||
: element(NULL), player(_player), volume(1.0) {}
|
||||
|
||||
~Voice ();
|
||||
|
||||
inline void append (Element *_element) { elements.push_back(_element); }
|
||||
|
||||
void play ();
|
||||
void stop (bool now);
|
||||
void set_volume (float _volume);
|
||||
void volume_changed ();
|
||||
void update ();
|
||||
|
||||
private:
|
||||
VoicePlayer *player;
|
||||
|
||||
float volume;
|
||||
|
||||
vector<Element *> elements;
|
||||
vector<Element *>::iterator iter;
|
||||
|
||||
inline float get_volume () const { return player->volume * player->speaker.volume * volume; }
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// MK_VIII::VoicePlayer (continued) ///////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
struct
|
||||
{
|
||||
float volume;
|
||||
} conf;
|
||||
|
||||
float volume;
|
||||
|
||||
Voice *voice;
|
||||
Voice *next_voice;
|
||||
|
||||
struct
|
||||
{
|
||||
Voice *application_data_base_failed;
|
||||
Voice *bank_angle;
|
||||
Voice *bank_angle_bank_angle;
|
||||
Voice *bank_angle_bank_angle_3;
|
||||
Voice *bank_angle_inop;
|
||||
Voice *bank_angle_pause_bank_angle;
|
||||
Voice *bank_angle_pause_bank_angle_3;
|
||||
Voice *callouts_inop;
|
||||
Voice *configuration_type_invalid;
|
||||
Voice *dont_sink;
|
||||
Voice *dont_sink_pause_dont_sink;
|
||||
Voice *five_hundred_above;
|
||||
Voice *glideslope;
|
||||
Voice *glideslope_inop;
|
||||
Voice *gpws_inop;
|
||||
Voice *hard_glideslope;
|
||||
Voice *minimums;
|
||||
Voice *minimums_minimums;
|
||||
Voice *pull_up;
|
||||
Voice *sink_rate;
|
||||
Voice *sink_rate_pause_sink_rate;
|
||||
Voice *soft_glideslope;
|
||||
Voice *terrain;
|
||||
Voice *terrain_pause_terrain;
|
||||
Voice *too_low_flaps;
|
||||
Voice *too_low_gear;
|
||||
Voice *too_low_terrain;
|
||||
Voice *altitude_callouts[n_altitude_callouts];
|
||||
} voices;
|
||||
|
||||
inline VoicePlayer (MK_VIII *device)
|
||||
: voice(NULL), next_voice(NULL), mk(device), speaker(this) {}
|
||||
|
||||
~VoicePlayer ();
|
||||
|
||||
void init ();
|
||||
|
||||
enum
|
||||
{
|
||||
PLAY_NOW = 1 << 0,
|
||||
PLAY_LOOPED = 1 << 1
|
||||
};
|
||||
void play (Voice *_voice, unsigned int flags = 0);
|
||||
|
||||
enum
|
||||
{
|
||||
STOP_NOW = 1 << 0
|
||||
};
|
||||
void stop (unsigned int flags = 0);
|
||||
|
||||
void set_volume (float _volume);
|
||||
void update ();
|
||||
|
||||
inline void bind (SGPropertyNode *node) { speaker.bind(node); }
|
||||
|
||||
public:
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// MK_VIII::VoicePlayer::Speaker //////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Speaker
|
||||
{
|
||||
VoicePlayer *player;
|
||||
|
||||
double pitch;
|
||||
|
||||
template <class T>
|
||||
inline void tie (SGPropertyNode *node, const char *name, T *ptr)
|
||||
{
|
||||
player->mk->properties_handler.tie
|
||||
(node, (string("speaker/") + name).c_str(),
|
||||
RawValueMethodsData<MK_VIII::VoicePlayer::Speaker,T,T*>
|
||||
(*this, ptr,
|
||||
&MK_VIII::VoicePlayer::Speaker::get_property,
|
||||
&MK_VIII::VoicePlayer::Speaker::set_property));
|
||||
}
|
||||
|
||||
public:
|
||||
template <class T>
|
||||
inline void set_property (T *ptr, T value) { *ptr = value; update_configuration(); }
|
||||
|
||||
template <class T>
|
||||
inline T get_property (T *ptr) const { return *ptr; }
|
||||
|
||||
float volume;
|
||||
|
||||
inline Speaker (VoicePlayer *_player)
|
||||
: player(_player),
|
||||
pitch(1),
|
||||
volume(1)
|
||||
{
|
||||
}
|
||||
|
||||
void bind (SGPropertyNode *node);
|
||||
void update_configuration ();
|
||||
};
|
||||
|
||||
private:
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// MK_VIII::VoicePlayer (continued) ///////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
MK_VIII *mk;
|
||||
|
||||
SGSharedPtr<SGSampleGroup> _sgr;
|
||||
Speaker speaker;
|
||||
|
||||
map< string, SGSharedPtr<SGSoundSample> > samples;
|
||||
vector<Voice *> _voices;
|
||||
|
||||
bool looped;
|
||||
bool next_looped;
|
||||
|
||||
SGSoundSample *get_sample (const char *name);
|
||||
|
||||
inline void append (Voice *voice, Voice::Element *element) { voice->append(element); }
|
||||
inline void append (Voice *voice, const char *sample_name) { voice->append(new Voice::SampleElement(get_sample(sample_name))); }
|
||||
inline void append (Voice *voice, double silence) { voice->append(new Voice::SilenceElement(silence)); }
|
||||
|
||||
inline void make_voice (Voice **voice) { *voice = new Voice(this); _voices.push_back(*voice); }
|
||||
|
||||
template <class T1>
|
||||
inline void make_voice (Voice **voice, T1 e1) { make_voice(voice); append(*voice, e1); }
|
||||
template <class T1, class T2>
|
||||
inline void make_voice (Voice **voice, T1 e1, T2 e2) { make_voice(voice, e1); append(*voice, e2); }
|
||||
template <class T1, class T2, class T3>
|
||||
inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3) { make_voice(voice, e1, e2); append(*voice, e3); }
|
||||
template <class T1, class T2, class T3, class T4>
|
||||
inline void make_voice (Voice **voice, T1 e1, T2 e2, T3 e3, T4 e4) { make_voice(voice, e1, e2, e3); append(*voice, e4); }
|
||||
Voice *application_data_base_failed;
|
||||
Voice *bank_angle;
|
||||
Voice *bank_angle_bank_angle;
|
||||
Voice *bank_angle_bank_angle_3;
|
||||
Voice *bank_angle_inop;
|
||||
Voice *bank_angle_pause_bank_angle;
|
||||
Voice *bank_angle_pause_bank_angle_3;
|
||||
Voice *callouts_inop;
|
||||
Voice *configuration_type_invalid;
|
||||
Voice *dont_sink;
|
||||
Voice *dont_sink_pause_dont_sink;
|
||||
Voice *five_hundred_above;
|
||||
Voice *glideslope;
|
||||
Voice *glideslope_inop;
|
||||
Voice *gpws_inop;
|
||||
Voice *hard_glideslope;
|
||||
Voice *minimums;
|
||||
Voice *minimums_minimums;
|
||||
Voice *pull_up;
|
||||
Voice *sink_rate;
|
||||
Voice *sink_rate_pause_sink_rate;
|
||||
Voice *soft_glideslope;
|
||||
Voice *terrain;
|
||||
Voice *terrain_pause_terrain;
|
||||
Voice *too_low_flaps;
|
||||
Voice *too_low_gear;
|
||||
Voice *too_low_terrain;
|
||||
Voice *altitude_callouts[n_altitude_callouts];
|
||||
} voices;
|
||||
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
1464
src/Instrumentation/tcas.cxx
Normal file
1464
src/Instrumentation/tcas.cxx
Normal file
File diff suppressed because it is too large
Load diff
390
src/Instrumentation/tcas.hxx
Normal file
390
src/Instrumentation/tcas.hxx
Normal file
|
@ -0,0 +1,390 @@
|
|||
// tcas.hxx -- Traffic Alert and Collision Avoidance System (TCAS)
|
||||
//
|
||||
// Written by Thorsten Brehm, started December 2010.
|
||||
//
|
||||
// Copyright (C) 2010 Thorsten Brehm - brehmt (at) gmail com
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License as
|
||||
// published by the Free Software Foundation; either version 2 of the
|
||||
// License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful, but
|
||||
// WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
|
||||
#ifndef __INSTRUMENTS_TCAS_HXX
|
||||
#define __INSTRUMENTS_TCAS_HXX
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <map>
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/sound/sample_openal.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include "mk_viii.hxx" // FGVoicePlayer only
|
||||
|
||||
using std::vector;
|
||||
using std::deque;
|
||||
using std::map;
|
||||
|
||||
class SGSampleGroup;
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning( push )
|
||||
# pragma warning( disable: 4355 )
|
||||
#endif
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// TCAS //////////////////////////////////////////////////////////////////////
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class TCAS : public SGSubsystem
|
||||
{
|
||||
|
||||
typedef enum
|
||||
{
|
||||
AdvisoryClear = 0, /*< Clear of traffic */
|
||||
AdvisoryIntrusion = 1, /*< Intrusion flag */
|
||||
AdvisoryClimb = AdvisoryIntrusion|(1 << 1), /*< RA climb */
|
||||
AdvisoryDescend = AdvisoryIntrusion|(1 << 2), /*< RA descend */
|
||||
AdvisoryAdjustVSpeed = AdvisoryIntrusion|(1 << 3), /*< RA adjust vertical speed (TCAS II 7.0 only) */
|
||||
AdvisoryMaintVSpeed = AdvisoryIntrusion|(1 << 4), /*< RA maintain vertical speed */
|
||||
AdvisoryMonitorVSpeed = AdvisoryIntrusion|(1 << 5), /*< RA monitor vertical speed */
|
||||
AdvisoryLevelOff = AdvisoryIntrusion|(1 << 6) /*< RA level off (TCAS II 7.1 only) */
|
||||
} EnumAdvisory;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
OptionNone = 0, /*< no option modifier */
|
||||
OptionIncreaseClimb = (1 << 0), /*< increase climb */
|
||||
OptionIncreaseDescend = (1 << 1), /*< increase descend */
|
||||
OptionCrossingClimb = (1 << 2), /*< crossing climb */
|
||||
OptionCrossingDescent = (1 << 3) /*< crossing descent */
|
||||
} EnumAdvisoryOption;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SwitchOff = 0, /*< TCAS switched off */
|
||||
SwitchStandby = 1, /*< TCAS standby (no TA/RA) */
|
||||
SwitchTaOnly = 2, /*< TCAS in TA-only mode (no RA) */
|
||||
SwitchAuto = 3 /*< TCAS in TA/RA mode */
|
||||
} EnumModeSwitch;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ThreatInvisible = -1,/*< Traffic is invisible to TCAS (i.e. no transponder) */
|
||||
ThreatNone = 0, /*< Traffic is visible but no threat. */
|
||||
ThreatProximity = 1, /*< Proximity intruder traffic (no threat). */
|
||||
ThreatTA = 2, /*< TA-level threat traffic. */
|
||||
ThreatRA = 3 /*< RA-level threat traffic. */
|
||||
} EnumThreatLevel;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int threatLevel; /*< intruder threat level: 0=clear, 1=proximity,
|
||||
2=intruder, 3=proximity intruder */
|
||||
int RA; /*< resolution advisory */
|
||||
int RAOption; /*< option flags for advisory */
|
||||
} ResolutionAdvisory;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
float Tau; /*< vertical/horizontal protection range in seconds */
|
||||
float DMOD; /*< horizontal protection range in nm */
|
||||
float ALIM; /*< vertical protection range in ft */
|
||||
} Thresholds;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double maxAltitude; /*< max altitude for this sensitivity level */
|
||||
int sl; /*< sensitivity level */
|
||||
Thresholds TA; /*< thresholds for TA-level threats */
|
||||
Thresholds RA; /*< thresholds for RA-level threats */
|
||||
} SensitivityLevel;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
string callsign;
|
||||
bool verticalTA;
|
||||
bool verticalRA;
|
||||
bool horizontalTA;
|
||||
bool horizontalRA;
|
||||
bool isTracked;
|
||||
float horizontalTau;
|
||||
float verticalTau;
|
||||
float relativeAltitudeFt;
|
||||
float verticalFps;
|
||||
int RASense;
|
||||
} ThreatInfo;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int threatLevel;
|
||||
double TAtimestamp;
|
||||
double RAtimestamp;
|
||||
} TrackerTarget;
|
||||
|
||||
typedef map<string,TrackerTarget*> TrackerTargets;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
double lat;
|
||||
double lon;
|
||||
float altFt;
|
||||
float heading;
|
||||
float velocityKt;
|
||||
float verticalFps;
|
||||
} LocalInfo; /*< info structure for local aircraft */
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// TCAS::PropertiesHandler ///////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class PropertiesHandler : public FGVoicePlayer::PropertiesHandler
|
||||
{
|
||||
TCAS *tcas;
|
||||
|
||||
public:
|
||||
PropertiesHandler (TCAS *device) :
|
||||
FGVoicePlayer::PropertiesHandler(), tcas(device) {}
|
||||
|
||||
PropertiesHandler (void) : FGVoicePlayer::PropertiesHandler() {}
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// TCAS::VoicePlayer ////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class VoicePlayer :
|
||||
public FGVoicePlayer
|
||||
{
|
||||
public:
|
||||
VoicePlayer (TCAS* tcas) :
|
||||
FGVoicePlayer(&tcas->properties_handler, "tcas") {}
|
||||
|
||||
~VoicePlayer (void) {}
|
||||
|
||||
void init (void);
|
||||
|
||||
struct
|
||||
{
|
||||
Voice* pTrafficTraffic;
|
||||
Voice* pClimb;
|
||||
Voice* pClimbNow;
|
||||
Voice* pClimbCrossing;
|
||||
Voice* pClimbIncrease;
|
||||
Voice* pDescend;
|
||||
Voice* pDescendNow;
|
||||
Voice* pDescendCrossing;
|
||||
Voice* pDescendIncrease;
|
||||
Voice* pClear;
|
||||
Voice* pAdjustVSpeed;
|
||||
Voice* pMaintVSpeed;
|
||||
Voice* pMonitorVSpeed;
|
||||
Voice* pLevelOff;
|
||||
Voice* pTestOk;
|
||||
Voice* pTestFail;
|
||||
} Voices;
|
||||
private:
|
||||
SGPropertyNode_ptr nodeSoundFilePrefix;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// TCAS::Annunciator ////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Annunciator
|
||||
{
|
||||
public:
|
||||
Annunciator (TCAS* tcas);
|
||||
~Annunciator (void) {}
|
||||
void bind (SGPropertyNode* node);
|
||||
void init (void);
|
||||
void update (void);
|
||||
|
||||
void trigger (const ResolutionAdvisory& newAdvisory, bool revertedRA);
|
||||
void test (bool testOk);
|
||||
void clear (void);
|
||||
bool isPlaying (void) { return voicePlayer.is_playing();}
|
||||
|
||||
private:
|
||||
TCAS* tcas;
|
||||
ResolutionAdvisory previous;
|
||||
FGVoicePlayer::Voice* pLastVoice;
|
||||
VoicePlayer voicePlayer;
|
||||
SGPropertyNode_ptr nodeGpwsAlertOn;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// TCAS::AdvisoryCoordinator ////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class AdvisoryCoordinator
|
||||
{
|
||||
public:
|
||||
AdvisoryCoordinator (TCAS* _tcas);
|
||||
~AdvisoryCoordinator (void) {}
|
||||
|
||||
void bind (SGPropertyNode* node);
|
||||
void init (void);
|
||||
void update (int mode);
|
||||
|
||||
void clear (void);
|
||||
void add (const ResolutionAdvisory& newAdvisory);
|
||||
|
||||
private:
|
||||
TCAS* tcas;
|
||||
double lastTATime;
|
||||
ResolutionAdvisory current;
|
||||
ResolutionAdvisory previous;
|
||||
SGPropertyNode_ptr nodeTAWarning;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// TCAS::Tracker ////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Tracker
|
||||
{
|
||||
public:
|
||||
Tracker (TCAS* _tcas);
|
||||
~Tracker (void) {}
|
||||
|
||||
void update (void);
|
||||
|
||||
void add (const string callsign, int detectedLevel);
|
||||
bool active (void) { return haveTargets;}
|
||||
bool newTraffic (void) { return newTargets;}
|
||||
bool isTracked (string callsign) { if (!haveTargets) return false;else return _isTracked(callsign);}
|
||||
bool _isTracked (string callsign);
|
||||
int getThreatLevel (string callsign);
|
||||
|
||||
private:
|
||||
TCAS* tcas;
|
||||
double currentTime;
|
||||
bool haveTargets;
|
||||
bool newTargets;
|
||||
TrackerTargets targets;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// TCAS::AdvisoryGenerator //////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class AdvisoryGenerator
|
||||
{
|
||||
public:
|
||||
AdvisoryGenerator (TCAS* _tcas);
|
||||
~AdvisoryGenerator (void) {}
|
||||
|
||||
void init (const LocalInfo* _pSelf, ThreatInfo* _pCurrentThreat);
|
||||
|
||||
void setAlarmThresholds (const SensitivityLevel* _pAlarmThresholds);
|
||||
|
||||
int resolution (int mode, int threatLevel, float distanceNm,
|
||||
float altFt, float heading, float velocityKt);
|
||||
|
||||
private:
|
||||
float verticalSeparation (float newVerticalFps);
|
||||
void determineRAsense (int& RASense, bool& isCrossing);
|
||||
|
||||
private:
|
||||
TCAS* tcas;
|
||||
const LocalInfo* pSelf; /*< info structure for local aircraft */
|
||||
ThreatInfo* pCurrentThreat; /*< info structure on current intruder/threat */
|
||||
const SensitivityLevel* pAlarmThresholds;
|
||||
};
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// TCAS::ThreatDetector /////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class ThreatDetector
|
||||
{
|
||||
public:
|
||||
ThreatDetector (TCAS* _tcas);
|
||||
~ThreatDetector (void) {}
|
||||
|
||||
void init (void);
|
||||
void update (void);
|
||||
|
||||
bool checkTransponder (const SGPropertyNode* pModel, float velocityKt);
|
||||
int checkThreat (int mode, const SGPropertyNode* pModel);
|
||||
void checkVerticalThreat (void);
|
||||
void horizontalThreat (float bearing, float distanceNm, float heading,
|
||||
float velocityKt);
|
||||
|
||||
void setAlt (float altFt) { self.altFt = altFt;}
|
||||
float getAlt (void) { return self.altFt;}
|
||||
float getVelocityKt (void) { return self.velocityKt;}
|
||||
int getRASense (void) { return currentThreat.RASense;}
|
||||
|
||||
private:
|
||||
void unitTest (void);
|
||||
|
||||
private:
|
||||
static const SensitivityLevel sensitivityLevels[];
|
||||
|
||||
TCAS* tcas;
|
||||
int checkCount;
|
||||
|
||||
SGPropertyNode_ptr nodeLat;
|
||||
SGPropertyNode_ptr nodeLon;
|
||||
SGPropertyNode_ptr nodeAlt;
|
||||
SGPropertyNode_ptr nodeHeading;
|
||||
SGPropertyNode_ptr nodeVelocity;
|
||||
SGPropertyNode_ptr nodeVerticalFps;
|
||||
|
||||
LocalInfo self; /*< info structure for local aircraft */
|
||||
ThreatInfo currentThreat; /*< info structure on current intruder/threat */
|
||||
const SensitivityLevel* pAlarmThresholds;
|
||||
};
|
||||
|
||||
private:
|
||||
string name;
|
||||
int num;
|
||||
double nextUpdateTime;
|
||||
int selfTestStep;
|
||||
|
||||
SGPropertyNode_ptr nodeModeSwitch;
|
||||
SGPropertyNode_ptr nodeServiceable;
|
||||
SGPropertyNode_ptr nodeSelfTest;
|
||||
SGPropertyNode_ptr nodeDebugTrigger;
|
||||
SGPropertyNode_ptr nodeDebugRA;
|
||||
SGPropertyNode_ptr nodeDebugThreat;
|
||||
|
||||
PropertiesHandler properties_handler;
|
||||
ThreatDetector threatDetector;
|
||||
Tracker tracker;
|
||||
AdvisoryCoordinator advisoryCoordinator;
|
||||
AdvisoryGenerator advisoryGenerator;
|
||||
Annunciator annunciator;
|
||||
|
||||
private:
|
||||
void selfTest (void);
|
||||
|
||||
public:
|
||||
TCAS (SGPropertyNode* node);
|
||||
|
||||
virtual void bind (void);
|
||||
virtual void unbind (void);
|
||||
virtual void init (void);
|
||||
virtual void update (double dt);
|
||||
};
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning( pop )
|
||||
#endif
|
||||
|
||||
#endif // __INSTRUMENTS_TCAS_HXX
|
|
@ -69,18 +69,29 @@ using std::endl;
|
|||
static const float UNIT = 1.0f / 8.0f; // 8 symbols in a row/column in the texture
|
||||
static const char *DEFAULT_FONT = "typewriter.txf";
|
||||
|
||||
|
||||
wxRadarBg::wxRadarBg(SGPropertyNode *node) :
|
||||
_name(node->getStringValue("name", "radar")),
|
||||
_num(node->getIntValue("number", 0)),
|
||||
_time(0.0),
|
||||
_interval(node->getDoubleValue("update-interval-sec", 1.0)),
|
||||
_elapsed_time(0),
|
||||
_persistance(0),
|
||||
_sim_init_done(false),
|
||||
_odg(0),
|
||||
_last_switchKnob("off"),
|
||||
_range_nm(0),
|
||||
_scale(0),
|
||||
_angle_offset(0),
|
||||
_view_heading(0),
|
||||
_x_offset(0),
|
||||
_y_offset(0),
|
||||
_radar_ref_rng(0),
|
||||
_lat(0),
|
||||
_lon(0),
|
||||
_antenna_ht(node->getDoubleValue("antenna-ht-ft", 0.0)),
|
||||
_resultTexture(0),
|
||||
_wxEcho(0)
|
||||
_wxEcho(0),
|
||||
_font_size(0),
|
||||
_font_spacing(0)
|
||||
{
|
||||
string branch;
|
||||
branch = "/instrumentation/" + _name;
|
||||
|
@ -174,6 +185,8 @@ wxRadarBg::init ()
|
|||
_radar_symbol_node = n->getNode("symbol", true);
|
||||
_radar_centre_node = n->getNode("centre", true);
|
||||
_radar_rotate_node = n->getNode("rotate", true);
|
||||
_radar_tcas_node = n->getNode("tcas", true);
|
||||
_radar_absalt_node = n->getNode("abs-altitude", true);
|
||||
|
||||
_radar_centre_node->setBoolValue(false);
|
||||
if (!_radar_coverage_node->hasValue())
|
||||
|
@ -231,6 +244,8 @@ wxRadarBg::init ()
|
|||
osg::Camera *camera = _odg->getCamera();
|
||||
camera->addChild(_radarGeode.get());
|
||||
camera->addChild(_textGeode.get());
|
||||
|
||||
updateFont();
|
||||
}
|
||||
|
||||
|
||||
|
@ -305,16 +320,6 @@ wxRadarBg::update (double delta_time_sec)
|
|||
}
|
||||
|
||||
string switchKnob = _Instrument->getStringValue("switch", "on");
|
||||
if (_last_switchKnob != switchKnob) {
|
||||
// since 3D models don't share textures with the rest of the world
|
||||
// we must locate them and replace their handle by hand
|
||||
// only do that when the instrument is turned on
|
||||
//if (_last_switchKnob == "off")
|
||||
//_odg->set_texture(_texture_path.c_str(), _resultTexture->getHandle());
|
||||
|
||||
_last_switchKnob = switchKnob;
|
||||
}
|
||||
|
||||
if (switchKnob == "off") {
|
||||
_Instrument->setStringValue("status", "");
|
||||
} else if (switchKnob == "stby") {
|
||||
|
@ -666,9 +671,11 @@ wxRadarBg::update_aircraft()
|
|||
if (!_ai_enabled_node->getBoolValue())
|
||||
return;
|
||||
|
||||
bool draw_echoes = _radar_position_node->getBoolValue();
|
||||
bool draw_symbols = _radar_symbol_node->getBoolValue();
|
||||
bool draw_data = _radar_data_node->getBoolValue();
|
||||
bool draw_tcas = _radar_tcas_node->getBoolValue();
|
||||
bool draw_absolute = _radar_absalt_node->getBoolValue();
|
||||
bool draw_echoes = _radar_position_node->getBoolValue();
|
||||
bool draw_symbols = _radar_symbol_node->getBoolValue();
|
||||
bool draw_data = _radar_data_node->getBoolValue();
|
||||
if (!draw_echoes && !draw_symbols && !draw_data)
|
||||
return;
|
||||
|
||||
|
@ -697,7 +704,8 @@ wxRadarBg::update_aircraft()
|
|||
model = ai->getChild(i);
|
||||
if (!model->nChildren())
|
||||
continue;
|
||||
if (model->getIntValue("id") == selected_id) {
|
||||
if ((model->getIntValue("id") == selected_id)&&
|
||||
(!draw_tcas)) {
|
||||
selected_ac = model; // save selected model for last iteration
|
||||
continue;
|
||||
}
|
||||
|
@ -752,8 +760,14 @@ wxRadarBg::update_aircraft()
|
|||
bearing += _angle_offset;
|
||||
heading += _angle_offset;
|
||||
|
||||
bool is_tcas_contact = false;
|
||||
if (draw_tcas)
|
||||
{
|
||||
is_tcas_contact = update_tcas(model,range,user_alt,alt,bearing,radius,draw_absolute);
|
||||
}
|
||||
|
||||
// pos mode
|
||||
if (draw_echoes) {
|
||||
if (draw_echoes && (!is_tcas_contact)) {
|
||||
float size = echo_radius * 120 * UNIT;
|
||||
|
||||
const osg::Vec2f texBase(3 * UNIT, 3 * UNIT);
|
||||
|
@ -764,7 +778,7 @@ wxRadarBg::update_aircraft()
|
|||
}
|
||||
|
||||
// data mode
|
||||
if (draw_symbols) {
|
||||
if (draw_symbols && (!draw_tcas)) {
|
||||
const osg::Vec2f texBase(0, 3 * UNIT);
|
||||
float size = 600 * UNIT;
|
||||
osg::Matrixf m(osg::Matrixf::scale(size, size, 1.0f)
|
||||
|
@ -774,11 +788,98 @@ wxRadarBg::update_aircraft()
|
|||
addQuad(_vertices, _texCoords, m, texBase);
|
||||
}
|
||||
|
||||
if (draw_data || i < 0) // selected one (i == -1) is always drawn
|
||||
if ((draw_data || i < 0)&& // selected one (i == -1) is always drawn
|
||||
((!draw_tcas)||(is_tcas_contact)||(draw_echoes)))
|
||||
update_data(model, alt, heading, radius, bearing, i < 0);
|
||||
}
|
||||
}
|
||||
|
||||
/** Update TCAS display.
|
||||
* Return true when processed as TCAS contact, false otherwise. */
|
||||
bool
|
||||
wxRadarBg::update_tcas(const SGPropertyNode *model,double range,double user_alt,double alt,
|
||||
double bearing,double radius,bool absMode)
|
||||
{
|
||||
int threatLevel=0;
|
||||
{
|
||||
// update TCAS symbol
|
||||
osg::Vec2f texBase;
|
||||
threatLevel = model->getIntValue("tcas/threat-level",-1);
|
||||
if (threatLevel == -1)
|
||||
{
|
||||
// no TCAS information (i.e. no transponder) => not visible to TCAS
|
||||
return false;
|
||||
}
|
||||
int row = 7 - threatLevel;
|
||||
int col = 4;
|
||||
double vspeed = model->getDoubleValue("velocities/vertical-speed-fps");
|
||||
if (vspeed < -3.0) // descending
|
||||
col+=1;
|
||||
else
|
||||
if (vspeed > 3.0) // climbing
|
||||
col+=2;
|
||||
texBase = osg::Vec2f(col*UNIT,row * UNIT);
|
||||
float size = 200 * UNIT;
|
||||
osg::Matrixf m(osg::Matrixf::scale(size, size, 1.0f)
|
||||
* wxRotate(-bearing)
|
||||
* osg::Matrixf::translate(0.0f, radius, 0.0f)
|
||||
* wxRotate(bearing) * _centerTrans);
|
||||
addQuad(_vertices, _texCoords, m, texBase);
|
||||
}
|
||||
|
||||
{
|
||||
// update TCAS data
|
||||
osgText::Text *altStr = new osgText::Text;
|
||||
altStr->setFont(_font.get());
|
||||
altStr->setFontResolution(12, 12);
|
||||
altStr->setCharacterSize(_font_size);
|
||||
altStr->setColor(_tcas_colors[threatLevel]);
|
||||
osg::Matrixf m(wxRotate(-bearing)
|
||||
* osg::Matrixf::translate(0.0f, radius, 0.0f)
|
||||
* wxRotate(bearing) * _centerTrans);
|
||||
|
||||
osg::Vec3 pos = m.preMult(osg::Vec3(16, 16, 0));
|
||||
// cast to int's, otherwise text comes out ugly
|
||||
altStr->setLineSpacing(_font_spacing);
|
||||
|
||||
stringstream text;
|
||||
altStr->setAlignment(osgText::Text::LEFT_CENTER);
|
||||
int altDif = (alt-user_alt+50)/100;
|
||||
char sign = 0;
|
||||
int dy=0;
|
||||
if (altDif>=0)
|
||||
{
|
||||
sign='+';
|
||||
dy=2;
|
||||
}
|
||||
else
|
||||
if (altDif<0)
|
||||
{
|
||||
sign='-';
|
||||
altDif = -altDif;
|
||||
dy=-30;
|
||||
}
|
||||
altStr->setPosition(osg::Vec3((int)pos.x()-30, (int)pos.y()+dy, 0));
|
||||
if (absMode)
|
||||
{
|
||||
// absolute altitude display
|
||||
text << setprecision(0) << fixed
|
||||
<< setw(3) << setfill('0') << alt/100 << endl;
|
||||
}
|
||||
else // relative altitude display
|
||||
if (sign)
|
||||
{
|
||||
text << sign
|
||||
<< setprecision(0) << fixed
|
||||
<< setw(2) << setfill('0') << altDif << endl;
|
||||
}
|
||||
|
||||
altStr->setText(text.str());
|
||||
_textGeode->addDrawable(altStr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
wxRadarBg::update_tacan()
|
||||
|
@ -983,11 +1084,23 @@ wxRadarBg::updateFont()
|
|||
_font->setGlyphImageMargin(0);
|
||||
_font->setGlyphImageMarginRatio(0);
|
||||
}
|
||||
|
||||
for (int i=0;i<4;i++)
|
||||
{
|
||||
const float defaultColors[4][3] = {{0,1,1},{0,1,1},{1,0.5,0},{1,0,0}};
|
||||
SGPropertyNode_ptr color_node = _font_node->getNode("tcas/color",i,true);
|
||||
float red = color_node->getFloatValue("red",defaultColors[i][0]);
|
||||
float green = color_node->getFloatValue("green",defaultColors[i][1]);
|
||||
float blue = color_node->getFloatValue("blue",defaultColors[i][2]);
|
||||
float alpha = color_node->getFloatValue("alpha",1);
|
||||
_tcas_colors[i]=osg::Vec4(red, green, blue, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
wxRadarBg::valueChanged(SGPropertyNode*)
|
||||
{
|
||||
updateFont();
|
||||
_time = _interval;
|
||||
}
|
||||
|
||||
|
|
|
@ -96,8 +96,6 @@ private:
|
|||
typedef enum { ARC, MAP, PLAN, ROSE, BSCAN} DisplayMode;
|
||||
DisplayMode _display_mode;
|
||||
|
||||
string _last_switchKnob;
|
||||
|
||||
float _range_nm;
|
||||
float _scale; // factor to convert nm to display units
|
||||
float _angle_offset;
|
||||
|
@ -130,6 +128,8 @@ private:
|
|||
SGPropertyNode_ptr _radar_ref_rng_node;
|
||||
SGPropertyNode_ptr _radar_hdg_marker_node;
|
||||
SGPropertyNode_ptr _radar_rotate_node;
|
||||
SGPropertyNode_ptr _radar_tcas_node;
|
||||
SGPropertyNode_ptr _radar_absalt_node;
|
||||
|
||||
SGPropertyNode_ptr _font_node;
|
||||
SGPropertyNode_ptr _ai_enabled_node;
|
||||
|
@ -144,6 +144,7 @@ private:
|
|||
osg::Matrixf _centerTrans;
|
||||
osg::ref_ptr<osgText::Font> _font;
|
||||
osg::Vec4 _font_color;
|
||||
osg::Vec4 _tcas_colors[4];
|
||||
float _font_size;
|
||||
float _font_spacing;
|
||||
|
||||
|
@ -155,6 +156,8 @@ private:
|
|||
void update_heading_marker();
|
||||
void update_data(const SGPropertyNode *ac, double alt, double heading,
|
||||
double radius, double bearing, bool selected);
|
||||
bool update_tcas(const SGPropertyNode *model,double range,double user_alt,double alt,
|
||||
double bearing,double radius, bool absMode);
|
||||
void center_map();
|
||||
void apply_map_offset();
|
||||
void updateFont();
|
||||
|
|
|
@ -182,6 +182,7 @@ FGGlobals::~FGGlobals()
|
|||
delete current_panel;
|
||||
|
||||
delete ATC_mgr;
|
||||
controls->unbind();
|
||||
delete controls;
|
||||
|
||||
delete channel_options_list;
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
/**
|
||||
* Log any property values to any number of CSV files.
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
// forward decls
|
||||
|
|
|
@ -272,13 +272,13 @@ bool FGGeneric::gen_message() {
|
|||
}
|
||||
}
|
||||
|
||||
bool FGGeneric::parse_message_binary() {
|
||||
bool FGGeneric::parse_message_binary(int length) {
|
||||
char *p2, *p1 = buf;
|
||||
int32_t tmp32;
|
||||
double val;
|
||||
int i = -1;
|
||||
|
||||
p2 = p1 + FG_MAX_MSG_SIZE;
|
||||
p2 = p1 + length;
|
||||
while ((++i < (int)_in_message.size()) && (p1 < p2)) {
|
||||
|
||||
switch (_in_message[i].type) {
|
||||
|
@ -353,14 +353,23 @@ bool FGGeneric::parse_message_binary() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FGGeneric::parse_message_ascii() {
|
||||
bool FGGeneric::parse_message_ascii(int length) {
|
||||
char *p2, *p1 = buf;
|
||||
double val;
|
||||
int i = -1;
|
||||
int chunks = _in_message.size();
|
||||
int line_separator_size = line_separator.size();
|
||||
|
||||
while ((++i < (int)_in_message.size()) &&
|
||||
p1 && strcmp(p1, line_separator.c_str())) {
|
||||
if (length < line_separator_size ||
|
||||
line_separator.compare(buf + length - line_separator_size) != 0) {
|
||||
|
||||
SG_LOG(SG_IO, SG_WARN,
|
||||
"Input line does not end with expected line separator." );
|
||||
} else {
|
||||
buf[length - line_separator_size] = 0;
|
||||
}
|
||||
|
||||
while ((++i < chunks) && p1) {
|
||||
p2 = strstr(p1, var_separator.c_str());
|
||||
if (p2) {
|
||||
*p2 = 0;
|
||||
|
@ -398,11 +407,11 @@ bool FGGeneric::parse_message_ascii() {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool FGGeneric::parse_message() {
|
||||
bool FGGeneric::parse_message(int length) {
|
||||
if (binary_mode) {
|
||||
return parse_message_binary();
|
||||
return parse_message_binary(length);
|
||||
} else {
|
||||
return parse_message_ascii();
|
||||
return parse_message_ascii(length);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -450,7 +459,7 @@ bool FGGeneric::process() {
|
|||
if (!binary_mode) {
|
||||
length = io->readline( buf, FG_MAX_MSG_SIZE );
|
||||
if ( length > 0 ) {
|
||||
parse_message();
|
||||
parse_message( length );
|
||||
} else {
|
||||
SG_LOG( SG_IO, SG_ALERT, "Error reading data." );
|
||||
return false;
|
||||
|
@ -458,7 +467,7 @@ bool FGGeneric::process() {
|
|||
} else {
|
||||
length = io->read( buf, binary_record_length );
|
||||
if ( length == binary_record_length ) {
|
||||
parse_message();
|
||||
parse_message( length );
|
||||
} else {
|
||||
SG_LOG( SG_IO, SG_ALERT,
|
||||
"Generic protocol: Received binary "
|
||||
|
@ -470,12 +479,12 @@ bool FGGeneric::process() {
|
|||
} else {
|
||||
if (!binary_mode) {
|
||||
while ((length = io->readline( buf, FG_MAX_MSG_SIZE )) > 0 ) {
|
||||
parse_message();
|
||||
parse_message( length );
|
||||
}
|
||||
} else {
|
||||
while ((length = io->read( buf, binary_record_length ))
|
||||
== binary_record_length ) {
|
||||
parse_message();
|
||||
parse_message( length );
|
||||
}
|
||||
|
||||
if ( length > 0 ) {
|
||||
|
@ -549,6 +558,13 @@ FGGeneric::reinit()
|
|||
if (input) {
|
||||
_in_message.clear();
|
||||
read_config(input, _in_message);
|
||||
if (!binary_mode && (line_separator.size() == 0 ||
|
||||
*line_separator.rbegin() != '\n')) {
|
||||
|
||||
SG_LOG(SG_IO, SG_WARN,
|
||||
"Warning: Appending newline to line separator in generic input.");
|
||||
line_separator.push_back('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ public:
|
|||
~FGGeneric();
|
||||
|
||||
bool gen_message();
|
||||
bool parse_message();
|
||||
bool parse_message(int length);
|
||||
|
||||
// open hailing frequencies
|
||||
bool open();
|
||||
|
@ -95,8 +95,8 @@ private:
|
|||
|
||||
bool gen_message_ascii();
|
||||
bool gen_message_binary();
|
||||
bool parse_message_ascii();
|
||||
bool parse_message_binary();
|
||||
bool parse_message_ascii(int length);
|
||||
bool parse_message_binary(int length);
|
||||
void read_config(SGPropertyNode *root, vector<_serial_prot> &msg);
|
||||
bool exitOnError;
|
||||
};
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <vector>
|
||||
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/sound/sample_group.hxx>
|
||||
|
||||
class SGXmlSound;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
#include <queue>
|
||||
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/sound/sample_group.hxx>
|
||||
|
||||
class SGSoundSample;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#define FG_TIME_TIMEMANAGER_HXX
|
||||
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
// forward decls
|
||||
class SGTime;
|
||||
|
|
Loading…
Add table
Reference in a new issue