int MapWindow::SharedTopView(LKSurface& Surface, DiagrammStruct* psDia , double fAS_Bearing, double fWP_Bearing) { int iOldDisplayOrientation = DisplayOrientation; DiagrammStruct m_Dia = *psDia; const RECT& rct = m_Dia.rc; unsigned short getsideviewpage=GetSideviewPage(); LKASSERT(getsideviewpage<NUMBER_OF_SHARED_MULTIMAPS); LKASSERT(Current_Multimap_SizeY!=SIZE0); DisplayOrientation = GetMMNorthUp(getsideviewpage); switch(GetMMNorthUp(getsideviewpage)) { case TRACKUP: break; case NORTHUP: default: m_Dia.fXMin = -m_Dia.fXMax; break; } double fOldScale = zoom.Scale(); const auto hfOld = Surface.SelectObject(LK8PanelUnitFont); if(zoom.AutoZoom()) zoom.AutoZoom(false); double fFact = 1.25 ; #ifdef INIT_CASE switch(ScreenSize) { case ss800x480: fFact=0.750; break; case ss640x480: fFact=0.938; break; case ss480x272: fFact=0.708; break; case ss400x240: fFact=0.750; break; case ss320x240: fFact=0.938; break; case ss480x800: fFact=1.250; break; case ss480x640: fFact=1.250; break; case ss272x480: fFact=1.250; break; case ss240x400: fFact=1.250; break; case ss240x320: fFact=1.250; break; default: fFact=1.000; break; } #endif if((ScreenSizeX > 0) && (ScreenSizeY > 0)) { if(ScreenSizeX > ScreenSizeY) fFact = (double)ScreenSizeY/(double)ScreenSizeX * 1.250; } PanLatitude = DrawInfo.Latitude; PanLongitude = DrawInfo.Longitude; switch(GetMMNorthUp(getsideviewpage)) { case TRACKUP: DisplayAngle = AngleLimit360(fAS_Bearing +270.0); DisplayAircraftAngle = AngleLimit360(fWP_Bearing); break; case NORTHUP: default: DisplayAngle = 0; if( getsideviewpage == IM_HEADING || getsideviewpage==IM_VISUALGLIDE) DisplayAircraftAngle = AngleLimit360(fAS_Bearing); else DisplayAircraftAngle = AngleLimit360(DrawInfo.TrackBearing); break; } int iOldLocator = EnableThermalLocator; EnableThermalLocator =0; /*******/ #warning "wrong place for do that, always bad idea to change layout inside drawing fonctions !" MapWindow::ChangeDrawRect(rct); // set new area for terrain and topology /*******/ zoom.RequestedScale((m_Dia.fXMax -m_Dia.fXMin) * fFact * (DISTANCEMODIFY)/10.0f); POINT Orig = { CalcDistanceCoordinat(0.0, (DiagrammStruct*) &m_Dia),(rct.bottom-rct.top)/2}; POINT Orig_Aircraft= {0,0}; zoom.ModifyMapScale(); zoom.UpdateMapScale(); const ScreenProjection _Proj = CalculateScreenPositions( Orig, rct, &Orig_Aircraft); CalculateScreenPositionsAirspace(rct, _Proj); bool terrainpainted=false; if (IsMultimapTerrain() && DerivedDrawInfo.TerrainValid && RasterTerrain::isTerrainLoaded() ) { LKTextBlack=false; BlackScreen=false; LockTerrainDataGraphics(); DrawTerrain(Surface, rct, _Proj, GetAzimuth(), 40.0); UnlockTerrainDataGraphics(); terrainpainted=true; } else { // We fill up the background wity chosen empty map color Surface.FillRect(&rct, hInvBackgroundBrush[BgMapColor]); // We force LK painting black values on screen depending on the background color in use // blackscreen would force everything to be painted white, instead LKTextBlack=BgMapColorTextBlack[BgMapColor]; if (BgMapColor>6 ) BlackScreen=true; else BlackScreen=false; } ResetLabelDeclutter(); // We reduce screen cluttering for some cases.. short olddecluttermode=DeclutterMode; if (Current_Multimap_SizeY==SIZE4) goto _nomoredeclutter; if (Current_Multimap_SizeY<SIZE3) { DeclutterMode+=2; } else { if (Current_Multimap_SizeY==SIZE3) DeclutterMode++; } if (DeclutterMode>dmVeryHigh) DeclutterMode=dmVeryHigh; _nomoredeclutter: if (IsMultimapTopology()) { // Do not print topology labels, to be used with another config later! // SaturateLabelDeclutter(); DrawTopology(Surface, rct, _Proj); } else { // No topology is desired, but terrain requires water areas nevertheless if (terrainpainted) { DrawTopology(Surface, rct, _Proj, true); // water only! } } if (IsMultimapAirspace()) { DrawAirSpace(Surface, rct, _Proj); // full screen, to hide clipping effect on low border } if (Flags_DrawTask && MapSpaceMode!=MSM_MAPASP && ValidTaskPoint(ActiveTaskPoint) && ValidTaskPoint(1)) { DrawTaskAAT(Surface, rct); DrawTask(Surface, rct, _Proj, Orig_Aircraft); } if (IsMultimapWaypoints()) { DrawWaypointsNew(Surface,rct); } if (Flags_DrawFAI) DrawFAIOptimizer(Surface, rct, _Proj, Orig_Aircraft); DeclutterMode=olddecluttermode; // set it back correctly /* THIS STUFF DOES NOT WORK IN SHARED MAPS, YET NEED FIXING LatLon2Screen for shared maps using Sideview #ifdef GTL2 if (((FinalGlideTerrain == 2) || (FinalGlideTerrain == 4)) && DerivedDrawInfo.TerrainValid) DrawTerrainAbove(hdc, rct); #endif */ // // Stuff for MAPTRK only (M1) if (MapSpaceMode==MSM_MAPTRK) { if(IsMultimapTerrain() || IsMultimapTopology() ) { if (FinalGlideTerrain && DerivedDrawInfo.TerrainValid) DrawGlideThroughTerrain(Surface, rct, _Proj); } if (extGPSCONNECT) DrawBearing(Surface, rct, _Proj); // Wind arrow if (IsMultimapOverlaysGauges()) DrawWindAtAircraft2(Surface, Orig_Aircraft, rct); } if (MapSpaceMode==MSM_MAPWPT) { if (extGPSCONNECT) DrawBearing(Surface, rct, _Proj); } switch(GetMMNorthUp(getsideviewpage)) { case NORTHUP: default: DrawCompass( Surface, rct, 0); break; case TRACKUP: if(getsideviewpage == IM_HEADING || getsideviewpage == IM_VISUALGLIDE) DrawCompass( Surface, rct, DrawInfo.TrackBearing-90.0); else DrawCompass( Surface, rct, DisplayAngle); break; } /**************************************************************************************************** * draw vertical line ****************************************************************************************************/ POINT line[2]; line[0].x = rct.left; line[0].y = Orig_Aircraft.y-1; line[1].x = rct.right; line[1].y = line[0].y; switch(GetMMNorthUp(getsideviewpage)) { case TRACKUP: // Are we are not topview fullscreen? if (Current_Multimap_SizeY<SIZE4 && !(MapSpaceMode==MSM_VISUALGLIDE)) { Surface.DrawDashLine(NIBLSCALE(1), line[0], line[1], Sideview_TextColor, rct); } else { if (TrackBar) { DrawHeadUpLine(Surface, Orig, rct, psDia->fXMin ,psDia->fXMax); if (ISGAAIRCRAFT) DrawFuturePos(Surface, Orig, rct, true); } } break; case NORTHUP: default: if (TrackBar) { DrawHeadUpLine(Surface, Orig, rct, psDia->fXMin ,psDia->fXMax); if (ISGAAIRCRAFT) DrawFuturePos(Surface, Orig, rct, true); } break; } DrawAircraft(Surface, Orig_Aircraft); // M3 has sideview always on, so wont apply here, and no need to check if (Current_Multimap_SizeY==SIZE4) { DrawMapScale(Surface,rct,0); } MapWindow::zoom.RequestedScale(fOldScale); EnableThermalLocator = iOldLocator; DisplayOrientation = iOldDisplayOrientation; Surface.SelectObject(hfOld); return 0; }
void MapWindow::RenderMapWindowBg(LKSurface& Surface, const RECT& rc) { if ( (LKSurface::AlphaBlendSupported() && BarOpacity < 100) || mode.AnyPan() ) { RECT newRect = {0, 0, ScreenSizeX, ScreenSizeY}; MapWindow::ChangeDrawRect(newRect); } else { RECT newRect = {0, 0, ScreenSizeX, ScreenSizeY - BottomSize - (ScreenSizeY-MapRect.bottom)-1}; MapWindow::ChangeDrawRect(newRect); } if (QUICKDRAW) { goto _skip_calcs; } // Here we calculate arrival altitude, GD etc for map waypoints. Splitting with multicalc will result in delayed // updating of visible landables, for example. The nearest pages do this separately, with their own sorting. // Basically we assume -like for nearest- that values will not change that much in the multicalc split time. // Target and tasks are recalculated in real time in any case. Nearest too. LKCalculateWaypointReachable(false); _skip_calcs: if (PGZoomTrigger) { if (!mode.Is(Mode::MODE_PANORAMA)) { mode.Special(Mode::MODE_SPECIAL_PANORAMA, true); LastZoomTrigger = DrawInfo.Time; Message::AddMessage(1000, 3, gettext(TEXT("_@M872_"))); // LANDSCAPE ZOOM FOR 20s LKSound(TEXT("LK_TONEUP.WAV")); } else { // previously called, see if time has passed if (DrawInfo.Time > (LastZoomTrigger + 20.0)) { // time has passed, lets go back LastZoomTrigger = 0; // just for safety mode.Special(Mode::MODE_SPECIAL_PANORAMA, false); PGZoomTrigger = false; Message::AddMessage(1500, 3, gettext(TEXT("_@M873_"))); // BACK TO NORMAL ZOOM LKSound(TEXT("LK_TONEDOWN.WAV")); } } } // // "Checkpoint Charlie" // This is were we process stuff for anything else but main map. // We let the calculations run also for MapSpace modes. // But for multimaps, we can also draw some more stuff.. // We are also sent back here from next code, when we detect that // the MapSpace mode has changed from MAP to something else while we // were rendering. // QuickRedraw: // if (DONTDRAWTHEMAP) { const bool isMultimap = IsMultiMapShared(); // DrawMapSpace can change "MapSpaceMode", get this before. DrawMapSpace(Surface, rc); // Is this a "shared map" environment? if (isMultimap) { // Shared map, of course not MSN_MAP, since dontdrawthemap was checked // if (IsMultimapOverlaysGauges()) { RenderOverlayGauges(Surface, rc); } if (IsMultimapOverlaysText()) { DrawLook8000(Surface, rc); } } else { // Not in map painting environment // ex. nearest pages, but also MAPRADAR.. } // DrawBottomBar(Surface, rc); #ifdef DRAWDEBUG DrawDebug(hdc, rc); #endif // no need to do SelectObject as at the bottom of function return; } POINT Orig, Orig_Aircraft; CalculateOrigin(rc, &Orig); const ScreenProjection _Proj = CalculateScreenPositions(Orig, rc, &Orig_Aircraft); // When no terrain is painted, set a background0 // Remember that in this case we have plenty of cpu time to spend for best result if (!IsMultimapTerrain() || !DerivedDrawInfo.TerrainValid || !RasterTerrain::isTerrainLoaded()) { // We force LK painting black values on screen depending on the background color in use // TODO make it an array once settled // blackscreen would force everything to be painted white, instead LKTextBlack = BgMapColorTextBlack[BgMapColor]; if (BgMapColor > 6) BlackScreen = true; else BlackScreen = false; } else { LKTextBlack = false; BlackScreen = false; } // Logic of DONTDRAWTHEMAP is the following: // We are rendering the screen page here. If we are here, we passed Checkpoint Charlie. // So we were, at charlie, in MSM_MAP: preparing the main map stuff. // If we detect that MapSpace has CHANGED while we were doing our job here, // it means that the user has clicked meanwhile. He desires another page, so let's // reset our intentions and go back to beginning, or nearby.. // We have a new job to do, for another MapSpace, no more MAP. if (DONTDRAWTHEMAP) { goto QuickRedraw; } bool terrainpainted = false; if ((IsMultimapTerrain() && (DerivedDrawInfo.TerrainValid) && RasterTerrain::isTerrainLoaded()) ) { // sunelevation is never used, it is still a todo in Terrain double sunelevation = 40.0; double sunazimuth = GetAzimuth(); LockTerrainDataGraphics(); if (DONTDRAWTHEMAP) { // 100318 UnlockTerrainDataGraphics(); goto QuickRedraw; } if(DrawTerrain(Surface, DrawRect, _Proj, sunazimuth, sunelevation)) { terrainpainted = true; } if (DONTDRAWTHEMAP) { UnlockTerrainDataGraphics(); goto QuickRedraw; } if (!QUICKDRAW) { // SHADED terrain unreachable, aka glide amoeba. This is not the outlined perimeter! #ifdef GTL2 if (((FinalGlideTerrain == 2) || (FinalGlideTerrain == 4)) && DerivedDrawInfo.TerrainValid) { #else if ((FinalGlideTerrain == 2) && DerivedDrawInfo.TerrainValid) { #endif DrawTerrainAbove(Surface, DrawRect); } } UnlockTerrainDataGraphics(); } // // REMINDER: WE ARE IN MAIN MAP HERE: MSM_MAP ONLY, OR PANNING MODE! // MAPSPACEMODE CAN STILL CHANGE, DUE TO USER INPUT. BUT WE GOT HERE IN // EITHER PAN OR MSM_MAP. // if (DONTDRAWTHEMAP) { goto QuickRedraw; } if(!terrainpainted) { // fill background.. Surface.FillRect(&rc, hInvBackgroundBrush[BgMapColor]); } if (IsMultimapTopology()) { DrawTopology(Surface, DrawRect, _Proj); } else { // If no topology wanted, but terrain painted, we paint only water stuff if (terrainpainted) DrawTopology(Surface, DrawRect, _Proj, true); } #if 0 StartupStore(_T("... Experimental1=%.0f\n"), Experimental1); StartupStore(_T("... Experimental2=%.0f\n"), Experimental2); Experimental1 = 0.0; Experimental2 = 0.0; #endif // Topology labels are printed first, using OLD wps positions from previous run! // Reset for topology labels decluttering engine occurs also in another place here! ResetLabelDeclutter(); if ((Flags_DrawTask || TargetDialogOpen) && ValidTaskPoint(ActiveTaskPoint) && ValidTaskPoint(1)) { DrawTaskAAT(Surface, DrawRect); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } if (IsMultimapAirspace()) { DrawAirSpace(Surface, rc, _Proj); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } // In QUICKDRAW dont draw trail, thermals, glide terrain if (QUICKDRAW) { goto _skip_stuff; } DrawThermalEstimate(Surface, DrawRect, _Proj); if (OvertargetMode == OVT_THER) DrawThermalEstimateMultitarget(Surface, DrawRect, _Proj); // draw red cross on glide through terrain marker if (FinalGlideTerrain && DerivedDrawInfo.TerrainValid) { DrawGlideThroughTerrain(Surface, DrawRect, _Proj); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } _skip_stuff: if (IsMultimapAirspace() && AirspaceWarningMapLabels) { DrawAirspaceLabels(Surface, DrawRect, _Proj, Orig_Aircraft); if (DONTDRAWTHEMAP) { // 100319 goto QuickRedraw; } } if (IsMultimapWaypoints()) { DrawWaypointsNew(Surface, DrawRect); } if (TrailActive) { LKDrawLongTrail(Surface, Orig_Aircraft, DrawRect); // NEED REWRITING LKDrawTrail(Surface, DrawRect, _Proj); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } if ((Flags_DrawTask || TargetDialogOpen) && ValidTaskPoint(ActiveTaskPoint) && ValidTaskPoint(1)) { DrawTask(Surface, DrawRect, _Proj, Orig_Aircraft); } if (Flags_DrawFAI) { if (MapWindow::DerivedDrawInfo.Flying) { // FAI optimizer does not depend on tasks, being based on trace DrawFAIOptimizer(Surface, DrawRect, _Proj, Orig_Aircraft); } else { // not flying => show FAI sectors for the task if (ValidTaskPoint(ActiveTaskPoint) && ValidTaskPoint(1)) { DrawTaskSectors(Surface, DrawRect, _Proj); } } } // In QUICKDRAW do not paint other useless stuff if (QUICKDRAW) { if (extGPSCONNECT) DrawBearing(Surface, DrawRect, _Proj); goto _skip_2; } // --------------------------------------------------- DrawTeammate(Surface, rc, _Proj); if (extGPSCONNECT) { DrawBestCruiseTrack(Surface, Orig_Aircraft); DrawBearing(Surface, DrawRect, _Proj); } // draw wind vector at aircraft if (NOTANYPAN) { DrawWindAtAircraft2(Surface, Orig_Aircraft, DrawRect); } else if (mode.Is(Mode::MODE_TARGET_PAN)) { DrawWindAtAircraft2(Surface, Orig, rc); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } // Draw traffic and other specifix LK gauges LKDrawFLARMTraffic(Surface, DrawRect, _Proj, Orig_Aircraft); // --------------------------------------------------- _skip_2: if (NOTANYPAN) { if (IsMultimapOverlaysGauges()) { RenderOverlayGauges(Surface, rc); } if (TrackBar) { DrawHeading(Surface, Orig, DrawRect); if (ISGAAIRCRAFT) { DrawFuturePos(Surface, Orig, DrawRect); } } if (ISGAAIRCRAFT) { DrawHSIarc(Surface, Orig, DrawRect); } if (IsMultimapOverlaysText()) { DrawLook8000(Surface, rc); } DrawBottomBar(Surface, rc); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } // Draw glider or paraglider if (extGPSCONNECT) { DrawAircraft(Surface, Orig_Aircraft); } #if USETOPOMARKS // marks on top... DrawMarks(hdc, rc); #endif if (!INPAN) { DrawMapScale(Surface, rc, zoom.BigZoom()); // unused BigZoom DrawCompass(Surface, rc, DisplayAngle); } #ifdef DRAWDEBUG DrawDebug(hdc, rc); #endif }
// // TODO CHECK BUFFER SIZE, which is 100 (set in Buttons). // bool ExpandMacros(const TCHAR *In, TCHAR *OutBuffer, size_t Size){ TCHAR *a; LK_tcsncpy(OutBuffer, In, Size - 1); if (_tcsstr(OutBuffer, TEXT("$(")) == NULL) { return false; } short items=1; bool invalid = false; // Accelerator for entire label replacement- only one macro per label accepted a =_tcsstr(OutBuffer, TEXT("$(AC")); if (a != NULL) { TCHAR tbuf[20]; short i; i= (*(a+4)-'0')*10; i+= *(a+5)-'0'; LKASSERT(i>=0 && i<41); switch(i) { case 0: // LOCKMODE _tcscpy(OutBuffer,_T("")); // default is button invisible if (LockMode(0)) { // query availability if (LockMode(1)) // query status _tcscpy(OutBuffer,MsgToken(965)); // UNLOCK\nSCREEN else _tcscpy(OutBuffer,MsgToken(966)); // LOCK\nSCREEN if (!LockMode(3)) invalid=true; // button not usable } break; case 1: // Pan Supertoggle PanModeStatus mode=pan location=8 if ( MapWindow::mode.AnyPan() ) _stprintf(OutBuffer, _T("%s%s"),MsgToken(2004),MsgToken(491)); // OFF else _stprintf(OutBuffer, _T("%s%s"),MsgToken(2004),MsgToken(894)); // ON break; case 2: // Pan Supertoggle PanModeStatus mode=ScreenMode location=8 if ( MapWindow::mode.AnyPan() ) _stprintf(OutBuffer, _T("%s\n%s"),MsgToken(2082),MsgToken(491)); // OFF else _stprintf(OutBuffer, _T("%s\n%s"),MsgToken(2082),MsgToken(894)); // ON break; case 3: // DISABLED _tcscpy(OutBuffer,MsgToken(2023)); // Reserved invalid=true; break; case 4: // MacCreadyValue + 2078 _stprintf(tbuf,_T("%2.1lf"), iround(LIFTMODIFY*MACCREADY*10)/10.0); _stprintf(OutBuffer, _T("%s\n%s"), MsgToken(2078), tbuf); break; case 5: if (CALCULATED_INFO.AutoMacCready) { switch(AutoMcMode) { case amcFinalGlide: _stprintf(tbuf,_T("%s"), MsgToken(1681)); break; case amcAverageClimb: _stprintf(tbuf,_T("%s"), MsgToken(1682)); break; case amcEquivalent: _stprintf(tbuf,_T("%s"), MsgToken(1683)); break; case amcFinalAndClimb: if (CALCULATED_INFO.FinalGlide) _stprintf(tbuf,_T("%s"), MsgToken(1681)); else _stprintf(tbuf,_T("%s"), MsgToken(1682)); break; default: // LKTOKEN _@M1202_ "Auto" _stprintf(tbuf,_T("%s"), MsgToken(1202)); break; } } else { // LKTOKEN _@M1201_ "Man" _stprintf(tbuf,_T("%s"), MsgToken(1201)); } _stprintf(OutBuffer,_T("Mc %s\n%2.1lf"), tbuf,iround(LIFTMODIFY*MACCREADY*10)/10.0); break; case 6: // WaypointNext invalid = !ValidTaskPoint(ActiveTaskPoint+1); if (!ValidTaskPoint(ActiveTaskPoint+2)) _tcscpy(OutBuffer,MsgToken(801)); // Waypoint Finish else _tcscpy(OutBuffer,MsgToken(802)); // Waypoint Next break; case 7: // WaypointPrevious if (ActiveTaskPoint==1) { invalid = !ValidTaskPoint(ActiveTaskPoint-1); _tcscpy(OutBuffer,MsgToken(804)); // Waypoint Start } else if (EnableMultipleStartPoints) { invalid = !ValidTaskPoint(0); if (ActiveTaskPoint==0) _tcscpy(OutBuffer,_T("StartPnt\nCycle")); else _tcscpy(OutBuffer,MsgToken(803)); // Waypoint Previous } else { invalid = (ActiveTaskPoint<=0); _tcscpy(OutBuffer,MsgToken(803)); // Waypoint Previous } break; case 8: // RealTask check for Task reset if (! (ValidTaskPoint(ActiveTaskPoint) && ValidTaskPoint(1))) { invalid=true; } _tcscpy(OutBuffer,MsgToken(2019)); // Task reset break; case 9: // TerrainVisible for ChangeBack topology color if (CALCULATED_INFO.TerrainValid && IsMultimapTerrain() && !LKVarioBar) { invalid = true; } _tcscpy(OutBuffer,MsgToken(2037)); // Change topo back break; case 10: // TOGGLEHBAR HBARAVAILABLE for Toggle HBAR button if (!GPS_INFO.BaroAltitudeAvailable) { _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2045),MsgToken(1068)); // Nav by HBAR invalid=true; } else { if (EnableNavBaroAltitude) _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2045),MsgToken(1174)); // Nav by HGPS else _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2045),MsgToken(1068)); // Nav by HBAR } break; case 11: // SIM MENU SIMONLY if (SIMMODE) _tcscpy(OutBuffer,MsgToken(2074)); // SIM MENU else _tcscpy(OutBuffer,_T("")); break; case 12: // THIS MACRO IS AVAILABLE FOR USE break; case 13: if(UseTotalEnergy) { _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2115),MsgToken(894)); // TE ON } else { _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2115),MsgToken(491)); // TE OFF } break; case 14: if ( Shading ) _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2080),MsgToken(491)); // OFF else _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2080),MsgToken(894)); // ON break; case 15: if (EnableSoundModes) _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2055),MsgToken(491)); // OFF else _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2055),MsgToken(894)); // ON break; case 16: // ActiveMap no more used now Radio Button #ifdef RADIO_ACTIVE if (RadioPara.Enabled) { _stprintf(OutBuffer,_T("%s\n"),MsgToken(2306)); // TEXT invalid=false; } else { _stprintf(OutBuffer,_T("%s\n"),MsgToken(2306)); // TEXT invalid=true; } #else invalid=true; #endif break; case 17: // Order is: ALL ON, TEXT ONLY, GAUGES ONLY, ALL OFF if (!HaveGauges()) { if (!IsMultimapOverlaysText()) { _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2079),MsgToken(2234)); // TEXT } else { _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2079),MsgToken(491)); // OFF } break; } if (!IsMultimapOverlaysText()&&!IsMultimapOverlaysGauges()) { _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2079),MsgToken(899)); // ALL ON } else { if (IsMultimapOverlaysAll()) { _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2079),MsgToken(2234)); // TEXT } else { if (IsMultimapOverlaysText()) _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2079),MsgToken(2235)); // GAUGES else _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2079),MsgToken(898)); // ALL OFF } } break; case 18: if (Orbiter) _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2065),MsgToken(491)); // OFF else _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2065),MsgToken(894)); // ON if (!EnableThermalLocator) invalid = true; break; case 19: if (IsMultimapAirspace()) _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2029),MsgToken(491)); // OFF else _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2029),MsgToken(894)); // ON break; case 20: if (MapWindow::zoom.AutoZoom() ) _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2009),MsgToken(418)); else _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2009),MsgToken(897)); break; case 21: if (IsMultimapTopology()) _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2027),MsgToken(491)); // OFF else _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2027),MsgToken(894)); // ON break; case 22: if (IsMultimapTerrain()) _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2028),MsgToken(491)); // OFF else _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2028),MsgToken(894)); // ON break; case 23: if (MapSpaceMode!=MSM_MAP) invalid=true; if (MapWindow::mode.UserForcedMode() == MapWindow::Mode::MODE_FLY_CIRCLING) _stprintf(OutBuffer,_T("DspMode\n_%s_"),MsgToken(2031)); else _stprintf(OutBuffer,_T("DspMode\n%s"),MsgToken(2031)); break; case 24: if (MapSpaceMode!=MSM_MAP) invalid=true; if (MapWindow::mode.UserForcedMode() == MapWindow::Mode::MODE_FLY_CRUISE) _stprintf(OutBuffer,_T("DspMode\n_%s_"),MsgToken(2032)); else _stprintf(OutBuffer,_T("DspMode\n%s"),MsgToken(2032)); break; case 25: if (MapSpaceMode!=MSM_MAP) invalid=true; if (MapWindow::mode.UserForcedMode() == MapWindow::Mode::MODE_FLY_NONE) _stprintf(OutBuffer,_T("DspMode\n_%s_"),MsgToken(2034)); else _stprintf(OutBuffer,_T("DspMode\n%s"),MsgToken(2034)); break; case 26: if (MapSpaceMode!=MSM_MAP) invalid=true; if (MapWindow::mode.UserForcedMode() == MapWindow::Mode::MODE_FLY_FINAL_GLIDE) _stprintf(OutBuffer,_T("DspMode\n_%s_"),MsgToken(2033)); else _stprintf(OutBuffer,_T("DspMode\n%s"),MsgToken(2033)); break; case 27: // amcIsBoth if (CALCULATED_INFO.AutoMacCready && AutoMcMode==amcFinalAndClimb) _stprintf(OutBuffer,_T("Auto\n_%s_"),MsgToken(2117)); else _stprintf(OutBuffer,_T("Auto\n%s"),MsgToken(2117)); break; case 28: // amcIsFinal if (CALCULATED_INFO.AutoMacCready && AutoMcMode==amcFinalGlide) _stprintf(OutBuffer,_T("Auto\n_%s_"),MsgToken(2033)); else _stprintf(OutBuffer,_T("Auto\n%s"),MsgToken(2033)); break; case 29: // amcIsClimb if (CALCULATED_INFO.AutoMacCready && AutoMcMode==amcAverageClimb) _stprintf(OutBuffer,_T("Auto\n_%s_"),MsgToken(2075)); else _stprintf(OutBuffer,_T("Auto\n%s"),MsgToken(2075)); break; case 30: // amcIsEquiv if (CALCULATED_INFO.AutoMacCready && AutoMcMode==amcEquivalent) _stprintf(OutBuffer,_T("Auto\n_%s_"),MsgToken(2076)); else _stprintf(OutBuffer,_T("Auto\n%s"),MsgToken(2076)); break; case 31: // CheckManMc if (CALCULATED_INFO.AutoMacCready) _stprintf(OutBuffer,_T("Mc\n%s"),MsgToken(2077)); else _stprintf(OutBuffer,_T("Mc\n_%s_"),MsgToken(2077)); break; case 32: // AirspaceMode switch(AltitudeMode) { case 0: _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2029),MsgToken(184)); // Clip break; case 1: _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2029),MsgToken(897)); // Auto break; case 2: _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2029),MsgToken(139)); // Below break; case 3: _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2029),MsgToken(359)); // Inside break; case 4: _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2029),MsgToken(75)); // All Off break; case 5: default: _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2029),MsgToken(76)); // All On break; } break; case 33: // SnailTrailToggleName if (MapSpaceMode!=MSM_MAP) invalid=true; // Since we show the next choice, but the order is not respected in 5.0: // the new order is artificially off-short-long-full, as in the inputevents button management switch(TrailActive) { case 0: // off to short _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2035),MsgToken(612)); // Short break; case 1: // long to full _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2035),MsgToken(312)); // Full break; case 2: // short to long _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2035),MsgToken(410)); // Long break; case 3: // full to off default: _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2035),MsgToken(491)); // OFF break; } break; case 34: // MapLabelsToggleActionName switch(GetMultimap_Labels()) { case MAPLABELS_ALLON: _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2026),MsgToken(1203)); // WPTS break; case MAPLABELS_ONLYWPS: _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2026),MsgToken(1204)); // TOPO break; case MAPLABELS_ONLYTOPO: _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2026),MsgToken(898)); break; case MAPLABELS_ALLOFF: default: _stprintf(OutBuffer,_T("%s\n%s"),MsgToken(2026),MsgToken(899)); break; } break; case 35: // SIM PAN MODE REPOSITION, PANREPOS if (SIMMODE) _tcscpy(OutBuffer,MsgToken(2133)); // Position else _tcscpy(OutBuffer,_T("")); break; case 36: // // Order is: ALL ON, TASK ONLY, FAI ONLY, ALL OFF if (Flags_DrawTask&&Flags_DrawFAI) { _tcscpy(OutBuffer,MsgToken(2238)); // Draw Task } else { if (Flags_DrawTask&&!Flags_DrawFAI) { _tcscpy(OutBuffer,MsgToken(2239)); // Draw FAI } else { if (!Flags_DrawTask&&Flags_DrawFAI) { _tcscpy(OutBuffer,MsgToken(2240)); // NoDraw TaskFAI } else { _tcscpy(OutBuffer,MsgToken(2241)); // Draw TaskFAI } } } break; case 37: // if (SonarWarning) _tcscpy(OutBuffer,MsgToken(2243)); // Sonar OFF else _tcscpy(OutBuffer,MsgToken(2242)); // Sonar ON break; case 38: // if (MapSpaceMode!=MSM_MAP) invalid=true; _tcscpy(OutBuffer,MsgToken(2081)); // Set Map break; case 39: if (! (ValidTaskPoint(ActiveTaskPoint) && ValidTaskPoint(1))) { invalid=true; } _tcscpy(OutBuffer,MsgToken(1850)); // Task reverse break; case 40: if(IsKobo()) { #ifdef KOBO if(IsKoboWifiOn()) { _tcscpy(OutBuffer,_T("Wifi\nOff")); } else { _tcscpy(OutBuffer,_T("Wifi\nOn")); } #endif } else { _tcscpy(OutBuffer,_T("")); } break; default: _stprintf(OutBuffer, _T("INVALID\n%d"),i); break; } goto label_ret; } // ACcelerator // No accelerator? First check if we have a second macro embedded in string a =_tcsstr(OutBuffer, TEXT("&(")); if (a != NULL) { *a=_T('$'); items=2; } // Then go for one-by-one match search, slow if (_tcsstr(OutBuffer, TEXT("$(AdvanceArmed)"))) { switch (AutoAdvance) { case 0: ReplaceInString(OutBuffer, TEXT("$(AdvanceArmed)"), MsgToken(892), Size); // (manual) invalid = true; break; case 1: ReplaceInString(OutBuffer, TEXT("$(AdvanceArmed)"), MsgToken(893), Size); // (auto) invalid = true; break; case 2: if (ActiveTaskPoint>0) { if (ValidTaskPoint(ActiveTaskPoint+1)) { CondReplaceInString(AdvanceArmed, OutBuffer, TEXT("$(AdvanceArmed)"), MsgToken(161), // Cancel MsgToken(678), Size); // TURN } else { ReplaceInString(OutBuffer, TEXT("$(AdvanceArmed)"), MsgToken(8), Size); // (finish) invalid = true; } } else { CondReplaceInString(AdvanceArmed, OutBuffer, TEXT("$(AdvanceArmed)"), MsgToken(161), // Cancel MsgToken(571), Size); // START } break; case 3: if (ActiveTaskPoint==0) { CondReplaceInString(AdvanceArmed, OutBuffer, TEXT("$(AdvanceArmed)"), MsgToken(161), // Cancel MsgToken(571), Size); // START } else if (ActiveTaskPoint==1) { CondReplaceInString(AdvanceArmed, OutBuffer, TEXT("$(AdvanceArmed)"), MsgToken(161), // Cancel MsgToken(539), Size); // RESTART } else { ReplaceInString(OutBuffer, TEXT("$(AdvanceArmed)"), MsgToken(893), Size); // (auto) invalid = true; } break; // TODO bug: no need to arm finish case 4: if (ActiveTaskPoint>0) { if (ValidTaskPoint(ActiveTaskPoint+1)) { CondReplaceInString(AdvanceArmed, OutBuffer, TEXT("$(AdvanceArmed)"), MsgToken(161), // Cancel MsgToken(678), Size); // TURN } else { ReplaceInString(OutBuffer, TEXT("$(AdvanceArmed)"), MsgToken(8), Size); // (finish) invalid = true; } } else { ReplaceInString(OutBuffer, TEXT("$(AdvanceArmed)"), MsgToken(893), Size); // (auto) invalid = true; } break; default: break; } if (--items<=0) goto label_ret; // 100517 } if (_tcsstr(OutBuffer, TEXT("$(CheckFlying)"))) { if (!CALCULATED_INFO.Flying) { invalid = true; } ReplaceInString(OutBuffer, TEXT("$(CheckFlying)"), TEXT(""), Size); if (--items<=0) goto label_ret; } if (_tcsstr(OutBuffer, TEXT("$(NotInReplay)"))) { if (ReplayLogger::IsEnabled()) { invalid = true; } ReplaceInString(OutBuffer, TEXT("$(NotInReplay)"), TEXT(""), Size); if (--items<=0) goto label_ret; // 100517 } if (_tcsstr(OutBuffer, TEXT("$(CheckWaypointFile)"))) { if (!ValidWayPoint(NUMRESWP)) { invalid = true; } ReplaceInString(OutBuffer, TEXT("$(CheckWaypointFile)"), TEXT(""), Size); if (--items<=0) goto label_ret; // 100517 } if (_tcsstr(OutBuffer, TEXT("$(CheckSettingsLockout)"))) { if (LockSettingsInFlight && CALCULATED_INFO.Flying) { invalid = true; } ReplaceInString(OutBuffer, TEXT("$(CheckSettingsLockout)"), TEXT(""), Size); if (--items<=0) goto label_ret; // 100517 } if (_tcsstr(OutBuffer, TEXT("$(CheckTask)"))) { if (!ValidTaskPoint(ActiveTaskPoint)) { invalid = true; } ReplaceInString(OutBuffer, TEXT("$(CheckTask)"), TEXT(""), Size); if (--items<=0) goto label_ret; // 100517 } if (_tcsstr(OutBuffer, TEXT("$(CheckAirspace)"))) { if (!CAirspaceManager::Instance().ValidAirspaces()) { invalid = true; } ReplaceInString(OutBuffer, TEXT("$(CheckAirspace)"), TEXT(""), Size); if (--items<=0) goto label_ret; // 100517 } if (_tcsstr(OutBuffer, TEXT("$(CheckFLARM)"))) { if (!GPS_INFO.FLARM_Available) { invalid = true; } ReplaceInString(OutBuffer, TEXT("$(CheckFLARM)"), TEXT(""), Size); if (--items<=0) goto label_ret; // 100517 } // If it is not SIM mode, it is invalid if (_tcsstr(OutBuffer, TEXT("$(OnlyInSim)"))) { if (!SIMMODE) invalid = true; ReplaceInString(OutBuffer, TEXT("$(OnlyInSim)"), TEXT(""), Size); if (--items<=0) goto label_ret; // 100517 } if (_tcsstr(OutBuffer, TEXT("$(OnlyInFly)"))) { #if TESTBENCH invalid=false; #else if (SIMMODE) invalid = true; #endif ReplaceInString(OutBuffer, TEXT("$(OnlyInFly)"), TEXT(""), Size); if (--items<=0) goto label_ret; // 100517 } if (_tcsstr(OutBuffer, TEXT("$(WCSpeed)"))) { TCHAR tbuf[10]; _stprintf(tbuf,_T("%.0f%s"),SPEEDMODIFY*WindCalcSpeed,Units::GetUnitName(Units::GetUserHorizontalSpeedUnit()) ); ReplaceInString(OutBuffer, TEXT("$(WCSpeed)"), tbuf, Size); if (--items<=0) goto label_ret; // 100517 } if (_tcsstr(OutBuffer, TEXT("$(GS"))) { TCHAR tbuf[10]; _stprintf(tbuf,_T("%.0f%s"),SPEEDMODIFY*GPS_INFO.Speed,Units::GetUnitName(Units::GetUserHorizontalSpeedUnit()) ); ReplaceInString(OutBuffer, TEXT("$(GS)"), tbuf, Size); if (--items<=0) goto label_ret; } if (_tcsstr(OutBuffer, TEXT("$(HGPS"))) { TCHAR tbuf[10]; _stprintf(tbuf,_T("%.0f%s"),ALTITUDEMODIFY*GPS_INFO.Altitude,Units::GetUnitName(Units::GetUserAltitudeUnit()) ); ReplaceInString(OutBuffer, TEXT("$(HGPS)"), tbuf, Size); if (--items<=0) goto label_ret; } if (_tcsstr(OutBuffer, TEXT("$(TURN"))) { TCHAR tbuf[10]; _stprintf(tbuf,_T("%.0f"),SimTurn); ReplaceInString(OutBuffer, TEXT("$(TURN)"), tbuf, Size); if (--items<=0) goto label_ret; } if (_tcsstr(OutBuffer, TEXT("$(NETTO"))) { TCHAR tbuf[10]; _stprintf(tbuf,_T("%.1f"),SimNettoVario); ReplaceInString(OutBuffer, TEXT("$(NETTO)"), tbuf, Size); if (--items<=0) goto label_ret; } if (_tcsstr(OutBuffer, TEXT("$(LoggerActive)"))) { CondReplaceInString(LoggerActive, OutBuffer, TEXT("$(LoggerActive)"), MsgToken(670), MsgToken(657), Size); // Stop Start if (--items<=0) goto label_ret; // 100517 } if (_tcsstr(OutBuffer, TEXT("$(NoSmart)"))) { if (DisplayOrientation == NORTHSMART) invalid = true; ReplaceInString(OutBuffer, TEXT("$(NoSmart)"), TEXT(""), Size); if (--items<=0) goto label_ret; // 100517 } if (_tcsstr(OutBuffer, TEXT("$(FinalForceToggleActionName)"))) { CondReplaceInString(ForceFinalGlide, OutBuffer, TEXT("$(FinalForceToggleActionName)"), MsgToken(896), // Unforce MsgToken(895), // Force Size); if (AutoForceFinalGlide) { invalid = true; } if (--items<=0) goto label_ret; // 100517 } if (_tcsstr(OutBuffer, TEXT("$(PCONLY)"))) { if(IsEmbedded()) { _tcscpy(OutBuffer,_T("")); invalid = true; } else { ReplaceInString(OutBuffer, TEXT("$(PCONLY)"), TEXT(""), Size); } if (--items<=0) goto label_ret; } if (_tcsstr(OutBuffer, TEXT("$(NOTPC)"))) { if(IsEmbedded()) { ReplaceInString(OutBuffer, TEXT("$(NOTPC)"), TEXT(""), Size); } else { _tcscpy(OutBuffer,_T("")); invalid = true; } if (--items<=0) goto label_ret; } if (_tcsstr(OutBuffer, TEXT("$(ONLYMAP)"))) { if (MapSpaceMode!=MSM_MAP) invalid=true; ReplaceInString(OutBuffer, TEXT("$(ONLYMAP)"), TEXT(""), Size); if (--items<=0) goto label_ret; } if (_tcsstr(OutBuffer, TEXT("$(SCREENROTATE)"))) { if(CanRotateScreen()) { ReplaceInString(OutBuffer, TEXT("$(SCREENROTATE)"), TEXT(""), Size); } else { _tcscpy(OutBuffer,_T("")); invalid = true; } if (--items<=0) goto label_ret; } extern unsigned int CustomKeyLabel[]; // We dont replace macro, we do replace the entire label a =_tcsstr(OutBuffer, TEXT("$(MM")); if (a != NULL) { short i; i= *(a+4)-48; LKASSERT(i>=0 && i<11); // get the label for the custom menu item here // Decide if invalid=true or if no label at all, setting Replace to empty string unsigned int ckeymode; // test mode only switch(i) { case 1: ckeymode=CustomMenu1; break; case 2: ckeymode=CustomMenu2; break; case 3: ckeymode=CustomMenu3; break; case 4: ckeymode=CustomMenu4; break; case 5: ckeymode=CustomMenu5; break; case 6: ckeymode=CustomMenu6; break; case 7: ckeymode=CustomMenu7; break; case 8: ckeymode=CustomMenu8; break; case 9: ckeymode=CustomMenu9; break; case 0: ckeymode=CustomMenu10; break; default: ckeymode=0; break; } if (ckeymode==0 || ckeymode>=ckTOP) { invalid=true; // non selectable // _stprintf(OutBuffer,_T("Key\n%d"),i); _tcscpy(OutBuffer,_T("")); // make it invisible } else { _tcscpy(OutBuffer,MsgToken( CustomKeyLabel[ckeymode] )); } } // MM label_ret: return invalid; }
void MapWindow::DrawGlideThroughTerrain(LKSurface& Surface, const RECT& rc) { LKPen hpOld; //double h,dh; TCHAR hbuf[10]; static bool doinit=true; static TextInBoxMode_t tmode = {0}; bool wrotevalue=false; if (doinit) { memset((void*)&tmode, 0, sizeof(TextInBoxMode_t)); tmode.Border=1; doinit=false; } #ifdef GTL2 bool ValidTP = ValidTaskPoint(ActiveWayPoint); // draw glide terrain line around next WP bool DrawGTL2 = ValidTP && (FinalGlideTerrain > 2); static bool LastDrewGTL2 = false; if (DrawGTL2) { int wp_index = (DoOptimizeRoute() || ACTIVE_WP_IS_AAT_AREA) ? RESWP_OPTIMIZED : TASKINDEX; double alt_arriv = WayPointCalc[wp_index].AltArriv[AltArrivMode]; // Calculate arrival altitude at the next waypoint relative to // the "terrain height" safety setting. if (CheckSafetyAltitudeApplies(wp_index)) alt_arriv += SAFETYALTITUDEARRIVAL/10; // AGL alt_arriv -= SAFETYALTITUDETERRAIN/10; // rel. to "terrain height" if (alt_arriv <= 0) DrawGTL2 = false; } if (LastDrewGTL2 != DrawGTL2) { LastDrewGTL2 = DrawGTL2; if (!DrawGTL2) ClearGTL2(); // clear next-WP glide terrain line } #endif hpOld = Surface.SelectObject(hpTerrainLineBg); #ifdef GTL2 // Draw the wide, solid part of the glide terrain line. #else // draw a dashed perimetral line first #endif Surface.Polyline(Groundline,NUMTERRAINSWEEPS+1, rc); // draw perimeter if selected and during a flight #ifdef GTL2 if (((FinalGlideTerrain == 1) || (FinalGlideTerrain == 3)) || ((!IsMultimapTerrain() || !DerivedDrawInfo.Flying) && FinalGlideTerrain)) { #else if ((FinalGlideTerrain==1) || ((!IsMultimapTerrain() || !DerivedDrawInfo.Flying) && (FinalGlideTerrain==2))) { #endif Surface.SelectObject(hpTerrainLine); Surface.Polyline(Groundline,NUMTERRAINSWEEPS+1, rc); } #ifdef GTL2 // draw glide terrain line around next waypoint if (DrawGTL2) { // Draw a solid white line. Surface.SelectObject(LKPen_White_N2); Surface.Polyline(Groundline2, NUMTERRAINSWEEPS+1, rc); // Draw a dashed red line. Surface.DrawDashPoly(NIBLSCALE(2), RGB_RED, Groundline2, NUMTERRAINSWEEPS+1, rc); } #endif // draw red cross obstacles only if destination looks reachable! // only if using OVT_TASK of course! #ifdef GTL2 if ((OvertargetMode == OVT_TASK) && DerivedDrawInfo.Flying && ValidTP) #else if ( (OvertargetMode==OVT_TASK) && DerivedDrawInfo.Flying && ValidTaskPoint(ActiveWayPoint)) #endif if (WayPointCalc[TASKINDEX].AltArriv[AltArrivMode] >0) { POINT sc; // If calculations detected an obstacle... if ((DerivedDrawInfo.TerrainWarningLatitude != 0.0) &&(DerivedDrawInfo.TerrainWarningLongitude != 0.0)) { // only if valid position, and visible if (DerivedDrawInfo.FarObstacle_Lon >0) if (PointVisible(DerivedDrawInfo.FarObstacle_Lon, DerivedDrawInfo.FarObstacle_Lat)) { LatLon2Screen(DerivedDrawInfo.FarObstacle_Lon, DerivedDrawInfo.FarObstacle_Lat, sc); DrawBitmapIn(Surface, sc, hTerrainWarning,true); if (DerivedDrawInfo.FarObstacle_AltArriv <=-50 || DerivedDrawInfo.FarObstacle_Dist<5000 ) { _stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*DerivedDrawInfo.FarObstacle_AltArriv); TextInBox(Surface,&rc,hbuf,sc.x+NIBLSCALE(15), sc.y, 0, &tmode,false); wrotevalue=true; } } // visible far obstacle if (PointVisible(DerivedDrawInfo.TerrainWarningLongitude, DerivedDrawInfo.TerrainWarningLatitude)) { LatLon2Screen(DerivedDrawInfo.TerrainWarningLongitude, DerivedDrawInfo.TerrainWarningLatitude, sc); DrawBitmapIn(Surface, sc, hTerrainWarning,true); #if 0 // 091203 add obstacle altitude on moving map h = max(0,RasterTerrain::GetTerrainHeight(DerivedDrawInfo.TerrainWarningLatitude, DerivedDrawInfo.TerrainWarningLongitude)); if (h==TERRAIN_INVALID) h=0; //@ 101027 FIX but unused dh = CALCULATED_INFO.NavAltitude - h - (SAFETYALTITUDETERRAIN/10); _stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*dh); TextInBox(hDC,&rc,hbuf,sc.x+NIBLSCALE(10), sc.y, 0, tmode,false); #else // if far obstacle was painted with value... if (wrotevalue) { // if it is not too near the nearest.. if ( (fabs(DerivedDrawInfo.FarObstacle_Lon - DerivedDrawInfo.TerrainWarningLongitude) >0.02) && (fabs(DerivedDrawInfo.FarObstacle_Lat - DerivedDrawInfo.TerrainWarningLatitude) >0.02)) { // and it the arrival altitude is actually negative (rounding terrain errors?) if ( DerivedDrawInfo.ObstacleAltArriv <=-50) // and there is a significant difference in the numbers, then paint value also for nearest if ( fabs(DerivedDrawInfo.ObstacleAltArriv - DerivedDrawInfo.FarObstacle_AltArriv) >100 ) { _stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*DerivedDrawInfo.ObstacleAltArriv); TextInBox(Surface,&rc,hbuf,sc.x+NIBLSCALE(15), sc.y, 0, &tmode,false); } } } else { // else paint value only if meaningful or very close to us // -1 to 10m become -1 for rounding errors if ( (DerivedDrawInfo.ObstacleAltArriv >-1) && (DerivedDrawInfo.ObstacleAltArriv <10)) DerivedDrawInfo.ObstacleAltArriv=-1; if (DerivedDrawInfo.ObstacleAltArriv <=-50 || ((DerivedDrawInfo.ObstacleAltArriv<0) && (DerivedDrawInfo.ObstacleDistance<5000)) ) { _stprintf(hbuf,_T(" %.0f"),ALTITUDEMODIFY*DerivedDrawInfo.ObstacleAltArriv); TextInBox(Surface,&rc,hbuf,sc.x+NIBLSCALE(15), sc.y, 0, &tmode,false); } } #endif } // visible nearest obstacle } // obstacles detected } // within glide range Surface.SelectObject(hpOld); }
void MapWindow::RenderMapWindowBg(HDC hdc, const RECT rc, const POINT &Orig, const POINT &Orig_Aircraft) { // Calculations are taking time and slow down painting of map, beware #define MULTICALC_MINROBIN 5 // minimum split #define MULTICALC_MAXROBIN 20 // max split static short multicalc_slot=0;// -1 (which becomes immediately 0) will force full loading on startup, but this is not good // because currently we are not waiting for ProgramStarted=3 // and the first scan is made while still initializing other things // TODO assign numslots with a function, based also on available CPU time short numslots=1; #if NEWSMARTZOOM static double quickdrawscale=0.0; static double delta_drawscale=1.0; #endif #if 0 extern void TestChangeRect(); TestChangeRect(); #endif if ((MapWindow::AlphaBlendSupported() && BarOpacity<100) || mode.AnyPan()) { MapWindow::ChangeDrawRect(MapRect); } else { RECT newRect={0,0,ScreenSizeX,ScreenSizeY-BottomSize}; MapWindow::ChangeDrawRect(newRect); } if (QUICKDRAW) { goto _skip_calcs; } if (NumberOfWayPoints>200) { numslots=NumberOfWayPoints/400; // keep numslots optimal if (numslots<MULTICALC_MINROBIN) numslots=MULTICALC_MINROBIN; // seconds for full scan, as this is executed at 1Hz if (numslots>MULTICALC_MAXROBIN) numslots=MULTICALC_MAXROBIN; // When waypointnumber has changed, we wont be using an exceeded multicalc_slot, which would crash the sw // In this case, we shall probably continue for the first round to calculate without going from the beginning // but this is not a problem, we are round-robin all the time here. if (++multicalc_slot>numslots) multicalc_slot=1; } else { multicalc_slot=0; // forcing full scan } // Here we calculate arrival altitude, GD etc for map waypoints. Splitting with multicalc will result in delayed // updating of visible landables, for example. The nearest pages do this separately, with their own sorting. // Basically we assume -like for nearest- that values will not change that much in the multicalc split time. // Target and tasks are recalculated in real time in any case. Nearest too. LKCalculateWaypointReachable(multicalc_slot, numslots); _skip_calcs: CalculateScreenPositionsAirspace(rc); CalculateScreenPositionsThermalSources(); // Make the glide amoeba out of the latlon points, converting them to screen // (This function is updated for supporting multimaps ) CalculateScreenPositionsGroundline(); if (PGZoomTrigger) { if(!mode.Is(Mode::MODE_PANORAMA)) { mode.Special(Mode::MODE_SPECIAL_PANORAMA, true); LastZoomTrigger=DrawInfo.Time; Message::Lock(); Message::AddMessage(1000, 3, gettext(TEXT("_@M872_"))); // LANDSCAPE ZOOM FOR 20s Message::Unlock(); #ifndef DISABLEAUDIO if (EnableSoundModes) LKSound(TEXT("LK_TONEUP.WAV")); #endif } else { // previously called, see if time has passed if ( DrawInfo.Time > (LastZoomTrigger + 20.0)) { // time has passed, lets go back LastZoomTrigger=0; // just for safety mode.Special(Mode::MODE_SPECIAL_PANORAMA, false); PGZoomTrigger=false; Message::Lock(); Message::AddMessage(1500, 3, gettext(TEXT("_@M873_"))); // BACK TO NORMAL ZOOM Message::Unlock(); #ifndef DISABLEAUDIO if (EnableSoundModes) LKSound(TEXT("LK_TONEDOWN.WAV")); #endif } } } // // "Checkpoint Charlie" // This is were we process stuff for anything else but main map. // We let the calculations run also for MapSpace modes. // But for multimaps, we can also draw some more stuff.. // We are also sent back here from next code, when we detect that // the MapSpace mode has changed from MAP to something else while we // were rendering. // QuickRedraw: // if (DONTDRAWTHEMAP) { DrawMapSpace(hdc, rc); // Is this a "shared map" environment? if (IsMultiMapShared()) { // Shared map, of course not MSN_MAP, since dontdrawthemap was checked // if (IsMultimapOverlaysText()) { DrawLook8000(hdc,rc); } if (IsMultimapOverlaysGauges()) { if (LKVarioBar) LKDrawVario(hdc,rc); if ((mode.Is(Mode::MODE_CIRCLING)) ) if (ThermalBar) DrawThermalBand(hdcDrawWindow, rc); DrawFinalGlide(hdcDrawWindow,rc); } } else { // Not in map painting environment // ex. nearest pages, but also MAPRADAR.. } // DrawBottomBar(hdc,rc); #ifdef CPUSTATS DrawCpuStats(hdc,rc); #endif #ifdef DRAWDEBUG DrawDebug(hdc,rc); #endif // no need to do SelectObject as at the bottom of function return; } // When no terrain is painted, set a background0 // Remember that in this case we have plenty of cpu time to spend for best result if (!IsMultimapTerrain() || !DerivedDrawInfo.TerrainValid || !RasterTerrain::isTerrainLoaded() ) { // display border and fill background.. SelectObject(hdc, hInvBackgroundBrush[BgMapColor]); SelectObject(hdc, GetStockObject(WHITE_PEN)); Rectangle(hdc,rc.left,rc.top,rc.right,rc.bottom); // We force LK painting black values on screen depending on the background color in use // TODO make it an array once settled // blackscreen would force everything to be painted white, instead LKTextBlack=BgMapColorTextBlack[BgMapColor]; if (BgMapColor>6 ) BlackScreen=true; else BlackScreen=false; } else { LKTextBlack=false; BlackScreen=false; } #if NEWSMARTZOOM // Copy the old background map with no overlays if (ONSMARTZOOM) { if (quickdrawscale>0) { delta_drawscale=zoom.DrawScale() / quickdrawscale; } // StartupStore(_T("... QuickDrawScale=%.2f new zoom=%.2f delta=%.2f\n"),quickdrawscale,zoom.DrawScale(),delta_drawscale); int dx=MapRect.right-MapRect.left; int dy=MapRect.bottom-MapRect.top; // notice: zoom in is always ok.. but zoom out starting from high zoom levels will make the picture // very small and unusable. We can consider to zoom out in fast zoom normally, in such cases? // // Notice 2: the delta is not yet working correctly // if (delta_drawscale>1.0) { // zoom in StretchBlt(hdcDrawWindow, 0,0, dx,dy, hdcQuickDrawWindow, (int)((dx/2) - (dx / delta_drawscale)/2), (int)((dy/2) - (dy / delta_drawscale)/2), (int)(dx / delta_drawscale), (int)(dy / delta_drawscale), SRCCOPY); } else { // zoom out StretchBlt(hdcDrawWindow, (int)((dx/2) - (dx * delta_drawscale)/2), (int)((dy/2) - (dy * delta_drawscale)/2), (int)(dx * delta_drawscale), (int)(dy * delta_drawscale), hdcQuickDrawWindow, 0,0, dx,dy, SRCCOPY); } } #endif // Logic of DONTDRAWTHEMAP is the following: // We are rendering the screen page here. If we are here, we passed Checkpoint Charlie. // So we were, at charlie, in MSM_MAP: preparing the main map stuff. // If we detect that MapSpace has CHANGED while we were doing our job here, // it means that the user has clicked meanwhile. He desires another page, so let's // reset our intentions and go back to beginning, or nearby.. // We have a new job to do, for another MapSpace, no more MAP. if (DONTDRAWTHEMAP) { goto QuickRedraw; } #if NEWSMARTZOOM if ( OFFSMARTZOOM ) { #endif bool terrainpainted=false; if ((IsMultimapTerrain() && (DerivedDrawInfo.TerrainValid) && RasterTerrain::isTerrainLoaded()) ) { // sunelevation is never used, it is still a todo in Terrain double sunelevation = 40.0; double sunazimuth=GetAzimuth(); LockTerrainDataGraphics(); if (DONTDRAWTHEMAP) { // 100318 UnlockTerrainDataGraphics(); goto QuickRedraw; } DrawTerrain(hdc, DrawRect, sunazimuth, sunelevation); terrainpainted=true; if (DONTDRAWTHEMAP) { UnlockTerrainDataGraphics(); goto QuickRedraw; } if (!QUICKDRAW) { // SHADED terrain unreachable, aka glide amoeba. This is not the outlined perimeter! #ifdef GTL2 if (((FinalGlideTerrain == 2) || (FinalGlideTerrain == 4)) && DerivedDrawInfo.TerrainValid) { #else if ((FinalGlideTerrain==2) && DerivedDrawInfo.TerrainValid) { #endif DrawTerrainAbove(hdc, DrawRect); } } UnlockTerrainDataGraphics(); } #if NEWSMARTZOOM } #endif // // REMINDER: WE ARE IN MAIN MAP HERE: MSM_MAP ONLY, OR PANNING MODE! // MAPSPACEMODE CAN STILL CHANGE, DUE TO USER INPUT. BUT WE GOT HERE IN // EITHER PAN OR MSM_MAP. // if (DONTDRAWTHEMAP) { goto QuickRedraw; } if (IsMultimapTopology()) { DrawTopology(hdc, DrawRect); } else { // If no topology wanted, but terrain painted, we paint only water stuff if (terrainpainted) DrawTopology(hdc, DrawRect,true); } #if 0 StartupStore(_T("... Experimental1=%.0f\n"),Experimental1); StartupStore(_T("... Experimental2=%.0f\n"),Experimental2); Experimental1=0.0; Experimental2=0.0; #endif // Topology labels are printed first, using OLD wps positions from previous run! // Reset for topology labels decluttering engine occurs also in another place here! ResetLabelDeclutter(); if (Flags_DrawTask && ValidTaskPoint(ActiveWayPoint) && ValidTaskPoint(1)) { DrawTaskAAT(hdc, DrawRect); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } if (IsMultimapAirspace()) { if ( (GetAirSpaceFillType() == asp_fill_ablend_full) || (GetAirSpaceFillType() == asp_fill_ablend_borders) ) DrawTptAirSpace(hdc, rc); else DrawAirSpace(hdc, rc); // full screen, to hide clipping effect on low border } if (DONTDRAWTHEMAP) { goto QuickRedraw; } // In QUICKDRAW dont draw trail, thermals, glide terrain if (QUICKDRAW) goto _skip_stuff; if(TrailActive) { // NEED REWRITING LKDrawTrail(hdc, Orig_Aircraft, DrawRect); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } DrawThermalEstimate(hdc, DrawRect); if (OvertargetMode==OVT_THER) DrawThermalEstimateMultitarget(hdc, DrawRect); // draw red cross on glide through terrain marker if (FinalGlideTerrain && DerivedDrawInfo.TerrainValid) { DrawGlideThroughTerrain(hdc, DrawRect); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } _skip_stuff: if (IsMultimapAirspace() && AirspaceWarningMapLabels) { DrawAirspaceLabels(hdc, DrawRect, Orig_Aircraft); if (DONTDRAWTHEMAP) { // 100319 goto QuickRedraw; } } if (IsMultimapWaypoints()) { DrawWaypointsNew(hdc,DrawRect); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } if (Flags_DrawTask && ValidTaskPoint(ActiveWayPoint) && ValidTaskPoint(1)) { DrawTask(hdc, DrawRect, Orig_Aircraft); } // FAI optimizer does not depend on tasks, being based on trace if (Flags_DrawFAI) DrawFAIOptimizer(hdc, DrawRect, Orig_Aircraft); // In QUICKDRAW do not paint other useless stuff if (QUICKDRAW) { if (extGPSCONNECT) DrawBearing(hdc, DrawRect); goto _skip_2; } // --------------------------------------------------- DrawTeammate(hdc, rc); if (extGPSCONNECT) { DrawBestCruiseTrack(hdc, Orig_Aircraft); DrawBearing(hdc, DrawRect); } // draw wind vector at aircraft if (NOTANYPAN) { DrawWindAtAircraft2(hdc, Orig_Aircraft, DrawRect); } else if (mode.Is(Mode::MODE_TARGET_PAN)) { DrawWindAtAircraft2(hdc, Orig, rc); } #if NEWSMARTZOOM // Save the current rendered map before painting overlays if ( OFFSMARTZOOM ) { quickdrawscale=zoom.DrawScale(); BitBlt(hdcQuickDrawWindow, 0, 0, MapRect.right-MapRect.left, MapRect.bottom-MapRect.top, hdcDrawWindow, 0, 0, SRCCOPY); } #endif // VisualGlide drawn BEFORE lk8000 overlays if (NOTANYPAN && (VisualGlide > 0)) { DrawGlideCircle(hdc, Orig, rc); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } // Draw traffic and other specifix LK gauges LKDrawFLARMTraffic(hdc, DrawRect, Orig_Aircraft); // --------------------------------------------------- _skip_2: if (NOTANYPAN) { // REMINDER TODO let it be configurable for not circling also, as before if ((mode.Is(Mode::MODE_CIRCLING)) ) if (ThermalBar) DrawThermalBand(hdcDrawWindow, rc); // 091122 if (IsMultimapOverlaysText()) DrawLook8000(hdc,rc); DrawBottomBar(hdc,rc); } if (DONTDRAWTHEMAP) { goto QuickRedraw; } if (IsMultimapOverlaysGauges() && (LKVarioBar && NOTANYPAN)) LKDrawVario(hdc,rc); // Draw glider or paraglider if (extGPSCONNECT) { DrawAircraft(hdc, Orig_Aircraft); } if (NOTANYPAN && !QUICKDRAW) { if (TrackBar) DrawHeading(hdc, Orig, DrawRect); } #if USETOPOMARKS // marks on top... DrawMarks(hdc, rc); #endif if (ISGAAIRCRAFT && IsMultimapOverlaysGauges() && NOTANYPAN) DrawHSI(hdc,Orig,DrawRect); if (!INPAN) { DrawMapScale(hdcDrawWindow,rc, zoom.BigZoom()); // unused BigZoom DrawCompass(hdcDrawWindow, rc, DisplayAngle); } if (IsMultimapOverlaysGauges() && NOTANYPAN) DrawFinalGlide(hdcDrawWindow,rc); #ifdef CPUSTATS DrawCpuStats(hdc,rc); #endif #ifdef DRAWDEBUG DrawDebug(hdc,rc); #endif }
void MapWindow::LKDrawMultimap_Test(LKSurface& Surface, const RECT& rc) { if (DoInit[MDI_MAPTEST]) { // init statics here and then clear init to false DoInit[MDI_MAPTEST]=false; } // // X,Y coordinates of last clicked point on screen // These coordinates are related to any point clicked, even for a page flip, for bottom bar etc. // In some cases, you will read old coordinates because for example after clicking in the center of // bottom bar, the page changed out of multimap and entered nearest pages. // int X=startScreen.x; int Y=startScreen.y; // // Duration of key is inside long VKtime, in milliseconds. // // // Draw a boxed terrain/topology example // -------------------------------------- // RECT rct=rc; // desired area is 400x180, topleft is (20,30) rct.top=20; rct.bottom=rct.top+180; rct.left=30; rct.right=rct.left+400; MapWindow::ChangeDrawRect(rct); // set new area for terrain and topology PanLatitude = DrawInfo.Latitude; PanLongitude = DrawInfo.Longitude; // Current position is in center map POINT Orig = { (rct.right-rct.left)/2,(rct.bottom-rct.top)/2}; POINT Orig_Aircraft= {0,0}; //zoom.ModifyMapScale(); //zoom.UpdateMapScale(); const ScreenProjection _Proj = CalculateScreenPositions( Orig, rct, &Orig_Aircraft); CalculateScreenPositionsAirspace(rct, _Proj); double sunelevation = 40.0; double sunazimuth=GetAzimuth(); if (IsMultimapTerrain() && DerivedDrawInfo.TerrainValid) { LockTerrainDataGraphics(); DrawTerrain(Surface, rct, _Proj, sunazimuth, sunelevation); UnlockTerrainDataGraphics(); } ResetLabelDeclutter(); // This is needed to reset at each run the declutter, for topology and waypoints! // SaturateLabelDeclutter(); // Use this to force no labels be printed, from now on. DrawTopology(Surface, rct, _Proj); DrawAirSpace(Surface, rct, _Proj); // ResetLabelDeclutter(); // If you saturated labels for topology, now you can reset the declutter to allow // printing only waypoints, DrawWaypointsNew(Surface,rct); const auto oldpen = Surface.SelectObject(LKPen_White_N1); const auto oldbrush = Surface.SelectObject(LKBrush_LightGrey); LKWriteBoxedText(Surface, rct, _T("MULTIMAP PAGE EXAMPLE"), 1, 1, WTALIGN_LEFT, RGB_BLACK, RGB_WHITE); TCHAR ttext[100]; switch(LKevent) { // // USABLE EVENTS // case LKEVENT_NEWRUN: // CALLED ON ENTRY: when we select this page coming from another mapspace _tcscpy(ttext,_T("Event = NEW RUN")); break; case LKEVENT_UP: // click on upper part of screen, excluding center _tcscpy(ttext,_T("Event = UP")); break; case LKEVENT_DOWN: // click on lower part of screen, excluding center _tcscpy(ttext,_T("Event = DOWN")); break; case LKEVENT_LONGCLICK: _stprintf(ttext,_T("Event = LONG CLICK")); break; case LKEVENT_PAGEUP: _tcscpy(ttext,_T("Event = PAGE UP")); break; case LKEVENT_PAGEDOWN: _tcscpy(ttext,_T("Event = PAGE DOWN")); break; case LKEVENT_TOPLEFT: _tcscpy(ttext,_T("Event = TOP LEFT")); break; case LKEVENT_TOPRIGHT: _tcscpy(ttext,_T("Event = TOP RIGHT")); break; case LKEVENT_SHORTCLICK: _tcscpy(ttext,_T("Event = SHORT CLICK")); break; // // THESE EVENTS ARE NOT AVAILABLE IN MULTIMAPS! // case LKEVENT_ENTER: // click longer on center, like to confirm a selection _tcscpy(ttext,_T("Event = ENTER")); break; case LKEVENT_NEWPAGE: // swipe gesture up/down produces NEW PAGE in this case _tcscpy(ttext,_T("Event = NEW PAGE")); break; case LKEVENT_NONE: // Normally no event. _tcscpy(ttext,_T("Event = NONE")); break; // default: // THIS SHOULD NEVER HAPPEN, but always CHECK FOR IT! _tcscpy(ttext,_T("Event = unknown")); break; } LKWriteBoxedText(Surface, rct, ttext, 1, 50 , WTALIGN_LEFT, RGB_BLACK, RGB_WHITE); // // Be sure to check that an EVENT was generated, otherwise you are checking even bottombar key presses. // if (LKevent!=LKEVENT_NONE) { _stprintf(ttext,_T("Last coords: X=%d Y=%d , duration=%ld ms"),X,Y,VKtime); LKWriteBoxedText(Surface, rct, ttext, 1, 100 , WTALIGN_LEFT, RGB_BLACK, RGB_WHITE); } // After using the event, WE MUST CLEAR IT, otherwise it will survive for next run. // This can be good for something, though, like automatic redo of last action. // You can also clear this event at the end of this function, to know during execution which was // the key pressed, but remember to clear it. LKevent=LKEVENT_NONE; Surface.SelectObject(oldbrush); Surface.SelectObject(oldpen); }