forked from qt-creator/qt-creator
QmlDesigner: Add configuration for qsb shader generator tool
Added default ShaderTool configuration block to new project template and use information specified there to generate qsb shaders. The args property specifies command line argument for qsb tool. The files property specifies files for which qsb tool is run for. E.g.: ShaderTool { args: "-s --glsl \"100 es,120,150\" --hlsl 50 --msl 12" files: [ "content/shaders/*" ] } Fixes: QDS-6590 Change-Id: I3bab0db21d20f486f9f25c1437a27ddb7fb47396 Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: Samuel Ghinet <samuel.ghinet@qt.io>
This commit is contained in:
@@ -95,6 +95,15 @@ Project {
|
|||||||
@if %{IsQt6Project}
|
@if %{IsQt6Project}
|
||||||
/* If any modules the project imports require widgets (e.g. QtCharts), widgetApp must be true */
|
/* If any modules the project imports require widgets (e.g. QtCharts), widgetApp must be true */
|
||||||
widgetApp: true
|
widgetApp: true
|
||||||
|
|
||||||
|
/* args: Specifies command line arguments for qsb tool to generate shaders.
|
||||||
|
files: Specifies target files for qsb tool. If path is included, it must be relative to this file.
|
||||||
|
Wildcard '*' can be used in the file name part of the path.
|
||||||
|
e.g. files: [ "content/shaders/*.vert", "*.frag" ] */
|
||||||
|
ShaderTool {
|
||||||
|
args: "-s --glsl \\\"100 es,120,150\\\" --hlsl 50 --msl 12"
|
||||||
|
files: [ "content/shaders/*" ]
|
||||||
|
}
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
multilanguageSupport: true
|
multilanguageSupport: true
|
||||||
|
@@ -237,6 +237,7 @@ private: // functions
|
|||||||
void updateWatcher(const QString &path);
|
void updateWatcher(const QString &path);
|
||||||
void handleShaderChanges();
|
void handleShaderChanges();
|
||||||
void handleQsbProcessExit(Utils::QtcProcess *qsbProcess, const QString &shader);
|
void handleQsbProcessExit(Utils::QtcProcess *qsbProcess, const QString &shader);
|
||||||
|
void updateQsbPathToFilterMap();
|
||||||
void updateRotationBlocks();
|
void updateRotationBlocks();
|
||||||
void maybeResetOnPropertyChange(const PropertyName &name, const ModelNode &node,
|
void maybeResetOnPropertyChange(const PropertyName &name, const ModelNode &node,
|
||||||
PropertyChangeFlags flags);
|
PropertyChangeFlags flags);
|
||||||
@@ -288,8 +289,9 @@ private:
|
|||||||
QTimer m_generateQsbFilesTimer;
|
QTimer m_generateQsbFilesTimer;
|
||||||
Utils::FilePath m_qsbPath;
|
Utils::FilePath m_qsbPath;
|
||||||
QSet<QString> m_pendingUpdateDirs;
|
QSet<QString> m_pendingUpdateDirs;
|
||||||
QSet<QString> m_pendingQsbTargets;
|
QHash<QString, bool> m_qsbTargets; // Value indicates if target is pending qsb generation
|
||||||
int m_remainingQsbTargets;
|
QHash<QString, QStringList> m_qsbPathToFilterMap;
|
||||||
|
int m_remainingQsbTargets = 0;
|
||||||
QTimer m_rotBlockTimer;
|
QTimer m_rotBlockTimer;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -98,6 +98,7 @@
|
|||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
|
|
||||||
#include <qmlprojectmanager/qmlmultilanguageaspect.h>
|
#include <qmlprojectmanager/qmlmultilanguageaspect.h>
|
||||||
|
#include <qmlprojectmanager/qmlproject.h>
|
||||||
|
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
@@ -113,6 +114,8 @@
|
|||||||
#include <QDirIterator>
|
#include <QDirIterator>
|
||||||
#include <QFileSystemWatcher>
|
#include <QFileSystemWatcher>
|
||||||
#include <QScopedPointer>
|
#include <QScopedPointer>
|
||||||
|
#include <QThread>
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
debug = false
|
debug = false
|
||||||
@@ -174,9 +177,6 @@ NodeInstanceView::NodeInstanceView(ConnectionManagerInterface &connectionManager
|
|||||||
m_generateQsbFilesTimer.setInterval(100);
|
m_generateQsbFilesTimer.setInterval(100);
|
||||||
QObject::connect(&m_generateQsbFilesTimer, &QTimer::timeout, [this] {
|
QObject::connect(&m_generateQsbFilesTimer, &QTimer::timeout, [this] {
|
||||||
handleShaderChanges();
|
handleShaderChanges();
|
||||||
|
|
||||||
if (m_qsbPath.isEmpty() || m_remainingQsbTargets <= 0)
|
|
||||||
m_resetTimer.start();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
connect(m_fileSystemWatcher, &QFileSystemWatcher::directoryChanged,
|
connect(m_fileSystemWatcher, &QFileSystemWatcher::directoryChanged,
|
||||||
@@ -196,8 +196,12 @@ NodeInstanceView::NodeInstanceView(ConnectionManagerInterface &connectionManager
|
|||||||
|
|
||||||
});
|
});
|
||||||
connect(m_fileSystemWatcher, &QFileSystemWatcher::fileChanged, [this](const QString &path) {
|
connect(m_fileSystemWatcher, &QFileSystemWatcher::fileChanged, [this](const QString &path) {
|
||||||
m_pendingQsbTargets.insert(path);
|
if (m_qsbTargets.contains(path)) {
|
||||||
|
m_qsbTargets.insert(path, true);
|
||||||
m_generateQsbFilesTimer.start();
|
m_generateQsbFilesTimer.start();
|
||||||
|
} else if (m_remainingQsbTargets <= 0) {
|
||||||
|
m_resetTimer.start();
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
m_rotBlockTimer.setSingleShot(true);
|
m_rotBlockTimer.setSingleShot(true);
|
||||||
@@ -277,7 +281,15 @@ void NodeInstanceView::modelAttached(Model *model)
|
|||||||
activateState(newStateInstance);
|
activateState(newStateInstance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If model gets attached on non-main thread of the application, do not attempt to monitor
|
||||||
|
// file changes. Such models are typically short lived for specific purpose, and timers
|
||||||
|
// will not work at all, if the thread is not based on QThread.
|
||||||
|
if (QThread::currentThread() == qApp->thread()) {
|
||||||
|
m_generateQsbFilesTimer.stop();
|
||||||
|
m_qsbTargets.clear();
|
||||||
|
updateQsbPathToFilterMap();
|
||||||
updateWatcher({});
|
updateWatcher({});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::modelAboutToBeDetached(Model * model)
|
void NodeInstanceView::modelAboutToBeDetached(Model * model)
|
||||||
@@ -303,6 +315,9 @@ void NodeInstanceView::modelAboutToBeDetached(Model * model)
|
|||||||
m_pendingUpdateDirs.clear();
|
m_pendingUpdateDirs.clear();
|
||||||
m_fileSystemWatcher->removePaths(m_fileSystemWatcher->directories());
|
m_fileSystemWatcher->removePaths(m_fileSystemWatcher->directories());
|
||||||
m_fileSystemWatcher->removePaths(m_fileSystemWatcher->files());
|
m_fileSystemWatcher->removePaths(m_fileSystemWatcher->files());
|
||||||
|
|
||||||
|
m_generateQsbFilesTimer.stop();
|
||||||
|
m_qsbTargets.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::handleCrash()
|
void NodeInstanceView::handleCrash()
|
||||||
@@ -1488,9 +1503,6 @@ void NodeInstanceView::setTarget(ProjectExplorer::Target *newTarget)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_generateQsbFilesTimer.stop();
|
|
||||||
m_pendingQsbTargets.clear();
|
|
||||||
m_remainingQsbTargets = 0;
|
|
||||||
restartProcess();
|
restartProcess();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1885,12 +1897,18 @@ void NodeInstanceView::updateWatcher(const QString &path)
|
|||||||
QStringList oldDirs;
|
QStringList oldDirs;
|
||||||
QStringList newFiles;
|
QStringList newFiles;
|
||||||
QStringList newDirs;
|
QStringList newDirs;
|
||||||
|
QStringList qsbFiles;
|
||||||
|
#ifndef QMLDESIGNER_TEST
|
||||||
|
const QString projPath = QmlDesignerPlugin::instance()->documentManager().currentProjectDirPath().toString();
|
||||||
|
#else
|
||||||
|
const QString projPath = QFileInfo(model()->fileUrl().toLocalFile()).absolutePath();
|
||||||
|
#endif
|
||||||
|
|
||||||
const QStringList files = m_fileSystemWatcher->files();
|
const QStringList files = m_fileSystemWatcher->files();
|
||||||
const QStringList directories = m_fileSystemWatcher->directories();
|
const QStringList directories = m_fileSystemWatcher->directories();
|
||||||
if (path.isEmpty()) {
|
if (path.isEmpty()) {
|
||||||
// Do full update
|
// Do full update
|
||||||
rootPath = QFileInfo(model()->fileUrl().toLocalFile()).absolutePath();
|
rootPath = projPath;
|
||||||
if (!directories.isEmpty())
|
if (!directories.isEmpty())
|
||||||
m_fileSystemWatcher->removePaths(directories);
|
m_fileSystemWatcher->removePaths(directories);
|
||||||
if (!files.isEmpty())
|
if (!files.isEmpty())
|
||||||
@@ -1916,12 +1934,47 @@ void NodeInstanceView::updateWatcher(const QString &path)
|
|||||||
// Common shader suffixes
|
// Common shader suffixes
|
||||||
static const QStringList filterList {"*.frag", "*.vert",
|
static const QStringList filterList {"*.frag", "*.vert",
|
||||||
"*.glsl", "*.glslv", "*.glslf",
|
"*.glsl", "*.glslv", "*.glslf",
|
||||||
"*.vsh","*.fsh"};
|
"*.vsh", "*.fsh"};
|
||||||
|
|
||||||
QDirIterator fileIterator(rootPath, filterList, QDir::Files, QDirIterator::Subdirectories);
|
QDirIterator fileIterator(rootPath, filterList, QDir::Files, QDirIterator::Subdirectories);
|
||||||
while (fileIterator.hasNext())
|
while (fileIterator.hasNext())
|
||||||
newFiles.append(fileIterator.next());
|
newFiles.append(fileIterator.next());
|
||||||
|
|
||||||
|
// Find out which shader files need qsb files generated for them.
|
||||||
|
// Go through all configured paths and find files that match the specified filter in that path.
|
||||||
|
bool generateQsb = false;
|
||||||
|
QHash<QString, QStringList>::const_iterator it = m_qsbPathToFilterMap.constBegin();
|
||||||
|
while (it != m_qsbPathToFilterMap.constEnd()) {
|
||||||
|
if (!it.key().isEmpty() && !it.key().startsWith(rootPath)) {
|
||||||
|
++it;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDirIterator qsbIterator(it.key().isEmpty() ? rootPath : it.key(),
|
||||||
|
it.value(), QDir::Files,
|
||||||
|
it.key().isEmpty() ? QDirIterator::Subdirectories
|
||||||
|
: QDirIterator::NoIteratorFlags);
|
||||||
|
|
||||||
|
while (qsbIterator.hasNext()) {
|
||||||
|
QString qsbFile = qsbIterator.next();
|
||||||
|
|
||||||
|
if (qsbFile.endsWith(".qsb"))
|
||||||
|
continue; // Skip any generated files that are caught by wildcards
|
||||||
|
|
||||||
|
// Filters may specify shader files with non-default suffixes, so add them to newFiles
|
||||||
|
if (!newFiles.contains(qsbFile))
|
||||||
|
newFiles.append(qsbFile);
|
||||||
|
|
||||||
|
// Only generate qsb files for newly detected files. This avoids immediately regenerating
|
||||||
|
// qsb file if it's manually deleted, as directory change triggers calling this method.
|
||||||
|
if (!oldFiles.contains(qsbFile)) {
|
||||||
|
m_qsbTargets.insert(qsbFile, true);
|
||||||
|
generateQsb = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
if (oldDirs != newDirs) {
|
if (oldDirs != newDirs) {
|
||||||
if (!oldDirs.isEmpty())
|
if (!oldDirs.isEmpty())
|
||||||
m_fileSystemWatcher->removePaths(oldDirs);
|
m_fileSystemWatcher->removePaths(oldDirs);
|
||||||
@@ -1934,15 +1987,10 @@ void NodeInstanceView::updateWatcher(const QString &path)
|
|||||||
m_fileSystemWatcher->removePaths(oldFiles);
|
m_fileSystemWatcher->removePaths(oldFiles);
|
||||||
if (!newFiles.isEmpty())
|
if (!newFiles.isEmpty())
|
||||||
m_fileSystemWatcher->addPaths(newFiles);
|
m_fileSystemWatcher->addPaths(newFiles);
|
||||||
|
|
||||||
for (const auto &newFile : qAsConst(newFiles)) {
|
|
||||||
if (!oldFiles.contains(newFile))
|
|
||||||
m_pendingQsbTargets.insert(newFile);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_pendingQsbTargets.isEmpty())
|
if (generateQsb)
|
||||||
m_generateQsbFilesTimer.start();
|
m_generateQsbFilesTimer.start();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::handleQsbProcessExit(Utils::QtcProcess *qsbProcess, const QString &shader)
|
void NodeInstanceView::handleQsbProcessExit(Utils::QtcProcess *qsbProcess, const QString &shader)
|
||||||
@@ -1969,26 +2017,80 @@ void NodeInstanceView::handleQsbProcessExit(Utils::QtcProcess *qsbProcess, const
|
|||||||
qsbProcess->deleteLater();
|
qsbProcess->deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NodeInstanceView::updateQsbPathToFilterMap()
|
||||||
|
{
|
||||||
|
m_qsbPathToFilterMap.clear();
|
||||||
|
if (m_currentTarget && !m_qsbPath.isEmpty()) {
|
||||||
|
const auto bs = qobject_cast<QmlProjectManager::QmlBuildSystem *>(m_currentTarget->buildSystem());
|
||||||
|
const QStringList shaderToolFiles = bs->shaderToolFiles();
|
||||||
|
|
||||||
|
#ifndef QMLDESIGNER_TEST
|
||||||
|
const QString projPath = QmlDesignerPlugin::instance()->documentManager().currentProjectDirPath().toString();
|
||||||
|
#else
|
||||||
|
const QString projPath = QFileInfo(model()->fileUrl().toLocalFile()).absolutePath();
|
||||||
|
#endif
|
||||||
|
// Parse ShaderTool files from project configuration.
|
||||||
|
// Separate files to path and file name (called filter here as it can contain wildcards)
|
||||||
|
// and group filters by paths. Blank path indicates project-wide file wildcard.
|
||||||
|
for (const auto &file : shaderToolFiles) {
|
||||||
|
int idx = file.lastIndexOf('/');
|
||||||
|
QString key;
|
||||||
|
QString filter;
|
||||||
|
if (idx >= 0) {
|
||||||
|
key = projPath + "/" + file.left(idx);
|
||||||
|
filter = file.mid(idx + 1);
|
||||||
|
} else {
|
||||||
|
filter = file;
|
||||||
|
}
|
||||||
|
m_qsbPathToFilterMap[key].append(filter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void NodeInstanceView::handleShaderChanges()
|
void NodeInstanceView::handleShaderChanges()
|
||||||
{
|
{
|
||||||
m_remainingQsbTargets += m_pendingQsbTargets.size();
|
if (!m_currentTarget)
|
||||||
|
return;
|
||||||
|
|
||||||
for (const auto &shader : qAsConst(m_pendingQsbTargets)) {
|
const auto bs = qobject_cast<QmlProjectManager::QmlBuildSystem *>(m_currentTarget->buildSystem());
|
||||||
// Run qsb for changed shader file
|
QStringList baseArgs = bs->shaderToolArgs();
|
||||||
if (!m_qsbPath.isEmpty() && !shader.isEmpty()) {
|
if (baseArgs.isEmpty())
|
||||||
const Utils::FilePath sourceFile = Utils::FilePath::fromString(shader);
|
return;
|
||||||
const Utils::FilePath srcPath = sourceFile.absolutePath();
|
|
||||||
|
QStringList newShaders;
|
||||||
|
QHash<QString, bool>::iterator it = m_qsbTargets.begin();
|
||||||
|
while (it != m_qsbTargets.end()) {
|
||||||
|
if (it.value()) {
|
||||||
|
newShaders.append(it.key());
|
||||||
|
it.value() = false;
|
||||||
|
}
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newShaders.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_remainingQsbTargets += newShaders.size();
|
||||||
|
|
||||||
|
for (const auto &shader : qAsConst(newShaders)) {
|
||||||
|
const Utils::FilePath srcFile = Utils::FilePath::fromString(shader);
|
||||||
|
const Utils::FilePath srcPath = srcFile.absolutePath();
|
||||||
const Utils::FilePath outPath = Utils::FilePath::fromString(shader + ".qsb");
|
const Utils::FilePath outPath = Utils::FilePath::fromString(shader + ".qsb");
|
||||||
|
|
||||||
if (!sourceFile.exists() || (outPath.exists() && outPath.lastModified() > sourceFile.lastModified())) {
|
if (!srcFile.exists()) {
|
||||||
|
m_qsbTargets.remove(shader);
|
||||||
--m_remainingQsbTargets;
|
--m_remainingQsbTargets;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run QSB with same parameters as Qt build does
|
if ((outPath.exists() && outPath.lastModified() > srcFile.lastModified())) {
|
||||||
// TODO: Parameters should be configurable (QDS-6590)
|
--m_remainingQsbTargets;
|
||||||
const QStringList args = {"-s", "--glsl", "100 es,120,150", "--hlsl", "50", "--msl", "12",
|
continue;
|
||||||
"-o", outPath.toString(), shader};
|
}
|
||||||
|
|
||||||
|
QStringList args = baseArgs;
|
||||||
|
args.append(outPath.toString());
|
||||||
|
args.append(shader);
|
||||||
auto qsbProcess = new Utils::QtcProcess;
|
auto qsbProcess = new Utils::QtcProcess;
|
||||||
qsbProcess->setWorkingDirectory(srcPath);
|
qsbProcess->setWorkingDirectory(srcPath);
|
||||||
qsbProcess->setCommand({m_qsbPath, args});
|
qsbProcess->setCommand({m_qsbPath, args});
|
||||||
@@ -2011,9 +2113,6 @@ void NodeInstanceView::handleShaderChanges()
|
|||||||
handleQsbProcessExit(qsbProcess, shader);
|
handleQsbProcessExit(qsbProcess, shader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
m_pendingQsbTargets.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodeInstanceView::updateRotationBlocks()
|
void NodeInstanceView::updateRotationBlocks()
|
||||||
|
@@ -161,6 +161,26 @@ QmlProjectItem *QmlProjectFileFormat::parseProjectFile(const Utils::FilePath &fi
|
|||||||
projectItem->addToEnviroment(i.key(), i.value().value.toString());
|
projectItem->addToEnviroment(i.key(), i.value().value.toString());
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
} else if (childNode->name() == "ShaderTool") {
|
||||||
|
QmlJS::SimpleReaderNode::Property commandLine = childNode->property("args");
|
||||||
|
if (commandLine.isValid()) {
|
||||||
|
const QStringList quotedArgs = commandLine.value.toString().split('\"');
|
||||||
|
QStringList args;
|
||||||
|
for (int i = 0; i < quotedArgs.size(); ++i) {
|
||||||
|
// Each odd arg in this list is a single quoted argument, which we should
|
||||||
|
// not be split further
|
||||||
|
if (i % 2 == 0)
|
||||||
|
args.append(quotedArgs[i].trimmed().split(' '));
|
||||||
|
else
|
||||||
|
args.append(quotedArgs[i]);
|
||||||
|
}
|
||||||
|
args.removeAll({});
|
||||||
|
args.append("-o"); // Prepare for adding output file as next arg
|
||||||
|
projectItem->setShaderToolArgs(args);
|
||||||
|
}
|
||||||
|
QmlJS::SimpleReaderNode::Property files = childNode->property("files");
|
||||||
|
if (files.isValid())
|
||||||
|
projectItem->setShaderToolFiles(files.value.toStringList());
|
||||||
} else {
|
} else {
|
||||||
qWarning() << "Unknown type:" << childNode->name();
|
qWarning() << "Unknown type:" << childNode->name();
|
||||||
}
|
}
|
||||||
|
@@ -84,6 +84,12 @@ public:
|
|||||||
bool widgetApp() const { return m_widgetApp; }
|
bool widgetApp() const { return m_widgetApp; }
|
||||||
void setWidgetApp(bool widgetApp) { m_widgetApp = widgetApp; }
|
void setWidgetApp(bool widgetApp) { m_widgetApp = widgetApp; }
|
||||||
|
|
||||||
|
QStringList shaderToolArgs() const { return m_shaderToolArgs; }
|
||||||
|
void setShaderToolArgs(const QStringList &args) {m_shaderToolArgs = args; }
|
||||||
|
|
||||||
|
QStringList shaderToolFiles() const { return m_shaderToolFiles; }
|
||||||
|
void setShaderToolFiles(const QStringList &files) {m_shaderToolFiles = files; }
|
||||||
|
|
||||||
void appendContent(QmlProjectContentItem *item) { m_content.append(item); }
|
void appendContent(QmlProjectContentItem *item) { m_content.append(item); }
|
||||||
|
|
||||||
Utils::EnvironmentItems environment() const;
|
Utils::EnvironmentItems environment() const;
|
||||||
@@ -107,6 +113,8 @@ protected:
|
|||||||
bool m_qtForMCUs = false;
|
bool m_qtForMCUs = false;
|
||||||
bool m_qt6Project = false;
|
bool m_qt6Project = false;
|
||||||
bool m_widgetApp = false;
|
bool m_widgetApp = false;
|
||||||
|
QStringList m_shaderToolArgs;
|
||||||
|
QStringList m_shaderToolFiles;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlProjectManager
|
} // namespace QmlProjectManager
|
||||||
|
@@ -625,6 +625,20 @@ bool QmlBuildSystem::widgetApp() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList QmlBuildSystem::shaderToolArgs() const
|
||||||
|
{
|
||||||
|
if (m_projectItem)
|
||||||
|
return m_projectItem->shaderToolArgs();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList QmlBuildSystem::shaderToolFiles() const
|
||||||
|
{
|
||||||
|
if (m_projectItem)
|
||||||
|
return m_projectItem->shaderToolFiles();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
bool QmlBuildSystem::addFiles(Node *context, const FilePaths &filePaths, FilePaths *)
|
bool QmlBuildSystem::addFiles(Node *context, const FilePaths &filePaths, FilePaths *)
|
||||||
{
|
{
|
||||||
if (!dynamic_cast<QmlProjectNode *>(context))
|
if (!dynamic_cast<QmlProjectNode *>(context))
|
||||||
|
@@ -95,6 +95,8 @@ public:
|
|||||||
void setPrimaryLanguage(QString language);
|
void setPrimaryLanguage(QString language);
|
||||||
bool forceFreeType() const;
|
bool forceFreeType() const;
|
||||||
bool widgetApp() const;
|
bool widgetApp() const;
|
||||||
|
QStringList shaderToolArgs() const;
|
||||||
|
QStringList shaderToolFiles() const;
|
||||||
|
|
||||||
bool addFiles(const QStringList &filePaths);
|
bool addFiles(const QStringList &filePaths);
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user