diff --git a/qrenderdoc/Code/Resources.h b/qrenderdoc/Code/Resources.h index a95c54ecb..92a7dae13 100644 --- a/qrenderdoc/Code/Resources.h +++ b/qrenderdoc/Code/Resources.h @@ -108,7 +108,8 @@ RESOURCE_DEF(topo_tristrip, "topologies/topo_tristrip.svg") \ RESOURCE_DEF(topo_tristrip_adj, "topologies/topo_tristrip_adj.svg") \ RESOURCE_DEF(action, "action.png") \ - RESOURCE_DEF(action_hover, "action_hover.png") + RESOURCE_DEF(action_hover, "action_hover.png") \ + RESOURCE_DEF(bookmark_blue, "bookmark_blue.png") struct Resource { diff --git a/qrenderdoc/Resources/bookmark_blue.png b/qrenderdoc/Resources/bookmark_blue.png new file mode 100644 index 000000000..acd8a6913 Binary files /dev/null and b/qrenderdoc/Resources/bookmark_blue.png differ diff --git a/qrenderdoc/Resources/bookmark_blue@2x.png b/qrenderdoc/Resources/bookmark_blue@2x.png new file mode 100644 index 000000000..3d6e93111 Binary files /dev/null and b/qrenderdoc/Resources/bookmark_blue@2x.png differ diff --git a/qrenderdoc/Resources/resources.qrc b/qrenderdoc/Resources/resources.qrc index 3860d68eb..fa750b87b 100644 --- a/qrenderdoc/Resources/resources.qrc +++ b/qrenderdoc/Resources/resources.qrc @@ -151,5 +151,7 @@ wrench@2x.png zoom.png zoom@2x.png + bookmark_blue.png + bookmark_blue@2x.png diff --git a/qrenderdoc/Windows/ShaderViewer.cpp b/qrenderdoc/Windows/ShaderViewer.cpp index 68063c33b..62b777a9a 100644 --- a/qrenderdoc/Windows/ShaderViewer.cpp +++ b/qrenderdoc/Windows/ShaderViewer.cpp @@ -838,6 +838,45 @@ void ShaderViewer::debugShader(const ShaderReflection *shader, ResourceId pipeli ui->execForwards->setMenu(forwardsMenu); } + { + QMenu *bookmarkMenu = new QMenu(this); + bookmarkMenu->setToolTipsVisible(true); + + QAction *toggleAction = MakeExecuteAction(tr("Toggle Bookmark"), Icons::bookmark_blue(), + tr("Toggle bookmark on current line"), + QKeySequence(Qt::Key_F2 | Qt::ControlModifier)); + QObject::connect(toggleAction, &QAction::triggered, [this]() { ToggleBookmark(); }); + bookmarkMenu->addAction(toggleAction); + + QAction *nextAction = MakeExecuteAction(tr("Next Bookmark"), Icons::arrow_right(), + tr("Go to next bookmark in the current file"), + QKeySequence(Qt::Key_F2)); + QObject::connect(nextAction, &QAction::triggered, [this]() { NextBookmark(); }); + bookmarkMenu->addAction(nextAction); + + QAction *prevAction = MakeExecuteAction(tr("Previous Bookmark"), Icons::arrow_left(), + tr("Go to previous bookmark in the current file"), + QKeySequence(Qt::Key_F2 | Qt::ShiftModifier)); + QObject::connect(prevAction, &QAction::triggered, [this]() { PreviousBookmark(); }); + bookmarkMenu->addAction(prevAction); + + QAction *clearAction = + MakeExecuteAction(tr("Clear All Bookmarks"), Icons::cross(), + tr("Clear all bookmarks in the current file"), QKeySequence()); + QObject::connect(clearAction, &QAction::triggered, [this]() { ClearAllBookmarks(); }); + bookmarkMenu->addAction(clearAction); + + QObject::connect(bookmarkMenu, &QMenu::aboutToShow, + [this, nextAction, prevAction, clearAction]() { + const bool hasBookmarks = HasBookmarks(); + nextAction->setEnabled(hasBookmarks); + prevAction->setEnabled(hasBookmarks); + clearAction->setEnabled(hasBookmarks); + }); + + ui->bookmark->setMenu(bookmarkMenu); + } + for(ScintillaEdit *edit : m_Scintillas) { edit->setMarginWidthN(1, 20.0 * devicePixelRatioF()); @@ -865,6 +904,16 @@ void ShaderViewer::debugShader(const ShaderReflection *shader, ResourceId pipeli m_Ctx.GetMainWindow()->RegisterShortcut(QKeySequence(Qt::Key_F9).toString(), this, [this](QWidget *) { ToggleBreakpointOnInstruction(); }); + // toggle bookmark - Ctrl-F2 + m_Ctx.GetMainWindow()->RegisterShortcut(QKeySequence(Qt::Key_F2 | Qt::ControlModifier).toString(), + this, [this](QWidget *) { ToggleBookmark(); }); + // next bookmark - F2 + m_Ctx.GetMainWindow()->RegisterShortcut(QKeySequence(Qt::Key_F2).toString(), this, + [this](QWidget *) { NextBookmark(); }); + // previous bookmark - Shift-F2 + m_Ctx.GetMainWindow()->RegisterShortcut(QKeySequence(Qt::Key_F2 | Qt::ShiftModifier).toString(), + this, [this](QWidget *) { PreviousBookmark(); }); + // event filter to pick up tooltip events ui->constants->installEventFilter(this); ui->accessedResources->installEventFilter(this); @@ -1173,6 +1222,10 @@ void ShaderViewer::debugShader(const ShaderReflection *shader, ResourceId pipeli edit->markerSetBack(BREAKPOINT_MARKER + 1, SCINTILLA_COLOUR(255, 0, 0)); edit->markerDefine(BREAKPOINT_MARKER, SC_MARK_CIRCLE); edit->markerDefine(BREAKPOINT_MARKER + 1, SC_MARK_BACKGROUND); + + // C# Highlight + edit->markerSetBack(BOOKMARK_MARKER, SCINTILLA_COLOUR(51, 153, 255)); + edit->markerDefine(BOOKMARK_MARKER, SC_MARK_BOOKMARK); } } @@ -1489,36 +1542,14 @@ void ShaderViewer::readonly_keyPressed(QKeyEvent *event) if(event->key() == Qt::Key_F && (event->modifiers() & Qt::ControlModifier)) { m_FindReplace->setReplaceMode(false); - - ScintillaEdit *edit = qobject_cast(QObject::sender()); - - if(edit) - { - // if there's a selection, fill the find prompt with that - if(!edit->getSelText().isEmpty()) - { - m_FindReplace->setFindText(QString::fromUtf8(edit->getSelText())); - } - else - { - // otherwise pick the word under the cursor, if there is one - sptr_t scintillaPos = edit->currentPos(); - - sptr_t start = edit->wordStartPosition(scintillaPos, true); - sptr_t end = edit->wordEndPosition(scintillaPos, true); - - QByteArray text = edit->textRange(start, end); - - if(!text.isEmpty()) - m_FindReplace->setFindText(QString::fromUtf8(text)); - } - } - + SetFindTextFromCurrentWord(); on_findReplace_clicked(); } if(event->key() == Qt::Key_F3) { + if(event->modifiers() & Qt::ControlModifier) + SetFindTextFromCurrentWord(); find((event->modifiers() & Qt::ShiftModifier) == 0); } } @@ -1604,6 +1635,31 @@ void ShaderViewer::debug_contextMenu(const QPoint &pos) contextMenu.addAction(&runForwardCursor); contextMenu.addSeparator(); + QAction toggleBookmark(tr("Toggle bookmark here"), this); + QAction nextBookmark(tr("Go to next Bookmark"), this); + QAction prevBookmark(tr("Go to previous Bookmark"), this); + QAction clearBookmarks(tr("Clear all Bookmarks"), this); + + const bool hasBookmarks = HasBookmarks(); + nextBookmark.setEnabled(hasBookmarks); + prevBookmark.setEnabled(hasBookmarks); + clearBookmarks.setEnabled(hasBookmarks); + + toggleBookmark.setShortcut(QKeySequence(Qt::Key_F2 | Qt::ControlModifier)); + nextBookmark.setShortcut(QKeySequence(Qt::Key_F2)); + prevBookmark.setShortcut(QKeySequence(Qt::Key_F2 | Qt::ShiftModifier)); + + QObject::connect(&toggleBookmark, &QAction::triggered, [this] { ToggleBookmark(); }); + QObject::connect(&nextBookmark, &QAction::triggered, [this] { NextBookmark(); }); + QObject::connect(&prevBookmark, &QAction::triggered, [this] { PreviousBookmark(); }); + QObject::connect(&clearBookmarks, &QAction::triggered, [this] { ClearAllBookmarks(); }); + + contextMenu.addAction(&toggleBookmark); + contextMenu.addAction(&nextBookmark); + contextMenu.addAction(&prevBookmark); + contextMenu.addAction(&clearBookmarks); + contextMenu.addSeparator(); + QAction watchExpr(tr("Add Watch Expression"), this); watchExpr.setEnabled(!edit->selectionEmpty()); @@ -6528,3 +6584,108 @@ void ShaderViewer::performReplaceAll() this, tr("Replace all"), tr("%1 replacements made in %2 files").arg(numReplacements).arg(scintillas.count())); } + +void ShaderViewer::ToggleBookmark() +{ + ScintillaEdit *cur = currentScintilla(); + if(!cur) + return; + + sptr_t curLine = cur->lineFromPosition(cur->currentPos()); + + QList &bookmarks = m_Bookmarks[cur]; + if(bookmarks.contains(curLine)) + { + bookmarks.removeOne(curLine); + cur->markerDelete(curLine, BOOKMARK_MARKER); + } + else + { + // Insert new bookmark in numerical order + bookmarks.insert(std::lower_bound(bookmarks.begin(), bookmarks.end(), curLine), curLine); + cur->markerAdd(curLine, BOOKMARK_MARKER); + } +} + +void ShaderViewer::NextBookmark() +{ + ScintillaEdit *cur = currentScintilla(); + if(!cur) + return; + + auto itBookmarks = m_Bookmarks.find(cur); + if(itBookmarks == m_Bookmarks.end() || itBookmarks->empty()) + return; + + sptr_t curLine = cur->lineFromPosition(cur->currentPos()); + auto itNextBookmark = std::upper_bound(itBookmarks->begin(), itBookmarks->end(), curLine); + if(itNextBookmark == itBookmarks->end()) + itNextBookmark = itBookmarks->begin(); + + if(*itNextBookmark != curLine) + cur->gotoLine(*itNextBookmark); +} + +void ShaderViewer::PreviousBookmark() +{ + ScintillaEdit *cur = currentScintilla(); + if(!cur) + return; + + auto itBookmarks = m_Bookmarks.find(cur); + if(itBookmarks == m_Bookmarks.end()) + return; + + sptr_t curLine = cur->lineFromPosition(cur->currentPos()); + auto itPrevBookmark = std::lower_bound(itBookmarks->begin(), itBookmarks->end(), curLine); + if(itPrevBookmark == itBookmarks->begin()) + itPrevBookmark = itBookmarks->end(); + --itPrevBookmark; + + if(*itPrevBookmark != curLine) + cur->gotoLine(*itPrevBookmark); +} + +void ShaderViewer::ClearAllBookmarks() +{ + ScintillaEdit *cur = currentScintilla(); + if(!cur) + return; + + cur->markerDeleteAll(BOOKMARK_MARKER); + m_Bookmarks.remove(cur); +} + +void ShaderViewer::SetFindTextFromCurrentWord() +{ + ScintillaEdit *edit = qobject_cast(QObject::sender()); + + if(edit) + { + // if there's a selection, fill the find prompt with that + if(!edit->getSelText().isEmpty()) + { + m_FindReplace->setFindText(QString::fromUtf8(edit->getSelText())); + } + else + { + // otherwise pick the word under the cursor, if there is one + sptr_t scintillaPos = edit->currentPos(); + + sptr_t start = edit->wordStartPosition(scintillaPos, true); + sptr_t end = edit->wordEndPosition(scintillaPos, true); + + QByteArray text = edit->textRange(start, end); + + if(!text.isEmpty()) + m_FindReplace->setFindText(QString::fromUtf8(text)); + } + } +} + +bool ShaderViewer::HasBookmarks() +{ + ScintillaEdit *cur = currentScintilla(); + auto itBookmarks = m_Bookmarks.find(cur); + return itBookmarks != m_Bookmarks.end() && !itBookmarks->empty(); +} diff --git a/qrenderdoc/Windows/ShaderViewer.h b/qrenderdoc/Windows/ShaderViewer.h index 1c34b5449..10df04745 100644 --- a/qrenderdoc/Windows/ShaderViewer.h +++ b/qrenderdoc/Windows/ShaderViewer.h @@ -238,6 +238,14 @@ private: ShaderEncoding currentEncoding(); + void ToggleBookmark(); + void NextBookmark(); + void PreviousBookmark(); + void ClearAllBookmarks(); + bool HasBookmarks(); + + void SetFindTextFromCurrentWord(); + QString m_TooltipVarPath; int m_TooltipVarIndex = -1; int m_TooltipMember = -1; @@ -326,9 +334,12 @@ private: QList> m_FindAllResults; + QMap> m_Bookmarks; + static const int CURRENT_MARKER = 0; static const int BREAKPOINT_MARKER = 2; static const int FINISHED_MARKER = 4; + static const int BOOKMARK_MARKER = 6; static const int CURRENT_INDICATOR = 20; static const int FINISHED_INDICATOR = 21; diff --git a/qrenderdoc/Windows/ShaderViewer.ui b/qrenderdoc/Windows/ShaderViewer.ui index 989ab02d4..ad0aee341 100644 --- a/qrenderdoc/Windows/ShaderViewer.ui +++ b/qrenderdoc/Windows/ShaderViewer.ui @@ -319,6 +319,29 @@ + + + + Add, remove or jump to bookmarks in current file + + + Bookmark... + + + + :/bookmark_blue.png:/bookmark_blue.png + + + QToolButton::InstantPopup + + + Qt::ToolButtonTextBesideIcon + + + true + + +