diff --git a/qrenderdoc/Code/QRDUtils.cpp b/qrenderdoc/Code/QRDUtils.cpp index 9b359fa25..bb842b3fa 100644 --- a/qrenderdoc/Code/QRDUtils.cpp +++ b/qrenderdoc/Code/QRDUtils.cpp @@ -28,11 +28,13 @@ #include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -51,6 +53,7 @@ #include #include #include "Code/Resources.h" +#include "Widgets/Extended/RDListWidget.h" #include "Widgets/Extended/RDTreeWidget.h" // normally this is in the renderdoc core library, but it's needed for the 'unknown enum' path, @@ -2669,3 +2672,62 @@ void LambdaThread::windowsSetName() } #endif + +void UpdateVisibleColumns(rdcstr windowTitle, int columnCount, QHeaderView *header, + const QStringList &headers) +{ + QDialog dialog; + RDListWidget list; + QDialogButtonBox buttons; + + dialog.setWindowTitle(windowTitle); + dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint); + + for(int visIdx = 0; visIdx < columnCount; visIdx++) + { + int logIdx = header->logicalIndex(visIdx); + + QListWidgetItem *item = new QListWidgetItem(headers[logIdx], &list); + + item->setData(Qt::UserRole, logIdx); + + item->setFlags(item->flags() | Qt::ItemIsUserCheckable); + + // The first column must stay enabled + if(logIdx == 0) + item->setFlags(item->flags() & ~Qt::ItemIsEnabled); + + item->setCheckState(header->isSectionHidden(logIdx) ? Qt::Unchecked : Qt::Checked); + } + + list.setSelectionMode(QAbstractItemView::SingleSelection); + list.setDragDropMode(QAbstractItemView::DragDrop); + list.setDefaultDropAction(Qt::MoveAction); + + buttons.setOrientation(Qt::Horizontal); + buttons.setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + buttons.setCenterButtons(true); + + QObject::connect(&buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); + QObject::connect(&buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); + + QVBoxLayout *layout = new QVBoxLayout(&dialog); + layout->addWidget(new QLabel(QString::fromUtf8("Select the columns to enable."), &dialog)); + layout->addWidget(&list); + layout->addWidget(&buttons); + + if(!RDDialog::show(&dialog)) + return; + + for(int i = 0; i < columnCount; i++) + { + int logicalIdx = list.item(i)->data(Qt::UserRole).toInt(); + + if(list.item(i)->checkState() == Qt::Unchecked) + header->hideSection(logicalIdx); + else + header->showSection(logicalIdx); + + header->moveSection(header->visualIndex(logicalIdx), i); + } +} diff --git a/qrenderdoc/Code/QRDUtils.h b/qrenderdoc/Code/QRDUtils.h index 4d7356841..9a8331093 100644 --- a/qrenderdoc/Code/QRDUtils.h +++ b/qrenderdoc/Code/QRDUtils.h @@ -37,6 +37,8 @@ #include #include "Code/Interface/QRDInterface.h" +class QHeaderView; + template inline T AlignUp(T x, T a) { @@ -733,3 +735,6 @@ float getLuminance(const QColor &col); QColor contrastingColor(const QColor &col, const QColor &defaultCol); void *AccessWaylandPlatformInterface(const QByteArray &resource, QWindow *window); + +void UpdateVisibleColumns(rdcstr windowTitle, int columnCount, QHeaderView *header, + const QStringList &headers); diff --git a/qrenderdoc/Widgets/Extended/RDTreeWidget.h b/qrenderdoc/Widgets/Extended/RDTreeWidget.h index 77d283dc7..7aa5e9d8f 100644 --- a/qrenderdoc/Widgets/Extended/RDTreeWidget.h +++ b/qrenderdoc/Widgets/Extended/RDTreeWidget.h @@ -241,6 +241,7 @@ public: QAbstractItemDelegate *itemDelegate() const; void setColumns(const QStringList &columns); + const QStringList &getHeaders() const { return m_headers; } QString headerText(int column) const { return m_headers[column]; } void setHeaderText(int column, const QString &text); RDTreeWidgetItem *selectedItem() const; diff --git a/qrenderdoc/Windows/EventBrowser.cpp b/qrenderdoc/Windows/EventBrowser.cpp index 3ed2c8e55..7fd5ecb0b 100644 --- a/qrenderdoc/Windows/EventBrowser.cpp +++ b/qrenderdoc/Windows/EventBrowser.cpp @@ -740,62 +740,8 @@ void EventBrowser::on_exportDraws_clicked() void EventBrowser::on_colSelect_clicked() { - QDialog dialog; - RDListWidget list; - QDialogButtonBox buttons; - - dialog.setWindowTitle(tr("Select Event Browser Columns")); - dialog.setWindowFlags(dialog.windowFlags() & ~Qt::WindowContextHelpButtonHint); - - for(int visIdx = 0; visIdx < COL_COUNT; visIdx++) - { - int logIdx = ui->events->header()->logicalIndex(visIdx); - - QListWidgetItem *item = new QListWidgetItem(ui->events->headerText(logIdx), &list); - - item->setData(Qt::UserRole, logIdx); - - item->setFlags(item->flags() | Qt::ItemIsUserCheckable); - - // this must stay enabled - if(logIdx == COL_NAME) - item->setFlags(item->flags() & ~Qt::ItemIsEnabled); - - item->setCheckState(ui->events->header()->isSectionHidden(logIdx) ? Qt::Unchecked : Qt::Checked); - } - - list.setSelectionMode(QAbstractItemView::SingleSelection); - list.setDragDropMode(QAbstractItemView::DragDrop); - list.setDefaultDropAction(Qt::MoveAction); - - buttons.setOrientation(Qt::Horizontal); - buttons.setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - buttons.setCenterButtons(true); - - QObject::connect(&buttons, &QDialogButtonBox::accepted, &dialog, &QDialog::accept); - QObject::connect(&buttons, &QDialogButtonBox::rejected, &dialog, &QDialog::reject); - - QVBoxLayout *layout = new QVBoxLayout(&dialog); - layout->addWidget(new QLabel(tr("Select the columns to enable."), &dialog)); - layout->addWidget(&list); - layout->addWidget(&buttons); - - int res = RDDialog::show(&dialog); - - if(res) - { - for(int i = 0; i < COL_COUNT; i++) - { - int logicalIdx = list.item(i)->data(Qt::UserRole).toInt(); - - if(list.item(i)->checkState() == Qt::Unchecked) - ui->events->header()->hideSection(logicalIdx); - else - ui->events->header()->showSection(logicalIdx); - - ui->events->header()->moveSection(ui->events->header()->visualIndex(logicalIdx), i); - } - } + UpdateVisibleColumns(tr("Select Event Browser Columns"), COL_COUNT, ui->events->header(), + ui->events->getHeaders()); } QString EventBrowser::GetExportDrawcallString(int indent, bool firstchild, diff --git a/qrenderdoc/Windows/TextureViewer.cpp b/qrenderdoc/Windows/TextureViewer.cpp index 1c4b627d1..ef60a3742 100644 --- a/qrenderdoc/Windows/TextureViewer.cpp +++ b/qrenderdoc/Windows/TextureViewer.cpp @@ -38,6 +38,7 @@ #include "Code/QRDUtils.h" #include "Code/Resources.h" #include "Dialogs/TextureSaveDialog.h" +#include "Widgets/Extended/RDHeaderView.h" #include "Widgets/ResourcePreview.h" #include "Widgets/TextureGoto.h" #include "flowlayout/FlowLayout.h" @@ -349,141 +350,19 @@ const ShaderBindpointMapping &Following::GetMapping(ICaptureContext &ctx) return GetMapping(ctx, Stage); } -class TextureListItemModel : public QAbstractItemModel +namespace TextureListFilter { -public: - enum FilterType - { - Textures, - RenderTargets, - String - }; - - TextureListItemModel(ICaptureContext &ctx, QWidget *parent) - : QAbstractItemModel(parent), m_Ctx(ctx) - { - goArrow.addPixmap(Pixmaps::action(parent), QIcon::Normal, QIcon::Off); - goArrow.addPixmap(Pixmaps::action_hover(parent), QIcon::Normal, QIcon::Off); - } - void reset(FilterType type, const QString &filter) - { - const rdcarray src = m_Ctx.GetTextures(); - - texs.clear(); - texs.reserve(src.count()); - - emit beginResetModel(); - - TextureCategory rtFlags = TextureCategory::ColorTarget | TextureCategory::DepthTarget; - - for(const TextureDescription &t : src) - { - if(type == Textures) - { - if(!(t.creationFlags & rtFlags)) - texs.push_back(t); - } - else if(type == RenderTargets) - { - if((t.creationFlags & rtFlags)) - texs.push_back(t); - } - else - { - if(filter.isEmpty()) - texs.push_back(t); - else if(QString(m_Ctx.GetResourceName(t.resourceId)).contains(filter, Qt::CaseInsensitive)) - texs.push_back(t); - } - } - - emit endResetModel(); - } - - QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const override - { - if(row < 0 || row >= rowCount()) - return QModelIndex(); - - return createIndex(row, 0); - } - - QModelIndex parent(const QModelIndex &index) const override { return QModelIndex(); } - int rowCount(const QModelIndex &parent = QModelIndex()) const override { return texs.count(); } - int columnCount(const QModelIndex &parent = QModelIndex()) const override { return 1; } - Qt::ItemFlags flags(const QModelIndex &index) const override - { - if(!index.isValid()) - return 0; - - return QAbstractItemModel::flags(index); - } - - QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override - { - if(index.isValid()) - { - if(role == Qt::DisplayRole) - { - if(index.row() >= 0 && index.row() < texs.count()) - return m_Ctx.GetResourceName(texs[index.row()].resourceId); - } - - if(role == Qt::UserRole) - { - return QVariant::fromValue(texs[index.row()].resourceId); - } - - if(role == Qt::DecorationRole) - { - return QVariant(goArrow); - } - } - - return QVariant(); - } - -private: - ICaptureContext &m_Ctx; - QVector texs; - QIcon goArrow; -}; - -class TextureListItemDelegate : public QItemDelegate +enum Columns { -public: - TextureListItemDelegate(QObject *parent = 0) : QItemDelegate(parent) {} - void paint(QPainter *painter, const QStyleOptionViewItem &opt, const QModelIndex &index) const override - { - if(index.isValid()) - { - QStyleOptionViewItem option = opt; - option.decorationAlignment = Qt::AlignBaseline | Qt::AlignRight; - painter->eraseRect(option.rect); - - QIcon icon = index.model()->data(index, Qt::DecorationRole).value(); - - drawBackground(painter, option, index); - if(option.state & QStyle::State_MouseOver) - drawDecoration(painter, option, option.rect, - icon.pixmap(option.decorationSize, QIcon::Active)); - else - drawDecoration(painter, option, option.rect, - icon.pixmap(option.decorationSize, QIcon::Normal)); - drawDisplay(painter, option, option.rect, - index.model()->data(index, Qt::DisplayRole).toString()); - drawFocus(painter, option, option.rect); - - if(option.state & QStyle::State_MouseOver) - { - QRect r = option.rect; - r.adjust(0, 0, -1, -1); - - painter->drawRect(r); - } - } - } + Column_TexName, + Column_TexWidth, + Column_TexHeight, + Column_TexDepth, + Column_MipsCount, + Column_TexFormat, + Column_Count, }; +} TextureDescription *TextureViewer::GetCurrentTexture() { @@ -635,6 +514,9 @@ TextureViewer::TextureViewer(ICaptureContext &ctx, QWidget *parent) }); } + QObject::connect(ui->textureList, &RDTreeWidget::itemActivated, this, + &TextureViewer::texture_itemActivated); + QWidget *renderContainer = ui->renderContainer; ui->dockarea->addToolWindow(ui->renderContainer, ToolWindowManager::EmptySpace); @@ -643,6 +525,12 @@ TextureViewer::TextureViewer(ICaptureContext &ctx, QWidget *parent) ToolWindowManager::DisableDraggableTab | ToolWindowManager::AlwaysDisplayFullTabs); + ui->dockarea->addToolWindow( + ui->textureListFrame, + ToolWindowManager::AreaReference(ToolWindowManager::NoArea, + ui->dockarea->areaOf(renderContainer), 0.25f)); + ui->dockarea->setToolWindowProperties(ui->textureListFrame, ToolWindowManager::HideOnClose); + ui->dockarea->addToolWindow(ui->inputThumbs, ToolWindowManager::AreaReference( ToolWindowManager::RightOf, ui->dockarea->areaOf(renderContainer), 0.25f)); @@ -659,9 +547,6 @@ TextureViewer::TextureViewer(ICaptureContext &ctx, QWidget *parent) ui->dockarea->areaOf(ui->outputThumbs), 0.25f)); ui->dockarea->setToolWindowProperties(ui->pixelContextLayout, ToolWindowManager::HideCloseButton); - ui->dockarea->addToolWindow(ui->textureListFrame, ToolWindowManager::NoArea); - ui->dockarea->setToolWindowProperties(ui->textureListFrame, ToolWindowManager::HideOnClose); - ui->dockarea->setAllowFloatingWindow(false); renderContainer->setWindowTitle(tr("Unbound")); @@ -670,8 +555,6 @@ TextureViewer::TextureViewer(ICaptureContext &ctx, QWidget *parent) ui->inputThumbs->setWindowTitle(tr("Inputs")); ui->textureListFrame->setWindowTitle(tr("Texture List")); - ui->textureList->setHoverCursor(Qt::PointingHandCursor); - m_Goto = new TextureGoto(this, [this](QPoint p) { GotoLocation(p.x(), p.y()); }); QVBoxLayout *vertical = new QVBoxLayout(this); @@ -749,9 +632,20 @@ TextureViewer::TextureViewer(ICaptureContext &ctx, QWidget *parent) ui->textureListFilter->addItems({QString(), tr("Textures"), tr("Render Targets")}); - ui->textureList->setModel(new TextureListItemModel(m_Ctx, this)); - ui->textureList->setItemDelegate(new TextureListItemDelegate(ui->textureList)); + ui->textureList->setColumns({tr("Texture Name"), tr("Width"), tr("Height"), tr("Depth/Slices"), + tr("Mips Count"), tr("Format"), tr("Go")}); + ui->textureList->setHoverIconColumn(6, Icons::action(), Icons::action_hover()); ui->textureList->viewport()->setAttribute(Qt::WA_Hover); + ui->textureList->setMouseTracking(true); + { + RDHeaderView *header = new RDHeaderView(Qt::Horizontal, this); + ui->textureList->setHeader(header); + + header->setColumnStretchHints({1, -1, -1, -1, -1, -1, -1}); + } + + ui->textureList->header()->sortIndicatorChanged(TextureListFilter::Column_TexName, + Qt::SortOrder::DescendingOrder); ui->zoomOption->setCurrentText(QString()); ui->fitToWindow->toggle(); @@ -2881,10 +2775,6 @@ void TextureViewer::OnCaptureLoaded() ui->debugPixelContext->setEnabled(false); ui->pixelHistory->setToolTip(QString()); - TextureListItemModel *model = (TextureListItemModel *)ui->textureList->model(); - - model->reset(TextureListItemModel::String, QString()); - m_TexDisplay.backgroundColor = backCol.isValid() ? FloatVector(backCol.redF(), backCol.greenF(), backCol.blueF(), 1.0f) : FloatVector(); @@ -2977,6 +2867,71 @@ void TextureViewer::Reset() UI_UpdateChannels(); } +void TextureViewer::refreshTextureList() +{ + refreshTextureList(FilterType::None, QString()); +} + +void addToRoot(RDTreeWidgetItem *root, const TextureDescription &t) +{ + const QVariant &res = QVariant::fromValue(t.resourceId); + RDTreeWidgetItem *child = + new RDTreeWidgetItem({res, t.width, t.height, (3 == t.dimension ? t.depth : t.arraysize), + t.mips, t.format.Name(), QString()}); + + child->setTag(res); + root->addChild(child); +} + +void TextureViewer::refreshTextureList(FilterType filterType, const QString &filterStr) +{ + ui->textureList->beginUpdate(); + ui->textureList->clearSelection(); + + ui->textureList->clear(); + RDTreeWidgetItem *root = ui->textureList->invisibleRootItem(); + + TextureCategory rtFlags = TextureCategory::ColorTarget | TextureCategory::DepthTarget; + + for(const TextureDescription &t : m_Ctx.GetTextures()) + { + if(filterType == FilterType::Textures) + { + if(!(t.creationFlags & rtFlags)) + addToRoot(root, t); + } + else if(filterType == FilterType::RenderTargets) + { + if((t.creationFlags & rtFlags)) + addToRoot(root, t); + } + else + { + if(filterStr.isEmpty()) + { + addToRoot(root, t); + } + else + { + if(QString(m_Ctx.GetResourceName(t.resourceId)).contains(filterStr, Qt::CaseInsensitive) || + QString::number(t.width).contains(filterStr, Qt::CaseInsensitive) || + QString::number(t.height).contains(filterStr, Qt::CaseInsensitive) || + QString::number((3 == t.dimension ? t.depth : t.arraysize)) + .contains(filterStr, Qt::CaseInsensitive) || + QString::number(t.mips).contains(filterStr, Qt::CaseInsensitive) || + QString(t.format.Name()).contains(filterStr, Qt::CaseInsensitive)) + addToRoot(root, t); + } + } + } + + ui->textureList->setSelectedItem(root); + + ui->textureList->setUpdatesEnabled(true); + + ui->textureList->endUpdate(); +} + void TextureViewer::OnCaptureClosed() { Reset(); @@ -3145,6 +3100,18 @@ QVariant TextureViewer::persistData() { QVariantMap state = ui->dockarea->saveState(); + QVariantList columns; + for(int i = 0; i < TextureListFilter::Column_Count; i++) + { + QVariantMap col; + + bool hidden = ui->textureList->header()->isSectionHidden(i); + + col[lit("hidden")] = hidden; + columns.push_back(col); + } + + state[lit("columns")] = columns; state[lit("backCol")] = backCol; state[lit("checker")] = !backCol.isValid(); @@ -3155,6 +3122,19 @@ void TextureViewer::setPersistData(const QVariant &persistData) { QVariantMap state = persistData.toMap(); + QVariantList columns = state[lit("columns")].toList(); + for(int i = 0; i < columns.count() && i < TextureListFilter::Column_Count; i++) + { + QVariantMap col = columns[i].toMap(); + + bool hidden = col[lit("hidden")].toBool(); + + if(hidden) + ui->textureList->header()->hideSection(i); + else + ui->textureList->header()->showSection(i); + } + backCol = state[lit("backCol")].value(); bool checker = state[lit("checker")].value(); @@ -3958,7 +3938,7 @@ void TextureViewer::on_texListShow_clicked() ui->textureListFilter->setCurrentText(QString()); ui->dockarea->moveToolWindow( ui->textureListFrame, - ToolWindowManager::AreaReference(ToolWindowManager::LeftOf, + ToolWindowManager::AreaReference(ToolWindowManager::BottomOf, ui->dockarea->areaOf(ui->renderContainer), 0.2f)); ui->dockarea->setToolWindowProperties(ui->textureListFrame, ToolWindowManager::HideOnClose); } @@ -3969,40 +3949,55 @@ void TextureViewer::on_cancelTextureListFilter_clicked() ui->textureListFilter->setCurrentText(QString()); } +void TextureViewer::on_colSelect_clicked() +{ + QStringList headers; + for(int i = 0; i < TextureListFilter::Column_Count; ++i) + { + headers.push_back( + ui->textureList->model()->headerData(i, Qt::Horizontal, Qt::DisplayRole).toString()); + } + + UpdateVisibleColumns(tr("Select Texture List Columns"), TextureListFilter::Column_Count, + ui->textureList->header(), headers); +} + void TextureViewer::on_textureListFilter_editTextChanged(const QString &text) { - TextureListItemModel *model = (TextureListItemModel *)ui->textureList->model(); - - if(model == NULL) - return; - - model->reset(TextureListItemModel::String, text); + refreshTextureList(FilterType::String, text); } void TextureViewer::on_textureListFilter_currentIndexChanged(int index) { - refreshTextureList(); + if(ui->textureListFilter->currentIndex() == 1) + refreshTextureList(FilterType::Textures, QString()); + else if(ui->textureListFilter->currentIndex() == 2) + refreshTextureList(FilterType::RenderTargets, QString()); + else + refreshTextureList(FilterType::String, ui->textureListFilter->currentText()); } -void TextureViewer::refreshTextureList() +void TextureViewer::texture_itemActivated(RDTreeWidgetItem *item, int column) { - TextureListItemModel *model = (TextureListItemModel *)ui->textureList->model(); - - if(model == NULL) + QVariant tag = item->tag(); + if(!tag.canConvert()) return; - if(ui->textureListFilter->currentIndex() == 1) - model->reset(TextureListItemModel::Textures, QString()); - else if(ui->textureListFilter->currentIndex() == 2) - model->reset(TextureListItemModel::RenderTargets, QString()); - else - model->reset(TextureListItemModel::String, ui->textureListFilter->currentText()); -} + TextureDescription *tex = m_Ctx.GetTexture(tag.value()); + if(!tex) + return; -void TextureViewer::on_textureList_clicked(const QModelIndex &index) -{ - ResourceId id = index.model()->data(index, Qt::UserRole).value(); - ViewTexture(id, false); + if(tex->type == TextureType::Buffer) + { + IBufferViewer *viewer = m_Ctx.ViewTextureAsBuffer( + tex->resourceId, Subresource(), BufferFormatter::GetTextureFormatString(*tex)); + + m_Ctx.AddDockWindow(viewer->Widget(), DockReference::AddTo, this); + } + else + { + ViewTexture(tex->resourceId, true); + } } bool TextureViewer::canCompileCustomShader(ShaderEncoding encoding) diff --git a/qrenderdoc/Windows/TextureViewer.h b/qrenderdoc/Windows/TextureViewer.h index 15e78d125..7c787f54c 100644 --- a/qrenderdoc/Windows/TextureViewer.h +++ b/qrenderdoc/Windows/TextureViewer.h @@ -36,6 +36,7 @@ namespace Ui class TextureViewer; } +class RDTreeWidgetItem; class ResourcePreview; class ThumbnailStrip; class TextureGoto; @@ -128,6 +129,15 @@ private: Q_PROPERTY(QVariant persistData READ persistData WRITE setPersistData DESIGNABLE false SCRIPTABLE false) + // Texture List + enum class FilterType + { + None, + Textures, + RenderTargets, + String + }; + public: explicit TextureViewer(ICaptureContext &ctx, QWidget *parent = 0); ~TextureViewer(); @@ -182,7 +192,8 @@ private slots: void on_cancelTextureListFilter_clicked(); void on_textureListFilter_editTextChanged(const QString &text); void on_textureListFilter_currentIndexChanged(int index); - void on_textureList_clicked(const QModelIndex &index); + void on_colSelect_clicked(); + void texture_itemActivated(RDTreeWidgetItem *item, int column); // manual slots void render_mouseClick(QMouseEvent *e); @@ -243,6 +254,7 @@ private: void Reset(); void refreshTextureList(); + void refreshTextureList(FilterType filterType, const QString &filterStr); ResourcePreview *UI_CreateThumbnail(ThumbnailStrip *strip); void UI_CreateThumbnails(); diff --git a/qrenderdoc/Windows/TextureViewer.ui b/qrenderdoc/Windows/TextureViewer.ui index 3112bbe83..be08fc2fb 100644 --- a/qrenderdoc/Windows/TextureViewer.ui +++ b/qrenderdoc/Windows/TextureViewer.ui @@ -1308,10 +1308,25 @@ See FAQ on "Gamma display of linear data" - + + + + Select visible columns + + + + :/timeline_marker.png:/timeline_marker.png + + + + true + + + + - + QFrame::Box @@ -1324,18 +1339,30 @@ See FAQ on "Gamma display of linear data" false - - Qt::CopyAction + + 0 - - QAbstractItemView::NoSelection + + true - - QListView::ListMode + + true - + + true + + + false + + + false + + true + + false + @@ -1379,6 +1406,11 @@ See FAQ on "Gamma display of linear data" QToolButton
Widgets/Extended/RDToolButton.h
+ + RDTreeWidget + QTreeView +
Widgets/Extended/RDTreeWidget.h
+