Files
qt-creator/share/qtcreator/qml/qmlpuppet/qml2puppet/instances/quick3drenderablenodeinstance.cpp
Miikka Heikkinen 80ea026fd8 QmlDesigner: Refactor library icon generation for imported 3D assets
Previously, icon generation was done at import time, but that was
wasteful, as we now have image cache backed icon generation
available for component library icons. Added the few remaining missing
bits to support icon generation for image cache and disabled the old
icon generation implementation for Qt6.

A few issues in fit algorithm for preview image generation were also
uncovered and fixed to make icons render scene in comparable size to
the old version.

Qt5 imports still generate using old way since component library
3D previews generation doesn't work on Qt5.

Fixes: QDS-6205
Change-Id: I5418fa19d86e81adcd184be023f1dfbc813d0bf5
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Samuel Ghinet <samuel.ghinet@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
2022-05-30 14:16:53 +00:00

221 lines
7.2 KiB
C++

/****************************************************************************
**
** Copyright (C) 2022 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
****************************************************************************/
#include "quick3drenderablenodeinstance.h"
#include "qt5nodeinstanceserver.h"
#include "quickitemnodeinstance.h"
#include "../editor3d/generalhelper.h"
#ifdef QUICK3D_MODULE
#include <private/qquick3dobject_p.h>
#include <private/qquickstategroup_p.h>
#endif
namespace QmlDesigner {
namespace Internal {
const QRectF preview3dBoundingRect(0, 0, 640, 480);
Quick3DRenderableNodeInstance::Quick3DRenderableNodeInstance(QObject *node)
: ObjectNodeInstance(node)
{
}
Quick3DRenderableNodeInstance::~Quick3DRenderableNodeInstance()
{
delete m_dummyRootView;
}
void Quick3DRenderableNodeInstance::initialize(const ObjectNodeInstance::Pointer &objectNodeInstance,
InstanceContainer::NodeFlags flags)
{
#ifdef QUICK3D_MODULE
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
// In case this is the scene root, we need to create a dummy View3D for the scene
// in preview puppets
if (instanceId() == 0 && (!nodeInstanceServer()->isInformationServer())) {
nodeInstanceServer()->quickWindow()->setDefaultAlphaBuffer(true);
nodeInstanceServer()->quickWindow()->setColor(Qt::transparent);
auto helper = new QmlDesigner::Internal::GeneralHelper();
engine()->rootContext()->setContextProperty("_generalHelper", helper);
QQmlComponent component(engine());
component.loadUrl(QUrl("qrc:/qtquickplugin/mockfiles/qt6/ModelNode3DImageView.qml"));
m_dummyRootView = qobject_cast<QQuickItem *>(component.create());
QMetaObject::invokeMethod(m_dummyRootView, m_dummyRootViewCreateFunction,
Q_ARG(QVariant, QVariant::fromValue(object())));
nodeInstanceServer()->setRootItem(m_dummyRootView);
}
#endif // QT_VERSION
#endif // QUICK3D_MODULE
ObjectNodeInstance::initialize(objectNodeInstance, flags);
}
QImage Quick3DRenderableNodeInstance::renderImage() const
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (!isRootNodeInstance() || !m_dummyRootView)
return {};
QSize size = preview3dBoundingRect.size().toSize();
nodeInstanceServer()->quickWindow()->resize(size);
m_dummyRootView->setSize(size);
// Just render the window once to update spatial nodes
nodeInstanceServer()->renderWindow();
QMetaObject::invokeMethod(m_dummyRootView, "fitToViewPort", Qt::DirectConnection);
QRectF renderBoundingRect = m_dummyRootView->boundingRect();
QImage renderImage;
if (QuickItemNodeInstance::unifiedRenderPath()) {
renderImage = nodeInstanceServer()->grabWindow();
renderImage = renderImage.copy(renderBoundingRect.toRect());
} else {
renderImage = nodeInstanceServer()->grabItem(m_dummyRootView);
}
// When grabbing an offscreen window the device pixel ratio is 1
renderImage.setDevicePixelRatio(1);
return renderImage;
#endif
return {};
}
QImage Quick3DRenderableNodeInstance::renderPreviewImage(const QSize &previewImageSize) const
{
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
if (!isRootNodeInstance() || !m_dummyRootView)
return {};
nodeInstanceServer()->quickWindow()->resize(previewImageSize);
m_dummyRootView->setSize(previewImageSize);
// Just render the window once to update spatial nodes
nodeInstanceServer()->renderWindow();
QMetaObject::invokeMethod(m_dummyRootView, "fitToViewPort", Qt::DirectConnection);
QRectF previewItemBoundingRect = boundingRect();
if (previewItemBoundingRect.isValid()) {
const QSize size = previewImageSize;
if (m_dummyRootView->isVisible()) {
QImage image;
image = nodeInstanceServer()->grabWindow();
image = image.copy(previewItemBoundingRect.toRect());
image = image.scaledToWidth(size.width());
return image;
} else {
QImage transparentImage(size, QImage::Format_ARGB32_Premultiplied);
transparentImage.fill(Qt::transparent);
return transparentImage;
}
}
#else
Q_UNUSED(previewImageSize)
#endif
return {};
}
bool Quick3DRenderableNodeInstance::isRenderable() const
{
return m_dummyRootView;
}
bool Quick3DRenderableNodeInstance::hasContent() const
{
return true;
}
QRectF Quick3DRenderableNodeInstance::boundingRect() const
{
//The information server has no m_dummyRootView therefore we use the hardcoded value
if (nodeInstanceServer()->isInformationServer())
return preview3dBoundingRect;
if (m_dummyRootView)
return m_dummyRootView->boundingRect();
return ObjectNodeInstance::boundingRect();
}
QRectF Quick3DRenderableNodeInstance::contentItemBoundingBox() const
{
return boundingRect();
}
QPointF Quick3DRenderableNodeInstance::position() const
{
return QPointF(0, 0);
}
QSizeF Quick3DRenderableNodeInstance::size() const
{
return boundingRect().size();
}
QList<ServerNodeInstance> Quick3DRenderableNodeInstance::stateInstances() const
{
QList<ServerNodeInstance> instanceList;
#ifdef QUICK3D_MODULE
if (auto obj3D = qobject_cast<QQuick3DObject *>(object())) {
const QList<QQuickState *> stateList = QQuick3DObjectPrivate::get(obj3D)->_states()->states();
for (QQuickState *state : stateList) {
if (state && nodeInstanceServer()->hasInstanceForObject(state))
instanceList.append(nodeInstanceServer()->instanceForObject(state));
}
}
#endif
return instanceList;
}
QQuickItem *Quick3DRenderableNodeInstance::contentItem() const
{
return m_dummyRootView;
}
void Quick3DRenderableNodeInstance::setPropertyVariant(const PropertyName &name,
const QVariant &value)
{
if (m_dummyRootView && name == "isLibraryIcon")
QMetaObject::invokeMethod(m_dummyRootView, "setIconMode", Q_ARG(QVariant, value));
ObjectNodeInstance::setPropertyVariant(name, value);
}
Qt5NodeInstanceServer *Quick3DRenderableNodeInstance::qt5NodeInstanceServer() const
{
return qobject_cast<Qt5NodeInstanceServer *>(nodeInstanceServer());
}
} // namespace Internal
} // namespace QmlDesigner