summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@qt.io>2016-12-14 17:55:21 +0200
committerMiikka Heikkinen <miikka.heikkinen@qt.io>2016-12-16 09:33:03 +0000
commit00b01d064c981e872a1a9eadfc43e5a83e92220a (patch)
tree436ab04a8a437efc97529726d24bbcd4b89dc5e4
parent2b9ddcd68e2b2813a08aafef6e89210997def07f (diff)
Change editor save format from QML to JSON + QGLTF when supported
Change-Id: If2bf099b5e77b3350ee5670e968cfa9a96d563b2 Reviewed-by: Antti Määttä <antti.maatta@qt.io>
-rw-r--r--editorlib/editorlib.pro7
-rw-r--r--editorlib/qml/EditorContent.qml10
-rw-r--r--editorlib/src/editorscene.cpp39
-rw-r--r--editorlib/src/editorscene.h11
-rw-r--r--editorlib/src/editorscenesaver.cpp244
-rw-r--r--editorlib/src/editorscenesaver.h57
-rw-r--r--editorlib/src/editorutils.cpp16
-rw-r--r--editorlib/src/editorutils.h1
8 files changed, 376 insertions, 9 deletions
diff --git a/editorlib/editorlib.pro b/editorlib/editorlib.pro
index d47c2b8..303f7a7 100644
--- a/editorlib/editorlib.pro
+++ b/editorlib/editorlib.pro
@@ -13,7 +13,6 @@ SOURCES += src/qt3dsceneeditor.cpp \
src/editorsceneitemmodel.cpp \
src/editorsceneitem.cpp \
src/editorsceneitemcomponentsmodel.cpp \
- src/editorsceneparser.cpp \
src/components/transformcomponentproxyitem.cpp \
src/components/editorsceneitemtransformcomponentsmodel.cpp \
src/components/materialcomponentproxyitem.cpp \
@@ -60,7 +59,6 @@ HEADERS += \
src/editorsceneitemmodel.h \
src/editorsceneitem.h \
src/editorsceneitemcomponentsmodel.h \
- src/editorsceneparser.h \
src/components/transformcomponentproxyitem.h \
src/components/editorsceneitemtransformcomponentsmodel.h \
src/components/materialcomponentproxyitem.h \
@@ -102,4 +100,9 @@ SOURCES = qml/*.qml \
greaterThan(QT_MAJOR_VERSION, 4):greaterThan(QT_MINOR_VERSION, 8) {
DEFINES += GLTF_EXPORTER_AVAILABLE
+ SOURCES += src/editorscenesaver.cpp
+ HEADERS += src/editorscenesaver.h
+} else {
+ SOURCES += src/editorsceneparser.cpp
+ HEADERS += src/editorsceneparser.h
}
diff --git a/editorlib/qml/EditorContent.qml b/editorlib/qml/EditorContent.qml
index 3cde3ef..8eb8726 100644
--- a/editorlib/qml/EditorContent.qml
+++ b/editorlib/qml/EditorContent.qml
@@ -52,6 +52,12 @@ Item {
else
saveFileUrl.toString()
}
+ property string saveFilterString: {
+ if (editorScene.canExportGltf)
+ qsTr("Qt3D Scenes (*.qt3dscene)") + editorScene.emptyString;
+ else
+ qsTr("Qt3D Scenes (*.qt3d.qrc)") + editorScene.emptyString;
+ }
property int currentHelperPlane: 1
property alias selectedEntityType: generalPropertyView.entityType
@@ -389,7 +395,7 @@ Item {
selectMultiple: false
selectExisting: true
title: qsTr("Load Scene") + editorScene.emptyString
- nameFilters: [qsTr("Qt3D Scenes (*.qt3d.qrc)") + editorScene.emptyString]
+ nameFilters: [editorContent.saveFilterString]
onAccepted: {
editorContent.loadScene(fileUrl, folder)
}
@@ -401,7 +407,7 @@ Item {
selectExisting: false
property bool exiting: false
title: qsTr("Save Scene") + editorScene.emptyString
- nameFilters: [qsTr("Qt3D Scenes (*.qt3d.qrc)") + editorScene.emptyString]
+ nameFilters: [editorContent.saveFilterString]
onAccepted: {
editorScene.saveScene(fileUrl)
editorContent.saveFolder = folder
diff --git a/editorlib/src/editorscene.cpp b/editorlib/src/editorscene.cpp
index 069f4b4..a3bbce2 100644
--- a/editorlib/src/editorscene.cpp
+++ b/editorlib/src/editorscene.cpp
@@ -28,7 +28,6 @@
#include "editorscene.h"
#include "editorutils.h"
#include "editorsceneitem.h"
-#include "editorsceneparser.h"
#include "editorsceneitemcomponentsmodel.h"
#include "editorviewportitem.h"
#include "ontopeffect.h"
@@ -70,6 +69,9 @@
#ifdef GLTF_EXPORTER_AVAILABLE
#include <Qt3DRender/private/qsceneexportfactory_p.h>
#include <Qt3DRender/private/qsceneexporter_p.h>
+#include "editorscenesaver.h"
+#else
+#include "editorsceneparser.h"
#endif
#include <cfloat>
@@ -85,7 +87,6 @@ static const QString cameraVisibleEntityName = QStringLiteral("__internal camera
static const QString lightVisibleEntityName = QStringLiteral("__internal light visible entity");
static const QString sceneLoaderSubEntityName = QStringLiteral("__internal sceneloader sub entity");
static const QString helperArrowName = QStringLiteral("__internal helper arrow");
-static const QString autoSavePostfix = QStringLiteral(".autosave");
static const QVector3D defaultLightDirection(0.0f, -1.0f, 0.0f);
static const float freeViewCameraNearPlane = 0.1f;
static const float freeViewCameraFarPlane = 10000.0f;
@@ -97,6 +98,9 @@ static const QColor helperPlaneColor("#585a5c");
static const QColor helperArrowColorX("red");
static const QColor helperArrowColorY("green");
static const QColor helperArrowColorZ("blue");
+#ifndef GLTF_EXPORTER_AVAILABLE
+static const QString autoSavePostfix = QStringLiteral(".autosave");
+#endif
EditorScene::EditorScene(QObject *parent)
: QObject(parent)
@@ -104,7 +108,6 @@ EditorScene::EditorScene(QObject *parent)
, m_componentCache(nullptr)
, m_rootItem(nullptr)
, m_sceneModel(new EditorSceneItemModel(this))
- , m_sceneParser(new EditorSceneParser(this))
, m_renderSettings(nullptr)
, m_renderer(nullptr)
, m_sceneEntity(nullptr)
@@ -142,6 +145,9 @@ EditorScene::EditorScene(QObject *parent)
, m_groupBoxUpdatePending(false)
#ifdef GLTF_EXPORTER_AVAILABLE
, m_gltfExporter(nullptr)
+ , m_sceneSaver(new EditorSceneSaver(this))
+#else
+ , m_sceneParser(new EditorSceneParser(this))
#endif
{
setLanguage(language());
@@ -300,6 +306,16 @@ void EditorScene::resetScene()
bool EditorScene::saveScene(const QUrl &fileUrl, bool autosave)
{
+ if (!fileUrl.isValid())
+ return false;
+
+#ifdef GLTF_EXPORTER_AVAILABLE
+ QString camera;
+ if (m_activeSceneCameraIndex >= 0 && m_activeSceneCameraIndex < m_sceneCameras.size())
+ camera = m_sceneCameras.at(m_activeSceneCameraIndex).cameraEntity->objectName();
+
+ bool retval = m_sceneSaver->saveScene(m_sceneEntity, camera, fileUrl.toLocalFile(), autosave);
+#else
QUrl url = fileUrl;
if (!url.toString().endsWith(QStringLiteral(".qt3d.qrc"))) {
QString filePath = url.toString() + QStringLiteral(".qt3d.qrc");
@@ -310,6 +326,8 @@ bool EditorScene::saveScene(const QUrl &fileUrl, bool autosave)
if (m_activeSceneCameraIndex >= 0 && m_activeSceneCameraIndex < m_sceneCameras.size())
camera = m_sceneCameras.at(m_activeSceneCameraIndex).cameraEntity;
bool retval = m_sceneParser->exportQmlScene(m_sceneEntity, url, camera, autosave);
+#endif
+
if (retval)
m_undoHandler->setClean();
else
@@ -319,8 +337,15 @@ bool EditorScene::saveScene(const QUrl &fileUrl, bool autosave)
bool EditorScene::loadScene(const QUrl &fileUrl)
{
+ if (!fileUrl.isValid())
+ return false;
+
Qt3DCore::QEntity *camera = nullptr;
+#ifdef GLTF_EXPORTER_AVAILABLE
+ Qt3DCore::QEntity *newSceneEntity = m_sceneSaver->loadScene(fileUrl.toLocalFile(), camera);
+#else
Qt3DCore::QEntity *newSceneEntity = m_sceneParser->importQmlScene(fileUrl, camera);
+#endif
if (newSceneEntity) {
clearSingleSelection();
@@ -347,6 +372,12 @@ bool EditorScene::loadScene(const QUrl &fileUrl)
void EditorScene::deleteScene(const QUrl &fileUrl, bool autosave)
{
+ if (!fileUrl.isValid())
+ return;
+
+#ifdef GLTF_EXPORTER_AVAILABLE
+ m_sceneSaver->deleteSavedScene(fileUrl.toLocalFile(), autosave);
+#else
// Remove qml file
QString fileName = fileUrl.toLocalFile();
if (autosave)
@@ -362,6 +393,7 @@ void EditorScene::deleteScene(const QUrl &fileUrl, bool autosave)
resourceDirName.append(autoSavePostfix);
QDir dir = QDir(resourceDirName);
dir.removeRecursively();
+#endif
}
QString EditorScene::cameraName(int index) const
@@ -2207,6 +2239,7 @@ bool EditorScene::exportGltfScene(const QUrl &folder, const QString &exportName,
#else
Q_UNUSED(folder)
Q_UNUSED(exportName)
+ Q_UNUSED(exportSelected)
Q_UNUSED(options)
#endif
return false;
diff --git a/editorlib/src/editorscene.h b/editorlib/src/editorscene.h
index 19322c0..0c1cff7 100644
--- a/editorlib/src/editorscene.h
+++ b/editorlib/src/editorscene.h
@@ -64,11 +64,16 @@ namespace Qt3DExtras {
class EditorSceneItemModel;
class EditorSceneItem;
-class EditorSceneParser;
class EditorViewportItem;
class UndoHandler;
class QMouseEvent;
+#ifdef GLTF_EXPORTER_AVAILABLE
+class EditorSceneSaver;
+#else
+class EditorSceneParser;
+#endif
+
class EditorScene : public QObject
{
Q_OBJECT
@@ -438,7 +443,6 @@ private:
QMap<Qt3DCore::QNodeId, EditorSceneItem *> m_sceneItems;
- EditorSceneParser *m_sceneParser;
Qt3DRender::QRenderSettings *m_renderSettings;
Qt3DExtras::QForwardRenderer *m_renderer;
Qt3DCore::QEntity *m_sceneEntity;
@@ -529,6 +533,9 @@ private:
bool m_groupBoxUpdatePending;
#ifdef GLTF_EXPORTER_AVAILABLE
Qt3DRender::QSceneExporter *m_gltfExporter;
+ EditorSceneSaver *m_sceneSaver;
+#else
+ EditorSceneParser *m_sceneParser;
#endif
};
diff --git a/editorlib/src/editorscenesaver.cpp b/editorlib/src/editorscenesaver.cpp
new file mode 100644
index 0000000..2e128f6
--- /dev/null
+++ b/editorlib/src/editorscenesaver.cpp
@@ -0,0 +1,244 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D Editor of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include "editorscenesaver.h"
+#include "editorutils.h"
+
+#include <Qt3DCore/qentity.h>
+#include <private/qsceneexportfactory_p.h>
+#include <private/qsceneexporter_p.h>
+#include <private/qsceneimportfactory_p.h>
+#include <private/qsceneimporter_p.h>
+
+#include <QtCore/qfile.h>
+#include <QtCore/qdir.h>
+#include <QtCore/qfileinfo.h>
+#include <QtCore/qtemporarydir.h>
+#include <QtCore/qtemporaryfile.h>
+#include <QtCore/qiodevice.h>
+#include <QtCore/qjsondocument.h>
+#include <QtCore/qjsonobject.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qdatetime.h>
+
+namespace {
+
+const QString autoSavePostfix = QStringLiteral("_autosave");
+const QString saveSuffix = QStringLiteral(".qt3dscene");
+const QString exportNameTemplate = QStringLiteral("%1_scene_res");
+const QString editorDataFile = QStringLiteral("qt3dscene_editor_data.json");
+const qint32 saveFileVersion = 1;
+const QByteArray saveFileId = QByteArrayLiteral("Qt3DSceneEditor_SaveFile");
+const QString activeCameraKey = QStringLiteral("activeCamera");
+const QString rootEntityNameKey = QStringLiteral("rootEntityName");
+
+} // namespace
+
+EditorSceneSaver::EditorSceneSaver(QObject *parent)
+ : QObject(parent)
+ , m_loadDir(nullptr)
+{
+}
+
+EditorSceneSaver::~EditorSceneSaver()
+{
+ delete m_loadDir;
+}
+
+bool EditorSceneSaver::saveScene(Qt3DCore::QEntity *sceneEntity,
+ const QString &activeSceneCamera,
+ const QString &saveFileName,
+ bool autosave)
+{
+ // Save consists of a single JSON file with .qt3dscene extension and the exported QGLTF scene
+ // in a separate subfolder in the same folder as the main save file.
+
+ // The save is first created in a temp directory to ensure saving over existing save doesn't
+ // partially overwrite the old save in case of error.
+ QString finalFullSaveFilePathName = saveFileName;
+ if (!finalFullSaveFilePathName.endsWith(saveSuffix))
+ finalFullSaveFilePathName.append(saveSuffix);
+ QFileInfo saveFileInfo(finalFullSaveFilePathName);
+ QString finalSavePath = saveFileInfo.path();
+ QString finalFileName = saveFileInfo.fileName();
+ QString saveExportName = exportNameTemplate.arg(saveFileInfo.completeBaseName());
+ QDir finalSaveDir = saveFileInfo.absoluteDir();
+ if (autosave) {
+ finalFullSaveFilePathName.append(autoSavePostfix);
+ finalFileName.append(autoSavePostfix);
+ saveExportName.append(autoSavePostfix);
+ }
+ QString finalScenePath = finalSavePath + QStringLiteral("/") + saveExportName;
+
+ // Save scene to a temp folder using GLTF export plugin
+ QTemporaryDir exportDir(finalScenePath + QStringLiteral("_temp_save_XXXXXX"));
+
+ const QStringList keys = Qt3DRender::QSceneExportFactory::keys();
+ for (const QString &key : keys) {
+ Qt3DRender::QSceneExporter *exporter =
+ Qt3DRender::QSceneExportFactory::create(key, QStringList());
+ if (exporter != nullptr && key == QStringLiteral("gltfexport")) {
+ QVariantHash options;
+ if (!exporter->exportScene(sceneEntity, exportDir.path(), saveExportName, options)) {
+ qWarning() << "Failed to export GLTF when saving the scene";
+ return false;
+ }
+ break;
+ }
+ }
+
+ // Create new save file in the temp folder
+ QJsonDocument jsonDoc;
+ QJsonObject editorData;
+ editorData[activeCameraKey] = activeSceneCamera;
+ editorData[rootEntityNameKey] = sceneEntity->objectName();
+ jsonDoc.setObject(editorData);
+ const QString tempScenePath = exportDir.path() + QStringLiteral("/") + saveExportName;
+ const QString saveFilePath = exportDir.path() + QStringLiteral("/") + finalFileName;
+ QFile saveFile(saveFilePath);
+ if (saveFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
+ QByteArray json = jsonDoc.toJson();
+ saveFile.write(json);
+ saveFile.close();
+ } else {
+ qWarning() << "Failed to create editor data file when saving the scene";
+ return false;
+ }
+
+ // Create a unique backup suffix from current time
+ QDateTime currentTime = QDateTime::currentDateTime();
+ QString uniqueSuffix = currentTime.toString(QStringLiteral("yyyyMMddHHmmsszzz"));
+ QString backupExportName = saveExportName + uniqueSuffix;
+ QString backupSaveFileName = finalFullSaveFilePathName + uniqueSuffix;
+
+ // Rename the old save file and exported resources and savefile
+ if (finalSaveDir.exists(saveExportName)) {
+ if (!finalSaveDir.rename(saveExportName, backupExportName)) {
+ qWarning() << "Failed to rename the old resource dir:" << saveExportName;
+ return false;
+ }
+ }
+ QFile oldSaveFile(finalFullSaveFilePathName);
+ if (oldSaveFile.exists()) {
+ if (!oldSaveFile.rename(backupSaveFileName)) {
+ qWarning() << "Failed to rename the old save file:" << finalFullSaveFilePathName;
+ finalSaveDir.rename(backupExportName, saveExportName);
+ return false;
+ }
+ }
+
+ // Rename the temporary files as finals
+ if (!QFile::rename(tempScenePath, finalScenePath)) {
+ qWarning() << "Failed to rename the temp scene:" << tempScenePath << "->" << finalScenePath;
+ return false;
+ }
+ if (!saveFile.rename(finalFullSaveFilePathName)) {
+ qWarning() << "Failed to rename the temp save file:" << saveFilePath <<
+ "->" << finalFullSaveFilePathName;
+ return false;
+ }
+
+ // If everything went well, remove the renamed originals.
+ QFile::remove(backupSaveFileName);
+ if (finalSaveDir.cd(backupExportName))
+ finalSaveDir.removeRecursively();
+
+ return true;
+}
+
+Qt3DCore::QEntity *EditorSceneSaver::loadScene(const QString &fileName, Qt3DCore::QEntity *camera)
+{
+ Qt3DCore::QEntity *loadedScene = nullptr;
+ camera = nullptr;
+
+ // Read the scene data
+ QFile jsonFile(fileName);
+ QString activeCameraId;
+ QString sceneName;
+ if (jsonFile.open(QIODevice::ReadOnly)) {
+ QByteArray jsonData = jsonFile.readAll();
+ jsonFile.close();
+ QJsonDocument jsonDocument = QJsonDocument::fromJson(jsonData);
+ QJsonObject editorData = jsonDocument.object();
+ activeCameraId = editorData.value(activeCameraKey).toString();
+ sceneName = editorData.value(rootEntityNameKey).toString();
+ } else {
+ qWarning() << "Failed to open scene save file:" << fileName;
+ return nullptr;
+ }
+
+ // Import scene from temp folder
+ const QStringList keys = Qt3DRender::QSceneImportFactory::keys();
+ for (const QString &key : keys) {
+ Qt3DRender::QSceneImporter *importer =
+ Qt3DRender::QSceneImportFactory::create(key, QStringList());
+ if (importer != nullptr && key == QStringLiteral("gltf")) {
+ QFileInfo saveFileInfo(fileName);
+ const QString exportName = exportNameTemplate.arg(saveFileInfo.completeBaseName());
+ QString sceneSource = saveFileInfo.absolutePath();
+ sceneSource += QStringLiteral("/");
+ sceneSource += exportName;
+ sceneSource += QStringLiteral("/");
+ sceneSource += exportName;
+ sceneSource += QStringLiteral(".qgltf");
+ importer->setSource(QUrl::fromLocalFile(sceneSource));
+ loadedScene = importer->scene();
+ break;
+ }
+ }
+
+ if (!loadedScene) {
+ qWarning() << "Failed to load the saved scene";
+ return nullptr;
+ }
+
+ loadedScene->setObjectName(sceneName);
+
+ // Find the active camera
+ camera = EditorUtils::findEntityByName(loadedScene, activeCameraId);
+ if (!EditorUtils::entityCameraLens(camera))
+ camera = nullptr;
+
+ return loadedScene;
+}
+
+void EditorSceneSaver::deleteSavedScene(const QString &saveFileName, bool autosave)
+{
+ QString fullSaveFilePathName = saveFileName;
+ if (!fullSaveFilePathName.endsWith(saveSuffix))
+ fullSaveFilePathName.append(saveSuffix);
+ QFileInfo saveFileInfo(fullSaveFilePathName);
+ QString savePath = saveFileInfo.path();
+ QString saveExportName = exportNameTemplate.arg(saveFileInfo.completeBaseName());
+ if (autosave) {
+ fullSaveFilePathName.append(autoSavePostfix);
+ saveExportName.append(autoSavePostfix);
+ }
+ QDir sceneResourcesDir(savePath + QStringLiteral("/") + saveExportName);
+ sceneResourcesDir.removeRecursively();
+ QFile::remove(fullSaveFilePathName);
+}
diff --git a/editorlib/src/editorscenesaver.h b/editorlib/src/editorscenesaver.h
new file mode 100644
index 0000000..d55314b
--- /dev/null
+++ b/editorlib/src/editorscenesaver.h
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D Editor of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** 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.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#ifndef EDITORSCENESAVER_H
+#define EDITORSCENESAVER_H
+
+#include <QtCore/qobject.h>
+
+namespace Qt3DCore {
+ class QEntity;
+}
+
+class QTemporaryDir;
+
+class EditorSceneSaver : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit EditorSceneSaver(QObject *parent = 0);
+ ~EditorSceneSaver();
+
+ bool saveScene(Qt3DCore::QEntity *sceneEntity, const QString &activeSceneCamera,
+ const QString &saveFileName, bool autosave = false);
+
+ Qt3DCore::QEntity *loadScene(const QString &fileName, Qt3DCore::QEntity *camera);
+ void deleteSavedScene(const QString &saveFileName, bool autosave = false);
+
+private:
+ QTemporaryDir *m_loadDir;
+};
+
+#endif // EDITORSCENESAVER_H
diff --git a/editorlib/src/editorutils.cpp b/editorlib/src/editorutils.cpp
index 82a2fe2..fb8b619 100644
--- a/editorlib/src/editorutils.cpp
+++ b/editorlib/src/editorutils.cpp
@@ -1298,6 +1298,22 @@ void EditorUtils::setEnabledToSubtree(Qt3DCore::QEntity *entity, bool enable)
}
}
+Qt3DCore::QEntity *EditorUtils::findEntityByName(Qt3DCore::QEntity *entity, const QString &name)
+{
+ if (entity->objectName() == name) {
+ return entity;
+ } else {
+ for (QObject *child : entity->children()) {
+ Qt3DCore::QEntity *childEntity = qobject_cast<Qt3DCore::QEntity *>(child);
+ if (childEntity) {
+ Qt3DCore::QEntity *foundEntity = findEntityByName(childEntity, name);
+ if (foundEntity)
+ return foundEntity;
+ }
+ }
+ }
+ return nullptr;
+}
template <typename T>
void EditorUtils::copyRenderParameters(T *source, T *target)
diff --git a/editorlib/src/editorutils.h b/editorlib/src/editorutils.h
index 582462f..c2fde0c 100644
--- a/editorlib/src/editorutils.h
+++ b/editorlib/src/editorutils.h
@@ -173,6 +173,7 @@ public:
static void lockProperty(const QByteArray &lockPropertyName, QObject *obj, bool lock);
static InsertableEntities insertableEntityType(Qt3DCore::QEntity *entity);
static void setEnabledToSubtree(Qt3DCore::QEntity *entity, bool enable);
+ static Qt3DCore::QEntity *findEntityByName(Qt3DCore::QEntity *entity, const QString &name);
private:
// Private constructor to ensure no actual instance is created