diff --git a/UI/CMakeLists.txt b/UI/CMakeLists.txt index 273032f60..0780cf554 100644 --- a/UI/CMakeLists.txt +++ b/UI/CMakeLists.txt @@ -224,6 +224,7 @@ set(obs_SOURCES window-basic-main-dropfiles.cpp window-basic-main-profiles.cpp window-basic-main-browser.cpp + window-basic-main-icons.cpp window-basic-status-bar.cpp window-basic-adv-audio.cpp window-basic-transform.cpp diff --git a/UI/data/themes/Acri.qss b/UI/data/themes/Acri.qss index 4dfba470c..4fa146dff 100644 --- a/UI/data/themes/Acri.qss +++ b/UI/data/themes/Acri.qss @@ -142,6 +142,7 @@ SourceTree::item { margin-bottom: 2px; margin-top: 0px; border: 1px solid transparent; + height: 24px; } QListWidget QLineEdit { @@ -200,11 +201,6 @@ SourceTree { border-bottom: 1px solid #2f2f2f; } -SourceTree QLabel { - padding: 2px 0px; - margin: -2px 4px -2px; -} - SourceTree QLineEdit { background-color: #0c101e; padding: 2px; @@ -1006,3 +1002,23 @@ QPushButton#extraPanelDelete:hover { QPushButton#extraPanelDelete:pressed { background-color: #161f41; } + +/* Source Icons */ + +OBSBasic { + qproperty-imageIcon: url(./Dark/sources/image.svg); + qproperty-colorIcon: url(./Dark/sources/brush.svg); + qproperty-slideshowIcon: url(./Dark/sources/slideshow.svg); + qproperty-audioInputIcon: url(./Dark/sources/microphone.svg); + qproperty-audioOutputIcon: url(./Dark/settings/audio.svg); + qproperty-desktopCapIcon: url(./Dark/settings/video.svg); + qproperty-windowCapIcon: url(./Dark/sources/window.svg); + qproperty-gameCapIcon: url(./Dark/sources/gamepad.svg); + qproperty-cameraIcon: url(./Dark/sources/camera.svg); + qproperty-textIcon: url(./Dark/sources/text.svg); + qproperty-mediaIcon: url(./Dark/sources/media.svg); + qproperty-browserIcon: url(./Dark/sources/globe.svg); + qproperty-groupIcon: url(./Dark/sources/group.svg); + qproperty-sceneIcon: url(./Dark/sources/scene.svg); + qproperty-defaultIcon: url(./Dark/sources/default.svg); +} diff --git a/UI/data/themes/Dark.qss b/UI/data/themes/Dark.qss index 151443b36..383753025 100644 --- a/UI/data/themes/Dark.qss +++ b/UI/data/themes/Dark.qss @@ -700,6 +700,11 @@ OBSBasicSettings QListWidget::item { padding-bottom: 5px; } +QListWidget::item, +SourceTree::item { + height: 24px; +} + /* Locked CheckBox */ LockedCheckBox { @@ -749,3 +754,23 @@ QPushButton#extraPanelDelete:hover { QPushButton#extraPanelDelete:pressed { background-color: rgb(31,30,31); } + +/* Source Icons */ + +OBSBasic { + qproperty-imageIcon: url(./Dark/sources/image.svg); + qproperty-colorIcon: url(./Dark/sources/brush.svg); + qproperty-slideshowIcon: url(./Dark/sources/slideshow.svg); + qproperty-audioInputIcon: url(./Dark/sources/microphone.svg); + qproperty-audioOutputIcon: url(./Dark/settings/audio.svg); + qproperty-desktopCapIcon: url(./Dark/settings/video.svg); + qproperty-windowCapIcon: url(./Dark/sources/window.svg); + qproperty-gameCapIcon: url(./Dark/sources/gamepad.svg); + qproperty-cameraIcon: url(./Dark/sources/camera.svg); + qproperty-textIcon: url(./Dark/sources/text.svg); + qproperty-mediaIcon: url(./Dark/sources/media.svg); + qproperty-browserIcon: url(./Dark/sources/globe.svg); + qproperty-groupIcon: url(./Dark/sources/group.svg); + qproperty-sceneIcon: url(./Dark/sources/scene.svg); + qproperty-defaultIcon: url(./Dark/sources/default.svg); +} diff --git a/UI/data/themes/Dark/sources/brush.svg b/UI/data/themes/Dark/sources/brush.svg new file mode 100644 index 000000000..0a01f1d87 --- /dev/null +++ b/UI/data/themes/Dark/sources/brush.svg @@ -0,0 +1,4 @@ + + + diff --git a/UI/data/themes/Dark/sources/camera.svg b/UI/data/themes/Dark/sources/camera.svg new file mode 100644 index 000000000..f569f5b6e --- /dev/null +++ b/UI/data/themes/Dark/sources/camera.svg @@ -0,0 +1 @@ + diff --git a/UI/data/themes/Dark/sources/default.svg b/UI/data/themes/Dark/sources/default.svg new file mode 100644 index 000000000..758bb19a2 --- /dev/null +++ b/UI/data/themes/Dark/sources/default.svg @@ -0,0 +1 @@ + diff --git a/UI/data/themes/Dark/sources/gamepad.svg b/UI/data/themes/Dark/sources/gamepad.svg new file mode 100644 index 000000000..a3ebb19a5 --- /dev/null +++ b/UI/data/themes/Dark/sources/gamepad.svg @@ -0,0 +1 @@ + diff --git a/UI/data/themes/Dark/sources/globe.svg b/UI/data/themes/Dark/sources/globe.svg new file mode 100644 index 000000000..9df020944 --- /dev/null +++ b/UI/data/themes/Dark/sources/globe.svg @@ -0,0 +1 @@ + diff --git a/UI/data/themes/Dark/sources/group.svg b/UI/data/themes/Dark/sources/group.svg new file mode 100644 index 000000000..785c3ad00 --- /dev/null +++ b/UI/data/themes/Dark/sources/group.svg @@ -0,0 +1,3 @@ + + + diff --git a/UI/data/themes/Dark/sources/image.svg b/UI/data/themes/Dark/sources/image.svg new file mode 100644 index 000000000..3ea06d713 --- /dev/null +++ b/UI/data/themes/Dark/sources/image.svg @@ -0,0 +1,3 @@ + + + diff --git a/UI/data/themes/Dark/sources/media.svg b/UI/data/themes/Dark/sources/media.svg new file mode 100644 index 000000000..df4659d21 --- /dev/null +++ b/UI/data/themes/Dark/sources/media.svg @@ -0,0 +1,3 @@ + + + diff --git a/UI/data/themes/Dark/sources/microphone.svg b/UI/data/themes/Dark/sources/microphone.svg new file mode 100644 index 000000000..2a8f3ceeb --- /dev/null +++ b/UI/data/themes/Dark/sources/microphone.svg @@ -0,0 +1,4 @@ + + + diff --git a/UI/data/themes/Dark/sources/scene.svg b/UI/data/themes/Dark/sources/scene.svg new file mode 100644 index 000000000..47dd72c65 --- /dev/null +++ b/UI/data/themes/Dark/sources/scene.svg @@ -0,0 +1,4 @@ + + + diff --git a/UI/data/themes/Dark/sources/slideshow.svg b/UI/data/themes/Dark/sources/slideshow.svg new file mode 100644 index 000000000..3599e6ddf --- /dev/null +++ b/UI/data/themes/Dark/sources/slideshow.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/UI/data/themes/Dark/sources/text.svg b/UI/data/themes/Dark/sources/text.svg new file mode 100644 index 000000000..f4713e1d7 --- /dev/null +++ b/UI/data/themes/Dark/sources/text.svg @@ -0,0 +1,3 @@ + + + diff --git a/UI/data/themes/Dark/sources/window.svg b/UI/data/themes/Dark/sources/window.svg new file mode 100644 index 000000000..6e2070d42 --- /dev/null +++ b/UI/data/themes/Dark/sources/window.svg @@ -0,0 +1 @@ + diff --git a/UI/data/themes/Rachni.qss b/UI/data/themes/Rachni.qss index f15913d68..21f6870d3 100644 --- a/UI/data/themes/Rachni.qss +++ b/UI/data/themes/Rachni.qss @@ -184,6 +184,11 @@ QListWidget::item:hover:!active { border: none; } +QListWidget::item, +SourceTree::item { + height: 24px; +} + /***********************/ /* --- Dock widget --- */ /***********************/ @@ -1340,3 +1345,23 @@ QPushButton#extraPanelDelete:hover { QPushButton#extraPanelDelete:pressed { background-color: rgb(240, 98, 146); } + +/* Source Icons */ + +OBSBasic { + qproperty-imageIcon: url(./Dark/sources/image.svg); + qproperty-colorIcon: url(./Dark/sources/brush.svg); + qproperty-slideshowIcon: url(./Dark/sources/slideshow.svg); + qproperty-audioInputIcon: url(./Dark/sources/microphone.svg); + qproperty-audioOutputIcon: url(./Dark/settings/audio.svg); + qproperty-desktopCapIcon: url(./Dark/settings/video.svg); + qproperty-windowCapIcon: url(./Dark/sources/window.svg); + qproperty-gameCapIcon: url(./Dark/sources/gamepad.svg); + qproperty-cameraIcon: url(./Dark/sources/camera.svg); + qproperty-textIcon: url(./Dark/sources/text.svg); + qproperty-mediaIcon: url(./Dark/sources/media.svg); + qproperty-browserIcon: url(./Dark/sources/globe.svg); + qproperty-groupIcon: url(./Dark/sources/group.svg); + qproperty-sceneIcon: url(./Dark/sources/scene.svg); + qproperty-defaultIcon: url(./Dark/sources/default.svg); +} diff --git a/UI/data/themes/System.qss b/UI/data/themes/System.qss index c82376f0b..3fe69c885 100644 --- a/UI/data/themes/System.qss +++ b/UI/data/themes/System.qss @@ -208,3 +208,28 @@ VisibilityCheckBox::indicator:unchecked { * [themeID="revertIcon"] { qproperty-icon: url(:res/images/revert.svg); } + +/* Source Icons */ + +OBSBasic { + qproperty-imageIcon: url(:res/images/sources/image.svg); + qproperty-colorIcon: url(:res/images/sources/brush.svg); + qproperty-slideshowIcon: url(:res/images/sources/slideshow.svg); + qproperty-audioInputIcon: url(:res/images/sources/microphone.svg); + qproperty-audioOutputIcon: url(:settings/images/settings/audio.svg); + qproperty-desktopCapIcon: url(:settings/images/settings/video.svg); + qproperty-windowCapIcon: url(:res/images/sources/window.svg); + qproperty-gameCapIcon: url(:res/images/sources/gamepad.svg); + qproperty-cameraIcon: url(:res/images/sources/camera.svg); + qproperty-textIcon: url(:res/images/sources/text.svg); + qproperty-mediaIcon: url(:res/images/sources/media.svg); + qproperty-browserIcon: url(:res/images/sources/globe.svg); + qproperty-groupIcon: url(:res/images/sources/group.svg); + qproperty-sceneIcon: url(:res/images/sources/scene.svg); + qproperty-defaultIcon: url(:res/images/sources/default.svg); +} + +QListWidget::item, +SourceTree::item { + height: 24px; +} diff --git a/UI/forms/images/sources/brush.svg b/UI/forms/images/sources/brush.svg new file mode 100644 index 000000000..55512ec7a --- /dev/null +++ b/UI/forms/images/sources/brush.svg @@ -0,0 +1,4 @@ + + + diff --git a/UI/forms/images/sources/camera.svg b/UI/forms/images/sources/camera.svg new file mode 100644 index 000000000..a97bb4842 --- /dev/null +++ b/UI/forms/images/sources/camera.svg @@ -0,0 +1 @@ + diff --git a/UI/forms/images/sources/default.svg b/UI/forms/images/sources/default.svg new file mode 100644 index 000000000..378519ab6 --- /dev/null +++ b/UI/forms/images/sources/default.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/UI/forms/images/sources/gamepad.svg b/UI/forms/images/sources/gamepad.svg new file mode 100644 index 000000000..894d7d84b --- /dev/null +++ b/UI/forms/images/sources/gamepad.svg @@ -0,0 +1 @@ + diff --git a/UI/forms/images/sources/globe.svg b/UI/forms/images/sources/globe.svg new file mode 100644 index 000000000..c90766d47 --- /dev/null +++ b/UI/forms/images/sources/globe.svg @@ -0,0 +1 @@ + diff --git a/UI/forms/images/sources/group.svg b/UI/forms/images/sources/group.svg new file mode 100644 index 000000000..8f639f986 --- /dev/null +++ b/UI/forms/images/sources/group.svg @@ -0,0 +1,3 @@ + + + diff --git a/UI/forms/images/sources/image.svg b/UI/forms/images/sources/image.svg new file mode 100644 index 000000000..84e81ae73 --- /dev/null +++ b/UI/forms/images/sources/image.svg @@ -0,0 +1,3 @@ + + + diff --git a/UI/forms/images/sources/media.svg b/UI/forms/images/sources/media.svg new file mode 100644 index 000000000..3b3ba714a --- /dev/null +++ b/UI/forms/images/sources/media.svg @@ -0,0 +1,3 @@ + + + diff --git a/UI/forms/images/sources/microphone.svg b/UI/forms/images/sources/microphone.svg new file mode 100644 index 000000000..e38fa2029 --- /dev/null +++ b/UI/forms/images/sources/microphone.svg @@ -0,0 +1,4 @@ + + + diff --git a/UI/forms/images/sources/scene.svg b/UI/forms/images/sources/scene.svg new file mode 100644 index 000000000..83ada76b0 --- /dev/null +++ b/UI/forms/images/sources/scene.svg @@ -0,0 +1,4 @@ + + + \ No newline at end of file diff --git a/UI/forms/images/sources/slideshow.svg b/UI/forms/images/sources/slideshow.svg new file mode 100644 index 000000000..b50d99de5 --- /dev/null +++ b/UI/forms/images/sources/slideshow.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/UI/forms/images/sources/text.svg b/UI/forms/images/sources/text.svg new file mode 100644 index 000000000..7b355033d --- /dev/null +++ b/UI/forms/images/sources/text.svg @@ -0,0 +1,3 @@ + + + diff --git a/UI/forms/images/sources/window.svg b/UI/forms/images/sources/window.svg new file mode 100644 index 000000000..7f2a39d6e --- /dev/null +++ b/UI/forms/images/sources/window.svg @@ -0,0 +1 @@ + diff --git a/UI/forms/obs.qrc b/UI/forms/obs.qrc index c619d065c..449b217e1 100644 --- a/UI/forms/obs.qrc +++ b/UI/forms/obs.qrc @@ -18,6 +18,19 @@ images/visible.svg images/trash.svg images/revert.svg + images/sources/brush.svg + images/sources/camera.svg + images/sources/gamepad.svg + images/sources/globe.svg + images/sources/group.svg + images/sources/image.svg + images/sources/media.svg + images/sources/microphone.svg + images/sources/scene.svg + images/sources/slideshow.svg + images/sources/text.svg + images/sources/window.svg + images/sources/default.svg images/settings/output.svg diff --git a/UI/source-tree.cpp b/UI/source-tree.cpp index 4032f3a3e..e88bf6d19 100644 --- a/UI/source-tree.cpp +++ b/UI/source-tree.cpp @@ -57,6 +57,24 @@ SourceTreeItem::SourceTreeItem(SourceTree *tree_, OBSSceneItem sceneitem_) obs_data_release(privData); + OBSBasic *main = reinterpret_cast(App()->GetMainWindow()); + const char *id = obs_source_get_id(source); + QIcon icon; + + if (strcmp(id, "scene") == 0) + icon = main->GetSceneIcon(); + else if (strcmp(id, "group") == 0) + icon = main->GetGroupIcon(); + else + icon = main->GetSourceIcon(id); + + QPixmap pixmap = icon.pixmap(QSize(16, 16)); + + QLabel *iconLabel = new QLabel(); + iconLabel->setPixmap(pixmap); + iconLabel->setFixedSize(16, 16); + iconLabel->setStyleSheet("background: none"); + vis = new VisibilityCheckBox(); vis->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); vis->setFixedSize(16, 16); @@ -80,11 +98,13 @@ SourceTreeItem::SourceTreeItem(SourceTree *tree_, OBSSceneItem sceneitem_) #endif boxLayout = new QHBoxLayout(); - boxLayout->setContentsMargins(1, 1, 1, 1); - boxLayout->setSpacing(1); + + boxLayout->setContentsMargins(0, 0, 0, 0); + boxLayout->addWidget(iconLabel); + boxLayout->addSpacing(2); boxLayout->addWidget(label); boxLayout->addWidget(vis); - boxLayout->setSpacing(2); + boxLayout->addSpacing(1); boxLayout->addWidget(lock); #ifdef __APPLE__ /* Hack: Fixes a bug where scrollbars would be above the lock icon */ @@ -943,6 +963,13 @@ SourceTree::SourceTree(QWidget *parent_) : QListView(parent_) UpdateNoSourcesMessage(); connect(App(), &OBSApp::StyleChanged, this, &SourceTree::UpdateNoSourcesMessage); + connect(App(), &OBSApp::StyleChanged, this, &SourceTree::UpdateIcons); +} + +void SourceTree::UpdateIcons() +{ + SourceTreeModel *stm = GetStm(); + stm->SceneChanged(); } void SourceTree::ResetWidgets() diff --git a/UI/source-tree.hpp b/UI/source-tree.hpp index d613e61d0..e9a26f33b 100644 --- a/UI/source-tree.hpp +++ b/UI/source-tree.hpp @@ -177,6 +177,8 @@ public: bool GroupsSelected() const; bool GroupedItemsSelected() const; + void UpdateIcons(); + public slots: inline void ReorderItems() { GetStm()->ReorderItems(); } void Remove(OBSSceneItem item); diff --git a/UI/window-basic-main-icons.cpp b/UI/window-basic-main-icons.cpp new file mode 100644 index 000000000..56096bbed --- /dev/null +++ b/UI/window-basic-main-icons.cpp @@ -0,0 +1,188 @@ +#include + +QIcon OBSBasic::GetSourceIcon(const char *id) const +{ + obs_icon_type type = obs_source_get_icon_type(id); + + switch (type) { + case OBS_ICON_TYPE_IMAGE: + return GetImageIcon(); + case OBS_ICON_TYPE_COLOR: + return GetColorIcon(); + case OBS_ICON_TYPE_SLIDESHOW: + return GetSlideshowIcon(); + case OBS_ICON_TYPE_AUDIO_INPUT: + return GetAudioInputIcon(); + case OBS_ICON_TYPE_AUDIO_OUTPUT: + return GetAudioOutputIcon(); + case OBS_ICON_TYPE_DESKTOP_CAPTURE: + return GetDesktopCapIcon(); + case OBS_ICON_TYPE_WINDOW_CAPTURE: + return GetWindowCapIcon(); + case OBS_ICON_TYPE_GAME_CAPTURE: + return GetGameCapIcon(); + case OBS_ICON_TYPE_CAMERA: + return GetCameraIcon(); + case OBS_ICON_TYPE_TEXT: + return GetTextIcon(); + case OBS_ICON_TYPE_MEDIA: + return GetMediaIcon(); + case OBS_ICON_TYPE_BROWSER: + return GetBrowserIcon(); + case OBS_ICON_TYPE_CUSTOM: + //TODO: Add ability for sources to define custom icons + return GetDefaultIcon(); + default: + return GetDefaultIcon(); + } +} + +void OBSBasic::SetImageIcon(const QIcon &icon) +{ + imageIcon = icon; +} + +void OBSBasic::SetColorIcon(const QIcon &icon) +{ + colorIcon = icon; +} + +void OBSBasic::SetSlideshowIcon(const QIcon &icon) +{ + slideshowIcon = icon; +} + +void OBSBasic::SetAudioInputIcon(const QIcon &icon) +{ + audioInputIcon = icon; +} + +void OBSBasic::SetAudioOutputIcon(const QIcon &icon) +{ + audioOutputIcon = icon; +} + +void OBSBasic::SetDesktopCapIcon(const QIcon &icon) +{ + desktopCapIcon = icon; +} + +void OBSBasic::SetWindowCapIcon(const QIcon &icon) +{ + windowCapIcon = icon; +} + +void OBSBasic::SetGameCapIcon(const QIcon &icon) +{ + gameCapIcon = icon; +} + +void OBSBasic::SetCameraIcon(const QIcon &icon) +{ + cameraIcon = icon; +} + +void OBSBasic::SetTextIcon(const QIcon &icon) +{ + textIcon = icon; +} + +void OBSBasic::SetMediaIcon(const QIcon &icon) +{ + mediaIcon = icon; +} + +void OBSBasic::SetBrowserIcon(const QIcon &icon) +{ + browserIcon = icon; +} + +void OBSBasic::SetGroupIcon(const QIcon &icon) +{ + groupIcon = icon; +} + +void OBSBasic::SetSceneIcon(const QIcon &icon) +{ + sceneIcon = icon; +} + +void OBSBasic::SetDefaultIcon(const QIcon &icon) +{ + defaultIcon = icon; +} + +QIcon OBSBasic::GetImageIcon() const +{ + return imageIcon; +} + +QIcon OBSBasic::GetColorIcon() const +{ + return colorIcon; +} + +QIcon OBSBasic::GetSlideshowIcon() const +{ + return slideshowIcon; +} + +QIcon OBSBasic::GetAudioInputIcon() const +{ + return audioInputIcon; +} + +QIcon OBSBasic::GetAudioOutputIcon() const +{ + return audioOutputIcon; +} + +QIcon OBSBasic::GetDesktopCapIcon() const +{ + return desktopCapIcon; +} + +QIcon OBSBasic::GetWindowCapIcon() const +{ + return windowCapIcon; +} + +QIcon OBSBasic::GetGameCapIcon() const +{ + return gameCapIcon; +} + +QIcon OBSBasic::GetCameraIcon() const +{ + return cameraIcon; +} + +QIcon OBSBasic::GetTextIcon() const +{ + return textIcon; +} + +QIcon OBSBasic::GetMediaIcon() const +{ + return mediaIcon; +} + +QIcon OBSBasic::GetBrowserIcon() const +{ + return browserIcon; +} + +QIcon OBSBasic::GetGroupIcon() const +{ + return groupIcon; +} + +QIcon OBSBasic::GetSceneIcon() const +{ + return sceneIcon; +} + +QIcon OBSBasic::GetDefaultIcon() const +{ + return defaultIcon; +} diff --git a/UI/window-basic-main.cpp b/UI/window-basic-main.cpp index 8c80112f6..f092c36f5 100644 --- a/UI/window-basic-main.cpp +++ b/UI/window-basic-main.cpp @@ -1816,6 +1816,8 @@ void OBSBasic::OBSInit() ui->viewMenu->addAction(QTStr("MultiviewWindowed"), this, SLOT(OpenMultiviewWindow())); + ui->sources->UpdateIcons(); + #if !defined(_WIN32) && !defined(__APPLE__) delete ui->actionShowCrashLogs; delete ui->actionUploadLastCrashLog; @@ -4612,6 +4614,15 @@ QMenu *OBSBasic::CreateAddSourcePopupMenu() connect(popupItem, SIGNAL(triggered(bool)), this, SLOT(AddSourceFromAction())); + QIcon icon; + + if (strcmp(type, "scene") == 0) + icon = GetSceneIcon(); + else + icon = GetSourceIcon(type); + + popupItem->setIcon(icon); + QAction *after = getActionAfter(popup, qname); popup->insertAction(after, popupItem); }; @@ -4637,6 +4648,7 @@ QMenu *OBSBasic::CreateAddSourcePopupMenu() popup->addSeparator(); QAction *addGroup = new QAction(QTStr("Group"), this); addGroup->setData(QT_UTF8("group")); + addGroup->setIcon(GetGroupIcon()); connect(addGroup, SIGNAL(triggered(bool)), this, SLOT(AddSourceFromAction())); popup->addAction(addGroup); diff --git a/UI/window-basic-main.hpp b/UI/window-basic-main.hpp index b449a518f..e4ecc2791 100644 --- a/UI/window-basic-main.hpp +++ b/UI/window-basic-main.hpp @@ -117,6 +117,36 @@ private: class OBSBasic : public OBSMainWindow { Q_OBJECT + Q_PROPERTY(QIcon imageIcon READ GetImageIcon WRITE SetImageIcon + DESIGNABLE true) + Q_PROPERTY(QIcon colorIcon READ GetColorIcon WRITE SetColorIcon + DESIGNABLE true) + Q_PROPERTY(QIcon slideshowIcon READ GetSlideshowIcon WRITE + SetSlideshowIcon DESIGNABLE true) + Q_PROPERTY(QIcon audioInputIcon READ GetAudioInputIcon WRITE + SetAudioInputIcon DESIGNABLE true) + Q_PROPERTY(QIcon audioOutputIcon READ GetAudioOutputIcon WRITE + SetAudioOutputIcon DESIGNABLE true) + Q_PROPERTY(QIcon desktopCapIcon READ GetDesktopCapIcon WRITE + SetDesktopCapIcon DESIGNABLE true) + Q_PROPERTY(QIcon windowCapIcon READ GetWindowCapIcon WRITE + SetWindowCapIcon DESIGNABLE true) + Q_PROPERTY(QIcon gameCapIcon READ GetGameCapIcon WRITE SetGameCapIcon + DESIGNABLE true) + Q_PROPERTY(QIcon cameraIcon READ GetCameraIcon WRITE SetCameraIcon + DESIGNABLE true) + Q_PROPERTY(QIcon textIcon READ GetTextIcon WRITE SetTextIcon + DESIGNABLE true) + Q_PROPERTY(QIcon mediaIcon READ GetMediaIcon WRITE SetMediaIcon + DESIGNABLE true) + Q_PROPERTY(QIcon browserIcon READ GetBrowserIcon WRITE SetBrowserIcon + DESIGNABLE true) + Q_PROPERTY(QIcon groupIcon READ GetGroupIcon WRITE SetGroupIcon + DESIGNABLE true) + Q_PROPERTY(QIcon sceneIcon READ GetSceneIcon WRITE SetSceneIcon + DESIGNABLE true) + Q_PROPERTY(QIcon defaultIcon READ GetDefaultIcon WRITE SetDefaultIcon + DESIGNABLE true) friend class OBSAbout; friend class OBSBasicPreview; @@ -441,6 +471,36 @@ private: bool firstCreate); #endif + QIcon imageIcon; + QIcon colorIcon; + QIcon slideshowIcon; + QIcon audioInputIcon; + QIcon audioOutputIcon; + QIcon desktopCapIcon; + QIcon windowCapIcon; + QIcon gameCapIcon; + QIcon cameraIcon; + QIcon textIcon; + QIcon mediaIcon; + QIcon browserIcon; + QIcon groupIcon; + QIcon sceneIcon; + QIcon defaultIcon; + + QIcon GetImageIcon() const; + QIcon GetColorIcon() const; + QIcon GetSlideshowIcon() const; + QIcon GetAudioInputIcon() const; + QIcon GetAudioOutputIcon() const; + QIcon GetDesktopCapIcon() const; + QIcon GetWindowCapIcon() const; + QIcon GetGameCapIcon() const; + QIcon GetCameraIcon() const; + QIcon GetTextIcon() const; + QIcon GetMediaIcon() const; + QIcon GetBrowserIcon() const; + QIcon GetDefaultIcon() const; + public slots: void DeferSaveBegin(); void DeferSaveEnd(); @@ -567,6 +627,22 @@ private slots: void ResetStatsHotkey(); + void SetImageIcon(const QIcon &icon); + void SetColorIcon(const QIcon &icon); + void SetSlideshowIcon(const QIcon &icon); + void SetAudioInputIcon(const QIcon &icon); + void SetAudioOutputIcon(const QIcon &icon); + void SetDesktopCapIcon(const QIcon &icon); + void SetWindowCapIcon(const QIcon &icon); + void SetGameCapIcon(const QIcon &icon); + void SetCameraIcon(const QIcon &icon); + void SetTextIcon(const QIcon &icon); + void SetMediaIcon(const QIcon &icon); + void SetBrowserIcon(const QIcon &icon); + void SetGroupIcon(const QIcon &icon); + void SetSceneIcon(const QIcon &icon); + void SetDefaultIcon(const QIcon &icon); + private: /* OBS Callbacks */ static void SceneReordered(void *data, calldata_t *params); @@ -696,6 +772,10 @@ public: void AddProjectorMenuMonitors(QMenu *parent, QObject *target, const char *slot); + QIcon GetSourceIcon(const char *id) const; + QIcon GetGroupIcon() const; + QIcon GetSceneIcon() const; + protected: virtual void closeEvent(QCloseEvent *event) override; virtual void changeEvent(QEvent *event) override; diff --git a/libobs/obs-source.c b/libobs/obs-source.c index d6269cb13..dd209595e 100644 --- a/libobs/obs-source.c +++ b/libobs/obs-source.c @@ -4734,3 +4734,9 @@ uint32_t obs_source_get_last_obs_version(const obs_source_t *source) ? source->last_obs_ver : 0; } + +enum obs_icon_type obs_source_get_icon_type(const char *id) +{ + const struct obs_source_info *info = get_source_info(id); + return (info) ? info->icon_type : OBS_ICON_TYPE_UNKNOWN; +} diff --git a/libobs/obs-source.h b/libobs/obs-source.h index 3e4aac3df..83b91f354 100644 --- a/libobs/obs-source.h +++ b/libobs/obs-source.h @@ -43,6 +43,23 @@ enum obs_balance_type { OBS_BALANCE_TYPE_LINEAR, }; +enum obs_icon_type { + OBS_ICON_TYPE_UNKNOWN, + OBS_ICON_TYPE_IMAGE, + OBS_ICON_TYPE_COLOR, + OBS_ICON_TYPE_SLIDESHOW, + OBS_ICON_TYPE_AUDIO_INPUT, + OBS_ICON_TYPE_AUDIO_OUTPUT, + OBS_ICON_TYPE_DESKTOP_CAPTURE, + OBS_ICON_TYPE_WINDOW_CAPTURE, + OBS_ICON_TYPE_GAME_CAPTURE, + OBS_ICON_TYPE_CAMERA, + OBS_ICON_TYPE_TEXT, + OBS_ICON_TYPE_MEDIA, + OBS_ICON_TYPE_BROWSER, + OBS_ICON_TYPE_CUSTOM, +}; + /** * @name Source output flags * @@ -471,6 +488,9 @@ struct obs_source_info { bool (*audio_mix)(void *data, uint64_t *ts_out, struct audio_output_data *audio_output, size_t channels, size_t sample_rate); + + /** Icon type for the source */ + enum obs_icon_type icon_type; }; EXPORT void obs_register_source_s(const struct obs_source_info *info, diff --git a/libobs/obs.h b/libobs/obs.h index 562984a46..fe0555267 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -2170,6 +2170,10 @@ static inline void obs_source_frame_destroy(struct obs_source_frame *frame) EXPORT void obs_source_frame_copy(struct obs_source_frame *dst, const struct obs_source_frame *src); +/* ------------------------------------------------------------------------- */ +/* Get source icon type */ +EXPORT enum obs_icon_type obs_source_get_icon_type(const char *id); + #ifdef __cplusplus } #endif diff --git a/plugins/decklink/decklink-source.cpp b/plugins/decklink/decklink-source.cpp index 939b0ff60..0b31623c6 100644 --- a/plugins/decklink/decklink-source.cpp +++ b/plugins/decklink/decklink-source.cpp @@ -342,6 +342,7 @@ struct obs_source_info create_decklink_source_info() decklink_source_info.update = decklink_update; decklink_source_info.show = decklink_show; decklink_source_info.hide = decklink_hide; + decklink_source_info.icon_type = OBS_ICON_TYPE_CAMERA; return decklink_source_info; } diff --git a/plugins/image-source/color-source.c b/plugins/image-source/color-source.c index 28b750ac3..5739200b2 100644 --- a/plugins/image-source/color-source.c +++ b/plugins/image-source/color-source.c @@ -119,4 +119,5 @@ struct obs_source_info color_source_info = { .get_height = color_source_getheight, .video_render = color_source_render, .get_properties = color_source_properties, + .icon_type = OBS_ICON_TYPE_COLOR, }; diff --git a/plugins/image-source/image-source.c b/plugins/image-source/image-source.c index c3fde0293..5817c9c62 100644 --- a/plugins/image-source/image-source.c +++ b/plugins/image-source/image-source.c @@ -265,7 +265,9 @@ static struct obs_source_info image_source_info = { .get_height = image_source_getheight, .video_render = image_source_render, .video_tick = image_source_tick, - .get_properties = image_source_properties}; + .get_properties = image_source_properties, + .icon_type = OBS_ICON_TYPE_IMAGE, +}; OBS_DECLARE_MODULE() OBS_MODULE_USE_DEFAULT_LOCALE("image-source", "en-US") diff --git a/plugins/image-source/obs-slideshow.c b/plugins/image-source/obs-slideshow.c index ae4cd8d10..7b6750dbb 100644 --- a/plugins/image-source/obs-slideshow.c +++ b/plugins/image-source/obs-slideshow.c @@ -940,4 +940,5 @@ struct obs_source_info slideshow_info = { .get_height = ss_height, .get_defaults = ss_defaults, .get_properties = ss_properties, + .icon_type = OBS_ICON_TYPE_SLIDESHOW, }; diff --git a/plugins/linux-alsa/alsa-input.c b/plugins/linux-alsa/alsa-input.c index d0253dbe2..64e7382db 100644 --- a/plugins/linux-alsa/alsa-input.c +++ b/plugins/linux-alsa/alsa-input.c @@ -88,6 +88,7 @@ struct obs_source_info alsa_input_capture = { .get_defaults = alsa_get_defaults, .get_name = alsa_get_name, .get_properties = alsa_get_properties, + .icon_type = OBS_ICON_TYPE_AUDIO_INPUT, }; static bool _alsa_try_open(struct alsa_data *); diff --git a/plugins/linux-capture/xcomposite-main.cpp b/plugins/linux-capture/xcomposite-main.cpp index 0fa659128..3af99a001 100644 --- a/plugins/linux-capture/xcomposite-main.cpp +++ b/plugins/linux-capture/xcomposite-main.cpp @@ -82,6 +82,7 @@ extern "C" void xcomposite_load(void) sinfo.video_render = xcompcap_video_render; sinfo.get_width = xcompcap_getwidth; sinfo.get_height = xcompcap_getheight; + sinfo.icon_type = OBS_ICON_TYPE_WINDOW_CAPTURE, obs_register_source(&sinfo); } diff --git a/plugins/linux-capture/xshm-input.c b/plugins/linux-capture/xshm-input.c index 1ff3ebba6..70c3fc06f 100644 --- a/plugins/linux-capture/xshm-input.c +++ b/plugins/linux-capture/xshm-input.c @@ -508,4 +508,5 @@ struct obs_source_info xshm_input = { .video_render = xshm_video_render, .get_width = xshm_getwidth, .get_height = xshm_getheight, + .icon_type = OBS_ICON_TYPE_DESKTOP_CAPTURE, }; diff --git a/plugins/linux-jack/jack-input.c b/plugins/linux-jack/jack-input.c index 7816f2f52..3fe97b6a1 100644 --- a/plugins/linux-jack/jack-input.c +++ b/plugins/linux-jack/jack-input.c @@ -147,4 +147,5 @@ struct obs_source_info jack_output_capture = { .update = jack_update, .get_defaults = jack_input_defaults, .get_properties = jack_input_properties, + .icon_type = OBS_ICON_TYPE_AUDIO_OUTPUT, }; diff --git a/plugins/linux-pulseaudio/pulse-input.c b/plugins/linux-pulseaudio/pulse-input.c index 68d44cdc4..15cb7f130 100644 --- a/plugins/linux-pulseaudio/pulse-input.c +++ b/plugins/linux-pulseaudio/pulse-input.c @@ -594,6 +594,7 @@ struct obs_source_info pulse_input_capture = { .update = pulse_update, .get_defaults = pulse_defaults, .get_properties = pulse_input_properties, + .icon_type = OBS_ICON_TYPE_AUDIO_INPUT, }; struct obs_source_info pulse_output_capture = { @@ -607,4 +608,5 @@ struct obs_source_info pulse_output_capture = { .update = pulse_update, .get_defaults = pulse_defaults, .get_properties = pulse_output_properties, + .icon_type = OBS_ICON_TYPE_AUDIO_OUTPUT, }; diff --git a/plugins/linux-v4l2/v4l2-input.c b/plugins/linux-v4l2/v4l2-input.c index 23298466a..302209f8c 100644 --- a/plugins/linux-v4l2/v4l2-input.c +++ b/plugins/linux-v4l2/v4l2-input.c @@ -1005,4 +1005,5 @@ struct obs_source_info v4l2_input = { .update = v4l2_update, .get_defaults = v4l2_defaults, .get_properties = v4l2_properties, + .icon_type = OBS_ICON_TYPE_CAMERA, }; diff --git a/plugins/mac-avcapture/av-capture.mm b/plugins/mac-avcapture/av-capture.mm index 1718bb53b..32556d69b 100644 --- a/plugins/mac-avcapture/av-capture.mm +++ b/plugins/mac-avcapture/av-capture.mm @@ -2194,6 +2194,7 @@ bool obs_module_load(void) .get_defaults = av_capture_defaults, .get_properties = av_capture_properties, .update = av_capture_update, + .icon_type = OBS_ICON_TYPE_CAMERA, }; obs_register_source(&av_capture_info); diff --git a/plugins/mac-capture/mac-audio.c b/plugins/mac-capture/mac-audio.c index 72e36d0f4..358f5ea8d 100644 --- a/plugins/mac-capture/mac-audio.c +++ b/plugins/mac-capture/mac-audio.c @@ -817,6 +817,7 @@ struct obs_source_info coreaudio_input_capture_info = { .update = coreaudio_update, .get_defaults = coreaudio_defaults, .get_properties = coreaudio_input_properties, + .icon_type = OBS_ICON_TYPE_AUDIO_INPUT, }; struct obs_source_info coreaudio_output_capture_info = { @@ -830,4 +831,5 @@ struct obs_source_info coreaudio_output_capture_info = { .update = coreaudio_update, .get_defaults = coreaudio_defaults, .get_properties = coreaudio_output_properties, + .icon_type = OBS_ICON_TYPE_AUDIO_OUTPUT, }; diff --git a/plugins/mac-capture/mac-display-capture.m b/plugins/mac-capture/mac-display-capture.m index 392a7a74c..5fed6c440 100644 --- a/plugins/mac-capture/mac-display-capture.m +++ b/plugins/mac-capture/mac-display-capture.m @@ -658,4 +658,5 @@ struct obs_source_info display_capture_info = { .get_defaults = display_capture_defaults, .get_properties = display_capture_properties, .update = display_capture_update, + .icon_type = OBS_ICON_TYPE_DESKTOP_CAPTURE, }; diff --git a/plugins/mac-capture/mac-window-capture.m b/plugins/mac-capture/mac-window-capture.m index 110ff4d83..a79942421 100644 --- a/plugins/mac-capture/mac-window-capture.m +++ b/plugins/mac-capture/mac-window-capture.m @@ -235,4 +235,5 @@ struct obs_source_info window_capture_info = { .get_defaults = window_capture_defaults, .get_properties = window_capture_properties, .update = window_capture_update, + .icon_type = OBS_ICON_TYPE_WINDOW_CAPTURE, }; diff --git a/plugins/mac-syphon/syphon.m b/plugins/mac-syphon/syphon.m index 0dfe60e9a..61d452dc7 100644 --- a/plugins/mac-syphon/syphon.m +++ b/plugins/mac-syphon/syphon.m @@ -1281,4 +1281,5 @@ struct obs_source_info syphon_info = { .get_height = syphon_get_height, .update = syphon_update, .save = syphon_save, + .icon_type = OBS_ICON_TYPE_GAME_CAPTURE, }; diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-source.c b/plugins/obs-ffmpeg/obs-ffmpeg-source.c index 1cf43d563..0719df46f 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-source.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-source.c @@ -505,4 +505,5 @@ struct obs_source_info ffmpeg_source = { .deactivate = ffmpeg_source_deactivate, .video_tick = ffmpeg_source_tick, .update = ffmpeg_source_update, + .icon_type = OBS_ICON_TYPE_MEDIA, }; diff --git a/plugins/obs-text/gdiplus/obs-text.cpp b/plugins/obs-text/gdiplus/obs-text.cpp index 0edbead07..0a34e988b 100644 --- a/plugins/obs-text/gdiplus/obs-text.cpp +++ b/plugins/obs-text/gdiplus/obs-text.cpp @@ -1042,6 +1042,7 @@ bool obs_module_load(void) si.type = OBS_SOURCE_TYPE_INPUT; si.output_flags = OBS_SOURCE_VIDEO | OBS_SOURCE_CUSTOM_DRAW; si.get_properties = get_properties; + si.icon_type = OBS_ICON_TYPE_TEXT; si.get_name = [](void *) { return obs_module_text("TextGDIPlus"); }; si.create = [](obs_data_t *settings, obs_source_t *source) { diff --git a/plugins/text-freetype2/text-freetype2.c b/plugins/text-freetype2/text-freetype2.c index bc2dd18d0..dc220b3b1 100644 --- a/plugins/text-freetype2/text-freetype2.c +++ b/plugins/text-freetype2/text-freetype2.c @@ -52,6 +52,7 @@ static struct obs_source_info freetype2_source_info = { .video_render = ft2_source_render, .video_tick = ft2_video_tick, .get_properties = ft2_source_properties, + .icon_type = OBS_ICON_TYPE_TEXT, }; static bool plugin_initialized = false; diff --git a/plugins/vlc-video/vlc-video-source.c b/plugins/vlc-video/vlc-video-source.c index 550b04f14..1c4cff0f7 100644 --- a/plugins/vlc-video/vlc-video-source.c +++ b/plugins/vlc-video/vlc-video-source.c @@ -961,4 +961,5 @@ struct obs_source_info vlc_source_info = { .get_properties = vlcs_properties, .activate = vlcs_activate, .deactivate = vlcs_deactivate, + .icon_type = OBS_ICON_TYPE_MEDIA, }; diff --git a/plugins/win-capture/duplicator-monitor-capture.c b/plugins/win-capture/duplicator-monitor-capture.c index 0efd48a99..abba08dd1 100644 --- a/plugins/win-capture/duplicator-monitor-capture.c +++ b/plugins/win-capture/duplicator-monitor-capture.c @@ -323,4 +323,5 @@ struct obs_source_info duplicator_capture_info = { .get_height = duplicator_capture_height, .get_defaults = duplicator_capture_defaults, .get_properties = duplicator_capture_properties, + .icon_type = OBS_ICON_TYPE_DESKTOP_CAPTURE, }; diff --git a/plugins/win-capture/game-capture.c b/plugins/win-capture/game-capture.c index f9ff2ac4c..5c9422afd 100644 --- a/plugins/win-capture/game-capture.c +++ b/plugins/win-capture/game-capture.c @@ -2103,4 +2103,5 @@ struct obs_source_info game_capture_info = { .update = game_capture_update, .video_tick = game_capture_tick, .video_render = game_capture_render, + .icon_type = OBS_ICON_TYPE_GAME_CAPTURE, }; diff --git a/plugins/win-capture/monitor-capture.c b/plugins/win-capture/monitor-capture.c index 9e7c76ebd..e8d43a6f0 100644 --- a/plugins/win-capture/monitor-capture.c +++ b/plugins/win-capture/monitor-capture.c @@ -243,4 +243,5 @@ struct obs_source_info monitor_capture_info = { .get_height = monitor_capture_height, .get_defaults = monitor_capture_defaults, .get_properties = monitor_capture_properties, + .icon_type = OBS_ICON_TYPE_DESKTOP_CAPTURE, }; diff --git a/plugins/win-capture/window-capture.c b/plugins/win-capture/window-capture.c index d75b38c83..886d56354 100644 --- a/plugins/win-capture/window-capture.c +++ b/plugins/win-capture/window-capture.c @@ -259,4 +259,5 @@ struct obs_source_info window_capture_info = { .get_height = wc_height, .get_defaults = wc_defaults, .get_properties = wc_properties, + .icon_type = OBS_ICON_TYPE_WINDOW_CAPTURE, }; diff --git a/plugins/win-dshow/win-dshow.cpp b/plugins/win-dshow/win-dshow.cpp index bc51c3226..84693e41b 100644 --- a/plugins/win-dshow/win-dshow.cpp +++ b/plugins/win-dshow/win-dshow.cpp @@ -1999,5 +1999,6 @@ void RegisterDShowSource() info.update = UpdateDShowInput; info.get_defaults = GetDShowDefaults; info.get_properties = GetDShowProperties; + info.icon_type = OBS_ICON_TYPE_CAMERA; obs_register_source(&info); } diff --git a/plugins/win-ivcam/realsense.cpp b/plugins/win-ivcam/realsense.cpp index 4395df5e5..83368bc61 100644 --- a/plugins/win-ivcam/realsense.cpp +++ b/plugins/win-ivcam/realsense.cpp @@ -185,6 +185,7 @@ bool obs_module_load(void) info.get_name = GetIVCamName; info.create = IVCamSource::CreateIVCamSource; info.destroy = DestroyIVCamSource; + info.icon_type = OBS_ICON_TYPE_CAMERA; obs_register_source(&info); return true; } diff --git a/plugins/win-wasapi/win-wasapi.cpp b/plugins/win-wasapi/win-wasapi.cpp index b66a29064..5eb139c7b 100644 --- a/plugins/win-wasapi/win-wasapi.cpp +++ b/plugins/win-wasapi/win-wasapi.cpp @@ -618,6 +618,7 @@ void RegisterWASAPIInput() info.update = UpdateWASAPISource; info.get_defaults = GetWASAPIDefaultsInput; info.get_properties = GetWASAPIPropertiesInput; + info.icon_type = OBS_ICON_TYPE_AUDIO_INPUT; obs_register_source(&info); } @@ -634,5 +635,6 @@ void RegisterWASAPIOutput() info.update = UpdateWASAPISource; info.get_defaults = GetWASAPIDefaultsOutput; info.get_properties = GetWASAPIPropertiesOutput; + info.icon_type = OBS_ICON_TYPE_AUDIO_OUTPUT; obs_register_source(&info); }