1
0
Fork 0

Merge branch 'next' of gitorious.org:fg/flightgear into next

This commit is contained in:
Erik Hofman 2012-05-24 20:24:57 +02:00
commit 9fa790bcac
201 changed files with 8647 additions and 4454 deletions

View file

@ -151,11 +151,13 @@ if (MSVC AND MSVC_3RDPARTY_ROOT)
if (CMAKE_CL_64) if (CMAKE_CL_64)
set( OSG_MSVC ${OSG_MSVC}-64 ) set( OSG_MSVC ${OSG_MSVC}-64 )
set( MSVC_3RDPARTY_DIR 3rdParty.x64 ) set( MSVC_3RDPARTY_DIR 3rdParty.x64 )
set( BOOST_LIB lib64 )
else (CMAKE_CL_64) else (CMAKE_CL_64)
set( MSVC_3RDPARTY_DIR 3rdParty ) set( MSVC_3RDPARTY_DIR 3rdParty )
set( BOOST_LIB lib )
endif (CMAKE_CL_64) endif (CMAKE_CL_64)
set (CMAKE_LIBRARY_PATH ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/lib ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/OpenScenegraph/lib ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/SimGear/lib ) set (CMAKE_LIBRARY_PATH ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/lib ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/OpenScenegraph/lib ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/SimGear/lib $(BOOST_ROOT)/$(BOOST_LIB) )
set (CMAKE_INCLUDE_PATH ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/include ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/OpenScenegraph/include ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/SimGear/include) set (CMAKE_INCLUDE_PATH ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/include ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/OpenScenegraph/include ${MSVC_3RDPARTY_ROOT}/install/${OSG_MSVC}/SimGear/include)
set (BOOST_ROOT ${MSVC_3RDPARTY_ROOT}/boost_1_44_0) set (BOOST_ROOT ${MSVC_3RDPARTY_ROOT}/boost_1_44_0)
set (OPENAL_INCLUDE_DIR ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/include) set (OPENAL_INCLUDE_DIR ${MSVC_3RDPARTY_ROOT}/${MSVC_3RDPARTY_DIR}/include)
@ -252,19 +254,6 @@ check_include_file(unistd.h HAVE_UNISTD_H)
check_include_file(sys/time.h HAVE_SYS_TIME_H) check_include_file(sys/time.h HAVE_SYS_TIME_H)
check_include_file(windows.h HAVE_WINDOWS_H) check_include_file(windows.h HAVE_WINDOWS_H)
# definition depends on OSG version
set(CMAKE_REQUIRED_INCLUDES ${OPENSCENEGRAPH_INCLUDE_DIRS})
check_cxx_source_compiles(
"#include <osg/CullSettings>
int main()
{
osg::CullSettings::VariablesMask mask = osg::CullSettings::CLEAR_MASK;
return 0;
}
"
HAVE_CULLSETTINGS_CLEAR_MASK)
if(ENABLE_RTI) if(ENABLE_RTI)
find_package(RTI) find_package(RTI)
if(RTI_FOUND) if(RTI_FOUND)
@ -273,11 +262,13 @@ if(ENABLE_RTI)
endif(ENABLE_RTI) endif(ENABLE_RTI)
if(CMAKE_COMPILER_IS_GNUCXX) if(CMAKE_COMPILER_IS_GNUCXX)
set(WARNING_FLAGS -Wall) set(WARNING_FLAGS_CXX "-Wall")
set(WARNING_FLAGS_C "-Wall")
endif(CMAKE_COMPILER_IS_GNUCXX) endif(CMAKE_COMPILER_IS_GNUCXX)
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
set (WARNING_FLAGS "-Wall -Wno-overloaded-virtual") set (WARNING_FLAGS_CXX "-Wall -Wno-overloaded-virtual")
set (WARNING_FLAGS_C "-Wall")
endif() endif()
if(WIN32) if(WIN32)
@ -297,8 +288,10 @@ if(WIN32)
set(NOMINMAX 1) set(NOMINMAX 1)
endif(WIN32) endif(WIN32)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} ${MSVC_FLAGS} -D_REENTRANT") set (BOOST_CXX_FLAGS "-DBOOST_MULTI_INDEX_DISABLE_SERIALIZATION -DBOOST_BIMAP_DISABLE_SERIALIZATION")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} ${MSVC_FLAGS} -D_REENTRANT")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS_C} ${MSVC_FLAGS} -D_REENTRANT")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS_CXX} ${MSVC_FLAGS} -D_REENTRANT ${BOOST_CXX_FLAGS}")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MSVC_LD_FLAGS}") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${MSVC_LD_FLAGS}")
include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS} include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS}

View file

@ -152,7 +152,6 @@ else(SIMGEAR_SHARED)
nasal nasal
tsync tsync
bucket bucket
route
io io
serial serial
math math

View file

@ -285,12 +285,12 @@
</b> </b>
<div class="indent"> <div class="indent">
<p>The latest development code is available for everyone through our <p>The latest development code is available for everyone through our
CVS repository. See git repository. See
<a href="http://flightgear.org/cvsResources/">http://flightgear.org/cvsResources/</a> for details. <a href="http://wiki.flightgear.org/FlightGear_and_Git">http://wiki.flightgear.org/FlightGear_and_Git</a> for details.
</p> </p>
<p>Otherwise, you can get relatively up-to-date snapshots of the <p>Otherwise, you can get relatively up-to-date snapshots of the
development tree at development tree at
<a href="ftp://flightgear.sourceforge.net/pub/flightgear/Devel/Snapshots/">ftp://flightgear.sourceforge.net/pub/flightgear/Devel/Snapshots/</a>. <a href="http://flightgear.simpits.org:8080/">http://flightgear.simpits.org:8080/</a>, which are recompiled at every git commit.
</p> </p>
</div> </div>

157
docs-mini/README.canvas Normal file
View file

