unsigned MapWindow::UpdateTopography(unsigned max_update) { if (topography != nullptr && GetMapSettings().topography_enabled) return topography->ScanVisibility(visible_projection, max_update); else return 0; }
void GlueMapWindow::DrawFlightMode(Canvas &canvas, const PixelRect &rc) const { PixelScalar offset = 0; // draw logger status if (logger != nullptr && logger->IsLoggerActive()) { bool flip = (Basic().date_time_utc.second % 2) == 0; const MaskedIcon &icon = flip ? look.logger_on_icon : look.logger_off_icon; offset = icon.GetSize().cx; icon.Draw(canvas, rc.right - offset, rc.bottom - icon.GetSize().cy); } // draw flight mode const MaskedIcon *bmp; if (Calculated().common_stats.task_type == TaskType::ABORT) bmp = &look.abort_mode_icon; else if (GetDisplayMode() == DisplayMode::CIRCLING) bmp = &look.climb_mode_icon; else if (GetDisplayMode() == DisplayMode::FINAL_GLIDE) bmp = &look.final_glide_mode_icon; else bmp = &look.cruise_mode_icon; offset += bmp->GetSize().cx + Layout::Scale(6); bmp->Draw(canvas, rc.right - offset, rc.bottom - bmp->GetSize().cy - Layout::Scale(4)); // draw flarm status if (!GetMapSettings().show_flarm_alarm_level) // Don't show indicator when the gauge is indicating the traffic anyway return; const FlarmStatus &flarm = Basic().flarm.status; if (!flarm.available) return; switch (flarm.alarm_level) { case FlarmTraffic::AlarmType::NONE: bmp = &look.traffic_safe_icon; break; case FlarmTraffic::AlarmType::LOW: case FlarmTraffic::AlarmType::INFO_ALERT: bmp = &look.traffic_warning_icon; break; case FlarmTraffic::AlarmType::IMPORTANT: case FlarmTraffic::AlarmType::URGENT: bmp = &look.traffic_alarm_icon; break; }; offset += bmp->GetSize().cx + Layout::Scale(6); bmp->Draw(canvas, rc.right - offset, rc.bottom - bmp->GetSize().cy - Layout::Scale(2)); }
void MapWindow::DrawTaskOffTrackIndicator(Canvas &canvas) { if (Calculated().circling || !Basic().location_available || !Basic().track_available || !GetMapSettings().detour_cost_markers_enabled) return; const TaskStats &task_stats = Calculated().task_stats; const ElementStat ¤t_leg = task_stats.current_leg; if (!task_stats.task_valid || !current_leg.location_remaining.IsValid()) return; const GeoPoint target = current_leg.location_remaining; GeoVector vec(Basic().location, target); if ((Basic().track - vec.bearing).AsDelta().AbsoluteDegrees() < fixed(10)) // insignificant error return; fixed distance_max = std::min(vec.distance, render_projection.GetScreenDistanceMeters() * fixed(0.7)); // too short to bother if (distance_max < fixed(5000)) return; GeoPoint start = Basic().location; canvas.Select(*look.overlay_font); canvas.SetTextColor(COLOR_BLACK); canvas.SetBackgroundTransparent(); GeoPoint dloc; int ilast = 0; for (fixed d = fixed(1) / 4; d <= fixed(1); d += fixed(1) / 4) { dloc = FindLatitudeLongitude(start, Basic().track, distance_max * d); fixed distance0 = start.Distance(dloc); fixed distance1 = target.Distance(dloc); fixed distance = fixed(distance0 + distance1) / vec.distance; int idist = iround((distance - fixed(1)) * 100); if ((idist != ilast) && (idist > 0) && (idist < 1000)) { TCHAR Buffer[5]; _stprintf(Buffer, _T("%d"), idist); RasterPoint sc = render_projection.GeoToScreen(dloc); PixelSize tsize = canvas.CalcTextSize(Buffer); canvas.DrawText(sc.x - tsize.cx / 2, sc.y - tsize.cy / 2, Buffer); ilast = idist; } } }
void GlueMapWindow::DrawVario(Canvas &canvas, const PixelRect &rc) const { if (!GetMapSettings().vario_bar_enabled) return; vario_bar_renderer.Draw(canvas, rc, Basic(), Calculated(), GetComputerSettings().polar.glide_polar_task, true); //NOTE: AVG enabled for now, make it configurable ; }
void MapWindow::DrawWaypoints(Canvas &canvas) { waypoint_renderer.render(canvas, label_block, render_projection, GetMapSettings().waypoint, GetComputerSettings().polar, GetComputerSettings().task, Basic(), Calculated(), task, route_planner); }
void MapWindow::DrawTrail(Canvas &canvas, const RasterPoint aircraft_pos, unsigned min_time, bool enable_traildrift) { if (glide_computer) trail_renderer.Draw(canvas, glide_computer->GetTraceComputer(), render_projection, min_time, enable_traildrift, aircraft_pos, Basic(), Calculated(), GetMapSettings()); }
void MapWindow::DrawWind(Canvas &canvas, const RasterPoint &Start, const PixelRect &rc) const { if (IsPanning()) return; WindArrowRenderer wind_arrow_renderer(look.wind); wind_arrow_renderer.Draw(canvas, render_projection.GetScreenAngle(), Start, rc, Calculated(), GetMapSettings()); }
void GlueMapWindow::RenderTrail(Canvas &canvas, const RasterPoint aircraft_pos) { unsigned min_time; switch(GetMapSettings().trail.length) { case TrailSettings::Length::OFF: return; case TrailSettings::Length::LONG: min_time = max(0, (int)Basic().time - 3600); break; case TrailSettings::Length::SHORT: min_time = max(0, (int)Basic().time - 600); break; case TrailSettings::Length::FULL: min_time = 0; // full break; } DrawTrail(canvas, aircraft_pos, min_time, GetMapSettings().trail.wind_drift_enabled && InCirclingMode()); }
void TargetMapWindow::DrawWaypoints(Canvas &canvas) { const MapSettings &settings_map = GetMapSettings(); WaypointRendererSettings settings = settings_map.waypoint; settings.display_text_type = DISPLAYNAME; way_point_renderer.render(canvas, label_block, projection, settings, GetComputerSettings().task, task, NULL); }
void MapWindow::RenderAirspace(Canvas &canvas) { if (GetMapSettings().airspace.enable) { airspace_renderer.Draw(canvas, #ifndef ENABLE_OPENGL buffer_canvas, #endif render_projection, Basic(), Calculated(), GetComputerSettings().airspace, GetMapSettings().airspace); airspace_label_renderer.Draw(canvas, #ifndef ENABLE_OPENGL buffer_canvas, #endif render_projection, Basic(), Calculated(), GetComputerSettings().airspace, GetMapSettings().airspace); } }
void TargetMapWindow::DrawWaypoints(Canvas &canvas) { const MapSettings &settings_map = GetMapSettings(); WaypointRendererSettings settings = settings_map.waypoint; settings.display_text_type = WaypointRendererSettings::DisplayTextType::NAME; way_point_renderer.render(canvas, label_block, projection, settings, GetComputerSettings().polar, GetComputerSettings().task, Basic(), Calculated(), task, nullptr); }
void GlueMapWindow::Render(Canvas &canvas, const PixelRect &rc) { MapWindow::Render(canvas, rc); if (IsNearSelf()) { draw_sw.Mark("DrawGlueMisc"); if (GetMapSettings().show_thermal_profile) DrawThermalBand(canvas, rc); DrawStallRatio(canvas, rc); DrawFlightMode(canvas, rc); DrawFinalGlide(canvas, rc); DrawVario(canvas, rc); DrawGPSStatus(canvas, rc, Basic()); } }
void TargetMapWindow::OnPaintBuffer(Canvas &canvas) { #ifdef ENABLE_OPENGL /* enable clipping */ GLCanvasScissor scissor(canvas); #endif // Calculate screen position of the aircraft const auto aircraft_pos = projection.GeoToScreen(Basic().location); // reset label over-write preventer label_block.reset(); // Render terrain, groundline and topography RenderTerrain(canvas); RenderTopography(canvas); // Render airspace RenderAirspace(canvas); #ifdef ENABLE_OPENGL /* desaturate the map background, to focus on the task */ canvas.FadeToWhite(0x80); #endif // Render task, waypoints DrawTask(canvas); DrawWaypoints(canvas); // Render the snail trail RenderTrail(canvas); // Render topography on top of airspace, to keep the text readable RenderTopographyLabels(canvas); // Finally, draw you! if (Basic().alive) AircraftRenderer::Draw(canvas, GetMapSettings(), aircraft_look, Basic().attitude.heading - projection.GetScreenAngle(), aircraft_pos); RenderMapScale(canvas, projection, GetClientRect(), overlay_look); }
void MapWindow::DrawTask(Canvas &canvas) { if (task == NULL) return; /* RLD bearing is invalid if GPS not connected and in non-sim mode, but we can still draw targets */ bool draw_bearing = Basic().track_available; bool draw_route = draw_bearing; if (draw_bearing) { if (Calculated().planned_route.size()>2) { draw_bearing = false; } else { draw_route = false; } } ProtectedTaskManager::Lease task_manager(*task); const AbstractTask *task = task_manager->GetActiveTask(); if (task && task->CheckTask()) { RenderTaskPoint::TargetVisibility target_visibility = IsNearSelf() ? RenderTaskPoint::ACTIVE : RenderTaskPoint::ALL; OZRenderer ozv(look.task, airspace_renderer.GetLook(), GetMapSettings().airspace); RenderTaskPoint tpv(canvas, render_projection, look.task, /* we're accessing the OrderedTask here, which may be invalid at this point, but it will be used only if active, so it's ok */ task_manager->GetOrderedTask().GetTaskProjection(), ozv, draw_bearing, target_visibility, Basic().location); TaskRenderer dv(tpv, render_projection.GetScreenBounds()); dv.Draw(*task); } if (draw_route) DrawRoute(canvas); }
void ActionInterface::SendMapSettings(const bool trigger_draw) { // trigger_draw: asks for an immediate exchange of blackboard data // (via ProcessTimer()) rather than waiting for the idle timer every 500ms if (trigger_draw) { DisplayModes(); InfoBoxManager::ProcessTimer(); } main_window.SetMapSettings(GetMapSettings()); if (trigger_draw) { main_window.full_redraw(); BroadcastUISettingsUpdate(); } // TODO: trigger refresh if the settings are changed }
void TargetMapWindow::DrawTask(Canvas &canvas) { if (task == NULL) return; ProtectedTaskManager::Lease task_manager(*task); const AbstractTask *task = task_manager->GetActiveTask(); if (task && task->CheckTask()) { OZRenderer ozv(task_look, airspace_renderer.GetLook(), GetMapSettings().airspace); TaskPointRenderer tpv(canvas, projection, task_look, /* we're accessing the OrderedTask here, which may be invalid at this point, but it will be used only if active, so it's ok */ task_manager->GetOrderedTask().GetTaskProjection(), ozv, false, TaskPointRenderer::ALL, Basic().location_available, Basic().location); TaskRenderer dv(tpv, projection.GetScreenBounds()); dv.Draw(*task); } }
void TargetMapWindow::on_paint_buffer(Canvas &canvas) { #ifdef ENABLE_OPENGL /* enable clipping */ GLCanvasScissor scissor(canvas); #endif // Calculate screen position of the aircraft const RasterPoint aircraft_pos = projection.GeoToScreen(Basic().location); // reset label over-write preventer label_block.reset(); // Render terrain, groundline and topography RenderTerrain(canvas); RenderTopography(canvas); // Render airspace RenderAirspace(canvas); // Render task, waypoints DrawTask(canvas); DrawWaypoints(canvas); // Render the snail trail RenderTrail(canvas); // Render topography on top of airspace, to keep the text readable RenderTopographyLabels(canvas); // Finally, draw you! if (Basic().connected) AircraftRenderer::Draw(canvas, GetMapSettings(), aircraft_look, Calculated().heading - projection.GetScreenAngle(), aircraft_pos); }
inline void MapWindow::RenderRasp(Canvas &canvas) { if (rasp_store == nullptr) return; const WeatherUIState &state = GetUIState().weather; if (rasp_renderer && state.map != (int)rasp_renderer->GetParameter()) { #ifndef ENABLE_OPENGL const ScopeLock protect(mutex); #endif rasp_renderer.reset(); } if (state.map < 0) return; if (!rasp_renderer) { #ifndef ENABLE_OPENGL const ScopeLock protect(mutex); #endif rasp_renderer.reset(new RaspRenderer(*rasp_store, state.map)); } rasp_renderer->SetTime(state.time); { QuietOperationEnvironment operation; rasp_renderer->Update(Calculated().date_time_local, operation); } const auto &terrain_settings = GetMapSettings().terrain; if (rasp_renderer->Generate(render_projection, terrain_settings)) rasp_renderer->Draw(canvas, render_projection); }
void GlueMapWindow::DrawMapScale(Canvas &canvas, const PixelRect &rc, const MapWindowProjection &projection) const { if (!projection.IsValid()) return; StaticString<80> buffer; fixed map_width = projection.GetScreenWidthMeters(); const Font &font = *look.overlay_font; canvas.Select(font); FormatUserMapScale(map_width, buffer.buffer(), true); PixelSize text_size = canvas.CalcTextSize(buffer); const PixelScalar text_padding_x = Layout::GetTextPadding(); const PixelScalar height = font.GetCapitalHeight() + Layout::GetTextPadding(); PixelScalar x = 0; look.map_scale_left_icon.Draw(canvas, 0, rc.bottom - height); x += look.map_scale_left_icon.GetSize().cx; canvas.DrawFilledRectangle(x, rc.bottom - height, x + 2 * text_padding_x + text_size.cx, rc.bottom, COLOR_WHITE); canvas.SetBackgroundTransparent(); canvas.SetTextColor(COLOR_BLACK); x += text_padding_x; canvas.DrawText(x, rc.bottom - font.GetAscentHeight() - Layout::Scale(1), buffer); x += text_padding_x + text_size.cx; look.map_scale_right_icon.Draw(canvas, x, rc.bottom - height); buffer.clear(); if (GetMapSettings().auto_zoom_enabled) buffer = _T("AUTO "); switch (follow_mode) { case FOLLOW_SELF: break; case FOLLOW_PAN: buffer += _T("PAN "); break; } const UIState &ui_state = GetUIState(); if (ui_state.auxiliary_enabled) { buffer += ui_state.panel_name; buffer += _T(" "); } if (Basic().gps.replay) buffer += _T("REPLAY "); else if (Basic().gps.simulator) { buffer += _("Simulator"); buffer += _T(" "); } if (GetComputerSettings().polar.ballast_timer_active) buffer.AppendFormat( _T("BALLAST %d LITERS "), (int)GetComputerSettings().polar.glide_polar_task.GetBallastLitres()); if (weather != nullptr && weather->GetParameter() > 0) { const TCHAR *label = weather->ItemLabel(weather->GetParameter()); if (label != nullptr) buffer += label; } if (!buffer.empty()) { int y = rc.bottom - height; TextInBoxMode mode; mode.vertical_position = TextInBoxMode::VerticalPosition::ABOVE; mode.shape = LabelShape::OUTLINED; TextInBox(canvas, buffer, 0, y, mode, rc, nullptr); } }
void GlueMapWindow::DrawMapScale(Canvas &canvas, const PixelRect &rc, const MapWindowProjection &projection) const { RenderMapScale(canvas, projection, rc, look.overlay); if (!projection.IsValid()) return; StaticString<80> buffer; buffer.clear(); if (GetMapSettings().auto_zoom_enabled) buffer = _T("AUTO "); switch (follow_mode) { case FOLLOW_SELF: break; case FOLLOW_PAN: buffer += _T("PAN "); break; } const UIState &ui_state = GetUIState(); if (ui_state.auxiliary_enabled) { buffer += ui_state.panel_name; buffer += _T(" "); } if (Basic().gps.replay) buffer += _T("REPLAY "); else if (Basic().gps.simulator) { buffer += _("Simulator"); buffer += _T(" "); } if (GetComputerSettings().polar.ballast_timer_active) buffer.AppendFormat( _T("BALLAST %d LITERS "), (int)GetComputerSettings().polar.glide_polar_task.GetBallastLitres()); if (rasp_renderer != nullptr) { const TCHAR *label = rasp_renderer->GetLabel(); if (label != nullptr) buffer += gettext(label); } if (!buffer.empty()) { const Font &font = *look.overlay.overlay_font; canvas.Select(font); const unsigned height = font.GetCapitalHeight() + Layout::GetTextPadding(); int y = rc.bottom - height; TextInBoxMode mode; mode.vertical_position = TextInBoxMode::VerticalPosition::ABOVE; mode.shape = LabelShape::OUTLINED; TextInBox(canvas, buffer, 0, y, mode, rc, nullptr); } }
void TargetMapWindow::RenderTopographyLabels(Canvas &canvas) { if (topography_renderer != nullptr && GetMapSettings().topography_enabled) topography_renderer->DrawLabels(canvas, projection, label_block); }
void TargetMapWindow::RenderTopography(Canvas &canvas) { if (topography_renderer != nullptr && GetMapSettings().topography_enabled) topography_renderer->Draw(canvas, projection); }
bool ButtonLabel::ExpandMacros(const TCHAR *In, TCHAR *OutBuffer, size_t Size) { // ToDo, check Buffer Size bool invalid = false; CopyString(OutBuffer, In, Size); if (_tcsstr(OutBuffer, _T("$(")) == NULL) return false; if (_tcsstr(OutBuffer, _T("$(CheckAirspace)"))) { if (airspace_database.empty()) invalid = true; ReplaceInString(OutBuffer, _T("$(CheckAirspace)"), _T(""), Size); } invalid |= ExpandTaskMacros(OutBuffer, Size, Calculated(), GetComputerSettings()); ExpandTrafficMacros(OutBuffer, Size); if (_tcsstr(OutBuffer, _T("$(CheckFLARM)"))) { if (!Basic().flarm.status.available) invalid = true; ReplaceInString(OutBuffer, _T("$(CheckFLARM)"), _T(""), Size); } if (_tcsstr(OutBuffer, _T("$(CheckCircling)"))) { if (!Calculated().circling) invalid = true; ReplaceInString(OutBuffer, _T("$(CheckCircling)"), _T(""), Size); } if (_tcsstr(OutBuffer, _T("$(CheckVega)"))) { if (devVarioFindVega()== NULL) invalid = true; ReplaceInString(OutBuffer, _T("$(CheckVega)"), _T(""), Size); } if (_tcsstr(OutBuffer, _T("$(CheckReplay)"))) { if (CommonInterface::MovementDetected()) invalid = true; ReplaceInString(OutBuffer, _T("$(CheckReplay)"), _T(""), Size); } if (_tcsstr(OutBuffer, _T("$(CheckWaypointFile)"))) { invalid |= way_points.IsEmpty(); ReplaceInString(OutBuffer, _T("$(CheckWaypointFile)"), _T(""), Size); } if (_tcsstr(OutBuffer, _T("$(CheckLogger)"))) { invalid |= Basic().gps.replay; ReplaceInString(OutBuffer, _T("$(CheckLogger)"), _T(""), Size); } if (_tcsstr(OutBuffer, _T("$(CheckNet)"))) { #ifndef HAVE_HTTP invalid = true; #endif ReplaceInString(OutBuffer, _T("$(CheckNet)"), _T(""), Size); } if (_tcsstr(OutBuffer, _T("$(CheckTerrain)"))) { if (!Calculated().terrain_valid) invalid = true; ReplaceInString(OutBuffer, _T("$(CheckTerrain)"), _T(""), Size); } CondReplaceInString(logger != nullptr && logger->IsLoggerActive(), OutBuffer, _T("$(LoggerActive)"), _("Stop"), _("Start"), Size); if (_tcsstr(OutBuffer, _T("$(SnailTrailToggleName)"))) { switch (GetMapSettings().trail.length) { case TrailSettings::Length::OFF: ReplaceInString(OutBuffer, _T("$(SnailTrailToggleName)"), _("Long"), Size); break; case TrailSettings::Length::LONG: ReplaceInString(OutBuffer, _T("$(SnailTrailToggleName)"), _("Short"), Size); break; case TrailSettings::Length::SHORT: ReplaceInString(OutBuffer, _T("$(SnailTrailToggleName)"), _("Full"), Size); break; case TrailSettings::Length::FULL: ReplaceInString(OutBuffer, _T("$(SnailTrailToggleName)"), _("Off"), Size); break; } } if (_tcsstr(OutBuffer, _T("$(AirSpaceToggleName)"))) { ReplaceInString(OutBuffer, _T("$(AirSpaceToggleName)"), GetMapSettings().airspace.enable ? _("Off") : _("On"), Size); } if (_tcsstr(OutBuffer, _T("$(TerrainTopologyToggleName)"))) { char val = 0; if (GetMapSettings().topography_enabled) val++; if (GetMapSettings().terrain.enable) val += (char)2; switch (val) { case 0: ReplaceInString(OutBuffer, _T("$(TerrainTopologyToggleName)"), _("Topography On"), Size); break; case 1: ReplaceInString(OutBuffer, _T("$(TerrainTopologyToggleName)"), _("Terrain On"), Size); break; case 2: ReplaceInString(OutBuffer, _T("$(TerrainTopologyToggleName)"), _("Terrain + Topography"), Size); break; case 3: ReplaceInString(OutBuffer, _T("$(TerrainTopologyToggleName)"), _("Terrain Off"), Size); break; } } if (_tcsstr(OutBuffer, _T("$(TerrainTopographyToggleName)"))) { char val = 0; if (GetMapSettings().topography_enabled) val++; if (GetMapSettings().terrain.enable) val += (char)2; switch (val) { case 0: ReplaceInString(OutBuffer, _T("$(TerrainTopographyToggleName)"), _("Topography On"), Size); break; case 1: ReplaceInString(OutBuffer, _T("$(TerrainTopographyToggleName)"), _("Terrain On"), Size); break; case 2: ReplaceInString(OutBuffer, _T("$(TerrainTopographyToggleName)"), _("Terrain + Topography"), Size); break; case 3: ReplaceInString(OutBuffer, _T("$(TerrainTopographyToggleName)"), _("Terrain Off"), Size); break; } } CondReplaceInString(CommonInterface::main_window->GetFullScreen(), OutBuffer, _T("$(FullScreenToggleActionName)"), _("Off"), _("On"), Size); CondReplaceInString(GetMapSettings().auto_zoom_enabled, OutBuffer, _T("$(ZoomAutoToggleActionName)"), _("Manual"), _("Auto"), Size); CondReplaceInString(GetMapSettings().topography_enabled, OutBuffer, _T("$(TopologyToggleActionName)"), _("Off"), _("On"), Size); CondReplaceInString(GetMapSettings().topography_enabled, OutBuffer, _T("$(TopographyToggleActionName)"), _("Off"), _("On"), Size); CondReplaceInString(GetMapSettings().terrain.enable, OutBuffer, _T("$(TerrainToggleActionName)"), _("Off"), _("On"), Size); CondReplaceInString(GetMapSettings().airspace.enable, OutBuffer, _T("$(AirspaceToggleActionName)"), _("Off"), _("On"), Size); if (_tcsstr(OutBuffer, _T("$(MapLabelsToggleActionName)"))) { static const TCHAR *const labels[] = { N_("All"), N_("Task & Landables"), N_("Task"), N_("None") }; static constexpr unsigned int n = ARRAY_SIZE(labels); unsigned int i = (unsigned)GetMapSettings().waypoint.label_selection; ReplaceInString(OutBuffer, _T("$(MapLabelsToggleActionName)"), gettext(labels[(i + 1) % n]), Size); } CondReplaceInString(GetComputerSettings().task.auto_mc, OutBuffer, _T("$(MacCreadyToggleActionName)"), _("Manual"), _("Auto"), Size); CondReplaceInString(GetUIState().auxiliary_enabled, OutBuffer, _T("$(AuxInfoToggleActionName)"), _("Off"), _("On"), Size); CondReplaceInString(GetUIState().force_display_mode == DisplayMode::CIRCLING, OutBuffer, _T("$(DispModeClimbShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetUIState().force_display_mode == DisplayMode::CRUISE, OutBuffer, _T("$(DispModeCruiseShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetUIState().force_display_mode == DisplayMode::NONE, OutBuffer, _T("$(DispModeAutoShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetUIState().force_display_mode == DisplayMode::FINAL_GLIDE, OutBuffer, _T("$(DispModeFinalShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().airspace.altitude_mode == AirspaceDisplayMode::ALLON, OutBuffer, _T("$(AirspaceModeAllShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().airspace.altitude_mode == AirspaceDisplayMode::CLIP, OutBuffer, _T("$(AirspaceModeClipShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().airspace.altitude_mode == AirspaceDisplayMode::AUTO, OutBuffer, _T("$(AirspaceModeAutoShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().airspace.altitude_mode == AirspaceDisplayMode::ALLBELOW, OutBuffer, _T("$(AirspaceModeBelowShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().airspace.altitude_mode == AirspaceDisplayMode::ALLOFF, OutBuffer, _T("$(AirspaceModeAllOffIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().trail.length == TrailSettings::Length::OFF, OutBuffer, _T("$(SnailTrailOffShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().trail.length == TrailSettings::Length::SHORT, OutBuffer, _T("$(SnailTrailShortShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().trail.length == TrailSettings::Length::LONG, OutBuffer, _T("$(SnailTrailLongShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().trail.length == TrailSettings::Length::FULL, OutBuffer, _T("$(SnailTrailFullShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(!GetMapSettings().airspace.enable, OutBuffer, _T("$(AirSpaceOffShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(GetMapSettings().airspace.enable, OutBuffer, _T("$(AirSpaceOnShortIndicator)"), _T("(*)"), _T(""), Size); CondReplaceInString(CommonInterface::GetUISettings().traffic.enable_gauge, OutBuffer, _T("$(FlarmDispToggleActionName)"), _("Off"), _("On"), Size); CondReplaceInString(GetMapSettings().auto_zoom_enabled, OutBuffer, _T("$(ZoomAutoToggleActionName)"), _("Manual"), _("Auto"), Size); if (_tcsstr(OutBuffer, _T("$(NextPageName)"))) { TCHAR label[30]; const PageLayout &page = CommonInterface::GetUISettings().pages.pages[Pages::NextIndex()]; page.MakeTitle(CommonInterface::GetUISettings().info_boxes, label, true); ReplaceInString(OutBuffer, _T("$(NextPageName)"), label, Size); } return invalid; }
void MapWindow::RenderTopography(Canvas &canvas) { if (topography_renderer != NULL && GetMapSettings().topography_enabled) topography_renderer->Draw(canvas, render_projection); }
void MapWindow::Render(Canvas &canvas, const PixelRect &rc) { const NMEAInfo &basic = Basic(); // reset label over-write preventer label_block.reset(); render_projection = visible_projection; if (!render_projection.IsValid()) { canvas.ClearWhite(); return; } // Calculate screen position of the aircraft RasterPoint aircraft_pos{0,0}; if (basic.location_available) aircraft_pos = render_projection.GeoToScreen(basic.location); // Render terrain, groundline and topography draw_sw.Mark("RenderTerrain"); RenderTerrain(canvas); draw_sw.Mark("RenderTopography"); RenderTopography(canvas); draw_sw.Mark("RenderFinalGlideShading"); RenderFinalGlideShading(canvas); // Render track bearing (ground track) draw_sw.Mark("DrawTrackBearing"); DrawTrackBearing(canvas, aircraft_pos); // Render airspace draw_sw.Mark("RenderAirspace"); RenderAirspace(canvas); // Render task, waypoints draw_sw.Mark("DrawContest"); DrawContest(canvas); draw_sw.Mark("DrawTask"); DrawTask(canvas); draw_sw.Mark("DrawWaypoints"); DrawWaypoints(canvas); draw_sw.Mark("DrawNOAAStations"); RenderNOAAStations(canvas); draw_sw.Mark("RenderMisc1"); // Render weather/terrain max/min values DrawTaskOffTrackIndicator(canvas); // Render the snail trail if (basic.location_available) RenderTrail(canvas, aircraft_pos); RenderMarkers(canvas); // Render estimate of thermal location DrawThermalEstimate(canvas); // Render topography on top of airspace, to keep the text readable draw_sw.Mark("RenderTopographyLabels"); RenderTopographyLabels(canvas); // Render glide through terrain range draw_sw.Mark("RenderGlide"); RenderGlide(canvas); draw_sw.Mark("RenderMisc2"); DrawBestCruiseTrack(canvas, aircraft_pos); airspace_renderer.DrawIntersections(canvas, render_projection); // Draw wind vector at aircraft if (basic.location_available) DrawWind(canvas, aircraft_pos, rc); // Draw traffic #ifdef HAVE_SKYLINES_TRACKING_HANDLER DrawSkyLinesTraffic(canvas); #endif DrawTeammate(canvas); if (basic.location_available) DrawFLARMTraffic(canvas, aircraft_pos); // Finally, draw you! if (basic.location_available) AircraftRenderer::Draw(canvas, GetMapSettings(), look.aircraft, basic.attitude.heading - render_projection.GetScreenAngle(), aircraft_pos); // Render compass DrawCompass(canvas, rc); }
void GlueMapWindow::DrawMapScale(Canvas &canvas, const PixelRect &rc, const MapWindowProjection &projection) const { StaticString<80> buffer; fixed map_width = projection.GetScreenWidthMeters(); canvas.Select(Fonts::map_bold); FormatUserMapScale(map_width, buffer.buffer(), true); PixelSize text_size = canvas.CalcTextSize(buffer); const PixelScalar text_padding_x = Layout::Scale(2); const PixelScalar height = Fonts::map_bold.GetCapitalHeight() + Layout::Scale(2); PixelScalar x = 0; look.map_scale_left_icon.Draw(canvas, 0, rc.bottom - height); x += look.map_scale_left_icon.GetSize().cx; canvas.DrawFilledRectangle(x, rc.bottom - height, x + 2 * text_padding_x + text_size.cx, rc.bottom, COLOR_WHITE); canvas.SetBackgroundTransparent(); canvas.SetTextColor(COLOR_BLACK); x += text_padding_x; canvas.text(x, rc.bottom - Fonts::map_bold.GetAscentHeight() - Layout::Scale(1), buffer); x += text_padding_x + text_size.cx; look.map_scale_right_icon.Draw(canvas, x, rc.bottom - height); buffer.clear(); if (GetMapSettings().auto_zoom_enabled) buffer = _T("AUTO "); switch (follow_mode) { case FOLLOW_SELF: break; case FOLLOW_PAN: buffer += _T("PAN "); break; } const UIState &ui_state = GetUIState(); if (ui_state.auxiliary_enabled) { buffer += ui_state.panel_name; buffer += _T(" "); } if (Basic().gps.replay) buffer += _T("REPLAY "); else if (Basic().gps.simulator) { buffer += _("Simulator"); buffer += _T(" "); } if (GetComputerSettings().polar.ballast_timer_active) buffer.AppendFormat( _T("BALLAST %d LITERS "), (int)GetComputerSettings().polar.glide_polar_task.GetBallastLitres()); if (weather != NULL && weather->GetParameter() > 0) { const TCHAR *label = weather->ItemLabel(weather->GetParameter()); if (label != NULL) buffer += label; } if (!buffer.empty()) { int y = rc.bottom - height; canvas.Select(Fonts::title); canvas.SetBackgroundOpaque(); canvas.SetBackgroundColor(COLOR_WHITE); canvas.text(0, y - canvas.CalcTextSize(buffer).cy, buffer); } }
/** * Draws the FLARM traffic icons onto the given canvas * @param canvas Canvas for drawing */ void MapWindow::DrawFLARMTraffic(Canvas &canvas, const PixelPoint aircraft_pos) const { // Return if FLARM icons on moving map are disabled if (!GetMapSettings().show_flarm_on_map) return; // Return if FLARM data is not available const TrafficList &flarm = Basic().flarm.traffic; if (flarm.IsEmpty()) return; const WindowProjection &projection = render_projection; // if zoomed in too far out, dont draw traffic since it will be too close to // the glider and so will be meaningless (serves only to clutter, cant help // the pilot) if (projection.GetMapScale() > 7300) return; canvas.Select(*traffic_look.font); // Circle through the FLARM targets for (auto it = flarm.list.begin(), end = flarm.list.end(); it != end; ++it) { const FlarmTraffic &traffic = *it; if (!traffic.location_available) continue; // Save the location of the FLARM target GeoPoint target_loc = traffic.location; // Points for the screen coordinates for the icon, name and average climb PixelPoint sc, sc_name, sc_av; // If FLARM target not on the screen, move to the next one if (!projection.GeoToScreenIfVisible(target_loc, sc)) continue; // Draw the name 16 points below the icon sc_name = sc; sc_name.y -= Layout::Scale(20); // Draw the average climb value above the icon sc_av = sc; sc_av.y += Layout::Scale(5); TextInBoxMode mode; mode.shape = LabelShape::OUTLINED; // JMW TODO enhancement: decluttering of FLARM altitudes (sort by max lift) int dx = sc_av.x - aircraft_pos.x; int dy = sc_av.y - aircraft_pos.y; // only draw labels if not close to aircraft if (dx * dx + dy * dy > Layout::Scale(30 * 30)) { // If FLARM callsign/name available draw it to the canvas if (traffic.HasName() && !StringIsEmpty(traffic.name)) TextInBox(canvas, traffic.name, sc_name.x, sc_name.y, mode, GetClientRect()); if (traffic.climb_rate_avg30s >= 0.1) { // If average climb data available draw it to the canvas TCHAR label_avg[100]; FormatUserVerticalSpeed(traffic.climb_rate_avg30s, label_avg, false); TextInBox(canvas, label_avg, sc_av.x, sc_av.y, mode, GetClientRect()); } } auto color = FlarmFriends::GetFriendColor(traffic.id); TrafficRenderer::Draw(canvas, traffic_look, traffic, traffic.track - projection.GetScreenAngle(), color, sc); } }
/** * Draws the GliderLink traffic icons onto the given canvas * @param canvas Canvas for drawing */ void MapWindow::DrawGLinkTraffic(Canvas &canvas, const PixelPoint aircraft_pos) const { #ifdef ANDROID // Return if FLARM icons on moving map are disabled if (!GetMapSettings().show_flarm_on_map) return; const GliderLinkTrafficList &traffic = Basic().glink_data.traffic; if (traffic.IsEmpty()) return; const MoreData &basic = Basic(); const WindowProjection &projection = render_projection; canvas.Select(*traffic_look.font); // Circle through the GliderLink targets for (const auto &traf : traffic.list) { // Save the location of the target GeoPoint target_loc = traf.location; // Points for the screen coordinates for the icon, name and average climb PixelPoint sc, sc_name, sc_av, sc_alt; // If FLARM target not on the screen, move to the next one if (!projection.GeoToScreenIfVisible(target_loc, sc)) continue; // Draw the callsign above the icon sc_name = sc; sc_name.x -= Layout::Scale(10); sc_name.y -= Layout::Scale(15); // Draw the average climb to the right of the icon sc_av = sc; sc_av.x += Layout::Scale(10); sc_av.y -= Layout::Scale(8); // Location of altitude label sc_alt = sc; sc_alt.x -= Layout::Scale(10); sc_alt.y -= Layout::Scale(0); TextInBoxMode mode; mode.shape = LabelShape::OUTLINED; mode.align = TextInBoxMode::Alignment::RIGHT; // If callsign/name available draw it to the canvas if (traf.HasName() && !StringIsEmpty(traf.name)) TextInBox(canvas, traf.name, sc_name.x, sc_name.y, mode, GetClientRect()); if (traf.climb_rate_received) { // If average climb data available draw it to the canvas TCHAR label_avg[100]; FormatUserVerticalSpeed(traf.climb_rate, label_avg, false); mode.align = TextInBoxMode::Alignment::LEFT; TextInBox(canvas, label_avg, sc_av.x, sc_av.y, mode, GetClientRect()); } // use GPS altitude to be consistent with GliderLink if(basic.gps_altitude_available && traf.altitude_received && fabs(double(traf.altitude) - basic.gps_altitude) >= 100.0) { // If average climb data available draw it to the canvas TCHAR label_alt[100]; double alt = (double(traf.altitude) - basic.gps_altitude) / 100.0; FormatRelativeUserAltitude(alt, label_alt, false); mode.align = TextInBoxMode::Alignment::RIGHT; TextInBox(canvas, label_alt, sc_alt.x, sc_alt.y, mode, GetClientRect()); } TrafficRenderer::Draw(canvas, traffic_look, traf, traf.track - projection.GetScreenAngle(), sc); } #endif }
void MapWindow::Render(Canvas &canvas, const PixelRect &rc) { const NMEAInfo &basic = Basic(); // reset label over-write preventer label_block.reset(); render_projection = visible_projection; if (!render_projection.IsValid()) { canvas.ClearWhite(); return; } // Calculate screen position of the aircraft PixelPoint aircraft_pos{0,0}; if (basic.location_available) aircraft_pos = render_projection.GeoToScreen(basic.location); // General layout principles: // - lower elevation drawn on bottom layers // - increasing elevation drawn above // - increasing importance drawn above // - attempt to not obscure text //////////////////////////////////////////////// items on ground // Render terrain, groundline and topography draw_sw.Mark("RenderTerrain"); RenderTerrain(canvas); draw_sw.Mark("RenderRasp"); RenderRasp(canvas); draw_sw.Mark("RenderTopography"); RenderTopography(canvas); draw_sw.Mark("RenderOverlays"); RenderOverlays(canvas); draw_sw.Mark("DrawNOAAStations"); RenderNOAAStations(canvas); //////////////////////////////////////////////// glide range info draw_sw.Mark("RenderFinalGlideShading"); RenderFinalGlideShading(canvas); //////////////////////////////////////////////// airspace // Render airspace draw_sw.Mark("RenderAirspace"); RenderAirspace(canvas); //////////////////////////////////////////////// task // Render task, waypoints draw_sw.Mark("DrawContest"); DrawContest(canvas); draw_sw.Mark("DrawTask"); DrawTask(canvas); draw_sw.Mark("DrawWaypoints"); DrawWaypoints(canvas); //////////////////////////////////////////////// aircraft level items // Render the snail trail if (basic.location_available) RenderTrail(canvas, aircraft_pos); DrawWaves(canvas); // Render estimate of thermal location DrawThermalEstimate(canvas); //////////////////////////////////////////////// text items // Render topography on top of airspace, to keep the text readable draw_sw.Mark("RenderTopographyLabels"); RenderTopographyLabels(canvas); //////////////////////////////////////////////// navigation overlays // Render glide through terrain range draw_sw.Mark("RenderGlide"); RenderGlide(canvas); draw_sw.Mark("RenderMisc1"); // Render weather/terrain max/min values DrawTaskOffTrackIndicator(canvas); // Render track bearing (projected track ground/air relative) draw_sw.Mark("DrawTrackBearing"); RenderTrackBearing(canvas, aircraft_pos); draw_sw.Mark("RenderMisc2"); DrawBestCruiseTrack(canvas, aircraft_pos); // Draw wind vector at aircraft if (basic.location_available) DrawWind(canvas, aircraft_pos, rc); // Render compass DrawCompass(canvas, rc); //////////////////////////////////////////////// traffic // Draw traffic #ifdef HAVE_SKYLINES_TRACKING DrawSkyLinesTraffic(canvas); #endif DrawTeammate(canvas); if (basic.location_available) DrawFLARMTraffic(canvas, aircraft_pos); //////////////////////////////////////////////// own aircraft // Finally, draw you! if (basic.location_available) AircraftRenderer::Draw(canvas, GetMapSettings(), look.aircraft, basic.attitude.heading - render_projection.GetScreenAngle(), aircraft_pos); //////////////////////////////////////////////// important overlays // Draw intersections on top of aircraft airspace_renderer.DrawIntersections(canvas, render_projection); }