diff --git a/src/entities/EntitiesManager.cpp b/src/entities/EntitiesManager.cpp
index e8271843..c13abace 100644
--- a/src/entities/EntitiesManager.cpp
+++ b/src/entities/EntitiesManager.cpp
@@ -180,7 +180,7 @@ Entity* EntitiesManager::CreateEntity(const QString& type, WorkSpace* workspace)
return entity;
}
-Entity* EntitiesManager::CreateEntityWithComponents(const QString& type, WorkSpace* workspace) {
+Entity* EntitiesManager::CreateEntityWithComponents(const QString& type, const QString& mesh, bool useLabel, WorkSpace* workspace) {
if (!initialized_) {
Initialize();
}
@@ -189,7 +189,7 @@ Entity* EntitiesManager::CreateEntityWithComponents(const QString& type, WorkSpa
workspace = WorkSpaceManager::Get().GetCurrent();
}
- Entity* entity = EntityFactory::Get().CreateEntityWithComponents(type, workspace);
+ Entity* entity = EntityFactory::Get().CreateEntityWithComponents(type, mesh, useLabel, workspace);
if (entity) {
AddEntity(entity);
if (workspace) {
diff --git a/src/entities/EntitiesManager.h b/src/entities/EntitiesManager.h
index ad2b43d5..5d223127 100644
--- a/src/entities/EntitiesManager.h
+++ b/src/entities/EntitiesManager.h
@@ -32,7 +32,7 @@ public:
// New factory methods
Entity* CreateEntity(const QString& type, WorkSpace* workspace = nullptr);
- Entity* CreateEntityWithComponents(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;
diff --git a/src/entities/EntityFactory.cpp b/src/entities/EntityFactory.cpp
index 3107dfd4..9a46e28a 100644
--- a/src/entities/EntityFactory.cpp
+++ b/src/entities/EntityFactory.cpp
@@ -23,7 +23,7 @@ Entity* EntityFactory::CreateEntity(const QString& type, WorkSpace* workspace) {
return entity;
}
-Entity* EntityFactory::CreateEntityWithComponents(const QString& type, WorkSpace* workspace) {
+Entity* EntityFactory::CreateEntityWithComponents(const QString& type, const QString& mesh, bool useLabel, WorkSpace* workspace) {
Entity* entity = CreateEntity(type, workspace);
if (!entity) {
return nullptr;
@@ -36,15 +36,36 @@ Entity* EntityFactory::CreateEntityWithComponents(const QString& type, WorkSpace
// 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.toStdString().c_str());
+ 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();
diff --git a/src/entities/EntityFactory.h b/src/entities/EntityFactory.h
index 7a40e94f..33e02898 100644
--- a/src/entities/EntityFactory.h
+++ b/src/entities/EntityFactory.h
@@ -66,7 +66,7 @@ public:
Entity* CreateEntity(const QString& type, WorkSpace* workspace);
- Entity* CreateEntityWithComponents(const QString& type, WorkSpace* workspace);
+ Entity* CreateEntityWithComponents(const QString& type, const QString& mesh, bool useLabel, WorkSpace* workspace);
QStringList GetRegisteredTypes() const;
diff --git a/src/translations/Dyt_zh_CN.ts b/src/translations/Dyt_zh_CN.ts
index 9a5fbf47..bb0a14dd 100644
--- a/src/translations/Dyt_zh_CN.ts
+++ b/src/translations/Dyt_zh_CN.ts
@@ -2082,12 +2082,12 @@
OsgWidget
-
+
warning
-
+
open dyt file failed
@@ -2188,26 +2188,6 @@
Preset Models
-
-
- Ships
-
-
-
-
- Satellites
-
-
-
-
- Missiles
-
-
-
-
- Jammers
-
-
PropertyBrowser
diff --git a/src/ui/ModelBrowser/PresetModelListWidget.cpp b/src/ui/ModelBrowser/PresetModelListWidget.cpp
index c0cabf0b..c79632ca 100644
--- a/src/ui/ModelBrowser/PresetModelListWidget.cpp
+++ b/src/ui/ModelBrowser/PresetModelListWidget.cpp
@@ -131,6 +131,8 @@ void PresetModelListWidget::setModelList(const QVector& models) {
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);
diff --git a/src/ui/ModelBrowser/PresetModelListWidget.h b/src/ui/ModelBrowser/PresetModelListWidget.h
index 65c46e78..96d30d32 100644
--- a/src/ui/ModelBrowser/PresetModelListWidget.h
+++ b/src/ui/ModelBrowser/PresetModelListWidget.h
@@ -1,3 +1,5 @@
+#pragma once
+
#include
#include
diff --git a/src/ui/ModelBrowser/PresetModelPanel.cpp b/src/ui/ModelBrowser/PresetModelPanel.cpp
index c9f7cccf..2fd26676 100644
--- a/src/ui/ModelBrowser/PresetModelPanel.cpp
+++ b/src/ui/ModelBrowser/PresetModelPanel.cpp
@@ -14,11 +14,13 @@
#include
#include
#include
+#include
#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;
}
@@ -57,80 +60,97 @@ void PresetModelPanel::InitUI()
QString presetsPath = QString("%1/presets").arg(RecourceHelper::Get().GetResourcesPath());
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: {}",
PresetModelConfigParser::Get().GetLastError().toStdString());
- LoadDefaultModels();
+ }
+}
+
+void PresetModelPanel::CreateDynamicUI()
+{
+ // 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;
+ }
+
+ // 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());
+ }
+
+ // Set first page as current if available
+ if (ui->PresetModelToolBox->count() > 0) {
+ ui->PresetModelToolBox->setCurrentIndex(0);
}
}
void PresetModelPanel::LoadModelsFromConfig() {
- // Load ship models
- ModelCategory shipCategory = PresetModelConfigParser::Get().GetCategory("Ship");
- if (!shipCategory.models.isEmpty()) {
- ui->shipList->setModelType("Ship");
- ui->shipList->setModelList(shipCategory.models);
- }
+ // Load models for each dynamically created category
+ QStringList categoryNames = PresetModelConfigParser::Get().GetCategoryNames();
- // Load satellite models
- ModelCategory satelliteCategory = PresetModelConfigParser::Get().GetCategory("Satellite");
- if (!satelliteCategory.models.isEmpty()) {
- ui->satelliteList->setModelType("Satellite");
- ui->satelliteList->setModelList(satelliteCategory.models);
- }
-
- // Load missile models
- ModelCategory missileCategory = PresetModelConfigParser::Get().GetCategory("Missile");
- if (!missileCategory.models.isEmpty()) {
- ui->missileList->setModelType("Missile");
- ui->missileList->setModelList(missileCategory.models);
- }
-
- // Load jammer models
- ModelCategory jammerCategory = PresetModelConfigParser::Get().GetCategory("Jammer");
- if (!jammerCategory.models.isEmpty()) {
- ui->jammerList->setModelType("Jammer");
- ui->jammerList->setModelList(jammerCategory.models);
+ 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::LoadDefaultModels() {
- // Use hardcoded default models as fallback mechanism
- QVector 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);
+void PresetModelPanel::ClearDynamicUI()
+{
+ // Clear all dynamic UI elements
+ categoryWidgets_.clear();
+ categoryPages_.clear();
- QVector 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 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 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();
+ }
+ }
}
diff --git a/src/ui/ModelBrowser/PresetModelPanel.h b/src/ui/ModelBrowser/PresetModelPanel.h
index 6d220217..bd0e24d5 100644
--- a/src/ui/ModelBrowser/PresetModelPanel.h
+++ b/src/ui/ModelBrowser/PresetModelPanel.h
@@ -14,9 +14,10 @@
#include
#include
#include
+#include
#include "workspace/ModelInfo.h"
-#include "workspace/PresetModelConfigParser.h"
+#include "ui/ModelBrowser/PresetModelListWidget.h"
namespace Ui { class PresetModelPanel; }
@@ -26,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
@@ -51,19 +49,28 @@ 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;
+ // Dynamic UI management
+ QMap categoryWidgets_;
+ QMap categoryPages_;
+
// Drag and drop support
QPoint dragStartPosition_;
QListWidget* dragSourceWidget_;
diff --git a/src/ui/ModelBrowser/PresetModelPanel.ui b/src/ui/ModelBrowser/PresetModelPanel.ui
index 60d64214..8206ddf1 100644
--- a/src/ui/ModelBrowser/PresetModelPanel.ui
+++ b/src/ui/ModelBrowser/PresetModelPanel.ui
@@ -32,168 +32,8 @@
-
- 0
+ -1
-
-
-
- 0
- 0
- 290
- 470
-
-
-
- Ships
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
-
-
-
- QAbstractItemView::DragOnly
-
-
- Qt::CopyAction
-
-
-
-
-
-
-
-
- 0
- 0
- 290
- 470
-
-
-
- Satellites
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
- -
-
-
- QAbstractItemView::DragOnly
-
-
- Qt::CopyAction
-
-
-
-
-
-
-
-
- 0
- 0
- 98
- 73
-
-
-
- Missiles
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
- -
-
-
- QAbstractItemView::DragOnly
-
-
- Qt::CopyAction
-
-
-
-
-
-
-
-
- 0
- 0
- 98
- 73
-
-
-
- Jammers
-
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
-
- 0
-
- -
-
-
- QAbstractItemView::DragOnly
-
-
- Qt::CopyAction
-
-
-
-
-
diff --git a/src/viewer/OsgWidget.cpp b/src/viewer/OsgWidget.cpp
index 0a28707a..43f540c5 100644
--- a/src/viewer/OsgWidget.cpp
+++ b/src/viewer/OsgWidget.cpp
@@ -28,6 +28,7 @@
#include "workspace/PresetModelConfigParser.h"
#include "entities/EntitiesManager.h"
+#include "entities/EntityFactory.h"
#include "entities/ComponentFactory.h"
#include "entities/Entity.h"
#include "entities/Component.h"
@@ -271,7 +272,14 @@ void OsgWidget::OnPresetModelDropped(const QString& modelType, const QString& mo
height = 0.0;
}
- Entity* entity = EntitiesManager::Get().CreateEntityWithComponents(modelType, currentWorkSpace);
+ 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;
diff --git a/src/viewer/OsgWidget.h b/src/viewer/OsgWidget.h
index e8cfc972..bb973ae4 100644
--- a/src/viewer/OsgWidget.h
+++ b/src/viewer/OsgWidget.h
@@ -1,4 +1,4 @@
-#pragma once
+#pragma once
#include
#include
diff --git a/src/workspace/ModelInfo.h b/src/workspace/ModelInfo.h
index e6582e44..bf8ea4b8 100644
--- a/src/workspace/ModelInfo.h
+++ b/src/workspace/ModelInfo.h
@@ -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) {}
};
/**
diff --git a/src/workspace/PresetModelConfigParser.cpp b/src/workspace/PresetModelConfigParser.cpp
index c0fd4428..67f27ac0 100644
--- a/src/workspace/PresetModelConfigParser.cpp
+++ b/src/workspace/PresetModelConfigParser.cpp
@@ -105,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");
@@ -118,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);
diff --git a/workspace/presets/jammers.xml b/workspace/presets/jammers.xml
index 9941ef0c..1e3ca715 100644
--- a/workspace/presets/jammers.xml
+++ b/workspace/presets/jammers.xml
@@ -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"/>
\ No newline at end of file
diff --git a/workspace/presets/ships.xml b/workspace/presets/ships.xml
index 8979bbbb..7acee27e 100644
--- a/workspace/presets/ships.xml
+++ b/workspace/presets/ships.xml
@@ -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"/>
+ enabled="true"/>
\ No newline at end of file