/** * Searches the FLARM_Traffic array for the TeamMate and updates TeamMate * position and TeamCode if found. */ void GlideComputer::FLARM_ScanTraffic() { // If (not FLARM available) cancel if (!Basic().flarm.FLARM_Available || !SettingsComputer().TeamFlarmTracking) return; if (SettingsComputer().TeamCodeRefWaypoint < 0) return; // Get bearing and distance to the reference waypoint const Waypoint *wp = way_points.lookup_id(SettingsComputer().TeamCodeRefWaypoint); if (!wp) return; const FLARM_TRAFFIC *traffic = Basic().flarm.FindTraffic(SettingsComputer().TeamFlarmIdTarget); if (!traffic) return; // Set Teammate location to FLARM contact location SetCalculated().TeammateLocation = traffic->Location; // Calculate distance and bearing from teammate to reference waypoint Angle bearing = wp->Location.bearing(traffic->Location); fixed distance = wp->Location.distance(traffic->Location); // Calculate TeamCode and save it in Calculated XCSoarInterface::SetSettingsComputer().TeammateCode.Update(bearing, distance); XCSoarInterface::SetSettingsComputer().TeammateCodeValid = true; }
void GlueMapWindow::DrawThermalBand(Canvas &canvas, const PixelRect &rc) const { if (Calculated().task_stats.total.solution_remaining.IsOk() && Calculated().task_stats.total.solution_remaining.altitude_difference > fixed(50) && GetDisplayMode() == DM_FINAL_GLIDE) return; PixelRect tb_rect; tb_rect.left = rc.left; tb_rect.right = rc.left+Layout::Scale(20); tb_rect.top = Layout::Scale(4); tb_rect.bottom = tb_rect.top+(rc.bottom-rc.top)/2-Layout::Scale(30); const ThermalBandRenderer &renderer = thermal_band_renderer; if (task != NULL) { ProtectedTaskManager::Lease task_manager(*task); renderer.DrawThermalBand(Basic(), Calculated(), SettingsComputer(), canvas, tb_rect, SettingsComputer().task, true, &task_manager->get_ordered_task_behaviour()); } else { renderer.DrawThermalBand(Basic(), Calculated(), SettingsComputer(), canvas, tb_rect, SettingsComputer().task, true); } }
/** * Logs GPS fixes for stats * @return True if valid fix (fix distance <= 200m), False otherwise */ bool GlideComputerStats::DoLogging() { /// @todo consider putting this sanity check inside Parser if (Distance(Basic().location, LastBasic().location) > fixed(200)) // prevent bad fixes from being logged or added to OLC store return false; // log points more often in circling mode if (Calculated().circling) log_clock.set_dt(fixed(SettingsComputer().LoggerTimeStepCircling)); else log_clock.set_dt(fixed(SettingsComputer().LoggerTimeStepCruise)); if (FastLogNum) { log_clock.set_dt(fixed_one); FastLogNum--; } if (log_clock.check_advance(Basic().time) && logger != NULL) logger->LogPoint(Basic()); if (Calculated().flight.flying && stats_clock.check_advance(Basic().time)) { flightstats.AddAltitudeTerrain(Calculated().flight.flight_time, Calculated().terrain_altitude); flightstats.AddAltitude(Calculated().flight.flight_time, Basic().NavAltitude); flightstats.AddTaskSpeed(Calculated().flight.flight_time, Calculated().task_stats.get_pirker_speed()); } return true; }
void MapWindow::DrawWaypoints(Canvas &canvas) { GlidePolar polar = get_glide_polar(); polar.set_mc(min(Calculated().common_stats.current_risk_mc, SettingsComputer().safety_mc)); way_point_renderer.render(canvas, label_block, render_projection, SettingsMap(), SettingsComputer(), polar, ToAircraftState(Basic()), task); }
/** * Calls the SearchBestAlternate() method if a certain time has passed since the last call * @author Paolo Ventafridda */ void GlideComputerTask::DoBestAlternateSlow() { static double LastSearchBestTime = 0; // VENTA3 // VENTA3 best landing slow calculation #ifdef WINDOWSPC if ( (SettingsComputer().EnableBestAlternate) && (Basic().Time > LastSearchBestTime+10.0) ) // VENTA3 #else if ((SettingsComputer().EnableBestAlternate) && (Basic().Time > LastSearchBestTime + BESTALTERNATEINTERVAL)) // VENTA3 #endif { LastSearchBestTime = Basic().Time; SearchBestAlternate(); } }
void MapWindow::DrawGlideThroughTerrain(Canvas &canvas) const { if (SettingsComputer().FinalGlideTerrain) { canvas.hollow_brush(); #ifndef ENABLE_OPENGL canvas.select(Graphics::hpTerrainLineBg); canvas.polygon(Groundline, TERRAIN_ALT_INFO::NUMTERRAINSWEEPS); #endif canvas.select(Graphics::hpTerrainLine); canvas.polygon(Groundline, TERRAIN_ALT_INFO::NUMTERRAINSWEEPS); } if (!Basic().flight.Flying) return; if (!Calculated().TerrainWarningLocation.is_null()) { RasterPoint sc; if (render_projection.GeoToScreenIfVisible(Calculated().TerrainWarningLocation, sc)) Graphics::hTerrainWarning.draw(canvas, sc.x, sc.y); } }
/* * Do not disturb too much. Play alert sound only once every x minutes, not more. */ void GlideComputerTask::AlertBestAlternate(short soundmode) { static double LastAlertTime = 0; if (Basic().Time > LastAlertTime + 180.0) { if (SettingsComputer().EnableSoundModes) { LastAlertTime = Basic().Time; switch (soundmode) { case 0: break; case 1: PlayResource(TEXT("IDR_WAV_GREEN")); break; case 2: PlayResource(TEXT("IDR_WAV_RED")); break; case 11: PlayResource(TEXT("IDR_WAV_GREEN")); PlayResource(TEXT("IDR_WAV_GREEN")); break; default: break; } } } }
void ActionInterface::SendSettingsComputer() { ScopeLock protect(mutexBlackboard); // send computer settings to the device because we know // that it won't be reading from them if we lock it, and // then others can retrieve from it at their convenience. device_blackboard.ReadSettingsComputer(SettingsComputer()); // TODO: trigger refresh if the settings are changed }
void GlideComputer::CalculateTeammateBearingRange() { static bool InTeamSector = false; // No reference waypoint for teamcode calculation chosen -> cancel if (SettingsComputer().TeamCodeRefWaypoint < 0) return; // Get bearing and distance to the reference waypoint const Waypoint *wp = way_points.lookup_id(SettingsComputer().TeamCodeRefWaypoint); if (!wp) return; Angle ownBearing = wp->Location.bearing(Basic().Location); // If (TeamCode exists and is valid) if (SettingsComputer().TeammateCodeValid) { // Calculate bearing and distance to teammate SetCalculated().TeammateLocation = SettingsComputer().TeammateCode.GetLocation(wp->Location); GeoVector team_vector(Basic().Location, Calculated().TeammateLocation); // Save bearing and distance to teammate in Calculated SetCalculated().TeammateBearing = team_vector.Bearing; SetCalculated().TeammateRange = team_vector.Distance; // Hysteresis for GlideComputerEvent // If (closer than 100m to the teammates last position and "event" not reset) if (Calculated().TeammateRange < fixed(100) && InTeamSector == false) { InTeamSector = true; // Raise GCE_TEAM_POS_REACHED event InputEvents::processGlideComputer(GCE_TEAM_POS_REACHED); } else if (Calculated().TeammateRange > fixed(300)) { // Reset "event" when distance is greater than 300m again InTeamSector = false; } } else { SetCalculated().TeammateBearing = Angle::degrees(fixed_zero); SetCalculated().TeammateRange = fixed_zero; } }
/** * Draws the teammate icon to the given canvas * @param canvas Canvas for drawing */ void MapWindow::DrawTeammate(Canvas &canvas) const { if (SettingsComputer().TeammateCodeValid) { RasterPoint sc; if (render_projection.GeoToScreenIfVisible(Calculated().TeammateLocation, sc)) Graphics::hBmpTeammatePosition.draw(canvas, sc); } }
void TargetMapWindow::DrawWaypoints(Canvas &canvas) { const SETTINGS_MAP &settings_map = SettingsMap(); WaypointRendererSettings settings = settings_map.waypoint; settings.display_text_type = DISPLAYNAME; way_point_renderer.render(canvas, label_block, projection, settings, SettingsComputer().task, task, NULL); }
void TargetMapWindow::RenderAirspace(Canvas &canvas) { if (SettingsMap().airspace.enable) airspace_renderer.Draw(canvas, #ifndef ENABLE_OPENGL buffer_canvas, stencil_canvas, #endif projection, Basic(), Calculated(), SettingsComputer(), SettingsMap()); }
void MapWindow::DrawGlideThroughTerrain(Canvas &canvas) { canvas.select(MapGfx.hpTerrainLineBg); canvas.polyline(Groundline, NUMTERRAINSWEEPS + 1); if ((SettingsComputer().FinalGlideTerrain==1) || ((!SettingsMap().EnableTerrain || !Calculated().Flying) && (SettingsComputer().FinalGlideTerrain==2))) { canvas.select(MapGfx.hpTerrainLine); canvas.polyline(Groundline, NUMTERRAINSWEEPS + 1); } if (Calculated().Flying && task.Valid()) { if ((Calculated().TerrainWarningLocation.Latitude != 0.0) &&(Calculated().TerrainWarningLocation.Longitude != 0.0)) { draw_masked_bitmap_if_visible(canvas, MapGfx.hTerrainWarning, Calculated().TerrainWarningLocation, 10, 10); } } }
void DeviceBlackboard::tick() { SetBasic().expire(); // calculate fast data to complete aircraft state computer.Compute(SetBasic(), LastBasic(), Calculated(), SettingsComputer()); if (Basic().Time!= LastBasic().Time) { state_last = Basic(); } }
/** * Calculates the own TeamCode and saves it to Calculated */ void GlideComputer::CalculateOwnTeamCode() { // No reference waypoint for teamcode calculation chosen -> cancel if (SettingsComputer().TeamCodeRefWaypoint < 0) return; // Only calculate every 10sec otherwise cancel calculation if (!last_team_code_update.check_update(10000)) return; // Get bearing and distance to the reference waypoint const Waypoint *wp = way_points.lookup_id(SettingsComputer().TeamCodeRefWaypoint); if (!wp) return; Angle bearing = wp->Location.bearing(Basic().Location); fixed distance = wp->Location.distance(Basic().Location); // Save teamcode to Calculated SetCalculated().OwnTeamCode.Update(bearing, distance); }
/** * Calculates the screen positions of all important features * @param canvas The drawing canvas * @param rc The area to draw in */ void MapWindow::RenderStart(Canvas &canvas, const RECT &rc) { // Calculate screen position of the aircraft projection.CalculateOrigin(rc, Basic(), Calculated(), SettingsComputer(), SettingsMap()); // Calculate screen positions of the thermal sources CalculateScreenPositionsThermalSources(); // Calculate screen positions of the final glide groundline CalculateScreenPositionsGroundline(); // reset label over-write preventer label_block.reset(); }
/* * VENTA3 Alternates destinations * * Used by Alternates and BestAlternate * * Colors VGR are disabled, but available */ void GlideComputerTask::DoAlternates(int AltWaypoint) { if (!way_points.verify_index(AltWaypoint)) { return; } const WAYPOINT &way_point = way_points.get(AltWaypoint); WPCALC &way_point_calc = way_points.set_calc(AltWaypoint); GEOPOINT w1 = way_point.Location; GEOPOINT w0 = Basic().Location; double *altwp_dist = &way_point_calc.Distance; double *altwp_gr = &way_point_calc.GR; double *altwp_arrival = &way_point_calc.AltArrival; short *altwp_vgr = &way_point_calc.VGR; *altwp_dist = Distance(w1, w0); double GRsafecalc = Calculated().NavAltitude - (way_point.Altitude + SettingsComputer().SafetyAltitudeArrival); if (GRsafecalc <= 0) { *altwp_gr = INVALID_GR; } else { *altwp_gr = *altwp_dist / GRsafecalc; if (*altwp_gr > ALTERNATE_MAXVALIDGR || *altwp_gr < 0) { *altwp_gr = INVALID_GR; } else if (*altwp_gr < 1) { *altwp_gr = 1; } } // We need to calculate arrival also for BestAlternate, since the last "reachable" could be // even 60 seconds old and things may have changed drastically *altwp_arrival = CalculateWaypointArrivalAltitude(way_point, way_point_calc); if ((*altwp_arrival - ALTERNATE_OVERSAFETY) > 0) { if (*altwp_gr <= (GlidePolar::bestld * SAFELD_FACTOR)) { *altwp_vgr = 1; // full green vgr } else if (*altwp_gr <= GlidePolar::bestld) { *altwp_vgr = 2; // yellow vgr } else *altwp_vgr = 3; // RED vgr } else { *altwp_vgr = 3; // full red } }
void MapWindow::DrawGlideThroughTerrain(Canvas &canvas) const { if (SettingsComputer().FinalGlideTerrain) { canvas.select(MapGfx.hpTerrainLineBg); canvas.polyline(Groundline, TERRAIN_ALT_INFO::NUMTERRAINSWEEPS + 1); canvas.select(MapGfx.hpTerrainLine); canvas.polyline(Groundline, TERRAIN_ALT_INFO::NUMTERRAINSWEEPS + 1); } if (!Basic().flight.Flying) return; if (!Calculated().TerrainWarningLocation.is_null()) { POINT sc; if (projection.LonLat2ScreenIfVisible(Calculated().TerrainWarningLocation, &sc)) MapGfx.hTerrainWarning.draw(canvas, bitmap_canvas, sc.x, sc.y); } }
/** * Is called by the CalculationThread and processes the received GPS data in Basic() */ bool GlideComputer::ProcessGPS() { PeriodClock clock; clock.update(); // Process basic information ProcessBasic(); // Process basic task information ProcessBasicTask(); ProcessMoreTask(); // Check if everything is okay with the gps time and process it if (!FlightTimes()) { return false; } // Process extended information ProcessVertical(); // Calculate the team code CalculateOwnTeamCode(); // Calculate the bearing and range of the teammate CalculateTeammateBearingRange(); // Calculate the bearing and range of the teammate // (if teammate is a FLARM target) FLARM_ScanTraffic(); vegavoice.Update(&Basic(), &Calculated(), SettingsComputer()); // Update the ConditionMonitors ConditionMonitorsUpdate(*this); SetCalculated().time_process_gps = clock.elapsed(); return true; }
/** * Renders the terrain background, the groundline and the topology * @param canvas The drawing canvas * @param rc The area to draw in */ void MapWindow::RenderMapLayer(Canvas &canvas) { m_background.sun_from_wind(projection, Basic().wind); m_background.Draw(canvas, projection, SettingsMap()); // Select black brush/pen and the MapWindowFont canvas.black_brush(); canvas.black_pen(); canvas.select(Fonts::Map); if (terrain != NULL) { if ((SettingsComputer().FinalGlideTerrain == 2) && Calculated().TerrainValid) // Draw the groundline (and shading) DrawTerrainAbove(canvas, buffer_canvas); } if (topology != NULL && SettingsMap().EnableTopology) // Draw the topology topology->Draw(canvas, bitmap_canvas, projection); }
void DeviceBlackboard::Merge() { real_data.reset(); for (unsigned i = 0; i < NUMDEV; ++i) { per_device_data[i].expire(); real_data.complement(per_device_data[i]); } if (replay_data.Connected) { replay_data.expire(); SetBasic() = replay_data; } else if (simulator_data.Connected) { simulator_data.expire(); SetBasic() = simulator_data; } else { SetBasic() = real_data; } computer.Fill(SetBasic(), SettingsComputer()); ProcessFLARM(); if (last_location_available != Basic().LocationAvailable) { last_location_available = Basic().LocationAvailable; TriggerGPSUpdate(); } else if (last_vario_counter != Basic().VarioCounter) { last_vario_counter = Basic().VarioCounter; TriggerGPSUpdate(); } if (last_te_vario_available != Basic().TotalEnergyVarioAvailable || last_netto_vario_available != Basic().NettoVarioAvailable) { last_te_vario_available = Basic().TotalEnergyVarioAvailable; last_netto_vario_available = Basic().NettoVarioAvailable; TriggerVarioUpdate(); } }
void GlueMapWindow::QuickRedraw(const SETTINGS_MAP &_settings_map) { assert(&_settings_map != &SettingsMap()); ReadSettingsMap(_settings_map); /* update the Projection */ visible_projection.CalculateOrigin(get_client_rect(), Basic(), Calculated(), SettingsComputer(), SettingsMap()); visible_projection.ExchangeBlackboard(Calculated(), SettingsMap()); ++ui_generation; /* quickly stretch the existing buffer into the window */ scale_buffer = 2; invalidate(); }
void XCSoarInterface::AfterStartup() { static bool first = true; if (!first) { return; } first = false; StartupStore(TEXT("ProgramStarted=3\n")); StartupLogFreeRamAndStorage(); status_messages.Startup(true); if (is_simulator()) { StartupStore(TEXT("GCE_STARTUP_SIMULATOR\n")); InputEvents::processGlideComputer(GCE_STARTUP_SIMULATOR); } else { StartupStore(TEXT("GCE_STARTUP_REAL\n")); InputEvents::processGlideComputer(GCE_STARTUP_REAL); } // Create default task if none exists StartupStore(TEXT("Create default task\n")); task.DefaultTask(SettingsComputer()); StartupStore(TEXT("CloseProgressDialog\n")); CloseProgressDialog(); main_window.full_screen(); InfoBoxManager::SetDirty(true); TriggerAll(); status_messages.Startup(false); #ifdef _INPUTDEBUG_ InputEvents::showErrors(); #endif }
void MapWindow::CalculateScreenPositionsGroundline(void) { if (SettingsComputer().FinalGlideTerrain) { LonLat2Screen(Calculated().GlideFootPrint, Groundline, NUMTERRAINSWEEPS+1, 1); } }
void XCSoarInterface::Shutdown(void) { CreateProgressDialog(gettext(TEXT("Shutdown, please wait..."))); StartHourglassCursor(); StartupStore(TEXT("Entering shutdown...\n")); StartupLogFreeRamAndStorage(); // turn off all displays globalRunningEvent.reset(); StartupStore(TEXT("dlgAirspaceWarningDeInit\n")); dlgAirspaceWarningDeInit(); CreateProgressDialog(gettext(TEXT("Shutdown, saving logs..."))); // stop logger logger.guiStopLogger(Basic(),true); CreateProgressDialog(gettext(TEXT("Shutdown, saving profile..."))); // Save settings Profile::StoreRegistry(); // Stop sound StartupStore(TEXT("SaveSoundSettings\n")); Profile::SaveSoundSettings(); #ifndef DISABLEAUDIOVARIO // VarioSound_EnableSound(false); // VarioSound_Close(); #endif // Stop drawing CreateProgressDialog(gettext(TEXT("Shutdown, please wait..."))); StartupStore(TEXT("CloseDrawingThread\n")); closeTriggerEvent.trigger(); calculation_thread->join(); StartupStore(TEXT("- calculation thread returned\n")); instrument_thread->join(); StartupStore(TEXT("- instrument thread returned\n")); draw_thread->join(); StartupStore(TEXT("- draw thread returned\n")); delete draw_thread; // Clear data CreateProgressDialog(gettext(TEXT("Shutdown, saving task..."))); StartupStore(TEXT("Resume abort task\n")); task.ResumeAbortTask(SettingsComputer(), -1); // turn off abort if it was on. StartupStore(TEXT("Save default task\n")); task.SaveDefaultTask(); StartupStore(TEXT("Clear task data\n")); task.ClearTask(); StartupStore(TEXT("Close airspace\n")); CloseAirspace(); StartupStore(TEXT("Close waypoints\n")); way_points.clear(); CreateProgressDialog(gettext(TEXT("Shutdown, please wait..."))); StartupStore(TEXT("CloseTerrainTopology\n")); RASP.Close(); terrain.CloseTerrain(); delete topology; delete marks; devShutdown(); SaveCalculationsPersist(Basic(),Calculated()); #if (EXPERIMENTAL > 0) // CalibrationSave(); #endif #if defined(GNAV) && !defined(PCGNAV) StartupStore(TEXT("Altair shutdown\n")); Sleep(2500); StopHourglassCursor(); InputEvents::eventDLLExecute(TEXT("altairplatform.dll SetShutdown 1")); while(1) { Sleep(100); // free time up for processor to perform shutdown } #endif CloseFLARMDetails(); // Kill windows StartupStore(TEXT("Destroy Info Boxes\n")); InfoBoxManager::Destroy(); StartupStore(TEXT("Destroy Button Labels\n")); ButtonLabel::Destroy(); StartupStore(TEXT("Delete Objects\n")); // Kill graphics objects DeleteFonts(); DeleteAirspace(); StartupStore(TEXT("Close Progress Dialog\n")); CloseProgressDialog(); CloseGeoid(); StartupStore(TEXT("Close Windows - main \n")); main_window.reset(); StartupStore(TEXT("Close Graphics\n")); MapGfx.Destroy(); #ifdef DEBUG_TRANSLATIONS StartupStore(TEXT("Writing missing translations\n")); WriteMissingTranslations(); #endif StartupLogFreeRamAndStorage(); StartupStore(TEXT("Finished shutdown\n")); StopHourglassCursor(); }
/** * "Boots" up XCSoar * @param hInstance Instance handle * @param lpCmdLine Command line string * @return True if bootup successful, False otherwise */ bool XCSoarInterface::Startup(HINSTANCE hInstance, LPTSTR lpCmdLine) { // The title bar text TCHAR szTitle[MAX_LOADSTRING]; // Store instance handle in our global variable hInst = hInstance; // IDS_APP_TITLE = XCSoar (see XCSoar.rc) LoadString(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING); //If it is already running, then focus on the window if (MainWindow::find(szTitle)) return false; // Send the SettingsMap to the DeviceBlackboard SendSettingsMap(); // Register window classes PaintWindow::register_class(hInst); MainWindow::register_class(hInst); MapWindow::register_class(hInst); // Fill the fast(co)sine table InitSineTable(); PreloadInitialisation(true); // Send the SettingsMap to the DeviceBlackboard SendSettingsMap(); // Creates the main window StartupStore(TEXT("Create main window\n")); RECT WindowSize = SystemWindowSize(); main_window.set(szTitle, WindowSize.left, WindowSize.top, WindowSize.right, WindowSize.bottom); if (!main_window.defined()) { return false; } main_window.install_timer(); // Initialize DeviceBlackboard device_blackboard.Initialise(); // Initialize Marks marks = new Marks("xcsoar-marks"); topology = new TopologyStore(marks->GetTopology()); // Show the main and map windows StartupStore(TEXT("Create map window\n")); main_window.show(); main_window.map.show(); #ifdef HAVE_ACTIVATE_INFO SHSetAppKeyWndAssoc(VK_APP1, main_window); SHSetAppKeyWndAssoc(VK_APP2, main_window); SHSetAppKeyWndAssoc(VK_APP3, main_window); SHSetAppKeyWndAssoc(VK_APP4, main_window); // Typical Record Button // Why you can't always get this to work // http://forums.devbuzz.com/m_1185/mpage_1/key_/tm.htm // To do with the fact it is a global hotkey, but you can with code above // Also APPA is record key on some systems SHSetAppKeyWndAssoc(VK_APP5, main_window); SHSetAppKeyWndAssoc(VK_APP6, main_window); #endif // Initialize main blackboard data task.ClearTask(); glide_computer.Initialise(); logger.LinkGRecordDLL(); // try to link DLL if it exists // Load the EGM96 geoid data OpenGeoid(); PreloadInitialisation(false); Profile::LoadWindFromRegistry(); // TODO TB: seems to be out of date?! CalculateNewPolarCoef(); // Calculate polar-related data and saves it to the cache StartupStore(TEXT("GlidePolar::UpdatePolar\n")); GlidePolar::UpdatePolar(false, SettingsComputer()); // Show startup info depending on device StartupInfo(); // Read the topology file(s) topology->Open(); // Read the terrain file terrain.OpenTerrain(); // Read the waypoint files ReadWayPoints(way_points, terrain); // Read and parse the airfield info file ReadAirfieldFile(); // Set the home waypoint SetHome(way_points, terrain, SetSettingsComputer(), false, true); // ReSynchronise the blackboards here since SetHome touches them ReadBlackboardBasic(device_blackboard.Basic()); terrain.ServiceFullReload(Basic().Location); // Scan for weather forecast CreateProgressDialog(gettext(TEXT("Scanning weather forecast"))); StartupStore(TEXT("RASP load\n")); RASP.ScanAll(Basic().Location); // Reads the airspace files ReadAirspace(); // Sorts the airspaces by priority SortAirspace(); // Read the FLARM details file OpenFLARMDetails(); #ifndef DISABLEAUDIOVARIO /* VarioSound_Init(); VarioSound_EnableSound(EnableSoundVario); VarioSound_SetVdead(SoundDeadband); VarioSound_SetV(0); VarioSound_SetSoundVolume(SoundVolume); */ #endif // Start the device thread(s) CreateProgressDialog(gettext(TEXT("Starting devices"))); devStartup(lpCmdLine); // Reset polar in case devices need the data StartupStore(TEXT("GlidePolar::UpdatePolar\n")); GlidePolar::UpdatePolar(true, SettingsComputer()); CreateProgressDialog(gettext(TEXT("Initialising display"))); // Finally ready to go.. all structures must be present before this. // Create the drawing thread StartupStore(TEXT("CreateDrawingThread\n")); draw_thread = new DrawThread(main_window.map, main_window.flarm); draw_thread->start(); // Show the infoboxes StartupStore(TEXT("ShowInfoBoxes\n")); InfoBoxManager::Show(); // Create the calculation thread StartupStore(TEXT("CreateCalculationThread\n")); CreateCalculationThread(); #ifdef NEWTASK { // NEWTASK PeriodClock t; t.reset(); t.update(); CreateProgressDialog(gettext(TEXT("Running test 0"))); test_newtask(0); StartupStore(TEXT("test 0 %d\n"),t.elapsed()); /* t.update(); CreateProgressDialog(gettext(TEXT("Running test 1"))); test_newtask(1); StartupStore(TEXT("test 1 %d\n"),t.elapsed()); t.update(); CreateProgressDialog(gettext(TEXT("Running test 2"))); test_newtask(2); StartupStore(TEXT("test 2 %d\n"),t.elapsed()); t.update(); CreateProgressDialog(gettext(TEXT("Running test 3"))); test_newtask(3); StartupStore(TEXT("test 3 %d\n"),t.elapsed()); t.update(); CreateProgressDialog(gettext(TEXT("Running test 4"))); test_newtask(4); StartupStore(TEXT("test 4 %d\n"),t.elapsed()); */ CreateProgressDialog(gettext(TEXT("test complete"))); } #endif // Initialise the airspace warning dialog StartupStore(TEXT("dlgAirspaceWarningInit\n")); dlgAirspaceWarningInit(); // Find unique ID of this PDA ReadAssetNumber(); StartupStore(TEXT("ProgramStarted\n")); // Give focus to the map main_window.map.set_focus(); // Start calculation thread calculation_thread->start(); // Start instrument thread instrument_thread->start(); globalRunningEvent.trigger(); return true; }
void MapWindow::DrawFlightMode(Canvas &canvas, const RECT rc) { static bool flip= true; static double LastTime = 0; bool drawlogger = true; static bool lastLoggerActive=false; int offset = -1; if (!Appearance.DontShowLoggerIndicator){ // has GPS time advanced? if(Basic().Time <= LastTime) { LastTime = Basic().Time; } else { flip = !flip; // don't bother drawing logger if not active for more than one second if ((!logger.isLoggerActive())&&(!lastLoggerActive)) { drawlogger = false; } lastLoggerActive = logger.isLoggerActive(); } if (drawlogger) { offset -= 7; draw_masked_bitmap(canvas, (logger.isLoggerActive() && flip) ? MapGfx.hLogger : MapGfx.hLoggerOff, rc.right + IBLSCALE(offset + Appearance.FlightModeOffset.x), rc.bottom + IBLSCALE(-7 + Appearance.FlightModeOffset.y), 7, 7, false); } } if (Appearance.FlightModeIcon == apFlightModeIconDefault){ Bitmap *bmp; if (task.isTaskAborted()) { bmp = &MapGfx.hAbort; } else if (DisplayMode == dmCircling) { bmp = &MapGfx.hClimb; } else if (DisplayMode == dmFinalGlide) { bmp = &MapGfx.hFinalGlide; } else { bmp = &MapGfx.hCruise; } offset -= 24; draw_masked_bitmap(canvas, *bmp, rc.right + IBLSCALE(offset - 1 + Appearance.FlightModeOffset.x), rc.bottom + IBLSCALE(-20 - 1 + Appearance.FlightModeOffset.y), 24, 20, false); } else if (Appearance.FlightModeIcon == apFlightModeIconAltA){ #define SetPoint(Idx,X,Y) Arrow[Idx].x = X; Arrow[Idx].y = Y POINT Arrow[3]; POINT Center; Center.x = rc.right-10; Center.y = rc.bottom-10; if (DisplayMode == dmCircling) { SetPoint(0, Center.x, Center.y-IBLSCALE(4)); SetPoint(1, Center.x-IBLSCALE(8), Center.y+IBLSCALE(4)); SetPoint(2, Center.x+IBLSCALE(8), Center.y+IBLSCALE(4)); } else if (DisplayMode == dmFinalGlide) { SetPoint(0, Center.x, Center.y+IBLSCALE(4)); SetPoint(1, Center.x-IBLSCALE(8), Center.y-IBLSCALE(4)); SetPoint(2, Center.x+IBLSCALE(8), Center.y-IBLSCALE(4)); } else { SetPoint(0, Center.x+IBLSCALE(4), Center.y); SetPoint(1, Center.x-IBLSCALE(4), Center.y+IBLSCALE(8)); SetPoint(2, Center.x-IBLSCALE(4), Center.y-IBLSCALE(8)); } if (task.isTaskAborted()) canvas.select(MapGfx.hBrushFlyingModeAbort); else canvas.select(MapGfx.hbCompass); canvas.select(MapGfx.hpCompassBorder); canvas.polygon(Arrow, 3); canvas.select(MapGfx.hpCompass); canvas.polygon(Arrow, 3); } if (!Appearance.DontShowAutoMacCready && SettingsComputer().AutoMacCready) { offset -= 24; //changed draw mode & icon for higher opacity 12aug -st draw_masked_bitmap(canvas, MapGfx.hAutoMacCready, rc.right + IBLSCALE(offset - 3 + Appearance.FlightModeOffset.x), rc.bottom + IBLSCALE(-20 - 3 + Appearance.FlightModeOffset.y), 24, 20, false); }; }
void InfoBoxFormatter::AssignValue(int i) { switch (i) { case 0: Value = ALTITUDEMODIFY*Basic().Altitude; break; case 1: Value = ALTITUDEMODIFY*Calculated().AltitudeAGL ; Valid = Calculated().TerrainValid; break; case 2: Value = LIFTMODIFY*Calculated().Average30s; break; case 3: Value = Calculated().WaypointBearing; Valid = Calculated().WaypointDistance > 10.0; break; case 4: if (Calculated().LD== 999) { Valid = false; } else { Valid = true; Value = Calculated().LD; } break; case 5: if (Calculated().CruiseLD== 999) { Valid = false; } else { Valid = true; Value = Calculated().CruiseLD; } break; case 6: Value = SPEEDMODIFY*Basic().Speed; break; case 7: Value = LIFTMODIFY*Calculated().LastThermalAverage; break; case 8: Value = ALTITUDEMODIFY*Calculated().LastThermalGain; break; case 10: Value = iround(LIFTMODIFY*GlidePolar::GetMacCready()*10)/10.0; break; case 11: Value = DISTANCEMODIFY*Calculated().WaypointDistance; Valid = task.ValidTaskPoint(task.getActiveIndex()); break; case 12: Value = ALTITUDEMODIFY*Calculated().NextAltitudeDifference; Valid = task.ValidTaskPoint(task.getActiveIndex()); break; case 13: Value = ALTITUDEMODIFY*Calculated().NextAltitudeRequired; Valid = task.ValidTaskPoint(task.getActiveIndex()); break; case 14: Value = 0; // Next Waypoint Text break; case 15: Value = ALTITUDEMODIFY*Calculated().TaskAltitudeDifference; Valid = task.ValidTaskPoint(task.getActiveIndex()); break; case 16: Value = ALTITUDEMODIFY*Calculated().TaskAltitudeRequired; Valid = task.ValidTaskPoint(task.getActiveIndex()); break; case 17: Value = TASKSPEEDMODIFY*Calculated().TaskSpeed; if (task.getActiveIndex()>=1) { Valid = task.ValidTaskPoint(task.getActiveIndex()); } else { Valid = false; } break; case 18: if (Calculated().ValidFinish) { Value = DISTANCEMODIFY*Calculated().WaypointDistance; } else { Value = DISTANCEMODIFY*Calculated().TaskDistanceToGo; } Valid = task.ValidTaskPoint(task.getActiveIndex()); break; case 19: if (Calculated().LDFinish== 999) { Valid = false; } else { Valid = task.ValidTaskPoint(task.getActiveIndex()); if (Calculated().ValidFinish) { Value = 0; } else { Value = Calculated().LDFinish; } } break; case 20: Value = ALTITUDEMODIFY*Calculated().TerrainAlt ; Valid = Calculated().TerrainValid; break; case 21: Value = LIFTMODIFY*Calculated().AverageThermal; break; case 22: Value = ALTITUDEMODIFY*Calculated().ThermalGain; break; case 23: Value = Basic().TrackBearing; break; case 24: if (Basic().VarioAvailable) { Value = LIFTMODIFY*Basic().Vario; } else { Value = LIFTMODIFY*Calculated().Vario; } break; case 25: Value = SPEEDMODIFY*Calculated().WindSpeed; break; case 26: Value = Calculated().WindBearing; break; case 28: Value = DISTANCEMODIFY*Calculated().AATMaxDistance ; Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled; break; case 29: Value = DISTANCEMODIFY*Calculated().AATMinDistance ; Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled; break; case 30: Value = TASKSPEEDMODIFY*Calculated().AATMaxSpeed; Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled; if (Calculated().AATTimeToGo<1) { Valid = false; } break; case 31: Value = TASKSPEEDMODIFY*Calculated().AATMinSpeed; Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled; if (Calculated().AATTimeToGo<1) { Valid = false; } break; case 32: Valid = Basic().AirspeedAvailable; Value = SPEEDMODIFY*Basic().IndicatedAirspeed; break; case 33: Valid = Basic().BaroAltitudeAvailable; Value = ALTITUDEMODIFY*Basic().BaroAltitude; break; case 34: Value = SPEEDMODIFY*Calculated().VMacCready; break; case 35: Value = Calculated().PercentCircling; break; case 37: Valid = Basic().AccelerationAvailable; Value = Basic().Gload; break; case 38: if (Calculated().LDNext== 999) { Valid = false; } else { Valid = task.ValidTaskPoint(task.getActiveIndex()); Value = Calculated().LDNext; } break; case 43: // Valid = Basic().AirspeedAvailable; Value = Calculated().VOpt*SPEEDMODIFY; break; case 44: // Valid = Basic().AirspeedAvailable; Value = Calculated().NettoVario*LIFTMODIFY; break; case 48: Value = Basic().OutsideAirTemperature; break; case 49: Value = Basic().RelativeHumidity; break; case 50: Value = CuSonde::maxGroundTemperature; break; case 51: Value = DISTANCEMODIFY*Calculated().AATTargetDistance ; Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled; break; case 52: Value = TASKSPEEDMODIFY*Calculated().AATTargetSpeed; Valid = task.ValidTaskPoint(task.getActiveIndex()) && task.getSettings().AATEnabled; if (Calculated().AATTimeToGo<1) { Valid = false; } break; case 53: if (Calculated().LDvario== 999) { Valid = false; } else { Valid = Basic().VarioAvailable && Basic().AirspeedAvailable; Value = Calculated().LDvario; } break; case 54: Valid = Basic().AirspeedAvailable; Value = SPEEDMODIFY*Basic().TrueAirspeed; break; case 56: // team bearing Value = Calculated().TeammateBearing; Valid = true; case 58: // team range if (SettingsComputer().TeammateCodeValid) { Value = DISTANCEMODIFY*Calculated().TeammateRange; if (Value > 100) { _tcscpy(Format, _T("%.0lf")); } else { _tcscpy(Format, _T("%.1lf")); } Valid = true; } else { Valid = false; } break; case 59: Value = TASKSPEEDMODIFY*Calculated().TaskSpeedInstantaneous; if (task.getActiveIndex()>=1) { Valid = task.ValidTaskPoint(task.getActiveIndex()); } else { Valid = false; } break; case 60: Value = DISTANCEMODIFY*Calculated().HomeDistance ; if (SettingsComputer().HomeWaypoint>=0) { Valid = way_points.verify_index(SettingsComputer().HomeWaypoint); } else { Valid = false; } break; case 61: Value = TASKSPEEDMODIFY*Calculated().TaskSpeedAchieved; if (task.getActiveIndex()>=1) { Valid = task.ValidTaskPoint(task.getActiveIndex()); } else { Valid = false; } break; case 63: if (Calculated().timeCircling>0) { Value = LIFTMODIFY*Calculated().TotalHeightClimb /Calculated().timeCircling; Valid = true; } else { Value = 0.0; Valid = false; } break; case 64: Value = LIFTMODIFY*Calculated().DistanceVario; if (task.getActiveIndex()>=1) { Valid = task.ValidTaskPoint(task.getActiveIndex()); } else { Valid = false; } break; case 65: // battery voltage #if !defined(WINDOWSPC) && !defined(HAVE_POSIX) if (!is_altair()) { Value = PDABatteryPercent; Valid = true; } else { Value = Basic().SupplyBatteryVoltage; if (Value>0.0) { Valid = true; } else { Valid = false; } } #else Value = 0.0; Valid = false; #endif break; case 66: // VENTA-ADDON added GR Final if (Calculated().GRFinish== 999) { Valid = false; } else { Valid = task.ValidTaskPoint(task.getActiveIndex()); if (Calculated().ValidFinish) { Value = 0; } else { Value = Calculated().GRFinish; if (Value >100 ) { _tcscpy(Format, _T("%1.0f")); } else { _tcscpy(Format, _T("%1.1f")); } } } break; case 70: // VENTA3 QFE // Valid = Basic().Altitude; Value = ALTITUDEMODIFY* (Basic().Altitude-QFEAltitudeOffset); break; case 71: if ( Calculated().AverageLD == 0) { Valid = false; } else { Valid = true; Value = Calculated().AverageLD; if (Value<0) _tcscpy(Format, _T("^^^")); else if (Value>=999) _tcscpy(Format, _T("+++")); else _tcscpy(Format, _T("%2.0f")); } break; case 72: Value = Calculated().Experimental; Valid = true; break; /* TODO feature: add extra infoboxes from Lars case 68: // distance flown if (Calculated().TaskDistanceCovered != 0) { Value = DISTANCEMODIFY*Calculated().TaskDistanceCovered; Valid = true; } else { Value = 0.0; Valid = false; } break; case 67: // termik liga points if (Calculated().TermikLigaPoints != 0) { Value = Calculated().TermikLigaPoints; Valid = true; } else { Value = 0.0; Valid = false; } break; */ default: break; }; }
void GlueMapWindow::DrawMapScale(Canvas &canvas, const PixelRect &rc, const MapWindowProjection &projection) const { TCHAR buffer[80]; fixed MapWidth = projection.GetScreenWidthMeters(); canvas.select(Fonts::MapBold); Units::FormatUserMapScale(MapWidth, buffer, sizeof(buffer) / sizeof(TCHAR), true); PixelSize TextSize = canvas.text_size(buffer); int Height = Fonts::MapBold.get_capital_height() + Layout::Scale(2); // 2: add 1pix border canvas.fill_rectangle(Layout::Scale(4), rc.bottom - Height, TextSize.cx + Layout::Scale(11), rc.bottom, COLOR_WHITE); canvas.background_transparent(); canvas.set_text_color(COLOR_BLACK); canvas.text(Layout::Scale(7), rc.bottom - Fonts::MapBold.get_ascent_height() - Layout::Scale(1), buffer); Graphics::hBmpMapScaleLeft.draw(canvas, 0, rc.bottom - Height); Graphics::hBmpMapScaleRight.draw(canvas, Layout::Scale(9) + TextSize.cx, rc.bottom - Height); buffer[0] = '\0'; if (SettingsMap().AutoZoom) _tcscat(buffer, _T("AUTO ")); switch (follow_mode) { case FOLLOW_SELF: break; case FOLLOW_PAN: _tcscat(buffer, _T("PAN ")); break; } const UIState &ui_state = CommonInterface::GetUIState(); if (ui_state.auxiliary_enabled) { _tcscat(buffer, InfoBoxManager::GetCurrentPanelName()); _tcscat(buffer, _T(" ")); } if (Basic().gps.replay) _tcscat(buffer, _T("REPLAY ")); else if (Basic().gps.simulator) { _tcscat(buffer, _("Simulator")); _tcscat(buffer, _T(" ")); } if (SettingsComputer().BallastTimerActive) { TCHAR TEMP[20]; _stprintf(TEMP, _T("BALLAST %d LITERS "), (int)SettingsComputer().glide_polar_task.GetBallastLitres()); _tcscat(buffer, TEMP); } if (weather != NULL && weather->GetParameter() > 0) { const TCHAR *label = weather->ItemLabel(weather->GetParameter()); if (label != NULL) _tcscat(buffer, label); } if (buffer[0]) { int y = rc.bottom - Height; canvas.select(Fonts::Title); canvas.background_opaque(); canvas.set_background_color(COLOR_WHITE); canvas.text(0, y - canvas.text_size(buffer).cy, buffer); } }
/** * "Boots" up XCSoar * @param hInstance Instance handle * @param lpCmdLine Command line string * @return True if bootup successful, False otherwise */ bool XCSoarInterface::Startup(HINSTANCE hInstance) { // Set the application title to "XCSoar" TCHAR szTitle[] = _T("XCSoar"); // Store instance handle in our global variable #ifdef WIN32 ResourceLoader::Init(hInstance); #endif //If "XCSoar" is already running, stop this instance if (MainWindow::find(szTitle)) return false; // Register window classes PaintWindow::register_class(hInstance); MainWindow::register_class(hInstance); // Creates the main window LogStartUp(_T("Create main window")); PixelRect WindowSize = SystemWindowSize(); main_window.set(szTitle, WindowSize.left, WindowSize.top, WindowSize.right, WindowSize.bottom); if (!main_window.defined()) return false; main_window.Initialise(); #ifdef SIMULATOR_AVAILABLE // prompt for simulator if not set by command line argument "-simulator" or "-fly" if (!sim_set_in_cmd_line_flag) { SimulatorPromptResult result = dlgSimulatorPromptShowModal(); switch (result) { case SPR_QUIT: return false; case SPR_FLY: global_simulator_flag = false; break; case SPR_SIMULATOR: global_simulator_flag = true; break; } } #endif if (!LoadProfile()) return false; ProgressGlue::Create(_("Initialising")); LoadDisplayOrientation(); main_window.InitialiseConfigured(); TCHAR path[MAX_PATH]; LocalPath(path, _T("cache")); file_cache = new FileCache(path); Graphics::InitialiseConfigured(SettingsMap()); ReadLanguageFile(); status_messages.LoadFile(); InputEvents::readFile(); // Initialize DeviceBlackboard device_blackboard.Initialise(); // Initialize Marks marks = new Marks(); // Send the SettingsMap to the DeviceBlackboard SendSettingsMap(); // Show the main and map windows LogStartUp(_T("Create map window")); main_window.show(); main_window.map.show(); #ifdef HAVE_AYGSHELL_DLL const AYGShellDLL &ayg = main_window.ayg_shell_dll; ayg.SHSetAppKeyWndAssoc(VK_APP1, main_window); ayg.SHSetAppKeyWndAssoc(VK_APP2, main_window); ayg.SHSetAppKeyWndAssoc(VK_APP3, main_window); ayg.SHSetAppKeyWndAssoc(VK_APP4, main_window); // Typical Record Button // Why you can't always get this to work // http://forums.devbuzz.com/m_1185/mpage_1/key_/tm.htm // To do with the fact it is a global hotkey, but you can with code above // Also APPA is record key on some systems ayg.SHSetAppKeyWndAssoc(VK_APP5, main_window); ayg.SHSetAppKeyWndAssoc(VK_APP6, main_window); #endif // Initialize main blackboard data task_manager = new TaskManager(task_events, way_points); task_manager->reset(); protected_task_manager = new ProtectedTaskManager(*task_manager, XCSoarInterface::SettingsComputer(), task_events, airspace_database); airspace_warning = new AirspaceWarningManager(airspace_database, *task_manager); airspace_warnings = new ProtectedAirspaceWarningManager(*airspace_warning); // Read the terrain file ProgressGlue::Create(_("Loading Terrain File...")); LogStartUp(_T("OpenTerrain")); terrain = RasterTerrain::OpenTerrain(file_cache); glide_computer = new GlideComputer(way_points, *protected_task_manager, *airspace_warnings, task_events); glide_computer->set_terrain(terrain); glide_computer->SetLogger(&logger); glide_computer->Initialise(); replay = new Replay(*protected_task_manager); // Load the EGM96 geoid data OpenGeoid(); GlidePolar &gp = SetSettingsComputer().glide_polar_task; gp = GlidePolar(fixed_zero); PolarGlue::LoadFromProfile(gp, SetSettingsComputer()); task_manager->set_glide_polar(gp); task_manager->set_contest(SettingsComputer().contest); // Read the topography file(s) topography = new TopographyStore(); LoadConfiguredTopography(*topography); // Read the waypoint files WayPointGlue::LoadWaypoints(way_points, terrain); // Read and parse the airfield info file ReadAirfieldFile(way_points); // Set the home waypoint WayPointGlue::SetHome(way_points, terrain, SetSettingsComputer(), false); // ReSynchronise the blackboards here since SetHome touches them ReadBlackboardBasic(device_blackboard.Basic()); // Scan for weather forecast ProgressGlue::Create(_("Scanning weather forecast")); LogStartUp(_T("RASP load")); RASP.ScanAll(Basic().Location); // Reads the airspace files ReadAirspace(airspace_database, terrain, SettingsComputer().pressure); const AIRCRAFT_STATE aircraft_state = ToAircraftState(device_blackboard.Basic(), device_blackboard.Calculated()); airspace_warning->reset(aircraft_state); airspace_warning->set_config(CommonInterface::SettingsComputer().airspace.warnings); // Read the FLARM details file FlarmDetails::Load(); #ifndef DISABLEAUDIOVARIO /* VarioSound_Init(); VarioSound_EnableSound(EnableSoundVario); VarioSound_SetVdead(SoundDeadband); VarioSound_SetV(0); VarioSound_SetSoundVolume(SoundVolume); */ #endif // Start the device thread(s) ProgressGlue::Create(_("Starting devices")); devStartup(); /* -- Reset polar in case devices need the data LogStartUp(_T("GlidePolar::UpdatePolar")); GlidePolar::UpdatePolar(true, SettingsComputer()); This should be done inside devStartup if it is really required */ ProgressGlue::Create(_("Initialising display")); main_window.map.set_way_points(&way_points); main_window.map.set_task(protected_task_manager); main_window.map.set_airspaces(&airspace_database, airspace_warnings); main_window.map.set_topography(topography); main_window.map.set_terrain(terrain); main_window.map.set_weather(&RASP); main_window.map.set_marks(marks); main_window.map.SetLogger(&logger); // Finally ready to go.. all structures must be present before this. // Create the drawing thread #ifndef ENABLE_OPENGL LogStartUp(_T("CreateDrawingThread")); draw_thread = new DrawThread(main_window.map, main_window.flarm, main_window.ta); draw_thread->start(); #endif // Show the infoboxes LogStartUp(_T("ShowInfoBoxes")); InfoBoxManager::Show(); // Create the calculation thread LogStartUp(_T("CreateCalculationThread")); CreateCalculationThread(); // Find unique ID of this PDA ReadAssetNumber(); LogStartUp(_T("ProgramStarted")); // Give focus to the map main_window.map.set_focus(); Pages::LoadFromProfile(); // Start calculation thread calculation_thread->start(); globalRunningEvent.trigger(); AfterStartup(); #ifndef ENABLE_OPENGL draw_thread->resume(); #endif return true; }