#include "workspace/WorkSpace.h" #include #include #include #include "workspace/WorkSpaceXMLParse.h" #include "workspace/WorkSpaceXMLWrite.h" #include "workspace/CommandManager.h" #include "workspace/WorkSpaceItem.h" #include "workspace/Timestep.h" #include "workspace/LampStatus.h" #include "xml/tinyxml2.h" #include "common/SpdLogger.h" #include "entities/Entity.h" #include "utils/FileUtils.h" #include //#include "workspace/WorkSpaceItemGroup.h" //#include "workspace/WorkSpaceRiverGroup.h" //#include "workspace/WorkSpaceRiverNetGroup.h" Q_DECLARE_METATYPE(WorkSpace*) WorkSpace::WorkSpace(QObject* parent) noexcept : QObject(parent) { uuid_ = QUuid::createUuid().toString(); homeViewpoint_ = osgEarth::Viewpoint("home", 120.000000, 25.000000, 100.000000, -2.500000, -90.000000, 8200000.000000); cmdMgr_ = std::make_unique(); } WorkSpace::WorkSpace(const QString& path, QObject* parent) : QObject(parent) , path_(path){ uuid_ = QUuid::createUuid().toString(); homeViewpoint_ = osgEarth::Viewpoint("home", 120.000000, 25.000000, 100.000000, -2.500000, -90.000000, 8200000.000000); cmdMgr_ = std::make_unique(); } const QString WorkSpace::GetDir() const { QFileInfo info(path_); return info.absolutePath(); } void WorkSpace::SetCommondFilePath(const QString& path) { QFileInfo fileInfo(path); QString dirPath = QString("%1/%2").arg(GetDir(), fileInfo.fileName()); bool sucess = FileUtils::CopyFileToPath(path, dirPath, true); LOG_INFO("copy commond file {}: {} to {}", path.toLocal8Bit().data(), dirPath.toLocal8Bit().data(), sucess); commondPath_ = fileInfo.fileName(); } const QString WorkSpace::GetCommondFilePath() const { QString path = QString("%1/%2").arg(GetDir(), commondPath_); return path; } void WorkSpace::SetSimMatlab(const QString& path) { QFileInfo fileInfo(path); QString dirPath = QString("%1/%2").arg(GetDir(), fileInfo.fileName()); bool sucess = FileUtils::CopyFileToPath(path, dirPath, true); LOG_INFO("copy simmatlab file {}: {} to {}", path.toLocal8Bit().data(), dirPath.toLocal8Bit().data(), sucess); simMatlabPath_ = fileInfo.fileName(); } const QString WorkSpace::GetSimMatlab() const { QString path = QString("%1/%2").arg(GetDir(), simMatlabPath_); return path; } void WorkSpace::SetWavePath(const QString& path) { QFileInfo fileInfo(path); QString dirPath = QString("%1/%2").arg(GetDir(), fileInfo.fileName()); bool sucess = FileUtils::CopyFileToPath(path, dirPath, true); LOG_INFO("copy Wave file {}: {} to {}", path.toLocal8Bit().data(), dirPath.toLocal8Bit().data(), sucess); waveFile_ = fileInfo.fileName(); } const QString WorkSpace::GetWavePath() const { QString path = QString("%1/%2").arg(GetDir(), waveFile_); return path; } void WorkSpace::SetReportPath(const QString& path) { QFileInfo fileInfo(path); QString dirPath = QString("%1/%2").arg(GetDir(), fileInfo.fileName()); bool sucess = FileUtils::CopyFileToPath(path, dirPath, true); LOG_INFO("copy Wave file {}: {} to {}", path.toLocal8Bit().data(), dirPath.toLocal8Bit().data(), sucess); reportFile_ = fileInfo.fileName(); } const QString WorkSpace::GetReportPath() const { QString path = QString("%1/%2").arg(GetDir(), reportFile_); return path; } void WorkSpace::SetRDPath(const QString& path) { QFileInfo fileInfo(path); QString dirPath = QString("%1/%2").arg(GetDir(), fileInfo.fileName()); bool sucess = FileUtils::CopyFileToPath(path, dirPath, true); LOG_INFO("copy RD file {}: {} to {}", path.toLocal8Bit().data(), dirPath.toLocal8Bit().data(), sucess); rdFile_ = fileInfo.fileName(); } std::vector WorkSpace::GetFileEntries(FileEntryType type) const { auto it = files_.find(type); if (it == files_.end()) { return {}; } return it->second; } WorkSpace::FileEntryResult WorkSpace::CreateFileEntry(FileEntryType type) { auto& vec = files_[type]; if (vec.size() >= 9) { return FileEntryResult::LimitExceeded; } // push a placeholder; actual filename may be set elsewhere via SetWavePath/SetRDPath/etc vec.push_back(FileEntry{ type, QString() }); ++filesSeq_; // Notify listeners (e.g., PropertyBrowser) to refresh workspace properties emit FilesChanged(type); return FileEntryResult::Ok; } bool WorkSpace::SetFileEntryCount(FileEntryType type, int count) { if (count < 0) count = 0; if (count > 9) count = 9; auto& vec = files_[type]; if (static_cast(vec.size()) == count) { return true; } if (static_cast(vec.size()) < count) { int toAdd = count - static_cast(vec.size()); for (int i = 0; i < toAdd; ++i) { vec.push_back(FileEntry{ type, QString() }); } } else { vec.resize(count); } ++filesSeq_; emit FilesChanged(type); return true; } bool WorkSpace::SetFileEntryPath(FileEntryType type, int index, const QString& path) { auto& vec = files_[type]; if (index < 0 || index >= static_cast(vec.size())) { return false; } QFileInfo fileInfo(path); if (!fileInfo.exists()) { return false; } QString dirPath = QString("%1/%2").arg(GetDir(), fileInfo.fileName()); bool sucess = FileUtils::CopyFileToPath(path, dirPath, true); LOG_INFO("copy grouped file {}: {} to {}", path.toLocal8Bit().data(), dirPath.toLocal8Bit().data(), sucess); if (!sucess) { return false; } vec[index].fileName = fileInfo.fileName(); ++filesSeq_; emit FilesChanged(type); return true; } QString WorkSpace::GetFileEntryAbsPath(FileEntryType type, int index) const { auto it = files_.find(type); if (it == files_.end()) { return QString(); } const auto& vec = it->second; if (index < 0 || index >= static_cast(vec.size())) { return QString(); } const QString& name = vec[index].fileName; if (name.isEmpty()) { return QString(); } return QString("%1/%2").arg(GetDir(), name); } const QString WorkSpace::GetRDPath() const { QString path = QString("%1/%2").arg(GetDir(), rdFile_); return path; } void WorkSpace::AddEntity(Entity* entity) { if (nullptr == entity) { LOG_WARN("entity is nullptr"); return; } LOG_INFO("add entity: {}", entity->GetName().toLocal8Bit().constData()); entities_.push_back(entity); entity->SetWorkspace(this); emit EntityAdded(entity); } void WorkSpace::RemoveEntity(Entity* entity) { auto itor = std::find_if(entities_.begin(), entities_.end(), [this, entity](const auto* item) { return item == entity; }); if (itor != entities_.end()) { emit EntityRemoved(entity); entities_.erase(itor); } } bool WorkSpace::TrackEntity(Entity* entity) { dyt_check(nullptr != entity); if (trackedEntity_ == entity) { LOG_INFO("entity already tracked: {}", entity->GetName().toStdString()); return true; } if (nullptr == scene_) { LOG_WARN("scene is nullptr, cannot track entity: {}", entity->GetName().toStdString()); return false; } if (trackedEntity_ != entity) { UntrackEntity(); } trackedEntity_ = entity; auto mt = entity->GetRootComponent()->GetMatrixTransform(); LOG_INFO("track entity: {}", entity->GetName().toStdString()); return scene_->TrackEntity(mt, true); } void WorkSpace::UntrackEntity() { if (trackedEntity_ != nullptr) { if (scene_ != nullptr) { LOG_INFO("untrack entity: {}", trackedEntity_->GetName().toStdString()); auto mt = trackedEntity_->GetRootComponent()->GetMatrixTransform(); scene_->TrackEntity(mt, false); } } trackedEntity_ = nullptr; } void WorkSpace::SetActiveScene(OEScene* scene) { dyt_check(nullptr != scene); scene_ = scene; //osgEarth::Viewpoint vp; //vp.name() = "home"; //vp.focalPoint()->set(scene->GetSrs(), -121.488, 46.2054, 0, osgEarth::AltitudeMode::ALTMODE_ABSOLUTE); //vp.pitch() = -50.0; //vp.range() = 100000; //homeViewpoint_ = vp; } bool WorkSpace::SetTimestep(Timestep* timestep) { if (!timestep) { return false; } if (nullptr != timestep_ && timestep_ != timestep) { timestep_->deleteLater(); } timestep_ = timestep; emit TimestepChanged(timestep_); return true; } bool WorkSpace::SetTimestepPath(const QString& path) { Timestep* timestep = Timestep::Load(path, this); return SetTimestep(timestep); } bool WorkSpace::SetLampStatus(class LampStatus* lampStatus) { if (!lampStatus) { return false; } if (nullptr != lampStatus_ && lampStatus_ != lampStatus) { lampStatus_->deleteLater(); } lampStatus_ = lampStatus; emit LampStatusChanged(lampStatus_); return true; } bool WorkSpace::SetLampPath(const QString& path) { LampStatus* timestep = LampStatus::Load(path, this); return SetLampStatus(timestep); } bool WorkSpace::Save(const QString& path) { path_ = path; return Save(); } bool WorkSpace::Save() { WorkSpaceXMLWrite xmlWrite(this); return xmlWrite.Save(path_); } bool WorkSpace::Load(const QString& dyt) { if (leaded_) { LOG_INFO("dyt {} loaded", dyt.toStdString()); return true; } LOG_INFO("dyt {} loading", dyt.toLocal8Bit().constData()); path_ = dyt; WorkSpaceXMLParse parse(this); bool success = parse.Load(dyt); if (!success) { path_ = ""; } leaded_ = success; return success; } void WorkSpace::Unlaod() { if (!leaded_) { LOG_INFO("dyt {} unloaded", name_.toStdString()); return; } while (!entities_.empty()) { auto entity = entities_.front(); entity->Destory(); } leaded_ = false; } void WorkSpace::Begin() { for (auto item : entities_) { item->Begin(); } } void WorkSpace::OnFrame(double dt) { if (nullptr != lampStatus_) { double current = timestep_->GetCurrent(); lampStatus_->OnFrame(current); } for (auto item : entities_) { item->Update(dt); } } void WorkSpace::End() { for (auto item : entities_) { item->End(); } } void WorkSpace::OnLoaded() { if (nullptr != lampStatus_) { emit LampStatusChanged(lampStatus_); } if (nullptr != timestep_) { emit TimestepChanged(timestep_); } // Execute commands configured for onLoad ExecuteCommands(CommandWhen::OnLoad); } void WorkSpace::ExecuteCommands(CommandWhen when) { if (!cmdMgr_) { cmdMgr_ = std::make_unique(); } cmdMgr_->Execute(this, when); }