modified panel
This commit is contained in:
commit
630552b156
@ -3,8 +3,10 @@
|
|||||||
#include "common/RecourceHelper.h"
|
#include "common/RecourceHelper.h"
|
||||||
#include "workspace/WorkSpaceManager.h"
|
#include "workspace/WorkSpaceManager.h"
|
||||||
#include "entities/EntitiesManager.h"
|
#include "entities/EntitiesManager.h"
|
||||||
|
#include "entities/EntityFactory.h"
|
||||||
#include "viewer/OsgViewer.h"
|
#include "viewer/OsgViewer.h"
|
||||||
#include "scene/MeshManager.h"
|
#include "scene/MeshManager.h"
|
||||||
|
#include "workspace/PresetModelConfigParser.h"
|
||||||
#include "network/NetDriver.h"
|
#include "network/NetDriver.h"
|
||||||
#include "python/PythonModule.h"
|
#include "python/PythonModule.h"
|
||||||
|
|
||||||
@ -30,9 +32,11 @@ QString Application::GetBinPath() {
|
|||||||
void Application::Init() {
|
void Application::Init() {
|
||||||
Singleton<MeshManager>::Create(this);
|
Singleton<MeshManager>::Create(this);
|
||||||
Singleton<RecourceHelper>::Create(this);
|
Singleton<RecourceHelper>::Create(this);
|
||||||
|
Singleton<EntityFactory>::Create(this);
|
||||||
Singleton<EntitiesManager>::Create(this);
|
Singleton<EntitiesManager>::Create(this);
|
||||||
Singleton<WorkSpaceManager>::Create(this);
|
Singleton<WorkSpaceManager>::Create(this);
|
||||||
Singleton<NetDriver>::Create(this);
|
Singleton<NetDriver>::Create(this);
|
||||||
|
Singleton<PresetModelConfigParser>::Create(this);
|
||||||
//Singleton<PythonModule>::Create(this);
|
//Singleton<PythonModule>::Create(this);
|
||||||
|
|
||||||
connect(&timer_, &QTimer::timeout, this, &Application::OnTimeout);
|
connect(&timer_, &QTimer::timeout, this, &Application::OnTimeout);
|
||||||
@ -46,8 +50,10 @@ void Application::OnTimeout() {
|
|||||||
void Application::Uninit() {
|
void Application::Uninit() {
|
||||||
//Singleton<PythonModule>::Destory();
|
//Singleton<PythonModule>::Destory();
|
||||||
Singleton<NetDriver>::Destory();
|
Singleton<NetDriver>::Destory();
|
||||||
|
Singleton<PresetModelConfigParser>::Destory();
|
||||||
Singleton<WorkSpaceManager>::Destory();
|
Singleton<WorkSpaceManager>::Destory();
|
||||||
Singleton<EntitiesManager>::Destory();
|
Singleton<EntitiesManager>::Destory();
|
||||||
|
Singleton<EntityFactory>::Destory();
|
||||||
Singleton<RecourceHelper>::Destory();
|
Singleton<RecourceHelper>::Destory();
|
||||||
Singleton<MeshManager>::Destory();
|
Singleton<MeshManager>::Destory();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,6 +7,8 @@
|
|||||||
#include "common/SpdLogger.h"
|
#include "common/SpdLogger.h"
|
||||||
#include "entities/Entity.h"
|
#include "entities/Entity.h"
|
||||||
#include "entities/ComponentFactory.h"
|
#include "entities/ComponentFactory.h"
|
||||||
|
#include "entities/EntityFactory.h"
|
||||||
|
#include "entities/EntityRegistration.h"
|
||||||
|
|
||||||
#include "xml/tinyxml2.h"
|
#include "xml/tinyxml2.h"
|
||||||
|
|
||||||
@ -14,6 +16,7 @@ template<> EntitiesManager* Singleton<EntitiesManager>::instance_ = nullptr;
|
|||||||
|
|
||||||
EntitiesManager::EntitiesManager(QObject* parent)
|
EntitiesManager::EntitiesManager(QObject* parent)
|
||||||
: QObject(parent) {
|
: QObject(parent) {
|
||||||
|
Initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
EntitiesManager::~EntitiesManager() {
|
EntitiesManager::~EntitiesManager() {
|
||||||
@ -107,9 +110,6 @@ Entity* EntitiesManager::CreateMesh(const QString& mesh) {
|
|||||||
conponent->SetAttribute("mesh", mesh.toStdString().c_str());
|
conponent->SetAttribute("mesh", mesh.toStdString().c_str());
|
||||||
conponent->AttachEntity(entity);
|
conponent->AttachEntity(entity);
|
||||||
|
|
||||||
//conponent = ComponentFactory::Create("PathComponent", conponent);
|
|
||||||
//conponent->AttachEntity(entity);
|
|
||||||
|
|
||||||
return entity;
|
return entity;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -148,3 +148,78 @@ void EntitiesManager::RemoveEntity(Entity* entity) {
|
|||||||
|
|
||||||
entities_.erase(entity->GetUUid());
|
entities_.erase(entity->GetUUid());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void EntitiesManager::Initialize() {
|
||||||
|
if (!initialized_) {
|
||||||
|
EntityRegistration::RegisterAllEntities();
|
||||||
|
initialized_ = true;
|
||||||
|
LOG_INFO("EntitiesManager::Initialize - Entity factory initialized");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* EntitiesManager::CreateEntity(const QString& type, WorkSpace* workspace) {
|
||||||
|
if (!initialized_) {
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!workspace) {
|
||||||
|
workspace = WorkSpaceManager::Get().GetCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* entity = EntityFactory::Get().CreateEntity(type, workspace);
|
||||||
|
if (entity) {
|
||||||
|
AddEntity(entity);
|
||||||
|
if (workspace) {
|
||||||
|
workspace->AddEntity(entity);
|
||||||
|
}
|
||||||
|
LOG_INFO("EntitiesManager::CreateEntity - Created entity of type: {}", type.toStdString());
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("EntitiesManager::CreateEntity - Failed to create entity of type: {}", type.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* EntitiesManager::CreateEntityWithComponents(const QString& type, const QString& mesh, bool useLabel, WorkSpace* workspace) {
|
||||||
|
if (!initialized_) {
|
||||||
|
Initialize();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!workspace) {
|
||||||
|
workspace = WorkSpaceManager::Get().GetCurrent();
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* entity = EntityFactory::Get().CreateEntityWithComponents(type, mesh, useLabel, workspace);
|
||||||
|
if (entity) {
|
||||||
|
AddEntity(entity);
|
||||||
|
if (workspace) {
|
||||||
|
workspace->AddEntity(entity);
|
||||||
|
}
|
||||||
|
LOG_INFO("EntitiesManager::CreateEntityWithComponents - Created entity with components of type: {}", type.toStdString());
|
||||||
|
} else {
|
||||||
|
LOG_ERROR("EntitiesManager::CreateEntityWithComponents - Failed to create entity of type: {}", type.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList EntitiesManager::GetSupportedEntityTypes() const {
|
||||||
|
if (!initialized_) {
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
return EntityFactory::Get().GetRegisteredTypes();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EntitiesManager::GetEntityDisplayName(const QString& type) const {
|
||||||
|
if (!initialized_) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
return EntityFactory::Get().GetDisplayName(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EntitiesManager::GetEntityDescription(const QString& type) const {
|
||||||
|
if (!initialized_) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
return EntityFactory::Get().GetDescription(type);
|
||||||
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@
|
|||||||
#include "xml/tinyxml2.h"
|
#include "xml/tinyxml2.h"
|
||||||
|
|
||||||
class Entity;
|
class Entity;
|
||||||
|
class WorkSpace;
|
||||||
|
|
||||||
class EntitiesManager : public QObject, public Singleton<EntitiesManager> {
|
class EntitiesManager : public QObject, public Singleton<EntitiesManager> {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -18,12 +19,26 @@ public:
|
|||||||
~EntitiesManager();
|
~EntitiesManager();
|
||||||
void OnDestory();
|
void OnDestory();
|
||||||
|
|
||||||
|
// Initialize entity factory
|
||||||
|
void Initialize();
|
||||||
|
|
||||||
bool Contains(const QString& name) const;
|
bool Contains(const QString& name) const;
|
||||||
|
|
||||||
bool Parse(const tinyxml2::XMLElement* element, class WorkSpace* workspce);
|
bool Parse(const tinyxml2::XMLElement* element, class WorkSpace* workspce);
|
||||||
|
|
||||||
|
// Legacy methods (for backward compatibility)
|
||||||
Entity* Create(const QString& name);
|
Entity* Create(const QString& name);
|
||||||
Entity* CreateMesh(const QString& mesh);
|
Entity* CreateMesh(const QString& mesh);
|
||||||
|
|
||||||
|
// New factory methods
|
||||||
|
Entity* CreateEntity(const QString& type, WorkSpace* workspace = nullptr);
|
||||||
|
Entity* CreateEntityWithComponents(const QString& type, const QString& mesh, bool useLabel, WorkSpace* workspace = nullptr);
|
||||||
|
|
||||||
|
// Get supported entity types
|
||||||
|
QStringList GetSupportedEntityTypes() const;
|
||||||
|
QString GetEntityDisplayName(const QString& type) const;
|
||||||
|
QString GetEntityDescription(const QString& type) const;
|
||||||
|
|
||||||
bool DeleteEntity(Entity* entity);
|
bool DeleteEntity(Entity* entity);
|
||||||
|
|
||||||
Entity* GetEntity(const QString& uuid);
|
Entity* GetEntity(const QString& uuid);
|
||||||
@ -36,5 +51,5 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<QString, Entity*> entities_;
|
std::unordered_map<QString, Entity*> entities_;
|
||||||
|
bool initialized_{false};
|
||||||
};
|
};
|
||||||
129
src/entities/EntityFactory.cpp
Normal file
129
src/entities/EntityFactory.cpp
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
#include "entities/EntityFactory.h"
|
||||||
|
#include "entities/ComponentFactory.h"
|
||||||
|
#include "common/SpdLogger.h"
|
||||||
|
#include "workspace/WorkSpace.h"
|
||||||
|
#include <QStringList>
|
||||||
|
|
||||||
|
template<> EntityFactory* Singleton<EntityFactory>::instance_ = nullptr;
|
||||||
|
|
||||||
|
Entity* EntityFactory::CreateEntity(const QString& type, WorkSpace* workspace) {
|
||||||
|
auto it = creators_.find(type);
|
||||||
|
if (it == creators_.end()) {
|
||||||
|
LOG_WARN("EntityFactory::CreateEntity - Unknown entity type: {}", type.toStdString());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* entity = it->second->CreateEntity(workspace);
|
||||||
|
if (!entity) {
|
||||||
|
LOG_ERROR("EntityFactory::CreateEntity - Failed to create entity of type: {}", type.toStdString());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("EntityFactory::CreateEntity - Successfully created entity of type: {}", type.toStdString());
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* EntityFactory::CreateEntityWithComponents(const QString& type, const QString& mesh, bool useLabel, WorkSpace* workspace) {
|
||||||
|
Entity* entity = CreateEntity(type, workspace);
|
||||||
|
if (!entity) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto it = creators_.find(type);
|
||||||
|
if (it == creators_.end()) {
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get default mesh
|
||||||
|
QString defaultMesh = it->second->GetDefaultMesh();
|
||||||
|
if (!mesh.isEmpty()) {
|
||||||
|
defaultMesh = mesh;
|
||||||
|
}
|
||||||
|
if (!defaultMesh.isEmpty()) {
|
||||||
|
SceneComponent* meshComponent = ComponentFactory::Create("MeshComponent", nullptr);
|
||||||
|
if (meshComponent) {
|
||||||
|
meshComponent->SetAttribute("mesh", defaultMesh.toLocal8Bit());
|
||||||
|
meshComponent->AttachEntity(entity);
|
||||||
|
LOG_INFO("EntityFactory::CreateEntityWithComponents - Added MeshComponent with mesh: {}", defaultMesh.toStdString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useLabel) {
|
||||||
|
SceneComponent* rootComponent = entity->GetRootComponent();
|
||||||
|
if (nullptr == rootComponent) {
|
||||||
|
SceneComponent* meshComponent = ComponentFactory::Create("LabelComponent", nullptr);
|
||||||
|
if (meshComponent) {
|
||||||
|
meshComponent->AttachEntity(entity);
|
||||||
|
LOG_INFO("EntityFactory::CreateEntityWithComponents - Added LabelComponent with mesh: {}", defaultMesh.toStdString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
SceneComponent* LabelComponent = ComponentFactory::Create("LabelComponent", rootComponent);
|
||||||
|
if (LabelComponent) {
|
||||||
|
LabelComponent->AttachTo(rootComponent);
|
||||||
|
LOG_INFO("EntityFactory::CreateEntityWithComponents - Added LabelComponent with mesh: {}", defaultMesh.toStdString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add required components
|
||||||
|
QStringList requiredComponents = it->second->GetRequiredComponents();
|
||||||
|
SceneComponent* rootComponent = entity->GetRootComponent();
|
||||||
|
|
||||||
|
for (int i = 0; i < requiredComponents.size(); ++i) {
|
||||||
|
QString componentType = requiredComponents.at(i);
|
||||||
|
SceneComponent* component = ComponentFactory::Create(componentType, rootComponent);
|
||||||
|
if (component && rootComponent) {
|
||||||
|
component->AttachTo(rootComponent);
|
||||||
|
LOG_INFO("EntityFactory::CreateEntityWithComponents - Added component: {}", componentType.toStdString());
|
||||||
|
} else {
|
||||||
|
LOG_WARN("EntityFactory::CreateEntityWithComponents - Failed to create component: {}", componentType.toStdString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList EntityFactory::GetRegisteredTypes() const {
|
||||||
|
QStringList types;
|
||||||
|
for (auto it = creators_.begin(); it != creators_.end(); ++it) {
|
||||||
|
types.append(it->first);
|
||||||
|
}
|
||||||
|
return types;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EntityFactory::GetDisplayName(const QString& type) const {
|
||||||
|
auto it = creators_.find(type);
|
||||||
|
if (it != creators_.end()) {
|
||||||
|
return it->second->GetDisplayName();
|
||||||
|
}
|
||||||
|
return type; // 返回类型名作为默认显示名
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EntityFactory::GetDescription(const QString& type) const {
|
||||||
|
auto it = creators_.find(type);
|
||||||
|
if (it != creators_.end()) {
|
||||||
|
return it->second->GetDescription();
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EntityFactory::GetDefaultMesh(const QString& type) const {
|
||||||
|
auto it = creators_.find(type);
|
||||||
|
if (it != creators_.end()) {
|
||||||
|
return it->second->GetDefaultMesh();
|
||||||
|
}
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList EntityFactory::GetRequiredComponents(const QString& type) const {
|
||||||
|
auto it = creators_.find(type);
|
||||||
|
if (it != creators_.end()) {
|
||||||
|
return it->second->GetRequiredComponents();
|
||||||
|
}
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EntityFactory::IsTypeSupported(const QString& type) const {
|
||||||
|
return creators_.find(type) != creators_.end();
|
||||||
|
}
|
||||||
86
src/entities/EntityFactory.h
Normal file
86
src/entities/EntityFactory.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <memory>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "app/Singleton.h"
|
||||||
|
#include "entities/Entity.h"
|
||||||
|
|
||||||
|
class WorkSpace;
|
||||||
|
|
||||||
|
class IEntityCreator {
|
||||||
|
public:
|
||||||
|
virtual ~IEntityCreator() = default;
|
||||||
|
virtual Entity* CreateEntity(WorkSpace* workspace) = 0;
|
||||||
|
virtual QString GetEntityType() const = 0;
|
||||||
|
virtual QString GetDisplayName() const = 0;
|
||||||
|
virtual QString GetDescription() const = 0;
|
||||||
|
virtual QString GetDefaultMesh() const = 0;
|
||||||
|
virtual QStringList GetRequiredComponents() const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
class EntityCreator : public IEntityCreator {
|
||||||
|
public:
|
||||||
|
EntityCreator(const QString& type, const QString& displayName,
|
||||||
|
const QString& description, const QString& defaultMesh,
|
||||||
|
const QStringList& requiredComponents = QStringList())
|
||||||
|
: entityType_(type), displayName_(displayName), description_(description),
|
||||||
|
defaultMesh_(defaultMesh), requiredComponents_(requiredComponents) {}
|
||||||
|
|
||||||
|
Entity* CreateEntity(WorkSpace* workspace) override {
|
||||||
|
return new T(workspace);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString GetEntityType() const override { return entityType_; }
|
||||||
|
QString GetDisplayName() const override { return displayName_; }
|
||||||
|
QString GetDescription() const override { return description_; }
|
||||||
|
QString GetDefaultMesh() const override { return defaultMesh_; }
|
||||||
|
QStringList GetRequiredComponents() const override { return requiredComponents_; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString entityType_;
|
||||||
|
QString displayName_;
|
||||||
|
QString description_;
|
||||||
|
QString defaultMesh_;
|
||||||
|
QStringList requiredComponents_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class EntityFactory : public Singleton<EntityFactory> {
|
||||||
|
public:
|
||||||
|
EntityFactory() = default;
|
||||||
|
explicit EntityFactory(class Application* app) : app_(app) {}
|
||||||
|
~EntityFactory() = default;
|
||||||
|
|
||||||
|
void OnDestory() { }
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void RegisterEntity(const QString& type, const QString& displayName,
|
||||||
|
const QString& description, const QString& defaultMesh,
|
||||||
|
const QStringList& requiredComponents = QStringList()) {
|
||||||
|
auto creator = std::make_unique<EntityCreator<T>>(type, displayName, description, defaultMesh, requiredComponents);
|
||||||
|
creators_[type] = std::move(creator);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* CreateEntity(const QString& type, WorkSpace* workspace);
|
||||||
|
|
||||||
|
Entity* CreateEntityWithComponents(const QString& type, const QString& mesh, bool useLabel, WorkSpace* workspace);
|
||||||
|
|
||||||
|
QStringList GetRegisteredTypes() const;
|
||||||
|
|
||||||
|
QString GetDisplayName(const QString& type) const;
|
||||||
|
QString GetDescription(const QString& type) const;
|
||||||
|
QString GetDefaultMesh(const QString& type) const;
|
||||||
|
QStringList GetRequiredComponents(const QString& type) const;
|
||||||
|
|
||||||
|
bool IsTypeSupported(const QString& type) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::unordered_map<QString, std::unique_ptr<IEntityCreator>> creators_;
|
||||||
|
class Application* app_ = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define REGISTER_ENTITY(EntityClass, Type, DisplayName, Description, DefaultMesh, ...) \
|
||||||
|
EntityFactory::Get().RegisterEntity<EntityClass>(Type, DisplayName, Description, DefaultMesh, QStringList{__VA_ARGS__})
|
||||||
88
src/entities/EntityRegistration.cpp
Normal file
88
src/entities/EntityRegistration.cpp
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
#include "entities/EntityRegistration.h"
|
||||||
|
#include "common/SpdLogger.h"
|
||||||
|
|
||||||
|
void EntityRegistration::RegisterAllEntities() {
|
||||||
|
EntityFactory& factory = EntityFactory::Get();
|
||||||
|
|
||||||
|
// Register missile entity
|
||||||
|
factory.RegisterEntity<MissileEntity>("Missile",
|
||||||
|
"Missile",
|
||||||
|
"Military missile entity with target tracking and flight capabilities",
|
||||||
|
"models/missile.osg",
|
||||||
|
QStringList() << "LabelComponent" << "TrajectoryComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register satellite entity
|
||||||
|
factory.RegisterEntity<SatelliteEntity>("Satellite",
|
||||||
|
"Satellite",
|
||||||
|
"Artificial satellite entity with orbital motion and communication capabilities",
|
||||||
|
"models/satellite.osg",
|
||||||
|
QStringList() << "LabelComponent" << "ConeWaveComponent" << "OrbitComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register ship entity
|
||||||
|
factory.RegisterEntity<ShipEntity>("Ship",
|
||||||
|
"Ship",
|
||||||
|
"Naval vessel entity with maritime navigation and combat capabilities",
|
||||||
|
"models/ship.osg",
|
||||||
|
QStringList() << "LabelComponent" << "NavigationComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register radar entity
|
||||||
|
factory.RegisterEntity<RadarEntity>("Radar",
|
||||||
|
"Radar",
|
||||||
|
"Radar system entity with target detection and tracking capabilities",
|
||||||
|
"models/radar.osg",
|
||||||
|
QStringList() << "LabelComponent" << "RadarComponent" << "ScanComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register vehicle entity
|
||||||
|
factory.RegisterEntity<VehicleEntity>("Vehicle",
|
||||||
|
"Vehicle",
|
||||||
|
"Generic vehicle entity configurable for different types of transportation",
|
||||||
|
"models/vehicle.osg",
|
||||||
|
QStringList() << "LabelComponent" << "MovementComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register aircraft entity
|
||||||
|
factory.RegisterEntity<VehicleEntity>("Aircraft",
|
||||||
|
"Aircraft",
|
||||||
|
"Aviation entity with flight and aerial combat capabilities",
|
||||||
|
"models/aircraft.osg",
|
||||||
|
QStringList() << "LabelComponent" << "FlightComponent" << "NavigationComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register tank entity
|
||||||
|
factory.RegisterEntity<VehicleEntity>("Tank",
|
||||||
|
"Tank",
|
||||||
|
"Armored vehicle entity with ground combat capabilities",
|
||||||
|
"models/tank.osg",
|
||||||
|
QStringList() << "LabelComponent" << "ArmorComponent" << "WeaponComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register submarine entity
|
||||||
|
factory.RegisterEntity<ShipEntity>("Submarine",
|
||||||
|
"Submarine",
|
||||||
|
"Submarine entity with underwater combat capabilities",
|
||||||
|
"models/submarine.osg",
|
||||||
|
QStringList() << "LabelComponent" << "SonarComponent" << "TorpedoComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register base entity
|
||||||
|
factory.RegisterEntity<Entity>("Base",
|
||||||
|
"Base",
|
||||||
|
"Military base entity serving as command and logistics center",
|
||||||
|
"models/base.osg",
|
||||||
|
QStringList() << "LabelComponent" << "CommandComponent" << "DefenseComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
// Register generic entity (for backward compatibility)
|
||||||
|
factory.RegisterEntity<Entity>("Entity",
|
||||||
|
"Entity",
|
||||||
|
"Basic entity type extensible through component system",
|
||||||
|
"models/default.osg",
|
||||||
|
QStringList() << "LabelComponent"
|
||||||
|
);
|
||||||
|
|
||||||
|
LOG_INFO("EntityRegistration::RegisterAllEntities - All entity types registered successfully");
|
||||||
|
}
|
||||||
11
src/entities/EntityRegistration.h
Normal file
11
src/entities/EntityRegistration.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "entities/EntityFactory.h"
|
||||||
|
#include "entities/SpecializedEntities.h"
|
||||||
|
|
||||||
|
// Entity registration class
|
||||||
|
class EntityRegistration {
|
||||||
|
public:
|
||||||
|
// Register all entity types
|
||||||
|
static void RegisterAllEntities();
|
||||||
|
};
|
||||||
60
src/entities/SpecializedEntities.cpp
Normal file
60
src/entities/SpecializedEntities.cpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include "entities/SpecializedEntities.h"
|
||||||
|
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
#include "common/SpdLogger.h"
|
||||||
|
|
||||||
|
MissileEntity::MissileEntity(WorkSpace* workspace)
|
||||||
|
: Entity(workspace) {
|
||||||
|
SetName("Missile");
|
||||||
|
LOG_INFO("MissileEntity created");
|
||||||
|
}
|
||||||
|
|
||||||
|
MissileEntity::MissileEntity(const QString& name, QObject* parent)
|
||||||
|
: Entity(name, parent) {
|
||||||
|
LOG_INFO("MissileEntity created with name: {}", name.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
SatelliteEntity::SatelliteEntity(WorkSpace* workspace)
|
||||||
|
: Entity(workspace) {
|
||||||
|
SetName("Satellite");
|
||||||
|
LOG_INFO("SatelliteEntity created");
|
||||||
|
}
|
||||||
|
|
||||||
|
SatelliteEntity::SatelliteEntity(const QString& name, QObject* parent)
|
||||||
|
: Entity(name, parent) {
|
||||||
|
LOG_INFO("SatelliteEntity created with name: {}", name.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
ShipEntity::ShipEntity(WorkSpace* workspace)
|
||||||
|
: Entity(workspace) {
|
||||||
|
SetName("Ship");
|
||||||
|
LOG_INFO("ShipEntity created");
|
||||||
|
}
|
||||||
|
|
||||||
|
ShipEntity::ShipEntity(const QString& name, QObject* parent)
|
||||||
|
: Entity(name, parent) {
|
||||||
|
LOG_INFO("ShipEntity created with name: {}", name.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
RadarEntity::RadarEntity(WorkSpace* workspace)
|
||||||
|
: Entity(workspace) {
|
||||||
|
SetName("Radar");
|
||||||
|
LOG_INFO("RadarEntity created");
|
||||||
|
}
|
||||||
|
|
||||||
|
RadarEntity::RadarEntity(const QString& name, QObject* parent)
|
||||||
|
: Entity(name, parent) {
|
||||||
|
LOG_INFO("RadarEntity created with name: {}", name.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
VehicleEntity::VehicleEntity(WorkSpace* workspace)
|
||||||
|
: Entity(workspace) {
|
||||||
|
SetName("Vehicle");
|
||||||
|
LOG_INFO("VehicleEntity created");
|
||||||
|
}
|
||||||
|
|
||||||
|
VehicleEntity::VehicleEntity(const QString& name, QObject* parent)
|
||||||
|
: Entity(name, parent) {
|
||||||
|
LOG_INFO("VehicleEntity created with name: {}", name.toStdString());
|
||||||
|
}
|
||||||
58
src/entities/SpecializedEntities.h
Normal file
58
src/entities/SpecializedEntities.h
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "entities/Entity.h"
|
||||||
|
|
||||||
|
// 导弹实体
|
||||||
|
class MissileEntity : public Entity {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MissileEntity(WorkSpace* workspace);
|
||||||
|
explicit MissileEntity(const QString& name, QObject* parent = nullptr);
|
||||||
|
~MissileEntity() override = default;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// 卫星实体
|
||||||
|
class SatelliteEntity : public Entity {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit SatelliteEntity(WorkSpace* workspace);
|
||||||
|
explicit SatelliteEntity(const QString& name, QObject* parent = nullptr);
|
||||||
|
~SatelliteEntity() override = default;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// 舰船实体
|
||||||
|
class ShipEntity : public Entity {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit ShipEntity(WorkSpace* workspace);
|
||||||
|
explicit ShipEntity(const QString& name, QObject* parent = nullptr);
|
||||||
|
~ShipEntity() override = default;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// 雷达实体
|
||||||
|
class RadarEntity : public Entity {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit RadarEntity(WorkSpace* workspace);
|
||||||
|
explicit RadarEntity(const QString& name, QObject* parent = nullptr);
|
||||||
|
~RadarEntity() override = default;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// 通用载具实体
|
||||||
|
class VehicleEntity : public Entity {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit VehicleEntity(WorkSpace* workspace);
|
||||||
|
explicit VehicleEntity(const QString& name, QObject* parent = nullptr);
|
||||||
|
~VehicleEntity() override = default;
|
||||||
|
|
||||||
|
};
|
||||||
@ -103,6 +103,64 @@ osg::Viewport* OEScene::GetViewport() const {
|
|||||||
return curentView_->getCamera()->getViewport();
|
return curentView_->getCamera()->getViewport();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OEScene::ScreenToWorldCoordinate(int x, int y, osg::Vec3d* output) const {
|
||||||
|
if (nullptr == output) {
|
||||||
|
LOG_WARN("OEScene::ScreenToWorldCoordinate - worldPoint is null");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Camera* camera = curentView_->getCamera();
|
||||||
|
if (!camera) {
|
||||||
|
LOG_WARN("OEScene::ScreenToWorldCoordinate - camera is null");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<osgUtil::LineSegmentIntersector> intersector =
|
||||||
|
new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x, y);
|
||||||
|
|
||||||
|
osgUtil::IntersectionVisitor iv(intersector.get());
|
||||||
|
camera->accept(iv);
|
||||||
|
|
||||||
|
if (intersector->containsIntersections()) {
|
||||||
|
osgUtil::LineSegmentIntersector::Intersections& intersections = intersector->getIntersections();
|
||||||
|
osgUtil::LineSegmentIntersector::Intersection intersection = *intersections.begin();
|
||||||
|
|
||||||
|
osg::Vec3d worldPoint = intersection.getWorldIntersectPoint();
|
||||||
|
|
||||||
|
Vec3ToLocation(worldPoint, output);
|
||||||
|
|
||||||
|
LOG_INFO("OsgWidget::ScreenToWorldCoordinate - Screen({}, {}) -> World({:.6f}, {:.6f}, {:.2f})",
|
||||||
|
x, y, output->x(), output->y(), output->z());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_WARN("OsgWidget::ScreenToWorldCoordinate - No intersection found for screen coordinates ({}, {})", x, y);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OEScene::Vec3ToLocation(const osg::Vec3& input, osg::Vec3d* output) const {
|
||||||
|
if (nullptr == output) {
|
||||||
|
LOG_WARN("OEScene::vec3ToLocation - output is null");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const osgEarth::SpatialReference* srs = OEScene::GetSrs();
|
||||||
|
if (!srs) {
|
||||||
|
LOG_WARN("OEScene::vec3ToLocation - spatial reference system is null");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
osgEarth::GeoPoint geoPoint;
|
||||||
|
geoPoint.fromWorld(srs, input);
|
||||||
|
|
||||||
|
const osgEarth::SpatialReference* wgs84 = osgEarth::SpatialReference::get("wgs84");
|
||||||
|
if (wgs84) {
|
||||||
|
geoPoint = geoPoint.transform(wgs84);
|
||||||
|
}
|
||||||
|
|
||||||
|
output->set(geoPoint.x(), geoPoint.y(),geoPoint.z());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
const osgEarth::SpatialReference* OEScene::GetSrs() {
|
const osgEarth::SpatialReference* OEScene::GetSrs() {
|
||||||
dyt_check(nullptr != g_srs_);
|
dyt_check(nullptr != g_srs_);
|
||||||
return g_srs_;
|
return g_srs_;
|
||||||
|
|||||||
@ -35,6 +35,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
osg::Viewport* GetViewport() const;
|
osg::Viewport* GetViewport() const;
|
||||||
|
bool ScreenToWorldCoordinate(int x, int y, osg::Vec3d* output) const;
|
||||||
|
bool Vec3ToLocation(const osg::Vec3& input, osg::Vec3d* output) const;
|
||||||
|
|
||||||
static const osgEarth::SpatialReference* GetSrs();
|
static const osgEarth::SpatialReference* GetSrs();
|
||||||
|
|
||||||
|
|||||||
@ -2110,12 +2110,12 @@
|
|||||||
<context>
|
<context>
|
||||||
<name>OsgWidget</name>
|
<name>OsgWidget</name>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../viewer/OsgWidget.cpp" line="122"/>
|
<location filename="../viewer/OsgWidget.cpp" line="131"/>
|
||||||
<source>warning</source>
|
<source>warning</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
<message>
|
||||||
<location filename="../viewer/OsgWidget.cpp" line="123"/>
|
<location filename="../viewer/OsgWidget.cpp" line="132"/>
|
||||||
<source>open dyt file failed</source>
|
<source>open dyt file failed</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
@ -2216,31 +2216,6 @@
|
|||||||
<source>Preset Models</source>
|
<source>Preset Models</source>
|
||||||
<translation type="unfinished"></translation>
|
<translation type="unfinished"></translation>
|
||||||
</message>
|
</message>
|
||||||
<message>
|
|
||||||
<location filename="../ui/ModelBrowser/PresetModelPanel.ui" line="35"/>
|
|
||||||
<source>PresetModelToolBox</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/ModelBrowser/PresetModelPanel.ui" line="50"/>
|
|
||||||
<source>Ships</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/ModelBrowser/PresetModelPanel.ui" line="75"/>
|
|
||||||
<source>Satellites</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/ModelBrowser/PresetModelPanel.ui" line="100"/>
|
|
||||||
<source>Missiles</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
<message>
|
|
||||||
<location filename="../ui/ModelBrowser/PresetModelPanel.ui" line="125"/>
|
|
||||||
<source>Jammers</source>
|
|
||||||
<translation type="unfinished"></translation>
|
|
||||||
</message>
|
|
||||||
</context>
|
</context>
|
||||||
<context>
|
<context>
|
||||||
<name>PropertyBrowser</name>
|
<name>PropertyBrowser</name>
|
||||||
|
|||||||
@ -42,6 +42,7 @@ void FileManagerMenu::InitConnect() {
|
|||||||
connect(ui->menu_table_file, &QToolButton::clicked, this, &FileManagerMenu::AddTableFile);
|
connect(ui->menu_table_file, &QToolButton::clicked, this, &FileManagerMenu::AddTableFile);
|
||||||
connect(ui->menu_light_file, &QToolButton::clicked, this, &FileManagerMenu::AddLightFile);
|
connect(ui->menu_light_file, &QToolButton::clicked, this, &FileManagerMenu::AddLightFile);
|
||||||
connect(ui->menu_polar_file, &QToolButton::clicked, this, &FileManagerMenu::AddPolarFile);
|
connect(ui->menu_polar_file, &QToolButton::clicked, this, &FileManagerMenu::AddPolarFile);
|
||||||
|
connect(ui->menu_image_file, &QToolButton::clicked, this, &FileManagerMenu::AddImageFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileManagerMenu::NewWorkSpace() {
|
void FileManagerMenu::NewWorkSpace() {
|
||||||
@ -277,7 +278,8 @@ void FileManagerMenu::AddLightFile() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileManagerMenu::AddPolarFile() {
|
void FileManagerMenu::AddPolarFile()
|
||||||
|
{
|
||||||
auto current = WorkSpaceManager::Get().GetCurrent();
|
auto current = WorkSpaceManager::Get().GetCurrent();
|
||||||
if (nullptr == current) {
|
if (nullptr == current) {
|
||||||
QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), QObject::tr("please create workspace first"));
|
QMessageBox::information(&MainFrame::Get(), QObject::tr("prompt"), QObject::tr("please create workspace first"));
|
||||||
@ -291,3 +293,8 @@ void FileManagerMenu::AddPolarFile() {
|
|||||||
SaveWorkSpace();
|
SaveWorkSpace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FileManagerMenu::AddImageFile()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
@ -26,6 +26,7 @@ protected:
|
|||||||
void AddTableFile();
|
void AddTableFile();
|
||||||
void AddLightFile();
|
void AddLightFile();
|
||||||
void AddPolarFile();
|
void AddPolarFile();
|
||||||
|
void AddImageFile();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void LoadDyt(const QString& path);
|
void LoadDyt(const QString& path);
|
||||||
|
|||||||
@ -104,6 +104,16 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="menu_image_file">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>new image file</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer">
|
<spacer name="horizontalSpacer">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
|
|||||||
146
src/ui/ModelBrowser/PresetModelListWidget.cpp
Normal file
146
src/ui/ModelBrowser/PresetModelListWidget.cpp
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
#include "ui/ModelBrowser/PresetModelListWidget.h"
|
||||||
|
|
||||||
|
#include <QListWidgetItem>
|
||||||
|
#include <QDrag>
|
||||||
|
#include <QMimeData>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
|
#include "common/RecourceHelper.h"
|
||||||
|
#include "common/SpdLogger.h"
|
||||||
|
|
||||||
|
PresetModelListWidget::PresetModelListWidget(QWidget* parent)
|
||||||
|
: QListWidget(parent)
|
||||||
|
{
|
||||||
|
setDragEnabled(true);
|
||||||
|
setDragDropMode(QAbstractItemView::DragOnly);
|
||||||
|
|
||||||
|
// Configure list widget for icon-text vertical layout
|
||||||
|
setViewMode(QListView::IconMode);
|
||||||
|
setResizeMode(QListView::Adjust);
|
||||||
|
setMovement(QListView::Static);
|
||||||
|
setGridSize(QSize(100, 80)); // Width x Height for each item
|
||||||
|
setIconSize(QSize(48, 48)); // Icon size
|
||||||
|
setSpacing(5); // Spacing between items
|
||||||
|
}
|
||||||
|
|
||||||
|
void PresetModelListWidget::startDrag(Qt::DropActions supportedActions) {
|
||||||
|
QListWidgetItem* item = currentItem();
|
||||||
|
if (nullptr == item) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString modelType = property("modelType").toString();
|
||||||
|
QString modelName = item->data(Qt::UserRole).toString();
|
||||||
|
if (modelName.isEmpty()) {
|
||||||
|
modelName = item->text(); // Fallback to item text
|
||||||
|
}
|
||||||
|
|
||||||
|
QMimeData* mimeData = new QMimeData;
|
||||||
|
|
||||||
|
QString dragData = QString("%1|%2").arg(modelType, modelName);
|
||||||
|
mimeData->setData("application/x-preset-model", dragData.toUtf8());
|
||||||
|
|
||||||
|
// Create drag object
|
||||||
|
QDrag* drag = new QDrag(this);
|
||||||
|
drag->setMimeData(mimeData);
|
||||||
|
|
||||||
|
// Create drag pixmap with icon on top and text below
|
||||||
|
const int iconSize = 32;
|
||||||
|
const int textHeight = 20;
|
||||||
|
const int totalWidth = 80;
|
||||||
|
const int totalHeight = iconSize + textHeight + 5; // 5px spacing between icon and text
|
||||||
|
|
||||||
|
QPixmap pixmap(totalWidth, totalHeight);
|
||||||
|
pixmap.fill(Qt::transparent);
|
||||||
|
|
||||||
|
QPainter painter(&pixmap);
|
||||||
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
|
|
||||||
|
// Draw semi-transparent background
|
||||||
|
painter.setBrush(QColor(255, 255, 255, 50)); // White with 70% opacity
|
||||||
|
painter.setPen(QPen(QColor(200, 200, 200, 200), 1)); // Light gray border
|
||||||
|
painter.drawRoundedRect(2, 2, totalWidth - 4, totalHeight - 4, 4, 4);
|
||||||
|
|
||||||
|
// Draw icon at the top center
|
||||||
|
QPixmap iconPixmap = item->icon().pixmap(iconSize, iconSize);
|
||||||
|
if (!iconPixmap.isNull()) {
|
||||||
|
int iconX = (totalWidth - iconSize) / 2;
|
||||||
|
painter.drawPixmap(iconX, 0, iconPixmap);
|
||||||
|
} else {
|
||||||
|
// Draw a default placeholder icon
|
||||||
|
int iconX = (totalWidth - iconSize) / 2;
|
||||||
|
painter.setPen(QPen(Qt::gray, 2));
|
||||||
|
painter.setBrush(Qt::lightGray);
|
||||||
|
painter.drawRect(iconX, 0, iconSize, iconSize);
|
||||||
|
painter.setPen(Qt::black);
|
||||||
|
painter.drawText(iconX, 0, iconSize, iconSize, Qt::AlignCenter, "?");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw text below the icon
|
||||||
|
painter.setPen(Qt::black);
|
||||||
|
QFont font = painter.font();
|
||||||
|
font.setPointSize(8);
|
||||||
|
painter.setFont(font);
|
||||||
|
|
||||||
|
QRect textRect(0, iconSize + 5, totalWidth, textHeight);
|
||||||
|
painter.drawText(textRect, Qt::AlignCenter | Qt::TextWordWrap, item->text());
|
||||||
|
drag->setPixmap(pixmap);
|
||||||
|
|
||||||
|
// Set hot spot to the center of the icon (not the entire pixmap)
|
||||||
|
int hotSpotX = totalWidth / 2;
|
||||||
|
int hotSpotY = iconSize / 2; // Center of the icon part only
|
||||||
|
drag->setHotSpot(QPoint(hotSpotX, hotSpotY));
|
||||||
|
|
||||||
|
// Execute drag
|
||||||
|
drag->exec(Qt::CopyAction);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PresetModelListWidget::setModelType(const QString& modelType) {
|
||||||
|
modelType_ = modelType;
|
||||||
|
setProperty("modelType", modelType_);
|
||||||
|
}
|
||||||
|
|
||||||
|
QString PresetModelListWidget::getModelType() const {
|
||||||
|
return modelType_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PresetModelListWidget::setModelList(const QVector<ModelInfo>& models) {
|
||||||
|
modelList_ = models;
|
||||||
|
|
||||||
|
clear();
|
||||||
|
|
||||||
|
for (const ModelInfo& modelInfo : models) {
|
||||||
|
if (!modelInfo.enabled) continue; // Skip disabled models
|
||||||
|
|
||||||
|
QListWidgetItem* item = new QListWidgetItem(modelInfo.displayName.isEmpty() ? modelInfo.name : modelInfo.displayName);
|
||||||
|
item->setFlags(item->flags() | Qt::ItemIsDragEnabled);
|
||||||
|
|
||||||
|
// Use icon from ModelInfo if available
|
||||||
|
if (!modelInfo.icon.isEmpty()) {
|
||||||
|
QString presetsPath = QString("%1/%2").arg(RecourceHelper::Get().GetResourcesPath(), modelInfo.icon);
|
||||||
|
QIcon icon(presetsPath);
|
||||||
|
item->setIcon(icon);
|
||||||
|
} else {
|
||||||
|
// Create a default icon if no icon is specified
|
||||||
|
QPixmap pixmap(48, 48);
|
||||||
|
pixmap.fill(Qt::lightGray);
|
||||||
|
QPainter painter(&pixmap);
|
||||||
|
painter.setPen(Qt::black);
|
||||||
|
painter.drawRect(0, 0, 47, 47);
|
||||||
|
painter.drawText(pixmap.rect(), Qt::AlignCenter, "?");
|
||||||
|
item->setIcon(QIcon(pixmap));
|
||||||
|
}
|
||||||
|
|
||||||
|
item->setToolTip(modelInfo.description.isEmpty() ? modelInfo.name : modelInfo.description);
|
||||||
|
|
||||||
|
// Store model name as simple string
|
||||||
|
item->setData(Qt::UserRole, modelInfo.name);
|
||||||
|
|
||||||
|
addItem(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<ModelInfo> PresetModelListWidget::getModelList() const {
|
||||||
|
return modelList_;
|
||||||
|
}
|
||||||
26
src/ui/ModelBrowser/PresetModelListWidget.h
Normal file
26
src/ui/ModelBrowser/PresetModelListWidget.h
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QListWidget>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
#include "workspace/ModelInfo.h"
|
||||||
|
|
||||||
|
class PresetModelListWidget : public QListWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit PresetModelListWidget(QWidget* parent = nullptr);
|
||||||
|
|
||||||
|
void setModelType(const QString& modelType);
|
||||||
|
QString getModelType() const;
|
||||||
|
|
||||||
|
void setModelList(const QVector<ModelInfo>& models);
|
||||||
|
QVector<ModelInfo> getModelList() const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void startDrag(Qt::DropActions supportedActions);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString modelType_;
|
||||||
|
QVector<ModelInfo> modelList_;
|
||||||
|
};
|
||||||
@ -8,14 +8,19 @@
|
|||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
|
#include <QMetaType>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
#include <QFontMetrics>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include "common/RecourceHelper.h"
|
||||||
#include "common/SpdLogger.h"
|
#include "common/SpdLogger.h"
|
||||||
#include "ui/DockTitleBar.h"
|
#include "ui/DockTitleBar.h"
|
||||||
#include "ui/DockWidget.h"
|
#include "ui/DockWidget.h"
|
||||||
|
#include "workspace/PresetModelConfigParser.h"
|
||||||
|
|
||||||
#include "ui_PresetModelPanel.h"
|
#include "ui_PresetModelPanel.h"
|
||||||
|
|
||||||
@ -23,6 +28,7 @@
|
|||||||
PresetModelPanel::PresetModelPanel(QWidget *parent)
|
PresetModelPanel::PresetModelPanel(QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
, ui(new Ui::PresetModelPanel)
|
, ui(new Ui::PresetModelPanel)
|
||||||
|
, dragSourceWidget_(nullptr)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
ui->setupUi(this);
|
||||||
InitUI();
|
InitUI();
|
||||||
@ -30,6 +36,7 @@ PresetModelPanel::PresetModelPanel(QWidget *parent)
|
|||||||
|
|
||||||
PresetModelPanel::~PresetModelPanel()
|
PresetModelPanel::~PresetModelPanel()
|
||||||
{
|
{
|
||||||
|
ClearDynamicUI();
|
||||||
delete ui;
|
delete ui;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -50,175 +57,100 @@ void PresetModelPanel::AttachDock(DockWidget* dockWidget)
|
|||||||
void PresetModelPanel::InitUI()
|
void PresetModelPanel::InitUI()
|
||||||
{
|
{
|
||||||
// Try to load model data from configuration files
|
// Try to load model data from configuration files
|
||||||
if (m_configParser.LoadAllConfigs("workspace/presets")) {
|
QString presetsPath = QString("%1/presets").arg(RecourceHelper::Get().GetResourcesPath());
|
||||||
|
if (PresetModelConfigParser::Get().LoadAllConfigs(presetsPath)) {
|
||||||
// Successfully loaded from configuration files
|
// Successfully loaded from configuration files
|
||||||
|
CreateDynamicUI();
|
||||||
LoadModelsFromConfig();
|
LoadModelsFromConfig();
|
||||||
} else {
|
} else {
|
||||||
// Failed to load configuration files, use hardcoded defaults as fallback
|
// Failed to load configuration files, use hardcoded defaults as fallback
|
||||||
LOG_WARN("Failed to load preset models from config files, using hardcoded defaults. Error: {}",
|
LOG_WARN("Failed to load preset models from config files, using hardcoded defaults. Error: {}",
|
||||||
m_configParser.GetLastError().toStdString());
|
PresetModelConfigParser::Get().GetLastError().toStdString());
|
||||||
LoadDefaultModels();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PresetModelPanel::LoadModelsFromConfig()
|
void PresetModelPanel::CreateDynamicUI()
|
||||||
{
|
{
|
||||||
// Load ship models
|
// Clear any existing dynamic UI
|
||||||
QStringList shipModels = m_configParser.GetModelNames("Ship");
|
ClearDynamicUI();
|
||||||
if (!shipModels.isEmpty()) {
|
|
||||||
PopulateModelList(ui->shipList, "Ship", shipModels);
|
// Get all category names from configuration
|
||||||
|
QStringList categoryNames = PresetModelConfigParser::Get().GetCategoryNames();
|
||||||
|
|
||||||
|
if (categoryNames.isEmpty()) {
|
||||||
|
LOG_WARN("No categories found in configuration");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load satellite models
|
// Create UI for each category
|
||||||
QStringList satelliteModels = m_configParser.GetModelNames("Satellite");
|
for (const QString& categoryName : categoryNames) {
|
||||||
if (!satelliteModels.isEmpty()) {
|
ModelCategory category = PresetModelConfigParser::Get().GetCategory(categoryName);
|
||||||
PopulateModelList(ui->satelliteList, "Satellite", satelliteModels);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load missile models
|
// Create page widget
|
||||||
QStringList missileModels = m_configParser.GetModelNames("Missile");
|
QWidget* page = new QWidget();
|
||||||
if (!missileModels.isEmpty()) {
|
page->setObjectName(QString("%1Page").arg(categoryName.toLower()));
|
||||||
PopulateModelList(ui->missileList, "Missile", missileModels);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load jammer models
|
// Create layout for the page
|
||||||
QStringList jammerModels = m_configParser.GetModelNames("Jammer");
|
QVBoxLayout* layout = new QVBoxLayout(page);
|
||||||
if (!jammerModels.isEmpty()) {
|
layout->setSpacing(0);
|
||||||
PopulateModelList(ui->jammerList, "Jammer", jammerModels);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void PresetModelPanel::LoadDefaultModels()
|
// Create list widget
|
||||||
{
|
PresetModelListWidget* listWidget = new PresetModelListWidget(page);
|
||||||
// Use hardcoded default models as fallback mechanism
|
listWidget->setObjectName(QString("%1List").arg(categoryName.toLower()));
|
||||||
QStringList shipModels = {
|
|
||||||
"Destroyer",
|
|
||||||
"Aircraft Carrier",
|
|
||||||
"Frigate",
|
|
||||||
"Submarine"
|
|
||||||
};
|
|
||||||
PopulateModelList(ui->shipList, "Ship", shipModels);
|
|
||||||
|
|
||||||
QStringList satelliteModels = {
|
|
||||||
"Communication Satellite",
|
|
||||||
"Weather Satellite",
|
|
||||||
"GPS Satellite",
|
|
||||||
"Spy Satellite"
|
|
||||||
};
|
|
||||||
PopulateModelList(ui->satelliteList, "Satellite", satelliteModels);
|
|
||||||
|
|
||||||
QStringList missileModels = {
|
|
||||||
"Cruise Missile",
|
|
||||||
"Ballistic Missile",
|
|
||||||
"Anti-Ship Missile",
|
|
||||||
"Surface-to-Air Missile"
|
|
||||||
};
|
|
||||||
PopulateModelList(ui->missileList, "Missile", missileModels);
|
|
||||||
|
|
||||||
QStringList jammerModels = {
|
|
||||||
"Electronic Jammer",
|
|
||||||
"Communication Jammer",
|
|
||||||
"Radar Jammer",
|
|
||||||
"GPS Jammer"
|
|
||||||
};
|
|
||||||
PopulateModelList(ui->jammerList, "Jammer", jammerModels);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PresetModelPanel::PopulateModelList(QListWidget* listWidget, const QString& modelType, const QStringList& models)
|
|
||||||
{
|
|
||||||
if (!listWidget) return;
|
|
||||||
|
|
||||||
// Set the model type as a property for later use
|
|
||||||
listWidget->setProperty("modelType", modelType);
|
|
||||||
|
|
||||||
for (const QString& model : models) {
|
|
||||||
QListWidgetItem* item = new QListWidgetItem(model);
|
|
||||||
item->setFlags(item->flags() | Qt::ItemIsDragEnabled);
|
|
||||||
|
|
||||||
if (modelType == "Ship") {
|
|
||||||
item->setIcon(QIcon(":/icons/ship.png"));
|
|
||||||
} else if (modelType == "Satellite") {
|
|
||||||
item->setIcon(QIcon(":/icons/satellite.png"));
|
|
||||||
} else if (modelType == "Missile") {
|
|
||||||
item->setIcon(QIcon(":/icons/missile.png"));
|
|
||||||
} else if (modelType == "Jammer") {
|
|
||||||
item->setIcon(QIcon(":/icons/jammer.png"));
|
|
||||||
}
|
|
||||||
|
|
||||||
listWidget->addItem(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
connect(listWidget, &QListWidget::itemDoubleClicked, this, &PresetModelPanel::OnModelItemDoubleClicked);
|
|
||||||
}
|
|
||||||
|
|
||||||
void PresetModelPanel::SetupDragAndDrop(QListWidget* listWidget)
|
|
||||||
{
|
|
||||||
listWidget->setDragDropMode(QAbstractItemView::DragOnly);
|
listWidget->setDragDropMode(QAbstractItemView::DragOnly);
|
||||||
listWidget->setDefaultDropAction(Qt::CopyAction);
|
listWidget->setDefaultDropAction(Qt::CopyAction);
|
||||||
|
|
||||||
|
// Add list widget to layout
|
||||||
|
layout->addWidget(listWidget);
|
||||||
|
|
||||||
|
// Add page to toolbox with display name
|
||||||
|
QString displayName = category.displayName.isEmpty() ? categoryName : category.displayName;
|
||||||
|
ui->PresetModelToolBox->addItem(page, displayName);
|
||||||
|
|
||||||
|
// Store references for later use
|
||||||
|
categoryWidgets_[categoryName] = listWidget;
|
||||||
|
categoryPages_[categoryName] = page;
|
||||||
|
|
||||||
|
LOG_INFO("Created dynamic UI for category: {}", categoryName.toStdString());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set first page as current if available
|
||||||
|
if (ui->PresetModelToolBox->count() > 0) {
|
||||||
|
ui->PresetModelToolBox->setCurrentIndex(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PresetModelPanel::OnModelItemDoubleClicked(QListWidgetItem* item)
|
void PresetModelPanel::LoadModelsFromConfig() {
|
||||||
|
// Load models for each dynamically created category
|
||||||
|
QStringList categoryNames = PresetModelConfigParser::Get().GetCategoryNames();
|
||||||
|
|
||||||
|
for (const QString& categoryName : categoryNames) {
|
||||||
|
ModelCategory category = PresetModelConfigParser::Get().GetCategory(categoryName);
|
||||||
|
|
||||||
|
if (!category.models.isEmpty() && categoryWidgets_.contains(categoryName)) {
|
||||||
|
PresetModelListWidget* listWidget = categoryWidgets_[categoryName];
|
||||||
|
listWidget->setModelType(categoryName);
|
||||||
|
listWidget->setModelList(category.models);
|
||||||
|
|
||||||
|
LOG_INFO("Loaded {} models for category: {}",
|
||||||
|
category.models.size(), categoryName.toStdString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PresetModelPanel::ClearDynamicUI()
|
||||||
{
|
{
|
||||||
if (!item) return;
|
// Clear all dynamic UI elements
|
||||||
|
categoryWidgets_.clear();
|
||||||
|
categoryPages_.clear();
|
||||||
|
|
||||||
QListWidget* listWidget = item->listWidget();
|
// Remove all pages from toolbox
|
||||||
if (!listWidget) return;
|
while (ui->PresetModelToolBox->count() > 0) {
|
||||||
|
QWidget* widget = ui->PresetModelToolBox->widget(0);
|
||||||
QString modelType = listWidget->property("modelType").toString();
|
ui->PresetModelToolBox->removeItem(0);
|
||||||
QString modelName = item->text();
|
if (widget) {
|
||||||
|
widget->deleteLater();
|
||||||
emit ModelDropped(modelType, modelName);
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// DraggableListWidget implementation
|
|
||||||
DraggableListWidget::DraggableListWidget(const QString& modelType, QWidget* parent)
|
|
||||||
: QListWidget(parent), modelType_(modelType)
|
|
||||||
{
|
|
||||||
setProperty("modelType", modelType);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DraggableListWidget::mousePressEvent(QMouseEvent* event)
|
|
||||||
{
|
|
||||||
if (event->button() == Qt::LeftButton) {
|
|
||||||
dragStartPosition_ = event->pos();
|
|
||||||
}
|
|
||||||
QListWidget::mousePressEvent(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DraggableListWidget::mouseMoveEvent(QMouseEvent* event) {
|
|
||||||
if (!(event->buttons() & Qt::LeftButton)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((event->pos() - dragStartPosition_).manhattanLength() < QApplication::startDragDistance()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QListWidgetItem* item = itemAt(dragStartPosition_);
|
|
||||||
if (!item) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QDrag* drag = new QDrag(this);
|
|
||||||
QMimeData* mimeData = new QMimeData;
|
|
||||||
|
|
||||||
QString modelType = this->property("modelType").toString();
|
|
||||||
QString modelName = item->text();
|
|
||||||
QString dragData = QString("%1|%2").arg(modelType, modelName);
|
|
||||||
|
|
||||||
mimeData->setData("application/x-preset-model", dragData.toUtf8());
|
|
||||||
drag->setMimeData(mimeData);
|
|
||||||
|
|
||||||
QPixmap pixmap(item->icon().pixmap(32, 32));
|
|
||||||
if (pixmap.isNull()) {
|
|
||||||
pixmap = QPixmap(100, 30);
|
|
||||||
pixmap.fill(Qt::transparent);
|
|
||||||
QPainter painter(&pixmap);
|
|
||||||
painter.setPen(Qt::black);
|
|
||||||
painter.drawText(pixmap.rect(), Qt::AlignCenter, modelName);
|
|
||||||
}
|
|
||||||
drag->setPixmap(pixmap);
|
|
||||||
|
|
||||||
Qt::DropAction dropAction = drag->exec(Qt::CopyAction);
|
|
||||||
Q_UNUSED(dropAction);
|
|
||||||
}
|
}
|
||||||
@ -10,22 +10,25 @@
|
|||||||
#include <QMimeData>
|
#include <QMimeData>
|
||||||
#include <QDrag>
|
#include <QDrag>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include "PresetModelConfigParser.h"
|
#include <QEvent>
|
||||||
|
#include <QStyledItemDelegate>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
#include "workspace/ModelInfo.h"
|
||||||
|
#include "ui/ModelBrowser/PresetModelListWidget.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
|
||||||
namespace Ui { class PresetModelPanel; }
|
namespace Ui { class PresetModelPanel; }
|
||||||
QT_END_NAMESPACE
|
|
||||||
|
|
||||||
class DockWidget;
|
class DockWidget;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Preset model panel class
|
* @brief Preset model panel class
|
||||||
*
|
*
|
||||||
* Provides preset 3D models for users to drag into the 3D scene, including:
|
* Provides preset 3D models for users to drag into the 3D scene.
|
||||||
* - Ships: Destroyer, Aircraft Carrier
|
* Dynamically creates UI based on configuration files, supporting any number of categories.
|
||||||
* - Satellites: Geostationary Satellites
|
|
||||||
* - Missiles: Hypersonic Missiles
|
|
||||||
* - Jammers: Passive Jammers, Active Jammers
|
|
||||||
*/
|
*/
|
||||||
class PresetModelPanel : public QWidget {
|
class PresetModelPanel : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@ -40,22 +43,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
void AttachDock(DockWidget* dockWidget);
|
void AttachDock(DockWidget* dockWidget);
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
/**
|
|
||||||
* @brief Signal emitted when model is dragged to scene
|
|
||||||
* @param modelType Model type
|
|
||||||
* @param modelName Model name
|
|
||||||
* @param position Scene position (optional)
|
|
||||||
*/
|
|
||||||
void ModelDropped(const QString& modelType, const QString& modelName, const QPointF& position = QPointF());
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
/**
|
|
||||||
* @brief Handle model item double click event
|
|
||||||
* @param item Clicked item
|
|
||||||
*/
|
|
||||||
void OnModelItemDoubleClicked(QListWidgetItem* item);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* @brief Initialize user interface
|
* @brief Initialize user interface
|
||||||
@ -63,18 +50,9 @@ private:
|
|||||||
void InitUI();
|
void InitUI();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Populate model list with items
|
* @brief Create dynamic UI based on configuration
|
||||||
* @param listWidget List widget to populate
|
|
||||||
* @param modelType Model type
|
|
||||||
* @param models Model name list
|
|
||||||
*/
|
*/
|
||||||
void PopulateModelList(QListWidget* listWidget, const QString& modelType, const QStringList& models);
|
void CreateDynamicUI();
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Setup drag and drop functionality
|
|
||||||
* @param listWidget List widget to setup drag and drop
|
|
||||||
*/
|
|
||||||
void SetupDragAndDrop(QListWidget* listWidget);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Load models from configuration file
|
* @brief Load models from configuration file
|
||||||
@ -82,32 +60,18 @@ private:
|
|||||||
void LoadModelsFromConfig();
|
void LoadModelsFromConfig();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Load default models when config is unavailable
|
* @brief Clear all dynamic UI elements
|
||||||
*/
|
*/
|
||||||
void LoadDefaultModels();
|
void ClearDynamicUI();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::PresetModelPanel *ui;
|
Ui::PresetModelPanel *ui;
|
||||||
PresetModelConfigParser m_configParser;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
// Dynamic UI management
|
||||||
* @brief Custom list widget with drag and drop support
|
QMap<QString, PresetModelListWidget*> categoryWidgets_;
|
||||||
*/
|
QMap<QString, QWidget*> categoryPages_;
|
||||||
class DraggableListWidget : public QListWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
// Drag and drop support
|
||||||
explicit DraggableListWidget(const QString& modelType, QWidget* parent = nullptr);
|
|
||||||
|
|
||||||
Q_SIGNALS:
|
|
||||||
void ItemDragged(const QString& modelType, const QString& modelName);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void mousePressEvent(QMouseEvent* event) override;
|
|
||||||
void mouseMoveEvent(QMouseEvent* event) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
QString modelType_;
|
|
||||||
QPoint dragStartPosition_;
|
QPoint dragStartPosition_;
|
||||||
|
QListWidget* dragSourceWidget_;
|
||||||
};
|
};
|
||||||
@ -14,129 +14,26 @@
|
|||||||
<string>Preset Models</string>
|
<string>Preset Models</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="mainLayout">
|
<layout class="QVBoxLayout" name="mainLayout">
|
||||||
<property name="leftMargin">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<property name="topMargin">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<property name="rightMargin">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<property name="bottomMargin">
|
|
||||||
<number>5</number>
|
|
||||||
</property>
|
|
||||||
<property name="spacing">
|
<property name="spacing">
|
||||||
<number>5</number>
|
<number>5</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<property name="leftMargin">
|
||||||
<widget class="QToolBox" name="toolBox">
|
|
||||||
<property name="objectName">
|
|
||||||
<string>PresetModelToolBox</string>
|
|
||||||
</property>
|
|
||||||
<property name="currentIndex">
|
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="shipPage">
|
<property name="topMargin">
|
||||||
<property name="geometry">
|
<number>0</number>
|
||||||
<rect>
|
</property>
|
||||||
<x>0</x>
|
<property name="rightMargin">
|
||||||
<y>0</y>
|
<number>0</number>
|
||||||
<width>290</width>
|
</property>
|
||||||
<height>540</height>
|
<property name="bottomMargin">
|
||||||
</rect>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<attribute name="label">
|
|
||||||
<string>Ships</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="shipLayout">
|
|
||||||
<item>
|
<item>
|
||||||
<widget class="QListWidget" name="shipList">
|
<widget class="QToolBox" name="PresetModelToolBox">
|
||||||
<property name="dragDropMode">
|
<property name="currentIndex">
|
||||||
<enum>QAbstractItemView::DragOnly</enum>
|
<number>-1</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="defaultDropAction">
|
|
||||||
<enum>Qt::CopyAction</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="satellitePage">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>290</width>
|
|
||||||
<height>540</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<attribute name="label">
|
|
||||||
<string>Satellites</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="satelliteLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QListWidget" name="satelliteList">
|
|
||||||
<property name="dragDropMode">
|
|
||||||
<enum>QAbstractItemView::DragOnly</enum>
|
|
||||||
</property>
|
|
||||||
<property name="defaultDropAction">
|
|
||||||
<enum>Qt::CopyAction</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="missilePage">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>290</width>
|
|
||||||
<height>540</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<attribute name="label">
|
|
||||||
<string>Missiles</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="missileLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QListWidget" name="missileList">
|
|
||||||
<property name="dragDropMode">
|
|
||||||
<enum>QAbstractItemView::DragOnly</enum>
|
|
||||||
</property>
|
|
||||||
<property name="defaultDropAction">
|
|
||||||
<enum>Qt::CopyAction</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<widget class="QWidget" name="jammerPage">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>290</width>
|
|
||||||
<height>540</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<attribute name="label">
|
|
||||||
<string>Jammers</string>
|
|
||||||
</attribute>
|
|
||||||
<layout class="QVBoxLayout" name="jammerLayout">
|
|
||||||
<item>
|
|
||||||
<widget class="QListWidget" name="jammerList">
|
|
||||||
<property name="dragDropMode">
|
|
||||||
<enum>QAbstractItemView::DragOnly</enum>
|
|
||||||
</property>
|
|
||||||
<property name="defaultDropAction">
|
|
||||||
<enum>Qt::CopyAction</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
|
|||||||
@ -434,6 +434,12 @@ void CurvePanel::updateParseWaveFile(const QString& strFile, int nT, FileEntryCu
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
curveChart->removeAllSeries();
|
||||||
|
m_seriesIDMap.clear();
|
||||||
|
|
||||||
|
m_dataWava.clear();
|
||||||
|
m_dataReport.clear();
|
||||||
|
|
||||||
QFile file(strFile);
|
QFile file(strFile);
|
||||||
if (file.open(QIODevice::ReadOnly))
|
if (file.open(QIODevice::ReadOnly))
|
||||||
{
|
{
|
||||||
@ -546,6 +552,12 @@ void CurvePanel::updateParseReportFile(const QString & strFile, int nT, FileEntr
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
curveChart->removeAllSeries();
|
||||||
|
m_seriesIDMap.clear();
|
||||||
|
|
||||||
|
m_dataWava.clear();
|
||||||
|
m_dataReport.clear();
|
||||||
|
|
||||||
QFile file(strFile);
|
QFile file(strFile);
|
||||||
if (file.open(QIODevice::ReadOnly))
|
if (file.open(QIODevice::ReadOnly))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -45,7 +45,9 @@ void LightPanel::RefreshPanel()
|
|||||||
|
|
||||||
void LightPanel::InitUI()
|
void LightPanel::InitUI()
|
||||||
{
|
{
|
||||||
|
QGridLayout* pMainLyt = new QGridLayout(this);
|
||||||
|
pMainLyt->setContentsMargins(5, 0, 5, 0);
|
||||||
|
setLayout(pMainLyt);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LightPanel::GetTypeDisplayName() const
|
QString LightPanel::GetTypeDisplayName() const
|
||||||
@ -111,10 +113,19 @@ void LightPanel::updateParseFile(const QString & strFile, int nT, FileEntryLight
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_dataLamp.clear();
|
||||||
|
|
||||||
|
clearLightPanel();
|
||||||
|
|
||||||
|
QGridLayout* layout = qobject_cast<QGridLayout*>(this->layout());
|
||||||
|
if (!layout)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
QFile file(strFile);
|
QFile file(strFile);
|
||||||
if (file.open(QIODevice::ReadOnly))
|
if (file.open(QIODevice::ReadOnly))
|
||||||
{
|
{
|
||||||
QGridLayout* pMainLyt = new QGridLayout(this);
|
|
||||||
for (int nI = 0; nI < listCurve.size(); nI++)
|
for (int nI = 0; nI < listCurve.size(); nI++)
|
||||||
{
|
{
|
||||||
FileEntryLight::LightRowProperty prop = listCurve.at(nI);
|
FileEntryLight::LightRowProperty prop = listCurve.at(nI);
|
||||||
@ -134,14 +145,12 @@ void LightPanel::updateParseFile(const QString & strFile, int nT, FileEntryLight
|
|||||||
pLyt->addWidget(pLampLab);
|
pLyt->addWidget(pLampLab);
|
||||||
pLyt->addWidget(pTextLab);
|
pLyt->addWidget(pTextLab);
|
||||||
|
|
||||||
pMainLyt->addLayout(pLyt, nI, i);
|
layout->addLayout(pLyt, nI, i);
|
||||||
|
|
||||||
QString strKey = QString::number(nI) + "-" + QString::number(i);
|
QString strKey = QString::number(nI) + "-" + QString::number(i);
|
||||||
m_mapLamp.insert(strKey, pLampLab);
|
m_mapLamp.insert(strKey, pLampLab);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
pMainLyt->setContentsMargins(5, 0, 5, 0);
|
|
||||||
setLayout(pMainLyt);
|
|
||||||
|
|
||||||
while (!file.atEnd())
|
while (!file.atEnd())
|
||||||
{
|
{
|
||||||
@ -174,6 +183,8 @@ void LightPanel::updateParseFile(const QString & strFile, int nT, FileEntryLight
|
|||||||
|
|
||||||
void LightPanel::updateLampColor(const QString & strOpenColor, const QString & strCloseColor)
|
void LightPanel::updateLampColor(const QString & strOpenColor, const QString & strCloseColor)
|
||||||
{
|
{
|
||||||
|
m_lampColor.clear();
|
||||||
|
|
||||||
{
|
{
|
||||||
QString strStyle = "QLabel{background-color: rgb(" + strCloseColor + ");border-radius: 10px;}; ";
|
QString strStyle = "QLabel{background-color: rgb(" + strCloseColor + ");border-radius: 10px;}; ";
|
||||||
m_lampColor.insert(0, strStyle);
|
m_lampColor.insert(0, strStyle);
|
||||||
@ -183,3 +194,32 @@ void LightPanel::updateLampColor(const QString & strOpenColor, const QString & s
|
|||||||
m_lampColor.insert(1, strStyle);
|
m_lampColor.insert(1, strStyle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void LightPanel::clearLightPanel()
|
||||||
|
{
|
||||||
|
if (auto* layout = qobject_cast<QGridLayout*>(this->layout()))
|
||||||
|
{
|
||||||
|
while (layout->count() > 0)
|
||||||
|
{
|
||||||
|
QLayoutItem* item = layout->takeAt(0);
|
||||||
|
if (item)
|
||||||
|
{
|
||||||
|
auto* childLayout = item->layout();
|
||||||
|
while (childLayout->count() > 0)
|
||||||
|
{
|
||||||
|
QLayoutItem* itemChild = childLayout->takeAt(0);
|
||||||
|
if (itemChild)
|
||||||
|
{
|
||||||
|
if (auto* w = itemChild->widget())
|
||||||
|
{
|
||||||
|
w->deleteLater();
|
||||||
|
}
|
||||||
|
delete itemChild;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_mapLamp.clear();
|
||||||
|
}
|
||||||
@ -64,6 +64,8 @@ private:
|
|||||||
void updateParseFile(const QString& strFile, int nT, FileEntryLight::LightRowProperties listCurve);
|
void updateParseFile(const QString& strFile, int nT, FileEntryLight::LightRowProperties listCurve);
|
||||||
void updateLampColor(const QString& strOpenColor, const QString& strCloseColor);
|
void updateLampColor(const QString& strOpenColor, const QString& strCloseColor);
|
||||||
|
|
||||||
|
void clearLightPanel();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMap<int, QString> m_lampColor;
|
QMap<int, QString> m_lampColor;
|
||||||
QMap<QString, SignalLabel*> m_mapLamp;
|
QMap<QString, SignalLabel*> m_mapLamp;
|
||||||
|
|||||||
@ -234,6 +234,9 @@ void SurfacePanel::updateParseFile(const QString & strFile, int nT, FileEntrySur
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_data.clear();
|
||||||
|
m_pSeries->dataProxy()->resetArray(nullptr);
|
||||||
|
|
||||||
QFile file(strFile);
|
QFile file(strFile);
|
||||||
if (file.open(QIODevice::ReadOnly))
|
if (file.open(QIODevice::ReadOnly))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -122,6 +122,10 @@ void TablePanel::updateParseFile(const QString & strFile, int nT, FileEntryTable
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_tableSetting.clear();
|
||||||
|
m_dataTable.clear();
|
||||||
|
clearTable();
|
||||||
|
|
||||||
QFile file(strFile);
|
QFile file(strFile);
|
||||||
if (file.open(QIODevice::ReadOnly))
|
if (file.open(QIODevice::ReadOnly))
|
||||||
{
|
{
|
||||||
|
|||||||
@ -54,8 +54,8 @@ void AddCurveFileDlg::setupConnections() {
|
|||||||
connect(ui->curveNameEdit, &QLineEdit::textChanged, this, &AddCurveFileDlg::onCurveNameChanged);
|
connect(ui->curveNameEdit, &QLineEdit::textChanged, this, &AddCurveFileDlg::onCurveNameChanged);
|
||||||
connect(ui->dataStartSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &AddCurveFileDlg::onCurveDataChanged);
|
connect(ui->dataStartSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &AddCurveFileDlg::onCurveDataChanged);
|
||||||
connect(ui->dataStopSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &AddCurveFileDlg::onCurveDataChanged);
|
connect(ui->dataStopSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &AddCurveFileDlg::onCurveDataChanged);
|
||||||
connect(ui->xValueSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &AddCurveFileDlg::onCurveDataChanged);
|
connect(ui->xValueSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &AddCurveFileDlg::onCurveDataChanged);
|
||||||
connect(ui->yValueSpinBox, QOverload<double>::of(&QDoubleSpinBox::valueChanged), this, &AddCurveFileDlg::onCurveDataChanged);
|
connect(ui->yValueSpinBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &AddCurveFileDlg::onCurveDataChanged);
|
||||||
|
|
||||||
// Dialog buttons
|
// Dialog buttons
|
||||||
connect(ui->addBtn, &QPushButton::clicked, this, &AddCurveFileDlg::onSure);
|
connect(ui->addBtn, &QPushButton::clicked, this, &AddCurveFileDlg::onSure);
|
||||||
@ -87,9 +87,11 @@ void AddCurveFileDlg::updateFileInfo(const QString& filePath) {
|
|||||||
ui->filePathEdit->setText(filePath);
|
ui->filePathEdit->setText(filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddCurveFileDlg::onAddCurveClicked() {
|
void AddCurveFileDlg::onAddCurveClicked()
|
||||||
|
{
|
||||||
// Save current curve properties if any curve is selected
|
// Save current curve properties if any curve is selected
|
||||||
if (currentCurveIndex_ >= 0) {
|
if (currentCurveIndex_ >= 0)
|
||||||
|
{
|
||||||
saveCurveProperties();
|
saveCurveProperties();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,10 +101,13 @@ void AddCurveFileDlg::onAddCurveClicked() {
|
|||||||
newCurve.color = generateCurveColor();
|
newCurve.color = generateCurveColor();
|
||||||
|
|
||||||
// Set default values based on chart type
|
// Set default values based on chart type
|
||||||
if (chartProperties_.chartType == ChartType::Wave) {
|
if (chartProperties_.chartType == ChartType::Wave)
|
||||||
|
{
|
||||||
newCurve.data.wave.start = 1;
|
newCurve.data.wave.start = 1;
|
||||||
newCurve.data.wave.stop = 241;
|
newCurve.data.wave.stop = 241;
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
newCurve.data.report.x = 0.0;
|
newCurve.data.report.x = 0.0;
|
||||||
newCurve.data.report.y = 0.0;
|
newCurve.data.report.y = 0.0;
|
||||||
}
|
}
|
||||||
@ -121,7 +126,7 @@ void AddCurveFileDlg::onAddCurveClicked() {
|
|||||||
.arg(newCurve.color.green())
|
.arg(newCurve.color.green())
|
||||||
.arg(newCurve.color.blue());
|
.arg(newCurve.color.blue());
|
||||||
} else {
|
} else {
|
||||||
displayText = QString("%1 (%.2f,%.2f) (%4,%5,%6)")
|
displayText = QString("%1 [%2,%3] (%4,%5,%6)")
|
||||||
.arg(newCurve.name)
|
.arg(newCurve.name)
|
||||||
.arg(newCurve.data.report.x)
|
.arg(newCurve.data.report.x)
|
||||||
.arg(newCurve.data.report.y)
|
.arg(newCurve.data.report.y)
|
||||||
@ -134,6 +139,8 @@ void AddCurveFileDlg::onAddCurveClicked() {
|
|||||||
ui->curveListWidget->addItem(item);
|
ui->curveListWidget->addItem(item);
|
||||||
++currentCurveIndex_;
|
++currentCurveIndex_;
|
||||||
|
|
||||||
|
ui->curveNameEdit->setText(newCurve.name);
|
||||||
|
|
||||||
// Select the new curve
|
// Select the new curve
|
||||||
ui->curveListWidget->setCurrentRow(curves_.size() - 1);
|
ui->curveListWidget->setCurrentRow(curves_.size() - 1);
|
||||||
}
|
}
|
||||||
@ -169,21 +176,36 @@ void AddCurveFileDlg::onRemoveCurveClicked() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AddCurveFileDlg::onCurveListWidgetItemClicked(QListWidgetItem* item) {
|
void AddCurveFileDlg::onCurveListWidgetItemClicked(QListWidgetItem* item) {
|
||||||
if (!item) {
|
if (!item)
|
||||||
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
int clickedIndex = ui->curveListWidget->row(item);
|
int clickedIndex = ui->curveListWidget->row(item);
|
||||||
|
|
||||||
if (clickedIndex == currentCurveIndex_) {
|
if (clickedIndex == currentCurveIndex_)
|
||||||
|
{
|
||||||
ui->curveNameEdit->setText(curves_[currentCurveIndex_].name);
|
ui->curveNameEdit->setText(curves_[currentCurveIndex_].name);
|
||||||
|
|
||||||
if (chartProperties_.chartType == ChartType::Wave) {
|
if (chartProperties_.chartType == ChartType::Wave)
|
||||||
|
{
|
||||||
|
ui->dataStartSpinBox->blockSignals(true);
|
||||||
ui->dataStartSpinBox->setValue(curves_[currentCurveIndex_].data.wave.start);
|
ui->dataStartSpinBox->setValue(curves_[currentCurveIndex_].data.wave.start);
|
||||||
|
ui->dataStartSpinBox->blockSignals(false);
|
||||||
|
|
||||||
|
ui->dataStopSpinBox->blockSignals(true);
|
||||||
ui->dataStopSpinBox->setValue(curves_[currentCurveIndex_].data.wave.stop);
|
ui->dataStopSpinBox->setValue(curves_[currentCurveIndex_].data.wave.stop);
|
||||||
} else {
|
ui->dataStopSpinBox->blockSignals(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui->xValueSpinBox->blockSignals(true);
|
||||||
ui->xValueSpinBox->setValue(curves_[currentCurveIndex_].data.report.x);
|
ui->xValueSpinBox->setValue(curves_[currentCurveIndex_].data.report.x);
|
||||||
|
ui->xValueSpinBox->blockSignals(false);
|
||||||
|
|
||||||
|
ui->yValueSpinBox->blockSignals(true);
|
||||||
ui->yValueSpinBox->setValue(curves_[currentCurveIndex_].data.report.y);
|
ui->yValueSpinBox->setValue(curves_[currentCurveIndex_].data.report.y);
|
||||||
|
ui->yValueSpinBox->blockSignals(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
updateColorPreview(curves_[currentCurveIndex_].color);
|
updateColorPreview(curves_[currentCurveIndex_].color);
|
||||||
@ -234,7 +256,7 @@ void AddCurveFileDlg::onCurveNameChanged() {
|
|||||||
.arg(curves_[currentCurveIndex_].color.green())
|
.arg(curves_[currentCurveIndex_].color.green())
|
||||||
.arg(curves_[currentCurveIndex_].color.blue());
|
.arg(curves_[currentCurveIndex_].color.blue());
|
||||||
} else {
|
} else {
|
||||||
displayText = QString("%1 (%.2f,%.2f) (%4,%5,%6)")
|
displayText = QString("%1 [%2,%3] (%4,%5,%6)")
|
||||||
.arg(newName)
|
.arg(newName)
|
||||||
.arg(curves_[currentCurveIndex_].data.report.x)
|
.arg(curves_[currentCurveIndex_].data.report.x)
|
||||||
.arg(curves_[currentCurveIndex_].data.report.y)
|
.arg(curves_[currentCurveIndex_].data.report.y)
|
||||||
@ -343,18 +365,32 @@ void AddCurveFileDlg::addCurveToList(const FileEntryCurve::CurveProperty& curve)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AddCurveFileDlg::updateCurveProperties() {
|
void AddCurveFileDlg::updateCurveProperties() {
|
||||||
if (currentCurveIndex_ >= 0 && currentCurveIndex_ < curves_.size()) {
|
if (currentCurveIndex_ >= 0 && currentCurveIndex_ < curves_.size())
|
||||||
|
{
|
||||||
const FileEntryCurve::CurveProperty& curve = curves_[currentCurveIndex_];
|
const FileEntryCurve::CurveProperty& curve = curves_[currentCurveIndex_];
|
||||||
|
|
||||||
ui->curveNameEdit->setText(curve.name);
|
ui->curveNameEdit->setText(curve.name);
|
||||||
|
|
||||||
// Update properties based on chart type
|
// Update properties based on chart type
|
||||||
if (chartProperties_.chartType == ChartType::Wave) {
|
if (chartProperties_.chartType == ChartType::Wave)
|
||||||
|
{
|
||||||
|
ui->dataStartSpinBox->blockSignals(true);
|
||||||
ui->dataStartSpinBox->setValue(curve.data.wave.start);
|
ui->dataStartSpinBox->setValue(curve.data.wave.start);
|
||||||
|
ui->dataStartSpinBox->blockSignals(false);
|
||||||
|
|
||||||
|
ui->dataStopSpinBox->blockSignals(true);
|
||||||
ui->dataStopSpinBox->setValue(curve.data.wave.stop);
|
ui->dataStopSpinBox->setValue(curve.data.wave.stop);
|
||||||
} else {
|
ui->dataStopSpinBox->blockSignals(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ui->xValueSpinBox->blockSignals(true);
|
||||||
ui->xValueSpinBox->setValue(curve.data.report.x);
|
ui->xValueSpinBox->setValue(curve.data.report.x);
|
||||||
|
ui->xValueSpinBox->blockSignals(false);
|
||||||
|
|
||||||
|
ui->yValueSpinBox->blockSignals(true);
|
||||||
ui->yValueSpinBox->setValue(curve.data.report.y);
|
ui->yValueSpinBox->setValue(curve.data.report.y);
|
||||||
|
ui->yValueSpinBox->blockSignals(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
selectedColor_ = curve.color;
|
selectedColor_ = curve.color;
|
||||||
@ -561,12 +597,12 @@ bool AddCurveFileDlg::validateSpecificParams() {
|
|||||||
double yMin = ui->yMinSpinBox->value();
|
double yMin = ui->yMinSpinBox->value();
|
||||||
double yMax = ui->yMaxSpinBox->value();
|
double yMax = ui->yMaxSpinBox->value();
|
||||||
|
|
||||||
if (xMin >= xMax) {
|
if (xMin > xMax) {
|
||||||
QMessageBox::warning(this, tr("Validation Error"), tr("X axis minimum value must be less than maximum value."));
|
QMessageBox::warning(this, tr("Validation Error"), tr("X axis minimum value must be less than maximum value."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (yMin >= yMax) {
|
if (yMin > yMax) {
|
||||||
QMessageBox::warning(this, tr("Validation Error"), tr("Y axis minimum value must be less than maximum value."));
|
QMessageBox::warning(this, tr("Validation Error"), tr("Y axis minimum value must be less than maximum value."));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -580,11 +616,11 @@ bool AddCurveFileDlg::validateSpecificParams() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// X axis tick count validation
|
// X axis tick count validation
|
||||||
int xTickCount = ui->xCountSpinBox->value();
|
//int xTickCount = ui->xCountSpinBox->value();
|
||||||
if (xTickCount < 2) {
|
//if (xTickCount < 2) {
|
||||||
QMessageBox::warning(this, tr("Validation Error"), tr("X axis tick count must be at least 2."));
|
// QMessageBox::warning(this, tr("Validation Error"), tr("X axis tick count must be at least 2."));
|
||||||
return false;
|
// return false;
|
||||||
}
|
//}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,12 +2,15 @@
|
|||||||
<ui version="4.0">
|
<ui version="4.0">
|
||||||
<class>AddCurveFileDlg</class>
|
<class>AddCurveFileDlg</class>
|
||||||
<widget class="QWidget" name="AddCurveFileDlg">
|
<widget class="QWidget" name="AddCurveFileDlg">
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
<property name="geometry">
|
<property name="geometry">
|
||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>600</width>
|
<width>600</width>
|
||||||
<height>789</height>
|
<height>842</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<property name="windowTitle">
|
<property name="windowTitle">
|
||||||
@ -287,7 +290,7 @@
|
|||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>2</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>50</number>
|
<number>50</number>
|
||||||
@ -377,7 +380,7 @@
|
|||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<number>2</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>50</number>
|
<number>50</number>
|
||||||
@ -543,7 +546,7 @@
|
|||||||
<property name="title">
|
<property name="title">
|
||||||
<string>Selected Curve Properties</string>
|
<string>Selected Curve Properties</string>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QGridLayout" name="curvePropertiesGridLayout">
|
<layout class="QGridLayout" name="gridLayout">
|
||||||
<item row="0" column="0">
|
<item row="0" column="0">
|
||||||
<widget class="QLabel" name="curveNameLabel">
|
<widget class="QLabel" name="curveNameLabel">
|
||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
@ -609,7 +612,7 @@
|
|||||||
<property name="minimumSize">
|
<property name="minimumSize">
|
||||||
<size>
|
<size>
|
||||||
<width>50</width>
|
<width>50</width>
|
||||||
<height>25</height>
|
<height>0</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="styleSheet">
|
<property name="styleSheet">
|
||||||
@ -701,8 +704,11 @@
|
|||||||
</item>
|
</item>
|
||||||
<item row="4" column="0">
|
<item row="4" column="0">
|
||||||
<widget class="QLabel" name="xValueLabel">
|
<widget class="QLabel" name="xValueLabel">
|
||||||
<property name="visible">
|
<property name="minimumSize">
|
||||||
<bool>false</bool>
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>X Value:</string>
|
<string>X Value:</string>
|
||||||
@ -710,25 +716,31 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="4" column="1">
|
<item row="4" column="1">
|
||||||
<widget class="QDoubleSpinBox" name="xValueSpinBox">
|
<widget class="QSpinBox" name="xValueSpinBox">
|
||||||
<property name="visible">
|
<property name="minimumSize">
|
||||||
<bool>false</bool>
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<double>-999999.000000000000000</double>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<double>999999.000000000000000</double>
|
<number>999999</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="value">
|
<property name="value">
|
||||||
<double>0.000000000000000</double>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="0">
|
<item row="5" column="0">
|
||||||
<widget class="QLabel" name="yValueLabel">
|
<widget class="QLabel" name="yValueLabel">
|
||||||
<property name="visible">
|
<property name="minimumSize">
|
||||||
<bool>false</bool>
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Y Value:</string>
|
<string>Y Value:</string>
|
||||||
@ -736,18 +748,21 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="5" column="1">
|
<item row="5" column="1">
|
||||||
<widget class="QDoubleSpinBox" name="yValueSpinBox">
|
<widget class="QSpinBox" name="yValueSpinBox">
|
||||||
<property name="visible">
|
<property name="minimumSize">
|
||||||
<bool>false</bool>
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="minimum">
|
<property name="minimum">
|
||||||
<double>-999999.000000000000000</double>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<double>999999.000000000000000</double>
|
<number>999999</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="value">
|
<property name="value">
|
||||||
<double>0.000000000000000</double>
|
<number>2</number>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
@ -230,17 +230,24 @@ void AddLightFileDlg::addLightToList(const FileEntryLight::LightRowProperty& lig
|
|||||||
ui->lightListWidget->addItem(item);
|
ui->lightListWidget->addItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddLightFileDlg::updateLightProperties() {
|
void AddLightFileDlg::updateLightProperties()
|
||||||
if (currentLightIndex_ >= 0 && currentLightIndex_ < lights_.size()) {
|
{
|
||||||
|
if (currentLightIndex_ >= 0 && currentLightIndex_ < lights_.size())
|
||||||
|
{
|
||||||
const FileEntryLight::LightRowProperty& light = lights_[currentLightIndex_];
|
const FileEntryLight::LightRowProperty& light = lights_[currentLightIndex_];
|
||||||
|
|
||||||
|
ui->lightNameEdit->blockSignals(true);
|
||||||
ui->lightNameEdit->setText(light.name.join(", "));
|
ui->lightNameEdit->setText(light.name.join(", "));
|
||||||
|
ui->lightNameEdit->blockSignals(false);
|
||||||
|
|
||||||
// Update data edit
|
// Update data edit
|
||||||
QStringList dataStrings;
|
QStringList dataStrings;
|
||||||
for (int dataValue : light.data) {
|
for (int dataValue : light.data) {
|
||||||
dataStrings.append(QString::number(dataValue));
|
dataStrings.append(QString::number(dataValue));
|
||||||
}
|
}
|
||||||
|
ui->lightDataEdit->blockSignals(true);
|
||||||
ui->lightDataEdit->setText(dataStrings.join(", "));
|
ui->lightDataEdit->setText(dataStrings.join(", "));
|
||||||
|
ui->lightDataEdit->blockSignals(false);
|
||||||
|
|
||||||
// Update row index display
|
// Update row index display
|
||||||
ui->rowIndexValue->setText(QString::number(currentLightIndex_));
|
ui->rowIndexValue->setText(QString::number(currentLightIndex_));
|
||||||
@ -290,15 +297,22 @@ QString AddLightFileDlg::generateLightName() {
|
|||||||
return QString("Light_%1").arg(lights_.size() + 1);
|
return QString("Light_%1").arg(lights_.size() + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddLightFileDlg::updateDataDisplay() {
|
void AddLightFileDlg::updateDataDisplay()
|
||||||
if (currentLightIndex_ >= 0 && currentLightIndex_ < lights_.size()) {
|
{
|
||||||
|
if (currentLightIndex_ >= 0 && currentLightIndex_ < lights_.size())
|
||||||
|
{
|
||||||
const FileEntryLight::LightRowProperty& light = lights_[currentLightIndex_];
|
const FileEntryLight::LightRowProperty& light = lights_[currentLightIndex_];
|
||||||
QStringList dataStrings;
|
QStringList dataStrings;
|
||||||
for (int dataValue : light.data) {
|
for (int dataValue : light.data)
|
||||||
|
{
|
||||||
dataStrings.append(QString::number(dataValue));
|
dataStrings.append(QString::number(dataValue));
|
||||||
}
|
}
|
||||||
|
ui->lightDataEdit->blockSignals(true);
|
||||||
ui->lightDataEdit->setText(dataStrings.join(", "));
|
ui->lightDataEdit->setText(dataStrings.join(", "));
|
||||||
} else {
|
ui->lightDataEdit->blockSignals(false);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
ui->lightDataEdit->clear();
|
ui->lightDataEdit->clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -376,6 +390,7 @@ void AddLightFileDlg::onSure() {
|
|||||||
if (lightEntry) {
|
if (lightEntry) {
|
||||||
lightEntry->SetName(sName);
|
lightEntry->SetName(sName);
|
||||||
|
|
||||||
|
colorProperties_.timeParam = ui->SpinBox_time->value();
|
||||||
// Set color properties
|
// Set color properties
|
||||||
lightEntry->SetColorProperties(colorProperties_);
|
lightEntry->SetColorProperties(colorProperties_);
|
||||||
|
|
||||||
|
|||||||
@ -123,7 +123,7 @@
|
|||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Chart Names:</string>
|
<string>Chart Name:</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@ -135,11 +135,37 @@
|
|||||||
<height>25</height>
|
<height>25</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Chart 1</string>
|
||||||
|
</property>
|
||||||
<property name="placeholderText">
|
<property name="placeholderText">
|
||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="timeParamLabel">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>Time:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QSpinBox" name="SpinBox_time">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>25</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
@ -539,7 +539,7 @@ void AddPolarFileDlg::onSure()
|
|||||||
QString errorMsg;
|
QString errorMsg;
|
||||||
switch (result) {
|
switch (result) {
|
||||||
case WorkSpace::FileEntryResult::LimitExceeded:
|
case WorkSpace::FileEntryResult::LimitExceeded:
|
||||||
errorMsg = tr("Curve file count has reached the limit (9 files)");
|
errorMsg = tr("Polar file count has reached the limit (9 files)");
|
||||||
break;
|
break;
|
||||||
case WorkSpace::FileEntryResult::Duplicate:
|
case WorkSpace::FileEntryResult::Duplicate:
|
||||||
errorMsg = tr("File already exists");
|
errorMsg = tr("File already exists");
|
||||||
@ -560,6 +560,10 @@ void AddPolarFileDlg::onSure()
|
|||||||
|
|
||||||
accept();
|
accept();
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
QMessageBox::critical(this, tr("Error"), tr("Failed to create Polar file entry."));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddPolarFileDlg::onCurveDataChanged()
|
void AddPolarFileDlg::onCurveDataChanged()
|
||||||
|
|||||||
@ -291,13 +291,29 @@ void AddSurfaceFileDlg::updateSurfaceProperties()
|
|||||||
if (currentSurfaceIndex_ >= 0 && currentSurfaceIndex_ < surfaces_.size()) {
|
if (currentSurfaceIndex_ >= 0 && currentSurfaceIndex_ < surfaces_.size()) {
|
||||||
const auto& surface = surfaces_[currentSurfaceIndex_];
|
const auto& surface = surfaces_[currentSurfaceIndex_];
|
||||||
|
|
||||||
|
ui->surfaceNameLineEdit->blockSignals(true);
|
||||||
ui->surfaceNameLineEdit->setText(surface.name);
|
ui->surfaceNameLineEdit->setText(surface.name);
|
||||||
ui->surfaceStartSpinBox->setValue(surface.start);
|
ui->surfaceNameLineEdit->blockSignals(false);
|
||||||
ui->surfaceStopSpinBox->setValue(surface.stop);
|
|
||||||
|
|
||||||
|
ui->surfaceStartSpinBox->blockSignals(true);
|
||||||
|
ui->surfaceStartSpinBox->setValue(surface.start);
|
||||||
|
ui->surfaceStartSpinBox->blockSignals(false);
|
||||||
|
|
||||||
|
ui->surfaceStopSpinBox->blockSignals(true);
|
||||||
|
ui->surfaceStopSpinBox->setValue(surface.stop);
|
||||||
|
ui->surfaceStopSpinBox->blockSignals(false);
|
||||||
|
|
||||||
|
ui->comboBox_x->blockSignals(true);
|
||||||
ui->comboBox_x->setCurrentText(surface.x);
|
ui->comboBox_x->setCurrentText(surface.x);
|
||||||
|
ui->comboBox_x->blockSignals(false);
|
||||||
|
|
||||||
|
ui->comboBox_y->blockSignals(true);
|
||||||
ui->comboBox_y->setCurrentText(surface.y);
|
ui->comboBox_y->setCurrentText(surface.y);
|
||||||
|
ui->comboBox_y->blockSignals(false);
|
||||||
|
|
||||||
|
ui->comboBox_z->blockSignals(true);
|
||||||
ui->comboBox_z->setCurrentText(surface.z);
|
ui->comboBox_z->setCurrentText(surface.z);
|
||||||
|
ui->comboBox_z->blockSignals(false);
|
||||||
|
|
||||||
selectedColor_ = surface.color;
|
selectedColor_ = surface.color;
|
||||||
updateColorPreview(ui->surfaceColorButton, selectedColor_);
|
updateColorPreview(ui->surfaceColorButton, selectedColor_);
|
||||||
|
|||||||
@ -11,6 +11,8 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <osgDB/ReadFile>
|
#include <osgDB/ReadFile>
|
||||||
#include <osgEarthUtil/EarthManipulator>
|
#include <osgEarthUtil/EarthManipulator>
|
||||||
|
#include <osgUtil/LineSegmentIntersector>
|
||||||
|
#include <osgEarth/SpatialReference>
|
||||||
|
|
||||||
#include <osgViewer/ViewerEventHandlers>
|
#include <osgViewer/ViewerEventHandlers>
|
||||||
#include <osgGA/StateSetManipulator>
|
#include <osgGA/StateSetManipulator>
|
||||||
@ -23,6 +25,13 @@
|
|||||||
#include "workspace/WorkSpaceManager.h"
|
#include "workspace/WorkSpaceManager.h"
|
||||||
#include "workspace/WorkSpace.h"
|
#include "workspace/WorkSpace.h"
|
||||||
#include "scutcheon/osgScutcheon.h"
|
#include "scutcheon/osgScutcheon.h"
|
||||||
|
#include "workspace/PresetModelConfigParser.h"
|
||||||
|
|
||||||
|
#include "entities/EntitiesManager.h"
|
||||||
|
#include "entities/EntityFactory.h"
|
||||||
|
#include "entities/ComponentFactory.h"
|
||||||
|
#include "entities/Entity.h"
|
||||||
|
#include "entities/Component.h"
|
||||||
|
|
||||||
static void ConfigureView( osgViewer::View* view ) {
|
static void ConfigureView( osgViewer::View* view ) {
|
||||||
view->addEventHandler(new osgViewer::StatsHandler());
|
view->addEventHandler(new osgViewer::StatsHandler());
|
||||||
@ -191,10 +200,14 @@ void OsgWidget::paintEvent(QPaintEvent*) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OsgWidget::dragEnterEvent(QDragEnterEvent* event) {
|
void OsgWidget::dragEnterEvent(QDragEnterEvent* event) {
|
||||||
// 检查是否是预制模型拖拽
|
LOG_INFO("OsgWidget::dragEnterEvent - Available formats:{}", event->mimeData()->formats().join(",").toStdString());
|
||||||
|
|
||||||
|
// Check if it's a preset model drag
|
||||||
if (event->mimeData()->hasFormat("application/x-preset-model")) {
|
if (event->mimeData()->hasFormat("application/x-preset-model")) {
|
||||||
|
LOG_INFO("OsgWidget::dragEnterEvent - Accept preset model drag");
|
||||||
event->acceptProposedAction();
|
event->acceptProposedAction();
|
||||||
} else {
|
} else {
|
||||||
|
LOG_INFO("OsgWidget::dragEnterEvent - Ignore drag, not preset model format");
|
||||||
event->ignore();
|
event->ignore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -209,40 +222,98 @@ void OsgWidget::dragMoveEvent(QDragMoveEvent* event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OsgWidget::dropEvent(QDropEvent* event) {
|
void OsgWidget::dropEvent(QDropEvent* event) {
|
||||||
// 检查是否是预制模型拖拽
|
LOG_INFO("OsgWidget::dropEvent - Start processing drop event");
|
||||||
|
|
||||||
if (event->mimeData()->hasFormat("application/x-preset-model")) {
|
if (event->mimeData()->hasFormat("application/x-preset-model")) {
|
||||||
QByteArray data = event->mimeData()->data("application/x-preset-model");
|
QByteArray data = event->mimeData()->data("application/x-preset-model");
|
||||||
QString modelInfo = QString::fromUtf8(data);
|
QString modelInfo = QString::fromUtf8(data);
|
||||||
|
|
||||||
// 解析模型信息 (格式: "modelType|modelName")
|
LOG_INFO("OsgWidget::dropEvent - Received model info:{}", modelInfo.toStdString());
|
||||||
|
|
||||||
QStringList parts = modelInfo.split("|");
|
QStringList parts = modelInfo.split("|");
|
||||||
if (parts.size() == 2) {
|
if (parts.size() == 2) {
|
||||||
QString modelType = parts[0];
|
QString modelType = parts[0];
|
||||||
QString modelName = parts[1];
|
QString modelName = parts[1];
|
||||||
|
|
||||||
// 获取拖拽位置
|
|
||||||
QPointF position = event->posF();
|
QPointF position = event->posF();
|
||||||
|
|
||||||
// 处理预制模型拖拽
|
LOG_INFO("OsgWidget::dropEvent - Parse success, type:{} name:{} position:({},{})", modelType.toStdString(), modelName.toStdString(), position.x(), position.y());
|
||||||
|
|
||||||
OnPresetModelDropped(modelType, modelName, position);
|
OnPresetModelDropped(modelType, modelName, position);
|
||||||
|
|
||||||
event->acceptProposedAction();
|
event->acceptProposedAction();
|
||||||
|
LOG_INFO("OsgWidget::dropEvent - Drag processing completed, accepted");
|
||||||
} else {
|
} else {
|
||||||
|
LOG_ERROR("OsgWidget::dropEvent - Data format error, expected: type|name, actual:{}", modelInfo.toStdString());
|
||||||
event->ignore();
|
event->ignore();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
LOG_INFO("OsgWidget::dropEvent - Not preset model format, ignore drag");
|
||||||
event->ignore();
|
event->ignore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void OsgWidget::OnPresetModelDropped(const QString& modelType, const QString& modelName, const QPointF& position) {
|
void OsgWidget::OnPresetModelDropped(const QString& modelType, const QString& modelName, const QPointF& position) {
|
||||||
// TODO: 实现预制模型拖拽处理逻辑
|
LOG_INFO("OsgWidget::OnPresetModelDropped - Dropped model type:{} name:{} position:({}, {})", modelType.toStdString(), modelName.toStdString(), position.x(), position.y());
|
||||||
// 1. 将屏幕坐标转换为世界坐标
|
|
||||||
// 2. 创建对应的Entity和MeshComponent
|
|
||||||
// 3. 添加到场景中
|
|
||||||
|
|
||||||
qDebug() << "预制模型拖拽:" << modelType << modelName << "位置:" << position;
|
WorkSpace* currentWorkSpace = WorkSpaceManager::Get().GetCurrent();
|
||||||
|
if (nullptr == currentWorkSpace) {
|
||||||
|
LOG_WARN("OsgWidget::OnPresetModelDropped - Current workspace is nullptr");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// 这里暂时只是输出调试信息,后续需要集成实体系统
|
// 将屏幕坐标转换为世界坐标
|
||||||
|
double longitude, latitude, height;
|
||||||
|
if (!ScreenToWorldCoordinate(static_cast<int>(position.x()), static_cast<int>(position.y()), longitude, latitude, height)) {
|
||||||
|
LOG_WARN("OsgWidget::OnPresetModelDropped - Failed to convert screen coordinates to world coordinates");
|
||||||
|
// 使用默认位置
|
||||||
|
longitude = 0.0;
|
||||||
|
latitude = 0.0;
|
||||||
|
height = 0.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool success = false;
|
||||||
|
ModelInfo modelInfo = PresetModelConfigParser::Get().GetModelInfo(modelType, modelName, &success);
|
||||||
|
if (!success) {
|
||||||
|
LOG_ERROR("OsgWidget::OnPresetModelDropped - Failed to get model info of type:{} name:{}", modelType.toStdString(), modelName.toStdString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity* entity = EntitiesManager::Get().CreateEntityWithComponents(modelType, modelInfo.meshFile, modelInfo.useLabel, currentWorkSpace);
|
||||||
|
if (nullptr == entity) {
|
||||||
|
LOG_ERROR("OsgWidget::OnPresetModelDropped - Failed to create entity of type: {}", modelType.toStdString());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int count = currentWorkSpace->GetEntities().size();
|
||||||
|
entity->SetName(QString("%1_%2").arg(modelName).arg(count));
|
||||||
|
|
||||||
|
SceneComponent* rootComponent = entity->GetRootComponent();
|
||||||
|
if (rootComponent) {
|
||||||
|
osg::Vec3 worldPos(longitude, latitude, height);
|
||||||
|
rootComponent->SetLocation(worldPos);
|
||||||
|
LOG_INFO("OsgWidget::OnPresetModelDropped - Set entity position to ({:.6f}, {:.6f}, {:.2f})", longitude, latitude, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
LOG_INFO("OsgWidget::OnPresetModelDropped - Successfully created {} entity: {} at position ({:.6f}, {:.6f}, {:.2f})",
|
||||||
|
modelType.toStdString(), entity->GetName().toStdString(), longitude, latitude, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool OsgWidget::ScreenToWorldCoordinate(int x, int y, double& longitude, double& latitude, double& height) {
|
||||||
|
if (!activeScene_.valid()) {
|
||||||
|
LOG_WARN("OsgWidget::ScreenToWorldCoordinate - active scene is null");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::Vec3d output;
|
||||||
|
if (!activeScene_->ScreenToWorldCoordinate(x, y, &output)) {
|
||||||
|
LOG_WARN("OsgWidget::ScreenToWorldCoordinate - Failed to convert screen coordinates to world coordinates");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
longitude = output.x();
|
||||||
|
latitude = output.y();
|
||||||
|
height = output.z();
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,6 +43,8 @@ public slots:
|
|||||||
*/
|
*/
|
||||||
void OnPresetModelDropped(const QString& modelType, const QString& modelName, const QPointF& position = QPointF());
|
void OnPresetModelDropped(const QString& modelType, const QString& modelName, const QPointF& position = QPointF());
|
||||||
|
|
||||||
|
bool ScreenToWorldCoordinate(int x, int y, double& longitude, double& latitude, double& altitude);
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QTimer timer_;
|
QTimer timer_;
|
||||||
|
|||||||
@ -510,6 +510,8 @@ bool FileEntryLight::SaveFiles(tinyxml2::XMLElement* scene, tinyxml2::XMLDocumen
|
|||||||
chartElement->SetAttribute("openColor", QColorToString(colorProperties_.openColor).toUtf8().constData());
|
chartElement->SetAttribute("openColor", QColorToString(colorProperties_.openColor).toUtf8().constData());
|
||||||
chartElement->SetAttribute("closeColor", QColorToString(colorProperties_.closeColor).toUtf8().constData());
|
chartElement->SetAttribute("closeColor", QColorToString(colorProperties_.closeColor).toUtf8().constData());
|
||||||
|
|
||||||
|
chartElement->SetAttribute("t", colorProperties_.timeParam);
|
||||||
|
|
||||||
// 为每个LightRowProperty创建<light>元素
|
// 为每个LightRowProperty创建<light>元素
|
||||||
for (const auto& lightRow : lightProperties_) {
|
for (const auto& lightRow : lightProperties_) {
|
||||||
tinyxml2::XMLElement* lightElement = doc->NewElement("curve");
|
tinyxml2::XMLElement* lightElement = doc->NewElement("curve");
|
||||||
@ -559,6 +561,8 @@ bool FileEntryLight::ParseFiles(const tinyxml2::XMLElement* chartElement) {
|
|||||||
colorProperties_.closeColor = StringToQColor(QString::fromUtf8(closeColorAttr));
|
colorProperties_.closeColor = StringToQColor(QString::fromUtf8(closeColorAttr));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
colorProperties_.timeParam = chartElement->DoubleAttribute("t", 0.0);
|
||||||
|
|
||||||
// 解析所有<light>元素
|
// 解析所有<light>元素
|
||||||
lightProperties_.clear();
|
lightProperties_.clear();
|
||||||
for (const tinyxml2::XMLElement* lightElement = chartElement->FirstChildElement("curve");
|
for (const tinyxml2::XMLElement* lightElement = chartElement->FirstChildElement("curve");
|
||||||
|
|||||||
49
src/workspace/ModelInfo.h
Normal file
49
src/workspace/ModelInfo.h
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
#include <QVector>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Model information structure
|
||||||
|
*
|
||||||
|
* Contains all information for a single preset model, including name, display name,
|
||||||
|
* description, mesh file path, icon path, enabled status, and entity registration info.
|
||||||
|
*/
|
||||||
|
struct ModelInfo {
|
||||||
|
QString name; ///< Model name (unique identifier)
|
||||||
|
QString displayName; ///< Display name (for UI display)
|
||||||
|
QString description; ///< Model description
|
||||||
|
QString meshFile; ///< 3D mesh file path
|
||||||
|
QString icon; ///< Icon file path
|
||||||
|
bool useLabel;
|
||||||
|
bool enabled; ///< Whether this model is enabled
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Default constructor
|
||||||
|
* Model is enabled by default
|
||||||
|
*/
|
||||||
|
ModelInfo() : useLabel(true), enabled(true) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Constructor with parameters
|
||||||
|
*/
|
||||||
|
ModelInfo(const QString& name, const QString& displayName, const QString& description,
|
||||||
|
const QString& meshFile, const QString& icon, bool enabled = true,
|
||||||
|
const QString& entityType = "", const QString& entityClass = "",
|
||||||
|
const QStringList& requiredComponents = QStringList())
|
||||||
|
: name(name), displayName(displayName), description(description),
|
||||||
|
meshFile(meshFile), icon(icon), useLabel(true), enabled(enabled) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Model category structure
|
||||||
|
*
|
||||||
|
* Contains information for a model category, such as ships, satellites, missiles, jammers, etc.
|
||||||
|
* Each category contains multiple specific models.
|
||||||
|
*/
|
||||||
|
struct ModelCategory {
|
||||||
|
QString name; ///< Category name (unique identifier)
|
||||||
|
QString displayName; ///< Display name (for UI display)
|
||||||
|
QString icon; ///< Category icon path
|
||||||
|
QVector<ModelInfo> models; ///< All models in this category
|
||||||
|
};
|
||||||
@ -1,19 +1,21 @@
|
|||||||
#include "PresetModelConfigParser.h"
|
#include "workspace/PresetModelConfigParser.h"
|
||||||
#include "../../xml/tinyxml2.h"
|
|
||||||
#include "../../common/SpdLogger.h"
|
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
|
||||||
PresetModelConfigParser::PresetModelConfigParser()
|
#include "xml/tinyxml2.h"
|
||||||
{
|
#include "common/SpdLogger.h"
|
||||||
|
|
||||||
|
template<> PresetModelConfigParser* Singleton<PresetModelConfigParser>::instance_ = nullptr;
|
||||||
|
|
||||||
|
PresetModelConfigParser::PresetModelConfigParser(QObject* parent)
|
||||||
|
: QObject(parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
PresetModelConfigParser::~PresetModelConfigParser()
|
PresetModelConfigParser::~PresetModelConfigParser() {
|
||||||
{
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PresetModelConfigParser::LoadAllConfigs(const QString& configDir)
|
bool PresetModelConfigParser::LoadAllConfigs(const QString& configDir) {
|
||||||
{
|
|
||||||
Clear();
|
Clear();
|
||||||
|
|
||||||
QDir dir(configDir);
|
QDir dir(configDir);
|
||||||
@ -102,8 +104,15 @@ bool PresetModelConfigParser::ParseXmlFile(const QString& filePath)
|
|||||||
const char* modelDisplayName = modelElement->Attribute("displayName");
|
const char* modelDisplayName = modelElement->Attribute("displayName");
|
||||||
const char* description = modelElement->Attribute("description");
|
const char* description = modelElement->Attribute("description");
|
||||||
const char* meshFile = modelElement->Attribute("meshFile");
|
const char* meshFile = modelElement->Attribute("meshFile");
|
||||||
|
const char* modelIcon = modelElement->Attribute("icon");
|
||||||
|
const char* label = modelElement->Attribute("label");
|
||||||
const char* enabled = modelElement->Attribute("enabled");
|
const char* enabled = modelElement->Attribute("enabled");
|
||||||
|
|
||||||
|
// Entity registration attributes
|
||||||
|
const char* entityType = modelElement->Attribute("entityType");
|
||||||
|
const char* entityClass = modelElement->Attribute("entityClass");
|
||||||
|
const char* requiredComponents = modelElement->Attribute("requiredComponents");
|
||||||
|
|
||||||
if (!modelName) {
|
if (!modelName) {
|
||||||
LOG_WARN("Model element missing name attribute in file: {}", filePath.toStdString());
|
LOG_WARN("Model element missing name attribute in file: {}", filePath.toStdString());
|
||||||
modelElement = modelElement->NextSiblingElement("model");
|
modelElement = modelElement->NextSiblingElement("model");
|
||||||
@ -114,6 +123,8 @@ bool PresetModelConfigParser::ParseXmlFile(const QString& filePath)
|
|||||||
model.displayName = modelDisplayName ? QString::fromUtf8(modelDisplayName) : model.name;
|
model.displayName = modelDisplayName ? QString::fromUtf8(modelDisplayName) : model.name;
|
||||||
model.description = description ? QString::fromUtf8(description) : "";
|
model.description = description ? QString::fromUtf8(description) : "";
|
||||||
model.meshFile = meshFile ? QString::fromUtf8(meshFile) : "";
|
model.meshFile = meshFile ? QString::fromUtf8(meshFile) : "";
|
||||||
|
model.icon = modelIcon ? QString::fromUtf8(modelIcon) : "";
|
||||||
|
model.useLabel = label ? (strcmp(label, "true") == 0) : true;
|
||||||
model.enabled = enabled ? (strcmp(enabled, "true") == 0) : true;
|
model.enabled = enabled ? (strcmp(enabled, "true") == 0) : true;
|
||||||
|
|
||||||
category.models.append(model);
|
category.models.append(model);
|
||||||
@ -156,16 +167,18 @@ ModelCategory PresetModelConfigParser::GetCategory(const QString& categoryName)
|
|||||||
return ModelCategory();
|
return ModelCategory();
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelInfo PresetModelConfigParser::GetModelInfo(const QString& categoryName, const QString& modelName) const
|
ModelInfo PresetModelConfigParser::GetModelInfo(const QString& categoryName, const QString& modelName, bool* success) const {
|
||||||
{
|
|
||||||
if (m_categories.contains(categoryName)) {
|
if (m_categories.contains(categoryName)) {
|
||||||
const ModelCategory& category = m_categories[categoryName];
|
const ModelCategory& category = m_categories[categoryName];
|
||||||
for (const ModelInfo& model : category.models) {
|
for (const ModelInfo& model : category.models) {
|
||||||
if (model.name == modelName) {
|
if (model.name == modelName) {
|
||||||
|
if (success) *success = true;
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (success) *success = false;
|
||||||
return ModelInfo();
|
return ModelInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1,33 +1,22 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QVector>
|
|
||||||
|
|
||||||
struct ModelInfo {
|
#include "app/Singleton.h"
|
||||||
QString name;
|
|
||||||
QString displayName;
|
|
||||||
QString description;
|
|
||||||
QString meshFile;
|
|
||||||
bool enabled;
|
|
||||||
|
|
||||||
ModelInfo() : enabled(true) {}
|
#include "ModelInfo.h"
|
||||||
};
|
|
||||||
|
|
||||||
struct ModelCategory {
|
class PresetModelConfigParser : public QObject, public Singleton<PresetModelConfigParser> {
|
||||||
QString name;
|
Q_OBJECT
|
||||||
QString displayName;
|
|
||||||
QString icon;
|
|
||||||
QVector<ModelInfo> models;
|
|
||||||
};
|
|
||||||
|
|
||||||
class PresetModelConfigParser
|
|
||||||
{
|
|
||||||
public:
|
public:
|
||||||
PresetModelConfigParser();
|
explicit PresetModelConfigParser(QObject* parent = nullptr);
|
||||||
~PresetModelConfigParser();
|
~PresetModelConfigParser();
|
||||||
|
|
||||||
|
void OnDestory() { }
|
||||||
|
|
||||||
// Load all preset model configurations
|
// Load all preset model configurations
|
||||||
bool LoadAllConfigs(const QString& configDir = "workspace/presets");
|
bool LoadAllConfigs(const QString& configDir = "workspace/presets");
|
||||||
|
|
||||||
@ -44,7 +33,7 @@ public:
|
|||||||
ModelCategory GetCategory(const QString& categoryName) const;
|
ModelCategory GetCategory(const QString& categoryName) const;
|
||||||
|
|
||||||
// Get model information
|
// Get model information
|
||||||
ModelInfo GetModelInfo(const QString& categoryName, const QString& modelName) const;
|
ModelInfo GetModelInfo(const QString& categoryName, const QString& modelName, bool* success) const;
|
||||||
|
|
||||||
// Check if configuration data exists
|
// Check if configuration data exists
|
||||||
bool HasData() const;
|
bool HasData() const;
|
||||||
@ -1,129 +0,0 @@
|
|||||||
#include <QApplication>
|
|
||||||
#include <QDebug>
|
|
||||||
#include <iostream>
|
|
||||||
#include "workspace/WorkSpaceXMLParse.h"
|
|
||||||
#include "common/ChartData.h"
|
|
||||||
|
|
||||||
void printChartData(const std::shared_ptr<BaseChartData>& chartData) {
|
|
||||||
if (!chartData) {
|
|
||||||
std::cout << " Chart data is null" << std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << " Chart Name: " << chartData->name.toStdString() << std::endl;
|
|
||||||
std::cout << " Chart Path: " << chartData->path.toStdString() << std::endl;
|
|
||||||
|
|
||||||
// Handle different chart types
|
|
||||||
if (auto curveChart = std::dynamic_pointer_cast<CurveChartData>(chartData)) {
|
|
||||||
std::cout << " Chart Type: Curve" << std::endl;
|
|
||||||
std::cout << " X Title: " << curveChart->xTitle.toStdString() << std::endl;
|
|
||||||
std::cout << " Y Title: " << curveChart->yTitle.toStdString() << std::endl;
|
|
||||||
std::cout << " X Range: [" << curveChart->xMin << " - " << curveChart->xMax << "]" << std::endl;
|
|
||||||
std::cout << " Y Range: [" << curveChart->yMin << " - " << curveChart->yMax << "]" << std::endl;
|
|
||||||
std::cout << " X Count: " << curveChart->xCount << std::endl;
|
|
||||||
std::cout << " Time: " << curveChart->t << std::endl;
|
|
||||||
std::cout << " Curves (" << curveChart->curves.size() << "):" << std::endl;
|
|
||||||
|
|
||||||
for (const auto& curve : curveChart->curves) {
|
|
||||||
std::cout << " - Name: " << curve.name.toStdString()
|
|
||||||
<< ", Range: [" << curve.start << " - " << curve.stop << "]"
|
|
||||||
<< ", Color: " << curve.color.toStdString() << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (auto surfaceChart = std::dynamic_pointer_cast<SurfaceChartData>(chartData)) {
|
|
||||||
std::cout << " Chart Type: Surface" << std::endl;
|
|
||||||
std::cout << " X Title: " << surfaceChart->xTitle.toStdString() << std::endl;
|
|
||||||
std::cout << " Y Title: " << surfaceChart->yTitle.toStdString() << std::endl;
|
|
||||||
std::cout << " Z Title: " << surfaceChart->zTitle.toStdString() << std::endl;
|
|
||||||
std::cout << " X Range: [" << surfaceChart->xMin << " - " << surfaceChart->xMax << "]" << std::endl;
|
|
||||||
std::cout << " Y Range: [" << surfaceChart->yMin << " - " << surfaceChart->yMax << "]" << std::endl;
|
|
||||||
std::cout << " Z Range: [" << surfaceChart->zMin << " - " << surfaceChart->zMax << "]" << std::endl;
|
|
||||||
std::cout << " X Count: " << surfaceChart->xCount << std::endl;
|
|
||||||
std::cout << " Y Count: " << surfaceChart->yCount << std::endl;
|
|
||||||
std::cout << " Z Count: " << surfaceChart->zCount << std::endl;
|
|
||||||
std::cout << " Time: " << surfaceChart->t << std::endl;
|
|
||||||
std::cout << " Surface Curves (" << surfaceChart->curves.size() << "):" << std::endl;
|
|
||||||
|
|
||||||
for (const auto& curve : surfaceChart->curves) {
|
|
||||||
std::cout << " - Name: " << curve.name.toStdString()
|
|
||||||
<< ", Range: [" << curve.start << " - " << curve.stop << "]"
|
|
||||||
<< ", Color: " << curve.color.toStdString()
|
|
||||||
<< ", Position: (" << curve.x << "," << curve.y << "," << curve.z << ")" << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (auto tableChart = std::dynamic_pointer_cast<TableChartData>(chartData)) {
|
|
||||||
std::cout << " Chart Type: Table" << std::endl;
|
|
||||||
std::cout << " Head: " << tableChart->head.toStdString() << std::endl;
|
|
||||||
std::cout << " Time: " << tableChart->t << std::endl;
|
|
||||||
std::cout << " Table Data (" << tableChart->curves.size() << "):" << std::endl;
|
|
||||||
|
|
||||||
for (const auto& curve : tableChart->curves) {
|
|
||||||
std::cout << " - Name: " << curve.name.toStdString()
|
|
||||||
<< ", Color: " << curve.color.toStdString()
|
|
||||||
<< ", Data: " << curve.data.toStdString() << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if (auto lightChart = std::dynamic_pointer_cast<LightChartData>(chartData)) {
|
|
||||||
std::cout << " Chart Type: Light" << std::endl;
|
|
||||||
std::cout << " Open Color: " << lightChart->openColor.toStdString() << std::endl;
|
|
||||||
std::cout << " Close Color: " << lightChart->closeColor.toStdString() << std::endl;
|
|
||||||
std::cout << " Time: " << lightChart->t << std::endl;
|
|
||||||
std::cout << " Light Data (" << lightChart->curves.size() << "):" << std::endl;
|
|
||||||
|
|
||||||
for (const auto& curve : lightChart->curves) {
|
|
||||||
std::cout << " - Name: " << curve.name.toStdString()
|
|
||||||
<< ", Data: " << curve.data.toStdString() << std::endl;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
std::cout << " Chart Type: Unknown" << std::endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
QApplication app(argc, argv);
|
|
||||||
|
|
||||||
std::cout << "Testing XML Chart Parsing with New Inheritance Structure..." << std::endl;
|
|
||||||
|
|
||||||
// Test XML file path
|
|
||||||
QString xmlFilePath = "test_workspace.xml";
|
|
||||||
|
|
||||||
// Create parser instance
|
|
||||||
WorkSpaceXMLParse parser;
|
|
||||||
|
|
||||||
// Parse the XML file
|
|
||||||
FileTypeData fileData;
|
|
||||||
bool success = parser.ParseFiles(xmlFilePath, fileData);
|
|
||||||
|
|
||||||
if (!success) {
|
|
||||||
std::cout << "Failed to parse XML file: " << xmlFilePath.toStdString() << std::endl;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Successfully parsed XML file!" << std::endl;
|
|
||||||
std::cout << "=== File Type Data ===" << std::endl;
|
|
||||||
std::cout << "Files count: " << fileData.files.size() << std::endl;
|
|
||||||
std::cout << "Charts count: " << fileData.charts.size() << std::endl;
|
|
||||||
|
|
||||||
// Print file information
|
|
||||||
std::cout << "\n=== Files ===" << std::endl;
|
|
||||||
for (int i = 0; i < fileData.files.size(); ++i) {
|
|
||||||
const auto& file = fileData.files[i];
|
|
||||||
std::cout << "File " << i << ":" << std::endl;
|
|
||||||
std::cout << " Name: " << file.name.toStdString() << std::endl;
|
|
||||||
std::cout << " Path: " << file.path.toStdString() << std::endl;
|
|
||||||
std::cout << " Type: " << static_cast<int>(file.type) << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Print chart information
|
|
||||||
std::cout << "\n=== Charts ===" << std::endl;
|
|
||||||
for (int i = 0; i < fileData.charts.size(); ++i) {
|
|
||||||
std::cout << "Chart " << i << ":" << std::endl;
|
|
||||||
printChartData(fileData.charts[i]);
|
|
||||||
std::cout << std::endl;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "Test completed successfully!" << std::endl;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
@ -1,45 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<scene name="test_chart" describe="测试图表解析" uuid="{test-uuid}" viewpoint="120.000000, 25.000000, 100.000000, 0.000000, -90.000000, 8200000.000000" commondPath="">
|
|
||||||
<charts>
|
|
||||||
<Wave file="D:/Project/DYTSrouce/bin/Release/workspace/test/Wave.txt"/>
|
|
||||||
<Report Report="D:/Project/DYTSrouce/bin/Release/workspace/test/Report.txt"/>
|
|
||||||
<RD RD="D:/Project/DYTSrouce/bin/Release/workspace/test/RD.txt"/>
|
|
||||||
<SimMatlab SimMatlab=""/>
|
|
||||||
</charts>
|
|
||||||
<timestep path="Timestep.txt"/>
|
|
||||||
<lamp path="D:/Project/DYTSrouce/bin/Release/workspace/test/Lamp.txt"/>
|
|
||||||
<commond path="command.xml"/>
|
|
||||||
<files>
|
|
||||||
<type name="curve" count="2">
|
|
||||||
<chart name="测试曲线1" path="Wave.txt" xTitle="时间" yTitle="幅度" xMin="0" xMax="250" xCount="6" yMin="-800" yMax="800" t="0">
|
|
||||||
<curve name="曲线1" color="255,0,0" start="1" stop="241"/>
|
|
||||||
<curve name="曲线2" color="0,255,0" start="50" stop="200"/>
|
|
||||||
</chart>
|
|
||||||
<chart name="测试曲线2" path="Wave2.txt" xTitle="频率" yTitle="功率" xMin="0" xMax="100" xCount="5" yMin="0" yMax="1000" t="0">
|
|
||||||
<curve name="功率曲线" color="0,0,255" start="1" stop="100"/>
|
|
||||||
</chart>
|
|
||||||
</type>
|
|
||||||
<type name="surface" count="1">
|
|
||||||
<Chart Name="RD图" path="RD.txt" xTitle="y" yTitle="z" zTitle="x" xMin="0" xMax="14000" xCount="7" yMin="0" yMax="0" yCount="0" zMin="0" zMax="70" zCount="7" t="0">
|
|
||||||
<curve Name="RD曲面" Color="61,38,168" Start="0" Stop="0" x="y" y="z" z="x"/>
|
|
||||||
</Chart>
|
|
||||||
</type>
|
|
||||||
<type name="table" count="1">
|
|
||||||
<chart Name="测试表格" path="Report.txt" head="编号,信噪比,方位瞄准线,俯仰注视角,方位,俯仰,属性,多普勒,航线,速度,经度,纬度,距离,速率,径向尺寸,目标RCS" t="0">
|
|
||||||
<curve Name="目标1" color="" data="1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16"/>
|
|
||||||
</chart>
|
|
||||||
</type>
|
|
||||||
<type name="light" count="1">
|
|
||||||
<chart name="信号灯" path="Lamp.txt" openColor="0,255,0" closeColor="255,0,0" t="0">
|
|
||||||
<curve name="目标1,目标2,目标3" data="1,2,3"/>
|
|
||||||
</chart>
|
|
||||||
</type>
|
|
||||||
</files>
|
|
||||||
<entities>
|
|
||||||
<Entity uuid="{test-entity-uuid}" name="test_entity">
|
|
||||||
<MeshComponent mesh="test/test.ive" location="0.000000,0.000000,0.000000" rotation="0.000000,0.000000,0.000000" scale="1.000000,1.000000,1.000000" uuid="{test-mesh-uuid}">
|
|
||||||
<LabelComponent text="test_entity" fontSize="26" visible="true" color="1.00,0.00,0.00,1.00" location="0.000000,0.000000,0.000000" rotation="0.000000,0.000000,0.000000" scale="1.000000,1.000000,1.000000" uuid="{test-label-uuid}"/>
|
|
||||||
</MeshComponent>
|
|
||||||
</Entity>
|
|
||||||
</entities>
|
|
||||||
</scene>
|
|
||||||
@ -3,21 +3,11 @@
|
|||||||
<model name="Electronic Jammer" displayName="Electronic Jammer"
|
<model name="Electronic Jammer" displayName="Electronic Jammer"
|
||||||
description="Comprehensive electronic warfare jamming equipment"
|
description="Comprehensive electronic warfare jamming equipment"
|
||||||
meshFile="models/electronic_jammer.ive"
|
meshFile="models/electronic_jammer.ive"
|
||||||
enabled="true" />
|
icon="icons/electronic_jammer_icon.png"
|
||||||
<model name="Communication Jammer" displayName="Communication Jammer"
|
|
||||||
description="Specialized communication signal jamming equipment"
|
|
||||||
meshFile="models/comm_jammer.ive"
|
|
||||||
enabled="true" />
|
|
||||||
<model name="Radar Jammer" displayName="Radar Jammer"
|
|
||||||
description="Radar signal jamming and deception equipment"
|
|
||||||
meshFile="models/radar_jammer.ive"
|
|
||||||
enabled="true" />
|
|
||||||
<model name="GPS Jammer" displayName="GPS Jammer"
|
|
||||||
description="Satellite navigation signal jamming equipment"
|
|
||||||
meshFile="models/gps_jammer.ive"
|
|
||||||
enabled="true" />
|
enabled="true" />
|
||||||
<model name="Signal Jammer" displayName="Signal Jammer"
|
<model name="Signal Jammer" displayName="Signal Jammer"
|
||||||
description="Multi-frequency signal jamming equipment"
|
description="Multi-frequency signal jamming equipment"
|
||||||
meshFile="models/signal_jammer.ive"
|
meshFile="models/signal_jammer.ive"
|
||||||
enabled="true" />
|
icon="icons/signal_jammer_icon.png"
|
||||||
|
enabled="true"/>
|
||||||
</modelCategory>
|
</modelCategory>
|
||||||
@ -1,23 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<modelCategory name="Missile" displayName="Missiles" icon="missile_icon.png">
|
<modelCategory name="Missile" displayName="Missiles" icon="missile_icon.png">
|
||||||
<model name="Cruise Missile" displayName="Cruise Missile"
|
|
||||||
description="Long-range precision strike cruise missile"
|
|
||||||
meshFile="models/cruise_missile.ive"
|
|
||||||
enabled="true" />
|
|
||||||
<model name="Ballistic Missile" displayName="Ballistic Missile"
|
<model name="Ballistic Missile" displayName="Ballistic Missile"
|
||||||
description="Long-range ballistic missile system"
|
description="Long-range ballistic missile system"
|
||||||
meshFile="models/ballistic_missile.ive"
|
meshFile="models/ballistic_missile.ive"
|
||||||
enabled="true" />
|
icon="icons/ballistic_missile_icon.png"
|
||||||
<model name="Anti-Ship Missile" displayName="Anti-Ship Missile"
|
|
||||||
description="Specialized anti-ship attack missile"
|
|
||||||
meshFile="models/antiship_missile.ive"
|
|
||||||
enabled="true" />
|
|
||||||
<model name="Surface-to-Air Missile" displayName="Surface-to-Air Missile"
|
|
||||||
description="Surface-to-air defense missile system"
|
|
||||||
meshFile="models/sam_missile.ive"
|
|
||||||
enabled="true" />
|
|
||||||
<model name="Anti-Tank Missile" displayName="Anti-Tank Missile"
|
|
||||||
description="Anti-armor precision guided missile"
|
|
||||||
meshFile="models/antitank_missile.ive"
|
|
||||||
enabled="true" />
|
enabled="true" />
|
||||||
</modelCategory>
|
</modelCategory>
|
||||||
@ -1,23 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<modelCategory name="Satellite" displayName="Satellites" icon="satellite_icon.png">
|
<modelCategory name="Satellite" displayName="Satellites" icon="satellite_icon.png">
|
||||||
<model name="Communication Satellite" displayName="Communication Satellite"
|
<model name="Communication Satellite" displayName="Communication Satellite"
|
||||||
description="Satellite platform providing global communication services"
|
description="High-capacity communication relay satellite"
|
||||||
meshFile="models/comm_satellite.ive"
|
meshFile="models/comm_satellite.ive"
|
||||||
enabled="true" />
|
icon="icons/comm_satellite_icon.png"
|
||||||
<model name="Weather Satellite" displayName="Weather Satellite"
|
|
||||||
description="Observation satellite monitoring weather and climate changes"
|
|
||||||
meshFile="models/weather_satellite.ive"
|
|
||||||
enabled="true" />
|
|
||||||
<model name="GPS Satellite" displayName="GPS Satellite"
|
|
||||||
description="Global Positioning System satellite"
|
|
||||||
meshFile="models/gps_satellite.ive"
|
|
||||||
enabled="true" />
|
|
||||||
<model name="Spy Satellite" displayName="Spy Satellite"
|
|
||||||
description="Military reconnaissance and surveillance satellite"
|
|
||||||
meshFile="models/spy_satellite.ive"
|
|
||||||
enabled="true" />
|
|
||||||
<model name="Scientific Satellite" displayName="Scientific Satellite"
|
|
||||||
description="Dedicated satellite for scientific research"
|
|
||||||
meshFile="models/science_satellite.ive"
|
|
||||||
enabled="true" />
|
enabled="true" />
|
||||||
</modelCategory>
|
</modelCategory>
|
||||||
@ -3,21 +3,11 @@
|
|||||||
<model name="Destroyer" displayName="Destroyer"
|
<model name="Destroyer" displayName="Destroyer"
|
||||||
description="High-speed combat vessel with powerful anti-submarine and air defense capabilities"
|
description="High-speed combat vessel with powerful anti-submarine and air defense capabilities"
|
||||||
meshFile="models/destroyer.ive"
|
meshFile="models/destroyer.ive"
|
||||||
enabled="true" />
|
icon="icons/destroyer_icon.png"
|
||||||
|
enabled="true"/>
|
||||||
<model name="Aircraft Carrier" displayName="Aircraft Carrier"
|
<model name="Aircraft Carrier" displayName="Aircraft Carrier"
|
||||||
description="Large aircraft carrier, mobile airfield and command center at sea"
|
description="Large aircraft carrier, mobile airfield and command center at sea"
|
||||||
meshFile="models/carrier.ive"
|
meshFile="models/carrier.ive"
|
||||||
enabled="true" />
|
icon="icons/carrier_icon.png"
|
||||||
<model name="Frigate" displayName="Frigate"
|
enabled="true"/>
|
||||||
description="Medium-sized escort vessel, multi-purpose combat platform"
|
|
||||||
meshFile="models/frigate.ive"
|
|
||||||
enabled="true" />
|
|
||||||
<model name="Submarine" displayName="Submarine"
|
|
||||||
description="Underwater combat platform with strong stealth capabilities"
|
|
||||||
meshFile="models/submarine.ive"
|
|
||||||
enabled="true" />
|
|
||||||
<model name="Cruiser" displayName="Cruiser"
|
|
||||||
description="Heavy combat vessel with powerful firepower"
|
|
||||||
meshFile="models/cruiser.ive"
|
|
||||||
enabled="true" />
|
|
||||||
</modelCategory>
|
</modelCategory>
|
||||||
Loading…
Reference in New Issue
Block a user