summaryrefslogtreecommitdiffstats
path: root/src/runtimerender/Qt3DSRenderInputStreamFactory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtimerender/Qt3DSRenderInputStreamFactory.cpp')
-rw-r--r--src/runtimerender/Qt3DSRenderInputStreamFactory.cpp214
1 files changed, 214 insertions, 0 deletions
diff --git a/src/runtimerender/Qt3DSRenderInputStreamFactory.cpp b/src/runtimerender/Qt3DSRenderInputStreamFactory.cpp
new file mode 100644
index 0000000..1a418b1
--- /dev/null
+++ b/src/runtimerender/Qt3DSRenderInputStreamFactory.cpp
@@ -0,0 +1,214 @@
+/****************************************************************************
+**
+** Copyright (C) 2008-2012 NVIDIA Corporation.
+** Copyright (C) 2017 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of Qt 3D Studio.
+**
+** $QT_BEGIN_LICENSE:GPL$
+** 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 or (at your option) any later version
+** approved by the KDE Free Qt Foundation. The licenses are as published by
+** the Free Software Foundation and appearing in the file LICENSE.GPL3
+** 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 "Qt3DSRenderInputStreamFactory.h"
+
+#include "stdio.h"
+
+#include "foundation/Qt3DSFoundation.h"
+#include "foundation/Qt3DSAllocatorCallback.h"
+#include "foundation/Qt3DSBroadcastingAllocator.h"
+#include "foundation/Qt3DSAtomic.h"
+#include "EASTL/string.h"
+#include "EASTL/vector.h"
+#include "foundation/Qt3DSContainers.h"
+#include "foundation/FileTools.h"
+#include "foundation/Qt3DSMutex.h"
+
+#include <QDir>
+#include <QDirIterator>
+#include <QFile>
+#include <QFileInfo>
+#include <QUrl>
+
+using namespace qt3ds::render;
+
+namespace {
+struct SInputStream : public IRefCountedInputStream
+{
+ NVFoundationBase &m_Foundation;
+ QString m_Path;
+ QFile m_File;
+ volatile QT3DSI32 mRefCount;
+
+ SInputStream(NVFoundationBase &inFoundation, const QString &inPath)
+ : m_Foundation(inFoundation)
+ , m_Path(inPath)
+ , m_File(inPath)
+ , mRefCount(0)
+ {
+ m_File.open(QIODevice::ReadOnly);
+ }
+ virtual ~SInputStream()
+ {
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE(m_Foundation.getAllocator())
+
+ QT3DSU32 Read(NVDataRef<QT3DSU8> data) override
+ {
+ return m_File.read((char *)data.begin(), data.size());
+ }
+
+ bool Write(NVConstDataRef<QT3DSU8> /*data*/) override
+ {
+ QT3DS_ASSERT(false);
+ return false;
+ }
+
+ void SetPosition(QT3DSI64 inOffset, qt3ds::foundation::SeekPosition::Enum inEnum) override
+ {
+ if (inOffset > QT3DS_MAX_I32 || inOffset < QT3DS_MIN_I32) {
+ qCCritical(INVALID_OPERATION, "Attempt to seek further than platform allows");
+ QT3DS_ASSERT(false);
+ return;
+ } else {
+ CFileTools::SetStreamPosition(m_File, inOffset, inEnum);
+ }
+ }
+ QT3DSI64 GetPosition() const override
+ {
+ return m_File.pos();
+ }
+
+ static SInputStream *OpenFile(const QString &inPath, NVFoundationBase &inFoundation)
+ {
+ return QT3DS_NEW(inFoundation.getAllocator(), SInputStream)(inFoundation, inPath);
+ }
+};
+
+typedef eastl::basic_string<char8_t, ForwardingAllocator> TStrType;
+struct SFactory : public IInputStreamFactory
+{
+ NVFoundationBase &m_Foundation;
+ volatile QT3DSI32 mRefCount;
+
+ Mutex m_Mutex;
+ typedef Mutex::ScopedLock TScopedLock;
+
+ const QString QT3DSTUDIO_TAG = QStringLiteral("qt3dstudio");
+
+ SFactory(NVFoundationBase &inFoundation)
+ : m_Foundation(inFoundation)
+ , mRefCount(0)
+ , m_Mutex(inFoundation.getAllocator())
+ {
+ // Add the top-level qrc directory
+ if (!QDir::searchPaths(QT3DSTUDIO_TAG).contains(QLatin1String(":/")))
+ QDir::addSearchPath(QT3DSTUDIO_TAG, QStringLiteral(":/"));
+ }
+
+ QT3DS_IMPLEMENT_REF_COUNT_ADDREF_RELEASE_OVERRIDE(m_Foundation.getAllocator())
+
+ QFileInfo matchCaseInsensitiveFile(const QString& file, bool inQuiet)
+ {
+ if (!inQuiet) {
+ // Some assets are searched for in several levels in the project structure,
+ // we don't want to alert user of things that can't be fixed in the presentation
+ // itself.
+ qCWarning(WARNING, PERF_INFO, "Case-insensitive matching with file: %s",
+ file.toLatin1().constData());
+ }
+ const QStringList searchDirectories = QDir::searchPaths(QT3DSTUDIO_TAG);
+ for (const auto &directoryPath : searchDirectories) {
+ QFileInfo fileInfo(file);
+ QDirIterator it(directoryPath, {fileInfo.fileName()}, QDir::NoFilter,
+ QDirIterator::Subdirectories);
+ while (it.hasNext()) {
+ QString filePath = it.next();
+ if (filePath.compare(QDir::cleanPath(directoryPath + '/' + file),
+ Qt::CaseInsensitive) == 0) {
+ return QFileInfo(filePath);
+ }
+ }
+ }
+
+ return QFileInfo();
+ }
+
+ void AddSearchDirectory(const char8_t *inDirectory) override
+ {
+ TScopedLock __factoryLocker(m_Mutex);
+ QString localDir = CFileTools::NormalizePathForQtUsage(inDirectory);
+ QDir directory(localDir);
+ if (!directory.exists()) {
+ qCCritical(INTERNAL_ERROR, "Adding search directory: %s", inDirectory);
+ return;
+ }
+
+ if (!QDir::searchPaths(QT3DSTUDIO_TAG).contains(localDir))
+ QDir::addSearchPath(QT3DSTUDIO_TAG, localDir);
+ }
+
+
+ IRefCountedInputStream *GetStreamForFile(const QString &inFilename, bool inQuiet) override
+ {
+ TScopedLock __factoryLocker(m_Mutex);
+ QString localFile = CFileTools::NormalizePathForQtUsage(inFilename);
+ QFileInfo fileInfo = QFileInfo(localFile);
+ SInputStream *inputStream = nullptr;
+ // Try to match the file with the search paths
+ if (!fileInfo.exists())
+ fileInfo.setFile(QStringLiteral("qt3dstudio:") + localFile);
+
+ // Try to match the case-insensitive file with the given search paths
+ if (!fileInfo.exists())
+ fileInfo = matchCaseInsensitiveFile(localFile, inQuiet);
+
+ if (fileInfo.exists())
+ inputStream = SInputStream::OpenFile(fileInfo.absoluteFilePath(), m_Foundation);
+
+ if (!inputStream && !inQuiet) {
+ // Print extensive debugging information.
+ qCCritical(INTERNAL_ERROR, "Failed to find file: %s", localFile.toLatin1().constData());
+ qCCritical(INTERNAL_ERROR, "Searched path: %s",
+ QDir::searchPaths(QT3DSTUDIO_TAG).join(',').toLatin1().constData());
+ }
+ return inputStream;
+ }
+
+ bool GetPathForFile(const QString &inFilename, QString &outFile,
+ bool inQuiet = false) override
+ {
+ NVScopedRefCounted<IRefCountedInputStream> theStream =
+ GetStreamForFile(inFilename, inQuiet);
+ if (theStream) {
+ SInputStream *theRealStream = static_cast<SInputStream *>(theStream.mPtr);
+ outFile = theRealStream->m_Path;
+ return true;
+ }
+ return false;
+ }
+};
+}
+
+IInputStreamFactory &IInputStreamFactory::Create(NVFoundationBase &inFoundation)
+{
+ return *QT3DS_NEW(inFoundation.getAllocator(), SFactory)(inFoundation);
+}