mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-06 01:50:38 +00:00
Add a mostly-complete capture dialog
This commit is contained in:
@@ -122,6 +122,25 @@ void RenderManager::CloseThread()
|
||||
m_Thread = NULL;
|
||||
}
|
||||
|
||||
uint32_t RenderManager::ExecuteAndInject(const QString &exe, const QString &workingDir,
|
||||
const QString &cmdLine,
|
||||
const QList<EnvironmentModification> &env,
|
||||
const QString &logfile, CaptureOptions opts)
|
||||
{
|
||||
// if (m_Remote == null)
|
||||
{
|
||||
// TODO env
|
||||
return RENDERDOC_ExecuteAndInject(exe.toUtf8().data(), workingDir.toUtf8().data(),
|
||||
cmdLine.toUtf8().data(), NULL, logfile.toUtf8().data(), &opts,
|
||||
false);
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void RenderManager::PushInvoke(RenderManager::InvokeHandle *cmd)
|
||||
{
|
||||
if(m_Thread == NULL || !m_Thread->isRunning() || !m_Running)
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <QSemaphore>
|
||||
#include <QString>
|
||||
#include <QThread>
|
||||
#include <QVariantMap>
|
||||
#include <QWaitCondition>
|
||||
#include <functional>
|
||||
#include "renderdoc_replay.h"
|
||||
@@ -40,6 +41,61 @@ class LambdaThread;
|
||||
#define INVOKE_MEMFN(function) \
|
||||
m_Ctx->Renderer()->AsyncInvoke([this](IReplayRenderer *r) { function(r); });
|
||||
|
||||
struct EnvironmentModification
|
||||
{
|
||||
QString variable;
|
||||
QString value;
|
||||
|
||||
EnvironmentModificationType type;
|
||||
EnvironmentSeparator separator;
|
||||
|
||||
QString GetTypeString() const
|
||||
{
|
||||
QString ret;
|
||||
|
||||
if(type == eEnvMod_Append)
|
||||
ret = QString("Append, %1").arg("TODO");
|
||||
else if(type == eEnvMod_Prepend)
|
||||
ret = QString("Prepend, %1").arg("TODO");
|
||||
else
|
||||
ret = "Set";
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString GetDescription() const
|
||||
{
|
||||
QString ret;
|
||||
|
||||
if(type == eEnvMod_Append)
|
||||
ret = QString("Append %1 with %2 using %3").arg(variable).arg(value).arg("TODO");
|
||||
else if(type == eEnvMod_Prepend)
|
||||
ret = QString("Prepend %1 with %2 using %3").arg(variable).arg(value).arg("TODO");
|
||||
else
|
||||
ret = QString("Set %1 to %2").arg(variable).arg(value);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
QVariantMap toJSON() const
|
||||
{
|
||||
QVariantMap ret;
|
||||
ret["variable"] = variable;
|
||||
ret["value"] = value;
|
||||
ret["type"] = "Append"; // TODO
|
||||
ret["separator"] = "Semi-colon"; // TODO
|
||||
return ret;
|
||||
}
|
||||
|
||||
void fromJSON(const QVariantMap &data)
|
||||
{
|
||||
variable = data["variable"].toString();
|
||||
value = data["value"].toString();
|
||||
type = eEnvMod_Append; // TODO
|
||||
separator = eEnvSep_SemiColon; // TODO
|
||||
}
|
||||
};
|
||||
|
||||
class RenderManager
|
||||
{
|
||||
public:
|
||||
@@ -58,6 +114,10 @@ public:
|
||||
|
||||
void CloseThread();
|
||||
|
||||
uint32_t ExecuteAndInject(const QString &exe, const QString &workingDir, const QString &cmdLine,
|
||||
const QList<EnvironmentModification> &env, const QString &logfile,
|
||||
CaptureOptions opts);
|
||||
|
||||
private:
|
||||
struct InvokeHandle
|
||||
{
|
||||
|
||||
@@ -0,0 +1,619 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 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 "CaptureDialog.h"
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QStandardItemModel>
|
||||
#include "Code/QRDUtils.h"
|
||||
#include "FlowLayout.h"
|
||||
#include "ui_CaptureDialog.h"
|
||||
|
||||
#define JSON_ID "rdocCaptureSettings"
|
||||
#define JSON_VER 1
|
||||
|
||||
Q_DECLARE_METATYPE(CaptureSettings);
|
||||
|
||||
CaptureSettings::CaptureSettings()
|
||||
{
|
||||
Inject = false;
|
||||
AutoStart = false;
|
||||
RENDERDOC_GetDefaultCaptureOptions(&Options);
|
||||
}
|
||||
|
||||
QVariantMap CaptureSettings::toJSON() const
|
||||
{
|
||||
QVariantMap ret;
|
||||
|
||||
ret["AutoStart"] = AutoStart;
|
||||
|
||||
ret["Executable"] = Executable;
|
||||
ret["WorkingDir"] = WorkingDir;
|
||||
ret["CmdLine"] = CmdLine;
|
||||
|
||||
QVariantList env;
|
||||
for(int i = 0; i < Environment.size(); i++)
|
||||
env.push_back(Environment[i].toJSON());
|
||||
ret["Environment"] = env;
|
||||
|
||||
QVariantMap opts;
|
||||
opts["AllowVSync"] = Options.AllowVSync;
|
||||
opts["AllowFullscreen"] = Options.AllowFullscreen;
|
||||
opts["APIValidation"] = Options.APIValidation;
|
||||
opts["CaptureCallstacks"] = Options.CaptureCallstacks;
|
||||
opts["CaptureCallstacksOnlyDraws"] = Options.CaptureCallstacksOnlyDraws;
|
||||
opts["DelayForDebugger"] = Options.DelayForDebugger;
|
||||
opts["VerifyMapWrites"] = Options.VerifyMapWrites;
|
||||
opts["HookIntoChildren"] = Options.HookIntoChildren;
|
||||
opts["RefAllResources"] = Options.RefAllResources;
|
||||
opts["SaveAllInitials"] = Options.SaveAllInitials;
|
||||
opts["CaptureAllCmdLists"] = Options.CaptureAllCmdLists;
|
||||
opts["DebugOutputMute"] = Options.DebugOutputMute;
|
||||
ret["Options"] = opts;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CaptureSettings::fromJSON(const QVariantMap &data)
|
||||
{
|
||||
AutoStart = data["AutoStart"].toBool();
|
||||
|
||||
Executable = data["Executable"].toString();
|
||||
WorkingDir = data["WorkingDir"].toString();
|
||||
CmdLine = data["CmdLine"].toString();
|
||||
|
||||
QVariantList env = data["Environment"].toList();
|
||||
for(int i = 0; i < env.size(); i++)
|
||||
{
|
||||
EnvironmentModification e;
|
||||
e.fromJSON(env[i].value<QVariantMap>());
|
||||
Environment.push_back(e);
|
||||
}
|
||||
|
||||
QVariantMap opts = data["Options"].toMap();
|
||||
|
||||
Options.AllowVSync = opts["AllowVSync"].toBool();
|
||||
Options.AllowFullscreen = opts["AllowFullscreen"].toBool();
|
||||
Options.APIValidation = opts["APIValidation"].toBool();
|
||||
Options.CaptureCallstacks = opts["CaptureCallstacks"].toBool();
|
||||
Options.CaptureCallstacksOnlyDraws = opts["CaptureCallstacksOnlyDraws"].toBool();
|
||||
Options.DelayForDebugger = opts["DelayForDebugger"].toUInt();
|
||||
Options.VerifyMapWrites = opts["VerifyMapWrites"].toBool();
|
||||
Options.HookIntoChildren = opts["HookIntoChildren"].toBool();
|
||||
Options.RefAllResources = opts["RefAllResources"].toBool();
|
||||
Options.SaveAllInitials = opts["SaveAllInitials"].toBool();
|
||||
Options.CaptureAllCmdLists = opts["CaptureAllCmdLists"].toBool();
|
||||
Options.DebugOutputMute = opts["DebugOutputMute"].toBool();
|
||||
}
|
||||
|
||||
CaptureDialog::CaptureDialog(CaptureContext *ctx, OnCaptureMethod captureCallback,
|
||||
OnInjectMethod injectCallback, QWidget *parent)
|
||||
: QFrame(parent), ui(new Ui::CaptureDialog), m_Ctx(ctx)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
|
||||
// setup FlowLayout for options group
|
||||
{
|
||||
QLayout *oldLayout = ui->optionsGroup->layout();
|
||||
|
||||
QObjectList options = ui->optionsGroup->children();
|
||||
options.removeOne((QObject *)oldLayout);
|
||||
|
||||
delete oldLayout;
|
||||
|
||||
FlowLayout *optionsFlow = new FlowLayout(ui->optionsGroup, -1, 3, 3);
|
||||
|
||||
for(QObject *o : options)
|
||||
optionsFlow->addWidget(qobject_cast<QWidget *>(o));
|
||||
|
||||
ui->optionsGroup->setLayout(optionsFlow);
|
||||
}
|
||||
|
||||
ui->envVar->setEnabled(false);
|
||||
|
||||
m_ProcessModel = new QStandardItemModel(0, 3, this);
|
||||
|
||||
m_ProcessModel->setHeaderData(0, Qt::Horizontal, tr("Name"));
|
||||
m_ProcessModel->setHeaderData(1, Qt::Horizontal, tr("PID"));
|
||||
m_ProcessModel->setHeaderData(2, Qt::Horizontal, tr("Window Title"));
|
||||
|
||||
QSortFilterProxyModel *proxy = new QSortFilterProxyModel(this);
|
||||
|
||||
proxy->setSourceModel(m_ProcessModel);
|
||||
// filter on all columns
|
||||
proxy->setFilterKeyColumn(-1);
|
||||
// allow updating the underlying model
|
||||
proxy->setDynamicSortFilter(true);
|
||||
|
||||
ui->processList->setModel(proxy);
|
||||
ui->processList->setAlternatingRowColors(true);
|
||||
|
||||
// sort by PID by default
|
||||
ui->processList->sortByColumn(1, Qt::AscendingOrder);
|
||||
|
||||
// TODO
|
||||
ui->vulkanLayerWarn->setVisible(true);
|
||||
|
||||
m_CaptureCallback = captureCallback;
|
||||
m_InjectCallback = injectCallback;
|
||||
|
||||
setSettings(CaptureSettings());
|
||||
|
||||
updateGlobalHook();
|
||||
}
|
||||
|
||||
CaptureDialog::~CaptureDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void CaptureDialog::setInjectMode(bool inject)
|
||||
{
|
||||
m_Inject = inject;
|
||||
|
||||
if(inject)
|
||||
{
|
||||
ui->injectGroup->setVisible(true);
|
||||
ui->exeGroup->setVisible(false);
|
||||
ui->topVerticalSpacer->spacerItem()->changeSize(0, 0, QSizePolicy::Minimum, QSizePolicy::Minimum);
|
||||
ui->verticalLayout->invalidate();
|
||||
|
||||
ui->globalGroup->setVisible(false);
|
||||
|
||||
fillProcessList();
|
||||
|
||||
ui->capture->setText("Inject");
|
||||
this->setWindowTitle("Inject into Process");
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->injectGroup->setVisible(false);
|
||||
ui->exeGroup->setVisible(true);
|
||||
ui->topVerticalSpacer->spacerItem()->changeSize(0, 0, QSizePolicy::Minimum,
|
||||
QSizePolicy::Expanding);
|
||||
ui->verticalLayout->invalidate();
|
||||
|
||||
ui->globalGroup->setVisible(m_Ctx->Config.AllowGlobalHook);
|
||||
|
||||
ui->capture->setText("Capture");
|
||||
this->setWindowTitle("Capture Executable");
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureDialog::on_CaptureCallstacks_toggled(bool checked)
|
||||
{
|
||||
if(ui->CaptureCallstacks->isChecked())
|
||||
{
|
||||
ui->CaptureCallstacksOnlyDraws->setEnabled(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->CaptureCallstacksOnlyDraws->setChecked(false);
|
||||
ui->CaptureCallstacksOnlyDraws->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureDialog::on_processFilter_textChanged(const QString &filter)
|
||||
{
|
||||
QSortFilterProxyModel *model = (QSortFilterProxyModel *)ui->processList->model();
|
||||
|
||||
if(model == NULL)
|
||||
return;
|
||||
|
||||
model->setFilterFixedString(filter);
|
||||
}
|
||||
|
||||
void CaptureDialog::on_exePath_textChanged(const QString &exe)
|
||||
{
|
||||
QFileInfo f(exe);
|
||||
QDir dir = f.dir();
|
||||
bool valid = dir.makeAbsolute();
|
||||
|
||||
if(valid && f.isAbsolute())
|
||||
ui->workDirPath->setPlaceholderText(QDir::toNativeSeparators(dir.absolutePath()));
|
||||
else if(exe == "")
|
||||
ui->workDirPath->setPlaceholderText("");
|
||||
|
||||
updateGlobalHook();
|
||||
}
|
||||
|
||||
void CaptureDialog::on_vulkanCapture_clicked()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CaptureDialog::on_processRefesh_clicked()
|
||||
{
|
||||
fillProcessList();
|
||||
}
|
||||
|
||||
void CaptureDialog::on_exePathBrowse_clicked()
|
||||
{
|
||||
QString initDir = "";
|
||||
QString file = "";
|
||||
|
||||
QFileInfo f(ui->exePath->text());
|
||||
QDir dir = f.dir();
|
||||
if(ui->exePath->text() != "" && f.isAbsolute() && dir.exists())
|
||||
{
|
||||
initDir = dir.absolutePath();
|
||||
}
|
||||
else if(m_Ctx->Config.LastCapturePath != "")
|
||||
{
|
||||
initDir = m_Ctx->Config.LastCapturePath;
|
||||
if(m_Ctx->Config.LastCaptureExe != "")
|
||||
file = m_Ctx->Config.LastCaptureExe;
|
||||
}
|
||||
|
||||
// if(m_Core.Renderer.Remote == null)
|
||||
{
|
||||
QString filename = RDDialog::getOpenFileName(this, tr("Choose executable"), initDir,
|
||||
"Executable files (*.exe);;All files (*.*)");
|
||||
|
||||
if(filename != "")
|
||||
setExecutableFilename(filename);
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
VirtualOpenFileDialog remoteBrowser = new VirtualOpenFileDialog(m_Core.Renderer);
|
||||
remoteBrowser.Opened += new EventHandler<FileOpenedEventArgs>(this.virtualExeBrowser_Opened);
|
||||
|
||||
remoteBrowser.ShowDialog(this);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void CaptureDialog::on_workDirBrowse_clicked()
|
||||
{
|
||||
QString initDir = "";
|
||||
|
||||
if(QDir(ui->workDirPath->text()).exists())
|
||||
{
|
||||
initDir = ui->workDirPath->text();
|
||||
}
|
||||
else
|
||||
{
|
||||
QDir dir = QFileInfo(ui->exePath->text()).dir();
|
||||
if(dir.exists())
|
||||
initDir = dir.absolutePath();
|
||||
else if(m_Ctx->Config.LastCapturePath != "")
|
||||
initDir = m_Ctx->Config.LastCapturePath;
|
||||
}
|
||||
|
||||
// if(m_Core.Renderer.Remote == null)
|
||||
{
|
||||
QString dir = RDDialog::getExistingDirectory(this, "Choose working directory", initDir);
|
||||
|
||||
if(dir != "")
|
||||
ui->workDirPath->setText(dir);
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
VirtualOpenFileDialog remoteBrowser = new VirtualOpenFileDialog(m_Core.Renderer);
|
||||
remoteBrowser.Opened += new
|
||||
EventHandler<FileOpenedEventArgs>(this.virtualWorkDirBrowser_Opened);
|
||||
|
||||
remoteBrowser.DirectoryBrowse = true;
|
||||
|
||||
remoteBrowser.ShowDialog(this);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void CaptureDialog::on_envVarEdit_clicked()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
void CaptureDialog::on_toggleGlobal_clicked()
|
||||
{
|
||||
if(ui->toggleGlobal->isEnabled())
|
||||
{
|
||||
ui->toggleGlobal->setChecked(!ui->toggleGlobal->isChecked());
|
||||
|
||||
updateGlobalHook();
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureDialog::on_saveSettings_clicked()
|
||||
{
|
||||
QString filename = RDDialog::getSaveFileName(this, tr("Save Settings As"), QString(),
|
||||
"Capture settings (*.cap)");
|
||||
|
||||
if(filename != "")
|
||||
{
|
||||
QDir dirinfo = QFileInfo(filename).dir();
|
||||
if(dirinfo.exists())
|
||||
{
|
||||
saveSettings(filename);
|
||||
PersistantConfig::AddRecentFile(m_Ctx->Config.RecentCaptureSettings, filename, 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureDialog::on_loadSettings_clicked()
|
||||
{
|
||||
QString filename =
|
||||
RDDialog::getOpenFileName(this, tr("Open Settings"), QString(), "Capture settings (*.cap)");
|
||||
|
||||
if(filename != "" && QFileInfo::exists(filename))
|
||||
{
|
||||
loadSettings(filename);
|
||||
PersistantConfig::AddRecentFile(m_Ctx->Config.RecentCaptureSettings, filename, 10);
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureDialog::on_capture_clicked()
|
||||
{
|
||||
triggerCapture();
|
||||
}
|
||||
|
||||
void CaptureDialog::on_close_clicked()
|
||||
{
|
||||
this->close();
|
||||
}
|
||||
|
||||
void CaptureDialog::setSettings(CaptureSettings settings)
|
||||
{
|
||||
setInjectMode(settings.Inject);
|
||||
|
||||
ui->exePath->setText(settings.Executable);
|
||||
ui->workDirPath->setText(settings.WorkingDir);
|
||||
ui->cmdline->setText(settings.CmdLine);
|
||||
|
||||
setEnvironmentModifications(settings.Environment);
|
||||
|
||||
ui->AllowFullscreen->setChecked(settings.Options.AllowFullscreen);
|
||||
ui->AllowVSync->setChecked(settings.Options.AllowVSync);
|
||||
ui->HookIntoChildren->setChecked(settings.Options.HookIntoChildren);
|
||||
ui->CaptureCallstacks->setChecked(settings.Options.CaptureCallstacks);
|
||||
ui->CaptureCallstacksOnlyDraws->setChecked(settings.Options.CaptureCallstacksOnlyDraws);
|
||||
ui->APIValidation->setChecked(settings.Options.APIValidation);
|
||||
ui->RefAllResources->setChecked(settings.Options.RefAllResources);
|
||||
ui->SaveAllInitials->setChecked(settings.Options.SaveAllInitials);
|
||||
ui->DelayForDebugger->setValue(settings.Options.DelayForDebugger);
|
||||
ui->VerifyMapWrites->setChecked(settings.Options.VerifyMapWrites);
|
||||
ui->AutoStart->setChecked(settings.AutoStart);
|
||||
|
||||
if(settings.AutoStart)
|
||||
{
|
||||
triggerCapture();
|
||||
}
|
||||
}
|
||||
|
||||
CaptureSettings CaptureDialog::settings()
|
||||
{
|
||||
CaptureSettings ret;
|
||||
|
||||
ret.Inject = injectMode();
|
||||
|
||||
ret.AutoStart = ui->AutoStart->isChecked();
|
||||
|
||||
ret.Executable = ui->exePath->text();
|
||||
ret.WorkingDir = ui->workDirPath->text();
|
||||
ret.CmdLine = ui->cmdline->text();
|
||||
|
||||
ret.Environment = m_EnvModifications;
|
||||
|
||||
ret.Options.AllowFullscreen = ui->AllowFullscreen->isChecked();
|
||||
ret.Options.AllowVSync = ui->AllowVSync->isChecked();
|
||||
ret.Options.HookIntoChildren = ui->HookIntoChildren->isChecked();
|
||||
ret.Options.CaptureCallstacks = ui->CaptureCallstacks->isChecked();
|
||||
ret.Options.CaptureCallstacksOnlyDraws = ui->CaptureCallstacksOnlyDraws->isChecked();
|
||||
ret.Options.APIValidation = ui->APIValidation->isChecked();
|
||||
ret.Options.RefAllResources = ui->RefAllResources->isChecked();
|
||||
ret.Options.SaveAllInitials = ui->SaveAllInitials->isChecked();
|
||||
ret.Options.CaptureAllCmdLists = ui->CaptureAllCmdLists->isChecked();
|
||||
ret.Options.DelayForDebugger = (uint32_t)ui->DelayForDebugger->value();
|
||||
ret.Options.VerifyMapWrites = ui->VerifyMapWrites->isChecked();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CaptureDialog::saveSettings(QString filename)
|
||||
{
|
||||
QFile f(filename);
|
||||
if(f.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text))
|
||||
{
|
||||
QVariantMap values;
|
||||
values["settings"] = settings().toJSON();
|
||||
SaveToJSON(values, f, JSON_ID, JSON_VER);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDDialog::critical(this, "Error saving config",
|
||||
tr("Couldn't open path %1 for write.").arg(filename));
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureDialog::fillProcessList()
|
||||
{
|
||||
m_ProcessModel->removeRows(0, m_ProcessModel->rowCount());
|
||||
|
||||
// no way of listing processes in Qt, fill with dummy data
|
||||
m_ProcessModel->insertRows(0, 5);
|
||||
|
||||
#define ROW(n, name, pid, title) \
|
||||
m_ProcessModel->setData(m_ProcessModel->index(n, 0), name); \
|
||||
m_ProcessModel->setData(m_ProcessModel->index(n, 1), pid); \
|
||||
m_ProcessModel->setData(m_ProcessModel->index(n, 2), title);
|
||||
|
||||
ROW(0, "foo.exe", 123, "Foo Window");
|
||||
ROW(1, "magic.exe", 456, "Magic Window");
|
||||
ROW(2, "system", 999, "Scary System process");
|
||||
ROW(3, "chrome.exe", 4539, "Chrome - renderdoc.org");
|
||||
ROW(4, "firefox.exe", 8483, "Firefox - renderdoc.org");
|
||||
}
|
||||
|
||||
void CaptureDialog::setExecutableFilename(QString filename)
|
||||
{
|
||||
filename = QDir::toNativeSeparators(QFileInfo(filename).absoluteFilePath());
|
||||
ui->exePath->setText(filename);
|
||||
|
||||
m_Ctx->Config.LastCapturePath = QFileInfo(filename).absolutePath();
|
||||
m_Ctx->Config.LastCaptureExe = QFileInfo(filename).completeBaseName();
|
||||
}
|
||||
|
||||
void CaptureDialog::loadSettings(QString filename)
|
||||
{
|
||||
QFile f(filename);
|
||||
if(f.open(QIODevice::ReadOnly | QIODevice::Text))
|
||||
{
|
||||
QVariantMap values;
|
||||
|
||||
bool success = LoadFromJSON(values, f, JSON_ID, JSON_VER);
|
||||
|
||||
if(success)
|
||||
{
|
||||
CaptureSettings settings;
|
||||
settings.fromJSON(values["settings"].value<QVariantMap>());
|
||||
setSettings(settings);
|
||||
}
|
||||
else
|
||||
{
|
||||
RDDialog::critical(this, "Error loading config",
|
||||
tr("Couldn't interpret settings in %1.").arg(filename));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RDDialog::critical(this, "Error loading config", tr("Couldn't open path %1.").arg(filename));
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureDialog::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
if(ui->toggleGlobal->isChecked())
|
||||
{
|
||||
ui->toggleGlobal->setChecked(false);
|
||||
|
||||
updateGlobalHook();
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureDialog::updateGlobalHook()
|
||||
{
|
||||
ui->globalGroup->setVisible(!injectMode() && m_Ctx->Config.AllowGlobalHook);
|
||||
|
||||
if(ui->exePath->text().length() >= 4)
|
||||
{
|
||||
ui->toggleGlobal->setEnabled(true);
|
||||
QString text = tr("Global hooking is risky!\nBe sure you know what you're doing.");
|
||||
|
||||
if(ui->toggleGlobal->isChecked())
|
||||
text += tr("\nEmergency restore @ %TEMP%\\RenderDoc_RestoreGlobalHook.reg");
|
||||
|
||||
ui->globalLabel->setText(text);
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->toggleGlobal->setEnabled(false);
|
||||
ui->globalLabel->setText(tr("Global hooking requires an executable path, or filename"));
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureDialog::setEnvironmentModifications(const QList<EnvironmentModification> &modifications)
|
||||
{
|
||||
m_EnvModifications = modifications;
|
||||
|
||||
QString envModText = "";
|
||||
|
||||
for(const EnvironmentModification &mod : modifications)
|
||||
{
|
||||
if(envModText != "")
|
||||
envModText += ", ";
|
||||
|
||||
envModText += mod.GetDescription();
|
||||
}
|
||||
|
||||
ui->envVar->setText(envModText);
|
||||
}
|
||||
|
||||
void CaptureDialog::triggerCapture()
|
||||
{
|
||||
if(injectMode())
|
||||
{
|
||||
QModelIndexList sel = ui->processList->selectionModel()->selectedRows();
|
||||
if(sel.size() == 1)
|
||||
{
|
||||
QModelIndex item = sel[0];
|
||||
|
||||
QSortFilterProxyModel *model = (QSortFilterProxyModel *)ui->processList->model();
|
||||
|
||||
item = model->mapToSource(item);
|
||||
|
||||
QString name = m_ProcessModel->data(m_ProcessModel->index(item.row(), 0)).toString();
|
||||
uint32_t PID = m_ProcessModel->data(m_ProcessModel->index(item.row(), 1)).toUInt();
|
||||
|
||||
// var live = ;
|
||||
m_InjectCallback(PID, settings().Environment, name, settings().Options);
|
||||
|
||||
/*
|
||||
if(queueFrameCap.Checked && live != null)
|
||||
live.QueueCapture((int)queuedCapFrame.Value);
|
||||
*/
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
QString exe = ui->exePath->text();
|
||||
|
||||
// for non-remote captures, check the executable locally
|
||||
// if(m_Core.Renderer.Remote == null)
|
||||
{
|
||||
if(!QFileInfo::exists(exe))
|
||||
{
|
||||
RDDialog::critical(this, tr("Invalid executable"),
|
||||
tr("Invalid application executable: %1").arg(exe));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
QString workingDir = "";
|
||||
|
||||
// for non-remote captures, check the directory locally
|
||||
// if(m_Core.Renderer.Remote == null)
|
||||
{
|
||||
if(QDir(ui->workDirPath->text()).exists())
|
||||
workingDir = ui->workDirPath->text();
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
workingDir = RealWorkDir;
|
||||
}
|
||||
*/
|
||||
|
||||
QString cmdLine = ui->cmdline->text();
|
||||
|
||||
// var live =
|
||||
m_CaptureCallback(exe, workingDir, cmdLine, settings().Environment, settings().Options);
|
||||
|
||||
/*
|
||||
if(queueFrameCap.Checked && live != null)
|
||||
live.QueueCapture((int)queuedCapFrame.Value);
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/******************************************************************************
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2016 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 <QFrame>
|
||||
#include <functional>
|
||||
#include "Code/CaptureContext.h"
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class CaptureDialog;
|
||||
}
|
||||
|
||||
class QStandardItemModel;
|
||||
|
||||
struct CaptureSettings
|
||||
{
|
||||
CaptureSettings();
|
||||
|
||||
CaptureOptions Options;
|
||||
bool Inject;
|
||||
bool AutoStart;
|
||||
QString Executable;
|
||||
QString WorkingDir;
|
||||
QString CmdLine;
|
||||
QList<EnvironmentModification> Environment;
|
||||
|
||||
QVariantMap toJSON() const;
|
||||
void fromJSON(const QVariantMap &data);
|
||||
};
|
||||
|
||||
class CaptureDialog : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
typedef std::function<void(const QString &exe, const QString &workingDir, const QString &cmdLine,
|
||||
const QList<EnvironmentModification> &env, CaptureOptions opts)>
|
||||
OnCaptureMethod;
|
||||
typedef std::function<void(uint32_t PID, const QList<EnvironmentModification> &env,
|
||||
const QString &name, CaptureOptions opts)>
|
||||
OnInjectMethod;
|
||||
|
||||
explicit CaptureDialog(CaptureContext *ctx, OnCaptureMethod captureCallback,
|
||||
OnInjectMethod injectCallback, QWidget *parent = 0);
|
||||
~CaptureDialog();
|
||||
|
||||
bool injectMode() { return m_Inject; }
|
||||
void setInjectMode(bool inject);
|
||||
|
||||
void setExecutableFilename(QString filename);
|
||||
void loadSettings(QString filename);
|
||||
|
||||
private slots:
|
||||
// automatic slots
|
||||
void on_exePathBrowse_clicked();
|
||||
void on_exePath_textChanged(const QString &arg1);
|
||||
void on_workDirBrowse_clicked();
|
||||
void on_envVarEdit_clicked();
|
||||
|
||||
void on_processFilter_textChanged(const QString &arg1);
|
||||
void on_processRefesh_clicked();
|
||||
|
||||
void on_saveSettings_clicked();
|
||||
void on_loadSettings_clicked();
|
||||
|
||||
void on_capture_clicked();
|
||||
void on_close_clicked();
|
||||
|
||||
void on_toggleGlobal_clicked();
|
||||
|
||||
void on_vulkanCapture_clicked();
|
||||
|
||||
void on_CaptureCallstacks_toggled(bool checked);
|
||||
|
||||
private:
|
||||
void closeEvent(QCloseEvent *event) override;
|
||||
|
||||
Ui::CaptureDialog *ui;
|
||||
CaptureContext *m_Ctx;
|
||||
|
||||
QStandardItemModel *m_ProcessModel;
|
||||
|
||||
OnCaptureMethod m_CaptureCallback;
|
||||
OnInjectMethod m_InjectCallback;
|
||||
|
||||
void updateGlobalHook();
|
||||
void setEnvironmentModifications(const QList<EnvironmentModification> &modifications);
|
||||
void triggerCapture();
|
||||
|
||||
void setSettings(CaptureSettings settings);
|
||||
CaptureSettings settings();
|
||||
|
||||
void saveSettings(QString filename);
|
||||
|
||||
QList<EnvironmentModification> m_EnvModifications;
|
||||
bool m_Inject;
|
||||
void fillProcessList();
|
||||
};
|
||||
@@ -0,0 +1,926 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>CaptureDialog</class>
|
||||
<widget class="QFrame" name="CaptureDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>270</width>
|
||||
<height>939</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Capture Executable</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="exeGroup">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>130</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Program</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLineEdit" name="exePath">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QToolButton" name="exePathBrowse">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="workDirLabel">
|
||||
<property name="text">
|
||||
<string>Working Directory</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QToolButton" name="workDirBrowse">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="cmdLineLabel">
|
||||
<property name="text">
|
||||
<string>Command-line Arguments</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="envVarLabel">
|
||||
<property name="text">
|
||||
<string>Environment Variables</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QToolButton" name="envVarEdit">
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="exePathLabel">
|
||||
<property name="text">
|
||||
<string>Executable Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLineEdit" name="workDirPath">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2" colspan="2">
|
||||
<widget class="QLineEdit" name="cmdline">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLineEdit" name="envVar">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="injectGroup">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>100</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>260</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Process</string>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="2" column="1">
|
||||
<widget class="QPushButton" name="processRefesh">
|
||||
<property name="text">
|
||||
<string>Refresh</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="processWarning">
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>106</red>
|
||||
<green>104</green>
|
||||
<blue>100</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>18</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>NOTE: Injecting only works when the process has not used the target API</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLineEdit" name="processFilter">
|
||||
<property name="placeholderText">
|
||||
<string>Filter process list by PID or name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QTreeView" name="processList">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="alternatingRowColors">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="indentation">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rootIsDecorated">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="itemsExpandable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="sortingEnabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="vulkanLayerWarn">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="Button">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>220</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="Button">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>220</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="Button">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>255</green>
|
||||
<blue>220</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="cursor">
|
||||
<cursorShape>PointingHandCursor</cursorShape>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Warning: Vulkan capture is not configured.
|
||||
Click here to set up Vulkan capture.</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../resources.qrc">
|
||||
<normaloff>:/Resources/information.png</normaloff>:/Resources/information.png</iconset>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::DelayedPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="arrowType">
|
||||
<enum>Qt::NoArrow</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="optionsGroup">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Capture Options</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="AllowFullscreen">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Allow Fullscreen</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="AllowVSync">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Allow VSync</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="DebuggerDelayFrame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<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>
|
||||
<widget class="QDoubleSpinBox" name="DelayForDebugger">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string comment="seconds"> secs</string>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>120.000000000000000</double>
|
||||
</property>
|
||||
<property name="value">
|
||||
<double>0.000000000000000</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="DebuggerDelayLabel">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Debugger Delay</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="CaptureCallstacks">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Collect Callstacks</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="CaptureCallstacksOnlyDraws">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Only Drawcall stacks</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="APIValidation">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable API Validation</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="HookIntoChildren">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Hook into Children</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="SaveAllInitials">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save all Initials</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="RefAllResources">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Ref all Resources</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="CaptureAllCmdLists">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Capture all Cmd Lists</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="VerifyMapWrites">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Verify Map() Writes</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="AutoStart">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Auto Start</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="actionGroup">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Actions</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="queueCaptureLabel">
|
||||
<property name="text">
|
||||
<string>Queue Capture</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDoubleSpinBox" name="queuedFrame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="prefix">
|
||||
<string comment="Frame number" extracomment="To Capture">Frame </string>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="ActionsSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>596</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="globalGroup">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Global Process Hook</string>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="globalLabel">
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>255</red>
|
||||
<green>0</green>
|
||||
<blue>0</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="WindowText">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>106</red>
|
||||
<green>104</green>
|
||||
<blue>100</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Text Set by Code</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="toggleGlobal">
|
||||
<property name="text">
|
||||
<string>Enable Global Hook</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="globalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>587</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="buttonsFrame">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="saveSettings">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="loadSettings">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Load</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="buttonsSpace">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>556</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="capture">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>60</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Capture</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="close">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Close</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="topVerticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../../resources.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "Code/CaptureContext.h"
|
||||
#include "Code/QRDUtils.h"
|
||||
#include "Windows/Dialogs/AboutDialog.h"
|
||||
#include "Windows/Dialogs/CaptureDialog.h"
|
||||
#include "EventBrowser.h"
|
||||
#include "TextureViewer.h"
|
||||
#include "ui_MainWindow.h"
|
||||
@@ -110,6 +111,11 @@ MainWindow::MainWindow(CaptureContext *ctx) : QMainWindow(NULL), ui(new Ui::Main
|
||||
eventBrowser->setObjectName("eventBrowser");
|
||||
return eventBrowser;
|
||||
}
|
||||
else if(objectName == "capDialog")
|
||||
{
|
||||
CaptureDialog *capDialog = this->createCaptureDialog();
|
||||
return capDialog;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
});
|
||||
@@ -131,6 +137,12 @@ MainWindow::MainWindow(CaptureContext *ctx) : QMainWindow(NULL), ui(new Ui::Main
|
||||
textureViewer,
|
||||
ToolWindowManager::AreaReference(ToolWindowManager::RightOf,
|
||||
ui->toolWindowManager->areaOf(eventBrowser), 0.75f));
|
||||
|
||||
CaptureDialog *capDialog = createCaptureDialog();
|
||||
|
||||
ui->toolWindowManager->addToolWindow(
|
||||
capDialog, ToolWindowManager::AreaReference(ToolWindowManager::AddTo,
|
||||
ui->toolWindowManager->areaOf(textureViewer)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,17 +185,17 @@ void MainWindow::LoadFromFilename(const QString &filename)
|
||||
QFileInfo path(filename);
|
||||
QString ext = path.suffix().toLower();
|
||||
|
||||
if(ext == ".rdc")
|
||||
if(ext == "rdc")
|
||||
{
|
||||
LoadLogfile(filename, false, true);
|
||||
}
|
||||
else if(ext == ".cap")
|
||||
else if(ext == "cap")
|
||||
{
|
||||
// OpenCaptureConfigFile(filename, false);
|
||||
OpenCaptureConfigFile(filename, false);
|
||||
}
|
||||
else if(ext == ".exe")
|
||||
else if(ext == "exe")
|
||||
{
|
||||
// OpenCaptureConfigFile(filename, true);
|
||||
OpenCaptureConfigFile(filename, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -192,6 +204,59 @@ void MainWindow::LoadFromFilename(const QString &filename)
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::OnCaptureTrigger(const QString &exe, const QString &workingDir,
|
||||
const QString &cmdLine, const QList<EnvironmentModification> &env,
|
||||
CaptureOptions opts)
|
||||
{
|
||||
if(!PromptCloseLog())
|
||||
return;
|
||||
|
||||
QString logfile = m_Ctx->TempLogFilename(QFileInfo(exe).baseName());
|
||||
|
||||
uint32_t ret = m_Ctx->Renderer()->ExecuteAndInject(exe, workingDir, cmdLine, env, logfile, opts);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
RDDialog::critical(
|
||||
this, tr("Error kicking capture"),
|
||||
tr("Error launching %1 for capture.\n\nCheck diagnostic log in Help menu for more details.")
|
||||
.arg(exe));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
var live = new LiveCapture(m_Core, m_Core.Renderer.Remote == null ? "" :
|
||||
m_Core.Renderer.Remote.Hostname, ret, this);
|
||||
ShowLiveCapture(live);
|
||||
return live;*/
|
||||
}
|
||||
|
||||
void MainWindow::OnInjectTrigger(uint32_t PID, const QList<EnvironmentModification> &env,
|
||||
const QString &name, CaptureOptions opts)
|
||||
{
|
||||
if(!PromptCloseLog())
|
||||
return;
|
||||
|
||||
QString logfile = m_Ctx->TempLogFilename(name);
|
||||
|
||||
// TODO - env
|
||||
uint32_t ret = RENDERDOC_InjectIntoProcess(PID, NULL, logfile.toUtf8().data(), &opts, false);
|
||||
|
||||
if(ret == 0)
|
||||
{
|
||||
RDDialog::critical(this, tr("Error kicking capture"),
|
||||
tr("Error injecting into process %1 for capture.\n\nCheck diagnostic log in "
|
||||
"Help menu for more details.")
|
||||
.arg(PID));
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
var live = new LiveCapture(m_Core, "", ret, this);
|
||||
ShowLiveCapture(live);
|
||||
return live;*/
|
||||
}
|
||||
|
||||
void MainWindow::LoadLogfile(const QString &filename, bool temporary, bool local)
|
||||
{
|
||||
if(PromptCloseLog())
|
||||
@@ -352,13 +417,25 @@ void MainWindow::LoadLogfile(const QString &filename, bool temporary, bool local
|
||||
|
||||
if(!remoteReplay)
|
||||
{
|
||||
m_Ctx->Config.LastLogPath = QFileInfo(filename).dir().absolutePath();
|
||||
m_Ctx->Config.LastLogPath = QFileInfo(filename).absolutePath();
|
||||
}
|
||||
|
||||
statusText->setText(tr("Loading ") + origFilename + "...");
|
||||
}
|
||||
}
|
||||
|
||||
void MainWindow::OpenCaptureConfigFile(const QString &filename, bool exe)
|
||||
{
|
||||
CaptureDialog *capDialog = createCaptureDialog();
|
||||
|
||||
if(exe)
|
||||
capDialog->setExecutableFilename(filename);
|
||||
else
|
||||
capDialog->loadSettings(filename);
|
||||
|
||||
ui->toolWindowManager->addToolWindow(capDialog, ToolWindowManager::EmptySpace);
|
||||
}
|
||||
|
||||
QString MainWindow::GetSavePath()
|
||||
{
|
||||
QString dir;
|
||||
@@ -490,6 +567,19 @@ void MainWindow::CloseLogfile()
|
||||
ui->action_Save_Log->setEnabled(false);
|
||||
}
|
||||
|
||||
CaptureDialog *MainWindow::createCaptureDialog()
|
||||
{
|
||||
CaptureDialog *ret = new CaptureDialog(
|
||||
m_Ctx,
|
||||
[this](const QString &exe, const QString &workingDir, const QString &cmdLine,
|
||||
const QList<EnvironmentModification> &env,
|
||||
CaptureOptions opts) { this->OnCaptureTrigger(exe, workingDir, cmdLine, env, opts); },
|
||||
[this](uint32_t PID, const QList<EnvironmentModification> &env, const QString &name,
|
||||
CaptureOptions opts) { this->OnInjectTrigger(PID, env, name, opts); });
|
||||
ret->setObjectName("capDialog");
|
||||
return ret;
|
||||
}
|
||||
|
||||
void MainWindow::SetTitle(const QString &filename)
|
||||
{
|
||||
QString prefix = "";
|
||||
@@ -595,7 +685,7 @@ void MainWindow::recentCapture(const QString &filename)
|
||||
{
|
||||
if(QFileInfo::exists(filename))
|
||||
{
|
||||
// OpenCaptureConfigFile(filename, false);
|
||||
OpenCaptureConfigFile(filename, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -715,6 +805,24 @@ void MainWindow::on_action_Texture_Viewer_triggered()
|
||||
ui->toolWindowManager->addToolWindow(textureViewer, ToolWindowManager::EmptySpace);
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Capture_Log_triggered()
|
||||
{
|
||||
CaptureDialog *capDialog = createCaptureDialog();
|
||||
|
||||
ui->toolWindowManager->addToolWindow(capDialog, ToolWindowManager::EmptySpace);
|
||||
|
||||
capDialog->setInjectMode(false);
|
||||
}
|
||||
|
||||
void MainWindow::on_action_Inject_into_Process_triggered()
|
||||
{
|
||||
CaptureDialog *capDialog = createCaptureDialog();
|
||||
|
||||
ui->toolWindowManager->addToolWindow(capDialog, ToolWindowManager::EmptySpace);
|
||||
|
||||
capDialog->setInjectMode(true);
|
||||
}
|
||||
|
||||
void MainWindow::saveLayout_triggered()
|
||||
{
|
||||
LoadSaveLayout(qobject_cast<QAction *>(QObject::sender()), true);
|
||||
|
||||
@@ -35,6 +35,7 @@ class MainWindow;
|
||||
|
||||
class QLabel;
|
||||
class QProgressBar;
|
||||
class CaptureDialog;
|
||||
|
||||
class MainWindow : public QMainWindow, public ILogViewerForm
|
||||
{
|
||||
@@ -53,6 +54,11 @@ public:
|
||||
bool ownTemporaryLog() { return m_OwnTempLog; }
|
||||
void LoadFromFilename(const QString &filename);
|
||||
|
||||
void OnCaptureTrigger(const QString &exe, const QString &workingDir, const QString &cmdLine,
|
||||
const QList<EnvironmentModification> &env, CaptureOptions opts);
|
||||
void OnInjectTrigger(uint32_t PID, const QList<EnvironmentModification> &env, const QString &name,
|
||||
CaptureOptions opts);
|
||||
|
||||
private slots:
|
||||
// automatic slots
|
||||
void on_action_Exit_triggered();
|
||||
@@ -62,6 +68,8 @@ private slots:
|
||||
void on_action_Mesh_Output_triggered();
|
||||
void on_action_Event_Viewer_triggered();
|
||||
void on_action_Texture_Viewer_triggered();
|
||||
void on_action_Capture_Log_triggered();
|
||||
void on_action_Inject_into_Process_triggered();
|
||||
|
||||
// manual slots
|
||||
void saveLayout_triggered();
|
||||
@@ -85,6 +93,8 @@ private:
|
||||
|
||||
QString m_LastSaveCapturePath = "";
|
||||
|
||||
CaptureDialog *createCaptureDialog();
|
||||
|
||||
void SetTitle(const QString &filename);
|
||||
void SetTitle();
|
||||
|
||||
@@ -97,6 +107,7 @@ private:
|
||||
bool PromptCloseLog();
|
||||
bool PromptSaveLog();
|
||||
void LoadLogfile(const QString &filename, bool temporary, bool local);
|
||||
void OpenCaptureConfigFile(const QString &filename, bool exe);
|
||||
QString GetSavePath();
|
||||
void CloseLogfile();
|
||||
|
||||
|
||||
@@ -96,6 +96,7 @@ SOURCES += 3rdparty/toolwindowmanager/ToolWindowManager.cpp \
|
||||
Widgets/TextureGoto.cpp \
|
||||
Widgets/RangeHistogram.cpp \
|
||||
Windows/Dialogs/TextureSaveDialog.cpp \
|
||||
Windows/Dialogs/CaptureDialog.cpp \
|
||||
Code/QRDUtils.cpp
|
||||
|
||||
HEADERS += 3rdparty/toolwindowmanager/ToolWindowManager.h \
|
||||
@@ -120,6 +121,7 @@ HEADERS += 3rdparty/toolwindowmanager/ToolWindowManager.h \
|
||||
Widgets/TextureGoto.h \
|
||||
Widgets/RangeHistogram.h \
|
||||
Windows/Dialogs/TextureSaveDialog.h \
|
||||
Windows/Dialogs/CaptureDialog.h \
|
||||
Code/QRDUtils.h
|
||||
|
||||
FORMS += Windows/Dialogs/AboutDialog.ui \
|
||||
@@ -128,7 +130,8 @@ FORMS += Windows/Dialogs/AboutDialog.ui \
|
||||
Windows/TextureViewer.ui \
|
||||
Widgets/ResourcePreview.ui \
|
||||
Widgets/ThumbnailStrip.ui \
|
||||
Windows/Dialogs/TextureSaveDialog.ui
|
||||
Windows/Dialogs/TextureSaveDialog.ui \
|
||||
Windows/Dialogs/CaptureDialog.ui
|
||||
|
||||
RESOURCES += \
|
||||
resources.qrc
|
||||
|
||||
@@ -281,6 +281,7 @@
|
||||
<ClCompile Include="Code\QRDUtils.cpp" />
|
||||
<ClCompile Include="generated\moc_AboutDialog.cpp" />
|
||||
<ClCompile Include="generated\moc_CaptureContext.cpp" />
|
||||
<ClCompile Include="generated\moc_CaptureDialog.cpp" />
|
||||
<ClCompile Include="generated\moc_CustomPaintWidget.cpp" />
|
||||
<ClCompile Include="generated\moc_EventBrowser.cpp" />
|
||||
<ClCompile Include="generated\moc_QRDUtils.cpp" />
|
||||
@@ -309,6 +310,7 @@
|
||||
<ClCompile Include="Code\CaptureContext.cpp" />
|
||||
<ClCompile Include="Widgets\CustomPaintWidget.cpp" />
|
||||
<ClCompile Include="Windows\Dialogs\AboutDialog.cpp" />
|
||||
<ClCompile Include="Windows\Dialogs\CaptureDialog.cpp" />
|
||||
<ClCompile Include="Windows\Dialogs\TextureSaveDialog.cpp" />
|
||||
<ClCompile Include="Windows\EventBrowser.cpp" />
|
||||
<ClCompile Include="3rdparty\flowlayout\FlowLayout.cpp">
|
||||
@@ -334,6 +336,7 @@
|
||||
<ClInclude Include="Code\PersistantConfig.h" />
|
||||
<ClInclude Include="Code\QRDUtils.h" />
|
||||
<ClInclude Include="generated\ui_AboutDialog.h" />
|
||||
<ClInclude Include="generated\ui_CaptureDialog.h" />
|
||||
<ClInclude Include="generated\ui_EventBrowser.h" />
|
||||
<ClInclude Include="generated\ui_MainWindow.h" />
|
||||
<ClInclude Include="generated\ui_ResourcePreview.h" />
|
||||
@@ -350,6 +353,7 @@
|
||||
<ClInclude Include="Code\CaptureContext.h" />
|
||||
<ClInclude Include="Widgets\CustomPaintWidget.h" />
|
||||
<ClInclude Include="Windows\Dialogs\AboutDialog.h" />
|
||||
<ClInclude Include="Windows\Dialogs\CaptureDialog.h" />
|
||||
<ClInclude Include="Windows\Dialogs\TextureSaveDialog.h" />
|
||||
<ClInclude Include="Windows\EventBrowser.h" />
|
||||
<ClInclude Include="3rdparty\flowlayout\FlowLayout.h" />
|
||||
@@ -365,6 +369,7 @@
|
||||
<None Include="Widgets\ResourcePreview.ui" />
|
||||
<None Include="Widgets\ThumbnailStrip.ui" />
|
||||
<None Include="Windows\Dialogs\AboutDialog.ui" />
|
||||
<None Include="Windows\Dialogs\CaptureDialog.ui" />
|
||||
<None Include="Windows\Dialogs\TextureSaveDialog.ui" />
|
||||
<None Include="Windows\EventBrowser.ui" />
|
||||
<None Include="Windows\MainWindow.ui" />
|
||||
|
||||
@@ -169,6 +169,12 @@
|
||||
<ClCompile Include="generated\moc_TextureSaveDialog.cpp">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="generated\moc_CaptureDialog.cpp">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Windows\Dialogs\CaptureDialog.cpp">
|
||||
<Filter>Windows\Dialogs</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Code\QRDUtils.cpp">
|
||||
<Filter>Code</Filter>
|
||||
</ClCompile>
|
||||
@@ -252,6 +258,12 @@
|
||||
<ClInclude Include="generated\ui_TextureSaveDialog.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="generated\ui_CaptureDialog.h">
|
||||
<Filter>Generated Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Windows\Dialogs\CaptureDialog.h">
|
||||
<Filter>Windows\Dialogs</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Code\QRDUtils.h">
|
||||
<Filter>Code</Filter>
|
||||
</ClInclude>
|
||||
@@ -459,6 +471,9 @@
|
||||
<None Include="Windows\Dialogs\TextureSaveDialog.ui">
|
||||
<Filter>Windows\Dialogs</Filter>
|
||||
</None>
|
||||
<None Include="Windows\Dialogs\CaptureDialog.ui">
|
||||
<Filter>Windows\Dialogs</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="generated\ui_AboutDialog.h">
|
||||
|
||||
Reference in New Issue
Block a user