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