diff options
author | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2020-03-24 13:51:16 +0200 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@qt.io> | 2020-03-30 07:59:03 +0000 |
commit | 6cf8d7d64572b01c180740c81708d3b02b528a3b (patch) | |
tree | 988b162ce99e754334da7397ea7935a845008d4d /share | |
parent | 27f6e838ee2965b508bd6422dac76817b4070bdb (diff) | |
download | qt-creator-6cf8d7d64572b01c180740c81708d3b02b528a3b.tar.gz |
QmlDesigner: Create thumbnail for imported 3D assets
Qmlpuppet now allows creating icon from qml source code.
Invoke qmlpuppet with following arguments to create icons:
--rendericon <size> <icon file name> <icon qml source>
E.g. --rendericon 24 ~/my_icon.png ~/my_icon.qml
Two icons are created, one with size x size dimensions and
one with double the dimensions and "@2x" injected into the file name.
3D asset import utilizes this icon rendering to produce item library
icons for imported components.
Change-Id: I92c62c80d961f5f61a0ce1c09b32bbcbf80ea56c
Fixes: QDS-1052
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Diffstat (limited to 'share')
8 files changed, 348 insertions, 2 deletions
diff --git a/share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml b/share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml new file mode 100644 index 0000000000..b16b27406d --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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. +** +****************************************************************************/ + +import QtQuick 2.15 +import QtQuick3D 1.15 + +Item { + id: viewRoot + width: 1024 + height: 1024 + visible: true + + property alias view3D: view3D + property alias camPos: viewCamera.position + + function setSceneToBox() + { + selectionBox.targetNode = view3D.importScene; + } + + function fitAndHideBox() : bool + { + cameraControl.focusObject(selectionBox.model, viewCamera.eulerRotation, true); + if (cameraControl._zoomFactor < 0.1) { + view3D.importScene.scale = view3D.importScene.scale.times(10); + return false; + } + if (cameraControl._zoomFactor > 100) { + view3D.importScene.scale = view3D.importScene.scale.times(0.1); + return false; + } + + selectionBox.visible = false; + return true + } + + View3D { + id: view3D + camera: viewCamera + environment: sceneEnv + + SceneEnvironment { + id: sceneEnv + antialiasingMode: SceneEnvironment.MSAA + antialiasingQuality: SceneEnvironment.VeryHigh + } + + PerspectiveCamera { + id: viewCamera + position: Qt.vector3d(-200, 200, 200) + eulerRotation: Qt.vector3d(-45, -45, 0) + } + + DirectionalLight { + rotation: viewCamera.rotation + } + + SelectionBox { + id: selectionBox + view3D: view3D + geometryName: "SB" + } + + EditCameraController { + id: cameraControl + camera: view3D.camera + view3d: view3D + } + } +} diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp index 8fe5395a6a..f99d219c5c 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp @@ -200,7 +200,7 @@ QVector4D GeneralHelper::focusObjectToCamera(QQuick3DCamera *camera, float defau camera->setPosition(lookAt + newLookVector); - float newZoomFactor = updateZoom ? qBound(.01f, float(maxExtent / 700.), 100.f) : oldZoom; + float newZoomFactor = updateZoom ? qBound(.01f, float(maxExtent / 900.), 100.f) : oldZoom; float cameraZoomFactor = zoomCamera(camera, 0, defaultLookAtDistance, lookAt, newZoomFactor, false); return QVector4D(lookAt, cameraZoomFactor); diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp new file mode 100644 index 0000000000..034a809b16 --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp @@ -0,0 +1,181 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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 "iconrenderer.h" +#include "../editor3d/selectionboxgeometry.h" +#include "../editor3d/generalhelper.h" + +#include <QtQml/qqmlcomponent.h> +#include <QtQml/qqmlengine.h> +#include <QtQml/qqmlproperty.h> +#include <QtQml/qqmlcontext.h> +#include <QtQuick/qquickview.h> +#include <QtQuick/qquickitem.h> +#include <QtGui/qsurfaceformat.h> +#include <QtGui/qimage.h> +#include <QtGui/qguiapplication.h> +#include <QtCore/qtimer.h> +#include <QtCore/qfileinfo.h> +#include <QtCore/qdir.h> + +#ifdef QUICK3D_MODULE +#include <QtQuick3D/private/qquick3dnode_p.h> +#include <QtQuick3D/private/qquick3dviewport_p.h> +#endif + +#include <private/qquickdesignersupportitems_p.h> + +IconRenderer::IconRenderer(int size, const QString &filePath, const QString &source) + : QObject(nullptr) + , m_size(size) + , m_filePath(filePath) + , m_source(source) +{ +} + +void IconRenderer::setupRender() +{ + DesignerSupport::activateDesignerMode(); + DesignerSupport::activateDesignerWindowManager(); + + m_quickView = new QQuickView; + + QSurfaceFormat surfaceFormat = m_quickView->requestedFormat(); + surfaceFormat.setVersion(4, 1); + surfaceFormat.setProfile(QSurfaceFormat::CoreProfile); + m_quickView->setFormat(surfaceFormat); + + DesignerSupport::createOpenGLContext(m_quickView); + + QQmlComponent component(m_quickView->engine()); + component.loadUrl(QUrl::fromLocalFile(m_source)); + QObject *iconItem = component.create(); + + if (iconItem) { + QQuickItem *containerItem = nullptr; + bool is3D = false; +#ifdef QUICK3D_MODULE + if (auto scene = qobject_cast<QQuick3DNode *>(iconItem)) { + qmlRegisterType<QmlDesigner::Internal::SelectionBoxGeometry>("SelectionBoxGeometry", 1, 0, "SelectionBoxGeometry"); + QQmlComponent component(m_quickView->engine()); + component.loadUrl(QUrl("qrc:/qtquickplugin/mockfiles/IconRenderer3D.qml")); + containerItem = qobject_cast<QQuickItem *>(component.create()); + DesignerSupport::setRootItem(m_quickView, containerItem); + + auto helper = new QmlDesigner::Internal::GeneralHelper(); + m_quickView->engine()->rootContext()->setContextProperty("_generalHelper", helper); + + m_contentItem = QQmlProperty::read(containerItem, "view3D").value<QQuickItem *>(); + auto view3D = qobject_cast<QQuick3DViewport *>(m_contentItem); + view3D->setImportScene(scene); + is3D = true; + } else +#endif + if (auto scene = qobject_cast<QQuickItem *>(iconItem)) { + m_contentItem = scene; + containerItem = new QQuickItem(); + containerItem->setSize(QSizeF(1024, 1024)); + DesignerSupport::setRootItem(m_quickView, containerItem); + m_contentItem->setParentItem(containerItem); + } + + if (containerItem && m_contentItem) { + m_contentItem->setSize(QSizeF(m_size, m_size)); + if (m_contentItem->width() > containerItem->width()) + containerItem->setWidth(m_contentItem->width()); + if (m_contentItem->height() > containerItem->height()) + containerItem->setHeight(m_contentItem->height()); + + QTimer::singleShot(0, this, [this, containerItem, is3D]() { + m_designerSupport.refFromEffectItem(m_quickView->rootObject(), false); + QQuickDesignerSupportItems::disableNativeTextRendering(m_quickView->rootObject()); + +#ifdef QUICK3D_MODULE + if (is3D) { + // Render once to make sure scene is up to date before we set up the selection box + render({}); + QMetaObject::invokeMethod(containerItem, "setSceneToBox"); + bool success = false; + int tries = 0; + while (!success && tries < 10) { + ++tries; + render({}); + QMetaObject::invokeMethod(containerItem, "fitAndHideBox", + Q_RETURN_ARG(bool, success)); + } + } +#else + Q_UNUSED(is3D) +#endif + QFileInfo fi(m_filePath); + + // Render regular size image + render(fi.absoluteFilePath()); + + // Render @2x image + m_contentItem->setSize(QSizeF(m_size * 2, m_size * 2)); + + QString saveFile; + saveFile = fi.absolutePath() + '/' + fi.completeBaseName() + "@2x"; + if (!fi.suffix().isEmpty()) + saveFile += '.' + fi.suffix(); + + fi.absoluteDir().mkpath("."); + + render(saveFile); + + // Allow little time for file operations to finish + QTimer::singleShot(1000, qGuiApp, &QGuiApplication::quit); + }); + } else { + qGuiApp->quit(); + } + } else { + qGuiApp->quit(); + } +} + +void IconRenderer::render(const QString &fileName) +{ + std::function<void (QQuickItem *)> updateNodesRecursive; + updateNodesRecursive = [&updateNodesRecursive](QQuickItem *item) { + const auto childItems = item->childItems(); + for (QQuickItem *childItem : childItems) + updateNodesRecursive(childItem); + DesignerSupport::updateDirtyNode(item); + }; + updateNodesRecursive(m_quickView->rootObject()); + + QRect rect(QPoint(), m_contentItem->size().toSize()); + QImage renderImage = m_designerSupport.renderImageForItem(m_quickView->rootObject(), + rect, rect.size()); + if (!fileName.isEmpty()) { + QFileInfo fi(fileName); + if (fi.suffix().isEmpty()) + renderImage.save(fileName, "PNG"); + else + renderImage.save(fileName); + } +} diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h new file mode 100644 index 0000000000..f7bab0f6fc --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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. +** +****************************************************************************/ + +#pragma once + +#include <QtCore/qobject.h> +#include <QtCore/qstring.h> + +#include <designersupportdelegate.h> + +QT_BEGIN_NAMESPACE +class QQuickView; +class QQuickItem; +QT_END_NAMESPACE + +class IconRenderer : public QObject +{ + Q_OBJECT + +public: + explicit IconRenderer(int size, const QString &filePath, const QString &source); + + void setupRender(); + +private: + void render(const QString &fileName); + + int m_size = 16; + QString m_filePath; + QString m_source; + QQuickView *m_quickView = nullptr; + QQuickItem *m_contentItem = nullptr; + DesignerSupport m_designerSupport; +}; diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.pri new file mode 100644 index 0000000000..59d5b12cee --- /dev/null +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.pri @@ -0,0 +1,3 @@ +HEADERS += $$PWD/iconrenderer.h + +SOURCES += $$PWD/iconrenderer.cpp diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri index d0bab57ca1..b801310276 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri @@ -13,6 +13,7 @@ include (../container/container.pri) include (../interfaces/interfaces.pri) include (../types/types.pri) include (../qmlprivategate/qmlprivategate.pri) +include (iconrenderer/iconrenderer.pri) SOURCES += $$PWD/qml2puppetmain.cpp RESOURCES += $$PWD/../qmlpuppet.qrc diff --git a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp index 70f403512f..ee2f5bac59 100644 --- a/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp +++ b/share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp @@ -32,6 +32,7 @@ #include <iostream> #include <qt5nodeinstanceclientproxy.h> +#include "iconrenderer/iconrenderer.h" #include <QQmlComponent> #include <QQmlEngine> @@ -52,11 +53,13 @@ int internalMain(QGuiApplication *application) QCoreApplication::setApplicationVersion("1.0.0"); if (application->arguments().count() < 2 - || (application->arguments().at(1) == "--readcapturedstream" && application->arguments().count() < 3)) { + || (application->arguments().at(1) == "--readcapturedstream" && application->arguments().count() < 3) + || (application->arguments().at(1) == "--rendericon" && application->arguments().count() < 5)) { qDebug() << "Usage:\n"; qDebug() << "--test"; qDebug() << "--version"; qDebug() << "--readcapturedstream <stream file> [control stream file]"; + qDebug() << "--rendericon <icon size> <icon file name> <icon source qml>"; return -1; } @@ -108,7 +111,16 @@ int internalMain(QGuiApplication *application) return -1; } + if (application->arguments().at(1) == "--rendericon") { + int size = application->arguments().at(2).toInt(); + QString iconFileName = application->arguments().at(3); + QString iconSource = application->arguments().at(4); + IconRenderer *iconRenderer = new IconRenderer(size, iconFileName, iconSource); + iconRenderer->setupRender(); + + return application->exec(); + } #ifdef ENABLE_QT_BREAKPAD const QString libexecPath = QCoreApplication::applicationDirPath() + '/' + RELATIVE_LIBEXEC_PATH; diff --git a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc index 0585896fed..81f28c13ed 100644 --- a/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc +++ b/share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc @@ -7,6 +7,7 @@ <file>mockfiles/SwipeView.qml</file> <file>mockfiles/GenericBackend.qml</file> <file>mockfiles/Dialog.qml</file> + <file>mockfiles/IconRenderer3D.qml</file> <file>mockfiles/EditView3D.qml</file> <file>mockfiles/EditCameraController.qml</file> <file>mockfiles/Arrow.qml</file> |