#include "viewer/OsgWidget.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "OsgView.h" #include "OsgViewer.h" #include "common/SpdLogger.h" #include "scene/OEScene.h" #include "ui/MainFrame.h" #include "workspace/WorkSpaceManager.h" #include "workspace/WorkSpace.h" #include "scutcheon/osgScutcheon.h" static void ConfigureView( osgViewer::View* view ) { view->addEventHandler(new osgViewer::StatsHandler()); view->addEventHandler(new osgViewer::WindowSizeHandler()); view->addEventHandler(new osgViewer::ThreadingHandler()); view->addEventHandler(new osgViewer::LODScaleHandler()); view->addEventHandler(new osgGA::StateSetManipulator(view->getCamera()->getOrCreateStateSet())); view->addEventHandler(new osgViewer::RecordCameraPathHandler()); view->addEventHandler(new osgViewer::ScreenCaptureHandler()); } OsgWidget::OsgWidget(QWidget* parent, Qt::WindowFlags f) : QWidget(parent, f) { // setAttribute(Qt::WA_PaintOnScreen, true); // setAttribute(Qt::WA_StaticContents, true); // setAttribute(Qt::WA_NoSystemBackground, true); //setAttribute(Qt::WA_OpaquePaintEvent, true); // setAttribute(Qt::WA_DontCreateNativeAncestors, false); setThreadingModel(osgViewer::ViewerBase::SingleThreaded); setMouseTracking(true); setKeyEventSetsDone(0); // 启用拖拽接收 setAcceptDrops(true); connect( &timer_, SIGNAL(timeout()), this, SLOT(update()) ); timer_.start( 10 ); setMinimumSize(100, 100); LOG_INFO("OsgWidget::OsgWidget"); } OsgWidget::~OsgWidget() { LOG_INFO("OsgWidget::~OsgWidget"); if (nullptr != workspace_) { workspace_->Unlaod(); } if (nullptr != viewUI_) { viewUI_->RemoveUI(activeScene_->GetOrCreateSceneUI()); viewUI_ = nullptr; } } void OsgWidget::Initialize() { LOG_INFO("OsgWidget::Initialize"); QHBoxLayout* layout = new QHBoxLayout(this); activeScene_ = new OEScene; connect(&WorkSpaceManager::Get(), &WorkSpaceManager::WorkSpaceChanged, [this](WorkSpace* workspace) { if (nullptr == workspace) { LOG_WARN("workspace is nullptr"); return; } activeScene_->SetHomeViewpoint(workspace->GetHomeViewpoint(), 3.0); } ); QWidget* widget = addViewWidget( createGraphicsWindow(0,0,100,100)); layout->addWidget(widget); viewUI_ = new OsgViewUI(view_, 100,100); viewUI_->AddUI(activeScene_->GetOrCreateSceneUI()); //osgScutcheonManager::instance()->Init(view_.get(), activeScene_); } void OsgWidget::Uninitialize() { LOG_INFO("OsgWidget::Uninitialize"); if (nullptr != viewUI_) { viewUI_->RemoveUI(activeScene_->GetOrCreateSceneUI()); viewUI_ = nullptr; } if (nullptr != activeScene_) { activeScene_->DetachView(view_); activeScene_ = nullptr; } if (nullptr != view_) { removeView(view_); view_ = nullptr; } } void OsgWidget::LoadDefaultScene() { dyt_check(nullptr != activeScene_); if (nullptr == WorkSpaceManager::Get().LoadDefaultWorkspace(activeScene_)) { LOG_ERROR("load default workspace failed"); //QMessageBox::warning(this, tr("warning"), tr("default workspace failed")); } } void OsgWidget::OnLoadDyt(const QString& path) { LOG_INFO("load dyt path:{}", path.toStdString()); WorkSpace* workSpace = WorkSpaceManager::Get().LoadDyt(path); if (nullptr == workSpace) { QMessageBox::warning(&MainFrame::Get(), tr("warning"), tr("open dyt file failed"), QMessageBox::Ok); return; } const QString& name = workSpace->GetName(); const QString windowTitle = MainFrame::Get().windowTitle(); MainFrame::Get().setWindowTitle(windowTitle + "-" + name); WorkSpaceManager::Get().SetCurrent(workSpace); if (nullptr != workspace_ && workspace_ != workSpace) { workspace_->Unlaod(); } workspace_ = workSpace; emit signalResetWorkSpace(); } osgQt::GraphicsWindowQt* OsgWidget::createGraphicsWindow(int x, int y, int w, int h, const std::string& name, bool windowDecoration) { osg::DisplaySettings* ds = osg::DisplaySettings::instance().get(); osg::ref_ptr traits = new osg::GraphicsContext::Traits; traits->windowName = name; traits->windowDecoration = windowDecoration; traits->x = x; traits->y = y; traits->width = w; traits->height = h; traits->doubleBuffer = true; traits->alpha = ds->getMinimumNumAlphaBits(); traits->stencil = ds->getMinimumNumStencilBits(); traits->sampleBuffers = ds->getMultiSamples(); traits->samples = ds->getNumMultiSamples(); return new osgQt::GraphicsWindowQt(traits.get()); } QWidget* OsgWidget::addViewWidget(osgQt::GraphicsWindowQt* gw) { view_ = new osgViewer::View; addView( view_ ); ConfigureView(view_); osg::Camera* camera = view_->getCamera(); camera->setGraphicsContext( gw ); const osg::GraphicsContext::Traits* traits = gw->getTraits(); camera->setClearColor( osg::Vec4(0.2f, 0.2f, 0.6f, 1.0) ); camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) ); camera->setProjectionMatrixAsPerspective(30.0f, static_cast(traits->width)/static_cast(traits->height), 1.0f, 10000.0f ); activeScene_->AttachView(view_); return gw->getGLWidget(); } void OsgWidget::resizeEvent(QResizeEvent* event) { QWidget::resizeEvent(event); if (nullptr == view_) { return; } qreal devicePixelRatio = screen()->devicePixelRatio(); const QSize& size = event->size(); viewUI_->Resize(size.width() * devicePixelRatio, size.height() * devicePixelRatio); } 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; // 这里暂时只是输出调试信息,后续需要集成实体系统 }