Add thumbnails to texture tooltips in pipeline state view

* If there would be no tooltip otherwise, it just shows the thumbnail. Otherwise
  any tooltip text (like view parameters or image layout) is displayed below the
  thumbnail
This commit is contained in:
baldurk
2021-04-20 13:51:41 +01:00
parent 260583b805
commit 9d3f7169ed
7 changed files with 288 additions and 12 deletions
@@ -26,6 +26,7 @@
#include <QMenu>
#include <QMouseEvent>
#include <QPainter>
#include <QStylePainter>
#include <QSvgRenderer>
#include <QToolButton>
#include <QXmlStreamWriter>
@@ -80,11 +81,122 @@ static uint32_t byteSize(const ResourceFormat &fmt)
return fmt.compByteWidth * fmt.compCount;
}
RDPreviewTooltip::RDPreviewTooltip(PipelineStateViewer *parent, CustomPaintWidget *thumbnail,
ICaptureContext &ctx)
: QFrame(parent), m_Ctx(ctx)
{
int margin = style()->pixelMetric(QStyle::PM_ToolTipLabelFrameWidth, NULL, this);
int opacity = style()->styleHint(QStyle::SH_ToolTipLabel_Opacity, NULL, this);
pipe = parent;
setWindowFlags(Qt::ToolTip);
setAttribute(Qt::WA_TransparentForMouseEvents);
setForegroundRole(QPalette::ToolTipText);
setBackgroundRole(QPalette::ToolTipBase);
setFrameStyle(QFrame::NoFrame);
setWindowOpacity(opacity / 255.0);
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
QHBoxLayout *hbox = new QHBoxLayout;
QVBoxLayout *vbox = new QVBoxLayout;
label = new QLabel(this);
label->setMargin(margin + 1);
label->setAlignment(Qt::AlignLeft);
label->setIndent(1);
title = new QLabel(this);
title->setMargin(margin + 1);
title->setAlignment(Qt::AlignLeft);
title->setIndent(1);
setLayout(vbox);
vbox->addWidget(title);
vbox->addLayout(hbox);
hbox->addWidget(thumbnail);
hbox->addStretch();
vbox->addWidget(label);
}
void RDPreviewTooltip::hideTip()
{
hide();
}
QSize RDPreviewTooltip::configureTip(QWidget *widget, QModelIndex idx, QString text)
{
ResourceId id = pipe->updateThumbnail(widget, idx);
if(id != ResourceId())
{
title->setText(m_Ctx.GetResourceName(id));
title->show();
}
else
{
title->hide();
}
label->setText(text);
label->setVisible(!text.isEmpty());
layout()->update();
layout()->activate();
return minimumSizeHint();
}
void RDPreviewTooltip::showTip(QPoint pos)
{
move(pos);
resize(minimumSize());
show();
}
bool RDPreviewTooltip::forceTip(QWidget *widget, QModelIndex idx)
{
return pipe->hasThumbnail(widget, idx);
}
void RDPreviewTooltip::paintEvent(QPaintEvent *ev)
{
QStylePainter p(this);
QStyleOptionFrame opt;
opt.init(this);
p.drawPrimitive(QStyle::PE_PanelTipLabel, opt);
p.end();
QWidget::paintEvent(ev);
}
void RDPreviewTooltip::resizeEvent(QResizeEvent *e)
{
QStyleHintReturnMask frameMask;
QStyleOption option;
option.init(this);
if(style()->styleHint(QStyle::SH_ToolTip_Mask, &option, this, &frameMask))
setMask(frameMask.region);
QWidget::resizeEvent(e);
}
PipelineStateViewer::PipelineStateViewer(ICaptureContext &ctx, QWidget *parent)
: QFrame(parent), ui(new Ui::PipelineStateViewer), m_Ctx(ctx)
{
ui->setupUi(this);
ui->thumbnail->SetContext(m_Ctx);
ui->layout->removeWidget(ui->thumbnail);
m_Tooltip = new RDPreviewTooltip(this, ui->thumbnail, m_Ctx);
QColor c = palette().color(QPalette::ToolTipBase).toRgb();
m_TexDisplay.backgroundColor = FloatVector();
m_TexDisplay.backgroundColor.w = 1.0f;
// auto-fit and center scale
m_TexDisplay.scale = -1.0f;
m_D3D11 = NULL;
m_D3D12 = NULL;
m_GL = NULL;
@@ -105,6 +217,8 @@ PipelineStateViewer::~PipelineStateViewer()
m_Ctx.BuiltinWindowClosed(this);
m_Ctx.RemoveCaptureViewer(this);
delete m_Tooltip;
delete ui;
}
@@ -121,6 +235,24 @@ void PipelineStateViewer::OnCaptureLoaded()
if(m_Current)
m_Current->OnCaptureLoaded();
WindowingData thumbData = ui->thumbnail->GetWidgetWindowingData();
m_Ctx.Replay().BlockInvoke([thumbData, this](IReplayController *r) {
m_Output = r->CreateOutput(thumbData, ReplayOutputType::Texture);
ui->thumbnail->SetOutput(m_Output);
RT_UpdateAndDisplay(r);
});
}
void PipelineStateViewer::RT_UpdateAndDisplay(IReplayController *r)
{
if(m_Output != NULL)
m_Output->SetTextureDisplay(m_TexDisplay);
GUIInvoke::call(this, [this]() { ui->thumbnail->update(); });
}
void PipelineStateViewer::OnCaptureClosed()
@@ -1057,6 +1189,77 @@ void PipelineStateViewer::ShowResourceContextMenu(RDTreeWidget *widget, const QP
RDDialog::show(&contextMenu, widget->viewport()->mapToGlobal(pos));
}
ResourceId PipelineStateViewer::updateThumbnail(QWidget *widget, QModelIndex idx)
{
ResourceId id;
RDTreeWidget *treeWidget = qobject_cast<RDTreeWidget *>(widget);
if(treeWidget)
{
RDTreeWidgetItem *item = treeWidget->itemForIndex(idx);
if(item)
{
if(m_D3D11)
id = m_D3D11->GetResource(item);
else if(m_D3D12)
id = m_D3D12->GetResource(item);
else if(m_GL)
id = m_GL->GetResource(item);
else if(m_Vulkan)
id = m_Vulkan->GetResource(item);
}
TextureDescription *tex = m_Ctx.GetTexture(id);
if(tex)
{
m_TexDisplay.resourceId = id;
INVOKE_MEMFN(RT_UpdateAndDisplay);
float aspect = (float)tex->width / (float)qMax(1U, tex->height);
// keep height fixed at 100, and make width match the aspect ratio of the texture - up to 21:9
// ratio
ui->thumbnail->setFixedSize((int)qBound(100.0f, aspect * 100.0f, (21.0f / 9.0f) * 100.0f), 100);
}
else
{
ui->thumbnail->setFixedSize(0, 0);
}
}
return id;
}
bool PipelineStateViewer::hasThumbnail(QWidget *widget, QModelIndex idx)
{
RDTreeWidget *treeWidget = qobject_cast<RDTreeWidget *>(widget);
if(treeWidget)
{
ResourceId id;
RDTreeWidgetItem *item = treeWidget->itemForIndex(idx);
if(item)
{
if(m_D3D11)
id = m_D3D11->GetResource(item);
else if(m_D3D12)
id = m_D3D12->GetResource(item);
else if(m_GL)
id = m_GL->GetResource(item);
else if(m_Vulkan)
id = m_Vulkan->GetResource(item);
}
if(id != ResourceId() && m_Ctx.GetTexture(id))
return true;
}
return false;
}
void PipelineStateViewer::SetupResourceView(RDTreeWidget *widget)
{
auto handler = [this, widget](const QPoint &pos) {
@@ -1091,6 +1294,8 @@ void PipelineStateViewer::SetupResourceView(RDTreeWidget *widget)
widget->setContextMenuPolicy(Qt::CustomContextMenu);
QObject::connect(widget, &RDTreeWidget::customContextMenuRequested, handler);
widget->setCustomTooltip(m_Tooltip);
}
QString PipelineStateViewer::GetVBufferFormatString(uint32_t slot)
@@ -27,6 +27,7 @@
#include <QFrame>
#include <QLabel>
#include "Code/Interface/QRDInterface.h"
#include "Widgets/Extended/RDTreeView.h"
namespace Ui
{
@@ -40,12 +41,39 @@ class QMenu;
class RDLabel;
class RDTreeWidgetItem;
class RDTreeWidget;
class CustomPaintWidget;
class D3D11PipelineStateViewer;
class D3D12PipelineStateViewer;
class GLPipelineStateViewer;
class VulkanPipelineStateViewer;
class PipelineStateViewer;
class RDPreviewTooltip : public QFrame, public ITreeViewTipDisplay
{
private:
Q_OBJECT
PipelineStateViewer *pipe = NULL;
QLabel *title = NULL;
QLabel *label = NULL;
ICaptureContext &m_Ctx;
public:
explicit RDPreviewTooltip(PipelineStateViewer *parent, CustomPaintWidget *thumbnail,
ICaptureContext &ctx);
void hideTip();
QSize configureTip(QWidget *widget, QModelIndex idx, QString text);
void showTip(QPoint pos);
bool forceTip(QWidget *widget, QModelIndex idx);
protected:
void paintEvent(QPaintEvent *);
void resizeEvent(QResizeEvent *);
};
class PipelineStateViewer : public QFrame, public IPipelineStateViewer, public ICaptureViewer
{
Q_OBJECT
@@ -84,6 +112,9 @@ public:
void setTopologyDiagram(QLabel *diagram, Topology topo);
void setMeshViewPixmap(RDLabel *meshView);
ResourceId updateThumbnail(QWidget *widget, QModelIndex idx);
bool hasThumbnail(QWidget *widget, QModelIndex idx);
QXmlStreamWriter *beginHTMLExport();
void exportHTMLTable(QXmlStreamWriter &xml, const QStringList &cols,
const QList<QVariantList> &rows);
@@ -101,6 +132,13 @@ private:
QMenu *editMenus[6] = {};
RDPreviewTooltip *m_Tooltip = NULL;
TextureDisplay m_TexDisplay;
IReplayOutput *m_Output = NULL;
void RT_UpdateAndDisplay(IReplayController *r);
void AddResourceUsageEntry(QMenu &menu, uint32_t start, uint32_t end, ResourceUsage usage);
void ShowResourceContextMenu(RDTreeWidget *widget, const QPoint &pos, ResourceId id,
const rdcarray<EventUsage> &usage);
@@ -29,8 +29,25 @@
<property name="bottomMargin">
<number>3</number>
</property>
<item>
<widget class="CustomPaintWidget" name="thumbnail" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>CustomPaintWidget</class>
<extends>QWidget</extends>
<header>Widgets/CustomPaintWidget.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>