mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-05 17:40:39 +00:00
Add registration and loading of extensions through a management window
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include "CaptureContext.h"
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
#include <QDirIterator>
|
||||
#include <QElapsedTimer>
|
||||
#include <QFileInfo>
|
||||
#include <QLabel>
|
||||
@@ -32,7 +33,9 @@
|
||||
#include <QMessageBox>
|
||||
#include <QMetaObject>
|
||||
#include <QProgressDialog>
|
||||
#include <QRegularExpression>
|
||||
#include <QTimer>
|
||||
#include "Code/pyrenderdoc/PythonContext.h"
|
||||
#include "Windows/APIInspector.h"
|
||||
#include "Windows/BufferViewer.h"
|
||||
#include "Windows/CommentView.h"
|
||||
@@ -54,6 +57,7 @@
|
||||
#include "Windows/TimelineBar.h"
|
||||
#include "QRDUtils.h"
|
||||
#include "RGPInterop.h"
|
||||
#include "version.h"
|
||||
|
||||
#include "pipestate.inl"
|
||||
|
||||
@@ -103,6 +107,24 @@ CaptureContext::CaptureContext(QString paramFilename, QString remoteHost, uint32
|
||||
m_MainWindow->takeCaptureOwnership();
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
QDir dir(configFilePath("extensions"));
|
||||
|
||||
if(!dir.exists())
|
||||
dir.mkpath(dir.absolutePath());
|
||||
}
|
||||
|
||||
rdcarray<ExtensionMetadata> exts = CaptureContext::GetInstalledExtensions();
|
||||
|
||||
for(const ExtensionMetadata &e : exts)
|
||||
{
|
||||
if(cfg.AlwaysLoad_Extensions.contains(e.Package))
|
||||
{
|
||||
qInfo() << "Automatically loading extension" << QString(e.Package);
|
||||
LoadExtension(e.Package);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CaptureContext::~CaptureContext()
|
||||
@@ -139,6 +161,197 @@ rdcstr CaptureContext::TempCaptureFilename(const rdcstr &appname)
|
||||
.arg(QDateTime::currentDateTimeUtc().toString(lit("yyyy.MM.dd_HH.mm.ss"))));
|
||||
}
|
||||
|
||||
rdcarray<ExtensionMetadata> CaptureContext::GetInstalledExtensions()
|
||||
{
|
||||
QString extensionFolder = configFilePath("extensions");
|
||||
|
||||
rdcarray<ExtensionMetadata> ret;
|
||||
|
||||
QDirIterator it(extensionFolder, QDirIterator::Subdirectories);
|
||||
|
||||
extensionFolder = extensionFolder.toLower();
|
||||
|
||||
while(it.hasNext())
|
||||
{
|
||||
QFileInfo fileinfo(it.next());
|
||||
|
||||
if(fileinfo.fileName().toLower() == lit("extension.json"))
|
||||
{
|
||||
QFile f(fileinfo.absoluteFilePath());
|
||||
|
||||
QString package = fileinfo.absolutePath()
|
||||
.toLower()
|
||||
.replace(extensionFolder, QString())
|
||||
.replace(QLatin1Char('/'), QLatin1Char('.'));
|
||||
|
||||
while(package[0] == QLatin1Char('.'))
|
||||
package.remove(0, 1);
|
||||
|
||||
while(package[package.size() - 1] == QLatin1Char('.'))
|
||||
package.remove(package.size() - 1, 1);
|
||||
|
||||
if(f.exists() && f.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
{
|
||||
QVariantMap json = JSONToVariant(QString::fromUtf8(f.readAll()));
|
||||
|
||||
if(json.empty())
|
||||
{
|
||||
qCritical() << fileinfo.absoluteFilePath() << "is corrupt, cannot parse json";
|
||||
continue;
|
||||
}
|
||||
|
||||
ExtensionMetadata ext;
|
||||
|
||||
ext.Package = package;
|
||||
ext.FilePath = fileinfo.absolutePath();
|
||||
|
||||
if(json.contains(lit("name")))
|
||||
{
|
||||
ext.Name = json[lit("name")].toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << "Extension" << package << "is corrupt, no name entry";
|
||||
continue;
|
||||
}
|
||||
|
||||
ext.ExtensionAPI = 1;
|
||||
if(json.contains(lit("extension_api")))
|
||||
{
|
||||
ext.ExtensionAPI = json[lit("extension_api")].toInt();
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << "Extension" << QString(ext.Name) << "is corrupt, no api version entry";
|
||||
continue;
|
||||
}
|
||||
|
||||
if(json.contains(lit("version")))
|
||||
{
|
||||
ext.Version = json[lit("version")].toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << "Extension" << QString(ext.Name) << "is corrupt, no version entry";
|
||||
continue;
|
||||
}
|
||||
|
||||
if(json.contains(lit("description")))
|
||||
{
|
||||
ext.Description = json[lit("description")].toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << "Extension" << QString(ext.Name) << "is corrupt, no description entry";
|
||||
continue;
|
||||
}
|
||||
|
||||
if(json.contains(lit("author")))
|
||||
{
|
||||
ext.Author = json[lit("author")].toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << "Extension" << QString(ext.Name) << "is corrupt, no author entry";
|
||||
continue;
|
||||
}
|
||||
|
||||
if(json.contains(lit("url")))
|
||||
{
|
||||
ext.URL = json[lit("url")].toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
qCritical() << "Extension" << QString(ext.Name) << "is corrupt, no URL entry";
|
||||
continue;
|
||||
}
|
||||
|
||||
if(json.contains(lit("minimum_renderdoc")))
|
||||
{
|
||||
QString minVer = json[lit("minimum_renderdoc")].toString();
|
||||
|
||||
QRegularExpression re(lit("([0-9]*).([0-9]*)"));
|
||||
QRegularExpressionMatch match = re.match(minVer);
|
||||
|
||||
bool ok = false, badversion = false;
|
||||
|
||||
if(match.hasMatch())
|
||||
{
|
||||
int major = match.captured(1).toInt(&ok);
|
||||
|
||||
if(ok)
|
||||
{
|
||||
int minor = match.captured(2).toInt(&ok);
|
||||
|
||||
// if it needs a higher major version, we can't load it
|
||||
if(major > RENDERDOC_VERSION_MAJOR)
|
||||
badversion = true;
|
||||
|
||||
// if major versions are the same and it needs a higher minor, we can't load it either
|
||||
if(major == RENDERDOC_VERSION_MAJOR && minor > RENDERDOC_VERSION_MINOR)
|
||||
badversion = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(!ok)
|
||||
{
|
||||
qCritical() << "Extension" << QString(ext.Name)
|
||||
<< "is corrupt, minimum_renderdoc doesn't match a MAJOR.MINOR version";
|
||||
continue;
|
||||
}
|
||||
|
||||
if(badversion)
|
||||
{
|
||||
qInfo() << "Extension" << QString(ext.Name) << "declares minimum_renderdoc" << minVer
|
||||
<< "so skipping";
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
ret.push_back(ext);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool CaptureContext::IsExtensionLoaded(rdcstr name)
|
||||
{
|
||||
return m_ExtensionObjects.contains(name);
|
||||
}
|
||||
|
||||
bool CaptureContext::LoadExtension(rdcstr name)
|
||||
{
|
||||
bool ret = false;
|
||||
|
||||
PythonContext::ProcessExtensionWork([this, &ret, name]() {
|
||||
for(QObject *o : m_ExtensionObjects[name])
|
||||
delete o;
|
||||
|
||||
m_ExtensionObjects[name].clear();
|
||||
|
||||
ret = PythonContext::LoadExtension(*this, name);
|
||||
|
||||
if(ret)
|
||||
{
|
||||
m_ExtensionObjects[name].swap(m_PendingExtensionObjects);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_ExtensionObjects.remove(name);
|
||||
|
||||
for(QObject *o : m_PendingExtensionObjects)
|
||||
delete o;
|
||||
|
||||
m_PendingExtensionObjects.clear();
|
||||
}
|
||||
});
|
||||
|
||||
m_MainWindow->CleanMenus();
|
||||
|
||||
return ret;
|
||||
}
|
||||
void CaptureContext::LoadCapture(const rdcstr &captureFile, const rdcstr &origFilename,
|
||||
bool temporary, bool local)
|
||||
{
|
||||
|
||||
@@ -52,7 +52,7 @@ class TimelineBar;
|
||||
class PythonShell;
|
||||
class ResourceInspector;
|
||||
|
||||
class CaptureContext : public ICaptureContext
|
||||
class CaptureContext : public ICaptureContext, IExtensionManager
|
||||
{
|
||||
Q_DECLARE_TR_FUNCTIONS(CaptureContext);
|
||||
|
||||
@@ -65,6 +65,13 @@ public:
|
||||
|
||||
rdcstr TempCaptureFilename(const rdcstr &appname) override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// IExtensionManager
|
||||
|
||||
rdcarray<ExtensionMetadata> GetInstalledExtensions() override;
|
||||
bool IsExtensionLoaded(rdcstr name) override;
|
||||
bool LoadExtension(rdcstr name) override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Control functions
|
||||
|
||||
@@ -99,6 +106,7 @@ public:
|
||||
// Accessors
|
||||
|
||||
IReplayManager &Replay() override { return m_Replay; }
|
||||
IExtensionManager &Extensions() override { return *this; }
|
||||
bool IsCaptureLoaded() override { return m_CaptureLoaded; }
|
||||
bool IsCaptureLocal() override { return m_CaptureLocal; }
|
||||
bool IsCaptureTemporary() override { return m_CaptureTemporary; }
|
||||
@@ -330,6 +338,9 @@ private:
|
||||
|
||||
QIcon *m_Icon = NULL;
|
||||
|
||||
QList<QObject *> m_PendingExtensionObjects;
|
||||
QMap<rdcstr, QList<QObject *>> m_ExtensionObjects;
|
||||
|
||||
// Windows
|
||||
MainWindow *m_MainWindow = NULL;
|
||||
EventBrowser *m_EventBrowser = NULL;
|
||||
|
||||
@@ -354,6 +354,8 @@ DECLARE_REFLECTION_STRUCT(BugReport);
|
||||
\
|
||||
CONFIG_SETTING(public, QVariantList, rdcarray<BugReport>, CrashReport_ReportedBugs) \
|
||||
\
|
||||
CONFIG_SETTING(public, QVariantList, rdcarray<rdcstr>, AlwaysLoad_Extensions) \
|
||||
\
|
||||
CONFIG_SETTING(private, QVariantMap, rdcstrpairs, ConfigSettings) \
|
||||
\
|
||||
CONFIG_SETTING(private, QVariantList, rdcarray<RemoteHost>, RemoteHostList)
|
||||
@@ -691,6 +693,12 @@ For more information about some of these settings that are user-facing see
|
||||
|
||||
A list of :class:`BugReport` detailing previously submitted bugs that we're watching for updates.
|
||||
|
||||
.. data:: AlwaysLoad_Extensions
|
||||
|
||||
A list of strings with extension packages to always load on startup, without needing manual
|
||||
enabling.
|
||||
|
||||
|
||||
)");
|
||||
class PersistantConfig
|
||||
{
|
||||
|
||||
@@ -1022,6 +1022,110 @@ protected:
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(IRGPInterop);
|
||||
|
||||
|
||||
DOCUMENT("The metadata for an extension.");
|
||||
struct ExtensionMetadata
|
||||
{
|
||||
DOCUMENT("");
|
||||
bool operator==(const ExtensionMetadata &o) const
|
||||
{
|
||||
return ExtensionAPI == o.ExtensionAPI && FilePath == o.FilePath && Package == o.Package &&
|
||||
Name == o.Name && Version == o.Version && Author == o.Author && URL == o.URL &&
|
||||
Description == o.Description;
|
||||
}
|
||||
bool operator<(const ExtensionMetadata &o) const
|
||||
{
|
||||
if(!(ExtensionAPI == o.ExtensionAPI))
|
||||
return ExtensionAPI < o.ExtensionAPI;
|
||||
if(!(FilePath == o.FilePath))
|
||||
return FilePath < o.FilePath;
|
||||
if(!(Package == o.Package))
|
||||
return Package < o.Package;
|
||||
if(!(Name == o.Name))
|
||||
return Name < o.Name;
|
||||
if(!(Version == o.Version))
|
||||
return Version < o.Version;
|
||||
if(!(Author == o.Author))
|
||||
return Author < o.Author;
|
||||
if(!(URL == o.URL))
|
||||
return URL < o.URL;
|
||||
if(!(Description == o.Description))
|
||||
return Description < o.Description;
|
||||
return false;
|
||||
}
|
||||
|
||||
DOCUMENT("The version of the extension API that this extension is written against");
|
||||
int ExtensionAPI;
|
||||
|
||||
DOCUMENT("The location of this package on disk");
|
||||
rdcstr FilePath;
|
||||
|
||||
DOCUMENT("The python package for this extension, e.g. foo.bar");
|
||||
rdcstr Package;
|
||||
|
||||
DOCUMENT("The short friendly name for the extension");
|
||||
rdcstr Name;
|
||||
|
||||
DOCUMENT("The version of the extension");
|
||||
rdcstr Version;
|
||||
|
||||
DOCUMENT("The author of the extension, optionally with an email contact");
|
||||
rdcstr Author;
|
||||
|
||||
DOCUMENT("The URL for where the extension is fetched from");
|
||||
rdcstr URL;
|
||||
|
||||
DOCUMENT("A longer description of what the extension does");
|
||||
rdcstr Description;
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(ExtensionMetadata);
|
||||
|
||||
DOCUMENT(R"(A manager for listing available and active extensions, as well as the interface for
|
||||
extensions to register hooks and additional functionality.
|
||||
|
||||
.. function:: ExtensionCallback(context)
|
||||
|
||||
Not a member function - the signature for any ``ExtensionCallback`` callbacks.
|
||||
|
||||
Callback for extensions to register entry points with, used in many situations depending on how it
|
||||
was registered.
|
||||
|
||||
:param CaptureContext context: The current capture context.
|
||||
)");
|
||||
struct IExtensionManager
|
||||
{
|
||||
typedef std::function<void(ICaptureContext *ctx)> ExtensionCallback;
|
||||
|
||||
DOCUMENT(R"(Retrieve a list of installed extensions.
|
||||
|
||||
:return: The list of installed extensions.
|
||||
:rtype: ``list`` of :class:`ExtensionMetadata`.
|
||||
)");
|
||||
virtual rdcarray<ExtensionMetadata> GetInstalledExtensions() = 0;
|
||||
|
||||
DOCUMENT(R"(Check if an installed extension is enabled.
|
||||
|
||||
:param str name: The qualified name of the extension, e.g. ``foo.bar``
|
||||
:return: If the extension is enabled or not.
|
||||
:rtype: bool
|
||||
)");
|
||||
virtual bool IsExtensionLoaded(rdcstr name) = 0;
|
||||
|
||||
DOCUMENT(R"(Enable an extension by name. If the extension is already enabled, this will reload it.
|
||||
|
||||
:param str name: The qualified name of the extension, e.g. ``foo.bar``
|
||||
)");
|
||||
virtual bool LoadExtension(rdcstr name) = 0;
|
||||
|
||||
protected:
|
||||
DOCUMENT("");
|
||||
IExtensionManager() = default;
|
||||
~IExtensionManager() = default;
|
||||
};
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(IExtensionManager);
|
||||
|
||||
DOCUMENT("The capture context that the python script is running in.")
|
||||
struct ICaptureContext
|
||||
{
|
||||
@@ -1924,6 +2028,13 @@ capture's API.
|
||||
)");
|
||||
virtual PersistantConfig &Config() = 0;
|
||||
|
||||
DOCUMENT(R"(Retrieve the manager for extensions.
|
||||
|
||||
:return: The current extension manager.
|
||||
:rtype: ExtensionManager
|
||||
)");
|
||||
virtual IExtensionManager &Extensions() = 0;
|
||||
|
||||
protected:
|
||||
ICaptureContext() = default;
|
||||
~ICaptureContext() = default;
|
||||
|
||||
@@ -506,6 +506,17 @@ bool PythonContext::LoadExtension(ICaptureContext &ctx, const rdcstr &extension)
|
||||
{
|
||||
qInfo() << "Reloading " << QString(extension);
|
||||
|
||||
// call unregister() if it exists
|
||||
PyObject *unregister_func = PyObject_GetAttrString(extensions[extension], "unregister");
|
||||
|
||||
if(unregister_func)
|
||||
{
|
||||
PyObject *retval = PyObject_CallFunction(unregister_func, "");
|
||||
|
||||
// discard the return value, regardless of error we don't abort the reload
|
||||
Py_XDECREF(retval);
|
||||
}
|
||||
|
||||
// if the extension is a package, we need to manually reload any loaded submodules
|
||||
PyObject *sysmodules = PyObject_GetAttrString(sysobj, "modules");
|
||||
|
||||
|
||||
@@ -83,6 +83,7 @@ TEMPLATE_ARRAY_INSTANTIATE(rdcarray, EventBookmark)
|
||||
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, ShaderProcessingTool)
|
||||
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, rdcstrpair)
|
||||
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, BugReport)
|
||||
TEMPLATE_ARRAY_INSTANTIATE(rdcarray, ExtensionMetadata)
|
||||
TEMPLATE_ARRAY_INSTANTIATE_PTR(rdcarray, ICaptureViewer)
|
||||
|
||||
// unignore the function from above
|
||||
|
||||
@@ -0,0 +1,241 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Baldur Karlsson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#include "ExtensionManager.h"
|
||||
#include <QDesktopServices>
|
||||
#include <QFileInfo>
|
||||
#include <QKeyEvent>
|
||||
#include <QRegularExpression>
|
||||
#include "Code/Interface/QRDInterface.h"
|
||||
#include "Code/Resources.h"
|
||||
#include "Widgets/Extended/RDHeaderView.h"
|
||||
#include "Windows/MainWindow.h"
|
||||
#include "ui_ExtensionManager.h"
|
||||
|
||||
Q_DECLARE_METATYPE(ExtensionMetadata);
|
||||
|
||||
ExtensionManager::ExtensionManager(ICaptureContext &ctx)
|
||||
: QDialog(NULL), ui(new Ui::ExtensionManager), m_Ctx(ctx)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
{
|
||||
RDHeaderView *header = new RDHeaderView(Qt::Horizontal, this);
|
||||
ui->extensions->setHeader(header);
|
||||
|
||||
ui->extensions->setColumns({tr("Package"), tr("Name"), tr("Loaded")});
|
||||
header->setColumnStretchHints({1, 4, -1});
|
||||
}
|
||||
|
||||
ui->name->setText(lit("---"));
|
||||
ui->version->setText(lit("---"));
|
||||
ui->author->setText(lit("---"));
|
||||
ui->URL->setText(lit("---"));
|
||||
ui->reload->setEnabled(false);
|
||||
ui->alwaysLoad->setEnabled(false);
|
||||
|
||||
QObject::connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
|
||||
|
||||
QString extensionFolder = configFilePath("extensions");
|
||||
|
||||
m_Extensions = m_Ctx.Extensions().GetInstalledExtensions();
|
||||
|
||||
if(m_Extensions.isEmpty())
|
||||
{
|
||||
ui->extensions->addTopLevelItem(
|
||||
new RDTreeWidgetItem({QString(), lit("No extensions found available"), QString()}));
|
||||
ui->extensions->addTopLevelItem(new RDTreeWidgetItem(
|
||||
{QString(), lit("Create packages in %1").arg(extensionFolder), QString()}));
|
||||
}
|
||||
else
|
||||
{
|
||||
for(const ExtensionMetadata &e : m_Extensions)
|
||||
{
|
||||
RDTreeWidgetItem *item = new RDTreeWidgetItem({e.Package, e.Name, QString()});
|
||||
|
||||
item->setCheckState(
|
||||
2, m_Ctx.Extensions().IsExtensionLoaded(e.Package) ? Qt::Checked : Qt::Unchecked);
|
||||
|
||||
ui->extensions->addTopLevelItem(item);
|
||||
}
|
||||
|
||||
ui->extensions->setCurrentItem(ui->extensions->topLevelItem(0));
|
||||
}
|
||||
}
|
||||
|
||||
ExtensionManager::~ExtensionManager()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ExtensionManager::on_reload_clicked()
|
||||
{
|
||||
RDTreeWidgetItem *item = ui->extensions->currentItem();
|
||||
if(!item)
|
||||
return;
|
||||
|
||||
int idx = ui->extensions->indexOfTopLevelItem(item);
|
||||
|
||||
if(idx >= 0 && idx < m_Extensions.count())
|
||||
{
|
||||
const ExtensionMetadata &e = m_Extensions[idx];
|
||||
if(!e.Name.isEmpty())
|
||||
{
|
||||
// if the load succeeds, set us as checked. Otherwise, unchecked
|
||||
if(m_Ctx.Extensions().LoadExtension(e.Package))
|
||||
{
|
||||
item->setCheckState(2, Qt::Checked);
|
||||
}
|
||||
else
|
||||
{
|
||||
item->setCheckState(2, Qt::Unchecked);
|
||||
RDDialog::critical(this, tr("Failed to load extension"),
|
||||
tr("Failed to load extension '%1'.\n"
|
||||
"Check the diagnostic log for python errors")
|
||||
.arg(e.Name));
|
||||
}
|
||||
|
||||
update_currentItem(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExtensionManager::on_openLocation_clicked()
|
||||
{
|
||||
if(m_Extensions.empty())
|
||||
{
|
||||
QDesktopServices::openUrl(QString(configFilePath("extensions")));
|
||||
return;
|
||||
}
|
||||
|
||||
RDTreeWidgetItem *item = ui->extensions->currentItem();
|
||||
if(!item)
|
||||
return;
|
||||
|
||||
int idx = ui->extensions->indexOfTopLevelItem(item);
|
||||
|
||||
if(idx >= 0 && idx < m_Extensions.count())
|
||||
{
|
||||
const ExtensionMetadata &e = m_Extensions[idx];
|
||||
if(!e.Name.isEmpty())
|
||||
{
|
||||
QDesktopServices::openUrl(QFileInfo(e.FilePath).absoluteFilePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExtensionManager::on_alwaysLoad_toggled(bool checked)
|
||||
{
|
||||
RDTreeWidgetItem *item = ui->extensions->currentItem();
|
||||
if(!item)
|
||||
return;
|
||||
|
||||
int idx = ui->extensions->indexOfTopLevelItem(item);
|
||||
|
||||
if(idx >= 0 && idx < m_Extensions.count())
|
||||
{
|
||||
const ExtensionMetadata &e = m_Extensions[idx];
|
||||
if(!e.Name.isEmpty())
|
||||
{
|
||||
m_Ctx.Config().AlwaysLoad_Extensions.removeOne(e.Package);
|
||||
if(checked)
|
||||
m_Ctx.Config().AlwaysLoad_Extensions.push_back(e.Package);
|
||||
|
||||
m_Ctx.Config().Save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExtensionManager::on_extensions_currentItemChanged(RDTreeWidgetItem *item, RDTreeWidgetItem *)
|
||||
{
|
||||
update_currentItem(item);
|
||||
}
|
||||
|
||||
void ExtensionManager::on_extensions_itemChanged(RDTreeWidgetItem *item, int col)
|
||||
{
|
||||
if(col == 2)
|
||||
{
|
||||
ui->extensions->setCurrentItem(item);
|
||||
|
||||
bool loaded = m_Ctx.Extensions().IsExtensionLoaded(item->text(0));
|
||||
|
||||
// if the extension is loaded, don't allow unchecking
|
||||
if(loaded && item->checkState(2) != Qt::Checked)
|
||||
{
|
||||
item->setCheckState(2, Qt::Checked);
|
||||
return;
|
||||
}
|
||||
|
||||
// if the extension is unloaded, if we're now checked then try to load it. If
|
||||
// we're unchecked allow that (it is a code-change after we failed to load)
|
||||
if(!loaded)
|
||||
{
|
||||
if(item->checkState(2) == Qt::Checked)
|
||||
on_reload_clicked();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ExtensionManager::update_currentItem(RDTreeWidgetItem *item)
|
||||
{
|
||||
if(!item)
|
||||
return;
|
||||
|
||||
if(item != ui->extensions->currentItem())
|
||||
{
|
||||
ui->extensions->setCurrentItem(item);
|
||||
return;
|
||||
}
|
||||
|
||||
int idx = ui->extensions->indexOfTopLevelItem(item);
|
||||
|
||||
if(idx >= 0 && idx < m_Extensions.count())
|
||||
{
|
||||
const ExtensionMetadata &e = m_Extensions[idx];
|
||||
if(!e.Name.isEmpty())
|
||||
{
|
||||
QRegularExpression authRE(lit("^(.*) <(.*)>$"));
|
||||
|
||||
ui->name->setText(e.Name);
|
||||
ui->version->setText(e.Version);
|
||||
ui->URL->setText(QFormatStr("<a href=\"%1\">%1</a>").arg(e.URL));
|
||||
ui->description->setText(e.Description);
|
||||
|
||||
QRegularExpressionMatch match = authRE.match(QString(e.Author).trimmed());
|
||||
|
||||
if(match.hasMatch() && match.captured(2).contains(QLatin1Char('@')))
|
||||
ui->author->setText(
|
||||
QFormatStr("<a href=\"mailto:%2\">%1</a>").arg(match.captured(1)).arg(match.captured(2)));
|
||||
else
|
||||
ui->author->setText(e.Author);
|
||||
|
||||
bool loaded = item->checkState(2) == Qt::Checked;
|
||||
ui->reload->setEnabled(true);
|
||||
ui->reload->setText(loaded ? tr("Reload") : tr("Load"));
|
||||
ui->alwaysLoad->setEnabled(loaded);
|
||||
|
||||
ui->alwaysLoad->setChecked(m_Ctx.Config().AlwaysLoad_Extensions.contains(e.Package));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2018 Baldur Karlsson
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
******************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <QDialog>
|
||||
#include <QList>
|
||||
#include <QSemaphore>
|
||||
#include "Code/Interface/QRDInterface.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ExtensionManager;
|
||||
}
|
||||
|
||||
class RDTreeWidgetItem;
|
||||
struct ICaptureContext;
|
||||
class MainWindow;
|
||||
|
||||
class ExtensionManager : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ExtensionManager(ICaptureContext &ctx);
|
||||
~ExtensionManager();
|
||||
|
||||
private slots:
|
||||
// automatic slots
|
||||
void on_reload_clicked();
|
||||
void on_openLocation_clicked();
|
||||
void on_alwaysLoad_toggled(bool checked);
|
||||
void on_extensions_currentItemChanged(RDTreeWidgetItem *item, RDTreeWidgetItem *);
|
||||
void on_extensions_itemChanged(RDTreeWidgetItem *item, int col);
|
||||
|
||||
private:
|
||||
void update_currentItem(RDTreeWidgetItem *item);
|
||||
|
||||
Ui::ExtensionManager *ui;
|
||||
ICaptureContext &m_Ctx;
|
||||
|
||||
rdcarray<ExtensionMetadata> m_Extensions;
|
||||
};
|
||||
@@ -0,0 +1,244 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ExtensionManager</class>
|
||||
<widget class="QDialog" name="ExtensionManager">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>556</width>
|
||||
<height>544</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Extension Manager</string>
|
||||
</property>
|
||||
<property name="modal">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Extension List</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="RDTreeWidget" name="extensions">
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="title">
|
||||
<string>Details</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="text">
|
||||
<string>URL:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Name:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Author:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Version:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="name">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QLabel" name="author">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QLabel" name="URL">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="openExternalLinks">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="openLocation">
|
||||
<property name="text">
|
||||
<string>Open Location</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="reload">
|
||||
<property name="text">
|
||||
<string>Reload</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="alwaysLoad">
|
||||
<property name="text">
|
||||
<string>Always Load</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Description:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTop|Qt::AlignTrailing</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QLabel" name="version">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QTextEdit" name="description">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Panel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="textInteractionFlags">
|
||||
<set>Qt::NoTextInteraction</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>RDTreeWidget</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>Widgets/Extended/RDTreeWidget.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "Windows/Dialogs/AboutDialog.h"
|
||||
#include "Windows/Dialogs/CaptureDialog.h"
|
||||
#include "Windows/Dialogs/CrashDialog.h"
|
||||
#include "Windows/Dialogs/ExtensionManager.h"
|
||||
#include "Windows/Dialogs/LiveCapture.h"
|
||||
#include "Windows/Dialogs/RemoteManager.h"
|
||||
#include "Windows/Dialogs/SettingsDialog.h"
|
||||
@@ -2432,6 +2433,12 @@ void MainWindow::on_action_Attach_to_Running_Instance_triggered()
|
||||
on_action_Manage_Remote_Servers_triggered();
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Manage_Extensions_triggered()
|
||||
{
|
||||
ExtensionManager manager(m_Ctx);
|
||||
RDDialog::show(&manager);
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Manage_Remote_Servers_triggered()
|
||||
{
|
||||
RemoteManager *rm = new RemoteManager(m_Ctx, this);
|
||||
|
||||
@@ -131,6 +131,7 @@ private slots:
|
||||
void on_action_Open_RGP_Profile_triggered();
|
||||
void on_action_Create_RGP_Profile_triggered();
|
||||
void on_action_Attach_to_Running_Instance_triggered();
|
||||
void on_action_Manage_Extensions_triggered();
|
||||
void on_action_Manage_Remote_Servers_triggered();
|
||||
void on_action_Settings_triggered();
|
||||
void on_action_View_Documentation_triggered();
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
<addaction name="action_Open_RGP_Profile"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_Settings"/>
|
||||
<addaction name="action_Manage_Extensions"/>
|
||||
<addaction name="action_Manage_Remote_Servers"/>
|
||||
<addaction name="separator"/>
|
||||
</widget>
|
||||
@@ -466,6 +467,11 @@
|
||||
<string>Open RGP Profile</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Manage_Extensions">
|
||||
<property name="text">
|
||||
<string>Manage Extensions</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<customwidgets>
|
||||
|
||||
@@ -52,6 +52,7 @@ struct CaptureContextInvoker : ICaptureContext
|
||||
{
|
||||
return m_Ctx.TempCaptureFilename(appname);
|
||||
}
|
||||
virtual IExtensionManager &Extensions() override { return m_Ctx.Extensions(); }
|
||||
virtual IReplayManager &Replay() override { return m_Ctx.Replay(); }
|
||||
virtual bool IsCaptureLoaded() override { return m_Ctx.IsCaptureLoaded(); }
|
||||
virtual bool IsCaptureLocal() override { return m_Ctx.IsCaptureLocal(); }
|
||||
|
||||
@@ -217,6 +217,7 @@ SOURCES += Code/qrenderdoc.cpp \
|
||||
Windows/Dialogs/SuggestRemoteDialog.cpp \
|
||||
Windows/Dialogs/VirtualFileDialog.cpp \
|
||||
Windows/Dialogs/RemoteManager.cpp \
|
||||
Windows/Dialogs/ExtensionManager.cpp \
|
||||
Windows/PixelHistoryView.cpp \
|
||||
Widgets/PipelineFlowChart.cpp \
|
||||
Windows/Dialogs/EnvironmentEditor.cpp \
|
||||
@@ -291,6 +292,7 @@ HEADERS += Code/CaptureContext.h \
|
||||
Windows/Dialogs/SuggestRemoteDialog.h \
|
||||
Windows/Dialogs/VirtualFileDialog.h \
|
||||
Windows/Dialogs/RemoteManager.h \
|
||||
Windows/Dialogs/ExtensionManager.h \
|
||||
Windows/PixelHistoryView.h \
|
||||
Widgets/PipelineFlowChart.h \
|
||||
Windows/Dialogs/EnvironmentEditor.h \
|
||||
@@ -331,6 +333,7 @@ FORMS += Windows/Dialogs/AboutDialog.ui \
|
||||
Windows/Dialogs/SuggestRemoteDialog.ui \
|
||||
Windows/Dialogs/VirtualFileDialog.ui \
|
||||
Windows/Dialogs/RemoteManager.ui \
|
||||
Windows/Dialogs/ExtensionManager.ui \
|
||||
Windows/PixelHistoryView.ui \
|
||||
Windows/Dialogs/EnvironmentEditor.ui \
|
||||
Widgets/FindReplace.ui \
|
||||
|
||||
@@ -613,6 +613,7 @@
|
||||
<ClCompile Include="$(IntDir)generated\moc_EnvironmentEditor.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_OrderedListEditor.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_RemoteManager.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_ExtensionManager.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_PerformanceCounterSelection.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_PerformanceCounterViewer.cpp" />
|
||||
<ClCompile Include="$(IntDir)generated\moc_PipelineStateViewer.cpp" />
|
||||
@@ -726,6 +727,7 @@
|
||||
<ClCompile Include="Windows\Dialogs\EnvironmentEditor.cpp" />
|
||||
<ClCompile Include="Windows\Dialogs\PerformanceCounterSelection.cpp" />
|
||||
<ClCompile Include="Windows\Dialogs\RemoteManager.cpp" />
|
||||
<ClCompile Include="Windows\Dialogs\ExtensionManager.cpp" />
|
||||
<ClCompile Include="Windows\Dialogs\SettingsDialog.cpp" />
|
||||
<ClCompile Include="Windows\Dialogs\SuggestRemoteDialog.cpp" />
|
||||
<ClCompile Include="Windows\Dialogs\TextureSaveDialog.cpp" />
|
||||
@@ -934,6 +936,7 @@
|
||||
<ClInclude Include="$(IntDir)generated\ui_MainWindow.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_EnvironmentEditor.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_RemoteManager.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_ExtensionManager.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_PerformanceCounterSelection.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_PipelineStateViewer.h" />
|
||||
<ClInclude Include="$(IntDir)generated\ui_ResourcePreview.h" />
|
||||
@@ -1209,6 +1212,12 @@
|
||||
<Message>MOC %(Filename).h</Message>
|
||||
<Outputs>$(IntDir)generated\moc_%(Filename).cpp</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Windows\Dialogs\ExtensionManager.h">
|
||||
<AdditionalInputs>%(Fullpath);$(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe;%(AdditionalInputs)</AdditionalInputs>
|
||||
<Command>"$(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe" -DUNICODE -DWIN32 -DWIN64 -D_WIN32 -D_WIN64 -DRENDERDOC_PLATFORM_WIN32 -DSCINTILLA_QT=1 -DSCI_LEXER=1 -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -D_MSC_VER=1900 -I"$(ProjectDir)." -I"$(SolutionDir)\renderdoc\api\replay" -I"$(ProjectDir)3rdparty\qt\$(Platform)\mkspecs/win32-msvc2015" -I"$(ProjectDir)3rdparty\qt\include" -I"$(ProjectDir)3rdparty\qt\include\QtWidgets" -I"$(ProjectDir)3rdparty\qt\include\QtGui" -I"$(ProjectDir)3rdparty\qt\include\QtCore" "%(Fullpath)" -o "$(IntDir)generated\moc_%(Filename).cpp"</Command>
|
||||
<Message>MOC %(Filename).h</Message>
|
||||
<Outputs>$(IntDir)generated\moc_%(Filename).cpp</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Windows\Dialogs\SettingsDialog.h">
|
||||
<AdditionalInputs>%(Fullpath);$(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe;%(AdditionalInputs)</AdditionalInputs>
|
||||
<Command>"$(ProjectDir)3rdparty\qt\$(Platform)\bin\moc.exe" -DUNICODE -DWIN32 -DWIN64 -D_WIN32 -D_WIN64 -DRENDERDOC_PLATFORM_WIN32 -DSCINTILLA_QT=1 -DSCI_LEXER=1 -DQT_NO_DEBUG -DQT_WIDGETS_LIB -DQT_GUI_LIB -DQT_CORE_LIB -D_MSC_VER=1900 -I"$(ProjectDir)." -I"$(SolutionDir)\renderdoc\api\replay" -I"$(ProjectDir)3rdparty\qt\$(Platform)\mkspecs/win32-msvc2015" -I"$(ProjectDir)3rdparty\qt\include" -I"$(ProjectDir)3rdparty\qt\include\QtWidgets" -I"$(ProjectDir)3rdparty\qt\include\QtGui" -I"$(ProjectDir)3rdparty\qt\include\QtCore" "%(Fullpath)" -o "$(IntDir)generated\moc_%(Filename).cpp"</Command>
|
||||
@@ -1456,6 +1465,12 @@
|
||||
<Message>UIC %(Filename).ui</Message>
|
||||
<Outputs>$(IntDir)generated\ui_%(Filename).h</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Windows\Dialogs\ExtensionManager.ui">
|
||||
<AdditionalInputs>%(Fullpath);$(ProjectDir)3rdparty\qt\$(Platform)\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs>
|
||||
<Command>"$(ProjectDir)3rdparty\qt\$(Platform)\bin\uic.exe" "%(Fullpath)" -o "$(IntDir)generated\ui_%(Filename).h"</Command>
|
||||
<Message>UIC %(Filename).ui</Message>
|
||||
<Outputs>$(IntDir)generated\ui_%(Filename).h</Outputs>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Windows\Dialogs\SettingsDialog.ui">
|
||||
<AdditionalInputs>%(Fullpath);$(ProjectDir)3rdparty\qt\$(Platform)\bin\uic.exe;%(AdditionalInputs)</AdditionalInputs>
|
||||
<Command>"$(ProjectDir)3rdparty\qt\$(Platform)\bin\uic.exe" "%(Fullpath)" -o "$(IntDir)generated\ui_%(Filename).h"</Command>
|
||||
|
||||
@@ -711,6 +711,12 @@
|
||||
<ClCompile Include="Code\Interface\ShaderProcessingTool.cpp">
|
||||
<Filter>Code\Interface</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="$(IntDir)generated\moc_ExtensionManager.cpp">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Windows\Dialogs\ExtensionManager.cpp">
|
||||
<Filter>Windows\Dialogs</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="3rdparty\flowlayout\FlowLayout.h">
|
||||
@@ -1061,6 +1067,9 @@
|
||||
<ClInclude Include="Code\RGPInterop.h">
|
||||
<Filter>Code</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="$(IntDir)generated\ui_ExtensionManager.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Code\pyrenderdoc\pyconversion.h">
|
||||
@@ -1436,6 +1445,12 @@
|
||||
<CustomBuild Include="Widgets\CollapseGroupBox.h">
|
||||
<Filter>Widgets</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Windows\Dialogs\ExtensionManager.ui">
|
||||
<Filter>Windows\Dialogs</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="Windows\Dialogs\ExtensionManager.h">
|
||||
<Filter>Windows\Dialogs</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Resources\action.png">
|
||||
|
||||
Reference in New Issue
Block a user