diff --git a/src/translations/Dyt_zh_CN.ts b/src/translations/Dyt_zh_CN.ts
index 10c08122..021ac0f5 100644
--- a/src/translations/Dyt_zh_CN.ts
+++ b/src/translations/Dyt_zh_CN.ts
@@ -573,22 +573,22 @@
AddParamSetting
-
+
ParamSetting
-
+
param
-
+
input param descript
-
+
input value
@@ -641,17 +641,17 @@
-
+
添加
-
+
删除
-
+
应用
@@ -1589,135 +1589,25 @@
-
+
model elements
-
+
+ preset models
+
+
+
+
attribte
-
+
Main View
-
-
- Wave Curve
-
-
-
-
- Speed Curve
-
-
-
-
- 3D Curve
-
-
-
-
- Target number
-
-
-
-
- Signal-to-noise ratio
-
-
-
-
- Azimuth line of sight
-
-
-
-
- Pitch gaze angle
-
-
-
-
- azimuth
-
-
-
-
- Pitch angle
-
-
-
-
- attribute
-
-
-
-
- Doppler
-
-
-
-
- course
-
-
-
-
- Speed
-
-
-
-
- longitude
-
-
-
-
- latitude
-
-
-
-
- distance
-
-
-
-
- velocity
-
-
-
-
- Radial dimensions
-
-
-
-
- Target RCS
-
-
-
-
- Report Table
-
-
-
-
- Signal Indicator Lamp
-
-
-
-
- ParamSetting
-
-
-
-
- bat File
-
-
ModelTreeWidget
@@ -1785,12 +1675,12 @@
OsgWidget
-
+
warning
-
+
open dyt file failed
@@ -1884,6 +1774,29 @@
+
+ PresetModelPanel
+
+
+ Ships
+
+
+
+
+ Satellites
+
+
+
+
+ Missiles
+
+
+
+
+ Jammers
+
+
+
PropertyBrowser
@@ -2850,25 +2763,32 @@
SimuRunMenu
-
+
no workspace
-
+
no commands
-
+
Commands
-
+
unnamed
+
+
+
+
+ MatlabParam
+
+
SimuRunMenuClass
diff --git a/src/ui/MainWindow.cpp b/src/ui/MainWindow.cpp
index c53cb78e..3f9e0526 100644
--- a/src/ui/MainWindow.cpp
+++ b/src/ui/MainWindow.cpp
@@ -5,6 +5,7 @@
#include "PropertyBrowser.h"
#include "ModelBrowser.h"
+#include "PresetModelPanel.h"
#include "DockWidget.h"
#include "viewer/QtOsgViewWidget.h"
@@ -65,6 +66,14 @@ void MainWindow::InitUI() {
modelBrowser_->AttachDock(model);
m_mapDockWidget.insert("ModelBrowser", model);
+ // 创建预制模型面板
+ DockWidget* presetModel = new DockWidget(tr("preset models"), 0);
+ presetModel->SetDockWidgetTitleBar(new DockTitleBar(presetModel));
+ presetModel->setObjectName("Dock.PresetModelPanel");
+ presetModelPanel_ = new PresetModelPanel(0);
+ presetModelPanel_->AttachDock(presetModel);
+ m_mapDockWidget.insert("PresetModelPanel", presetModel);
+
DockWidget* attribte = new DockWidget(tr("attribte"), 0);
attribte->SetDockWidgetTitleBar(new DockTitleBar(attribte));
attribte->setObjectName("Dock.PropertyBrowser");
@@ -88,7 +97,11 @@ void MainWindow::InitUI() {
m_mapDockWidget.insert("MainView", viewDock);
addDockWidget(Qt::LeftDockWidgetArea, model);
+ addDockWidget(Qt::LeftDockWidgetArea, presetModel);
splitDockWidget(model, viewDock, Qt::Horizontal);
+
+ // 将预制模型面板与模型浏览器标签化
+ tabifyDockWidget(model, presetModel);
QString wavePath ="", speedPath = "", rdPath = "", matlabParam="";
if (WorkSpaceManager::Get().GetCurrent())
diff --git a/src/ui/MainWindow.h b/src/ui/MainWindow.h
index 2c1e54f4..7e6e29e3 100644
--- a/src/ui/MainWindow.h
+++ b/src/ui/MainWindow.h
@@ -25,6 +25,9 @@ public:
class ModelBrowser* GetModelBrowser() const {
return modelBrowser_;
}
+ class PresetModelPanel* GetPresetModelPanel() const {
+ return presetModelPanel_;
+ }
class OsgWidget* GetViewWidget() const {
return qtOsgViewWidget_;
}
@@ -58,6 +61,7 @@ private:
Ui::MainWindow* ui;
class ModelBrowser* modelBrowser_{ nullptr };
+ class PresetModelPanel* presetModelPanel_{ nullptr };
class PropertyBrowser* propertyBrowser_{ nullptr };
class QWebEngineView* webEngineView_{ nullptr };
class OsgWidget* qtOsgViewWidget_{ nullptr };
diff --git a/src/ui/PresetModelPanel.cpp b/src/ui/PresetModelPanel.cpp
new file mode 100644
index 00000000..da4ffb61
--- /dev/null
+++ b/src/ui/PresetModelPanel.cpp
@@ -0,0 +1,238 @@
+#include "PresetModelPanel.h"
+#include "DockTitleBar.h"
+#include "DockWidget.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+PresetModelPanel::PresetModelPanel(QWidget *parent)
+ : QWidget(parent)
+ , toolBox_(nullptr)
+ , mainLayout_(nullptr)
+ , shipList_(nullptr)
+ , satelliteList_(nullptr)
+ , missileList_(nullptr)
+ , jammerList_(nullptr)
+{
+ InitUI();
+}
+
+PresetModelPanel::~PresetModelPanel()
+{
+}
+
+void PresetModelPanel::AttachDock(DockWidget* dockWidget)
+{
+ if (nullptr == dockWidget) {
+ qDebug() << __FUNCTION__ << "dockwidget is nullptr";
+ return;
+ }
+
+ dockWidget->SetDockWidgetTitleBar(nullptr);
+ dockWidget->setWidget(this);
+
+ DockTitleBar* dockTitleBar = new DockTitleBar;
+ dockWidget->SetDockWidgetTitleBar(dockTitleBar);
+}
+
+void PresetModelPanel::InitUI()
+{
+ mainLayout_ = new QVBoxLayout(this);
+ mainLayout_->setContentsMargins(5, 5, 5, 5);
+ mainLayout_->setSpacing(5);
+
+ toolBox_ = new QToolBox(this);
+ toolBox_->setObjectName("PresetModelToolBox");
+
+ toolBox_->addItem(CreateShipPage(), QIcon(), tr("Ships"));
+ toolBox_->addItem(CreateSatellitePage(), QIcon(), tr("Satellites"));
+ toolBox_->addItem(CreateMissilePage(), QIcon(), tr("Missiles"));
+ toolBox_->addItem(CreateJammerPage(), QIcon(), tr("Jammers"));
+
+ mainLayout_->addWidget(toolBox_);
+
+ setLayout(mainLayout_);
+}
+
+QWidget* PresetModelPanel::CreateShipPage()
+{
+ QWidget* page = new QWidget;
+ QVBoxLayout* layout = new QVBoxLayout(page);
+
+ QStringList shipModels = {
+ "Destroyer",
+ "Aircraft Carrier",
+ "Frigate",
+ "Submarine"
+ };
+
+ shipList_ = CreateModelList(page, "Ship", shipModels);
+ layout->addWidget(shipList_);
+
+ return page;
+}
+
+QWidget* PresetModelPanel::CreateSatellitePage()
+{
+ QWidget* page = new QWidget;
+ QVBoxLayout* layout = new QVBoxLayout(page);
+
+ QStringList satelliteModels = {
+ "Geostationary Satellite",
+ "Communication Satellite",
+ "Weather Satellite",
+ "Navigation Satellite"
+ };
+
+ satelliteList_ = CreateModelList(page, "Satellite", satelliteModels);
+ layout->addWidget(satelliteList_);
+
+ return page;
+}
+
+QWidget* PresetModelPanel::CreateMissilePage()
+{
+ QWidget* page = new QWidget;
+ QVBoxLayout* layout = new QVBoxLayout(page);
+
+ QStringList missileModels = {
+ "Hypersonic Missile",
+ "Cruise Missile",
+ "Ballistic Missile",
+ "Anti-Ship Missile"
+ };
+
+ missileList_ = CreateModelList(page, "Missile", missileModels);
+ layout->addWidget(missileList_);
+
+ return page;
+}
+
+QWidget* PresetModelPanel::CreateJammerPage()
+{
+ QWidget* page = new QWidget;
+ QVBoxLayout* layout = new QVBoxLayout(page);
+
+ QStringList jammerModels = {
+ "Passive Jammer",
+ "Active Jammer",
+ "Electronic Warfare Pod",
+ "Decoy System"
+ };
+
+ jammerList_ = CreateModelList(page, "Jammer", jammerModels);
+ layout->addWidget(jammerList_);
+
+ return page;
+}
+
+QListWidget* PresetModelPanel::CreateModelList(QWidget* parent, const QString& modelType, const QStringList& models)
+{
+ DraggableListWidget* listWidget = new DraggableListWidget(modelType, parent);
+
+ listWidget->setDragDropMode(QAbstractItemView::DragOnly);
+ listWidget->setDefaultDropAction(Qt::CopyAction);
+
+ 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);
+
+ return listWidget;
+}
+
+void PresetModelPanel::SetupDragAndDrop(QListWidget* listWidget)
+{
+ listWidget->setDragDropMode(QAbstractItemView::DragOnly);
+ listWidget->setDefaultDropAction(Qt::CopyAction);
+}
+
+void PresetModelPanel::OnModelItemDoubleClicked(QListWidgetItem* item)
+{
+ if (!item) return;
+
+ QListWidget* listWidget = item->listWidget();
+ if (!listWidget) return;
+
+ QString modelType = listWidget->property("modelType").toString();
+ QString modelName = item->text();
+
+ 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);
+}
\ No newline at end of file
diff --git a/src/ui/PresetModelPanel.h b/src/ui/PresetModelPanel.h
new file mode 100644
index 00000000..9e9c25ed
--- /dev/null
+++ b/src/ui/PresetModelPanel.h
@@ -0,0 +1,128 @@
+#pragma once
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+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
+ */
+class PresetModelPanel : public QWidget {
+ Q_OBJECT
+
+public:
+ explicit PresetModelPanel(QWidget *parent = nullptr);
+ ~PresetModelPanel() override;
+
+ /**
+ * @brief Attach to dock widget
+ * @param dockWidget Dock widget pointer
+ */
+ 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:
+ /**
+ * @brief Initialize user interface
+ */
+ void InitUI();
+
+ /**
+ * @brief Create ship category page
+ * @return Ship page widget
+ */
+ QWidget* CreateShipPage();
+
+ /**
+ * @brief Create satellite category page
+ * @return Satellite page widget
+ */
+ QWidget* CreateSatellitePage();
+
+ /**
+ * @brief Create missile category page
+ * @return Missile page widget
+ */
+ QWidget* CreateMissilePage();
+
+ /**
+ * @brief Create jammer category page
+ * @return Jammer page widget
+ */
+ QWidget* CreateJammerPage();
+
+ /**
+ * @brief Create model list items
+ * @param parent Parent widget
+ * @param modelType Model type
+ * @param models Model name list
+ * @return Configured QListWidget
+ */
+ QListWidget* CreateModelList(QWidget* parent, const QString& modelType, const QStringList& models);
+
+ /**
+ * @brief Setup drag and drop functionality
+ * @param listWidget List widget to setup drag and drop
+ */
+ void SetupDragAndDrop(QListWidget* listWidget);
+
+private:
+ QToolBox* toolBox_;
+ QVBoxLayout* mainLayout_;
+
+ QListWidget* shipList_;
+ QListWidget* satelliteList_;
+ QListWidget* missileList_;
+ QListWidget* jammerList_;
+};
+
+/**
+ * @brief Custom list widget with drag and drop support
+ */
+class DraggableListWidget : public QListWidget {
+ Q_OBJECT
+
+public:
+ 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_;
+};
\ No newline at end of file
diff --git a/src/viewer/OsgWidget.cpp b/src/viewer/OsgWidget.cpp
index 2e484e25..9d90214a 100644
--- a/src/viewer/OsgWidget.cpp
+++ b/src/viewer/OsgWidget.cpp
@@ -5,6 +5,10 @@
#include
#include
#include
+#include
+#include
+#include
+#include
#include
#include
@@ -44,6 +48,9 @@ OsgWidget::OsgWidget(QWidget* parent, Qt::WindowFlags f)
setMouseTracking(true);
setKeyEventSetsDone(0);
+ // 启用拖拽接收
+ setAcceptDrops(true);
+
connect( &timer_, SIGNAL(timeout()), this, SLOT(update()) );
timer_.start( 10 );
@@ -183,3 +190,59 @@ void OsgWidget::paintEvent(QPaintEvent*) {
frame();
}
+void OsgWidget::dragEnterEvent(QDragEnterEvent* event) {
+ // 检查是否是预制模型拖拽
+ if (event->mimeData()->hasFormat("application/x-preset-model")) {
+ event->acceptProposedAction();
+ } else {
+ event->ignore();
+ }
+}
+
+void OsgWidget::dragMoveEvent(QDragMoveEvent* event) {
+ // 检查是否是预制模型拖拽
+ if (event->mimeData()->hasFormat("application/x-preset-model")) {
+ event->acceptProposedAction();
+ } else {
+ event->ignore();
+ }
+}
+
+void OsgWidget::dropEvent(QDropEvent* event) {
+ // 检查是否是预制模型拖拽
+ if (event->mimeData()->hasFormat("application/x-preset-model")) {
+ QByteArray data = event->mimeData()->data("application/x-preset-model");
+ QString modelInfo = QString::fromUtf8(data);
+
+ // 解析模型信息 (格式: "modelType|modelName")
+ QStringList parts = modelInfo.split("|");
+ if (parts.size() == 2) {
+ QString modelType = parts[0];
+ QString modelName = parts[1];
+
+ // 获取拖拽位置
+ QPointF position = event->posF();
+
+ // 处理预制模型拖拽
+ OnPresetModelDropped(modelType, modelName, position);
+
+ event->acceptProposedAction();
+ } else {
+ event->ignore();
+ }
+ } else {
+ event->ignore();
+ }
+}
+
+void OsgWidget::OnPresetModelDropped(const QString& modelType, const QString& modelName, const QPointF& position) {
+ // TODO: 实现预制模型拖拽处理逻辑
+ // 1. 将屏幕坐标转换为世界坐标
+ // 2. 创建对应的Entity和MeshComponent
+ // 3. 添加到场景中
+
+ qDebug() << "预制模型拖拽:" << modelType << modelName << "位置:" << position;
+
+ // 这里暂时只是输出调试信息,后续需要集成实体系统
+}
+
diff --git a/src/viewer/OsgWidget.h b/src/viewer/OsgWidget.h
index ff64a146..b8664ac4 100644
--- a/src/viewer/OsgWidget.h
+++ b/src/viewer/OsgWidget.h
@@ -29,6 +29,20 @@ protected:
void resizeEvent(QResizeEvent* event) override;
void paintEvent( QPaintEvent* /*event*/ ) override;
+ // 拖拽事件处理
+ void dragEnterEvent(QDragEnterEvent* event) override;
+ void dragMoveEvent(QDragMoveEvent* event) override;
+ void dropEvent(QDropEvent* event) override;
+
+public slots:
+ /**
+ * @brief 处理预制模型拖拽
+ * @param modelType 模型类型
+ * @param modelName 模型名称
+ * @param position 屏幕位置(可选)
+ */
+ void OnPresetModelDropped(const QString& modelType, const QString& modelName, const QPointF& position = QPointF());
+
private:
QTimer timer_;