2022-08-19 15:59:36 +02:00
|
|
|
// Copyright (C) 2020 The Qt Company Ltd.
|
|
|
|
|
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0+ OR GPL-3.0 WITH Qt-GPL-exception-1.0
|
2020-02-11 11:33:25 +02:00
|
|
|
|
|
|
|
|
#include "edit3dcanvas.h"
|
|
|
|
|
#include "edit3dview.h"
|
|
|
|
|
#include "edit3dwidget.h"
|
|
|
|
|
|
|
|
|
|
#include "nodehints.h"
|
|
|
|
|
#include "qmlvisualnode.h"
|
|
|
|
|
|
2022-03-18 17:28:28 +02:00
|
|
|
#include <bindingproperty.h>
|
|
|
|
|
#include <nodemetainfo.h>
|
|
|
|
|
#include <nodelistproperty.h>
|
|
|
|
|
#include <variantproperty.h>
|
|
|
|
|
|
2022-02-09 18:49:40 +01:00
|
|
|
#include <utils/qtcassert.h>
|
|
|
|
|
|
|
|
|
|
#include <coreplugin/icore.h>
|
|
|
|
|
|
2020-11-20 12:24:58 +01:00
|
|
|
#include <qmldesignerplugin.h>
|
|
|
|
|
#include <qmldesignerconstants.h>
|
|
|
|
|
|
2022-02-09 18:49:40 +01:00
|
|
|
#include <QFileInfo>
|
2020-02-11 11:33:25 +02:00
|
|
|
#include <QPainter>
|
2022-02-09 18:49:40 +01:00
|
|
|
#include <QQuickWidget>
|
|
|
|
|
#include <QtCore/qmimedata.h>
|
2020-02-11 11:33:25 +02:00
|
|
|
|
|
|
|
|
namespace QmlDesigner {
|
|
|
|
|
|
2022-02-09 18:49:40 +01:00
|
|
|
static QQuickWidget *createBusyIndicator(QWidget *p)
|
|
|
|
|
{
|
|
|
|
|
auto widget = new QQuickWidget(p);
|
|
|
|
|
|
|
|
|
|
const QString source = Core::ICore::resourcePath("qmldesigner/misc/BusyIndicator.qml").toString();
|
|
|
|
|
QTC_ASSERT(QFileInfo::exists(source), return widget);
|
|
|
|
|
widget->setSource(QUrl::fromLocalFile(source));
|
|
|
|
|
widget->setFixedSize(64, 64);
|
|
|
|
|
widget->setAttribute(Qt::WA_AlwaysStackOnTop);
|
|
|
|
|
widget->setClearColor(Qt::transparent);
|
|
|
|
|
widget->setResizeMode(QQuickWidget::SizeRootObjectToView);
|
|
|
|
|
return widget;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-11 11:33:25 +02:00
|
|
|
Edit3DCanvas::Edit3DCanvas(Edit3DWidget *parent)
|
2022-02-09 18:49:40 +01:00
|
|
|
: QWidget(parent)
|
|
|
|
|
, m_parent(parent)
|
|
|
|
|
, m_busyIndicator(createBusyIndicator(this))
|
2020-02-11 11:33:25 +02:00
|
|
|
{
|
|
|
|
|
setMouseTracking(true);
|
|
|
|
|
setAcceptDrops(true);
|
2020-12-10 10:57:37 +01:00
|
|
|
setFocusPolicy(Qt::ClickFocus);
|
2022-02-09 18:49:40 +01:00
|
|
|
m_busyIndicator->show();
|
2020-02-11 11:33:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Edit3DCanvas::updateRenderImage(const QImage &img)
|
|
|
|
|
{
|
|
|
|
|
m_image = img;
|
|
|
|
|
update();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Edit3DCanvas::updateActiveScene(qint32 activeScene)
|
|
|
|
|
{
|
|
|
|
|
m_activeScene = activeScene;
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-09 18:49:40 +01:00
|
|
|
QImage QmlDesigner::Edit3DCanvas::renderImage() const
|
|
|
|
|
{
|
|
|
|
|
return m_image;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Edit3DCanvas::setOpacity(qreal opacity)
|
|
|
|
|
{
|
|
|
|
|
m_opacity = opacity;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
QWidget *Edit3DCanvas::busyIndicator() const
|
|
|
|
|
{
|
|
|
|
|
return m_busyIndicator;
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-11 11:33:25 +02:00
|
|
|
void Edit3DCanvas::mousePressEvent(QMouseEvent *e)
|
|
|
|
|
{
|
2022-08-19 13:04:26 +03:00
|
|
|
if (e->button() == Qt::RightButton && e->modifiers() == Qt::NoModifier)
|
|
|
|
|
m_parent->view()->startContextMenu(e->pos());
|
|
|
|
|
|
2020-02-11 11:33:25 +02:00
|
|
|
m_parent->view()->sendInputEvent(e);
|
|
|
|
|
QWidget::mousePressEvent(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Edit3DCanvas::mouseReleaseEvent(QMouseEvent *e)
|
|
|
|
|
{
|
|
|
|
|
m_parent->view()->sendInputEvent(e);
|
|
|
|
|
QWidget::mouseReleaseEvent(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Edit3DCanvas::mouseDoubleClickEvent(QMouseEvent *e)
|
|
|
|
|
{
|
|
|
|
|
m_parent->view()->sendInputEvent(e);
|
|
|
|
|
QWidget::mouseDoubleClickEvent(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Edit3DCanvas::mouseMoveEvent(QMouseEvent *e)
|
|
|
|
|
{
|
|
|
|
|
m_parent->view()->sendInputEvent(e);
|
|
|
|
|
QWidget::mouseMoveEvent(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Edit3DCanvas::wheelEvent(QWheelEvent *e)
|
|
|
|
|
{
|
|
|
|
|
m_parent->view()->sendInputEvent(e);
|
|
|
|
|
QWidget::wheelEvent(e);
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-10 16:40:35 +02:00
|
|
|
void Edit3DCanvas::keyPressEvent(QKeyEvent *e)
|
|
|
|
|
{
|
|
|
|
|
m_parent->view()->sendInputEvent(e);
|
|
|
|
|
QWidget::keyPressEvent(e);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Edit3DCanvas::keyReleaseEvent(QKeyEvent *e)
|
|
|
|
|
{
|
|
|
|
|
m_parent->view()->sendInputEvent(e);
|
|
|
|
|
QWidget::keyReleaseEvent(e);
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-07 18:04:18 +02:00
|
|
|
void Edit3DCanvas::paintEvent([[maybe_unused]] QPaintEvent *e)
|
2020-02-11 11:33:25 +02:00
|
|
|
{
|
|
|
|
|
QWidget::paintEvent(e);
|
|
|
|
|
|
|
|
|
|
QPainter painter(this);
|
|
|
|
|
|
2022-02-09 18:49:40 +01:00
|
|
|
if (m_opacity < 1.0) {
|
|
|
|
|
painter.fillRect(rect(), Qt::black);
|
|
|
|
|
painter.setOpacity(m_opacity);
|
|
|
|
|
}
|
|
|
|
|
|
2020-10-08 10:50:15 +03:00
|
|
|
painter.drawImage(rect(), m_image, QRect(0, 0, m_image.width(), m_image.height()));
|
2020-02-11 11:33:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Edit3DCanvas::resizeEvent(QResizeEvent *e)
|
|
|
|
|
{
|
2022-02-09 18:49:40 +01:00
|
|
|
positionBusyInidicator();
|
2020-02-11 11:33:25 +02:00
|
|
|
m_parent->view()->edit3DViewResized(e->size());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Edit3DCanvas::dragEnterEvent(QDragEnterEvent *e)
|
|
|
|
|
{
|
2020-10-09 11:14:14 +02:00
|
|
|
// Block all drags if scene root node is locked
|
|
|
|
|
ModelNode node;
|
|
|
|
|
if (m_parent->view()->hasModelNodeForInternalId(m_activeScene))
|
|
|
|
|
node = m_parent->view()->modelNodeForInternalId(m_activeScene);
|
|
|
|
|
|
|
|
|
|
// Allow drop when there is no valid active scene, as the drop goes under the root node of
|
|
|
|
|
// the document in that case.
|
2022-08-31 10:21:21 +02:00
|
|
|
if (!ModelNode::isThisOrAncestorLocked(node)) {
|
2022-05-10 20:31:05 +03:00
|
|
|
QByteArray data = e->mimeData()->data(Constants::MIME_TYPE_ITEM_LIBRARY_INFO);
|
2020-10-09 11:14:14 +02:00
|
|
|
if (!data.isEmpty()) {
|
|
|
|
|
QDataStream stream(data);
|
|
|
|
|
stream >> m_itemLibraryEntry;
|
|
|
|
|
if (NodeHints::fromItemLibraryEntry(m_itemLibraryEntry).canBeDroppedInView3D())
|
|
|
|
|
e->accept();
|
|
|
|
|
}
|
2020-02-11 11:33:25 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Edit3DCanvas::dropEvent(QDropEvent *e)
|
|
|
|
|
{
|
2022-06-07 13:39:25 +03:00
|
|
|
m_parent->view()->executeInTransaction(__FUNCTION__, [&] {
|
|
|
|
|
auto modelNode = QmlVisualNode::createQml3DNode(m_parent->view(), m_itemLibraryEntry, m_activeScene).modelNode();
|
|
|
|
|
QTC_ASSERT(modelNode.isValid(), return);
|
2022-03-18 17:28:28 +02:00
|
|
|
|
2022-06-07 13:39:25 +03:00
|
|
|
e->accept();
|
|
|
|
|
m_parent->view()->setSelectedModelNode(modelNode);
|
2020-03-17 17:08:58 +02:00
|
|
|
|
2022-06-07 13:39:25 +03:00
|
|
|
// if added node is a Model, assign it a material
|
2022-08-24 13:11:33 +02:00
|
|
|
if (modelNode.metaInfo().isQtQuick3DModel())
|
2022-06-07 13:39:25 +03:00
|
|
|
m_parent->view()->assignMaterialTo3dModel(modelNode);
|
|
|
|
|
});
|
2020-02-11 11:33:25 +02:00
|
|
|
}
|
|
|
|
|
|
2020-11-20 12:24:58 +01:00
|
|
|
void Edit3DCanvas::focusOutEvent(QFocusEvent *focusEvent)
|
|
|
|
|
{
|
|
|
|
|
QmlDesignerPlugin::emitUsageStatisticsTime(Constants::EVENT_3DEDITOR_TIME,
|
|
|
|
|
m_usageTimer.elapsed());
|
|
|
|
|
QWidget::focusOutEvent(focusEvent);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Edit3DCanvas::focusInEvent(QFocusEvent *focusEvent)
|
|
|
|
|
{
|
|
|
|
|
m_usageTimer.restart();
|
|
|
|
|
QWidget::focusInEvent(focusEvent);
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-09 18:49:40 +01:00
|
|
|
void Edit3DCanvas::positionBusyInidicator()
|
|
|
|
|
{
|
|
|
|
|
m_busyIndicator->move(width() / 2 - 32, height() / 2 - 32);
|
|
|
|
|
}
|
|
|
|
|
|
2020-02-11 11:33:25 +02:00
|
|
|
}
|