add persets
This commit is contained in:
parent
00b9093481
commit
9df23631c8
File diff suppressed because it is too large
Load Diff
46
src/ui/ModelBrowser/ModelInfo.h
Normal file
46
src/ui/ModelBrowser/ModelInfo.h
Normal file
@ -0,0 +1,46 @@
|
||||
#pragma once
|
||||
|
||||
#include <QString>
|
||||
#include <QVector>
|
||||
|
||||
/**
|
||||
* @brief Model information structure
|
||||
*
|
||||
* Contains all information for a single preset model, including name, display name,
|
||||
* description, mesh file path, icon path, and enabled status.
|
||||
*/
|
||||
struct ModelInfo {
|
||||
QString name; ///< Model name (unique identifier)
|
||||
QString displayName; ///< Display name (for UI display)
|
||||
QString description; ///< Model description
|
||||
QString meshFile; ///< 3D mesh file path
|
||||
QString icon; ///< Icon file path
|
||||
bool enabled; ///< Whether this model is enabled
|
||||
|
||||
/**
|
||||
* @brief Default constructor
|
||||
* Model is enabled by default
|
||||
*/
|
||||
ModelInfo() : 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)
|
||||
: name(name), displayName(displayName), description(description),
|
||||
meshFile(meshFile), icon(icon), enabled(enabled) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Model category structure
|
||||
*
|
||||
* Contains information for a model category, such as ships, satellites, missiles, jammers, etc.
|
||||
* Each category contains multiple specific models.
|
||||
*/
|
||||
struct ModelCategory {
|
||||
QString name; ///< Category name (unique identifier)
|
||||
QString displayName; ///< Display name (for UI display)
|
||||
QString icon; ///< Category icon path
|
||||
QVector<ModelInfo> models; ///< All models in this category
|
||||
};
|
||||
@ -102,6 +102,7 @@ bool PresetModelConfigParser::ParseXmlFile(const QString& filePath)
|
||||
const char* modelDisplayName = modelElement->Attribute("displayName");
|
||||
const char* description = modelElement->Attribute("description");
|
||||
const char* meshFile = modelElement->Attribute("meshFile");
|
||||
const char* modelIcon = modelElement->Attribute("icon");
|
||||
const char* enabled = modelElement->Attribute("enabled");
|
||||
|
||||
if (!modelName) {
|
||||
@ -114,6 +115,7 @@ bool PresetModelConfigParser::ParseXmlFile(const QString& filePath)
|
||||
model.displayName = modelDisplayName ? QString::fromUtf8(modelDisplayName) : model.name;
|
||||
model.description = description ? QString::fromUtf8(description) : "";
|
||||
model.meshFile = meshFile ? QString::fromUtf8(meshFile) : "";
|
||||
model.icon = modelIcon ? QString::fromUtf8(modelIcon) : "";
|
||||
model.enabled = enabled ? (strcmp(enabled, "true") == 0) : true;
|
||||
|
||||
category.models.append(model);
|
||||
|
||||
@ -3,24 +3,7 @@
|
||||
#include <QString>
|
||||
#include <QStringList>
|
||||
#include <QMap>
|
||||
#include <QVector>
|
||||
|
||||
struct ModelInfo {
|
||||
QString name;
|
||||
QString displayName;
|
||||
QString description;
|
||||
QString meshFile;
|
||||
bool enabled;
|
||||
|
||||
ModelInfo() : enabled(true) {}
|
||||
};
|
||||
|
||||
struct ModelCategory {
|
||||
QString name;
|
||||
QString displayName;
|
||||
QString icon;
|
||||
QVector<ModelInfo> models;
|
||||
};
|
||||
#include "ModelInfo.h"
|
||||
|
||||
class PresetModelConfigParser
|
||||
{
|
||||
|
||||
144
src/ui/ModelBrowser/PresetModelListWidget.cpp
Normal file
144
src/ui/ModelBrowser/PresetModelListWidget.cpp
Normal file
@ -0,0 +1,144 @@
|
||||
#include "ui/ModelBrowser/PresetModelListWidget.h"
|
||||
|
||||
#include <QListWidgetItem>
|
||||
#include <QDrag>
|
||||
#include <QMimeData>
|
||||
#include <QPainter>
|
||||
|
||||
#include "common/RecourceHelper.h"
|
||||
#include "common/SpdLogger.h"
|
||||
|
||||
PresetModelListWidget::PresetModelListWidget(QWidget* parent)
|
||||
: QListWidget(parent)
|
||||
{
|
||||
setDragEnabled(true);
|
||||
setDragDropMode(QAbstractItemView::DragOnly);
|
||||
|
||||
// Configure list widget for icon-text vertical layout
|
||||
setViewMode(QListView::IconMode);
|
||||
setResizeMode(QListView::Adjust);
|
||||
setMovement(QListView::Static);
|
||||
setGridSize(QSize(100, 80)); // Width x Height for each item
|
||||
setIconSize(QSize(48, 48)); // Icon size
|
||||
setSpacing(5); // Spacing between items
|
||||
}
|
||||
|
||||
void PresetModelListWidget::startDrag(Qt::DropActions supportedActions) {
|
||||
QListWidgetItem* item = currentItem();
|
||||
if (nullptr == item) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString modelType = property("modelType").toString();
|
||||
QString modelName = item->data(Qt::UserRole).toString();
|
||||
if (modelName.isEmpty()) {
|
||||
modelName = item->text(); // Fallback to item text
|
||||
}
|
||||
|
||||
QMimeData* mimeData = new QMimeData;
|
||||
|
||||
QString dragData = QString("%1|%2").arg(modelType, modelName);
|
||||
mimeData->setData("application/x-preset-model", dragData.toUtf8());
|
||||
|
||||
// Create drag object
|
||||
QDrag* drag = new QDrag(this);
|
||||
drag->setMimeData(mimeData);
|
||||
|
||||
// Create drag pixmap with icon on top and text below
|
||||
const int iconSize = 32;
|
||||
const int textHeight = 20;
|
||||
const int totalWidth = 80;
|
||||
const int totalHeight = iconSize + textHeight + 5; // 5px spacing between icon and text
|
||||
|
||||
QPixmap pixmap(totalWidth, totalHeight);
|
||||
pixmap.fill(Qt::transparent);
|
||||
|
||||
QPainter painter(&pixmap);
|
||||
painter.setRenderHint(QPainter::Antialiasing);
|
||||
|
||||
// Draw semi-transparent background
|
||||
painter.setBrush(QColor(255, 255, 255, 80)); // White with 70% opacity
|
||||
painter.setPen(QPen(QColor(200, 200, 200, 200), 1)); // Light gray border
|
||||
painter.drawRoundedRect(2, 2, totalWidth - 4, totalHeight - 4, 4, 4);
|
||||
|
||||
// Draw icon at the top center
|
||||
QPixmap iconPixmap = item->icon().pixmap(iconSize, iconSize);
|
||||
if (!iconPixmap.isNull()) {
|
||||
int iconX = (totalWidth - iconSize) / 2;
|
||||
painter.drawPixmap(iconX, 0, iconPixmap);
|
||||
} else {
|
||||
// Draw a default placeholder icon
|
||||
int iconX = (totalWidth - iconSize) / 2;
|
||||
painter.setPen(QPen(Qt::gray, 2));
|
||||
painter.setBrush(Qt::lightGray);
|
||||
painter.drawRect(iconX, 0, iconSize, iconSize);
|
||||
painter.setPen(Qt::black);
|
||||
painter.drawText(iconX, 0, iconSize, iconSize, Qt::AlignCenter, "?");
|
||||
}
|
||||
|
||||
// Draw text below the icon
|
||||
painter.setPen(Qt::black);
|
||||
QFont font = painter.font();
|
||||
font.setPointSize(8);
|
||||
painter.setFont(font);
|
||||
|
||||
QRect textRect(0, iconSize + 5, totalWidth, textHeight);
|
||||
painter.drawText(textRect, Qt::AlignCenter | Qt::TextWordWrap, item->text());
|
||||
drag->setPixmap(pixmap);
|
||||
|
||||
// Set hot spot to the center of the icon (not the entire pixmap)
|
||||
int hotSpotX = totalWidth / 2;
|
||||
int hotSpotY = iconSize / 2; // Center of the icon part only
|
||||
drag->setHotSpot(QPoint(hotSpotX, hotSpotY));
|
||||
|
||||
// Execute drag
|
||||
drag->exec(Qt::CopyAction);
|
||||
|
||||
}
|
||||
|
||||
void PresetModelListWidget::setModelType(const QString& modelType) {
|
||||
modelType_ = modelType;
|
||||
setProperty("modelType", modelType_);
|
||||
}
|
||||
|
||||
QString PresetModelListWidget::getModelType() const {
|
||||
return modelType_;
|
||||
}
|
||||
|
||||
void PresetModelListWidget::setModelList(const QVector<ModelInfo>& models) {
|
||||
modelList_ = models;
|
||||
|
||||
clear();
|
||||
|
||||
for (const ModelInfo& modelInfo : models) {
|
||||
if (!modelInfo.enabled) continue; // Skip disabled models
|
||||
|
||||
QListWidgetItem* item = new QListWidgetItem(modelInfo.displayName.isEmpty() ? modelInfo.name : modelInfo.displayName);
|
||||
item->setFlags(item->flags() | Qt::ItemIsDragEnabled);
|
||||
|
||||
// Use icon from ModelInfo if available
|
||||
if (!modelInfo.icon.isEmpty()) {
|
||||
QString presetsPath = QString("%1/%2").arg(RecourceHelper::Get().GetResourcesPath(), modelInfo.icon);
|
||||
QIcon icon(presetsPath);
|
||||
item->setIcon(icon);
|
||||
} else {
|
||||
// Create a default icon if no icon is specified
|
||||
QPixmap pixmap(48, 48);
|
||||
pixmap.fill(Qt::lightGray);
|
||||
QPainter painter(&pixmap);
|
||||
painter.setPen(Qt::black);
|
||||
painter.drawRect(0, 0, 47, 47);
|
||||
painter.drawText(pixmap.rect(), Qt::AlignCenter, "?");
|
||||
item->setIcon(QIcon(pixmap));
|
||||
}
|
||||
|
||||
// Store model name as simple string
|
||||
item->setData(Qt::UserRole, modelInfo.name);
|
||||
|
||||
addItem(item);
|
||||
}
|
||||
}
|
||||
|
||||
QVector<ModelInfo> PresetModelListWidget::getModelList() const {
|
||||
return modelList_;
|
||||
}
|
||||
23
src/ui/ModelBrowser/PresetModelListWidget.h
Normal file
23
src/ui/ModelBrowser/PresetModelListWidget.h
Normal file
@ -0,0 +1,23 @@
|
||||
#include <QListWidget>
|
||||
#include <QString>
|
||||
#include "ui/ModelBrowser/ModelInfo.h"
|
||||
|
||||
class PresetModelListWidget : public QListWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit PresetModelListWidget(QWidget* parent = nullptr);
|
||||
|
||||
void setModelType(const QString& modelType);
|
||||
QString getModelType() const;
|
||||
|
||||
void setModelList(const QVector<ModelInfo>& models);
|
||||
QVector<ModelInfo> getModelList() const;
|
||||
|
||||
protected:
|
||||
void startDrag(Qt::DropActions supportedActions);
|
||||
|
||||
private:
|
||||
QString modelType_;
|
||||
QVector<ModelInfo> modelList_;
|
||||
};
|
||||
@ -8,11 +8,14 @@
|
||||
#include <QPixmap>
|
||||
#include <QPainter>
|
||||
#include <QVBoxLayout>
|
||||
#include <QMetaType>
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QIcon>
|
||||
#include <QMouseEvent>
|
||||
#include <QFontMetrics>
|
||||
|
||||
#include "common/RecourceHelper.h"
|
||||
#include "common/SpdLogger.h"
|
||||
#include "ui/DockTitleBar.h"
|
||||
#include "ui/DockWidget.h"
|
||||
@ -23,6 +26,7 @@
|
||||
PresetModelPanel::PresetModelPanel(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, ui(new Ui::PresetModelPanel)
|
||||
, dragSourceWidget_(nullptr)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
InitUI();
|
||||
@ -50,13 +54,14 @@ void PresetModelPanel::AttachDock(DockWidget* dockWidget)
|
||||
void PresetModelPanel::InitUI()
|
||||
{
|
||||
// Try to load model data from configuration files
|
||||
if (m_configParser.LoadAllConfigs("workspace/presets")) {
|
||||
QString presetsPath = QString("%1/presets").arg(RecourceHelper::Get().GetResourcesPath());
|
||||
if (configParser_.LoadAllConfigs(presetsPath)) {
|
||||
// Successfully loaded from configuration files
|
||||
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: {}",
|
||||
m_configParser.GetLastError().toStdString());
|
||||
configParser_.GetLastError().toStdString());
|
||||
LoadDefaultModels();
|
||||
}
|
||||
}
|
||||
@ -64,161 +69,175 @@ void PresetModelPanel::InitUI()
|
||||
void PresetModelPanel::LoadModelsFromConfig()
|
||||
{
|
||||
// Load ship models
|
||||
QStringList shipModels = m_configParser.GetModelNames("Ship");
|
||||
if (!shipModels.isEmpty()) {
|
||||
PopulateModelList(ui->shipList, "Ship", shipModels);
|
||||
ModelCategory shipCategory = configParser_.GetCategory("Ship");
|
||||
if (!shipCategory.models.isEmpty()) {
|
||||
ui->shipList->setModelType("Ship");
|
||||
ui->shipList->setModelList(shipCategory.models);
|
||||
}
|
||||
|
||||
// Load satellite models
|
||||
QStringList satelliteModels = m_configParser.GetModelNames("Satellite");
|
||||
if (!satelliteModels.isEmpty()) {
|
||||
PopulateModelList(ui->satelliteList, "Satellite", satelliteModels);
|
||||
ModelCategory satelliteCategory = configParser_.GetCategory("Satellite");
|
||||
if (!satelliteCategory.models.isEmpty()) {
|
||||
ui->satelliteList->setModelType("Satellite");
|
||||
ui->satelliteList->setModelList(satelliteCategory.models);
|
||||
}
|
||||
|
||||
// Load missile models
|
||||
QStringList missileModels = m_configParser.GetModelNames("Missile");
|
||||
if (!missileModels.isEmpty()) {
|
||||
PopulateModelList(ui->missileList, "Missile", missileModels);
|
||||
ModelCategory missileCategory = configParser_.GetCategory("Missile");
|
||||
if (!missileCategory.models.isEmpty()) {
|
||||
ui->missileList->setModelType("Missile");
|
||||
ui->missileList->setModelList(missileCategory.models);
|
||||
}
|
||||
|
||||
// Load jammer models
|
||||
QStringList jammerModels = m_configParser.GetModelNames("Jammer");
|
||||
if (!jammerModels.isEmpty()) {
|
||||
PopulateModelList(ui->jammerList, "Jammer", jammerModels);
|
||||
ModelCategory jammerCategory = configParser_.GetCategory("Jammer");
|
||||
if (!jammerCategory.models.isEmpty()) {
|
||||
ui->jammerList->setModelType("Jammer");
|
||||
ui->jammerList->setModelList(jammerCategory.models);
|
||||
}
|
||||
}
|
||||
|
||||
void PresetModelPanel::LoadDefaultModels()
|
||||
{
|
||||
// Use hardcoded default models as fallback mechanism
|
||||
QStringList shipModels = {
|
||||
"Destroyer",
|
||||
"Aircraft Carrier",
|
||||
"Frigate",
|
||||
"Submarine"
|
||||
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}
|
||||
};
|
||||
PopulateModelList(ui->shipList, "Ship", shipModels);
|
||||
ui->shipList->setModelType("Ship");
|
||||
ui->shipList->setModelList(shipModels);
|
||||
|
||||
QStringList satelliteModels = {
|
||||
"Communication Satellite",
|
||||
"Weather Satellite",
|
||||
"GPS Satellite",
|
||||
"Spy Satellite"
|
||||
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}
|
||||
};
|
||||
PopulateModelList(ui->satelliteList, "Satellite", satelliteModels);
|
||||
ui->satelliteList->setModelType("Satellite");
|
||||
ui->satelliteList->setModelList(satelliteModels);
|
||||
|
||||
QStringList missileModels = {
|
||||
"Cruise Missile",
|
||||
"Ballistic Missile",
|
||||
"Anti-Ship Missile",
|
||||
"Surface-to-Air Missile"
|
||||
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}
|
||||
};
|
||||
PopulateModelList(ui->missileList, "Missile", missileModels);
|
||||
ui->missileList->setModelType("Missile");
|
||||
ui->missileList->setModelList(missileModels);
|
||||
|
||||
QStringList jammerModels = {
|
||||
"Electronic Jammer",
|
||||
"Communication Jammer",
|
||||
"Radar Jammer",
|
||||
"GPS Jammer"
|
||||
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}
|
||||
};
|
||||
PopulateModelList(ui->jammerList, "Jammer", jammerModels);
|
||||
ui->jammerList->setModelType("Jammer");
|
||||
ui->jammerList->setModelList(jammerModels);
|
||||
}
|
||||
|
||||
void PresetModelPanel::PopulateModelList(QListWidget* listWidget, const QString& modelType, const QStringList& models)
|
||||
{
|
||||
if (!listWidget) return;
|
||||
// void PresetModelPanel::OnModelItemDoubleClicked(QListWidgetItem* item)
|
||||
// {
|
||||
// if (!item) return;
|
||||
|
||||
// Set the model type as a property for later use
|
||||
listWidget->setProperty("modelType", modelType);
|
||||
// // Get the list widget that contains this item
|
||||
// QListWidget* listWidget = item->listWidget();
|
||||
// if (!listWidget) return;
|
||||
|
||||
for (const QString& model : models) {
|
||||
QListWidgetItem* item = new QListWidgetItem(model);
|
||||
item->setFlags(item->flags() | Qt::ItemIsDragEnabled);
|
||||
// QString modelType = listWidget->property("modelType").toString();
|
||||
|
||||
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"));
|
||||
}
|
||||
// // Get model name from stored data
|
||||
// QString modelName = item->data(Qt::UserRole).toString();
|
||||
// if (modelName.isEmpty()) {
|
||||
// modelName = item->text(); // Fallback to display text
|
||||
// }
|
||||
|
||||
listWidget->addItem(item);
|
||||
}
|
||||
// LOG_INFO("Model double-clicked: {} of type {}", qPrintable(modelName), qPrintable(modelType));
|
||||
|
||||
connect(listWidget, &QListWidget::itemDoubleClicked, this, &PresetModelPanel::OnModelItemDoubleClicked);
|
||||
}
|
||||
// // Emit signal for model selection
|
||||
// emit ModelDropped(modelType, modelName);
|
||||
// }
|
||||
|
||||
void PresetModelPanel::SetupDragAndDrop(QListWidget* listWidget)
|
||||
{
|
||||
listWidget->setDragDropMode(QAbstractItemView::DragOnly);
|
||||
listWidget->setDefaultDropAction(Qt::CopyAction);
|
||||
}
|
||||
// bool PresetModelPanel::eventFilter(QObject* obj, QEvent* event)
|
||||
// {
|
||||
// QListWidget* listWidget = qobject_cast<QListWidget*>(obj);
|
||||
// if (!listWidget) {
|
||||
// return QWidget::eventFilter(obj, event);
|
||||
// }
|
||||
|
||||
void PresetModelPanel::OnModelItemDoubleClicked(QListWidgetItem* item)
|
||||
{
|
||||
if (!item) return;
|
||||
// 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);
|
||||
// }
|
||||
|
||||
QListWidget* listWidget = item->listWidget();
|
||||
if (!listWidget) return;
|
||||
// if ((mouseEvent->pos() - dragStartPosition_).manhattanLength() < QApplication::startDragDistance()) {
|
||||
// return QWidget::eventFilter(obj, event);
|
||||
// }
|
||||
|
||||
QString modelType = listWidget->property("modelType").toString();
|
||||
QString modelName = item->text();
|
||||
// QListWidgetItem* item = listWidget->itemAt(dragStartPosition_);
|
||||
// if (!item) {
|
||||
// return QWidget::eventFilter(obj, event);
|
||||
// }
|
||||
|
||||
emit ModelDropped(modelType, modelName);
|
||||
}
|
||||
// QString modelType = listWidget->property("modelType").toString();
|
||||
|
||||
// DraggableListWidget implementation
|
||||
DraggableListWidget::DraggableListWidget(const QString& modelType, QWidget* parent)
|
||||
: QListWidget(parent), modelType_(modelType)
|
||||
{
|
||||
setProperty("modelType", modelType);
|
||||
}
|
||||
// // Get model name from stored data
|
||||
// QString modelName = item->data(Qt::UserRole).toString();
|
||||
// if (modelName.isEmpty()) {
|
||||
// modelName = item->text(); // Fallback to item text
|
||||
// }
|
||||
|
||||
void DraggableListWidget::mousePressEvent(QMouseEvent* event)
|
||||
{
|
||||
if (event->button() == Qt::LeftButton) {
|
||||
dragStartPosition_ = event->pos();
|
||||
}
|
||||
QListWidget::mousePressEvent(event);
|
||||
}
|
||||
// // Create mime data
|
||||
// QMimeData* mimeData = new QMimeData;
|
||||
// QString dragData = QString("%1|%2").arg(modelType, modelName);
|
||||
// mimeData->setData("application/x-preset-model", dragData.toUtf8());
|
||||
|
||||
void DraggableListWidget::mouseMoveEvent(QMouseEvent* event) {
|
||||
if (!(event->buttons() & Qt::LeftButton)) {
|
||||
return;
|
||||
}
|
||||
// // Create drag object
|
||||
// QDrag* drag = new QDrag(this);
|
||||
// drag->setMimeData(mimeData);
|
||||
|
||||
if ((event->pos() - dragStartPosition_).manhattanLength() < QApplication::startDragDistance()) {
|
||||
return;
|
||||
}
|
||||
// // 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);
|
||||
|
||||
QListWidgetItem* item = itemAt(dragStartPosition_);
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
// // Execute drag
|
||||
// Qt::DropAction dropAction = drag->exec(Qt::CopyAction);
|
||||
// Q_UNUSED(dropAction);
|
||||
|
||||
QDrag* drag = new QDrag(this);
|
||||
QMimeData* mimeData = new QMimeData;
|
||||
// return true;
|
||||
// }
|
||||
|
||||
QString modelType = this->property("modelType").toString();
|
||||
QString modelName = item->text();
|
||||
QString dragData = QString("%1|%2").arg(modelType, modelName);
|
||||
// return QWidget::eventFilter(obj, event);
|
||||
// }
|
||||
|
||||
mimeData->setData("application/x-preset-model", dragData.toUtf8());
|
||||
drag->setMimeData(mimeData);
|
||||
// // DraggableListWidget implementation
|
||||
// DraggableListWidget::DraggableListWidget(const QString& modelType, QWidget* parent)
|
||||
// : QListWidget(parent), modelType_(modelType)
|
||||
// {
|
||||
// setProperty("modelType", modelType);
|
||||
// }
|
||||
|
||||
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);
|
||||
// void DraggableListWidget::mousePressEvent(QMouseEvent* event)
|
||||
// {
|
||||
// QListWidget::mousePressEvent(event);
|
||||
// }
|
||||
|
||||
Qt::DropAction dropAction = drag->exec(Qt::CopyAction);
|
||||
Q_UNUSED(dropAction);
|
||||
}
|
||||
// void DraggableListWidget::mouseMoveEvent(QMouseEvent* event)
|
||||
// {
|
||||
// QListWidget::mouseMoveEvent(event);
|
||||
// }
|
||||
@ -10,14 +10,18 @@
|
||||
#include <QMimeData>
|
||||
#include <QDrag>
|
||||
#include <QMouseEvent>
|
||||
#include <QEvent>
|
||||
#include <QStyledItemDelegate>
|
||||
#include <QPainter>
|
||||
#include <QApplication>
|
||||
#include "ModelInfo.h"
|
||||
#include "PresetModelConfigParser.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
namespace Ui { class PresetModelPanel; }
|
||||
QT_END_NAMESPACE
|
||||
|
||||
class DockWidget;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Preset model panel class
|
||||
*
|
||||
@ -40,42 +44,12 @@ public:
|
||||
*/
|
||||
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 Populate model list with items
|
||||
* @param listWidget List widget to populate
|
||||
* @param modelType Model type
|
||||
* @param models Model name list
|
||||
*/
|
||||
void PopulateModelList(QListWidget* listWidget, const QString& modelType, const QStringList& models);
|
||||
|
||||
/**
|
||||
* @brief Setup drag and drop functionality
|
||||
* @param listWidget List widget to setup drag and drop
|
||||
*/
|
||||
void SetupDragAndDrop(QListWidget* listWidget);
|
||||
|
||||
/**
|
||||
* @brief Load models from configuration file
|
||||
*/
|
||||
@ -88,26 +62,9 @@ private:
|
||||
|
||||
private:
|
||||
Ui::PresetModelPanel *ui;
|
||||
PresetModelConfigParser m_configParser;
|
||||
};
|
||||
PresetModelConfigParser configParser_;
|
||||
|
||||
/**
|
||||
* @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_;
|
||||
// Drag and drop support
|
||||
QPoint dragStartPosition_;
|
||||
QListWidget* dragSourceWidget_;
|
||||
};
|
||||
@ -14,6 +14,9 @@
|
||||
<string>Preset Models</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="mainLayout">
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
@ -26,16 +29,10 @@
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<property name="spacing">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QToolBox" name="toolBox">
|
||||
<property name="objectName">
|
||||
<string>PresetModelToolBox</string>
|
||||
</property>
|
||||
<widget class="QToolBox" name="PresetModelToolBox">
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
<number>1</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="shipPage">
|
||||
<property name="geometry">
|
||||
@ -43,15 +40,30 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>290</width>
|
||||
<height>540</height>
|
||||
<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="QListWidget" name="shipList">
|
||||
<widget class="PresetModelListWidget" name="shipList">
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragOnly</enum>
|
||||
</property>
|
||||
@ -68,15 +80,30 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>290</width>
|
||||
<height>540</height>
|
||||
<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="QListWidget" name="satelliteList">
|
||||
<widget class="PresetModelListWidget" name="satelliteList">
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragOnly</enum>
|
||||
</property>
|
||||
@ -93,15 +120,30 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>290</width>
|
||||
<height>540</height>
|
||||
<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="QListWidget" name="missileList">
|
||||
<widget class="PresetModelListWidget" name="missileList">
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragOnly</enum>
|
||||
</property>
|
||||
@ -118,15 +160,30 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>290</width>
|
||||
<height>540</height>
|
||||
<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="QListWidget" name="jammerList">
|
||||
<widget class="PresetModelListWidget" name="jammerList">
|
||||
<property name="dragDropMode">
|
||||
<enum>QAbstractItemView::DragOnly</enum>
|
||||
</property>
|
||||
@ -141,6 +198,13 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>PresetModelListWidget</class>
|
||||
<extends>QListWidget</extends>
|
||||
<header>ui/ModelBrowser/PresetModelListWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@ -191,10 +191,14 @@ void OsgWidget::paintEvent(QPaintEvent*) {
|
||||
}
|
||||
|
||||
void OsgWidget::dragEnterEvent(QDragEnterEvent* event) {
|
||||
// 检查是否是预制模型拖拽
|
||||
LOG_INFO("OsgWidget::dragEnterEvent - Available formats:{}", event->mimeData()->formats().join(",").toStdString());
|
||||
|
||||
// Check if it's a preset model drag
|
||||
if (event->mimeData()->hasFormat("application/x-preset-model")) {
|
||||
LOG_INFO("OsgWidget::dragEnterEvent - Accept preset model drag");
|
||||
event->acceptProposedAction();
|
||||
} else {
|
||||
LOG_INFO("OsgWidget::dragEnterEvent - Ignore drag, not preset model format");
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
@ -209,28 +213,33 @@ void OsgWidget::dragMoveEvent(QDragMoveEvent* event) {
|
||||
}
|
||||
|
||||
void OsgWidget::dropEvent(QDropEvent* event) {
|
||||
// 检查是否是预制模型拖拽
|
||||
LOG_INFO("OsgWidget::dropEvent - Start processing drop 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")
|
||||
LOG_INFO("OsgWidget::dropEvent - Received model info:{}", modelInfo.toStdString());
|
||||
|
||||
QStringList parts = modelInfo.split("|");
|
||||
if (parts.size() == 2) {
|
||||
QString modelType = parts[0];
|
||||
QString modelName = parts[1];
|
||||
|
||||
// 获取拖拽位置
|
||||
QPointF position = event->posF();
|
||||
|
||||
// 处理预制模型拖拽
|
||||
LOG_INFO("OsgWidget::dropEvent - Parse success, type:{} name:{} position:({},{})", modelType.toStdString(), modelName.toStdString(), position.x(), position.y());
|
||||
|
||||
OnPresetModelDropped(modelType, modelName, position);
|
||||
|
||||
event->acceptProposedAction();
|
||||
LOG_INFO("OsgWidget::dropEvent - Drag processing completed, accepted");
|
||||
} else {
|
||||
LOG_ERROR("OsgWidget::dropEvent - Data format error, expected: type|name, actual:{}", modelInfo.toStdString());
|
||||
event->ignore();
|
||||
}
|
||||
} else {
|
||||
LOG_INFO("OsgWidget::dropEvent - Not preset model format, ignore drag");
|
||||
event->ignore();
|
||||
}
|
||||
}
|
||||
@ -241,7 +250,7 @@ void OsgWidget::OnPresetModelDropped(const QString& modelType, const QString& mo
|
||||
// 2. 创建对应的Entity和MeshComponent
|
||||
// 3. 添加到场景中
|
||||
|
||||
qDebug() << "预制模型拖拽:" << modelType << modelName << "位置:" << position;
|
||||
LOG_INFO("OsgWidget::OnPresetModelDropped - Dropped model type:{} name:{} position:({}, {})", modelType.toStdString(), modelName.toStdString(), position.x(), position.y());
|
||||
|
||||
// 这里暂时只是输出调试信息,后续需要集成实体系统
|
||||
}
|
||||
|
||||
@ -3,21 +3,11 @@
|
||||
<model name="Electronic Jammer" displayName="Electronic Jammer"
|
||||
description="Comprehensive electronic warfare jamming equipment"
|
||||
meshFile="models/electronic_jammer.ive"
|
||||
enabled="true" />
|
||||
<model name="Communication Jammer" displayName="Communication Jammer"
|
||||
description="Specialized communication signal jamming equipment"
|
||||
meshFile="models/comm_jammer.ive"
|
||||
enabled="true" />
|
||||
<model name="Radar Jammer" displayName="Radar Jammer"
|
||||
description="Radar signal jamming and deception equipment"
|
||||
meshFile="models/radar_jammer.ive"
|
||||
enabled="true" />
|
||||
<model name="GPS Jammer" displayName="GPS Jammer"
|
||||
description="Satellite navigation signal jamming equipment"
|
||||
meshFile="models/gps_jammer.ive"
|
||||
icon="icons/electronic_jammer_icon.png"
|
||||
enabled="true" />
|
||||
<model name="Signal Jammer" displayName="Signal Jammer"
|
||||
description="Multi-frequency signal jamming equipment"
|
||||
meshFile="models/signal_jammer.ive"
|
||||
icon="icons/signal_jammer_icon.png"
|
||||
enabled="true" />
|
||||
</modelCategory>
|
||||
@ -1,23 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<modelCategory name="Missile" displayName="Missiles" icon="missile_icon.png">
|
||||
<model name="Cruise Missile" displayName="Cruise Missile"
|
||||
description="Long-range precision strike cruise missile"
|
||||
meshFile="models/cruise_missile.ive"
|
||||
enabled="true" />
|
||||
<model name="Ballistic Missile" displayName="Ballistic Missile"
|
||||
description="Long-range ballistic missile system"
|
||||
meshFile="models/ballistic_missile.ive"
|
||||
enabled="true" />
|
||||
<model name="Anti-Ship Missile" displayName="Anti-Ship Missile"
|
||||
description="Specialized anti-ship attack missile"
|
||||
meshFile="models/antiship_missile.ive"
|
||||
enabled="true" />
|
||||
<model name="Surface-to-Air Missile" displayName="Surface-to-Air Missile"
|
||||
description="Surface-to-air defense missile system"
|
||||
meshFile="models/sam_missile.ive"
|
||||
enabled="true" />
|
||||
<model name="Anti-Tank Missile" displayName="Anti-Tank Missile"
|
||||
description="Anti-armor precision guided missile"
|
||||
meshFile="models/antitank_missile.ive"
|
||||
icon="icons/ballistic_missile_icon.png"
|
||||
enabled="true" />
|
||||
</modelCategory>
|
||||
@ -1,23 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<modelCategory name="Satellite" displayName="Satellites" icon="satellite_icon.png">
|
||||
<model name="Communication Satellite" displayName="Communication Satellite"
|
||||
description="Satellite platform providing global communication services"
|
||||
description="High-capacity communication relay satellite"
|
||||
meshFile="models/comm_satellite.ive"
|
||||
enabled="true" />
|
||||
<model name="Weather Satellite" displayName="Weather Satellite"
|
||||
description="Observation satellite monitoring weather and climate changes"
|
||||
meshFile="models/weather_satellite.ive"
|
||||
enabled="true" />
|
||||
<model name="GPS Satellite" displayName="GPS Satellite"
|
||||
description="Global Positioning System satellite"
|
||||
meshFile="models/gps_satellite.ive"
|
||||
enabled="true" />
|
||||
<model name="Spy Satellite" displayName="Spy Satellite"
|
||||
description="Military reconnaissance and surveillance satellite"
|
||||
meshFile="models/spy_satellite.ive"
|
||||
enabled="true" />
|
||||
<model name="Scientific Satellite" displayName="Scientific Satellite"
|
||||
description="Dedicated satellite for scientific research"
|
||||
meshFile="models/science_satellite.ive"
|
||||
icon="icons/comm_satellite_icon.png"
|
||||
enabled="true" />
|
||||
</modelCategory>
|
||||
@ -3,21 +3,11 @@
|
||||
<model name="Destroyer" displayName="Destroyer"
|
||||
description="High-speed combat vessel with powerful anti-submarine and air defense capabilities"
|
||||
meshFile="models/destroyer.ive"
|
||||
icon="icons/destroyer_icon.png"
|
||||
enabled="true" />
|
||||
<model name="Aircraft Carrier" displayName="Aircraft Carrier"
|
||||
description="Large aircraft carrier, mobile airfield and command center at sea"
|
||||
meshFile="models/carrier.ive"
|
||||
enabled="true" />
|
||||
<model name="Frigate" displayName="Frigate"
|
||||
description="Medium-sized escort vessel, multi-purpose combat platform"
|
||||
meshFile="models/frigate.ive"
|
||||
enabled="true" />
|
||||
<model name="Submarine" displayName="Submarine"
|
||||
description="Underwater combat platform with strong stealth capabilities"
|
||||
meshFile="models/submarine.ive"
|
||||
enabled="true" />
|
||||
<model name="Cruiser" displayName="Cruiser"
|
||||
description="Heavy combat vessel with powerful firepower"
|
||||
meshFile="models/cruiser.ive"
|
||||
icon="icons/carrier_icon.png"
|
||||
enabled="true" />
|
||||
</modelCategory>
|
||||
Loading…
Reference in New Issue
Block a user