Merge branch 'next' of gitorious.org:fg/flightgear into next
This commit is contained in:
commit
9fa790bcac
201 changed files with 8647 additions and 4454 deletions
|
@ -151,11 +151,13 @@ if (MSVC AND MSVC_3RDPARTY_ROOT)
|
|||
if (CMAKE_CL_64)
|
||||
set( OSG_MSVC ${OSG_MSVC}-64 )
|
||||
set( MSVC_3RDPARTY_DIR 3rdParty.x64 )
|
||||
set( BOOST_LIB lib64 )
|
||||
else (CMAKE_CL_64)
|
||||
set( MSVC_3RDPARTY_DIR 3rdParty )
|
||||
set( BOOST_LIB lib )
|
||||
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 (BOOST_ROOT ${MSVC_3RDPARTY_ROOT}/boost_1_44_0)
|
||||
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(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)
|
||||
find_package(RTI)
|
||||
if(RTI_FOUND)
|
||||
|
@ -273,11 +262,13 @@ if(ENABLE_RTI)
|
|||
endif(ENABLE_RTI)
|
||||
|
||||
if(CMAKE_COMPILER_IS_GNUCXX)
|
||||
set(WARNING_FLAGS -Wall)
|
||||
set(WARNING_FLAGS_CXX "-Wall")
|
||||
set(WARNING_FLAGS_C "-Wall")
|
||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||
|
||||
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()
|
||||
|
||||
if(WIN32)
|
||||
|
@ -297,8 +288,10 @@ if(WIN32)
|
|||
set(NOMINMAX 1)
|
||||
endif(WIN32)
|
||||
|
||||
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${WARNING_FLAGS} ${MSVC_FLAGS} -D_REENTRANT")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${WARNING_FLAGS} ${MSVC_FLAGS} -D_REENTRANT")
|
||||
set (BOOST_CXX_FLAGS "-DBOOST_MULTI_INDEX_DISABLE_SERIALIZATION -DBOOST_BIMAP_DISABLE_SERIALIZATION")
|
||||
|
||||
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}")
|
||||
|
||||
include_directories(${OPENSCENEGRAPH_INCLUDE_DIRS}
|
||||
|
|
|
@ -152,7 +152,6 @@ else(SIMGEAR_SHARED)
|
|||
nasal
|
||||
tsync
|
||||
bucket
|
||||
route
|
||||
io
|
||||
serial
|
||||
math
|
||||
|
|
|
@ -285,12 +285,12 @@
|
|||
</b>
|
||||
<div class="indent">
|
||||
<p>The latest development code is available for everyone through our
|
||||
CVS repository. See
|
||||
<a href="http://flightgear.org/cvsResources/">http://flightgear.org/cvsResources/</a> for details.
|
||||
git repository. See
|
||||
<a href="http://wiki.flightgear.org/FlightGear_and_Git">http://wiki.flightgear.org/FlightGear_and_Git</a> for details.
|
||||
</p>
|
||||
<p>Otherwise, you can get relatively up-to-date snapshots of the
|
||||
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>
|
||||
</div>
|
||||
|
||||
|
|
157
docs-mini/README.canvas
Normal file
157
docs-mini/README.canvas
Normal 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>
|
|
@ -11,7 +11,7 @@ fi
|
|||
if [ "x$2" != "x" ]; then
|
||||
VERSION="$2"
|
||||
else
|
||||
VERSION="2.5"
|
||||
VERSION="2.7"
|
||||
fi
|
||||
|
||||
echo base dir = $BASE, version = $VERSION
|
||||
|
@ -41,6 +41,7 @@ tar \
|
|||
data/Aircraft/Instruments-3d \
|
||||
data/Aircraft/UIUC \
|
||||
data/Aircraft/777 \
|
||||
data/Aircraft/777-200 \
|
||||
data/Aircraft/A6M2 \
|
||||
data/Aircraft/ASK13 \
|
||||
data/Aircraft/b1900d \
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
#include <Viewer/viewer.hxx>
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <osg/Node>
|
||||
#include <osgDB/FileUtils>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/scene/model/modellib.hxx>
|
||||
#include <simgear/scene/util/SGNodeMasks.hxx>
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#include <string>
|
||||
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/scene/model/placement.hxx>
|
||||
#include <simgear/scene/model/modellib.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <vector>
|
||||
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
||||
#include <math.h>
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
#include <vector>
|
||||
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
||||
#include <math.h>
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/constants.h>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
|
||||
#ifndef _FG_AIFLIGHTPLAN_HXX
|
||||
#define _FG_AIFLIGHTPLAN_HXX
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "AIFlightPlan.hxx"
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
*
|
||||
**************************************************************************/
|
||||
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
|
||||
#include <Airports/simple.hxx>
|
||||
#include <Airports/runways.hxx>
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
|
||||
#include <Airports/simple.hxx>
|
||||
|
|
|
@ -69,10 +69,7 @@ void
|
|||
FGAIManager::init() {
|
||||
root = fgGetNode("sim/ai", true);
|
||||
|
||||
enabled = root->getNode("enabled", true)->getBoolValue();
|
||||
|
||||
if (!enabled)
|
||||
return;
|
||||
enabled = root->getNode("enabled", true);
|
||||
|
||||
thermal_lift_node = fgGetNode("/environment/thermal-lift-fps", true);
|
||||
wind_from_east_node = fgGetNode("/environment/wind-from-east-fps",true);
|
||||
|
@ -92,6 +89,15 @@ FGAIManager::init() {
|
|||
void
|
||||
FGAIManager::postinit() {
|
||||
// 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;
|
||||
for (int i = 0 ; i < root->nChildren() ; i++) {
|
||||
SGPropertyNode *n = root->getChild(i);
|
||||
|
@ -143,7 +149,7 @@ FGAIManager::update(double dt) {
|
|||
range_nearest = 10000.0;
|
||||
strength = 0.0;
|
||||
|
||||
if (!enabled)
|
||||
if (!enabled->getBoolValue())
|
||||
return;
|
||||
|
||||
FGTrafficManager *tmgr = (FGTrafficManager*) globals->get_subsystem("traffic-manager");
|
||||
|
|
|
@ -96,13 +96,13 @@ public:
|
|||
|
||||
private:
|
||||
|
||||
bool enabled;
|
||||
int mNumAiTypeModels[FGAIBase::MAX_OBJECTS];
|
||||
int mNumAiModels;
|
||||
|
||||
double calcRange(double lat, double lon, double lat2, double lon2)const;
|
||||
|
||||
SGPropertyNode_ptr root;
|
||||
SGPropertyNode_ptr enabled;
|
||||
SGPropertyNode_ptr thermal_lift_node;
|
||||
SGPropertyNode_ptr user_latitude_node;
|
||||
SGPropertyNode_ptr user_longitude_node;
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#endif
|
||||
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
|
||||
#include "AIWingman.hxx"
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include "AIBase.hxx"
|
||||
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
|
||||
class FGAIWingman : public FGAIBallistic {
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/props/props_io.hxx>
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <Airports/dynamics.hxx>
|
||||
#include <Airports/simple.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
|
|
|
@ -45,8 +45,6 @@
|
|||
#include <ATC/CommStation.hxx>
|
||||
|
||||
|
||||
FGATCDialogNew *currentATCDialog;
|
||||
|
||||
static SGPropertyNode *getNamedNode(SGPropertyNode *prop, const char *name)
|
||||
{
|
||||
SGPropertyNode* p;
|
||||
|
|
|
@ -273,8 +273,8 @@ int FGTrafficRecord::crosses(FGGroundNetwork * net,
|
|||
if (intentions.size()) {
|
||||
for (i = intentions.begin(); i != intentions.end(); i++) {
|
||||
if ((*i) > 0) {
|
||||
if ((currentTargetNode ==
|
||||
net->findSegment(*i)->getEnd()->getIndex())) {
|
||||
if (currentTargetNode ==
|
||||
net->findSegment(*i)->getEnd()->getIndex()) {
|
||||
//cerr << "Current crosses at " << currentTargetNode <<endl;
|
||||
return currentTargetNode;
|
||||
}
|
||||
|
|
|
@ -35,18 +35,22 @@
|
|||
#include <Airports/simple.hxx>
|
||||
|
||||
FGATC::FGATC() :
|
||||
freq(0),
|
||||
_currentStation(NULL),
|
||||
range(0),
|
||||
_voice(true),
|
||||
_playing(false),
|
||||
_voiceOK(false),
|
||||
_sgr(NULL),
|
||||
freqClear(true),
|
||||
_type(INVALID),
|
||||
_display(false)
|
||||
#ifdef OLD_ATC_MGR
|
||||
,freqClear(true),
|
||||
receiving(false),
|
||||
respond(false),
|
||||
responseID(""),
|
||||
runResponseCounter(false),
|
||||
_runReleaseCounter(false),
|
||||
responseReqd(false),
|
||||
_type(INVALID),
|
||||
_display(false),
|
||||
// Transmission timing stuff
|
||||
pending_transmission(""),
|
||||
_timeout(0),
|
||||
|
@ -55,12 +59,13 @@ FGATC::FGATC() :
|
|||
_transmitting(false),
|
||||
_counter(0.0),
|
||||
_max_count(5.0)
|
||||
#endif
|
||||
{
|
||||
SGSoundMgr *smgr = globals->get_soundmgr();
|
||||
_sgr = smgr->find("atc", true);
|
||||
_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);
|
||||
_atc_external = fgGetNode("/sim/sound/atc/external-view", true);
|
||||
_internal = fgGetNode("/sim/current-view/internal", true);
|
||||
|
@ -69,9 +74,164 @@ FGATC::FGATC() :
|
|||
FGATC::~FGATC() {
|
||||
}
|
||||
|
||||
#ifndef 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
|
||||
}
|
||||
#endif
|
||||
|
||||
void FGATC::SetStation(flightgear::CommStation* sta) {
|
||||
if (_currentStation == sta)
|
||||
return;
|
||||
_currentStation = sta;
|
||||
|
||||
if (sta)
|
||||
{
|
||||
switch (sta->type()) {
|
||||
case FGPositioned::FREQ_ATIS: _type = ATIS; break;
|
||||
case FGPositioned::FREQ_AWOS: _type = AWOS; break;
|
||||
default:
|
||||
sta = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (sta == NULL)
|
||||
{
|
||||
range = 0;
|
||||
ident = "";
|
||||
name = "";
|
||||
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
|
||||
// Outputs the transmission either on screen or as audio depending on user preference
|
||||
// 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.
|
||||
void FGATC::Render(string& msg, const float volume,
|
||||
const string& refname, const bool repeating) {
|
||||
if ((!_display) ||(volume < 0.05))
|
||||
{
|
||||
NoRender(refname);
|
||||
return;
|
||||
}
|
||||
|
||||
if (repeating)
|
||||
fgSetString("/sim/messages/atis", msg.c_str());
|
||||
else
|
||||
fgSetString("/sim/messages/atc", msg.c_str());
|
||||
|
||||
#ifdef ENABLE_AUDIO_SUPPORT
|
||||
bool useVoice = _voice && fgGetBool("/sim/sound/voice") && fgGetBool("/sim/sound/atc/enabled");
|
||||
SGSoundSample *simple = _sgr->find(refname);
|
||||
if(useVoice) {
|
||||
if (simple && (_currentMsg == msg))
|
||||
{
|
||||
simple->set_volume(volume);
|
||||
}
|
||||
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,
|
||||
// >>> because the (remove) method is going to do a (delete)
|
||||
// >>> whether that's what you want or not.
|
||||
simple = new SGSoundSample(&buf, len, 8000);
|
||||
simple->set_volume(volume);
|
||||
_sgr->add(simple, refname);
|
||||
_sgr->play(refname, repeating);
|
||||
} catch ( sg_io_exception &e ) {
|
||||
SG_LOG(SG_ATC, SG_ALERT, e.getFormattedMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
if (simple)
|
||||
{
|
||||
NoRender(refname);
|
||||
}
|
||||
#endif // ENABLE_AUDIO_SUPPORT
|
||||
|
||||
if (!useVoice)
|
||||
{
|
||||
// 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.
|
||||
void FGATC::NoRender(const string& refname) {
|
||||
if(_playing) {
|
||||
if(_voice) {
|
||||
#ifdef ENABLE_AUDIO_SUPPORT
|
||||
_sgr->stop(refname);
|
||||
_sgr->remove(refname);
|
||||
#endif
|
||||
}
|
||||
_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) {
|
||||
|
@ -112,18 +272,6 @@ void FGATC::Update(double dt) {
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_AUDIO_SUPPORT
|
||||
bool active = _atc_external->getBoolValue() ||
|
||||
_internal->getBoolValue();
|
||||
|
||||
if ( active && _enabled->getBoolValue() ) {
|
||||
_sgr->set_volume( _volume->getFloatValue() );
|
||||
_sgr->resume(); // no-op if already in resumed state
|
||||
} else {
|
||||
_sgr->suspend();
|
||||
}
|
||||
#endif
|
||||
|
||||
if(_transmit) {
|
||||
_counter = 0.0;
|
||||
_max_count = 5.0; // FIXME - hardwired length of message - need to calculate it!
|
||||
|
@ -181,81 +329,6 @@ void FGATC::NotifyTransmissionFinished(const string& rid) {
|
|||
}
|
||||
}
|
||||
|
||||
void FGATC::SetStation(flightgear::CommStation* sta) {
|
||||
switch (sta->type()) {
|
||||
case FGPositioned::FREQ_ATIS: _type = ATIS; break;
|
||||
case FGPositioned::FREQ_AWOS: _type = AWOS; break;
|
||||
default:
|
||||
throw sg_exception("unsupported comm station type");
|
||||
}
|
||||
|
||||
_geod = sta->geod();
|
||||
_cart = sta->cart();
|
||||
range = sta->rangeNm();
|
||||
ident = sta->airport()->ident();
|
||||
name = sta->airport()->name();
|
||||
freq = sta->freqKHz();
|
||||
}
|
||||
|
||||
// Render a transmission
|
||||
// Outputs the transmission either on screen or as audio depending on user preference
|
||||
// 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.
|
||||
void FGATC::Render(string& msg, const float volume,
|
||||
const string& refname, const bool repeating) {
|
||||
if (volume < 0.05) return;
|
||||
|
||||
if (repeating)
|
||||
fgSetString("/sim/messages/atis", msg.c_str());
|
||||
else
|
||||
fgSetString("/sim/messages/atc", msg.c_str());
|
||||
|
||||
#ifdef ENABLE_AUDIO_SUPPORT
|
||||
_voice = (_voiceOK && fgGetBool("/sim/sound/voice"));
|
||||
if(_voice) {
|
||||
size_t len;
|
||||
void* buf = _vPtr->WriteMessage((char*)msg.c_str(), &len);
|
||||
if(buf) {
|
||||
NoRender(refname);
|
||||
try {
|
||||
// >>> Beware: must pass a (new) object to the (add) method,
|
||||
// >>> because the (remove) method is going to do a (delete)
|
||||
// >>> whether that's what you want or not.
|
||||
SGSoundSample *simple = new SGSoundSample(&buf, len, 8000);
|
||||
simple->set_volume(volume);
|
||||
_sgr->add(simple, refname);
|
||||
_sgr->play(refname, repeating);
|
||||
} catch ( sg_io_exception &e ) {
|
||||
SG_LOG(SG_ATC, SG_ALERT, e.getFormattedMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_AUDIO_SUPPORT
|
||||
if(!_voice) {
|
||||
// first rip the underscores and the pause hints out of the string - these are for the convienience 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.
|
||||
void FGATC::NoRender(const string& refname) {
|
||||
if(_playing) {
|
||||
if(_voice) {
|
||||
#ifdef ENABLE_AUDIO_SUPPORT
|
||||
_sgr->stop(refname);
|
||||
_sgr->remove(refname);
|
||||
#endif
|
||||
}
|
||||
_playing = false;
|
||||
}
|
||||
}
|
||||
|
||||
// Generate the text of a message from its parameters and the current context.
|
||||
string FGATC::GenText(const string& m, int c) {
|
||||
return("");
|
||||
|
@ -332,4 +405,4 @@ std::istream& operator >> ( std::istream& fin, ATCData& a )
|
|||
a.cart = SGVec3d::fromGeod(a.geod);
|
||||
return fin >> skipeol;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -42,20 +42,6 @@ namespace flightgear
|
|||
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.
|
||||
// INVALID implies not tuned in to anything.
|
||||
enum atc_type {
|
||||
|
@ -69,6 +55,7 @@ enum atc_type {
|
|||
INVALID /* must be last element; see ATC_NUM_TYPES */
|
||||
};
|
||||
|
||||
#ifdef OLD_ATC_MGR
|
||||
const int ATC_NUM_TYPES = 1 + INVALID;
|
||||
|
||||
// DCL - new experimental ATC data store
|
||||
|
@ -98,9 +85,10 @@ struct RunwayDetails {
|
|||
};
|
||||
|
||||
std::ostream& operator << (std::ostream& os, atc_type atc);
|
||||
#endif
|
||||
|
||||
class FGATC {
|
||||
friend class FGATCMgr;
|
||||
friend class FGATISMgr;
|
||||
public:
|
||||
|
||||
FGATC();
|
||||
|
@ -113,15 +101,16 @@ public:
|
|||
// wish to use the response timer functionality.
|
||||
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
|
||||
inline void SetDisplay() { _display = true; }
|
||||
|
||||
// Indicate that this instance should not output to the display
|
||||
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.
|
||||
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.
|
||||
// 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
|
||||
inline atc_type GetType() { return _type; }
|
||||
|
||||
// Set the core ATC data
|
||||
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 void set_ident(const std::string& id) { ident = id; }
|
||||
inline const std::string& get_name() { return name; }
|
||||
|
@ -169,25 +161,26 @@ protected:
|
|||
// Requires the sound manager refname if audio, else "".
|
||||
void NoRender(const std::string& refname);
|
||||
|
||||
virtual FGATCVoice* GetVoicePointer() = 0;
|
||||
|
||||
SGGeod _geod;
|
||||
SGVec3d _cart;
|
||||
int freq;
|
||||
std::map<std::string,int> active_on;
|
||||
flightgear::CommStation* _currentStation;
|
||||
|
||||
int range;
|
||||
std::string ident; // Code of the airport its at.
|
||||
std::string name; // Name transmitted in the broadcast.
|
||||
|
||||
std::string _currentMsg; // Current message being transmitted
|
||||
|
||||
// Rendering related stuff
|
||||
bool _voice; // Flag - true if we are using voice
|
||||
bool _playing; // Indicates a message in progress
|
||||
bool _voiceOK; // Flag - true if at least one voice has loaded OK
|
||||
FGATCVoice* _vPtr;
|
||||
|
||||
SGSharedPtr<SGSampleGroup> _sgr; // default sample group;
|
||||
|
||||
|
||||
#ifdef OLD_ATC_MGR
|
||||
bool freqClear; // Flag to indicate if the frequency is clear of ongoing dialog
|
||||
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
|
||||
double _releaseTime;
|
||||
double _releaseCounter;
|
||||
std::string pending_transmission; // derived classes set this string before calling Transmit(...)
|
||||
#endif
|
||||
atc_type _type;
|
||||
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:
|
||||
|
||||
#ifdef OLD_ATC_MGR
|
||||
// Transmission timing stuff.
|
||||
double _timeout;
|
||||
bool _pending;
|
||||
|
@ -216,13 +212,16 @@ private:
|
|||
bool _transmitting; // we are transmitting
|
||||
double _counter;
|
||||
double _max_count;
|
||||
#endif
|
||||
|
||||
SGPropertyNode_ptr _volume;
|
||||
SGPropertyNode_ptr _masterVolume;
|
||||
SGPropertyNode_ptr _enabled;
|
||||
SGPropertyNode_ptr _atc_external;
|
||||
SGPropertyNode_ptr _internal;
|
||||
};
|
||||
|
||||
#ifdef OLD_ATC_MGR
|
||||
std::istream& operator>> ( std::istream& fin, ATCData& a );
|
||||
#endif
|
||||
|
||||
#endif // _FG_ATC_HXX
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -23,8 +23,8 @@
|
|||
#endif
|
||||
|
||||
#include <sstream>
|
||||
#include <cstdlib>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <Airports/simple.hxx>
|
||||
#include <Airports/runways.hxx>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
using std::string;
|
||||
|
|
208
src/ATCDCL/ATISmgr.cxx
Normal file
208
src/ATCDCL/ATISmgr.cxx
Normal 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);
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
// ATCMgr.hxx - definition of FGATCMgr
|
||||
// - a global management class for FlightGear generated ATC
|
||||
// ATISmgr.hxx - definition of FGATISMgr
|
||||
// - a global management class for FlightGear generated ATIS
|
||||
//
|
||||
// Written by David Luff, started February 2002.
|
||||
//
|
||||
|
@ -30,23 +30,26 @@
|
|||
|
||||
#include "ATC.hxx"
|
||||
|
||||
class FGATCMgr : public SGSubsystem
|
||||
namespace flightgear
|
||||
{
|
||||
class CommStation;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SGPropertyNode_ptr freq;
|
||||
FGATC* station;
|
||||
} CommRadioData;
|
||||
|
||||
class FGATISMgr : public SGSubsystem
|
||||
{
|
||||
|
||||
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
|
||||
|
||||
// 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
|
||||
// Any member function of FGATISMgr is permitted to leave this iterator pointing
|
||||
// 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.
|
||||
|
||||
|
@ -58,19 +61,18 @@ private:
|
|||
SGPropertyNode_ptr lat_node;
|
||||
SGPropertyNode_ptr elev_node;
|
||||
|
||||
//FGATIS atis;
|
||||
unsigned int _currentUnit;
|
||||
unsigned int _maxCommRadios;
|
||||
|
||||
// Voice related stuff
|
||||
bool voice; // Flag - true if we are using voice
|
||||
#ifdef ENABLE_AUDIO_SUPPORT
|
||||
bool voiceOK; // Flag - true if at least one voice has loaded OK
|
||||
FGATCVoice* v1;
|
||||
FGATCVoice* voice1;
|
||||
#endif
|
||||
|
||||
public:
|
||||
|
||||
FGATCMgr();
|
||||
~FGATCMgr();
|
||||
FGATISMgr();
|
||||
~FGATISMgr();
|
||||
|
||||
void init();
|
||||
|
||||
|
@ -80,9 +82,8 @@ public:
|
|||
|
||||
void update(double dt);
|
||||
|
||||
|
||||
// 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.
|
||||
//
|
||||
// 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.
|
||||
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:
|
||||
|
||||
// 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.
|
||||
void FreqSearch(const std::string navcomm, const int unit);
|
||||
void FreqSearch(const unsigned int unit);
|
||||
};
|
||||
|
||||
#endif // _FG_ATCMGR_HXX
|
|
@ -3,9 +3,8 @@ include(FlightGearComponent)
|
|||
set(SOURCES
|
||||
ATC.cxx
|
||||
atis.cxx
|
||||
ATCDialogOld.cxx
|
||||
ATCVoice.cxx
|
||||
ATCmgr.cxx
|
||||
ATISmgr.cxx
|
||||
ATCutils.cxx
|
||||
ATCProjection.cxx
|
||||
)
|
||||
|
@ -13,9 +12,8 @@ set(SOURCES
|
|||
set(HEADERS
|
||||
ATC.hxx
|
||||
atis.hxx
|
||||
ATCDialogOld.hxx
|
||||
ATCVoice.hxx
|
||||
ATCmgr.hxx
|
||||
ATISmgr.hxx
|
||||
ATCutils.hxx
|
||||
ATCProjection.hxx
|
||||
atis_lexicon.hxx
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
|
||||
|
||||
#include "ATCutils.hxx"
|
||||
#include "ATCmgr.hxx"
|
||||
#include "ATISmgr.hxx"
|
||||
|
||||
using std::string;
|
||||
using std::map;
|
||||
|
@ -66,7 +66,7 @@ using std::cout;
|
|||
using boost::ref;
|
||||
using boost::tie;
|
||||
|
||||
FGATIS::FGATIS() :
|
||||
FGATIS::FGATIS(const string& commbase) :
|
||||
transmission(""),
|
||||
trans_ident(""),
|
||||
old_volume(0),
|
||||
|
@ -74,20 +74,8 @@ FGATIS::FGATIS() :
|
|||
msg_OK(0),
|
||||
attention(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);
|
||||
|
||||
///////////////
|
||||
|
@ -115,6 +103,18 @@ FGATIS::~FGATIS() {
|
|||
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() {
|
||||
// Nothing to see here. Move along.
|
||||
}
|
||||
|
@ -137,6 +137,7 @@ FGATIS::attend (int attn)
|
|||
void FGATIS::Update(double dt) {
|
||||
cur_time = globals->get_time_params()->get_cur_time();
|
||||
msg_OK = (msg_time < cur_time);
|
||||
|
||||
#ifdef ATIS_TEST
|
||||
if (msg_OK || _display != _prev_display) {
|
||||
cout << "ATIS Update: " << _display << " " << _prev_display
|
||||
|
@ -146,29 +147,27 @@ void FGATIS::Update(double dt) {
|
|||
msg_time = cur_time;
|
||||
}
|
||||
#endif
|
||||
if(_display) {
|
||||
double volume(0);
|
||||
for (map<string,int>::iterator act = active_on.begin();
|
||||
act != active_on.end(); act++) {
|
||||
string prop = "/instrumentation/" + act->first + "/volume";
|
||||
volume += globals->get_props()->getDoubleValue(prop.c_str());
|
||||
}
|
||||
|
||||
if(_display)
|
||||
{
|
||||
string prop = _commbase + "/volume";
|
||||
double volume = globals->get_props()->getDoubleValue(prop.c_str());
|
||||
|
||||
// Check if we need to update the message
|
||||
// - 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
|
||||
// "transmission" variable was lost when we were de-instantiated.
|
||||
int rslt = GenTransmission(!_prev_display, attention);
|
||||
int changed = GenTransmission(!_prev_display, attention);
|
||||
TreeOut(msg_OK);
|
||||
if (rslt || volume != old_volume) {
|
||||
if (changed || volume != old_volume) {
|
||||
//cout << "ATIS calling ATC::render volume: " << volume << endl;
|
||||
Render(transmission, volume, refname, true);
|
||||
Render(transmission, volume, _commbase, true);
|
||||
old_volume = volume;
|
||||
}
|
||||
} else {
|
||||
// We shouldn't be displaying
|
||||
//cout << "ATIS.CXX - calling NoRender()..." << endl;
|
||||
NoRender(refname);
|
||||
NoRender(_commbase);
|
||||
}
|
||||
_prev_display = _display;
|
||||
attention = 0;
|
||||
|
@ -517,26 +516,16 @@ int FGATIS::GenTransmission(const int regen, const int special) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Put the transmission into the property tree,
|
||||
// possibly in multiple places if multiple radios
|
||||
// are tuned to the same ATIS.
|
||||
// Put the transmission into the property tree.
|
||||
// You can see it by pointing a web browser
|
||||
// at the property tree. The second comm radio is:
|
||||
// http://localhost:5400/instrumentation/comm[1]
|
||||
//
|
||||
// (Also, if in debug mode, dump it to the console.)
|
||||
void FGATIS::TreeOut(int msg_OK){
|
||||
for (map<string,int>::iterator act = active_on.begin();
|
||||
act != active_on.end();
|
||||
act++){
|
||||
string prop = "/instrumentation/" + act->first + "/atis";
|
||||
string prop = _commbase + "/atis";
|
||||
globals->get_props()->setStringValue(prop.c_str(),
|
||||
("<pre>\n" + transmission_readable + "</pre>\n").c_str());
|
||||
#ifdef ATIS_TEST
|
||||
if (msg_OK) cout << "**** ATIS active on: " << prop << endl;
|
||||
#endif
|
||||
}
|
||||
#ifdef ATIS_TEST
|
||||
if (msg_OK) cout << transmission_readable << endl;
|
||||
#endif
|
||||
SG_LOG(SG_ATC, SG_DEBUG, "**** ATIS active on: " << prop <<
|
||||
"transmission: " << transmission_readable);
|
||||
}
|
||||
|
|
|
@ -60,6 +60,8 @@ class FGATIS : public FGATC {
|
|||
bool _prev_display; // Previous value of _display flag
|
||||
MSS _remap; // abbreviations to be expanded
|
||||
|
||||
std::string _commbase;
|
||||
|
||||
// Aircraft position
|
||||
// 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
|
||||
|
@ -69,9 +71,9 @@ class FGATIS : public FGATC {
|
|||
//SGPropertyNode_ptr airplane_lat_node;
|
||||
//SGPropertyNode_ptr airplane_elev_node;
|
||||
|
||||
public:
|
||||
public:
|
||||
|
||||
FGATIS(void);
|
||||
FGATIS(const std::string& commbase);
|
||||
~FGATIS(void);
|
||||
virtual void Init();
|
||||
void attend (int);
|
||||
|
@ -81,11 +83,11 @@ class FGATIS : public FGATC {
|
|||
|
||||
//inline void set_type(const atc_type tp) {type = tp;}
|
||||
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:
|
||||
int GenTransmission(const int regen, const int special);
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
@ -33,6 +33,7 @@
|
|||
#include <simgear/misc/ResourceManager.hxx>
|
||||
#include <simgear/misc/strutils.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
#include "flightrecorder.hxx"
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
// Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <Airports/runways.hxx>
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include <osg/Shape>
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
#include <simgear/scene/material/EffectGeode.hxx>
|
||||
#include <simgear/scene/material/matlib.hxx>
|
||||
#include <simgear/scene/material/mat.hxx>
|
||||
|
@ -531,7 +530,7 @@ FGTaxiNode *FGGroundNetwork::findNode(unsigned idx)
|
|||
return itr->getAddress();
|
||||
} */
|
||||
|
||||
if ((idx >= 0) && (idx < nodes.size()))
|
||||
if (idx < nodes.size())
|
||||
return nodes[idx]->getAddress();
|
||||
else
|
||||
return 0;
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
|
|
@ -172,7 +172,7 @@ void FGRunway::setReciprocalRunway(FGRunway* other)
|
|||
_reciprocal = other;
|
||||
}
|
||||
|
||||
std::vector<flightgear::SID*> FGRunway::getSIDs()
|
||||
std::vector<flightgear::SID*> FGRunway::getSIDs() const
|
||||
{
|
||||
std::vector<flightgear::SID*> result;
|
||||
for (unsigned int i=0; i<_airport->numSIDs(); ++i) {
|
||||
|
@ -185,7 +185,7 @@ std::vector<flightgear::SID*> FGRunway::getSIDs()
|
|||
return result;
|
||||
}
|
||||
|
||||
std::vector<flightgear::STAR*> FGRunway::getSTARs()
|
||||
std::vector<flightgear::STAR*> FGRunway::getSTARs() const
|
||||
{
|
||||
std::vector<flightgear::STAR*> result;
|
||||
for (unsigned int i=0; i<_airport->numSTARs(); ++i) {
|
||||
|
@ -198,3 +198,16 @@ std::vector<flightgear::STAR*> FGRunway::getSTARs()
|
|||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ class SGPropertyNode;
|
|||
namespace flightgear {
|
||||
class SID;
|
||||
class STAR;
|
||||
class Approach;
|
||||
}
|
||||
|
||||
class FGRunway : public FGRunwayBase
|
||||
|
@ -124,12 +125,15 @@ public:
|
|||
/**
|
||||
* Get SIDs (DPs) associated with this runway
|
||||
*/
|
||||
std::vector<flightgear::SID*> getSIDs();
|
||||
std::vector<flightgear::SID*> getSIDs() const;
|
||||
|
||||
/**
|
||||
* Get STARs associared with this runway
|
||||
*/
|
||||
std::vector<flightgear::STAR*> getSTARs();
|
||||
std::vector<flightgear::STAR*> getSTARs() const;
|
||||
|
||||
|
||||
std::vector<flightgear::Approach*> getApproaches() const;
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -329,6 +329,9 @@ FGAirport* FGAirport::findClosest(const SGGeod& aPos, double aCuttofNm, Filter*
|
|||
FGAirport::HardSurfaceFilter::HardSurfaceFilter(double minLengthFt) :
|
||||
mMinLengthFt(minLengthFt)
|
||||
{
|
||||
if (minLengthFt < 0.0) {
|
||||
mMinLengthFt = fgGetDouble("/sim/navdb/min-runway-length-ft", 0.0);
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
Route::loadAirportProcedures(path, const_cast<FGAirport*>(this));
|
||||
RouteBase::loadAirportProcedures(path, const_cast<FGAirport*>(this));
|
||||
}
|
||||
|
||||
void FGAirport::loadSceneryDefinitions() const
|
||||
|
@ -469,128 +472,6 @@ void FGAirport::readTowerData(SGPropertyNode* aRoot)
|
|||
_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)
|
||||
{
|
||||
mSIDs.push_back(aSid);
|
||||
|
@ -666,6 +547,18 @@ Approach* FGAirport::getApproachByIndex(unsigned int aIndex) const
|
|||
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)
|
||||
{
|
||||
mCommStations.swap(comms);
|
||||
|
|
|
@ -161,7 +161,7 @@ public:
|
|||
class HardSurfaceFilter : public AirportFilter
|
||||
{
|
||||
public:
|
||||
HardSurfaceFilter(double minLengthFt);
|
||||
HardSurfaceFilter(double minLengthFt = -1);
|
||||
|
||||
virtual bool passAirport(FGAirport* aApt) const;
|
||||
|
||||
|
@ -188,6 +188,7 @@ public:
|
|||
|
||||
unsigned int numApproaches() const;
|
||||
flightgear::Approach* getApproachByIndex(unsigned int aIndex) const;
|
||||
flightgear::Approach* findApproachWithIdent(const std::string& aIdent) const;
|
||||
|
||||
/**
|
||||
* Syntactic wrapper around FGPositioned::findClosest - find the closest
|
||||
|
@ -216,22 +217,6 @@ public:
|
|||
*/
|
||||
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);
|
||||
|
||||
flightgear::CommStationList commStationsOfType(FGPositioned::Type aTy) const;
|
||||
|
|
|
@ -18,8 +18,11 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include "inputvalue.hxx"
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
using namespace FGXMLAutopilot;
|
||||
|
||||
PeriodicalValue::PeriodicalValue( SGPropertyNode_ptr root )
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#ifndef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#endif
|
||||
|
||||
#include "logic.hxx"
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -25,26 +25,21 @@
|
|||
#define _ROUTE_MGR_HXX 1
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
|
||||
#include <Navaids/route.hxx>
|
||||
#include <Navaids/FlightPlan.hxx>
|
||||
|
||||
// forward decls
|
||||
class SGPath;
|
||||
class PropertyWatcher;
|
||||
|
||||
class FGAirport;
|
||||
class FGRunway;
|
||||
|
||||
typedef SGSharedPtr<FGAirport> FGAirportRef;
|
||||
|
||||
/**
|
||||
* Top level route manager class
|
||||
*
|
||||
*/
|
||||
|
||||
class FGRouteMgr : public SGSubsystem
|
||||
class FGRouteMgr : public SGSubsystem,
|
||||
public flightgear::FlightPlan::Delegate
|
||||
{
|
||||
public:
|
||||
FGRouteMgr();
|
||||
|
@ -56,51 +51,29 @@ public:
|
|||
void unbind ();
|
||||
void update (double dt);
|
||||
|
||||
void insertWayptAtIndex(flightgear::Waypt* aWpt, int aIndex);
|
||||
flightgear::WayptRef removeWayptAtIndex(int index);
|
||||
bool isRouteActive() const;
|
||||
|
||||
int currentIndex() const;
|
||||
|
||||
void setFlightPlan(flightgear::FlightPlan* plan);
|
||||
flightgear::FlightPlan* flightPlan() const;
|
||||
|
||||
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* nextWaypt() const;
|
||||
flightgear::Waypt* previousWaypt() const;
|
||||
|
||||
const flightgear::WayptVec& waypts() const
|
||||
{ return _route; }
|
||||
int numLegs() const;
|
||||
|
||||
// deprecated
|
||||
int numWaypts() const
|
||||
{ return _route.size(); }
|
||||
{ return numLegs(); }
|
||||
|
||||
// deprecated
|
||||
flightgear::Waypt* wayptAtIndex(int index) const;
|
||||
|
||||
SGPropertyNode_ptr wayptNodeAtIndex(int index) const;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
void removeLegAtIndex(int aIndex);
|
||||
|
||||
/**
|
||||
* Activate a built route. This checks for various mandatory pieces of
|
||||
|
@ -125,38 +98,20 @@ public:
|
|||
bool saveRoute(const SGPath& p);
|
||||
bool loadRoute(const SGPath& p);
|
||||
|
||||
flightgear::WayptRef waypointFromString(const std::string& target);
|
||||
|
||||
/**
|
||||
* Helper command to setup current airport/runway if necessary
|
||||
*/
|
||||
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:
|
||||
flightgear::WayptVec _route;
|
||||
int _currentIndex;
|
||||
flightgear::FlightPlan* _plan;
|
||||
|
||||
time_t _takeoffTime;
|
||||
time_t _touchdownTime;
|
||||
FGAirportRef _departure;
|
||||
FGAirportRef _destination;
|
||||
|
||||
// automatic inputs
|
||||
SGPropertyNode_ptr lon;
|
||||
SGPropertyNode_ptr lat;
|
||||
SGPropertyNode_ptr alt;
|
||||
SGPropertyNode_ptr magvar;
|
||||
|
||||
// automatic outputs
|
||||
|
@ -181,8 +136,6 @@ private:
|
|||
SGPropertyNode_ptr _pathNode;
|
||||
SGPropertyNode_ptr _currentWpt;
|
||||
|
||||
/// integer property corresponding to the RouteType enum
|
||||
SGPropertyNode_ptr _routingType;
|
||||
|
||||
/**
|
||||
* Signal property to notify people that the route was edited
|
||||
|
@ -194,6 +147,8 @@ private:
|
|||
*/
|
||||
SGPropertyNode_ptr _finished;
|
||||
|
||||
SGPropertyNode_ptr _flightplanChanged;
|
||||
|
||||
void setETAPropertyFromDistance(SGPropertyNode_ptr aProp, double aDistance);
|
||||
|
||||
/**
|
||||
|
@ -212,31 +167,21 @@ private:
|
|||
|
||||
SGPropertyNode_ptr input;
|
||||
SGPropertyNode_ptr weightOnWheels;
|
||||
SGPropertyNode_ptr groundSpeed;
|
||||
|
||||
InputListener *listener;
|
||||
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
|
||||
* modified (waypoints added, inserted, removed). Notably, this fires the
|
||||
* 'edited' signal.
|
||||
*/
|
||||
void waypointsChanged();
|
||||
virtual void waypointsChanged();
|
||||
|
||||
void update_mirror();
|
||||
|
||||
void currentWaypointChanged();
|
||||
|
||||
/**
|
||||
* Parse a route/wp node (from a saved, property-lsit formatted route)
|
||||
*/
|
||||
void parseRouteWaypoint(SGPropertyNode* aWP);
|
||||
virtual void currentWaypointChanged();
|
||||
|
||||
/**
|
||||
* Check if we've reached the final waypoint.
|
||||
|
@ -244,14 +189,6 @@ private:
|
|||
*/
|
||||
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
|
||||
* entered by the user (as opposed to being generated by the route-manager)
|
||||
|
@ -263,12 +200,27 @@ private:
|
|||
const char* getDepartureName() const;
|
||||
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* getDestinationName() const;
|
||||
void setDestinationICAO(const char* aIdent);
|
||||
|
||||
PropertyWatcher* _departureWatcher;
|
||||
PropertyWatcher* _arrivalWatcher;
|
||||
const char* getDestinationRunway() const;
|
||||
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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ foreach( mylibfolder
|
|||
Aircraft
|
||||
ATC
|
||||
ATCDCL
|
||||
Canvas
|
||||
Radio
|
||||
Autopilot
|
||||
Cockpit
|
||||
|
|
19
src/Canvas/CMakeLists.txt
Normal file
19
src/Canvas/CMakeLists.txt
Normal 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
430
src/Canvas/canvas.cxx
Normal 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
101
src/Canvas/canvas.hxx
Normal 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
144
src/Canvas/canvas_mgr.cxx
Normal 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
76
src/Canvas/canvas_mgr.hxx
Normal 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_ */
|
266
src/Canvas/elements/element.cxx
Normal file
266
src/Canvas/elements/element.cxx
Normal 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
|
107
src/Canvas/elements/element.hxx
Normal file
107
src/Canvas/elements/element.hxx
Normal 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_ */
|
65
src/Canvas/elements/group.cxx
Normal file
65
src/Canvas/elements/group.cxx
Normal 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
|
47
src/Canvas/elements/group.hxx
Normal file
47
src/Canvas/elements/group.hxx
Normal 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_ */
|
41
src/Canvas/elements/text-alignment.hxx
Normal file
41
src/Canvas/elements/text-alignment.hxx
Normal 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")
|
184
src/Canvas/elements/text.cxx
Normal file
184
src/Canvas/elements/text.cxx
Normal 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
|
56
src/Canvas/elements/text.hxx
Normal file
56
src/Canvas/elements/text.hxx
Normal 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_ */
|
|
@ -93,28 +93,6 @@ get_aspect_adjust (int xsize, int ysize)
|
|||
float real_aspect = float(xsize) / float(ysize);
|
||||
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.
|
||||
|
@ -201,8 +179,6 @@ FGPanel::FGPanel ()
|
|||
: _mouseDown(false),
|
||||
_mouseInstrument(0),
|
||||
_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)),
|
||||
_y_offset(fgGetNode("/sim/panel/y-offset", true)),
|
||||
_jitter(fgGetNode("/sim/panel/jitter", true)),
|
||||
|
@ -210,6 +186,7 @@ FGPanel::FGPanel ()
|
|||
_xsize_node(fgGetNode("/sim/startup/xsize", true)),
|
||||
_ysize_node(fgGetNode("/sim/startup/ysize", true)),
|
||||
_enable_depth_test(false),
|
||||
_autohide(true),
|
||||
_drawPanelHotspots("/sim/panel-hotspots")
|
||||
{
|
||||
}
|
||||
|
@ -238,44 +215,6 @@ FGPanel::addInstrument (FGPanelInstrument * 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
|
||||
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.
|
||||
*/
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/props/propertyObject.hxx>
|
||||
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/structure/SGBinding.hxx>
|
||||
#include <simgear/math/interpolater.hxx>
|
||||
#include <simgear/timing/timestamp.hxx>
|
||||
|
@ -118,22 +117,14 @@ private:
|
|||
* redraw themselves when necessary, and will pass mouse clicks on to
|
||||
* the appropriate instruments for processing.
|
||||
*/
|
||||
class FGPanel : public SGSubsystem
|
||||
class FGPanel : public SGReferenced
|
||||
{
|
||||
public:
|
||||
|
||||
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 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);
|
||||
|
||||
|
@ -146,11 +137,6 @@ public:
|
|||
// Background multiple textures.
|
||||
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 int getWidth () const { return _width; }
|
||||
|
||||
|
@ -201,7 +187,6 @@ private:
|
|||
int _height;
|
||||
// int _view_height;
|
||||
|
||||
SGPropertyNode_ptr _visibility;
|
||||
SGPropertyNode_ptr _x_offset;
|
||||
SGPropertyNode_ptr _y_offset;
|
||||
SGPropertyNode_ptr _jitter;
|
||||
|
@ -584,22 +569,7 @@ public:
|
|||
FGSwitchLayer ();
|
||||
virtual void draw (osg::State& state);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Functions.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Test whether the panel should be visible.
|
||||
*/
|
||||
bool fgPanelVisible ();
|
||||
|
||||
|
||||
|
||||
};
|
||||
#endif // __PANEL_HXX
|
||||
|
||||
// end of panel.hxx
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include <boost/tuple/tuple.hpp>
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <algorithm>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
#include "environment_ctrl.hxx"
|
||||
#include "environment.hxx"
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/props/tiedpropertylist.hxx>
|
||||
|
||||
#ifdef SG_HAVE_STD_INCLUDES
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <cmath>
|
||||
#include <simgear/math/SGMisc.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
namespace Environment {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// 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 $
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
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
|
||||
--------------------------------------------------------------------------------
|
||||
|
|
0
src/FDM/JSBSim/input_output/FGScript.cpp
Executable file → Normal file
0
src/FDM/JSBSim/input_output/FGScript.cpp
Executable file → Normal file
0
src/FDM/JSBSim/models/FGAuxiliary.cpp
Executable file → Normal file
0
src/FDM/JSBSim/models/FGAuxiliary.cpp
Executable file → Normal file
0
src/FDM/JSBSim/models/FGExternalForce.cpp
Executable file → Normal file
0
src/FDM/JSBSim/models/FGExternalForce.cpp
Executable file → Normal file
0
src/FDM/JSBSim/models/FGExternalForce.h
Executable file → Normal file
0
src/FDM/JSBSim/models/FGExternalForce.h
Executable file → Normal file
0
src/FDM/JSBSim/models/FGExternalReactions.h
Executable file → Normal file
0
src/FDM/JSBSim/models/FGExternalReactions.h
Executable file → Normal file
0
src/FDM/JSBSim/models/flight_control/FGFCSFunction.h
Executable file → Normal file
0
src/FDM/JSBSim/models/flight_control/FGFCSFunction.h
Executable file → Normal file
0
src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
Executable file → Normal file
0
src/FDM/JSBSim/models/propulsion/FGTurboProp.cpp
Executable file → Normal file
|
@ -3,6 +3,8 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/math/sg_geodesy.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
|
|
@ -5,8 +5,6 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
#include "Math.hpp"
|
||||
#include "FGFDM.hpp"
|
||||
#include "PropEngine.hpp"
|
||||
|
|
|
@ -10,8 +10,6 @@
|
|||
#include "Atmosphere.hpp"
|
||||
#include "Airplane.hpp"
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
using namespace yasim;
|
||||
|
||||
// Stubs. Not needed by a batch program, but required to link.
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/timing/timestamp.hxx>
|
||||
|
||||
#include <Scenery/scenery.hxx>
|
||||
|
|
|
@ -62,4 +62,9 @@ private:
|
|||
|
||||
};
|
||||
|
||||
/**
|
||||
* open a URL using the system's web-browser
|
||||
*/
|
||||
void cocoaOpenUrl(const std::string& url);
|
||||
|
||||
#endif // __MENUBAR_HXX
|
||||
|
|
|
@ -110,6 +110,23 @@ static void setItemShortcutFromString(NSMenuItem* item, const string& s)
|
|||
}
|
||||
|
||||
namespace {
|
||||
class CocoaAutoreleasePool
|
||||
{
|
||||
public:
|
||||
CocoaAutoreleasePool()
|
||||
{
|
||||
pool = [[NSAutoreleasePool alloc] init];
|
||||
}
|
||||
|
||||
~CocoaAutoreleasePool()
|
||||
{
|
||||
[pool release];
|
||||
}
|
||||
|
||||
private:
|
||||
NSAutoreleasePool* pool;
|
||||
};
|
||||
|
||||
class CocoaEnabledListener : public SGPropertyChangeListener
|
||||
{
|
||||
public:
|
||||
|
@ -120,6 +137,7 @@ namespace {
|
|||
|
||||
virtual void valueChanged(SGPropertyNode *node)
|
||||
{
|
||||
CocoaAutoreleasePool pool;
|
||||
BOOL b = node->getBoolValue();
|
||||
[item setEnabled:b];
|
||||
}
|
||||
|
@ -137,6 +155,7 @@ FGCocoaMenuBar::CocoaMenuBarPrivate::CocoaMenuBarPrivate()
|
|||
|
||||
FGCocoaMenuBar::CocoaMenuBarPrivate::~CocoaMenuBarPrivate()
|
||||
{
|
||||
CocoaAutoreleasePool pool;
|
||||
[delegate release];
|
||||
}
|
||||
|
||||
|
@ -153,16 +172,9 @@ void FGCocoaMenuBar::CocoaMenuBarPrivate::menuFromProps(NSMenu* menu, SGProperty
|
|||
n->setBoolValue("enabled", true);
|
||||
}
|
||||
|
||||
string shortcut;
|
||||
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));
|
||||
}
|
||||
|
||||
string l = getLocalizedLabel(n);
|
||||
NSString* label = stdStringToCocoa(strutils::simplify(l));
|
||||
string shortcut = n->getStringValue("key");
|
||||
|
||||
NSMenuItem* item;
|
||||
if (index >= [menu numberOfItems]) {
|
||||
|
@ -227,6 +239,8 @@ FGCocoaMenuBar::~FGCocoaMenuBar()
|
|||
|
||||
void FGCocoaMenuBar::init()
|
||||
{
|
||||
CocoaAutoreleasePool pool;
|
||||
|
||||
NSMenu* mainBar = [[NSApplication sharedApplication] mainMenu];
|
||||
SGPropertyNode_ptr props = fgGetNode("/sim/menubar/default",true);
|
||||
|
||||
|
@ -237,7 +251,7 @@ void FGCocoaMenuBar::init()
|
|||
}
|
||||
|
||||
BOOST_FOREACH(SGPropertyNode_ptr n, props->getChildren("menu")) {
|
||||
NSString* label = stdStringToCocoa(n->getStringValue("label"));
|
||||
NSString* label = stdStringToCocoa(getLocalizedLabel(n));
|
||||
NSMenuItem* item = [mainBar itemWithTitle:label];
|
||||
NSMenu* menu;
|
||||
|
||||
|
@ -283,3 +297,10 @@ void FGCocoaMenuBar::hide()
|
|||
{
|
||||
// no-op
|
||||
}
|
||||
|
||||
void cocoaOpenUrl(const std::string& url)
|
||||
{
|
||||
CocoaAutoreleasePool pool;
|
||||
NSURL* nsu = [NSURL URLWithString:stdStringToCocoa(url)];
|
||||
[[NSWorkspace sharedWorkspace] openURL:nsu];
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
#include <iostream>
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// FGColor class.
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
#ifndef __FGFONTCACHE_HXX
|
||||
#define __FGFONTCACHE_HXX
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#include <map>
|
||||
|
|
|
@ -8,8 +8,6 @@
|
|||
#include <algorithm> // for std::sort
|
||||
#include <plib/puAux.h>
|
||||
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <simgear/misc/strutils.hxx>
|
||||
#include <simgear/magvar/magvar.hxx>
|
||||
|
@ -682,7 +680,7 @@ void MapWidget::paintRoute()
|
|||
return;
|
||||
}
|
||||
|
||||
RoutePath path(_route->waypts());
|
||||
RoutePath path(_route->flightPlan());
|
||||
|
||||
// first pass, draw the actual lines
|
||||
glLineWidth(2.0);
|
||||
|
@ -889,7 +887,7 @@ public:
|
|||
{
|
||||
_heliports = nd->getBoolValue("show-heliports", false);
|
||||
_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 {
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
|
||||
#include <plib/puAux.h>
|
||||
|
||||
#include <simgear/route/waypoint.hxx>
|
||||
#include <simgear/structure/callback.hxx>
|
||||
#include <simgear/sg_inlines.h>
|
||||
|
||||
|
@ -37,34 +36,37 @@ enum {
|
|||
static const double BLINK_TIME = 0.3;
|
||||
static const int DRAG_START_DISTANCE_PX = 5;
|
||||
|
||||
class RouteManagerWaypointModel :
|
||||
class FlightPlanWaypointModel :
|
||||
public WaypointList::Model,
|
||||
public SGPropertyChangeListener
|
||||
{
|
||||
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* flightplanChanged = fgGetNode("/autopilot/route-manager/signals/flightplan-changed", true);
|
||||
routeEdited->addChangeListener(this);
|
||||
flightplanChanged->addChangeListener(this);
|
||||
}
|
||||
|
||||
virtual ~RouteManagerWaypointModel()
|
||||
~FlightPlanWaypointModel()
|
||||
{
|
||||
SGPropertyNode* routeEdited = fgGetNode("/autopilot/route-manager/signals/edited", true);
|
||||
SGPropertyNode* flightplanChanged = fgGetNode("/autopilot/route-manager/signals/flightplan-changed", true);
|
||||
routeEdited->removeChangeListener(this);
|
||||
flightplanChanged->removeChangeListener(this);
|
||||
}
|
||||
|
||||
// implement WaypointList::Model
|
||||
virtual unsigned int numWaypoints() const
|
||||
{
|
||||
return _rm->numWaypts();
|
||||
return _fp->numLegs();
|
||||
}
|
||||
|
||||
virtual int currentWaypoint() const
|
||||
{
|
||||
return _rm->currentIndex();
|
||||
return _fp->currentIndex();
|
||||
}
|
||||
|
||||
virtual flightgear::Waypt* waypointAt(unsigned int index) const
|
||||
|
@ -73,12 +75,12 @@ public:
|
|||
return NULL;
|
||||
}
|
||||
|
||||
return _rm->wayptAtIndex(index);
|
||||
return _fp->legAtIndex(index)->waypoint();
|
||||
}
|
||||
|
||||
virtual void deleteAt(unsigned int index)
|
||||
{
|
||||
_rm->removeWayptAtIndex(index);
|
||||
_fp->deleteIndex(index);
|
||||
}
|
||||
|
||||
virtual void moveWaypointToIndex(unsigned int srcIndex, unsigned int destIndex)
|
||||
|
@ -89,13 +91,15 @@ public:
|
|||
}
|
||||
|
||||
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());
|
||||
_rm->insertWayptAtIndex(w, destIndex);
|
||||
_fp->insertWayptAtIndex(w, destIndex);
|
||||
|
||||
if (srcIndex == currentWpIndex) {
|
||||
// current waypoint was moved
|
||||
_rm->jumpToIndex(destIndex);
|
||||
_fp->setCurrentIndex(destIndex);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,12 +111,19 @@ public:
|
|||
// implement SGPropertyChangeListener
|
||||
void valueChanged(SGPropertyNode *prop)
|
||||
{
|
||||
if (prop->getNameString() == "edited") {
|
||||
if (_cb) {
|
||||
(*_cb)();
|
||||
}
|
||||
}
|
||||
|
||||
if (prop->getNameString() == "flightplan-changed") {
|
||||
_fp =
|
||||
static_cast<FGRouteMgr*>(globals->get_subsystem("route-manager"))->flightPlan();
|
||||
}
|
||||
}
|
||||
private:
|
||||
FGRouteMgr* _rm;
|
||||
flightgear::FlightPlan* _fp;
|
||||
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
|
||||
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);
|
||||
setValue(-1);
|
||||
|
||||
|
@ -399,12 +412,12 @@ void WaypointList::drawRow(int dx, int dy, int rowIndex, int y)
|
|||
if (wp->flag(WPT_MISS)) {
|
||||
drawBox = true;
|
||||
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;
|
||||
puSetColor(col, 0.0, 0.0, 0.0, 0.3);
|
||||
} else if (wp->flag(WPT_DEPARTURE)) {
|
||||
} else if (wp->flag(WPT_APPROACH)) {
|
||||
drawBox = true;
|
||||
puSetColor(col, 0.0, 0.0, 0.0, 0.3);
|
||||
puSetColor(col, 0.0, 0.0, 0.1, 0.3);
|
||||
}
|
||||
|
||||
if (isDragSource) {
|
||||
|
|
|
@ -837,4 +837,4 @@ static fntBitmapFont fntHelvetica12(FontHelvetica12.Characters, 1,
|
|||
|
||||
puFont FONT_HELVETICA_14(&fntHelvetica14, 14, 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 */
|
||||
|
|
|
@ -60,6 +60,10 @@
|
|||
# include <shellapi.h>
|
||||
#endif
|
||||
|
||||
#ifdef SG_MAC
|
||||
# include "FGCocoaMenuBar.hxx" // for cocoaOpenUrl
|
||||
#endif
|
||||
|
||||
#include "gui.h"
|
||||
|
||||
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
|
||||
|
||||
string command = globals->get_browser();
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
#include <plib/pu.h>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
#include "layout.hxx"
|
||||
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
|
||||
#include "layout.hxx"
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
// This file contains the actual layout engine. It has no dependence
|
||||
// on outside libraries; see layout-props.cxx for the glue code.
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include "menubar.hxx"
|
||||
#include <Main/locale.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
FGMenuBar::FGMenuBar()
|
||||
{
|
||||
|
|
|
@ -51,7 +51,7 @@ public:
|
|||
* Take care of mapping it to the appropriate translation, if available.
|
||||
* Returns an UTF-8 encoded string.
|
||||
*/
|
||||
const char* getLocalizedLabel(SGPropertyNode* node);
|
||||
static const char* getLocalizedLabel(SGPropertyNode* node);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -68,6 +68,8 @@ NewGUI::init ()
|
|||
setStyle();
|
||||
SGPath p(globals->get_fg_root(), "gui/dialogs");
|
||||
readDir(p);
|
||||
const std::string aircraft_dir(fgGetString("/sim/aircraft-dir"));
|
||||
readDir( SGPath(aircraft_dir, "gui/dialogs") );
|
||||
_menubar->init();
|
||||
}
|
||||
|
||||
|
|
|
@ -164,8 +164,6 @@
|
|||
|
||||
#define NOMINMAX 1
|
||||
|
||||
#define HAVE_CULLSETTINGS_CLEAR_MASK 1
|
||||
|
||||
#ifndef ENABLE_AUDIO_SUPPORT
|
||||
#define ENABLE_AUDIO_SUPPORT
|
||||
#endif
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
|
||||
#cmakedefine HAVE_SYS_TIME_H
|
||||
#cmakedefine HAVE_WINDOWS_H
|
||||
#cmakedefine HAVE_CULLSETTINGS_CLEAR_MASK
|
||||
#cmakedefine HAVE_MKFIFO
|
||||
|
||||
#define VERSION "@FLIGHTGEAR_VERSION@"
|
||||
|
|
|
@ -16,8 +16,8 @@
|
|||
//
|
||||
// You should have received a copy of the GNU Library General Public
|
||||
// License along with this library; if not, write to the
|
||||
// Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
// Boston, MA 02111-1307, USA.
|
||||
// Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
// Boston, MA 02110-1301, USA.
|
||||
//
|
||||
// $Id$
|
||||
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
|
||||
#include "FGButton.hxx"
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
FGButton::FGButton ()
|
||||
: is_repeatable(false),
|
||||
|
|
|
@ -30,8 +30,6 @@
|
|||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_os.hxx>
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
using simgear::PropertyList;
|
||||
using std::string;
|
||||
|
||||
|
|
|
@ -26,8 +26,6 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
#include "FGDeviceConfigurationMap.hxx"
|
||||
|
||||
#include <simgear/misc/sg_dir.hxx>
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue