Files
qt5-legatus-legacy/Lts/Plugins/BuildingViewer/Common/bdv_controller.cpp
T
2026-08-13 18:33:10 +02:00

443 lines
13 KiB
C++
Executable File

/**
* @RDE_HEADER@
*
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Last, SLSY, 2017-08-14
*/
#include "bdv_controller.h"
#include "bdv_dds_controller.h"
#include "bdv_bgviewer_widget_container.h"
#include <LtsAppManager/lts_app_manager.h>
#include <LtsPluginManager/lts_plugin_manager.h>
#include <LtsSession/lts_session.h>
#include <Common/bdv_communication_interface_internal.h>
#include <Common/bdv_plugin_provider.h>
#include <ngltools/ngltools_filesystem.h>
#include <QDir>
#include <QMessageBox>
namespace BuildingViewer
{
static int argc_dummy = 1;
static char *argv_dummy[] = { (char*)"Dummy" };
BgViewerController::BgViewerController(QObject *parent)
: QObject(parent)
, m_mainloop(argc_dummy, argv_dummy, nullptr)
, m_widgetStolen(false)
, m_comIfc(nullptr)
, m_pBgViewerDDSController(nullptr)
, m_bgvApp(nullptr)
, m_tickTimer(new QTimer(this))
, m_logger(getLogger("BgViewerControllerSingleton"))
{
m_tickTimer->setInterval(1000 / 25); // 25fps
connect(m_tickTimer, &QTimer::timeout, this, [this]() { m_mainloop.tick(); });
m_mainloop.getViewerInterface()->getMainWindow()->setMinimumSize(200, 200);
m_viewerInterface = m_mainloop.getViewerInterface();
m_comIfc = new CommunicationInterfaceInternal(m_viewerInterface);
m_viewerInterface->SetViewerCallback(m_comIfc);
m_pBgViewerDDSController = new BuildingViewerDdsController(m_comIfc, m_viewerInterface);
connect(m_pBgViewerDDSController, &BuildingViewerDdsController::signalDdsInitFinished, this, [this]() {
m_initExerciseWasSuccessful = true;
});
connect(m_comIfc, &CommunicationInterfaceInternal::signalBgViewerInitFinished,
this, &BgViewerController::signalBgViewerInitFinished);
connect(m_comIfc, &CommunicationInterfaceInternal::signalReceivedBuildingList,
this, &BgViewerController::signalReceivedBuildingList);
connect(m_comIfc, &CommunicationInterfaceInternal::signalReceivedViewState,
this, &BgViewerController::signalReceivedViewState);
connect(m_comIfc, &CommunicationInterfaceInternal::signalPlayerPicked,
this, &BgViewerController::signalPlayerPicked);
connect(m_comIfc, &CommunicationInterfaceInternal::signalAssetPicked,
this, &BgViewerController::signalAssetPicked);
connect(m_comIfc, &CommunicationInterfaceInternal::signalViewerEventWidgetClosed,
this, &BgViewerController::signalViewerEventWidgetClosed);
connect(m_comIfc, &CommunicationInterfaceInternal::signalViewerEventWidgetMaximized,
this, &BgViewerController::signalViewerEventWidgetMaximized);
connect(m_comIfc, &CommunicationInterfaceInternal::signalViewerEventWidgetMinimized,
this, &BgViewerController::signalViewerEventWidgetMinimized);
connect(m_comIfc, &CommunicationInterfaceInternal::signalViewerEventWidgetFocused,
this, &BgViewerController::signalViewerEventWidgetFocused);
connect(m_comIfc, &CommunicationInterfaceInternal::signalViewerEventRoomNameClicked,
this, &BgViewerController::signalViewerEventRoomNameClicked);
connect(m_comIfc, &CommunicationInterfaceInternal::signalViewerZoomChanged,
this, &BgViewerController::signalViewerZoomChanged);
connect(m_comIfc, &CommunicationInterfaceInternal::signalViewerEventButton,
this, &BgViewerController::signalViewerEventButton);
}
BgViewerController::~BgViewerController()
{
delete m_tickTimer;
if (m_bgvApp != nullptr)
{
m_bgvApp->disconnect();
delete m_bgvApp;
}
delete m_pBgViewerDDSController;
delete m_comIfc;
m_bgvApp = nullptr;
m_comIfc = nullptr;
m_pBgViewerDDSController = nullptr;
}
void BgViewerController::excConnect(const std::vector<std::string> &paths, const QString &strXMLFile)
{
if (m_comIfc)
m_comIfc->excConnect(paths, strXMLFile);
}
void BgViewerController::excGetBuildingList()
{
if (m_comIfc)
m_comIfc->excGetBuildingList();
}
void BgViewerController::excGetViewState()
{
if (m_comIfc)
m_comIfc->excGetViewState();
}
void BgViewerController::excHighlightView(const QString &strFeatureID)
{
if (m_comIfc)
m_comIfc->excHighlightView(strFeatureID);
}
void BgViewerController::excRestoreViewState(const QJsonValue &state)
{
if (m_comIfc)
{
m_comIfc->excRestoreViewState(state);
m_comIfc->excGetBuildingList();
}
}
void BgViewerController::excSetGlobalDotsMode(bool useDots)
{
if (m_comIfc)
m_comIfc->excSetGlobalDotsMode(useDots);
}
void BgViewerController::excSetGlobalTransparency(double transparency)
{
if (m_comIfc)
m_comIfc->excSetGlobalTransparency(transparency);
}
void BgViewerController::excSetGlobalViewMode(bool useOrtho)
{
if (m_comIfc)
m_comIfc->excSetGlobalViewMode(useOrtho);
}
void BgViewerController::excSetHitlineDuration(uint32_t duration_s)
{
if (m_comIfc)
m_comIfc->excSetHitlineDuration(duration_s);
}
void BgViewerController::excStartRecording(const QString &strPathOutputFolder,
const QString &strFeatureID,
int w, int h, int framerate, int quality)
{
if (m_comIfc)
m_comIfc->excStartRecording(strPathOutputFolder, strFeatureID, w, h, framerate, quality);
}
void BgViewerController::excStopRecording(const QString &strFeatureID)
{
if (m_comIfc)
m_comIfc->excStopRecording(strFeatureID);
}
QString BgViewerController::buildingModelPath()
{
QVector<QString> directoriesToSearch = NGL::directories(NGL::FileType::ConfigFile);
#ifndef WIN32
directoriesToSearch += QStringLiteral("/opt");
#endif
for (const QString &d : qAsConst(directoriesToSearch))
{
const QDir dir(d + QStringLiteral("/BuildingModels/StaticMeshes/"));
if (dir.exists() && dir.isReadable())
return dir.absolutePath();
INFO_LOG(getLogger("BgViewerController")) << "Map path '" << dir.absolutePath() << "' either does not exist or is not readable - skipping";
}
return QString();
}
void BgViewerController::clearInterfaces(const LtsSession::DdsConnectionParams &conParams)
{
DEBUG_LOG(m_logger) << "BgViewerControllerSingleton::clearInterfaces()";
if (m_pBgViewerDDSController && m_currentDdsConnParams == conParams)
{
m_pBgViewerDDSController->uninitialize();
m_currentDdsConnParams = LtsSession::DdsConnectionParams();
}
}
void BgViewerController::hideLiveVideo()
{
/* if (m_pBgViewerDDSController)
if (m_pBgViewerDDSController->activeSession())
if (m_pBgViewerDDSController->activeSession()->avmDataIfc())
m_pBgViewerDDSController->activeSession()->avmDataIfc()->hideLiveVideo();
*/
// js ftw: m_pBgViewerDDSController?->activeSession()?->avmDataIfc()?->hideLiveVideo();
}
bool BgViewerController::isBgViewerApplicationRunning() const
{
return (m_bgvApp != nullptr);
}
LtsSession::DdsConnectionParams BgViewerController::currentDdsConnParams() const
{
return m_currentDdsConnParams;
}
PluginProvider *BgViewerController::activeSession() const
{
return m_pBgViewerDDSController->activeSession();
}
bool BgViewerController::init(PluginProvider *pSession, bool bStartRendering, const QString &modelPath)
{
DEBUG_LOG(m_logger) << "getDdsController init: " << pSession->toString();
if (m_currentDdsConnParams == pSession->connParams())
{
if (m_initExerciseWasSuccessful)
{
DEBUG_LOG(m_logger) << "BgViewerControllerSingleton::init Already initialized";
slotLoadBuilding();
// Already initialized
//emit signalExerciseInitializationComplete();
}
return true;
}
m_currentDdsConnParams = pSession->connParams();
m_initExerciseWasSuccessful = false;
if (!m_pBgViewerDDSController->init(m_bgViewerBaseLayoutWidget, modelPath, pSession))
return false;
if (bStartRendering)
{
m_bgvAppIsInitialized = true;
m_tickTimer->start();
}
return true;
}
bool BgViewerController::forceInit(PluginProvider *pSession)
{
delete m_pBgViewerDDSController;
m_pBgViewerDDSController = new BuildingViewerDdsController(m_comIfc, m_viewerInterface);
DEBUG_LOG(m_logger) << "FORCE INIT! with " << pSession;
return (m_pBgViewerDDSController->init(m_bgViewerBaseLayoutWidget, buildingModelPath(), pSession));
}
void BgViewerController::showBgViewerInfoMessageBox()
{
static bool showMsgBox = true;
if (!showMsgBox)
return;
QMessageBox msgbox;
msgbox.setText(tr("BuildingViewer is currently used by another application.\nPlease close the corresponding application."));
msgbox.setIcon(QMessageBox::Information);
msgbox.addButton(QMessageBox::Ok);
QCheckBox *cb = new QCheckBox(tr("Do not show this message again."));
msgbox.setCheckBox(cb);
connect(cb, &QCheckBox::stateChanged, [](int state) {
showMsgBox = state != Qt::Checked;
});
msgbox.exec();
}
bool BgViewerController::startBgViewerAppInSession(PluginProvider* pStartingSession)
{
DEBUG_LOG(m_logger) << std::hex << this << " startBgViewerAppInSession " << (m_currentDdsConnParams == pStartingSession->connParams());
if (m_bgvApp && (m_currentDdsConnParams == pStartingSession->connParams()))
{
INFO_LOG(m_logger) << std::hex << this << " BuildingViewer already opened. Doing nothing...";
return true;
}
// Widget is stolen but BgViewer App is not running -> Do not start App
if (!m_bgvApp && m_widgetStolen)
{
showBgViewerInfoMessageBox();
return false;
}
if (m_bgvApp)
{
DEBUG_LOG(m_logger) << std::hex << this << " Releasing m_bgvApp";
delete m_bgvApp;
m_bgvApp = nullptr;
clearInterfaces(m_currentDdsConnParams);
m_comIfc->excCloseAllViews();
}
m_bgvAppIsInitialized = false;
m_bgvApp = LtsAppManager::LtsAppManager::getInstance()->createApp(LtsAppDescriptor::App::BuildingViewer, pStartingSession->connParams());
if (!m_bgvApp || !m_bgvApp->sessions().size())
{
ERROR_LOG(m_logger) << std::hex << this << " m_bgvApp is nullptr or has no associated session!";
return false;
}
connect(m_bgvApp, &LtsPluginManager::LtsPluginManager::signalInitializationFinished,
this, [this, pStartingSession]()
{
m_tickTimer->start();
m_bgvAppIsInitialized = true;
QWidget *w = nullptr;
if (m_bgvApp)
{
LtsSession::LtsSession *session = m_bgvApp->getSession(pStartingSession->connParams().partitionType, pStartingSession->connParams().partitionId);
w = session->baseLayoutWidget();
}
m_bgViewerBaseLayoutWidget = w;
slotLoadBuilding();
emit bgvAppIsInitialized();
});
connect(m_bgvApp, &LtsPluginManager::LtsPluginManager::destroyed,
this, [this]()
{
DEBUG_LOG(m_logger) << std::hex << this << " LtsPluginManager destroyed m_bgvApp";
m_tickTimer->stop();
clearInterfaces(m_currentDdsConnParams);
m_comIfc->excCloseAllViews();
m_bgvAppIsInitialized = false;
m_bgvApp = nullptr;
m_bgViewerBaseLayoutWidget = nullptr;
});
return true;
}
QWidget *BgViewerController::getBgViewerWidget()
{
if (m_widgetStolen)
{
showBgViewerInfoMessageBox();
return nullptr;
}
BgViewerWidgetContainer *pDummy = new BgViewerWidgetContainer(m_mainloop.getViewerInterface()->getMainWindow());
m_widgetStolen = true;
connect(pDummy, &BgViewerWidgetContainer::signalWidgetReleased, this, &BgViewerController::slotWidgetReleased);
return pDummy;
}
void BgViewerController::slotWidgetReleased()
{
m_widgetStolen = false;
}
void BgViewerController::openBuilding(const QString &strBuildingFeatureId)
{
m_buildingsToShow.push_back(strBuildingFeatureId.toStdString());
slotLoadBuilding();
}
void BgViewerController::closeBuilding(const QString &strBuildingFeatureId)
{
if (!strBuildingFeatureId.isEmpty())
{
const std::string s = strBuildingFeatureId.toStdString();
m_buildingsToShow.erase(std::remove_if(m_buildingsToShow.begin(), m_buildingsToShow.end(),
[s](const std::string &str) { return s == str;}), m_buildingsToShow.end());
}
else
m_buildingsToShow.clear();
if (m_comIfc)
{
if (strBuildingFeatureId.isEmpty())
m_comIfc->excCloseAllViews();
else
m_comIfc->excCloseView({strBuildingFeatureId.toStdString()});
m_comIfc->excGetBuildingList();
}
}
void BgViewerController::updatePlayerSymbols(int size)
{
m_pBgViewerDDSController->updatePlayerSymbols(size);
}
void BgViewerController::closeAll()
{
m_bgvApp->deleteLater();
}
/*
* Called each time 'signalInitializationComplete' is emitted. If the user started the BuildingViewer-App
* with specifying a building (see 'showBgViewerApplication'), e.g. by starting it through clicking on a building on the situation map,
* this slot will load the specified building. Otherwise, nothing will happen.
*/
void BgViewerController::slotLoadBuilding()
{
if (!m_bgvAppIsInitialized)
return;
m_comIfc->excOpenView(m_buildingsToShow);
m_comIfc->excGetBuildingList();
m_buildingsToShow.clear();
}
void BgViewerController::slotStartRecording(const QString &strFolderPath, const QJsonValue &state)
{
excRestoreViewState(state);
excStartRecording(strFolderPath, QStringLiteral("all"), 800, 600, 15, 40);
}
void BgViewerController::slotStopRecording()
{
excStopRecording();
}
}