Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 28 additions & 14 deletions vSMR/Rimcas.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "stdafx.h"
#include "Rimcas.hpp"
#include "SMRRadar.hpp"
#include "Logger.h"

CRimcas::CRimcas() {}
Expand Down Expand Up @@ -234,8 +235,7 @@ void CRimcas::OnRefreshEnd(CRadarScreen *instance, int threshold) {

bool isAnotherAcApproaching = ApproachingAircrafts.count(it->first) > 0;

if (AcOnRunway.count(it->first) > 1 || isOnClosedRunway ||
isAnotherAcApproaching) {
if (AcOnRunway.count(it->first) > 1 || isOnClosedRunway || (AcOnRunway.count(it->first) > 0 && isAnotherAcApproaching)) {

auto AcOnRunwayRange = AcOnRunway.equal_range(it->first);

Expand Down Expand Up @@ -356,7 +356,11 @@ void CRimcas::TrackDeparture(CRadarTarget Rt, CFlightPlan fp,
string runwayArea = GetAcInRunwayArea(Rt, instance);
bool onRunway = (runwayArea != string_false);

if (onRunway && DepartedAircraft.find(callsign) == DepartedAircraft.end()) {
// Only add if the aircraft is on its assigned departure runway, not crossing another
string depRwy = fp.GetFlightPlanData().GetDepartureRwy();
bool onDepartureRunway = onRunway && depRwy.length() > 0 && runwayArea.find(depRwy) != string::npos;

if (onDepartureRunway && DepartedAircraft.find(callsign) == DepartedAircraft.end()) {
DepartureInfo info;
info.callsign = callsign;
if (info.callsign.length() > 8) {
Expand All @@ -375,12 +379,13 @@ void CRimcas::TrackDeparture(CRadarTarget Rt, CFlightPlan fp,
info.wakeTurbCat = "";
info.wakeTurbCat += fp.GetFlightPlanData().GetAircraftWtc();

info.airborneFreq = fp.GetControllerAssignedData().GetFlightStripAnnotation(8);
if (info.airborneFreq.length() == 0) {
info.airborneFreq = "QSY";
}
if (info.airborneFreq.length() > 7) {
info.airborneFreq = info.airborneFreq.substr(0, 7);
info.airborneFreq = "QSY";
// Get frequency from UKCP integration socket
if (SMRPluginSharedData::ukcpIntegration != nullptr) {
std::string ukcpFreq = SMRPluginSharedData::ukcpIntegration->GetDepartureFrequency(callsign);
if (!ukcpFreq.empty()) {
info.airborneFreq = ukcpFreq;
}
}

info.groundAltitude = Rt.GetPosition().GetPressureAltitude();
Expand All @@ -394,11 +399,20 @@ void CRimcas::TrackDeparture(CRadarTarget Rt, CFlightPlan fp,
// Update and start timer once aircraft is airborne
if (DepartedAircraft.find(callsign) != DepartedAircraft.end()) {
DepartureInfo &info = DepartedAircraft[callsign];

// (always check for updates)
if (SMRPluginSharedData::ukcpIntegration != nullptr) {
std::string ukcpFreq = SMRPluginSharedData::ukcpIntegration->GetDepartureFrequency(callsign);
if (!ukcpFreq.empty()) {
info.airborneFreq = ukcpFreq;
}
}

int currentAltitude = Rt.GetPosition().GetPressureAltitude();

// Remove aircraft if above 6000 feet
if (currentAltitude > 6000) {
Logger::info("TrackDeparture: Removing " + callsign + " - above 6000ft (alt=" + std::to_string(currentAltitude) + ")");
// Remove aircraft if above 11000 feet
if (currentAltitude > 11000) {
Logger::info("TrackDeparture: Removing " + callsign + " - above 11000ft (alt=" + std::to_string(currentAltitude) + ")");
DepartedAircraft.erase(callsign);
return;
}
Expand Down Expand Up @@ -429,9 +443,9 @@ void CRimcas::UpdateDepartureTimer(int departureDisplayDurationSecs, CRadarScree
continue;
}

// Remove if above 6000 feet
// Remove if above 11000 feet
CRadarTarget rt = instance->GetPlugIn()->RadarTargetSelect(pair.first.c_str());
if (rt.IsValid() && rt.GetPosition().GetPressureAltitude() > 6000) {
if (rt.IsValid() && rt.GetPosition().GetPressureAltitude() > 11000) {
toRemove.push_back(pair.first);
continue;
}
Expand Down
3 changes: 2 additions & 1 deletion vSMR/Rimcas.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ class CRimcas {
string wakeTurbCat = "";
string airborneFreq = ""; // QSY frequency
clock_t liftoffTime = 0;
bool dismissed = false;
bool handedOff = false; // First click: mark as handed off (green)
bool dismissed = false; // Second click: remove from list
int groundAltitude = 0; // Altitude when on ground
bool timerStarted = false; // Whether timer has begun
};
Expand Down
15 changes: 14 additions & 1 deletion vSMR/SMRPlugin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,7 @@ CSMRPlugin::CSMRPlugin(void) :CPlugIn(EuroScopePlugIn::COMPATIBILITY_CODE, MY_PL
{

Logger::DLL_PATH = "";
Logger::ENABLED = true;
Logger::ENABLED = false;

//
// Adding the SMR Display type
Expand Down Expand Up @@ -334,6 +334,12 @@ CSMRPlugin::CSMRPlugin(void) :CPlugIn(EuroScopePlugIn::COMPATIBILITY_CODE, MY_PL
DllPath = DllPathFile;
DllPath.resize(DllPath.size() - strlen("vSMR.dll"));
Logger::DLL_PATH = DllPath;

// Start UKCP integration socket client
if (SMRPluginSharedData::ukcpIntegration == nullptr) {
SMRPluginSharedData::ukcpIntegration = new UKCPIntegration();
}
SMRPluginSharedData::ukcpIntegration->Start();
}

CSMRPlugin::~CSMRPlugin()
Expand All @@ -350,6 +356,13 @@ CSMRPlugin::~CSMRPlugin()
{
io_service.stop();
//vStripsThread.join();

// Stop UKCP integration
if (SMRPluginSharedData::ukcpIntegration != nullptr) {
SMRPluginSharedData::ukcpIntegration->Stop();
delete SMRPluginSharedData::ukcpIntegration;
SMRPluginSharedData::ukcpIntegration = nullptr;
}
}
catch (std::exception& e)
{
Expand Down
31 changes: 24 additions & 7 deletions vSMR/SMRRadar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -815,12 +815,19 @@ void CSMRRadar::OnClickScreenObject(int ObjectType, const char *sObjectId,
getActiveAirport().c_str());
}

// Handle click on QSY to dismiss the aircraft
// Handle click on QSY - two stage: first marks handed off (green), second dismisses
if (ObjectType == RIMCAS_DEP_WINDOW_QSY) {
string idStr(sObjectId);
if (idStr.length() > 4 && idStr.substr(0, 4) == "QSY_") {
string callsign = idStr.substr(4);
RimcasInstance->DismissDeparture(callsign);
auto it = RimcasInstance->DepartedAircraft.find(callsign);
if (it != RimcasInstance->DepartedAircraft.end()) {
if (!it->second.handedOff) {
it->second.handedOff = true;
} else {
RimcasInstance->DismissDeparture(callsign);
}
}
RequestRefresh();
}
}
Expand Down Expand Up @@ -3243,7 +3250,11 @@ void CSMRRadar::OnRefresh(HDC hDC, int Phase) {

// Draw each enabled column
if (depWindowShowCallsign) {
dc.TextOutA(rowX, rowY, info.callsign.c_str());
string displayCallsign = info.callsign;
if (info.timerStarted) {
displayCallsign = "^ " + displayCallsign;
}
dc.TextOutA(rowX, rowY, displayCallsign.c_str());
rowX += colCallsignWidth + colPadding;
}

Expand Down Expand Up @@ -3272,20 +3283,26 @@ void CSMRRadar::OnRefresh(HDC hDC, int Phase) {
if (depWindowShowFreq) {
CRect qsyRect = {rowX, rowY, rowX + colFreqWidth, rowY + TextHeight};

// Draw box around QSY button
CPen ButtonPen(PS_SOLID, 1, RGB(100, 100, 100));
// Draw box around QSY button - bright green fill if handed off
COLORREF boxColor = info.handedOff ? RGB(0, 255, 0) : RGB(100, 100, 100);
CPen ButtonPen(PS_SOLID, 1, boxColor);
CPen *oldPen = dc.SelectObject(&ButtonPen);
if (info.handedOff) {
CBrush greenBrush(RGB(0, 190, 0));
dc.FillRect(&qsyRect, &greenBrush);
}
dc.Rectangle(&qsyRect);
dc.SelectObject(oldPen);

// Right-justify the QSY text
int textWidth = dc.GetTextExtent(info.airborneFreq.c_str()).cx;
int qsyX = rowX + colFreqWidth - textWidth - 2; // -2 for padding from edge
dc.TextOutA(qsyX, rowY, info.airborneFreq.c_str());
// Make QSY clickable to dismiss
// Make QSY clickable - first click hands off, second dismisses
string qsyKey = "QSY_" + info.callsign;
const char* tooltip = info.handedOff ? "Click to dismiss" : "Click to mark handed off";
AddScreenObject(RIMCAS_DEP_WINDOW_QSY, qsyKey.c_str(), qsyRect,
true, "Click to dismiss");
true, tooltip);
rowX += colFreqWidth + colPadding;
}

Expand Down
4 changes: 3 additions & 1 deletion vSMR/SMRRadar.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "InsetWindow.h"
#include "Logger.h"
#include "Rimcas.hpp"
#include "UKCPIntegration.hpp"
#include <asio/io_service.hpp>
#include <filesystem>
#include <iostream>
Expand All @@ -37,6 +38,7 @@ static vector<string> ManuallyCorrelated;

namespace SMRPluginSharedData {
static asio::io_service io_service;
extern UKCPIntegration* ukcpIntegration; // The TCP handler is a shared resource
}

using namespace SMRSharedData;
Expand Down Expand Up @@ -106,7 +108,7 @@ class CSMRRadar : public EuroScopePlugIn::CRadarScreen {

// Departure Timer Window settings
bool showDepartureWindow = true;
int departureDisplayDuration = 180; // 3 minutes in seconds (default)
int departureDisplayDuration = 300; // 5 minutes in seconds (default)
bool depWindowShowCallsign = true;
bool depWindowShowDest = true;
bool depWindowShowAcType = true;
Expand Down
Loading
Loading