Merge branch 'next' of git://gitorious.org/fg/flightgear into next
This commit is contained in:
commit
269595a366
101 changed files with 3643 additions and 3269 deletions
|
@ -41,7 +41,7 @@ set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMakeModules;${CMAKE_MODULE_PATH}")
|
|||
if (FG_DATA_DIR)
|
||||
message(STATUS "Using explicit data-dir: ${FG_DATA_DIR}")
|
||||
else()
|
||||
set(FG_DATA_DIR "${CMAKE_INSTALL_PREFIX}/lib/FlightGear")
|
||||
set(FG_DATA_DIR "${CMAKE_INSTALL_PREFIX}/lib/FlightGear" CACHE PATH "Default location where data files are located")
|
||||
message(STATUS "Using default data-dir: ${FG_DATA_DIR}")
|
||||
endif()
|
||||
|
||||
|
@ -94,7 +94,7 @@ option(EVENT_INPUT "Set to ON to build FlightGear with event-based Input support
|
|||
option(ENABLE_LIBSVN "Set to ON to build FlightGear/terrasync with libsvnclient support" ON)
|
||||
option(ENABLE_RTI "Set to ON to build SimGear with RTI support" OFF)
|
||||
option(WITH_FGPANEL "Set to ON to build the fgpanel application" ON)
|
||||
|
||||
option(JPEG_FACTORY "Enable JPEG-factory support" OFF)
|
||||
|
||||
if (MSVC)
|
||||
GET_FILENAME_COMPONENT(PARENT_DIR ${PROJECT_SOURCE_DIR} PATH)
|
||||
|
@ -191,6 +191,26 @@ endif(ENABLE_LIBSVN)
|
|||
find_package(PLIB REQUIRED puaux pu js fnt)
|
||||
find_package(SimGear 2.5.0 REQUIRED)
|
||||
|
||||
if (JPEG_FACTORY)
|
||||
# check simgear was built with JPEG-factory support
|
||||
find_package(JPEG REQUIRED)
|
||||
include_directories(${JPEG_INCLUDE_DIR})
|
||||
|
||||
set(CMAKE_REQUIRED_INCLUDES
|
||||
${SIMGEAR_INCLUDE_DIR}
|
||||
${JPEG_INCLUDE_DIR}
|
||||
${OPENSCENEGRAPH_INCLUDE_DIRS})
|
||||
|
||||
check_cxx_source_compiles(
|
||||
"#include <simgear/screen/jpgfactory.hxx>
|
||||
int main() { return 0; } "
|
||||
FG_JPEG_SERVER)
|
||||
|
||||
if (NOT FG_JPEG_SERVER)
|
||||
message(STATUS "JPEG server support requested, but SimGear was built without JPEG support")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
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)
|
||||
|
|
|
@ -3,11 +3,7 @@
|
|||
You *must* have OpenSceneGraph (OSG) installed to build this version of
|
||||
FlightGear.
|
||||
|
||||
Notice that from FlightGear version 1.9.0, OSG version 2.7.8 or later
|
||||
is required. Using earlier versions of OSG will yield serious
|
||||
rendering bugs. If you are using an 'older' distribution, this may mean
|
||||
a suitable version of OSG may not be availble through the usual package
|
||||
repositories.
|
||||
Notice that FlightGear 2.6.0 requires at least version 3.0.0.
|
||||
|
||||
You can get the latest version of OSG from:
|
||||
|
||||
|
|
72
README.cmake
72
README.cmake
|
@ -1,5 +1,7 @@
|
|||
Getting started with CMake
|
||||
|
||||
[Windows instructions at the end of this document]
|
||||
|
||||
(These instructions apply to Unix-like systems, including Cygwin and Mac. To
|
||||
build using Visual Studio or some other IDE supported by CMake, most of the
|
||||
information below still applies)
|
||||
|
@ -8,7 +10,7 @@ Always compile in a separate directory to the code. For example, if the
|
|||
code (eg, from Git) is at /home/curt/projects/flightgear, you might create
|
||||
/home/curt/projects/fgbuild. Change into the new directory, and run
|
||||
|
||||
cmake ../flightger
|
||||
cmake ../flightgear
|
||||
|
||||
To generate standard Unix Makefiles in fgbuild.
|
||||
|
||||
|
@ -153,3 +155,71 @@ If you add an additional line
|
|||
|
||||
Then running 'make test' will run your executable as a unit test. The
|
||||
executable should return either a success or failure result code.
|
||||
|
||||
|
||||
|
||||
SPECIAL INSTRUCTIONS TO BUILD UNDER WINDOWS WITH VISUAL STUDIO
|
||||
==============================================================
|
||||
|
||||
On Windows, assumptions on the directory structure are made to automate the discovery of dependencies.
|
||||
This recommended directory structure is described below:
|
||||
|
||||
${MSVC_3RDPARTY_ROOT} /
|
||||
3rdParty / ( includes plib, fltk, zlib, libpng, libjpeg, libtiff, freetype, libsvn, gdal, ...
|
||||
bin /
|
||||
include /
|
||||
lib /
|
||||
3rdParty.x64 / ( 64 bit version )
|
||||
...
|
||||
boost_1_44_0 /
|
||||
boost /
|
||||
install /
|
||||
msvc100 / ( for VS2010 32 bits, or msvc90, msvc90-64 or msvc100-64 for VS2008 32, VS2008 64 and VS2010 64 )
|
||||
OpenSceneGraph / ( OSG CMake install
|
||||
bin /
|
||||
include /
|
||||
lib /
|
||||
SimGear /
|
||||
include /
|
||||
lib /
|
||||
|
||||
If you do not use the recommended structure you will need to enter paths by hand. Source and build directories can be located anywhere.
|
||||
|
||||
The suggested inputs to cmake are :
|
||||
MSVC_3RDPARTY_ROOT : location of the above directory structure
|
||||
CMAKE_INSTALL_PREFIX : ${MSVC_3RDPARTY_ROOT}/install/msvc100/FlightGear (or any variation for the compiler version described above )
|
||||
|
||||
|
||||
1. Set up a work directory as described above.
|
||||
|
||||
2. Open the Cmake gui.
|
||||
|
||||
3. Set "Where is the source code" to wherever you put the FlightGear sources (from the released tarball or the git repository).
|
||||
|
||||
4. Set "Where to build the binaries" to an empty directory.
|
||||
|
||||
5. Press the "Configure" button. The first time that the project is configured, Cmake will bring up a window asking which compiler you wish to use. Normally just accept Cmakes suggestion, and press Finish. Cmake will now do a check on your system and will produce a preliminary build configuration.
|
||||
|
||||
6. Cmake adds new configuration variables in red. Some have a value ending with -NOTFOUND. These variables should receive your attention. Some errors will prevent FlightGear to build and others will simply invalidate some options without provoking build errors. First check the MSVC_3RDPARTY_ROOT variable. If it is not set, chances are that there will be a lot of -NOTFOUND errors. Instead of trying to fix every error individually, set that variable and press the "Configure" button again.
|
||||
|
||||
7. Also check the lines with a checkbox. These are build options and may impact the feature set of the built program.
|
||||
|
||||
8. Change the CMAKE_INSTALL_PREFIX to ${MSVC_3RDPARTY_ROOT}/install/msvc100/FlightGear because C:\Program Files is likely unwritable to ordinary Windows users and will integrate better with the above directory structure (this is mandatory for SimGear if you don't want to solve errors by hand).
|
||||
|
||||
10. Repeat the process until the "Generate" button is enabled.
|
||||
|
||||
11. Press the "Generate" button.
|
||||
|
||||
12. Start Visual Studio 2010 and load the FlightGear solution (FlightGear.sln) located in "Where to build the binaries" (point 4.)
|
||||
|
||||
13. Choose the "Release" build in the VS2010 "Generation" toolbar
|
||||
|
||||
14. Generate the solution.
|
||||
|
||||
15. If there are build errors, return to Cmake, clear remaining errors, "Configure" and "Generate"
|
||||
|
||||
16. When Visual Studio is able to build everything without errors, build the INSTALL project to put the product files in ${CMAKE_INSTALL_PREFIX}
|
||||
|
||||
17. Enjoy!
|
||||
|
||||
PS: When updating the source from git, it is usually unnecessary to restart Cmake as the solution is able to reconfigure itself when Cmake files are changed. Simply rebuild the solution from Visual Studio and accept the reload of updated projects. It also possible to edit CMakeList.txt files directly in Visual Studio as they also appear in the solution, and projects will be reconfigured on the next generation. To change build options or directory path, it is mandatory to use the Cmake Gui. In case of problems, locate the CMakeCache.txt in "Where to build the binaries” directory and delete it to reconfigure from scratch or use the menu item File->Delete Cache.
|
||||
|
|
|
@ -89,7 +89,7 @@ Section "" ;No components page, name is not important
|
|||
; VC runtime redistributables
|
||||
File "$%VCINSTALLDIR%\redist\x86\Microsoft.VC100.CRT\*.dll"
|
||||
|
||||
File /r ${FGRunDir}\share
|
||||
File /r ${FGRunDir}\share\locale
|
||||
|
||||
SetOutPath $INSTDIR\osgPlugins-${OSGVersion}
|
||||
File ${OSGPluginsDir}\osgdb_ac.dll
|
||||
|
@ -102,6 +102,7 @@ Section "" ;No components page, name is not important
|
|||
File ${OSGPluginsDir}\osgdb_png.dll
|
||||
File ${OSGPluginsDir}\osgdb_dds.dll
|
||||
File ${OSGPluginsDir}\osgdb_txf.dll
|
||||
File ${OSGPluginsDir}\osgdb_freetype.dll
|
||||
File ${OSGPluginsDir}\osgdb_serializers_osg.dll
|
||||
File ${OSGPluginsDir}\osgdb_serializers_osganimation.dll
|
||||
File ${OSGPluginsDir}\osgdb_serializers_osgfx.dll
|
||||
|
|
91
package/make-base-package.noarch.sh
Executable file
91
package/make-base-package.noarch.sh
Executable file
|
@ -0,0 +1,91 @@
|
|||
#!/bin/sh
|
||||
|
||||
echo $1 $2
|
||||
|
||||
if [ "x$1" != "x" ]; then
|
||||
BASE="$1"
|
||||
else
|
||||
BASE="/home/curt/Projects/FlightGear/"
|
||||
fi
|
||||
|
||||
if [ "x$2" != "x" ]; then
|
||||
VERSION="$2"
|
||||
else
|
||||
VERSION="2.5"
|
||||
fi
|
||||
|
||||
echo base dir = $BASE, version = $VERSION
|
||||
|
||||
cd $BASE
|
||||
|
||||
tar \
|
||||
--exclude=CVS \
|
||||
--exclude='*~' \
|
||||
--exclude='*.bak' \
|
||||
--exclude='*.tex' \
|
||||
--exclude='*.xcf' \
|
||||
--exclude='*/c172/Instruments.high' \
|
||||
--exclude='*/Textures/Unused' \
|
||||
--exclude='*/Textures/*.orig' \
|
||||
--exclude='*/Textures.high/*.new' \
|
||||
--exclude='*/Textures.high/*.orig' \
|
||||
--exclude='*/Textures.high/*.save' \
|
||||
--exclude='*/data/Data' \
|
||||
--exclude='*/Docs/source' \
|
||||
--exclude='*/Models/MNUAV' \
|
||||
--exclude='*/Models/Airspace' \
|
||||
-cjvf FlightGear-data-${VERSION}.tar.bz2 \
|
||||
data/AI \
|
||||
data/Aircraft/Generic \
|
||||
data/Aircraft/Instruments \
|
||||
data/Aircraft/Instruments-3d \
|
||||
data/Aircraft/UIUC \
|
||||
data/Aircraft/777-200 \
|
||||
data/Aircraft/A6M2 \
|
||||
data/Aircraft/ASK13 \
|
||||
data/Aircraft/b1900d \
|
||||
data/Aircraft/bo105 \
|
||||
data/Aircraft/c172p \
|
||||
data/Aircraft/CitationX \
|
||||
data/Aircraft/Dragonfly \
|
||||
data/Aircraft/dhc2 \
|
||||
data/Aircraft/f-14b \
|
||||
data/Aircraft/Cub \
|
||||
data/Aircraft/SenecaII \
|
||||
data/Aircraft/sopwithCamel \
|
||||
data/Aircraft/ufo \
|
||||
data/Aircraft/ZLT-NT \
|
||||
data/Airports \
|
||||
data/Astro \
|
||||
data/ATC \
|
||||
data/AUTHORS \
|
||||
data/ChangeLog \
|
||||
data/COPYING \
|
||||
data/D* \
|
||||
data/Effects \
|
||||
data/Environment \
|
||||
data/Fonts \
|
||||
data/gui \
|
||||
data/HLA \
|
||||
data/Huds \
|
||||
data/Input \
|
||||
data/joysticks.xml \
|
||||
data/keyboard.xml \
|
||||
data/Lighting \
|
||||
data/materials.dtd \
|
||||
data/materials.xml \
|
||||
data/mice.xml \
|
||||
data/Models \
|
||||
data/MP \
|
||||
data/N* \
|
||||
data/options.xml \
|
||||
data/preferences.xml \
|
||||
data/Protocol \
|
||||
data/README \
|
||||
data/Scenery/Airports \
|
||||
data/Scenery/Objects \
|
||||
data/Scenery/Terrain \
|
||||
data/Shaders \
|
||||
data/Sounds \
|
||||
data/T* \
|
||||
data/version
|
|
@ -385,14 +385,6 @@
|
|||
RelativePath="..\..\..\src\Aircraft\controls.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Aircraft\replay.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Aircraft\replay.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Aircraft\flightrecorder.cxx"
|
||||
>
|
||||
|
@ -401,6 +393,14 @@
|
|||
RelativePath="..\..\..\src\Aircraft\flightrecorder.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Aircraft\replay.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Aircraft\replay.hxx"
|
||||
>
|
||||
</File>
|
||||
</Filter>
|
||||
<Filter
|
||||
Name="Lib_Airports"
|
||||
|
@ -2525,6 +2525,38 @@
|
|||
RelativePath="..\..\..\src\GUI\dialog.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\GUI\FGColor.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\GUI\FGColor.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\GUI\FGFontCache.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\GUI\FGFontCache.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\GUI\FGPUIDialog.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\GUI\FGPUIDialog.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\GUI\FGPUIMenuBar.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\GUI\FGPUIMenuBar.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Gui\fonts.cxx"
|
||||
>
|
||||
|
@ -3753,6 +3785,14 @@
|
|||
RelativePath="..\..\..\src\Instrumentation\mrg.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Instrumentation\NavDisplay.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Instrumentation\NavDisplay.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Instrumentation\navradio.cxx"
|
||||
>
|
||||
|
@ -3777,14 +3817,6 @@
|
|||
RelativePath="..\..\..\src\Instrumentation\od_gauge.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Instrumentation\NavDisplay.cxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Instrumentation\NavDisplay.hxx"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath="..\..\..\src\Instrumentation\rad_alt.cxx"
|
||||
>
|
||||
|
|
|
@ -820,10 +820,10 @@ bool FGAIAircraft::leadPointReached(FGAIWaypoint* curr) {
|
|||
}
|
||||
if (trafficRef) {
|
||||
//cerr << "Tracking callsign : \"" << fgGetString("/ai/track-callsign") << "\"" << endl;
|
||||
/* if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
|
||||
cerr << trafficRef->getCallSign() << " " << tgt_altitude_ft << " " << _getSpeed() << " "
|
||||
<< _getAltitude() << " "<< _getLatitude() << " " << _getLongitude() << " " << dist_to_go << " " << lead_dist << " " << curr->name << " " << vs << " " << tgt_vs << " " << bearing << " " << minBearing << " " << speedFraction << endl;
|
||||
}*/
|
||||
//if (trafficRef->getCallSign() == fgGetString("/ai/track-callsign")) {
|
||||
//cerr << trafficRef->getCallSign() << " " << tgt_altitude_ft << " " << _getSpeed() << " "
|
||||
// << _getAltitude() << " "<< _getLatitude() << " " << _getLongitude() << " " << dist_to_go << " " << lead_dist << " " << curr->getName() << " " << vs << " " << //tgt_vs << " " << bearing << " " << minBearing << " " << speedFraction << endl;
|
||||
//}
|
||||
}
|
||||
if ((dist_to_go < lead_dist) ||
|
||||
((dist_to_go > prev_dist_to_go) && (bearing > (minBearing * 1.1))) ) {
|
||||
|
@ -1275,9 +1275,9 @@ void FGAIAircraft::updateActualState() {
|
|||
updatePosition();
|
||||
|
||||
if (onGround())
|
||||
speed = _performance->actualSpeed(this, groundTargetSpeed, dt);
|
||||
speed = _performance->actualSpeed(this, groundTargetSpeed, dt, holdPos);
|
||||
else
|
||||
speed = _performance->actualSpeed(this, (tgt_speed *speedFraction), dt);
|
||||
speed = _performance->actualSpeed(this, (tgt_speed *speedFraction), dt, false);
|
||||
//assertSpeed(speed);
|
||||
updateHeading();
|
||||
roll = _performance->actualBankAngle(this, tgt_roll, dt);
|
||||
|
|
|
@ -267,7 +267,7 @@ bool FGAIBase::init(bool search_in_AI_path) {
|
|||
else
|
||||
_installed = true;
|
||||
|
||||
osg::Node * mdl = SGModelLib::loadPagedModel(f, props, new FGNasalModelData(props));
|
||||
osg::Node * mdl = SGModelLib::loadDeferredModel(f, props, new FGNasalModelData(props));
|
||||
|
||||
if (_model.valid())
|
||||
{
|
||||
|
|
|
@ -357,7 +357,7 @@ void FGAIFlightPlan::createDefaultLandingTaxi(FGAIAircraft * ac,
|
|||
double heading, lat, lon;
|
||||
aAirport->getDynamics()->getParking(gateId, &lat, &lon, &heading);
|
||||
wpt =
|
||||
createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), airportElev,
|
||||
createOnGround(ac, "ENDtaxi", SGGeod::fromDeg(lon, lat), airportElev,
|
||||
ac->getPerformance()->vTaxi());
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
|
@ -1039,7 +1039,7 @@ bool FGAIFlightPlan::createParking(FGAIAircraft * ac, FGAirport * apt,
|
|||
pushBackWaypoint(wpt);
|
||||
|
||||
wpt =
|
||||
createOnGround(ac, "END", SGGeod::fromDeg(lon, lat), aptElev,
|
||||
createOnGround(ac, "END-Parking", SGGeod::fromDeg(lon, lat), aptElev,
|
||||
vTaxiReduced);
|
||||
pushBackWaypoint(wpt);
|
||||
return true;
|
||||
|
|
|
@ -38,13 +38,13 @@
|
|||
|
||||
// TODO: Use James Turner's createOnGround functions.
|
||||
bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
|
||||
bool firstFlight, FGAirport *dep,
|
||||
double latitude,
|
||||
double longitude,
|
||||
double radius,
|
||||
const string& fltType,
|
||||
const string& aircraftType,
|
||||
const string& airline)
|
||||
bool firstFlight, FGAirport *dep,
|
||||
double latitude,
|
||||
double longitude,
|
||||
double radius,
|
||||
const string& fltType,
|
||||
const string& aircraftType,
|
||||
const string& airline)
|
||||
{
|
||||
double lat, lon, heading;
|
||||
double vTaxi = ac->getPerformance()->vTaxi();
|
||||
|
@ -56,132 +56,132 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
|
|||
activeRunway.clear();
|
||||
|
||||
if (!(dep->getDynamics()->getGroundNetwork()->exists())) {
|
||||
//cerr << "Push Back fallback" << endl;
|
||||
createPushBackFallBack(ac, firstFlight, dep, latitude, longitude,
|
||||
radius, fltType, aircraftType, airline);
|
||||
//cerr << "Push Back fallback" << endl;
|
||||
createPushBackFallBack(ac, firstFlight, dep, latitude, longitude,
|
||||
radius, fltType, aircraftType, airline);
|
||||
} else {
|
||||
if (firstFlight) {
|
||||
if (firstFlight) {
|
||||
|
||||
if (!(dep->getDynamics()->getAvailableParking(&lat, &lon,
|
||||
&heading, &gateId,
|
||||
radius, fltType,
|
||||
aircraftType, airline))) {
|
||||
SG_LOG(SG_INPUT, SG_WARN, "Warning: Could not find parking for a " <<
|
||||
aircraftType <<
|
||||
" of flight type " << fltType <<
|
||||
" of airline " << airline <<
|
||||
" at airport " << dep->getId());
|
||||
return false;
|
||||
char buffer[10];
|
||||
snprintf (buffer, 10, "%d", gateId);
|
||||
SGGeod coord = coord.fromDeg(lon, lat);
|
||||
//FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiBackward);
|
||||
wpt->setRouteIndex(-1);
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
//cerr << "Success : GateId = " << gateId << endl;
|
||||
SG_LOG(SG_INPUT, SG_WARN, "Warning: Succesfully found a parking for a " <<
|
||||
aircraftType <<
|
||||
" of flight type " << fltType <<
|
||||
" of airline " << airline <<
|
||||
" at airport " << dep->getId());
|
||||
} else {
|
||||
//cerr << "Push Back follow-up Flight" << endl;
|
||||
dep->getDynamics()->getParking(gateId, &lat, &lon, &heading);
|
||||
}
|
||||
if (gateId < 0) {
|
||||
createPushBackFallBack(ac, firstFlight, dep, latitude, longitude,
|
||||
radius, fltType, aircraftType, airline);
|
||||
return true;
|
||||
if (!(dep->getDynamics()->getAvailableParking(&lat, &lon,
|
||||
&heading, &gateId,
|
||||
radius, fltType,
|
||||
aircraftType, airline))) {
|
||||
SG_LOG(SG_INPUT, SG_WARN, "Warning: Could not find parking for a " <<
|
||||
aircraftType <<
|
||||
" of flight type " << fltType <<
|
||||
" of airline " << airline <<
|
||||
" at airport " << dep->getId());
|
||||
return false;
|
||||
char buffer[10];
|
||||
snprintf (buffer, 10, "%d", gateId);
|
||||
SGGeod coord = coord.fromDeg(lon, lat);
|
||||
//FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiBackward);
|
||||
wpt->setRouteIndex(-1);
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
//cerr << "Success : GateId = " << gateId << endl;
|
||||
SG_LOG(SG_INPUT, SG_WARN, "Warning: Succesfully found a parking for a " <<
|
||||
aircraftType <<
|
||||
" of flight type " << fltType <<
|
||||
" of airline " << airline <<
|
||||
" at airport " << dep->getId());
|
||||
} else {
|
||||
//cerr << "Push Back follow-up Flight" << endl;
|
||||
dep->getDynamics()->getParking(gateId, &lat, &lon, &heading);
|
||||
}
|
||||
if (gateId < 0) {
|
||||
createPushBackFallBack(ac, firstFlight, dep, latitude, longitude,
|
||||
radius, fltType, aircraftType, airline);
|
||||
return true;
|
||||
|
||||
}
|
||||
//cerr << "getting parking " << gateId;
|
||||
//cerr << " for a " <<
|
||||
// aircraftType <<
|
||||
// " of flight type " << fltType <<
|
||||
// " of airline " << airline <<
|
||||
// " at airport " << dep->getId() << endl;
|
||||
FGParking *parking = dep->getDynamics()->getParking(gateId);
|
||||
int pushBackNode = parking->getPushBackPoint();
|
||||
}
|
||||
//cerr << "getting parking " << gateId;
|
||||
//cerr << " for a " <<
|
||||
// aircraftType <<
|
||||
// " of flight type " << fltType <<
|
||||
// " of airline " << airline <<
|
||||
// " at airport " << dep->getId() << endl;
|
||||
FGParking *parking = dep->getDynamics()->getParking(gateId);
|
||||
int pushBackNode = parking->getPushBackPoint();
|
||||
|
||||
|
||||
pushBackRoute = parking->getPushBackRoute();
|
||||
if ((pushBackNode > 0) && (pushBackRoute == 0)) { // Load the already established route for this gate
|
||||
int node, rte;
|
||||
FGTaxiRoute route;
|
||||
//cerr << "Creating push-back for " << gateId << " (" << parking->getName() << ") using push-back point " << pushBackNode << endl;
|
||||
route = dep->getDynamics()->getGroundNetwork()->findShortestRoute(gateId, pushBackNode, false);
|
||||
parking->setPushBackRoute(new FGTaxiRoute(route));
|
||||
pushBackRoute = parking->getPushBackRoute();
|
||||
if ((pushBackNode > 0) && (pushBackRoute == 0)) { // Load the already established route for this gate
|
||||
int node, rte;
|
||||
FGTaxiRoute route;
|
||||
//cerr << "Creating push-back for " << gateId << " (" << parking->getName() << ") using push-back point " << pushBackNode << endl;
|
||||
route = dep->getDynamics()->getGroundNetwork()->findShortestRoute(gateId, pushBackNode, false);
|
||||
parking->setPushBackRoute(new FGTaxiRoute(route));
|
||||
|
||||
|
||||
pushBackRoute = parking->getPushBackRoute();
|
||||
int size = pushBackRoute->size();
|
||||
if (size < 2) {
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "Push back route from gate " << gateId << " has only " << size << " nodes.");
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "Using " << pushBackNode);
|
||||
}
|
||||
pushBackRoute->first();
|
||||
while(pushBackRoute->next(&node, &rte))
|
||||
{
|
||||
//FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd();
|
||||
char buffer[10];
|
||||
snprintf (buffer, 10, "%d", node);
|
||||
FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
|
||||
//ids.pop_back();
|
||||
//wpt = new waypoint;
|
||||
SGGeod coord = coord.fromDeg(tn->getLongitude(), tn->getLatitude());
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiBackward);
|
||||
pushBackRoute = parking->getPushBackRoute();
|
||||
int size = pushBackRoute->size();
|
||||
if (size < 2) {
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "Push back route from gate " << gateId << " has only " << size << " nodes.");
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "Using " << pushBackNode);
|
||||
}
|
||||
pushBackRoute->first();
|
||||
while (pushBackRoute->next(&node, &rte))
|
||||
{
|
||||
//FGTaxiNode *tn = apt->getDynamics()->getGroundNetwork()->findSegment(node)->getEnd();
|
||||
char buffer[10];
|
||||
snprintf (buffer, 10, "%d", node);
|
||||
FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(node);
|
||||
//ids.pop_back();
|
||||
//wpt = new waypoint;
|
||||
SGGeod coord = coord.fromDeg(tn->getLongitude(), tn->getLatitude());
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiBackward);
|
||||
|
||||
wpt->setRouteIndex(rte);
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
// some special considerations for the last point:
|
||||
waypoints.back()->setName(string("PushBackPoint"));
|
||||
waypoints.back()->setSpeed(vTaxi);
|
||||
ac->setTaxiClearanceRequest(true);
|
||||
} else { // In case of a push forward departure...
|
||||
ac->setTaxiClearanceRequest(false);
|
||||
double lat2 = 0.0, lon2 = 0.0, az2 = 0.0;
|
||||
wpt->setRouteIndex(rte);
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
// some special considerations for the last point:
|
||||
waypoints.back()->setName(string("PushBackPoint"));
|
||||
waypoints.back()->setSpeed(vTaxi);
|
||||
ac->setTaxiClearanceRequest(true);
|
||||
} else { // In case of a push forward departure...
|
||||
ac->setTaxiClearanceRequest(false);
|
||||
double lat2 = 0.0, lon2 = 0.0, az2 = 0.0;
|
||||
|
||||
//cerr << "Creating final push forward point for gate " << gateId << endl;
|
||||
FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(gateId);
|
||||
FGTaxiSegmentVectorIterator ts = tn->getBeginRoute();
|
||||
FGTaxiSegmentVectorIterator te = tn->getEndRoute();
|
||||
// if the starting node equals the ending node, then there aren't any routes for this parking.
|
||||
// in cases like these we should flag the gate as being inoperative and return false
|
||||
if (ts == te) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Gate " << gateId << "doesn't seem to have routes associated with it.");
|
||||
parking->setAvailable(false);
|
||||
return false;
|
||||
}
|
||||
tn = (*ts)->getEnd();
|
||||
lastNodeVisited = tn->getIndex();
|
||||
if (tn == NULL) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "No valid taxinode found");
|
||||
exit(1);
|
||||
}
|
||||
double distance = (*ts)->getLength();
|
||||
//cerr << "Length of push forward route = " << distance << " and heading is " << heading << endl;
|
||||
lat2 = tn->getLatitude();
|
||||
lon2 = tn->getLongitude();
|
||||
//cerr << "Creating final push forward point for gate " << gateId << endl;
|
||||
FGTaxiNode *tn = dep->getDynamics()->getGroundNetwork()->findNode(gateId);
|
||||
FGTaxiSegmentVectorIterator ts = tn->getBeginRoute();
|
||||
FGTaxiSegmentVectorIterator te = tn->getEndRoute();
|
||||
// if the starting node equals the ending node, then there aren't any routes for this parking.
|
||||
// in cases like these we should flag the gate as being inoperative and return false
|
||||
if (ts == te) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Gate " << gateId << "doesn't seem to have routes associated with it.");
|
||||
parking->setAvailable(false);
|
||||
return false;
|
||||
}
|
||||
tn = (*ts)->getEnd();
|
||||
lastNodeVisited = tn->getIndex();
|
||||
if (tn == NULL) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "No valid taxinode found");
|
||||
exit(1);
|
||||
}
|
||||
double distance = (*ts)->getLength();
|
||||
//cerr << "Length of push forward route = " << distance << " and heading is " << heading << endl;
|
||||
lat2 = tn->getLatitude();
|
||||
lon2 = tn->getLongitude();
|
||||
|
||||
for (int i = 1; i < 10; i++) {
|
||||
geo_direct_wgs_84 ( 0, lat, lon, heading,
|
||||
((i / 10.0) * distance), &lat2, &lon2, &az2 );
|
||||
char buffer[16];
|
||||
snprintf(buffer, 16, "pushback-%02d", i);
|
||||
SGGeod coord = coord.fromDeg(lon2, lat2);
|
||||
//cerr << i << endl;
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiReduced);
|
||||
for (int i = 1; i < 10; i++) {
|
||||
geo_direct_wgs_84 ( 0, lat, lon, heading,
|
||||
((i / 10.0) * distance), &lat2, &lon2, &az2 );
|
||||
char buffer[16];
|
||||
snprintf(buffer, 16, "pushback-%02d", i);
|
||||
SGGeod coord = coord.fromDeg(lon2, lat2);
|
||||
//cerr << i << endl;
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string(buffer), coord, dep->getElevation(), vTaxiReduced);
|
||||
|
||||
wpt->setRouteIndex((*ts)->getIndex());
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
// cerr << "Done " << endl;
|
||||
waypoints.back()->setName(string("PushBackPoint"));
|
||||
// cerr << "Done assinging new name" << endl;
|
||||
}
|
||||
wpt->setRouteIndex((*ts)->getIndex());
|
||||
pushBackWaypoint(wpt);
|
||||
}
|
||||
// cerr << "Done " << endl;
|
||||
waypoints.back()->setName(string("PushBackPoint"));
|
||||
// cerr << "Done assinging new name" << endl;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -191,50 +191,50 @@ bool FGAIFlightPlan::createPushBack(FGAIAircraft *ac,
|
|||
* network yet.
|
||||
******************************************************************/
|
||||
void FGAIFlightPlan::createPushBackFallBack(FGAIAircraft *ac, bool firstFlight, FGAirport *dep,
|
||||
double latitude,
|
||||
double longitude,
|
||||
double radius,
|
||||
const string& fltType,
|
||||
const string& aircraftType,
|
||||
const string& airline)
|
||||
double latitude,
|
||||
double longitude,
|
||||
double radius,
|
||||
const string& fltType,
|
||||
const string& aircraftType,
|
||||
const string& airline)
|
||||
{
|
||||
double heading;
|
||||
double lat;
|
||||
double lon;
|
||||
double lat2 = 0.0;
|
||||
double lon2 = 0.0;
|
||||
double az2 = 0.0;
|
||||
double heading;
|
||||
double lat;
|
||||
double lon;
|
||||
double lat2 = 0.0;
|
||||
double lon2 = 0.0;
|
||||
double az2 = 0.0;
|
||||
|
||||
double vTaxi = ac->getPerformance()->vTaxi();
|
||||
double vTaxiBackward = vTaxi * (-2.0/3.0);
|
||||
double vTaxiReduced = vTaxi * (2.0/3.0);
|
||||
double vTaxi = ac->getPerformance()->vTaxi();
|
||||
double vTaxiBackward = vTaxi * (-2.0/3.0);
|
||||
double vTaxiReduced = vTaxi * (2.0/3.0);
|
||||
|
||||
|
||||
|
||||
dep->getDynamics()->getParking(-1, &lat, &lon, &heading);
|
||||
dep->getDynamics()->getParking(-1, &lat, &lon, &heading);
|
||||
|
||||
heading += 180.0;
|
||||
if (heading > 360)
|
||||
heading -= 360;
|
||||
heading += 180.0;
|
||||
if (heading > 360)
|
||||
heading -= 360;
|
||||
|
||||
SGGeod coord = coord.fromDeg(lon, lat);
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string("park"), coord, dep->getElevation(), vTaxiBackward);
|
||||
SGGeod coord = coord.fromDeg(lon, lat);
|
||||
FGAIWaypoint *wpt = createOnGround(ac, string("park"), coord, dep->getElevation(), vTaxiBackward);
|
||||
|
||||
pushBackWaypoint(wpt);
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
geo_direct_wgs_84 ( 0, lat, lon, heading,
|
||||
10,
|
||||
&lat2, &lon2, &az2 );
|
||||
coord = coord.fromDeg(lon2, lat2);
|
||||
wpt = createOnGround(ac, string("park2"), coord, dep->getElevation(), vTaxiBackward);
|
||||
geo_direct_wgs_84 ( 0, lat, lon, heading,
|
||||
10,
|
||||
&lat2, &lon2, &az2 );
|
||||
coord = coord.fromDeg(lon2, lat2);
|
||||
wpt = createOnGround(ac, string("park2"), coord, dep->getElevation(), vTaxiBackward);
|
||||
|
||||
pushBackWaypoint(wpt);
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
geo_direct_wgs_84 ( 0, lat, lon, heading,
|
||||
2.2*radius,
|
||||
&lat2, &lon2, &az2 );
|
||||
coord = coord.fromDeg(lon2, lat2);
|
||||
wpt = createOnGround(ac, string("taxiStart"), coord, dep->getElevation(), vTaxiReduced);
|
||||
pushBackWaypoint(wpt);
|
||||
geo_direct_wgs_84 ( 0, lat, lon, heading,
|
||||
2.2*radius,
|
||||
&lat2, &lon2, &az2 );
|
||||
coord = coord.fromDeg(lon2, lat2);
|
||||
wpt = createOnGround(ac, string("taxiStart"), coord, dep->getElevation(), vTaxiReduced);
|
||||
pushBackWaypoint(wpt);
|
||||
|
||||
}
|
||||
|
|
|
@ -146,7 +146,7 @@ FGAIManager::update(double dt) {
|
|||
if (!enabled)
|
||||
return;
|
||||
|
||||
FGTrafficManager *tmgr = (FGTrafficManager*) globals->get_subsystem("Traffic Manager");
|
||||
FGTrafficManager *tmgr = (FGTrafficManager*) globals->get_subsystem("traffic-manager");
|
||||
_dt = dt;
|
||||
|
||||
ai_list_iterator ai_list_itr = ai_list.begin();
|
||||
|
|
|
@ -49,7 +49,7 @@ PerformanceData::PerformanceData( const std::string& filename)
|
|||
PerformanceData::~PerformanceData()
|
||||
{}
|
||||
|
||||
double PerformanceData::actualSpeed(FGAIAircraft* ac, double tgt_speed, double dt) {
|
||||
double PerformanceData::actualSpeed(FGAIAircraft* ac, double tgt_speed, double dt, bool maxBrakes) {
|
||||
// if (tgt_speed > _vTaxi & ac->onGround()) // maximum taxi speed on ground
|
||||
// tgt_speed = _vTaxi;
|
||||
// bad idea for a take off roll :-)
|
||||
|
@ -66,7 +66,13 @@ double PerformanceData::actualSpeed(FGAIAircraft* ac, double tgt_speed, double d
|
|||
} else if (speed_diff < 0.0) { // decelerate
|
||||
if (ac->onGround()) {
|
||||
// deceleration performance is better due to wheel brakes.
|
||||
speed -= BRAKE_SETTING * _deceleration * dt;
|
||||
double brakePower = 0;
|
||||
if (maxBrakes) {
|
||||
brakePower = 3;
|
||||
} else {
|
||||
brakePower = BRAKE_SETTING;
|
||||
}
|
||||
speed -= brakePower * _deceleration * dt;
|
||||
} else {
|
||||
speed -= _deceleration * dt;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ public:
|
|||
PerformanceData(const std::string& filename);
|
||||
~PerformanceData();
|
||||
|
||||
double actualSpeed(FGAIAircraft* ac, double tgt_speed, double dt);
|
||||
double actualSpeed(FGAIAircraft* ac, double tgt_speed, double dt, bool needMaxBrake);
|
||||
double actualBankAngle(FGAIAircraft* ac, double tgt_roll, double dt);
|
||||
double actualPitch(FGAIAircraft* ac, double tgt_pitch, double dt);
|
||||
double actualHeading(FGAIAircraft* ac, double tgt_heading, double dt);
|
||||
|
|
|
@ -45,7 +45,7 @@ FGSubmodelMgr::~FGSubmodelMgr()
|
|||
|
||||
FGAIManager* FGSubmodelMgr::aiManager()
|
||||
{
|
||||
return (FGAIManager*)globals->get_subsystem("ai_model");
|
||||
return (FGAIManager*)globals->get_subsystem("ai-model");
|
||||
}
|
||||
|
||||
void FGSubmodelMgr::init()
|
||||
|
|
|
@ -100,7 +100,7 @@ void FGATCManager::init() {
|
|||
|
||||
|
||||
FGAirport *apt = FGAirport::findByIdent(airport);
|
||||
if (apt && onGround) {
|
||||
if (apt && onGround && !runway.empty()) {
|
||||
FGAirportDynamics* dcs = apt->getDynamics();
|
||||
int park_index = dcs->getNrOfParkings() - 1;
|
||||
//cerr << "found information: " << runway << " " << airport << ": parking = " << parking << endl;
|
||||
|
|
|
@ -18,8 +18,13 @@
|
|||
//
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <Main/fg_commands.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/structure/commands.hxx>
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#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"
|
||||
|
@ -205,7 +206,13 @@ void FGATCDialog::PopupDialog() {
|
|||
button_group->removeChildren("button", false);
|
||||
|
||||
string label;
|
||||
FGATC* atcptr = globals->get_ATC_mgr()->GetComm1ATCPointer(); // Hardwired to comm1 at the moment
|
||||
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";
|
||||
|
@ -260,7 +267,13 @@ void FGATCDialog::PopupDialog() {
|
|||
}
|
||||
|
||||
void FGATCDialog::PopupCallback(int num) {
|
||||
FGATC* atcptr = globals->get_ATC_mgr()->GetComm1ATCPointer(); // FIXME - Hardwired to comm1 at the moment
|
||||
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;
|
||||
|
|
|
@ -48,9 +48,11 @@ FGATCMgr::FGATCMgr() :
|
|||
voice(false),
|
||||
#endif
|
||||
{
|
||||
globals->set_ATC_mgr(this);
|
||||
}
|
||||
|
||||
FGATCMgr::~FGATCMgr() {
|
||||
globals->set_ATC_mgr(NULL);
|
||||
delete v1;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,14 @@ FGATIS::FGATIS() :
|
|||
_prev_display(0),
|
||||
refname("atis")
|
||||
{
|
||||
_vPtr = globals->get_ATC_mgr()->GetVoicePointer(ATIS);
|
||||
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");
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
//
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
|
|
@ -102,6 +102,7 @@ bool FGAirportDynamics::getAvailableParking(double *lat, double *lon,
|
|||
//cerr << "Could not find parking spot at " << _ap->getId() << endl;
|
||||
*lat = _ap->getLatitude();
|
||||
*lon = _ap->getLongitude();
|
||||
* gateId = -1;
|
||||
*heading = 0;
|
||||
found = true;
|
||||
} else {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
|
||||
#include <math.h>
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
|
||||
|
||||
#include <osg/Geode>
|
||||
|
|
|
@ -13,6 +13,10 @@
|
|||
// 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/xml/easyxml.hxx>
|
||||
#include <simgear/misc/strutils.hxx>
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
#include <Main/fg_props.hxx>
|
||||
#include <Main/viewmgr.hxx>
|
||||
#include <Time/light.hxx>
|
||||
#include <GUI/new_gui.hxx> // FGFontCache
|
||||
#include <GUI/FGFontCache.hxx>
|
||||
#include <Main/viewer.hxx>
|
||||
#include <Instrumentation/dclgps.hxx>
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <simgear/structure/event_mgr.hxx>
|
||||
|
||||
#include <Main/main.hxx>
|
||||
#include <Main/renderer.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <FDM/flight.hxx>
|
||||
|
||||
|
@ -45,9 +46,6 @@
|
|||
#include "Airports/simple.hxx"
|
||||
#include "gravity.hxx"
|
||||
|
||||
class SGSky;
|
||||
extern SGSky *thesky;
|
||||
|
||||
class FG3DCloudsListener : public SGPropertyChangeListener {
|
||||
public:
|
||||
FG3DCloudsListener( FGClouds * fgClouds );
|
||||
|
@ -91,7 +89,8 @@ FGEnvironmentMgr::FGEnvironmentMgr () :
|
|||
_altitude_n(fgGetNode("/position/altitude-ft", true)),
|
||||
_longitude_n(fgGetNode( "/position/longitude-deg", true )),
|
||||
_latitude_n( fgGetNode( "/position/latitude-deg", true )),
|
||||
_3dCloudsEnableListener(new FG3DCloudsListener(fgClouds) )
|
||||
_3dCloudsEnableListener(new FG3DCloudsListener(fgClouds) ),
|
||||
_sky(globals->get_renderer()->getSky())
|
||||
{
|
||||
set_subsystem("controller", Environment::LayerInterpolateController::createInstance( fgGetNode("/environment/config", true ) ));
|
||||
set_subsystem("realwx", Environment::RealWxController::createInstance( fgGetNode("/environment/realwx", true ) ), 1.0 );
|
||||
|
@ -171,7 +170,7 @@ FGEnvironmentMgr::bind ()
|
|||
|
||||
_tiedProperties.setRoot( fgGetNode( "/environment", true ) );
|
||||
|
||||
_tiedProperties.Tie( "effective-visibility-m", thesky,
|
||||
_tiedProperties.Tie( "effective-visibility-m", _sky,
|
||||
&SGSky::get_visibility );
|
||||
|
||||
_tiedProperties.Tie("rebuild-layers", fgClouds,
|
||||
|
@ -220,15 +219,15 @@ FGEnvironmentMgr::bind ()
|
|||
|
||||
_tiedProperties.setRoot( fgGetNode("/sim/rendering", true ) );
|
||||
|
||||
_tiedProperties.Tie( "clouds3d-density", thesky,
|
||||
_tiedProperties.Tie( "clouds3d-density", _sky,
|
||||
&SGSky::get_3dCloudDensity,
|
||||
&SGSky::set_3dCloudDensity);
|
||||
|
||||
_tiedProperties.Tie("clouds3d-vis-range", thesky,
|
||||
_tiedProperties.Tie("clouds3d-vis-range", _sky,
|
||||
&SGSky::get_3dCloudVisRange,
|
||||
&SGSky::set_3dCloudVisRange);
|
||||
|
||||
_tiedProperties.Tie("clouds3d-wrap", thesky,
|
||||
_tiedProperties.Tie("clouds3d-wrap", _sky,
|
||||
&SGSky::get_3dCloudWrap,
|
||||
&SGSky::set_3dCloudWrap);
|
||||
|
||||
|
@ -325,19 +324,19 @@ FGEnvironmentMgr::getEnvironment(const SGGeod& aPos) const
|
|||
double
|
||||
FGEnvironmentMgr::get_cloud_layer_span_m (int index) const
|
||||
{
|
||||
return thesky->get_cloud_layer(index)->getSpan_m();
|
||||
return _sky->get_cloud_layer(index)->getSpan_m();
|
||||
}
|
||||
|
||||
void
|
||||
FGEnvironmentMgr::set_cloud_layer_span_m (int index, double span_m)
|
||||
{
|
||||
thesky->get_cloud_layer(index)->setSpan_m(span_m);
|
||||
_sky->get_cloud_layer(index)->setSpan_m(span_m);
|
||||
}
|
||||
|
||||
double
|
||||
FGEnvironmentMgr::get_cloud_layer_elevation_ft (int index) const
|
||||
{
|
||||
return thesky->get_cloud_layer(index)->getElevation_m() * SG_METER_TO_FEET;
|
||||
return _sky->get_cloud_layer(index)->getElevation_m() * SG_METER_TO_FEET;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -346,88 +345,88 @@ FGEnvironmentMgr::set_cloud_layer_elevation_ft (int index, double elevation_ft)
|
|||
FGEnvironment env = *_environment;
|
||||
env.set_elevation_ft(elevation_ft);
|
||||
|
||||
thesky->get_cloud_layer(index)
|
||||
_sky->get_cloud_layer(index)
|
||||
->setElevation_m(elevation_ft * SG_FEET_TO_METER);
|
||||
|
||||
thesky->get_cloud_layer(index)
|
||||
_sky->get_cloud_layer(index)
|
||||
->setSpeed(env.get_wind_speed_kt() * 0.5151); // 1 kt = 0.5151 m/s
|
||||
|
||||
thesky->get_cloud_layer(index)
|
||||
_sky->get_cloud_layer(index)
|
||||
->setDirection(env.get_wind_from_heading_deg());
|
||||
}
|
||||
|
||||
double
|
||||
FGEnvironmentMgr::get_cloud_layer_thickness_ft (int index) const
|
||||
{
|
||||
return thesky->get_cloud_layer(index)->getThickness_m() * SG_METER_TO_FEET;
|
||||
return _sky->get_cloud_layer(index)->getThickness_m() * SG_METER_TO_FEET;
|
||||
}
|
||||
|
||||
void
|
||||
FGEnvironmentMgr::set_cloud_layer_thickness_ft (int index, double thickness_ft)
|
||||
{
|
||||
thesky->get_cloud_layer(index)
|
||||
_sky->get_cloud_layer(index)
|
||||
->setThickness_m(thickness_ft * SG_FEET_TO_METER);
|
||||
}
|
||||
|
||||
double
|
||||
FGEnvironmentMgr::get_cloud_layer_transition_ft (int index) const
|
||||
{
|
||||
return thesky->get_cloud_layer(index)->getTransition_m() * SG_METER_TO_FEET;
|
||||
return _sky->get_cloud_layer(index)->getTransition_m() * SG_METER_TO_FEET;
|
||||
}
|
||||
|
||||
void
|
||||
FGEnvironmentMgr::set_cloud_layer_transition_ft (int index,
|
||||
double transition_ft)
|
||||
{
|
||||
thesky->get_cloud_layer(index)
|
||||
_sky->get_cloud_layer(index)
|
||||
->setTransition_m(transition_ft * SG_FEET_TO_METER);
|
||||
}
|
||||
|
||||
const char *
|
||||
FGEnvironmentMgr::get_cloud_layer_coverage (int index) const
|
||||
{
|
||||
return thesky->get_cloud_layer(index)->getCoverageString().c_str();
|
||||
return _sky->get_cloud_layer(index)->getCoverageString().c_str();
|
||||
}
|
||||
|
||||
void
|
||||
FGEnvironmentMgr::set_cloud_layer_coverage (int index,
|
||||
const char * coverage_name)
|
||||
{
|
||||
if( thesky->get_cloud_layer(index)->getCoverageString() == coverage_name )
|
||||
if( _sky->get_cloud_layer(index)->getCoverageString() == coverage_name )
|
||||
return;
|
||||
|
||||
thesky->get_cloud_layer(index)->setCoverageString(coverage_name);
|
||||
_sky->get_cloud_layer(index)->setCoverageString(coverage_name);
|
||||
_cloudLayersDirty = true;
|
||||
}
|
||||
|
||||
int
|
||||
FGEnvironmentMgr::get_cloud_layer_coverage_type (int index) const
|
||||
{
|
||||
return thesky->get_cloud_layer(index)->getCoverage();
|
||||
return _sky->get_cloud_layer(index)->getCoverage();
|
||||
}
|
||||
|
||||
double
|
||||
FGEnvironmentMgr::get_cloud_layer_visibility_m (int index) const
|
||||
{
|
||||
return thesky->get_cloud_layer(index)->getVisibility_m();
|
||||
return _sky->get_cloud_layer(index)->getVisibility_m();
|
||||
}
|
||||
|
||||
void
|
||||
FGEnvironmentMgr::set_cloud_layer_visibility_m (int index, double visibility_m)
|
||||
{
|
||||
thesky->get_cloud_layer(index)->setVisibility_m(visibility_m);
|
||||
_sky->get_cloud_layer(index)->setVisibility_m(visibility_m);
|
||||
}
|
||||
|
||||
double
|
||||
FGEnvironmentMgr::get_cloud_layer_maxalpha (int index ) const
|
||||
{
|
||||
return thesky->get_cloud_layer(index)->getMaxAlpha();
|
||||
return _sky->get_cloud_layer(index)->getMaxAlpha();
|
||||
}
|
||||
|
||||
void
|
||||
FGEnvironmentMgr::set_cloud_layer_maxalpha (int index, double maxalpha)
|
||||
{
|
||||
thesky->get_cloud_layer(index)->setMaxAlpha(maxalpha);
|
||||
_sky->get_cloud_layer(index)->setMaxAlpha(maxalpha);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -438,10 +437,10 @@ FGEnvironmentMgr::set_cloud_layer_coverage_type (int index, int type )
|
|||
return;
|
||||
}
|
||||
|
||||
if( static_cast<SGCloudLayer::Coverage>(type) == thesky->get_cloud_layer(index)->getCoverage() )
|
||||
if( static_cast<SGCloudLayer::Coverage>(type) == _sky->get_cloud_layer(index)->getCoverage() )
|
||||
return;
|
||||
|
||||
thesky->get_cloud_layer(index)->setCoverage(static_cast<SGCloudLayer::Coverage>(type));
|
||||
_sky->get_cloud_layer(index)->setCoverage(static_cast<SGCloudLayer::Coverage>(type));
|
||||
_cloudLayersDirty = true;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ class FGMetarCtrl;
|
|||
class FGMetarFetcher;
|
||||
class FGClouds;
|
||||
class FGPrecipitationMgr;
|
||||
class SGSky;
|
||||
|
||||
/**
|
||||
* Manage environment information.
|
||||
|
@ -102,6 +103,8 @@ private:
|
|||
SGPropertyNode_ptr _latitude_n;
|
||||
simgear::TiedPropertyList _tiedProperties;
|
||||
SGPropertyChangeListener * _3dCloudsEnableListener;
|
||||
SGSky* _sky;
|
||||
|
||||
};
|
||||
|
||||
#endif // _ENVIRONMENT_MGR_HXX
|
||||
|
|
|
@ -32,6 +32,10 @@ Ephemeris::Ephemeris() :
|
|||
_impl(NULL),
|
||||
_latProp(NULL)
|
||||
{
|
||||
SGPath ephem_data_path(globals->get_fg_root());
|
||||
ephem_data_path.append("Astro");
|
||||
_impl = new SGEphemeris(ephem_data_path.c_str());
|
||||
globals->set_ephem(_impl);
|
||||
}
|
||||
|
||||
Ephemeris::~Ephemeris()
|
||||
|
@ -41,15 +45,6 @@ Ephemeris::~Ephemeris()
|
|||
|
||||
void Ephemeris::init()
|
||||
{
|
||||
if (_impl) {
|
||||
return;
|
||||
}
|
||||
|
||||
SGPath ephem_data_path(globals->get_fg_root());
|
||||
ephem_data_path.append("Astro");
|
||||
_impl = new SGEphemeris(ephem_data_path.c_str());
|
||||
globals->set_ephem(_impl);
|
||||
|
||||
_latProp = fgGetNode("/position/latitude-deg", true);
|
||||
update(0.0);
|
||||
}
|
||||
|
|
|
@ -38,13 +38,12 @@
|
|||
#include <simgear/props/props_io.hxx>
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/renderer.hxx>
|
||||
#include <Airports/simple.hxx>
|
||||
#include <Main/util.hxx>
|
||||
|
||||
#include "fgclouds.hxx"
|
||||
|
||||
extern SGSky *thesky;
|
||||
|
||||
static bool do_delete_3Dcloud (const SGPropertyNode *arg);
|
||||
static bool do_move_3Dcloud (const SGPropertyNode *arg);
|
||||
static bool do_add_3Dcloud (const SGPropertyNode *arg);
|
||||
|
@ -182,6 +181,8 @@ void FGClouds::buildLayer(int iLayer, const string& name, double coverage) {
|
|||
int CloudVarietyCount = 0;
|
||||
double totalCount = 0.0;
|
||||
|
||||
SGSky* thesky = globals->get_renderer()->getSky();
|
||||
|
||||
SGPropertyNode *cloud_def_root = fgGetNode("/environment/cloudlayers/clouds", false);
|
||||
SGPropertyNode *box_def_root = fgGetNode("/environment/cloudlayers/boxes", false);
|
||||
SGPropertyNode *layer_def_root = fgGetNode("/environment/cloudlayers/layers", false);
|
||||
|
@ -274,6 +275,7 @@ void FGClouds::buildCloudLayers(void) {
|
|||
double cumulus_base = 122.0 * (temperature_degc - dewpoint_degc);
|
||||
double stratus_base = 100.0 * (100.0 - rel_humidity) * SG_FEET_TO_METER;
|
||||
|
||||
SGSky* thesky = globals->get_renderer()->getSky();
|
||||
for(int iLayer = 0 ; iLayer < thesky->get_cloud_layer_count(); iLayer++) {
|
||||
SGPropertyNode *cloud_root = fgGetNode("/environment/clouds/layer", iLayer, true);
|
||||
|
||||
|
@ -366,7 +368,7 @@ bool FGClouds::get_3dClouds() const
|
|||
float x = arg->getFloatValue("x-offset-m", 0.0f);
|
||||
float y = arg->getFloatValue("y-offset-m", 0.0f);
|
||||
|
||||
|
||||
SGSky* thesky = globals->get_renderer()->getSky();
|
||||
SGCloudField *layer = thesky->get_cloud_layer(l)->get_layer3D();
|
||||
SGNewCloud cld = SGNewCloud(texture_root, arg);
|
||||
bool success = layer->addCloud(lon, lat, alt, x, y, index, cld.genCloud());
|
||||
|
@ -392,6 +394,7 @@ bool FGClouds::get_3dClouds() const
|
|||
int l = arg->getIntValue("layer", 0);
|
||||
int i = arg->getIntValue("index", 0);
|
||||
|
||||
SGSky* thesky = globals->get_renderer()->getSky();
|
||||
SGCloudField *layer = thesky->get_cloud_layer(l)->get_layer3D();
|
||||
return layer->deleteCloud(i);
|
||||
}
|
||||
|
@ -410,6 +413,7 @@ bool FGClouds::get_3dClouds() const
|
|||
{
|
||||
int l = arg->getIntValue("layer", 0);
|
||||
int i = arg->getIntValue("index", 0);
|
||||
SGSky* thesky = globals->get_renderer()->getSky();
|
||||
|
||||
float lon = arg->getFloatValue("lon-deg", 0.0f);
|
||||
float lat = arg->getFloatValue("lat-deg", 0.0f);
|
||||
|
|
|
@ -39,13 +39,11 @@
|
|||
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/renderer.hxx>
|
||||
#include <Scenery/scenery.hxx>
|
||||
|
||||
#include "precipitation_mgr.hxx"
|
||||
|
||||
extern SGSky *thesky;
|
||||
|
||||
|
||||
/**
|
||||
* @brief FGPrecipitation Manager constructor
|
||||
*
|
||||
|
@ -141,6 +139,8 @@ float FGPrecipitationMgr::getPrecipitationAtAltitudeMax(void)
|
|||
max = SGCloudLayer::SG_MAX_CLOUD_COVERAGES;
|
||||
result = 0;
|
||||
|
||||
SGSky* thesky = globals->get_renderer()->getSky();
|
||||
|
||||
// To avoid messing up
|
||||
if (thesky == NULL)
|
||||
return result;
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "Math.hpp"
|
||||
#include "BodyEnvironment.hpp"
|
||||
#include "RigidBody.hpp"
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
|
||||
#include "Math.hpp"
|
||||
|
|
|
@ -139,7 +139,14 @@ void YASim::init()
|
|||
SGPath f(fgGetString("/sim/aircraft-dir"));
|
||||
f.append(fgGetString("/sim/aero"));
|
||||
f.concat(".xml");
|
||||
readXML(f.str(), *_fdm);
|
||||
try {
|
||||
readXML(f.str(), *_fdm);
|
||||
} catch (const sg_exception &e) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT,
|
||||
"Error reading YASim FDM: '" << f.str() << "'" << std::endl
|
||||
<< e.getFormattedMessage());
|
||||
throw e;
|
||||
}
|
||||
|
||||
// Compile it into a real airplane, and tell the user what they got
|
||||
a->compile();
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
#include <simgear/compiler.h>
|
||||
#include <plib/puAux.h>
|
||||
#include "dialog.hxx"
|
||||
#include "FGPUIDialog.hxx"
|
||||
|
||||
class FGAirportList;
|
||||
|
||||
|
|
|
@ -6,14 +6,18 @@ set(SOURCES
|
|||
SafeTexFont.cxx
|
||||
WaypointList.cxx
|
||||
dialog.cxx
|
||||
FGPUIDialog.cxx
|
||||
fonts.cxx
|
||||
gui.cxx
|
||||
gui_funcs.cxx
|
||||
layout-props.cxx
|
||||
layout.cxx
|
||||
menubar.cxx
|
||||
FGPUIMenuBar.cxx
|
||||
new_gui.cxx
|
||||
property_list.cxx
|
||||
FGFontCache.cxx
|
||||
FGColor.cxx
|
||||
)
|
||||
|
||||
set(HEADERS
|
||||
|
@ -22,11 +26,15 @@ set(HEADERS
|
|||
SafeTexFont.hxx
|
||||
WaypointList.hxx
|
||||
dialog.hxx
|
||||
FGPUIDialog.hxx
|
||||
gui.h
|
||||
layout.hxx
|
||||
menubar.hxx
|
||||
FGPUIMenuBar.hxx
|
||||
new_gui.hxx
|
||||
property_list.hxx
|
||||
FGFontCache.hxx
|
||||
FGColor.hxx
|
||||
)
|
||||
|
||||
flightgear_component(GUI "${SOURCES}" "${HEADERS}")
|
||||
|
|
55
src/GUI/FGColor.cxx
Normal file
55
src/GUI/FGColor.cxx
Normal file
|
@ -0,0 +1,55 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "FGColor.hxx"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// FGColor class.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
FGColor::print() const {
|
||||
std::cerr << "red=" << _red << ", green=" << _green
|
||||
<< ", blue=" << _blue << ", alpha=" << _alpha << std::endl;
|
||||
}
|
||||
|
||||
bool
|
||||
FGColor::merge(const SGPropertyNode *node)
|
||||
{
|
||||
if (!node)
|
||||
return false;
|
||||
|
||||
bool dirty = false;
|
||||
const SGPropertyNode * n;
|
||||
if ((n = node->getNode("red")))
|
||||
_red = n->getFloatValue(), dirty = true;
|
||||
if ((n = node->getNode("green")))
|
||||
_green = n->getFloatValue(), dirty = true;
|
||||
if ((n = node->getNode("blue")))
|
||||
_blue = n->getFloatValue(), dirty = true;
|
||||
if ((n = node->getNode("alpha")))
|
||||
_alpha = n->getFloatValue(), dirty = true;
|
||||
return dirty;
|
||||
}
|
||||
|
||||
bool
|
||||
FGColor::merge(const FGColor *color)
|
||||
{
|
||||
bool dirty = false;
|
||||
if (color && color->_red >= 0.0)
|
||||
_red = color->_red, dirty = true;
|
||||
if (color && color->_green >= 0.0)
|
||||
_green = color->_green, dirty = true;
|
||||
if (color && color->_blue >= 0.0)
|
||||
_blue = color->_blue, dirty = true;
|
||||
if (color && color->_alpha >= 0.0)
|
||||
_alpha = color->_alpha, dirty = true;
|
||||
return dirty;
|
||||
}
|
||||
|
49
src/GUI/FGColor.hxx
Normal file
49
src/GUI/FGColor.hxx
Normal file
|
@ -0,0 +1,49 @@
|
|||
#ifndef FG_GUI_COLOR_HXX
|
||||
#define FG_GUI_COLOR_HXX
|
||||
|
||||
// forward decls
|
||||
class SGPropertyNode;
|
||||
|
||||
class FGColor {
|
||||
public:
|
||||
FGColor() { clear(); }
|
||||
FGColor(float r, float g, float b, float a = 1.0f) { set(r, g, b, a); }
|
||||
FGColor(const SGPropertyNode *prop) { set(prop); }
|
||||
FGColor(FGColor *c) {
|
||||
if (c) set(c->_red, c->_green, c->_blue, c->_alpha);
|
||||
}
|
||||
|
||||
inline void clear() { _red = _green = _blue = _alpha = -1.0f; }
|
||||
// merges in non-negative components from property with children <red> etc.
|
||||
bool merge(const SGPropertyNode *prop);
|
||||
bool merge(const FGColor *color);
|
||||
|
||||
bool set(const SGPropertyNode *prop) { clear(); return merge(prop); };
|
||||
bool set(const FGColor *color) { clear(); return merge(color); }
|
||||
bool set(float r, float g, float b, float a = 1.0f) {
|
||||
_red = r, _green = g, _blue = b, _alpha = a;
|
||||
return true;
|
||||
}
|
||||
bool isValid() const {
|
||||
return _red >= 0.0 && _green >= 0.0 && _blue >= 0.0;
|
||||
}
|
||||
void print() const;
|
||||
|
||||
inline void setRed(float red) { _red = red; }
|
||||
inline void setGreen(float green) { _green = green; }
|
||||
inline void setBlue(float blue) { _blue = blue; }
|
||||
inline void setAlpha(float alpha) { _alpha = alpha; }
|
||||
|
||||
inline float red() const { return clamp(_red); }
|
||||
inline float green() const { return clamp(_green); }
|
||||
inline float blue() const { return clamp(_blue); }
|
||||
inline float alpha() const { return _alpha < 0.0 ? 1.0 : clamp(_alpha); }
|
||||
|
||||
protected:
|
||||
float _red, _green, _blue, _alpha;
|
||||
|
||||
private:
|
||||
float clamp(float f) const { return f < 0.0 ? 0.0 : f > 1.0 ? 1.0 : f; }
|
||||
};
|
||||
|
||||
#endif
|
223
src/GUI/FGFontCache.cxx
Normal file
223
src/GUI/FGFontCache.cxx
Normal file
|
@ -0,0 +1,223 @@
|
|||
//
|
||||
// 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
|
||||
|
||||
#ifdef HAVE_WINDOWS_H
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "FGFontCache.hxx"
|
||||
|
||||
#include <plib/fnt.h>
|
||||
#include <plib/pu.h>
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// FGFontCache class.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
extern puFont FONT_HELVETICA_14;
|
||||
extern puFont FONT_SANS_12B;
|
||||
|
||||
namespace
|
||||
{
|
||||
struct GuiFont
|
||||
{
|
||||
const char *name;
|
||||
puFont *font;
|
||||
struct Predicate
|
||||
: public std::unary_function<const GuiFont, bool>
|
||||
{
|
||||
Predicate(const char* name_) : name(name_) {}
|
||||
bool operator() (const GuiFont& f1) const
|
||||
{
|
||||
return ::strcmp(f1.name, name) == 0;
|
||||
}
|
||||
const char* name;
|
||||
};
|
||||
};
|
||||
|
||||
const GuiFont guifonts[] = {
|
||||
{ "default", &PUFONT_HELVETICA_12 },
|
||||
{ "FIXED_8x13", &PUFONT_8_BY_13 },
|
||||
{ "FIXED_9x15", &PUFONT_9_BY_15 },
|
||||
{ "TIMES_10", &PUFONT_TIMES_ROMAN_10 },
|
||||
{ "TIMES_24", &PUFONT_TIMES_ROMAN_24 },
|
||||
{ "HELVETICA_10", &PUFONT_HELVETICA_10 },
|
||||
{ "HELVETICA_12", &PUFONT_HELVETICA_12 },
|
||||
{ "HELVETICA_14", &FONT_HELVETICA_14 },
|
||||
{ "HELVETICA_18", &PUFONT_HELVETICA_18 },
|
||||
{ "SANS_12B", &FONT_SANS_12B }
|
||||
};
|
||||
|
||||
const GuiFont* guifontsEnd = &guifonts[sizeof(guifonts)/ sizeof(guifonts[0])];
|
||||
}
|
||||
|
||||
FGFontCache::FGFontCache() :
|
||||
_initialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
FGFontCache::~FGFontCache()
|
||||
{
|
||||
PuFontMap::iterator it, end = _puFonts.end();
|
||||
for (it = _puFonts.begin(); it != end; ++it)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
inline bool FGFontCache::FntParamsLess::operator()(const FntParams& f1,
|
||||
const FntParams& f2) const
|
||||
{
|
||||
int comp = f1.name.compare(f2.name);
|
||||
if (comp < 0)
|
||||
return true;
|
||||
else if (comp > 0)
|
||||
return false;
|
||||
if (f1.size < f2.size)
|
||||
return true;
|
||||
else if (f1.size > f2.size)
|
||||
return false;
|
||||
return f1.slant < f2.slant;
|
||||
}
|
||||
|
||||
struct FGFontCache::fnt *
|
||||
FGFontCache::getfnt(const char *name, float size, float slant)
|
||||
{
|
||||
std::string fontName(name);
|
||||
FntParams fntParams(fontName, size, slant);
|
||||
PuFontMap::iterator i = _puFonts.find(fntParams);
|
||||
if (i != _puFonts.end())
|
||||
return i->second;
|
||||
// fntTexFont s are all preloaded into the _texFonts map
|
||||
TexFontMap::iterator texi = _texFonts.find(fontName);
|
||||
fntTexFont* texfont = 0;
|
||||
puFont* pufont = 0;
|
||||
if (texi != _texFonts.end()) {
|
||||
texfont = texi->second;
|
||||
} else {
|
||||
const GuiFont* guifont = std::find_if(&guifonts[0], guifontsEnd,
|
||||
GuiFont::Predicate(name));
|
||||
if (guifont != guifontsEnd) {
|
||||
pufont = guifont->font;
|
||||
}
|
||||
}
|
||||
fnt* f = new fnt;
|
||||
if (pufont) {
|
||||
f->pufont = pufont;
|
||||
} else if (texfont) {
|
||||
f->texfont = texfont;
|
||||
f->pufont = new puFont;
|
||||
f->pufont->initialize(static_cast<fntFont *>(f->texfont), size, slant);
|
||||
} else {
|
||||
f->pufont = guifonts[0].font;
|
||||
}
|
||||
_puFonts[fntParams] = f;
|
||||
return f;
|
||||
}
|
||||
|
||||
puFont *
|
||||
FGFontCache::get(const char *name, float size, float slant)
|
||||
{
|
||||
return getfnt(name, size, slant)->pufont;
|
||||
}
|
||||
|
||||
fntTexFont *
|
||||
FGFontCache::getTexFont(const char *name, float size, float slant)
|
||||
{
|
||||
init();
|
||||
return getfnt(name, size, slant)->texfont;
|
||||
}
|
||||
|
||||
puFont *
|
||||
FGFontCache::get(SGPropertyNode *node)
|
||||
{
|
||||
if (!node)
|
||||
return get("Helvetica.txf", 15.0, 0.0);
|
||||
|
||||
const char *name = node->getStringValue("name", "Helvetica.txf");
|
||||
float size = node->getFloatValue("size", 15.0);
|
||||
float slant = node->getFloatValue("slant", 0.0);
|
||||
|
||||
return get(name, size, slant);
|
||||
}
|
||||
|
||||
void FGFontCache::init()
|
||||
{
|
||||
if (!_initialized) {
|
||||
char *envp = ::getenv("FG_FONTS");
|
||||
if (envp != NULL) {
|
||||
_path.set(envp);
|
||||
} else {
|
||||
_path.set(globals->get_fg_root());
|
||||
_path.append("Fonts");
|
||||
}
|
||||
_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
SGPath
|
||||
FGFontCache::getfntpath(const char *name)
|
||||
{
|
||||
init();
|
||||
SGPath path(_path);
|
||||
if (name && std::string(name) != "") {
|
||||
path.append(name);
|
||||
if (path.exists())
|
||||
return path;
|
||||
}
|
||||
|
||||
path = SGPath(_path);
|
||||
path.append("Helvetica.txf");
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
bool FGFontCache::initializeFonts()
|
||||
{
|
||||
static std::string fontext("txf");
|
||||
init();
|
||||
ulDir* fontdir = ulOpenDir(_path.c_str());
|
||||
if (!fontdir)
|
||||
return false;
|
||||
const ulDirEnt *dirEntry;
|
||||
while ((dirEntry = ulReadDir(fontdir)) != 0) {
|
||||
SGPath path(_path);
|
||||
path.append(dirEntry->d_name);
|
||||
if (path.extension() == fontext) {
|
||||
fntTexFont* f = new fntTexFont;
|
||||
if (f->load((char *)path.c_str()))
|
||||
_texFonts[std::string(dirEntry->d_name)] = f;
|
||||
else
|
||||
delete f;
|
||||
}
|
||||
}
|
||||
ulCloseDir(fontdir);
|
||||
return true;
|
||||
}
|
||||
|
||||
FGFontCache::fnt::~fnt()
|
||||
{
|
||||
if (texfont) {
|
||||
delete pufont;
|
||||
delete texfont;
|
||||
}
|
||||
}
|
||||
|
96
src/GUI/FGFontCache.hxx
Normal file
96
src/GUI/FGFontCache.hxx
Normal file
|
@ -0,0 +1,96 @@
|
|||
// 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 __FGFONTCACHE_HXX
|
||||
#define __FGFONTCACHE_HXX
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
// forward decls
|
||||
class SGPropertyNode;
|
||||
class puFont;
|
||||
class fntTexFont;
|
||||
|
||||
/**
|
||||
* A class to keep all fonts available for future use.
|
||||
* This also assures a font isn't resident more than once.
|
||||
*/
|
||||
class FGFontCache {
|
||||
private:
|
||||
// The parameters of a request to the cache.
|
||||
struct FntParams
|
||||
{
|
||||
const std::string name;
|
||||
const float size;
|
||||
const float slant;
|
||||
FntParams() : size(0.0f), slant(0.0f) {}
|
||||
FntParams(const FntParams& rhs)
|
||||
: name(rhs.name), size(rhs.size), slant(rhs.slant)
|
||||
{
|
||||
}
|
||||
FntParams(const std::string& name_, float size_, float slant_)
|
||||
: name(name_), size(size_), slant(slant_)
|
||||
{
|
||||
}
|
||||
};
|
||||
struct FntParamsLess
|
||||
: public std::binary_function<const FntParams, const FntParams, bool>
|
||||
{
|
||||
bool operator() (const FntParams& f1, const FntParams& f2) const;
|
||||
};
|
||||
struct fnt {
|
||||
fnt(puFont *pu = 0) : pufont(pu), texfont(0) {}
|
||||
~fnt();
|
||||
|
||||
// Font used by plib GUI code
|
||||
puFont *pufont;
|
||||
// TXF font
|
||||
fntTexFont *texfont;
|
||||
};
|
||||
// Path to the font directory
|
||||
SGPath _path;
|
||||
|
||||
typedef std::map<const std::string, fntTexFont*> TexFontMap;
|
||||
typedef std::map<const FntParams, fnt*, FntParamsLess> PuFontMap;
|
||||
TexFontMap _texFonts;
|
||||
PuFontMap _puFonts;
|
||||
|
||||
bool _initialized;
|
||||
struct fnt *getfnt(const char *name, float size, float slant);
|
||||
void init();
|
||||
|
||||
public:
|
||||
FGFontCache();
|
||||
~FGFontCache();
|
||||
|
||||
puFont *get(const char *name, float size=15.0, float slant=0.0);
|
||||
puFont *get(SGPropertyNode *node);
|
||||
|
||||
fntTexFont *getTexFont(const char *name, float size=15.0, float slant=0.0);
|
||||
|
||||
SGPath getfntpath(const char *name);
|
||||
/**
|
||||
* Preload all the fonts in the FlightGear font directory. It is
|
||||
* important to load the font textures early, with the proper
|
||||
* graphics context current, so that no plib (or our own) code
|
||||
* tries to load a font from disk when there's no current graphics
|
||||
* context.
|
||||
*/
|
||||
bool initializeFonts();
|
||||
};
|
||||
#endif
|
1418
src/GUI/FGPUIDialog.cxx
Normal file
1418
src/GUI/FGPUIDialog.cxx
Normal file
File diff suppressed because it is too large
Load diff
277
src/GUI/FGPUIDialog.hxx
Normal file
277
src/GUI/FGPUIDialog.hxx
Normal file
|
@ -0,0 +1,277 @@
|
|||
// FGPUIDialog.hxx - XML-configured dialog box.
|
||||
|
||||
#ifndef FG_PUI_DIALOG_HXX
|
||||
#define FG_PUI_DIALOG_HXX 1
|
||||
|
||||
#include "dialog.hxx"
|
||||
|
||||
#include <plib/puAux.h>
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/props/condition.hxx>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
// ugly temporary workaround for plib's lack of user defined class ids FIXME
|
||||
#define FGCLASS_LIST 0x00000001
|
||||
#define FGCLASS_AIRPORTLIST 0x00000002
|
||||
#define FGCLASS_PROPERTYLIST 0x00000004
|
||||
#define FGCLASS_WAYPOINTLIST 0x00000008
|
||||
|
||||
class GUI_ID { public: GUI_ID(int id) : id(id) {} virtual ~GUI_ID() {} int id; };
|
||||
|
||||
|
||||
|
||||
class NewGUI;
|
||||
class FGColor;
|
||||
class puObject;
|
||||
class puFont;
|
||||
|
||||
/**
|
||||
* An XML-configured dialog box.
|
||||
*
|
||||
* The GUI manager stores only the property tree for the dialog
|
||||
* boxes. This class creates a PUI dialog box on demand from
|
||||
* the properties in that tree. The manager recreates the dialog
|
||||
* every time it needs to show it.
|
||||
*/
|
||||
class FGPUIDialog : public FGDialog
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Construct a new GUI widget configured by a property tree.
|
||||
*
|
||||
* The configuration properties are not part of the main
|
||||
* FlightGear property tree; the GUI manager reads them
|
||||
* from individual configuration files.
|
||||
*
|
||||
* @param props A property tree describing the dialog.
|
||||
*/
|
||||
FGPUIDialog (SGPropertyNode * props);
|
||||
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~FGPUIDialog ();
|
||||
|
||||
|
||||
/**
|
||||
* Update the values of all GUI objects with a specific name,
|
||||
* or all if name is 0 (default).
|
||||
*
|
||||
* This method copies values from the FlightGear property tree to
|
||||
* the GUI object(s).
|
||||
*
|
||||
* @param objectName The name of the GUI object(s) to update.
|
||||
* Use the empty name for all unnamed objects.
|
||||
*/
|
||||
virtual void updateValues (const char * objectName = 0);
|
||||
|
||||
|
||||
/**
|
||||
* Apply the values of all GUI objects with a specific name,
|
||||
* or all if name is 0 (default)
|
||||
*
|
||||
* This method copies values from the GUI object(s) to the
|
||||
* FlightGear property tree.
|
||||
*
|
||||
* @param objectName The name of the GUI object(s) to update.
|
||||
* Use the empty name for all unnamed objects.
|
||||
*/
|
||||
virtual void applyValues (const char * objectName = 0);
|
||||
|
||||
|
||||
/**
|
||||
* Update state. Called on active dialogs before rendering.
|
||||
*/
|
||||
virtual void update ();
|
||||
|
||||
/**
|
||||
* Recompute the dialog's layout
|
||||
*/
|
||||
void relayout();
|
||||
|
||||
|
||||
void setNeedsLayout() {
|
||||
_needsRelayout = true;
|
||||
}
|
||||
private:
|
||||
|
||||
enum {
|
||||
BACKGROUND = 0x01,
|
||||
FOREGROUND = 0x02,
|
||||
HIGHLIGHT = 0x04,
|
||||
LABEL = 0x08,
|
||||
LEGEND = 0x10,
|
||||
MISC = 0x20,
|
||||
EDITFIELD = 0x40
|
||||
};
|
||||
|
||||
// Show the dialog.
|
||||
void display (SGPropertyNode * props);
|
||||
|
||||
// Build the dialog or a subobject of it.
|
||||
puObject * makeObject (SGPropertyNode * props,
|
||||
int parentWidth, int parentHeight);
|
||||
|
||||
// Common configuration for all GUI objects.
|
||||
void setupObject (puObject * object, SGPropertyNode * props);
|
||||
|
||||
// Common configuration for all GUI group objects.
|
||||
void setupGroup (puGroup * group, SGPropertyNode * props,
|
||||
int width, int height, bool makeFrame = false);
|
||||
|
||||
// Set object colors: the "which" argument defines which color qualities
|
||||
// (PUCOL_LABEL, etc.) should pick up the <color> property.
|
||||
void setColor(puObject * object, SGPropertyNode * props, int which = 0);
|
||||
|
||||
// return key code number for keystring
|
||||
int getKeyCode(const char *keystring);
|
||||
|
||||
/**
|
||||
* Apply layout sizes to a tree of puObjects
|
||||
*/
|
||||
void applySize(puObject *object);
|
||||
|
||||
// The top-level PUI object.
|
||||
puObject * _object;
|
||||
|
||||
// The GUI subsystem.
|
||||
NewGUI * _gui;
|
||||
|
||||
// The dialog font. Defaults to the global gui font, but can get
|
||||
// overridden by a top level font definition.
|
||||
puFont * _font;
|
||||
|
||||
// The source xml tree, so that we can pass data back, such as the
|
||||
// last position.
|
||||
SGPropertyNode_ptr _props;
|
||||
|
||||
bool _needsRelayout;
|
||||
|
||||
// Nasal module.
|
||||
std::string _module;
|
||||
SGPropertyNode_ptr _nasal_close;
|
||||
|
||||
// PUI provides no way for userdata to be deleted automatically
|
||||
// with a GUI object, so we have to keep track of all the special
|
||||
// data we allocated and then free it manually when the dialog
|
||||
// closes.
|
||||
std::vector<void *> _info;
|
||||
struct PropertyObject {
|
||||
PropertyObject (const char * name,
|
||||
puObject * object,
|
||||
SGPropertyNode_ptr node);
|
||||
std::string name;
|
||||
puObject * object;
|
||||
SGPropertyNode_ptr node;
|
||||
};
|
||||
std::vector<PropertyObject *> _propertyObjects;
|
||||
std::vector<PropertyObject *> _liveObjects;
|
||||
|
||||
class ConditionalObject : public SGConditional
|
||||
{
|
||||
public:
|
||||
ConditionalObject(const std::string& aName, puObject* aPu) :
|
||||
_name(aName),
|
||||
_pu(aPu)
|
||||
{ ; }
|
||||
|
||||
void update(FGPUIDialog* aDlg);
|
||||
|
||||
private:
|
||||
const std::string _name;
|
||||
puObject* _pu;
|
||||
};
|
||||
|
||||
typedef SGSharedPtr<ConditionalObject> ConditionalObjectRef;
|
||||
std::vector<ConditionalObjectRef> _conditionalObjects;
|
||||
};
|
||||
|
||||
//
|
||||
// Custom subclass of puPopup to implement "draggable" windows in the
|
||||
// interface. Note that this is a subclass of puPopup, not
|
||||
// puDialogBox. Sadly, PUI (mis)uses subclassing to implement a
|
||||
// boolean property: modality. That means that we can't implement
|
||||
// dragging of both puPopup windows and puDialogBoxes with the same
|
||||
// code. Rather than duplicate code, I've chosen to implement only
|
||||
// "non-modal dragability" here. Modal dialog boxes (like the exit
|
||||
// confirmation) are not draggable.
|
||||
//
|
||||
class fgPopup : public puPopup {
|
||||
public:
|
||||
fgPopup(int x, int y, bool r = true, bool d = true) :
|
||||
puPopup(x, y), _draggable(d), _resizable(r), _dragging(false)
|
||||
{}
|
||||
int checkHit(int b, int up, int x, int y);
|
||||
int checkKey(int key, int updown);
|
||||
int getHitObjects(puObject *, int x, int y);
|
||||
puObject *getKeyObject(puObject *, int key);
|
||||
puObject *getActiveInputField(puObject *);
|
||||
void applySize(puObject *);
|
||||
private:
|
||||
enum { LEFT = 1, RIGHT = 2, TOP = 4, BOTTOM = 8 };
|
||||
bool _draggable;
|
||||
bool _resizable;
|
||||
bool _dragging;
|
||||
int _resizing;
|
||||
int _start_cursor;
|
||||
int _cursor;
|
||||
int _dlgX, _dlgY, _dlgW, _dlgH;
|
||||
int _startX, _startY;
|
||||
};
|
||||
|
||||
|
||||
class fgValueList {
|
||||
public:
|
||||
fgValueList(SGPropertyNode *p);
|
||||
virtual ~fgValueList();
|
||||
virtual void update();
|
||||
|
||||
protected:
|
||||
char **_list;
|
||||
|
||||
private:
|
||||
void make_list();
|
||||
void destroy_list();
|
||||
SGPropertyNode_ptr _props;
|
||||
};
|
||||
|
||||
|
||||
class fgList : public fgValueList, public puaList, public GUI_ID {
|
||||
public:
|
||||
fgList(int x1, int y1, int x2, int y2, SGPropertyNode *p, int sw) :
|
||||
fgValueList(p), puaList(x1, y1, x2, y2, _list, sw), GUI_ID(FGCLASS_LIST) {}
|
||||
void update();
|
||||
};
|
||||
|
||||
class fgComboBox : public fgValueList, public puaComboBox {
|
||||
public:
|
||||
fgComboBox(int x1, int y1, int x2, int y2, SGPropertyNode *p, bool editable) :
|
||||
fgValueList(p),
|
||||
puaComboBox(x1, y1, x2, y2, _list, editable),
|
||||
_inHit(false)
|
||||
{}
|
||||
|
||||
void update();
|
||||
|
||||
virtual void setSize(int w, int h);
|
||||
|
||||
virtual int checkHit(int b, int up, int x, int y);
|
||||
|
||||
virtual void recalc_bbox();
|
||||
private:
|
||||
bool _inHit;
|
||||
};
|
||||
|
||||
class fgSelectBox : public fgValueList, public puaSelectBox {
|
||||
public:
|
||||
fgSelectBox(int x1, int y1, int x2, int y2, SGPropertyNode *p) :
|
||||
fgValueList(p), puaSelectBox(x1, y1, x2, y2, _list) {}
|
||||
};
|
||||
|
||||
#endif // __DIALOG_HXX
|
376
src/GUI/FGPUIMenuBar.cxx
Normal file
376
src/GUI/FGPUIMenuBar.cxx
Normal file
|
@ -0,0 +1,376 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <plib/pu.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/structure/SGBinding.hxx>
|
||||
#include <simgear/props/props_io.hxx>
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
#include "new_gui.hxx"
|
||||
#include "FGPUIMenuBar.hxx"
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::map;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// FIXME!!
|
||||
//
|
||||
// Deprecated wrappers for old menu commands.
|
||||
//
|
||||
// DO NOT ADD TO THESE. THEY WILL BE DELETED SOON!
|
||||
//
|
||||
// These are defined in gui_funcs.cxx. They should be replaced with
|
||||
// user-configured dialogs and new commands where necessary.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(TR_HIRES_SNAP)
|
||||
extern void dumpHiResSnapShot ();
|
||||
static bool
|
||||
do_hires_snapshot_dialog (const SGPropertyNode * arg)
|
||||
{
|
||||
dumpHiResSnapShot();
|
||||
return true;
|
||||
}
|
||||
#endif // TR_HIRES_SNAP
|
||||
|
||||
static struct {
|
||||
const char * name;
|
||||
SGCommandMgr::command_t command;
|
||||
} deprecated_dialogs [] = {
|
||||
#if defined(TR_HIRES_SNAP)
|
||||
{ "old-hires-snapshot-dialog", do_hires_snapshot_dialog },
|
||||
#endif
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static void
|
||||
add_deprecated_dialogs ()
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Initializing old dialog commands:");
|
||||
for (int i = 0; deprecated_dialogs[i].name != 0; i++) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, " " << deprecated_dialogs[i].name);
|
||||
globals->get_commands()->addCommand(deprecated_dialogs[i].name,
|
||||
deprecated_dialogs[i].command);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Static functions.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static void
|
||||
menu_callback (puObject * object)
|
||||
{
|
||||
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
|
||||
FGPUIMenuBar* mb = static_cast<FGPUIMenuBar*>(gui->getMenuBar());
|
||||
mb->fireItem(object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGPUIMenuBar.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
FGPUIMenuBar::FGPUIMenuBar ()
|
||||
: _visible(false),
|
||||
_menuBar(0)
|
||||
{
|
||||
}
|
||||
|
||||
FGPUIMenuBar::~FGPUIMenuBar ()
|
||||
{
|
||||
destroy_menubar();
|
||||
}
|
||||
|
||||
void
|
||||
FGPUIMenuBar::init ()
|
||||
{
|
||||
delete _menuBar; // FIXME: check if PUI owns the pointer
|
||||
make_menubar();
|
||||
// FIXME: temporary commands to get at
|
||||
// old, hard-coded dialogs.
|
||||
add_deprecated_dialogs();
|
||||
}
|
||||
|
||||
void
|
||||
FGPUIMenuBar::show ()
|
||||
{
|
||||
if (_menuBar != 0)
|
||||
_menuBar->reveal();
|
||||
_visible = true;
|
||||
}
|
||||
|
||||
void
|
||||
FGPUIMenuBar::hide ()
|
||||
{
|
||||
if (_menuBar != 0)
|
||||
_menuBar->hide();
|
||||
_visible = false;
|
||||
}
|
||||
|
||||
bool
|
||||
FGPUIMenuBar::isVisible () const
|
||||
{
|
||||
return _visible;
|
||||
}
|
||||
|
||||
void
|
||||
FGPUIMenuBar::fireItem (puObject * item)
|
||||
{
|
||||
const char * name = item->getLegend();
|
||||
vector<SGBinding *> &bindings = _bindings[name];
|
||||
int nBindings = bindings.size();
|
||||
|
||||
for (int i = 0; i < nBindings; i++)
|
||||
bindings[i]->fire();
|
||||
}
|
||||
|
||||
void
|
||||
FGPUIMenuBar::make_menu (SGPropertyNode * node)
|
||||
{
|
||||
const char * name = strdup(node->getStringValue("label"));
|
||||
vector<SGPropertyNode_ptr> item_nodes = node->getChildren("item");
|
||||
|
||||
int array_size = item_nodes.size();
|
||||
|
||||
char ** items = make_char_array(array_size);
|
||||
puCallback * callbacks = make_callback_array(array_size);
|
||||
|
||||
for (unsigned int i = 0, j = item_nodes.size() - 1;
|
||||
i < item_nodes.size();
|
||||
i++, j--) {
|
||||
|
||||
// Set up the PUI entries for this item
|
||||
items[j] = strdup((char *)item_nodes[i]->getStringValue("label"));
|
||||
callbacks[j] = menu_callback;
|
||||
|
||||
// Load all the bindings for this item
|
||||
vector<SGPropertyNode_ptr> bindings = item_nodes[i]->getChildren("binding");
|
||||
SGPropertyNode * dest = fgGetNode("/sim/bindings/menu", true);
|
||||
|
||||
for (unsigned int k = 0; k < bindings.size(); k++) {
|
||||
unsigned int m = 0;
|
||||
SGPropertyNode_ptr binding;
|
||||
while (dest->getChild("binding", m))
|
||||
m++;
|
||||
|
||||
binding = dest->getChild("binding", m, true);
|
||||
copyProperties(bindings[k], binding);
|
||||
_bindings[items[j]].push_back(new SGBinding(binding, globals->get_props()));
|
||||
}
|
||||
}
|
||||
|
||||
_menuBar->add_submenu(name, items, callbacks);
|
||||
}
|
||||
|
||||
void
|
||||
FGPUIMenuBar::make_menubar ()
|
||||
{
|
||||
SGPropertyNode *targetpath;
|
||||
|
||||
targetpath = fgGetNode("/sim/menubar/default",true);
|
||||
// fgLoadProps("gui/menubar.xml", targetpath);
|
||||
|
||||
/* NOTE: there is no check to see whether there's any usable data at all
|
||||
*
|
||||
* This would also have the advantage of being able to create some kind of
|
||||
* 'fallback' menu - just in case that either menubar.xml is empty OR that
|
||||
* its XML data is not valid, that way we would avoid displaying an
|
||||
* unusable menubar without any functionality - if we decided to add another
|
||||
* char * element to the commands structure in
|
||||
* $FG_SRC/src/Main/fgcommands.cxx
|
||||
* we could additionally save each function's (short) description and use
|
||||
* this as label for the fallback PUI menubar item labels - as a workaround
|
||||
* one might simply use the internal fgcommands and put them into the
|
||||
* fallback menu, so that the user is at least able to re-init the menu
|
||||
* loading - just in case there was some malformed XML in it
|
||||
* (it happend to me ...)
|
||||
*/
|
||||
|
||||
make_menubar(targetpath);
|
||||
}
|
||||
|
||||
/* WARNING: We aren't yet doing any validation of what's found - but since
|
||||
* this isn't done with menubar.xml either, it should not really matter
|
||||
* right now. Although one should later on consider to validate the
|
||||
* contents, whether they are representing a 'legal' menubar structure.
|
||||
*/
|
||||
void
|
||||
FGPUIMenuBar::make_menubar(SGPropertyNode * props)
|
||||
{
|
||||
// Just in case.
|
||||
destroy_menubar();
|
||||
_menuBar = new puMenuBar;
|
||||
|
||||
vector<SGPropertyNode_ptr> menu_nodes = props->getChildren("menu");
|
||||
for (unsigned int i = 0; i < menu_nodes.size(); i++)
|
||||
make_menu(menu_nodes[i]);
|
||||
|
||||
_menuBar->close();
|
||||
make_object_map(props);
|
||||
|
||||
if (_visible)
|
||||
_menuBar->reveal();
|
||||
else
|
||||
_menuBar->hide();
|
||||
}
|
||||
|
||||
void
|
||||
FGPUIMenuBar::destroy_menubar ()
|
||||
{
|
||||
if ( _menuBar == 0 )
|
||||
return;
|
||||
|
||||
hide();
|
||||
puDeleteObject(_menuBar);
|
||||
|
||||
unsigned int i;
|
||||
|
||||
// Delete all the character arrays
|
||||
// we were forced to keep around for
|
||||
// plib.
|
||||
SG_LOG(SG_GENERAL, SG_BULK, "Deleting char arrays");
|
||||
for (i = 0; i < _char_arrays.size(); i++) {
|
||||
for (int j = 0; _char_arrays[i][j] != 0; j++)
|
||||
free(_char_arrays[i][j]); // added with strdup
|
||||
delete[] _char_arrays[i];
|
||||
}
|
||||
|
||||
// Delete all the callback arrays
|
||||
// we were forced to keep around for
|
||||
// plib.
|
||||
SG_LOG(SG_GENERAL, SG_BULK, "Deleting callback arrays");
|
||||
for (i = 0; i < _callback_arrays.size(); i++)
|
||||
delete[] _callback_arrays[i];
|
||||
|
||||
// Delete all those bindings
|
||||
SG_LOG(SG_GENERAL, SG_BULK, "Deleting bindings");
|
||||
map<string,vector<SGBinding *> >::iterator it;
|
||||
for (it = _bindings.begin(); it != _bindings.end(); it++) {
|
||||
SG_LOG(SG_GENERAL, SG_BULK, "Deleting bindings for " << it->first);
|
||||
for ( i = 0; i < it->second.size(); i++ )
|
||||
delete it->second[i];
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_BULK, "Done.");
|
||||
}
|
||||
|
||||
void
|
||||
FGPUIMenuBar::make_object_map(SGPropertyNode * node)
|
||||
{
|
||||
unsigned int menu_index = 0;
|
||||
vector<SGPropertyNode_ptr> menus = node->getChildren("menu");
|
||||
for (puObject *obj = ((puGroup *)_menuBar)->getFirstChild();
|
||||
obj; obj = obj->getNextObject()) {
|
||||
|
||||
// skip puPopupMenus. They are also children of _menuBar,
|
||||
// but we access them via getUserData() (see below)
|
||||
if (!(obj->getType() & PUCLASS_ONESHOT))
|
||||
continue;
|
||||
|
||||
if (menu_index >= menus.size()) {
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "'menu' object without node: "
|
||||
<< node->getPath() << "/menu[" << menu_index << ']');
|
||||
return;
|
||||
}
|
||||
|
||||
SGPropertyNode *menu = menus.at(menu_index);
|
||||
_objects[menu->getPath()] = obj;
|
||||
add_enabled_listener(menu);
|
||||
|
||||
puGroup *popup = (puGroup *)obj->getUserData();
|
||||
if (!popup)
|
||||
continue;
|
||||
|
||||
// the entries are for some reason reversed (last first), and we
|
||||
// don't know yet how many there will be; so we collect first
|
||||
vector<puObject *> e;
|
||||
for (puObject *me = popup->getFirstChild(); me; me = me->getNextObject())
|
||||
e.push_back(me);
|
||||
|
||||
vector<SGPropertyNode_ptr> items = menu->getChildren("item");
|
||||
for (unsigned int i = 0; i < e.size(); i++) {
|
||||
if (i >= items.size()) {
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "'item' object without node: "
|
||||
<< menu->getPath() << "/item[" << i << ']');
|
||||
break;
|
||||
}
|
||||
SGPropertyNode *item = items.at(e.size() - i - 1);
|
||||
_objects[item->getPath()] = e[i];
|
||||
add_enabled_listener(item);
|
||||
}
|
||||
menu_index++;
|
||||
}
|
||||
}
|
||||
|
||||
struct EnabledListener : SGPropertyChangeListener {
|
||||
void valueChanged(SGPropertyNode *node) {
|
||||
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
|
||||
if (!gui)
|
||||
return;
|
||||
FGPUIMenuBar* menubar = static_cast<FGPUIMenuBar*>(gui->getMenuBar());
|
||||
if (menubar)
|
||||
menubar->enable_item(node->getParent(), node->getBoolValue());
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
FGPUIMenuBar::add_enabled_listener(SGPropertyNode * node)
|
||||
{
|
||||
if (!node->hasValue("enabled"))
|
||||
node->setBoolValue("enabled", true);
|
||||
|
||||
enable_item(node, node->getBoolValue("enabled"));
|
||||
node->getNode("enabled")->addChangeListener(new EnabledListener());
|
||||
}
|
||||
|
||||
bool
|
||||
FGPUIMenuBar::enable_item(const SGPropertyNode * node, bool state)
|
||||
{
|
||||
string path = node->getPath();
|
||||
if (_objects.find(path) == _objects.end()) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Trying to enable/disable "
|
||||
"non-existent menu item for node `" << path << '\'');
|
||||
return false;
|
||||
}
|
||||
puObject *object = _objects[path];
|
||||
if (state)
|
||||
object->activate();
|
||||
else
|
||||
object->greyOut();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char **
|
||||
FGPUIMenuBar::make_char_array (int size)
|
||||
{
|
||||
char ** list = new char*[size+1];
|
||||
for (int i = 0; i <= size; i++)
|
||||
list[i] = 0;
|
||||
_char_arrays.push_back(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
puCallback *
|
||||
FGPUIMenuBar::make_callback_array (int size)
|
||||
{
|
||||
puCallback * list = new puCallback[size+1];
|
||||
for (int i = 0; i <= size; i++)
|
||||
list[i] = 0;
|
||||
_callback_arrays.push_back(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
// end of menubar.cxx
|
138
src/GUI/FGPUIMenuBar.hxx
Normal file
138
src/GUI/FGPUIMenuBar.hxx
Normal file
|
@ -0,0 +1,138 @@
|
|||
// menubar.hxx - XML-configured menu bar.
|
||||
|
||||
#ifndef FG_PUI_MENUBAR_HXX
|
||||
#define FG_PUI_MENUBAR_HXX 1
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
#include <GUI/menubar.hxx>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
// forward decls, avoid pulling in PLIB headers here
|
||||
class puMenuBar;
|
||||
class puObject;
|
||||
class SGPropertyNode;
|
||||
class SGBinding;
|
||||
|
||||
typedef void (*puCallback)(class puObject *) ;
|
||||
|
||||
/**
|
||||
* XML-configured PUI menu bar.
|
||||
*
|
||||
* This class creates a menu bar from a tree of XML properties. These
|
||||
* properties are not part of the main FlightGear property tree, but
|
||||
* are read from a separate file ($FG_ROOT/gui/menubar.xml).
|
||||
*
|
||||
* WARNING: because PUI provides no easy way to attach user data to a
|
||||
* menu item, all menu item strings must be unique; otherwise, this
|
||||
* class will always use the first binding with any given name.
|
||||
*/
|
||||
class FGPUIMenuBar : public FGMenuBar
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
FGPUIMenuBar ();
|
||||
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~FGPUIMenuBar ();
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the menu bar from $FG_ROOT/gui/menubar.xml
|
||||
*/
|
||||
virtual void init ();
|
||||
|
||||
/**
|
||||
* Make the menu bar visible.
|
||||
*/
|
||||
virtual void show ();
|
||||
|
||||
|
||||
/**
|
||||
* Make the menu bar invisible.
|
||||
*/
|
||||
virtual void hide ();
|
||||
|
||||
|
||||
/**
|
||||
* Test whether the menu bar is visible.
|
||||
*/
|
||||
virtual bool isVisible () const;
|
||||
|
||||
|
||||
/**
|
||||
* IGNORE THIS METHOD!!!
|
||||
*
|
||||
* This is necessary only because plib does not provide any easy
|
||||
* way to attach user data to a menu item. FlightGear should not
|
||||
* have to know about PUI internals, but this method allows the
|
||||
* callback to pass the menu item one-shot on to the current menu.
|
||||
*/
|
||||
virtual void fireItem (puObject * item);
|
||||
|
||||
|
||||
/**
|
||||
* create a menubar based on a PropertyList within the PropertyTree
|
||||
*/
|
||||
void make_menubar (SGPropertyNode * props);
|
||||
|
||||
|
||||
/**
|
||||
* destroy a menubar based on a PropertyList within the PropertyTree
|
||||
*/
|
||||
void destroy_menubar ();
|
||||
|
||||
|
||||
/**
|
||||
* Disable/enable menu titles and entries
|
||||
*/
|
||||
bool enable_item (const SGPropertyNode * item, bool state);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Make a single menu.
|
||||
void make_menu (SGPropertyNode * node);
|
||||
|
||||
// Make the top-level menubar.
|
||||
void make_menubar ();
|
||||
|
||||
// Create a property-path -> puObject map for menu node
|
||||
void make_object_map(SGPropertyNode * node);
|
||||
|
||||
// Add <enabled> listener that enables/disables menu entries.
|
||||
void add_enabled_listener(SGPropertyNode * node);
|
||||
|
||||
// Is the menu visible?
|
||||
bool _visible;
|
||||
|
||||
// The top-level menubar itself.
|
||||
puMenuBar * _menuBar;
|
||||
|
||||
// A map of bindings for the menubar.
|
||||
std::map<std::string,std::vector<SGBinding *> > _bindings;
|
||||
|
||||
// These are hoops that we have to jump through because PUI doesn't
|
||||
// do memory management for lists. We have to allocate the arrays,
|
||||
// hang onto pointers, and then delete them when the menubar is
|
||||
// freed.
|
||||
char ** make_char_array (int size);
|
||||
puCallback * make_callback_array (int size);
|
||||
std::vector<char **> _char_arrays;
|
||||
std::vector<puCallback *> _callback_arrays;
|
||||
|
||||
// A map for {menu node path}->puObject translation.
|
||||
std::map<std::string, puObject *> _objects;
|
||||
};
|
||||
|
||||
#endif // __MENUBAR_HXX
|
|
@ -374,7 +374,7 @@ int MapData::_fontDescender = 0;
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
const int MAX_ZOOM = 16;
|
||||
const int MAX_ZOOM = 12;
|
||||
const int SHOW_DETAIL_ZOOM = 8;
|
||||
const int CURSOR_PAN_STEP = 32;
|
||||
|
||||
|
@ -403,11 +403,13 @@ MapWidget::~MapWidget()
|
|||
void MapWidget::setProperty(SGPropertyNode_ptr prop)
|
||||
{
|
||||
_root = prop;
|
||||
int zoom = _root->getBoolValue("zoom", -1);
|
||||
int zoom = _root->getIntValue("zoom", -1);
|
||||
if (zoom < 0) {
|
||||
_root->setIntValue("zoom", 6); // default zoom
|
||||
}
|
||||
|
||||
// expose MAX_ZOOM to the UI
|
||||
_root->setIntValue("max-zoom", MAX_ZOOM);
|
||||
_root->setBoolValue("centre-on-aircraft", true);
|
||||
_root->setBoolValue("draw-data", false);
|
||||
_root->setBoolValue("magnetic-headings", true);
|
||||
|
@ -515,15 +517,6 @@ int MapWidget::zoom() const
|
|||
}
|
||||
|
||||
void MapWidget::zoomIn()
|
||||
{
|
||||
if (zoom() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
_root->setIntValue("zoom", zoom() - 1);
|
||||
}
|
||||
|
||||
void MapWidget::zoomOut()
|
||||
{
|
||||
if (zoom() >= MAX_ZOOM) {
|
||||
return;
|
||||
|
@ -532,6 +525,15 @@ void MapWidget::zoomOut()
|
|||
_root->setIntValue("zoom", zoom() + 1);
|
||||
}
|
||||
|
||||
void MapWidget::zoomOut()
|
||||
{
|
||||
if (zoom() <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
_root->setIntValue("zoom", zoom() - 1);
|
||||
}
|
||||
|
||||
void MapWidget::draw(int dx, int dy)
|
||||
{
|
||||
_aircraft = SGGeod::fromDeg(fgGetDouble("/position/longitude-deg"),
|
||||
|
@ -561,7 +563,7 @@ void MapWidget::draw(int dx, int dy)
|
|||
_upHeading = 0.0;
|
||||
}
|
||||
|
||||
_cachedZoom = zoom();
|
||||
_cachedZoom = MAX_ZOOM - zoom();
|
||||
SGGeod topLeft = unproject(SGVec2d(_width/2, _height/2));
|
||||
// compute draw range, including a fudge factor for ILSs and other 'long'
|
||||
// symbols
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
#include <plib/pu.h>
|
||||
|
||||
#include "dialog.hxx" // for GUI_ID
|
||||
#include "FGPUIDialog.hxx" // for GUI_ID
|
||||
|
||||
// forward decls
|
||||
class puaScrollBar;
|
||||
|
|
1398
src/GUI/dialog.cxx
1398
src/GUI/dialog.cxx
File diff suppressed because it is too large
Load diff
|
@ -7,31 +7,8 @@
|
|||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
#include <plib/puAux.h>
|
||||
|
||||
#include <simgear/compiler.h> // for SG_USING_STD
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/props/condition.hxx>
|
||||
|
||||
#include <vector>
|
||||
using std::vector;
|
||||
|
||||
|
||||
// ugly temporary workaround for plib's lack of user defined class ids FIXME
|
||||
#define FGCLASS_LIST 0x00000001
|
||||
#define FGCLASS_AIRPORTLIST 0x00000002
|
||||
#define FGCLASS_PROPERTYLIST 0x00000004
|
||||
#define FGCLASS_WAYPOINTLIST 0x00000008
|
||||
|
||||
class GUI_ID { public: GUI_ID(int id) : id(id) {} virtual ~GUI_ID() {} int id; };
|
||||
|
||||
|
||||
|
||||
class FGDialog;
|
||||
class NewGUI;
|
||||
class FGColor;
|
||||
|
||||
// forward decls
|
||||
class SGPropertyNode;
|
||||
|
||||
/**
|
||||
* An XML-configured dialog box.
|
||||
|
@ -45,16 +22,6 @@ class FGDialog
|
|||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Construct a new GUI widget configured by a property tree.
|
||||
*
|
||||
* The configuration properties are not part of the main
|
||||
* FlightGear property tree; the GUI manager reads them
|
||||
* from individual configuration files.
|
||||
*
|
||||
* @param props A property tree describing the dialog.
|
||||
*/
|
||||
FGDialog (SGPropertyNode * props);
|
||||
|
||||
|
||||
/**
|
||||
|
@ -73,7 +40,7 @@ public:
|
|||
* @param objectName The name of the GUI object(s) to update.
|
||||
* Use the empty name for all unnamed objects.
|
||||
*/
|
||||
virtual void updateValues (const char * objectName = 0);
|
||||
virtual void updateValues (const char * objectName = 0) = 0;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -86,199 +53,28 @@ public:
|
|||
* @param objectName The name of the GUI object(s) to update.
|
||||
* Use the empty name for all unnamed objects.
|
||||
*/
|
||||
virtual void applyValues (const char * objectName = 0);
|
||||
virtual void applyValues (const char * objectName = 0) = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Update state. Called on active dialogs before rendering.
|
||||
*/
|
||||
virtual void update ();
|
||||
|
||||
/**
|
||||
* Recompute the dialog's layout
|
||||
*/
|
||||
void relayout();
|
||||
|
||||
|
||||
void setNeedsLayout() {
|
||||
_needsRelayout = true;
|
||||
}
|
||||
private:
|
||||
|
||||
enum {
|
||||
BACKGROUND = 0x01,
|
||||
FOREGROUND = 0x02,
|
||||
HIGHLIGHT = 0x04,
|
||||
LABEL = 0x08,
|
||||
LEGEND = 0x10,
|
||||
MISC = 0x20,
|
||||
EDITFIELD = 0x40
|
||||
};
|
||||
|
||||
// Private copy constructor to avoid unpleasant surprises.
|
||||
FGDialog (const FGDialog &);
|
||||
|
||||
// Show the dialog.
|
||||
void display (SGPropertyNode * props);
|
||||
|
||||
// Build the dialog or a subobject of it.
|
||||
puObject * makeObject (SGPropertyNode * props,
|
||||
int parentWidth, int parentHeight);
|
||||
|
||||
// Common configuration for all GUI objects.
|
||||
void setupObject (puObject * object, SGPropertyNode * props);
|
||||
|
||||
// Common configuration for all GUI group objects.
|
||||
void setupGroup (puGroup * group, SGPropertyNode * props,
|
||||
int width, int height, bool makeFrame = false);
|
||||
|
||||
// Set object colors: the "which" argument defines which color qualities
|
||||
// (PUCOL_LABEL, etc.) should pick up the <color> property.
|
||||
void setColor(puObject * object, SGPropertyNode * props, int which = 0);
|
||||
|
||||
// return key code number for keystring
|
||||
int getKeyCode(const char *keystring);
|
||||
|
||||
/**
|
||||
* Apply layout sizes to a tree of puObjects
|
||||
*/
|
||||
void applySize(puObject *object);
|
||||
|
||||
// The top-level PUI object.
|
||||
puObject * _object;
|
||||
|
||||
// The GUI subsystem.
|
||||
NewGUI * _gui;
|
||||
|
||||
// The dialog font. Defaults to the global gui font, but can get
|
||||
// overridden by a top level font definition.
|
||||
puFont * _font;
|
||||
|
||||
// The source xml tree, so that we can pass data back, such as the
|
||||
// last position.
|
||||
SGPropertyNode_ptr _props;
|
||||
|
||||
bool _needsRelayout;
|
||||
|
||||
// Nasal module.
|
||||
std::string _module;
|
||||
SGPropertyNode_ptr _nasal_close;
|
||||
|
||||
// PUI provides no way for userdata to be deleted automatically
|
||||
// with a GUI object, so we have to keep track of all the special
|
||||
// data we allocated and then free it manually when the dialog
|
||||
// closes.
|
||||
vector<void *> _info;
|
||||
struct PropertyObject {
|
||||
PropertyObject (const char * name,
|
||||
puObject * object,
|
||||
SGPropertyNode_ptr node);
|
||||
std::string name;
|
||||
puObject * object;
|
||||
SGPropertyNode_ptr node;
|
||||
};
|
||||
vector<PropertyObject *> _propertyObjects;
|
||||
vector<PropertyObject *> _liveObjects;
|
||||
|
||||
class ConditionalObject : public SGConditional
|
||||
{
|
||||
public:
|
||||
ConditionalObject(const std::string& aName, puObject* aPu) :
|
||||
_name(aName),
|
||||
_pu(aPu)
|
||||
{ ; }
|
||||
|
||||
void update(FGDialog* aDlg);
|
||||
|
||||
private:
|
||||
const std::string _name;
|
||||
puObject* _pu;
|
||||
};
|
||||
|
||||
typedef SGSharedPtr<ConditionalObject> ConditionalObjectRef;
|
||||
vector<ConditionalObjectRef> _conditionalObjects;
|
||||
};
|
||||
|
||||
//
|
||||
// Custom subclass of puPopup to implement "draggable" windows in the
|
||||
// interface. Note that this is a subclass of puPopup, not
|
||||
// puDialogBox. Sadly, PUI (mis)uses subclassing to implement a
|
||||
// boolean property: modality. That means that we can't implement
|
||||
// dragging of both puPopup windows and puDialogBoxes with the same
|
||||
// code. Rather than duplicate code, I've chosen to implement only
|
||||
// "non-modal dragability" here. Modal dialog boxes (like the exit
|
||||
// confirmation) are not draggable.
|
||||
//
|
||||
class fgPopup : public puPopup {
|
||||
public:
|
||||
fgPopup(int x, int y, bool r = true, bool d = true) :
|
||||
puPopup(x, y), _draggable(d), _resizable(r), _dragging(false)
|
||||
{}
|
||||
int checkHit(int b, int up, int x, int y);
|
||||
int checkKey(int key, int updown);
|
||||
int getHitObjects(puObject *, int x, int y);
|
||||
puObject *getKeyObject(puObject *, int key);
|
||||
puObject *getActiveInputField(puObject *);
|
||||
void applySize(puObject *);
|
||||
private:
|
||||
enum { LEFT = 1, RIGHT = 2, TOP = 4, BOTTOM = 8 };
|
||||
bool _draggable;
|
||||
bool _resizable;
|
||||
bool _dragging;
|
||||
int _resizing;
|
||||
int _start_cursor;
|
||||
int _cursor;
|
||||
int _dlgX, _dlgY, _dlgW, _dlgH;
|
||||
int _startX, _startY;
|
||||
};
|
||||
|
||||
|
||||
class fgValueList {
|
||||
public:
|
||||
fgValueList(SGPropertyNode *p);
|
||||
virtual ~fgValueList();
|
||||
virtual void update();
|
||||
virtual void update () = 0;
|
||||
|
||||
protected:
|
||||
char **_list;
|
||||
/**
|
||||
* Construct a new GUI widget configured by a property tree.
|
||||
*
|
||||
* The configuration properties are not part of the main
|
||||
* FlightGear property tree; the GUI manager reads them
|
||||
* from individual configuration files.
|
||||
*
|
||||
* @param props A property tree describing the dialog.
|
||||
*/
|
||||
FGDialog (SGPropertyNode * props);
|
||||
|
||||
private:
|
||||
void make_list();
|
||||
void destroy_list();
|
||||
SGPropertyNode_ptr _props;
|
||||
};
|
||||
|
||||
|
||||
class fgList : public fgValueList, public puaList, public GUI_ID {
|
||||
public:
|
||||
fgList(int x1, int y1, int x2, int y2, SGPropertyNode *p, int sw) :
|
||||
fgValueList(p), puaList(x1, y1, x2, y2, _list, sw), GUI_ID(FGCLASS_LIST) {}
|
||||
void update();
|
||||
};
|
||||
|
||||
class fgComboBox : public fgValueList, public puaComboBox {
|
||||
public:
|
||||
fgComboBox(int x1, int y1, int x2, int y2, SGPropertyNode *p, bool editable) :
|
||||
fgValueList(p),
|
||||
puaComboBox(x1, y1, x2, y2, _list, editable),
|
||||
_inHit(false)
|
||||
{}
|
||||
|
||||
void update();
|
||||
|
||||
virtual void setSize(int w, int h);
|
||||
|
||||
virtual int checkHit(int b, int up, int x, int y);
|
||||
|
||||
virtual void recalc_bbox();
|
||||
private:
|
||||
bool _inHit;
|
||||
};
|
||||
|
||||
class fgSelectBox : public fgValueList, public puaSelectBox {
|
||||
public:
|
||||
fgSelectBox(int x1, int y1, int x2, int y2, SGPropertyNode *p) :
|
||||
fgValueList(p), puaSelectBox(x1, y1, x2, y2, _list) {}
|
||||
};
|
||||
|
||||
#endif // __DIALOG_HXX
|
||||
|
|
|
@ -44,6 +44,7 @@
|
|||
#include <Main/fg_props.hxx>
|
||||
#include <Main/WindowSystemAdapter.hxx>
|
||||
#include <GUI/new_gui.hxx>
|
||||
#include <GUI/FGFontCache.hxx>
|
||||
|
||||
#include "gui.h"
|
||||
#include "layout.hxx"
|
||||
|
|
|
@ -2,373 +2,11 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <iostream>
|
||||
#include <plib/pu.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/structure/SGBinding.hxx>
|
||||
#include <simgear/props/props_io.hxx>
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
|
||||
#include "new_gui.hxx"
|
||||
#include "menubar.hxx"
|
||||
|
||||
using std::vector;
|
||||
using std::string;
|
||||
using std::map;
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// FIXME!!
|
||||
//
|
||||
// Deprecated wrappers for old menu commands.
|
||||
//
|
||||
// DO NOT ADD TO THESE. THEY WILL BE DELETED SOON!
|
||||
//
|
||||
// These are defined in gui_funcs.cxx. They should be replaced with
|
||||
// user-configured dialogs and new commands where necessary.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(TR_HIRES_SNAP)
|
||||
extern void dumpHiResSnapShot ();
|
||||
static bool
|
||||
do_hires_snapshot_dialog (const SGPropertyNode * arg)
|
||||
{
|
||||
dumpHiResSnapShot();
|
||||
return true;
|
||||
}
|
||||
#endif // TR_HIRES_SNAP
|
||||
|
||||
static struct {
|
||||
const char * name;
|
||||
SGCommandMgr::command_t command;
|
||||
} deprecated_dialogs [] = {
|
||||
#if defined(TR_HIRES_SNAP)
|
||||
{ "old-hires-snapshot-dialog", do_hires_snapshot_dialog },
|
||||
#endif
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static void
|
||||
add_deprecated_dialogs ()
|
||||
{
|
||||
SG_LOG(SG_GENERAL, SG_INFO, "Initializing old dialog commands:");
|
||||
for (int i = 0; deprecated_dialogs[i].name != 0; i++) {
|
||||
SG_LOG(SG_GENERAL, SG_INFO, " " << deprecated_dialogs[i].name);
|
||||
globals->get_commands()->addCommand(deprecated_dialogs[i].name,
|
||||
deprecated_dialogs[i].command);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Static functions.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
static void
|
||||
menu_callback (puObject * object)
|
||||
{
|
||||
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
|
||||
gui->getMenuBar()->fireItem(object);
|
||||
}
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Implementation of FGMenuBar.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
||||
FGMenuBar::FGMenuBar ()
|
||||
: _visible(false),
|
||||
_menuBar(0)
|
||||
{
|
||||
}
|
||||
|
||||
FGMenuBar::~FGMenuBar ()
|
||||
{
|
||||
destroy_menubar();
|
||||
}
|
||||
|
||||
void
|
||||
FGMenuBar::init ()
|
||||
{
|
||||
delete _menuBar; // FIXME: check if PUI owns the pointer
|
||||
make_menubar();
|
||||
// FIXME: temporary commands to get at
|
||||
// old, hard-coded dialogs.
|
||||
add_deprecated_dialogs();
|
||||
}
|
||||
|
||||
void
|
||||
FGMenuBar::show ()
|
||||
{
|
||||
if (_menuBar != 0)
|
||||
_menuBar->reveal();
|
||||
_visible = true;
|
||||
}
|
||||
|
||||
void
|
||||
FGMenuBar::hide ()
|
||||
{
|
||||
if (_menuBar != 0)
|
||||
_menuBar->hide();
|
||||
_visible = false;
|
||||
}
|
||||
|
||||
bool
|
||||
FGMenuBar::isVisible () const
|
||||
{
|
||||
return _visible;
|
||||
}
|
||||
|
||||
void
|
||||
FGMenuBar::fireItem (puObject * item)
|
||||
{
|
||||
const char * name = item->getLegend();
|
||||
vector<SGBinding *> &bindings = _bindings[name];
|
||||
int nBindings = bindings.size();
|
||||
|
||||
for (int i = 0; i < nBindings; i++)
|
||||
bindings[i]->fire();
|
||||
}
|
||||
|
||||
void
|
||||
FGMenuBar::make_menu (SGPropertyNode * node)
|
||||
{
|
||||
const char * name = strdup(node->getStringValue("label"));
|
||||
vector<SGPropertyNode_ptr> item_nodes = node->getChildren("item");
|
||||
|
||||
int array_size = item_nodes.size();
|
||||
|
||||
char ** items = make_char_array(array_size);
|
||||
puCallback * callbacks = make_callback_array(array_size);
|
||||
|
||||
for (unsigned int i = 0, j = item_nodes.size() - 1;
|
||||
i < item_nodes.size();
|
||||
i++, j--) {
|
||||
|
||||
// Set up the PUI entries for this item
|
||||
items[j] = strdup((char *)item_nodes[i]->getStringValue("label"));
|
||||
callbacks[j] = menu_callback;
|
||||
|
||||
// Load all the bindings for this item
|
||||
vector<SGPropertyNode_ptr> bindings = item_nodes[i]->getChildren("binding");
|
||||
SGPropertyNode * dest = fgGetNode("/sim/bindings/menu", true);
|
||||
|
||||
for (unsigned int k = 0; k < bindings.size(); k++) {
|
||||
unsigned int m = 0;
|
||||
SGPropertyNode_ptr binding;
|
||||
while (dest->getChild("binding", m))
|
||||
m++;
|
||||
|
||||
binding = dest->getChild("binding", m, true);
|
||||
copyProperties(bindings[k], binding);
|
||||
_bindings[items[j]].push_back(new SGBinding(binding, globals->get_props()));
|
||||
}
|
||||
}
|
||||
|
||||
_menuBar->add_submenu(name, items, callbacks);
|
||||
}
|
||||
|
||||
void
|
||||
FGMenuBar::make_menubar ()
|
||||
{
|
||||
SGPropertyNode *targetpath;
|
||||
|
||||
targetpath = fgGetNode("/sim/menubar/default",true);
|
||||
// fgLoadProps("gui/menubar.xml", targetpath);
|
||||
|
||||
/* NOTE: there is no check to see whether there's any usable data at all
|
||||
*
|
||||
* This would also have the advantage of being able to create some kind of
|
||||
* 'fallback' menu - just in case that either menubar.xml is empty OR that
|
||||
* its XML data is not valid, that way we would avoid displaying an
|
||||
* unusable menubar without any functionality - if we decided to add another
|
||||
* char * element to the commands structure in
|
||||
* $FG_SRC/src/Main/fgcommands.cxx
|
||||
* we could additionally save each function's (short) description and use
|
||||
* this as label for the fallback PUI menubar item labels - as a workaround
|
||||
* one might simply use the internal fgcommands and put them into the
|
||||
* fallback menu, so that the user is at least able to re-init the menu
|
||||
* loading - just in case there was some malformed XML in it
|
||||
* (it happend to me ...)
|
||||
*/
|
||||
|
||||
make_menubar(targetpath);
|
||||
}
|
||||
|
||||
/* WARNING: We aren't yet doing any validation of what's found - but since
|
||||
* this isn't done with menubar.xml either, it should not really matter
|
||||
* right now. Although one should later on consider to validate the
|
||||
* contents, whether they are representing a 'legal' menubar structure.
|
||||
*/
|
||||
void
|
||||
FGMenuBar::make_menubar(SGPropertyNode * props)
|
||||
{
|
||||
// Just in case.
|
||||
destroy_menubar();
|
||||
_menuBar = new puMenuBar;
|
||||
|
||||
vector<SGPropertyNode_ptr> menu_nodes = props->getChildren("menu");
|
||||
for (unsigned int i = 0; i < menu_nodes.size(); i++)
|
||||
make_menu(menu_nodes[i]);
|
||||
|
||||
_menuBar->close();
|
||||
make_object_map(props);
|
||||
|
||||
if (_visible)
|
||||
_menuBar->reveal();
|
||||
else
|
||||
_menuBar->hide();
|
||||
}
|
||||
|
||||
void
|
||||
FGMenuBar::destroy_menubar ()
|
||||
{
|
||||
if ( _menuBar == 0 )
|
||||
return;
|
||||
|
||||
hide();
|
||||
puDeleteObject(_menuBar);
|
||||
|
||||
unsigned int i;
|
||||
|
||||
// Delete all the character arrays
|
||||
// we were forced to keep around for
|
||||
// plib.
|
||||
SG_LOG(SG_GENERAL, SG_BULK, "Deleting char arrays");
|
||||
for (i = 0; i < _char_arrays.size(); i++) {
|
||||
for (int j = 0; _char_arrays[i][j] != 0; j++)
|
||||
free(_char_arrays[i][j]); // added with strdup
|
||||
delete[] _char_arrays[i];
|
||||
}
|
||||
|
||||
// Delete all the callback arrays
|
||||
// we were forced to keep around for
|
||||
// plib.
|
||||
SG_LOG(SG_GENERAL, SG_BULK, "Deleting callback arrays");
|
||||
for (i = 0; i < _callback_arrays.size(); i++)
|
||||
delete[] _callback_arrays[i];
|
||||
|
||||
// Delete all those bindings
|
||||
SG_LOG(SG_GENERAL, SG_BULK, "Deleting bindings");
|
||||
map<string,vector<SGBinding *> >::iterator it;
|
||||
for (it = _bindings.begin(); it != _bindings.end(); it++) {
|
||||
SG_LOG(SG_GENERAL, SG_BULK, "Deleting bindings for " << it->first);
|
||||
for ( i = 0; i < it->second.size(); i++ )
|
||||
delete it->second[i];
|
||||
}
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_BULK, "Done.");
|
||||
}
|
||||
|
||||
void
|
||||
FGMenuBar::make_object_map(SGPropertyNode * node)
|
||||
{
|
||||
unsigned int menu_index = 0;
|
||||
vector<SGPropertyNode_ptr> menus = node->getChildren("menu");
|
||||
for (puObject *obj = ((puGroup *)_menuBar)->getFirstChild();
|
||||
obj; obj = obj->getNextObject()) {
|
||||
|
||||
// skip puPopupMenus. They are also children of _menuBar,
|
||||
// but we access them via getUserData() (see below)
|
||||
if (!(obj->getType() & PUCLASS_ONESHOT))
|
||||
continue;
|
||||
|
||||
if (menu_index >= menus.size()) {
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "'menu' object without node: "
|
||||
<< node->getPath() << "/menu[" << menu_index << ']');
|
||||
return;
|
||||
}
|
||||
|
||||
SGPropertyNode *menu = menus.at(menu_index);
|
||||
_objects[menu->getPath()] = obj;
|
||||
add_enabled_listener(menu);
|
||||
|
||||
puGroup *popup = (puGroup *)obj->getUserData();
|
||||
if (!popup)
|
||||
continue;
|
||||
|
||||
// the entries are for some reason reversed (last first), and we
|
||||
// don't know yet how many there will be; so we collect first
|
||||
vector<puObject *> e;
|
||||
for (puObject *me = popup->getFirstChild(); me; me = me->getNextObject())
|
||||
e.push_back(me);
|
||||
|
||||
vector<SGPropertyNode_ptr> items = menu->getChildren("item");
|
||||
for (unsigned int i = 0; i < e.size(); i++) {
|
||||
if (i >= items.size()) {
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "'item' object without node: "
|
||||
<< menu->getPath() << "/item[" << i << ']');
|
||||
break;
|
||||
}
|
||||
SGPropertyNode *item = items.at(e.size() - i - 1);
|
||||
_objects[item->getPath()] = e[i];
|
||||
add_enabled_listener(item);
|
||||
}
|
||||
menu_index++;
|
||||
}
|
||||
}
|
||||
|
||||
struct EnabledListener : SGPropertyChangeListener {
|
||||
void valueChanged(SGPropertyNode *node) {
|
||||
NewGUI * gui = (NewGUI *)globals->get_subsystem("gui");
|
||||
if (!gui)
|
||||
return;
|
||||
FGMenuBar *menubar = gui->getMenuBar();
|
||||
if (menubar)
|
||||
menubar->enable_item(node->getParent(), node->getBoolValue());
|
||||
}
|
||||
};
|
||||
|
||||
void
|
||||
FGMenuBar::add_enabled_listener(SGPropertyNode * node)
|
||||
{
|
||||
if (!node->hasValue("enabled"))
|
||||
node->setBoolValue("enabled", true);
|
||||
|
||||
enable_item(node, node->getBoolValue("enabled"));
|
||||
node->getNode("enabled")->addChangeListener(new EnabledListener());
|
||||
}
|
||||
|
||||
bool
|
||||
FGMenuBar::enable_item(const SGPropertyNode * node, bool state)
|
||||
{
|
||||
string path = node->getPath();
|
||||
if (_objects.find(path) == _objects.end()) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Trying to enable/disable "
|
||||
"non-existent menu item for node `" << path << '\'');
|
||||
return false;
|
||||
}
|
||||
puObject *object = _objects[path];
|
||||
if (state)
|
||||
object->activate();
|
||||
else
|
||||
object->greyOut();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
char **
|
||||
FGMenuBar::make_char_array (int size)
|
||||
{
|
||||
char ** list = new char*[size+1];
|
||||
for (int i = 0; i <= size; i++)
|
||||
list[i] = 0;
|
||||
_char_arrays.push_back(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
puCallback *
|
||||
FGMenuBar::make_callback_array (int size)
|
||||
{
|
||||
puCallback * list = new puCallback[size+1];
|
||||
for (int i = 0; i <= size; i++)
|
||||
list[i] = 0;
|
||||
_callback_arrays.push_back(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
// end of menubar.cxx
|
||||
|
|
|
@ -3,42 +3,19 @@
|
|||
#ifndef __MENUBAR_HXX
|
||||
#define __MENUBAR_HXX 1
|
||||
|
||||
#ifndef __cplusplus
|
||||
# error This library requires C++
|
||||
#endif
|
||||
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
#include <plib/pu.h>
|
||||
|
||||
#include <map>
|
||||
#include <vector>
|
||||
|
||||
class puMenuBar;
|
||||
class puObject;
|
||||
class SGBinding;
|
||||
|
||||
|
||||
/**
|
||||
* XML-configured PUI menu bar.
|
||||
* XML-configured menu bar interface
|
||||
*
|
||||
* This class creates a menu bar from a tree of XML properties. These
|
||||
* properties are not part of the main FlightGear property tree, but
|
||||
* are read from a separate file ($FG_ROOT/gui/menubar.xml).
|
||||
*
|
||||
* WARNING: because PUI provides no easy way to attach user data to a
|
||||
* menu item, all menu item strings must be unique; otherwise, this
|
||||
* class will always use the first binding with any given name.
|
||||
|
||||
*/
|
||||
class FGMenuBar
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
FGMenuBar ();
|
||||
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
|
@ -49,89 +26,25 @@ public:
|
|||
/**
|
||||
* Initialize the menu bar from $FG_ROOT/gui/menubar.xml
|
||||
*/
|
||||
virtual void init ();
|
||||
virtual void init () = 0;
|
||||
|
||||
/**
|
||||
* Make the menu bar visible.
|
||||
*/
|
||||
virtual void show ();
|
||||
virtual void show () = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Make the menu bar invisible.
|
||||
*/
|
||||
virtual void hide ();
|
||||
virtual void hide () = 0;
|
||||
|
||||
|
||||
/**
|
||||
* Test whether the menu bar is visible.
|
||||
*/
|
||||
virtual bool isVisible () const;
|
||||
virtual bool isVisible () const = 0;
|
||||
|
||||
|
||||
/**
|
||||
* IGNORE THIS METHOD!!!
|
||||
*
|
||||
* This is necessary only because plib does not provide any easy
|
||||
* way to attach user data to a menu item. FlightGear should not
|
||||
* have to know about PUI internals, but this method allows the
|
||||
* callback to pass the menu item one-shot on to the current menu.
|
||||
*/
|
||||
virtual void fireItem (puObject * item);
|
||||
|
||||
|
||||
/**
|
||||
* create a menubar based on a PropertyList within the PropertyTree
|
||||
*/
|
||||
void make_menubar (SGPropertyNode * props);
|
||||
|
||||
|
||||
/**
|
||||
* destroy a menubar based on a PropertyList within the PropertyTree
|
||||
*/
|
||||
void destroy_menubar ();
|
||||
|
||||
|
||||
/**
|
||||
* Disable/enable menu titles and entries
|
||||
*/
|
||||
bool enable_item (const SGPropertyNode * item, bool state);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
// Make a single menu.
|
||||
void make_menu (SGPropertyNode * node);
|
||||
|
||||
// Make the top-level menubar.
|
||||
void make_menubar ();
|
||||
|
||||
// Create a property-path -> puObject map for menu node
|
||||
void make_object_map(SGPropertyNode * node);
|
||||
|
||||
// Add <enabled> listener that enables/disables menu entries.
|
||||
void add_enabled_listener(SGPropertyNode * node);
|
||||
|
||||
// Is the menu visible?
|
||||
bool _visible;
|
||||
|
||||
// The top-level menubar itself.
|
||||
puMenuBar * _menuBar;
|
||||
|
||||
// A map of bindings for the menubar.
|
||||
std::map<std::string,std::vector<SGBinding *> > _bindings;
|
||||
|
||||
// These are hoops that we have to jump through because PUI doesn't
|
||||
// do memory management for lists. We have to allocate the arrays,
|
||||
// hang onto pointers, and then delete them when the menubar is
|
||||
// freed.
|
||||
char ** make_char_array (int size);
|
||||
puCallback * make_callback_array (int size);
|
||||
std::vector<char **> _char_arrays;
|
||||
std::vector<puCallback *> _callback_arrays;
|
||||
|
||||
// A map for {menu node path}->puObject translation.
|
||||
std::map<std::string, puObject *> _objects;
|
||||
};
|
||||
|
||||
#endif // __MENUBAR_HXX
|
||||
|
|
|
@ -26,11 +26,10 @@
|
|||
#include "GL/glx.h"
|
||||
#endif
|
||||
|
||||
#include "menubar.hxx"
|
||||
#include "dialog.hxx"
|
||||
|
||||
extern puFont FONT_HELVETICA_14;
|
||||
extern puFont FONT_SANS_12B;
|
||||
#include "FGPUIMenuBar.hxx"
|
||||
#include "FGPUIDialog.hxx"
|
||||
#include "FGFontCache.hxx"
|
||||
#include "FGColor.hxx"
|
||||
|
||||
using std::map;
|
||||
using std::string;
|
||||
|
@ -42,14 +41,13 @@ using std::string;
|
|||
|
||||
|
||||
NewGUI::NewGUI ()
|
||||
: _menubar(new FGMenuBar),
|
||||
: _menubar(new FGPUIMenuBar),
|
||||
_active_dialog(0)
|
||||
{
|
||||
}
|
||||
|
||||
NewGUI::~NewGUI ()
|
||||
{
|
||||
delete _menubar;
|
||||
_dialog_props.clear();
|
||||
for (_itt_t it = _colors.begin(); it != _colors.end(); ++it)
|
||||
delete it->second;
|
||||
|
@ -81,7 +79,7 @@ void
|
|||
NewGUI::reset (bool reload)
|
||||
{
|
||||
map<string,FGDialog *>::iterator iter;
|
||||
vector<string> dlg;
|
||||
std::vector<string> dlg;
|
||||
// close all open dialogs and remember them ...
|
||||
for (iter = _active_dialogs.begin(); iter != _active_dialogs.end(); ++iter)
|
||||
dlg.push_back(iter->first);
|
||||
|
@ -93,8 +91,7 @@ NewGUI::reset (bool reload)
|
|||
setStyle();
|
||||
|
||||
unbind();
|
||||
delete _menubar;
|
||||
_menubar = new FGMenuBar;
|
||||
_menubar.reset(new FGPUIMenuBar);
|
||||
|
||||
if (reload) {
|
||||
_dialog_props.clear();
|
||||
|
@ -139,7 +136,7 @@ NewGUI::showDialog (const string &name)
|
|||
return false;
|
||||
} else {
|
||||
if(!_active_dialogs[name])
|
||||
_active_dialogs[name] = new FGDialog(_dialog_props[name]);
|
||||
_active_dialogs[name] = new FGPUIDialog(_dialog_props[name]);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -215,7 +212,7 @@ NewGUI::getActiveDialog ()
|
|||
FGMenuBar *
|
||||
NewGUI::getMenuBar ()
|
||||
{
|
||||
return _menubar;
|
||||
return _menubar.get();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -326,247 +323,4 @@ NewGUI::setupFont (SGPropertyNode *node)
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// FGColor class.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void
|
||||
FGColor::print() const {
|
||||
std::cerr << "red=" << _red << ", green=" << _green
|
||||
<< ", blue=" << _blue << ", alpha=" << _alpha << std::endl;
|
||||
}
|
||||
|
||||
bool
|
||||
FGColor::merge(const SGPropertyNode *node)
|
||||
{
|
||||
if (!node)
|
||||
return false;
|
||||
|
||||
bool dirty = false;
|
||||
const SGPropertyNode * n;
|
||||
if ((n = node->getNode("red")))
|
||||
_red = n->getFloatValue(), dirty = true;
|
||||
if ((n = node->getNode("green")))
|
||||
_green = n->getFloatValue(), dirty = true;
|
||||
if ((n = node->getNode("blue")))
|
||||
_blue = n->getFloatValue(), dirty = true;
|
||||
if ((n = node->getNode("alpha")))
|
||||
_alpha = n->getFloatValue(), dirty = true;
|
||||
return dirty;
|
||||
}
|
||||
|
||||
bool
|
||||
FGColor::merge(const FGColor *color)
|
||||
{
|
||||
bool dirty = false;
|
||||
if (color && color->_red >= 0.0)
|
||||
_red = color->_red, dirty = true;
|
||||
if (color && color->_green >= 0.0)
|
||||
_green = color->_green, dirty = true;
|
||||
if (color && color->_blue >= 0.0)
|
||||
_blue = color->_blue, dirty = true;
|
||||
if (color && color->_alpha >= 0.0)
|
||||
_alpha = color->_alpha, dirty = true;
|
||||
return dirty;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// FGFontCache class.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace
|
||||
{
|
||||
struct GuiFont
|
||||
{
|
||||
const char *name;
|
||||
puFont *font;
|
||||
struct Predicate
|
||||
: public std::unary_function<const GuiFont, bool>
|
||||
{
|
||||
Predicate(const char* name_) : name(name_) {}
|
||||
bool operator() (const GuiFont& f1) const
|
||||
{
|
||||
return std::strcmp(f1.name, name) == 0;
|
||||
}
|
||||
const char* name;
|
||||
};
|
||||
};
|
||||
|
||||
const GuiFont guifonts[] = {
|
||||
{ "default", &FONT_HELVETICA_14 },
|
||||
{ "FIXED_8x13", &PUFONT_8_BY_13 },
|
||||
{ "FIXED_9x15", &PUFONT_9_BY_15 },
|
||||
{ "TIMES_10", &PUFONT_TIMES_ROMAN_10 },
|
||||
{ "TIMES_24", &PUFONT_TIMES_ROMAN_24 },
|
||||
{ "HELVETICA_10", &PUFONT_HELVETICA_10 },
|
||||
{ "HELVETICA_12", &PUFONT_HELVETICA_12 },
|
||||
{ "HELVETICA_14", &FONT_HELVETICA_14 },
|
||||
{ "HELVETICA_18", &PUFONT_HELVETICA_18 },
|
||||
{ "SANS_12B", &FONT_SANS_12B }
|
||||
};
|
||||
|
||||
const GuiFont* guifontsEnd = &guifonts[sizeof(guifonts)/ sizeof(guifonts[0])];
|
||||
}
|
||||
|
||||
FGFontCache::FGFontCache() :
|
||||
_initialized(false)
|
||||
{
|
||||
}
|
||||
|
||||
FGFontCache::~FGFontCache()
|
||||
{
|
||||
#if defined(SG_UNIX) && !defined(SG_MAC)
|
||||
// Ugly workaround for a crash on exit with multiple screens configured
|
||||
if (!glXGetCurrentContext())
|
||||
return;
|
||||
#endif
|
||||
PuFontMap::iterator it, end = _puFonts.end();
|
||||
for (it = _puFonts.begin(); it != end; ++it)
|
||||
delete it->second;
|
||||
}
|
||||
|
||||
inline bool FGFontCache::FntParamsLess::operator()(const FntParams& f1,
|
||||
const FntParams& f2) const
|
||||
{
|
||||
int comp = f1.name.compare(f2.name);
|
||||
if (comp < 0)
|
||||
return true;
|
||||
else if (comp > 0)
|
||||
return false;
|
||||
if (f1.size < f2.size)
|
||||
return true;
|
||||
else if (f1.size > f2.size)
|
||||
return false;
|
||||
return f1.slant < f2.slant;
|
||||
}
|
||||
|
||||
struct FGFontCache::fnt *
|
||||
FGFontCache::getfnt(const char *name, float size, float slant)
|
||||
{
|
||||
string fontName = boost::to_lower_copy(string(name));
|
||||
FntParams fntParams(fontName, size, slant);
|
||||
PuFontMap::iterator i = _puFonts.find(fntParams);
|
||||
if (i != _puFonts.end()) {
|
||||
// found in the puFonts map, all done
|
||||
return i->second;
|
||||
}
|
||||
|
||||
// fntTexFont s are all preloaded into the _texFonts map
|
||||
TexFontMap::iterator texi = _texFonts.find(fontName);
|
||||
fntTexFont* texfont = NULL;
|
||||
puFont* pufont = NULL;
|
||||
if (texi != _texFonts.end()) {
|
||||
texfont = texi->second;
|
||||
} else {
|
||||
// check the built-in PUI fonts (in guifonts array)
|
||||
const GuiFont* guifont = std::find_if(&guifonts[0], guifontsEnd,
|
||||
GuiFont::Predicate(name));
|
||||
if (guifont != guifontsEnd) {
|
||||
pufont = guifont->font;
|
||||
}
|
||||
}
|
||||
|
||||
fnt* f = new fnt;
|
||||
if (pufont) {
|
||||
f->pufont = pufont;
|
||||
} else if (texfont) {
|
||||
f->texfont = texfont;
|
||||
f->pufont = new puFont;
|
||||
f->pufont->initialize(static_cast<fntFont *>(f->texfont), size, slant);
|
||||
} else {
|
||||
f->pufont = guifonts[0].font;
|
||||
}
|
||||
_puFonts[fntParams] = f;
|
||||
return f;
|
||||
}
|
||||
|
||||
puFont *
|
||||
FGFontCache::get(const char *name, float size, float slant)
|
||||
{
|
||||
return getfnt(name, size, slant)->pufont;
|
||||
}
|
||||
|
||||
fntTexFont *
|
||||
FGFontCache::getTexFont(const char *name, float size, float slant)
|
||||
{
|
||||
return getfnt(name, size, slant)->texfont;
|
||||
}
|
||||
|
||||
puFont *
|
||||
FGFontCache::get(SGPropertyNode *node)
|
||||
{
|
||||
if (!node)
|
||||
return get("Helvetica.txf", 15.0, 0.0);
|
||||
|
||||
const char *name = node->getStringValue("name", "Helvetica.txf");
|
||||
float size = node->getFloatValue("size", 15.0);
|
||||
float slant = node->getFloatValue("slant", 0.0);
|
||||
|
||||
return get(name, size, slant);
|
||||
}
|
||||
|
||||
void FGFontCache::init()
|
||||
{
|
||||
if (_initialized) {
|
||||
return;
|
||||
}
|
||||
|
||||
char *envp = ::getenv("FG_FONTS");
|
||||
if (envp != NULL) {
|
||||
_path.set(envp);
|
||||
} else {
|
||||
_path.set(globals->get_fg_root());
|
||||
_path.append("Fonts");
|
||||
}
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
SGPath
|
||||
FGFontCache::getfntpath(const char *name)
|
||||
{
|
||||
init();
|
||||
SGPath path(_path);
|
||||
if (name && std::string(name) != "") {
|
||||
path.append(name);
|
||||
if (path.exists())
|
||||
return path;
|
||||
}
|
||||
|
||||
path = SGPath(_path);
|
||||
path.append("Helvetica.txf");
|
||||
SG_LOG(SG_GENERAL, SG_WARN, "Unknown font name '" << name << "', defaulting to Helvetica");
|
||||
return path;
|
||||
}
|
||||
|
||||
bool FGFontCache::initializeFonts()
|
||||
{
|
||||
static string fontext("txf");
|
||||
init();
|
||||
ulDir* fontdir = ulOpenDir(_path.c_str());
|
||||
if (!fontdir)
|
||||
return false;
|
||||
const ulDirEnt *dirEntry;
|
||||
while ((dirEntry = ulReadDir(fontdir)) != 0) {
|
||||
SGPath path(_path);
|
||||
path.append(dirEntry->d_name);
|
||||
if (path.extension() == fontext) {
|
||||
fntTexFont* f = new fntTexFont;
|
||||
if (f->load((char *)path.c_str())) {
|
||||
// convert font names in the map to lowercase for matching
|
||||
string fontName = boost::to_lower_copy(string(dirEntry->d_name));
|
||||
_texFonts[fontName] = f;
|
||||
} else
|
||||
delete f;
|
||||
}
|
||||
}
|
||||
ulCloseDir(fontdir);
|
||||
return true;
|
||||
}
|
||||
|
||||
// end of new_gui.cxx
|
||||
|
|
|
@ -3,17 +3,15 @@
|
|||
#ifndef __NEW_GUI_HXX
|
||||
#define __NEW_GUI_HXX 1
|
||||
|
||||
#include <plib/pu.h>
|
||||
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <simgear/structure/subsystem_mgr.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#include <string.h>
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <memory> // for auto_ptr on some systems
|
||||
|
||||
class SGBinding;
|
||||
|
||||
|
@ -21,7 +19,7 @@ class FGMenuBar;
|
|||
class FGDialog;
|
||||
class FGColor;
|
||||
class FGFontCache;
|
||||
|
||||
class puFont;
|
||||
|
||||
/**
|
||||
* XML-configured GUI subsystem.
|
||||
|
@ -222,7 +220,7 @@ private:
|
|||
// Read all the configuration files in a directory.
|
||||
void readDir (const SGPath& path);
|
||||
|
||||
FGMenuBar * _menubar;
|
||||
std::auto_ptr<FGMenuBar> _menubar;
|
||||
FGDialog * _active_dialog;
|
||||
std::map<std::string,FGDialog *> _active_dialogs;
|
||||
std::map<std::string,SGPropertyNode_ptr> _dialog_props;
|
||||
|
@ -230,117 +228,5 @@ private:
|
|||
};
|
||||
|
||||
|
||||
class FGColor {
|
||||
public:
|
||||
FGColor() { clear(); }
|
||||
FGColor(float r, float g, float b, float a = 1.0f) { set(r, g, b, a); }
|
||||
FGColor(const SGPropertyNode *prop) { set(prop); }
|
||||
FGColor(FGColor *c) {
|
||||
if (c) set(c->_red, c->_green, c->_blue, c->_alpha);
|
||||
}
|
||||
|
||||
inline void clear() { _red = _green = _blue = _alpha = -1.0f; }
|
||||
// merges in non-negative components from property with children <red> etc.
|
||||
bool merge(const SGPropertyNode *prop);
|
||||
bool merge(const FGColor *color);
|
||||
|
||||
bool set(const SGPropertyNode *prop) { clear(); return merge(prop); };
|
||||
bool set(const FGColor *color) { clear(); return merge(color); }
|
||||
bool set(float r, float g, float b, float a = 1.0f) {
|
||||
_red = r, _green = g, _blue = b, _alpha = a;
|
||||
return true;
|
||||
}
|
||||
bool isValid() const {
|
||||
return _red >= 0.0 && _green >= 0.0 && _blue >= 0.0;
|
||||
}
|
||||
void print() const;
|
||||
|
||||
inline void setRed(float red) { _red = red; }
|
||||
inline void setGreen(float green) { _green = green; }
|
||||
inline void setBlue(float blue) { _blue = blue; }
|
||||
inline void setAlpha(float alpha) { _alpha = alpha; }
|
||||
|
||||
inline float red() const { return clamp(_red); }
|
||||
inline float green() const { return clamp(_green); }
|
||||
inline float blue() const { return clamp(_blue); }
|
||||
inline float alpha() const { return _alpha < 0.0 ? 1.0 : clamp(_alpha); }
|
||||
|
||||
protected:
|
||||
float _red, _green, _blue, _alpha;
|
||||
|
||||
private:
|
||||
float clamp(float f) const { return f < 0.0 ? 0.0 : f > 1.0 ? 1.0 : f; }
|
||||
};
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* A class to keep all fonts available for future use.
|
||||
* This also assures a font isn't resident more than once.
|
||||
*/
|
||||
class FGFontCache {
|
||||
private:
|
||||
// The parameters of a request to the cache.
|
||||
struct FntParams
|
||||
{
|
||||
const std::string name;
|
||||
const float size;
|
||||
const float slant;
|
||||
FntParams() : size(0.0f), slant(0.0f) {}
|
||||
FntParams(const FntParams& rhs)
|
||||
: name(rhs.name), size(rhs.size), slant(rhs.slant)
|
||||
{
|
||||
}
|
||||
FntParams(const std::string& name_, float size_, float slant_)
|
||||
: name(name_), size(size_), slant(slant_)
|
||||
{
|
||||
}
|
||||
};
|
||||
struct FntParamsLess
|
||||
: public std::binary_function<const FntParams, const FntParams, bool>
|
||||
{
|
||||
bool operator() (const FntParams& f1, const FntParams& f2) const;
|
||||
};
|
||||
struct fnt {
|
||||
fnt(puFont *pu = 0) : pufont(pu), texfont(0) {}
|
||||
~fnt() { if (texfont) { delete pufont; delete texfont; } }
|
||||
// Font used by plib GUI code
|
||||
puFont *pufont;
|
||||
// TXF font
|
||||
fntTexFont *texfont;
|
||||
};
|
||||
// Path to the font directory
|
||||
SGPath _path;
|
||||
|
||||
typedef std::map<const std::string, fntTexFont*> TexFontMap;
|
||||
typedef std::map<const FntParams, fnt*, FntParamsLess> PuFontMap;
|
||||
TexFontMap _texFonts;
|
||||
PuFontMap _puFonts;
|
||||
|
||||
bool _initialized;
|
||||
struct fnt *getfnt(const char *name, float size, float slant);
|
||||
void init();
|
||||
|
||||
public:
|
||||
FGFontCache();
|
||||
~FGFontCache();
|
||||
|
||||
puFont *get(const char *name, float size=15.0, float slant=0.0);
|
||||
puFont *get(SGPropertyNode *node);
|
||||
|
||||
fntTexFont *getTexFont(const char *name, float size=15.0, float slant=0.0);
|
||||
|
||||
SGPath getfntpath(const char *name);
|
||||
/**
|
||||
* Preload all the fonts in the FlightGear font directory. It is
|
||||
* important to load the font textures early, with the proper
|
||||
* graphics context current, so that no plib (or our own) code
|
||||
* tries to load a font from disk when there's no current graphics
|
||||
* context.
|
||||
*/
|
||||
bool initializeFonts();
|
||||
};
|
||||
|
||||
|
||||
#endif // __NEW_GUI_HXX
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
|
||||
#include <plib/puAux.h>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include "dialog.hxx"
|
||||
#include "FGPUIDialog.hxx"
|
||||
|
||||
|
||||
class PropertyList : public puaList, public SGPropertyChangeListener, public GUI_ID {
|
||||
|
|
|
@ -36,3 +36,4 @@
|
|||
#define PKGLIBDIR "@FG_DATA_DIR@"
|
||||
|
||||
#cmakedefine FG_HAVE_HLA
|
||||
#cmakedefine FG_JPEG_SERVER
|
||||
|
|
|
@ -1,148 +0,0 @@
|
|||
/**************************************************************************
|
||||
* fg_callback.hxx -- Wrapper classes to treat function and method pointers
|
||||
* as objects.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* $Id$
|
||||
**************************************************************************/
|
||||
|
||||
#ifndef _FG_CALLBACK_HXX
|
||||
#define _FG_CALLBACK_HXX
|
||||
|
||||
/**
|
||||
* Abstract base class for all FlightGear callbacks.
|
||||
*/
|
||||
class fgCallback
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
virtual ~fgCallback() {}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
virtual fgCallback* clone() const = 0;
|
||||
|
||||
/**
|
||||
* Execute the callback function.
|
||||
*/
|
||||
virtual void operator()() = 0;
|
||||
|
||||
protected:
|
||||
/**
|
||||
*
|
||||
*/
|
||||
fgCallback() {}
|
||||
|
||||
private:
|
||||
// Not implemented.
|
||||
void operator=( const fgCallback& );
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for invoking a file scope function.
|
||||
*/
|
||||
template< typename Fun >
|
||||
class fgFunctionCallback : public fgCallback
|
||||
{
|
||||
public:
|
||||
/**
|
||||
*
|
||||
*/
|
||||
fgFunctionCallback( const Fun& fun )
|
||||
: fgCallback(), f_(fun) {}
|
||||
|
||||
fgCallback* clone() const
|
||||
{
|
||||
return new fgFunctionCallback( *this );
|
||||
}
|
||||
|
||||
void operator()() { f_(); }
|
||||
|
||||
private:
|
||||
// Not defined.
|
||||
fgFunctionCallback();
|
||||
|
||||
private:
|
||||
Fun f_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Callback for invoking a member function.
|
||||
*/
|
||||
template< class ObjPtr, typename MemFn >
|
||||
class fgMethodCallback : public fgCallback
|
||||
{
|
||||
public:
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
fgMethodCallback( const ObjPtr& pObj, MemFn pMemFn )
|
||||
: fgCallback(),
|
||||
pObj_(pObj),
|
||||
pMemFn_(pMemFn)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
fgCallback* clone() const
|
||||
{
|
||||
return new fgMethodCallback( *this );
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void operator()()
|
||||
{
|
||||
((*pObj_).*pMemFn_)();
|
||||
}
|
||||
|
||||
private:
|
||||
// Not defined.
|
||||
fgMethodCallback();
|
||||
|
||||
private:
|
||||
ObjPtr pObj_;
|
||||
MemFn pMemFn_;
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper template functions.
|
||||
*/
|
||||
|
||||
template< typename Fun >
|
||||
fgCallback*
|
||||
make_callback( const Fun& fun )
|
||||
{
|
||||
return new fgFunctionCallback<Fun>(fun);
|
||||
}
|
||||
|
||||
template< class ObjPtr, typename MemFn >
|
||||
fgCallback*
|
||||
make_callback( const ObjPtr& pObj, MemFn pMemFn )
|
||||
{
|
||||
return new fgMethodCallback<ObjPtr,MemFn>(pObj, pMemFn );
|
||||
}
|
||||
|
||||
#endif // _FG_CALLBACK_HXX
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
/*
|
||||
// Alterations: Copyright C. Hotchkiss 1996
|
||||
//
|
||||
// $Log$
|
||||
// Revision 1.2 2010/01/23 22:26:52 fredb
|
||||
// MINGW patch from Benoît Laniel
|
||||
//
|
||||
// Revision 1.1.1.1 2002-09-10 01:14:04 curt
|
||||
// Initial revision of FlightGear-0.9.0
|
||||
//
|
||||
// Revision 1.2 2001/05/16 21:27:59 curt
|
||||
// Added David Megginson's patch for reconfigurable keyboard bindings.
|
||||
//
|
||||
// Revision 1.1.1.1 1999/06/17 18:07:30 curt
|
||||
// Start of 0.7.x branch
|
||||
//
|
||||
// Revision 1.2 1999/04/22 18:45:42 curt
|
||||
// Borland tweaks.
|
||||
//
|
||||
// Revision 1.1.1.1 1999/04/05 21:32:40 curt
|
||||
// Start of 0.6.x branch.
|
||||
//
|
||||
// Revision 1.2 1998/05/13 18:23:46 curt
|
||||
// fg_typedefs.h: updated version by Charlie Hotchkiss
|
||||
// general.h: moved fg_root info to fgOPTIONS structure.
|
||||
//
|
||||
// Revision 1.1 1998/05/11 18:26:12 curt
|
||||
// Initial revision.
|
||||
//
|
||||
// Rev 1.4 11 Nov 1997 15:34:28 CHOTCHKISS
|
||||
// Expanded definitions.
|
||||
//
|
||||
// Rev 1.3 20 Jan 1997 9:21:26 CHOTCHKISS
|
||||
// Minor additions.
|
||||
//
|
||||
// Rev 1.2 12 Nov 1996 15:06:52 CHOTCHKISS
|
||||
// Dropped PC Write print format control lines.
|
||||
//
|
||||
// Rev 1.1 20 Nov 1995 15:59:02 CHOTCHKISS
|
||||
// Additions and improvements. Memcheck compatibilities.
|
||||
//
|
||||
// Rev 1.0 06 Apr 1995 14:00:32 CHOTCHKISS
|
||||
// Initial revision.
|
||||
|
||||
*/
|
||||
/*
|
||||
// TYPEDEFS.H - General purpose definition file
|
||||
// Copyright (C) 1992 Paradigm Systems. All rights reserved.
|
||||
//
|
||||
// Function
|
||||
// ========
|
||||
// This file contains the general purpose definitions common to the
|
||||
// all Paradigm applications. By defining synonyms for the physical
|
||||
// data types to be manipulated, portability between memory models
|
||||
// and machines is maximized.
|
||||
//
|
||||
// Note that this file follows the system include files and before
|
||||
// any application include files.
|
||||
*/
|
||||
|
||||
#ifndef _FG_TYPEDEFS
|
||||
#define _FG_TYPEDEFS
|
||||
|
||||
//
|
||||
// Define the types to be used to manipulate 8-, 16-, and 32-bit
|
||||
// data.
|
||||
//
|
||||
typedef unsigned int BIT ; // Use for defining Borland bit fields
|
||||
typedef char CHAR ; // 8-bit signed data
|
||||
typedef const char COCHAR;
|
||||
typedef unsigned char UCHAR ; // 8-bit unsigned data
|
||||
typedef unsigned char BYTE;
|
||||
typedef int INT ; // 16-bit signed data
|
||||
typedef unsigned int UINT ; // 16-bit unsigned data
|
||||
typedef const int COINT; // 16=bit constant int
|
||||
typedef const UINT COUINT;
|
||||
typedef long LONG ; // 32-bit signed data
|
||||
typedef unsigned long ULONG ; // 32-bit unsigned data
|
||||
|
||||
typedef unsigned short UWORD; // Unsigned 16 bit quantity (WIN=SHORT)
|
||||
#ifndef _WIN32
|
||||
typedef signed short WORD; // Signed 16 bit quantity
|
||||
#endif
|
||||
typedef BYTE UBYTE; // Used in some 3rd party code
|
||||
#ifndef _WIN32
|
||||
typedef int BOOLEAN; //
|
||||
#endif
|
||||
|
||||
typedef float FLOAT ; // 32-bit floating point data
|
||||
typedef double DOUBLE ; // 64-bit floating point data
|
||||
typedef long double LDOUBLE ; // 80-bit floating point data
|
||||
|
||||
typedef void(*VFNPTR) ( void );
|
||||
typedef void(*VFNINTPTR)( int );
|
||||
typedef int (*FNPTR) ( void );
|
||||
typedef int (*FNINTPTR) ( int );
|
||||
typedef int (*FNUIPTR) ( UINT );
|
||||
typedef double( *DBLFNPTR)( void );
|
||||
typedef float( *FLTFNPTR)( void );
|
||||
|
||||
#endif // _FG_TYPEDEFS
|
|
@ -22,6 +22,10 @@
|
|||
//
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "FGJoystickInput.hxx"
|
||||
|
||||
#include <simgear/props/props_io.hxx>
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
//
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "FGKeyboardInput.hxx"
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <Scripting/NasalSys.hxx>
|
||||
|
|
|
@ -225,7 +225,7 @@ static struct enbet {
|
|||
};
|
||||
|
||||
|
||||
class EventNameByEventType : public map<unsigned,const char*> {
|
||||
class EventNameByEventType : public std::map<unsigned,const char*> {
|
||||
public:
|
||||
EventNameByEventType() {
|
||||
for( unsigned i = 0; i < sizeof(EVENT_NAMES_BY_EVENT_TYPE)/sizeof(EVENT_NAMES_BY_EVENT_TYPE[0]); i++ )
|
||||
|
@ -234,7 +234,7 @@ public:
|
|||
};
|
||||
static EventNameByEventType EVENT_NAME_BY_EVENT_TYPE;
|
||||
|
||||
class EventNameByType : public map<TypeCode,const char*> {
|
||||
class EventNameByType : public std::map<TypeCode,const char*> {
|
||||
public:
|
||||
EventNameByType() {
|
||||
for( unsigned i = 0; i < sizeof(EVENT_TYPES)/sizeof(EVENT_TYPES[0]); i++ )
|
||||
|
@ -246,11 +246,11 @@ static EventNameByType EVENT_NAME_BY_TYPE;
|
|||
|
||||
struct ltstr {
|
||||
bool operator()(const char * s1, const char * s2 ) const {
|
||||
return string(s1).compare( s2 ) < 0;
|
||||
return std::string(s1).compare( s2 ) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
class EventTypeByName : public map<const char *,TypeCode,ltstr> {
|
||||
class EventTypeByName : public std::map<const char *,TypeCode,ltstr> {
|
||||
public:
|
||||
EventTypeByName() {
|
||||
for( unsigned i = 0; i < sizeof(EVENT_TYPES)/sizeof(EVENT_TYPES[0]); i++ )
|
||||
|
@ -260,7 +260,7 @@ public:
|
|||
static EventTypeByName EVENT_TYPE_BY_NAME;
|
||||
|
||||
|
||||
FGLinuxInputDevice::FGLinuxInputDevice( string aName, string aDevname ) :
|
||||
FGLinuxInputDevice::FGLinuxInputDevice( std::string aName, std::string aDevname ) :
|
||||
FGInputDevice(aName),
|
||||
devname( aDevname ),
|
||||
fd(-1)
|
||||
|
@ -290,7 +290,7 @@ void FGLinuxInputDevice::Open()
|
|||
{
|
||||
if( fd != -1 ) return;
|
||||
if( (fd = ::open( devname.c_str(), O_RDWR )) == -1 ) {
|
||||
throw exception();
|
||||
throw std::exception();
|
||||
}
|
||||
|
||||
if( GetGrab() && ioctl( fd, EVIOCGRAB, 2 ) == -1 ) {
|
||||
|
@ -440,7 +440,7 @@ const char * FGLinuxInputDevice::TranslateEventName( FGEventData & eventData )
|
|||
return EVENT_NAME_BY_TYPE[typeCode];
|
||||
}
|
||||
|
||||
void FGLinuxInputDevice::SetDevname( string name )
|
||||
void FGLinuxInputDevice::SetDevname( std::string name )
|
||||
{
|
||||
this->devname = name;
|
||||
}
|
||||
|
@ -540,8 +540,8 @@ void FGLinuxEventInput::update( double dt )
|
|||
// index the input devices by the associated fd and prepare
|
||||
// the pollfd array by filling in the file descriptor
|
||||
struct pollfd fds[input_devices.size()];
|
||||
map<int,FGLinuxInputDevice*> devicesByFd;
|
||||
map<int,FGInputDevice*>::const_iterator it;
|
||||
std::map<int,FGLinuxInputDevice*> devicesByFd;
|
||||
std::map<int,FGInputDevice*>::const_iterator it;
|
||||
int i;
|
||||
for( i=0, it = input_devices.begin(); it != input_devices.end(); ++it, i++ ) {
|
||||
FGInputDevice* p = (*it).second;
|
||||
|
|
|
@ -43,7 +43,7 @@ struct FGLinuxEventData : public FGEventData {
|
|||
class FGLinuxInputDevice : public FGInputDevice {
|
||||
public:
|
||||
FGLinuxInputDevice();
|
||||
FGLinuxInputDevice( string name, string devname );
|
||||
FGLinuxInputDevice( std::string name, std::string devname );
|
||||
virtual ~FGLinuxInputDevice();
|
||||
|
||||
virtual void Open();
|
||||
|
@ -51,17 +51,17 @@ public:
|
|||
virtual void Send( const char * eventName, double value );
|
||||
virtual const char * TranslateEventName( FGEventData & eventData );
|
||||
|
||||
void SetDevname( const string name );
|
||||
string GetDevname() const { return devname; }
|
||||
void SetDevname( const std::string name );
|
||||
std::string GetDevname() const { return devname; }
|
||||
|
||||
int GetFd() { return fd; }
|
||||
|
||||
double Normalize( struct input_event & event );
|
||||
private:
|
||||
string devname;
|
||||
std::string devname;
|
||||
int fd;
|
||||
|
||||
map<unsigned int,input_absinfo> absinfo;
|
||||
std::map<unsigned int,input_absinfo> absinfo;
|
||||
};
|
||||
|
||||
class FGLinuxEventInput : public FGEventInput {
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
//
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "FGMouseInput.hxx"
|
||||
#include "Main/globals.hxx"
|
||||
|
||||
|
|
|
@ -34,9 +34,12 @@
|
|||
#include <simgear/props/props_io.hxx>
|
||||
#include <osg/GLU>
|
||||
|
||||
#include <plib/fnt.h>
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
#include <Main/viewmgr.hxx>
|
||||
#include <Main/viewer.hxx>
|
||||
#include <GUI/FGFontCache.hxx>
|
||||
|
||||
#include "HUD.hxx"
|
||||
|
||||
|
|
|
@ -45,7 +45,6 @@ using std::vector;
|
|||
#include <Airports/runways.hxx> // FGRunway
|
||||
#include <GUI/gui.h> // fntRenderer ? guiErrorMessage()
|
||||
#include <GUI/new_gui.hxx> // FGFontCache, FGColor
|
||||
#include <Include/fg_typedefs.h>
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
|
||||
|
|
|
@ -145,6 +145,22 @@ static osg::Vec2 mult(const osg::Vec2& v, const osg::Matrixf& m)
|
|||
return osg::Vec2(r.x(), r.y());
|
||||
}
|
||||
|
||||
class NavDisplay::CacheListener : public SGPropertyChangeListener
|
||||
{
|
||||
public:
|
||||
CacheListener(NavDisplay *nd) :
|
||||
_nd(nd)
|
||||
{}
|
||||
|
||||
virtual void valueChanged (SGPropertyNode * prop)
|
||||
{
|
||||
_nd->invalidatePositionedCache();
|
||||
SG_LOG(SG_INSTR, SG_INFO, "invalidating NavDisplay cache");
|
||||
}
|
||||
private:
|
||||
NavDisplay* _nd;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////
|
||||
|
||||
class SymbolDef
|
||||
|
@ -381,7 +397,13 @@ NavDisplay::~NavDisplay()
|
|||
void
|
||||
NavDisplay::init ()
|
||||
{
|
||||
_cachedItemsValid = false;
|
||||
_cacheListener.reset(new CacheListener(this));
|
||||
|
||||
_serviceable_node = _Instrument->getNode("serviceable", true);
|
||||
_rangeNode = _Instrument->getNode("range", true);
|
||||
_rangeNode->setDoubleValue(40.0);
|
||||
_rangeNode->addChangeListener(_cacheListener.get());
|
||||
|
||||
// texture name to use in 2D and 3D instruments
|
||||
_texture_path = _Instrument->getStringValue("radar-texture-path",
|
||||
|
@ -402,11 +424,6 @@ NavDisplay::init ()
|
|||
_odg = (FGODGauge *)imgr->get_subsystem("od_gauge");
|
||||
_odg->setSize(_Instrument->getIntValue("texture-size", 512));
|
||||
|
||||
|
||||
_user_lat_node = fgGetNode("/position/latitude-deg", true);
|
||||
_user_lon_node = fgGetNode("/position/longitude-deg", true);
|
||||
_user_alt_node = fgGetNode("/position/altitude-ft", true);
|
||||
|
||||
_route = static_cast<FGRouteMgr*>(globals->get_subsystem("route-manager"));
|
||||
|
||||
_navRadio1Node = fgGetNode("/instrumentation/nav[0]", true);
|
||||
|
@ -508,7 +525,7 @@ NavDisplay::update (double delta_time_sec)
|
|||
}
|
||||
_time -= _updateInterval;
|
||||
|
||||
_rangeNm = _Instrument->getFloatValue("range", 40.0);
|
||||
_rangeNm = _rangeNode->getFloatValue();
|
||||
if (_Instrument->getBoolValue("aircraft-heading-up", true)) {
|
||||
_view_heading = fgGetDouble("/orientation/heading-deg");
|
||||
} else {
|
||||
|
@ -527,9 +544,17 @@ NavDisplay::update (double delta_time_sec)
|
|||
_projectMat = osg::Matrixf::scale(_scale, _scale, 1.0) *
|
||||
degRotation(-_view_heading) * _centerTrans;
|
||||
|
||||
_pos = SGGeod::fromDegFt(_user_lon_node->getDoubleValue(),
|
||||
_user_lat_node->getDoubleValue(),
|
||||
_user_alt_node->getDoubleValue());
|
||||
_pos = globals->get_aircraft_position();
|
||||
|
||||
// invalidate the cache of positioned items, if we travelled more than 1nm
|
||||
if (_cachedItemsValid) {
|
||||
SGVec3d cartNow(SGVec3d::fromGeod(_pos));
|
||||
double movedNm = dist(_cachedPos, cartNow) * SG_METER_TO_NM;
|
||||
_cachedItemsValid = (movedNm < 1.0);
|
||||
if (!_cachedItemsValid) {
|
||||
SG_LOG(SG_INSTR, SG_INFO, "invalidating NavDisplay cache due to moving: " << movedNm);
|
||||
}
|
||||
}
|
||||
|
||||
_vertices->clear();
|
||||
_lineVertices->clear();
|
||||
|
@ -538,6 +563,11 @@ NavDisplay::update (double delta_time_sec)
|
|||
_texCoords->clear();
|
||||
_textGeode->removeDrawables(0, _textGeode->getNumDrawables());
|
||||
|
||||
BOOST_FOREACH(SymbolInstance* si, _symbols) {
|
||||
delete si;
|
||||
}
|
||||
_symbols.clear();
|
||||
|
||||
BOOST_FOREACH(SymbolDef* def, _rules) {
|
||||
if (def->enable) {
|
||||
def->enabled = def->enable->test();
|
||||
|
@ -787,15 +817,17 @@ public:
|
|||
|
||||
void NavDisplay::findItems()
|
||||
{
|
||||
Filter filt;
|
||||
filt.minRunwayLengthFt = 2000;
|
||||
if (!_cachedItemsValid) {
|
||||
SG_LOG(SG_INSTR, SG_INFO, "re-validating NavDisplay cache");
|
||||
Filter filt;
|
||||
filt.minRunwayLengthFt = 2000;
|
||||
_itemsInRange = FGPositioned::findWithinRange(_pos, _rangeNm, &filt);
|
||||
_cachedItemsValid = true;
|
||||
_cachedPos = SGVec3d::fromGeod(_pos);
|
||||
}
|
||||
|
||||
FGPositioned::List items =
|
||||
FGPositioned::findWithinRange(_pos, _rangeNm, &filt);
|
||||
|
||||
FGPositioned::List::const_iterator it;
|
||||
for (it = items.begin(); it != items.end(); ++it) {
|
||||
foundPositionedItem(*it);
|
||||
BOOST_FOREACH(FGPositioned* pos, _itemsInRange) {
|
||||
foundPositionedItem(pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1118,11 +1150,26 @@ void NavDisplay::computeAIStates(const SGPropertyNode* ai, string_set& states)
|
|||
}
|
||||
}
|
||||
|
||||
void NavDisplay::addSymbolInstance(const osg::Vec2& proj, double heading, SymbolDef* def, SGPropertyNode* vars)
|
||||
bool NavDisplay::addSymbolInstance(const osg::Vec2& proj, double heading, SymbolDef* def, SGPropertyNode* vars)
|
||||
{
|
||||
if (isProjectedClipped(proj)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SymbolInstance* sym = new SymbolInstance(proj, heading, def, vars);
|
||||
_symbols.push_back(sym);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NavDisplay::isProjectedClipped(const osg::Vec2& projected) const
|
||||
{
|
||||
double size = _odg->size();
|
||||
return (projected.x() < 0.0) ||
|
||||
(projected.y() < 0.0) ||
|
||||
(projected.x() >= size) ||
|
||||
(projected.y() >= size);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -34,11 +34,13 @@
|
|||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
|
||||
#include <Navaids/positioned.hxx>
|
||||
|
||||
class FGODGauge;
|
||||
class FGRouteMgr;
|
||||
class FGNavRecord;
|
||||
class FGPositioned;
|
||||
|
||||
class SymbolInstance;
|
||||
class SymbolDef;
|
||||
|
@ -61,6 +63,10 @@ public:
|
|||
virtual void init();
|
||||
virtual void update(double dt);
|
||||
|
||||
void invalidatePositionedCache()
|
||||
{
|
||||
_cachedItemsValid = false;
|
||||
}
|
||||
protected:
|
||||
std::string _name;
|
||||
int _num;
|
||||
|
@ -70,11 +76,7 @@ protected:
|
|||
SGPropertyNode_ptr _serviceable_node;
|
||||
SGPropertyNode_ptr _Instrument;
|
||||
SGPropertyNode_ptr _radar_mode_control_node;
|
||||
|
||||
SGPropertyNode_ptr _user_lat_node;
|
||||
SGPropertyNode_ptr _user_lon_node;
|
||||
SGPropertyNode_ptr _user_heading_node;
|
||||
SGPropertyNode_ptr _user_alt_node;
|
||||
|
||||
FGODGauge *_odg;
|
||||
|
||||
|
@ -103,11 +105,11 @@ private:
|
|||
bool anyRuleMatches(const std::string& type, const string_set& states) const;
|
||||
void findRules(const std::string& type, const string_set& states, SymbolDefVector& rules);
|
||||
|
||||
void addSymbolInstance(const osg::Vec2& proj, double heading, SymbolDef* def, SGPropertyNode* vars);
|
||||
bool addSymbolInstance(const osg::Vec2& proj, double heading, SymbolDef* def, SGPropertyNode* vars);
|
||||
void addLine(osg::Vec2 a, osg::Vec2 b, const osg::Vec4& color);
|
||||
osg::Vec2 projectBearingRange(double bearingDeg, double rangeNm) const;
|
||||
osg::Vec2 projectGeod(const SGGeod& geod) const;
|
||||
|
||||
bool isProjectedClipped(const osg::Vec2& projected) const;
|
||||
void updateFont();
|
||||
|
||||
std::string _texture_path;
|
||||
|
@ -154,13 +156,21 @@ private:
|
|||
FGRouteMgr* _route;
|
||||
SGGeod _pos;
|
||||
double _rangeNm;
|
||||
SGPropertyNode_ptr _rangeNode;
|
||||
|
||||
SymbolDefVector _rules;
|
||||
FGNavRecord* _nav1Station;
|
||||
FGNavRecord* _nav2Station;
|
||||
std::vector<SymbolInstance*> _symbols;
|
||||
std::set<FGPositioned*> _routeSources;
|
||||
|
||||
bool _cachedItemsValid;
|
||||
SGVec3d _cachedPos;
|
||||
FGPositioned::List _itemsInRange;
|
||||
SGPropertyNode_ptr _excessDataNode;
|
||||
|
||||
class CacheListener;
|
||||
std::auto_ptr<CacheListener> _cacheListener;
|
||||
};
|
||||
|
||||
#endif // _INST_ND_HXX
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
//
|
||||
// This file is in the Public Domain and comes with no warranty.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include <simgear/math/interpolater.hxx>
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
// TODO:
|
||||
// - better spin-up
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
|
||||
#include <iostream>
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
//
|
||||
// This file is in the Public Domain and comes with no warranty.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <simgear/sg_inlines.h>
|
||||
#include <iostream>
|
||||
|
|
|
@ -5,6 +5,10 @@
|
|||
//
|
||||
// This file is in the Public Domain and comes with no warranty.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
//
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <limits>
|
||||
#include <simgear/math/interpolater.hxx>
|
||||
|
||||
|
|
|
@ -440,6 +440,7 @@ void FGNavRadio::updateReceiver(double dt)
|
|||
_gsNeedleDeflectionNorm = 0.0;
|
||||
heading_node->setDoubleValue(0.0);
|
||||
inrange_node->setBoolValue(false);
|
||||
signal_quality_norm_node->setDoubleValue(0.0);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
//
|
||||
// This file is in the Public Domain and comes with no warranty.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "slip_skid_ball.hxx"
|
||||
#include <Main/fg_props.hxx>
|
||||
#include <Main/util.hxx>
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
//
|
||||
// This file is in the Public Domain and comes with no warranty.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <simgear/compiler.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
//
|
||||
// This file is in the Public Domain and comes with no warranty.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <simgear/math/interpolater.hxx>
|
||||
|
||||
#include "vertical_speed_indicator.hxx"
|
||||
|
|
|
@ -77,6 +77,7 @@ target_link_libraries(fgfs
|
|||
${OPENAL_LIBRARY}
|
||||
${OPENGL_LIBRARIES}
|
||||
${PLIB_LIBRARIES}
|
||||
${JPEG_LIBRARY}
|
||||
${LIBSVN_LIBRARIES}
|
||||
${HLA_LIBRARIES}
|
||||
${SIMGEAR_CORE_LIBRARY_DEPENDENCIES}
|
||||
|
|
|
@ -56,6 +56,7 @@
|
|||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/structure/event_mgr.hxx>
|
||||
#include <simgear/structure/SGPerfMon.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/misc/sg_dir.hxx>
|
||||
#include <simgear/misc/sgstream.hxx>
|
||||
|
@ -106,7 +107,7 @@
|
|||
#include <Traffic/TrafficMgr.hxx>
|
||||
#include <MultiPlayer/multiplaymgr.hxx>
|
||||
#include <FDM/fdm_shell.hxx>
|
||||
|
||||
#include <Environment/ephemeris.hxx>
|
||||
#include <Environment/environment_mgr.hxx>
|
||||
|
||||
#include "fg_init.hxx"
|
||||
|
@ -1176,12 +1177,6 @@ bool fgInitGeneral() {
|
|||
// gear, its initialization call should located in this routine.
|
||||
// Returns non-zero if a problem encountered.
|
||||
bool fgInitSubsystems() {
|
||||
// static const SGPropertyNode *longitude
|
||||
// = fgGetNode("/sim/presets/longitude-deg");
|
||||
// static const SGPropertyNode *latitude
|
||||
// = fgGetNode("/sim/presets/latitude-deg");
|
||||
// static const SGPropertyNode *altitude
|
||||
// = fgGetNode("/sim/presets/altitude-ft");
|
||||
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "Initialize Subsystems");
|
||||
SG_LOG( SG_GENERAL, SG_INFO, "========== ==========");
|
||||
|
@ -1205,6 +1200,14 @@ bool fgInitSubsystems() {
|
|||
////////////////////////////////////////////////////////////////////
|
||||
globals->add_subsystem("properties", new FGProperties);
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Add the performance monitoring system.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
globals->add_subsystem("performance-mon",
|
||||
new SGPerformanceMonitor(globals->get_subsystem_mgr(),
|
||||
fgGetNode("/sim/performance-monitor", true)));
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize the material property subsystem.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
@ -1239,6 +1242,7 @@ bool fgInitSubsystems() {
|
|||
|
||||
// Initialize the weather modeling subsystem
|
||||
globals->add_subsystem("environment", new FGEnvironmentMgr);
|
||||
globals->add_subsystem("ephemeris", new Ephemeris);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize the aircraft systems and instrumentation (before the
|
||||
|
@ -1287,9 +1291,7 @@ bool fgInitSubsystems() {
|
|||
// sub system infrastructure.
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
SG_LOG(SG_GENERAL, SG_INFO, " ATC Manager");
|
||||
globals->set_ATC_mgr(new FGATCMgr);
|
||||
globals->get_ATC_mgr()->init();
|
||||
globals->add_subsystem("ATC-old", new FGATCMgr, SGSubsystemMgr::INIT);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Initialize the ATC subsystem
|
||||
|
@ -1311,14 +1313,14 @@ bool fgInitSubsystems() {
|
|||
// Initialise the AI Model Manager
|
||||
////////////////////////////////////////////////////////////////////
|
||||
SG_LOG(SG_GENERAL, SG_INFO, " AI Model Manager");
|
||||
globals->add_subsystem("ai_model", new FGAIManager, SGSubsystemMgr::POST_FDM);
|
||||
globals->add_subsystem("submodel_mgr", new FGSubmodelMgr, SGSubsystemMgr::POST_FDM);
|
||||
globals->add_subsystem("ai-model", new FGAIManager, SGSubsystemMgr::POST_FDM);
|
||||
globals->add_subsystem("submodel-mgr", new FGSubmodelMgr, SGSubsystemMgr::POST_FDM);
|
||||
|
||||
|
||||
// It's probably a good idea to initialize the top level traffic manager
|
||||
// After the AI and ATC systems have been initialized properly.
|
||||
// AI Traffic manager
|
||||
globals->add_subsystem("Traffic Manager", new FGTrafficManager, SGSubsystemMgr::POST_FDM);
|
||||
globals->add_subsystem("traffic-manager", new FGTrafficManager, SGSubsystemMgr::POST_FDM);
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// Add a new 2D panel.
|
||||
|
@ -1453,7 +1455,7 @@ void fgReInitSubsystems()
|
|||
|
||||
// Force reupdating the positions of the ai 3d models. They are used for
|
||||
// initializing ground level for the FDM.
|
||||
globals->get_subsystem("ai_model")->reinit();
|
||||
globals->get_subsystem("ai-model")->reinit();
|
||||
|
||||
// Initialize the FDM
|
||||
globals->get_subsystem("flight")->reinit();
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/scene/material/EffectCullVisitor.hxx>
|
||||
#include <simgear/scene/material/matlib.hxx>
|
||||
#include <simgear/scene/tgdb/SGReaderWriterBTGOptions.hxx>
|
||||
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
||||
#include <simgear/scene/tgdb/userdata.hxx>
|
||||
#include <simgear/scene/tgdb/TileEntry.hxx>
|
||||
#include <simgear/scene/model/ModelRegistry.hxx>
|
||||
|
@ -223,15 +223,14 @@ fgviewerMain(int argc, char** argv)
|
|||
// The file path list must be set in the registry.
|
||||
osgDB::Registry::instance()->getDataFilePathList() = filePathList;
|
||||
|
||||
SGReaderWriterBTGOptions* btgOptions = new SGReaderWriterBTGOptions;
|
||||
btgOptions->getDatabasePathList() = filePathList;
|
||||
btgOptions->setMatlib(globals->get_matlib());
|
||||
btgOptions->setUseRandomObjects(fgGetBool("/sim/rendering/random-objects", false));
|
||||
btgOptions->setUseRandomVegetation(fgGetBool("/sim/rendering/random-vegetation", false));
|
||||
simgear::SGReaderWriterOptions* options = new simgear::SGReaderWriterOptions;
|
||||
options->getDatabasePathList() = filePathList;
|
||||
options->setMaterialLib(globals->get_matlib());
|
||||
options->setPropertyNode(globals->get_props());
|
||||
|
||||
// read the scene from the list of file specified command line args.
|
||||
osg::ref_ptr<osg::Node> loadedModel;
|
||||
loadedModel = osgDB::readNodeFiles(dataFiles, btgOptions);
|
||||
loadedModel = osgDB::readNodeFiles(dataFiles, options);
|
||||
|
||||
// if no model has been successfully loaded report failure.
|
||||
if (!loadedModel.valid()) {
|
||||
|
|
|
@ -47,7 +47,7 @@
|
|||
#include <ATCDCL/ATCmgr.hxx>
|
||||
#include <Autopilot/route_mgr.hxx>
|
||||
#include <Cockpit/panel.hxx>
|
||||
#include <GUI/new_gui.hxx>
|
||||
#include <GUI/FGFontCache.hxx>
|
||||
#include <Model/acmodel.hxx>
|
||||
#include <Model/modelmgr.hxx>
|
||||
#include <MultiPlayer/multiplaymgr.hxx>
|
||||
|
@ -161,16 +161,13 @@ FGGlobals::FGGlobals() :
|
|||
// Destructor
|
||||
FGGlobals::~FGGlobals()
|
||||
{
|
||||
delete renderer;
|
||||
renderer = NULL;
|
||||
|
||||
// The AIModels manager performs a number of actions upon
|
||||
// Shutdown that implicitly assume that other subsystems
|
||||
// are still operational (Due to the dynamic allocation and
|
||||
// deallocation of AIModel objects. To ensure we can safely
|
||||
// shut down all subsystems, make sure we take down the
|
||||
// AIModels system first.
|
||||
SGSubsystem* ai = subsystem_mgr->remove("ai_model");
|
||||
SGSubsystem* ai = subsystem_mgr->remove("ai-model");
|
||||
if (ai) {
|
||||
ai->unbind();
|
||||
delete ai;
|
||||
|
@ -180,6 +177,9 @@ FGGlobals::~FGGlobals()
|
|||
subsystem_mgr->unbind();
|
||||
delete subsystem_mgr;
|
||||
|
||||
delete renderer;
|
||||
renderer = NULL;
|
||||
|
||||
delete time_params;
|
||||
delete mag;
|
||||
delete matlib;
|
||||
|
@ -220,7 +220,7 @@ void FGGlobals::set_fg_root (const string &root) {
|
|||
SGPath tmp( fg_root );
|
||||
tmp.append( "data" );
|
||||
tmp.append( "version" );
|
||||
if ( ulFileExists( tmp.c_str() ) ) {
|
||||
if ( tmp.exists() ) {
|
||||
fgGetNode("BAD_FG_ROOT", true)->setStringValue(fg_root);
|
||||
fg_root += "/data";
|
||||
fgGetNode("GOOD_FG_ROOT", true)->setStringValue(fg_root);
|
||||
|
|
|
@ -67,7 +67,6 @@
|
|||
#include <ATCDCL/ATCmgr.hxx>
|
||||
#include <Time/TimeManager.hxx>
|
||||
#include <Environment/environment_mgr.hxx>
|
||||
#include <Environment/ephemeris.hxx>
|
||||
#include <GUI/gui.h>
|
||||
#include <GUI/new_gui.hxx>
|
||||
#include <MultiPlayer/multiplaymgr.hxx>
|
||||
|
@ -83,7 +82,7 @@
|
|||
#include "fg_os.hxx"
|
||||
#include "WindowSystemAdapter.hxx"
|
||||
#include <Main/viewer.hxx>
|
||||
|
||||
#include <Main/fg_props.hxx>
|
||||
|
||||
using namespace flightgear;
|
||||
|
||||
|
@ -104,33 +103,11 @@ extern int _bootstrap_OSInit;
|
|||
|
||||
// What should we do when we have nothing else to do? Let's get ready
|
||||
// for the next move and update the display?
|
||||
static void fgMainLoop( void ) {
|
||||
|
||||
static SGConstPropertyNode_ptr longitude
|
||||
= fgGetNode("/position/longitude-deg");
|
||||
static SGConstPropertyNode_ptr latitude
|
||||
= fgGetNode("/position/latitude-deg");
|
||||
static SGConstPropertyNode_ptr altitude
|
||||
= fgGetNode("/position/altitude-ft");
|
||||
static SGConstPropertyNode_ptr vn_fps
|
||||
= fgGetNode("/velocities/speed-north-fps");
|
||||
static SGConstPropertyNode_ptr ve_fps
|
||||
= fgGetNode("/velocities/speed-east-fps");
|
||||
static SGConstPropertyNode_ptr vd_fps
|
||||
= fgGetNode("/velocities/speed-down-fps");
|
||||
|
||||
static void fgMainLoop( void )
|
||||
{
|
||||
static SGPropertyNode_ptr frame_signal
|
||||
= fgGetNode("/sim/signals/frame", true);
|
||||
|
||||
static SGPropertyNode_ptr _statisticsFlag
|
||||
= fgGetNode("/sim/timing-statistics/enabled", true);
|
||||
static SGPropertyNode_ptr _statisticsInterval
|
||||
= fgGetNode("/sim/timing-statistics/interval-s", true);
|
||||
static SGPropertyNode_ptr _statiticsMinJitter
|
||||
= fgGetNode("/sim/timing-statistics/min-jitter-ms", true);
|
||||
static SGPropertyNode_ptr _statiticsMinTime
|
||||
= fgGetNode("/sim/timing-statistics/min-time-ms", true);
|
||||
|
||||
frame_signal->fireValueChanged();
|
||||
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "Running Main Loop");
|
||||
|
@ -145,16 +122,9 @@ static void fgMainLoop( void ) {
|
|||
timeMgr->computeTimeDeltas(sim_dt, real_dt);
|
||||
|
||||
// update magvar model
|
||||
globals->get_mag()->update( longitude->getDoubleValue()
|
||||
* SGD_DEGREES_TO_RADIANS,
|
||||
latitude->getDoubleValue()
|
||||
* SGD_DEGREES_TO_RADIANS,
|
||||
altitude->getDoubleValue() * SG_FEET_TO_METER,
|
||||
globals->get_mag()->update( globals->get_aircraft_position(),
|
||||
globals->get_time_params()->getJD() );
|
||||
|
||||
// Run ATC subsystem
|
||||
globals->get_ATC_mgr()->update(sim_dt);
|
||||
|
||||
globals->get_subsystem_mgr()->update(sim_dt);
|
||||
|
||||
// Update the sound manager last so it can use the CPU while the GPU
|
||||
|
@ -218,27 +188,6 @@ static void fgMainLoop( void ) {
|
|||
}
|
||||
}
|
||||
|
||||
// print timing statistics
|
||||
static bool _lastStatisticsFlag = false;
|
||||
if (_lastStatisticsFlag != _statisticsFlag->getBoolValue())
|
||||
{
|
||||
// flag has changed, update subsystem manager
|
||||
_lastStatisticsFlag = _statisticsFlag->getBoolValue();
|
||||
globals->get_subsystem_mgr()->collectDebugTiming(_lastStatisticsFlag);
|
||||
}
|
||||
if (_lastStatisticsFlag)
|
||||
{
|
||||
static double elapsed = 0;
|
||||
elapsed += real_dt;
|
||||
if (elapsed >= _statisticsInterval->getDoubleValue())
|
||||
{
|
||||
// print and reset timing statistics
|
||||
globals->get_subsystem_mgr()->printTimingStatistics(_statiticsMinTime->getDoubleValue(),
|
||||
_statiticsMinJitter->getDoubleValue());
|
||||
elapsed = 0;
|
||||
}
|
||||
}
|
||||
|
||||
simgear::AtomicChangeListener::fireChangeListeners();
|
||||
|
||||
SG_LOG( SG_GENERAL, SG_DEBUG, "" );
|
||||
|
@ -410,63 +359,27 @@ static void fgIdleFunction ( void ) {
|
|||
|
||||
} else if ( idle_state == 6 ) {
|
||||
idle_state++;
|
||||
// Initialize the sky
|
||||
|
||||
Ephemeris* eph = new Ephemeris;
|
||||
globals->add_subsystem("ephemeris", eph);
|
||||
eph->init(); // FIXME - remove this once SGSky code below is also a subsystem
|
||||
eph->bind();
|
||||
|
||||
// TODO: move to environment mgr
|
||||
thesky = new SGSky;
|
||||
SGPath texture_path(globals->get_fg_root());
|
||||
texture_path.append("Textures");
|
||||
texture_path.append("Sky");
|
||||
for (int i = 0; i < FGEnvironmentMgr::MAX_CLOUD_LAYERS; i++) {
|
||||
SGCloudLayer * layer = new SGCloudLayer(texture_path.str());
|
||||
thesky->add_cloud_layer(layer);
|
||||
}
|
||||
|
||||
SGPath sky_tex_path( globals->get_fg_root() );
|
||||
sky_tex_path.append( "Textures" );
|
||||
sky_tex_path.append( "Sky" );
|
||||
thesky->texture_path( sky_tex_path.str() );
|
||||
|
||||
// The sun and moon diameters are scaled down numbers of the
|
||||
// actual diameters. This was needed to fit both the sun and the
|
||||
// moon within the distance to the far clip plane.
|
||||
// Moon diameter: 3,476 kilometers
|
||||
// Sun diameter: 1,390,000 kilometers
|
||||
thesky->build( 80000.0, 80000.0,
|
||||
463.3, 361.8,
|
||||
*globals->get_ephem(),
|
||||
fgGetNode("/environment", true));
|
||||
|
||||
// Initialize MagVar model
|
||||
SGMagVar *magvar = new SGMagVar();
|
||||
globals->set_mag( magvar );
|
||||
|
||||
|
||||
// kludge to initialize mag compass
|
||||
// (should only be done for in-flight
|
||||
// startup)
|
||||
// kludge to initialize mag compass
|
||||
// (should only be done for in-flight
|
||||
// startup)
|
||||
// update magvar model
|
||||
globals->get_mag()->update( fgGetDouble("/position/longitude-deg")
|
||||
* SGD_DEGREES_TO_RADIANS,
|
||||
fgGetDouble("/position/latitude-deg")
|
||||
* SGD_DEGREES_TO_RADIANS,
|
||||
fgGetDouble("/position/altitude-ft")
|
||||
* SG_FEET_TO_METER,
|
||||
globals->get_time_params()->getJD() );
|
||||
* SGD_DEGREES_TO_RADIANS,
|
||||
fgGetDouble("/position/latitude-deg")
|
||||
* SGD_DEGREES_TO_RADIANS,
|
||||
fgGetDouble("/position/altitude-ft")
|
||||
* SG_FEET_TO_METER,
|
||||
globals->get_time_params()->getJD() );
|
||||
double var = globals->get_mag()->get_magvar() * SGD_RADIANS_TO_DEGREES;
|
||||
fgSetDouble("/instrumentation/heading-indicator/offset-deg", -var);
|
||||
fgSetDouble("/instrumentation/heading-indicator-fg/offset-deg", -var);
|
||||
|
||||
|
||||
// airport = new ssgBranch;
|
||||
// airport->setName( "Airport Lighting" );
|
||||
// lighting->addKid( airport );
|
||||
|
||||
fgSplashProgress("initializing subsystems");
|
||||
|
||||
} else if ( idle_state == 7 ) {
|
||||
|
|
|
@ -80,6 +80,7 @@ using std::cout;
|
|||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::vector;
|
||||
using std::cin;
|
||||
|
||||
#define NEW_DEFAULT_MODEL_HZ 120
|
||||
|
||||
|
@ -1560,6 +1561,10 @@ public:
|
|||
{
|
||||
OptionValueVec::const_iterator it = values.begin();
|
||||
for (; it != values.end(); ++it) {
|
||||
if (!it->desc) {
|
||||
continue; // ignore markers
|
||||
}
|
||||
|
||||
if (it->desc->option == key) {
|
||||
return it;
|
||||
}
|
||||
|
@ -1580,6 +1585,10 @@ public:
|
|||
|
||||
int processOption(OptionDesc* desc, const string& arg_value)
|
||||
{
|
||||
if (!desc) {
|
||||
return FG_OPTIONS_OK; // tolerate marker options
|
||||
}
|
||||
|
||||
switch ( desc->type & 0xffff ) {
|
||||
case OPTION_BOOL:
|
||||
fgSetBool( desc->property, desc->b_param );
|
||||
|
@ -1648,9 +1657,35 @@ public:
|
|||
return FG_OPTIONS_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* insert a marker value into the values vector. This is necessary
|
||||
* when processing options, to ensure the correct ordering, where we scan
|
||||
* for marker values in reverse, and then forwards within each group.
|
||||
*/
|
||||
void insertGroupMarker()
|
||||
{
|
||||
values.push_back(OptionValue(NULL, "-"));
|
||||
}
|
||||
|
||||
/**
|
||||
* given a current iterator into the values, find the preceeding group marker,
|
||||
* or return the beginning of the value vector.
|
||||
*/
|
||||
OptionValueVec::const_iterator rfindGroup(OptionValueVec::const_iterator pos) const
|
||||
{
|
||||
while (--pos != values.begin()) {
|
||||
if (pos->desc == NULL) {
|
||||
return pos; // found a marker, we're done
|
||||
}
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
bool showHelp,
|
||||
verbose,
|
||||
showAircraft;
|
||||
|
||||
OptionDescDict options;
|
||||
OptionValueVec values;
|
||||
simgear::PathList propertyFiles;
|
||||
|
@ -1710,6 +1745,7 @@ void Options::init(int argc, char **argv, const SGPath& appDataPath)
|
|||
p->propertyFiles.push_back(f);
|
||||
}
|
||||
} // of arguments iteration
|
||||
p->insertGroupMarker(); // command line is one group
|
||||
|
||||
// then config files
|
||||
SGPath config;
|
||||
|
@ -1850,6 +1886,7 @@ void Options::readConfig(const SGPath& path)
|
|||
in >> skipcomment;
|
||||
}
|
||||
|
||||
p->insertGroupMarker(); // each config file is a group
|
||||
}
|
||||
|
||||
int Options::parseOption(const string& s)
|
||||
|
@ -1898,6 +1935,7 @@ int Options::addOption(const string &key, const string &value)
|
|||
{
|
||||
OptionDesc* desc = p->findOption(key);
|
||||
if (!desc) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "unknown option:" << key);
|
||||
return FG_OPTIONS_ERROR;
|
||||
}
|
||||
|
||||
|
@ -1934,6 +1972,10 @@ string_list Options::valuesForOption(const std::string& key) const
|
|||
string_list result;
|
||||
OptionValueVec::const_iterator it = p->values.begin();
|
||||
for (; it != p->values.end(); ++it) {
|
||||
if (!it->desc) {
|
||||
continue; // ignore marker values
|
||||
}
|
||||
|
||||
if (it->desc->option == key) {
|
||||
result.push_back(it->value);
|
||||
}
|
||||
|
@ -1951,15 +1993,26 @@ void Options::processOptions()
|
|||
exit(0);
|
||||
}
|
||||
|
||||
// proces options in LIFO order, so earlier (first in) options are processed
|
||||
// after, and hence override, later specified options.
|
||||
OptionValueVec::const_reverse_iterator it = p->values.rbegin();
|
||||
for (; it != p->values.rend(); ++it) {
|
||||
int result = p->processOption(it->desc, it->value);
|
||||
if (result == FG_OPTIONS_ERROR) {
|
||||
showUsage();
|
||||
exit(-1);
|
||||
// processing order is complicated. We must process groups LIFO, but the
|
||||
// values *within* each group in FIFO order, to retain consistency with
|
||||
// older versions of FG, and existing user configs.
|
||||
// in practice this means system.fgfsrc must be *processed* before
|
||||
// .fgfsrc, which must be processed before the command line args, and so on.
|
||||
OptionValueVec::const_iterator groupEnd = p->values.end();
|
||||
|
||||
while (groupEnd != p->values.begin()) {
|
||||
OptionValueVec::const_iterator groupBegin = p->rfindGroup(groupEnd);
|
||||
// run over the group in FIFO order
|
||||
OptionValueVec::const_iterator it;
|
||||
for (it = groupBegin; it != groupEnd; ++it) {
|
||||
int result = p->processOption(it->desc, it->value);
|
||||
if (result == FG_OPTIONS_ERROR) {
|
||||
showUsage();
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
groupEnd = groupBegin;
|
||||
}
|
||||
|
||||
BOOST_FOREACH(const SGPath& file, p->propertyFiles) {
|
||||
|
@ -2137,8 +2190,8 @@ void Options::showUsage() const
|
|||
cout << "For a complete list of options use --help --verbose" << endl;
|
||||
}
|
||||
#ifdef _MSC_VER
|
||||
cout << "Hit a key to continue..." << endl;
|
||||
cin.get();
|
||||
std::cout << "Hit a key to continue..." << std::endl;
|
||||
std::cin.get();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -93,6 +93,7 @@
|
|||
#include <GUI/new_gui.hxx>
|
||||
#include <Instrumentation/HUD/HUD.hxx>
|
||||
#include <Environment/precipitation_mgr.hxx>
|
||||
#include <Environment/environment_mgr.hxx>
|
||||
|
||||
#include "splash.hxx"
|
||||
#include "renderer.hxx"
|
||||
|
@ -374,9 +375,6 @@ public:
|
|||
|
||||
bool FGScenerySwitchCallback::scenery_enabled = false;
|
||||
|
||||
// Sky structures
|
||||
SGSky *thesky;
|
||||
|
||||
static osg::ref_ptr<osg::FrameStamp> mFrameStamp = new osg::FrameStamp;
|
||||
static osg::ref_ptr<SGUpdateVisitor> mUpdateVisitor= new SGUpdateVisitor;
|
||||
|
||||
|
@ -391,7 +389,8 @@ static void updateRenderer()
|
|||
}
|
||||
#endif
|
||||
|
||||
FGRenderer::FGRenderer()
|
||||
FGRenderer::FGRenderer() :
|
||||
_sky(NULL)
|
||||
{
|
||||
#ifdef FG_JPEG_SERVER
|
||||
jpgRenderFrame = updateRenderer;
|
||||
|
@ -404,6 +403,7 @@ FGRenderer::~FGRenderer()
|
|||
#ifdef FG_JPEG_SERVER
|
||||
jpgRenderFrame = NULL;
|
||||
#endif
|
||||
delete _sky;
|
||||
}
|
||||
|
||||
// Initialize various GL/view parameters
|
||||
|
@ -411,7 +411,7 @@ FGRenderer::~FGRenderer()
|
|||
// critical parts of the scene graph in addition to the splash screen.
|
||||
void
|
||||
FGRenderer::splashinit( void ) {
|
||||
osgViewer::Viewer* viewer = globals->get_renderer()->getViewer();
|
||||
osgViewer::Viewer* viewer = getViewer();
|
||||
mRealRoot = dynamic_cast<osg::Group*>(viewer->getSceneData());
|
||||
mRealRoot->addChild(fgCreateSplashNode());
|
||||
mFrameStamp = viewer->getFrameStamp();
|
||||
|
@ -454,6 +454,20 @@ FGRenderer::init( void )
|
|||
|
||||
SGConfigureDirectionalLights( use_point_sprites, enhanced_lighting,
|
||||
distance_attenuation );
|
||||
|
||||
// create sky, but can't build until setupView, since we depend
|
||||
// on other subsystems to be inited, eg Ephemeris
|
||||
_sky = new SGSky;
|
||||
|
||||
SGPath texture_path(globals->get_fg_root());
|
||||
texture_path.append("Textures");
|
||||
texture_path.append("Sky");
|
||||
for (int i = 0; i < FGEnvironmentMgr::MAX_CLOUD_LAYERS; i++) {
|
||||
SGCloudLayer * layer = new SGCloudLayer(texture_path.str());
|
||||
_sky->add_cloud_layer(layer);
|
||||
}
|
||||
|
||||
_sky->texture_path( texture_path.str() );
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -472,6 +486,17 @@ FGRenderer::setupView( void )
|
|||
if ( fgGetBool("/sim/startup/fullscreen") )
|
||||
fgOSFullScreen();
|
||||
|
||||
// build the sky
|
||||
// The sun and moon diameters are scaled down numbers of the
|
||||
// actual diameters. This was needed to fit both the sun and the
|
||||
// moon within the distance to the far clip plane.
|
||||
// Moon diameter: 3,476 kilometers
|
||||
// Sun diameter: 1,390,000 kilometers
|
||||
_sky->build( 80000.0, 80000.0,
|
||||
463.3, 361.8,
|
||||
*globals->get_ephem(),
|
||||
fgGetNode("/environment", true));
|
||||
|
||||
viewer->getCamera()
|
||||
->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
|
||||
|
@ -547,15 +572,17 @@ FGRenderer::setupView( void )
|
|||
sunLight->setUpdateCallback(new FGLightSourceUpdateCallback(true));
|
||||
sunLight->setReferenceFrame(osg::LightSource::RELATIVE_RF);
|
||||
sunLight->setLocalStateSetModes(osg::StateAttribute::ON);
|
||||
|
||||
// Hang a StateSet above the sky subgraph in order to turn off
|
||||
// light 0
|
||||
Group* skyGroup = new Group;
|
||||
StateSet* skySS = skyGroup->getOrCreateStateSet();
|
||||
skySS->setMode(GL_LIGHT0, StateAttribute::OFF);
|
||||
skyGroup->addChild(thesky->getPreRoot());
|
||||
skyGroup->addChild(_sky->getPreRoot());
|
||||
sunLight->addChild(skyGroup);
|
||||
mRoot->addChild(sceneGroup);
|
||||
mRoot->addChild(sunLight);
|
||||
|
||||
// Clouds are added to the scene graph later
|
||||
stateSet = globals->get_scenery()->get_scene_graph()->getOrCreateStateSet();
|
||||
stateSet->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
|
||||
|
@ -594,7 +621,7 @@ FGRenderer::setupView( void )
|
|||
// The clouds are attached directly to the scene graph root
|
||||
// because, in theory, they don't want the same default state set
|
||||
// as the rest of the scene. This may not be true in practice.
|
||||
mRealRoot->addChild(thesky->getCloudRoot());
|
||||
mRealRoot->addChild(_sky->getCloudRoot());
|
||||
mRealRoot->addChild(FGCreateRedoutNode());
|
||||
// Attach empty program to the scene root so that shader programs
|
||||
// don't leak into state sets (effects) that shouldn't have one.
|
||||
|
@ -644,7 +671,7 @@ FGRenderer::update( ) {
|
|||
// update fog params
|
||||
double actual_visibility;
|
||||
if (_cloud_status->getBoolValue()) {
|
||||
actual_visibility = thesky->get_visibility();
|
||||
actual_visibility = _sky->get_visibility();
|
||||
} else {
|
||||
actual_visibility = _visibility_m->getDoubleValue();
|
||||
}
|
||||
|
@ -673,10 +700,10 @@ FGRenderer::update( ) {
|
|||
|
||||
// update fog params if visibility has changed
|
||||
double visibility_meters = _visibility_m->getDoubleValue();
|
||||
thesky->set_visibility(visibility_meters);
|
||||
_sky->set_visibility(visibility_meters);
|
||||
|
||||
double altitude_m = _altitude_ft->getDoubleValue() * SG_FEET_TO_METER;
|
||||
thesky->modify_vis( altitude_m, 0.0 /* time factor, now unused */);
|
||||
_sky->modify_vis( altitude_m, 0.0 /* time factor, now unused */);
|
||||
|
||||
// update the sky dome
|
||||
if ( skyblend ) {
|
||||
|
@ -720,8 +747,8 @@ FGRenderer::update( ) {
|
|||
scolor.moon_angle = l->get_moon_angle();
|
||||
|
||||
double delta_time_sec = _sim_delta_sec->getDoubleValue();
|
||||
thesky->reposition( sstate, *globals->get_ephem(), delta_time_sec );
|
||||
thesky->repaint( scolor, *globals->get_ephem() );
|
||||
_sky->reposition( sstate, *globals->get_ephem(), delta_time_sec );
|
||||
_sky->repaint( scolor, *globals->get_ephem() );
|
||||
|
||||
//OSGFIXME
|
||||
// shadows->setupShadows(
|
||||
|
|
|
@ -35,7 +35,6 @@ class FGEventHandler;
|
|||
}
|
||||
|
||||
class SGSky;
|
||||
extern SGSky *thesky;
|
||||
|
||||
class FGRenderer {
|
||||
|
||||
|
@ -73,6 +72,8 @@ public:
|
|||
*/
|
||||
void addCamera(osg::Camera* camera, bool useSceneData);
|
||||
|
||||
SGSky* getSky() const { return _sky; }
|
||||
|
||||
protected:
|
||||
osg::ref_ptr<osgViewer::Viewer> viewer;
|
||||
osg::ref_ptr<flightgear::FGEventHandler> eventHandler;
|
||||
|
@ -85,6 +86,7 @@ protected:
|
|||
SGPropertyNode_ptr _panel_hotspots, _sim_delta_sec, _horizon_effect, _altitude_ft;
|
||||
SGPropertyNode_ptr _virtual_cockpit;
|
||||
SGTimeStamp _splash_time;
|
||||
SGSky* _sky;
|
||||
};
|
||||
|
||||
bool fgDumpSceneGraphToFile(const char* filename);
|
||||
|
|
|
@ -46,7 +46,10 @@
|
|||
#include <simgear/math/sg_random.h>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
|
||||
#include <GUI/new_gui.hxx>
|
||||
#include <plib/fnt.h>
|
||||
|
||||
#include "GUI/FGFontCache.hxx"
|
||||
#include "GUI/FGColor.hxx"
|
||||
|
||||
#include "globals.hxx"
|
||||
#include "fg_props.hxx"
|
||||
|
|
|
@ -75,7 +75,7 @@ FGModelMgr::add_model (SGPropertyNode * node)
|
|||
osg::Node *object;
|
||||
|
||||
try {
|
||||
object = SGModelLib::loadPagedModel(path, globals->get_props());
|
||||
object = SGModelLib::loadDeferredModel(path, globals->get_props());
|
||||
} catch (const sg_throwable& t) {
|
||||
SG_LOG(SG_GENERAL, SG_ALERT, "Error loading " << path << ":\n "
|
||||
<< t.getFormattedMessage() << t.getOrigin());
|
||||
|
|
|
@ -1309,7 +1309,7 @@ FGMultiplayMgr::addMultiplayer(const std::string& callsign,
|
|||
mp->setCallSign(callsign);
|
||||
mMultiPlayerMap[callsign] = mp;
|
||||
|
||||
FGAIManager *aiMgr = (FGAIManager*)globals->get_subsystem("ai_model");
|
||||
FGAIManager *aiMgr = (FGAIManager*)globals->get_subsystem("ai-model");
|
||||
if (aiMgr) {
|
||||
aiMgr->attach(mp);
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <Navaids/routePath.hxx>
|
||||
|
||||
#include <simgear/structure/exception.hxx>
|
||||
|
|
|
@ -701,7 +701,7 @@ public:
|
|||
if (modelPath.empty())
|
||||
return;
|
||||
FGAIManager *aiMgr;
|
||||
aiMgr = static_cast<FGAIManager*>(globals->get_subsystem("ai_model"));
|
||||
aiMgr = static_cast<FGAIManager*>(globals->get_subsystem("ai-model"));
|
||||
if (!aiMgr)
|
||||
return;
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <simgear/scene/model/SGPagedLOD.hxx>
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include "SceneryPager.hxx"
|
||||
#include <algorithm>
|
||||
|
@ -44,25 +43,6 @@ SceneryPager::~SceneryPager()
|
|||
{
|
||||
}
|
||||
|
||||
#if SG_PAGEDLOD_HAS_OPTIONS
|
||||
#else
|
||||
void SceneryPager::requestNodeFile(const std::string& fileName, Group* group,
|
||||
float priority, const FrameStamp* framestamp,
|
||||
ref_ptr<Referenced>& databaseRequest,
|
||||
osgDB::ReaderWriter::Options* options)
|
||||
{
|
||||
simgear::SGPagedLOD *sgplod = dynamic_cast<simgear::SGPagedLOD*>(group);
|
||||
if(sgplod)
|
||||
DatabasePager::requestNodeFile(fileName, group, priority, framestamp,
|
||||
databaseRequest,
|
||||
sgplod->getReaderWriterOptions());
|
||||
else
|
||||
DatabasePager::requestNodeFile(fileName, group, priority, framestamp,
|
||||
databaseRequest,
|
||||
options);
|
||||
}
|
||||
#endif
|
||||
|
||||
void SceneryPager::queueRequest(const std::string& fileName, Group* group,
|
||||
float priority, FrameStamp* frameStamp,
|
||||
ref_ptr<Referenced>& databaseRequest,
|
||||
|
|
|
@ -28,7 +28,6 @@
|
|||
#include <osgDB/DatabasePager>
|
||||
|
||||
#include <simgear/structure/OSGVersion.hxx>
|
||||
#include <simgear/scene/model/SGPagedLOD.hxx>
|
||||
|
||||
namespace flightgear
|
||||
{
|
||||
|
@ -39,15 +38,6 @@ public:
|
|||
SceneryPager(const SceneryPager& rhs);
|
||||
// Unhide DatabasePager::requestNodeFile
|
||||
using osgDB::DatabasePager::requestNodeFile;
|
||||
// reimplement to add readerWriterOptions from SGPagedLOD
|
||||
#if SG_PAGEDLOD_HAS_OPTIONS
|
||||
#else
|
||||
virtual void requestNodeFile(const std::string& fileName, osg::Group* group,
|
||||
float priority,
|
||||
const osg::FrameStamp* framestamp,
|
||||
osg::ref_ptr<osg::Referenced>& databaseRequest,
|
||||
osgDB::ReaderWriter::Options* options);
|
||||
#endif
|
||||
void queueRequest(const std::string& fileName, osg::Group* node,
|
||||
float priority, osg::FrameStamp* frameStamp,
|
||||
osg::ref_ptr<osg::Referenced>& databaseRequest,
|
||||
|
|
|
@ -29,12 +29,13 @@
|
|||
#include <functional>
|
||||
|
||||
#include <osgViewer/Viewer>
|
||||
#include <osgDB/Registry>
|
||||
|
||||
#include <simgear/constants.h>
|
||||
#include <simgear/debug/logstream.hxx>
|
||||
#include <simgear/structure/exception.hxx>
|
||||
#include <simgear/scene/model/modellib.hxx>
|
||||
#include <simgear/scene/tgdb/SGReaderWriterBTGOptions.hxx>
|
||||
#include <simgear/scene/util/SGReaderWriterOptions.hxx>
|
||||
#include <simgear/scene/tsync/terrasync.hxx>
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
|
@ -54,33 +55,11 @@ using simgear::TileEntry;
|
|||
using simgear::TileCache;
|
||||
|
||||
|
||||
// helper: listen to property changes affecting tile loading
|
||||
class LoaderPropertyWatcher : public SGPropertyChangeListener
|
||||
{
|
||||
public:
|
||||
LoaderPropertyWatcher(FGTileMgr* pTileMgr) :
|
||||
_pTileMgr(pTileMgr)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void valueChanged(SGPropertyNode*)
|
||||
{
|
||||
_pTileMgr->configChanged();
|
||||
}
|
||||
|
||||
private:
|
||||
FGTileMgr* _pTileMgr;
|
||||
};
|
||||
|
||||
|
||||
FGTileMgr::FGTileMgr():
|
||||
state( Start ),
|
||||
vis( 16000 ),
|
||||
_terra_sync(NULL),
|
||||
_propListener(new LoaderPropertyWatcher(this))
|
||||
_terra_sync(NULL)
|
||||
{
|
||||
_randomObjects = fgGetNode("/sim/rendering/random-objects", true);
|
||||
_randomVegetation = fgGetNode("/sim/rendering/random-vegetation", true);
|
||||
_maxTileRangeM = fgGetNode("/sim/rendering/static-lod/bare", true);
|
||||
}
|
||||
|
||||
|
@ -90,8 +69,6 @@ FGTileMgr::~FGTileMgr()
|
|||
// remove all nodes we might have left behind
|
||||
osg::Group* group = globals->get_scenery()->get_terrain_branch();
|
||||
group->removeChildren(0, group->getNumChildren());
|
||||
delete _propListener;
|
||||
_propListener = NULL;
|
||||
// clear OSG cache
|
||||
osgDB::Registry::instance()->clearObjectCache();
|
||||
}
|
||||
|
@ -101,12 +78,9 @@ FGTileMgr::~FGTileMgr()
|
|||
void FGTileMgr::init() {
|
||||
SG_LOG( SG_TERRAIN, SG_INFO, "Initializing Tile Manager subsystem." );
|
||||
|
||||
_options = new SGReaderWriterBTGOptions;
|
||||
_options->setMatlib(globals->get_matlib());
|
||||
|
||||
_randomObjects.get()->addChangeListener(_propListener, false);
|
||||
_randomVegetation.get()->addChangeListener(_propListener, false);
|
||||
configChanged();
|
||||
_options = new simgear::SGReaderWriterOptions;
|
||||
_options->setMaterialLib(globals->get_matlib());
|
||||
_options->setPropertyNode(globals->get_props());
|
||||
|
||||
osgDB::FilePathList &fp = _options->getDatabasePathList();
|
||||
const string_list &sc = globals->get_fg_scenery();
|
||||
|
@ -120,6 +94,10 @@ void FGTileMgr::init() {
|
|||
reinit();
|
||||
}
|
||||
|
||||
void FGTileMgr::refresh_tile(void* tileMgr, long tileIndex)
|
||||
{
|
||||
((FGTileMgr*) tileMgr)->tile_cache.refresh_tile(tileIndex);
|
||||
}
|
||||
|
||||
void FGTileMgr::reinit()
|
||||
{
|
||||
|
@ -142,18 +120,12 @@ void FGTileMgr::reinit()
|
|||
|
||||
_terra_sync = (simgear::SGTerraSync*) globals->get_subsystem("terrasync");
|
||||
if (_terra_sync)
|
||||
_terra_sync->setTileCache(&tile_cache);
|
||||
_terra_sync->setTileRefreshCb(&refresh_tile, this);
|
||||
|
||||
// force an update now
|
||||
update(0.0);
|
||||
}
|
||||
|
||||
void FGTileMgr::configChanged()
|
||||
{
|
||||
_options->setUseRandomObjects(_randomObjects.get()->getBoolValue());
|
||||
_options->setUseRandomVegetation(_randomVegetation.get()->getBoolValue());
|
||||
}
|
||||
|
||||
/* schedule a tile for loading, keep request for given amount of time.
|
||||
* Returns true if tile is already loaded. */
|
||||
bool FGTileMgr::sched_tile( const SGBucket& b, double priority, bool current_view, double duration)
|
||||
|
@ -275,8 +247,8 @@ FGTileMgr::loadTileModel(const string& modelPath, bool cacheModel)
|
|||
new FGNasalModelData);
|
||||
else
|
||||
result=
|
||||
SGModelLib::loadPagedModel(fullPath.str(), globals->get_props(),
|
||||
new FGNasalModelData);
|
||||
SGModelLib::loadDeferredModel(fullPath.str(), globals->get_props(),
|
||||
new FGNasalModelData);
|
||||
} catch (const sg_io_exception& exc) {
|
||||
string m(exc.getMessage());
|
||||
m += " ";
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
#include <simgear/scene/tgdb/TileEntry.hxx>
|
||||
#include <simgear/scene/tgdb/TileCache.hxx>
|
||||
|
||||
class SGReaderWriterBTGOptions;
|
||||
|
||||
namespace osg
|
||||
{
|
||||
class Node;
|
||||
|
@ -41,6 +39,7 @@ class Node;
|
|||
namespace simgear
|
||||
{
|
||||
class SGTerraSync;
|
||||
class SGReaderWriterOptions;
|
||||
}
|
||||
|
||||
class FGTileMgr : public SGSubsystem, public simgear::ModelLoadHelper {
|
||||
|
@ -65,7 +64,7 @@ private:
|
|||
SGBucket previous_bucket;
|
||||
SGBucket current_bucket;
|
||||
SGBucket pending;
|
||||
osg::ref_ptr<SGReaderWriterBTGOptions> _options;
|
||||
osg::ref_ptr<simgear::SGReaderWriterOptions> _options;
|
||||
|
||||
// x and y distance of tiles to load/draw
|
||||
float vis;
|
||||
|
@ -86,10 +85,9 @@ private:
|
|||
// internal function, do not call directly.)
|
||||
void update_queues();
|
||||
|
||||
static void refresh_tile(void* tileMgr, long tileIndex);
|
||||
|
||||
SGPropertyNode* _visibilityMeters;
|
||||
SGPropertyChangeListener* _propListener;
|
||||
SGPropertyNode_ptr _randomObjects;
|
||||
SGPropertyNode_ptr _randomVegetation;
|
||||
SGPropertyNode_ptr _maxTileRangeM;
|
||||
|
||||
public:
|
||||
|
@ -103,9 +101,6 @@ public:
|
|||
|
||||
virtual void update(double dt);
|
||||
|
||||
// update loader configuration options
|
||||
void configChanged();
|
||||
|
||||
int schedule_tiles_at(const SGGeod& location, double rangeM);
|
||||
|
||||
|
||||
|
|
|
@ -20,6 +20,10 @@
|
|||
//
|
||||
// $Id$
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <Main/globals.hxx>
|
||||
#include <sstream>
|
||||
#include <simgear/compiler.h>
|
||||
|
|
|
@ -3,6 +3,10 @@
|
|||
//
|
||||
// This file is in the Public Domain and comes with no warranty.
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "static.hxx"
|
||||
|
||||
#include <string>
|
||||
|
|
|
@ -102,6 +102,7 @@ void TimeManager::init()
|
|||
// frame-rate / worst-case latency / update-rate counters
|
||||
_frameRate = fgGetNode("/sim/frame-rate", true);
|
||||
_frameLatency = fgGetNode("/sim/frame-latency-max-ms", true);
|
||||
_frameRateWorst = fgGetNode("/sim/frame-rate-worst", true);
|
||||
_lastFrameTime = 0;
|
||||
_frameLatencyMax = 0.0;
|
||||
_frameCount = 0;
|
||||
|
@ -267,6 +268,8 @@ void TimeManager::computeFrameRate()
|
|||
if ((_impl->get_cur_time() != _lastFrameTime)) {
|
||||
_frameRate->setIntValue(_frameCount);
|
||||
_frameLatency->setDoubleValue(_frameLatencyMax*1000);
|
||||
if (_frameLatencyMax>0)
|
||||
_frameRateWorst->setIntValue(1/_frameLatencyMax);
|
||||
_frameCount = 0;
|
||||
_frameLatencyMax = 0.0;
|
||||
}
|
||||
|
@ -331,7 +334,7 @@ void TimeManager::setTimeOffset(const std::string& offset_type, long int offset)
|
|||
} else if ( offset_type == "noon" ) {
|
||||
warp = fgTimeSecondsUntilSunAngle( cur_time, lon, lat, 0.0, true );
|
||||
} else if ( offset_type == "afternoon" ) {
|
||||
warp = fgTimeSecondsUntilSunAngle( cur_time, lon, lat, 60.0, false );
|
||||
warp = fgTimeSecondsUntilSunAngle( cur_time, lon, lat, 75.0, false );
|
||||
} else if ( offset_type == "dusk" ) {
|
||||
warp = fgTimeSecondsUntilSunAngle( cur_time, lon, lat, 90.0, false );
|
||||
} else if ( offset_type == "evening" ) {
|
||||
|
|
|
@ -82,6 +82,7 @@ private:
|
|||
|
||||
// frame-rate / worst-case latency / update-rate counters
|
||||
SGPropertyNode_ptr _frameRate;
|
||||
SGPropertyNode_ptr _frameRateWorst;
|
||||
SGPropertyNode_ptr _frameLatency;
|
||||
time_t _lastFrameTime;
|
||||
double _frameLatencyMax;
|
||||
|
|
|
@ -149,6 +149,7 @@ void FGLight::bind () {
|
|||
prop->tie("/rendering/scene/overcast",SGRawValuePointer<float>(&_overcast));
|
||||
|
||||
_sunAngleRad = prop->getNode("/sim/time/sun-angle-rad", true);
|
||||
_sunAngleRad->setDoubleValue(_sun_angle);
|
||||
|
||||
// Read Only
|
||||
prop->tie("/rendering/scene/ambient/red",SGRawValuePointer<float>(&_scene_ambient[0]));
|
||||
|
@ -290,6 +291,8 @@ void FGLight::update_sky_color () {
|
|||
_scene_ambient[3] = 1.0;
|
||||
gamma_correct_rgb( _scene_ambient.data() );
|
||||
|
||||
SGSky* thesky = globals->get_renderer()->getSky();
|
||||
|
||||
SGVec4f color = thesky->get_scene_color();
|
||||
_scene_diffuse[0] = color[0] * diffuse;
|
||||
_scene_diffuse[1] = color[1] * diffuse;
|
||||
|
@ -361,6 +364,7 @@ void FGLight::update_adj_fog_color () {
|
|||
|
||||
// revert to unmodified values before using them.
|
||||
//
|
||||
SGSky* thesky = globals->get_renderer()->getSky();
|
||||
SGVec4f color = thesky->get_scene_color();
|
||||
|
||||
gamma_restore_rgb( _fog_color.data(), gamma );
|
||||
|
|
|
@ -228,7 +228,7 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
|
|||
|
||||
if (AIManagerRef) {
|
||||
// Check if this aircraft has been released.
|
||||
FGTrafficManager *tmgr = (FGTrafficManager *) globals->get_subsystem("Traffic Manager");
|
||||
FGTrafficManager *tmgr = (FGTrafficManager *) globals->get_subsystem("traffic-manager");
|
||||
if (tmgr->isReleased(AIManagerRef)) {
|
||||
AIManagerRef = 0;
|
||||
} else {
|
||||
|
@ -347,7 +347,7 @@ bool FGAISchedule::createAIAircraft(FGScheduledFlight* flight, double speedKnots
|
|||
airline);
|
||||
if (fp->isValidPlan()) {
|
||||
aircraft->SetFlightPlan(fp);
|
||||
FGAIManager* aimgr = (FGAIManager *) globals-> get_subsystem("ai_model");
|
||||
FGAIManager* aimgr = (FGAIManager *) globals-> get_subsystem("ai-model");
|
||||
aimgr->attach(aircraft);
|
||||
AIManagerRef = aircraft->getID();
|
||||
return true;
|
||||
|
@ -465,7 +465,7 @@ FGScheduledFlight* FGAISchedule::findAvailableFlight (const string ¤tDesti
|
|||
{
|
||||
time_t now = time(NULL) + fgGetLong("/sim/time/warp");
|
||||
|
||||
FGTrafficManager *tmgr = (FGTrafficManager *) globals->get_subsystem("Traffic Manager");
|
||||
FGTrafficManager *tmgr = (FGTrafficManager *) globals->get_subsystem("traffic-manager");
|
||||
FGScheduledFlightVecIterator fltBegin, fltEnd;
|
||||
fltBegin = tmgr->getFirstFlight(req);
|
||||
fltEnd = tmgr->getLastFlight(req);
|
||||
|
|
|
@ -22,11 +22,16 @@
|
|||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <map>
|
||||
#include <algorithm>
|
||||
|
||||
#include <plib/fnt.h>
|
||||
#include <plib/pu.h>
|
||||
|
||||
#include "ApplicationProperties.hxx"
|
||||
#include "FGFontCache.hxx"
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// FGFontCache class.
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
@ -68,6 +73,14 @@ const GuiFont guifonts[] = {
|
|||
const GuiFont* guifontsEnd = &guifonts[sizeof(guifonts)/ sizeof(guifonts[0])];
|
||||
}
|
||||
|
||||
FGFontCache::fnt::~fnt()
|
||||
{
|
||||
if (texfont) {
|
||||
delete pufont;
|
||||
delete texfont;
|
||||
}
|
||||
}
|
||||
|
||||
FGFontCache::FGFontCache() :
|
||||
_initialized(false)
|
||||
{
|
||||
|
|
|
@ -14,10 +14,16 @@
|
|||
//
|
||||
#ifndef __FGFONTCACHE_HXX
|
||||
#define __FGFONTCACHE_HXX
|
||||
|
||||
#include <simgear/math/SGMath.hxx>
|
||||
#include <simgear/misc/sg_path.hxx>
|
||||
#include <simgear/props/props.hxx>
|
||||
#include <plib/pu.h>
|
||||
|
||||
|
||||
// forward declare only!
|
||||
class puFont;
|
||||
class fntTexFont;
|
||||
|
||||
/**
|
||||
* A class to keep all fonts available for future use.
|
||||
* This also assures a font isn't resident more than once.
|
||||
|
@ -47,7 +53,7 @@ private:
|
|||
};
|
||||
struct fnt {
|
||||
fnt(puFont *pu = 0) : pufont(pu), texfont(0) {}
|
||||
~fnt() { if (texfont) { delete pufont; delete texfont; } }
|
||||
~fnt();
|
||||
// Font used by plib GUI code
|
||||
puFont *pufont;
|
||||
// TXF font
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <simgear/io/sg_socket.hxx>
|
||||
#include <simgear/misc/strutils.hxx>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class PropertySetter {
|
||||
public:
|
||||
PropertySetter( SGPropertyNode_ptr node ) : _node(node) {}
|
||||
|
@ -123,15 +125,25 @@ FGPanelProtocol::~FGPanelProtocol()
|
|||
|
||||
void FGPanelProtocol::update( double dt )
|
||||
{
|
||||
char buf[8192];
|
||||
char buf[2][8192];
|
||||
|
||||
if( io == NULL )
|
||||
return;
|
||||
|
||||
int length = io->readline( buf, sizeof(buf)-1 );
|
||||
buf[sizeof(buf)-1] = 0;
|
||||
if ( length > 0 ) {
|
||||
vector<string> tokens = simgear::strutils::split( buf, "," );
|
||||
// read all available lines, keep last one
|
||||
int Page = 0;
|
||||
bool HaveData = false;
|
||||
while ( io->readline( buf[Page], sizeof(buf[Page])-1 ) > 0 )
|
||||
{
|
||||
HaveData = true;
|
||||
Page ^= 1;
|
||||
}
|
||||
|
||||
if ( HaveData ) {
|
||||
// process most recent line of data
|
||||
Page ^= 1;
|
||||
buf[Page][sizeof(buf[Page])-1] = 0;
|
||||
vector<string> tokens = simgear::strutils::split( buf[Page], "," );
|
||||
for( vector<string>::size_type i = 0; i < tokens.size(); i++ ) {
|
||||
if( i < propertySetterVector.size() )
|
||||
propertySetterVector[i]->setValue( tokens[i].c_str() );
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
#include "FGTextureLoaderInterface.hxx"
|
||||
|
||||
class FGPanelInstrument;
|
||||
|
||||
using namespace std;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Texture management.
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue