diff --git a/UI/data/themes/Acri.qss b/UI/data/themes/Acri.qss index e7c70496a..a4be95b8c 100644 --- a/UI/data/themes/Acri.qss +++ b/UI/data/themes/Acri.qss @@ -166,7 +166,7 @@ QMenu::item:disabled { } QMenu::right-arrow { - image: url(./Dark/expand.svg); + image: url(theme:Dark/expand.svg); } /* Top Menu Bar Items */ @@ -304,8 +304,8 @@ QDockWidget { font-size: 10.5pt; font-weight: bold; - titlebar-close-icon: url('./Dark/close.svg'); - titlebar-normal-icon: url('./Dark/popout.svg'); + titlebar-close-icon: url(theme:Dark/close.svg); + titlebar-normal-icon: url(theme:Dark/popout.svg); } QDockWidget::title { @@ -453,11 +453,11 @@ QScrollBar::handle:horizontal { } QPushButton#sourcePropertiesButton { - qproperty-icon: url(./Dark/settings/general.svg); + qproperty-icon: url(theme:Dark/settings/general.svg); } QPushButton#sourceFiltersButton { - qproperty-icon: url(./Dark/filter.svg); + qproperty-icon: url(theme:Dark/filter.svg); } /* Scenes and Sources toolbar */ @@ -493,55 +493,55 @@ QToolButton:pressed { } * [themeID="addIconSmall"] { - qproperty-icon: url(./Dark/plus.svg); + qproperty-icon: url(theme:Dark/plus.svg); } * [themeID="removeIconSmall"] { - qproperty-icon: url(./Dark/trash.svg); + qproperty-icon: url(theme:Dark/trash.svg); } * [themeID="clearIconSmall"] { - qproperty-icon: url(./Dark/entry-clear.svg); + qproperty-icon: url(theme:Dark/entry-clear.svg); } * [themeID="propertiesIconSmall"] { - qproperty-icon: url(./Dark/settings/general.svg); + qproperty-icon: url(theme:Dark/settings/general.svg); } * [themeID="configIconSmall"] { - qproperty-icon: url(./Dark/settings/general.svg); + qproperty-icon: url(theme:Dark/settings/general.svg); } * [themeID="menuIconSmall"] { - qproperty-icon: url(./Dark/dots-vert.svg); + qproperty-icon: url(theme:Dark/dots-vert.svg); } * [themeID="refreshIconSmall"] { - qproperty-icon: url(./Dark/refresh.svg); + qproperty-icon: url(theme:Dark/refresh.svg); } * [themeID="cogsIcon"] { - qproperty-icon: url(./Dark/cogs.svg); + qproperty-icon: url(theme:Dark/cogs.svg); } #sourceInteractButton { - qproperty-icon: url(./Dark/interact.svg); + qproperty-icon: url(theme:Dark/interact.svg); } * [themeID="upArrowIconSmall"] { - qproperty-icon: url(./Dark/up.svg); + qproperty-icon: url(theme:Dark/up.svg); } * [themeID="downArrowIconSmall"] { - qproperty-icon: url(./Dark/down.svg); + qproperty-icon: url(theme:Dark/down.svg); } * [themeID="pauseIconSmall"] { - qproperty-icon: url(./Dark/media-pause.svg); + qproperty-icon: url(theme:Dark/media-pause.svg); } * [themeID="filtersIcon"] { - qproperty-icon: url(./Dark/filter.svg); + qproperty-icon: url(theme:Dark/filter.svg); } QToolBarExtension { @@ -551,7 +551,7 @@ QToolBarExtension { padding: 4px 0px; margin-left: 0px; - qproperty-icon: url(./Dark/dots-vert.svg); + qproperty-icon: url(theme:Dark/dots-vert.svg); } @@ -647,7 +647,7 @@ QDateTimeEdit::drop-down { QComboBox::down-arrow, QDateTimeEdit::down-arrow { qproperty-alignment: AlignTop; - image: url(./Dark/updown.svg); + image: url(theme:Dark/updown.svg); width: 100%; } @@ -669,7 +669,7 @@ QDateTimeEdit::drop-down:editable { QComboBox::down-arrow:editable, QDateTimeEdit::down-arrow:editable { qproperty-alignment: AlignTop; - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); width: 8%; } @@ -757,13 +757,13 @@ QDoubleSpinBox::up-button:disabled, QDoubleSpinBox::up-button:off, QDoubleSpinBo } QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { - image: url(./Dark/up.svg); + image: url(theme:Dark/up.svg); width: 100%; margin: 2px; } QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); width: 100%; padding: 2px; } @@ -844,7 +844,7 @@ QPushButton:disabled, QToolButton:disabled { } QPushButton::menu-indicator { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); subcontrol-position: right; subcontrol-origin: padding; width: 25px; @@ -995,15 +995,15 @@ QHeaderView::section { /* Mute CheckBox */ MuteCheckBox::indicator:checked { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:indeterminate { - image: url(./Dark/unassigned.svg); + image: url(theme:Dark/unassigned.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } OBSHotkeyLabel[hotkeyPairHover=true] { @@ -1102,14 +1102,14 @@ OBSBasicFilters #widget_2 QPushButton { /* Settings Icons */ OBSBasicSettings { - qproperty-generalIcon: url(./Dark/settings/general.svg); - qproperty-streamIcon: url(./Dark/settings/stream.svg); - qproperty-outputIcon: url(./Dark/settings/output.svg); - qproperty-audioIcon: url(./Dark/settings/audio.svg); - qproperty-videoIcon: url(./Dark/settings/video.svg); - qproperty-hotkeysIcon: url(./Dark/settings/hotkeys.svg); - qproperty-accessibilityIcon: url(./Dark/settings/accessibility.svg); - qproperty-advancedIcon: url(./Dark/settings/advanced.svg); + qproperty-generalIcon: url(theme:Dark/settings/general.svg); + qproperty-streamIcon: url(theme:Dark/settings/stream.svg); + qproperty-outputIcon: url(theme:Dark/settings/output.svg); + qproperty-audioIcon: url(theme:Dark/settings/audio.svg); + qproperty-videoIcon: url(theme:Dark/settings/video.svg); + qproperty-hotkeysIcon: url(theme:Dark/settings/hotkeys.svg); + qproperty-accessibilityIcon: url(theme:Dark/settings/accessibility.svg); + qproperty-advancedIcon: url(theme:Dark/settings/advanced.svg); } /* Checkboxes */ @@ -1129,34 +1129,34 @@ QGroupBox::indicator { QCheckBox::indicator:unchecked, QGroupBox::indicator:unchecked { - image: url(./Yami/checkbox_unchecked.svg); + image: url(theme:Yami/checkbox_unchecked.svg); } QCheckBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:hover { border: none; - image: url(./Yami/checkbox_unchecked_focus.svg); + image: url(theme:Yami/checkbox_unchecked_focus.svg); } QCheckBox::indicator:checked, QGroupBox::indicator:checked { - image: url(./Yami/checkbox_checked.svg); + image: url(theme:Yami/checkbox_checked.svg); } QCheckBox::indicator:checked:hover, QGroupBox::indicator:checked:hover { border: none; - image: url(./Yami/checkbox_checked_focus.svg); + image: url(theme:Yami/checkbox_checked_focus.svg); } QCheckBox::indicator:checked:disabled, QGroupBox::indicator:checked:disabled { - image: url(./Yami/checkbox_checked_disabled.svg); + image: url(theme:Yami/checkbox_checked_disabled.svg); } QCheckBox::indicator:unchecked:disabled, QGroupBox::indicator:unchecked:disabled { - image: url(./Yami/checkbox_unchecked_disabled.svg); + image: url(theme:Yami/checkbox_unchecked_disabled.svg); } /* Locked CheckBox */ @@ -1173,7 +1173,7 @@ LockedCheckBox::indicator { LockedCheckBox::indicator:checked, LockedCheckBox::indicator:checked:hover { - image: url(./Dark/locked.svg); + image: url(theme:Dark/locked.svg); } LockedCheckBox::indicator:unchecked, @@ -1195,7 +1195,7 @@ VisibilityCheckBox::indicator { VisibilityCheckBox::indicator:checked, VisibilityCheckBox::indicator:checked:hover { - image: url(./Dark/visible.svg); + image: url(theme:Dark/visible.svg); } VisibilityCheckBox::indicator:unchecked, @@ -1204,7 +1204,7 @@ VisibilityCheckBox::indicator:unchecked:hover { } * [themeID="revertIcon"] { - qproperty-icon: url(./Dark/revert.svg); + qproperty-icon: url(theme:Dark/revert.svg); } QPushButton#extraPanelDelete { @@ -1233,35 +1233,35 @@ MuteCheckBox::indicator { } MuteCheckBox::indicator:checked { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:hover { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:focus { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } MuteCheckBox::indicator:checked:hover { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:checked:focus { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:checked:disabled { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:unchecked:disabled { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } #hotkeyFilterReset { @@ -1291,46 +1291,46 @@ OBSHotkeyWidget QPushButton { /* Sources List Group Collapse Checkbox */ -SourceTreeSubItemCheckBox { +QCheckBox[sourceTreeSubItem=true] { background: transparent; outline: none; padding: 0px; } -SourceTreeSubItemCheckBox::indicator { +QCheckBox[sourceTreeSubItem=true]::indicator { width: 12px; height: 12px; } -SourceTreeSubItemCheckBox::indicator:checked, -SourceTreeSubItemCheckBox::indicator:checked:hover { - image: url(./Dark/expand.svg); +QCheckBox[sourceTreeSubItem=true]::indicator:checked, +QCheckBox[sourceTreeSubItem=true]::indicator:checked:hover { + image: url(theme:Dark/expand.svg); } -SourceTreeSubItemCheckBox::indicator:unchecked, -SourceTreeSubItemCheckBox::indicator:unchecked:hover { - image: url(./Dark/collapse.svg); +QCheckBox[sourceTreeSubItem=true]::indicator:unchecked, +QCheckBox[sourceTreeSubItem=true]::indicator:unchecked:hover { + image: url(theme:Dark/collapse.svg); } /* 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); - qproperty-audioProcessOutputIcon: url(./Dark/sources/windowaudio.svg); + qproperty-imageIcon: url(theme:Dark/sources/image.svg); + qproperty-colorIcon: url(theme:Dark/sources/brush.svg); + qproperty-slideshowIcon: url(theme:Dark/sources/slideshow.svg); + qproperty-audioInputIcon: url(theme:Dark/sources/microphone.svg); + qproperty-audioOutputIcon: url(theme:Dark/settings/audio.svg); + qproperty-desktopCapIcon: url(theme:Dark/settings/video.svg); + qproperty-windowCapIcon: url(theme:Dark/sources/window.svg); + qproperty-gameCapIcon: url(theme:Dark/sources/gamepad.svg); + qproperty-cameraIcon: url(theme:Dark/sources/camera.svg); + qproperty-textIcon: url(theme:Dark/sources/text.svg); + qproperty-mediaIcon: url(theme:Dark/sources/media.svg); + qproperty-browserIcon: url(theme:Dark/sources/globe.svg); + qproperty-groupIcon: url(theme:Dark/sources/group.svg); + qproperty-sceneIcon: url(theme:Dark/sources/scene.svg); + qproperty-defaultIcon: url(theme:Dark/sources/default.svg); + qproperty-audioProcessOutputIcon: url(theme:Dark/sources/windowaudio.svg); } /* Scene Tree Grid Mode */ @@ -1366,7 +1366,7 @@ SceneTree { /* Save icon */ * [themeID="replayIconSmall"] { - qproperty-icon: url(./Dark/save.svg); + qproperty-icon: url(theme:Dark/save.svg); } /* Studio Mode T-Bar */ @@ -1396,32 +1396,32 @@ QSlider::handle:horizontal[themeID="tBarSlider"] { /* Media icons */ * [themeID="playIcon"] { - qproperty-icon: url(./Dark/media/media_play.svg); + qproperty-icon: url(theme:Dark/media/media_play.svg); } * [themeID="pauseIcon"] { - qproperty-icon: url(./Dark/media/media_pause.svg); + qproperty-icon: url(theme:Dark/media/media_pause.svg); } * [themeID="restartIcon"] { - qproperty-icon: url(./Dark/media/media_restart.svg); + qproperty-icon: url(theme:Dark/media/media_restart.svg); } * [themeID="stopIcon"] { - qproperty-icon: url(./Dark/media/media_stop.svg); + qproperty-icon: url(theme:Dark/media/media_stop.svg); } * [themeID="nextIcon"] { - qproperty-icon: url(./Dark/media/media_next.svg); + qproperty-icon: url(theme:Dark/media/media_next.svg); } * [themeID="previousIcon"] { - qproperty-icon: url(./Dark/media/media_previous.svg); + qproperty-icon: url(theme:Dark/media/media_previous.svg); } /* YouTube Integration */ OBSYoutubeActions { - qproperty-thumbPlaceholder: url(./Dark/sources/image.svg); + qproperty-thumbPlaceholder: url(theme:Dark/sources/image.svg); } #ytEventList QLabel { @@ -1449,7 +1449,7 @@ OBSYoutubeActions { /* Calendar Widget */ QDateTimeEdit::down-arrow { qproperty-alignment: AlignTop; - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); width: 100%; } @@ -1472,7 +1472,7 @@ QCalendarWidget QToolButton { } #qt_calendar_monthbutton::menu-indicator { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); subcontrol-position: right; padding-top: 2px; padding-right: 6px; @@ -1482,13 +1482,13 @@ QCalendarWidget QToolButton { QCalendarWidget #qt_calendar_prevmonth { padding: 2px; - qproperty-icon: url(./Dark/left.svg); + qproperty-icon: url(theme:Dark/left.svg); icon-size: 16px, 16px; } QCalendarWidget #qt_calendar_nextmonth { padding: 2px; - qproperty-icon: url(./Dark/right.svg); + qproperty-icon: url(theme:Dark/right.svg); icon-size: 16px, 16px; } diff --git a/UI/data/themes/Dark.qss b/UI/data/themes/Dark.qss index 6c96a902c..a2e262d4e 100644 --- a/UI/data/themes/Dark.qss +++ b/UI/data/themes/Dark.qss @@ -132,8 +132,8 @@ QMainWindow::separator { /* Dock Widget */ QDockWidget { - titlebar-close-icon: url('./Dark/close.svg'); - titlebar-normal-icon: url('./Dark/popout.svg'); + titlebar-close-icon: url(theme:Dark/close.svg); + titlebar-normal-icon: url(theme:Dark/popout.svg); } QDockWidget::title { @@ -242,15 +242,15 @@ QScrollBar::left-arrow:horizontal, QScrollBar::right-arrow:horizontal, QScrollBa } #contextContainer QPushButton#sourcePropertiesButton { - qproperty-icon: url(./Dark/settings/general.svg); + qproperty-icon: url(theme:Dark/settings/general.svg); } #contextContainer QPushButton#sourceFiltersButton { - qproperty-icon: url(./Dark/filter.svg); + qproperty-icon: url(theme:Dark/filter.svg); } #contextContainer QPushButton#sourceInteractButton { - qproperty-icon: url(./Dark/interact.svg); + qproperty-icon: url(theme:Dark/interact.svg); } /* Scenes and Sources toolbar */ @@ -286,51 +286,51 @@ QToolButton:pressed { } * [themeID="addIconSmall"] { - qproperty-icon: url(./Dark/plus.svg); + qproperty-icon: url(theme:Dark/plus.svg); } * [themeID="removeIconSmall"] { - qproperty-icon: url(./Dark/minus.svg); + qproperty-icon: url(theme:Dark/minus.svg); } * [themeID="clearIconSmall"] { - qproperty-icon: url(./Dark/entry-clear.svg); + qproperty-icon: url(theme:Dark/entry-clear.svg); } * [themeID="propertiesIconSmall"] { - qproperty-icon: url(./Dark/settings/general.svg); + qproperty-icon: url(theme:Dark/settings/general.svg); } * [themeID="configIconSmall"] { - qproperty-icon: url(./Dark/settings/general.svg); + qproperty-icon: url(theme:Dark/settings/general.svg); } * [themeID="refreshIconSmall"] { - qproperty-icon: url(./Dark/refresh.svg); + qproperty-icon: url(theme:Dark/refresh.svg); } * [themeID="upArrowIconSmall"] { - qproperty-icon: url(./Dark/up.svg); + qproperty-icon: url(theme:Dark/up.svg); } * [themeID="downArrowIconSmall"] { - qproperty-icon: url(./Dark/down.svg); + qproperty-icon: url(theme:Dark/down.svg); } * [themeID="pauseIconSmall"] { - qproperty-icon: url(./Dark/media-pause.svg); + qproperty-icon: url(theme:Dark/media-pause.svg); } * [themeID="menuIconSmall"] { - qproperty-icon: url(./Dark/dots-vert.svg); + qproperty-icon: url(theme:Dark/dots-vert.svg); } * [themeID="cogsIcon"] { - qproperty-icon: url(./Dark/cogs.svg); + qproperty-icon: url(theme:Dark/cogs.svg); } * [themeID="filtersIcon"] { - qproperty-icon: url(./Dark/filter.svg); + qproperty-icon: url(theme:Dark/filter.svg); } /* Tab Widget */ @@ -407,7 +407,7 @@ QComboBox::drop-down { QDateTimeEdit::down-arrow, QComboBox::down-arrow { qproperty-alignment: AlignTop; - image: url(./Dark/updown.svg); + image: url(theme:Dark/updown.svg); width: 100%; } @@ -431,7 +431,7 @@ QComboBox::drop-down:editable { QDateTimeEdit::down-arrow:editable, QComboBox::down-arrow:editable { qproperty-alignment: AlignTop; - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); width: 8%; } @@ -497,12 +497,12 @@ QDoubleSpinBox::up-button:disabled, QDoubleSpinBox::up-button:off, QDoubleSpinBo } QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { - image: url(./Dark/up.svg); + image: url(theme:Dark/up.svg); width: 100%; } QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); width: 100%; } @@ -540,7 +540,7 @@ QPushButton:disabled, QToolButton:disabled { } QPushButton::menu-indicator { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); subcontrol-position: right; subcontrol-origin: padding; width: 25px; @@ -680,15 +680,15 @@ MuteCheckBox { } MuteCheckBox::indicator:checked { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:indeterminate { - image: url(./Dark/unassigned.svg); + image: url(theme:Dark/unassigned.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } OBSHotkeyLabel[hotkeyPairHover=true] { @@ -697,22 +697,22 @@ OBSHotkeyLabel[hotkeyPairHover=true] { /* Group Collapse Checkbox */ -SourceTreeSubItemCheckBox { +QCheckBox[sourceTreeSubItem=true] { background: transparent; outline: none; } -SourceTreeSubItemCheckBox::indicator { +QCheckBox[sourceTreeSubItem=true]::indicator { width: 10px; height: 10px; } -SourceTreeSubItemCheckBox::indicator:checked { - image: url(./Dark/expand.svg); +QCheckBox[sourceTreeSubItem=true]::indicator:checked { + image: url(theme:Dark/expand.svg); } -SourceTreeSubItemCheckBox::indicator:unchecked { - image: url(./Dark/collapse.svg); +QCheckBox[sourceTreeSubItem=true]::indicator:unchecked { + image: url(theme:Dark/collapse.svg); } @@ -780,14 +780,14 @@ OBSQTDisplay { /* Settings Icons */ OBSBasicSettings { - qproperty-generalIcon: url(./Dark/settings/general.svg); - qproperty-streamIcon: url(./Dark/settings/stream.svg); - qproperty-outputIcon: url(./Dark/settings/output.svg); - qproperty-audioIcon: url(./Dark/settings/audio.svg); - qproperty-videoIcon: url(./Dark/settings/video.svg); - qproperty-hotkeysIcon: url(./Dark/settings/hotkeys.svg); - qproperty-accessibilityIcon: url(./Dark/settings/accessibility.svg); - qproperty-advancedIcon: url(./Dark/settings/advanced.svg); + qproperty-generalIcon: url(theme:Dark/settings/general.svg); + qproperty-streamIcon: url(theme:Dark/settings/stream.svg); + qproperty-outputIcon: url(theme:Dark/settings/output.svg); + qproperty-audioIcon: url(theme:Dark/settings/audio.svg); + qproperty-videoIcon: url(theme:Dark/settings/video.svg); + qproperty-hotkeysIcon: url(theme:Dark/settings/hotkeys.svg); + qproperty-accessibilityIcon: url(theme:Dark/settings/accessibility.svg); + qproperty-advancedIcon: url(theme:Dark/settings/advanced.svg); } OBSBasicSettings QListWidget::item { @@ -803,7 +803,7 @@ LockedCheckBox { } LockedCheckBox::indicator:checked { - image: url(./Dark/locked.svg); + image: url(theme:Dark/locked.svg); } LockedCheckBox::indicator:unchecked { @@ -818,7 +818,7 @@ VisibilityCheckBox { } VisibilityCheckBox::indicator:checked { - image: url(./Dark/visible.svg); + image: url(theme:Dark/visible.svg); } VisibilityCheckBox::indicator:unchecked { @@ -826,7 +826,7 @@ VisibilityCheckBox::indicator:unchecked { } * [themeID="revertIcon"] { - qproperty-icon: url(./Dark/revert.svg); + qproperty-icon: url(theme:Dark/revert.svg); } QPushButton#extraPanelDelete { @@ -842,28 +842,28 @@ QPushButton#extraPanelDelete:pressed { } OBSMissingFiles { - qproperty-warningIcon: url(./Dark/alert.svg); + qproperty-warningIcon: url(theme:Dark/alert.svg); } /* 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); - qproperty-audioProcessOutputIcon: url(./Dark/sources/windowaudio.svg); + qproperty-imageIcon: url(theme:Dark/sources/image.svg); + qproperty-colorIcon: url(theme:Dark/sources/brush.svg); + qproperty-slideshowIcon: url(theme:Dark/sources/slideshow.svg); + qproperty-audioInputIcon: url(theme:Dark/sources/microphone.svg); + qproperty-audioOutputIcon: url(theme:Dark/settings/audio.svg); + qproperty-desktopCapIcon: url(theme:Dark/settings/video.svg); + qproperty-windowCapIcon: url(theme:Dark/sources/window.svg); + qproperty-gameCapIcon: url(theme:Dark/sources/gamepad.svg); + qproperty-cameraIcon: url(theme:Dark/sources/camera.svg); + qproperty-textIcon: url(theme:Dark/sources/text.svg); + qproperty-mediaIcon: url(theme:Dark/sources/media.svg); + qproperty-browserIcon: url(theme:Dark/sources/globe.svg); + qproperty-groupIcon: url(theme:Dark/sources/group.svg); + qproperty-sceneIcon: url(theme:Dark/sources/scene.svg); + qproperty-defaultIcon: url(theme:Dark/sources/default.svg); + qproperty-audioProcessOutputIcon: url(theme:Dark/sources/windowaudio.svg); } /* Scene Tree */ @@ -903,7 +903,7 @@ SceneTree { /* Save icon */ * [themeID="replayIconSmall"] { - qproperty-icon: url(./Dark/save.svg); + qproperty-icon: url(theme:Dark/save.svg); } /* Studio Mode T-Bar */ @@ -933,32 +933,32 @@ QSlider::handle:horizontal[themeID="tBarSlider"] { /* Media icons */ * [themeID="playIcon"] { - qproperty-icon: url(./Dark/media/media_play.svg); + qproperty-icon: url(theme:Dark/media/media_play.svg); } * [themeID="pauseIcon"] { - qproperty-icon: url(./Dark/media/media_pause.svg); + qproperty-icon: url(theme:Dark/media/media_pause.svg); } * [themeID="restartIcon"] { - qproperty-icon: url(./Dark/media/media_restart.svg); + qproperty-icon: url(theme:Dark/media/media_restart.svg); } * [themeID="stopIcon"] { - qproperty-icon: url(./Dark/media/media_stop.svg); + qproperty-icon: url(theme:Dark/media/media_stop.svg); } * [themeID="nextIcon"] { - qproperty-icon: url(./Dark/media/media_next.svg); + qproperty-icon: url(theme:Dark/media/media_next.svg); } * [themeID="previousIcon"] { - qproperty-icon: url(./Dark/media/media_previous.svg); + qproperty-icon: url(theme:Dark/media/media_previous.svg); } /* YouTube Integration */ OBSYoutubeActions { - qproperty-thumbPlaceholder: url(./Dark/sources/image.svg); + qproperty-thumbPlaceholder: url(theme:Dark/sources/image.svg); } #ytEventList QLabel { @@ -981,7 +981,7 @@ OBSYoutubeActions { /* Calendar Widget */ QDateTimeEdit::down-arrow { qproperty-alignment: AlignTop; - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); width: 100%; } @@ -1004,7 +1004,7 @@ QCalendarWidget QToolButton { } #qt_calendar_monthbutton::menu-indicator { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); subcontrol-position: right; padding-top: 2px; padding-right: 6px; @@ -1014,13 +1014,13 @@ QCalendarWidget QToolButton { QCalendarWidget #qt_calendar_prevmonth { padding: 2px; - qproperty-icon: url(./Dark/left.svg); + qproperty-icon: url(theme:Dark/left.svg); icon-size: 16px, 16px; } QCalendarWidget #qt_calendar_nextmonth { padding: 2px; - qproperty-icon: url(./Dark/right.svg); + qproperty-icon: url(theme:Dark/right.svg); icon-size: 16px, 16px; } diff --git a/UI/data/themes/Grey.qss b/UI/data/themes/Grey.qss index 0748deffa..b19434bfd 100644 --- a/UI/data/themes/Grey.qss +++ b/UI/data/themes/Grey.qss @@ -166,7 +166,7 @@ QMenu::item:disabled { } QMenu::right-arrow { - image: url(./Dark/expand.svg); + image: url(theme:Dark/expand.svg); } /* Top Menu Bar Items */ @@ -304,8 +304,8 @@ QDockWidget { font-size: 10.5pt; font-weight: bold; - titlebar-close-icon: url('./Dark/close.svg'); - titlebar-normal-icon: url('./Dark/popout.svg'); + titlebar-close-icon: url(theme:Dark/close.svg); + titlebar-normal-icon: url(theme:Dark/popout.svg); } QDockWidget::title { @@ -453,11 +453,11 @@ QScrollBar::handle:horizontal { } QPushButton#sourcePropertiesButton { - qproperty-icon: url(./Dark/settings/general.svg); + qproperty-icon: url(theme:Dark/settings/general.svg); } QPushButton#sourceFiltersButton { - qproperty-icon: url(./Dark/filter.svg); + qproperty-icon: url(theme:Dark/filter.svg); } /* Scenes and Sources toolbar */ @@ -491,55 +491,55 @@ QToolButton:pressed { } * [themeID="addIconSmall"] { - qproperty-icon: url(./Dark/plus.svg); + qproperty-icon: url(theme:Dark/plus.svg); } * [themeID="removeIconSmall"] { - qproperty-icon: url(./Dark/trash.svg); + qproperty-icon: url(theme:Dark/trash.svg); } * [themeID="clearIconSmall"] { - qproperty-icon: url(./Dark/entry-clear.svg); + qproperty-icon: url(theme:Dark/entry-clear.svg); } * [themeID="propertiesIconSmall"] { - qproperty-icon: url(./Dark/settings/general.svg); + qproperty-icon: url(theme:Dark/settings/general.svg); } * [themeID="configIconSmall"] { - qproperty-icon: url(./Dark/settings/general.svg); + qproperty-icon: url(theme:Dark/settings/general.svg); } * [themeID="menuIconSmall"] { - qproperty-icon: url(./Dark/dots-vert.svg); + qproperty-icon: url(theme:Dark/dots-vert.svg); } * [themeID="refreshIconSmall"] { - qproperty-icon: url(./Dark/refresh.svg); + qproperty-icon: url(theme:Dark/refresh.svg); } * [themeID="cogsIcon"] { - qproperty-icon: url(./Dark/cogs.svg); + qproperty-icon: url(theme:Dark/cogs.svg); } #sourceInteractButton { - qproperty-icon: url(./Dark/interact.svg); + qproperty-icon: url(theme:Dark/interact.svg); } * [themeID="upArrowIconSmall"] { - qproperty-icon: url(./Dark/up.svg); + qproperty-icon: url(theme:Dark/up.svg); } * [themeID="downArrowIconSmall"] { - qproperty-icon: url(./Dark/down.svg); + qproperty-icon: url(theme:Dark/down.svg); } * [themeID="pauseIconSmall"] { - qproperty-icon: url(./Dark/media-pause.svg); + qproperty-icon: url(theme:Dark/media-pause.svg); } * [themeID="filtersIcon"] { - qproperty-icon: url(./Dark/filter.svg); + qproperty-icon: url(theme:Dark/filter.svg); } QToolBarExtension { @@ -549,7 +549,7 @@ QToolBarExtension { padding: 4px 0px; margin-left: 0px; - qproperty-icon: url(./Dark/dots-vert.svg); + qproperty-icon: url(theme:Dark/dots-vert.svg); } @@ -645,7 +645,7 @@ QDateTimeEdit::drop-down { QComboBox::down-arrow, QDateTimeEdit::down-arrow { qproperty-alignment: AlignTop; - image: url(./Dark/updown.svg); + image: url(theme:Dark/updown.svg); width: 100%; } @@ -667,7 +667,7 @@ QDateTimeEdit::drop-down:editable { QComboBox::down-arrow:editable, QDateTimeEdit::down-arrow:editable { qproperty-alignment: AlignTop; - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); width: 8%; } @@ -755,13 +755,13 @@ QDoubleSpinBox::up-button:disabled, QDoubleSpinBox::up-button:off, QDoubleSpinBo } QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { - image: url(./Dark/up.svg); + image: url(theme:Dark/up.svg); width: 100%; margin: 2px; } QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); width: 100%; padding: 2px; } @@ -833,7 +833,7 @@ QPushButton:disabled, QToolButton:disabled { } QPushButton::menu-indicator { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); subcontrol-position: right; subcontrol-origin: padding; width: 25px; @@ -983,15 +983,15 @@ QHeaderView::section { /* Mute CheckBox */ MuteCheckBox::indicator:checked { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:indeterminate { - image: url(./Dark/unassigned.svg); + image: url(theme:Dark/unassigned.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } OBSHotkeyLabel[hotkeyPairHover=true] { @@ -1090,14 +1090,14 @@ OBSBasicFilters #widget_2 QPushButton { /* Settings Icons */ OBSBasicSettings { - qproperty-generalIcon: url(./Dark/settings/general.svg); - qproperty-streamIcon: url(./Dark/settings/stream.svg); - qproperty-outputIcon: url(./Dark/settings/output.svg); - qproperty-audioIcon: url(./Dark/settings/audio.svg); - qproperty-videoIcon: url(./Dark/settings/video.svg); - qproperty-hotkeysIcon: url(./Dark/settings/hotkeys.svg); - qproperty-accessibilityIcon: url(./Dark/settings/accessibility.svg); - qproperty-advancedIcon: url(./Dark/settings/advanced.svg); + qproperty-generalIcon: url(theme:Dark/settings/general.svg); + qproperty-streamIcon: url(theme:Dark/settings/stream.svg); + qproperty-outputIcon: url(theme:Dark/settings/output.svg); + qproperty-audioIcon: url(theme:Dark/settings/audio.svg); + qproperty-videoIcon: url(theme:Dark/settings/video.svg); + qproperty-hotkeysIcon: url(theme:Dark/settings/hotkeys.svg); + qproperty-accessibilityIcon: url(theme:Dark/settings/accessibility.svg); + qproperty-advancedIcon: url(theme:Dark/settings/advanced.svg); } /* Checkboxes */ @@ -1117,34 +1117,34 @@ QGroupBox::indicator { QCheckBox::indicator:unchecked, QGroupBox::indicator:unchecked { - image: url(./Yami/checkbox_unchecked.svg); + image: url(theme:Yami/checkbox_unchecked.svg); } QCheckBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:hover { border: none; - image: url(./Yami/checkbox_unchecked_focus.svg); + image: url(theme:Yami/checkbox_unchecked_focus.svg); } QCheckBox::indicator:checked, QGroupBox::indicator:checked { - image: url(./Yami/checkbox_checked.svg); + image: url(theme:Yami/checkbox_checked.svg); } QCheckBox::indicator:checked:hover, QGroupBox::indicator:checked:hover { border: none; - image: url(./Yami/checkbox_checked_focus.svg); + image: url(theme:Yami/checkbox_checked_focus.svg); } QCheckBox::indicator:checked:disabled, QGroupBox::indicator:checked:disabled { - image: url(./Yami/checkbox_checked_disabled.svg); + image: url(theme:Yami/checkbox_checked_disabled.svg); } QCheckBox::indicator:unchecked:disabled, QGroupBox::indicator:unchecked:disabled { - image: url(./Yami/checkbox_unchecked_disabled.svg); + image: url(theme:Yami/checkbox_unchecked_disabled.svg); } /* Locked CheckBox */ @@ -1161,7 +1161,7 @@ LockedCheckBox::indicator { LockedCheckBox::indicator:checked, LockedCheckBox::indicator:checked:hover { - image: url(./Dark/locked.svg); + image: url(theme:Dark/locked.svg); } LockedCheckBox::indicator:unchecked, @@ -1183,7 +1183,7 @@ VisibilityCheckBox::indicator { VisibilityCheckBox::indicator:checked, VisibilityCheckBox::indicator:checked:hover { - image: url(./Dark/visible.svg); + image: url(theme:Dark/visible.svg); } VisibilityCheckBox::indicator:unchecked, @@ -1192,7 +1192,7 @@ VisibilityCheckBox::indicator:unchecked:hover { } * [themeID="revertIcon"] { - qproperty-icon: url(./Dark/revert.svg); + qproperty-icon: url(theme:Dark/revert.svg); } QPushButton#extraPanelDelete { @@ -1221,35 +1221,35 @@ MuteCheckBox::indicator { } MuteCheckBox::indicator:checked { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:hover { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:focus { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } MuteCheckBox::indicator:checked:hover { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:checked:focus { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:checked:disabled { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:unchecked:disabled { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } #hotkeyFilterReset { @@ -1279,46 +1279,46 @@ OBSHotkeyWidget QPushButton { /* Sources List Group Collapse Checkbox */ -SourceTreeSubItemCheckBox { +QCheckBox[sourceTreeSubItem=true] { background: transparent; outline: none; padding: 0px; } -SourceTreeSubItemCheckBox::indicator { +QCheckBox[sourceTreeSubItem=true]::indicator { width: 12px; height: 12px; } -SourceTreeSubItemCheckBox::indicator:checked, -SourceTreeSubItemCheckBox::indicator:checked:hover { - image: url(./Dark/expand.svg); +QCheckBox[sourceTreeSubItem=true]::indicator:checked, +QCheckBox[sourceTreeSubItem=true]::indicator:checked:hover { + image: url(theme:Dark/expand.svg); } -SourceTreeSubItemCheckBox::indicator:unchecked, -SourceTreeSubItemCheckBox::indicator:unchecked:hover { - image: url(./Dark/collapse.svg); +QCheckBox[sourceTreeSubItem=true]::indicator:unchecked, +QCheckBox[sourceTreeSubItem=true]::indicator:unchecked:hover { + image: url(theme:Dark/collapse.svg); } /* 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); - qproperty-audioProcessOutputIcon: url(./Dark/sources/windowaudio.svg); + qproperty-imageIcon: url(theme:Dark/sources/image.svg); + qproperty-colorIcon: url(theme:Dark/sources/brush.svg); + qproperty-slideshowIcon: url(theme:Dark/sources/slideshow.svg); + qproperty-audioInputIcon: url(theme:Dark/sources/microphone.svg); + qproperty-audioOutputIcon: url(theme:Dark/settings/audio.svg); + qproperty-desktopCapIcon: url(theme:Dark/settings/video.svg); + qproperty-windowCapIcon: url(theme:Dark/sources/window.svg); + qproperty-gameCapIcon: url(theme:Dark/sources/gamepad.svg); + qproperty-cameraIcon: url(theme:Dark/sources/camera.svg); + qproperty-textIcon: url(theme:Dark/sources/text.svg); + qproperty-mediaIcon: url(theme:Dark/sources/media.svg); + qproperty-browserIcon: url(theme:Dark/sources/globe.svg); + qproperty-groupIcon: url(theme:Dark/sources/group.svg); + qproperty-sceneIcon: url(theme:Dark/sources/scene.svg); + qproperty-defaultIcon: url(theme:Dark/sources/default.svg); + qproperty-audioProcessOutputIcon: url(theme:Dark/sources/windowaudio.svg); } /* Scene Tree Grid Mode */ @@ -1354,7 +1354,7 @@ SceneTree { /* Save icon */ * [themeID="replayIconSmall"] { - qproperty-icon: url(./Dark/save.svg); + qproperty-icon: url(theme:Dark/save.svg); } /* Studio Mode T-Bar */ @@ -1384,32 +1384,32 @@ QSlider::handle:horizontal[themeID="tBarSlider"] { /* Media icons */ * [themeID="playIcon"] { - qproperty-icon: url(./Dark/media/media_play.svg); + qproperty-icon: url(theme:Dark/media/media_play.svg); } * [themeID="pauseIcon"] { - qproperty-icon: url(./Dark/media/media_pause.svg); + qproperty-icon: url(theme:Dark/media/media_pause.svg); } * [themeID="restartIcon"] { - qproperty-icon: url(./Dark/media/media_restart.svg); + qproperty-icon: url(theme:Dark/media/media_restart.svg); } * [themeID="stopIcon"] { - qproperty-icon: url(./Dark/media/media_stop.svg); + qproperty-icon: url(theme:Dark/media/media_stop.svg); } * [themeID="nextIcon"] { - qproperty-icon: url(./Dark/media/media_next.svg); + qproperty-icon: url(theme:Dark/media/media_next.svg); } * [themeID="previousIcon"] { - qproperty-icon: url(./Dark/media/media_previous.svg); + qproperty-icon: url(theme:Dark/media/media_previous.svg); } /* YouTube Integration */ OBSYoutubeActions { - qproperty-thumbPlaceholder: url(./Dark/sources/image.svg); + qproperty-thumbPlaceholder: url(theme:Dark/sources/image.svg); } #ytEventList QLabel { @@ -1437,7 +1437,7 @@ OBSYoutubeActions { /* Calendar Widget */ QDateTimeEdit::down-arrow { qproperty-alignment: AlignTop; - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); width: 100%; } @@ -1460,7 +1460,7 @@ QCalendarWidget QToolButton { } #qt_calendar_monthbutton::menu-indicator { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); subcontrol-position: right; padding-top: 2px; padding-right: 6px; @@ -1470,13 +1470,13 @@ QCalendarWidget QToolButton { QCalendarWidget #qt_calendar_prevmonth { padding: 2px; - qproperty-icon: url(./Dark/left.svg); + qproperty-icon: url(theme:Dark/left.svg); icon-size: 16px, 16px; } QCalendarWidget #qt_calendar_nextmonth { padding: 2px; - qproperty-icon: url(./Dark/right.svg); + qproperty-icon: url(theme:Dark/right.svg); icon-size: 16px, 16px; } diff --git a/UI/data/themes/Light.qss b/UI/data/themes/Light.qss index e6c9a6be0..87795ed52 100644 --- a/UI/data/themes/Light.qss +++ b/UI/data/themes/Light.qss @@ -166,7 +166,7 @@ QMenu::item:disabled { } QMenu::right-arrow { - image: url(./Light/expand.svg); + image: url(theme:Light/expand.svg); } /* Top Menu Bar Items */ @@ -304,8 +304,8 @@ QDockWidget { font-size: 10.5pt; font-weight: bold; - titlebar-close-icon: url('./Light/close.svg'); - titlebar-normal-icon: url('./Light/popout.svg'); + titlebar-close-icon: url(theme:Light/close.svg); + titlebar-normal-icon: url(theme:Light/popout.svg); } QDockWidget::title { @@ -453,11 +453,11 @@ QScrollBar::handle:horizontal { } QPushButton#sourcePropertiesButton { - qproperty-icon: url(./Light/settings/general.svg); + qproperty-icon: url(theme:Light/settings/general.svg); } QPushButton#sourceFiltersButton { - qproperty-icon: url(./Light/filter.svg); + qproperty-icon: url(theme:Light/filter.svg); } /* Scenes and Sources toolbar */ @@ -491,55 +491,55 @@ QToolButton:pressed { } * [themeID="addIconSmall"] { - qproperty-icon: url(./Light/plus.svg); + qproperty-icon: url(theme:Light/plus.svg); } * [themeID="removeIconSmall"] { - qproperty-icon: url(./Light/trash.svg); + qproperty-icon: url(theme:Light/trash.svg); } * [themeID="clearIconSmall"] { - qproperty-icon: url(./Light/entry-clear.svg); + qproperty-icon: url(theme:Light/entry-clear.svg); } * [themeID="propertiesIconSmall"] { - qproperty-icon: url(./Light/settings/general.svg); + qproperty-icon: url(theme:Light/settings/general.svg); } * [themeID="configIconSmall"] { - qproperty-icon: url(./Light/settings/general.svg); + qproperty-icon: url(theme:Light/settings/general.svg); } * [themeID="menuIconSmall"] { - qproperty-icon: url(./Light/dots-vert.svg); + qproperty-icon: url(theme:Light/dots-vert.svg); } * [themeID="refreshIconSmall"] { - qproperty-icon: url(./Light/refresh.svg); + qproperty-icon: url(theme:Light/refresh.svg); } * [themeID="cogsIcon"] { - qproperty-icon: url(./Light/cogs.svg); + qproperty-icon: url(theme:Light/cogs.svg); } #sourceInteractButton { - qproperty-icon: url(./Light/interact.svg); + qproperty-icon: url(theme:Light/interact.svg); } * [themeID="upArrowIconSmall"] { - qproperty-icon: url(./Light/up.svg); + qproperty-icon: url(theme:Light/up.svg); } * [themeID="downArrowIconSmall"] { - qproperty-icon: url(./Light/down.svg); + qproperty-icon: url(theme:Light/down.svg); } * [themeID="pauseIconSmall"] { - qproperty-icon: url(./Light/media-pause.svg); + qproperty-icon: url(theme:Light/media-pause.svg); } * [themeID="filtersIcon"] { - qproperty-icon: url(./Light/filter.svg); + qproperty-icon: url(theme:Light/filter.svg); } QToolBarExtension { @@ -549,7 +549,7 @@ QToolBarExtension { padding: 4px 0px; margin-left: 0px; - qproperty-icon: url(./Light/dots-vert.svg); + qproperty-icon: url(theme:Light/dots-vert.svg); } @@ -645,7 +645,7 @@ QDateTimeEdit::drop-down { QComboBox::down-arrow, QDateTimeEdit::down-arrow { qproperty-alignment: AlignTop; - image: url(./Light/updown.svg); + image: url(theme:Light/updown.svg); width: 100%; } @@ -667,7 +667,7 @@ QDateTimeEdit::drop-down:editable { QComboBox::down-arrow:editable, QDateTimeEdit::down-arrow:editable { qproperty-alignment: AlignTop; - image: url(./Light/down.svg); + image: url(theme:Light/down.svg); width: 8%; } @@ -755,13 +755,13 @@ QDoubleSpinBox::up-button:disabled, QDoubleSpinBox::up-button:off, QDoubleSpinBo } QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { - image: url(./Light/up.svg); + image: url(theme:Light/up.svg); width: 100%; margin: 2px; } QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { - image: url(./Light/down.svg); + image: url(theme:Light/down.svg); width: 100%; padding: 2px; } @@ -833,7 +833,7 @@ QPushButton:disabled, QToolButton:disabled { } QPushButton::menu-indicator { - image: url(./Light/down.svg); + image: url(theme:Light/down.svg); subcontrol-position: right; subcontrol-origin: padding; width: 25px; @@ -983,15 +983,15 @@ QHeaderView::section { /* Mute CheckBox */ MuteCheckBox::indicator:checked { - image: url(./Light/mute.svg); + image: url(theme:Light/mute.svg); } MuteCheckBox::indicator:indeterminate { - image: url(./Dark/unassigned.svg); + image: url(theme:Dark/unassigned.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Light/settings/audio.svg); + image: url(theme:Light/settings/audio.svg); } OBSHotkeyLabel[hotkeyPairHover=true] { @@ -1090,14 +1090,14 @@ OBSBasicFilters #widget_2 QPushButton { /* Settings Icons */ OBSBasicSettings { - qproperty-generalIcon: url(./Light/settings/general.svg); - qproperty-streamIcon: url(./Light/settings/stream.svg); - qproperty-outputIcon: url(./Light/settings/output.svg); - qproperty-audioIcon: url(./Light/settings/audio.svg); - qproperty-videoIcon: url(./Light/settings/video.svg); - qproperty-hotkeysIcon: url(./Light/settings/hotkeys.svg); - qproperty-accessibilityIcon: url(./Light/settings/accessibility.svg); - qproperty-advancedIcon: url(./Light/settings/advanced.svg); + qproperty-generalIcon: url(theme:Light/settings/general.svg); + qproperty-streamIcon: url(theme:Light/settings/stream.svg); + qproperty-outputIcon: url(theme:Light/settings/output.svg); + qproperty-audioIcon: url(theme:Light/settings/audio.svg); + qproperty-videoIcon: url(theme:Light/settings/video.svg); + qproperty-hotkeysIcon: url(theme:Light/settings/hotkeys.svg); + qproperty-accessibilityIcon: url(theme:Light/settings/accessibility.svg); + qproperty-advancedIcon: url(theme:Light/settings/advanced.svg); } /* Checkboxes */ @@ -1117,34 +1117,34 @@ QGroupBox::indicator { QCheckBox::indicator:unchecked, QGroupBox::indicator:unchecked { - image: url(./Light/checkbox_unchecked.svg); + image: url(theme:Light/checkbox_unchecked.svg); } QCheckBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:hover { border: none; - image: url(./Light/checkbox_unchecked_focus.svg); + image: url(theme:Light/checkbox_unchecked_focus.svg); } QCheckBox::indicator:checked, QGroupBox::indicator:checked { - image: url(./Light/checkbox_checked.svg); + image: url(theme:Light/checkbox_checked.svg); } QCheckBox::indicator:checked:hover, QGroupBox::indicator:checked:hover { border: none; - image: url(./Light/checkbox_checked_focus.svg); + image: url(theme:Light/checkbox_checked_focus.svg); } QCheckBox::indicator:checked:disabled, QGroupBox::indicator:checked:disabled { - image: url(./Light/checkbox_checked_disabled.svg); + image: url(theme:Light/checkbox_checked_disabled.svg); } QCheckBox::indicator:unchecked:disabled, QGroupBox::indicator:unchecked:disabled { - image: url(./Light/checkbox_unchecked_disabled.svg); + image: url(theme:Light/checkbox_unchecked_disabled.svg); } /* Locked CheckBox */ @@ -1161,7 +1161,7 @@ LockedCheckBox::indicator { LockedCheckBox::indicator:checked, LockedCheckBox::indicator:checked:hover { - image: url(./Light/locked.svg); + image: url(theme:Light/locked.svg); } LockedCheckBox::indicator:unchecked, @@ -1183,7 +1183,7 @@ VisibilityCheckBox::indicator { VisibilityCheckBox::indicator:checked, VisibilityCheckBox::indicator:checked:hover { - image: url(./Light/visible.svg); + image: url(theme:Light/visible.svg); } VisibilityCheckBox::indicator:unchecked, @@ -1192,7 +1192,7 @@ VisibilityCheckBox::indicator:unchecked:hover { } * [themeID="revertIcon"] { - qproperty-icon: url(./Light/revert.svg); + qproperty-icon: url(theme:Light/revert.svg); } QPushButton#extraPanelDelete { @@ -1221,35 +1221,35 @@ MuteCheckBox::indicator { } MuteCheckBox::indicator:checked { - image: url(./Light/mute.svg); + image: url(theme:Light/mute.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Light/settings/audio.svg); + image: url(theme:Light/settings/audio.svg); } MuteCheckBox::indicator:unchecked:hover { - image: url(./Light/settings/audio.svg); + image: url(theme:Light/settings/audio.svg); } MuteCheckBox::indicator:unchecked:focus { - image: url(./Light/settings/audio.svg); + image: url(theme:Light/settings/audio.svg); } MuteCheckBox::indicator:checked:hover { - image: url(./Light/mute.svg); + image: url(theme:Light/mute.svg); } MuteCheckBox::indicator:checked:focus { - image: url(./Light/mute.svg); + image: url(theme:Light/mute.svg); } MuteCheckBox::indicator:checked:disabled { - image: url(./Light/mute.svg); + image: url(theme:Light/mute.svg); } MuteCheckBox::indicator:unchecked:disabled { - image: url(./Light/settings/audio.svg); + image: url(theme:Light/settings/audio.svg); } #hotkeyFilterReset { @@ -1279,46 +1279,46 @@ OBSHotkeyWidget QPushButton { /* Sources List Group Collapse Checkbox */ -SourceTreeSubItemCheckBox { +QCheckBox[sourceTreeSubItem=true] { background: transparent; outline: none; padding: 0px; } -SourceTreeSubItemCheckBox::indicator { +QCheckBox[sourceTreeSubItem=true]::indicator { width: 12px; height: 12px; } -SourceTreeSubItemCheckBox::indicator:checked, -SourceTreeSubItemCheckBox::indicator:checked:hover { - image: url(./Light/expand.svg); +QCheckBox[sourceTreeSubItem=true]::indicator:checked, +QCheckBox[sourceTreeSubItem=true]::indicator:checked:hover { + image: url(theme:Light/expand.svg); } -SourceTreeSubItemCheckBox::indicator:unchecked, -SourceTreeSubItemCheckBox::indicator:unchecked:hover { - image: url(./Light/collapse.svg); +QCheckBox[sourceTreeSubItem=true]::indicator:unchecked, +QCheckBox[sourceTreeSubItem=true]::indicator:unchecked:hover { + image: url(theme:Light/collapse.svg); } /* Source Icons */ OBSBasic { - qproperty-imageIcon: url(./Light/sources/image.svg); - qproperty-colorIcon: url(./Light/sources/brush.svg); - qproperty-slideshowIcon: url(./Light/sources/slideshow.svg); - qproperty-audioInputIcon: url(./Light/sources/microphone.svg); - qproperty-audioOutputIcon: url(./Light/settings/audio.svg); - qproperty-desktopCapIcon: url(./Light/settings/video.svg); - qproperty-windowCapIcon: url(./Light/sources/window.svg); - qproperty-gameCapIcon: url(./Light/sources/gamepad.svg); - qproperty-cameraIcon: url(./Light/sources/camera.svg); - qproperty-textIcon: url(./Light/sources/text.svg); - qproperty-mediaIcon: url(./Light/sources/media.svg); - qproperty-browserIcon: url(./Light/sources/globe.svg); - qproperty-groupIcon: url(./Light/sources/group.svg); - qproperty-sceneIcon: url(./Light/sources/scene.svg); - qproperty-defaultIcon: url(./Light/sources/default.svg); - qproperty-audioProcessOutputIcon: url(./Light/sources/windowaudio.svg); + qproperty-imageIcon: url(theme:Light/sources/image.svg); + qproperty-colorIcon: url(theme:Light/sources/brush.svg); + qproperty-slideshowIcon: url(theme:Light/sources/slideshow.svg); + qproperty-audioInputIcon: url(theme:Light/sources/microphone.svg); + qproperty-audioOutputIcon: url(theme:Light/settings/audio.svg); + qproperty-desktopCapIcon: url(theme:Light/settings/video.svg); + qproperty-windowCapIcon: url(theme:Light/sources/window.svg); + qproperty-gameCapIcon: url(theme:Light/sources/gamepad.svg); + qproperty-cameraIcon: url(theme:Light/sources/camera.svg); + qproperty-textIcon: url(theme:Light/sources/text.svg); + qproperty-mediaIcon: url(theme:Light/sources/media.svg); + qproperty-browserIcon: url(theme:Light/sources/globe.svg); + qproperty-groupIcon: url(theme:Light/sources/group.svg); + qproperty-sceneIcon: url(theme:Light/sources/scene.svg); + qproperty-defaultIcon: url(theme:Light/sources/default.svg); + qproperty-audioProcessOutputIcon: url(theme:Light/sources/windowaudio.svg); } /* Scene Tree Grid Mode */ @@ -1354,7 +1354,7 @@ SceneTree { /* Save icon */ * [themeID="replayIconSmall"] { - qproperty-icon: url(./Light/save.svg); + qproperty-icon: url(theme:Light/save.svg); } /* Studio Mode Labels */ @@ -1390,32 +1390,32 @@ QSlider::handle:horizontal[themeID="tBarSlider"] { /* Media icons */ * [themeID="playIcon"] { - qproperty-icon: url(./Light/media/media_play.svg); + qproperty-icon: url(theme:Light/media/media_play.svg); } * [themeID="pauseIcon"] { - qproperty-icon: url(./Light/media/media_pause.svg); + qproperty-icon: url(theme:Light/media/media_pause.svg); } * [themeID="restartIcon"] { - qproperty-icon: url(./Light/media/media_restart.svg); + qproperty-icon: url(theme:Light/media/media_restart.svg); } * [themeID="stopIcon"] { - qproperty-icon: url(./Light/media/media_stop.svg); + qproperty-icon: url(theme:Light/media/media_stop.svg); } * [themeID="nextIcon"] { - qproperty-icon: url(./Light/media/media_next.svg); + qproperty-icon: url(theme:Light/media/media_next.svg); } * [themeID="previousIcon"] { - qproperty-icon: url(./Light/media/media_previous.svg); + qproperty-icon: url(theme:Light/media/media_previous.svg); } /* YouTube Integration */ OBSYoutubeActions { - qproperty-thumbPlaceholder: url(./Light/sources/image.svg); + qproperty-thumbPlaceholder: url(theme:Light/sources/image.svg); } #ytEventList QLabel { @@ -1443,7 +1443,7 @@ OBSYoutubeActions { /* Calendar Widget */ QDateTimeEdit::down-arrow { qproperty-alignment: AlignTop; - image: url(./Light/down.svg); + image: url(theme:Light/down.svg); width: 100%; } @@ -1466,7 +1466,7 @@ QCalendarWidget QToolButton { } #qt_calendar_monthbutton::menu-indicator { - image: url(./Light/down.svg); + image: url(theme:Light/down.svg); subcontrol-position: right; padding-top: 2px; padding-right: 6px; @@ -1476,13 +1476,13 @@ QCalendarWidget QToolButton { QCalendarWidget #qt_calendar_prevmonth { padding: 2px; - qproperty-icon: url(./Light/left.svg); + qproperty-icon: url(theme:Light/left.svg); icon-size: 16px, 16px; } QCalendarWidget #qt_calendar_nextmonth { padding: 2px; - qproperty-icon: url(./Light/right.svg); + qproperty-icon: url(theme:Light/right.svg); icon-size: 16px, 16px; } diff --git a/UI/data/themes/Rachni.qss b/UI/data/themes/Rachni.qss index 92880cfd0..579737ea9 100644 --- a/UI/data/themes/Rachni.qss +++ b/UI/data/themes/Rachni.qss @@ -168,7 +168,7 @@ QMenu::item:disabled { } QMenu::right-arrow { - image: url(./Dark/expand.svg); + image: url(theme:Dark/expand.svg); } /* Top Menu Bar Items */ @@ -306,8 +306,8 @@ QDockWidget { font-size: 10.5pt; font-weight: bold; - titlebar-close-icon: url('./Dark/close.svg'); - titlebar-normal-icon: url('./Dark/popout.svg'); + titlebar-close-icon: url(theme:Dark/close.svg); + titlebar-normal-icon: url(theme:Dark/popout.svg); } QDockWidget::title { @@ -456,11 +456,11 @@ QScrollBar::handle:horizontal { } QPushButton#sourcePropertiesButton { - qproperty-icon: url(./Dark/settings/general.svg); + qproperty-icon: url(theme:Dark/settings/general.svg); } QPushButton#sourceFiltersButton { - qproperty-icon: url(./Dark/filter.svg); + qproperty-icon: url(theme:Dark/filter.svg); } /* Scenes and Sources toolbar */ @@ -499,55 +499,55 @@ QToolButton:pressed { } * [themeID="addIconSmall"] { - qproperty-icon: url(./Dark/plus.svg); + qproperty-icon: url(theme:Dark/plus.svg); } * [themeID="removeIconSmall"] { - qproperty-icon: url(./Dark/trash.svg); + qproperty-icon: url(theme:Dark/trash.svg); } * [themeID="clearIconSmall"] { - qproperty-icon: url(./Dark/entry-clear.svg); + qproperty-icon: url(theme:Dark/entry-clear.svg); } * [themeID="propertiesIconSmall"] { - qproperty-icon: url(./Dark/settings/general.svg); + qproperty-icon: url(theme:Dark/settings/general.svg); } * [themeID="configIconSmall"] { - qproperty-icon: url(./Dark/settings/general.svg); + qproperty-icon: url(theme:Dark/settings/general.svg); } * [themeID="menuIconSmall"] { - qproperty-icon: url(./Dark/dots-vert.svg); + qproperty-icon: url(theme:Dark/dots-vert.svg); } * [themeID="refreshIconSmall"] { - qproperty-icon: url(./Dark/refresh.svg); + qproperty-icon: url(theme:Dark/refresh.svg); } * [themeID="cogsIcon"] { - qproperty-icon: url(./Dark/cogs.svg); + qproperty-icon: url(theme:Dark/cogs.svg); } #sourceInteractButton { - qproperty-icon: url(./Dark/interact.svg); + qproperty-icon: url(theme:Dark/interact.svg); } * [themeID="upArrowIconSmall"] { - qproperty-icon: url(./Dark/up.svg); + qproperty-icon: url(theme:Dark/up.svg); } * [themeID="downArrowIconSmall"] { - qproperty-icon: url(./Dark/down.svg); + qproperty-icon: url(theme:Dark/down.svg); } * [themeID="pauseIconSmall"] { - qproperty-icon: url(./Dark/media-pause.svg); + qproperty-icon: url(theme:Dark/media-pause.svg); } * [themeID="filtersIcon"] { - qproperty-icon: url(./Dark/filter.svg); + qproperty-icon: url(theme:Dark/filter.svg); } QToolBarExtension { @@ -557,7 +557,7 @@ QToolBarExtension { padding: 4px 0px; margin-left: 0px; - qproperty-icon: url(./Dark/dots-vert.svg); + qproperty-icon: url(theme:Dark/dots-vert.svg); } @@ -652,7 +652,7 @@ QDateTimeEdit::drop-down { QComboBox::down-arrow, QDateTimeEdit::down-arrow { qproperty-alignment: AlignTop; - image: url(./Dark/updown.svg); + image: url(theme:Dark/updown.svg); width: 100%; } @@ -674,7 +674,7 @@ QDateTimeEdit::drop-down:editable { QComboBox::down-arrow:editable, QDateTimeEdit::down-arrow:editable { qproperty-alignment: AlignTop; - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); width: 8%; } @@ -759,13 +759,13 @@ QDoubleSpinBox::up-button:disabled, QDoubleSpinBox::up-button:off, QDoubleSpinBo } QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { - image: url(./Dark/up.svg); + image: url(theme:Dark/up.svg); width: 100%; margin: 2px; } QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); width: 100%; padding: 2px; } @@ -837,7 +837,7 @@ QPushButton:disabled, QToolButton:disabled { } QPushButton::menu-indicator { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); subcontrol-position: right; subcontrol-origin: padding; width: 25px; @@ -987,15 +987,15 @@ QHeaderView::section { /* Mute CheckBox */ MuteCheckBox::indicator:checked { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:indeterminate { - image: url(./Dark/unassigned.svg); + image: url(theme:Dark/unassigned.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } OBSHotkeyLabel[hotkeyPairHover=true] { @@ -1094,14 +1094,14 @@ OBSBasicFilters #widget_2 QPushButton { /* Settings Icons */ OBSBasicSettings { - qproperty-generalIcon: url(./Dark/settings/general.svg); - qproperty-streamIcon: url(./Dark/settings/stream.svg); - qproperty-outputIcon: url(./Dark/settings/output.svg); - qproperty-audioIcon: url(./Dark/settings/audio.svg); - qproperty-videoIcon: url(./Dark/settings/video.svg); - qproperty-hotkeysIcon: url(./Dark/settings/hotkeys.svg); - qproperty-accessibilityIcon: url(./Dark/settings/accessibility.svg); - qproperty-advancedIcon: url(./Dark/settings/advanced.svg); + qproperty-generalIcon: url(theme:Dark/settings/general.svg); + qproperty-streamIcon: url(theme:Dark/settings/stream.svg); + qproperty-outputIcon: url(theme:Dark/settings/output.svg); + qproperty-audioIcon: url(theme:Dark/settings/audio.svg); + qproperty-videoIcon: url(theme:Dark/settings/video.svg); + qproperty-hotkeysIcon: url(theme:Dark/settings/hotkeys.svg); + qproperty-accessibilityIcon: url(theme:Dark/settings/accessibility.svg); + qproperty-advancedIcon: url(theme:Dark/settings/advanced.svg); } /* Checkboxes */ @@ -1121,34 +1121,34 @@ QGroupBox::indicator { QCheckBox::indicator:unchecked, QGroupBox::indicator:unchecked { - image: url(./Yami/checkbox_unchecked.svg); + image: url(theme:Yami/checkbox_unchecked.svg); } QCheckBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:hover { border: none; - image: url(./Yami/checkbox_unchecked_focus.svg); + image: url(theme:Yami/checkbox_unchecked_focus.svg); } QCheckBox::indicator:checked, QGroupBox::indicator:checked { - image: url(./Yami/checkbox_checked.svg); + image: url(theme:Yami/checkbox_checked.svg); } QCheckBox::indicator:checked:hover, QGroupBox::indicator:checked:hover { border: none; - image: url(./Yami/checkbox_checked_focus.svg); + image: url(theme:Yami/checkbox_checked_focus.svg); } QCheckBox::indicator:checked:disabled, QGroupBox::indicator:checked:disabled { - image: url(./Yami/checkbox_checked_disabled.svg); + image: url(theme:Yami/checkbox_checked_disabled.svg); } QCheckBox::indicator:unchecked:disabled, QGroupBox::indicator:unchecked:disabled { - image: url(./Yami/checkbox_unchecked_disabled.svg); + image: url(theme:Yami/checkbox_unchecked_disabled.svg); } /* Locked CheckBox */ @@ -1165,7 +1165,7 @@ LockedCheckBox::indicator { LockedCheckBox::indicator:checked, LockedCheckBox::indicator:checked:hover { - image: url(./Dark/locked.svg); + image: url(theme:Dark/locked.svg); } LockedCheckBox::indicator:unchecked, @@ -1187,7 +1187,7 @@ VisibilityCheckBox::indicator { VisibilityCheckBox::indicator:checked, VisibilityCheckBox::indicator:checked:hover { - image: url(./Dark/visible.svg); + image: url(theme:Dark/visible.svg); } VisibilityCheckBox::indicator:unchecked, @@ -1196,7 +1196,7 @@ VisibilityCheckBox::indicator:unchecked:hover { } * [themeID="revertIcon"] { - qproperty-icon: url(./Dark/revert.svg); + qproperty-icon: url(theme:Dark/revert.svg); } QPushButton#extraPanelDelete { @@ -1225,35 +1225,35 @@ MuteCheckBox::indicator { } MuteCheckBox::indicator:checked { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:hover { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:focus { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } MuteCheckBox::indicator:checked:hover { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:checked:focus { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:checked:disabled { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:unchecked:disabled { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } #hotkeyFilterReset { @@ -1283,46 +1283,46 @@ OBSHotkeyWidget QPushButton { /* Sources List Group Collapse Checkbox */ -SourceTreeSubItemCheckBox { +QCheckBox[sourceTreeSubItem=true] { background: transparent; outline: none; padding: 0px; } -SourceTreeSubItemCheckBox::indicator { +QCheckBox[sourceTreeSubItem=true]::indicator { width: 12px; height: 12px; } -SourceTreeSubItemCheckBox::indicator:checked, -SourceTreeSubItemCheckBox::indicator:checked:hover { - image: url(./Dark/expand.svg); +QCheckBox[sourceTreeSubItem=true]::indicator:checked, +QCheckBox[sourceTreeSubItem=true]::indicator:checked:hover { + image: url(theme:Dark/expand.svg); } -SourceTreeSubItemCheckBox::indicator:unchecked, -SourceTreeSubItemCheckBox::indicator:unchecked:hover { - image: url(./Dark/collapse.svg); +QCheckBox[sourceTreeSubItem=true]::indicator:unchecked, +QCheckBox[sourceTreeSubItem=true]::indicator:unchecked:hover { + image: url(theme:Dark/collapse.svg); } /* 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); - qproperty-audioProcessOutputIcon: url(./Dark/sources/windowaudio.svg); + qproperty-imageIcon: url(theme:Dark/sources/image.svg); + qproperty-colorIcon: url(theme:Dark/sources/brush.svg); + qproperty-slideshowIcon: url(theme:Dark/sources/slideshow.svg); + qproperty-audioInputIcon: url(theme:Dark/sources/microphone.svg); + qproperty-audioOutputIcon: url(theme:Dark/settings/audio.svg); + qproperty-desktopCapIcon: url(theme:Dark/settings/video.svg); + qproperty-windowCapIcon: url(theme:Dark/sources/window.svg); + qproperty-gameCapIcon: url(theme:Dark/sources/gamepad.svg); + qproperty-cameraIcon: url(theme:Dark/sources/camera.svg); + qproperty-textIcon: url(theme:Dark/sources/text.svg); + qproperty-mediaIcon: url(theme:Dark/sources/media.svg); + qproperty-browserIcon: url(theme:Dark/sources/globe.svg); + qproperty-groupIcon: url(theme:Dark/sources/group.svg); + qproperty-sceneIcon: url(theme:Dark/sources/scene.svg); + qproperty-defaultIcon: url(theme:Dark/sources/default.svg); + qproperty-audioProcessOutputIcon: url(theme:Dark/sources/windowaudio.svg); } /* Scene Tree Grid Mode */ @@ -1358,7 +1358,7 @@ SceneTree { /* Save icon */ * [themeID="replayIconSmall"] { - qproperty-icon: url(./Dark/save.svg); + qproperty-icon: url(theme:Dark/save.svg); } /* Studio Mode T-Bar */ @@ -1388,32 +1388,32 @@ QSlider::handle:horizontal[themeID="tBarSlider"] { /* Media icons */ * [themeID="playIcon"] { - qproperty-icon: url(./Dark/media/media_play.svg); + qproperty-icon: url(theme:Dark/media/media_play.svg); } * [themeID="pauseIcon"] { - qproperty-icon: url(./Dark/media/media_pause.svg); + qproperty-icon: url(theme:Dark/media/media_pause.svg); } * [themeID="restartIcon"] { - qproperty-icon: url(./Dark/media/media_restart.svg); + qproperty-icon: url(theme:Dark/media/media_restart.svg); } * [themeID="stopIcon"] { - qproperty-icon: url(./Dark/media/media_stop.svg); + qproperty-icon: url(theme:Dark/media/media_stop.svg); } * [themeID="nextIcon"] { - qproperty-icon: url(./Dark/media/media_next.svg); + qproperty-icon: url(theme:Dark/media/media_next.svg); } * [themeID="previousIcon"] { - qproperty-icon: url(./Dark/media/media_previous.svg); + qproperty-icon: url(theme:Dark/media/media_previous.svg); } /* YouTube Integration */ OBSYoutubeActions { - qproperty-thumbPlaceholder: url(./Dark/sources/image.svg); + qproperty-thumbPlaceholder: url(theme:Dark/sources/image.svg); } #ytEventList QLabel { @@ -1441,7 +1441,7 @@ OBSYoutubeActions { /* Calendar Widget */ QDateTimeEdit::down-arrow { qproperty-alignment: AlignTop; - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); width: 100%; } @@ -1464,7 +1464,7 @@ QCalendarWidget QToolButton { } #qt_calendar_monthbutton::menu-indicator { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); subcontrol-position: right; padding-top: 2px; padding-right: 6px; @@ -1474,13 +1474,13 @@ QCalendarWidget QToolButton { QCalendarWidget #qt_calendar_prevmonth { padding: 2px; - qproperty-icon: url(./Dark/left.svg); + qproperty-icon: url(theme:Dark/left.svg); icon-size: 16px, 16px; } QCalendarWidget #qt_calendar_nextmonth { padding: 2px; - qproperty-icon: url(./Dark/right.svg); + qproperty-icon: url(theme:Dark/right.svg); icon-size: 16px, 16px; } diff --git a/UI/data/themes/System.qss b/UI/data/themes/System.qss index 94c446673..a2476d367 100644 --- a/UI/data/themes/System.qss +++ b/UI/data/themes/System.qss @@ -71,28 +71,28 @@ MuteCheckBox::indicator:checked { } MuteCheckBox::indicator:indeterminate { - image: url(./Dark/unassigned.svg); + image: url(theme:Dark/unassigned.svg); } MuteCheckBox::indicator:unchecked { image: url(:/settings/images/settings/audio.svg); } -SourceTreeSubItemCheckBox { +QCheckBox[sourceTreeSubItem=true] { background: transparent; outline: none; } -SourceTreeSubItemCheckBox::indicator { +QCheckBox[sourceTreeSubItem=true]::indicator { width: 10px; height: 10px; } -SourceTreeSubItemCheckBox::indicator:checked { +QCheckBox[sourceTreeSubItem=true]::indicator:checked { image: url(:/res/images/expand.svg); } -SourceTreeSubItemCheckBox::indicator:unchecked { +QCheckBox[sourceTreeSubItem=true]::indicator:unchecked { image: url(:/res/images/collapse.svg); } @@ -378,7 +378,7 @@ QCalendarWidget QToolButton { } #qt_calendar_monthbutton::menu-indicator { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); subcontrol-position: right; padding-top: 2px; padding-right: 2px; @@ -393,13 +393,13 @@ QCalendarWidget QToolButton { QCalendarWidget #qt_calendar_prevmonth { padding: 2px; - qproperty-icon: url(./Dark/left.svg); + qproperty-icon: url(theme:Dark/left.svg); icon-size: 16px, 16px; } QCalendarWidget #qt_calendar_nextmonth { padding: 2px; - qproperty-icon: url(./Dark/right.svg); + qproperty-icon: url(theme:Dark/right.svg); icon-size: 16px, 16px; } diff --git a/UI/data/themes/Yami.qss b/UI/data/themes/Yami.qss index b32a7b47d..819b507ec 100644 --- a/UI/data/themes/Yami.qss +++ b/UI/data/themes/Yami.qss @@ -166,7 +166,7 @@ QMenu::item:disabled { } QMenu::right-arrow { - image: url(./Dark/expand.svg); + image: url(theme:Dark/expand.svg); } /* Top Menu Bar Items */ @@ -308,8 +308,8 @@ QDockWidget { font-size: 10.5pt; font-weight: bold; - titlebar-close-icon: url('./Dark/close.svg'); - titlebar-normal-icon: url('./Dark/popout.svg'); + titlebar-close-icon: url(theme:Dark/close.svg); + titlebar-normal-icon: url(theme:Dark/popout.svg); } QDockWidget::title { @@ -457,11 +457,11 @@ QScrollBar::handle:horizontal { } QPushButton#sourcePropertiesButton { - qproperty-icon: url(./Dark/settings/general.svg); + qproperty-icon: url(theme:Dark/settings/general.svg); } QPushButton#sourceFiltersButton { - qproperty-icon: url(./Dark/filter.svg); + qproperty-icon: url(theme:Dark/filter.svg); } /* Scenes and Sources toolbar */ @@ -495,55 +495,55 @@ QToolButton:pressed { } * [themeID="addIconSmall"] { - qproperty-icon: url(./Dark/plus.svg); + qproperty-icon: url(theme:Dark/plus.svg); } * [themeID="removeIconSmall"] { - qproperty-icon: url(./Dark/trash.svg); + qproperty-icon: url(theme:Dark/trash.svg); } * [themeID="clearIconSmall"] { - qproperty-icon: url(./Dark/entry-clear.svg); + qproperty-icon: url(theme:Dark/entry-clear.svg); } * [themeID="propertiesIconSmall"] { - qproperty-icon: url(./Dark/settings/general.svg); + qproperty-icon: url(theme:Dark/settings/general.svg); } * [themeID="configIconSmall"] { - qproperty-icon: url(./Dark/settings/general.svg); + qproperty-icon: url(theme:Dark/settings/general.svg); } * [themeID="menuIconSmall"] { - qproperty-icon: url(./Dark/dots-vert.svg); + qproperty-icon: url(theme:Dark/dots-vert.svg); } * [themeID="refreshIconSmall"] { - qproperty-icon: url(./Dark/refresh.svg); + qproperty-icon: url(theme:Dark/refresh.svg); } * [themeID="cogsIcon"] { - qproperty-icon: url(./Dark/cogs.svg); + qproperty-icon: url(theme:Dark/cogs.svg); } #sourceInteractButton { - qproperty-icon: url(./Dark/interact.svg); + qproperty-icon: url(theme:Dark/interact.svg); } * [themeID="upArrowIconSmall"] { - qproperty-icon: url(./Dark/up.svg); + qproperty-icon: url(theme:Dark/up.svg); } * [themeID="downArrowIconSmall"] { - qproperty-icon: url(./Dark/down.svg); + qproperty-icon: url(theme:Dark/down.svg); } * [themeID="pauseIconSmall"] { - qproperty-icon: url(./Dark/media-pause.svg); + qproperty-icon: url(theme:Dark/media-pause.svg); } * [themeID="filtersIcon"] { - qproperty-icon: url(./Dark/filter.svg); + qproperty-icon: url(theme:Dark/filter.svg); } QToolBarExtension { @@ -553,7 +553,7 @@ QToolBarExtension { padding: 4px 0px; margin-left: 0px; - qproperty-icon: url(./Dark/dots-vert.svg); + qproperty-icon: url(theme:Dark/dots-vert.svg); } @@ -649,7 +649,7 @@ QDateTimeEdit::drop-down { QComboBox::down-arrow, QDateTimeEdit::down-arrow { qproperty-alignment: AlignTop; - image: url(./Dark/updown.svg); + image: url(theme:Dark/updown.svg); width: 100%; } @@ -671,7 +671,7 @@ QDateTimeEdit::drop-down:editable { QComboBox::down-arrow:editable, QDateTimeEdit::down-arrow:editable { qproperty-alignment: AlignTop; - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); width: 8%; } @@ -759,13 +759,13 @@ QDoubleSpinBox::up-button:disabled, QDoubleSpinBox::up-button:off, QDoubleSpinBo } QSpinBox::up-arrow, QDoubleSpinBox::up-arrow { - image: url(./Dark/up.svg); + image: url(theme:Dark/up.svg); width: 100%; margin: 2px; } QSpinBox::down-arrow, QDoubleSpinBox::down-arrow { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); width: 100%; padding: 2px; } @@ -837,7 +837,7 @@ QPushButton:disabled, QToolButton:disabled { } QPushButton::menu-indicator { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); subcontrol-position: right; subcontrol-origin: padding; width: 25px; @@ -987,15 +987,15 @@ QHeaderView::section { /* Mute CheckBox */ MuteCheckBox::indicator:checked { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:indeterminate { - image: url(./Dark/unassigned.svg); + image: url(theme:Dark/unassigned.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } OBSHotkeyLabel[hotkeyPairHover=true] { @@ -1094,14 +1094,14 @@ OBSBasicFilters #widget_2 QPushButton { /* Settings Icons */ OBSBasicSettings { - qproperty-generalIcon: url(./Dark/settings/general.svg); - qproperty-streamIcon: url(./Dark/settings/stream.svg); - qproperty-outputIcon: url(./Dark/settings/output.svg); - qproperty-audioIcon: url(./Dark/settings/audio.svg); - qproperty-videoIcon: url(./Dark/settings/video.svg); - qproperty-hotkeysIcon: url(./Dark/settings/hotkeys.svg); - qproperty-accessibilityIcon: url(./Dark/settings/accessibility.svg); - qproperty-advancedIcon: url(./Dark/settings/advanced.svg); + qproperty-generalIcon: url(theme:Dark/settings/general.svg); + qproperty-streamIcon: url(theme:Dark/settings/stream.svg); + qproperty-outputIcon: url(theme:Dark/settings/output.svg); + qproperty-audioIcon: url(theme:Dark/settings/audio.svg); + qproperty-videoIcon: url(theme:Dark/settings/video.svg); + qproperty-hotkeysIcon: url(theme:Dark/settings/hotkeys.svg); + qproperty-accessibilityIcon: url(theme:Dark/settings/accessibility.svg); + qproperty-advancedIcon: url(theme:Dark/settings/advanced.svg); } /* Checkboxes */ @@ -1121,34 +1121,34 @@ QGroupBox::indicator { QCheckBox::indicator:unchecked, QGroupBox::indicator:unchecked { - image: url(./Yami/checkbox_unchecked.svg); + image: url(theme:Yami/checkbox_unchecked.svg); } QCheckBox::indicator:unchecked:hover, QGroupBox::indicator:unchecked:hover { border: none; - image: url(./Yami/checkbox_unchecked_focus.svg); + image: url(theme:Yami/checkbox_unchecked_focus.svg); } QCheckBox::indicator:checked, QGroupBox::indicator:checked { - image: url(./Yami/checkbox_checked.svg); + image: url(theme:Yami/checkbox_checked.svg); } QCheckBox::indicator:checked:hover, QGroupBox::indicator:checked:hover { border: none; - image: url(./Yami/checkbox_checked_focus.svg); + image: url(theme:Yami/checkbox_checked_focus.svg); } QCheckBox::indicator:checked:disabled, QGroupBox::indicator:checked:disabled { - image: url(./Yami/checkbox_checked_disabled.svg); + image: url(theme:Yami/checkbox_checked_disabled.svg); } QCheckBox::indicator:unchecked:disabled, QGroupBox::indicator:unchecked:disabled { - image: url(./Yami/checkbox_unchecked_disabled.svg); + image: url(theme:Yami/checkbox_unchecked_disabled.svg); } /* Locked CheckBox */ @@ -1165,7 +1165,7 @@ LockedCheckBox::indicator { LockedCheckBox::indicator:checked, LockedCheckBox::indicator:checked:hover { - image: url(./Dark/locked.svg); + image: url(theme:Dark/locked.svg); } LockedCheckBox::indicator:unchecked, @@ -1187,7 +1187,7 @@ VisibilityCheckBox::indicator { VisibilityCheckBox::indicator:checked, VisibilityCheckBox::indicator:checked:hover { - image: url(./Dark/visible.svg); + image: url(theme:Dark/visible.svg); } VisibilityCheckBox::indicator:unchecked, @@ -1196,7 +1196,7 @@ VisibilityCheckBox::indicator:unchecked:hover { } * [themeID="revertIcon"] { - qproperty-icon: url(./Dark/revert.svg); + qproperty-icon: url(theme:Dark/revert.svg); } QPushButton#extraPanelDelete { @@ -1225,35 +1225,35 @@ MuteCheckBox::indicator { } MuteCheckBox::indicator:checked { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:unchecked { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:hover { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } MuteCheckBox::indicator:unchecked:focus { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } MuteCheckBox::indicator:checked:hover { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:checked:focus { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:checked:disabled { - image: url(./Dark/mute.svg); + image: url(theme:Dark/mute.svg); } MuteCheckBox::indicator:unchecked:disabled { - image: url(./Dark/settings/audio.svg); + image: url(theme:Dark/settings/audio.svg); } #hotkeyFilterReset { @@ -1283,46 +1283,46 @@ OBSHotkeyWidget QPushButton { /* Sources List Group Collapse Checkbox */ -SourceTreeSubItemCheckBox { +QCheckBox[sourceTreeSubItem=true] { background: transparent; outline: none; padding: 0px; } -SourceTreeSubItemCheckBox::indicator { +QCheckBox[sourceTreeSubItem=true]::indicator { width: 12px; height: 12px; } -SourceTreeSubItemCheckBox::indicator:checked, -SourceTreeSubItemCheckBox::indicator:checked:hover { - image: url(./Dark/expand.svg); +QCheckBox[sourceTreeSubItem=true]::indicator:checked, +QCheckBox[sourceTreeSubItem=true]::indicator:checked:hover { + image: url(theme:Dark/expand.svg); } -SourceTreeSubItemCheckBox::indicator:unchecked, -SourceTreeSubItemCheckBox::indicator:unchecked:hover { - image: url(./Dark/collapse.svg); +QCheckBox[sourceTreeSubItem=true]::indicator:unchecked, +QCheckBox[sourceTreeSubItem=true]::indicator:unchecked:hover { + image: url(theme:Dark/collapse.svg); } /* 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); - qproperty-audioProcessOutputIcon: url(./Dark/sources/windowaudio.svg); + qproperty-imageIcon: url(theme:Dark/sources/image.svg); + qproperty-colorIcon: url(theme:Dark/sources/brush.svg); + qproperty-slideshowIcon: url(theme:Dark/sources/slideshow.svg); + qproperty-audioInputIcon: url(theme:Dark/sources/microphone.svg); + qproperty-audioOutputIcon: url(theme:Dark/settings/audio.svg); + qproperty-desktopCapIcon: url(theme:Dark/settings/video.svg); + qproperty-windowCapIcon: url(theme:Dark/sources/window.svg); + qproperty-gameCapIcon: url(theme:Dark/sources/gamepad.svg); + qproperty-cameraIcon: url(theme:Dark/sources/camera.svg); + qproperty-textIcon: url(theme:Dark/sources/text.svg); + qproperty-mediaIcon: url(theme:Dark/sources/media.svg); + qproperty-browserIcon: url(theme:Dark/sources/globe.svg); + qproperty-groupIcon: url(theme:Dark/sources/group.svg); + qproperty-sceneIcon: url(theme:Dark/sources/scene.svg); + qproperty-defaultIcon: url(theme:Dark/sources/default.svg); + qproperty-audioProcessOutputIcon: url(theme:Dark/sources/windowaudio.svg); } /* Scene Tree Grid Mode */ @@ -1358,7 +1358,7 @@ SceneTree { /* Save icon */ * [themeID="replayIconSmall"] { - qproperty-icon: url(./Dark/save.svg); + qproperty-icon: url(theme:Dark/save.svg); } /* Studio Mode T-Bar */ @@ -1388,32 +1388,32 @@ QSlider::handle:horizontal[themeID="tBarSlider"] { /* Media icons */ * [themeID="playIcon"] { - qproperty-icon: url(./Dark/media/media_play.svg); + qproperty-icon: url(theme:Dark/media/media_play.svg); } * [themeID="pauseIcon"] { - qproperty-icon: url(./Dark/media/media_pause.svg); + qproperty-icon: url(theme:Dark/media/media_pause.svg); } * [themeID="restartIcon"] { - qproperty-icon: url(./Dark/media/media_restart.svg); + qproperty-icon: url(theme:Dark/media/media_restart.svg); } * [themeID="stopIcon"] { - qproperty-icon: url(./Dark/media/media_stop.svg); + qproperty-icon: url(theme:Dark/media/media_stop.svg); } * [themeID="nextIcon"] { - qproperty-icon: url(./Dark/media/media_next.svg); + qproperty-icon: url(theme:Dark/media/media_next.svg); } * [themeID="previousIcon"] { - qproperty-icon: url(./Dark/media/media_previous.svg); + qproperty-icon: url(theme:Dark/media/media_previous.svg); } /* YouTube Integration */ OBSYoutubeActions { - qproperty-thumbPlaceholder: url(./Dark/sources/image.svg); + qproperty-thumbPlaceholder: url(theme:Dark/sources/image.svg); } #ytEventList QLabel { @@ -1441,7 +1441,7 @@ OBSYoutubeActions { /* Calendar Widget */ QDateTimeEdit::down-arrow { qproperty-alignment: AlignTop; - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); width: 100%; } @@ -1464,7 +1464,7 @@ QCalendarWidget QToolButton { } #qt_calendar_monthbutton::menu-indicator { - image: url(./Dark/down.svg); + image: url(theme:Dark/down.svg); subcontrol-position: right; padding-top: 2px; padding-right: 6px; @@ -1474,13 +1474,13 @@ QCalendarWidget QToolButton { QCalendarWidget #qt_calendar_prevmonth { padding: 2px; - qproperty-icon: url(./Dark/left.svg); + qproperty-icon: url(theme:Dark/left.svg); icon-size: 16px, 16px; } QCalendarWidget #qt_calendar_nextmonth { padding: 2px; - qproperty-icon: url(./Dark/right.svg); + qproperty-icon: url(theme:Dark/right.svg); icon-size: 16px, 16px; } diff --git a/UI/obs-app.cpp b/UI/obs-app.cpp index c98408c4a..887d6bb63 100644 --- a/UI/obs-app.cpp +++ b/UI/obs-app.cpp @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -1272,6 +1273,19 @@ bool OBSApp::InitTheme() defaultPalette = palette(); setStyle(new OBSProxyStyle()); + /* Set search paths for custom 'theme:' URI prefix */ + string searchDir; + if (GetDataFilePath("themes", searchDir)) { + auto installSearchDir = filesystem::u8path(searchDir); + QDir::addSearchPath("theme", absolute(installSearchDir)); + } + + char userDir[512]; + if (GetConfigPath(userDir, sizeof(userDir), "obs-studio/themes")) { + auto configSearchDir = filesystem::u8path(userDir); + QDir::addSearchPath("theme", absolute(configSearchDir)); + } + const char *themeName = config_get_string(globalConfig, "General", "CurrentTheme3"); if (!themeName) diff --git a/UI/source-tree.cpp b/UI/source-tree.cpp index 3cfdcd5ed..66f44da71 100644 --- a/UI/source-tree.cpp +++ b/UI/source-tree.cpp @@ -577,7 +577,8 @@ void SourceTreeItem::Update(bool force) boxLayout->insertItem(0, spacer); } else if (type == Type::Group) { - expand = new SourceTreeSubItemCheckBox(); + expand = new QCheckBox(); + expand->setProperty("sourceTreeSubItem", true); expand->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum); expand->setMaximumSize(10, 16); @@ -1664,11 +1665,8 @@ void SourceTree::AddGroup() void SourceTree::UpdateNoSourcesMessage() { - std::string darkPath; - GetDataFilePath("themes/Dark/no_sources.svg", darkPath); - QString file = !App()->IsThemeDark() ? ":res/images/no_sources.svg" - : darkPath.c_str(); + : "theme:Dark/no_sources.svg"; iconNoSources.load(file); QTextOption opt(Qt::AlignHCenter); diff --git a/UI/source-tree.hpp b/UI/source-tree.hpp index 0ab3ad80f..c4b419686 100644 --- a/UI/source-tree.hpp +++ b/UI/source-tree.hpp @@ -22,10 +22,6 @@ class LockedCheckBox; class VisibilityCheckBox; class VisibilityItemWidget; -class SourceTreeSubItemCheckBox : public QCheckBox { - Q_OBJECT -}; - class SourceTreeItem : public QFrame { Q_OBJECT diff --git a/UI/window-basic-status-bar.cpp b/UI/window-basic-status-bar.cpp index 300b769c5..5f08ba78b 100644 --- a/UI/window-basic-status-bar.cpp +++ b/UI/window-basic-status-bar.cpp @@ -569,19 +569,9 @@ void OBSBasicStatusBar::RecordingUnpaused() static QPixmap GetPixmap(const QString &filename) { - bool darkTheme = obs_frontend_is_theme_dark(); - QString path; - - if (darkTheme) { - std::string darkPath; - QString themePath = QString("themes/Dark/") + filename; - GetDataFilePath(QT_TO_UTF8(themePath), darkPath); - path = QT_UTF8(darkPath.c_str()); - } else { - path = QString(":/res/images/" + filename); - } - - return QIcon(path).pixmap(QSize(16, 16)); + QString path = obs_frontend_is_theme_dark() ? "theme:Dark/" + : ":/res/images/"; + return QIcon(path + filename).pixmap(QSize(16, 16)); } void OBSBasicStatusBar::UpdateIcons() diff --git a/deps/obs-scripting/obs-scripting-lua.c b/deps/obs-scripting/obs-scripting-lua.c index c322e0850..9b3c44441 100644 --- a/deps/obs-scripting/obs-scripting-lua.c +++ b/deps/obs-scripting/obs-scripting-lua.c @@ -52,6 +52,7 @@ static const char *get_script_path_func = "\ function script_path()\n\ return \"%s\"\n\ end\n\ +package.cpath = package.cpath .. \";\" .. script_path() .. \"/?." SO_EXT "\"\n\ package.path = package.path .. \";\" .. script_path() .. \"/?.lua\"\n"; static char *startup_script = NULL; diff --git a/libobs/CMakeLists.txt b/libobs/CMakeLists.txt index 39bfa1fd0..279dab4c1 100644 --- a/libobs/CMakeLists.txt +++ b/libobs/CMakeLists.txt @@ -33,6 +33,8 @@ target_sources( obs-audio-controls.c obs-audio-controls.h obs-audio.c + obs-av1.c + obs-av1.h obs-avc.c obs-avc.h obs-data.c diff --git a/libobs/cmake/legacy.cmake b/libobs/cmake/legacy.cmake index 5f13c4c0f..dd77cdfb9 100644 --- a/libobs/cmake/legacy.cmake +++ b/libobs/cmake/legacy.cmake @@ -32,6 +32,8 @@ target_sources( obs-audio.c obs-audio-controls.c obs-audio-controls.h + obs-av1.c + obs-av1.h obs-avc.c obs-avc.h obs-data.c diff --git a/libobs/obs-av1.c b/libobs/obs-av1.c new file mode 100644 index 000000000..a01513053 --- /dev/null +++ b/libobs/obs-av1.c @@ -0,0 +1,123 @@ +// SPDX-FileCopyrightText: 2023 David Rosca +// +// SPDX-License-Identifier: GPL-2.0-or-later + +#include "obs-av1.h" + +#include "obs.h" + +static inline uint64_t leb128(const uint8_t *buf, size_t size, size_t *len) +{ + uint64_t value = 0; + uint8_t leb128_byte; + + *len = 0; + + for (int i = 0; i < 8; i++) { + if (size-- < 1) + break; + (*len)++; + leb128_byte = buf[i]; + value |= (leb128_byte & 0x7f) << (i * 7); + if (!(leb128_byte & 0x80)) + break; + } + + return value; +} + +static inline unsigned int get_bits(uint8_t val, unsigned int n, + unsigned int count) +{ + return (val >> (8 - n - count)) & ((1 << (count - 1)) * 2 - 1); +} + +static void parse_obu_header(const uint8_t *buf, size_t size, size_t *obu_start, + size_t *obu_size, int *obu_type) +{ + int extension_flag, has_size_field; + size_t size_len = 0; + + *obu_start = 0; + *obu_size = 0; + *obu_type = 0; + + if (size < 1) + return; + + *obu_type = get_bits(*buf, 1, 4); + extension_flag = get_bits(*buf, 5, 1); + has_size_field = get_bits(*buf, 6, 1); + + if (extension_flag) + (*obu_start)++; + + (*obu_start)++; + + if (has_size_field) + *obu_size = (size_t)leb128(buf + *obu_start, size - *obu_start, + &size_len); + else + *obu_size = size - 1; + + *obu_start += size_len; +} + +bool obs_av1_keyframe(const uint8_t *data, size_t size) +{ + const uint8_t *start = data, *end = data + size; + + while (start < end) { + size_t obu_start, obu_size; + int obu_type; + parse_obu_header(start, end - start, &obu_start, &obu_size, + &obu_type); + + if (obu_size) { + if (obu_type == OBS_OBU_FRAME || + obu_type == OBS_OBU_FRAME_HEADER) { + uint8_t val = *(start + obu_start); + if (!get_bits(val, 0, 1)) // show_existing_frame + return get_bits(val, 1, 2) == + 0; // frame_type + return false; + } + } + + start += obu_start + obu_size; + } + + return false; +} + +void obs_extract_av1_headers(const uint8_t *packet, size_t size, + uint8_t **new_packet_data, size_t *new_packet_size, + uint8_t **header_data, size_t *header_size) +{ + DARRAY(uint8_t) new_packet; + DARRAY(uint8_t) header; + const uint8_t *start = packet, *end = packet + size; + + da_init(new_packet); + da_init(header); + + while (start < end) { + size_t obu_start, obu_size; + int obu_type; + parse_obu_header(start, end - start, &obu_start, &obu_size, + &obu_type); + + if (obu_type == OBS_OBU_METADATA || + obu_type == OBS_OBU_SEQUENCE_HEADER) { + da_push_back_array(header, start, obu_start + obu_size); + } + da_push_back_array(new_packet, start, obu_start + obu_size); + + start += obu_start + obu_size; + } + + *new_packet_data = new_packet.array; + *new_packet_size = new_packet.num; + *header_data = header.array; + *header_size = header.num; +} diff --git a/libobs/obs-av1.h b/libobs/obs-av1.h new file mode 100644 index 000000000..031299da0 --- /dev/null +++ b/libobs/obs-av1.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: 2023 David Rosca +// +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include "util/c99defs.h" + +#ifdef __cplusplus +extern "C" { +#endif + +enum { + OBS_OBU_SEQUENCE_HEADER = 1, + OBS_OBU_TEMPORAL_DELIMITER = 2, + OBS_OBU_FRAME_HEADER = 3, + OBS_OBU_TILE_GROUP = 4, + OBS_OBU_METADATA = 5, + OBS_OBU_FRAME = 6, + OBS_OBU_REDUNDANT_FRAME_HEADER = 7, + OBS_OBU_TILE_LIST = 8, + OBS_OBU_PADDING = 15, +}; + +/* Helpers for parsing AV1 OB units. */ + +EXPORT bool obs_av1_keyframe(const uint8_t *data, size_t size); +EXPORT void obs_extract_av1_headers(const uint8_t *packet, size_t size, + uint8_t **new_packet_data, + size_t *new_packet_size, + uint8_t **header_data, size_t *header_size); + +#ifdef __cplusplus +} +#endif diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c index 25c5f7900..b7e5d5edd 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c @@ -24,6 +24,7 @@ #include #include #include +#include #ifdef ENABLE_HEVC #include #endif @@ -51,8 +52,15 @@ #define info(format, ...) do_log(LOG_INFO, format, ##__VA_ARGS__) #define debug(format, ...) do_log(LOG_DEBUG, format, ##__VA_ARGS__) +enum codec_type { + CODEC_H264, + CODEC_HEVC, + CODEC_AV1, +}; + struct vaapi_encoder { obs_encoder_t *encoder; + enum codec_type codec; AVBufferRef *vadevice_ref; AVBufferRef *vaframes_ref; @@ -83,59 +91,48 @@ static const char *h264_vaapi_getname(void *unused) return "FFmpeg VAAPI H.264"; } -#ifdef ENABLE_HEVC -static const char *hevc_vaapi_getname(void *unused) +static const char *av1_vaapi_getname(void *unused) { UNUSED_PARAMETER(unused); - return "FFmpeg VAAPI HEVC"; -} -#endif - -static inline bool h264_valid_format(enum video_format format) -{ - return format == VIDEO_FORMAT_NV12; + return "FFmpeg VAAPI AV1"; } #ifdef ENABLE_HEVC -static inline bool hevc_valid_format(enum video_format format) +static const char *hevc_vaapi_getname(void *unused) { - return (format == VIDEO_FORMAT_NV12) || (format == VIDEO_FORMAT_P010); + UNUSED_PARAMETER(unused); + return "FFmpeg VAAPI HEVC"; } #endif -static void h264_vaapi_video_info(void *data, struct video_scale_info *info) +static inline bool vaapi_valid_format(struct vaapi_encoder *enc, + enum video_format format) { - struct vaapi_encoder *enc = data; - enum video_format pref_format; - - pref_format = obs_encoder_get_preferred_video_format(enc->encoder); - - if (!h264_valid_format(pref_format)) { - pref_format = h264_valid_format(info->format) - ? info->format - : VIDEO_FORMAT_NV12; + if (enc->codec == CODEC_H264) { + return format == VIDEO_FORMAT_NV12; + } else if (enc->codec == CODEC_HEVC || enc->codec == CODEC_AV1) { + return (format == VIDEO_FORMAT_NV12) || + (format == VIDEO_FORMAT_P010); + } else { + return false; } - - info->format = pref_format; } -#ifdef ENABLE_HEVC -static void hevc_vaapi_video_info(void *data, struct video_scale_info *info) +static void vaapi_video_info(void *data, struct video_scale_info *info) { struct vaapi_encoder *enc = data; enum video_format pref_format; pref_format = obs_encoder_get_preferred_video_format(enc->encoder); - if (!hevc_valid_format(pref_format)) { - pref_format = hevc_valid_format(info->format) + if (!vaapi_valid_format(enc, pref_format)) { + pref_format = vaapi_valid_format(enc, info->format) ? info->format : VIDEO_FORMAT_NV12; } info->format = pref_format; } -#endif static bool vaapi_init_codec(struct vaapi_encoder *enc, const char *path) { @@ -232,7 +229,7 @@ static const rc_mode_t *get_rc_mode(const char *name) return rc_mode ? rc_mode : RC_MODES; } -static bool vaapi_update(void *data, obs_data_t *settings, bool hevc) +static bool vaapi_update(void *data, obs_data_t *settings) { struct vaapi_encoder *enc = data; @@ -247,7 +244,7 @@ static bool vaapi_update(void *data, obs_data_t *settings, bool hevc) int bf = (int)obs_data_get_int(settings, "bf"); int qp = rc_mode->qp ? (int)obs_data_get_int(settings, "qp") : 0; - av_opt_set_int(enc->context->priv_data, "qp", qp, 0); + enc->context->global_quality = enc->codec == CODEC_AV1 ? qp * 5 : qp; int level = (int)obs_data_get_int(settings, "level"); int bitrate = rc_mode->bitrate @@ -277,21 +274,15 @@ static bool vaapi_update(void *data, obs_data_t *settings, bool hevc) info.range = voi->range; #ifdef ENABLE_HEVC - if (hevc) { + if (enc->codec == CODEC_HEVC) { if ((profile == FF_PROFILE_HEVC_MAIN) && (info.format == VIDEO_FORMAT_P010)) { warn("Forcing Main10 for P010"); profile = FF_PROFILE_HEVC_MAIN_10; } - - hevc_vaapi_video_info(enc, &info); - } else -#else - UNUSED_PARAMETER(hevc); -#endif - { - h264_vaapi_video_info(enc, &info); } +#endif + vaapi_video_info(enc, &info); enc->context->profile = profile; enc->context->max_b_frames = bf; @@ -418,16 +409,28 @@ static void vaapi_destroy(void *data) bfree(enc); } +static inline const char *vaapi_encoder_name(enum codec_type codec) +{ + if (codec == CODEC_H264) { + return "h264_vaapi"; + } else if (codec == CODEC_HEVC) { + return "hevc_vaapi"; + } else if (codec == CODEC_AV1) { + return "av1_vaapi"; + } + return NULL; +} + static void *vaapi_create_internal(obs_data_t *settings, obs_encoder_t *encoder, - bool hevc) + enum codec_type codec) { struct vaapi_encoder *enc; enc = bzalloc(sizeof(*enc)); enc->encoder = encoder; - const char *const name = hevc ? "hevc_vaapi" : "h264_vaapi"; - enc->vaapi = avcodec_find_encoder_by_name(name); + enc->codec = codec; + enc->vaapi = avcodec_find_encoder_by_name(vaapi_encoder_name(codec)); enc->first_packet = true; @@ -444,7 +447,7 @@ static void *vaapi_create_internal(obs_data_t *settings, obs_encoder_t *encoder, goto fail; } - if (!vaapi_update(enc, settings, hevc)) + if (!vaapi_update(enc, settings)) goto fail; return enc; @@ -456,13 +459,18 @@ fail: static void *h264_vaapi_create(obs_data_t *settings, obs_encoder_t *encoder) { - return vaapi_create_internal(settings, encoder, false); + return vaapi_create_internal(settings, encoder, CODEC_H264); +} + +static void *av1_vaapi_create(obs_data_t *settings, obs_encoder_t *encoder) +{ + return vaapi_create_internal(settings, encoder, CODEC_AV1); } #ifdef ENABLE_HEVC static void *hevc_vaapi_create(obs_data_t *settings, obs_encoder_t *encoder) { - return vaapi_create_internal(settings, encoder, true); + return vaapi_create_internal(settings, encoder, CODEC_HEVC); } #endif @@ -492,9 +500,8 @@ static inline void copy_data(AVFrame *pic, const struct encoder_frame *frame, } } -static bool vaapi_encode_internal(void *data, struct encoder_frame *frame, - struct encoder_packet *packet, - bool *received_packet, bool hevc) +static bool vaapi_encode(void *data, struct encoder_frame *frame, + struct encoder_packet *packet, bool *received_packet) { struct vaapi_encoder *enc = data; AVFrame *hwframe = NULL; @@ -556,22 +563,26 @@ static bool vaapi_encode_internal(void *data, struct encoder_frame *frame, enc->first_packet = false; #ifdef ENABLE_HEVC - if (hevc) { + if (enc->codec == CODEC_HEVC) { obs_extract_hevc_headers( enc->packet->data, enc->packet->size, &new_packet, &size, &enc->header, &enc->header_size, &enc->sei, &enc->sei_size); } else -#else - UNUSED_PARAMETER(hevc); #endif - { + if (enc->codec == CODEC_H264) { obs_extract_avc_headers( enc->packet->data, enc->packet->size, &new_packet, &size, &enc->header, &enc->header_size, &enc->sei, &enc->sei_size); + } else if (enc->codec == CODEC_AV1) { + obs_extract_av1_headers(enc->packet->data, + enc->packet->size, + &new_packet, &size, + &enc->header, + &enc->header_size); } da_copy_array(enc->buffer, new_packet, size); @@ -587,14 +598,17 @@ static bool vaapi_encode_internal(void *data, struct encoder_frame *frame, packet->size = enc->buffer.num; packet->type = OBS_ENCODER_VIDEO; #ifdef ENABLE_HEVC - if (hevc) { + if (enc->codec == CODEC_HEVC) { packet->keyframe = obs_hevc_keyframe(packet->data, packet->size); } else #endif - { + if (enc->codec == CODEC_H264) { packet->keyframe = obs_avc_keyframe(packet->data, packet->size); + } else if (enc->codec == CODEC_AV1) { + packet->keyframe = + obs_av1_keyframe(packet->data, packet->size); } *received_packet = true; } else { @@ -610,58 +624,60 @@ fail: return false; } -static bool h264_vaapi_encode(void *data, struct encoder_frame *frame, - struct encoder_packet *packet, - bool *received_packet) +static void set_visible(obs_properties_t *ppts, const char *name, bool visible) { - return vaapi_encode_internal(data, frame, packet, received_packet, - false); + obs_property_t *p = obs_properties_get(ppts, name); + obs_property_set_visible(p, visible); } -#ifdef ENABLE_HEVC -static bool hevc_vaapi_encode(void *data, struct encoder_frame *frame, - struct encoder_packet *packet, - bool *received_packet) +static inline VAProfile vaapi_profile(enum codec_type codec) { - return vaapi_encode_internal(data, frame, packet, received_packet, - true); -} + if (codec == CODEC_H264) { + return VAProfileH264ConstrainedBaseline; + } else if (codec == CODEC_AV1) { + return VAProfileAV1Profile0; +#if ENABLE_HEVC + } else if (codec == CODEC_HEVC) { + return VAProfileHEVCMain; #endif - -static void set_visible(obs_properties_t *ppts, const char *name, bool visible) -{ - obs_property_t *p = obs_properties_get(ppts, name); - obs_property_set_visible(p, visible); + } + return VAProfileNone; } -static void vaapi_defaults_internal(obs_data_t *settings, bool hevc) +static inline const char *vaapi_default_device(enum codec_type codec) { -#ifdef ENABLE_HEVC - const char *device = hevc ? vaapi_get_hevc_default_device() - : vaapi_get_h264_default_device(); -#else - const char *const device = vaapi_get_h264_default_device(); + if (codec == CODEC_H264) { + return vaapi_get_h264_default_device(); + } else if (codec == CODEC_AV1) { + return vaapi_get_av1_default_device(); +#if ENABLE_HEVC + } else if (codec == CODEC_HEVC) { + return vaapi_get_hevc_default_device(); #endif + } + return NULL; +} +static void vaapi_defaults_internal(obs_data_t *settings, enum codec_type codec) +{ + const char *const device = vaapi_default_device(codec); obs_data_set_default_string(settings, "vaapi_device", device); #ifdef ENABLE_HEVC - if (hevc) { + if (codec == CODEC_HEVC) obs_data_set_default_int(settings, "profile", FF_PROFILE_HEVC_MAIN); - - } else -#else - UNUSED_PARAMETER(hevc); + else #endif - { + if (codec == CODEC_H264) obs_data_set_default_int(settings, "profile", - FF_PROFILE_H264_CONSTRAINED_BASELINE); - } - obs_data_set_default_int(settings, "level", 40); + FF_PROFILE_H264_HIGH); + else if (codec == CODEC_AV1) + obs_data_set_default_int(settings, "profile", + FF_PROFILE_AV1_MAIN); + obs_data_set_default_int(settings, "level", FF_LEVEL_UNKNOWN); obs_data_set_default_int(settings, "bitrate", 2500); obs_data_set_default_int(settings, "keyint_sec", 0); obs_data_set_default_int(settings, "bf", 0); - obs_data_set_default_int(settings, "rendermode", 0); obs_data_set_default_int(settings, "qp", 20); obs_data_set_default_int(settings, "maxrate", 0); @@ -670,12 +686,7 @@ static void vaapi_defaults_internal(obs_data_t *settings, bool hevc) if (!va_dpy) return; -#ifdef ENABLE_HEVC - const VAProfile profile = hevc ? VAProfileHEVCMain - : VAProfileH264ConstrainedBaseline; -#else - const VAProfile profile = VAProfileH264ConstrainedBaseline; -#endif + const VAProfile profile = vaapi_profile(codec); if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_CBR, device)) obs_data_set_default_string(settings, "rate_control", "CBR"); else if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_VBR, device)) @@ -688,12 +699,17 @@ static void vaapi_defaults_internal(obs_data_t *settings, bool hevc) static void h264_vaapi_defaults(obs_data_t *settings) { - vaapi_defaults_internal(settings, false); + vaapi_defaults_internal(settings, CODEC_H264); +} + +static void av1_vaapi_defaults(obs_data_t *settings) +{ + vaapi_defaults_internal(settings, CODEC_AV1); } static void hevc_vaapi_defaults(obs_data_t *settings) { - vaapi_defaults_internal(settings, true); + vaapi_defaults_internal(settings, CODEC_HEVC); } static bool vaapi_device_modified(obs_properties_t *ppts, obs_property_t *p, @@ -729,6 +745,11 @@ static bool vaapi_device_modified(obs_properties_t *ppts, obs_property_t *p, goto fail; profile = VAProfileH264High; break; + case FF_PROFILE_AV1_MAIN: + if (!vaapi_display_av1_supported(va_dpy, device)) + goto fail; + profile = VAProfileAV1Profile0; + break; #ifdef ENABLE_HEVC case FF_PROFILE_HEVC_MAIN: if (!vaapi_display_hevc_supported(va_dpy, device)) @@ -744,7 +765,7 @@ static bool vaapi_device_modified(obs_properties_t *ppts, obs_property_t *p, } if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_CBR, device)) - obs_property_list_add_string(rc_p, "CBR (default)", "CBR"); + obs_property_list_add_string(rc_p, "CBR", "CBR"); if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_VBR, device)) obs_property_list_add_string(rc_p, "VBR", "VBR"); @@ -752,6 +773,8 @@ static bool vaapi_device_modified(obs_properties_t *ppts, obs_property_t *p, if (vaapi_device_rc_supported(profile, va_dpy, VA_RC_CQP, device)) obs_property_list_add_string(rc_p, "CQP", "CQP"); + set_visible(ppts, "bf", vaapi_device_bframe_supported(profile, va_dpy)); + fail: vaapi_close_device(&drm_fd, va_dpy); return true; @@ -800,7 +823,7 @@ static bool get_device_name_from_pci(struct pci_access *pacc, char *pci_slot, return false; } -static obs_properties_t *vaapi_properties_internal(bool hevc) +static obs_properties_t *vaapi_properties_internal(enum codec_type codec) { obs_properties_t *props = obs_properties_create(); obs_property_t *list; @@ -891,16 +914,17 @@ static obs_properties_t *vaapi_properties_internal(bool hevc) obs_module_text("Profile"), OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); - if (hevc) { + if (codec == CODEC_HEVC) { obs_property_list_add_int(list, "Main", FF_PROFILE_HEVC_MAIN); obs_property_list_add_int(list, "Main10", FF_PROFILE_HEVC_MAIN_10); - } else { - obs_property_list_add_int(list, - "Constrained Baseline (default)", + } else if (codec == CODEC_H264) { + obs_property_list_add_int(list, "Constrained Baseline", FF_PROFILE_H264_CONSTRAINED_BASELINE); obs_property_list_add_int(list, "Main", FF_PROFILE_H264_MAIN); obs_property_list_add_int(list, "High", FF_PROFILE_H264_HIGH); + } else if (codec == CODEC_AV1) { + obs_property_list_add_int(list, "Main", FF_PROFILE_AV1_MAIN); } obs_property_set_modified_callback(list, vaapi_device_modified); @@ -909,15 +933,33 @@ static obs_properties_t *vaapi_properties_internal(bool hevc) OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT); obs_property_list_add_int(list, "Auto", FF_LEVEL_UNKNOWN); - obs_property_list_add_int(list, "3.0", 30); - obs_property_list_add_int(list, "3.1", 31); - obs_property_list_add_int(list, "4.0 (default) (Compatibility mode)", - 40); - obs_property_list_add_int(list, "4.1", 41); - obs_property_list_add_int(list, "4.2", 42); - obs_property_list_add_int(list, "5.0", 50); - obs_property_list_add_int(list, "5.1", 51); - obs_property_list_add_int(list, "5.2", 52); + if (codec == CODEC_H264) { + obs_property_list_add_int(list, "3.0", 30); + obs_property_list_add_int(list, "3.1", 31); + obs_property_list_add_int(list, "4.0", 40); + obs_property_list_add_int(list, "4.1", 41); + obs_property_list_add_int(list, "4.2", 42); + obs_property_list_add_int(list, "5.0", 50); + obs_property_list_add_int(list, "5.1", 51); + obs_property_list_add_int(list, "5.2", 52); + } else if (codec == CODEC_HEVC) { + obs_property_list_add_int(list, "3.0", 90); + obs_property_list_add_int(list, "3.1", 93); + obs_property_list_add_int(list, "4.0", 120); + obs_property_list_add_int(list, "4.1", 123); + obs_property_list_add_int(list, "5.0", 150); + obs_property_list_add_int(list, "5.1", 153); + obs_property_list_add_int(list, "5.2", 156); + } else if (codec == CODEC_AV1) { + obs_property_list_add_int(list, "3.0", 4); + obs_property_list_add_int(list, "3.1", 5); + obs_property_list_add_int(list, "4.0", 8); + obs_property_list_add_int(list, "4.1", 9); + obs_property_list_add_int(list, "5.0", 12); + obs_property_list_add_int(list, "5.1", 13); + obs_property_list_add_int(list, "5.2", 14); + obs_property_list_add_int(list, "5.3", 15); + } list = obs_properties_add_list(props, "rate_control", obs_module_text("RateControl"), @@ -942,6 +984,9 @@ static obs_properties_t *vaapi_properties_internal(bool hevc) 20, 1); obs_property_int_set_suffix(p, " s"); + obs_properties_add_int(props, "bf", obs_module_text("BFrames"), 0, 4, + 1); + obs_properties_add_text(props, "ffmpeg_opts", obs_module_text("FFmpegOpts"), OBS_TEXT_DEFAULT); @@ -952,14 +997,20 @@ static obs_properties_t *vaapi_properties_internal(bool hevc) static obs_properties_t *h264_vaapi_properties(void *unused) { UNUSED_PARAMETER(unused); - return vaapi_properties_internal(false); + return vaapi_properties_internal(CODEC_H264); +} + +static obs_properties_t *av1_vaapi_properties(void *unused) +{ + UNUSED_PARAMETER(unused); + return vaapi_properties_internal(CODEC_AV1); } #ifdef ENABLE_HEVC static obs_properties_t *hevc_vaapi_properties(void *unused) { UNUSED_PARAMETER(unused); - return vaapi_properties_internal(true); + return vaapi_properties_internal(CODEC_HEVC); } #endif @@ -988,12 +1039,27 @@ struct obs_encoder_info h264_vaapi_encoder_info = { .get_name = h264_vaapi_getname, .create = h264_vaapi_create, .destroy = vaapi_destroy, - .encode = h264_vaapi_encode, + .encode = vaapi_encode, .get_defaults = h264_vaapi_defaults, .get_properties = h264_vaapi_properties, .get_extra_data = vaapi_extra_data, .get_sei_data = vaapi_sei_data, - .get_video_info = h264_vaapi_video_info, + .get_video_info = vaapi_video_info, +}; + +struct obs_encoder_info av1_vaapi_encoder_info = { + .id = "av1_ffmpeg_vaapi", + .type = OBS_ENCODER_VIDEO, + .codec = "av1", + .get_name = av1_vaapi_getname, + .create = av1_vaapi_create, + .destroy = vaapi_destroy, + .encode = vaapi_encode, + .get_defaults = av1_vaapi_defaults, + .get_properties = av1_vaapi_properties, + .get_extra_data = vaapi_extra_data, + .get_sei_data = vaapi_sei_data, + .get_video_info = vaapi_video_info, }; #ifdef ENABLE_HEVC @@ -1004,11 +1070,11 @@ struct obs_encoder_info hevc_vaapi_encoder_info = { .get_name = hevc_vaapi_getname, .create = hevc_vaapi_create, .destroy = vaapi_destroy, - .encode = hevc_vaapi_encode, + .encode = vaapi_encode, .get_defaults = hevc_vaapi_defaults, .get_properties = hevc_vaapi_properties, .get_extra_data = vaapi_extra_data, .get_sei_data = vaapi_sei_data, - .get_video_info = hevc_vaapi_video_info, + .get_video_info = vaapi_video_info, }; #endif diff --git a/plugins/obs-ffmpeg/obs-ffmpeg.c b/plugins/obs-ffmpeg/obs-ffmpeg.c index 7eb9a876d..981bb9c65 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg.c @@ -47,6 +47,7 @@ extern struct obs_encoder_info aom_av1_encoder_info; #ifdef LIBAVUTIL_VAAPI_AVAILABLE extern struct obs_encoder_info h264_vaapi_encoder_info; +extern struct obs_encoder_info av1_vaapi_encoder_info; #ifdef ENABLE_HEVC extern struct obs_encoder_info hevc_vaapi_encoder_info; #endif @@ -337,6 +338,17 @@ static bool h264_vaapi_supported(void) * that support H264. */ return vaapi_get_h264_default_device() != NULL; } +static bool av1_vaapi_supported(void) +{ + const AVCodec *vaenc = avcodec_find_encoder_by_name("av1_vaapi"); + + if (!vaenc) + return false; + + /* NOTE: If default device is NULL, it means there is no device + * that support AV1. */ + return vaapi_get_av1_default_device() != NULL; +} #ifdef ENABLE_HEVC static bool hevc_vaapi_supported(void) { @@ -447,6 +459,13 @@ bool obs_module_load(void) blog(LOG_INFO, "FFmpeg VAAPI H264 encoding not supported"); } + if (av1_vaapi_supported()) { + blog(LOG_INFO, "FFmpeg VAAPI AV1 encoding supported"); + obs_register_encoder(&av1_vaapi_encoder_info); + } else { + blog(LOG_INFO, "FFmpeg VAAPI AV1 encoding not supported"); + } + #ifdef ENABLE_HEVC if (hevc_vaapi_supported()) { blog(LOG_INFO, "FFmpeg VAAPI HEVC encoding supported"); diff --git a/plugins/obs-ffmpeg/vaapi-utils.c b/plugins/obs-ffmpeg/vaapi-utils.c index 4198ee59c..2ca7e468c 100644 --- a/plugins/obs-ffmpeg/vaapi-utils.c +++ b/plugins/obs-ffmpeg/vaapi-utils.c @@ -185,6 +185,38 @@ bool vaapi_device_rc_supported(VAProfile profile, VADisplay dpy, uint32_t rc, return false; } +static bool vaapi_display_ep_bframe_supported(VAProfile profile, + VAEntrypoint entrypoint, + VADisplay dpy) +{ + bool ret = false; + VAStatus va_status; + VAConfigAttrib attrib[1]; + attrib->type = VAConfigAttribEncMaxRefFrames; + + va_status = vaGetConfigAttributes(dpy, profile, entrypoint, attrib, 1); + + if (va_status == VA_STATUS_SUCCESS && + attrib->value != VA_ATTRIB_NOT_SUPPORTED) + return attrib->value >> 16; + + return false; +} + +bool vaapi_device_bframe_supported(VAProfile profile, VADisplay dpy) +{ + bool ret = vaapi_display_ep_bframe_supported(profile, + VAEntrypointEncSlice, dpy); + if (ret) + return true; + ret = vaapi_display_ep_bframe_supported(profile, VAEntrypointEncSliceLP, + dpy); + if (ret) + return true; + + return false; +} + #define CHECK_PROFILE(ret, profile, va_dpy, device_path) \ if (vaapi_display_ep_combo_supported(profile, VAEntrypointEncSlice, \ va_dpy, device_path)) { \ @@ -261,6 +293,61 @@ const char *vaapi_get_h264_default_device() return default_h264_device; } +bool vaapi_display_av1_supported(VADisplay dpy, const char *device_path) +{ + bool ret = false; + + CHECK_PROFILE(ret, VAProfileAV1Profile0, dpy, device_path); + + if (!ret) { + CHECK_PROFILE_LP(ret, VAProfileAV1Profile0, dpy, device_path); + } + + return ret; +} + +bool vaapi_device_av1_supported(const char *device_path) +{ + bool ret = false; + VADisplay va_dpy; + + int drm_fd = -1; + + va_dpy = vaapi_open_device(&drm_fd, device_path, + "vaapi_device_av1_supported"); + if (!va_dpy) + return false; + + ret = vaapi_display_av1_supported(va_dpy, device_path); + + vaapi_close_device(&drm_fd, va_dpy); + + return ret; +} + +const char *vaapi_get_av1_default_device() +{ + static const char *default_av1_device = NULL; + + if (!default_av1_device) { + bool ret = false; + char path[32] = "/dev/dri/renderD1"; + for (int i = 28;; i++) { + sprintf(path, "/dev/dri/renderD1%d", i); + if (access(path, F_OK) != 0) + break; + + ret = vaapi_device_av1_supported(path); + if (ret) { + default_av1_device = strdup(path); + break; + } + } + } + + return default_av1_device; +} + #ifdef ENABLE_HEVC bool vaapi_display_hevc_supported(VADisplay dpy, const char *device_path) diff --git a/plugins/obs-ffmpeg/vaapi-utils.h b/plugins/obs-ffmpeg/vaapi-utils.h index b90b23947..d458bad2c 100644 --- a/plugins/obs-ffmpeg/vaapi-utils.h +++ b/plugins/obs-ffmpeg/vaapi-utils.h @@ -14,11 +14,16 @@ void vaapi_close_device(int *fd, VADisplay dpy); bool vaapi_device_rc_supported(VAProfile profile, VADisplay dpy, uint32_t rc, const char *device_path); +bool vaapi_device_bframe_supported(VAProfile profile, VADisplay dpy); bool vaapi_display_h264_supported(VADisplay dpy, const char *device_path); bool vaapi_device_h264_supported(const char *device_path); const char *vaapi_get_h264_default_device(void); +bool vaapi_display_av1_supported(VADisplay dpy, const char *device_path); +bool vaapi_device_av1_supported(const char *device_path); +const char *vaapi_get_av1_default_device(void); + #ifdef ENABLE_HEVC bool vaapi_display_hevc_supported(VADisplay dpy, const char *device_path); bool vaapi_device_hevc_supported(const char *device_path);