@ -0,0 +1,157 @@
Canvas - A 2D Drawing API
=========================
Author: Thomas Geymayer <admin@tomprogs.at>
Revision: 2012/05/04
Introduction
------------
With the increasing complexity of (glass) cockpits the need for a simple API to
draw on a 2D surface without modifying the C++ core increased heavily in the
last time. The 2D canvas is an effort to satisfy this needs. It is now possible
to create offscreen rendertargets only by using the property tree and placing
them on any 3D object on the aircraft by using certain filter criteria.
Currently it is only possible to place text on the canvas but 2d shapes (using
OpenVG) are going to follow.
Creating a canvas
-----------------
A new canvas can be instantiated by creating a node /canvas/texture[<INDEX>]
with at least the following children:
<size-x type="int"> The width of the underlying texture
<size-y type="int"> The height of the underlying texture
<view-width type="int"> The width of the canvas
<view-height type="int"> The height of the canvas
The dimensions of the canvas are needed to be able to use textures with
different resolutions but use the same units for rendering to the canvas.
Therefore you can choose any texture size with the same canvas size and always
get the same results (apart from resolution dependent artifacts).
* Filtering:
Optionally you can enable mipmapping and/or multisampling (Coverage Sampling
Antialiasing):
<mipmapping type="bool"> Use mipmapping (default: false)
<coverage-samples type="int"> Coverage Samples (default: 0)
<color-samples type="int"> Color Samples (default: 0, always
have to be <= coverage-samples)
Drawing
-------
Drawing to the canvas is accomplished by creating nodes as childs of the
canvas root node. Every shape has to be a child of a <group> node. Currently
only drawing Text is possible:
* General:
The following parameters are used by multiple elements:
Color:
A color can be specified by the following subtree (NAME is replaced by
another name depending on the usage of the color)
<NAME>
<red type="float">
<green type="float">
<blue type="float">
</NAME>
* Text:
Create a <text> node and configure with the following properties:
<text type="string"> The text to be displayed
<font type="string"> The font to be used (Searched in
1. aircraft-dir/Fonts
2. aircraft-dir
3. $FG_DATA/Fonts
4. Default osg font paths
<size type="float"> The font size (default: 32)
<tf> A 3x3 transformation matrix specified by 6 values
(child elements <a>, ..., <f>) See
http://www.w3.org/TR/SVG/coords.html#TransformMatrixDefined
for details.
You can also use shortcuts and use an alternative to
specifying six values:
- Translation: <tx>, <ty> (ty, ty default to 0)
- Totation: <rot>
- Scale: <sx>, <sy> (sx is required, sy defaults to sx)
<alginment type="string"> Text alignment (default: "left-baseline") One of:
"left-top"
"left-center"
"left-bottom"
"center-top"
"center-center"
"center-bottom"
"right-top"
"right-center"
"right-bottom"
"left-baseline"
"center-baseline"
"right-baseline"
"left-bottom-baseline"
"center-bottom-baseline"
"right-bottom-baseline"
<draw-mode type="int"> A bitwise combination of the following values
1 (Text - default)
2 (Boundingbox)
4 (Filled boundingbox)
8 (Alignment -> Draw a cross at the position
of the text)
<padding type="float"> Padding between for the boundingbox (default: 0)
<color> Text color
<color-fill> Fill color (for the bounding box)
Placement
---------
To place the canvas into the scene one ore more <placement> elements can be
added to the texture node. By setting at least on of the following nodes
the objects where the canvas texture should be placed on are selected:
<texture type="string"> Match objects with the given texture assigned
<node type="string"> Match objects with the given name
<parent type="string"> Match objects with a parent matching the given name
(Not necessarily the direct parent)
Example
-------
<canvas>
<texture>
<size-x type="int">384</size-x>
<size-y type="int">512</size-y>
<view-width type="int">768</view-width>
<view-height type="int">1024</view-height>
<mipmapping type="bool">false</mipmapping>
<coverage-samples type="int">0</coverage-samples>
<color-samples type="int">0</color-samples>
<group>
<text>
<text type="string">TEST MESSAGE</text>
<font type="string">helvetica_bold.txf</font>
<tf>
<!-- Translate (18|50) -->
<tx>18</tx>
<ty>50</ty>
</tf>
</text>
</group>
<placement>
<!-- Place on objects with the texture EICAS.png
and a parent called HDD 1 -->
<texture type="string">EICAS.png</texture>
<parent type="string">HDD 1</parent>
</placement>
</texture>
</canvas>

View file

@ -11,7 +11,7 @@ fi
if [ "x$2" != "x" ]; then if [ "x$2" != "x" ]; then
VERSION="$2" VERSION="$2"
else else
VERSION="2.5" VERSION="2.7"
fi fi
echo base dir = $BASE, version = $VERSION echo base dir = $BASE, version = $VERSION
@ -41,6 +41,7 @@ tar \
data/Aircraft/Instruments-3d \ data/Aircraft/Instruments-3d \
data/Aircraft/UIUC \ data/Aircraft/UIUC \
data/Aircraft/777 \ data/Aircraft/777 \
data/Aircraft/777-200 \
data/Aircraft/A6M2 \ data/Aircraft/A6M2 \
data/Aircraft/ASK13 \ data/Aircraft/ASK13 \
data/Aircraft/b1900d \ data/Aircraft/b1900d \

View file

@ -22,7 +22,6 @@
# include <config.h> # include <config.h>
#endif #endif
#include <simgear/route/waypoint.hxx>
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
#include <Main/globals.hxx> #include <Main/globals.hxx>
#include <Viewer/viewer.hxx> #include <Viewer/viewer.hxx>

View file

@ -34,7 +34,6 @@
#include <osg/Node> #include <osg/Node>
#include <osgDB/FileUtils> #include <osgDB/FileUtils>
#include <simgear/math/SGMath.hxx>
#include <simgear/misc/sg_path.hxx> #include <simgear/misc/sg_path.hxx>
#include <simgear/scene/model/modellib.hxx> #include <simgear/scene/model/modellib.hxx>
#include <simgear/scene/util/SGNodeMasks.hxx> #include <simgear/scene/util/SGNodeMasks.hxx>

View file

@ -23,7 +23,6 @@
#include <string> #include <string>
#include <simgear/constants.h> #include <simgear/constants.h>
#include <simgear/math/SGMath.hxx>
#include <simgear/scene/model/placement.hxx> #include <simgear/scene/model/placement.hxx>
#include <simgear/scene/model/modellib.hxx> #include <simgear/scene/model/modellib.hxx>
#include <simgear/misc/sg_path.hxx> #include <simgear/misc/sg_path.hxx>

View file

@ -26,7 +26,6 @@
#include <vector> #include <vector>
#include <simgear/sg_inlines.h> #include <simgear/sg_inlines.h>
#include <simgear/math/SGMath.hxx>
#include <simgear/math/sg_geodesy.hxx> #include <simgear/math/sg_geodesy.hxx>
#include <math.h> #include <math.h>

View file

@ -27,7 +27,6 @@
#include <vector> #include <vector>
#include <simgear/sg_inlines.h> #include <simgear/sg_inlines.h>
#include <simgear/math/SGMath.hxx>
#include <simgear/math/sg_geodesy.hxx> #include <simgear/math/sg_geodesy.hxx>
#include <math.h> #include <math.h>

View file

@ -24,7 +24,6 @@
#include <simgear/misc/sg_path.hxx> #include <simgear/misc/sg_path.hxx>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/route/waypoint.hxx>
#include <simgear/math/sg_geodesy.hxx> #include <simgear/math/sg_geodesy.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
#include <simgear/constants.h> #include <simgear/constants.h>

View file

@ -14,7 +14,7 @@
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef _FG_AIFLIGHTPLAN_HXX #ifndef _FG_AIFLIGHTPLAN_HXX
#define _FG_AIFLIGHTPLAN_HXX #define _FG_AIFLIGHTPLAN_HXX

View file

@ -22,6 +22,7 @@
# include <config.h> # include <config.h>
#endif #endif
#include <cstdlib>
#include "AIFlightPlan.hxx" #include "AIFlightPlan.hxx"
#include <simgear/math/sg_geodesy.hxx> #include <simgear/math/sg_geodesy.hxx>

View file

@ -14,7 +14,7 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
* *
* *
**************************************************************************/ **************************************************************************/
@ -25,7 +25,6 @@
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <simgear/route/waypoint.hxx>
#include <Airports/simple.hxx> #include <Airports/simple.hxx>
#include <Airports/runways.hxx> #include <Airports/runways.hxx>

View file

@ -22,6 +22,8 @@
# include <config.h> # include <config.h>
#endif #endif
#include <cstdlib>
#include <simgear/math/sg_geodesy.hxx> #include <simgear/math/sg_geodesy.hxx>
#include <Airports/simple.hxx> #include <Airports/simple.hxx>

View file

@ -69,10 +69,7 @@ void
FGAIManager::init() { FGAIManager::init() {
root = fgGetNode("sim/ai", true); root = fgGetNode("sim/ai", true);
enabled = root->getNode("enabled", true)->getBoolValue(); enabled = root->getNode("enabled", true);
if (!enabled)
return;
thermal_lift_node = fgGetNode("/environment/thermal-lift-fps", true); thermal_lift_node = fgGetNode("/environment/thermal-lift-fps", true);
wind_from_east_node = fgGetNode("/environment/wind-from-east-fps",true); wind_from_east_node = fgGetNode("/environment/wind-from-east-fps",true);
@ -92,6 +89,15 @@ FGAIManager::init() {
void void
FGAIManager::postinit() { FGAIManager::postinit() {
// postinit, so that it can access the Nasal subsystem // postinit, so that it can access the Nasal subsystem
if (!root->getBoolValue("scenarios-enabled", true))
return;
// scenarios enabled, AI subsystem required
if (!enabled->getBoolValue())
enabled->setBoolValue(true);
// process all scenarios
map<string, bool> scenarios; map<string, bool> scenarios;
for (int i = 0 ; i < root->nChildren() ; i++) { for (int i = 0 ; i < root->nChildren() ; i++) {
SGPropertyNode *n = root->getChild(i); SGPropertyNode *n = root->getChild(i);
@ -143,7 +149,7 @@ FGAIManager::update(double dt) {
range_nearest = 10000.0; range_nearest = 10000.0;
strength = 0.0; strength = 0.0;
if (!enabled) if (!enabled->getBoolValue())
return; return;
FGTrafficManager *tmgr = (FGTrafficManager*) globals->get_subsystem("traffic-manager"); FGTrafficManager *tmgr = (FGTrafficManager*) globals->get_subsystem("traffic-manager");

View file

@ -96,13 +96,13 @@ public:
private: private:
bool enabled;
int mNumAiTypeModels[FGAIBase::MAX_OBJECTS]; int mNumAiTypeModels[FGAIBase::MAX_OBJECTS];
int mNumAiModels; int mNumAiModels;
double calcRange(double lat, double lon, double lat2, double lon2)const; double calcRange(double lat, double lon, double lat2, double lon2)const;
SGPropertyNode_ptr root; SGPropertyNode_ptr root;
SGPropertyNode_ptr enabled;
SGPropertyNode_ptr thermal_lift_node; SGPropertyNode_ptr thermal_lift_node;
SGPropertyNode_ptr user_latitude_node; SGPropertyNode_ptr user_latitude_node;
SGPropertyNode_ptr user_longitude_node; SGPropertyNode_ptr user_longitude_node;

View file

@ -22,7 +22,6 @@
#endif #endif
#include <simgear/sg_inlines.h> #include <simgear/sg_inlines.h>
#include <simgear/math/SGMath.hxx>
#include "AIWingman.hxx" #include "AIWingman.hxx"

View file

@ -26,7 +26,6 @@
#include "AIBase.hxx" #include "AIBase.hxx"
#include <simgear/sg_inlines.h> #include <simgear/sg_inlines.h>
#include <simgear/math/SGMath.hxx>
class FGAIWingman : public FGAIBallistic { class FGAIWingman : public FGAIBallistic {

View file

@ -1,4 +1,3 @@
#include <simgear/math/SGMath.hxx>
#include <simgear/misc/sg_path.hxx> #include <simgear/misc/sg_path.hxx>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/props/props_io.hxx> #include <simgear/props/props_io.hxx>

View file

@ -26,7 +26,6 @@
#include <iostream> #include <iostream>
#include <simgear/math/SGMath.hxx>
#include <Airports/dynamics.hxx> #include <Airports/dynamics.hxx>
#include <Airports/simple.hxx> #include <Airports/simple.hxx>
#include <Scenery/scenery.hxx> #include <Scenery/scenery.hxx>

View file

@ -45,8 +45,6 @@
#include <ATC/CommStation.hxx> #include <ATC/CommStation.hxx>
FGATCDialogNew *currentATCDialog;
static SGPropertyNode *getNamedNode(SGPropertyNode *prop, const char *name) static SGPropertyNode *getNamedNode(SGPropertyNode *prop, const char *name)
{ {
SGPropertyNode* p; SGPropertyNode* p;

View file

@ -273,8 +273,8 @@ int FGTrafficRecord::crosses(FGGroundNetwork * net,
if (intentions.size()) { if (intentions.size()) {
for (i = intentions.begin(); i != intentions.end(); i++) { for (i = intentions.begin(); i != intentions.end(); i++) {
if ((*i) > 0) { if ((*i) > 0) {
if ((currentTargetNode == if (currentTargetNode ==
net->findSegment(*i)->getEnd()->getIndex())) { net->findSegment(*i)->getEnd()->getIndex()) {
//cerr << "Current crosses at " << currentTargetNode <<endl; //cerr << "Current crosses at " << currentTargetNode <<endl;
return currentTargetNode; return currentTargetNode;
} }

View file

@ -35,166 +35,101 @@
#include <Airports/simple.hxx> #include <Airports/simple.hxx>
FGATC::FGATC() : FGATC::FGATC() :
_playing(false), freq(0),
_voiceOK(false), _currentStation(NULL),
_sgr(NULL), range(0),
freqClear(true), _voice(true),
receiving(false), _playing(false),
respond(false), _sgr(NULL),
responseID(""), _type(INVALID),
runResponseCounter(false), _display(false)
_runReleaseCounter(false), #ifdef OLD_ATC_MGR
responseReqd(false), ,freqClear(true),
_type(INVALID), receiving(false),
_display(false), respond(false),
// Transmission timing stuff responseID(""),
pending_transmission(""), runResponseCounter(false),
_timeout(0), _runReleaseCounter(false),
_pending(false), responseReqd(false),
_transmit(false), // Transmission timing stuff
_transmitting(false), pending_transmission(""),
_counter(0.0), _timeout(0),
_max_count(5.0) _pending(false),
_transmit(false),
_transmitting(false),
_counter(0.0),
_max_count(5.0)
#endif
{ {
SGSoundMgr *smgr = globals->get_soundmgr(); SGSoundMgr *smgr = globals->get_soundmgr();
_sgr = smgr->find("atc", true); _sgr = smgr->find("atc", true);
_sgr->tie_to_listener(); _sgr->tie_to_listener();
_volume = fgGetNode("/sim/sound/atc/volume", true); _masterVolume = fgGetNode("/sim/sound/atc/volume", true);
_enabled = fgGetNode("/sim/sound/atc/enabled", true); _enabled = fgGetNode("/sim/sound/atc/enabled", true);
_atc_external = fgGetNode("/sim/sound/atc/external-view", true); _atc_external = fgGetNode("/sim/sound/atc/external-view", true);
_internal = fgGetNode("/sim/current-view/internal", true); _internal = fgGetNode("/sim/current-view/internal", true);
} }
FGATC::~FGATC() { FGATC::~FGATC() {
} }
#ifndef OLD_ATC_MGR
// Derived classes wishing to use the response counter should // Derived classes wishing to use the response counter should
// call this from their own Update(...). // call this from their own Update(...).
void FGATC::Update(double dt) { void FGATC::Update(double dt) {
if(runResponseCounter) {
//cout << responseCounter << '\t' << responseTime << '\n';
if(responseCounter >= responseTime) {
runResponseCounter = false;
respond = true;
//cout << "RESPOND\n";
} else {
responseCounter += dt;
}
}
if(_runReleaseCounter) {
if(_releaseCounter >= _releaseTime) {
freqClear = true;
_runReleaseCounter = false;
} else {
_releaseCounter += dt;
}
}
// Transmission stuff cribbed from AIPlane.cxx
if(_pending) {
if(GetFreqClear()) {
//cout << "TUNED STATION FREQ CLEAR\n";
SetFreqInUse();
_pending = false;
_transmit = true;
_transmitting = false;
} else {
if(_timeout > 0.0) { // allows count down to be avoided by initially setting it to zero
_timeout -= dt;
if(_timeout <= 0.0) {
_timeout = 0.0;
_pending = false;
// timed out - don't render.
}
}
}
}
#ifdef ENABLE_AUDIO_SUPPORT #ifdef ENABLE_AUDIO_SUPPORT
bool active = _atc_external->getBoolValue() || bool active = _atc_external->getBoolValue() ||
_internal->getBoolValue(); _internal->getBoolValue();
if ( active && _enabled->getBoolValue() ) { if ( active && _enabled->getBoolValue() ) {
_sgr->set_volume( _volume->getFloatValue() ); _sgr->set_volume( _masterVolume->getFloatValue() );
_sgr->resume(); // no-op if already in resumed state _sgr->resume(); // no-op if already in resumed state
} else { } else {
_sgr->suspend(); _sgr->suspend();
} }
#endif
}
#endif #endif
if(_transmit) {
_counter = 0.0;
_max_count = 5.0; // FIXME - hardwired length of message - need to calculate it!
//cout << "Transmission = " << pending_transmission << '\n';
if(_display) {
//Render(pending_transmission, ident, false);
Render(pending_transmission);
}
_transmit = false;
_transmitting = true;
} else if(_transmitting) {
if(_counter >= _max_count) {
//NoRender(plane.callsign); commented out since at the moment NoRender is designed just to stop repeating messages,
// and this will be primarily used on single messages.
_transmitting = false;
//if(tuned_station) tuned_station->NotifyTransmissionFinished(plane.callsign);
// TODO - need to let the plane the transmission is aimed at that it's finished.
// However, for now we'll just release the frequency since if we don't it all goes pear-shaped
_releaseCounter = 0.0;
_releaseTime = 0.9;
_runReleaseCounter = true;
}
_counter += dt;
}
}
void FGATC::ReceiveUserCallback(int code) {
SG_LOG(SG_ATC, SG_WARN, "WARNING - whichever ATC class was intended to receive callback code " << code << " didn't get it!!!");
}
void FGATC::SetResponseReqd(const string& rid) {
receiving = false;
responseReqd = true;
respond = false; // TODO - this ignores the fact that more than one plane could call this before response
// Shouldn't happen with AI only, but user could confuse things??
responseID = rid;
runResponseCounter = true;
responseCounter = 0.0;
responseTime = 1.8; // TODO - randomize this slightly.
}
void FGATC::NotifyTransmissionFinished(const string& rid) {
//cout << "Transmission finished, callsign = " << rid << '\n';
receiving = false;
responseID = rid;
if(responseReqd) {
runResponseCounter = true;
responseCounter = 0.0;
responseTime = 1.2; // TODO - randomize this slightly, and allow it to be dependent on the transmission and how busy the ATC is.
respond = false; // TODO - this ignores the fact that more than one plane could call this before response
// Shouldn't happen with AI only, but user could confuse things??
} else {
freqClear = true;
}
}
void FGATC::SetStation(flightgear::CommStation* sta) { void FGATC::SetStation(flightgear::CommStation* sta) {
switch (sta->type()) { if (_currentStation == sta)
case FGPositioned::FREQ_ATIS: _type = ATIS; break; return;
case FGPositioned::FREQ_AWOS: _type = AWOS; break; _currentStation = sta;
default:
throw sg_exception("unsupported comm station type"); if (sta)
{
switch (sta->type()) {
case FGPositioned::FREQ_ATIS: _type = ATIS; break;
case FGPositioned::FREQ_AWOS: _type = AWOS; break;
default:
sta = NULL;
break;
}
} }
_geod = sta->geod(); if (sta == NULL)
_cart = sta->cart(); {
range = sta->rangeNm(); range = 0;
ident = sta->airport()->ident(); ident = "";
name = sta->airport()->name(); name = "";
freq = sta->freqKHz(); freq = 0;
SetNoDisplay();
Update(0); // one last update
}
else
{
_geod = sta->geod();
_cart = sta->cart();
range = sta->rangeNm();
ident = sta->airport()->ident();
name = sta->airport()->name();
freq = sta->freqKHz();
SetDisplay();
}
} }
// Render a transmission // Render a transmission
@ -202,134 +137,272 @@ void FGATC::SetStation(flightgear::CommStation* sta) {
// The refname is a string to identify this sample to the sound manager // The refname is a string to identify this sample to the sound manager
// The repeating flag indicates whether the message should be repeated continuously or played once. // The repeating flag indicates whether the message should be repeated continuously or played once.
void FGATC::Render(string& msg, const float volume, void FGATC::Render(string& msg, const float volume,
const string& refname, const bool repeating) { const string& refname, const bool repeating) {
if (volume < 0.05) return; if ((!_display) ||(volume < 0.05))
{
NoRender(refname);
return;
}
if (repeating) if (repeating)
fgSetString("/sim/messages/atis", msg.c_str()); fgSetString("/sim/messages/atis", msg.c_str());
else else
fgSetString("/sim/messages/atc", msg.c_str()); fgSetString("/sim/messages/atc", msg.c_str());
#ifdef ENABLE_AUDIO_SUPPORT #ifdef ENABLE_AUDIO_SUPPORT
_voice = (_voiceOK && fgGetBool("/sim/sound/voice")); bool useVoice = _voice && fgGetBool("/sim/sound/voice") && fgGetBool("/sim/sound/atc/enabled");
if(_voice) { SGSoundSample *simple = _sgr->find(refname);
size_t len; if(useVoice) {
void* buf = _vPtr->WriteMessage((char*)msg.c_str(), &len); if (simple && (_currentMsg == msg))
if(buf) { {
NoRender(refname); simple->set_volume(volume);
try { }
else
{
_currentMsg = msg;
size_t len;
void* buf = NULL;
if (!_vPtr)
_vPtr = GetVoicePointer();
if (_vPtr)
buf = _vPtr->WriteMessage((char*)msg.c_str(), &len);
NoRender(refname);
if(buf) {
try {
// >>> Beware: must pass a (new) object to the (add) method, // >>> Beware: must pass a (new) object to the (add) method,
// >>> because the (remove) method is going to do a (delete) // >>> because the (remove) method is going to do a (delete)
// >>> whether that's what you want or not. // >>> whether that's what you want or not.
SGSoundSample *simple = new SGSoundSample(&buf, len, 8000); simple = new SGSoundSample(&buf, len, 8000);
simple->set_volume(volume); simple->set_volume(volume);
_sgr->add(simple, refname); _sgr->add(simple, refname);
_sgr->play(refname, repeating); _sgr->play(refname, repeating);
} catch ( sg_io_exception &e ) { } catch ( sg_io_exception &e ) {
SG_LOG(SG_ATC, SG_ALERT, e.getFormattedMessage()); SG_LOG(SG_ATC, SG_ALERT, e.getFormattedMessage());
} }
} }
} }
#endif // ENABLE_AUDIO_SUPPORT }
if(!_voice) { else
// first rip the underscores and the pause hints out of the string - these are for the convienience of the voice parser if (simple)
for(unsigned int i = 0; i < msg.length(); ++i) { {
if((msg.substr(i,1) == "_") || (msg.substr(i,1) == "/")) { NoRender(refname);
msg[i] = ' '; }
} #endif // ENABLE_AUDIO_SUPPORT
}
} if (!useVoice)
_playing = true; {
// first rip the underscores and the pause hints out of the string - these are for the convenience of the voice parser
for(unsigned int i = 0; i < msg.length(); ++i) {
if((msg.substr(i,1) == "_") || (msg.substr(i,1) == "/")) {
msg[i] = ' ';
}
}
}
_playing = true;
} }
// Cease rendering a transmission. // Cease rendering a transmission.
void FGATC::NoRender(const string& refname) { void FGATC::NoRender(const string& refname) {
if(_playing) { if(_playing) {
if(_voice) { if(_voice) {
#ifdef ENABLE_AUDIO_SUPPORT #ifdef ENABLE_AUDIO_SUPPORT
_sgr->stop(refname); _sgr->stop(refname);
_sgr->remove(refname); _sgr->remove(refname);
#endif #endif
} }
_playing = false; _playing = false;
} }
}
#ifdef OLD_ATC_MGR
// Derived classes wishing to use the response counter should
// call this from their own Update(...).
void FGATC::Update(double dt) {
#ifdef ENABLE_AUDIO_SUPPORT
bool active = _atc_external->getBoolValue() ||
_internal->getBoolValue();
if ( active && _enabled->getBoolValue() ) {
_sgr->set_volume( _masterVolume->getFloatValue() );
_sgr->resume(); // no-op if already in resumed state
} else {
_sgr->suspend();
}
#endif
if(runResponseCounter) {
//cout << responseCounter << '\t' << responseTime << '\n';
if(responseCounter >= responseTime) {
runResponseCounter = false;
respond = true;
//cout << "RESPOND\n";
} else {
responseCounter += dt;
}
}
if(_runReleaseCounter) {
if(_releaseCounter >= _releaseTime) {
freqClear = true;
_runReleaseCounter = false;
} else {
_releaseCounter += dt;
}
}
// Transmission stuff cribbed from AIPlane.cxx
if(_pending) {
if(GetFreqClear()) {
//cout << "TUNED STATION FREQ CLEAR\n";
SetFreqInUse();
_pending = false;
_transmit = true;
_transmitting = false;
} else {
if(_timeout > 0.0) { // allows count down to be avoided by initially setting it to zero
_timeout -= dt;
if(_timeout <= 0.0) {
_timeout = 0.0;
_pending = false;
// timed out - don't render.
}
}
}
}
if(_transmit) {
_counter = 0.0;
_max_count = 5.0; // FIXME - hardwired length of message - need to calculate it!
//cout << "Transmission = " << pending_transmission << '\n';
if(_display) {
//Render(pending_transmission, ident, false);
Render(pending_transmission);
}
_transmit = false;
_transmitting = true;
} else if(_transmitting) {
if(_counter >= _max_count) {
//NoRender(plane.callsign); commented out since at the moment NoRender is designed just to stop repeating messages,
// and this will be primarily used on single messages.
_transmitting = false;
//if(tuned_station) tuned_station->NotifyTransmissionFinished(plane.callsign);
// TODO - need to let the plane the transmission is aimed at that it's finished.
// However, for now we'll just release the frequency since if we don't it all goes pear-shaped
_releaseCounter = 0.0;
_releaseTime = 0.9;
_runReleaseCounter = true;
}
_counter += dt;
}
}
void FGATC::ReceiveUserCallback(int code) {
SG_LOG(SG_ATC, SG_WARN, "WARNING - whichever ATC class was intended to receive callback code " << code << " didn't get it!!!");
}
void FGATC::SetResponseReqd(const string& rid) {
receiving = false;
responseReqd = true;
respond = false; // TODO - this ignores the fact that more than one plane could call this before response
// Shouldn't happen with AI only, but user could confuse things??
responseID = rid;
runResponseCounter = true;
responseCounter = 0.0;
responseTime = 1.8; // TODO - randomize this slightly.
}
void FGATC::NotifyTransmissionFinished(const string& rid) {
//cout << "Transmission finished, callsign = " << rid << '\n';
receiving = false;
responseID = rid;
if(responseReqd) {
runResponseCounter = true;
responseCounter = 0.0;
responseTime = 1.2; // TODO - randomize this slightly, and allow it to be dependent on the transmission and how busy the ATC is.
respond = false; // TODO - this ignores the fact that more than one plane could call this before response
// Shouldn't happen with AI only, but user could confuse things??
} else {
freqClear = true;
}
} }
// Generate the text of a message from its parameters and the current context. // Generate the text of a message from its parameters and the current context.
string FGATC::GenText(const string& m, int c) { string FGATC::GenText(const string& m, int c) {
return(""); return("");
} }
ostream& operator << (ostream& os, atc_type atc) { ostream& operator << (ostream& os, atc_type atc) {
switch(atc) { switch(atc) {
case(AWOS): return(os << "AWOS"); case(AWOS): return(os << "AWOS");
case(ATIS): return(os << "ATIS"); case(ATIS): return(os << "ATIS");
case(GROUND): return(os << "GROUND"); case(GROUND): return(os << "GROUND");
case(TOWER): return(os << "TOWER"); case(TOWER): return(os << "TOWER");
case(APPROACH): return(os << "APPROACH"); case(APPROACH): return(os << "APPROACH");
case(DEPARTURE): return(os << "DEPARTURE"); case(DEPARTURE): return(os << "DEPARTURE");
case(ENROUTE): return(os << "ENROUTE"); case(ENROUTE): return(os << "ENROUTE");
case(INVALID): return(os << "INVALID"); case(INVALID): return(os << "INVALID");
} }
return(os << "ERROR - Unknown switch in atc_type operator << "); return(os << "ERROR - Unknown switch in atc_type operator << ");
} }
std::istream& operator >> ( std::istream& fin, ATCData& a ) std::istream& operator >> ( std::istream& fin, ATCData& a )
{ {
double f; double f;
char ch; char ch;
char tp; char tp;
fin >> tp; fin >> tp;
switch(tp) { switch(tp) {
case 'I': case 'I':
a.type = ATIS; a.type = ATIS;
break; break;
case 'T': case 'T':
a.type = TOWER; a.type = TOWER;
break; break;
case 'G': case 'G':
a.type = GROUND; a.type = GROUND;
break; break;
case 'A': case 'A':
a.type = APPROACH; a.type = APPROACH;
break; break;
case '[': case '[':
a.type = INVALID; a.type = INVALID;
return fin >> skipeol; return fin >> skipeol;
default: default:
SG_LOG(SG_ATC, SG_ALERT, "Warning - unknown type \'" << tp << "\' found whilst reading ATC frequency data!\n"); SG_LOG(SG_ATC, SG_ALERT, "Warning - unknown type \'" << tp << "\' found whilst reading ATC frequency data!\n");
a.type = INVALID; a.type = INVALID;
return fin >> skipeol; return fin >> skipeol;
} }
double lat, lon, elev; double lat, lon, elev;
fin >> lat >> lon >> elev >> f >> a.range >> a.ident; fin >> lat >> lon >> elev >> f >> a.range >> a.ident;
a.geod = SGGeod::fromDegM(lon, lat, elev); a.geod = SGGeod::fromDegM(lon, lat, elev);
a.name = ""; a.name = "";
fin >> ch; fin >> ch;
if(ch != '"') a.name += ch; if(ch != '"') a.name += ch;
while(1) { while(1) {
//in >> noskipws //in >> noskipws
fin.unsetf(std::ios::skipws); fin.unsetf(std::ios::skipws);
fin >> ch; fin >> ch;
if((ch == '"') || (ch == 0x0A)) { if((ch == '"') || (ch == 0x0A)) {
break; break;
} // we shouldn't need the 0x0A but it makes a nice safely in case someone leaves off the " } // we shouldn't need the 0x0A but it makes a nice safely in case someone leaves off the "
a.name += ch; a.name += ch;
} }
fin.setf(std::ios::skipws); fin.setf(std::ios::skipws);
//cout << "Comm name = " << a.name << '\n'; //cout << "Comm name = " << a.name << '\n';
a.freq = (int)(f*100.0 + 0.5); a.freq = (int)(f*100.0 + 0.5);
// cout << a.ident << endl; // cout << a.ident << endl;
// generate cartesian coordinates // generate cartesian coordinates
a.cart = SGVec3d::fromGeod(a.geod); a.cart = SGVec3d::fromGeod(a.geod);
return fin >> skipeol; return fin >> skipeol;
} }
#endif

View file

@ -42,20 +42,6 @@ namespace flightgear
class CommStation; class CommStation;
} }
// Convert a frequency in MHz to tens of kHz
// so we can use it e.g. as an index into commlist_freq
//
// If freq > 1000 assume it's already in tens of KHz;
// otherwise assume MHz.
//
// Note: 122.375 must be rounded DOWN to 12237
// in order to be consistent with apt.dat et cetera.
inline int kHz10(double freq)
{
if (freq > 1000.) return int(freq);
return int(freq*100.0 + 0.25);
}
// Possible types of ATC type that the radios may be tuned to. // Possible types of ATC type that the radios may be tuned to.
// INVALID implies not tuned in to anything. // INVALID implies not tuned in to anything.
enum atc_type { enum atc_type {
@ -69,6 +55,7 @@ enum atc_type {
INVALID /* must be last element; see ATC_NUM_TYPES */ INVALID /* must be last element; see ATC_NUM_TYPES */
}; };
#ifdef OLD_ATC_MGR
const int ATC_NUM_TYPES = 1 + INVALID; const int ATC_NUM_TYPES = 1 + INVALID;
// DCL - new experimental ATC data store // DCL - new experimental ATC data store
@ -98,9 +85,10 @@ struct RunwayDetails {
}; };
std::ostream& operator << (std::ostream& os, atc_type atc); std::ostream& operator << (std::ostream& os, atc_type atc);
#endif
class FGATC { class FGATC {
friend class FGATCMgr; friend class FGATISMgr;
public: public:
FGATC(); FGATC();
@ -113,15 +101,16 @@ public:
// wish to use the response timer functionality. // wish to use the response timer functionality.
virtual void Update(double dt); virtual void Update(double dt);
// Recieve a coded callback from the ATC menu system based on the user's selection
virtual void ReceiveUserCallback(int code);
// Indicate that this instance should output to the display if appropriate // Indicate that this instance should output to the display if appropriate
inline void SetDisplay() { _display = true; } inline void SetDisplay() { _display = true; }
// Indicate that this instance should not output to the display // Indicate that this instance should not output to the display
inline void SetNoDisplay() { _display = false; } inline void SetNoDisplay() { _display = false; }
#ifdef OLD_ATC_MGR
// Receive a coded callback from the ATC menu system based on the user's selection
virtual void ReceiveUserCallback(int code);
// Generate the text of a message from its parameters and the current context. // Generate the text of a message from its parameters and the current context.
virtual std::string GenText(const std::string& m, int c); virtual std::string GenText(const std::string& m, int c);
@ -141,16 +130,19 @@ public:
// AI traffic should check FreqClear() is true prior to transmitting. // AI traffic should check FreqClear() is true prior to transmitting.
// The user will just have to wait for a gap in dialog as in real life. // The user will just have to wait for a gap in dialog as in real life.
inline int get_freq() const { return freq; }
inline void set_freq(const int fq) {freq = fq;}
inline int get_range() const { return range; }
inline void set_range(const int rg) {range = rg;}
#endif
// Return the type of ATC station that the class represents // Return the type of ATC station that the class represents
inline atc_type GetType() { return _type; } inline atc_type GetType() { return _type; }
// Set the core ATC data // Set the core ATC data
void SetStation(flightgear::CommStation* sta); void SetStation(flightgear::CommStation* sta);
inline int get_freq() const { return freq; }
inline void set_freq(const int fq) {freq = fq;}
inline int get_range() const { return range; }
inline void set_range(const int rg) {range = rg;}
inline const std::string& get_ident() { return ident; } inline const std::string& get_ident() { return ident; }
inline void set_ident(const std::string& id) { ident = id; } inline void set_ident(const std::string& id) { ident = id; }
inline const std::string& get_name() { return name; } inline const std::string& get_name() { return name; }
@ -169,25 +161,26 @@ protected:
// Requires the sound manager refname if audio, else "". // Requires the sound manager refname if audio, else "".
void NoRender(const std::string& refname); void NoRender(const std::string& refname);
virtual FGATCVoice* GetVoicePointer() = 0;
SGGeod _geod; SGGeod _geod;
SGVec3d _cart; SGVec3d _cart;
int freq; int freq;
std::map<std::string,int> active_on; flightgear::CommStation* _currentStation;
int range; int range;
std::string ident; // Code of the airport its at. std::string ident; // Code of the airport its at.
std::string name; // Name transmitted in the broadcast. std::string name; // Name transmitted in the broadcast.
std::string _currentMsg; // Current message being transmitted
// Rendering related stuff // Rendering related stuff
bool _voice; // Flag - true if we are using voice bool _voice; // Flag - true if we are using voice
bool _playing; // Indicates a message in progress bool _playing; // Indicates a message in progress
bool _voiceOK; // Flag - true if at least one voice has loaded OK
FGATCVoice* _vPtr; FGATCVoice* _vPtr;
SGSharedPtr<SGSampleGroup> _sgr; // default sample group; SGSharedPtr<SGSampleGroup> _sgr; // default sample group;
#ifdef OLD_ATC_MGR
bool freqClear; // Flag to indicate if the frequency is clear of ongoing dialog bool freqClear; // Flag to indicate if the frequency is clear of ongoing dialog
bool receiving; // Flag to indicate we are receiving a transmission bool receiving; // Flag to indicate we are receiving a transmission
@ -204,11 +197,14 @@ protected:
bool responseReqd; // Flag to indicate we should be responding to a request/report bool responseReqd; // Flag to indicate we should be responding to a request/report
double _releaseTime; double _releaseTime;
double _releaseCounter; double _releaseCounter;
std::string pending_transmission; // derived classes set this string before calling Transmit(...)
#endif
atc_type _type; atc_type _type;
bool _display; // Flag to indicate whether we should be outputting to the ATC display. bool _display; // Flag to indicate whether we should be outputting to the ATC display.
std::string pending_transmission; // derived classes set this string before calling Transmit(...)
private: private:
#ifdef OLD_ATC_MGR
// Transmission timing stuff. // Transmission timing stuff.
double _timeout; double _timeout;
bool _pending; bool _pending;
@ -216,13 +212,16 @@ private:
bool _transmitting; // we are transmitting bool _transmitting; // we are transmitting
double _counter; double _counter;
double _max_count; double _max_count;
#endif
SGPropertyNode_ptr _volume; SGPropertyNode_ptr _masterVolume;
SGPropertyNode_ptr _enabled; SGPropertyNode_ptr _enabled;
SGPropertyNode_ptr _atc_external; SGPropertyNode_ptr _atc_external;
SGPropertyNode_ptr _internal; SGPropertyNode_ptr _internal;
}; };
#ifdef OLD_ATC_MGR
std::istream& operator>> ( std::istream& fin, ATCData& a ); std::istream& operator>> ( std::istream& fin, ATCData& a );
#endif
#endif // _FG_ATC_HXX #endif // _FG_ATC_HXX

View file

@ -1,308 +0,0 @@
// ATCDialog.cxx - Functions and classes to handle the pop-up ATC dialog
//
// Written by Alexander Kappes and David Luff, started February 2003.
//
// Copyright (C) 2003 Alexander Kappes and David Luff
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <simgear/compiler.h>
#include <simgear/structure/commands.hxx>
#include <simgear/props/props_io.hxx>
#include <Main/globals.hxx>
#include <GUI/gui.h> // mkDialog
#include <GUI/new_gui.hxx>
#include <Main/fg_props.hxx>
#include "ATCDialogOld.hxx"
#include "ATC.hxx"
#include "ATCmgr.hxx"
#include "ATCutils.hxx"
#include <Airports/simple.hxx>
#include <ATC/CommStation.hxx>
#include <sstream>
using std::ostringstream;
using std::cerr;
using std::endl;
FGATCDialog *current_atcdialog;
// For the command manager - maybe eventually this should go in the built in command list
#if 0
static bool do_ATC_dialog(const SGPropertyNode* arg) {
cerr << "Running ATCDCL do_ATC_dialog" << endl;
current_atcdialog->PopupDialog();
return(true);
}
static bool do_ATC_freq_search(const SGPropertyNode* arg) {
current_atcdialog->FreqDialog();
return(true);
}
#endif
ATCMenuEntry::ATCMenuEntry() {
stationid = "";
//stationfr = 0;
transmission = "";
menuentry = "";
callback_code = 0;
}
ATCMenuEntry::~ATCMenuEntry() {
}
void atcUppercase(string &s) {
for(unsigned int i=0; i<s.size(); ++i) {
s[i] = toupper(s[i]);
}
}
// find child whose <name>...</name> entry matches 'name'
static SGPropertyNode *getNamedNode(SGPropertyNode *prop, const char *name) {
SGPropertyNode* p;
for (int i = 0; i < prop->nChildren(); i++)
if ((p = getNamedNode(prop->getChild(i), name)))
return p;
if (!strcmp(prop->getStringValue("name"), name))
return prop;
return 0;
}
FGATCDialog::FGATCDialog() {
_callbackPending = false;
_callbackTimer = 0.0;
_callbackWait = 0.0;
_callbackPtr = NULL;
_callbackCode = 0;
_gui = (NewGUI *)globals->get_subsystem("gui");
}
FGATCDialog::~FGATCDialog() {
}
void FGATCDialog::Init() {
// Add ATC-dialog to the command list
//globals->get_commands()->addCommand("ATC-dialog", do_ATC_dialog);
// Add ATC-freq-search to the command list
//globals->get_commands()->addCommand("ATC-freq-search", do_ATC_freq_search);
// initialize properties polled in Update()
//globals->get_props()->setStringValue("/sim/atc/freq-airport", "");
//globals->get_props()->setIntValue("/sim/atc/transmission-num", -1);
}
void FGATCDialog::Update(double dt) {
//static SGPropertyNode_ptr airport = globals->get_props()->getNode("/sim/atc/freq-airport", true);
//string s = airport->getStringValue();
//if (!s.empty()) {
// airport->setStringValue("");
// FreqDisplay(s);
//}
//static SGPropertyNode_ptr trans_num = globals->get_props()->getNode("/sim/atc/transmission-num", true);
//int n = trans_num->getIntValue();
//if (n >= 0) {
// trans_num->setIntValue(-1);
// PopupCallback(n);
//}
//if(_callbackPending) {
// if(_callbackTimer > _callbackWait) {
// _callbackPtr->ReceiveUserCallback(_callbackCode);
// _callbackPtr->NotifyTransmissionFinished(fgGetString("/sim/user/callsign"));
// _callbackPending = false;
// } else {
// _callbackTimer += dt;
// }
//}
}
// Add an entry
void FGATCDialog::add_entry(const string& station, const string& transmission, const string& menutext, atc_type type, int code) {
ATCMenuEntry a;
a.stationid = station;
a.transmission = transmission;
a.menuentry = menutext;
a.callback_code = code;
(available_dialog[type])[station.c_str()].push_back(a);
}
void FGATCDialog::remove_entry( const string &station, const string &trans, atc_type type ) {
atcmentry_vec_type* p = &((available_dialog[type])[station]);
atcmentry_vec_iterator current = p->begin();
while(current != p->end()) {
if(current->transmission == trans) current = p->erase(current);
else ++current;
}
}
void FGATCDialog::remove_entry( const string &station, int code, atc_type type ) {
atcmentry_vec_type* p = &((available_dialog[type])[station]);
atcmentry_vec_iterator current = p->begin();
while(current != p->end()) {
if(current->callback_code == code) current = p->erase(current);
else ++current;
}
}
// query the database whether the transmission is already registered;
bool FGATCDialog::trans_reg( const string &station, const string &trans, atc_type type ) {
atcmentry_vec_type* p = &((available_dialog[type])[station]);
atcmentry_vec_iterator current = p->begin();
for ( ; current != p->end() ; ++current ) {
if ( current->transmission == trans ) return true;
}
return false;
}
// query the database whether the transmission is already registered;
bool FGATCDialog::trans_reg( const string &station, int code, atc_type type ) {
atcmentry_vec_type* p = &((available_dialog[type])[station]);
atcmentry_vec_iterator current = p->begin();
for ( ; current != p->end() ; ++current ) {
if ( current->callback_code == code ) return true;
}
return false;
}
// Display the ATC popup dialog box with options relevant to the users current situation.
void FGATCDialog::PopupDialog() {
const char *dialog_name = "atc-dialog";
SGPropertyNode_ptr dlg = _gui->getDialogProperties(dialog_name);
if (!dlg)
return;
_gui->closeDialog(dialog_name);
SGPropertyNode_ptr button_group = getNamedNode(dlg, "transmission-choice");
// remove all transmission buttons
button_group->removeChildren("button", false);
string label;
FGATCMgr* pAtcMgr = globals->get_ATC_mgr();
if (!pAtcMgr)
{
SG_LOG(SG_ATC, SG_ALERT, "ERROR! No ATC manager! Oops...");
return;
}
FGATC* atcptr = pAtcMgr->GetComm1ATCPointer(); // Hardwired to comm1 at the moment
if (!atcptr) {
label = "Not currently tuned to any ATC service";
mkDialog(label.c_str());
return;
}
if(atcptr->GetType() == ATIS) {
label = "Tuned to ATIS - no communication possible";
mkDialog(label.c_str());
return;
}
atcmentry_vec_type atcmlist = (available_dialog[atcptr->GetType()])[atcptr->get_ident()];
atcmentry_vec_iterator current = atcmlist.begin();
atcmentry_vec_iterator last = atcmlist.end();
if(!atcmlist.size()) {
label = "No transmission available";
mkDialog(label.c_str());
return;
}
const int bufsize = 32;
char buf[bufsize];
// loop over all entries in atcmentrylist
for (int n = 0; n < 10; ++n) {
snprintf(buf, bufsize, "/sim/atc/opt[%d]", n);
fgSetBool(buf, false);
if (current == last)
continue;
// add transmission button (modified copy of <button-template>)
SGPropertyNode *entry = button_group->getNode("button", n, true);
copyProperties(button_group->getNode("button-template", true), entry);
entry->removeChildren("enabled", true);
entry->setStringValue("property", buf);
entry->setIntValue("keynum", '1' + n);
if (n == 0)
entry->setBoolValue("default", true);
snprintf(buf, bufsize, "%d", n + 1);
string legend = string(buf) + ". " + current->menuentry;
entry->setStringValue("legend", legend.c_str());
entry->setIntValue("binding/value", n);
current++;
}
_gui->showDialog(dialog_name);
return;
}
void FGATCDialog::PopupCallback(int num) {
FGATCMgr* pAtcMgr = globals->get_ATC_mgr();
if (!pAtcMgr)
{
SG_LOG(SG_ATC, SG_ALERT, "ERROR! No ATC manager! Oops...");
return;
}
FGATC* atcptr = pAtcMgr->GetComm1ATCPointer(); // FIXME - Hardwired to comm1 at the moment
if (!atcptr)
return;
if (atcptr->GetType() == TOWER) {
//cout << "TOWER " << endl;
//cout << "ident is " << atcptr->get_ident() << endl;
atcmentry_vec_type atcmlist = (available_dialog[TOWER])[atcptr->get_ident()];
int size = atcmlist.size();
if(size && num < size) {
//cout << "Doing callback...\n";
ATCMenuEntry a = atcmlist[num];
atcptr->SetFreqInUse();
string pilot = atcptr->GenText(a.transmission, a.callback_code);
fgSetString("/sim/messages/pilot", pilot.c_str());
// This is the user's speech getting displayed.
_callbackPending = true;
_callbackTimer = 0.0;
_callbackWait = 5.0;
_callbackPtr = atcptr;
_callbackCode = a.callback_code;
} else {
//cout << "No options available...\n";
}
//cout << "Donded" << endl;
}
}

View file

@ -1,116 +0,0 @@
// ATCDialog.hxx - Functions and classes to handle the pop-up ATC dialog
//
// Written by Alexander Kappes and David Luff, started February 2003.
//
// Copyright (C) 2003 Alexander Kappes and David Luff
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef ATC_DIALOG_HXX
#define ATC_DIALOG_HXX
#include <simgear/compiler.h>
#include <vector>
#include <map>
#include "ATC.hxx"
using std::vector;
using std::map;
class NewGUI;
// ATCMenuEntry - an encapsulation of an entry in the ATC dialog
struct ATCMenuEntry {
string stationid; // ID of transmitting station
//int stationfr; // ?
string transmission; // Actual speech of transmission
string menuentry; // Shortened version for display in the dialog
int callback_code; // This code is supplied by the registering station, and then
// returned to the registering station if that option is chosen.
// The actual value is only understood by the registering station -
// FGATCDialog only stores it and returns it if appropriate.
ATCMenuEntry();
~ATCMenuEntry();
};
typedef vector < ATCMenuEntry > atcmentry_vec_type;
typedef atcmentry_vec_type::iterator atcmentry_vec_iterator;
typedef map < string, atcmentry_vec_type > atcmentry_map_type;
typedef atcmentry_map_type::iterator atcmentry_map_iterator;
void atcUppercase(string &s);
//void ATCDialogInit();
//void ATCDoDialog(atc_type type);
class FGATCDialog {
public:
FGATCDialog();
~FGATCDialog();
void Init();
void Update(double dt);
void PopupDialog();
void PopupCallback(int);
void add_entry( const string& station, const string& transmission, const string& menutext, atc_type type, int code);
void remove_entry( const string &station, const string &trans, atc_type type );
void remove_entry( const string &station, int code, atc_type type );
// query the database whether the transmission is already registered;
bool trans_reg( const string &station, const string &trans, atc_type type );
// query the database whether the transmission is already registered;
bool trans_reg( const string &station, int code, atc_type type );
// Display a frequency search dialog for nearby stations
void FreqDialog();
// Display the comm ATC frequencies for airport ident
// where ident is a valid ICAO code.
void FreqDisplay(string& ident);
private:
atcmentry_map_type available_dialog[ATC_NUM_TYPES];
int freq;
bool reset;
bool _callbackPending;
double _callbackTimer;
double _callbackWait;
FGATC* _callbackPtr;
int _callbackCode;
NewGUI *_gui;
};
extern FGATCDialog *current_atcdialog;
#endif // ATC_DIALOG_HXX

View file

@ -1,316 +0,0 @@
// ATCmgr.cxx - Implementation of FGATCMgr - a global Flightgear ATC manager.
//
// Written by David Luff, started February 2002.
//
// Copyright (C) 2002 David C Luff - david.luff@nottingham.ac.uk
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/misc/sg_path.hxx>
#include <simgear/debug/logstream.hxx>
#include <simgear/structure/exception.hxx>
#include <Airports/simple.hxx>
#include <ATC/CommStation.hxx>
#include <Main/fg_props.hxx>
#include "ATCmgr.hxx"
#include "ATCDialogOld.hxx"
#include "ATCutils.hxx"
#include "atis.hxx"
using flightgear::CommStation;
FGATCMgr::FGATCMgr() :
initDone(false),
atc_list(new atc_list_type),
#ifdef ENABLE_AUDIO_SUPPORT
voice(true),
voiceOK(false),
v1(0)
#else
voice(false),
#endif
{
globals->set_ATC_mgr(this);
}
FGATCMgr::~FGATCMgr() {
globals->set_ATC_mgr(NULL);
delete v1;
}
void FGATCMgr::bind() {
}
void FGATCMgr::unbind() {
}
void FGATCMgr::init() {
//cout << "ATCMgr::init called..." << endl;
lon_node = fgGetNode("/position/longitude-deg", true);
lat_node = fgGetNode("/position/latitude-deg", true);
elev_node = fgGetNode("/position/altitude-ft", true);
atc_list_itr = atc_list->begin();
// Search for connected ATC stations once per 0.8 seconds or so
// globals->get_event_mgr()->add( "fgATCSearch()", fgATCSearch,
// FGEvent::FG_EVENT_READY, 800);
//
// For some reason the above doesn't compile - including Time/event.hxx stops compilation.
// Is this still true after the reorganization of the event managar??
// -EMH-
// Initialise the ATC Dialogs
SG_LOG(SG_ATC, SG_INFO, " ATC Dialog System");
current_atcdialog = new FGATCDialog;
current_atcdialog->Init();
initDone = true;
//cout << "ATCmgr::init done!" << endl;
}
void FGATCMgr::update(double dt) {
if(!initDone) {
init();
SG_LOG(SG_ATC, SG_WARN, "Warning - ATCMgr::update(...) called before ATCMgr::init()");
}
current_atcdialog->Update(dt);
//cout << "Entering update..." << endl;
//Traverse the list of active stations.
//Only update one class per update step to avoid the whole ATC system having to calculate between frames.
//Eventually we should only update every so many steps.
//cout << "In FGATCMgr::update - atc_list.size = " << atc_list->size() << endl;
if(atc_list->size()) {
if(atc_list_itr == atc_list->end()) {
atc_list_itr = atc_list->begin();
}
//cout << "Updating " << (*atc_list_itr)->get_ident() << ' ' << (*atc_list_itr)->GetType() << '\n';
//cout << "Freq = " << (*atc_list_itr)->get_freq() << '\n';
//cout << "Updating...\n";
(*atc_list_itr).second->Update(dt * atc_list->size());
//cout << "Done ATC update..." << endl;
++atc_list_itr;
}
#ifdef ATC_TEST
//cout << "ATC_LIST: " << atc_list->size() << ' ';
for(atc_list_iterator it = atc_list->begin(); it != atc_list->end(); it++) {
cout << (*it)->get_ident() << ' ';
}
//cout << '\n';
#endif
// Search the tuned frequencies every now and then - this should be done with the event scheduler
static int i = 0; // Very ugly - but there should only ever be one instance of FGATCMgr.
if(i == 15) {
//cout << "About to search navcomm1" << endl;
FreqSearch("comm", 0);
FreqSearch("nav", 0);
}
if(i == 30) {
//cout << "About to search navcomm2" << endl;
FreqSearch("comm", 1);
FreqSearch("nav", 1);
i = 0;
}
++i;
//cout << "comm1 type = " << comm_type[0] << '\n';
//cout << "Leaving update..." << endl;
}
typedef map<string,int> MSI;
void FGATCMgr::ZapOtherService(const string ncunit, const string svc_name){
for (atc_list_iterator svc = atc_list->begin(); svc != atc_list->end(); svc++) {
if (svc->first != svc_name) {
MSI &actv = svc->second->active_on;
// OK, we have found some OTHER service;
// see if it is (was) active on our unit:
if (!actv.count(ncunit)) continue;
//cout << "Eradicating '" << svc->first << "' from: " << ncunit << endl;
actv.erase(ncunit);
if (!actv.size()) {
//cout << "Eradicating service: '" << svc->first << "'" << endl;
svc->second->SetNoDisplay();
svc->second->Update(0); // one last update
SG_LOG(SG_ATC, SG_INFO, "would have erased ATC service:" << svc->second->get_name()<< "/"
<< svc->second->get_ident());
// delete svc->second;
atc_list->erase(svc);
// ALL pointers into the ATC list are now invalid,
// so let's reset them:
atc_list_itr = atc_list->begin();
}
break; // cannot be duplicates in the active list
}
}
}
// Find in list - return a currently active ATC pointer given ICAO code and type
// Return NULL if the given service is not in the list
// - *** THE CALLING FUNCTION MUST CHECK FOR THIS ***
FGATC* FGATCMgr::FindInList(const string& id, const atc_type& tp) {
string ndx = id + decimalNumeral(tp);
if (!atc_list->count(ndx)) return 0;
return (*atc_list)[ndx];
}
// Return a pointer to an appropriate voice for a given type of ATC
// creating the voice if necessary - ie. make sure exactly one copy
// of every voice in use exists in memory.
//
// TODO - in the future this will get more complex and dole out country/airport
// specific voices, and possible make sure that the same voice doesn't get used
// at different airports in quick succession if a large enough selection are available.
FGATCVoice* FGATCMgr::GetVoicePointer(const atc_type& type) {
// TODO - implement me better - maintain a list of loaded voices and other voices!!
if(voice) {
switch(type) {
case ATIS: case AWOS:
#ifdef ENABLE_AUDIO_SUPPORT
// Delayed loading fo all available voices, needed because the
// soundmanager might not be initialized (at all) at this point.
// For now we'll do one hardwired one
/* I've loaded the voice even if /sim/sound/pause is true
* since I know no way of forcing load of the voice if the user
* subsequently switches /sim/sound/audible to true.
* (which is the right thing to do -- CLO) :-)
*/
if (!voiceOK && fgGetBool("/sim/sound/working")) {
v1 = new FGATCVoice;
try {
voiceOK = v1->LoadVoice("default");
voice = voiceOK;
} catch ( sg_io_exception & e) {
voiceOK = false;
SG_LOG(SG_ATC, SG_ALERT, "Unable to load default voice : "
<< e.getFormattedMessage().c_str());
voice = false;
delete v1;
v1 = 0;
}
}
#endif
if(voiceOK) {
return(v1);
}
case TOWER:
return(NULL);
case APPROACH:
return(NULL);
case GROUND:
return(NULL);
default:
return(NULL);
}
return(NULL);
} else {
return(NULL);
}
}
// Search for ATC stations by frequency
void FGATCMgr::FreqSearch(const string navcomm, const int unit) {
string ncunit = navcomm + "[" + decimalNumeral(unit) + "]";
string commbase = "/instrumentation/" + ncunit;
string commfreq = commbase + "/frequencies/selected-mhz";
SGPropertyNode_ptr comm_node = fgGetNode(commfreq.c_str(), false);
//cout << "FreqSearch: " << ncunit
// << " node: " << comm_node << endl;
if (!comm_node) return; // no such radio unit
ATCData data;
// Note: 122.375 must be rounded DOWN to 12237
// in order to be consistent with apt.dat et cetera.
int freqKhz = static_cast<int>(comm_node->getDoubleValue() * 100.0 + 0.25);
_aircraftPos = SGGeod::fromDegFt(lon_node->getDoubleValue(),
lat_node->getDoubleValue(), elev_node->getDoubleValue());
class RangeFilter : public CommStation::Filter {
public:
RangeFilter( const SGGeod & pos ) :
CommStation::Filter(),
_cart(SGVec3d::fromGeod(pos)),
_pos(pos)
{}
virtual bool pass(FGPositioned* aPos) const
{
flightgear::CommStation * stn = dynamic_cast<flightgear::CommStation*>(aPos);
if( NULL == stn ) return false;
// do the range check in cartesian space, since the distances are potentially
// large enough that the geodetic functions become unstable
// (eg, station on opposite side of the planet)
double rangeM = SGMiscd::max( stn->rangeNm(), 10.0 ) * SG_NM_TO_METER;
double d2 = distSqr( aPos->cart(), _cart);
return d2 <= (rangeM * rangeM);
}
private:
SGVec3d _cart;
SGGeod _pos;
};
RangeFilter rangeFilter(_aircraftPos );
CommStation* sta = CommStation::findByFreq(freqKhz, _aircraftPos, &rangeFilter );
if (!sta) {
ZapOtherService(ncunit, "x x x");
return;
}
// Get rid of any *other* service that was on this radio unit:
FGPositioned::Type ty = sta->type();
string svc_name = sta->ident() + FGPositioned::nameForType(ty);
ZapOtherService(ncunit, svc_name);
// See if the service already exists, possibly connected to
// some other radio unit:
if (atc_list->count(svc_name)) {
// make sure the service knows it's tuned on this radio:
FGATC* svc = (*atc_list)[svc_name];
svc->active_on[ncunit] = 1;
svc->SetDisplay();
return;
}
// This was a switch-case statement but the compiler didn't like
// the new variable creation with it.
if(ty == FGPositioned::FREQ_ATIS || ty == FGPositioned::FREQ_AWOS) {
(*atc_list)[svc_name] = new FGATIS;
FGATC* svc = (*atc_list)[svc_name];
if(svc != NULL) {
svc->SetStation(sta);
svc->active_on[ncunit] = 1;
svc->SetDisplay();
svc->Init();
}
}
}

View file

@ -23,8 +23,8 @@
#endif #endif
#include <sstream> #include <sstream>
#include <cstdlib>
#include <simgear/math/SGMath.hxx>
#include <simgear/constants.h> #include <simgear/constants.h>
#include <simgear/misc/sg_path.hxx> #include <simgear/misc/sg_path.hxx>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>

View file

@ -21,7 +21,6 @@
#include <Airports/simple.hxx> #include <Airports/simple.hxx>
#include <Airports/runways.hxx> #include <Airports/runways.hxx>
#include <simgear/math/SGMath.hxx>
#include <math.h> #include <math.h>
#include <string> #include <string>
using std::string; using std::string;

208
src/ATCDCL/ATISmgr.cxx Normal file
View file

@ -0,0 +1,208 @@
// ATISmgr.cxx - Implementation of FGATISMgr - a global Flightgear ATIS manager.
//
// Written by David Luff, started February 2002.
//
// Copyright (C) 2002 David C Luff - david.luff@nottingham.ac.uk
// Copyright (C) 2012 Thorsten Brehm
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <simgear/misc/sg_path.hxx>
#include <simgear/debug/logstream.hxx>
#include <simgear/structure/exception.hxx>
#include <Airports/simple.hxx>
#include <ATC/CommStation.hxx>
#include <Main/fg_props.hxx>
#include "ATISmgr.hxx"
#include "ATCutils.hxx"
#include "atis.hxx"
using flightgear::CommStation;
FGATISMgr::FGATISMgr() :
_currentUnit(0),
_maxCommRadios(2),
#ifdef ENABLE_AUDIO_SUPPORT
voice(true),
voice1(0)
#else
voice(false)
#endif
{
globals->set_ATIS_mgr(this);
}
FGATISMgr::~FGATISMgr()
{
globals->set_ATIS_mgr(NULL);
for (unsigned int unit = 0;unit < _maxCommRadios; ++unit)
{
delete radios[unit].station;
radios[unit].station = NULL;
}
#ifdef ENABLE_AUDIO_SUPPORT
delete voice1;
#endif
}
void FGATISMgr::bind()
{
}
void FGATISMgr::unbind()
{
}
void FGATISMgr::init()
{
lon_node = fgGetNode("/position/longitude-deg", true);
lat_node = fgGetNode("/position/latitude-deg", true);
elev_node = fgGetNode("/position/altitude-ft", true);
for (unsigned int unit = 0;unit < _maxCommRadios; ++unit)
{
CommRadioData data;
string ncunit = "comm[" + decimalNumeral(unit) + "]";
string commbase = "/instrumentation/" + ncunit;
string commfreq = commbase + "/frequencies/selected-mhz";
data.freq = fgGetNode(commfreq.c_str(), true);
data.station = new FGATIS(commbase);
radios.push_back(data);
}
}
void FGATISMgr::update(double dt)
{
// update only runs every now and then (1-2 per second)
if (++_currentUnit >= _maxCommRadios)
_currentUnit = 0;
FGATC* pStation = radios[_currentUnit].station;
if (pStation)
pStation->Update(dt * _maxCommRadios);
// Search the tuned frequencies
FreqSearch(_currentUnit);
}
// Return a pointer to an appropriate voice for a given type of ATC
// creating the voice if necessary - i.e. make sure exactly one copy
// of every voice in use exists in memory.
//
// TODO - in the future this will get more complex and dole out country/airport
// specific voices, and possible make sure that the same voice doesn't get used
// at different airports in quick succession if a large enough selection are available.
FGATCVoice* FGATISMgr::GetVoicePointer(const atc_type& type)
{
// TODO - implement me better - maintain a list of loaded voices and other voices!!
if(voice)
{
switch(type)
{
case ATIS: case AWOS:
#ifdef ENABLE_AUDIO_SUPPORT
// Delayed loading for all available voices, needed because the
// sound manager might not be initialized (at all) at this point.
// For now we'll do one hard-wired one
/* I've loaded the voice even if /sim/sound/pause is true
* since I know no way of forcing load of the voice if the user
* subsequently switches /sim/sound/audible to true.
* (which is the right thing to do -- CLO) :-)
*/
if (!voice1 && fgGetBool("/sim/sound/working")) {
voice1 = new FGATCVoice;
try {
voice = voice1->LoadVoice("default");
} catch ( sg_io_exception & e) {
SG_LOG(SG_ATC, SG_ALERT, "Unable to load default voice : "
<< e.getFormattedMessage().c_str());
voice = false;
delete voice1;
voice1 = 0;
}
}
if (voice)
return voice1;
#endif
return NULL;
case TOWER:
return NULL;
case APPROACH:
return NULL;
case GROUND:
return NULL;
default:
return NULL;
}
}
return NULL;
}
class RangeFilter : public CommStation::Filter
{
public:
RangeFilter( const SGGeod & pos ) :
CommStation::Filter(),
_cart(SGVec3d::fromGeod(pos)),
_pos(pos)
{
}
virtual bool pass(FGPositioned* aPos) const
{
flightgear::CommStation * stn = dynamic_cast<flightgear::CommStation*>(aPos);
if( NULL == stn )
return false;
// do the range check in cartesian space, since the distances are potentially
// large enough that the geodetic functions become unstable
// (eg, station on opposite side of the planet)
double rangeM = SGMiscd::max( stn->rangeNm(), 10.0 ) * SG_NM_TO_METER;
double d2 = distSqr( aPos->cart(), _cart);
return d2 <= (rangeM * rangeM);
}
private:
SGVec3d _cart;
SGGeod _pos;
};
// Search for ATC stations by frequency
void FGATISMgr::FreqSearch(const unsigned int unit)
{
double frequency = radios[unit].freq->getDoubleValue();
// Note: 122.375 must be rounded DOWN to 12237
// in order to be consistent with apt.dat et cetera.
int freqKhz = static_cast<int>(frequency * 100.0 + 0.25);
_aircraftPos = SGGeod::fromDegFt(lon_node->getDoubleValue(),
lat_node->getDoubleValue(), elev_node->getDoubleValue());
RangeFilter rangeFilter(_aircraftPos );
CommStation* sta = CommStation::findByFreq(freqKhz, _aircraftPos, &rangeFilter );
radios[unit].station->SetStation(sta);
}

View file

@ -1,5 +1,5 @@
// ATCMgr.hxx - definition of FGATCMgr // ATISmgr.hxx - definition of FGATISMgr
// - a global management class for FlightGear generated ATC // - a global management class for FlightGear generated ATIS
// //
// Written by David Luff, started February 2002. // Written by David Luff, started February 2002.
// //
@ -30,23 +30,26 @@
#include "ATC.hxx" #include "ATC.hxx"
class FGATCMgr : public SGSubsystem namespace flightgear
{
class CommStation;
}
typedef struct
{
SGPropertyNode_ptr freq;
FGATC* station;
} CommRadioData;
class FGATISMgr : public SGSubsystem
{ {
private: private:
// A vector containing all comm radios
typedef std::vector<CommRadioData> radio_list_type;
radio_list_type radios;
bool initDone; // Hack - guard against update getting called before init // Any member function of FGATISMgr is permitted to leave this iterator pointing
// A list of pointers to all currently active ATC classes
typedef std::map<std::string,FGATC*> atc_list_type;
typedef atc_list_type::iterator atc_list_iterator;
typedef atc_list_type::const_iterator atc_list_const_iterator;
// Everything put in this list should be created dynamically
// on the heap and ***DELETED WHEN REMOVED!!!!!***
atc_list_type* atc_list;
atc_list_iterator atc_list_itr;
// Any member function of FGATCMgr is permitted to leave this iterator pointing
// at any point in or at the end of the list. // at any point in or at the end of the list.
// Hence any new access must explicitly first check for atc_list.end() before dereferencing. // Hence any new access must explicitly first check for atc_list.end() before dereferencing.
@ -58,19 +61,18 @@ private:
SGPropertyNode_ptr lat_node; SGPropertyNode_ptr lat_node;
SGPropertyNode_ptr elev_node; SGPropertyNode_ptr elev_node;
//FGATIS atis; unsigned int _currentUnit;
unsigned int _maxCommRadios;
// Voice related stuff // Voice related stuff
bool voice; // Flag - true if we are using voice bool voice; // Flag - true if we are using voice
#ifdef ENABLE_AUDIO_SUPPORT #ifdef ENABLE_AUDIO_SUPPORT
bool voiceOK; // Flag - true if at least one voice has loaded OK FGATCVoice* voice1;
FGATCVoice* v1;
#endif #endif
public: public:
FGATISMgr();
FGATCMgr(); ~FGATISMgr();
~FGATCMgr();
void init(); void init();
@ -80,9 +82,8 @@ public:
void update(double dt); void update(double dt);
// Return a pointer to an appropriate voice for a given type of ATC // Return a pointer to an appropriate voice for a given type of ATC
// creating the voice if necessary - ie. make sure exactly one copy // creating the voice if necessary - i.e. make sure exactly one copy
// of every voice in use exists in memory. // of every voice in use exists in memory.
// //
// TODO - in the future this will get more complex and dole out country/airport // TODO - in the future this will get more complex and dole out country/airport
@ -90,25 +91,9 @@ public:
// at different airports in quick succession if a large enough selection are available. // at different airports in quick succession if a large enough selection are available.
FGATCVoice* GetVoicePointer(const atc_type& type); FGATCVoice* GetVoicePointer(const atc_type& type);
atc_type GetComm1ATCType() { return(INVALID/* kludge */); }
FGATC* GetComm1ATCPointer() { return(0/* kludge */); }
atc_type GetComm2ATCType() { return(INVALID); }
FGATC* GetComm2ATCPointer() { return(0/* kludge */); }
private: private:
// Remove a class from the atc_list and delete it from memory
// *if* no other comm channel or AI plane is using it.
void ZapOtherService(const std::string ncunit, const std::string svc_name);
// Return a pointer to a class in the list given ICAO code and type
// Return NULL if the given service is not in the list
// - *** THE CALLING FUNCTION MUST CHECK FOR THIS ***
FGATC* FindInList(const std::string& id, const atc_type& tp);
// Search the specified radio for stations on the same frequency and in range. // Search the specified radio for stations on the same frequency and in range.
void FreqSearch(const std::string navcomm, const int unit); void FreqSearch(const unsigned int unit);
}; };
#endif // _FG_ATCMGR_HXX #endif // _FG_ATCMGR_HXX

View file

@ -3,9 +3,8 @@ include(FlightGearComponent)
set(SOURCES set(SOURCES
ATC.cxx ATC.cxx
atis.cxx atis.cxx
ATCDialogOld.cxx
ATCVoice.cxx ATCVoice.cxx
ATCmgr.cxx ATISmgr.cxx
ATCutils.cxx ATCutils.cxx
ATCProjection.cxx ATCProjection.cxx
) )
@ -13,9 +12,8 @@ set(SOURCES
set(HEADERS set(HEADERS
ATC.hxx ATC.hxx
atis.hxx atis.hxx
ATCDialogOld.hxx
ATCVoice.hxx ATCVoice.hxx
ATCmgr.hxx ATISmgr.hxx
ATCutils.hxx ATCutils.hxx
ATCProjection.hxx ATCProjection.hxx
atis_lexicon.hxx atis_lexicon.hxx

View file

@ -57,7 +57,7 @@
#include "ATCutils.hxx" #include "ATCutils.hxx"
#include "ATCmgr.hxx" #include "ATISmgr.hxx"
using std::string; using std::string;
using std::map; using std::map;
@ -66,7 +66,7 @@ using std::cout;
using boost::ref; using boost::ref;
using boost::tie; using boost::tie;
FGATIS::FGATIS() : FGATIS::FGATIS(const string& commbase) :
transmission(""), transmission(""),
trans_ident(""), trans_ident(""),
old_volume(0), old_volume(0),
@ -74,20 +74,8 @@ FGATIS::FGATIS() :
msg_OK(0), msg_OK(0),
attention(0), attention(0),
_prev_display(0), _prev_display(0),
refname("atis") _commbase(commbase)
{ {
FGATCMgr* pAtcMgr = globals->get_ATC_mgr();
if (!pAtcMgr)
{
SG_LOG(SG_ATC, SG_ALERT, "ERROR! No ATC manager! Oops...");
_vPtr = NULL;
}
else
_vPtr = pAtcMgr->GetVoicePointer(ATIS);
_voiceOK = (_vPtr == NULL ? false : true);
if (!(_type != ATIS || _type == AWOS)) {
SG_LOG(SG_ATC, SG_ALERT, "ERROR - _type not ATIS or AWOS in atis.cxx");
}
fgTie("/environment/attention", this, (int_getter)0, &FGATIS::attend); fgTie("/environment/attention", this, (int_getter)0, &FGATIS::attend);
/////////////// ///////////////
@ -115,6 +103,18 @@ FGATIS::~FGATIS() {
fgUntie("/environment/attention"); fgUntie("/environment/attention");
} }
FGATCVoice* FGATIS::GetVoicePointer()
{
FGATISMgr* pAtisMgr = globals->get_ATIS_mgr();
if (!pAtisMgr)
{
SG_LOG(SG_ATC, SG_ALERT, "ERROR! No ATIS manager! Oops...");
return NULL;
}
return pAtisMgr->GetVoicePointer(ATIS);
}
void FGATIS::Init() { void FGATIS::Init() {
// Nothing to see here. Move along. // Nothing to see here. Move along.
} }
@ -137,6 +137,7 @@ FGATIS::attend (int attn)
void FGATIS::Update(double dt) { void FGATIS::Update(double dt) {
cur_time = globals->get_time_params()->get_cur_time(); cur_time = globals->get_time_params()->get_cur_time();
msg_OK = (msg_time < cur_time); msg_OK = (msg_time < cur_time);
#ifdef ATIS_TEST #ifdef ATIS_TEST
if (msg_OK || _display != _prev_display) { if (msg_OK || _display != _prev_display) {
cout << "ATIS Update: " << _display << " " << _prev_display cout << "ATIS Update: " << _display << " " << _prev_display
@ -146,29 +147,27 @@ void FGATIS::Update(double dt) {
msg_time = cur_time; msg_time = cur_time;
} }
#endif #endif
if(_display) {
double volume(0); if(_display)
for (map<string,int>::iterator act = active_on.begin(); {
act != active_on.end(); act++) { string prop = _commbase + "/volume";
string prop = "/instrumentation/" + act->first + "/volume"; double volume = globals->get_props()->getDoubleValue(prop.c_str());
volume += globals->get_props()->getDoubleValue(prop.c_str());
}
// Check if we need to update the message // Check if we need to update the message
// - basically every hour and if the weather changes significantly at the station // - basically every hour and if the weather changes significantly at the station
// If !_prev_display, the radio had been detuned for a while and our // If !_prev_display, the radio had been detuned for a while and our
// "transmission" variable was lost when we were de-instantiated. // "transmission" variable was lost when we were de-instantiated.
int rslt = GenTransmission(!_prev_display, attention); int changed = GenTransmission(!_prev_display, attention);
TreeOut(msg_OK); TreeOut(msg_OK);
if (rslt || volume != old_volume) { if (changed || volume != old_volume) {
//cout << "ATIS calling ATC::render volume: " << volume << endl; //cout << "ATIS calling ATC::render volume: " << volume << endl;
Render(transmission, volume, refname, true); Render(transmission, volume, _commbase, true);
old_volume = volume; old_volume = volume;
} }
} else { } else {
// We shouldn't be displaying // We shouldn't be displaying
//cout << "ATIS.CXX - calling NoRender()..." << endl; //cout << "ATIS.CXX - calling NoRender()..." << endl;
NoRender(refname); NoRender(_commbase);
} }
_prev_display = _display; _prev_display = _display;
attention = 0; attention = 0;
@ -517,26 +516,16 @@ int FGATIS::GenTransmission(const int regen, const int special) {
return 1; return 1;
} }
// Put the transmission into the property tree, // Put the transmission into the property tree.
// possibly in multiple places if multiple radios
// are tuned to the same ATIS.
// You can see it by pointing a web browser // You can see it by pointing a web browser
// at the property tree. The second comm radio is: // at the property tree. The second comm radio is:
// http://localhost:5400/instrumentation/comm[1] // http://localhost:5400/instrumentation/comm[1]
// //
// (Also, if in debug mode, dump it to the console.) // (Also, if in debug mode, dump it to the console.)
void FGATIS::TreeOut(int msg_OK){ void FGATIS::TreeOut(int msg_OK){
for (map<string,int>::iterator act = active_on.begin(); string prop = _commbase + "/atis";
act != active_on.end();
act++){
string prop = "/instrumentation/" + act->first + "/atis";
globals->get_props()->setStringValue(prop.c_str(), globals->get_props()->setStringValue(prop.c_str(),
("<pre>\n" + transmission_readable + "</pre>\n").c_str()); ("<pre>\n" + transmission_readable + "</pre>\n").c_str());
#ifdef ATIS_TEST SG_LOG(SG_ATC, SG_DEBUG, "**** ATIS active on: " << prop <<
if (msg_OK) cout << "**** ATIS active on: " << prop << endl; "transmission: " << transmission_readable);
#endif
}
#ifdef ATIS_TEST
if (msg_OK) cout << transmission_readable << endl;
#endif
} }

View file

@ -60,6 +60,8 @@ class FGATIS : public FGATC {
bool _prev_display; // Previous value of _display flag bool _prev_display; // Previous value of _display flag
MSS _remap; // abbreviations to be expanded MSS _remap; // abbreviations to be expanded
std::string _commbase;
// Aircraft position // Aircraft position
// ATIS is actually a special case in that unlike other ATC eg.tower it doesn't actually know about // ATIS is actually a special case in that unlike other ATC eg.tower it doesn't actually know about
// or the whereabouts of the aircraft it is transmitting to. However, to ensure consistancy of // or the whereabouts of the aircraft it is transmitting to. However, to ensure consistancy of
@ -69,9 +71,9 @@ class FGATIS : public FGATC {
//SGPropertyNode_ptr airplane_lat_node; //SGPropertyNode_ptr airplane_lat_node;
//SGPropertyNode_ptr airplane_elev_node; //SGPropertyNode_ptr airplane_elev_node;
public: public:
FGATIS(void); FGATIS(const std::string& commbase);
~FGATIS(void); ~FGATIS(void);
virtual void Init(); virtual void Init();
void attend (int); void attend (int);
@ -81,11 +83,11 @@ class FGATIS : public FGATC {
//inline void set_type(const atc_type tp) {type = tp;} //inline void set_type(const atc_type tp) {type = tp;}
inline const std::string& get_trans_ident() { return trans_ident; } inline const std::string& get_trans_ident() { return trans_ident; }
inline void set_refname(const std::string& r) { refname = r; }
private: protected:
virtual FGATCVoice* GetVoicePointer();
std::string refname; // Holds the refname of a transmission in progress private:
// Generate the ATIS transmission text: // Generate the ATIS transmission text:
int GenTransmission(const int regen, const int special); int GenTransmission(const int regen, const int special);

View file

@ -16,7 +16,7 @@
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
@ -33,6 +33,7 @@
#include <simgear/misc/ResourceManager.hxx> #include <simgear/misc/ResourceManager.hxx>
#include <simgear/misc/strutils.hxx> #include <simgear/misc/strutils.hxx>
#include <simgear/structure/exception.hxx> #include <simgear/structure/exception.hxx>
#include <simgear/math/SGMath.hxx>
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
#include "flightrecorder.hxx" #include "flightrecorder.hxx"

View file

@ -16,7 +16,7 @@
// //
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// //
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////

View file

@ -32,7 +32,6 @@
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/structure/subsystem_mgr.hxx> #include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/route/waypoint.hxx>
#include <Main/globals.hxx> #include <Main/globals.hxx>
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
#include <Airports/runways.hxx> #include <Airports/runways.hxx>

View file

@ -35,7 +35,6 @@
#include <osg/Shape> #include <osg/Shape>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/route/waypoint.hxx>
#include <simgear/scene/material/EffectGeode.hxx> #include <simgear/scene/material/EffectGeode.hxx>
#include <simgear/scene/material/matlib.hxx> #include <simgear/scene/material/matlib.hxx>
#include <simgear/scene/material/mat.hxx> #include <simgear/scene/material/mat.hxx>
@ -531,7 +530,7 @@ FGTaxiNode *FGGroundNetwork::findNode(unsigned idx)
return itr->getAddress(); return itr->getAddress();
} */ } */
if ((idx >= 0) && (idx < nodes.size())) if (idx < nodes.size())
return nodes[idx]->getAddress(); return nodes[idx]->getAddress();
else else
return 0; return 0;

View file

@ -31,7 +31,6 @@
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <simgear/route/waypoint.hxx>
#include <string> #include <string>
#include <vector> #include <vector>

View file

@ -26,6 +26,7 @@
#endif #endif
#include <math.h> #include <math.h>
#include <cstdlib>
#include <cstring> #include <cstring>
#include <simgear/compiler.h> #include <simgear/compiler.h>

View file

@ -172,7 +172,7 @@ void FGRunway::setReciprocalRunway(FGRunway* other)
_reciprocal = other; _reciprocal = other;
} }
std::vector<flightgear::SID*> FGRunway::getSIDs() std::vector<flightgear::SID*> FGRunway::getSIDs() const
{ {
std::vector<flightgear::SID*> result; std::vector<flightgear::SID*> result;
for (unsigned int i=0; i<_airport->numSIDs(); ++i) { for (unsigned int i=0; i<_airport->numSIDs(); ++i) {
@ -185,7 +185,7 @@ std::vector<flightgear::SID*> FGRunway::getSIDs()
return result; return result;
} }
std::vector<flightgear::STAR*> FGRunway::getSTARs() std::vector<flightgear::STAR*> FGRunway::getSTARs() const
{ {
std::vector<flightgear::STAR*> result; std::vector<flightgear::STAR*> result;
for (unsigned int i=0; i<_airport->numSTARs(); ++i) { for (unsigned int i=0; i<_airport->numSTARs(); ++i) {
@ -198,3 +198,16 @@ std::vector<flightgear::STAR*> FGRunway::getSTARs()
return result; return result;
} }
std::vector<flightgear::Approach*> FGRunway::getApproaches() const
{
std::vector<flightgear::Approach*> result;
for (unsigned int i=0; i<_airport->numApproaches(); ++i) {
flightgear::Approach* s = _airport->getApproachByIndex(i);
if (s->runway() == this) {
result.push_back(s);
}
} // of approaches at the airport iteration
return result;
}

View file

@ -36,6 +36,7 @@ class SGPropertyNode;
namespace flightgear { namespace flightgear {
class SID; class SID;
class STAR; class STAR;
class Approach;
} }
class FGRunway : public FGRunwayBase class FGRunway : public FGRunwayBase
@ -124,12 +125,15 @@ public:
/** /**
* Get SIDs (DPs) associated with this runway * Get SIDs (DPs) associated with this runway
*/ */
std::vector<flightgear::SID*> getSIDs(); std::vector<flightgear::SID*> getSIDs() const;
/** /**
* Get STARs associared with this runway * Get STARs associared with this runway
*/ */
std::vector<flightgear::STAR*> getSTARs(); std::vector<flightgear::STAR*> getSTARs() const;
std::vector<flightgear::Approach*> getApproaches() const;
}; };

View file

@ -329,6 +329,9 @@ FGAirport* FGAirport::findClosest(const SGGeod& aPos, double aCuttofNm, Filter*
FGAirport::HardSurfaceFilter::HardSurfaceFilter(double minLengthFt) : FGAirport::HardSurfaceFilter::HardSurfaceFilter(double minLengthFt) :
mMinLengthFt(minLengthFt) mMinLengthFt(minLengthFt)
{ {
if (minLengthFt < 0.0) {
mMinLengthFt = fgGetDouble("/sim/navdb/min-runway-length-ft", 0.0);
}
} }
bool FGAirport::HardSurfaceFilter::passAirport(FGAirport* aApt) const bool FGAirport::HardSurfaceFilter::passAirport(FGAirport* aApt) const
@ -406,7 +409,7 @@ void FGAirport::loadProcedures() const
} }
SG_LOG(SG_GENERAL, SG_INFO, ident() << ": loading procedures from " << path.str()); SG_LOG(SG_GENERAL, SG_INFO, ident() << ": loading procedures from " << path.str());
Route::loadAirportProcedures(path, const_cast<FGAirport*>(this)); RouteBase::loadAirportProcedures(path, const_cast<FGAirport*>(this));
} }
void FGAirport::loadSceneryDefinitions() const void FGAirport::loadSceneryDefinitions() const
@ -469,128 +472,6 @@ void FGAirport::readTowerData(SGPropertyNode* aRoot)
_tower_location = SGGeod::fromDegM(lon, lat, fieldElevationM + elevM); _tower_location = SGGeod::fromDegM(lon, lat, fieldElevationM + elevM);
} }
bool FGAirport::buildApproach(Waypt* aEnroute, STAR* aSTAR, FGRunway* aRwy, WayptVec& aRoute)
{
loadProcedures();
if ((aRwy && (aRwy->airport() != this))) {
throw sg_exception("invalid parameters", "FGAirport::buildApproach");
}
if (aSTAR) {
bool ok = aSTAR->route(aRwy, aEnroute, aRoute);
if (!ok) {
SG_LOG(SG_GENERAL, SG_WARN, ident() << ": build approach, STAR " << aSTAR->ident()
<< " failed to route from transition " << aEnroute->ident());
return false;
}
} else if (aEnroute) {
// no a STAR specified, just use enroute point directly
aRoute.push_back(aEnroute);
}
if (!aRwy) {
// no runway selected yet, but we loaded the STAR, so that's fine, we're done
return true;
}
// build the approach (possibly including transition), and including the missed segment
vector<Approach*> aps;
for (unsigned int j=0; j<mApproaches.size();++j) {
if (mApproaches[j]->runway() == aRwy) {
aps.push_back(mApproaches[j]);
}
} // of approach filter by runway
if (aps.empty()) {
SG_LOG(SG_GENERAL, SG_INFO, ident() << "; no approaches defined for runway " << aRwy->ident());
// could build a fallback approach here
return false;
}
for (unsigned int k=0; k<aps.size(); ++k) {
if (aps[k]->route(aRoute.back(), aRoute)) {
return true;
}
} // of initial approach iteration
SG_LOG(SG_GENERAL, SG_INFO, ident() << ": unable to find transition to runway "
<< aRwy->ident() << ", assume vectors");
WayptRef v(new ATCVectors(NULL, this));
aRoute.push_back(v);
return aps.front()->routeFromVectors(aRoute);
}
pair<flightgear::SID*, WayptRef>
FGAirport::selectSID(const SGGeod& aDest, FGRunway* aRwy)
{
loadProcedures();
WayptRef enroute;
flightgear::SID* sid = NULL;
double d = 1e9;
for (unsigned int i=0; i<mSIDs.size(); ++i) {
if (aRwy && !mSIDs[i]->isForRunway(aRwy)) {
continue;
}
WayptRef e = mSIDs[i]->findBestTransition(aDest);
if (!e) {
continue; // strange, but let's not worry about it
}
// assert(e->isFixedPosition());
double ed = SGGeodesy::distanceM(aDest, e->position());
if (ed < d) { // new best match
enroute = e;
d = ed;
sid = mSIDs[i];
}
} // of SID iteration
if (!mSIDs.empty() && !sid) {
SG_LOG(SG_GENERAL, SG_INFO, ident() << "selectSID, no SID found (runway="
<< (aRwy ? aRwy->ident() : "no runway preference"));
}
return std::make_pair(sid, enroute);
}
pair<STAR*, WayptRef>
FGAirport::selectSTAR(const SGGeod& aOrigin, FGRunway* aRwy)
{
loadProcedures();
WayptRef enroute;
STAR* star = NULL;
double d = 1e9;
for (unsigned int i=0; i<mSTARs.size(); ++i) {
if (!mSTARs[i]->isForRunway(aRwy)) {
continue;
}
SG_LOG(SG_GENERAL, SG_INFO, "STAR " << mSTARs[i]->ident() << " is valid for runway");
WayptRef e = mSTARs[i]->findBestTransition(aOrigin);
if (!e) {
continue; // strange, but let's not worry about it
}
// assert(e->isFixedPosition());
double ed = SGGeodesy::distanceM(aOrigin, e->position());
if (ed < d) { // new best match
enroute = e;
d = ed;
star = mSTARs[i];
}
} // of STAR iteration
return std::make_pair(star, enroute);
}
void FGAirport::addSID(flightgear::SID* aSid) void FGAirport::addSID(flightgear::SID* aSid)
{ {
mSIDs.push_back(aSid); mSIDs.push_back(aSid);
@ -666,6 +547,18 @@ Approach* FGAirport::getApproachByIndex(unsigned int aIndex) const
return mApproaches[aIndex]; return mApproaches[aIndex];
} }
Approach* FGAirport::findApproachWithIdent(const std::string& aIdent) const
{
loadProcedures();
for (unsigned int i=0; i<mApproaches.size(); ++i) {
if (mApproaches[i]->ident() == aIdent) {
return mApproaches[i];
}
}
return NULL;
}
void FGAirport::setCommStations(CommStationList& comms) void FGAirport::setCommStations(CommStationList& comms)
{ {
mCommStations.swap(comms); mCommStations.swap(comms);

View file

@ -161,7 +161,7 @@ public:
class HardSurfaceFilter : public AirportFilter class HardSurfaceFilter : public AirportFilter
{ {
public: public:
HardSurfaceFilter(double minLengthFt); HardSurfaceFilter(double minLengthFt = -1);
virtual bool passAirport(FGAirport* aApt) const; virtual bool passAirport(FGAirport* aApt) const;
@ -188,6 +188,7 @@ public:
unsigned int numApproaches() const; unsigned int numApproaches() const;
flightgear::Approach* getApproachByIndex(unsigned int aIndex) const; flightgear::Approach* getApproachByIndex(unsigned int aIndex) const;
flightgear::Approach* findApproachWithIdent(const std::string& aIdent) const;
/** /**
* Syntactic wrapper around FGPositioned::findClosest - find the closest * Syntactic wrapper around FGPositioned::findClosest - find the closest
@ -216,22 +217,6 @@ public:
*/ */
static char** searchNamesAndIdents(const std::string& aFilter); static char** searchNamesAndIdents(const std::string& aFilter);
bool buildApproach(flightgear::Waypt* aEnroute, flightgear::STAR* aSTAR,
FGRunway* aRwy, flightgear::WayptVec& aRoute);
/**
* Given a destiation point, select the best SID and transition waypt from
* this airport. Returns (NULL,NULL) is no SIDs are defined, otherwise the
* best SID/transition is that which is closest to the destination point.
*/
std::pair<flightgear::SID*, flightgear::WayptRef> selectSID(const SGGeod& aDest, FGRunway* aRwy);
/**
* Select a STAR and enroute transition waypt, given an origin (departure) position.
* returns (NULL, NULL) is no suitable STAR is exists
*/
std::pair<flightgear::STAR*, flightgear::WayptRef> selectSTAR(const SGGeod& aOrigin, FGRunway* aRwy);
void setCommStations(flightgear::CommStationList& comms); void setCommStations(flightgear::CommStationList& comms);
flightgear::CommStationList commStationsOfType(FGPositioned::Type aTy) const; flightgear::CommStationList commStationsOfType(FGPositioned::Type aTy) const;

View file

@ -18,8 +18,11 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// //
#include <cstdlib>
#include "inputvalue.hxx" #include "inputvalue.hxx"
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
using namespace FGXMLAutopilot; using namespace FGXMLAutopilot;
PeriodicalValue::PeriodicalValue( SGPropertyNode_ptr root ) PeriodicalValue::PeriodicalValue( SGPropertyNode_ptr root )

View file

@ -24,7 +24,6 @@
#ifndef HAVE_CONFIG_H #ifndef HAVE_CONFIG_H
# include <config.h> # include <config.h>
#endif #endif
#include <simgear/math/SGMath.hxx>
#endif #endif
#include "logic.hxx" #include "logic.hxx"

File diff suppressed because it is too large Load diff

View file

@ -25,26 +25,21 @@
#define _ROUTE_MGR_HXX 1 #define _ROUTE_MGR_HXX 1
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/route/waypoint.hxx>
#include <simgear/structure/subsystem_mgr.hxx> #include <simgear/structure/subsystem_mgr.hxx>
#include <Navaids/route.hxx> #include <Navaids/FlightPlan.hxx>
// forward decls // forward decls
class SGPath; class SGPath;
class PropertyWatcher; class PropertyWatcher;
class FGAirport;
class FGRunway;
typedef SGSharedPtr<FGAirport> FGAirportRef;
/** /**
* Top level route manager class * Top level route manager class
* *
*/ */
class FGRouteMgr : public SGSubsystem class FGRouteMgr : public SGSubsystem,
public flightgear::FlightPlan::Delegate
{ {
public: public:
FGRouteMgr(); FGRouteMgr();
@ -56,51 +51,29 @@ public:
void unbind (); void unbind ();
void update (double dt); void update (double dt);
void insertWayptAtIndex(flightgear::Waypt* aWpt, int aIndex); bool isRouteActive() const;
flightgear::WayptRef removeWayptAtIndex(int index);
int currentIndex() const;
void setFlightPlan(flightgear::FlightPlan* plan);
flightgear::FlightPlan* flightPlan() const;
void clearRoute(); void clearRoute();
typedef enum {
ROUTE_HIGH_AIRWAYS, ///< high-level airways routing
ROUTE_LOW_AIRWAYS, ///< low-level airways routing
ROUTE_VOR ///< VOR-VOR routing
} RouteType;
/**
* Insert waypoints from index-1 to index. In practice this means you can
* 'fill in the gaps' between defined waypoints. If index=0, the departure
* airport is used as index-1; if index is -1, the destination airport is
* used as the final waypoint.
*/
bool routeToIndex(int index, RouteType aRouteType);
void autoRoute();
bool isRouteActive() const;
int currentIndex() const
{ return _currentIndex; }
flightgear::Waypt* currentWaypt() const; flightgear::Waypt* currentWaypt() const;
flightgear::Waypt* nextWaypt() const;
flightgear::Waypt* previousWaypt() const;
const flightgear::WayptVec& waypts() const int numLegs() const;
{ return _route; }
// deprecated
int numWaypts() const int numWaypts() const
{ return _route.size(); } { return numLegs(); }
// deprecated
flightgear::Waypt* wayptAtIndex(int index) const; flightgear::Waypt* wayptAtIndex(int index) const;
SGPropertyNode_ptr wayptNodeAtIndex(int index) const; SGPropertyNode_ptr wayptNodeAtIndex(int index) const;
/** void removeLegAtIndex(int aIndex);
* Find a waypoint in the route, by position, and return its index, or
* -1 if no matching waypoint was found in the route.
*/
int findWayptIndex(const SGGeod& aPos) const;
/** /**
* Activate a built route. This checks for various mandatory pieces of * Activate a built route. This checks for various mandatory pieces of
@ -125,38 +98,20 @@ public:
bool saveRoute(const SGPath& p); bool saveRoute(const SGPath& p);
bool loadRoute(const SGPath& p); bool loadRoute(const SGPath& p);
flightgear::WayptRef waypointFromString(const std::string& target);
/** /**
* Helper command to setup current airport/runway if necessary * Helper command to setup current airport/runway if necessary
*/ */
void initAtPosition(); void initAtPosition();
/**
* Create a WayPoint from a string in the following format:
* - simple identifier
* - decimal-lon,decimal-lat
* - airport-id/runway-id
* - navaid/radial-deg/offset-nm
*/
flightgear::WayptRef waypointFromString(const std::string& target);
FGAirportRef departureAirport() const;
FGAirportRef destinationAirport() const;
FGRunway* departureRunway() const;
FGRunway* destinationRunway() const;
private: private:
flightgear::WayptVec _route; flightgear::FlightPlan* _plan;
int _currentIndex;
time_t _takeoffTime; time_t _takeoffTime;
time_t _touchdownTime; time_t _touchdownTime;
FGAirportRef _departure;
FGAirportRef _destination;
// automatic inputs // automatic inputs
SGPropertyNode_ptr lon;
SGPropertyNode_ptr lat;
SGPropertyNode_ptr alt;
SGPropertyNode_ptr magvar; SGPropertyNode_ptr magvar;
// automatic outputs // automatic outputs
@ -181,8 +136,6 @@ private:
SGPropertyNode_ptr _pathNode; SGPropertyNode_ptr _pathNode;
SGPropertyNode_ptr _currentWpt; SGPropertyNode_ptr _currentWpt;
/// integer property corresponding to the RouteType enum
SGPropertyNode_ptr _routingType;
/** /**
* Signal property to notify people that the route was edited * Signal property to notify people that the route was edited
@ -194,6 +147,8 @@ private:
*/ */
SGPropertyNode_ptr _finished; SGPropertyNode_ptr _finished;
SGPropertyNode_ptr _flightplanChanged;
void setETAPropertyFromDistance(SGPropertyNode_ptr aProp, double aDistance); void setETAPropertyFromDistance(SGPropertyNode_ptr aProp, double aDistance);
/** /**
@ -212,31 +167,21 @@ private:
SGPropertyNode_ptr input; SGPropertyNode_ptr input;
SGPropertyNode_ptr weightOnWheels; SGPropertyNode_ptr weightOnWheels;
SGPropertyNode_ptr groundSpeed;
InputListener *listener; InputListener *listener;
SGPropertyNode_ptr mirror; SGPropertyNode_ptr mirror;
void departureChanged();
void buildDeparture(flightgear::WayptRef enroute, flightgear::WayptVec& wps);
void arrivalChanged();
void buildArrival(flightgear::WayptRef enroute, flightgear::WayptVec& wps);
/** /**
* Helper to keep various pieces of state in sync when the route is * Helper to keep various pieces of state in sync when the route is
* modified (waypoints added, inserted, removed). Notably, this fires the * modified (waypoints added, inserted, removed). Notably, this fires the
* 'edited' signal. * 'edited' signal.
*/ */
void waypointsChanged(); virtual void waypointsChanged();
void update_mirror(); void update_mirror();
void currentWaypointChanged(); virtual void currentWaypointChanged();
/**
* Parse a route/wp node (from a saved, property-lsit formatted route)
*/
void parseRouteWaypoint(SGPropertyNode* aWP);
/** /**
* Check if we've reached the final waypoint. * Check if we've reached the final waypoint.
@ -244,14 +189,6 @@ private:
*/ */
bool checkFinished(); bool checkFinished();
bool loadPlainTextRoute(const SGPath& path);
void loadVersion1XMLRoute(SGPropertyNode_ptr routeData);
void loadVersion2XMLRoute(SGPropertyNode_ptr routeData);
void loadXMLRouteHeader(SGPropertyNode_ptr routeData);
flightgear::WayptRef parseVersion1XMLWaypt(SGPropertyNode* aWP);
/** /**
* Predicate for helping the UI - test if at least one waypoint was * Predicate for helping the UI - test if at least one waypoint was
* entered by the user (as opposed to being generated by the route-manager) * entered by the user (as opposed to being generated by the route-manager)
@ -263,12 +200,27 @@ private:
const char* getDepartureName() const; const char* getDepartureName() const;
void setDepartureICAO(const char* aIdent); void setDepartureICAO(const char* aIdent);
const char* getDepartureRunway() const;
void setDepartureRunway(const char* aIdent);
const char* getSID() const;
void setSID(const char* aIdent);
const char* getDestinationICAO() const; const char* getDestinationICAO() const;
const char* getDestinationName() const; const char* getDestinationName() const;
void setDestinationICAO(const char* aIdent); void setDestinationICAO(const char* aIdent);
PropertyWatcher* _departureWatcher; const char* getDestinationRunway() const;
PropertyWatcher* _arrivalWatcher; void setDestinationRunway(const char* aIdent);
const char* getApproach() const;
void setApproach(const char* aIdent);
const char* getSTAR() const;
void setSTAR(const char* aIdent);
double getDepartureFieldElevation() const;
double getDestinationFieldElevation() const;
}; };

View file

@ -8,6 +8,7 @@ foreach( mylibfolder
Aircraft Aircraft
ATC ATC
ATCDCL ATCDCL
Canvas
Radio Radio
Autopilot Autopilot
Cockpit Cockpit

19
src/Canvas/CMakeLists.txt Normal file
View file

@ -0,0 +1,19 @@
include(FlightGearComponent)
set(SOURCES
canvas.cxx
canvas_mgr.cxx
elements/element.cxx
elements/group.cxx
elements/text.cxx
)
set(HEADERS
canvas.hxx
canvas_mgr.hxx
elements/element.hxx
elements/group.hxx
elements/text.hxx
)
flightgear_component(Canvas "${SOURCES}" "${HEADERS}")

430
src/Canvas/canvas.cxx Normal file
View file

@ -0,0 +1,430 @@
// The canvas for rendering with the 2d api
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "canvas.hxx"
#include "elements/group.hxx"
#include <osg/Camera>
#include <osg/Geode>
#include <osgText/Text>
#include <iostream>
//#include <Main/globals.hxx>
//#include <Viewer/renderer.hxx>
//------------------------------------------------------------------------------
/**
* Callback used to disable/enable rendering to the texture if it is not
* visible
*/
class CameraCullCallback:
public osg::NodeCallback
{
public:
CameraCullCallback():
_render( true )
{}
/**
* Enable rendering for the next frame
*/
void enableRendering()
{
_render = true;
}
private:
bool _render;
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
if( _render )
{
traverse(node, nv);
_render = false;
}
}
};
/**
* This callback is installed on every placement of the canvas in the scene to
* only render the canvas if at least one placement is visible
*/
class PlacementCullCallback:
public osg::NodeCallback
{
public:
PlacementCullCallback(Canvas* canvas, CameraCullCallback* camera_cull):
_canvas( canvas ),
_camera_cull( camera_cull )
{}
private:
Canvas *_canvas;
CameraCullCallback *_camera_cull;
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
_camera_cull->enableRendering();
traverse(node, nv);
}
};
//------------------------------------------------------------------------------
Canvas::Canvas():
_size_x(-1),
_size_y(-1),
_view_width(-1),
_view_height(-1),
_status(0),
_node(0),
_sampling_dirty(false)
{
setStatusFlags(MISSING_SIZE_X | MISSING_SIZE_Y);
CameraCullCallback *camera_callback = new CameraCullCallback;
_camera_callback = camera_callback;
_cull_callback = new PlacementCullCallback(this, camera_callback);
}
//------------------------------------------------------------------------------
Canvas::~Canvas()
{
}
//------------------------------------------------------------------------------
int Canvas::getStatus() const
{
return _status;
}
//------------------------------------------------------------------------------
void Canvas::reset(SGPropertyNode* node)
{
if( _node )
{
_node->untie("size[0]");
_node->untie("size[1]");
_node->untie("view[0]");
_node->untie("view[1]");
_node->untie("status");
_node->untie("status-msg");
_node->removeChangeListener(this);
_node = 0;
}
setStatusFlags(MISSING_SIZE_X | MISSING_SIZE_Y);
if( node )
{
_node = node;
_node->tie
(
"size[0]",
SGRawValueMethods<Canvas, int>( *this, &Canvas::getSizeX,
&Canvas::setSizeX )
);
_node->tie
(
"size[1]",
SGRawValueMethods<Canvas, int>( *this, &Canvas::getSizeY,
&Canvas::setSizeY )
);
_node->tie
(
"view[0]",
SGRawValueMethods<Canvas, int>( *this, &Canvas::getViewWidth,
&Canvas::setViewWidth )
);
_node->tie
(
"view[1]",
SGRawValueMethods<Canvas, int>( *this, &Canvas::getViewHeight,
&Canvas::setViewHeight )
);
_node->tie
(
"status",
SGRawValueMethods<Canvas, int>(*this, &Canvas::getStatus)
);
_node->tie
(
"status-msg",
SGRawValueMethods<Canvas, const char*>(*this, &Canvas::getStatusMsg)
);
_node->addChangeListener(this);
}
}
//------------------------------------------------------------------------------
void Canvas::update(double delta_time_sec)
{
if( !_texture.serviceable() )
{
if( _status != STATUS_OK )
return;
_texture.setSize(_size_x, _size_y);
_texture.useImageCoords(true);
_texture.useStencil(true);
_texture.allocRT(_camera_callback);
_texture.getCamera()->setClearColor(osg::Vec4(0.0f, 0.0f, 0.0f , 1.0f));
for( size_t i = 0; i < _groups.size(); ++i )
_texture.getCamera()->addChild( _groups[i]->getMatrixTransform() );
if( _texture.serviceable() )
{
setStatusFlags(STATUS_OK);
}
else
{
setStatusFlags(CREATE_FAILED);
return;
}
}
for( size_t i = 0; i < _groups.size(); ++i )
_groups[i]->update(delta_time_sec);
if( _sampling_dirty )
{
_texture.setSampling(
_node->getBoolValue("mipmapping"),
_node->getIntValue("coverage-samples"),
_node->getIntValue("color-samples")
);
_sampling_dirty = false;
}
while( !_dirty_placements.empty() )
{
SGPropertyNode *node = _dirty_placements.back();
_dirty_placements.pop_back();
if( node->getIndex() >= static_cast<int>(_placements.size()) )
// New placement
_placements.resize(node->getIndex() + 1);
else
// Remove maybe already existing placements
clearPlacements(node->getIndex());
// add new placements
_placements[node->getIndex()] = _texture.set_texture(
node,
_texture.getTexture(),
_cull_callback
);
}
}
//------------------------------------------------------------------------------
void Canvas::setSizeX(int sx)
{
if( _size_x == sx )
return;
_size_x = sx;
// TODO resize if texture already allocated
if( _size_x <= 0 )
setStatusFlags(MISSING_SIZE_X);
else
setStatusFlags(MISSING_SIZE_X, false);
// reset flag to allow creation with new size
setStatusFlags(CREATE_FAILED, false);
}
//------------------------------------------------------------------------------
int Canvas::getSizeX() const
{
return _size_x;
}
//------------------------------------------------------------------------------
void Canvas::setSizeY(int sy)
{
if( _size_y == sy )
return;
_size_y = sy;
// TODO resize if texture already allocated
if( _size_y <= 0 )
setStatusFlags(MISSING_SIZE_Y);
else
setStatusFlags(MISSING_SIZE_Y, false);
// reset flag to allow creation with new size
setStatusFlags(CREATE_FAILED, false);
}
//------------------------------------------------------------------------------
int Canvas::getSizeY() const
{
return _size_y;
}
//------------------------------------------------------------------------------
void Canvas::setViewWidth(int w)
{
if( _view_width == w )
return;
_view_width = w;
_texture.setViewSize(_view_width, _view_height);
}
//------------------------------------------------------------------------------
int Canvas::getViewWidth() const
{
return _view_width;
}
//------------------------------------------------------------------------------
void Canvas::setViewHeight(int h)
{
if( _view_height == h )
return;
_view_height = h;
_texture.setViewSize(_view_width, _view_height);
}
//------------------------------------------------------------------------------
int Canvas::getViewHeight() const
{
return _view_height;
}
//------------------------------------------------------------------------------
const char* Canvas::getStatusMsg() const
{
return _status_msg.c_str();
}
//------------------------------------------------------------------------------
void Canvas::childAdded( SGPropertyNode * parent,
SGPropertyNode * child )
{
if( parent != _node )
return;
if( child->getNameString() == "group" )
{
_groups.push_back
(
boost::shared_ptr<canvas::Group>(new canvas::Group(child))
);
if( _texture.serviceable() )
_texture.getCamera()->addChild( _groups.back()->getMatrixTransform() );
}
else if( child->getNameString() == "placement" )
{
_dirty_placements.push_back(child);
}
// else
// std::cout << "Canvas::childAdded: " << child->getPath() << std::endl;
}
//------------------------------------------------------------------------------
void Canvas::childRemoved( SGPropertyNode * parent,
SGPropertyNode * child )
{
if( parent != _node )
return;
if( child->getNameString() == "placement" )
clearPlacements(child->getIndex());
else
std::cout << "Canvas::childRemoved: " << child->getPath() << std::endl;
}
//----------------------------------------------------------------------------
void Canvas::valueChanged(SGPropertyNode * node)
{
if( node->getParent()->getParent() == _node
&& node->getParent()->getNameString() == "placement" )
{
// prevent double updates...
for( size_t i = 0; i < _dirty_placements.size(); ++i )
{
if( node->getParent() == _dirty_placements[i] )
return;
}
_dirty_placements.push_back(node->getParent());
}
else if( node->getParent() == _node )
{
if( node->getNameString() == "mipmapping"
|| node->getNameString() == "coverage-samples"
|| node->getNameString() == "color-samples" )
_sampling_dirty = true;
}
}
//------------------------------------------------------------------------------
void Canvas::setStatusFlags(unsigned int flags, bool set)
{
if( set )
_status |= flags;
else
_status &= ~flags;
if( (_status & MISSING_SIZE_X) && (_status & MISSING_SIZE_Y) )
_status_msg = "Missing size";
else if( _status & MISSING_SIZE_X )
_status_msg = "Missing size-x";
else if( _status & MISSING_SIZE_Y )
_status_msg = "Missing size-y";
else if( _status & CREATE_FAILED )
_status_msg = "Creating render target failed";
else if( _status == STATUS_OK && !_texture.serviceable() )
_status_msg = "Creation pending...";
else
_status_msg = "Ok";
}
//------------------------------------------------------------------------------
void Canvas::clearPlacements(int index)
{
Placements& placements = _placements.at(index);
while( !placements.empty() )
{
osg::ref_ptr<osg::Group> group = placements.back();
placements.pop_back();
assert( group->getNumParents() == 1 );
assert( group->getNumChildren() == 1 );
osg::Group *parent = group->getParent(0);
osg::Node *child = group->getChild(0);
parent->addChild(child);
group->removeChild(child);
parent->removeChild(group);
}
}

101
src/Canvas/canvas.hxx Normal file
View file

@ -0,0 +1,101 @@
// The canvas for rendering with the 2d api
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef CANVAS_HXX_
#define CANVAS_HXX_
#include <Instrumentation/od_gauge.hxx>
#include <simgear/props/props.hxx>
#include <osg/NodeCallback>
#include <boost/shared_ptr.hpp>
#include <string>
namespace canvas
{
class Group;
}
class Canvas:
public SGPropertyChangeListener
{
public:
enum StatusFlags
{
STATUS_OK,
MISSING_SIZE_X = 0x0001,
MISSING_SIZE_Y = 0x0002,
CREATE_FAILED = 0x0004
};
Canvas();
virtual ~Canvas();
void reset(SGPropertyNode* node);
void update(double delta_time_sec);
void setSizeX(int sx);
int getSizeX() const;
void setSizeY(int sy);
int getSizeY() const;
void setViewWidth(int w);
int getViewWidth() const;
void setViewHeight(int h);
int getViewHeight() const;
int getStatus() const;
const char* getStatusMsg() const;
virtual void childAdded( SGPropertyNode * parent,
SGPropertyNode * child );
virtual void childRemoved( SGPropertyNode * parent,
SGPropertyNode * child );
virtual void valueChanged (SGPropertyNode * node);
private:
int _size_x,
_size_y,
_view_width,
_view_height;
int _status;
std::string _status_msg;
FGODGauge _texture;
SGPropertyNode *_node;
bool _sampling_dirty;
osg::ref_ptr<osg::NodeCallback> _camera_callback;
osg::ref_ptr<osg::NodeCallback> _cull_callback;
std::vector<SGPropertyNode*> _dirty_placements;
std::vector<Placements> _placements;
// TODO replace auto_ptr with unique_ptr as soon as C++11 is used!
std::vector<boost::shared_ptr<canvas::Group> > _groups;
void setStatusFlags(unsigned int flags, bool set = true);
void clearPlacements(int index);
};
#endif /* CANVAS_HXX_ */

144
src/Canvas/canvas_mgr.cxx Normal file
View file

@ -0,0 +1,144 @@
// Canvas with 2D rendering api
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "canvas_mgr.hxx"
#include "canvas.hxx"
#include <Main/fg_props.hxx>
#include <osg/Camera>
#include <osg/Texture2D>
#include <stdexcept>
#include <string>
//------------------------------------------------------------------------------
CanvasMgr::CanvasMgr():
_props( fgGetNode("/canvas", true) )
{
}
//------------------------------------------------------------------------------
CanvasMgr::~CanvasMgr()
{
}
//------------------------------------------------------------------------------
void CanvasMgr::init()
{
_props->addChangeListener(this);
triggerChangeRecursive(_props);
}
//------------------------------------------------------------------------------
void CanvasMgr::reinit()
{
}
//------------------------------------------------------------------------------
void CanvasMgr::shutdown()
{
_props->removeChangeListener(this);
}
//------------------------------------------------------------------------------
void CanvasMgr::bind()
{
}
//------------------------------------------------------------------------------
void CanvasMgr::unbind()
{
}
//------------------------------------------------------------------------------
void CanvasMgr::update(double delta_time_sec)
{
for( size_t i = 0; i < _canvases.size(); ++i )
_canvases[i].update(delta_time_sec);
}
//------------------------------------------------------------------------------
void CanvasMgr::childAdded( SGPropertyNode * parent,
SGPropertyNode * child )
{
if( parent != _props )
return;
if( child->getNameString() == "texture" )
textureAdded(child);
else
std::cout << "CanvasMgr::childAdded: " << child->getPath() << std::endl;
}
//------------------------------------------------------------------------------
void CanvasMgr::childRemoved( SGPropertyNode * parent,
SGPropertyNode * child )
{
if( parent != _props )
return;
std::cout << "CanvasMgr::childRemoved: " << child->getPath() << std::endl;
}
//------------------------------------------------------------------------------
void CanvasMgr::textureAdded(SGPropertyNode* node)
{
size_t index = node->getIndex();
if( index >= _canvases.size() )
{
if( index > _canvases.size() )
SG_LOG(SG_GL, SG_WARN, "Skipping unused texture slot(s)!");
SG_LOG(SG_GL, SG_INFO, "Add new texture[" << index << "]");
_canvases.resize(index + 1);
_canvases[index];
}
else
{
SG_LOG(SG_GL, SG_WARN, "texture[" << index << "] already exists!");
}
_canvases[index].reset(node);
}
//------------------------------------------------------------------------------
void CanvasMgr::triggerChangeRecursive(SGPropertyNode* node)
{
node->getParent()->fireChildAdded(node);
if( node->nChildren() == 0 && node->getType() != simgear::props::NONE )
return node->fireValueChanged();
for( int i = 0; i < node->nChildren(); ++i )
triggerChangeRecursive( node->getChild(i) );
}
//------------------------------------------------------------------------------
template<class T>
T CanvasMgr::getParam(const SGPropertyNode* node, const char* prop)
{
const SGPropertyNode* child = node->getChild(prop);
if( !child )
throw std::runtime_error(std::string("Missing property ") + prop);
return getValue<T>(child);
}

76
src/Canvas/canvas_mgr.hxx Normal file
View file

@ -0,0 +1,76 @@
// Canvas with 2D rendering api
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef CANVAS_MGR_H_
#define CANVAS_MGR_H_
#include <simgear/props/props.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
#include <boost/shared_ptr.hpp>
#include <vector>
class Canvas;
class CanvasMgr:
public SGSubsystem,
public SGPropertyChangeListener
{
public:
CanvasMgr();
virtual ~CanvasMgr();
virtual void init();
virtual void reinit();
virtual void shutdown();
virtual void bind();
virtual void unbind();
virtual void update(double delta_time_sec);
virtual void childAdded( SGPropertyNode * parent,
SGPropertyNode * child );
virtual void childRemoved( SGPropertyNode * parent,
SGPropertyNode * child );
private:
/** Root node for everything concerning the canvas system */
SGPropertyNode_ptr _props;
/** The actual canvases */
std::vector<Canvas> _canvases;
void textureAdded(SGPropertyNode* node);
/**
* Trigger a childAdded and valueChanged event for every child of node
* (Unlimited depth) and node itself.
*/
void triggerChangeRecursive(SGPropertyNode* node);
/**
* Get the value of a property or throw an exception if it doesn't exist.
*/
template<class T>
T getParam(const SGPropertyNode* node, const char* prop);
};
#endif /* CANVAS_MGR_H_ */

View file

@ -0,0 +1,266 @@
// Interface for 2D canvas element
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "element.hxx"
#include <cassert>
#include <osg/Drawable>
namespace canvas
{
const std::string NAME_TRANSFORM = "tf";
const std::string NAME_COLOR = "color";
const std::string NAME_COLOR_FILL = "color-fill";
//----------------------------------------------------------------------------
Element::~Element()
{
}
//----------------------------------------------------------------------------
SGPropertyNode* Element::getPropertyNode()
{
return _node;
}
//----------------------------------------------------------------------------
void Element::update(double dt)
{
if( _transform_dirty )
{
osg::Matrix m;
for( size_t i = 0; i < _transform_types.size(); ++i )
{
// Skip unused indizes...
if( _transform_types[i] == TT_NONE )
continue;
SGPropertyNode* tf_node = _node->getChild("tf", i, true);
// Build up the matrix representation of the current transform node
osg::Matrix tf;
switch( _transform_types[i] )
{
case TT_MATRIX:
tf = osg::Matrix( tf_node->getDoubleValue("a", 1),
tf_node->getDoubleValue("b", 0), 0, 0,
tf_node->getDoubleValue("c", 0),
tf_node->getDoubleValue("d", 1), 0, 0,
0, 0, 1, 0,
tf_node->getDoubleValue("e", 0),
tf_node->getDoubleValue("f", 0), 0, 1 );
break;
case TT_TRANSLATE:
tf.makeTranslate( osg::Vec3f( tf_node->getDoubleValue("tx", 0),
tf_node->getDoubleValue("ty", 0),
0 ) );
break;
case TT_ROTATE:
tf.makeRotate( tf_node->getDoubleValue("rot", 0), 0, 0, 1 );
break;
case TT_SCALE:
{
float sx = tf_node->getDoubleValue("sx", 1);
// sy defaults to sx...
tf.makeScale( sx, tf_node->getDoubleValue("sy", sx), 1 );
break;
}
default:
break;
}
m.postMult( tf );
}
_transform->setMatrix(m);
_transform_dirty = false;
}
if( _attributes_dirty & COLOR )
{
colorChanged( osg::Vec4( _color[0]->getFloatValue(),
_color[1]->getFloatValue(),
_color[2]->getFloatValue(),
1 ) );
_attributes_dirty &= ~COLOR;
}
if( _attributes_dirty & COLOR_FILL )
{
colorFillChanged( osg::Vec4( _color_fill[0]->getFloatValue(),
_color_fill[1]->getFloatValue(),
_color_fill[2]->getFloatValue(),
1 ) );
_attributes_dirty &= ~COLOR_FILL;
}
if( _drawable && (_attributes_dirty & BOUNDING_BOX) )
{
_bounding_box[0]->setFloatValue(_drawable->getBound()._min.x());
_bounding_box[1]->setFloatValue(_drawable->getBound()._min.y());
_bounding_box[2]->setFloatValue(_drawable->getBound()._max.x());
_bounding_box[3]->setFloatValue(_drawable->getBound()._max.y());
_attributes_dirty &= ~BOUNDING_BOX;
}
}
//----------------------------------------------------------------------------
osg::ref_ptr<osg::MatrixTransform> Element::getMatrixTransform()
{
return _transform;
}
//----------------------------------------------------------------------------
Element::Element(SGPropertyNode* node, uint32_t attributes_used):
_node( node ),
_drawable( 0 ),
_attributes_used( attributes_used ),
_attributes_dirty( 0 ),
_transform_dirty( false ),
_transform( new osg::MatrixTransform )
{
assert( _node );
_node->addChangeListener(this);
if( _attributes_used & COLOR )
linkColorNodes("color", _color, osg::Vec4f(0,1,0,1));
if( _attributes_used & COLOR_FILL )
linkColorNodes("color-fill", _color_fill);
if( _attributes_used & BOUNDING_BOX )
{
SGPropertyNode* bb = _node->getChild("bounding-box", 0, true);
_bounding_box[0] = bb->getChild("x-min", 0, true);
_bounding_box[1] = bb->getChild("y-min", 0, true);
_bounding_box[2] = bb->getChild("x-max", 0, true);
_bounding_box[3] = bb->getChild("y-max", 0, true);
}
SG_LOG
(
SG_GL,
SG_DEBUG,
"New canvas element " << node->getPath()
);
}
//----------------------------------------------------------------------------
void Element::linkColorNodes( const char* name,
SGPropertyNode** nodes,
const osg::Vec4& def )
{
// Don't tie to allow the usage of aliases
SGPropertyNode* color = _node->getChild(name, 0, true);
static const char* color_names[] = {"red", "green", "blue"};
for( size_t i = 0; i < sizeof(color_names)/sizeof(color_names[0]); ++i )
{
color->setFloatValue
(
color_names[i],
color->getFloatValue(color_names[i], def[i])
);
nodes[i] = color->getChild(color_names[i]);
}
}
//----------------------------------------------------------------------------
void Element::childAdded(SGPropertyNode* parent, SGPropertyNode* child)
{
if( parent == _node )
{
if( child->getNameString() == NAME_TRANSFORM )
{
if( child->getIndex() >= static_cast<int>(_transform_types.size()) )
_transform_types.resize( child->getIndex() + 1 );
_transform_types[ child->getIndex() ] = TT_NONE;
_transform_dirty = true;
}
else
childAdded(child);
}
else if( parent->getParent() == _node
&& parent->getNameString() == NAME_TRANSFORM )
{
assert(parent->getIndex() < static_cast<int>(_transform_types.size()));
const std::string& name = child->getNameString();
TransformType& type = _transform_types[parent->getIndex()];
if( name == "a" || name == "b" || name == "c"
|| name == "d" || name == "e" || name == "f" )
type = TT_MATRIX;
else if( name == "tx" || name == "ty" )
type = TT_TRANSLATE;
else if( name == "rot" )
type = TT_ROTATE;
else if( name == "sx" || name == "sy" )
type = TT_SCALE;
else
SG_LOG
(
SG_GL,
SG_WARN,
"Unknown transform element " << child->getPath()
);
_transform_dirty = true;
}
}
//----------------------------------------------------------------------------
void Element::childRemoved(SGPropertyNode* parent, SGPropertyNode* child)
{
if( parent != _node )
return;
if( child->getNameString() == NAME_TRANSFORM )
{
assert(child->getIndex() < static_cast<int>(_transform_types.size()));
_transform_types[ child->getIndex() ] = TT_NONE;
while( !_transform_types.empty() && _transform_types.back() == TT_NONE )
_transform_types.pop_back();
_transform_dirty = true;
}
else
childRemoved(child);
}
//----------------------------------------------------------------------------
void Element::valueChanged(SGPropertyNode* child)
{
SGPropertyNode *parent = child->getParent();
if( parent->getParent() == _node )
{
if( parent->getNameString() == NAME_TRANSFORM )
_transform_dirty = true;
else if( parent->getNameString() == NAME_COLOR )
_attributes_dirty |= COLOR;
else if( parent->getNameString() == NAME_COLOR_FILL )
_attributes_dirty |= COLOR_FILL;
}
else
childChanged(child);
}
} // namespace canvas

View file

@ -0,0 +1,107 @@
// Interface for 2D canvas element
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef CANVAS_ELEMENT_HXX_
#define CANVAS_ELEMENT_HXX_
#include <simgear/props/props.hxx>
#include <osg/MatrixTransform>
#include <simgear/misc/stdint.hxx> // for uint32_t
namespace osg
{
class Drawable;
}
namespace canvas
{
class Element:
private SGPropertyChangeListener
{
public:
virtual ~Element() = 0;
SGPropertyNode* getPropertyNode();
/**
* Called every frame to update internal state
*
* @param dt Frame time in seconds
*/
virtual void update(double dt);
osg::ref_ptr<osg::MatrixTransform> getMatrixTransform();
protected:
enum Attributes
{
COLOR = 0x0001,
COLOR_FILL = 0x0002,
BOUNDING_BOX = 0x0004
};
enum TransformType
{
TT_NONE,
TT_MATRIX,
TT_TRANSLATE,
TT_ROTATE,
TT_SCALE
};
SGPropertyNode *_node;
osg::Drawable *_drawable;
uint32_t _attributes_used;
uint32_t _attributes_dirty;
bool _transform_dirty;
osg::ref_ptr<osg::MatrixTransform> _transform;
std::vector<TransformType> _transform_types;
SGPropertyNode *_bounding_box[4]; ///<! x-min, y-min, x-max, y-max
SGPropertyNode *_color[3];
SGPropertyNode *_color_fill[3];
Element(SGPropertyNode* node, uint32_t attributes_used = 0);
virtual void childAdded(SGPropertyNode * child) {}
virtual void childRemoved(SGPropertyNode * child){}
virtual void childChanged(SGPropertyNode * child){}
virtual void colorChanged(const osg::Vec4& color) {}
virtual void colorFillChanged(const osg::Vec4& color){}
void linkColorNodes( const char* name,
SGPropertyNode** nodes,
const osg::Vec4& def = osg::Vec4(1,1,0,1) );
private:
Element(const Element&);// = delete
virtual void childAdded( SGPropertyNode * parent,
SGPropertyNode * child );
virtual void childRemoved( SGPropertyNode * parent,
SGPropertyNode * child );
virtual void valueChanged(SGPropertyNode * child);
};
} // namespace canvas
#endif /* CANVAS_ELEMENT_HXX_ */

View file

@ -0,0 +1,65 @@
// A group of 2D canvas elements
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "group.hxx"
#include "text.hxx"
namespace canvas
{
//----------------------------------------------------------------------------
Group::Group(SGPropertyNode* node):
Element(node)
{
}
//----------------------------------------------------------------------------
Group::~Group()
{
}
//----------------------------------------------------------------------------
void Group::update(double dt)
{
for( size_t i = 0; i < _children.size(); ++i )
_children[i]->update(dt);
Element::update(dt);
}
//----------------------------------------------------------------------------
void Group::childAdded(SGPropertyNode* child)
{
if( child->getNameString() == "text" )
{
_children.push_back( boost::shared_ptr<Element>(new Text(child)) );
_transform->addChild( _children.back()->getMatrixTransform() );
}
else
std::cout << "New unknown child: " << child->getDisplayName() << std::endl;
}
//----------------------------------------------------------------------------
void Group::childRemoved(SGPropertyNode* child)
{
}
} // namespace canvas

View file

@ -0,0 +1,47 @@
// A group of 2D canvas elements
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef CANVAS_GROUP_HXX_
#define CANVAS_GROUP_HXX_
#include "element.hxx"
#include <boost/shared_ptr.hpp>
#include <vector>
namespace canvas
{
class Group:
public Element
{
public:
Group(SGPropertyNode* node);
virtual ~Group();
virtual void update(double dt);
protected:
std::vector<boost::shared_ptr<Element> > _children;
virtual void childAdded(SGPropertyNode * child);
virtual void childRemoved(SGPropertyNode * child);
};
} // namespace canvas
#endif /* CANVAS_GROUP_HXX_ */

View file

@ -0,0 +1,41 @@
// Mapping between strings and osg text alignment flags
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef ENUM_MAPPING
# error "Only include with ENUM_MAPPING defined!"
#endif
ENUM_MAPPING(LEFT_TOP, "left-top")
ENUM_MAPPING(LEFT_CENTER, "left-center")
ENUM_MAPPING(LEFT_BOTTOM, "left-bottom")
ENUM_MAPPING(CENTER_TOP, "center-top")
ENUM_MAPPING(CENTER_CENTER, "center-center")
ENUM_MAPPING(CENTER_BOTTOM, "center-bottom")
ENUM_MAPPING(RIGHT_TOP, "right-top")
ENUM_MAPPING(RIGHT_CENTER, "right-center")
ENUM_MAPPING(RIGHT_BOTTOM, "right-bottom")
ENUM_MAPPING(LEFT_BASE_LINE, "left-baseline")
ENUM_MAPPING(CENTER_BASE_LINE, "center-baseline")
ENUM_MAPPING(RIGHT_BASE_LINE, "right-baseline")
ENUM_MAPPING(LEFT_BOTTOM_BASE_LINE, "left-bottom-baseline")
ENUM_MAPPING(CENTER_BOTTOM_BASE_LINE, "center-bottom-baseline")
ENUM_MAPPING(RIGHT_BOTTOM_BASE_LINE, "right-bottom-baseline")

View file

@ -0,0 +1,184 @@
// A text on the canvas
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include "text.hxx"
#include <osgText/Text>
#include <Main/globals.hxx>
#include <Main/fg_props.hxx>
namespace canvas
{
//----------------------------------------------------------------------------
Text::Text(SGPropertyNode* node):
Element(node, COLOR | COLOR_FILL | BOUNDING_BOX),
_text( new osgText::Text )
{
_drawable = _text;
_text->setCharacterSizeMode(osgText::Text::SCREEN_COORDS);
// font size and property node
float character_size = _node->getFloatValue("size", 32);
_text->setCharacterSize( character_size );
_node->setFloatValue("size", character_size);
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(_text);
_transform->addChild(geode);
_node->tie
(
"alignment",
SGRawValueMethods<Text, const char*>
(
*this,
&Text::getAlignment,
&Text::setAlignment
)
);
_node->tie
(
"padding",
SGRawValueMethods<osgText::Text, float>
(
*_text.get(),
&osgText::Text::getBoundingBoxMargin,
&osgText::Text::setBoundingBoxMargin
)
);
typedef SGRawValueMethods<osgText::Text, int> TextIntMethods;
_node->tie
(
"draw-mode",
// TEXT = 1 default
// BOUNDINGBOX = 2
// FILLEDBOUNDINGBOX = 4
// ALIGNMENT = 8
TextIntMethods
(
*_text.get(),
(TextIntMethods::getter_t)&osgText::Text::getDrawMode,
(TextIntMethods::setter_t)&osgText::Text::setDrawMode
)
);
}
//----------------------------------------------------------------------------
Text::~Text()
{
}
//----------------------------------------------------------------------------
void Text::setFont(const char* name)
{
_text->setFont( getFont(name) );
}
//----------------------------------------------------------------------------
void Text::setAlignment(const char* align)
{
const std::string align_string(align);
if( 0 ) return;
#define ENUM_MAPPING(enum_val, string_val) \
else if( align_string == string_val )\
_text->setAlignment( osgText::Text::enum_val );
#include "text-alignment.hxx"
#undef ENUM_MAPPING
else
_text->setAlignment(osgText::Text::LEFT_BASE_LINE);
}
//----------------------------------------------------------------------------
const char* Text::getAlignment() const
{
switch( _text->getAlignment() )
{
#define ENUM_MAPPING(enum_val, string_val) \
case osgText::Text::enum_val:\
return string_val;
#include "text-alignment.hxx"
#undef ENUM_MAPPING
default:
return "unknown";
}
}
//----------------------------------------------------------------------------
void Text::childChanged(SGPropertyNode* child)
{
if( child->getNameString() == "text" )
_text->setText(child->getStringValue());
else if( child->getNameString() == "size" )
_text->setCharacterSize( child->getFloatValue() );
else if( child->getNameString() == "font" )
setFont( child->getStringValue() );
else
return;
_attributes_dirty |= BOUNDING_BOX;
}
//----------------------------------------------------------------------------
void Text::colorChanged(const osg::Vec4& color)
{
_text->setColor(color);
}
//----------------------------------------------------------------------------
void Text::colorFillChanged(const osg::Vec4& color)
{
_text->setBoundingBoxColor(color);
}
//----------------------------------------------------------------------------
Text::font_ptr Text::getFont(const std::string& name)
{
SGPath path = globals->resolve_ressource_path("Fonts/" + name);
if( path.isNull() )
{
SG_LOG
(
SG_GL,
SG_ALERT,
"canvas::Text: No such font: " << name
);
return font_ptr();
}
SG_LOG
(
SG_GL,
SG_INFO,
"canvas::Text: using font file " << path.str()
);
font_ptr font = osgText::readFontFile(path.c_str());
if( !font )
SG_LOG
(
SG_GL,
SG_ALERT,
"canvas::Text: Failed to open font file " << path.c_str()
);
return font;
}
} // namespace canvas

View file

@ -0,0 +1,56 @@
// A text on the canvas
//
// Copyright (C) 2012 Thomas Geymayer <tomgey@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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#ifndef CANVAS_TEXT_HXX_
#define CANVAS_TEXT_HXX_
#include "element.hxx"
#include <osgText/Text>
#include <boost/shared_ptr.hpp>
#include <map>
#include <vector>
namespace canvas
{
class Text:
public Element
{
public:
Text(SGPropertyNode* node);
virtual ~Text();
void setFont(const char* name);
void setAlignment(const char* align);
const char* getAlignment() const;
protected:
osg::ref_ptr<osgText::Text> _text;
virtual void childChanged(SGPropertyNode * child);
virtual void colorChanged(const osg::Vec4& color);
virtual void colorFillChanged(const osg::Vec4& color);
typedef osg::ref_ptr<osgText::Font> font_ptr;
static font_ptr getFont(const std::string& name);
};
} // namespace canvas
#endif /* CANVAS_TEXT_HXX_ */

View file

@ -93,28 +93,6 @@ get_aspect_adjust (int xsize, int ysize)
float real_aspect = float(xsize) / float(ysize); float real_aspect = float(xsize) / float(ysize);
return (real_aspect / ideal_aspect); return (real_aspect / ideal_aspect);
} }
////////////////////////////////////////////////////////////////////////
// Global functions.
////////////////////////////////////////////////////////////////////////
bool
fgPanelVisible ()
{
const FGPanel* current = globals->get_current_panel();
if (current == 0)
return false;
if (current->getVisibility() == 0)
return false;
if (globals->get_viewmgr()->get_current() != 0)
return false;
if (current->getAutohide() && globals->get_current_view()->getHeadingOffset_deg() * SGD_DEGREES_TO_RADIANS != 0)
return false;
return true;
}
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// Implementation of FGTextureManager. // Implementation of FGTextureManager.
@ -201,8 +179,6 @@ FGPanel::FGPanel ()
: _mouseDown(false), : _mouseDown(false),
_mouseInstrument(0), _mouseInstrument(0),
_width(WIN_W), _height(int(WIN_H * 0.5768 + 1)), _width(WIN_W), _height(int(WIN_H * 0.5768 + 1)),
// _view_height(int(WIN_H * 0.4232)),
_visibility(fgGetNode("/sim/panel/visibility", true)),
_x_offset(fgGetNode("/sim/panel/x-offset", true)), _x_offset(fgGetNode("/sim/panel/x-offset", true)),
_y_offset(fgGetNode("/sim/panel/y-offset", true)), _y_offset(fgGetNode("/sim/panel/y-offset", true)),
_jitter(fgGetNode("/sim/panel/jitter", true)), _jitter(fgGetNode("/sim/panel/jitter", true)),
@ -210,6 +186,7 @@ FGPanel::FGPanel ()
_xsize_node(fgGetNode("/sim/startup/xsize", true)), _xsize_node(fgGetNode("/sim/startup/xsize", true)),
_ysize_node(fgGetNode("/sim/startup/ysize", true)), _ysize_node(fgGetNode("/sim/startup/ysize", true)),
_enable_depth_test(false), _enable_depth_test(false),
_autohide(true),
_drawPanelHotspots("/sim/panel-hotspots") _drawPanelHotspots("/sim/panel-hotspots")
{ {
} }
@ -238,44 +215,6 @@ FGPanel::addInstrument (FGPanelInstrument * instrument)
_instruments.push_back(instrument); _instruments.push_back(instrument);
} }
/**
* Initialize the panel.
*/
void
FGPanel::init ()
{
}
/**
* Bind panel properties.
*/
void
FGPanel::bind ()
{
fgSetArchivable("/sim/panel/visibility");
fgSetArchivable("/sim/panel/x-offset");
fgSetArchivable("/sim/panel/y-offset");
fgSetArchivable("/sim/panel/jitter");
}
/**
* Unbind panel properties.
*/
void
FGPanel::unbind ()
{
}
void
FGPanel::update (double dt)
{
updateMouseDelay(dt);
}
double double
FGPanel::getAspectScale() const FGPanel::getAspectScale() const
{ {
@ -506,26 +445,6 @@ FGPanel::draw(osg::State& state)
} }
} }
/**
* Set the panel's visibility.
*/
void
FGPanel::setVisibility (bool visibility)
{
_visibility->setBoolValue( visibility );
}
/**
* Return true if the panel is visible.
*/
bool
FGPanel::getVisibility () const
{
return _visibility->getBoolValue();
}
/** /**
* Set the panel's background texture. * Set the panel's background texture.
*/ */

View file

@ -29,7 +29,6 @@
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/props/propertyObject.hxx> #include <simgear/props/propertyObject.hxx>
#include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/structure/SGBinding.hxx> #include <simgear/structure/SGBinding.hxx>
#include <simgear/math/interpolater.hxx> #include <simgear/math/interpolater.hxx>
#include <simgear/timing/timestamp.hxx> #include <simgear/timing/timestamp.hxx>
@ -118,22 +117,14 @@ private:
* redraw themselves when necessary, and will pass mouse clicks on to * redraw themselves when necessary, and will pass mouse clicks on to
* the appropriate instruments for processing. * the appropriate instruments for processing.
*/ */
class FGPanel : public SGSubsystem class FGPanel : public SGReferenced
{ {
public: public:
FGPanel (); FGPanel ();
virtual ~FGPanel (); virtual ~FGPanel ();
// Update the panel (every frame).
virtual void init ();
virtual void bind ();
virtual void unbind ();
virtual void draw (osg::State& state); virtual void draw (osg::State& state);
virtual void update (double);
//void update (osg::State& state);
//virtual void update (osg::State& state, GLfloat winx, GLfloat winw, GLfloat winy, GLfloat winh);
virtual void updateMouseDelay(double dt); virtual void updateMouseDelay(double dt);
@ -146,11 +137,6 @@ public:
// Background multiple textures. // Background multiple textures.
virtual void setMultiBackground (osg::Texture2D* texture, int idx); virtual void setMultiBackground (osg::Texture2D* texture, int idx);
// Make the panel visible or invisible.
virtual bool getVisibility () const;
virtual void setVisibility (bool visibility);
// Full width of panel.
virtual void setWidth (int width) { _width = width; } virtual void setWidth (int width) { _width = width; }
virtual int getWidth () const { return _width; } virtual int getWidth () const { return _width; }
@ -201,7 +187,6 @@ private:
int _height; int _height;
// int _view_height; // int _view_height;
SGPropertyNode_ptr _visibility;
SGPropertyNode_ptr _x_offset; SGPropertyNode_ptr _x_offset;
SGPropertyNode_ptr _y_offset; SGPropertyNode_ptr _y_offset;
SGPropertyNode_ptr _jitter; SGPropertyNode_ptr _jitter;
@ -584,22 +569,7 @@ public:
FGSwitchLayer (); FGSwitchLayer ();
virtual void draw (osg::State& state); virtual void draw (osg::State& state);
}; };
////////////////////////////////////////////////////////////////////////
// Functions.
////////////////////////////////////////////////////////////////////////
/**
* Test whether the panel should be visible.
*/
bool fgPanelVisible ();
#endif // __PANEL_HXX #endif // __PANEL_HXX
// end of panel.hxx // end of panel.hxx

View file

@ -28,6 +28,7 @@
#include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple.hpp>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/math/SGMath.hxx>
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>

View file

@ -26,6 +26,7 @@
#include <algorithm> #include <algorithm>
#include <simgear/math/SGMath.hxx>
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
#include "environment_ctrl.hxx" #include "environment_ctrl.hxx"
#include "environment.hxx" #include "environment.hxx"

View file

@ -24,7 +24,6 @@
#include <simgear/compiler.h> #include <simgear/compiler.h>
#include <simgear/structure/subsystem_mgr.hxx> #include <simgear/structure/subsystem_mgr.hxx>
#include <simgear/math/SGMath.hxx>
#include <simgear/props/tiedpropertylist.hxx> #include <simgear/props/tiedpropertylist.hxx>
#ifdef SG_HAVE_STD_INCLUDES #ifdef SG_HAVE_STD_INCLUDES

View file

@ -26,6 +26,7 @@
#include <cmath> #include <cmath>
#include <simgear/math/SGMisc.hxx> #include <simgear/math/SGMisc.hxx>
#include <simgear/math/SGMath.hxx>
#include <Main/fg_props.hxx> #include <Main/fg_props.hxx>
namespace Environment { namespace Environment {

View file

@ -16,7 +16,7 @@
// //
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with this program; if not, write to the Free Software // along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
// //
// $Id: JSBSim.cxx,v 1.64 2010/10/31 04:49:25 jberndt Exp $ // $Id: JSBSim.cxx,v 1.64 2010/10/31 04:49:25 jberndt Exp $

View file

@ -19,7 +19,7 @@
You should have received a copy of the GNU Lesser General Public License You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
HISTORY HISTORY
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------

0
src/FDM/JSBSim/input_output/FGScript.cpp Executable file → Normal file
View file

0
src/FDM/JSBSim/models/FGAuxiliary.cpp Executable file → Normal file
View file

0
src/FDM/JSBSim/models/FGExternalForce.cpp Executable file → Normal file
View file

0
src/FDM/JSBSim/models/FGExternalForce.h Executable file → Normal file
View file

0
src/FDM/JSBSim/models/FGExternalReactions.h Executable file → Normal file
View file

0
src/FDM/JSBSim/models/flight_control/FGFCSFunction.h Executable file → Normal file
View file

0
src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp Executable file → Normal file
View file

View file

@ -3,6 +3,8 @@
# include "config.h" # include "config.h"
#endif #endif
#include <cstdlib>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/math/sg_geodesy.hxx> #include <simgear/math/sg_geodesy.hxx>
#include <simgear/misc/sg_path.hxx> #include <simgear/misc/sg_path.hxx>

View file

@ -5,8 +5,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <simgear/math/SGMath.hxx>
#include "Math.hpp" #include "Math.hpp"
#include "FGFDM.hpp" #include "FGFDM.hpp"
#include "PropEngine.hpp" #include "PropEngine.hpp"

View file

@ -10,8 +10,6 @@
#include "Atmosphere.hpp" #include "Atmosphere.hpp"
#include "Airplane.hpp" #include "Airplane.hpp"
#include <simgear/math/SGMath.hxx>
using namespace yasim; using namespace yasim;
// Stubs. Not needed by a batch program, but required to link. // Stubs. Not needed by a batch program, but required to link.

View file

@ -28,7 +28,6 @@
#include <simgear/constants.h> #include <simgear/constants.h>
#include <simgear/debug/logstream.hxx> #include <simgear/debug/logstream.hxx>
#include <simgear/math/SGMath.hxx>
#include <simgear/timing/timestamp.hxx> #include <simgear/timing/timestamp.hxx>
#include <Scenery/scenery.hxx> #include <Scenery/scenery.hxx>

View file

@ -62,4 +62,9 @@ private:
}; };
/**
* open a URL using the system's web-browser
*/
void cocoaOpenUrl(const std::string& url);
#endif // __MENUBAR_HXX #endif // __MENUBAR_HXX

View file

@ -110,6 +110,23 @@ static void setItemShortcutFromString(NSMenuItem* item, const string& s)
} }
namespace { namespace {
class CocoaAutoreleasePool
{
public:
CocoaAutoreleasePool()
{
pool = [[NSAutoreleasePool alloc] init];
}
~CocoaAutoreleasePool()
{
[pool release];
}
private:
NSAutoreleasePool* pool;
};
class CocoaEnabledListener : public SGPropertyChangeListener class CocoaEnabledListener : public SGPropertyChangeListener
{ {
public: public:
@ -120,6 +137,7 @@ namespace {
virtual void valueChanged(SGPropertyNode *node) virtual void valueChanged(SGPropertyNode *node)
{ {
CocoaAutoreleasePool pool;
BOOL b = node->getBoolValue(); BOOL b = node->getBoolValue();
[item setEnabled:b]; [item setEnabled:b];
} }
@ -137,6 +155,7 @@ FGCocoaMenuBar::CocoaMenuBarPrivate::CocoaMenuBarPrivate()
FGCocoaMenuBar::CocoaMenuBarPrivate::~CocoaMenuBarPrivate() FGCocoaMenuBar::CocoaMenuBarPrivate::~CocoaMenuBarPrivate()
{ {
CocoaAutoreleasePool pool;
[delegate release]; [delegate release];
} }
@ -153,16 +172,9 @@ void FGCocoaMenuBar::CocoaMenuBarPrivate::menuFromProps(NSMenu* menu, SGProperty
n->setBoolValue("enabled", true); n->setBoolValue("enabled", true);
} }
string shortcut; string l = getLocalizedLabel(n);
string l = n->getStringValue("label");
string::size_type pos = l.find("(");
if (pos != string::npos) {
string full(l);
l = full.substr(0, pos);
shortcut = full.substr(pos + 1, full.size() - (pos + 2));
}
NSString* label = stdStringToCocoa(strutils::simplify(l)); NSString* label = stdStringToCocoa(strutils::simplify(l));
string shortcut = n->getStringValue("key");
NSMenuItem* item; NSMenuItem* item;
if (index >= [menu numberOfItems]) { if (index >= [menu numberOfItems]) {
@ -227,6 +239,8 @@ FGCocoaMenuBar::~FGCocoaMenuBar()
void FGCocoaMenuBar::init() void FGCocoaMenuBar::init()
{ {
CocoaAutoreleasePool pool;
NSMenu* mainBar = [[NSApplication sharedApplication] mainMenu]; NSMenu* mainBar = [[NSApplication sharedApplication] mainMenu];
SGPropertyNode_ptr props = fgGetNode("/sim/menubar/default",true); SGPropertyNode_ptr props = fgGetNode("/sim/menubar/default",true);
@ -237,7 +251,7 @@ void FGCocoaMenuBar::init()
} }
BOOST_FOREACH(SGPropertyNode_ptr n, props->getChildren("menu")) { BOOST_FOREACH(SGPropertyNode_ptr n, props->getChildren("menu")) {
NSString* label = stdStringToCocoa(n->getStringValue("label")); NSString* label = stdStringToCocoa(getLocalizedLabel(n));
NSMenuItem* item = [mainBar itemWithTitle:label]; NSMenuItem* item = [mainBar itemWithTitle:label];
NSMenu* menu; NSMenu* menu;
@ -283,3 +297,10 @@ void FGCocoaMenuBar::hide()
{ {
// no-op // no-op
} }
void cocoaOpenUrl(const std::string& url)
{
CocoaAutoreleasePool pool;
NSURL* nsu = [NSURL URLWithString:stdStringToCocoa(url)];
[[NSWorkspace sharedWorkspace] openURL:nsu];
}

View file

@ -7,7 +7,6 @@
#include <iostream> #include <iostream>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/math/SGMath.hxx>
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
// FGColor class. // FGColor class.

View file

@ -15,7 +15,6 @@
#ifndef __FGFONTCACHE_HXX #ifndef __FGFONTCACHE_HXX
#define __FGFONTCACHE_HXX #define __FGFONTCACHE_HXX
#include <simgear/math/SGMath.hxx>
#include <simgear/misc/sg_path.hxx> #include <simgear/misc/sg_path.hxx>
#include <map> #include <map>

View file

@ -8,8 +8,6 @@
#include <algorithm> // for std::sort #include <algorithm> // for std::sort
#include <plib/puAux.h> #include <plib/puAux.h>
#include <simgear/sg_inlines.h>
#include <simgear/route/waypoint.hxx>
#include <simgear/sg_inlines.h> #include <simgear/sg_inlines.h>
#include <simgear/misc/strutils.hxx> #include <simgear/misc/strutils.hxx>
#include <simgear/magvar/magvar.hxx> #include <simgear/magvar/magvar.hxx>
@ -682,7 +680,7 @@ void MapWidget::paintRoute()
return; return;
} }
RoutePath path(_route->waypts()); RoutePath path(_route->flightPlan());
// first pass, draw the actual lines // first pass, draw the actual lines
glLineWidth(2.0); glLineWidth(2.0);
@ -889,7 +887,7 @@ public:
{ {
_heliports = nd->getBoolValue("show-heliports", false); _heliports = nd->getBoolValue("show-heliports", false);
_hardRunwaysOnly = nd->getBoolValue("hard-surfaced-airports", true); _hardRunwaysOnly = nd->getBoolValue("hard-surfaced-airports", true);
_minLengthFt = nd->getDoubleValue("min-runway-length-ft", 2000.0); _minLengthFt = fgGetDouble("/sim/navdb/min-runway-length-ft", 2000);
} }
virtual FGPositioned::Type maxType() const { virtual FGPositioned::Type maxType() const {

View file

@ -11,7 +11,6 @@
#include <plib/puAux.h> #include <plib/puAux.h>
#include <simgear/route/waypoint.hxx>
#include <simgear/structure/callback.hxx> #include <simgear/structure/callback.hxx>
#include <simgear/sg_inlines.h> #include <simgear/sg_inlines.h>
@ -37,34 +36,37 @@ enum {
static const double BLINK_TIME = 0.3; static const double BLINK_TIME = 0.3;
static const int DRAG_START_DISTANCE_PX = 5; static const int DRAG_START_DISTANCE_PX = 5;
class RouteManagerWaypointModel : class FlightPlanWaypointModel :
public WaypointList::Model, public WaypointList::Model,
public SGPropertyChangeListener public SGPropertyChangeListener
{ {
public: public:
RouteManagerWaypointModel() FlightPlanWaypointModel(flightgear::FlightPlan* fp) :
_fp(fp)
{ {
_rm = static_cast<FGRouteMgr*>(globals->get_subsystem("route-manager"));
SGPropertyNode* routeEdited = fgGetNode("/autopilot/route-manager/signals/edited", true); SGPropertyNode* routeEdited = fgGetNode("/autopilot/route-manager/signals/edited", true);
SGPropertyNode* flightplanChanged = fgGetNode("/autopilot/route-manager/signals/flightplan-changed", true);
routeEdited->addChangeListener(this); routeEdited->addChangeListener(this);
flightplanChanged->addChangeListener(this);
} }
virtual ~RouteManagerWaypointModel() ~FlightPlanWaypointModel()
{ {
SGPropertyNode* routeEdited = fgGetNode("/autopilot/route-manager/signals/edited", true); SGPropertyNode* routeEdited = fgGetNode("/autopilot/route-manager/signals/edited", true);
SGPropertyNode* flightplanChanged = fgGetNode("/autopilot/route-manager/signals/flightplan-changed", true);
routeEdited->removeChangeListener(this); routeEdited->removeChangeListener(this);
flightplanChanged->removeChangeListener(this);
} }
// implement WaypointList::Model // implement WaypointList::Model
virtual unsigned int numWaypoints() const virtual unsigned int numWaypoints() const
{ {
return _rm->numWaypts(); return _fp->numLegs();
} }
virtual int currentWaypoint() const virtual int currentWaypoint() const
{ {
return _rm->currentIndex(); return _fp->currentIndex();
} }
virtual flightgear::Waypt* waypointAt(unsigned int index) const virtual flightgear::Waypt* waypointAt(unsigned int index) const
@ -73,12 +75,12 @@ public:
return NULL; return NULL;
} }
return _rm->wayptAtIndex(index); return _fp->legAtIndex(index)->waypoint();
} }
virtual void deleteAt(unsigned int index) virtual void deleteAt(unsigned int index)
{ {
_rm->removeWayptAtIndex(index); _fp->deleteIndex(index);
} }
virtual void moveWaypointToIndex(unsigned int srcIndex, unsigned int destIndex) virtual void moveWaypointToIndex(unsigned int srcIndex, unsigned int destIndex)
@ -89,13 +91,15 @@ public:
} }
unsigned int currentWpIndex = currentWaypoint(); unsigned int currentWpIndex = currentWaypoint();
WayptRef w(_rm->removeWayptAtIndex(srcIndex)); WayptRef w(waypointAt(currentWpIndex));
_fp->deleteIndex(currentWpIndex);
SG_LOG(SG_GENERAL, SG_INFO, "wpt:" << w->ident()); SG_LOG(SG_GENERAL, SG_INFO, "wpt:" << w->ident());
_rm->insertWayptAtIndex(w, destIndex); _fp->insertWayptAtIndex(w, destIndex);
if (srcIndex == currentWpIndex) { if (srcIndex == currentWpIndex) {
// current waypoint was moved // current waypoint was moved
_rm->jumpToIndex(destIndex); _fp->setCurrentIndex(destIndex);
} }
} }
@ -107,12 +111,19 @@ public:
// implement SGPropertyChangeListener // implement SGPropertyChangeListener
void valueChanged(SGPropertyNode *prop) void valueChanged(SGPropertyNode *prop)
{ {
if (_cb) { if (prop->getNameString() == "edited") {
(*_cb)(); if (_cb) {
(*_cb)();
}
}
if (prop->getNameString() == "flightplan-changed") {
_fp =
static_cast<FGRouteMgr*>(globals->get_subsystem("route-manager"))->flightPlan();
} }
} }
private: private:
FGRouteMgr* _rm; flightgear::FlightPlan* _fp;
SGCallback* _cb; SGCallback* _cb;
}; };
@ -152,7 +163,9 @@ WaypointList::WaypointList(int x, int y, int width, int height) :
{ {
// pretend to be a list, so fgPopup doesn't mess with our mouse events // pretend to be a list, so fgPopup doesn't mess with our mouse events
type |= PUCLASS_LIST; type |= PUCLASS_LIST;
setModel(new RouteManagerWaypointModel()); flightgear::FlightPlan* fp =
static_cast<FGRouteMgr*>(globals->get_subsystem("route-manager"))->flightPlan();
setModel(new FlightPlanWaypointModel(fp));
setSize(width, height); setSize(width, height);
setValue(-1); setValue(-1);
@ -399,12 +412,12 @@ void WaypointList::drawRow(int dx, int dy, int rowIndex, int y)
if (wp->flag(WPT_MISS)) { if (wp->flag(WPT_MISS)) {
drawBox = true; drawBox = true;
puSetColor(col, 1.0, 0.0, 0.0, 0.3); // red puSetColor(col, 1.0, 0.0, 0.0, 0.3); // red
} else if (wp->flag(WPT_ARRIVAL)) { } else if (wp->flag(WPT_ARRIVAL) || wp->flag(WPT_DEPARTURE)) {
drawBox = true; drawBox = true;
puSetColor(col, 0.0, 0.0, 0.0, 0.3); puSetColor(col, 0.0, 0.0, 0.0, 0.3);
} else if (wp->flag(WPT_DEPARTURE)) { } else if (wp->flag(WPT_APPROACH)) {
drawBox = true; drawBox = true;
puSetColor(col, 0.0, 0.0, 0.0, 0.3); puSetColor(col, 0.0, 0.0, 0.1, 0.3);
} }
if (isDragSource) { if (isDragSource) {

View file

@ -837,4 +837,4 @@ static fntBitmapFont fntHelvetica12(FontHelvetica12.Characters, 1,
puFont FONT_HELVETICA_14(&fntHelvetica14, 14, 0); puFont FONT_HELVETICA_14(&fntHelvetica14, 14, 0);
puFont FONT_SANS_12B(&fntSans12B, 12, 0); puFont FONT_SANS_12B(&fntSans12B, 12, 0);
puFont FONT_HELVETICA_12(&fntHelvetica12, 12, 0); puFont FONT_HELVETICA_12(&fntHelvetica12, 13 /*[sic!]*/, 0); /* Original plib Helvetica 12 font also reported size 13, instead of 12 */

View file

@ -60,6 +60,10 @@
# include <shellapi.h> # include <shellapi.h>
#endif #endif
#ifdef SG_MAC
# include "FGCocoaMenuBar.hxx" // for cocoaOpenUrl
#endif
#include "gui.h" #include "gui.h"
using std::string; using std::string;
@ -182,6 +186,15 @@ bool openBrowser(string address)
} }
} }
#ifdef SG_MAC
if (address.find("://")==string::npos) {
address = "file://" + address;
}
cocoaOpenUrl(address);
return ok;
#endif
#ifndef _WIN32 #ifndef _WIN32
string command = globals->get_browser(); string command = globals->get_browser();

View file

@ -4,7 +4,6 @@
#include <plib/pu.h> #include <plib/pu.h>
#include <simgear/props/props.hxx> #include <simgear/props/props.hxx>
#include <simgear/math/SGMath.hxx>
#include "layout.hxx" #include "layout.hxx"

View file

@ -5,7 +5,6 @@
#include "layout.hxx" #include "layout.hxx"
#include <simgear/math/SGMath.hxx>
// This file contains the actual layout engine. It has no dependence // This file contains the actual layout engine. It has no dependence
// on outside libraries; see layout-props.cxx for the glue code. // on outside libraries; see layout-props.cxx for the glue code.

View file

@ -6,7 +6,6 @@
#include "menubar.hxx" #include "menubar.hxx"
#include <Main/locale.hxx> #include <Main/locale.hxx>
#include <Main/globals.hxx> #include <Main/globals.hxx>
#include <simgear/math/SGMath.hxx>
FGMenuBar::FGMenuBar() FGMenuBar::FGMenuBar()
{ {

View file

@ -51,7 +51,7 @@ public:
* Take care of mapping it to the appropriate translation, if available. * Take care of mapping it to the appropriate translation, if available.
* Returns an UTF-8 encoded string. * Returns an UTF-8 encoded string.
*/ */
const char* getLocalizedLabel(SGPropertyNode* node); static const char* getLocalizedLabel(SGPropertyNode* node);
}; };

View file

@ -68,6 +68,8 @@ NewGUI::init ()
setStyle(); setStyle();
SGPath p(globals->get_fg_root(), "gui/dialogs"); SGPath p(globals->get_fg_root(), "gui/dialogs");
readDir(p); readDir(p);
const std::string aircraft_dir(fgGetString("/sim/aircraft-dir"));
readDir( SGPath(aircraft_dir, "gui/dialogs") );
_menubar->init(); _menubar->init();
} }

View file

@ -164,8 +164,6 @@
#define NOMINMAX 1 #define NOMINMAX 1
#define HAVE_CULLSETTINGS_CLEAR_MASK 1
#ifndef ENABLE_AUDIO_SUPPORT #ifndef ENABLE_AUDIO_SUPPORT
#define ENABLE_AUDIO_SUPPORT #define ENABLE_AUDIO_SUPPORT
#endif #endif

View file

@ -18,7 +18,6 @@
#cmakedefine HAVE_SYS_TIME_H #cmakedefine HAVE_SYS_TIME_H
#cmakedefine HAVE_WINDOWS_H #cmakedefine HAVE_WINDOWS_H
#cmakedefine HAVE_CULLSETTINGS_CLEAR_MASK
#cmakedefine HAVE_MKFIFO #cmakedefine HAVE_MKFIFO
#define VERSION "@FLIGHTGEAR_VERSION@" #define VERSION "@FLIGHTGEAR_VERSION@"

View file

@ -16,8 +16,8 @@
// //
// You should have received a copy of the GNU Library General Public // You should have received a copy of the GNU Library General Public
// License along with this library; if not, write to the // License along with this library; if not, write to the
// Free Software Foundation, Inc., 59 Temple Place - Suite 330, // Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
// Boston, MA 02111-1307, USA. // Boston, MA 02110-1301, USA.
// //
// $Id$ // $Id$

View file

@ -28,7 +28,6 @@
#include "FGButton.hxx" #include "FGButton.hxx"
#include <simgear/math/SGMath.hxx>
FGButton::FGButton () FGButton::FGButton ()
: is_repeatable(false), : is_repeatable(false),

View file

@ -30,8 +30,6 @@
#include <Main/globals.hxx> #include <Main/globals.hxx>
#include <Main/fg_os.hxx> #include <Main/fg_os.hxx>
#include <simgear/math/SGMath.hxx>
using simgear::PropertyList; using simgear::PropertyList;
using std::string; using std::string;

View file

@ -26,8 +26,6 @@
# include <config.h> # include <config.h>
#endif #endif
#include <simgear/math/SGMath.hxx>
#include "FGDeviceConfigurationMap.hxx" #include "FGDeviceConfigurationMap.hxx"
#include <simgear/misc/sg_dir.hxx> #include <simgear/misc/sg_dir.hxx>

Some files were not shown because too many files have changed in this diff Show more