/** * @RDE_HEADER@ * HMI Plugin for MeteoDataManagement - Meteo Data Overview Dialog * $Id$ * $HeadURL$ * $Author$ * Created by Philipp Last, SLSY, 2017-08-15 */ #include "bdv_communication_interface_internal.h" #include #include #include namespace BuildingViewer { static const char PLAYER_PREFIX[] = "player_"; static const char ROOM_PREFIX[] = ""; static const char BUILDING_PREFIX[] = "House_"; //static const char CAMERA_PREFIX[] = "Camera_"; static inline std::string createPlayerIdString(int playerId) { return PLAYER_PREFIX + std::to_string(playerId); } static inline std::string createBuildingIdString(int buildingId) { return BUILDING_PREFIX + std::to_string(buildingId); } static inline std::string createRoomNumberString(int roomNumber) { return ROOM_PREFIX + std::to_string(roomNumber); } CommunicationInterfaceInternal::CommunicationInterfaceInternal(VCtrl::ViewerInterface* pviewerInterface) : m_pviewerInterface(pviewerInterface) , m_logger(getLogger("CommunicationInterface")) { assert(m_pviewerInterface); } void CommunicationInterfaceInternal::playerCreate(int playerID, int partyID, const QString &strPathToSymbolFile, const LtsUtils::QPoint3D &pos, int buildingID, int roomNumber, Core::PositionReportingSource reportingSource) { std::string playerIdStr = createPlayerIdString(playerID); VCtrl::Color partyColor = m_teamMap.value(partyID).color; m_pviewerInterface->CreatePlayer(playerIdStr, strPathToSymbolFile.toStdString(), partyColor); std::string buildingIdStr, roomNumberStr; if (buildingID > 0) { buildingIdStr = createBuildingIdString(buildingID); } if (roomNumber > 0) { roomNumberStr = createRoomNumberString(roomNumber); } const VCtrl::Vec3d tgt(pos.x(), pos.y(), pos.z()); m_pviewerInterface->Teleport(playerIdStr, 0, tgt, buildingIdStr, roomNumber, roomNumberStr, (reportingSource == Core::PositionReportingSource::Wls ? VCtrl::ZValue::AboveMsl : VCtrl::ZValue::RelativeBuildings)); m_pviewerInterface->SetPlayerShown(playerIdStr, true, 0); m_playerId2String[playerID] = playerIdStr; m_string2PlayerId[playerIdStr] = playerID; m_player2TeamMap[playerID] = partyID; } void CommunicationInterfaceInternal::playerPlace(int playerID, const LtsUtils::QPoint3D &pos, int buildingID, int roomNumber, Core::PositionReportingSource reportingSource) { auto it = m_playerId2String.find(playerID); if (it == m_playerId2String.end()) { WARNING_LOG(m_logger) << "Trying to set player position for unknown (=not created) player with id " << playerID; return; } const std::string &playerIdStr = it.value(); std::string buildingIdStr, roomNumberStr; if (buildingID > 0 ) { buildingIdStr = createBuildingIdString(buildingID); } if ( roomNumber > 0) { roomNumberStr = createRoomNumberString(roomNumber); } const VCtrl::Vec3d tgt(pos.x(), pos.y(), pos.z()); m_pviewerInterface->Teleport(playerIdStr, 0, tgt, buildingIdStr, roomNumber, roomNumberStr, (reportingSource == Core::PositionReportingSource::Wls ? VCtrl::ZValue::AboveMsl : VCtrl::ZValue::RelativeBuildings)); } void CommunicationInterfaceInternal::playerDelete(int playerID) { if (playerID <= 0) return; std::string playerIdStr = createPlayerIdString(playerID); m_pviewerInterface->DeletePlayer(playerIdStr); m_playerId2String.remove(playerID); m_string2PlayerId.remove(playerIdStr); m_player2TeamMap.remove(playerID); } void CommunicationInterfaceInternal::setPlayerVisible(int playerID, bool bVisible) { if (playerID <= 0) return; std::string playerIdStr = createPlayerIdString(playerID); m_pviewerInterface->SetPlayerShown(playerIdStr, bVisible); } void CommunicationInterfaceInternal::playerClear() { const auto string2PlayerId_Copy = m_string2PlayerId; for (const int playerId : string2PlayerId_Copy) playerDelete(playerId); m_player2TeamMap.clear(); m_playerId2String.clear(); m_string2PlayerId.clear(); } void CommunicationInterfaceInternal::playerUpdateSymbols() { m_pviewerInterface->reloadPlayerIcons(); } void CommunicationInterfaceInternal::playerUpdatePlayerSymbol(int playerID, const QString &strPathToSymbolFile) { std::string playerIdStr = createPlayerIdString(playerID); m_pviewerInterface->SetPlayerIcon(playerIdStr, strPathToSymbolFile.toStdString()); } /* * Also causes the reload the symbol file for playerIdDst. * Hence, the new symbol file needs to be created before calling this function. */ void CommunicationInterfaceInternal::playerHit(const int32_t id, int playerIdSrc, int playerIdDst, const LtsUtils::QPoint3D &posSrc, const LtsUtils::QPoint3D &posDst, int buildingIdSrc, int roomNumberSrc, int buildingIdDst, int roomNumberDst, int lineType, int64_t time) { DEBUG_LOG(m_logger) << "playerHit id= " << id; const std::string playerIdStrDst = m_playerId2String.value(playerIdDst); const std::string playerIdStrSrc = m_playerId2String.value(playerIdSrc); const VCtrl::Vec3d src(posSrc.x(), posSrc.y(), posSrc.z()); const VCtrl::Vec3d dst(posDst.x(), posDst.y(), posDst.z()); m_pviewerInterface->Shoot(id, playerIdStrSrc, playerIdStrDst, src, dst, buildingIdSrc, roomNumberSrc, buildingIdDst, roomNumberDst, lineType, time / 1000.); } void CommunicationInterfaceInternal::buildingHit(const int32_t id, int buildingId, int damagePercent, const QMap& mapRoomDestructions) { DEBUG_LOG(m_logger) << "buildingHit for building " << buildingId << " id=" << id << " damagePercent " << damagePercent << " roomlist size: " << mapRoomDestructions.size(); const std::string buildingIdStr = createBuildingIdString(buildingId); // Nur bei ganz zersört oder gar nicht zerstört auch die buildingDestruction setzen da diese alle Räume beeinflusst if (damagePercent <= 0 || damagePercent >= 80) { if (damagePercent >= 80) damagePercent = 100; m_pviewerInterface->SetBuildingDestructionValue(buildingIdStr, damagePercent / 100.f); } else { for (auto it = mapRoomDestructions.begin(); it != mapRoomDestructions.end(); ++it) { const int roomNumber = it.key(); DEBUG_LOG(m_logger) << "BuildingId " << buildingId << ", room: "<< roomNumber << ", destruction: " << it.value(); std::string roomNumberStr = createRoomNumberString(roomNumber); if (!m_pviewerInterface->SetRoomDestructionValue(buildingIdStr, roomNumberStr,it.value() / 100.f)) ERROR_LOG(m_logger) << "SetRoomDestructionValue failed for room "<< roomNumber; } } } void CommunicationInterfaceInternal::roomHit(const int32_t id, int playerIdSrc, int buildingId, int roomNumber, const LtsUtils::QPoint3D &posSrc, int lineType, int64_t time) { // ERROR_LOG(m_logger) << "HOTLINE roomHit for building " << buildingId //<< " id=" << id; const std::string playerIdStrSrc = m_playerId2String.value(playerIdSrc); const std::string buildingIdStrDst = createBuildingIdString(buildingId); const std::string roomNumberStrDst = createRoomNumberString(roomNumber); const VCtrl::Vec3d src(posSrc.x(), posSrc.y(), posSrc.z()); DEBUG_LOG(m_logger) << "roomHit for building palyer " << playerIdStrSrc << " building " << buildingIdStrDst << " room " << roomNumberStrDst << " id=" << id; m_pviewerInterface->Shoot(id, playerIdStrSrc, buildingIdStrDst, roomNumberStrDst, src, lineType, time / 1000.); } void CommunicationInterfaceInternal::removeRoomHit(const int32_t id) { DEBUG_LOG(m_logger) << "removeRoomHit id=" << id; m_pviewerInterface->removeShoot(id); } void CommunicationInterfaceInternal::setTeamConfiguration(const QMap &parties) { for (const ParticipantManagement::Party &party : parties) { BdvParty bdvParty; bdvParty.id = party.id(); bdvParty.name = ParticipantManagement::trPartyName(party.name()); const uint32_t argb = party.color(); bdvParty.color.w = ( ( ( argb >> 24 ) & 0xff ) / 255.); bdvParty.color.x = ( ( ( argb >> 16 ) & 0xff ) / 255.); bdvParty.color.y = ( ( ( argb >> 8 ) & 0xff ) / 255.); bdvParty.color.z = ( ( ( argb >> 0 ) & 0xff ) / 255.); m_teamMap[bdvParty.id] = bdvParty; } std::map mapPlayerColors; for (auto it = m_player2TeamMap.cbegin(); it != m_player2TeamMap.cend(); ++it) { const auto itParty = m_teamMap.constFind(it.value()); if (itParty == m_teamMap.cend()) continue; mapPlayerColors.emplace(std::make_pair(createPlayerIdString(it.key()), itParty.value().color)); } m_pviewerInterface->UpdatePlayerPartyColors(mapPlayerColors); } void CommunicationInterfaceInternal::systemSetSimulationTime(qint64 time) { double tSimTime = time / 1000; double tCurSimTime = m_pviewerInterface->GetSimulationTime(); if(fabs(tCurSimTime - tSimTime) < 0.5) return; m_pviewerInterface->SetSimulationTime(tSimTime); } void CommunicationInterfaceInternal::setSimuationPace(double pace) { m_pviewerInterface->SetTimeScale(pace); } void CommunicationInterfaceInternal::systemDisconnect() { playerClear(); clearCameras(); systemSetPaused(true); } void CommunicationInterfaceInternal::systemSetPaused(bool bPaused) { m_pviewerInterface->SetPaused(bPaused); } void CommunicationInterfaceInternal::systemSetMountingPoint(const InfrastructureManagement::MountingPoint &data, const QString &filename, bool show) { int buildingId = data.buildingId(); const QString &mountingPointName = filename; double x = data.relPosition().offsetX(); double y = data.relPosition().offsetY(); double z = data.relPosition().offsetZ(); const std::string buildingIdStr = createBuildingIdString(buildingId); if(!show) { DEBUG_LOG(m_logger) << "Hiding mounting point \"" << mountingPointName<< "\""; m_pviewerInterface->HideDeviceIcon(mountingPointName.toStdString()); return; } if(m_deviceMap.contains(mountingPointName)) { WARNING_LOG(m_logger) << "Trying to add a mounting point which was already added - trying to re-add"; //remove first and then reAdd m_pviewerInterface->HideDeviceIcon(mountingPointName.toStdString()); } const VCtrl::Vec3d position(x,y,z); if(m_pviewerInterface->ShowDeviceIcon(mountingPointName.toStdString(), buildingIdStr, position, filename.toStdString())) { DEBUG_LOG(m_logger) << "Added mounting point to scene: " << mountingPointName; m_deviceMap[mountingPointName] = DeviceInfo(buildingId, mountingPointName); } } void CommunicationInterfaceInternal::excStartRecording(const QString& strPathOutputFolder, const QString &buildingId, int w, int h, int framerate, int quality) { m_pviewerInterface->StartVideoRecording(buildingId.toStdString(), strPathOutputFolder.toStdString(), w, h, framerate, quality); } void CommunicationInterfaceInternal::excStopRecording(const QString &buildingId) { m_pviewerInterface->StopVideoRecording(buildingId.toStdString()); } void CommunicationInterfaceInternal::excConnect(const std::vector &paths, const QString &strXMLFile) { m_pviewerInterface->SetProjectDataPaths(paths); m_pviewerInterface->LoadBuildingPositionMap(strXMLFile.toStdString(), (strXMLFile.size() ? false : true)); emit signalBgViewerInitFinished(); } void CommunicationInterfaceInternal::excDeleteBuildingList() { m_pviewerInterface->LoadBuildingPositionMap(std::string(), false); } void CommunicationInterfaceInternal::excSetHitlineDuration(uint32_t duration_s) { DEBUG_LOG(m_logger) << "excSetHitlineDuration=" << duration_s; m_pviewerInterface->setHitLineDuration(duration_s); } void CommunicationInterfaceInternal::excUseExactPositioning(bool useExactPositioning) { m_useExactPositioning = useExactPositioning; m_pviewerInterface->UseExactPositioning(useExactPositioning); } void CommunicationInterfaceInternal::excOpenView(const std::vector &bldIds) { m_pviewerInterface->openViews(bldIds, m_useExactPositioning); } void CommunicationInterfaceInternal::excCloseView(const std::vector &bldIds) { m_pviewerInterface->closeViews(bldIds); } void CommunicationInterfaceInternal::excCloseAllViews() { m_pviewerInterface->closeViews({"all"}); } void CommunicationInterfaceInternal::excHighlightView(const QString &buildingId) { m_pviewerInterface->highlightView(buildingId.toStdString()); } void CommunicationInterfaceInternal::excGetBuildingList() { const auto states = m_pviewerInterface->getBuildingState(); QVector tplStates; BuildingTuple tpl; tplStates.reserve(states.size()); for (const auto &state : states) { tpl.buildingId = QString::fromStdString(state.buildingId); tpl.description = QString::fromStdString(state.description); tpl.entityId = state.entityId; tpl.isShown = state.isShown; tplStates += tpl; } emit signalReceivedBuildingList(tplStates); } void CommunicationInterfaceInternal::excSetGlobalTransparency(double transparency) { m_pviewerInterface->setTransparency(transparency / 100.0); } void CommunicationInterfaceInternal::excSetGlobalViewMode(bool useOrtho) { m_pviewerInterface->setViewMode(useOrtho ? VCtrl::ViewMode::ORTHOGRAPHIC : VCtrl::ViewMode::ISOMETRIC); } void CommunicationInterfaceInternal::excSetGlobalDotsMode(bool useDots) { m_pviewerInterface->setDisplayMode(useDots ? VCtrl::PlayerDisplayMode::Dots : VCtrl::PlayerDisplayMode::Icons); } void CommunicationInterfaceInternal::excRestoreViewState(const QJsonValue &val) { m_pviewerInterface->setViewState(val); } void CommunicationInterfaceInternal::excGetViewState() { const auto state = m_pviewerInterface->getViewState(); emit signalReceivedViewState(state); } void CommunicationInterfaceInternal::excSetBuildingDisplayName(const QString &buildingId, const QString &strBuildingDisplayName) { m_pviewerInterface->setBuildingDisplayName(buildingId.toStdString(), strBuildingDisplayName.toStdString()); } void CommunicationInterfaceInternal::excSetRoomDisplayName(const QString &strFeatureID, const QString &strRoomName, const QString &strRoomDisplayName) { m_pviewerInterface->SetDisplayName(strFeatureID.toStdString(), strRoomName.toStdString(), strRoomDisplayName.toStdString()); } void CommunicationInterfaceInternal::extSetMountingPointAsset(const QString &strFeatureID, const QString &strMountingPointId, const QVector3D& position, BuildingViewer::AssetTypes assetType) { m_pviewerInterface->setMountingPointAsset({strFeatureID.toStdString(), strMountingPointId.toStdString(), {position.x(), position.y(), position.z()}, assetType}); } void CommunicationInterfaceInternal::extHideMountingPointAsset(const QString &strMountingPointId) { m_pviewerInterface->HideDeviceIcon(strMountingPointId.toStdString()); } void CommunicationInterfaceInternal::clearCameras() { for (const DeviceInfo &di : qAsConst(m_deviceMap)) { if (!di.deviceName.startsWith(QLatin1String("Camera"))) continue; if (!m_pviewerInterface->HideDeviceIcon(di.deviceName.toStdString())) ERROR_LOG(m_logger) << "Could not remove camera with id " << di.deviceName; } m_deviceMap.clear(); } // VCtrl::ViewerCallback interface void CommunicationInterfaceInternal::SystemReady() { } void CommunicationInterfaceInternal::TransformChanged(const std::string &id, const VCtrl::Vec3d &pos, const VCtrl::Quat &attitude) { Q_UNUSED(id); Q_UNUSED(pos); Q_UNUSED(attitude); } void CommunicationInterfaceInternal::NavMeshGroupChanged(const std::string &id, const std::string &grpname) { Q_UNUSED(id); Q_UNUSED(grpname); } static inline bool isPlayerId(const std::string &playerIdString, int *playerId) { const QString playerIdQString(QString::fromStdString(playerIdString)); bool bOk = false; if (playerIdQString.startsWith(QLatin1String(PLAYER_PREFIX))) *playerId = playerIdQString.midRef(QLatin1String(PLAYER_PREFIX).size()).toInt(&bOk); return bOk; } void CommunicationInterfaceInternal::PlayerPicked(const std::string &strId) { int playerId = 0; if (isPlayerId(strId, &playerId)) { emit signalPlayerPicked(playerId); } else { // asset string may be, e.g., "House_56_MountingPoint_37" QString str = QString::fromStdString(strId); int structureElementId = str.remove(0, str.lastIndexOf(QStringLiteral("_")) + 1).toInt(); INFO_LOG(m_logger) << "Picked mounting point with id " << strId << " mountingPointId=" << structureElementId; if(structureElementId < 0) { WARNING_LOG(m_logger) << "Picked mounting point with id " << strId; return; } emit signalAssetPicked(structureElementId); } } void CommunicationInterfaceInternal::DisplayNamePicked(const std::string &buildingid, const std::string &roomname) { // HandleViewerEvent (see below) handles this... Q_UNUSED(buildingid); Q_UNUSED(roomname); } void CommunicationInterfaceInternal::ViewCreated(unsigned int contextId, VCtrl::ViewMode viewmode) { Q_UNUSED(contextId); Q_UNUSED(viewmode); } void CommunicationInterfaceInternal::ViewModeChanged(unsigned int contextId, VCtrl::ViewMode viewmode) { Q_UNUSED(contextId); Q_UNUSED(viewmode); emit signalViewerEventButton(); } void CommunicationInterfaceInternal::ViewLineModeChanged(unsigned int contextId, bool line) { Q_UNUSED(contextId); Q_UNUSED(line); emit signalViewerEventButton(); } void CommunicationInterfaceInternal::ViewNameModeChanged(unsigned int contextId, bool name) { Q_UNUSED(contextId); Q_UNUSED(name); emit signalViewerEventButton(); } void CommunicationInterfaceInternal::ViewLockRotationChanged(unsigned int contextId, bool lock) { Q_UNUSED(contextId); Q_UNUSED(lock); emit signalViewerEventButton(); } void CommunicationInterfaceInternal::ViewTransparencyChanged() { emit signalViewerEventButton(); } void CommunicationInterfaceInternal::PlayerDisplayModeChanged(unsigned int contextId, VCtrl::PlayerDisplayMode mode) { Q_UNUSED(contextId); Q_UNUSED(mode); emit signalViewerEventButton(); } void CommunicationInterfaceInternal::ViewClosed(unsigned int contextId) { Q_UNUSED(contextId); } void CommunicationInterfaceInternal::HandleViewerEvent(BgViewerEvents event, const std::vector &args) { if (args.size() < 1) { Q_ASSERT(false); return; } const QString featureID = QString::fromStdString(args[0]); switch (event) { case BuildingViewer::BgViewerEvents::WidgetClosed: emit signalViewerEventWidgetClosed(featureID); break; case BuildingViewer::BgViewerEvents::WidgetMaximized: emit signalViewerEventWidgetMaximized(featureID); break; case BuildingViewer::BgViewerEvents::WidgetMinimized: emit signalViewerEventWidgetMinimized(featureID); break; case BuildingViewer::BgViewerEvents::WidgetGotFocus: emit signalViewerEventWidgetFocused(featureID); break; case BuildingViewer::BgViewerEvents::RoomNameClicked: { if (args.size() >= 2) { const QString roomID = QString::fromStdString(args[1]); emit signalViewerEventRoomNameClicked(featureID, roomID); } break; } } } void CommunicationInterfaceInternal::ViewZoomChanged(const std::string &buildingId, double top, double left, double bottom, double right) { emit signalViewerZoomChanged(QString::fromStdString(buildingId), top, left, bottom, right); } void CommunicationInterfaceInternal::LogMessage(Severity &severity, const std::string &filename, const std::string &methodname, int linenumber, const std::string &msg) { auto logLevel = NGL::LogLevel::Info; bool logAlways = false; switch (severity) { case Severity::Always: logAlways = true; logLevel = NGL::LogLevel::Info; break; case Severity::Debug: logLevel = NGL::LogLevel::Debug; break; case Severity::Info: logLevel = NGL::LogLevel::Info; break; case Severity::Warning: logLevel = NGL::LogLevel::Warning; break; case Severity::Error: logLevel = NGL::LogLevel::Error; break; case Severity::Fatal: logLevel = NGL::LogLevel::Fatal; break; } if (logAlways || m_logger.isLevelEnabled(logLevel)) NGL::LogStreamHelper(m_logger, logLevel, filename.c_str(), linenumber, methodname.c_str()) << msg; } } // namesapce BuildingViewer