summaryrefslogtreecommitdiff
path: root/share
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@qt.io>2020-03-24 13:51:16 +0200
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2020-03-30 07:59:03 +0000
commit6cf8d7d64572b01c180740c81708d3b02b528a3b (patch)
tree988b162ce99e754334da7397ea7935a845008d4d /share
parent27f6e838ee2965b508bd6422dac76817b4070bdb (diff)
downloadqt-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')
-rw-r--r--share/qtcreator/qml/qmlpuppet/mockfiles/IconRenderer3D.qml92
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/editor3d/generalhelper.cpp2
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.cpp181
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.h56
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/iconrenderer/iconrenderer.pri3
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppet.pri1
-rw-r--r--share/qtcreator/qml/qmlpuppet/qml2puppet/qml2puppetmain.cpp14
-rw-r--r--share/qtcreator/qml/qmlpuppet/qmlpuppet.qrc1
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>