diff --git a/src/entities/ComponentFactory.cpp b/src/entities/ComponentFactory.cpp index 08e7f2cf..b99e84e4 100644 --- a/src/entities/ComponentFactory.cpp +++ b/src/entities/ComponentFactory.cpp @@ -10,6 +10,7 @@ #include "entities/ConeWaveComponent.h" #include "entities/DashedLineComponent.h" #include "entities/LabelComponent.h" +#include "entities/TrajectoryTraceComponent.h" //Component::Component(QObject* parent) // : QObject(parent) { @@ -37,6 +38,8 @@ SceneComponent* ComponentFactory::Create(const QString& name, SceneComponent* pa return new ConeWaveComponent(parenet); } else if ("DashedLineComponent" == name) { return new DashedLineComponent(parenet); + } else if ("TrajectoryTraceComponent" == name) { + return new TrajectoryTraceComponent(parenet); } else if ("LabelComponent" == name) { return new LabelComponent(parenet); } diff --git a/src/entities/Entity.h b/src/entities/Entity.h index 13e7752d..d0ff95cb 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -53,7 +53,7 @@ public: if (nullptr == rootComponet_) { return nullptr; } - return rootComponet_->GetComponent(); + return rootComponet_->GetComponent(); } bool HasComponent(const std::string& name) const; @@ -91,4 +91,4 @@ protected: std::vector childer_; class NetDriver* netDriver_{ nullptr }; -}; \ No newline at end of file +}; diff --git a/src/entities/SceneComponent.h b/src/entities/SceneComponent.h index 42052a25..ad120efc 100644 --- a/src/entities/SceneComponent.h +++ b/src/entities/SceneComponent.h @@ -37,7 +37,7 @@ public: template T* GetComponent() { - for (auto& componet : childer_) { + for (auto& componet : children_) { if (componet->GetTypeName() == T::GetTypeName()) { return reinterpret_cast(componet); } @@ -83,4 +83,4 @@ protected: protected: Transform transform_; bool visible_{ true }; -}; \ No newline at end of file +}; diff --git a/src/entities/TrajectoryTraceComponent.cpp b/src/entities/TrajectoryTraceComponent.cpp new file mode 100644 index 00000000..8a6bf8ee --- /dev/null +++ b/src/entities/TrajectoryTraceComponent.cpp @@ -0,0 +1,383 @@ +#include "entities/TrajectoryTraceComponent.h" + +#include + +#include +#include +#include +#include +#include + +#include "common/SpdLogger.h" +#include "entities/Entity.h" +#include "scene/SceneContent.h" +#include "utils/StringUtils.h" +#include "workspace/WorkSpace.h" + +TrajectoryTraceComponent::TrajectoryTraceComponent(SceneComponent* parent) + : SceneComponent(parent) { +} + +TrajectoryTraceComponent::~TrajectoryTraceComponent() { +} + +std::string TrajectoryTraceComponent::GetTypeName() { + return "TrajectoryTraceComponent"; +} + +bool TrajectoryTraceComponent::SetAttribute(const char* name, const char* value) { + if (0 == strcmp(name, "color")) { + SetColor(StringUtils::StringToVec4(value)); + return true; + } else if (0 == strcmp(name, "lineWidth")) { + SetLineWidth(static_cast(atof(value))); + return true; + } else if (0 == strcmp(name, "sampleInterval")) { + SetSampleInterval(atof(value)); + return true; + } else if (0 == strcmp(name, "minMoveDistance")) { + SetMinMoveDistance(atof(value)); + return true; + } else if (0 == strcmp(name, "maxPoints")) { + SetMaxPoints(atoi(value)); + return true; + } else if (0 == strcmp(name, "tailDuration")) { + SetTailDuration(atof(value)); + return true; + } else if (0 == strcmp(name, "visible")) { + SetTraceVisible(0 == strcmp(value, "true")); + return true; + } + + return SceneComponent::SetAttribute(name, value); +} + +bool TrajectoryTraceComponent::SaveAttribute(tinyxml2::XMLElement* element) { + element->SetAttribute("color", StringUtils::Vec4ToString(color_).c_str()); + element->SetAttribute("lineWidth", std::to_string(lineWidth_).c_str()); + element->SetAttribute("sampleInterval", std::to_string(sampleInterval_).c_str()); + element->SetAttribute("minMoveDistance", std::to_string(minMoveDistance_).c_str()); + element->SetAttribute("maxPoints", maxPoints_); + element->SetAttribute("tailDuration", std::to_string(tailDuration_).c_str()); + element->SetAttribute("visible", traceVisible_ ? "true" : "false"); + return SceneComponent::SaveAttribute(element); +} + +void TrajectoryTraceComponent::Begin() { + SceneComponent::Begin(); + + if (mt_.valid()) { + RemoveRender(); + } + + sampleAccum_ = 0.0; + elapsedTime_ = 0.0; + hasLastSample_ = false; + attachedToScene_ = false; + ClearTrace(); +} + +void TrajectoryTraceComponent::Update(double dt) { + SceneComponent::Update(dt); + + Entity* entity = GetEntity(); + if (nullptr == entity || nullptr == entity->GetTransform()) { + return; + } + + /* elapsedTime_ += dt; + sampleAccum_ += dt; + TrimExpiredPoints(); + if (sampleAccum_ < sampleInterval_) { + return; + } + sampleAccum_ = 0.0;*/ + + const osg::Vec3d currentPos = entity->GetTransform()->GetLocation(); + if (!hasLastSample_) { + lastSamplePos_ = currentPos; + hasLastSample_ = true; + return; + } + + /*const osg::Vec3d delta = currentPos - lastSamplePos_; + if (delta.length2() < minMoveDistance_ * minMoveDistance_) { + return; + }*/ + + EnsureAttachedToScene(); + if (vertices_->empty()) { + if (!AppendPoint(lastSamplePos_)) { + return; + } + } + if (!AppendPoint(currentPos)) { + return; + } + lastSamplePos_ = currentPos; +} + +void TrajectoryTraceComponent::AddToRender() { + InitializeGeometry(); + + if (!attachedToScene_) { + return; + } + + if (mt_->getNumParents() > 0) { + return; + } + AttachTraceToScene(); +} + +void TrajectoryTraceComponent::SetColor(const osg::Vec4& color) { + color_ = color; + UpdateStyle(); +} + +const osg::Vec4& TrajectoryTraceComponent::GetColor() const { + return color_; +} + +void TrajectoryTraceComponent::SetLineWidth(float width) { + lineWidth_ = std::max(1.0f, width); + UpdateStyle(); +} + +float TrajectoryTraceComponent::GetLineWidth() const { + return lineWidth_; +} + +void TrajectoryTraceComponent::SetSampleInterval(double interval) { + const double newInterval = std::max(0.01, interval); + if (sampleInterval_ == newInterval) { + return; + } + + sampleInterval_ = newInterval; + // Make editor changes visible immediately instead of waiting for the old accumulated cadence. + sampleAccum_ = 0.0; +} + +double TrajectoryTraceComponent::GetSampleInterval() const { + return sampleInterval_; +} + +void TrajectoryTraceComponent::SetMinMoveDistance(double distance) { + minMoveDistance_ = std::max(0.0, distance); +} + +double TrajectoryTraceComponent::GetMinMoveDistance() const { + return minMoveDistance_; +} + +void TrajectoryTraceComponent::SetMaxPoints(int maxPoints) { + maxPoints_ = std::max(2, maxPoints); + if (vertices_.valid() && static_cast(vertices_->size()) > maxPoints_) { + const int overflow = static_cast(vertices_->size()) - maxPoints_; + vertices_->erase(vertices_->begin(), vertices_->begin() + overflow); + drawArrays_->setCount(static_cast(vertices_->size())); + vertices_->dirty(); + geometry_->dirtyBound(); + } +} + +int TrajectoryTraceComponent::GetMaxPoints() const { + return maxPoints_; +} + +void TrajectoryTraceComponent::SetTailDuration(double duration) { + tailDuration_ = std::max(0.0, duration); + TrimExpiredPoints(); +} + +double TrajectoryTraceComponent::GetTailDuration() const { + return tailDuration_; +} + +void TrajectoryTraceComponent::SetTraceVisible(bool visible) { + traceVisible_ = visible; + if (geode_.valid()) { + geode_->setNodeMask(traceVisible_ ? 0xffffffff : 0x0); + } +} + +bool TrajectoryTraceComponent::IsTraceVisible() const { + return traceVisible_; +} + +void TrajectoryTraceComponent::ClearTrace() { + InitializeGeometry(); + + vertices_->clear(); + sampleTimes_.clear(); + drawArrays_->setCount(0); + vertices_->dirty(); + geometry_->dirtyBound(); + if (geode_.valid()) { + geode_->dirtyBound(); + } + if (mt_.valid()) { + mt_->dirtyBound(); + } +} + +void TrajectoryTraceComponent::InitializeGeometry() { + if (mt_.valid()) { + return; + } + + mt_ = new osg::MatrixTransform; + geode_ = new osg::Geode; + geometry_ = new osg::Geometry; + vertices_ = new osg::Vec3Array; + colors_ = new osg::Vec4Array; + drawArrays_ = new osg::DrawArrays(GL_LINE_STRIP, 0, 0); + lineWidthState_ = new osg::LineWidth(lineWidth_); + + geometry_->setDataVariance(osg::Object::DYNAMIC); + geometry_->setUseDisplayList(false); + geometry_->setUseVertexBufferObjects(true); + geometry_->setVertexArray(vertices_.get()); + geometry_->addPrimitiveSet(drawArrays_.get()); + + colors_->push_back(color_); + geometry_->setColorArray(colors_.get(), osg::Array::BIND_OVERALL); + + osg::StateSet* stateSet = geode_->getOrCreateStateSet(); + stateSet->setMode(GL_LIGHTING, osg::StateAttribute::OFF); + stateSet->setMode(GL_BLEND, osg::StateAttribute::ON); + stateSet->setAttributeAndModes(lineWidthState_.get(), osg::StateAttribute::ON); + stateSet->setAttributeAndModes(new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)); + stateSet->setAttributeAndModes(new osg::Depth(osg::Depth::LEQUAL, 0.0, 1.0, false)); + stateSet->setRenderingHint(osg::StateSet::TRANSPARENT_BIN); + + geode_->addDrawable(geometry_.get()); + mt_->addChild(geode_.get()); + geode_->setNodeMask(traceVisible_ ? 0xffffffff : 0x0); +} + +void TrajectoryTraceComponent::EnsureAttachedToScene() { + InitializeGeometry(); + + if (!attachedToScene_) { + attachedToScene_ = true; + } +} + +bool TrajectoryTraceComponent::AppendPoint(const osg::Vec3d& geoPoint) { + InitializeGeometry(); + + osg::Vec3d worldPoint; + if (!ConvertGeoPointToWorld(geoPoint, worldPoint)) { + return false; + } + + vertices_->push_back(worldPoint); + sampleTimes_.push_back(elapsedTime_); + if (static_cast(vertices_->size()) > maxPoints_) { + const int overflow = static_cast(vertices_->size()) - maxPoints_; + vertices_->erase(vertices_->begin(), vertices_->begin() + overflow); + for (int i = 0; i < overflow && !sampleTimes_.empty(); ++i) { + sampleTimes_.pop_front(); + } + } + + drawArrays_->setCount(static_cast(vertices_->size())); + vertices_->dirty(); + geometry_->dirtyBound(); + if (geode_.valid()) { + geode_->dirtyBound(); + } + if (mt_.valid()) { + mt_->dirtyBound(); + } + + if (attachedToScene_ && mt_->getNumParents() == 0) { + AttachTraceToScene(); + } + return true; +} + +bool TrajectoryTraceComponent::ConvertGeoPointToWorld(const osg::Vec3d& geoPoint, osg::Vec3d& worldPoint) const { + if (nullptr == g_srs_) { + LOG_WARN("TrajectoryTraceComponent::ConvertGeoPointToWorld - g_srs_ is nullptr"); + return false; + } + + osgEarth::GeoPoint point(g_srs_, geoPoint); + if (!point.toWorld(worldPoint)) { + LOG_WARN("TrajectoryTraceComponent::ConvertGeoPointToWorld - failed to convert geo point to world"); + return false; + } + return true; +} + +void TrajectoryTraceComponent::AttachTraceToScene() { + Entity* entity = GetEntity(); + if (nullptr == entity) { + LOG_WARN("TrajectoryTraceComponent::AttachTraceToScene - entity is nullptr"); + return; + } + + WorkSpace* workspace = entity->GetWorkspace(); + if (nullptr == workspace) { + LOG_WARN("TrajectoryTraceComponent::AttachTraceToScene - workspace is nullptr"); + return; + } + + OEScene* scene = workspace->GetActiveScene(); + if (nullptr == scene) { + LOG_WARN("TrajectoryTraceComponent::AttachTraceToScene - scene is nullptr"); + return; + } + + scene->AddToScene(mt_.get()); +} + +void TrajectoryTraceComponent::TrimExpiredPoints() { + if (!vertices_.valid()) { + return; + } + + if (tailDuration_ <= 0.0) { + if (!vertices_->empty()) { + ClearTrace(); + } + return; + } + + bool removed = false; + while (!sampleTimes_.empty() && (elapsedTime_ - sampleTimes_.front()) > tailDuration_) { + sampleTimes_.pop_front(); + if (!vertices_->empty()) { + vertices_->erase(vertices_->begin()); + removed = true; + } + } + + if (removed) { + drawArrays_->setCount(static_cast(vertices_->size())); + vertices_->dirty(); + geometry_->dirtyBound(); + if (geode_.valid()) { + geode_->dirtyBound(); + } + if (mt_.valid()) { + mt_->dirtyBound(); + } + } +} + +void TrajectoryTraceComponent::UpdateStyle() { + if (colors_.valid()) { + colors_->clear(); + colors_->push_back(color_); + colors_->dirty(); + geometry_->dirtyBound(); + } + + if (lineWidthState_.valid()) { + lineWidthState_->setWidth(lineWidth_); + } +} diff --git a/src/entities/TrajectoryTraceComponent.h b/src/entities/TrajectoryTraceComponent.h new file mode 100644 index 00000000..93a66cf9 --- /dev/null +++ b/src/entities/TrajectoryTraceComponent.h @@ -0,0 +1,83 @@ +#pragma once + +#include "entities/SceneComponent.h" + +#include +#include +#include +#include + +class TrajectoryTraceComponent : public SceneComponent { + Q_OBJECT + +public: + explicit TrajectoryTraceComponent(SceneComponent* parent = nullptr); + ~TrajectoryTraceComponent(); + + static std::string GetTypeName(); + std::string GetSelfTypeName() const override { + return TrajectoryTraceComponent::GetTypeName(); + } + + bool SetAttribute(const char* name, const char* value) override; + bool SaveAttribute(tinyxml2::XMLElement* element) override; + + void Begin() override; + void Update(double dt) override; + void AddToRender() override; + + void SetColor(const osg::Vec4& color); + const osg::Vec4& GetColor() const; + + void SetLineWidth(float width); + float GetLineWidth() const; + + void SetSampleInterval(double interval); + double GetSampleInterval() const; + + void SetMinMoveDistance(double distance); + double GetMinMoveDistance() const; + + void SetMaxPoints(int maxPoints); + int GetMaxPoints() const; + + void SetTailDuration(double duration); + double GetTailDuration() const; + + void SetTraceVisible(bool visible); + bool IsTraceVisible() const; + + void ClearTrace(); + +private: + void InitializeGeometry(); + void EnsureAttachedToScene(); + bool AppendPoint(const osg::Vec3d& geoPoint); + bool ConvertGeoPointToWorld(const osg::Vec3d& geoPoint, osg::Vec3d& worldPoint) const; + void AttachTraceToScene(); + void TrimExpiredPoints(); + void UpdateStyle(); + +private: + osg::ref_ptr geode_; + osg::ref_ptr geometry_; + osg::ref_ptr vertices_; + osg::ref_ptr colors_; + osg::ref_ptr drawArrays_; + osg::ref_ptr lineWidthState_; + + osg::Vec4 color_{1.0f, 0.8f, 0.1f, 1.0f}; + float lineWidth_{2.0f}; + double sampleInterval_{0.1}; + double minMoveDistance_{1.0}; + int maxPoints_{5000}; + double tailDuration_{30.0}; + bool traceVisible_{true}; + + double sampleAccum_{0.0}; + double elapsedTime_{0.0}; + osg::Vec3d lastSamplePos_{0.0, 0.0, 0.0}; + bool hasLastSample_{false}; + bool attachedToScene_{false}; + std::deque sampleTimes_; +}; diff --git a/src/ui/ModelBrowser/ModelTreeWidget.cpp b/src/ui/ModelBrowser/ModelTreeWidget.cpp index 8a0dc7c5..c6bd77bc 100644 --- a/src/ui/ModelBrowser/ModelTreeWidget.cpp +++ b/src/ui/ModelBrowser/ModelTreeWidget.cpp @@ -12,6 +12,7 @@ #include "common/SpdLogger.h" #include "entities/EntitiesManager.h" #include "entities/ComponentFactory.h" +#include "entities/TrajectoryTraceComponent.h" #include "viewer/OsgViewer.h" #include "viewer/OsgView.h" #include "viewer/OsgCameraManipulator.h" @@ -407,6 +408,28 @@ void ModelTreeWidget::PopupEntityMenu(QContextMenuEvent* event, Entity* entity) ); } + bool hasTrajectoryTraceComponent = entity->HasComponent("TrajectoryTraceComponent"); + if (!hasTrajectoryTraceComponent) { + QAction* addEntiy = new QAction(tr("Add Trajectory Trace Component"), this); + menu.addAction(addEntiy); + connect(addEntiy, &QAction::triggered, [this, entity]() { + OnAddComponent("TrajectoryTraceComponent", entity); + } + ); + } + else { + QAction* clearTrace = new QAction(tr("Clear Trajectory Trace"), this); + menu.addAction(clearTrace); + connect(clearTrace, &QAction::triggered, [this, entity]() { + if (auto* traceComponent = entity->GetComponent()) { + traceComponent->ClearTrace(); + QVariant value; + value.setValue(entity); + emit EntityChange(value); + } + }); + } + QAction* addEntiy = new QAction(tr("Delete"), this); menu.addAction(addEntiy); connect(addEntiy, &QAction::triggered, [this, entity]() { diff --git a/src/ui/PropertyBrowser.cpp b/src/ui/PropertyBrowser.cpp index b3c94e67..3d34e918 100644 --- a/src/ui/PropertyBrowser.cpp +++ b/src/ui/PropertyBrowser.cpp @@ -1320,6 +1320,13 @@ void PropertyBrowser::InitComponentPropertyManager() { browser_->setFactoryForManager(coneWaveComponentManager->subColorProperyManager(), colorFactory); componetManager_[coneWaveComponentManager->GetPropertyId()] = coneWaveComponentManager; + QtTrajectoryTraceComponentManager* trajectoryTraceComponentManager = new QtTrajectoryTraceComponentManager(this); + browser_->setFactoryForManager(trajectoryTraceComponentManager->subDoubleProperyManager(), doubleSpinBoxFactory); + browser_->setFactoryForManager(trajectoryTraceComponentManager->subIntProperyManager(), spinBoxFactory); + browser_->setFactoryForManager(trajectoryTraceComponentManager->subBoolProperyManager(), checkBoxFactory); + browser_->setFactoryForManager(trajectoryTraceComponentManager->subColorProperyManager(), colorFactory); + componetManager_[trajectoryTraceComponentManager->GetPropertyId()] = trajectoryTraceComponentManager; + QtDashedLineComponentManager* dashedLineComponentManager = new QtDashedLineComponentManager(this); browser_->setFactoryForManager(dashedLineComponentManager->subEntityProperyManager(), entityUUIDFactory); browser_->setFactoryForManager(dashedLineComponentManager->subDoubleProperyManager(), doubleSpinBoxFactory); @@ -1353,4 +1360,4 @@ void PropertyBrowser::Test() { property = colorManager_->addProperty(tr("color base")); colorManager_->setValue(property, QColor(255, 12, 231, 252)); addProperty(property, QLatin1String("bda")); -} \ No newline at end of file +} diff --git a/src/ui/PropertyBrowser/qtpropertymanager.cpp b/src/ui/PropertyBrowser/qtpropertymanager.cpp index dab1011e..26412cce 100644 --- a/src/ui/PropertyBrowser/qtpropertymanager.cpp +++ b/src/ui/PropertyBrowser/qtpropertymanager.cpp @@ -63,6 +63,7 @@ #include "entities/EntitiesManager.h" #include "entities/MeshComponent.h" #include "entities/PathComponent.h" +#include "entities/TrajectoryTraceComponent.h" #include "entities/ConeWaveComponent.h" #include "entities/DashedLineComponent.h" @@ -10175,6 +10176,328 @@ void QtConeWaveComponentManager::uninitializeProperty(QtProperty* property) { #pragma endregion +// QtTrajectoryTraceComponentManager +#pragma region QtTrajectoryTraceComponentManager + +class QtTrajectoryTraceComponentManagerPrivate { + QtTrajectoryTraceComponentManager* q_ptr; + Q_DECLARE_PUBLIC(QtTrajectoryTraceComponentManager) +public: + void slotDoubleChanged(QtProperty* property, double value); + void slotIntChanged(QtProperty* property, int value); + void slotBoolChanged(QtProperty* property, bool value); + void slotColorChanged(QtProperty* property, const QColor& value); + void slotPropertyDestroyed(QtProperty* property); + + typedef QMap PropertyValueMap; + PropertyValueMap m_values; + + QtDoublePropertyManager* m_doubleProperyManager; + QtIntPropertyManager* m_intProperyManager; + QtBoolPropertyManager* m_boolProperyManager; + QtColorPropertyManager* m_colorProperyManager; + + QMap m_properyToLineWidth; + QMap m_properyToSampleInterval; + QMap m_properyToMinMoveDistance; + QMap m_properyToMaxPoints; + QMap m_properyToTailDuration; + QMap m_properyToVisible; + QMap m_properyToColor; + + QMap m_lineWidthToPropery; + QMap m_sampleIntervalToPropery; + QMap m_minMoveDistanceToPropery; + QMap m_maxPointsToPropery; + QMap m_tailDurationToPropery; + QMap m_visibleToPropery; + QMap m_colorToPropery; +}; + +void QtTrajectoryTraceComponentManagerPrivate::slotDoubleChanged(QtProperty* property, double value) { + if (QtProperty* prop = m_lineWidthToPropery.value(property, 0)) { + QTrajectoryTraceComponentAttribute c = m_values[prop]; + c.SetLineWidth(value); + q_ptr->setValue(prop, c); + } else if (QtProperty* prop = m_sampleIntervalToPropery.value(property, 0)) { + QTrajectoryTraceComponentAttribute c = m_values[prop]; + c.SetSampleInterval(value); + q_ptr->setValue(prop, c); + } else if (QtProperty* prop = m_minMoveDistanceToPropery.value(property, 0)) { + QTrajectoryTraceComponentAttribute c = m_values[prop]; + c.SetMinMoveDistance(value); + q_ptr->setValue(prop, c); + } +} + +void QtTrajectoryTraceComponentManagerPrivate::slotIntChanged(QtProperty* property, int value) { + if (QtProperty* prop = m_maxPointsToPropery.value(property, 0)) { + QTrajectoryTraceComponentAttribute c = m_values[prop]; + c.SetMaxPoints(value); + q_ptr->setValue(prop, c); + } +} + +void QtTrajectoryTraceComponentManagerPrivate::slotBoolChanged(QtProperty* property, bool value) { + if (QtProperty* prop = m_visibleToPropery.value(property, 0)) { + QTrajectoryTraceComponentAttribute c = m_values[prop]; + c.SetVisible(value); + q_ptr->setValue(prop, c); + } +} + +void QtTrajectoryTraceComponentManagerPrivate::slotColorChanged(QtProperty* property, const QColor& value) { + if (QtProperty* prop = m_colorToPropery.value(property, 0)) { + QTrajectoryTraceComponentAttribute c = m_values[prop]; + c.SetColor(value); + q_ptr->setValue(prop, c); + } +} + +void QtTrajectoryTraceComponentManagerPrivate::slotPropertyDestroyed(QtProperty* property) { + if (QtProperty* subProp = m_lineWidthToPropery.value(property, nullptr)) { + m_lineWidthToPropery[subProp] = 0; + m_lineWidthToPropery.remove(property); + } + if (QtProperty* subProp = m_sampleIntervalToPropery.value(property, nullptr)) { + m_sampleIntervalToPropery[subProp] = 0; + m_sampleIntervalToPropery.remove(property); + } + if (QtProperty* subProp = m_minMoveDistanceToPropery.value(property, nullptr)) { + m_minMoveDistanceToPropery[subProp] = 0; + m_minMoveDistanceToPropery.remove(property); + } + if (QtProperty* subProp = m_maxPointsToPropery.value(property, nullptr)) { + m_maxPointsToPropery[subProp] = 0; + m_maxPointsToPropery.remove(property); + } + if (QtProperty* subProp = m_tailDurationToPropery.value(property, nullptr)) { + m_tailDurationToPropery[subProp] = 0; + m_tailDurationToPropery.remove(property); + } + if (QtProperty* subProp = m_visibleToPropery.value(property, nullptr)) { + m_visibleToPropery[subProp] = 0; + m_visibleToPropery.remove(property); + } + if (QtProperty* subProp = m_colorToPropery.value(property, nullptr)) { + m_colorToPropery[subProp] = 0; + m_colorToPropery.remove(property); + } +} + +QtTrajectoryTraceComponentManager::QtTrajectoryTraceComponentManager(QObject* parent) + : QtComponentPropertyManager(parent), d_ptr(new QtTrajectoryTraceComponentManagerPrivate) { + d_ptr->q_ptr = this; + + d_ptr->m_doubleProperyManager = new QtDoublePropertyManager(this); + connect(d_ptr->m_doubleProperyManager, SIGNAL(valueChanged(QtProperty*, double)), + this, SLOT(slotDoubleChanged(QtProperty*, double))); + connect(d_ptr->m_doubleProperyManager, SIGNAL(propertyDestroyed(QtProperty*)), + this, SLOT(slotPropertyDestroyed(QtProperty*))); + + d_ptr->m_intProperyManager = new QtIntPropertyManager(this); + connect(d_ptr->m_intProperyManager, SIGNAL(valueChanged(QtProperty*, int)), + this, SLOT(slotIntChanged(QtProperty*, int))); + connect(d_ptr->m_intProperyManager, SIGNAL(propertyDestroyed(QtProperty*)), + this, SLOT(slotPropertyDestroyed(QtProperty*))); + + d_ptr->m_boolProperyManager = new QtBoolPropertyManager(this); + connect(d_ptr->m_boolProperyManager, SIGNAL(valueChanged(QtProperty*, bool)), + this, SLOT(slotBoolChanged(QtProperty*, bool))); + connect(d_ptr->m_boolProperyManager, SIGNAL(propertyDestroyed(QtProperty*)), + this, SLOT(slotPropertyDestroyed(QtProperty*))); + + d_ptr->m_colorProperyManager = new QtColorPropertyManager(this); + connect(d_ptr->m_colorProperyManager, SIGNAL(valueChanged(QtProperty*, const QColor&)), + this, SLOT(slotColorChanged(QtProperty*, const QColor&))); + connect(d_ptr->m_colorProperyManager, SIGNAL(propertyDestroyed(QtProperty*)), + this, SLOT(slotPropertyDestroyed(QtProperty*))); +} + +QtTrajectoryTraceComponentManager::~QtTrajectoryTraceComponentManager() { + clear(); +} + +QtProperty* QtTrajectoryTraceComponentManager::AddProperty() { + return addProperty(tr("TrajectoryTraceComponent")); +} + +void QtTrajectoryTraceComponentManager::SetPropertyValue(QtProperty* property, SceneComponent* sceneComponent) { + QTrajectoryTraceComponentAttribute componentAttribute(reinterpret_cast(sceneComponent)); + setValue(property, componentAttribute); +} + +QString QtTrajectoryTraceComponentManager::GetPropertyId() const { + return QStringLiteral("TrajectoryTraceComponent"); +} + +QTrajectoryTraceComponentAttribute QtTrajectoryTraceComponentManager::value(const QtProperty* property) const { + return d_ptr->m_values.value(property, QTrajectoryTraceComponentAttribute()); +} + +QtDoublePropertyManager* QtTrajectoryTraceComponentManager::subDoubleProperyManager() const { + return d_ptr->m_doubleProperyManager; +} + +QtIntPropertyManager* QtTrajectoryTraceComponentManager::subIntProperyManager() const { + return d_ptr->m_intProperyManager; +} + +QtBoolPropertyManager* QtTrajectoryTraceComponentManager::subBoolProperyManager() const { + return d_ptr->m_boolProperyManager; +} + +QtColorPropertyManager* QtTrajectoryTraceComponentManager::subColorProperyManager() const { + return d_ptr->m_colorProperyManager; +} + +QString QtTrajectoryTraceComponentManager::valueText(const QtProperty* property) const { + const QtTrajectoryTraceComponentManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); + if (it == d_ptr->m_values.constEnd()) + return QString(); + + return QString("TrajectoryTraceComponent"); +} + +QIcon QtTrajectoryTraceComponentManager::valueIcon(const QtProperty* property) const { + const QtTrajectoryTraceComponentManagerPrivate::PropertyValueMap::const_iterator it = d_ptr->m_values.constFind(property); + if (it == d_ptr->m_values.constEnd()) + return QIcon(); + + return QIcon(); +} + +void QtTrajectoryTraceComponentManager::setValue(QtProperty* property, const QTrajectoryTraceComponentAttribute& value) { + const QtTrajectoryTraceComponentManagerPrivate::PropertyValueMap::iterator it = d_ptr->m_values.find(property); + if (it == d_ptr->m_values.end()) + return; + + it.value() = value; + + d_ptr->m_doubleProperyManager->setValue(d_ptr->m_properyToLineWidth[property], value.GetLineWidth()); + d_ptr->m_doubleProperyManager->setValue(d_ptr->m_properyToSampleInterval[property], value.GetSampleInterval()); + d_ptr->m_doubleProperyManager->setValue(d_ptr->m_properyToMinMoveDistance[property], value.GetMinMoveDistance()); + d_ptr->m_intProperyManager->setValue(d_ptr->m_properyToMaxPoints[property], value.GetMaxPoints()); + d_ptr->m_doubleProperyManager->setValue(d_ptr->m_properyToTailDuration[property], value.GetTailDuration()); + d_ptr->m_boolProperyManager->setValue(d_ptr->m_properyToVisible[property], value.IsVisible()); + d_ptr->m_colorProperyManager->setValue(d_ptr->m_properyToColor[property], value.GetColor()); + + emit propertyChanged(property); + emit valueChanged(property, value); +} + +void QtTrajectoryTraceComponentManager::initializeProperty(QtProperty* property) { + QTrajectoryTraceComponentAttribute val; + d_ptr->m_values[property] = val; + + QtProperty* prop = d_ptr->m_doubleProperyManager->addProperty(); + prop->setPropertyName(tr("LineWidth")); + d_ptr->m_doubleProperyManager->setValueOnly(prop, val.GetLineWidth()); + d_ptr->m_doubleProperyManager->setRange(prop, 1.0, 20.0); + d_ptr->m_properyToLineWidth[property] = prop; + d_ptr->m_lineWidthToPropery[prop] = property; + property->addSubProperty(prop); + + prop = d_ptr->m_doubleProperyManager->addProperty(); + prop->setPropertyName(tr("SampleInterval")); + d_ptr->m_doubleProperyManager->setValueOnly(prop, val.GetSampleInterval()); + d_ptr->m_doubleProperyManager->setRange(prop, 0.01, 60.0); + d_ptr->m_properyToSampleInterval[property] = prop; + d_ptr->m_sampleIntervalToPropery[prop] = property; + property->addSubProperty(prop); + + prop = d_ptr->m_doubleProperyManager->addProperty(); + prop->setPropertyName(tr("MinMoveDistance")); + d_ptr->m_doubleProperyManager->setValueOnly(prop, val.GetMinMoveDistance()); + d_ptr->m_doubleProperyManager->setRange(prop, 0.0, 1000000.0); + d_ptr->m_properyToMinMoveDistance[property] = prop; + d_ptr->m_minMoveDistanceToPropery[prop] = property; + property->addSubProperty(prop); + + prop = d_ptr->m_intProperyManager->addProperty(); + prop->setPropertyName(tr("MaxPoints")); + d_ptr->m_intProperyManager->setValueOnly(prop, val.GetMaxPoints()); + d_ptr->m_intProperyManager->setRange(prop, 2, 1000000); + d_ptr->m_properyToMaxPoints[property] = prop; + d_ptr->m_maxPointsToPropery[prop] = property; + property->addSubProperty(prop); + + prop = d_ptr->m_doubleProperyManager->addProperty(); + prop->setPropertyName(tr("TailDuration")); + d_ptr->m_doubleProperyManager->setValueOnly(prop, val.GetTailDuration()); + d_ptr->m_doubleProperyManager->setRange(prop, 0.0, 36000.0); + d_ptr->m_properyToTailDuration[property] = prop; + d_ptr->m_tailDurationToPropery[prop] = property; + property->addSubProperty(prop); + + prop = d_ptr->m_boolProperyManager->addProperty(); + prop->setPropertyName(tr("Visible")); + d_ptr->m_boolProperyManager->setValue(prop, val.IsVisible()); + d_ptr->m_properyToVisible[property] = prop; + d_ptr->m_visibleToPropery[prop] = property; + property->addSubProperty(prop); + + prop = d_ptr->m_colorProperyManager->addProperty(); + prop->setPropertyName(tr("Color")); + d_ptr->m_colorProperyManager->setValue(prop, val.GetColor()); + d_ptr->m_properyToColor[property] = prop; + d_ptr->m_colorToPropery[prop] = property; + property->addSubProperty(prop); +} + +void QtTrajectoryTraceComponentManager::uninitializeProperty(QtProperty* property) { + QtProperty* prop = d_ptr->m_lineWidthToPropery[property]; + if (prop) { + d_ptr->m_lineWidthToPropery.remove(prop); + delete prop; + } + d_ptr->m_properyToLineWidth.remove(property); + + prop = d_ptr->m_sampleIntervalToPropery[property]; + if (prop) { + d_ptr->m_sampleIntervalToPropery.remove(prop); + delete prop; + } + d_ptr->m_properyToSampleInterval.remove(property); + + prop = d_ptr->m_minMoveDistanceToPropery[property]; + if (prop) { + d_ptr->m_minMoveDistanceToPropery.remove(prop); + delete prop; + } + d_ptr->m_properyToMinMoveDistance.remove(property); + + prop = d_ptr->m_maxPointsToPropery[property]; + if (prop) { + d_ptr->m_maxPointsToPropery.remove(prop); + delete prop; + } + d_ptr->m_properyToMaxPoints.remove(property); + + prop = d_ptr->m_tailDurationToPropery[property]; + if (prop) { + d_ptr->m_tailDurationToPropery.remove(prop); + delete prop; + } + d_ptr->m_properyToTailDuration.remove(property); + + prop = d_ptr->m_visibleToPropery[property]; + if (prop) { + d_ptr->m_visibleToPropery.remove(prop); + delete prop; + } + d_ptr->m_properyToVisible.remove(property); + + prop = d_ptr->m_colorToPropery[property]; + if (prop) { + d_ptr->m_colorToPropery.remove(prop); + delete prop; + } + d_ptr->m_properyToColor.remove(property); +} + +#pragma endregion + // QtDashedLineComponentManager #pragma region QtDashedLineComponentManager diff --git a/src/ui/PropertyBrowser/qtpropertymanager.h b/src/ui/PropertyBrowser/qtpropertymanager.h index c6abf204..ce05a56f 100644 --- a/src/ui/PropertyBrowser/qtpropertymanager.h +++ b/src/ui/PropertyBrowser/qtpropertymanager.h @@ -1259,6 +1259,50 @@ private: #pragma endregion +#pragma region QtTrajectoryTraceComponentManager + +class QtTrajectoryTraceComponentManagerPrivate; + +class QtTrajectoryTraceComponentManager : public QtComponentPropertyManager { + Q_OBJECT +public: + QtTrajectoryTraceComponentManager(QObject* parent = 0); + ~QtTrajectoryTraceComponentManager(); + + QtProperty* AddProperty() override; + void SetPropertyValue(QtProperty* property, SceneComponent* sceneComponent) override; + QString GetPropertyId() const override; + + QTrajectoryTraceComponentAttribute value(const QtProperty* property) const; + + QtDoublePropertyManager* subDoubleProperyManager() const; + QtIntPropertyManager* subIntProperyManager() const; + QtBoolPropertyManager* subBoolProperyManager() const; + QtColorPropertyManager* subColorProperyManager() const; + +public Q_SLOTS: + void setValue(QtProperty* property, const QTrajectoryTraceComponentAttribute& val); +Q_SIGNALS: + void valueChanged(QtProperty* property, const QTrajectoryTraceComponentAttribute& val); +protected: + QString valueText(const QtProperty* property) const override; + QIcon valueIcon(const QtProperty* property) const override; + void initializeProperty(QtProperty* property) override; + void uninitializeProperty(QtProperty* property) override; +private: + QScopedPointer d_ptr; + Q_DECLARE_PRIVATE(QtTrajectoryTraceComponentManager) + Q_DISABLE_COPY_MOVE(QtTrajectoryTraceComponentManager) + Q_PRIVATE_SLOT(d_func(), void slotDoubleChanged(QtProperty*, double)) + Q_PRIVATE_SLOT(d_func(), void slotIntChanged(QtProperty*, int)) + Q_PRIVATE_SLOT(d_func(), void slotBoolChanged(QtProperty*, bool)) + Q_PRIVATE_SLOT(d_func(), void slotColorChanged(QtProperty*, const QColor&)) + Q_PRIVATE_SLOT(d_func(), void slotPropertyDestroyed(QtProperty*)) +}; + +#pragma endregion + + #pragma region QtDashedLineComponentManager class QtDashedLineComponentManagerPrivate; diff --git a/src/ui/PropertyBrowser/qtworkspaceattribute.cpp b/src/ui/PropertyBrowser/qtworkspaceattribute.cpp index d174758b..9b52d82b 100644 --- a/src/ui/PropertyBrowser/qtworkspaceattribute.cpp +++ b/src/ui/PropertyBrowser/qtworkspaceattribute.cpp @@ -5,6 +5,7 @@ #include "entities/Entity.h" #include "entities/MeshComponent.h" #include "entities/PathComponent.h" +#include "entities/TrajectoryTraceComponent.h" #include "entities/ConeWaveComponent.h" #include "entities/DashedLineComponent.h" #include "entities/EntitiesManager.h" @@ -465,6 +466,146 @@ QPathComponentAttribute& QPathComponentAttribute::operator=(const QPathComponent return *this; } +QTrajectoryTraceComponentAttribute::QTrajectoryTraceComponentAttribute(TrajectoryTraceComponent* obj) + : object_(obj) { +} + +void QTrajectoryTraceComponentAttribute::SetColor(const QColor& c) { + if (nullptr == object_) { + return; + } + + osg::Vec4 vColor = object_->GetColor(); + QColor color; + OsgUtils::Vec4ToQColor(vColor, &color); + if (c == color) { + return; + } + + OsgUtils::QColorToVec4(c, &vColor); + object_->SetColor(vColor); +} + +QColor QTrajectoryTraceComponentAttribute::GetColor() const { + if (nullptr == object_) { + return QColor(); + } + + osg::Vec4 vColor = object_->GetColor(); + QColor color; + OsgUtils::Vec4ToQColor(vColor, &color); + return color; +} + +void QTrajectoryTraceComponentAttribute::SetLineWidth(double width) { + if (nullptr == object_) { + return; + } + + object_->SetLineWidth(static_cast(width)); +} + +double QTrajectoryTraceComponentAttribute::GetLineWidth() const { + if (nullptr == object_) { + return 2.0; + } + + return object_->GetLineWidth(); +} + +void QTrajectoryTraceComponentAttribute::SetSampleInterval(double interval) { + if (nullptr == object_) { + return; + } + + object_->SetSampleInterval(interval); +} + +double QTrajectoryTraceComponentAttribute::GetSampleInterval() const { + if (nullptr == object_) { + return 0.1; + } + + return object_->GetSampleInterval(); +} + +void QTrajectoryTraceComponentAttribute::SetMinMoveDistance(double distance) { + if (nullptr == object_) { + return; + } + + object_->SetMinMoveDistance(distance); +} + +double QTrajectoryTraceComponentAttribute::GetMinMoveDistance() const { + if (nullptr == object_) { + return 1.0; + } + + return object_->GetMinMoveDistance(); +} + +void QTrajectoryTraceComponentAttribute::SetMaxPoints(int maxPoints) { + if (nullptr == object_) { + return; + } + + object_->SetMaxPoints(maxPoints); +} + +int QTrajectoryTraceComponentAttribute::GetMaxPoints() const { + if (nullptr == object_) { + return 5000; + } + + return object_->GetMaxPoints(); +} + +void QTrajectoryTraceComponentAttribute::SetTailDuration(double duration) { + if (nullptr == object_) { + return; + } + + object_->SetTailDuration(duration); +} + +double QTrajectoryTraceComponentAttribute::GetTailDuration() const { + if (nullptr == object_) { + return 30.0; + } + + return object_->GetTailDuration(); +} + +void QTrajectoryTraceComponentAttribute::SetVisible(bool visible) { + if (nullptr == object_) { + return; + } + + object_->SetTraceVisible(visible); +} + +bool QTrajectoryTraceComponentAttribute::IsVisible() const { + if (nullptr == object_) { + return true; + } + + return object_->IsTraceVisible(); +} + +bool QTrajectoryTraceComponentAttribute::operator==(const QTrajectoryTraceComponentAttribute& other) { + return object_ == other.object_; +} + +QTrajectoryTraceComponentAttribute& QTrajectoryTraceComponentAttribute::operator=(const QTrajectoryTraceComponentAttribute& other) { + if (this == &other) { + return *this; + } + + object_ = other.object_; + return *this; +} + QConeWaveComponentAttribute::QConeWaveComponentAttribute(ConeWaveComponent* object) : object_(object) { } diff --git a/src/ui/PropertyBrowser/qtworkspaceattribute.h b/src/ui/PropertyBrowser/qtworkspaceattribute.h index 09269158..2daec57b 100644 --- a/src/ui/PropertyBrowser/qtworkspaceattribute.h +++ b/src/ui/PropertyBrowser/qtworkspaceattribute.h @@ -234,6 +234,40 @@ private: class PathComponent* object_{ nullptr }; }; +class QTrajectoryTraceComponentAttribute { +public: + QTrajectoryTraceComponentAttribute() = default; + QTrajectoryTraceComponentAttribute(class TrajectoryTraceComponent* obj); + QTrajectoryTraceComponentAttribute& operator=(const QTrajectoryTraceComponentAttribute& other); + ~QTrajectoryTraceComponentAttribute() = default; + + bool operator== (const QTrajectoryTraceComponentAttribute& other); + + void SetColor(const QColor& c); + QColor GetColor() const; + + void SetLineWidth(double width); + double GetLineWidth() const; + + void SetSampleInterval(double interval); + double GetSampleInterval() const; + + void SetMinMoveDistance(double distance); + double GetMinMoveDistance() const; + + void SetMaxPoints(int maxPoints); + int GetMaxPoints() const; + + void SetTailDuration(double duration); + double GetTailDuration() const; + + void SetVisible(bool visible); + bool IsVisible() const; + +private: + class TrajectoryTraceComponent* object_{ nullptr }; +}; + class QConeWaveComponentAttribute { public: QConeWaveComponentAttribute() = default;