Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qquick3dlightmapbaker.cpp
Go to the documentation of this file.
1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5
8
10
11/*!
12 \class QQuick3DLightmapBaker
13 \inmodule QtQuick3D
14 \internal
15*/
16
17QQuick3DLightmapBaker::QQuick3DLightmapBaker(QQuick3DViewport *view) :
18 QObject(view), m_bakingControl(new BakingControl()), m_view(view)
19{
20
21}
22
23QQuick3DLightmapBaker::~QQuick3DLightmapBaker()
24{
25 if (m_lmWindow) {
26 m_lmWindow->close();
27 delete m_lmWindow;
28 }
29
30 delete m_bakingControl;
31}
32
33/*!
34 \internal
35
36 Triggers a new frame where lightmap baking will take place.
37 Will call \a callback for feedback and handling.
38
39 \note Lightmap baking is a slow blocking operation running on the
40 render thread. The application will be frozen until completed.
41*/
42void QQuick3DLightmapBaker::bake(Callback callback)
43{
44 Q_ASSERT(m_view);
45 m_bakingRequested = true;
46 m_bakingControl->reset();
47 m_callback = callback;
48 updateView();
49}
50
51/*!
52 \internal
53*/
54void QQuick3DLightmapBaker::bake()
55{
56 Q_ASSERT(m_view);
57 if (m_currentlyBaking)
58 return;
59
60 m_bakingRequested = true;
61 m_bakingControl->reset();
62
63 m_windowCancelRequested = false;
64
65 if (!m_lmWindow) {
66 m_lmWindow = new QQuickView();
67 m_lmWindow->setSource(QUrl::fromLocalFile(QStringLiteral(":/qt-project.org/imports/QtQuick3D/LightmapperOutputWindow.qml")));
68 m_lmWindow->show();
69 m_lmWindow->setProperty("width", 400);
70 m_lmWindow->setProperty("height", 400);
71
72 QObject *rootObject = m_lmWindow->rootObject();
73 QObject *cancelButton = rootObject->findChild<QObject *>(QStringLiteral("cancelButton"));
74 if (cancelButton)
75 QObject::connect(cancelButton, SIGNAL(clicked()), this, SLOT(onLmCancelButtonClicked()));
76
77 QObject::connect(m_lmWindow, &QQuickWindow::closing, this, &QQuick3DLightmapBaker::onLmWindowClosing);
78 } else {
79 QObject *rootObject = m_lmWindow->rootObject();
80 QMetaObject::invokeMethod(rootObject, "clearText");
81 }
82
83 m_callback = [this] (const QVariantMap &payload, BakingControl *bakingControl) {
84 if (m_windowCancelRequested && !bakingControl->isCancelled())
85 bakingControl->requestCancel();
86
87 const BakingStatus status = static_cast<BakingStatus>(payload[QStringLiteral("status")].toInt());
88
89 QQuickWindow *window = m_view->window();
90 if (status == BakingStatus::Complete) {
91 m_currentlyBaking = false;
92 QQuickWindowPrivate::get(window)->updatesEnabled = true;
93 } else if (status != BakingStatus::None) {
94 if (status == BakingStatus::Cancelled || status == BakingStatus::Failed) {
95 m_currentlyBaking = false;
96 }
97
98 if (m_lmWindow) {
99 QObject *rootObject = m_lmWindow->rootObject();
100
101 QString msg;
102 if (payload.contains(QStringLiteral("message"))) {
103 msg = payload[QStringLiteral("message")].toString();
104 }
105 if (!msg.isEmpty()) {
106 if (status == BakingStatus::Warning)
107 msg.prepend(QStringLiteral("Warning: "));
108 else if (status == BakingStatus::Error)
109 msg.prepend(QStringLiteral("Error: "));
110
111 }
112
113 QMetaObject::invokeMethod(rootObject, "update", Q_ARG(QVariant, payload));
114 }
115 }
116 };
117
118 m_currentlyBaking = true;
119 updateView();
120}
121
122/*!
123 \internal
124
125 Triggers a new frame where lightmap denoising will take place.
126 Will call \a callback for feedback and handling.
127*/
128void QQuick3DLightmapBaker::denoise(Callback callback)
129{
130 Q_ASSERT(m_view);
131 m_denoisingRequested = true;
132 m_bakingControl->reset();
133 m_callback = callback;
134 updateView();
135}
136
137/*!
138 \internal
139*/
140void QQuick3DLightmapBaker::denoise()
141{
142 Q_ASSERT(m_view);
143 if (m_currentlyBaking)
144 return;
145 m_denoisingRequested = true;
146 m_bakingControl->reset();
147
148 m_windowCancelRequested = false;
149
150 if (!m_lmWindow) {
151 m_lmWindow = new QQuickView();
152 m_lmWindow->setSource(QUrl::fromLocalFile(QStringLiteral(":/qt-project.org/imports/QtQuick3D/LightmapperOutputWindow.qml")));
153 m_lmWindow->show();
154 m_lmWindow->setProperty("width", 400);
155 m_lmWindow->setProperty("height", 400);
156
157 QObject *rootObject = m_lmWindow->rootObject();
158 QObject *cancelButton = rootObject->findChild<QObject *>(QStringLiteral("cancelButton"));
159 if (cancelButton)
160 QObject::connect(cancelButton, SIGNAL(clicked()), this, SLOT(onLmCancelButtonClicked()));
161
162 QObject::connect(m_lmWindow, &QQuickWindow::closing, this, &QQuick3DLightmapBaker::onLmWindowClosing);
163 } else {
164 QObject *rootObject = m_lmWindow->rootObject();
165 QMetaObject::invokeMethod(rootObject, "clearText");
166 }
167
168 m_callback = [this] (const QVariantMap &payload, BakingControl *bakingControl) {
169 if (m_windowCancelRequested && !bakingControl->isCancelled())
170 bakingControl->requestCancel();
171
172 const BakingStatus status = static_cast<BakingStatus>(payload[QStringLiteral("status")].toInt());
173
174 QQuickWindow *window = m_view->window();
175 if (status == BakingStatus::Complete) {
176 QMetaObject::invokeMethod(window, "releaseResources", Qt::QueuedConnection);
177 updateView();
178 m_currentlyBaking = false;
179 QQuickWindowPrivate::get(window)->updatesEnabled = true;
180 } else if (status != BakingStatus::None) {
181 if (status == BakingStatus::Cancelled || status == BakingStatus::Failed)
182 m_currentlyBaking = false;
183
184 if (m_lmWindow) {
185 QObject *rootObject = m_lmWindow->rootObject();
186
187 QString msg;
188 if (payload.contains(QStringLiteral("message"))) {
189 msg = payload[QStringLiteral("message")].toString();
190 }
191 if (!msg.isEmpty()) {
192 if (status == BakingStatus::Warning)
193 msg.prepend(QStringLiteral("Warning: "));
194 else if (status == BakingStatus::Error)
195 msg.prepend(QStringLiteral("Error: "));
196
197 }
198
199 QMetaObject::invokeMethod(rootObject, "update", Q_ARG(QVariant, payload));
200 }
201 }
202 };
203
204 m_currentlyBaking = true;
205 updateView();
206}
207
208void QQuick3DLightmapBaker::updateView()
209{
210 QMetaObject::invokeMethod(m_view, "update", Qt::QueuedConnection);
211}
212
213void QQuick3DLightmapBaker::onLmCancelButtonClicked()
214{
215 if (m_windowCancelRequested)
216 return;
217
218 m_windowCancelRequested = true;
219}
220
221void QQuick3DLightmapBaker::onLmWindowClosing(QQuickCloseEvent *event)
222{
223 Q_UNUSED(event);
224
225 onLmCancelButtonClicked();
226 m_lmWindow->deleteLater();
227 m_lmWindow = nullptr;
228}
229
230void QQuick3DLightmapBaker::BakingControl::reset() {
231 cancelFlag = false;
232}
233
234void QQuick3DLightmapBaker::BakingControl::requestCancel() {
235 cancelFlag = true;
236}
237
238bool QQuick3DLightmapBaker::BakingControl::isCancelled() const {
239 return cancelFlag;
240}
241
242QT_END_NAMESPACE
Combined button and popup list for selecting options.