mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-10-07 12:51:33 +00:00
Allow registering window, panel and context menu items with callbacks
This commit is contained in:
24 files changed
+963
-67
No files matched your search
@@ -35,6 +35,7 @@
|
||||
#include <QProgressDialog>
|
||||
#include <QRegularExpression>
|
||||
#include <QTimer>
|
||||
#include "Code/Resources.h"
|
||||
#include "Code/pyrenderdoc/PythonContext.h"
|
||||
#include "Windows/APIInspector.h"
|
||||
#include "Windows/BufferViewer.h"
|
||||
@@ -348,10 +349,309 @@ bool CaptureContext::LoadExtension(rdcstr name)
|
||||
}
|
||||
});
|
||||
|
||||
m_MainWindow->CleanMenus();
|
||||
for(QAction *a : m_MainWindow->GetMenuActions())
|
||||
CleanMenu(a);
|
||||
|
||||
m_RegisteredMenuItems.removeAll(NULL);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CaptureContext::RegisterWindowMenu(WindowMenu base, const rdcarray<rdcstr> &submenus,
|
||||
ExtensionCallback callback)
|
||||
{
|
||||
if(base == WindowMenu::Unknown)
|
||||
{
|
||||
qCritical() << "Can't register menu for WindowMenu::Unknown";
|
||||
return;
|
||||
}
|
||||
|
||||
if(submenus.isEmpty())
|
||||
{
|
||||
qCritical() << "Empty list of submenus";
|
||||
return;
|
||||
}
|
||||
|
||||
if(base == WindowMenu::NewMenu && submenus.count() == 1)
|
||||
{
|
||||
qCritical() << "Need at least two items in submenus for WindowMenu::NewMenu";
|
||||
return;
|
||||
}
|
||||
|
||||
QMenu *menu = m_MainWindow->GetBaseMenu(base, submenus[0]);
|
||||
|
||||
if(!menu)
|
||||
{
|
||||
qCritical() << "Couldn't get base menu";
|
||||
return;
|
||||
}
|
||||
|
||||
std::function<void()> slotcallback = [this, callback]() { callback(this, {}); };
|
||||
|
||||
// if it's a new menu, GetBaseMenu already did the work, so skip the 0th element of submenus
|
||||
if(base == WindowMenu::NewMenu)
|
||||
{
|
||||
rdcarray<rdcstr> items = submenus;
|
||||
items.erase(0);
|
||||
AddSortedMenuItem(menu, false, items, slotcallback);
|
||||
}
|
||||
else
|
||||
{
|
||||
AddSortedMenuItem(menu, false, submenus, slotcallback);
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureContext::RegisterPanelMenu(PanelMenu base, const rdcarray<rdcstr> &submenus,
|
||||
ExtensionCallback callback)
|
||||
{
|
||||
if(base == PanelMenu::Unknown)
|
||||
{
|
||||
qCritical() << "Can't register menu for PanelMenu::Unknown";
|
||||
return;
|
||||
}
|
||||
|
||||
RegisteredMenuItem *item = new RegisteredMenuItem();
|
||||
item->panel = base;
|
||||
item->submenus = submenus;
|
||||
item->callback = callback;
|
||||
m_RegisteredMenuItems.push_back(item);
|
||||
m_PendingExtensionObjects.push_back(item);
|
||||
}
|
||||
|
||||
void CaptureContext::RegisterContextMenu(ContextMenu base, const rdcarray<rdcstr> &submenus,
|
||||
ExtensionCallback callback)
|
||||
{
|
||||
if(base == ContextMenu::Unknown)
|
||||
{
|
||||
qCritical() << "Can't register menu for ContextMenu::Unknown";
|
||||
return;
|
||||
}
|
||||
|
||||
RegisteredMenuItem *item = new RegisteredMenuItem();
|
||||
item->context = base;
|
||||
item->submenus = submenus;
|
||||
item->callback = callback;
|
||||
m_RegisteredMenuItems.push_back(item);
|
||||
m_PendingExtensionObjects.push_back(item);
|
||||
}
|
||||
|
||||
void CaptureContext::MenuDisplaying(ContextMenu contextMenu, QMenu *menu,
|
||||
const ExtensionCallbackData &data)
|
||||
{
|
||||
ContextMenu contextMenuAlt = contextMenu;
|
||||
|
||||
switch(contextMenu)
|
||||
{
|
||||
case ContextMenu::MeshPreview_GSOutVertex:
|
||||
case ContextMenu::MeshPreview_VSInVertex:
|
||||
case ContextMenu::MeshPreview_VSOutVertex:
|
||||
contextMenuAlt = ContextMenu::MeshPreview_Vertex;
|
||||
break;
|
||||
case ContextMenu::TextureViewer_InputThumbnail:
|
||||
case ContextMenu::TextureViewer_OutputThumbnail:
|
||||
contextMenuAlt = ContextMenu::TextureViewer_Thumbnail;
|
||||
break;
|
||||
}
|
||||
|
||||
for(RegisteredMenuItem *item : m_RegisteredMenuItems)
|
||||
{
|
||||
if(item->context == contextMenu || item->context == contextMenuAlt)
|
||||
{
|
||||
AddSortedMenuItem(menu, true, item->submenus, [this, item, data]() {
|
||||
rdcarray<rdcpair<rdcstr, PyObject *>> args;
|
||||
|
||||
PythonContext::ConvertPyArgs(data, args);
|
||||
|
||||
item->callback(this, args);
|
||||
|
||||
PythonContext::FreePyArgs(args);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CaptureContext::MenuDisplaying(PanelMenu panelMenu, QWidget *extensionButton,
|
||||
const ExtensionCallbackData &data)
|
||||
{
|
||||
QMenu contextMenu(m_MainWindow);
|
||||
|
||||
for(RegisteredMenuItem *item : m_RegisteredMenuItems)
|
||||
{
|
||||
if(item->panel == panelMenu)
|
||||
{
|
||||
AddSortedMenuItem(&contextMenu, false, item->submenus, [this, item, data]() {
|
||||
rdcarray<rdcpair<rdcstr, PyObject *>> args;
|
||||
|
||||
PythonContext::ConvertPyArgs(data, args);
|
||||
|
||||
item->callback(this, args);
|
||||
|
||||
PythonContext::FreePyArgs(args);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
QAction emptyAction(tr("No extension commands configured"), m_MainWindow);
|
||||
|
||||
if(contextMenu.isEmpty())
|
||||
{
|
||||
contextMenu.addAction(&emptyAction);
|
||||
QObject::connect(&emptyAction, &QAction::triggered,
|
||||
[this]() { m_MainWindow->showExtensionManager(); });
|
||||
}
|
||||
|
||||
RDDialog::show(&contextMenu, extensionButton->mapToGlobal(extensionButton->rect().bottomLeft()));
|
||||
}
|
||||
|
||||
void CaptureContext::AddSortedMenuItem(QMenu *menu, bool rootMenu, const rdcarray<rdcstr> &items,
|
||||
std::function<void()> callback)
|
||||
{
|
||||
QAction *beforeAction = NULL;
|
||||
bool addIcon = rootMenu;
|
||||
|
||||
// if we're inserting into a pre-existing menu, try to find an __examples__ action which tells us
|
||||
// where
|
||||
// to be inserting
|
||||
{
|
||||
QList<QAction *> children = menu->actions();
|
||||
int idx = 0;
|
||||
for(; idx < children.count(); idx++)
|
||||
{
|
||||
if(children[idx]->text() == lit("__extensions__"))
|
||||
break;
|
||||
}
|
||||
|
||||
// if we found it, set beforeAction
|
||||
if(idx < children.count())
|
||||
{
|
||||
// search back to find the right place alphabetically to place this, if there are existing
|
||||
// menus
|
||||
|
||||
for(; idx > 0;)
|
||||
{
|
||||
// if the previous child is a separator, break, there are no more previous menus
|
||||
if(children[idx - 1]->isSeparator())
|
||||
break;
|
||||
|
||||
// if we should be sorted before the previous child, move backwards
|
||||
if(children[idx - 1]->text() > items[0])
|
||||
{
|
||||
idx--;
|
||||
continue;
|
||||
}
|
||||
|
||||
// if we found the right place, break
|
||||
break;
|
||||
}
|
||||
|
||||
beforeAction = children[idx];
|
||||
addIcon = true;
|
||||
}
|
||||
}
|
||||
|
||||
for(int i = 0; i < items.count() - 1; i++)
|
||||
{
|
||||
QList<QAction *> children = menu->actions();
|
||||
|
||||
bool found = false;
|
||||
|
||||
// see if this submenu already exists, if so just iterate down to it
|
||||
for(QAction *a : children)
|
||||
{
|
||||
if(a->text() == items[i])
|
||||
{
|
||||
menu = a->menu();
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(found)
|
||||
{
|
||||
addIcon = false;
|
||||
beforeAction = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
// create the new submenu
|
||||
QMenu *submenu = new QMenu(items[i], m_MainWindow);
|
||||
|
||||
// if we don't have a beforeAction, find where to insert this to keep alphabetical order.
|
||||
if(!beforeAction)
|
||||
{
|
||||
for(QAction *a : children)
|
||||
{
|
||||
if(submenu->menuAction()->text() < a->text())
|
||||
{
|
||||
beforeAction = a;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(beforeAction)
|
||||
menu->insertMenu(beforeAction, submenu);
|
||||
else
|
||||
menu->addMenu(submenu);
|
||||
|
||||
if(addIcon)
|
||||
submenu->setIcon(Icons::plugin());
|
||||
|
||||
addIcon = false;
|
||||
|
||||
beforeAction = NULL;
|
||||
|
||||
menu = submenu;
|
||||
}
|
||||
|
||||
QAction *action = new QAction(m_MainWindow);
|
||||
|
||||
action->setText(items.back());
|
||||
|
||||
QObject::connect(action, &QAction::triggered, callback);
|
||||
|
||||
if(!beforeAction)
|
||||
{
|
||||
QList<QAction *> children = menu->actions();
|
||||
|
||||
for(QAction *a : children)
|
||||
{
|
||||
if(action->text() < a->text())
|
||||
{
|
||||
beforeAction = a;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(beforeAction)
|
||||
menu->insertAction(beforeAction, action);
|
||||
else
|
||||
menu->addAction(action);
|
||||
|
||||
if(addIcon)
|
||||
action->setIcon(Icons::plugin());
|
||||
|
||||
m_PendingExtensionObjects.push_back(action);
|
||||
}
|
||||
|
||||
void CaptureContext::CleanMenu(QAction *action)
|
||||
{
|
||||
QMenu *menu = action->menu();
|
||||
|
||||
// if this isn't a menu, nothing to do - return
|
||||
if(!menu)
|
||||
return;
|
||||
|
||||
// first clean all our children
|
||||
for(QAction *a : menu->actions())
|
||||
CleanMenu(a);
|
||||
|
||||
// if we no longer have any children in this menu, delete it.
|
||||
if(menu->actions().isEmpty())
|
||||
delete menu;
|
||||
}
|
||||
|
||||
void CaptureContext::LoadCapture(const rdcstr &captureFile, const rdcstr &origFilename,
|
||||
bool temporary, bool local)
|
||||
{
|
||||
|
||||
@@ -72,6 +72,17 @@ public:
|
||||
bool IsExtensionLoaded(rdcstr name) override;
|
||||
bool LoadExtension(rdcstr name) override;
|
||||
|
||||
void RegisterWindowMenu(WindowMenu base, const rdcarray<rdcstr> &submenus,
|
||||
ExtensionCallback callback) override;
|
||||
void RegisterPanelMenu(PanelMenu base, const rdcarray<rdcstr> &submenus,
|
||||
ExtensionCallback callback) override;
|
||||
void RegisterContextMenu(ContextMenu base, const rdcarray<rdcstr> &submenus,
|
||||
ExtensionCallback callback) override;
|
||||
void MenuDisplaying(ContextMenu contextMenu, QMenu *menu,
|
||||
const ExtensionCallbackData &data) override;
|
||||
void MenuDisplaying(PanelMenu panelMenu, QWidget *extensionButton,
|
||||
const ExtensionCallbackData &data) override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Control functions
|
||||
|
||||
@@ -277,6 +288,10 @@ private:
|
||||
void LoadCaptureThreaded(const QString &captureFile, const QString &origFilename, bool temporary,
|
||||
bool local);
|
||||
|
||||
void AddSortedMenuItem(QMenu *menu, bool rootMenu, const rdcarray<rdcstr> &items,
|
||||
std::function<void()> callback);
|
||||
void CleanMenu(QAction *action);
|
||||
|
||||
uint32_t m_SelectedEventID = 0;
|
||||
uint32_t m_EventID = 0;
|
||||
|
||||
@@ -341,6 +356,8 @@ private:
|
||||
QList<QObject *> m_PendingExtensionObjects;
|
||||
QMap<rdcstr, QList<QObject *>> m_ExtensionObjects;
|
||||
|
||||
QList<QPointer<RegisteredMenuItem>> m_RegisteredMenuItems;
|
||||
|
||||
// Windows
|
||||
MainWindow *m_MainWindow = NULL;
|
||||
EventBrowser *m_EventBrowser = NULL;
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
|
||||
// this is pre-declared as an opaque type as we only support converting to QWidget* via PySide
|
||||
class QWidget;
|
||||
class QMenu;
|
||||
|
||||
// we only support QVariant as an 'internal' interface, it's not exposed to python. However we need
|
||||
// to use it in constructors/operators so conditionally compile it rather than split small structs
|
||||
@@ -64,6 +65,13 @@ class QWidget;
|
||||
#include "PersistantConfig.h"
|
||||
#include "RemoteHost.h"
|
||||
|
||||
#ifdef RENDERDOC_QT_COMPAT
|
||||
|
||||
typedef rdcarray<rdcpair<rdcstr, QVariant> > ExtensionCallbackData;
|
||||
#define make_pyarg make_rdcpair<rdcstr, QVariant>
|
||||
|
||||
#endif
|
||||
|
||||
struct ICaptureContext;
|
||||
|
||||
DOCUMENT("Contains all of the settings that control how to capture an executable.");
|
||||
@@ -1022,6 +1030,111 @@ protected:
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(IRGPInterop);
|
||||
|
||||
DOCUMENT(R"(Specifies the base menu to add a menu item into.
|
||||
|
||||
.. data:: File
|
||||
|
||||
The menu item will be in a section between Open/Save/Close captures and Import/Export.
|
||||
|
||||
.. data:: Window
|
||||
|
||||
The menu item will be in a new section at the end of the menu.
|
||||
|
||||
.. data:: Tools
|
||||
|
||||
The menu item will be added to a new section above Settings.
|
||||
|
||||
.. data:: NewMenu
|
||||
|
||||
The menu item will be a root menu, placed between Tools and Help.
|
||||
|
||||
.. data:: Help
|
||||
|
||||
The menu item will be added after the error reporting item.
|
||||
)");
|
||||
enum class WindowMenu
|
||||
{
|
||||
Unknown,
|
||||
File,
|
||||
Window,
|
||||
Tools,
|
||||
NewMenu,
|
||||
Help,
|
||||
};
|
||||
|
||||
DOCUMENT(R"(Specifies the panel to add a menu item into.
|
||||
|
||||
.. data:: EventBrowser
|
||||
|
||||
The :class:`EventBrowser`.
|
||||
|
||||
.. data:: PipelineStateViewer
|
||||
|
||||
The :class:`PipelineStateViewer`.
|
||||
|
||||
.. data:: MeshPreview
|
||||
|
||||
The mesh previewing :class:`BufferViewer`.
|
||||
|
||||
.. data:: TextureViewer
|
||||
|
||||
The :class:`TextureViewer`.
|
||||
)");
|
||||
enum class PanelMenu
|
||||
{
|
||||
Unknown,
|
||||
EventBrowser,
|
||||
PipelineStateViewer,
|
||||
MeshPreview,
|
||||
TextureViewer,
|
||||
};
|
||||
|
||||
DOCUMENT(R"(Specifies the panel to add a menu item into.
|
||||
|
||||
.. data:: EventBrowser_Event
|
||||
|
||||
Adds the item to the context menu for events in the :class:`EventBrowser`.
|
||||
|
||||
.. data:: MeshPreview_Vertex
|
||||
|
||||
Adds the item to the context menu for all vertices in the mesh previewing :class:`BufferViewer`.
|
||||
|
||||
.. data:: MeshPreview_VSInVertex
|
||||
|
||||
Adds the item to the context menu for vertex inputs in the mesh previewing :class:`BufferViewer`.
|
||||
|
||||
.. data:: MeshPreview_VSOutVertex
|
||||
|
||||
Adds the item to the context menu for VS output in the mesh previewing :class:`BufferViewer`.
|
||||
|
||||
.. data:: MeshPreview_GSOutVertex
|
||||
|
||||
Adds the item to the context menu for GS/Tess output in the mesh previewing :class:`BufferViewer`.
|
||||
|
||||
.. data:: TextureViewer_Thumbnail
|
||||
|
||||
Adds the item to the context menu for all thumbnails in the :class:`TextureViewer`.
|
||||
|
||||
.. data:: TextureViewer_InputThumbnail
|
||||
|
||||
Adds the item to the context menu for input thumbnails in the :class:`TextureViewer`.
|
||||
|
||||
.. data:: TextureViewer_OutputThumbnail
|
||||
|
||||
Adds the item to the context menu for output thumbnails in the :class:`TextureViewer`.
|
||||
)");
|
||||
enum class ContextMenu
|
||||
{
|
||||
Unknown,
|
||||
EventBrowser_Event,
|
||||
MeshPreview_Vertex,
|
||||
MeshPreview_VSInVertex,
|
||||
MeshPreview_VSOutVertex,
|
||||
MeshPreview_GSOutVertex,
|
||||
TextureViewer_Thumbnail,
|
||||
TextureViewer_InputThumbnail,
|
||||
TextureViewer_OutputThumbnail,
|
||||
};
|
||||
|
||||
DOCUMENT("The metadata for an extension.");
|
||||
struct ExtensionMetadata
|
||||
@@ -1081,10 +1194,12 @@ struct ExtensionMetadata
|
||||
|
||||
DECLARE_REFLECTION_STRUCT(ExtensionMetadata);
|
||||
|
||||
typedef struct _object PyObject;
|
||||
|
||||
DOCUMENT(R"(A manager for listing available and active extensions, as well as the interface for
|
||||
extensions to register hooks and additional functionality.
|
||||
|
||||
.. function:: ExtensionCallback(context)
|
||||
.. function:: ExtensionCallback(context, data)
|
||||
|
||||
Not a member function - the signature for any ``ExtensionCallback`` callbacks.
|
||||
|
||||
@@ -1092,10 +1207,13 @@ extensions to register hooks and additional functionality.
|
||||
was registered.
|
||||
|
||||
:param CaptureContext context: The current capture context.
|
||||
:param dict data: Additional data for the call, as a dictionary with string keys.
|
||||
Context-dependent based on what generated the callback
|
||||
)");
|
||||
struct IExtensionManager
|
||||
{
|
||||
typedef std::function<void(ICaptureContext *ctx)> ExtensionCallback;
|
||||
typedef std::function<void(ICaptureContext *ctx, const rdcarray<rdcpair<rdcstr, PyObject *> > &data)>
|
||||
ExtensionCallback;
|
||||
|
||||
DOCUMENT(R"(Retrieve a list of installed extensions.
|
||||
|
||||
@@ -1118,6 +1236,65 @@ struct IExtensionManager
|
||||
)");
|
||||
virtual bool LoadExtension(rdcstr name) = 0;
|
||||
|
||||
DOCUMENT(R"(Register a new menu item in the main window's menus for an extension.
|
||||
|
||||
.. note:
|
||||
The intermediate submenu items will be created as needed, there's no need to register each item
|
||||
in the hierarchy. Registering a menu item and then registering a child is undefined, and the item
|
||||
with a child may not receive callbacks at the correct times.
|
||||
|
||||
:param WindowMenu base: The base menu to add the item to.
|
||||
:param list submenus: A list of strings containing the submenus to add before the item. The last
|
||||
string will be the name of the menu item itself. Must contain at least one entry, or two entries
|
||||
if ``base`` is :data:`WindowMenu.NewMenu`.
|
||||
:param callback: The function to callback when the menu item is selected.
|
||||
:type method: :func:`ExtensionCallback`
|
||||
)");
|
||||
virtual void RegisterWindowMenu(WindowMenu base, const rdcarray<rdcstr> &submenus,
|
||||
ExtensionCallback callback) = 0;
|
||||
|
||||
DOCUMENT(R"(Register a menu item in a panel for an extension.
|
||||
|
||||
.. note:
|
||||
The intermediate submenu items will be created as needed, there's no need to register each item
|
||||
in the hierarchy. Registering a menu item and then registering a child is undefined, and the item
|
||||
with a child may not receive callbacks at the correct times.
|
||||
|
||||
:param PanelMenu base: The panel to add the item to.
|
||||
:param list submenus: A list of strings containing the submenus to add before the item. The last
|
||||
string will be the name of the menu item itself. Must contain at least one entry.
|
||||
:param callback: The function to callback when the menu item is selected.
|
||||
:type method: :func:`ExtensionCallback`
|
||||
)");
|
||||
virtual void RegisterPanelMenu(PanelMenu base, const rdcarray<rdcstr> &submenus,
|
||||
ExtensionCallback callback) = 0;
|
||||
|
||||
DOCUMENT(R"(Register a context menu item in a panel for an extension.
|
||||
|
||||
.. note:
|
||||
The intermediate submenu items will be created as needed, there's no need to register each item
|
||||
in the hierarchy. Registering a menu item and then registering a child is undefined, and the item
|
||||
with a child may not receive callbacks at the correct times.
|
||||
|
||||
:param ContextMenu base: The panel to add the item to.
|
||||
:param list submenus: A list of strings containing the submenus to add before the item. The last
|
||||
string will be the name of the menu item itself. Must contain at least one entry.
|
||||
:param callback: The function to callback when the menu item is selected.
|
||||
:type method: :func:`ExtensionCallback`
|
||||
)");
|
||||
virtual void RegisterContextMenu(ContextMenu base, const rdcarray<rdcstr> &submenus,
|
||||
ExtensionCallback callback) = 0;
|
||||
|
||||
#if !defined(SWIG) && !defined(SWIG_GENERATED)
|
||||
// not exposed to SWIG, only used internally. For when a menu is displayed dynamically in a panel,
|
||||
// this function is called to add any relevant menu items. Doing this almost immediate-mode GUI
|
||||
// style avoids complex retained state that has to be refreshed each time a panel is created.
|
||||
virtual void MenuDisplaying(ContextMenu contextMenu, QMenu *menu,
|
||||
const ExtensionCallbackData &data) = 0;
|
||||
virtual void MenuDisplaying(PanelMenu panelMenu, QWidget *extensionButton,
|
||||
const ExtensionCallbackData &data) = 0;
|
||||
#endif
|
||||
|
||||
protected:
|
||||
DOCUMENT("");
|
||||
IExtensionManager() = default;
|
||||
@@ -1616,7 +1793,7 @@ If no bookmark exists, this function will do nothing.
|
||||
DOCUMENT(R"(Retrieve the current singleton :class:`EventBrowser`.
|
||||
|
||||
:return: The current window, which is created (but not shown) it there wasn't one open.
|
||||
:rtype: EventBrowser
|
||||
:rtype: ~qrenderdoc.EventBrowser
|
||||
)");
|
||||
virtual IEventBrowser *GetEventBrowser() = 0;
|
||||
|
||||
@@ -1630,7 +1807,7 @@ If no bookmark exists, this function will do nothing.
|
||||
DOCUMENT(R"(Retrieve the current singleton :class:`TextureViewer`.
|
||||
|
||||
:return: The current window, which is created (but not shown) it there wasn't one open.
|
||||
:rtype: TextureViewer
|
||||
:rtype: ~qrenderdoc.TextureViewer
|
||||
)");
|
||||
virtual ITextureViewer *GetTextureViewer() = 0;
|
||||
|
||||
@@ -1644,7 +1821,7 @@ If no bookmark exists, this function will do nothing.
|
||||
DOCUMENT(R"(Retrieve the current singleton :class:`PipelineStateViewer`.
|
||||
|
||||
:return: The current window, which is created (but not shown) it there wasn't one open.
|
||||
:rtype: PipelineStateViewer
|
||||
:rtype: ~qrenderdoc.PipelineStateViewer
|
||||
)");
|
||||
virtual IPipelineStateViewer *GetPipelineViewer() = 0;
|
||||
|
||||
|
||||
@@ -315,6 +315,17 @@ public:
|
||||
void detach() { setProcessState(QProcess::NotRunning); }
|
||||
};
|
||||
|
||||
class RegisteredMenuItem : public QObject
|
||||
{
|
||||
private:
|
||||
Q_OBJECT
|
||||
public:
|
||||
ContextMenu context;
|
||||
PanelMenu panel;
|
||||
rdcarray<rdcstr> submenus;
|
||||
IExtensionManager::ExtensionCallback callback;
|
||||
};
|
||||
|
||||
class QFileFilterModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -74,6 +74,7 @@ bool CheckQtInterface();
|
||||
// defined in SWIG-generated renderdoc_python.cpp
|
||||
extern "C" PyObject *PyInit_renderdoc(void);
|
||||
extern "C" PyObject *PassObjectToPython(const char *type, void *obj);
|
||||
extern "C" PyObject *PassNewObjectToPython(const char *type, void *obj);
|
||||
// this one is in qrenderdoc_python.cpp
|
||||
extern "C" PyObject *PyInit_qrenderdoc(void);
|
||||
extern "C" PyObject *WrapBareQWidget(QWidget *);
|
||||
@@ -642,6 +643,70 @@ bool PythonContext::LoadExtension(ICaptureContext &ctx, const rdcstr &extension)
|
||||
return ext != NULL;
|
||||
}
|
||||
|
||||
void PythonContext::ConvertPyArgs(const ExtensionCallbackData &data,
|
||||
rdcarray<rdcpair<rdcstr, PyObject *>> &args)
|
||||
{
|
||||
PyGILState_STATE gil = PyGILState_Ensure();
|
||||
|
||||
args.resize(data.size());
|
||||
for(size_t i = 0; i < data.size(); i++)
|
||||
{
|
||||
rdcpair<rdcstr, PyObject *> &a = args[i];
|
||||
a.first = data[i].first;
|
||||
|
||||
// convert QVariant to python object
|
||||
const QVariant &in = data[i].second;
|
||||
PyObject *&out = a.second;
|
||||
|
||||
// coverity[mixed_enums]
|
||||
QMetaType::Type type = (QMetaType::Type)in.type();
|
||||
switch(type)
|
||||
{
|
||||
case QMetaType::Bool: out = PyBool_FromLong(in.toBool()); break;
|
||||
case QMetaType::Short:
|
||||
case QMetaType::Long:
|
||||
case QMetaType::Int: out = PyLong_FromLong(in.toInt()); break;
|
||||
case QMetaType::UShort:
|
||||
case QMetaType::ULong:
|
||||
case QMetaType::UInt: out = PyLong_FromUnsignedLong(in.toUInt()); break;
|
||||
case QMetaType::LongLong: out = PyLong_FromLongLong(in.toLongLong()); break;
|
||||
case QMetaType::ULongLong: out = PyLong_FromUnsignedLongLong(in.toULongLong()); break;
|
||||
case QMetaType::Float: out = PyFloat_FromDouble(in.toFloat()); break;
|
||||
case QMetaType::Double: out = PyFloat_FromDouble(in.toDouble()); break;
|
||||
case QMetaType::QString: out = PyUnicode_FromString(in.toString().toUtf8().data()); break;
|
||||
default: break;
|
||||
}
|
||||
|
||||
if(!out)
|
||||
{
|
||||
// try various other types
|
||||
if(in.userType() == qMetaTypeId<ResourceId>())
|
||||
out = PassNewObjectToPython("ResourceId *", new ResourceId(in.value<ResourceId>()));
|
||||
}
|
||||
|
||||
if(!out)
|
||||
{
|
||||
qCritical() << "Couldn't convert" << in << "to python object";
|
||||
out = Py_None;
|
||||
Py_XINCREF(out);
|
||||
}
|
||||
}
|
||||
|
||||
PyGILState_Release(gil);
|
||||
}
|
||||
|
||||
void PythonContext::FreePyArgs(rdcarray<rdcpair<rdcstr, PyObject *>> &args)
|
||||
{
|
||||
PyGILState_STATE gil = PyGILState_Ensure();
|
||||
|
||||
for(rdcpair<rdcstr, PyObject *> &a : args)
|
||||
{
|
||||
Py_XDECREF(a.second);
|
||||
}
|
||||
|
||||
PyGILState_Release(gil);
|
||||
}
|
||||
|
||||
QString PythonContext::versionString()
|
||||
{
|
||||
return QFormatStr("%1.%2.%3").arg(PY_MAJOR_VERSION).arg(PY_MINOR_VERSION).arg(PY_MICRO_VERSION);
|
||||
|
||||
@@ -332,6 +332,15 @@ PyObject *PassObjectToPython(const char *type, void *obj)
|
||||
return SWIG_InternalNewPointerObj(obj, t, 0);
|
||||
}
|
||||
|
||||
PyObject *PassNewObjectToPython(const char *type, void *obj)
|
||||
{
|
||||
swig_type_info *t = SWIG_TypeQuery(type);
|
||||
if(t == NULL)
|
||||
return NULL;
|
||||
|
||||
return SWIG_InternalNewPointerObj(obj, t, SWIG_POINTER_OWN);
|
||||
}
|
||||
|
||||
%}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -1132,6 +1132,15 @@ BufferViewer::BufferViewer(ICaptureContext &ctx, bool meshview, QWidget *parent)
|
||||
QObject::connect(ui->matrixType, OverloadedSlot<int>::of(&QComboBox::currentIndexChanged),
|
||||
[this](int) { camGuess_changed(0.0); });
|
||||
|
||||
{
|
||||
QMenu *extensionsMenu = new QMenu(this);
|
||||
|
||||
QObject::connect(extensionsMenu, &QMenu::aboutToShow, [this, extensionsMenu]() {
|
||||
extensionsMenu->clear();
|
||||
m_Ctx.Extensions().MenuDisplaying(PanelMenu::MeshPreview, ui->extensions, {});
|
||||
});
|
||||
}
|
||||
|
||||
Reset();
|
||||
|
||||
m_Ctx.AddCaptureViewer(this);
|
||||
@@ -1328,6 +1337,30 @@ void BufferViewer::stageRowMenu(MeshDataStage stage, QMenu *menu, const QPoint &
|
||||
menu->addAction(m_ExportBytes);
|
||||
|
||||
menu->popup(m_CurView->viewport()->mapToGlobal(pos));
|
||||
|
||||
ContextMenu contextMenu = ContextMenu::MeshPreview_VSInVertex;
|
||||
|
||||
if(stage == MeshDataStage::VSOut)
|
||||
contextMenu = ContextMenu::MeshPreview_VSOutVertex;
|
||||
else if(stage == MeshDataStage::GSOut)
|
||||
contextMenu = ContextMenu::MeshPreview_GSOutVertex;
|
||||
|
||||
QModelIndex idx = m_CurView->selectionModel()->currentIndex();
|
||||
|
||||
ExtensionCallbackData callbackdata = {make_pyarg("stage", (uint32_t)stage)};
|
||||
|
||||
if(idx.isValid())
|
||||
{
|
||||
uint32_t vertid =
|
||||
m_CurView->model()->data(m_CurView->model()->index(idx.row(), 0), Qt::DisplayRole).toUInt();
|
||||
uint32_t index =
|
||||
m_CurView->model()->data(m_CurView->model()->index(idx.row(), 1), Qt::DisplayRole).toUInt();
|
||||
|
||||
callbackdata.push_back(make_pyarg("vertex", vertid));
|
||||
callbackdata.push_back(make_pyarg("index", index));
|
||||
}
|
||||
|
||||
m_Ctx.Extensions().MenuDisplaying(contextMenu, menu, callbackdata);
|
||||
}
|
||||
|
||||
BufferViewer::~BufferViewer()
|
||||
|
||||
@@ -752,6 +752,17 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="extensions">
|
||||
<property name="icon">
|
||||
<iconset resource="../Resources/resources.qrc">
|
||||
<normaloff>:/plugin.png</normaloff>:/plugin.png</iconset>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="offsetLine">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -189,6 +189,15 @@ EventBrowser::EventBrowser(ICaptureContext &ctx, QWidget *parent)
|
||||
QObject::connect(ui->events->header(), &QHeaderView::customContextMenuRequested, this,
|
||||
&EventBrowser::events_contextMenu);
|
||||
|
||||
{
|
||||
QMenu *extensionsMenu = new QMenu(this);
|
||||
|
||||
QObject::connect(extensionsMenu, &QMenu::aboutToShow, [this, extensionsMenu]() {
|
||||
extensionsMenu->clear();
|
||||
m_Ctx.Extensions().MenuDisplaying(PanelMenu::EventBrowser, ui->extensions, {});
|
||||
});
|
||||
}
|
||||
|
||||
OnCaptureClosed();
|
||||
|
||||
m_redPalette = palette();
|
||||
@@ -1009,6 +1018,11 @@ void EventBrowser::events_contextMenu(const QPoint &pos)
|
||||
[this, rgp]() { rgp->SelectRGPEvent(m_Ctx.CurEvent()); });
|
||||
}
|
||||
|
||||
contextMenu.addSeparator();
|
||||
|
||||
m_Ctx.Extensions().MenuDisplaying(ContextMenu::EventBrowser_Event, &contextMenu,
|
||||
{{"eventId", m_Ctx.CurEvent()}});
|
||||
|
||||
RDDialog::show(&contextMenu, ui->events->viewport()->mapToGlobal(pos));
|
||||
}
|
||||
|
||||
|
||||
@@ -191,6 +191,17 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="extensions">
|
||||
<property name="icon">
|
||||
<iconset resource="../Resources/resources.qrc">
|
||||
<normaloff>:/plugin.png</normaloff>:/plugin.png</iconset>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -389,6 +389,13 @@ MainWindow::MainWindow(ICaptureContext &ctx) : QMainWindow(NULL), ui(new Ui::Mai
|
||||
if(a->menu())
|
||||
actions.append(a->menu()->actions());
|
||||
}
|
||||
|
||||
// hide the dummy extension markers. They shouldn't be visible, they're just there so the code can
|
||||
// easily find where to insert new extension menu items.
|
||||
ui->extension_dummy_File->setVisible(false);
|
||||
ui->extension_dummy_Window->setVisible(false);
|
||||
ui->extension_dummy_Tools->setVisible(false);
|
||||
ui->extension_dummy_Help->setVisible(false);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
@@ -1324,6 +1331,42 @@ void MainWindow::LiveCaptureClosed(LiveCapture *live)
|
||||
m_LiveCaptures.removeOne(live);
|
||||
}
|
||||
|
||||
QMenu *MainWindow::GetBaseMenu(WindowMenu base, rdcstr name)
|
||||
{
|
||||
switch(base)
|
||||
{
|
||||
case WindowMenu::File: return ui->menu_File;
|
||||
case WindowMenu::Window: return ui->menu_Window;
|
||||
case WindowMenu::Tools: return ui->menu_Tools;
|
||||
case WindowMenu::Help: return ui->menu_Help;
|
||||
case WindowMenu::NewMenu: break;
|
||||
default: return NULL;
|
||||
}
|
||||
|
||||
// new menu. See if we have one for name already. If not, create a new one and add it to the menu
|
||||
// bar.
|
||||
for(QAction *m : ui->menuBar->actions())
|
||||
{
|
||||
// if it has an object name it's a built-in, ignore it.
|
||||
if(!m->objectName().isEmpty())
|
||||
continue;
|
||||
|
||||
if(m->text() == name)
|
||||
return m->menu();
|
||||
}
|
||||
|
||||
// no existing menu, add a new one
|
||||
QMenu *menu = new QMenu(name, this);
|
||||
menu->setIcon(Icons::plugin());
|
||||
ui->menuBar->insertMenu(ui->menu_Help->menuAction(), menu);
|
||||
return menu;
|
||||
}
|
||||
|
||||
QList<QAction *> MainWindow::GetMenuActions()
|
||||
{
|
||||
return ui->menuBar->actions();
|
||||
}
|
||||
|
||||
ToolWindowManager *MainWindow::mainToolManager()
|
||||
{
|
||||
return ui->toolWindowManager;
|
||||
|
||||
@@ -89,6 +89,9 @@ public:
|
||||
void ShowLiveCapture(LiveCapture *live);
|
||||
void LiveCaptureClosed(LiveCapture *live);
|
||||
|
||||
QMenu *GetBaseMenu(WindowMenu base, rdcstr name);
|
||||
QList<QAction *> GetMenuActions();
|
||||
|
||||
void showEventBrowser() { on_action_Event_Browser_triggered(); }
|
||||
void showAPIInspector() { on_action_API_Inspector_triggered(); }
|
||||
void showMeshPreview() { on_action_Mesh_Output_triggered(); }
|
||||
@@ -102,6 +105,7 @@ public:
|
||||
void showPythonShell() { on_action_Python_Shell_triggered(); }
|
||||
void showPerformanceCounterViewer() { on_action_Counter_Viewer_triggered(); }
|
||||
void showResourceInspector() { on_action_Resource_Inspector_triggered(); }
|
||||
void showExtensionManager() { on_action_Manage_Extensions_triggered(); }
|
||||
void PopulateRecentCaptureFiles();
|
||||
void PopulateRecentCaptureSettings();
|
||||
void PopulateReportedBugs();
|
||||
|
||||
@@ -56,6 +56,8 @@
|
||||
<addaction name="action_Create_RGP_Profile"/>
|
||||
<addaction name="action_Open_RGP_Profile"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="extension_dummy_Tools"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_Settings"/>
|
||||
<addaction name="action_Manage_Extensions"/>
|
||||
<addaction name="action_Manage_Remote_Servers"/>
|
||||
@@ -104,6 +106,8 @@
|
||||
<addaction name="action_Save_Capture_As"/>
|
||||
<addaction name="action_Close_Capture"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="extension_dummy_File"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="menu_Import_From"/>
|
||||
<addaction name="menu_Export_As"/>
|
||||
<addaction name="separator"/>
|
||||
@@ -159,6 +163,8 @@
|
||||
<addaction name="action_Counter_Viewer"/>
|
||||
<addaction name="action_Resource_Inspector"/>
|
||||
<addaction name="action_Comments"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="extension_dummy_Window"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menu_Help">
|
||||
<property name="title">
|
||||
@@ -178,6 +184,8 @@
|
||||
<addaction name="action_Send_Error_Report"/>
|
||||
<addaction name="menu_Reported_Bugs"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="extension_dummy_Help"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_Check_for_Updates"/>
|
||||
<addaction name="separator"/>
|
||||
<addaction name="action_Source_on_GitHub"/>
|
||||
@@ -467,6 +475,26 @@
|
||||
<string>Open RGP Profile</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="extension_dummy_Tools">
|
||||
<property name="text">
|
||||
<string notr="true">__extensions__</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="extension_dummy_Help">
|
||||
<property name="text">
|
||||
<string notr="true">__extensions__</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="extension_dummy_Window">
|
||||
<property name="text">
|
||||
<string notr="true">__extensions__</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="extension_dummy_File">
|
||||
<property name="text">
|
||||
<string notr="true">__extensions__</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="action_Manage_Extensions">
|
||||
<property name="text">
|
||||
<string>Manage Extensions</string>
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "D3D11PipelineStateViewer.h"
|
||||
#include <float.h>
|
||||
#include <QMenu>
|
||||
#include <QMouseEvent>
|
||||
#include <QScrollBar>
|
||||
#include <QXmlStreamWriter>
|
||||
@@ -171,6 +172,15 @@ D3D11PipelineStateViewer::D3D11PipelineStateViewer(ICaptureContext &ctx,
|
||||
QObject::connect(cbuffer, &RDTreeWidget::itemActivated, this,
|
||||
&D3D11PipelineStateViewer::cbuffer_itemActivated);
|
||||
|
||||
{
|
||||
QMenu *extensionsMenu = new QMenu(this);
|
||||
|
||||
QObject::connect(extensionsMenu, &QMenu::aboutToShow, [this, extensionsMenu]() {
|
||||
extensionsMenu->clear();
|
||||
m_Ctx.Extensions().MenuDisplaying(PanelMenu::PipelineStateViewer, ui->extensions, {});
|
||||
});
|
||||
}
|
||||
|
||||
addGridLines(ui->rasterizerGridLayout, palette().color(QPalette::WindowText));
|
||||
addGridLines(ui->blendStateGridLayout, palette().color(QPalette::WindowText));
|
||||
addGridLines(ui->depthStateGridLayout, palette().color(QPalette::WindowText));
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="controlsLabel">
|
||||
<property name="text">
|
||||
<string>Display Controls</string>
|
||||
<string>Controls</string>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>4</number>
|
||||
@@ -136,6 +136,23 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="extensions">
|
||||
<property name="text">
|
||||
<string>Extensions</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../Resources/resources.qrc">
|
||||
<normaloff>:/plugin.png</normaloff>:/plugin.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
@@ -202,8 +219,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1000</width>
|
||||
<height>576</height>
|
||||
<width>454</width>
|
||||
<height>245</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
@@ -646,7 +663,7 @@
|
||||
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
@@ -708,8 +725,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1000</width>
|
||||
<height>527</height>
|
||||
<width>101</width>
|
||||
<height>344</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_10">
|
||||
@@ -1036,7 +1053,7 @@
|
||||
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
@@ -1095,8 +1112,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1000</width>
|
||||
<height>527</height>
|
||||
<width>101</width>
|
||||
<height>344</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
@@ -1423,7 +1440,7 @@
|
||||
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
@@ -1482,8 +1499,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1000</width>
|
||||
<height>527</height>
|
||||
<width>101</width>
|
||||
<height>344</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
@@ -1810,7 +1827,7 @@
|
||||
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
@@ -1869,8 +1886,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1000</width>
|
||||
<height>527</height>
|
||||
<width>101</width>
|
||||
<height>430</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
@@ -2868,7 +2885,7 @@
|
||||
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
@@ -2927,8 +2944,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1000</width>
|
||||
<height>527</height>
|
||||
<width>101</width>
|
||||
<height>344</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||
@@ -3204,8 +3221,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1000</width>
|
||||
<height>576</height>
|
||||
<width>829</width>
|
||||
<height>311</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_9">
|
||||
@@ -4474,16 +4491,16 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>RDLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>Widgets/Extended/RDLabel.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RDTreeWidget</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>Widgets/Extended/RDTreeWidget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RDLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>Widgets/Extended/RDLabel.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PipelineFlowChart</class>
|
||||
<extends>QFrame</extends>
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "D3D12PipelineStateViewer.h"
|
||||
#include <float.h>
|
||||
#include <QMenu>
|
||||
#include <QMouseEvent>
|
||||
#include <QScrollBar>
|
||||
#include <QXmlStreamWriter>
|
||||
@@ -211,6 +212,15 @@ D3D12PipelineStateViewer::D3D12PipelineStateViewer(ICaptureContext &ctx,
|
||||
QObject::connect(cbuffer, &RDTreeWidget::itemActivated, this,
|
||||
&D3D12PipelineStateViewer::cbuffer_itemActivated);
|
||||
|
||||
{
|
||||
QMenu *extensionsMenu = new QMenu(this);
|
||||
|
||||
QObject::connect(extensionsMenu, &QMenu::aboutToShow, [this, extensionsMenu]() {
|
||||
extensionsMenu->clear();
|
||||
m_Ctx.Extensions().MenuDisplaying(PanelMenu::PipelineStateViewer, ui->extensions, {});
|
||||
});
|
||||
}
|
||||
|
||||
addGridLines(ui->rasterizerGridLayout, palette().color(QPalette::WindowText));
|
||||
addGridLines(ui->blendStateGridLayout, palette().color(QPalette::WindowText));
|
||||
addGridLines(ui->depthStateGridLayout, palette().color(QPalette::WindowText));
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="controlsLabel">
|
||||
<property name="text">
|
||||
<string>Display Controls</string>
|
||||
<string>Controls</string>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>4</number>
|
||||
@@ -136,6 +136,23 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="extensions">
|
||||
<property name="text">
|
||||
<string>Extensions</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../Resources/resources.qrc">
|
||||
<normaloff>:/plugin.png</normaloff>:/plugin.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
@@ -549,9 +566,9 @@
|
||||
<property name="icon">
|
||||
<iconset resource="../../Resources/resources.qrc">
|
||||
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
|
||||
</property>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
@@ -945,7 +962,7 @@
|
||||
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
@@ -1237,6 +1254,12 @@
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -1333,7 +1356,7 @@
|
||||
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
@@ -1625,6 +1648,12 @@
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -1721,7 +1750,7 @@
|
||||
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
@@ -2065,6 +2094,12 @@
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -2708,7 +2743,7 @@
|
||||
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
@@ -3000,6 +3035,12 @@
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
@@ -3764,7 +3805,7 @@
|
||||
<normaloff>:/page_white_edit.png</normaloff>:/page_white_edit.png</iconset>
|
||||
</property>
|
||||
<property name="popupMode">
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
<enum>QToolButton::MenuButtonPopup</enum>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
@@ -4132,6 +4173,12 @@
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "GLPipelineStateViewer.h"
|
||||
#include <float.h>
|
||||
#include <QMenu>
|
||||
#include <QMouseEvent>
|
||||
#include <QScrollBar>
|
||||
#include <QXmlStreamWriter>
|
||||
@@ -168,6 +169,15 @@ GLPipelineStateViewer::GLPipelineStateViewer(ICaptureContext &ctx, PipelineState
|
||||
QObject::connect(res, &RDTreeWidget::itemActivated, this,
|
||||
&GLPipelineStateViewer::resource_itemActivated);
|
||||
|
||||
{
|
||||
QMenu *extensionsMenu = new QMenu(this);
|
||||
|
||||
QObject::connect(extensionsMenu, &QMenu::aboutToShow, [this, extensionsMenu]() {
|
||||
extensionsMenu->clear();
|
||||
m_Ctx.Extensions().MenuDisplaying(PanelMenu::PipelineStateViewer, ui->extensions, {});
|
||||
});
|
||||
}
|
||||
|
||||
addGridLines(ui->rasterizerGridLayout, palette().color(QPalette::WindowText));
|
||||
addGridLines(ui->MSAAGridLayout, palette().color(QPalette::WindowText));
|
||||
addGridLines(ui->blendStateGridLayout, palette().color(QPalette::WindowText));
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="controlsLabel">
|
||||
<property name="text">
|
||||
<string>Display Controls</string>
|
||||
<string>Controls</string>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>4</number>
|
||||
@@ -136,6 +136,23 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="extensions">
|
||||
<property name="text">
|
||||
<string>Extensions</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../Resources/resources.qrc">
|
||||
<normaloff>:/plugin.png</normaloff>:/plugin.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
@@ -671,8 +688,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>883</width>
|
||||
<height>552</height>
|
||||
<width>116</width>
|
||||
<height>430</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_16">
|
||||
@@ -1125,8 +1142,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>883</width>
|
||||
<height>552</height>
|
||||
<width>116</width>
|
||||
<height>430</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_15">
|
||||
@@ -1579,8 +1596,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>883</width>
|
||||
<height>552</height>
|
||||
<width>116</width>
|
||||
<height>430</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_14">
|
||||
@@ -2033,8 +2050,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>883</width>
|
||||
<height>552</height>
|
||||
<width>117</width>
|
||||
<height>544</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_13">
|
||||
@@ -3465,8 +3482,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>883</width>
|
||||
<height>552</height>
|
||||
<width>116</width>
|
||||
<height>430</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
@@ -3794,8 +3811,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>883</width>
|
||||
<height>601</height>
|
||||
<width>488</width>
|
||||
<height>311</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
@@ -4426,8 +4443,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>883</width>
|
||||
<height>552</height>
|
||||
<width>116</width>
|
||||
<height>430</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_11">
|
||||
@@ -4730,16 +4747,16 @@
|
||||
</layout>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>RDLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>Widgets/Extended/RDLabel.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RDTreeWidget</class>
|
||||
<extends>QTreeView</extends>
|
||||
<header>Widgets/Extended/RDTreeWidget.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>RDLabel</class>
|
||||
<extends>QLabel</extends>
|
||||
<header>Widgets/Extended/RDLabel.h</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PipelineFlowChart</class>
|
||||
<extends>QFrame</extends>
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "VulkanPipelineStateViewer.h"
|
||||
#include <float.h>
|
||||
#include <QMenu>
|
||||
#include <QMouseEvent>
|
||||
#include <QScrollBar>
|
||||
#include <QXmlStreamWriter>
|
||||
@@ -163,6 +164,15 @@ VulkanPipelineStateViewer::VulkanPipelineStateViewer(ICaptureContext &ctx,
|
||||
QObject::connect(ubo, &RDTreeWidget::itemActivated, this,
|
||||
&VulkanPipelineStateViewer::ubo_itemActivated);
|
||||
|
||||
{
|
||||
QMenu *extensionsMenu = new QMenu(this);
|
||||
|
||||
QObject::connect(extensionsMenu, &QMenu::aboutToShow, [this, extensionsMenu]() {
|
||||
extensionsMenu->clear();
|
||||
m_Ctx.Extensions().MenuDisplaying(PanelMenu::PipelineStateViewer, ui->extensions, {});
|
||||
});
|
||||
}
|
||||
|
||||
addGridLines(ui->rasterizerGridLayout, palette().color(QPalette::WindowText));
|
||||
addGridLines(ui->MSAAGridLayout, palette().color(QPalette::WindowText));
|
||||
addGridLines(ui->blendStateGridLayout, palette().color(QPalette::WindowText));
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
<item>
|
||||
<widget class="QLabel" name="controlsLabel">
|
||||
<property name="text">
|
||||
<string>Display Controls</string>
|
||||
<string>Controls</string>
|
||||
</property>
|
||||
<property name="margin">
|
||||
<number>4</number>
|
||||
@@ -136,6 +136,23 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="extensions">
|
||||
<property name="text">
|
||||
<string>Extensions</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../../Resources/resources.qrc">
|
||||
<normaloff>:/plugin.png</normaloff>:/plugin.png</iconset>
|
||||
</property>
|
||||
<property name="toolButtonStyle">
|
||||
<enum>Qt::ToolButtonTextBesideIcon</enum>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
|
||||
@@ -540,6 +540,15 @@ TextureViewer::TextureViewer(ICaptureContext &ctx, QWidget *parent)
|
||||
&TextureViewer::channelsWidget_mouseClicked);
|
||||
}
|
||||
|
||||
{
|
||||
QMenu *extensionsMenu = new QMenu(this);
|
||||
|
||||
QObject::connect(extensionsMenu, &QMenu::aboutToShow, [this, extensionsMenu]() {
|
||||
extensionsMenu->clear();
|
||||
m_Ctx.Extensions().MenuDisplaying(PanelMenu::TextureViewer, ui->extensions, {});
|
||||
});
|
||||
}
|
||||
|
||||
QWidget *renderContainer = ui->renderContainer;
|
||||
|
||||
ui->dockarea->addToolWindow(ui->renderContainer, ToolWindowManager::EmptySpace);
|
||||
@@ -1885,7 +1894,8 @@ void TextureViewer::AddResourceUsageEntry(QMenu &menu, uint32_t start, uint32_t
|
||||
menu.addAction(item);
|
||||
}
|
||||
|
||||
void TextureViewer::OpenResourceContextMenu(ResourceId id, const rdcarray<EventUsage> &usage)
|
||||
void TextureViewer::OpenResourceContextMenu(ResourceId id, bool input,
|
||||
const rdcarray<EventUsage> &usage)
|
||||
{
|
||||
QMenu contextMenu(this);
|
||||
|
||||
@@ -1920,6 +1930,12 @@ void TextureViewer::OpenResourceContextMenu(ResourceId id, const rdcarray<EventU
|
||||
contextMenu.addSeparator();
|
||||
contextMenu.addAction(&openLockedTab);
|
||||
contextMenu.addAction(&openResourceInspector);
|
||||
|
||||
contextMenu.addSeparator();
|
||||
m_Ctx.Extensions().MenuDisplaying(input ? ContextMenu::TextureViewer_InputThumbnail
|
||||
: ContextMenu::TextureViewer_OutputThumbnail,
|
||||
&contextMenu, {{"resourceId", id}});
|
||||
|
||||
contextMenu.addSeparator();
|
||||
contextMenu.addAction(&usageTitle);
|
||||
|
||||
@@ -1943,6 +1959,11 @@ void TextureViewer::OpenResourceContextMenu(ResourceId id, const rdcarray<EventU
|
||||
}
|
||||
else
|
||||
{
|
||||
contextMenu.addSeparator();
|
||||
m_Ctx.Extensions().MenuDisplaying(input ? ContextMenu::TextureViewer_InputThumbnail
|
||||
: ContextMenu::TextureViewer_OutputThumbnail,
|
||||
&contextMenu, {});
|
||||
|
||||
RDDialog::show(&contextMenu, QCursor::pos());
|
||||
}
|
||||
}
|
||||
@@ -2154,16 +2175,19 @@ void TextureViewer::thumb_clicked(QMouseEvent *e)
|
||||
|
||||
rdcarray<EventUsage> empty;
|
||||
|
||||
bool input = follow.Type == FollowType::ReadOnly;
|
||||
|
||||
if(id == ResourceId())
|
||||
{
|
||||
OpenResourceContextMenu(id, empty);
|
||||
OpenResourceContextMenu(id, input, empty);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Ctx.Replay().AsyncInvoke([this, id](IReplayController *r) {
|
||||
m_Ctx.Replay().AsyncInvoke([this, id, input](IReplayController *r) {
|
||||
rdcarray<EventUsage> usage = r->GetUsage(id);
|
||||
|
||||
GUIInvoke::call(this, [this, id, usage]() { OpenResourceContextMenu(id, usage); });
|
||||
GUIInvoke::call(this,
|
||||
[this, id, input, usage]() { OpenResourceContextMenu(id, input, usage); });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,7 +248,7 @@ private:
|
||||
int &prevIndex, bool copy, bool rw);
|
||||
|
||||
void AddResourceUsageEntry(QMenu &menu, uint32_t start, uint32_t end, ResourceUsage usage);
|
||||
void OpenResourceContextMenu(ResourceId id, const rdcarray<EventUsage> &usage);
|
||||
void OpenResourceContextMenu(ResourceId id, bool input, const rdcarray<EventUsage> &usage);
|
||||
|
||||
void AutoFitRange();
|
||||
void rangePoint_Update();
|
||||
|
||||
@@ -227,7 +227,7 @@
|
||||
<widget class="QFrame" name="overlayToolbar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>490</x>
|
||||
<x>530</x>
|
||||
<y>40</y>
|
||||
<width>129</width>
|
||||
<height>32</height>
|
||||
@@ -418,7 +418,7 @@
|
||||
<rect>
|
||||
<x>330</x>
|
||||
<y>40</y>
|
||||
<width>149</width>
|
||||
<width>181</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
@@ -539,6 +539,17 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="extensions">
|
||||
<property name="icon">
|
||||
<iconset resource="../Resources/resources.qrc">
|
||||
<normaloff>:/plugin.png</normaloff>:/plugin.png</iconset>
|
||||
</property>
|
||||
<property name="autoRaise">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QFrame" name="subresourceToolbar">
|
||||
|
||||
Reference in new issue
Block a user