Compare commits
4 Commits
9df23631c8
...
e3117d6687
| Author | SHA1 | Date | |
|---|---|---|---|
| e3117d6687 | |||
| 596d60f6bc | |||
| 5c5143e6c2 | |||
| 743565fd75 |
@ -3,8 +3,10 @@
|
||||
#include "common/RecourceHelper.h"
|
||||
#include "workspace/WorkSpaceManager.h"
|
||||
#include "entities/EntitiesManager.h"
|
||||
#include "entities/EntityFactory.h"
|
||||
#include "viewer/OsgViewer.h"
|
||||
#include "scene/MeshManager.h"
|
||||
#include "workspace/PresetModelConfigParser.h"
|
||||
#include "network/NetDriver.h"
|
||||
#include "python/PythonModule.h"
|
||||
|
||||
@ -30,9 +32,11 @@ QString Application::GetBinPath() {
|
||||
void Application::Init() {
|
||||
Singleton<MeshManager>::Create(this);
|
||||
Singleton<RecourceHelper>::Create(this);
|
||||
Singleton<EntityFactory>::Create(this);
|
||||
Singleton<EntitiesManager>::Create(this);
|
||||
Singleton<WorkSpaceManager>::Create(this);
|
||||
Singleton<NetDriver>::Create(this);
|
||||
Singleton<PresetModelConfigParser>::Create(this);
|
||||
//Singleton<PythonModule>::Create(this);
|
||||
|
||||
connect(&timer_, &QTimer::timeout, this, &Application::OnTimeout);
|
||||
@ -46,8 +50,10 @@ void Application::OnTimeout() {
|
||||
void Application::Uninit() {
|
||||
//Singleton<PythonModule>::Destory();
|
||||
Singleton<NetDriver>::Destory();
|
||||
Singleton<PresetModelConfigParser>::Destory();
|
||||
Singleton<WorkSpaceManager>::Destory();
|
||||
Singleton<EntitiesManager>::Destory();
|
||||
Singleton<EntityFactory>::Destory();
|
||||
Singleton<RecourceHelper>::Destory();
|
||||
Singleton<MeshManager>::Destory();
|
||||
}
|
||||
|
||||
@ -7,6 +7,8 @@
|
||||
#include "common/SpdLogger.h"
|
||||
#include "entities/Entity.h"
|
||||
#include "entities/ComponentFactory.h"
|
||||
#include "entities/EntityFactory.h"
|
||||
#include "entities/EntityRegistration.h"
|
||||
|
||||
#include "xml/tinyxml2.h"
|
||||
|
||||
@ -14,6 +16,7 @@ template<> EntitiesManager* Singleton<EntitiesManager>::instance_ = nullptr;
|
||||
|
||||
EntitiesManager::EntitiesManager(QObject* parent)
|
||||
: QObject(parent) {
|
||||
Initialize();
|
||||
}
|
||||
|
||||
EntitiesManager::~EntitiesManager() {
|
||||
@ -107,9 +110,6 @@ Entity* EntitiesManager::CreateMesh(const QString& mesh) {
|
||||
conponent->SetAttribute("mesh", mesh.toStdString().c_str());
|
||||
conponent->AttachEntity(entity);
|
||||
|
||||
//conponent = ComponentFactory::Create("PathComponent", conponent);
|
||||
//conponent->AttachEntity(entity);
|
||||
|
||||
return entity;
|
||||
}
|
||||
|
||||
@ -148,3 +148,78 @@ void EntitiesManager::RemoveEntity(Entity* entity) {
|
||||
|
||||
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"
|
||||
|
||||
class Entity;
|
||||
class WorkSpace;
|
||||
|
||||
class EntitiesManager : public QObject, public Singleton<EntitiesManager> {
|
||||
Q_OBJECT
|
||||
@ -18,12 +19,26 @@ public:
|
||||
~EntitiesManager();
|
||||
void OnDestory();
|
||||
|
||||
// Initialize entity factory
|
||||
void Initialize();
|
||||
|
||||
bool Contains(const QString& name) const;
|
||||
|
||||
bool Parse(const tinyxml2::XMLElement* element, class WorkSpace* workspce);
|
||||
|
||||
// Legacy methods (for backward compatibility)
|
||||
Entity* Create(const QString& name);
|
||||
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);
|
||||
|
||||
Entity* GetEntity(const QString& uuid);
|
||||
@ -36,5 +51,5 @@ protected:
|
||||
|
||||
private:
|
||||
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();
|
||||
}
|
||||
|
||||
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() {
|
||||
dyt_check(nullptr != g_srs_);
|
||||
return g_srs_;
|
||||
|
||||
@ -35,6 +35,8 @@ public:
|
||||
}
|
||||
|
||||
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();
|
||||
|
||||
|
||||
@ -2082,12 +2082,12 @@
|
||||
<context>
|
||||
<name>OsgWidget</name>
|
||||
<message>
|
||||
<location filename="../viewer/OsgWidget.cpp" line="122"/>
|
||||
<location filename="../viewer/OsgWidget.cpp" line="131"/>
|
||||
<source>warning</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../viewer/OsgWidget.cpp" line="123"/>
|
||||
<location filename="../viewer/OsgWidget.cpp" line="132"/>
|
||||
<source>open dyt file failed</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
@ -2188,26 +2188,6 @@
|
||||
<source>Preset Models</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/ModelBrowser/PresetModelPanel.ui" line="47"/>
|
||||
<source>Ships</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/ModelBrowser/PresetModelPanel.ui" line="87"/>
|
||||
<source>Satellites</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/ModelBrowser/PresetModelPanel.ui" line="127"/>
|
||||
<source>Missiles</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
<message>
|
||||
<location filename="../ui/ModelBrowser/PresetModelPanel.ui" line="167"/>
|
||||
<source>Jammers</source>
|
||||
<translation type="unfinished"></translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>PropertyBrowser</name>
|
||||
|
||||
@ -57,7 +57,7 @@ void PresetModelListWidget::startDrag(Qt::DropActions supportedActions) {
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
// Draw semi-transparent background
|
||||
painter.setBrush(QColor(255, 255, 255, 80)); // White with 70% opacity
|
||||
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);
|
||||
|
||||
@ -132,6 +132,8 @@ void PresetModelListWidget::setModelList(const QVector<ModelInfo>& models) {
|
||||
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);
|
||||
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include <QListWidget>
|
||||
#include <QString>
|
||||
#include "ui/ModelBrowser/ModelInfo.h"
|
||||
|
||||
#include "workspace/ModelInfo.h"
|
||||
|
||||
class PresetModelListWidget : public QListWidget
|
||||
{
|
||||
|
||||
@ -14,11 +14,13 @@
|
||||
#include <QIcon>
|
||||
#include <QMouseEvent>
|
||||
#include <QFontMetrics>
|
||||
#include <QWidget>
|
||||
|
||||
#include "common/RecourceHelper.h"
|
||||
#include "common/SpdLogger.h"
|
||||
#include "ui/DockTitleBar.h"
|
||||
#include "ui/DockWidget.h"
|
||||
#include "workspace/PresetModelConfigParser.h"
|
||||
|
||||
#include "ui_PresetModelPanel.h"
|
||||
|
||||
@ -34,6 +36,7 @@ PresetModelPanel::PresetModelPanel(QWidget *parent)
|
||||
|
||||
PresetModelPanel::~PresetModelPanel()
|
||||
{
|
||||
ClearDynamicUI();
|
||||
delete ui;
|
||||
}
|
||||
|
||||
@ -55,189 +58,99 @@ void PresetModelPanel::InitUI()
|
||||
{
|
||||
// Try to load model data from configuration files
|
||||
QString presetsPath = QString("%1/presets").arg(RecourceHelper::Get().GetResourcesPath());
|
||||
if (configParser_.LoadAllConfigs(presetsPath)) {
|
||||
if (PresetModelConfigParser::Get().LoadAllConfigs(presetsPath)) {
|
||||
// Successfully loaded from configuration files
|
||||
CreateDynamicUI();
|
||||
LoadModelsFromConfig();
|
||||
} else {
|
||||
// Failed to load configuration files, use hardcoded defaults as fallback
|
||||
LOG_WARN("Failed to load preset models from config files, using hardcoded defaults. Error: {}",
|
||||
configParser_.GetLastError().toStdString());
|
||||
LoadDefaultModels();
|
||||
PresetModelConfigParser::Get().GetLastError().toStdString());
|
||||
}
|
||||
}
|
||||
|
||||
void PresetModelPanel::LoadModelsFromConfig()
|
||||
void PresetModelPanel::CreateDynamicUI()
|
||||
{
|
||||
// Load ship models
|
||||
ModelCategory shipCategory = configParser_.GetCategory("Ship");
|
||||
if (!shipCategory.models.isEmpty()) {
|
||||
ui->shipList->setModelType("Ship");
|
||||
ui->shipList->setModelList(shipCategory.models);
|
||||
// Clear any existing dynamic UI
|
||||
ClearDynamicUI();
|
||||
|
||||
// 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
|
||||
ModelCategory satelliteCategory = configParser_.GetCategory("Satellite");
|
||||
if (!satelliteCategory.models.isEmpty()) {
|
||||
ui->satelliteList->setModelType("Satellite");
|
||||
ui->satelliteList->setModelList(satelliteCategory.models);
|
||||
// Create UI for each category
|
||||
for (const QString& categoryName : categoryNames) {
|
||||
ModelCategory category = PresetModelConfigParser::Get().GetCategory(categoryName);
|
||||
|
||||
// Create page widget
|
||||
QWidget* page = new QWidget();
|
||||
page->setObjectName(QString("%1Page").arg(categoryName.toLower()));
|
||||
|
||||
// Create layout for the page
|
||||
QVBoxLayout* layout = new QVBoxLayout(page);
|
||||
layout->setSpacing(0);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
// Create list widget
|
||||
PresetModelListWidget* listWidget = new PresetModelListWidget(page);
|
||||
listWidget->setObjectName(QString("%1List").arg(categoryName.toLower()));
|
||||
listWidget->setDragDropMode(QAbstractItemView::DragOnly);
|
||||
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());
|
||||
}
|
||||
|
||||
// Load missile models
|
||||
ModelCategory missileCategory = configParser_.GetCategory("Missile");
|
||||
if (!missileCategory.models.isEmpty()) {
|
||||
ui->missileList->setModelType("Missile");
|
||||
ui->missileList->setModelList(missileCategory.models);
|
||||
}
|
||||
|
||||
// Load jammer models
|
||||
ModelCategory jammerCategory = configParser_.GetCategory("Jammer");
|
||||
if (!jammerCategory.models.isEmpty()) {
|
||||
ui->jammerList->setModelType("Jammer");
|
||||
ui->jammerList->setModelList(jammerCategory.models);
|
||||
// Set first page as current if available
|
||||
if (ui->PresetModelToolBox->count() > 0) {
|
||||
ui->PresetModelToolBox->setCurrentIndex(0);
|
||||
}
|
||||
}
|
||||
|
||||
void PresetModelPanel::LoadDefaultModels()
|
||||
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()
|
||||
{
|
||||
// Use hardcoded default models as fallback mechanism
|
||||
QVector<ModelInfo> shipModels = {
|
||||
{"destroyer", "Destroyer", "Naval destroyer vessel", "", ":/icons/ship.png", true},
|
||||
{"aircraft_carrier", "Aircraft Carrier", "Large naval vessel", "", ":/icons/ship.png", true},
|
||||
{"frigate", "Frigate", "Fast naval vessel", "", ":/icons/ship.png", true},
|
||||
{"submarine", "Submarine", "Underwater vessel", "", ":/icons/ship.png", true}
|
||||
};
|
||||
ui->shipList->setModelType("Ship");
|
||||
ui->shipList->setModelList(shipModels);
|
||||
// Clear all dynamic UI elements
|
||||
categoryWidgets_.clear();
|
||||
categoryPages_.clear();
|
||||
|
||||
QVector<ModelInfo> satelliteModels = {
|
||||
{"comm_satellite", "Communication Satellite", "Communication satellite", "", ":/icons/satellite.png", true},
|
||||
{"weather_satellite", "Weather Satellite", "Weather monitoring satellite", "", ":/icons/satellite.png", true},
|
||||
{"gps_satellite", "GPS Satellite", "GPS navigation satellite", "", ":/icons/satellite.png", true},
|
||||
{"spy_satellite", "Spy Satellite", "Reconnaissance satellite", "", ":/icons/satellite.png", true}
|
||||
};
|
||||
ui->satelliteList->setModelType("Satellite");
|
||||
ui->satelliteList->setModelList(satelliteModels);
|
||||
|
||||
QVector<ModelInfo> missileModels = {
|
||||
{"cruise_missile", "Cruise Missile", "Long-range cruise missile", "", ":/icons/missile.png", true},
|
||||
{"ballistic_missile", "Ballistic Missile", "Ballistic missile", "", ":/icons/missile.png", true},
|
||||
{"anti_ship_missile", "Anti-Ship Missile", "Anti-ship missile", "", ":/icons/missile.png", true},
|
||||
{"sam_missile", "Surface-to-Air Missile", "Surface-to-air missile", "", ":/icons/missile.png", true}
|
||||
};
|
||||
ui->missileList->setModelType("Missile");
|
||||
ui->missileList->setModelList(missileModels);
|
||||
|
||||
QVector<ModelInfo> jammerModels = {
|
||||
{"electronic_jammer", "Electronic Jammer", "Electronic warfare jammer", "", ":/icons/jammer.png", true},
|
||||
{"comm_jammer", "Communication Jammer", "Communication jammer", "", ":/icons/jammer.png", true},
|
||||
{"radar_jammer", "Radar Jammer", "Radar jamming device", "", ":/icons/jammer.png", true},
|
||||
{"gps_jammer", "GPS Jammer", "GPS jamming device", "", ":/icons/jammer.png", true}
|
||||
};
|
||||
ui->jammerList->setModelType("Jammer");
|
||||
ui->jammerList->setModelList(jammerModels);
|
||||
// Remove all pages from toolbox
|
||||
while (ui->PresetModelToolBox->count() > 0) {
|
||||
QWidget* widget = ui->PresetModelToolBox->widget(0);
|
||||
ui->PresetModelToolBox->removeItem(0);
|
||||
if (widget) {
|
||||
widget->deleteLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// void PresetModelPanel::OnModelItemDoubleClicked(QListWidgetItem* item)
|
||||
// {
|
||||
// if (!item) return;
|
||||
|
||||
// // Get the list widget that contains this item
|
||||
// QListWidget* listWidget = item->listWidget();
|
||||
// if (!listWidget) return;
|
||||
|
||||
// QString modelType = listWidget->property("modelType").toString();
|
||||
|
||||
// // Get model name from stored data
|
||||
// QString modelName = item->data(Qt::UserRole).toString();
|
||||
// if (modelName.isEmpty()) {
|
||||
// modelName = item->text(); // Fallback to display text
|
||||
// }
|
||||
|
||||
// LOG_INFO("Model double-clicked: {} of type {}", qPrintable(modelName), qPrintable(modelType));
|
||||
|
||||
// // Emit signal for model selection
|
||||
// emit ModelDropped(modelType, modelName);
|
||||
// }
|
||||
|
||||
// bool PresetModelPanel::eventFilter(QObject* obj, QEvent* event)
|
||||
// {
|
||||
// QListWidget* listWidget = qobject_cast<QListWidget*>(obj);
|
||||
// if (!listWidget) {
|
||||
// return QWidget::eventFilter(obj, event);
|
||||
// }
|
||||
|
||||
// if (event->type() == QEvent::MouseButtonPress) {
|
||||
// QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
// if (mouseEvent->button() == Qt::LeftButton) {
|
||||
// dragStartPosition_ = mouseEvent->pos();
|
||||
// dragSourceWidget_ = listWidget;
|
||||
// }
|
||||
// } else if (event->type() == QEvent::MouseMove) {
|
||||
// QMouseEvent* mouseEvent = static_cast<QMouseEvent*>(event);
|
||||
// if (!(mouseEvent->buttons() & Qt::LeftButton)) {
|
||||
// return QWidget::eventFilter(obj, event);
|
||||
// }
|
||||
|
||||
// if ((mouseEvent->pos() - dragStartPosition_).manhattanLength() < QApplication::startDragDistance()) {
|
||||
// return QWidget::eventFilter(obj, event);
|
||||
// }
|
||||
|
||||
// QListWidgetItem* item = listWidget->itemAt(dragStartPosition_);
|
||||
// if (!item) {
|
||||
// return QWidget::eventFilter(obj, event);
|
||||
// }
|
||||
|
||||
// QString modelType = listWidget->property("modelType").toString();
|
||||
|
||||
// // Get model name from stored data
|
||||
// QString modelName = item->data(Qt::UserRole).toString();
|
||||
// if (modelName.isEmpty()) {
|
||||
// modelName = item->text(); // Fallback to item text
|
||||
// }
|
||||
|
||||
// // Create mime data
|
||||
// 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);
|
||||
|
||||
// // Set drag pixmap (icon or text)
|
||||
// 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, item->text());
|
||||
// }
|
||||
// drag->setPixmap(pixmap);
|
||||
|
||||
// // Execute drag
|
||||
// Qt::DropAction dropAction = drag->exec(Qt::CopyAction);
|
||||
// Q_UNUSED(dropAction);
|
||||
|
||||
// return true;
|
||||
// }
|
||||
|
||||
// return QWidget::eventFilter(obj, event);
|
||||
// }
|
||||
|
||||
// // DraggableListWidget implementation
|
||||
// DraggableListWidget::DraggableListWidget(const QString& modelType, QWidget* parent)
|
||||
// : QListWidget(parent), modelType_(modelType)
|
||||
// {
|
||||
// setProperty("modelType", modelType);
|
||||
// }
|
||||
|
||||
// void DraggableListWidget::mousePressEvent(QMouseEvent* event)
|
||||
// {
|
||||
// QListWidget::mousePressEvent(event);
|
||||
// }
|
||||
|
||||
// void DraggableListWidget::mouseMoveEvent(QMouseEvent* event)
|
||||
// {
|
||||
// QListWidget::mouseMoveEvent(event);
|
||||
// }
|
||||
@ -14,8 +14,10 @@
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QPainter>
|
||||
#include <QApplication>
|
||||
#include "ModelInfo.h"
|
||||
#include "PresetModelConfigParser.h"
|
||||
#include <QMap>
|
||||
|
||||
#include "workspace/ModelInfo.h"
|
||||
#include "ui/ModelBrowser/PresetModelListWidget.h"
|
||||
|
||||
namespace Ui { class PresetModelPanel; }
|
||||
|
||||
@ -25,11 +27,8 @@ class DockWidget;
|
||||
/**
|
||||
* @brief Preset model panel class
|
||||
*
|
||||
* Provides preset 3D models for users to drag into the 3D scene, including:
|
||||
* - Ships: Destroyer, Aircraft Carrier
|
||||
* - Satellites: Geostationary Satellites
|
||||
* - Missiles: Hypersonic Missiles
|
||||
* - Jammers: Passive Jammers, Active Jammers
|
||||
* Provides preset 3D models for users to drag into the 3D scene.
|
||||
* Dynamically creates UI based on configuration files, supporting any number of categories.
|
||||
*/
|
||||
class PresetModelPanel : public QWidget {
|
||||
Q_OBJECT
|
||||
@ -50,19 +49,27 @@ private:
|
||||
*/
|
||||
void InitUI();
|
||||
|
||||
/**
|
||||
* @brief Create dynamic UI based on configuration
|
||||
*/
|
||||
void CreateDynamicUI();
|
||||
|
||||
/**
|
||||
* @brief Load models from configuration file
|
||||
*/
|
||||
void LoadModelsFromConfig();
|
||||
|
||||
/**
|
||||
* @brief Load default models when config is unavailable
|
||||
* @brief Clear all dynamic UI elements
|
||||
*/
|
||||
void LoadDefaultModels();
|
||||
void ClearDynamicUI();
|
||||
|
||||
private:
|
||||
Ui::PresetModelPanel *ui;
|
||||
PresetModelConfigParser configParser_;
|
||||
|
||||
// Dynamic UI management
|
||||
QMap<QString, PresetModelListWidget*> categoryWidgets_;
|
||||
QMap<QString, QWidget*> categoryPages_;
|
||||
|
||||
// Drag and drop support
|
||||
QPoint dragStartPosition_;
|
||||
|
||||
@ -32,168 +32,8 @@
|
||||
<item>
|
||||
<widget class="QToolBox" name="PresetModelToolBox">
|
||||
<property name="currentIndex">
|
||||
<number>1</number>
|
||||
<number>-1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="shipPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>290</width>
|
||||
<height>470</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>Ships</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="shipLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="PresetModelListWidget" name="shipList">
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragOnly</enum>
|
||||
</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>470</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>Satellites</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="satelliteLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="PresetModelListWidget" 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>470</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>Missiles</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="missileLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="PresetModelListWidget" 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>470</height>
|
||||
</rect>
|
||||
</property>
|
||||
<attribute name="label">
|
||||
<string>Jammers</string>
|
||||
</attribute>
|
||||
<layout class="QVBoxLayout" name="jammerLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="PresetModelListWidget" name="jammerList">
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragOnly</enum>
|
||||
</property>
|
||||
<property name="defaultDropAction">
|
||||
<enum>Qt::CopyAction</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
@ -11,6 +11,8 @@
|
||||
#include <QDebug>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgEarthUtil/EarthManipulator>
|
||||
#include <osgUtil/LineSegmentIntersector>
|
||||
#include <osgEarth/SpatialReference>
|
||||
|
||||
#include <osgViewer/ViewerEventHandlers>
|
||||
#include <osgGA/StateSetManipulator>
|
||||
@ -23,6 +25,13 @@
|
||||
#include "workspace/WorkSpaceManager.h"
|
||||
#include "workspace/WorkSpace.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 ) {
|
||||
view->addEventHandler(new osgViewer::StatsHandler());
|
||||
@ -245,13 +254,66 @@ void OsgWidget::dropEvent(QDropEvent* event) {
|
||||
}
|
||||
|
||||
void OsgWidget::OnPresetModelDropped(const QString& modelType, const QString& modelName, const QPointF& position) {
|
||||
// TODO: 实现预制模型拖拽处理逻辑
|
||||
// 1. 将屏幕坐标转换为世界坐标
|
||||
// 2. 创建对应的Entity和MeshComponent
|
||||
// 3. 添加到场景中
|
||||
|
||||
LOG_INFO("OsgWidget::OnPresetModelDropped - Dropped model type:{} name:{} position:({}, {})", modelType.toStdString(), modelName.toStdString(), position.x(), position.y());
|
||||
|
||||
// 这里暂时只是输出调试信息,后续需要集成实体系统
|
||||
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());
|
||||
|
||||
bool ScreenToWorldCoordinate(int x, int y, double& longitude, double& latitude, double& altitude);
|
||||
|
||||
|
||||
private:
|
||||
QTimer timer_;
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
* @brief Model information structure
|
||||
*
|
||||
* Contains all information for a single preset model, including name, display name,
|
||||
* description, mesh file path, icon path, and enabled status.
|
||||
* description, mesh file path, icon path, enabled status, and entity registration info.
|
||||
*/
|
||||
struct ModelInfo {
|
||||
QString name; ///< Model name (unique identifier)
|
||||
@ -15,21 +15,24 @@ struct ModelInfo {
|
||||
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() : enabled(true) {}
|
||||
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& 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), enabled(enabled) {}
|
||||
meshFile(meshFile), icon(icon), useLabel(true), enabled(enabled) {}
|
||||
};
|
||||
|
||||
/**
|
||||
@ -1,19 +1,21 @@
|
||||
#include "PresetModelConfigParser.h"
|
||||
#include "../../xml/tinyxml2.h"
|
||||
#include "../../common/SpdLogger.h"
|
||||
#include "workspace/PresetModelConfigParser.h"
|
||||
|
||||
#include <QDir>
|
||||
#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();
|
||||
|
||||
QDir dir(configDir);
|
||||
@ -103,8 +105,14 @@ bool PresetModelConfigParser::ParseXmlFile(const QString& filePath)
|
||||
const char* description = modelElement->Attribute("description");
|
||||
const char* meshFile = modelElement->Attribute("meshFile");
|
||||
const char* modelIcon = modelElement->Attribute("icon");
|
||||
const char* label = modelElement->Attribute("label");
|
||||
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) {
|
||||
LOG_WARN("Model element missing name attribute in file: {}", filePath.toStdString());
|
||||
modelElement = modelElement->NextSiblingElement("model");
|
||||
@ -116,6 +124,7 @@ bool PresetModelConfigParser::ParseXmlFile(const QString& filePath)
|
||||
model.description = description ? QString::fromUtf8(description) : "";
|
||||
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;
|
||||
|
||||
category.models.append(model);
|
||||
@ -158,16 +167,18 @@ ModelCategory PresetModelConfigParser::GetCategory(const QString& categoryName)
|
||||
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)) {
|
||||
const ModelCategory& category = m_categories[categoryName];
|
||||
for (const ModelInfo& model : category.models) {
|
||||
if (model.name == modelName) {
|
||||
if (success) *success = true;
|
||||
return model;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (success) *success = false;
|
||||
return ModelInfo();
|
||||
}
|
||||
|
||||
@ -1,16 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include <QObject>
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QMap>
|
||||
|
||||
#include "app/Singleton.h"
|
||||
|
||||
#include "ModelInfo.h"
|
||||
|
||||
class PresetModelConfigParser
|
||||
{
|
||||
class PresetModelConfigParser : public QObject, public Singleton<PresetModelConfigParser> {
|
||||
Q_OBJECT
|
||||
public:
|
||||
PresetModelConfigParser();
|
||||
explicit PresetModelConfigParser(QObject* parent = nullptr);
|
||||
~PresetModelConfigParser();
|
||||
|
||||
void OnDestory() { }
|
||||
|
||||
// Load all preset model configurations
|
||||
bool LoadAllConfigs(const QString& configDir = "workspace/presets");
|
||||
|
||||
@ -27,7 +33,7 @@ public:
|
||||
ModelCategory GetCategory(const QString& categoryName) const;
|
||||
|
||||
// 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
|
||||
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>
|
||||
@ -9,5 +9,5 @@
|
||||
description="Multi-frequency signal jamming equipment"
|
||||
meshFile="models/signal_jammer.ive"
|
||||
icon="icons/signal_jammer_icon.png"
|
||||
enabled="true" />
|
||||
enabled="true"/>
|
||||
</modelCategory>
|
||||
@ -4,10 +4,10 @@
|
||||
description="High-speed combat vessel with powerful anti-submarine and air defense capabilities"
|
||||
meshFile="models/destroyer.ive"
|
||||
icon="icons/destroyer_icon.png"
|
||||
enabled="true" />
|
||||
enabled="true"/>
|
||||
<model name="Aircraft Carrier" displayName="Aircraft Carrier"
|
||||
description="Large aircraft carrier, mobile airfield and command center at sea"
|
||||
meshFile="models/carrier.ive"
|
||||
icon="icons/carrier_icon.png"
|
||||
enabled="true" />
|
||||
enabled="true"/>
|
||||
</modelCategory>
|
||||
Loading…
Reference in New Issue
Block a user