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
+
+
+
-