diff --git a/configure.ac b/configure.ac index cd12966c0..07715d1a0 100644 --- a/configure.ac +++ b/configure.ac @@ -773,23 +773,31 @@ if test "x$ac_cv_header_zlib_h" != "xyes"; then fi dnl Check for Subversion library support +# libsvn support defaults to yes save_LIBS=$LIBS save_CPPFLAGS=$CPPFLAGS -LIBS="`apr-1-config --link-ld`" -CPPFLAGS="-I/usr/include/subversion-1 `apr-1-config --includes`" -AC_CHECK_HEADERS([svn_client.h]) -if test "x$ac_cv_header_svn_client_h" != "xyes"; then - echo "TerraSync will shell out for command line subversion" +AC_ARG_WITH(libsvn, [ --without-libsvn Do not use libsvn for terrasync [default=no]], [], [with_libsvn=yes]) +if test "x$with_libsvn" = "xyes"; then + LIBS="`apr-1-config --link-ld`" + CPPFLAGS="-I/usr/include/subversion-1 `apr-1-config --includes --cppflags`" + AC_CHECK_HEADERS([svn_client.h]) + if test "x$ac_cv_header_svn_client_h" = "xyes"; then + echo "TerraSync will use libsvn" + AC_SEARCH_LIBS(svn_client_checkout, svn_client-1) + AC_SEARCH_LIBS(svn_cmdline_init, svn_subr-1) + svn_LIBS=$LIBS + svn_CPPFLAGS=$CPPFLAGS + AC_SUBST(svn_LIBS) + AC_SUBST(svn_CPPFLAGS) + else + echo "Libsvn not found. TerraSync will use command line subversion" + svn_LIBS="" + svn_CPPFLAGS="" + fi +else +echo "Libsvn explicitly disabled. TerraSync will use command line subversion" svn_LIBS="" svn_CPPFLAGS="" -else - echo "TerraSync will use integrated subversion library" - AC_SEARCH_LIBS(svn_client_checkout, svn_client-1) - AC_SEARCH_LIBS(svn_cmdline_init, svn_subr-1) - svn_LIBS=$LIBS - svn_CPPFLAGS=$CPPFLAGS - AC_SUBST(svn_LIBS) - AC_SUBST(svn_CPPFLAGS) fi LIBS=$save_LIBS CPPFLAGS=$save_CPPFLAGS @@ -908,9 +916,9 @@ echo "=================" echo "Prefix: $prefix" if test "x$with_logging" != "x"; then - echo "Debug messages: $with_logging" + echo "Log messages: $with_logging" else - echo "Debug messages: yes" + echo "Log messages: yes" fi echo -n "Automake version: " @@ -921,15 +929,15 @@ if test "x$with_multiplayer" != "xno"; then fi if test "x$with_threads" = "xyes"; then - echo "threads: yes" + echo "Threads: yes" else - echo "threads: no" + echo "Threads: no" fi if test "x$with_eventinput" = "xyes"; then - echo "event input: yes" + echo "Event input: yes" else - echo "event input: no" + echo "Event input: no" fi if test "x$enable_sp_fdms" != "xno"; then @@ -939,8 +947,8 @@ else fi if test "x$enable_atcdcl" = "xyes"; then - echo "Build depricated ATC/AI module: yes" + echo "Build deprecated ATC/AI module: yes" else - echo "Build depricated ATC/AI module: no" + echo "Build deprecated ATC/AI module: no" fi diff --git a/src/Instrumentation/KLN89/kln89.cxx b/src/Instrumentation/KLN89/kln89.cxx index 48d5646ca..aa7b734e4 100644 --- a/src/Instrumentation/KLN89/kln89.cxx +++ b/src/Instrumentation/KLN89/kln89.cxx @@ -7,7 +7,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -206,9 +206,8 @@ KLN89::KLN89(RenderArea2D* instrument) } _activeFP = _flightPlans[0]; - // Hackish - _entJump = -1; - _entRestoreCrsr = false; + _entJump = _clrJump = -1; + _jumpRestoreCrsr = false; _dispMsg = false; @@ -490,8 +489,8 @@ void KLN89::CrsrPressed() { _pages[(unsigned int)_cleanUpPage]->CleanUp(); _cleanUpPage = -1; } - _entRestoreCrsr = false; - _entJump = -1; + _jumpRestoreCrsr = false; + _entJump = _clrJump = -1; ((KLN89Page*)_activePage)->SetEntInvert(false); if(_mode == KLN89_MODE_DISP) { _mode = KLN89_MODE_CRSR; @@ -512,8 +511,8 @@ void KLN89::EntPressed() { } _curPage = _entJump; _activePage = _pages[(unsigned int)_entJump]; - if(_entRestoreCrsr) _mode = KLN89_MODE_CRSR; - _entJump = -1; + if(_jumpRestoreCrsr) _mode = KLN89_MODE_CRSR; + _entJump = _clrJump = -1; } if(_activePage == _dir_page) { _dir_page->EntPressed(); @@ -525,6 +524,12 @@ void KLN89::EntPressed() { } void KLN89::ClrPressed() { + if(_clrJump >= 0) { + _curPage = _clrJump; + _activePage = _pages[(unsigned int)_clrJump]; + if(_jumpRestoreCrsr) _mode = KLN89_MODE_CRSR; + _entJump = _clrJump = -1; + } _activePage->ClrPressed(); } @@ -775,10 +780,10 @@ void KLN89::DrawMap(bool draw_avs) { GPSWaypoint* wp1 = _activeFP->waypoints[i]; SGVec3d p0 = mapProj.ConvertToLocal(SGGeod::fromRad(wp0->lon, wp0->lat)); SGVec3d p1 = mapProj.ConvertToLocal(SGGeod::fromRad(wp1->lon, wp1->lat)); - int mx0 = int(p0.x() / meter_per_pix) + 56; - int my0 = int(p0.y() / meter_per_pix) + (_mapOrientation == 0 ? 19 : 10); - int mx1 = int(p1.x() / meter_per_pix) + 56; - int my1 = int(p1.y() / meter_per_pix) + (_mapOrientation == 0 ? 19 : 10); + int mx0 = int(p0.x() / meter_per_pix + 0.5) + 56; + int my0 = int(p0.y() / meter_per_pix + 0.5) + (_mapOrientation == 0 ? 19 : 10); + int mx1 = int(p1.x() / meter_per_pix + 0.5) + 56; + int my1 = int(p1.y() / meter_per_pix + 0.5) + (_mapOrientation == 0 ? 19 : 10); if(i == 1) { xvec.push_back(mx0); yvec.push_back(my0); diff --git a/src/Instrumentation/KLN89/kln89.hxx b/src/Instrumentation/KLN89/kln89.hxx index 2206fb1b0..c3542f4cb 100644 --- a/src/Instrumentation/KLN89/kln89.hxx +++ b/src/Instrumentation/KLN89/kln89.hxx @@ -7,7 +7,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -213,9 +213,12 @@ private: // And a facility to save the immediately preceeding active page KLN89Page* _lastActivePage; - // Hackish - int _entJump; // The page to jump back to if ent is pressed. -1 indicates no jump - bool _entRestoreCrsr; // Indicates that pressing ENT at this point should restore cursor mode + // Ugly hack. Housekeeping to allow us to temporarily display one page, while remembering which + // other page to "jump" back to. Used when the waypoint pages are used to review waypoint entry + // from the flightplan page. + int _entJump; // The page to jump back to if ENT is pressed. -1 indicates no jump. + int _clrJump; // The page to jump back to if CLR is pressed. -1 indicates no jump. + bool _jumpRestoreCrsr; // Indicates that jump back at this point should restore cursor mode. // Misc pages that aren't in the cyclic list. // Direct To diff --git a/src/Instrumentation/KLN89/kln89_page.cxx b/src/Instrumentation/KLN89/kln89_page.cxx index 43c78550b..a53f3065b 100644 --- a/src/Instrumentation/KLN89/kln89_page.cxx +++ b/src/Instrumentation/KLN89/kln89_page.cxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page.hxx b/src/Instrumentation/KLN89/kln89_page.hxx index 89ea5a7e7..7c2e1802e 100644 --- a/src/Instrumentation/KLN89/kln89_page.hxx +++ b/src/Instrumentation/KLN89/kln89_page.hxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_act.cxx b/src/Instrumentation/KLN89/kln89_page_act.cxx index 516502582..3fccfce61 100644 --- a/src/Instrumentation/KLN89/kln89_page_act.cxx +++ b/src/Instrumentation/KLN89/kln89_page_act.cxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_act.hxx b/src/Instrumentation/KLN89/kln89_page_act.hxx index 016fd3fdd..f9291954d 100644 --- a/src/Instrumentation/KLN89/kln89_page_act.hxx +++ b/src/Instrumentation/KLN89/kln89_page_act.hxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_apt.cxx b/src/Instrumentation/KLN89/kln89_page_apt.cxx index e15b1a45e..67a4c8ddc 100644 --- a/src/Instrumentation/KLN89/kln89_page_apt.cxx +++ b/src/Instrumentation/KLN89/kln89_page_apt.cxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_apt.hxx b/src/Instrumentation/KLN89/kln89_page_apt.hxx index 993fca550..b091193ba 100644 --- a/src/Instrumentation/KLN89/kln89_page_apt.hxx +++ b/src/Instrumentation/KLN89/kln89_page_apt.hxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_dir.cxx b/src/Instrumentation/KLN89/kln89_page_dir.cxx index a8382b06f..9b04ffb9b 100644 --- a/src/Instrumentation/KLN89/kln89_page_dir.cxx +++ b/src/Instrumentation/KLN89/kln89_page_dir.cxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_dir.hxx b/src/Instrumentation/KLN89/kln89_page_dir.hxx index ac5899327..2f23d6276 100644 --- a/src/Instrumentation/KLN89/kln89_page_dir.hxx +++ b/src/Instrumentation/KLN89/kln89_page_dir.hxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_fpl.cxx b/src/Instrumentation/KLN89/kln89_page_fpl.cxx index 86e6178c7..0cb8d13b8 100644 --- a/src/Instrumentation/KLN89/kln89_page_fpl.cxx +++ b/src/Instrumentation/KLN89/kln89_page_fpl.cxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -34,469 +34,509 @@ using namespace std; KLN89FplPage::KLN89FplPage(KLN89* parent) : KLN89Page(parent) { - _nSubPages = 26; - _subPage = 0; - _name = "FPL"; - _fpMode = 0; - _actFpMode = 0; - _wLinePos = 0; - _bEntWp = false; - _bEntExp = false; - _entWp = NULL; - _fplPos = 0; - _resetFplPos0 = true; - _delFP = false; - _delWp = false; - _delAppr = false; - _changeAppr = false; - _fp0SelWpId = ""; + _nSubPages = 26; + _subPage = 0; + _name = "FPL"; + _fpMode = 0; + _actFpMode = 0; + _wLinePos = 0; + _bEntWp = false; + _bEntExp = false; + _entWp = NULL; + _fplPos = 0; + _resetFplPos0 = true; + _delFP = false; + _delWp = false; + _delAppr = false; + _changeAppr = false; + _fp0SelWpId = ""; } KLN89FplPage::~KLN89FplPage() { } void KLN89FplPage::Update(double dt) { - Calc(); - - // NOTE - we need to draw the active leg arrow outside of this block to avoid the _delFP check. - // TODO - we really ought to merge the page 0 and other pages drawing code with a couple of lines of extra logic. - if(_subPage == 0 && !_delFP) { // Note that in the _delFP case, the active flightplan gets a header, and hence the same geometry as the other fps, so we draw it there. - // active FlightPlan - // NOTE THAT FOR THE ACTIVE FLIGHT PLAN, TOP POSITION IS STILL 4 in the underline position scheme, to make - // copy and paste easier!!!! + Calc(); + + // NOTE - we need to draw the active leg arrow outside of this block to avoid the _delFP check. + // TODO - we really ought to merge the page 0 and other pages drawing code with a couple of lines of extra logic. + if(_subPage == 0 && !_delFP) { // Note that in the _delFP case, the active flightplan gets a header, and hence the same geometry as the other fps, so we draw it there. + // active FlightPlan + // NOTE THAT FOR THE ACTIVE FLIGHT PLAN, TOP POSITION IS STILL 4 in the underline position scheme, to make + // copy and paste easier!!!! - // ---------------------------------- Copy the active FlightPlan and insert approach header and fence if required --------------- - // For synatical convienience - //vector waylist = _kln89->_flightPlans[_subPage]->waypoints; - // Copy every waypoint for now. + // ---------------------------------- Copy the active FlightPlan and insert approach header and fence if required --------------- + // For synatical convienience + //vector waylist = _kln89->_flightPlans[_subPage]->waypoints; + // Copy every waypoint for now. // This is inefficient, but allows us to insert dummy waypoints to represent the header and fence - // in our *local copy* of the flightplan, if an approach is loaded. There must be a better way to do this!!!! - vector waylist; - for(unsigned int i=0; i<_kln89->_flightPlans[_subPage]->waypoints.size(); ++i) { - waylist.push_back(*_kln89->_flightPlans[_subPage]->waypoints[i]); - } - _hdrPos = -1; - _fencePos = -1; - if(_kln89->_approachLoaded) { - GPSWaypoint wp; - wp.id = "HHHH"; - wp.type = GPS_WP_VIRT; - wp.appType = GPS_HDR; - for(unsigned int i=0; i numlist; - numlist.clear(); - for(unsigned int i=0; iGetActiveWaypointIndex(); - if(_resetFplPos0) { - if(waylist.size() <= 1) { - _fplPos = 0; - } else if(waylist.size() <= 4) { - _fplPos = 1; - } else { - // Make the active waypoint the second WP displayed - _fplPos = idx; - if(_fplPos != 0) { - _fplPos--; - } - } - //cout << "HeaderPos = " << _hdrPos << ", fencePos = " << _fencePos << ", _fplPos = " << _fplPos << ", active waypoint index = " << _parent->GetActiveWaypointIndex() << '\n'; - if(_hdrPos >= 0 && idx >= _hdrPos) { - _fplPos++; - if(_fencePos >= 0 && (idx + 1) >= _fencePos) { - _fplPos++; - } - } - _resetFplPos0 = false; - } - - // Increment the active waypoint position if required due hdr and fence here not above so it gets called every frame - if(_hdrPos >= 0 && idx >= _hdrPos) { - idx++; - if(_fencePos >= 0 && idx >= _fencePos) { - idx++; - } - } - - // Draw the leg arrow etc - int diff = idx - (int)_fplPos; - int drawPos = -1; - if(idx < 0) { - // No active waypoint - } else if(diff < 0) { - // Off screen to the top - } else if(diff > 2) { - // TODO ! - } else { - drawPos = diff; - } - // Only the head is blinked during waypoint alerting - if(!(_kln89->_waypointAlert && _kln89->_blink)) { - _kln89->DrawSpecialChar(4, 2, 0, 3-drawPos); - } - // If the active waypoint is immediately after an approach header then we need to do an extra-long tail leg - if(_hdrPos >= 0 && idx == _hdrPos + 1) { - if(drawPos > 0 && !_kln89->_dto) _kln89->DrawLongLegTail(3-drawPos); - } else { - if(drawPos > 0 && !_kln89->_dto) _kln89->DrawLegTail(3-drawPos); - } - - //cout << "Top pos is " << _fplPos0 << ' '; - - if(_kln89->_mode == KLN89_MODE_CRSR) { - if(_uLinePos == 3) { - _kln89->Underline(2, 13, 3, 3); - } else if(_uLinePos >= 4) { - if(_bEntWp) { - if(_wLinePos == 0) { - _kln89->Underline(2, 5, 3 - (_uLinePos - 4), 4); - } else if(_wLinePos == 4) { - _kln89->Underline(2, 4, 3 - (_uLinePos - 4), 4); - } else { - _kln89->Underline(2, 4, 3 - (_uLinePos - 4), _wLinePos); - _kln89->Underline(2, 5 + _wLinePos, 3 - (_uLinePos - 4), 4 - _wLinePos); - } - if(!_kln89->_blink) { - //_kln89->DrawText(_entWp->id, 2, 4, 2 - (_uLinePos - 4), false, _wLinePos); - _kln89->DrawEnt(); - } - } else { - _kln89->Underline(2, 4, 3 - (_uLinePos - 4), 5); - } - } - } - // ---------------------------------- - - // Sanity check the top position - remember that we can have an extra blank one at the bottom even if CRSR is off if crsr is switched on then off - if((int)_fplPos > ((int)waylist.size()) - 3) _fplPos = (((int)waylist.size()) - 3 < 0 ? 0 : waylist.size() - 3); - unsigned int last_pos; - if(waylist.empty()) { - last_pos = 0; - } else { - last_pos = ((int)_fplPos == ((int)waylist.size()) - 3 ? waylist.size() : waylist.size() - 1); - } - //cout << "Initialising last_pos, last_pos = " << last_pos << '\n'; - if(waylist.size() < 4) last_pos = waylist.size(); - - // Don't draw the cyclic field header if the top waypoint is the approach header - // Not sure if this also applies to the fence - don't think so but TODO - check! - if(!waylist.empty() && _fplPos < waylist.size()) { - if(waylist[_fplPos].appType != GPS_HDR) { - _kln89->DrawChar('>', 2, 12, 3); - if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == 3 && _kln89->_blink)) { - DrawFpMode(3); - } - } - } - - // - // NOTE: this is the drawing routine for the ACTIVE flightplan, due to the number - // of differences there is a seperate routine for the stored flightplans. - // - // There are 4 rows to display flightplan data on the KLN89. Draw each row. - for(unsigned int i=0; i<4; ++i) { - // Sanity check - we should no longer tickle this. - if((_fplPos+i) > waylist.size()) { - break; - } + // in our *local copy* of the flightplan, if an approach is loaded. There must be a better way to do this!!!! + vector waylist; + for(unsigned int i=0; i<_kln89->_flightPlans[_subPage]->waypoints.size(); ++i) { + waylist.push_back(*_kln89->_flightPlans[_subPage]->waypoints[i]); + } + _hdrPos = -1; + _fencePos = -1; + if(_kln89->_approachLoaded) { + GPSWaypoint wp; + wp.id = "HHHH"; + wp.type = GPS_WP_VIRT; + wp.appType = GPS_HDR; + for(unsigned int i=0; i numlist; + numlist.clear(); + for(unsigned int i=0; iGetActiveWaypointIndex(); + if(_resetFplPos0) { + if(waylist.size() <= 1) { + _fplPos = 0; + } else if(waylist.size() <= 4) { + _fplPos = 1; + } else { + // Make the active waypoint the second WP displayed + _fplPos = idx; + if(_fplPos != 0) { + _fplPos--; + } + } + //cout << "HeaderPos = " << _hdrPos << ", fencePos = " << _fencePos << ", _fplPos = " << _fplPos << ", active waypoint index = " << _parent->GetActiveWaypointIndex() << '\n'; + if(_hdrPos >= 0 && idx >= _hdrPos) { + _fplPos++; + if(_fencePos >= 0 && (idx + 1) >= _fencePos) { + _fplPos++; + } + } + _resetFplPos0 = false; + } + + // Increment the active waypoint position if required due hdr and fence here not above so it gets called every frame + if(_hdrPos >= 0 && idx >= _hdrPos) { + idx++; + if(_fencePos >= 0 && idx >= _fencePos) { + idx++; + } + } + + // Draw the leg arrow etc + int diff = idx - (int)_fplPos; + int drawPos = -1; + if(idx < 0) { + // No active waypoint + } else if(diff < 0) { + // Off screen to the top + } else if(diff > 2) { + // TODO ! + } else { + drawPos = diff; + } + // Only the head is blinked during waypoint alerting + if(!(_kln89->_waypointAlert && _kln89->_blink)) { + _kln89->DrawSpecialChar(4, 2, 0, 3-drawPos); + } + // If the active waypoint is immediately after an approach header then we need to do an extra-long tail leg + if(_hdrPos >= 0 && idx == _hdrPos + 1) { + if(drawPos > 0 && !_kln89->_dto) _kln89->DrawLongLegTail(3-drawPos); + } else { + if(drawPos > 0 && !_kln89->_dto) _kln89->DrawLegTail(3-drawPos); + } + + //cout << "Top pos is " << _fplPos0 << ' '; + + if(_kln89->_mode == KLN89_MODE_CRSR) { + if(_uLinePos == 3) { + _kln89->Underline(2, 13, 3, 3); + } else if(_uLinePos >= 4) { + if(_bEntWp) { + if(_wLinePos == 0) { + _kln89->Underline(2, 5, 3 - (_uLinePos - 4), 4); + } else if(_wLinePos == 4) { + _kln89->Underline(2, 4, 3 - (_uLinePos - 4), 4); + } else { + _kln89->Underline(2, 4, 3 - (_uLinePos - 4), _wLinePos); + _kln89->Underline(2, 5 + _wLinePos, 3 - (_uLinePos - 4), 4 - _wLinePos); + } + if(!_kln89->_blink) { + //_kln89->DrawText(_entWp->id, 2, 4, 2 - (_uLinePos - 4), false, _wLinePos); + _kln89->DrawEnt(); + } + } else { + _kln89->Underline(2, 4, 3 - (_uLinePos - 4), 5); + } + } + } + // ---------------------------------- + + // Sanity check the top position - remember that we can have an extra blank one at the bottom even if CRSR is off if crsr is switched on then off + if((int)_fplPos > ((int)waylist.size()) - 3) _fplPos = (((int)waylist.size()) - 3 < 0 ? 0 : waylist.size() - 3); + unsigned int last_pos; + if(waylist.empty()) { + last_pos = 0; + } else { + last_pos = ((int)_fplPos == ((int)waylist.size()) - 3 ? waylist.size() : waylist.size() - 1); + } + //cout << "Initialising last_pos, last_pos = " << last_pos << '\n'; + if(waylist.size() < 4) last_pos = waylist.size(); + + // Don't draw the cyclic field header if the top waypoint is the approach header + // Not sure if this also applies to the fence - don't think so but TODO - check! + if(!waylist.empty() && _fplPos < waylist.size()) { + if(waylist[_fplPos].appType != GPS_HDR) { + _kln89->DrawChar('>', 2, 12, 3); + if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == 3 && _kln89->_blink)) { + DrawFpMode(3); + } + } + } + + // + // NOTE: this is the drawing routine for the ACTIVE flightplan, due to the number + // of differences there is a seperate routine for the stored flightplans. + // + // There are 4 rows to display flightplan data on the KLN89. Draw each row. + for(unsigned int i=0; i<4; ++i) { + // Sanity check - we should no longer tickle this. + if((_fplPos+i) > waylist.size()) { + break; + } - // Draw the number and (optional) colon for each row. - bool drawNum = true; - int n = (i < 3 ? _fplPos + i + 1 : last_pos + 1); - if(_kln89->_approachLoaded) { - if(n > _hdrPos) --n; - if(n > _fencePos) --n; - } - string s = GPSitoa(n); - if(_fplPos+i < waylist.size()) { - // Don't draw the waypoint number for the header or fence - if((waylist[_fplPos+i].appType == GPS_HDR || waylist[_fplPos+i].appType == GPS_FENCE) - && i != 3) { // By definition, the header and fence lines can't be displayed on the last line hence the unconditional !i==3 is safe. - drawNum = false; - } else { - // Don't draw the colon for waypoints that are part of the published approach - if(waylist[_fplPos+i].appType == GPS_APP_NONE) { - s += ':'; - } - } - } else { - // We must be drawing the next entry field at the end of the list - this has a colon - s += ':'; - } - if(drawNum) { - if(!(_delWp && _uLinePos == i+4)) _kln89->DrawText(s, 2, 4 - (s[s.size()-1] == ':' ? s.size() : s.size()+1), 3 - i); - } - // Done drawing numbers and colons. - - bool drawID = true; - if(_delWp && _uLinePos == i+4) { - if(!_kln89->_blink) { - _kln89->DrawText("Del", 2, 0, 3-i); - _kln89->DrawChar('?', 2, 10, 3-i); - _kln89->Underline(2, 0, 3-i, 11); - _kln89->DrawEnt(); - } - } else if(_kln89->_mode == KLN89_MODE_CRSR && _bEntWp && _uLinePos == i+4) { - if(!_kln89->_blink) { - if(_wLinePos >= _entWp->id.size()) { - _kln89->DrawText(_entWp->id, 2, 4, 3-i); - _kln89->DrawChar(' ', 2, 4+_wLinePos, 3-i, false, true); - } else { - _kln89->DrawText(_entWp->id.substr(0, _wLinePos), 2, 4, 3-i); - _kln89->DrawChar(_entWp->id[_wLinePos], 2, 4+_wLinePos, 3-i, false, true); - _kln89->DrawText(_entWp->id.substr(_wLinePos+1, _entWp->id.size()-_wLinePos-1), 2, 5+_wLinePos, 3-i); - } - } - drawID = false; - } - if(drawID) { - if(i == 3 || _fplPos + i == waylist.size()) { - //cout << "_uLinePos = " << _uLinePos << ", i = " << i << ", waylist.size() = " << waylist.size() << endl; - if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == (i + 4) && _kln89->_blink)) { - // Draw the underline symbol at the end of the flightplan - _kln89->DrawText(last_pos < waylist.size() ? waylist[last_pos].GetAprId() : "_____", 2, 4, 3-i); - } - //cout << "last_pos = " << last_pos << endl; - if(last_pos > 0 && last_pos < waylist.size() && i > 0) { - // Draw the param - if(_actFpMode == 0) { - string s = _params[last_pos - 1]; - _kln89->DrawText(s, 2, 16-s.size(), 3-i); - } else if(_actFpMode == 3) { - string s = _params[last_pos - 1]; - _kln89->DrawText(s, 2, 15-s.size(), 3-i); - _kln89->DrawSpecialChar(0, 2, 15, 3-i); - } - } - break; - } else { - if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == (i + 4) && _kln89->_blink)) { - if(waylist[_fplPos+i].appType == GPS_HDR) { - if(_delAppr) { - _kln89->DrawText("DELETE APPR?", 2, 1, 3-i); - } else if(_changeAppr) { - _kln89->DrawText("CHANGE APPR?", 2, 1, 3-i); - } else { - _kln89->DrawText(_kln89->_approachAbbrev, 2, 1, 3-i); - _kln89->DrawText(_kln89->_approachRwyStr, 2, 7, 3-i); - _kln89->DrawText(_kln89->_approachID, 2, 12, 3-i); - } - } else if(waylist[_fplPos+i].appType == GPS_FENCE) { - _kln89->DrawText("*NO WPT SEQ", 2, 0, 3-i); - } else { - _kln89->DrawText(waylist[_fplPos+i].GetAprId(), 2, 4, 3-i); - } - } - } - if(i > 0) { - // Draw the param - //cout << "i > 0 param draw...\n"; - if(_actFpMode == 0) { - string s = _params[_fplPos + i - 1]; - _kln89->DrawText(s, 2, 16-s.size(), 3-i); - } else if(_actFpMode == 3) { - string s = _params[_fplPos + i - 1]; - _kln89->DrawText(s, 2, 15-s.size(), 3-i); - _kln89->DrawSpecialChar(0, 2, 15, 3-i); - } - } - } - } - } else { // Not active flightplan - //cout << "Top pos is " << _fplPos << ' '; - // For synatical convienience - //int nWp = (_subPage == 0 && !_delFP ? 4 : 3); // number of waypoints to display - vector waylist = _kln89->_flightPlans[_subPage]->waypoints; - if(waylist.empty()) { - if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == 1 && _kln89->_blink)) { - _kln89->DrawText(_delFP ? "Delete FPL?" : "Copy FPL 0?", 2, 0, 3); - } - } else { - if(!(_kln89->_mode == KLN89_MODE_CRSR && (_uLinePos == 1 || _uLinePos == 2) && _kln89->_blink)) { - _kln89->DrawText(_delFP ? "Delete FPL?" : "Use?", 2, 0, 3); - } - if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == 2 && _kln89->_blink)) { - if(!_delFP) _kln89->DrawText("Inverted?", 2, 5, 3); - } - } - - // ---------------------------------- - if(_kln89->_mode == KLN89_MODE_CRSR) { - if(_uLinePos == 1) { - if(!_kln89->_blink) { - _kln89->Underline(2, 0, 3, (waylist.empty() || _delFP ? 11 : 4)); // This underline is blinked - _kln89->DrawEnt(); - } - } else if(_uLinePos == 2) { - // assert(!waylist.empty()); - if(!_kln89->_blink) { - _kln89->Underline(2, 0, 3, 14); // This underline is blinked - _kln89->DrawEnt(); - } - } else if(_uLinePos == 3) { - _kln89->Underline(2, 13, 2, 3); - } else if(_uLinePos >= 4) { - if(_bEntWp) { - if(_wLinePos == 0) { - _kln89->Underline(2, 5, 2 - (_uLinePos - 4), 4); - } else if(_wLinePos == 4) { - _kln89->Underline(2, 4, 2 - (_uLinePos - 4), 4); - } else { - _kln89->Underline(2, 4, 2 - (_uLinePos - 4), _wLinePos); - _kln89->Underline(2, 5 + _wLinePos, 2 - (_uLinePos - 4), 4 - _wLinePos); - } - if(!_kln89->_blink) { - //_kln89->DrawText(_entWp->id, 2, 4, 2 - (_uLinePos - 4), false, _wLinePos); - _kln89->DrawEnt(); - } - } else { - if(!_delWp) _kln89->Underline(2, 4, 2 - (_uLinePos - 4), 5); - } - } - } - // ---------------------------------- - - _kln89->DrawChar('>', 2, 12, 2); - if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == 3 && _kln89->_blink)) DrawFpMode(2); - // Sanity check the top position - remember that we can have an extra blank one at the bottom even if CRSR is off if crsr is switched on then off - if((int)_fplPos > ((int)waylist.size()) - 2) _fplPos = (((int)waylist.size()) - 2 < 0 ? 0 : waylist.size() - 2); - unsigned int last_pos; - if(waylist.empty()) { - last_pos = 0; - } else { - last_pos = ((int)_fplPos == ((int)waylist.size()) - 2 ? waylist.size() : waylist.size() - 1); - } - if(waylist.size() < 3) last_pos = waylist.size(); - for(unsigned int i=0; i<3; ++i) { - string s = GPSitoa(i < 2 ? _fplPos + i + 1 : last_pos + 1); - s += ':'; - if(!(_delWp && _uLinePos == i+4)) _kln89->DrawText(s, 2, 4 - s.size(), 2 - i); - bool drawID = true; - if(_delWp && _uLinePos == i+4) { - if(!_kln89->_blink) { - _kln89->DrawText("Del", 2, 0, 2-i); - _kln89->DrawChar('?', 2, 10, 2-i); - _kln89->Underline(2, 0, 2-i, 11); - _kln89->DrawEnt(); - } - } else if(_kln89->_mode == KLN89_MODE_CRSR && _bEntWp && _uLinePos == i+4) { - if(!_kln89->_blink) { - if(_wLinePos >= _entWp->id.size()) { - _kln89->DrawText(_entWp->id, 2, 4, 2-i); - _kln89->DrawChar(' ', 2, 4+_wLinePos, 2-i, false, true); - } else { - _kln89->DrawText(_entWp->id.substr(0, _wLinePos), 2, 4, 2-i); - _kln89->DrawChar(_entWp->id[_wLinePos], 2, 4+_wLinePos, 2-i, false, true); - _kln89->DrawText(_entWp->id.substr(_wLinePos+1, _entWp->id.size()-_wLinePos-1), 2, 5+_wLinePos, 2-i); - } - } - drawID = false; - } - if(drawID) { - if(i == 2 || _fplPos + i == waylist.size()) { - if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == (i + 4) && _kln89->_blink)) { - _kln89->DrawText(last_pos < waylist.size() ? waylist[last_pos]->id : "_____", 2, 4, 2-i); - } - if(last_pos > 0 && last_pos < waylist.size() && i > 0) { - // Draw the param - if(_fpMode == 0) { - string s = _params[last_pos - 1]; - _kln89->DrawText(s, 2, 16-s.size(), 2-i); - } - } - break; - } else { - if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == (i + 4) && _kln89->_blink)) { - _kln89->DrawText(waylist[_fplPos+i]->id, 2, 4, 2-i); - } - if(i > 0) { - // Draw the param - if(_fpMode == 0) { - string s = _params[_fplPos + i - 1]; - _kln89->DrawText(s, 2, 16-s.size(), 2-i); - } - } - } - } - } - } - - KLN89Page::Update(dt); + // Draw the number and (optional) colon for each row. + bool drawNum = true; + int n = (i < 3 ? _fplPos + i + 1 : last_pos + 1); + if(_kln89->_approachLoaded) { + if(n > _hdrPos) --n; + if(n > _fencePos) --n; + } + string s = GPSitoa(n); + if(_fplPos+i < waylist.size()) { + // Don't draw the waypoint number for the header or fence + if((waylist[_fplPos+i].appType == GPS_HDR || waylist[_fplPos+i].appType == GPS_FENCE) + && i != 3) { // By definition, the header and fence lines can't be displayed on the last line hence the unconditional !i==3 is safe. + drawNum = false; + } else { + // Don't draw the colon for waypoints that are part of the published approach + if(waylist[_fplPos+i].appType == GPS_APP_NONE) { + s += ':'; + } + } + } else { + // We must be drawing the next entry field at the end of the list - this has a colon + s += ':'; + } + if(drawNum) { + if(!(_delWp && _uLinePos == i+4)) _kln89->DrawText(s, 2, 4 - (s[s.size()-1] == ':' ? s.size() : s.size()+1), 3 - i); + } + // Done drawing numbers and colons. + + bool drawID = true; + if(_delWp && _uLinePos == i+4) { + if(!_kln89->_blink) { + _kln89->DrawText("Del", 2, 0, 3-i); + _kln89->DrawChar('?', 2, 10, 3-i); + _kln89->Underline(2, 0, 3-i, 11); + _kln89->DrawEnt(); + } + } else if(_kln89->_mode == KLN89_MODE_CRSR && _bEntWp && _uLinePos == i+4) { + if(!_kln89->_blink) { + if(_wLinePos >= _entWpStr.size()) { + _kln89->DrawText(_entWpStr, 2, 4, 3-i); + _kln89->DrawChar(' ', 2, 4+_wLinePos, 3-i, false, true); + } else { + _kln89->DrawText(_entWpStr.substr(0, _wLinePos), 2, 4, 3-i); + _kln89->DrawChar(_entWpStr[_wLinePos], 2, 4+_wLinePos, 3-i, false, true); + _kln89->DrawText(_entWpStr.substr(_wLinePos+1, _entWpStr.size()-_wLinePos-1), 2, 5+_wLinePos, 3-i); + } + } + // Draw the param - this is "----" during waypoint entry (not for the first row though or we draw through the label!) + if(i != 0) { + _kln89->DrawText("----", 2, 12, 3-i); + } + + drawID = false; + } + if(drawID) { + if(i == 3 || _fplPos + i == waylist.size()) { + //cout << "_uLinePos = " << _uLinePos << ", i = " << i << ", waylist.size() = " << waylist.size() << endl; + if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == (i + 4) && _kln89->_blink)) { + // Draw the underline symbol at the end of the flightplan + _kln89->DrawText(last_pos < waylist.size() ? waylist[last_pos].GetAprId() : "_____", 2, 4, 3-i); + } + //cout << "last_pos = " << last_pos << endl; + if(last_pos > 0 && last_pos < waylist.size() && i > 0) { + // Draw the param + if(_actFpMode == 0) { // DIS + if(_kln89->_mode == KLN89_MODE_CRSR && _bEntWp && _uLinePos < i+4) { + // This means that we are beyond the waypoint being entered. In DIS mode + // this means that we dash out the field. + _kln89->DrawText("----", 2, 12, 3-i); + } else { + string s = _params[last_pos - 1]; + _kln89->DrawText(s, 2, 16-s.size(), 3-i); + } + } else if(_actFpMode == 3) { // DTK + string s = _params[last_pos - 1]; + _kln89->DrawText(s, 2, 15-s.size(), 3-i); + _kln89->DrawSpecialChar(0, 2, 15, 3-i); + } + } + break; + } else { + if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == (i + 4) && _kln89->_blink)) { + if(waylist[_fplPos+i].appType == GPS_HDR) { + if(_delAppr) { + _kln89->DrawText("DELETE APPR?", 2, 1, 3-i); + } else if(_changeAppr) { + _kln89->DrawText("CHANGE APPR?", 2, 1, 3-i); + } else { + _kln89->DrawText(_kln89->_approachAbbrev, 2, 1, 3-i); + _kln89->DrawText(_kln89->_approachRwyStr, 2, 7, 3-i); + _kln89->DrawText(_kln89->_approachID, 2, 12, 3-i); + } + } else if(waylist[_fplPos+i].appType == GPS_FENCE) { + _kln89->DrawText("*NO WPT SEQ", 2, 0, 3-i); + } else { + _kln89->DrawText(waylist[_fplPos+i].GetAprId(), 2, 4, 3-i); + } + } + } + if(i > 0) { + // Draw the param + //cout << "i > 0 param draw...\n"; + if(_actFpMode == 0) { // DIS + if(_kln89->_mode == KLN89_MODE_CRSR && _bEntWp && _uLinePos < i+4) { + // This means that we are beyond the waypoint being entered. In DIS mode + // this means that we dash out the field. + _kln89->DrawText("----", 2, 12, 3-i); + } else { + string s = _params[_fplPos + i - 1]; + _kln89->DrawText(s, 2, 16-s.size(), 3-i); + } + } else if(_actFpMode == 3) { // DTK + // TODO - figure out properly what to do in DTK mode when beyond a waypoint being entered. + // I *think* it is OK to do the same as here, but maybe not for the waypoint immediately + // beyond the one being entered - need to check. + string s = _params[_fplPos + i - 1]; + _kln89->DrawText(s, 2, 15-s.size(), 3-i); + _kln89->DrawSpecialChar(0, 2, 15, 3-i); + } + } + } + } + } else { // Not active flightplan + //cout << "Top pos is " << _fplPos << ' '; + // For synatical convienience + //int nWp = (_subPage == 0 && !_delFP ? 4 : 3); // number of waypoints to display + vector waylist = _kln89->_flightPlans[_subPage]->waypoints; + if(waylist.empty()) { + if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == 1 && _kln89->_blink)) { + _kln89->DrawText(_delFP ? "Delete FPL?" : "Copy FPL 0?", 2, 0, 3); + } + } else { + if(!(_kln89->_mode == KLN89_MODE_CRSR && (_uLinePos == 1 || _uLinePos == 2) && _kln89->_blink)) { + _kln89->DrawText(_delFP ? "Delete FPL?" : "Use?", 2, 0, 3); + } + if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == 2 && _kln89->_blink)) { + if(!_delFP) _kln89->DrawText("Inverted?", 2, 5, 3); + } + } + + // ---------------------------------- + if(_kln89->_mode == KLN89_MODE_CRSR) { + if(_uLinePos == 1) { + if(!_kln89->_blink) { + _kln89->Underline(2, 0, 3, (waylist.empty() || _delFP ? 11 : 4)); // This underline is blinked + _kln89->DrawEnt(); + } + } else if(_uLinePos == 2) { + // assert(!waylist.empty()); + if(!_kln89->_blink) { + _kln89->Underline(2, 0, 3, 14); // This underline is blinked + _kln89->DrawEnt(); + } + } else if(_uLinePos == 3) { + _kln89->Underline(2, 13, 2, 3); + } else if(_uLinePos >= 4) { + if(_bEntWp) { + if(_wLinePos == 0) { + _kln89->Underline(2, 5, 2 - (_uLinePos - 4), 4); + } else if(_wLinePos == 4) { + _kln89->Underline(2, 4, 2 - (_uLinePos - 4), 4); + } else { + _kln89->Underline(2, 4, 2 - (_uLinePos - 4), _wLinePos); + _kln89->Underline(2, 5 + _wLinePos, 2 - (_uLinePos - 4), 4 - _wLinePos); + } + if(!_kln89->_blink) { + //_kln89->DrawText(_entWp->id, 2, 4, 2 - (_uLinePos - 4), false, _wLinePos); + _kln89->DrawEnt(); + } + } else { + if(!_delWp) _kln89->Underline(2, 4, 2 - (_uLinePos - 4), 5); + } + } + } + // ---------------------------------- + + _kln89->DrawChar('>', 2, 12, 2); + if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == 3 && _kln89->_blink)) DrawFpMode(2); + // Sanity check the top position - remember that we can have an extra blank one at the bottom even if CRSR is off if crsr is switched on then off + if((int)_fplPos > ((int)waylist.size()) - 2) _fplPos = (((int)waylist.size()) - 2 < 0 ? 0 : waylist.size() - 2); + unsigned int last_pos; + if(waylist.empty()) { + last_pos = 0; + } else { + last_pos = ((int)_fplPos == ((int)waylist.size()) - 2 ? waylist.size() : waylist.size() - 1); + } + if(waylist.size() < 3) last_pos = waylist.size(); + for(unsigned int i=0; i<3; ++i) { + string s = GPSitoa(i < 2 ? _fplPos + i + 1 : last_pos + 1); + s += ':'; + if(!(_delWp && _uLinePos == i+4)) _kln89->DrawText(s, 2, 4 - s.size(), 2 - i); + bool drawID = true; + if(_delWp && _uLinePos == i+4) { + if(!_kln89->_blink) { + _kln89->DrawText("Del", 2, 0, 2-i); + _kln89->DrawChar('?', 2, 10, 2-i); + _kln89->Underline(2, 0, 2-i, 11); + _kln89->DrawEnt(); + } + } else if(_kln89->_mode == KLN89_MODE_CRSR && _bEntWp && _uLinePos == i+4) { + // This means that we are drawing a waypoint currently being entered + if(!_kln89->_blink) { + if(_wLinePos >= _entWpStr.size()) { + _kln89->DrawText(_entWpStr, 2, 4, 2-i); + _kln89->DrawChar(' ', 2, 4+_wLinePos, 2-i, false, true); + } else { + _kln89->DrawText(_entWpStr.substr(0, _wLinePos), 2, 4, 2-i); + _kln89->DrawChar(_entWpStr[_wLinePos], 2, 4+_wLinePos, 2-i, false, true); + _kln89->DrawText(_entWpStr.substr(_wLinePos+1, _entWpStr.size()-_wLinePos-1), 2, 5+_wLinePos, 2-i); + } + } + // Draw the param - this is "----" during waypoint entry (not for the first row though or we draw through the label!) + if(i != 0) { + _kln89->DrawText("----", 2, 12, 2-i); + } + + drawID = false; + } + if(drawID) { + if(i == 2 || _fplPos + i == waylist.size()) { + if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == (i + 4) && _kln89->_blink)) { + _kln89->DrawText(last_pos < waylist.size() ? waylist[last_pos]->id : "_____", 2, 4, 2-i); + } + if(last_pos > 0 && last_pos < waylist.size() && i > 0) { + // Draw the param + // TODO - we should also handle DTK mode params here. + if(_fpMode == 0) { // DIS + if(_kln89->_mode == KLN89_MODE_CRSR && _bEntWp && _uLinePos < i+4) { + // This means that we are beyond the waypoint being entered. In DIS mode + // this means that we dash out the field. + _kln89->DrawText("----", 2, 12, 2-i); + } else { + string s = _params[last_pos - 1]; + _kln89->DrawText(s, 2, 16-s.size(), 2-i); + } + } + } + break; + } else { + if(!(_kln89->_mode == KLN89_MODE_CRSR && _uLinePos == (i + 4) && _kln89->_blink)) { + _kln89->DrawText(waylist[_fplPos+i]->id, 2, 4, 2-i); + } + if(i > 0) { + // Draw the param + // TODO - we should also handle DTK mode params here. + if(_fpMode == 0) { // DIS + if(_kln89->_mode == KLN89_MODE_CRSR && _bEntWp && _uLinePos < i+4) { + // This means that we are beyond the waypoint being entered. In DIS mode + // this means that we dash out the field. + _kln89->DrawText("----", 2, 12, 2-i); + } else { + string s = _params[_fplPos + i - 1]; + _kln89->DrawText(s, 2, 16-s.size(), 2-i); + } + } + } + } + } + } + } + + KLN89Page::Update(dt); } void KLN89FplPage::DrawFpMode(int ypos) { - string s = "Dis"; - if(0 == _subPage) { - if(_actFpMode == 1) { - s = "ETE"; - } else if(_actFpMode == 2) { - s = "UTC"; // TODO - alter depending on chosen timezone - } else if(_actFpMode == 3) { - s = (_kln89->_obsMode ? "OBS" : "Dtk"); - } - } else { - if(_fpMode == 1) { - s = "Dtk"; - } - } - _kln89->DrawText(s, 2, 13, ypos); + string s = "Dis"; + if(0 == _subPage) { + if(_actFpMode == 1) { + s = "ETE"; + } else if(_actFpMode == 2) { + s = "UTC"; // TODO - alter depending on chosen timezone + } else if(_actFpMode == 3) { + s = (_kln89->_obsMode ? "OBS" : "Dtk"); + } + } else { + if(_fpMode == 1) { + s = "Dtk"; + } + } + _kln89->DrawText(s, 2, 13, ypos); } // Calculate the displayable parameters for the currently displayed flightplan. @@ -505,545 +545,586 @@ void KLN89FplPage::DrawFpMode(int ypos) { // which is a really really really ugly and potentially bug-prone and hard to maintain way of doing this. // TODO: When the unit is fully working rip out _params and replace with a better solution. void KLN89FplPage::Calc() { - _params.clear(); - GPSFlightPlan* fp = _kln89->_flightPlans[_subPage]; - vector wv = fp->waypoints; - // Some parameters are calculated differently for the active and the stored flightplans, so - // do the two cases seperately. - if(0 == _subPage) { - // Active FP - parameters are only displayed for the active waypoint onwards for the active plan, - // and distance is cumulative from the user position. - if(0 == _actFpMode) { - // Dis - double cum_tot = 0.0; - if(wv.size() > 0) { - cum_tot += _kln89->GetGreatCircleDistance(_kln89->_gpsLat, _kln89->_gpsLon, wv[0]->lat, wv[0]->lon); - } - for(unsigned int i=1; iGetGreatCircleDistance(wv[i-1]->lat, wv[i-1]->lon, wv[i]->lat, wv[i]->lon); // TODO - add units switch! - int n = (int)(cum_tot + 0.5); - _params.push_back(GPSitoa(n)); - } - } else if(1 == _actFpMode) { - // TODO - } else if(2 == _actFpMode) { - // TODO - } else { - // Dtk - for(unsigned int i=1; iGetMagHeadingFromTo(wv[i-1]->lat, wv[i-1]->lon, wv[i]->lat, wv[i]->lon); - int n = (int)(dtk + 0.5); - _params.push_back(GPSitoa(n)); - } - - } - } else { - // other FPs - if(0 == _fpMode) { - double cum_tot = 0.0; - for(unsigned int i=1; iGetGreatCircleDistance(wv[i-1]->lat, wv[i-1]->lon, wv[i]->lat, wv[i]->lon); // TODO - add units switch! - int n = (int)(cum_tot + 0.5); - _params.push_back(GPSitoa(n)); - } - } else { - // Dtk - for(unsigned int i=1; iGetMagHeadingFromTo(wv[i-1]->lat, wv[i-1]->lon, wv[i]->lat, wv[i]->lon); - int n = (int)(dtk + 0.5); - _params.push_back(GPSitoa(n)); - } - } - } + _params.clear(); + GPSFlightPlan* fp = _kln89->_flightPlans[_subPage]; + vector wv = fp->waypoints; + // Some parameters are calculated differently for the active and the stored flightplans, so + // do the two cases seperately. + if(0 == _subPage) { + // Active FP - parameters are only displayed for the active waypoint onwards for the active plan, + // and distance is cumulative from the user position. + if(0 == _actFpMode) { + // Dis + double cum_tot = 0.0; + if(wv.size() > 0) { + cum_tot += _kln89->GetGreatCircleDistance(_kln89->_gpsLat, _kln89->_gpsLon, wv[0]->lat, wv[0]->lon); + } + for(unsigned int i=1; iGetGreatCircleDistance(wv[i-1]->lat, wv[i-1]->lon, wv[i]->lat, wv[i]->lon); // TODO - add units switch! + int n = (int)(cum_tot + 0.5); + _params.push_back(GPSitoa(n)); + } + } else if(1 == _actFpMode) { + // TODO + } else if(2 == _actFpMode) { + // TODO + } else { + // Dtk + for(unsigned int i=1; iGetMagHeadingFromTo(wv[i-1]->lat, wv[i-1]->lon, wv[i]->lat, wv[i]->lon); + int n = (int)(dtk + 0.5); + _params.push_back(GPSitoa(n)); + } + + } + } else { + // other FPs + if(0 == _fpMode) { + double cum_tot = 0.0; + for(unsigned int i=1; iGetGreatCircleDistance(wv[i-1]->lat, wv[i-1]->lon, wv[i]->lat, wv[i]->lon); // TODO - add units switch! + int n = (int)(cum_tot + 0.5); + _params.push_back(GPSitoa(n)); + } + } else { + // Dtk + for(unsigned int i=1; iGetMagHeadingFromTo(wv[i-1]->lat, wv[i-1]->lon, wv[i]->lat, wv[i]->lon); + int n = (int)(dtk + 0.5); + _params.push_back(GPSitoa(n)); + } + } + } } void KLN89FplPage::CrsrPressed() { - if(_delFP || _delAppr) { - _delFP = _delAppr = false; - _kln89->_mode = KLN89_MODE_DISP; - return; - } + if(_delFP || _delAppr) { + _delFP = _delAppr = false; + _kln89->_mode = KLN89_MODE_DISP; + return; + } - _wLinePos = 0; - if(_kln89->_mode == KLN89_MODE_DISP) { - _fp0SelWpId.clear(); - if(_bEntWp) { - for(unsigned int i = 0; i < _kln89->_flightPlans[_subPage]->waypoints.size(); ++i) { - if(_kln89->_flightPlans[_subPage]->waypoints[i] == _entWp) { - _kln89->_flightPlans[_subPage]->waypoints.erase(_kln89->_flightPlans[_subPage]->waypoints.begin() + i); - } - } - delete _entWp; - _entWp = NULL; - _bEntWp = false; - _entWpStr.clear(); - } - } else { - if(_kln89->_obsMode) { - _uLinePos = 0; - } else { - if(_kln89->_flightPlans[_subPage]->IsEmpty()) { - _uLinePos = 4; - } else { - _uLinePos = (_subPage == 0 ? 3 : 1); - } - } - } + _wLinePos = 0; + if(_kln89->_mode == KLN89_MODE_DISP) { + _fp0SelWpId.clear(); + if(_bEntWp) { + for(unsigned int i = 0; i < _kln89->_flightPlans[_subPage]->waypoints.size(); ++i) { + if(_kln89->_flightPlans[_subPage]->waypoints[i] == _entWp) { + _kln89->_flightPlans[_subPage]->waypoints.erase(_kln89->_flightPlans[_subPage]->waypoints.begin() + i); + } + } + delete _entWp; + _entWp = NULL; + _bEntWp = false; + _entWpStr.clear(); + } + } else { + if(_kln89->_obsMode) { + _uLinePos = 0; + } else { + if(_kln89->_flightPlans[_subPage]->IsEmpty()) { + _uLinePos = 4; + } else { + _uLinePos = (_subPage == 0 ? 3 : 1); + } + } + } } void KLN89FplPage::ClrPressed() { - if(_delFP || _delAppr) { - _delFP = _delAppr = false; - _kln89->_mode = KLN89_MODE_DISP; - } else { - if(KLN89_MODE_CRSR == _kln89->_mode) { - // TODO - see if we need to delete a waypoint - if(_uLinePos >= 4) { - if(_delWp) { - _kln89->_mode = KLN89_MODE_DISP; - _delWp = false; - } else { - // First check that we're not trying to delete an approach waypoint. Note that we can delete the approach by deleting the header though. - // Check for approach waypoints or header/fences in flightplan 0 - int n = _fplPos + _uLinePos - 4; - bool hdrPos = false; - bool fencePos = false; - //cout << "_fplPos = " << _fplPos << ", _uLinePos = " << _uLinePos << ", n = " << n << ", _hdrPos = " << _hdrPos << ", _fencePos = " << _fencePos << '\n'; - if(n == _hdrPos) { - //cout << "HEADER POS\n"; - hdrPos = true; - } - if(n == _fencePos) { - //cout << "FENCE POS\n"; - fencePos = true; - } - if(_hdrPos >= 0 && n > _hdrPos) --n; - if(_fencePos >= 0 && n >= _fencePos) --n; // This one needs to be >= since n is already decremented by 1 in the line above! - //cout << "New n = " << n << '\n'; - if(hdrPos) { - //cout << "HDRP\n"; - _delAppr = true; - } else if(fencePos) { - //cout << "FENP\n"; - // no-op - } else if(n >= static_cast(_kln89->_flightPlans[_subPage]->waypoints.size())) { - // no-op - off the end of the list on the entry field - } else if(_kln89->_flightPlans[_subPage]->waypoints[n]->appType == GPS_APP_NONE) { - //cout << "DELFP\n"; - _kln89->_mode = KLN89_MODE_CRSR; - _delWp = true; - } else { - ShowScratchpadMessage("Invald", " Del "); - } - } - } else if(_uLinePos == 3) { - if(_subPage == 0) { - _actFpMode++; - if(_actFpMode > 3) _actFpMode = 0; - } else { - _fpMode++; - if(_fpMode > 1) _fpMode = 0; - } - } - } else { - _delFP = true; - _uLinePos = 1; - _kln89->_mode = KLN89_MODE_CRSR; - } - } + if(_delFP || _delAppr) { + _delFP = _delAppr = false; + _kln89->_mode = KLN89_MODE_DISP; + } else { + if(KLN89_MODE_CRSR == _kln89->_mode) { + // TODO - see if we need to delete a waypoint + if(_uLinePos >= 4) { + if(_delWp) { + // If we are already displaying a clear waypoint dialog in response to the CLR button, + // then a further press of the CLR button cancels the dialog. + _kln89->_mode = KLN89_MODE_DISP; + _delWp = false; + } else if(_bEntWp) { + // If we are currently entering a waypoint, then CLR deletes it unconditionally + // without a confirmation dialog and cancels waypoint entry. + int pos = _uLinePos - 4 + _fplPos; + // Sanity check - the calculated wp position should never be off the end of the waypoint list. + if(pos > static_cast(_kln89->_flightPlans[_subPage]->waypoints.size()) - 1) { + SG_LOG(SG_GENERAL, SG_ALERT, "ERROR - _uLinePos too big in KLN89FplPage::ClrPressed!\n"); + return; + } + _kln89->_flightPlans[_subPage]->waypoints.erase(_kln89->_flightPlans[_subPage]->waypoints.begin() + pos); + _bEntWp = false; + _entWp = NULL; + _entWpStr.clear(); + _wLinePos = 0; + // We can also get here from the waypoint review page, so clear _bEntExp as well + _bEntExp = false; + // Do we need to re-calc _fplPos here? + } else { + // First check that we're not trying to delete an approach waypoint. Note that we can delete the approach by deleting the header though. + // Check for approach waypoints or header/fences in flightplan 0 + int n = _fplPos + _uLinePos - 4; + bool hdrPos = false; + bool fencePos = false; + //cout << "_fplPos = " << _fplPos << ", _uLinePos = " << _uLinePos << ", n = " << n << ", _hdrPos = " << _hdrPos << ", _fencePos = " << _fencePos << '\n'; + if(n == _hdrPos) { + //cout << "HEADER POS\n"; + hdrPos = true; + } + if(n == _fencePos) { + //cout << "FENCE POS\n"; + fencePos = true; + } + if(_hdrPos >= 0 && n > _hdrPos) --n; + if(_fencePos >= 0 && n >= _fencePos) --n; // This one needs to be >= since n is already decremented by 1 in the line above! + //cout << "New n = " << n << '\n'; + if(hdrPos) { + //cout << "HDRP\n"; + _delAppr = true; + } else if(fencePos) { + //cout << "FENP\n"; + // no-op + } else if(n >= static_cast(_kln89->_flightPlans[_subPage]->waypoints.size())) { + // no-op - off the end of the list on the entry field + } else if(_kln89->_flightPlans[_subPage]->waypoints[n]->appType == GPS_APP_NONE) { + //cout << "DELFP\n"; + _kln89->_mode = KLN89_MODE_CRSR; + _delWp = true; + } else { + ShowScratchpadMessage("Invald", " Del "); + } + } + } else if(_uLinePos == 3) { + if(_subPage == 0) { + _actFpMode++; + if(_actFpMode > 3) _actFpMode = 0; + } else { + _fpMode++; + if(_fpMode > 1) _fpMode = 0; + } + } + } else { + _delFP = true; + _uLinePos = 1; + _kln89->_mode = KLN89_MODE_CRSR; + } + } } void KLN89FplPage::CleanUp() { - // TODO - possibly need to clean up _delWp here as well, since it goes off if dto and then ent are pressed. - - _bEntWp = false; - for(unsigned int i = 0; i < _kln89->_flightPlans[_subPage]->waypoints.size(); ++i) { - if(_kln89->_flightPlans[_subPage]->waypoints[i] == _entWp) { - _kln89->_flightPlans[_subPage]->waypoints.erase(_kln89->_flightPlans[_subPage]->waypoints.begin() + i); - } - } - delete _entWp; - _entWp = NULL; - _entWpStr.clear(); - KLN89Page::CleanUp(); + // TODO - possibly need to clean up _delWp here as well, since it goes off if dto and then ent are pressed. + + _bEntWp = false; + for(unsigned int i = 0; i < _kln89->_flightPlans[_subPage]->waypoints.size(); ++i) { + if(_kln89->_flightPlans[_subPage]->waypoints[i] == _entWp) { + _kln89->_flightPlans[_subPage]->waypoints.erase(_kln89->_flightPlans[_subPage]->waypoints.begin() + i); + } + } + delete _entWp; + _entWp = NULL; + _entWpStr.clear(); + KLN89Page::CleanUp(); } void KLN89FplPage::LooseFocus() { - _fplPos = 0; - _resetFplPos0 = true; - _wLinePos = 0; - _uLinePos = 0; - _fp0SelWpId.clear(); - _scratchpadMsg = false; + _fplPos = 0; + _resetFplPos0 = true; + _wLinePos = 0; + _uLinePos = 0; + _fp0SelWpId.clear(); + _scratchpadMsg = false; } void KLN89FplPage::EntPressed() { - if(_delFP) { - _kln89->ClearFlightPlan(_subPage); - CrsrPressed(); - } else if(_delWp) { - int pos = _uLinePos - 4 + _fplPos; - // Sanity check - the calculated wp position should never be off the end of the waypoint list. - if(pos > static_cast(_kln89->_flightPlans[_subPage]->waypoints.size()) - 1) { - cout << "ERROR - _uLinePos too big in KLN89FplPage::EntPressed!\n"; - return; - } - _kln89->_flightPlans[_subPage]->waypoints.erase(_kln89->_flightPlans[_subPage]->waypoints.begin() + pos); - _delWp = false; - // Do we need to re-calc _fplPos here? - } else if(_bEntExp) { - _bEntWp = false; - _bEntExp = false; - _entWp = NULL; // DON'T delete it! - it's been pushed onto the waypoint list at this point. - _entWpStr.clear(); - _kln89->_cleanUpPage = -1; - _wLinePos = 0; - // TODO - in actual fact the previously underlined waypoint stays in the same position and underlined - // in some or possibly all circumstances - need to check this out and match it, but not too important - // for now. - } else if(_bEntWp) { - if(_entWp != NULL) { - // TODO - should be able to get rid of this switch I think and use the enum values. - switch(_entWp->type) { - case GPS_WP_APT: - _kln89->_activePage = _kln89->_pages[0]; - _kln89->_curPage = 0; - ((KLN89Page*)_kln89->_pages[0])->SetEntInvert(true); - break; - case GPS_WP_VOR: - _kln89->_activePage = _kln89->_pages[1]; - _kln89->_curPage = 1; - ((KLN89Page*)_kln89->_pages[1])->SetEntInvert(true); - break; - case GPS_WP_NDB: - _kln89->_activePage = _kln89->_pages[2]; - _kln89->_curPage = 2; - ((KLN89Page*)_kln89->_pages[2])->SetEntInvert(true); - break; - case GPS_WP_INT: - _kln89->_activePage = _kln89->_pages[3]; - _kln89->_curPage = 3; - ((KLN89Page*)_kln89->_pages[3])->SetEntInvert(true); - break; - case GPS_WP_USR: - _kln89->_activePage = _kln89->_pages[4]; - _kln89->_curPage = 4; - ((KLN89Page*)_kln89->_pages[4])->SetEntInvert(true); - break; - default: - cout << "Error - unknown waypoint type found in KLN89::FplPage::EntPressed()\n"; - } - _kln89->_activePage->SetId(_entWp->id); - _kln89->_entJump = 7; - _kln89->_cleanUpPage = 7; - _kln89->_entRestoreCrsr = true; - _kln89->_mode = KLN89_MODE_DISP; - } - _bEntExp = true; - } else if(_uLinePos == 1) { - if(_kln89->_flightPlans[_subPage]->IsEmpty()) { - // Copy fpl 0 - for(unsigned int i=0; i<_kln89->_flightPlans[0]->waypoints.size(); ++i) { - GPSWaypoint* wp = new GPSWaypoint; - *wp = *(_kln89->_flightPlans[0]->waypoints[i]); - _kln89->_flightPlans[_subPage]->waypoints.push_back(wp); - } - } else { - // Use - _kln89->ClearFlightPlan(0); - for(unsigned int i=0; i<_kln89->_flightPlans[_subPage]->waypoints.size(); ++i) { - GPSWaypoint* wp = new GPSWaypoint; - *wp = *(_kln89->_flightPlans[_subPage]->waypoints[i]); - _kln89->_flightPlans[0]->waypoints.push_back(wp); - } - _kln89->OrientateToActiveFlightPlan(); - _subPage = 0; - } - _kln89->CrsrPressed(); - } else if(_uLinePos == 2) { - if(_kln89->_flightPlans[_subPage]->IsEmpty()) { - // ERROR !!! - } else { - // Use Invert - _kln89->ClearFlightPlan(0); - for(unsigned int i=0; i<_kln89->_flightPlans[_subPage]->waypoints.size(); ++i) { - GPSWaypoint* wp = new GPSWaypoint; - *wp = *(_kln89->_flightPlans[_subPage]->waypoints[i]); - // FIXME - very inefficient - use a reverse iterator on the source array and push_back instead!!!!!!!! - _kln89->_flightPlans[0]->waypoints.insert(_kln89->_flightPlans[0]->waypoints.begin(), wp); - } - _kln89->OrientateToActiveFlightPlan(); - } - _kln89->CrsrPressed(); - _subPage = 0; - } + if(_delFP) { + _kln89->ClearFlightPlan(_subPage); + CrsrPressed(); + } else if(_delWp) { + int pos = _uLinePos - 4 + _fplPos; + // Sanity check - the calculated wp position should never be off the end of the waypoint list. + if(pos > static_cast(_kln89->_flightPlans[_subPage]->waypoints.size()) - 1) { + SG_LOG(SG_GENERAL, SG_ALERT, "ERROR - _uLinePos too big in KLN89FplPage::EntPressed!\n"); + return; + } + _kln89->_flightPlans[_subPage]->waypoints.erase(_kln89->_flightPlans[_subPage]->waypoints.begin() + pos); + _delWp = false; + // Do we need to re-calc _fplPos here? + } else if(_bEntExp) { + // We get here if we have just approved a waypoint review for addition with the ENT button + _bEntWp = false; + _bEntExp = false; + _entWp = NULL; // DON'T delete it! - it's been pushed onto the waypoint list at this point. + _entWpStr.clear(); + _kln89->_cleanUpPage = -1; + _wLinePos = 0; + // The cursor should be moved either to the next waypoint in the list, or to the empty position at + // the end of the list if the waypoint just entered was the last one in the list. Unfortunately + // that means that we have to deal with the horrible _uLinePos / _fplPos interaction yet again :-( + if(_uLinePos == 4) { + // We can't handle this case by calling K1R1, since we want to jump the field type + _uLinePos = 5; + } else { + // Just call Knob1Right1 and let that handle the horrible logic :-) + Knob1Right1(); + } + } else if(_bEntWp) { + if(_entWp != NULL) { + // TODO - should be able to get rid of this switch I think and use the enum values. + switch(_entWp->type) { + case GPS_WP_APT: + _kln89->_activePage = _kln89->_pages[0]; + _kln89->_curPage = 0; + ((KLN89Page*)_kln89->_pages[0])->SetEntInvert(true); + break; + case GPS_WP_VOR: + _kln89->_activePage = _kln89->_pages[1]; + _kln89->_curPage = 1; + ((KLN89Page*)_kln89->_pages[1])->SetEntInvert(true); + break; + case GPS_WP_NDB: + _kln89->_activePage = _kln89->_pages[2]; + _kln89->_curPage = 2; + ((KLN89Page*)_kln89->_pages[2])->SetEntInvert(true); + break; + case GPS_WP_INT: + _kln89->_activePage = _kln89->_pages[3]; + _kln89->_curPage = 3; + ((KLN89Page*)_kln89->_pages[3])->SetEntInvert(true); + break; + case GPS_WP_USR: + _kln89->_activePage = _kln89->_pages[4]; + _kln89->_curPage = 4; + ((KLN89Page*)_kln89->_pages[4])->SetEntInvert(true); + break; + default: + SG_LOG(SG_GENERAL, SG_ALERT, "Error - unknown waypoint type found in KLN89::FplPage::EntPressed()\n"); + } + _kln89->_activePage->SetId(_entWp->id); + _kln89->_entJump = _kln89->_clrJump = 7; + _kln89->_cleanUpPage = 7; + _kln89->_jumpRestoreCrsr = true; + _kln89->_mode = KLN89_MODE_DISP; + } + _bEntExp = true; + } else if(_uLinePos == 1) { + if(_kln89->_flightPlans[_subPage]->IsEmpty()) { + // Copy fpl 0 + for(unsigned int i=0; i<_kln89->_flightPlans[0]->waypoints.size(); ++i) { + GPSWaypoint* wp = new GPSWaypoint; + *wp = *(_kln89->_flightPlans[0]->waypoints[i]); + _kln89->_flightPlans[_subPage]->waypoints.push_back(wp); + } + } else { + // Use + _kln89->ClearFlightPlan(0); + for(unsigned int i=0; i<_kln89->_flightPlans[_subPage]->waypoints.size(); ++i) { + GPSWaypoint* wp = new GPSWaypoint; + *wp = *(_kln89->_flightPlans[_subPage]->waypoints[i]); + _kln89->_flightPlans[0]->waypoints.push_back(wp); + } + _kln89->OrientateToActiveFlightPlan(); + _subPage = 0; + } + _kln89->CrsrPressed(); + } else if(_uLinePos == 2) { + if(_kln89->_flightPlans[_subPage]->IsEmpty()) { + // ERROR !!! + } else { + // Use Invert + _kln89->ClearFlightPlan(0); + for(unsigned int i=0; i<_kln89->_flightPlans[_subPage]->waypoints.size(); ++i) { + GPSWaypoint* wp = new GPSWaypoint; + *wp = *(_kln89->_flightPlans[_subPage]->waypoints[i]); + // FIXME - very inefficient - use a reverse iterator on the source array and push_back instead!!!!!!!! + _kln89->_flightPlans[0]->waypoints.insert(_kln89->_flightPlans[0]->waypoints.begin(), wp); + } + _kln89->OrientateToActiveFlightPlan(); + } + _kln89->CrsrPressed(); + _subPage = 0; + } } void KLN89FplPage::Knob1Left1() { - if(_delFP) { - _delFP = false; - return; - } - _delWp = false; - _changeAppr = false; + if(_delFP) { + _delFP = false; + return; + } + _delWp = false; + _changeAppr = false; - if(_kln89->_mode == KLN89_MODE_CRSR) { - if(_bEntWp) { - if(_wLinePos > 0) _wLinePos--; - } else { - // _uLinePos with empty/not-empty plan: 1 = Copy FPL 0? / Use?, 2 = unused if empty / Invert?, 3 = >Dis/Dtk field, 4+ = Waypoint 1+ - if(_uLinePos == 0) { - // No-op - } else if(_uLinePos == 1 || _uLinePos == 2) { - _uLinePos--; - } else if(_uLinePos == 3) { - _uLinePos = 4; - } else if(_uLinePos == 4) { - if(_kln89->_flightPlans[_subPage]->IsEmpty()) { - _uLinePos = (_subPage == 0 ? 0 : 1); - } else if(_fplPos == 0) { - _uLinePos = (_subPage == 0 ? 0 : 2); - } else { - _fplPos--; - } - } else if(_uLinePos == 5) { - _uLinePos = 3; - } else { - _uLinePos--; - } + if(_kln89->_mode == KLN89_MODE_CRSR) { + if(_bEntWp) { + if(_wLinePos > 0) _wLinePos--; + } else { + // _uLinePos with empty/not-empty plan: 1 = Copy FPL 0? / Use?, 2 = unused if empty / Invert?, 3 = >Dis/Dtk field, 4+ = Waypoint 1+ + if(_uLinePos == 0) { + // No-op + } else if(_uLinePos == 1 || _uLinePos == 2) { + _uLinePos--; + } else if(_uLinePos == 3) { + _uLinePos = 4; + } else if(_uLinePos == 4) { + if(_kln89->_flightPlans[_subPage]->IsEmpty()) { + _uLinePos = (_subPage == 0 ? 0 : 1); + } else if(_fplPos == 0) { + _uLinePos = (_subPage == 0 ? 0 : 2); + } else { + _fplPos--; + } + } else if(_uLinePos == 5) { + _uLinePos = 3; + } else { + _uLinePos--; + } - if(_subPage == 0 && _uLinePos > 3) { - int ix = _fplPos + (_uLinePos - 4); - if(_fencePos >= 0 && ix >= _fencePos) ix--; - if(_hdrPos >= 0 && ix >= _hdrPos) ix--; - if(ix >= static_cast(_kln89->_activeFP->waypoints.size())) { - _fp0SelWpId.clear(); - } else { - _fp0SelWpId = _kln89->_activeFP->waypoints[ix]->id; - } - } else { - _fp0SelWpId.clear(); - //cout << "Not page 0, or not in waypoints, clearing id!\n"; - } - } - } + if(_subPage == 0 && _uLinePos > 3) { + int ix = _fplPos + (_uLinePos - 4); + if(_fencePos >= 0 && ix >= _fencePos) ix--; + if(_hdrPos >= 0 && ix >= _hdrPos) ix--; + if(ix >= static_cast(_kln89->_activeFP->waypoints.size())) { + _fp0SelWpId.clear(); + } else { + _fp0SelWpId = _kln89->_activeFP->waypoints[ix]->id; + } + } else { + _fp0SelWpId.clear(); + //cout << "Not page 0, or not in waypoints, clearing id!\n"; + } + } + } } void KLN89FplPage::Knob1Right1() { - if(_delFP) { - _delFP = false; - return; - } - _delWp = false; - _changeAppr = false; - - if(_kln89->_mode == KLN89_MODE_CRSR) { - if(_bEntWp) { - if(_wLinePos < 4) _wLinePos++; - } else { - // _uLinePos with empty/not-empty plan: - // 1 = Copy FPL 0? / Use?, 2 = unused if empty / Invert?, 3 = >Dis/Dtk field, 4+ = Waypoint 1+ - if(_uLinePos == 0) { - _uLinePos = (_subPage == 0 ? 4 : 1); - } else if(_uLinePos == 1) { - _uLinePos = (_kln89->_flightPlans[_subPage]->IsEmpty() ? 4 : 2); - } else if(_uLinePos == 2) { - _uLinePos = 4; - } else if(_uLinePos == 3) { - if(!_kln89->_flightPlans[_subPage]->IsEmpty()) _uLinePos = 5; - } else if(_uLinePos == 4) { - _uLinePos = 3; - } else if((_subPage == 0 && _uLinePos == 6) || (_subPage > 0 && _uLinePos == 5)) { - // Urrggh - complicated! - // 3 possibilities: - // 1: We're on the entry field at the end of the list, and can't move any more. - // 2: We're on the last or second-last field, and move to the last position - // 3: We're on a field before the second-last one, and don't move, but change the list-head position - // And 4: _subPage 0 can be complicated by the presence of header/fence lines in an approach. - int hfcount = 0; - if(_subPage == 0) { - if(_hdrPos >= 0) hfcount++; - if(_fencePos >= 0) hfcount++; - } - if(_kln89->_flightPlans[_subPage]->waypoints.size() == 1 || _fplPos == _kln89->_flightPlans[_subPage]->waypoints.size() + hfcount - 1) { - // 1: Don't move - } else if(_fplPos >= _kln89->_flightPlans[_subPage]->waypoints.size() + hfcount - (_subPage == 0 ? 4 : 3)) { - _uLinePos++; - } else { - _fplPos++; - } - } else if(_uLinePos == 5) { - // Must be _subPage 0 - _uLinePos++; - } else { - // Must be the last line - either _uLinePos 6 or 7 depending on _subPage - const unsigned thresh = (_subPage == 0 ? 3 : 2); - if(_kln89->_flightPlans[_subPage]->waypoints.size() == thresh || _fplPos == _kln89->_flightPlans[_subPage]->waypoints.size() - thresh) { - // Don't move - } else { - _fplPos++; - } - } - - if(_subPage == 0 && _uLinePos > 3) { - int ix = _fplPos + (_uLinePos - 4); - if(_fencePos >= 0 && ix >= _fencePos) ix--; - if(_hdrPos >= 0 && ix >= _hdrPos) ix--; - if(ix >= static_cast(_kln89->_activeFP->waypoints.size())) { - _fp0SelWpId.clear(); - } else { - _fp0SelWpId = _kln89->_activeFP->waypoints[ix]->id; - } - } else { - _fp0SelWpId.clear(); - //cout << "Not page 0, or not in waypoints, clearing id!\n"; - } - } - } + if(_delFP) { + _delFP = false; + return; + } + _delWp = false; + _changeAppr = false; + + if(_kln89->_mode == KLN89_MODE_CRSR) { + if(_bEntWp) { + if(_wLinePos < 4) _wLinePos++; + } else { + // _uLinePos with empty/not-empty plan: + // 1 = Copy FPL 0? / Use?, 2 = unused if empty / Invert?, 3 = >Dis/Dtk field, 4+ = Waypoint 1+ + if(_uLinePos == 0) { + _uLinePos = (_subPage == 0 ? 4 : 1); + } else if(_uLinePos == 1) { + _uLinePos = (_kln89->_flightPlans[_subPage]->IsEmpty() ? 4 : 2); + } else if(_uLinePos == 2) { + _uLinePos = 4; + } else if(_uLinePos == 3) { + if(!_kln89->_flightPlans[_subPage]->IsEmpty()) _uLinePos = 5; + } else if(_uLinePos == 4) { + _uLinePos = 3; + } else if((_subPage == 0 && _uLinePos == 6) || (_subPage > 0 && _uLinePos == 5)) { + // Urrggh - complicated! + // 3 possibilities: + // 1: We're on the entry field at the end of the list, and can't move any more. + // 2: We're on the last or second-last field, and move to the last position + // 3: We're on a field before the second-last one, and don't move, but change the list-head position + // And 4: _subPage 0 can be complicated by the presence of header/fence lines in an approach. + int hfcount = 0; + if(_subPage == 0) { + if(_hdrPos >= 0) hfcount++; + if(_fencePos >= 0) hfcount++; + } + if(_kln89->_flightPlans[_subPage]->waypoints.size() == 1 || _fplPos == _kln89->_flightPlans[_subPage]->waypoints.size() + hfcount - 1) { + // 1: Don't move + } else if((int)_fplPos >= static_cast(_kln89->_flightPlans[_subPage]->waypoints.size()) + hfcount - (_subPage == 0 ? 4 : 3)) { + _uLinePos++; + } else { + _fplPos++; + } + } else if(_uLinePos == 5) { + // Must be _subPage 0 + _uLinePos++; + } else { + // Must be the last line - either _uLinePos 6 or 7 depending on _subPage + const unsigned thresh = (_subPage == 0 ? 3 : 2); + if(_kln89->_flightPlans[_subPage]->waypoints.size() == thresh || _fplPos == _kln89->_flightPlans[_subPage]->waypoints.size() - thresh) { + // Don't move + } else { + _fplPos++; + } + } + + if(_subPage == 0 && _uLinePos > 3) { + int ix = _fplPos + (_uLinePos - 4); + if(_fencePos >= 0 && ix >= _fencePos) ix--; + if(_hdrPos >= 0 && ix >= _hdrPos) ix--; + if(ix >= static_cast(_kln89->_activeFP->waypoints.size())) { + _fp0SelWpId.clear(); + } else { + _fp0SelWpId = _kln89->_activeFP->waypoints[ix]->id; + } + } else { + _fp0SelWpId.clear(); + //cout << "Not page 0, or not in waypoints, clearing id!\n"; + } + } + } } void KLN89FplPage::Knob2Left1() { - if(_delFP) { - _delFP = false; - return; - } - _delWp = false; + if(_delFP) { + _delFP = false; + return; + } + _delWp = false; - if(_kln89->_mode != KLN89_MODE_CRSR || _uLinePos == 0) { - if(_kln89->_mode != KLN89_MODE_CRSR) _resetFplPos0 = true; - KLN89Page::Knob2Left1(); - } else { - if(_uLinePos > 3) { - // Check for approach waypoints or header/fences in flightplan 0 - int n = _fplPos + _uLinePos - 4; - bool hdrPos = false; - bool fencePos = false; - bool appWp = false; - //cout << "_fplPos = " << _fplPos << ", _uLinePos = " << _uLinePos << ", n = " << n << ", _hdrPos = " << _hdrPos << ", _fencePos = " << _fencePos << '\n'; - if(n == _hdrPos) { - //cout << "HEADER POS\n"; - hdrPos = true; - } - if(n == _fencePos) { - //cout << "FENCE POS\n"; - fencePos = true; - } - if(_hdrPos >= 0 && n > _hdrPos) --n; - if(_fencePos >= 0 && n >= _fencePos) --n; // This one needs to be >= since n is already decremented by 1 in the line above! - //cout << "New n = " << n << '\n'; - - if(n < static_cast(_kln89->_flightPlans[_subPage]->waypoints.size())) { - if(_kln89->_flightPlans[_subPage]->waypoints[n]->appType != GPS_APP_NONE) { - appWp = true; - } - } - - if(hdrPos) { - // TODO - not sure what we actually do in this condition - _changeAppr = true; - } else if(fencePos) { - // no-op? - } else if(appWp) { - ShowScratchpadMessage("Invald", " Add "); - } else { - if((_wLinePos + 1) > _entWpStr.size()) { - _entWpStr += '9'; - } else { - _entWpStr[_wLinePos] = _kln89->DecChar(_entWpStr[_wLinePos], (_wLinePos == 0 ? false : true)); - } - _bEntWp = true; - _fp0SelWpId.clear(); // Waypoints don't become the DTO default whilst being entered. - - GPSWaypoint* wp = _kln89->FindFirstById(_entWpStr.substr(0, _wLinePos+1)); - if(NULL == wp) { - // no-op - } else { - if(_entWp) { - *_entWp = *wp; // copy - delete wp; - } else { - _entWp = wp; - if(_fplPos + (_uLinePos - 4) >= _kln89->_flightPlans[_subPage]->waypoints.size()) { - _kln89->_flightPlans[_subPage]->waypoints.push_back(_entWp); - } else { - _kln89->_flightPlans[_subPage]->waypoints.insert(_kln89->_flightPlans[_subPage]->waypoints.begin()+(_fplPos + (_uLinePos - 4)), _entWp); - } - } - } - } - } - } + if(_kln89->_mode != KLN89_MODE_CRSR || _uLinePos == 0) { + if(_kln89->_mode != KLN89_MODE_CRSR) _resetFplPos0 = true; + KLN89Page::Knob2Left1(); + } else { + if(_uLinePos > 3) { + // Check for approach waypoints or header/fences in flightplan 0 + int n = _fplPos + _uLinePos - 4; + bool hdrPos = false; + bool fencePos = false; + bool appWp = false; + //cout << "_fplPos = " << _fplPos << ", _uLinePos = " << _uLinePos << ", n = " << n << ", _hdrPos = " << _hdrPos << ", _fencePos = " << _fencePos << '\n'; + if(n == _hdrPos) { + //cout << "HEADER POS\n"; + hdrPos = true; + } + if(n == _fencePos) { + //cout << "FENCE POS\n"; + fencePos = true; + } + if(_hdrPos >= 0 && n > _hdrPos) --n; + if(_fencePos >= 0 && n >= _fencePos) --n; // This one needs to be >= since n is already decremented by 1 in the line above! + //cout << "New n = " << n << '\n'; + + if(n < static_cast(_kln89->_flightPlans[_subPage]->waypoints.size())) { + if(_kln89->_flightPlans[_subPage]->waypoints[n]->appType != GPS_APP_NONE) { + appWp = true; + } + } + + if(hdrPos) { + // TODO - not sure what we actually do in this condition + _changeAppr = true; + } else if(fencePos) { + // no-op? + } else if(appWp) { + ShowScratchpadMessage("Invald", " Add "); + } else { + if((_wLinePos + 1) > _entWpStr.size()) { + _entWpStr += '9'; + } else { + _entWpStr[_wLinePos] = _kln89->DecChar(_entWpStr[_wLinePos], (_wLinePos == 0 ? false : true)); + } + _bEntWp = true; + _fp0SelWpId.clear(); // Waypoints don't become the DTO default whilst being entered. + + GPSWaypoint* wp = _kln89->FindFirstById(_entWpStr.substr(0, _wLinePos+1)); + if(NULL == wp) { + // No ID matches the partial ID entered so _entWpStr must be shortened to the cursor + // position if it was longer due to a match on the previous character. + if(_entWpStr.size() > _wLinePos+1) { + _entWpStr = _entWpStr.substr(0, _wLinePos+1); + } + } else { + // There is a matching full ID to the entered partial ID, so copy the full ID + // into _entWpStr + _entWpStr = wp->id; + if(_entWp) { + *_entWp = *wp; // copy + delete wp; + } else { + _entWp = wp; + if(_fplPos + (_uLinePos - 4) >= _kln89->_flightPlans[_subPage]->waypoints.size()) { + _kln89->_flightPlans[_subPage]->waypoints.push_back(_entWp); + } else { + _kln89->_flightPlans[_subPage]->waypoints.insert(_kln89->_flightPlans[_subPage]->waypoints.begin()+(_fplPos + (_uLinePos - 4)), _entWp); + } + } + } + } + } + } } void KLN89FplPage::Knob2Right1() { - if(_delFP) { - _delFP = false; - return; - } - _delWp = false; + if(_delFP) { + _delFP = false; + return; + } + _delWp = false; - if(_kln89->_mode != KLN89_MODE_CRSR || _uLinePos == 0) { - if(_kln89->_mode != KLN89_MODE_CRSR) _resetFplPos0 = true; - KLN89Page::Knob2Right1(); - } else { - if(_uLinePos > 3) { - // Check for approach waypoints or header/fences in flightplan 0 - int n = _fplPos + _uLinePos - 4; - bool hdrPos = false; - bool fencePos = false; - bool appWp = false; - //cout << "_fplPos = " << _fplPos << ", _uLinePos = " << _uLinePos << ", n = " << n << ", _hdrPos = " << _hdrPos << ", _fencePos = " << _fencePos << '\n'; - if(n == _hdrPos) { - //cout << "HEADER POS\n"; - hdrPos = true; - } - if(n == _fencePos) { - //cout << "FENCE POS\n"; - fencePos = true; - } - if(_hdrPos >= 0 && n > _hdrPos) --n; - if(_fencePos >= 0 && n >= _fencePos) --n; // This one needs to be >= since n is already decremented by 1 in the line above! - //cout << "New n = " << n << '\n'; - - if(n < static_cast(_kln89->_flightPlans[_subPage]->waypoints.size())) { - if(_kln89->_flightPlans[_subPage]->waypoints[n]->appType != GPS_APP_NONE) { - appWp = true; - } - } - - if(hdrPos) { - // TODO - not sure what we actually do in this condition - _changeAppr = true; - } else if(fencePos) { - // no-op? - } else if(appWp) { - ShowScratchpadMessage("Invald", " Add "); - } else { - if((_wLinePos + 1) > _entWpStr.size()) { - _entWpStr += '9'; - } else { - _entWpStr[_wLinePos] = _kln89->DecChar(_entWpStr[_wLinePos], (_wLinePos == 0 ? false : true)); - } - _bEntWp = true; - _fp0SelWpId.clear(); // Waypoints don't become the DTO default whilst being entered. - - GPSWaypoint* wp = _kln89->FindFirstById(_entWpStr.substr(0, _wLinePos+1)); - if(NULL == wp) { - // no-op - } else { - if(_entWp) { - *_entWp = *wp; // copy - delete wp; - } else { - _entWp = wp; - if(_fplPos + (_uLinePos - 4) >= _kln89->_flightPlans[_subPage]->waypoints.size()) { - _kln89->_flightPlans[_subPage]->waypoints.push_back(_entWp); - } else { - _kln89->_flightPlans[_subPage]->waypoints.insert(_kln89->_flightPlans[_subPage]->waypoints.begin()+(_fplPos + (_uLinePos - 4)), _entWp); - } - } - } - } - } - } + if(_kln89->_mode != KLN89_MODE_CRSR || _uLinePos == 0) { + if(_kln89->_mode != KLN89_MODE_CRSR) _resetFplPos0 = true; + KLN89Page::Knob2Right1(); + } else { + if(_uLinePos > 3) { + // Check for approach waypoints or header/fences in flightplan 0 + int n = _fplPos + _uLinePos - 4; + bool hdrPos = false; + bool fencePos = false; + bool appWp = false; + //cout << "_fplPos = " << _fplPos << ", _uLinePos = " << _uLinePos << ", n = " << n << ", _hdrPos = " << _hdrPos << ", _fencePos = " << _fencePos << '\n'; + if(n == _hdrPos) { + //cout << "HEADER POS\n"; + hdrPos = true; + } + if(n == _fencePos) { + //cout << "FENCE POS\n"; + fencePos = true; + } + if(_hdrPos >= 0 && n > _hdrPos) --n; + if(_fencePos >= 0 && n >= _fencePos) --n; // This one needs to be >= since n is already decremented by 1 in the line above! + //cout << "New n = " << n << '\n'; + + if(n < static_cast(_kln89->_flightPlans[_subPage]->waypoints.size())) { + if(_kln89->_flightPlans[_subPage]->waypoints[n]->appType != GPS_APP_NONE) { + appWp = true; + } + } + + if(hdrPos) { + // TODO - not sure what we actually do in this condition + _changeAppr = true; + } else if(fencePos) { + // no-op? + } else if(appWp) { + ShowScratchpadMessage("Invald", " Add "); + } else { + if((_wLinePos + 1) > _entWpStr.size()) { + _entWpStr += 'A'; + } else { + _entWpStr[_wLinePos] = _kln89->IncChar(_entWpStr[_wLinePos], (_wLinePos == 0 ? false : true)); + } + _bEntWp = true; + _fp0SelWpId.clear(); // Waypoints don't become the DTO default whilst being entered. + + GPSWaypoint* wp = _kln89->FindFirstById(_entWpStr.substr(0, _wLinePos+1)); + if(NULL == wp) { + // No ID matches the partial ID entered so _entWpStr must be shortened to the cursor + // position if it was longer due to a match on the previous character. + if(_entWpStr.size() > _wLinePos+1) { + _entWpStr = _entWpStr.substr(0, _wLinePos+1); + } + } else { + // There is a matching full ID to the entered partial ID, so copy the full ID + // into _entWpStr + _entWpStr = wp->id; + if(_entWp) { + *_entWp = *wp; // copy + delete wp; + } else { + _entWp = wp; + if(_fplPos + (_uLinePos - 4) >= _kln89->_flightPlans[_subPage]->waypoints.size()) { + _kln89->_flightPlans[_subPage]->waypoints.push_back(_entWp); + } else { + _kln89->_flightPlans[_subPage]->waypoints.insert(_kln89->_flightPlans[_subPage]->waypoints.begin()+(_fplPos + (_uLinePos - 4)), _entWp); + } + } + } + } + } + } } diff --git a/src/Instrumentation/KLN89/kln89_page_fpl.hxx b/src/Instrumentation/KLN89/kln89_page_fpl.hxx index 92c79e249..770c7ab37 100644 --- a/src/Instrumentation/KLN89/kln89_page_fpl.hxx +++ b/src/Instrumentation/KLN89/kln89_page_fpl.hxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_int.cxx b/src/Instrumentation/KLN89/kln89_page_int.cxx index 1edb2428d..4d5ff6923 100644 --- a/src/Instrumentation/KLN89/kln89_page_int.cxx +++ b/src/Instrumentation/KLN89/kln89_page_int.cxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_int.hxx b/src/Instrumentation/KLN89/kln89_page_int.hxx index 2b990225f..8923db886 100644 --- a/src/Instrumentation/KLN89/kln89_page_int.hxx +++ b/src/Instrumentation/KLN89/kln89_page_int.hxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_nav.cxx b/src/Instrumentation/KLN89/kln89_page_nav.cxx index 0081d70a9..7804878cf 100644 --- a/src/Instrumentation/KLN89/kln89_page_nav.cxx +++ b/src/Instrumentation/KLN89/kln89_page_nav.cxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -251,15 +251,24 @@ void KLN89NavPage::Update(double dt) { _kln89->DrawText("-:--", 2, 11, 0); } } else { // if(3 == _subPage) + // // Switch the cursor off if scan-pull is out on this page. + // if(fgGetBool("/instrumentation/kln89/scan-pull")) { _kln89->_mode = KLN89_MODE_DISP; } - // The moving map page the core KLN89 class draws this. + + // + // Draw the moving map if valid. + // We call the core KLN89 class to do this. + // if(_kln89->_mapOrientation == 2 && _kln89->_groundSpeed_kts < 2) { // Don't draw it if in track up mode and groundspeed < 2kts, as per real-life unit. } else { _kln89->DrawMap(!_suspendAVS); } - // Now draw any annotation over it. + + // + // Now that the map has been drawn, add the annotation (scale, etc). + // int scale = KLN89MapScales[_kln89->_mapScaleUnits][_kln89->_mapScaleIndex]; string scle_str = GPSitoa(scale); if(crsr) { @@ -325,7 +334,10 @@ void KLN89NavPage::Update(double dt) { } } } - // And do part of the field 1 update, since NAV 4 is a special case for the last line. + + // + // Do part of the field 1 update, since NAV 4 is a special case for the last line. + // _kln89->DrawChar('>', 1, 0, 0); if(crsr && _uLinePos == 1) _kln89->Underline(1, 1, 0, 5); if(!(crsr && _uLinePos == 1 && _kln89->_blink)) { diff --git a/src/Instrumentation/KLN89/kln89_page_nav.hxx b/src/Instrumentation/KLN89/kln89_page_nav.hxx index baae8ee75..53ec9e5ee 100644 --- a/src/Instrumentation/KLN89/kln89_page_nav.hxx +++ b/src/Instrumentation/KLN89/kln89_page_nav.hxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_ndb.cxx b/src/Instrumentation/KLN89/kln89_page_ndb.cxx index b6b90bebd..c6ba4bb0e 100644 --- a/src/Instrumentation/KLN89/kln89_page_ndb.cxx +++ b/src/Instrumentation/KLN89/kln89_page_ndb.cxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_ndb.hxx b/src/Instrumentation/KLN89/kln89_page_ndb.hxx index 74be689f4..191a8d1af 100644 --- a/src/Instrumentation/KLN89/kln89_page_ndb.hxx +++ b/src/Instrumentation/KLN89/kln89_page_ndb.hxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_nrst.cxx b/src/Instrumentation/KLN89/kln89_page_nrst.cxx index c592a95c4..85f4d31f1 100644 --- a/src/Instrumentation/KLN89/kln89_page_nrst.cxx +++ b/src/Instrumentation/KLN89/kln89_page_nrst.cxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_nrst.hxx b/src/Instrumentation/KLN89/kln89_page_nrst.hxx index 837af3dac..e3bc91dc4 100644 --- a/src/Instrumentation/KLN89/kln89_page_nrst.hxx +++ b/src/Instrumentation/KLN89/kln89_page_nrst.hxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_oth.cxx b/src/Instrumentation/KLN89/kln89_page_oth.cxx index d8d72f9a2..3caa76ce3 100644 --- a/src/Instrumentation/KLN89/kln89_page_oth.cxx +++ b/src/Instrumentation/KLN89/kln89_page_oth.cxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_oth.hxx b/src/Instrumentation/KLN89/kln89_page_oth.hxx index f2fade95e..fde454233 100644 --- a/src/Instrumentation/KLN89/kln89_page_oth.hxx +++ b/src/Instrumentation/KLN89/kln89_page_oth.hxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_set.cxx b/src/Instrumentation/KLN89/kln89_page_set.cxx index f3bb2ba25..e6bc9c05b 100644 --- a/src/Instrumentation/KLN89/kln89_page_set.cxx +++ b/src/Instrumentation/KLN89/kln89_page_set.cxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_set.hxx b/src/Instrumentation/KLN89/kln89_page_set.hxx index fd99968b0..5d4b5fa70 100644 --- a/src/Instrumentation/KLN89/kln89_page_set.hxx +++ b/src/Instrumentation/KLN89/kln89_page_set.hxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_usr.cxx b/src/Instrumentation/KLN89/kln89_page_usr.cxx index 58c6dad26..455351889 100644 --- a/src/Instrumentation/KLN89/kln89_page_usr.cxx +++ b/src/Instrumentation/KLN89/kln89_page_usr.cxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_usr.hxx b/src/Instrumentation/KLN89/kln89_page_usr.hxx index 7890cea42..c5af056e6 100644 --- a/src/Instrumentation/KLN89/kln89_page_usr.hxx +++ b/src/Instrumentation/KLN89/kln89_page_usr.hxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_vor.cxx b/src/Instrumentation/KLN89/kln89_page_vor.cxx index 414a8c487..cbc70e669 100644 --- a/src/Instrumentation/KLN89/kln89_page_vor.cxx +++ b/src/Instrumentation/KLN89/kln89_page_vor.cxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/KLN89/kln89_page_vor.hxx b/src/Instrumentation/KLN89/kln89_page_vor.hxx index 695f82d0f..f07fd8232 100644 --- a/src/Instrumentation/KLN89/kln89_page_vor.hxx +++ b/src/Instrumentation/KLN89/kln89_page_vor.hxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as diff --git a/src/Instrumentation/dclgps.cxx b/src/Instrumentation/dclgps.cxx index 41697092b..4ceb2b023 100644 --- a/src/Instrumentation/dclgps.cxx +++ b/src/Instrumentation/dclgps.cxx @@ -232,7 +232,7 @@ DCLGPS::~DCLGPS() { } void DCLGPS::draw(osg::State& state) { - _instrument->draw(state); + _instrument->Draw(state); } void DCLGPS::init() { diff --git a/src/Instrumentation/render_area_2d.cxx b/src/Instrumentation/render_area_2d.cxx index c0da87fd7..c3230fb67 100644 --- a/src/Instrumentation/render_area_2d.cxx +++ b/src/Instrumentation/render_area_2d.cxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -29,313 +29,361 @@ #include "render_area_2d.hxx" RA2DPrimitive::RA2DPrimitive() { - invert = false; - debug = false; + invert = false; + debug = false; } - + RenderArea2D::RenderArea2D(int logx, int logy, int sizex, int sizey, int posx, int posy) { - _logx = logx; - _logy = logy; - _sizex = sizex; - _sizey = sizey; - _posx = posx; - _posy = posy; - _clipx1 = 0; - _clipx2 = _logx - 1; - _clipy1 = 0; - _clipy2 = _logy - 1; - - _backgroundColor[0] = 0.0; - _backgroundColor[1] = 0.0; - _backgroundColor[2] = 0.0; - _backgroundColor[3] = 1.0; - _pixelColor[0] = 1.0; - _pixelColor[1] = 0.0; - _pixelColor[2] = 0.0; - _pixelColor[3] = 1.0; - - _ra2d_debug = false; + _logx = logx; + _logy = logy; + _sizex = sizex; + _sizey = sizey; + _posx = posx; + _posy = posy; + _clipx1 = 0; + _clipx2 = _logx - 1; + _clipy1 = 0; + _clipy2 = _logy - 1; + + _backgroundColor[0] = 0.0; + _backgroundColor[1] = 0.0; + _backgroundColor[2] = 0.0; + _backgroundColor[3] = 1.0; + _pixelColor[0] = 1.0; + _pixelColor[1] = 0.0; + _pixelColor[2] = 0.0; + _pixelColor[3] = 1.0; + + _ra2d_debug = false; } -void RenderArea2D::draw(osg::State& state) { - - static osg::ref_ptr renderArea2DStateSet; - if(!renderArea2DStateSet.valid()) { - renderArea2DStateSet = new osg::StateSet; - renderArea2DStateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OFF); - renderArea2DStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); - } - - state.pushStateSet(renderArea2DStateSet.get()); - state.apply(); - state.setActiveTextureUnit(0); - state.setClientActiveTextureUnit(0); - - // DCL - the 2 lines below are copied verbatim from the hotspot drawing code. - // I am not sure if they are needed here or not. - glPushAttrib(GL_ENABLE_BIT); - glDisable(GL_COLOR_MATERIAL); - - // FIXME - disabling all clip planes causes bleed-through through the splash screen. - glDisable(GL_CLIP_PLANE0); - glDisable(GL_CLIP_PLANE1); - glDisable(GL_CLIP_PLANE2); - glDisable(GL_CLIP_PLANE3); +void RenderArea2D::Draw(osg::State& state) { + + static osg::ref_ptr renderArea2DStateSet; + if(!renderArea2DStateSet.valid()) { + renderArea2DStateSet = new osg::StateSet; + renderArea2DStateSet->setTextureMode(0, GL_TEXTURE_2D, osg::StateAttribute::OFF); + renderArea2DStateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + } + + state.pushStateSet(renderArea2DStateSet.get()); + state.apply(); + state.setActiveTextureUnit(0); + state.setClientActiveTextureUnit(0); + + // DCL - the 2 lines below are copied verbatim from the hotspot drawing code. + // I am not sure if they are needed here or not. + glPushAttrib(GL_ENABLE_BIT); + glDisable(GL_COLOR_MATERIAL); + + // FIXME - disabling all clip planes causes bleed-through through the splash screen. + glDisable(GL_CLIP_PLANE0); + glDisable(GL_CLIP_PLANE1); + glDisable(GL_CLIP_PLANE2); + glDisable(GL_CLIP_PLANE3); - oldDrawBackground(); - - for(unsigned int i = 0; i < drawing_list.size(); ++i) { - RA2DPrimitive prim = drawing_list[i]; - switch(prim.type) { - case RA2D_LINE: - oldDrawLine(prim.x1, prim.y1, prim.x2, prim.y2); - break; - case RA2D_QUAD: - if(prim.debug) { - //cout << "Clipping = " << _clipx1 << ", " << _clipy1 << " to " << _clipx2 << ", " << _clipy2 << '\n'; - //cout << "Drawing quad " << prim.x1 << ", " << prim.y1 << " to " << prim.x2 << ", " << prim.y2 << '\n'; - } - oldDrawQuad(prim.x1, prim.y1, prim.x2, prim.y2, prim.invert); - break; - case RA2D_PIXEL: - oldDrawPixel(prim.x1, prim.y1, prim.invert); - break; - } - } - - glPopAttrib(); - - state.popStateSet(); - state.apply(); - state.setActiveTextureUnit(0); - state.setClientActiveTextureUnit(0); + DoDrawBackground(); + + for(unsigned int i = 0; i < drawing_list.size(); ++i) { + RA2DPrimitive prim = drawing_list[i]; + switch(prim.type) { + case RA2D_LINE: + DoDrawLine(prim.x1, prim.y1, prim.x2, prim.y2); + break; + case RA2D_QUAD: + if(prim.debug) { + //cout << "Clipping = " << _clipx1 << ", " << _clipy1 << " to " << _clipx2 << ", " << _clipy2 << '\n'; + //cout << "Drawing quad " << prim.x1 << ", " << prim.y1 << " to " << prim.x2 << ", " << prim.y2 << '\n'; + } + DoDrawQuad(prim.x1, prim.y1, prim.x2, prim.y2, prim.invert); + break; + case RA2D_PIXEL: + DoDrawPixel(prim.x1, prim.y1, prim.invert); + break; + } + } + + drawing_list.clear(); + + glPopAttrib(); + + state.popStateSet(); + state.apply(); + state.setActiveTextureUnit(0); + state.setClientActiveTextureUnit(0); +} + +void RenderArea2D::Flush() { + drawing_list.clear(); } // Set clipping region in logical units void RenderArea2D::SetClipRegion(int x1, int y1, int x2, int y2) { - _clipx1 = x1; - _clipx2 = x2; - _clipy1 = y1; - _clipy2 = y2; - //cout << "Set clip region, clip region = " << _clipx1 << ", " << _clipy1 << " to " << _clipx2 << ", " << _clipy2 << '\n'; + _clipx1 = x1; + _clipx2 = x2; + _clipy1 = y1; + _clipy2 = y2; + //cout << "Set clip region, clip region = " << _clipx1 << ", " << _clipy1 << " to " << _clipx2 << ", " << _clipy2 << '\n'; } // Set clip region to be the same as the rendered area (default) void RenderArea2D::ResetClipRegion() { - _clipx1 = 0; - _clipx2 = _logx - 1; - _clipy1 = 0; - _clipy2 = _logy - 1; - //cout << "Reset clip region, clip region = " << _clipx1 << ", " << _clipy1 << " to " << _clipx2 << ", " << _clipy2 << '\n'; + _clipx1 = 0; + _clipx2 = _logx - 1; + _clipy1 = 0; + _clipy2 = _logy - 1; + //cout << "Reset clip region, clip region = " << _clipx1 << ", " << _clipy1 << " to " << _clipx2 << ", " << _clipy2 << '\n'; } void RenderArea2D::SetPosition(int posx, int posy) { - _posx = posx; - _posy = posy; + _posx = posx; + _posy = posy; } void RenderArea2D::SetLogicalSize(int logx, int logy) { - _logx = logx; - _logy = logy; + _logx = logx; + _logy = logy; } void RenderArea2D::SetActualSize(int sizex, int sizey) { - _sizex = sizex; - _sizey = sizey; + _sizex = sizex; + _sizey = sizey; } void RenderArea2D::DrawPixel(int x, int y, bool invert) { - // Clipping is currently performed in oldDrawPixel - could clip here instead though. + // Clip + if(x < _clipx1 || x > _clipx2 || y < _clipy1 || y > _clipy2) return; - RA2DPrimitive prim; - prim.x1 = x; - prim.y1 = y; - prim.x2 = 0; - prim.y2 = 0; - prim.type = RA2D_PIXEL; - prim.invert = invert; - drawing_list.push_back(prim); + RA2DPrimitive prim; + prim.x1 = x; + prim.y1 = y; + prim.x2 = 0; + prim.y2 = 0; + prim.type = RA2D_PIXEL; + prim.invert = invert; + drawing_list.push_back(prim); } -void RenderArea2D::oldDrawPixel(int x, int y, bool invert) { - // Clip - if(x < _clipx1 || x > _clipx2 || y < _clipy1 || y > _clipy2) return; - - // Scale to position within background - float fx1 = (float)x, fy1 = (float)y; - float rx = (float)_sizex / (float)_logx; - float ry = (float)_sizey / (float)_logy; - fx1 *= rx; - fy1 *= ry; - float fx2 = fx1 + rx; - float fy2 = fy1 + ry; - - // Translate to final position - fx1 += (float)_posx; - fx2 += (float)_posx; - fy1 += (float)_posy; - fy2 += (float)_posy; - - //cout << "DP: " << fx1 << ", " << fy1 << " ... " << fx2 << ", " << fy2 << '\n'; - - doSetColor(invert ? _backgroundColor : _pixelColor); - SGVec2f corners[4] = { - SGVec2f(fx1, fy1), - SGVec2f(fx2, fy1), - SGVec2f(fx2, fy2), - SGVec2f(fx1, fy2) - }; - doDrawQuad(corners); +void RenderArea2D::DoDrawPixel(int x, int y, bool invert) { + // Clip. In theory this shouldn't be necessary, since all input is clipped before adding + // to the drawing list, but it ensures that any errors in clipping lines etc will only + // spill over the clip area within the instrument, and still be clipped from straying + // outside the instrument. + if(x < _clipx1 || x > _clipx2 || y < _clipy1 || y > _clipy2) return; + + // Scale to position within background + float fx1 = (float)x, fy1 = (float)y; + float rx = (float)_sizex / (float)_logx; + float ry = (float)_sizey / (float)_logy; + fx1 *= rx; + fy1 *= ry; + float fx2 = fx1 + rx; + float fy2 = fy1 + ry; + + // Translate to final position + fx1 += (float)_posx; + fx2 += (float)_posx; + fy1 += (float)_posy; + fy2 += (float)_posy; + + //cout << "DP: " << fx1 << ", " << fy1 << " ... " << fx2 << ", " << fy2 << '\n'; + + SetRenderColor(invert ? _backgroundColor : _pixelColor); + SGVec2f corners[4] = { + SGVec2f(fx1, fy1), + SGVec2f(fx2, fy1), + SGVec2f(fx2, fy2), + SGVec2f(fx1, fy2) + }; + RenderQuad(corners); } void RenderArea2D::DrawLine(int x1, int y1, int x2, int y2) { - RA2DPrimitive prim; - prim.x1 = x1; - prim.y1 = y1; - prim.x2 = x2; - prim.y2 = y2; - prim.type = RA2D_LINE; - prim.invert = false; - drawing_list.push_back(prim); + // We need to clip the line to the current region before storing it in the drawing + // list, since when we come to actually draw it the clip region may have changed. + + // Liang-Barsky clipping algorithm + int p[4], q[4]; + float u1 = 0.0f, u2 = 1.0f; + p[0] = -(x2 - x1); q[0] = (x1 - _clipx1); + p[1] = (x2 - x1); q[1] = (_clipx2 - x1); + p[2] = -(y2 - y1); q[2] = (y1 - _clipy1); + p[3] = (y2 - y1); q[3] = (_clipy2 - y1); + + for(int i=0; i<4; ++i) { + if(p[i] == 0) { + if(q[i] < 0) { + // Then we have a trivial rejection of a line parallel to a clip plane + // completely outside the clip region. + return; + } + } else if(p[i] < 0) { + float r = (float)q[i]/(float)p[i]; + u1 = (u1 > r ? u1 : r); + } else { // p[i] > 0 + float r = (float)q[i]/(float)p[i]; + u2 = (u2 < r ? u2 : r); + } + if(u1 > u2) { + // Then the line is completely outside the clip area. + return; + } + } + + float fx1 = x1 + u1 * (float)(x2 - x1); + float fy1 = y1 + u1 * (float)(y2 - y1); + float fx2 = x1 + u2 * (float)(x2 - x1); + float fy2 = y1 + u2 * (float)(y2 - y1); + x1 = (int)(fx1 + 0.5); + y1 = (int)(fy1 + 0.5); + x2 = (int)(fx2 + 0.5); + y2 = (int)(fy2 + 0.5); + + RA2DPrimitive prim; + prim.x1 = x1; + prim.y1 = y1; + prim.x2 = x2; + prim.y2 = y2; + prim.type = RA2D_LINE; + prim.invert = false; + drawing_list.push_back(prim); } -void RenderArea2D::oldDrawLine(int x1, int y1, int x2, int y2) { - // Crude implementation of Bresenham line drawing algorithm. - - // Our lines are non directional, so first order the points x-direction-wise to leave only 4 octants to consider. - if(x2 < x1) { - int tmp_x = x1; - int tmp_y = y1; - x1 = x2; - y1 = y2; - x2 = tmp_x; - y2 = tmp_y; - } - - bool flip_y = (y1 > y2 ? true : false); - int dx = x2 - x1; - int dy = (flip_y ? y1 - y2 : y2 - y1); - if(dx > dy) { - // push the x dir - int y = y1; - int yn = dx/2; - for(int x=x1; x<=x2; ++x) { - DrawPixel(x, y); - yn += dy; - if(yn >= dx) { - yn -= dx; - y = (flip_y ? y - 1 : y + 1); - } - } - } else { - // push the y dir - int x = x1; - int xn = dy/2; - // Must be a more elegant way to roll the next two cases into one! - if(flip_y) { - for(int y=y1; y>=y2; --y) { - DrawPixel(x, y); - xn += dx; - if(xn >= dy) { - xn -= dy; - x++; - } - } - } else { - for(int y=y1; y<=y2; ++y) { - DrawPixel(x, y); - xn += dx; - if(xn >= dy) { - xn -= dy; - x++; - } - } - } - } +void RenderArea2D::DoDrawLine(int x1, int y1, int x2, int y2) { + // Crude implementation of Bresenham line drawing algorithm. + + // Our lines are non directional, so first order the points x-direction-wise to leave only 4 octants to consider. + if(x2 < x1) { + int tmp_x = x1; + int tmp_y = y1; + x1 = x2; + y1 = y2; + x2 = tmp_x; + y2 = tmp_y; + } + + bool flip_y = (y1 > y2 ? true : false); + int dx = x2 - x1; + int dy = (flip_y ? y1 - y2 : y2 - y1); + if(dx > dy) { + // push the x dir + int y = y1; + int yn = dx/2; + for(int x=x1; x<=x2; ++x) { + DoDrawPixel(x, y); + yn += dy; + if(yn >= dx) { + yn -= dx; + y = (flip_y ? y - 1 : y + 1); + } + } + } else { + // push the y dir + int x = x1; + int xn = dy/2; + // Must be a more elegant way to roll the next two cases into one! + if(flip_y) { + for(int y=y1; y>=y2; --y) { + DoDrawPixel(x, y); + xn += dx; + if(xn >= dy) { + xn -= dy; + x++; + } + } + } else { + for(int y=y1; y<=y2; ++y) { + DoDrawPixel(x, y); + xn += dx; + if(xn >= dy) { + xn -= dy; + x++; + } + } + } + } } void RenderArea2D::DrawQuad(int x1, int y1, int x2, int y2, bool invert) { - // Clip and sanity-check. - if(x1 > x2) { - int x = x2; - x2 = x1; - x1 = x; - } - if(y1 > y2) { - int y = y2; - y2 = y1; - y1 = y; - } - x1 = x1 < _clipx1 ? _clipx1 : x1; - if(x1 > _clipx2) { return; } - x2 = x2 > _clipx2 ? _clipx2 : x2; - if(x2 < _clipx1) { return; } - y1 = y1 < _clipy1 ? _clipy1 : y1; - if(y1 > _clipy2) { return; } - y2 = y2 > _clipy2 ? _clipy2 : y2; - if(y2 < _clipy1) { return; } - - RA2DPrimitive prim; - prim.x1 = x1; - prim.y1 = y1; - prim.x2 = x2; - prim.y2 = y2; - prim.type = RA2D_QUAD; - prim.invert = invert; - if(_ra2d_debug) prim.debug = true; - drawing_list.push_back(prim); + // Force the input to be ordered with x1 < x2 and y1 < y2. + if(x1 > x2) { + int x = x2; + x2 = x1; + x1 = x; + } + if(y1 > y2) { + int y = y2; + y2 = y1; + y1 = y; + } + + // Clip the input to the current drawing region. + x1 = x1 < _clipx1 ? _clipx1 : x1; + if(x1 > _clipx2) { return; } + x2 = x2 > _clipx2 ? _clipx2 : x2; + if(x2 < _clipx1) { return; } + y1 = y1 < _clipy1 ? _clipy1 : y1; + if(y1 > _clipy2) { return; } + y2 = y2 > _clipy2 ? _clipy2 : y2; + if(y2 < _clipy1) { return; } + + RA2DPrimitive prim; + prim.x1 = x1; + prim.y1 = y1; + prim.x2 = x2; + prim.y2 = y2; + prim.type = RA2D_QUAD; + prim.invert = invert; + if(_ra2d_debug) prim.debug = true; + drawing_list.push_back(prim); } -void RenderArea2D::oldDrawQuad(int x1, int y1, int x2, int y2, bool invert) { - // Scale to position within background - float fx1 = (float)x1, fy1 = (float)y1; - float fx2 = (float)x2, fy2 = (float)y2; - float rx = (float)_sizex / (float)_logx; - float ry = (float)_sizey / (float)_logy; - fx1 *= rx; - fy1 *= ry; - fx2 *= rx; - fy2 *= ry; - - fx2 += rx; - fy2 += ry; - - // Translate to final position - fx1 += (float)_posx; - fx2 += (float)_posx; - fy1 += (float)_posy; - fy2 += (float)_posy; - - //cout << "DP: " << fx1 << ", " << fy1 << " ... " << fx2 << ", " << fy2 << '\n'; - - doSetColor(invert ? _backgroundColor : _pixelColor); - SGVec2f corners[4] = { - SGVec2f(fx1, fy1), - SGVec2f(fx2, fy1), - SGVec2f(fx2, fy2), - SGVec2f(fx1, fy2) - }; - doDrawQuad(corners); +void RenderArea2D::DoDrawQuad(int x1, int y1, int x2, int y2, bool invert) { + // Scale to position within background + float fx1 = (float)x1, fy1 = (float)y1; + float fx2 = (float)x2, fy2 = (float)y2; + float rx = (float)_sizex / (float)_logx; + float ry = (float)_sizey / (float)_logy; + fx1 *= rx; + fy1 *= ry; + fx2 *= rx; + fy2 *= ry; + + fx2 += rx; + fy2 += ry; + + // Translate to final position + fx1 += (float)_posx; + fx2 += (float)_posx; + fy1 += (float)_posy; + fy2 += (float)_posy; + + //cout << "DP: " << fx1 << ", " << fy1 << " ... " << fx2 << ", " << fy2 << '\n'; + + SetRenderColor(invert ? _backgroundColor : _pixelColor); + SGVec2f corners[4] = { + SGVec2f(fx1, fy1), + SGVec2f(fx2, fy1), + SGVec2f(fx2, fy2), + SGVec2f(fx1, fy2) + }; + RenderQuad(corners); } void RenderArea2D::DrawBackground() { - // TODO + // Currently a NO-OP } -void RenderArea2D::oldDrawBackground() { - doSetColor(_backgroundColor); - SGVec2f corners[4] = { - SGVec2f(_posx, _posy), - SGVec2f(_posx + _sizex, _posy), - SGVec2f(_posx + _sizex, _posy + _sizey), - SGVec2f(_posx, _posy + _sizey) - }; +void RenderArea2D::DoDrawBackground() { + SetRenderColor(_backgroundColor); + SGVec2f corners[4] = { + SGVec2f(_posx, _posy), + SGVec2f(_posx + _sizex, _posy), + SGVec2f(_posx + _sizex, _posy + _sizey), + SGVec2f(_posx, _posy + _sizey) + }; - doDrawQuad(corners); -} - -void RenderArea2D::Flush() { - drawing_list.clear(); + RenderQuad(corners); } // ----------------------------------------- @@ -344,28 +392,27 @@ void RenderArea2D::Flush() { // // ----------------------------------------- -void RenderArea2D::doSetColor( const float *rgba ) { - glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, rgba); - glColor4fv( rgba ); +void RenderArea2D::SetRenderColor( const float *rgba ) { + glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, rgba); + glColor4fv( rgba ); } -void RenderArea2D::doDrawQuad( const SGVec2f *p) { - glBegin(GL_QUADS); - glNormal3f(0.0f, 0.0f, 0.0f); - glVertex2fv( p[0].data() ); - glVertex2fv( p[1].data() ); - glVertex2fv( p[2].data() ); - glVertex2fv( p[3].data() ); - glEnd(); +void RenderArea2D::RenderQuad( const SGVec2f *p) { + glBegin(GL_QUADS); + glNormal3f(0.0f, 0.0f, 0.0f); + glVertex2fv( p[0].data() ); + glVertex2fv( p[1].data() ); + glVertex2fv( p[2].data() ); + glVertex2fv( p[3].data() ); + glEnd(); } -void RenderArea2D::doDrawQuad( const SGVec2f *p, const SGVec4f *color ) { - - glBegin(GL_QUADS); - glNormal3f(0.0f, 0.0f, 0.0f); - glColor4fv( color[0].data() ); glVertex2fv( p[0].data() ); - glColor4fv( color[1].data() ); glVertex2fv( p[1].data() ); - glColor4fv( color[2].data() ); glVertex2fv( p[2].data() ); - glColor4fv( color[3].data() ); glVertex2fv( p[3].data() ); - glEnd(); +void RenderArea2D::RenderQuad( const SGVec2f *p, const SGVec4f *color ) { + glBegin(GL_QUADS); + glNormal3f(0.0f, 0.0f, 0.0f); + glColor4fv( color[0].data() ); glVertex2fv( p[0].data() ); + glColor4fv( color[1].data() ); glVertex2fv( p[1].data() ); + glColor4fv( color[2].data() ); glVertex2fv( p[2].data() ); + glColor4fv( color[3].data() ); glVertex2fv( p[3].data() ); + glEnd(); } diff --git a/src/Instrumentation/render_area_2d.hxx b/src/Instrumentation/render_area_2d.hxx index 646045ea4..83d74efef 100644 --- a/src/Instrumentation/render_area_2d.hxx +++ b/src/Instrumentation/render_area_2d.hxx @@ -3,7 +3,7 @@ // // Written by David Luff, started 2005. // -// Copyright (C) 2005 - David C Luff - david.luff@nottingham.ac.uk +// Copyright (C) 2005 - David C Luff - daveluff AT ntlworld.com // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License as @@ -60,8 +60,6 @@ public: RenderArea2D(int logx, int logy, int sizex, int sizey, int posx, int posy); ~RenderArea2D(); - void draw(osg::State& state); - void SetPixelColor(const float* rgba); void SetBackgroundColor(const float* rgba); void SetPosition(int posx, int posy); @@ -73,23 +71,17 @@ public: // Set clip region to be the same as the rendered area (default) void ResetClipRegion(); - // Drawing specified in logical units + // The DrawXXX functions place the shapes in the buffer, specified + // in logical units, and clipped to the current clip region. + void DrawPixel(int x, int y, bool invert = false); void DrawLine(int x1, int y1, int x2, int y2); void DrawQuad(int x1, int y1, int x2, int y2, bool invert = false); void DrawBackground(); - // Draw a pixel specified by *logical* position - void DrawPixel(int x, int y, bool invert = false); - // The old drawing functions have been renamed in order to buffer the drawing for FG - // - // Drawing specified in logical units - void oldDrawLine(int x1, int y1, int x2, int y2); - void oldDrawQuad(int x1, int y1, int x2, int y2, bool invert = false); - void oldDrawBackground(); - // Draw a pixel specified by *logical* position - void oldDrawPixel(int x, int y, bool invert = false); + // Call Draw to have the buffer contents drawn and then cleared. + void Draw(osg::State& state); - // Flush the buffer pipeline + // Clear the buffer contents void Flush(); // Turn debugging on or off. @@ -104,10 +96,16 @@ private: float _backgroundColor[4]; float _pixelColor[4]; - // Actual drawing routines copied from Atlas - void doSetColor( const float *rgb ); - void doDrawQuad( const SGVec2f *p); - void doDrawQuad( const SGVec2f *p, const SGVec4f *color ); + // Drawing specified in logical units + void DoDrawPixel(int x, int y, bool invert = false); + void DoDrawLine(int x1, int y1, int x2, int y2); + void DoDrawQuad(int x1, int y1, int x2, int y2, bool invert = false); + void DoDrawBackground(); + + // Actual rendering routines copied from Atlas + void SetRenderColor( const float *rgb ); + void RenderQuad( const SGVec2f *p); + void RenderQuad( const SGVec2f *p, const SGVec4f *color ); vector drawing_list; diff --git a/src/Main/fg_commands.cxx b/src/Main/fg_commands.cxx index 28bf42770..a8c45e999 100644 --- a/src/Main/fg_commands.cxx +++ b/src/Main/fg_commands.cxx @@ -697,8 +697,6 @@ do_timeofday (const SGPropertyNode * arg) = fgGetNode("/position/longitude-deg"); static const SGPropertyNode *latitude = fgGetNode("/position/latitude-deg"); - static const SGPropertyNode *cur_time_override - = fgGetNode("/sim/time/cur-time-override", true); int orig_warp = globals->get_warp(); SGTime *t = globals->get_time_params(); @@ -759,14 +757,10 @@ do_timeofday (const SGPropertyNode * arg) * SGD_DEGREES_TO_RADIANS, 180.0, false ); } - // cout << "warp = " << warp << endl; - globals->set_warp( orig_warp + warp ); - - t->update( longitude->getDoubleValue() * SGD_DEGREES_TO_RADIANS, - latitude->getDoubleValue() * SGD_DEGREES_TO_RADIANS, - cur_time_override->getLongValue(), - globals->get_warp() ); + + fgSetInt("/sim/time/warp", orig_warp + warp); + return true; } diff --git a/src/Main/fg_props.cxx b/src/Main/fg_props.cxx index 4d944bfc3..3312889f0 100644 --- a/src/Main/fg_props.cxx +++ b/src/Main/fg_props.cxx @@ -256,7 +256,14 @@ static const char * getDateString () { static char buf[64]; // FIXME - struct tm * t = globals->get_time_params()->getGmt(); + + SGTime * st = globals->get_time_params(); + if (!st) { + buf[0] = 0; + return buf; + } + + struct tm * t = st->getGmt(); sprintf(buf, "%.4d-%.2d-%.2dT%.2d:%.2d:%.2d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec); @@ -270,9 +277,6 @@ getDateString () static void setDateString (const char * date_string) { - static const SGPropertyNode *cur_time_override - = fgGetNode("/sim/time/cur-time-override", true); - SGTime * st = globals->get_time_params(); struct tm * current_time = st->getGmt(); struct tm new_time; @@ -298,16 +302,13 @@ setDateString (const char * date_string) // values, one way or another. new_time.tm_year -= 1900; new_time.tm_mon -= 1; - // Now, tell flight gear to use // the new time. This was far // too difficult, by the way. long int warp = mktime(&new_time) - mktime(current_time) + globals->get_warp(); - double lon = fgGetDouble("/position/longitude-deg") * SG_DEGREES_TO_RADIANS; - double lat = fgGetDouble("/position/latitude-deg") * SG_DEGREES_TO_RADIANS; - globals->set_warp(warp); - st->update(lon, lat, cur_time_override->getLongValue(), warp); + + fgSetInt("/sim/time/warp", warp); } /** @@ -317,7 +318,13 @@ static const char * getGMTString () { static char buf[16]; - struct tm *t = globals->get_time_params()->getGmt(); + SGTime * st = globals->get_time_params(); + if (!st) { + buf[0] = 0; + return buf; + } + + struct tm *t = st->getGmt(); snprintf(buf, 16, "%.2d:%.2d:%.2d", t->tm_hour, t->tm_min, t->tm_sec); return buf; @@ -367,30 +374,6 @@ getTrackMag () return magtrack; } -static long -getWarp () -{ - return globals->get_warp(); -} - -static void -setWarp (long warp) -{ - globals->set_warp(warp); -} - -static long -getWarpDelta () -{ - return globals->get_warp_delta(); -} - -static void -setWarpDelta (long delta) -{ - globals->set_warp_delta(delta); -} - static bool getWindingCCW () { @@ -515,9 +498,6 @@ FGProperties::bind () fgTie("/environment/magnetic-variation-deg", getMagVar); fgTie("/environment/magnetic-dip-deg", getMagDip); - fgTie("/sim/time/warp", getWarp, setWarp, false); - fgTie("/sim/time/warp-delta", getWarpDelta, setWarpDelta); - // Misc. Temporary junk. fgTie("/sim/temp/winding-ccw", getWindingCCW, setWindingCCW, false); } @@ -545,9 +525,6 @@ FGProperties::unbind () fgUntie("/environment/magnetic-variation-deg"); fgUntie("/environment/magnetic-dip-deg"); - fgUntie("/sim/time/warp"); - fgUntie("/sim/time/warp-delta"); - // Misc. Temporary junk. fgUntie("/sim/temp/winding-ccw"); fgUntie("/sim/temp/full-screen"); diff --git a/src/Main/globals.cxx b/src/Main/globals.cxx index aa34a9660..2e72e8276 100644 --- a/src/Main/globals.cxx +++ b/src/Main/globals.cxx @@ -122,8 +122,6 @@ FGGlobals::FGGlobals() : soundmgr( new SGSoundMgr ), sim_time_sec( 0.0 ), fg_root( "" ), - warp( 0 ), - warp_delta( 0 ), time_params( NULL ), ephem( NULL ), mag( NULL ), @@ -401,4 +399,24 @@ FGGlobals::get_current_view () const return viewmgr->get_current_view(); } +long int FGGlobals::get_warp() const +{ + return fgGetInt("/sim/time/warp"); +} + +void FGGlobals::set_warp( long int w ) +{ + fgSetInt("/sim/time/warp", w); +} + +long int FGGlobals::get_warp_delta() const +{ + return fgGetInt("/sim/time/warp-delta"); +} + +void FGGlobals::set_warp_delta( long int d ) +{ + fgSetInt("/sim/time/warp-delta", d); +} + // end of globals.cxx diff --git a/src/Main/globals.hxx b/src/Main/globals.hxx index 097e3acb5..e241b6297 100644 --- a/src/Main/globals.hxx +++ b/src/Main/globals.hxx @@ -104,14 +104,6 @@ private: std::string browser; - // An offset in seconds from the true time. Allows us to adjust - // the effective time of day. - long int warp; - - // How much to change the value of warp each iteration. Allows us - // to make time progress faster than normal (or even run in reverse.) - long int warp_delta; - // Time structure SGTime *time_params; @@ -227,13 +219,11 @@ public: inline const std::string &get_browser () const { return browser; } void set_browser (const std::string &b) { browser = b; } - inline long int get_warp() const { return warp; } - inline void set_warp( long int w ) { warp = w; } - inline void inc_warp( long int w ) { warp += w; } + long int get_warp() const; + void set_warp( long int w ); - inline long int get_warp_delta() const { return warp_delta; } - inline void set_warp_delta( long int d ) { warp_delta = d; } - inline void inc_warp_delta( long int d ) { warp_delta += d; } + long int get_warp_delta() const; + void set_warp_delta( long int d ); inline SGTime *get_time_params() const { return time_params; } inline void set_time_params( SGTime *t ) { time_params = t; } diff --git a/src/Main/options.cxx b/src/Main/options.cxx index 1b5d7325b..5604e2f98 100644 --- a/src/Main/options.cxx +++ b/src/Main/options.cxx @@ -1552,6 +1552,10 @@ parse_option (const string& arg) SG_LOG( SG_GENERAL, SG_ALERT, "Bad property assignment: " << arg ); return FG_OPTIONS_ERROR; } + } else if ( arg.find("-psn_") == 0) { + // on Mac, when launched from the GUI, we are passed the ProcessSerialNumber + // as an argument (and no others). Silently ignore the argument here. + return FG_OPTIONS_OK; } else if ( arg.find( "--" ) == 0 ) { size_t pos = arg.find( '=' ); string arg_name, arg_value; diff --git a/src/Time/TimeManager.cxx b/src/Time/TimeManager.cxx index f28deeaf9..2e2389695 100644 --- a/src/Time/TimeManager.cxx +++ b/src/Time/TimeManager.cxx @@ -58,10 +58,15 @@ void TimeManager::init() _firstUpdate = true; _inited = true; _dtRemainder = 0.0; + _adjustWarpOnUnfreeze = false; _maxDtPerFrame = fgGetNode("/sim/max-simtime-per-frame", true); _clockFreeze = fgGetNode("/sim/freeze/clock", true); _timeOverride = fgGetNode("/sim/time/cur-time-override", true); + _warp = fgGetNode("/sim/time/warp", true); + _warp->addChangeListener(this); + + _warpDelta = fgGetNode("/sim/time/warp-delta", true); _longitudeDeg = fgGetNode("/position/longitude-deg", true); _latitudeDeg = fgGetNode("/position/latitude-deg", true); @@ -70,16 +75,17 @@ void TimeManager::init() zone.append("Timezone"); double lon = _longitudeDeg->getDoubleValue() * SG_DEGREES_TO_RADIANS; double lat = _latitudeDeg->getDoubleValue() * SG_DEGREES_TO_RADIANS; + _impl = new SGTime(lon, lat, zone.str(), _timeOverride->getLongValue()); - globals->set_warp_delta(0); + _warpDelta->setIntValue(0); globals->get_event_mgr()->addTask("updateLocalTime", this, &TimeManager::updateLocalTime, 30*60 ); updateLocalTime(); _impl->update(lon, lat, _timeOverride->getLongValue(), - globals->get_warp()); + _warp->getIntValue()); globals->set_time_params(_impl); // frame/update-rate counters @@ -95,14 +101,38 @@ void TimeManager::postinit() void TimeManager::reinit() { + shutdown(); + init(); + postinit(); +} + +void TimeManager::shutdown() +{ + _warp->removeChangeListener(this); + globals->set_time_params(NULL); delete _impl; _impl = NULL; _inited = false; globals->get_event_mgr()->removeTask("updateLocalTime"); - - init(); - postinit(); +} + +void TimeManager::valueChanged(SGPropertyNode* aProp) +{ + if (aProp == _warp) { + if (_clockFreeze->getBoolValue()) { + // if the warp is changed manually while frozen, don't modify it when + // un-freezing - the user wants to unfreeze with exactly the warp + // they specified. + _adjustWarpOnUnfreeze = false; + } + + double lon = _longitudeDeg->getDoubleValue() * SG_DEGREES_TO_RADIANS; + double lat = _latitudeDeg->getDoubleValue() * SG_DEGREES_TO_RADIANS; + _impl->update(lon, lat, + _timeOverride->getLongValue(), + _warp->getIntValue()); + } } void TimeManager::computeTimeDeltas(double& simDt, double& realDt) @@ -177,25 +207,32 @@ void TimeManager::computeTimeDeltas(double& simDt, double& realDt) void TimeManager::update(double dt) { bool freeze = _clockFreeze->getBoolValue(); + time_t now = time(NULL); + if (freeze) { // clock freeze requested if (_timeOverride->getLongValue() == 0) { - fgSetLong( "/sim/time/cur-time-override", _impl->get_cur_time()); - globals->set_warp(0); + _timeOverride->setLongValue(now); + _adjustWarpOnUnfreeze = true; } } else { // no clock freeze requested if (_lastClockFreeze) { - // clock just unfroze, let's set warp as the difference - // between frozen time and current time so we don't get a - // time jump (and corresponding sky object and lighting - // jump.) - globals->set_warp(_timeOverride->getLongValue() - time(NULL)); - fgSetLong( "/sim/time/cur-time-override", 0 ); + if (_adjustWarpOnUnfreeze) { + // clock just unfroze, let's set warp as the difference + // between frozen time and current time so we don't get a + // time jump (and corresponding sky object and lighting + // jump.) + int adjust = _timeOverride->getLongValue() - now; + SG_LOG(SG_GENERAL, SG_INFO, "adjusting on un-freeze:" << adjust); + _warp->setIntValue(_warp->getIntValue() + adjust); + } + _timeOverride->setLongValue(0); } - if ( globals->get_warp_delta() != 0 ) { - globals->inc_warp( globals->get_warp_delta() ); + int warpDelta = _warpDelta->getIntValue(); + if (warpDelta != 0) { + _warp->setIntValue(_warp->getIntValue() + warpDelta); } } @@ -204,7 +241,7 @@ void TimeManager::update(double dt) double lat = _latitudeDeg->getDoubleValue() * SG_DEGREES_TO_RADIANS; _impl->update(lon, lat, _timeOverride->getLongValue(), - globals->get_warp()); + _warp->getIntValue()); computeFrameRate(); } @@ -304,7 +341,7 @@ void TimeManager::updateLocalTime() void TimeManager::initTimeOffset() { // Handle potential user specified time offsets - int orig_warp = globals->get_warp(); + int orig_warp = _warp->getIntValue(); time_t cur_time = _impl->get_cur_time(); time_t currGMT = sgTimeGetGMT( gmtime(&cur_time) ); time_t systemLocalTime = sgTimeGetGMT( localtime(&cur_time) ); @@ -355,10 +392,8 @@ void TimeManager::initTimeOffset() warp = 0; } - globals->set_warp( orig_warp + warp ); - _impl->update(lon, lat, _timeOverride->getLongValue(), - globals->get_warp() ); + _warp->setIntValue( orig_warp + warp ); SG_LOG( SG_GENERAL, SG_INFO, "After fgInitTimeOffset(): warp = " - << globals->get_warp() ); + << _warp->getIntValue() ); } diff --git a/src/Time/TimeManager.hxx b/src/Time/TimeManager.hxx index c0a89c39a..d0dff8155 100644 --- a/src/Time/TimeManager.hxx +++ b/src/Time/TimeManager.hxx @@ -26,7 +26,7 @@ // forward decls class SGTime; -class TimeManager : public SGSubsystem +class TimeManager : public SGSubsystem, public SGPropertyChangeListener { public: TimeManager(); @@ -36,10 +36,14 @@ public: virtual void init(); virtual void reinit(); virtual void postinit(); + virtual void shutdown(); void update(double dt); +// SGPropertyChangeListener overrides + virtual void valueChanged(SGPropertyNode *); private: + /** * Ensure a consistent update-rate using a combination of * sleep()-ing and busy-waiting. @@ -64,8 +68,12 @@ private: SGPropertyNode_ptr _maxDtPerFrame; SGPropertyNode_ptr _clockFreeze; SGPropertyNode_ptr _timeOverride; + SGPropertyNode_ptr _warp; + SGPropertyNode_ptr _warpDelta; + bool _lastClockFreeze; - + bool _adjustWarpOnUnfreeze; + SGPropertyNode_ptr _longitudeDeg; SGPropertyNode_ptr _latitudeDeg;