mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-09-07 17:16:00 -05:00
Compare commits
83 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08933a3683 | ||
|
|
9be00ba3ca | ||
|
|
cce15529fe | ||
|
|
588f90f0b1 | ||
|
|
d3220c40dc | ||
|
|
79c659b4fa | ||
|
|
292adb990d | ||
|
|
b7a0f6c5d0 | ||
|
|
b3f1aff03c | ||
|
|
aea9d1b319 | ||
|
|
1fd724e4f4 | ||
|
|
3d1c613f1c | ||
|
|
9ca2f4470b | ||
|
|
34527b08a9 | ||
|
|
3ae1050488 | ||
|
|
d7ec7c6e40 | ||
|
|
e98ee64974 | ||
|
|
7c6428b27e | ||
|
|
aca9b84fc6 | ||
|
|
d397f5e406 | ||
|
|
97cbcd7e61 | ||
|
|
64fd8dd50d | ||
|
|
a0dd1cf3ef | ||
|
|
25cf51abea | ||
|
|
3c8f5088d3 | ||
|
|
66f3c74cf3 | ||
|
|
6c23110fb9 | ||
|
|
c9001df97c | ||
|
|
76fa1f8942 | ||
|
|
55ca146a82 | ||
|
|
a3625242de | ||
|
|
db4214c918 | ||
|
|
f024199e2d | ||
|
|
299e7bc868 | ||
|
|
0262e066bf | ||
|
|
bee75336d0 | ||
|
|
96b472776a | ||
|
|
fb457f723a | ||
|
|
eee3e05c10 | ||
|
|
ccc147a1b3 | ||
|
|
45a149f6df | ||
|
|
076be21d40 | ||
|
|
ab5bdb32f5 | ||
|
|
8cfed048cc | ||
|
|
c842595214 | ||
|
|
8fa3e8b038 | ||
|
|
174c17edea | ||
|
|
9d8fadda80 | ||
|
|
58028d3c3d | ||
|
|
3dcabe543f | ||
|
|
1a7ebc5569 | ||
|
|
522ab2963e | ||
|
|
d9bd98ce9c | ||
|
|
2af0735a2f | ||
|
|
556943c293 | ||
|
|
e3004184c4 | ||
|
|
7b2c2e91db | ||
|
|
06ea7bf1d9 | ||
|
|
1474509cb9 | ||
|
|
87aa8d3b40 | ||
|
|
d3e8b76fa6 | ||
|
|
99c9b1a4a2 | ||
|
|
8c0aad4c96 | ||
|
|
c964ed04d3 | ||
|
|
810235e0b7 | ||
|
|
e2b3563810 | ||
|
|
76c5ec480b | ||
|
|
84e4b740a8 | ||
|
|
95409dfa26 | ||
|
|
058af0d3bb | ||
|
|
fd789b476b | ||
|
|
3fc82df278 | ||
|
|
d541356fd3 | ||
|
|
5c2adacca1 | ||
|
|
7200668158 | ||
|
|
7cf7fd6112 | ||
|
|
41821cbeb2 | ||
|
|
9537579235 | ||
|
|
40a701a934 | ||
|
|
6c8556c66c | ||
|
|
a467dffd05 | ||
|
|
497dbd89d4 | ||
|
|
0fdbce25a1 |
49
.github/workflows/build-debian.yml
vendored
Normal file
49
.github/workflows/build-debian.yml
vendored
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
name: debian-build
|
||||||
|
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
submodules: 'recursive'
|
||||||
|
- name: check_libobs_revision
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install libobs-dev
|
||||||
|
mkdir source
|
||||||
|
cd source
|
||||||
|
dpkg -l libobs-dev | tr -s " "| grep libobs | cut -d" " -f3 > libobs.rev
|
||||||
|
- name: install_frontend_header
|
||||||
|
run: |
|
||||||
|
[ -e /usr/include/obs/obs-frontend-api.h ] && { echo "ERROR: obs-frontend-api.h already in system. Maybe the package libobs-dev is installing it."; exit 1; }
|
||||||
|
cd source
|
||||||
|
LIBOBSREV=$(cat libobs.rev)
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install devscripts
|
||||||
|
dget -u http://archive.ubuntu.com/ubuntu/pool/universe/o/obs-studio/obs-studio_$LIBOBSREV.dsc
|
||||||
|
cd ..
|
||||||
|
sudo find -name obs-frontend-api.h -exec cp {} /usr/include/obs/ \;
|
||||||
|
egrep '#include <obs.h>' /usr/include/obs/obs-frontend-api.h || { echo "ERROR: check if the sed commands are needed from now."; exit 1; }
|
||||||
|
sudo sed -i 's/#include <obs.h>/#include <obs\/obs.h>/' /usr/include/obs/obs-frontend-api.h
|
||||||
|
sudo sed -i 's/#include <util\/darray.h>/#include <obs\/util\/darray.h>/' /usr/include/obs/obs-frontend-api.h
|
||||||
|
- name: create_tarball
|
||||||
|
run: |
|
||||||
|
cd ..
|
||||||
|
tar --exclude=.git -cvzf obs-scene-switcher_0.1+testonly.orig.tar.gz SceneSwitcher
|
||||||
|
- name: create_debian_dir
|
||||||
|
run: |
|
||||||
|
cp -a CI/linux/debian .
|
||||||
|
- name: install_dependencies
|
||||||
|
run: |
|
||||||
|
# devscripts and libobs-dev are needed but they were already installed
|
||||||
|
# from check_libobs_revision and install_frontend_header sections.
|
||||||
|
sudo apt update
|
||||||
|
sudo apt install cmake debhelper libcurl4-openssl-dev libxss-dev libxtst-dev qtbase5-dev libopencv-dev
|
||||||
|
- name: build
|
||||||
|
run: |
|
||||||
|
debuild --no-lintian --no-sign
|
||||||
109
.github/workflows/build.yml
vendored
109
.github/workflows/build.yml
vendored
@@ -9,6 +9,7 @@ on:
|
|||||||
env:
|
env:
|
||||||
PLUGIN_NAME: SceneSwitcher
|
PLUGIN_NAME: SceneSwitcher
|
||||||
LIB_NAME: advanced-scene-switcher
|
LIB_NAME: advanced-scene-switcher
|
||||||
|
OBS_TAG: 27.1.1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
macos64:
|
macos64:
|
||||||
@@ -23,6 +24,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
repository: obsproject/obs-studio
|
repository: obsproject/obs-studio
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
ref: 'refs/tags/${{ env.OBS_TAG }}'
|
||||||
- name: "Checkout plugin"
|
- name: "Checkout plugin"
|
||||||
uses: actions/checkout@v2.3.4
|
uses: actions/checkout@v2.3.4
|
||||||
with:
|
with:
|
||||||
@@ -57,6 +59,15 @@ jobs:
|
|||||||
curl -L -O https://github.com/obsproject/obs-deps/releases/download/${{ env.MACOS_DEPS_VERSION }}/macos-qt-${{ env.QT_VERSION }}-${{ env.MACOS_DEPS_VERSION }}.tar.gz
|
curl -L -O https://github.com/obsproject/obs-deps/releases/download/${{ env.MACOS_DEPS_VERSION }}/macos-qt-${{ env.QT_VERSION }}-${{ env.MACOS_DEPS_VERSION }}.tar.gz
|
||||||
tar -xf ./macos-qt-${{ env.QT_VERSION }}-${{ env.MACOS_DEPS_VERSION }}.tar.gz -C "/tmp"
|
tar -xf ./macos-qt-${{ env.QT_VERSION }}-${{ env.MACOS_DEPS_VERSION }}.tar.gz -C "/tmp"
|
||||||
xattr -r -d com.apple.quarantine /tmp/obsdeps
|
xattr -r -d com.apple.quarantine /tmp/obsdeps
|
||||||
|
- name: 'Build prerequisite: OpenCV'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
cd UI/frontend-plugins/${{ env.PLUGIN_NAME }}/deps/opencv
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake -DBUILD_LIST="core,imgproc,objdetect" ..
|
||||||
|
make -j4
|
||||||
|
make install
|
||||||
- name: Configure
|
- name: Configure
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -111,6 +122,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
repository: obsproject/obs-studio
|
repository: obsproject/obs-studio
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
ref: 'refs/tags/${{ env.OBS_TAG }}'
|
||||||
- name: "Checkout plugin"
|
- name: "Checkout plugin"
|
||||||
uses: actions/checkout@v2.3.4
|
uses: actions/checkout@v2.3.4
|
||||||
with:
|
with:
|
||||||
@@ -168,7 +180,8 @@ jobs:
|
|||||||
qtbase5-private-dev \
|
qtbase5-private-dev \
|
||||||
libqt5svg5-dev \
|
libqt5svg5-dev \
|
||||||
swig \
|
swig \
|
||||||
libxss-dev
|
libxss-dev \
|
||||||
|
libopencv-dev
|
||||||
- name: 'Configure'
|
- name: 'Configure'
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
@@ -186,6 +199,7 @@ jobs:
|
|||||||
FILE_NAME=${{ env.PLUGIN_NAME }}-$FILE_DATE-${{ github.sha }}-linux64.tar.gz
|
FILE_NAME=${{ env.PLUGIN_NAME }}-$FILE_DATE-${{ github.sha }}-linux64.tar.gz
|
||||||
echo "FILE_NAME=${FILE_NAME}" >> $GITHUB_ENV
|
echo "FILE_NAME=${FILE_NAME}" >> $GITHUB_ENV
|
||||||
mkdir -p ./${{ env.LIB_NAME }}/bin/64bit/
|
mkdir -p ./${{ env.LIB_NAME }}/bin/64bit/
|
||||||
|
strip -d ./build/UI/frontend-plugins/${{ env.PLUGIN_NAME }}/${{ env.LIB_NAME }}.so
|
||||||
mv ./build/UI/frontend-plugins/${{ env.PLUGIN_NAME }}/${{ env.LIB_NAME }}.so ./${{ env.LIB_NAME }}/bin/64bit/${{ env.LIB_NAME }}.so
|
mv ./build/UI/frontend-plugins/${{ env.PLUGIN_NAME }}/${{ env.LIB_NAME }}.so ./${{ env.LIB_NAME }}/bin/64bit/${{ env.LIB_NAME }}.so
|
||||||
mv ./UI/frontend-plugins/${{ env.PLUGIN_NAME }}/data ./${{ env.LIB_NAME }}/data
|
mv ./UI/frontend-plugins/${{ env.PLUGIN_NAME }}/data ./${{ env.LIB_NAME }}/data
|
||||||
tar -cvzf "${FILE_NAME}" ${{ env.LIB_NAME }}
|
tar -cvzf "${FILE_NAME}" ${{ env.LIB_NAME }}
|
||||||
@@ -197,6 +211,9 @@ jobs:
|
|||||||
windows:
|
windows:
|
||||||
name: Windows
|
name: Windows
|
||||||
runs-on: [windows-latest]
|
runs-on: [windows-latest]
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
arch: [32, 64]
|
||||||
env:
|
env:
|
||||||
QT_VERSION: 5.10.1
|
QT_VERSION: 5.10.1
|
||||||
CMAKE_GENERATOR: "Visual Studio 16 2019"
|
CMAKE_GENERATOR: "Visual Studio 16 2019"
|
||||||
@@ -210,6 +227,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
repository: obsproject/obs-studio
|
repository: obsproject/obs-studio
|
||||||
submodules: 'recursive'
|
submodules: 'recursive'
|
||||||
|
ref: 'refs/tags/${{ env.OBS_TAG }}'
|
||||||
- name: Checkout plugin
|
- name: Checkout plugin
|
||||||
uses: actions/checkout@v2.3.4
|
uses: actions/checkout@v2.3.4
|
||||||
with:
|
with:
|
||||||
@@ -228,53 +246,97 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
curl -kLO https://cdn-fastly.obsproject.com/downloads/dependencies${{ env.WINDOWS_DEPS_VERSION }}.zip -f --retry 5 -C -
|
curl -kLO https://cdn-fastly.obsproject.com/downloads/dependencies${{ env.WINDOWS_DEPS_VERSION }}.zip -f --retry 5 -C -
|
||||||
7z x dependencies${{ env.WINDOWS_DEPS_VERSION }}.zip -o"${{ github.workspace }}/cmbuild/deps"
|
7z x dependencies${{ env.WINDOWS_DEPS_VERSION }}.zip -o"${{ github.workspace }}/cmbuild/deps"
|
||||||
|
- name: 'Build prerequisite: OpenCV'
|
||||||
|
run: |
|
||||||
|
cd UI/frontend-plugins/${{ env.PLUGIN_NAME }}/deps/opencv
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
if ( ${{ matrix.arch }} -eq 32 )
|
||||||
|
{
|
||||||
|
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"Win32" -DBUILD_LIST="core,imgproc,objdetect" ..
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"x64" -DBUILD_LIST="core,imgproc,objdetect" ..
|
||||||
|
}
|
||||||
|
msbuild /m /p:Configuration=Release OpenCV.sln
|
||||||
|
msbuild INSTALL.vcxproj
|
||||||
- name: Configure
|
- name: Configure
|
||||||
run: |
|
run: |
|
||||||
mkdir ./package
|
mkdir ./package
|
||||||
mkdir ./build32
|
mkdir ./build${{ matrix.arch }}
|
||||||
cd ./build32
|
cd ./build${{ matrix.arch }}
|
||||||
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"Win32" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=false -DBUILD_CAPTIONS=false -DCOMPILE_D3D12_HOOK=false -DDepsPath="${{ github.workspace }}/cmbuild/deps/win32" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
|
Get-Location
|
||||||
cd ..
|
if ( ${{ matrix.arch }} -eq 32 )
|
||||||
mkdir ./build64
|
{
|
||||||
cd ./build64
|
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"Win32" -DOpenCV_DIR="${{ github.workspace }}/UI/frontend-plugins/SceneSwitcher/deps/opencv/build/" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=false -DBUILD_CAPTIONS=false -DCOMPILE_D3D12_HOOK=false -DDepsPath="${{ github.workspace }}/cmbuild/deps/win32" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
|
||||||
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"x64" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=false -DBUILD_CAPTIONS=false -DCOMPILE_D3D12_HOOK=false -DDepsPath="${{ github.workspace }}/cmbuild/deps/win64" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017_64" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cmake -G"${{ env.CMAKE_GENERATOR }}" -A"x64" -DOpenCV_DIR="${{ github.workspace }}/UI/frontend-plugins/SceneSwitcher/deps/opencv/build/" -DCMAKE_SYSTEM_VERSION="${{ env.CMAKE_SYSTEM_VERSION }}" -DBUILD_BROWSER=false -DBUILD_CAPTIONS=false -DCOMPILE_D3D12_HOOK=false -DDepsPath="${{ github.workspace }}/cmbuild/deps/win64" -DQTDIR="${{ github.workspace }}/cmbuild/QT/${{ env.QT_VERSION }}/msvc2017_64" -DCOPIED_DEPENDENCIES=FALSE -DCOPY_DEPENDENCIES=TRUE ..
|
||||||
|
}
|
||||||
- name: Build
|
- name: Build
|
||||||
run: |
|
run: |
|
||||||
msbuild /m /p:Configuration=RelWithDebInfo .\build32\obs-studio.sln
|
msbuild /m /p:Configuration=RelWithDebInfo .\build${{ matrix.arch }}\obs-studio.sln
|
||||||
msbuild /m /p:Configuration=RelWithDebInfo .\build64\obs-studio.sln
|
|
||||||
- name: Package
|
- name: Package
|
||||||
if: success()
|
if: success()
|
||||||
run: |
|
run: |
|
||||||
$env:FILE_DATE=(Get-Date -UFormat "%F")
|
$env:FILE_DATE=(Get-Date -UFormat "%F")
|
||||||
$env:FILE_NAME="${{ env.PLUGIN_NAME }}-${env:FILE_DATE}-${{ github.sha }}-windows"
|
$env:FILE_NAME="${{ env.PLUGIN_NAME }}-${env:FILE_DATE}-${{ github.sha }}-windows"
|
||||||
echo "FILE_NAME=${env:FILE_NAME}" >> ${env:GITHUB_ENV}
|
echo "FILE_NAME=${env:FILE_NAME}" >> ${env:GITHUB_ENV}
|
||||||
robocopy .\build32\rundir\RelWithDebInfo\obs-plugins\32bit\ .\package\obs-plugins\32bit ${{ env.LIB_NAME }}.* /E /XF .gitignore
|
robocopy .\build${{ matrix.arch }}\rundir\RelWithDebInfo\obs-plugins\${{ matrix.arch }}bit\ .\package\obs-plugins\${{ matrix.arch }}bit ${{ env.LIB_NAME }}.* /E /XF .gitignore
|
||||||
robocopy .\build64\rundir\RelWithDebInfo\obs-plugins\64bit\ .\package\obs-plugins\64bit ${{ env.LIB_NAME }}.* /E /XF .gitignore
|
robocopy .\build${{ matrix.arch }}\rundir\RelWithDebInfo\data\obs-plugins\${{ env.LIB_NAME }}\ .\package\data\obs-plugins\${{ env.LIB_NAME }}\ /E /XF .gitignore
|
||||||
robocopy .\build64\rundir\RelWithDebInfo\data\obs-plugins\${{ env.LIB_NAME }}\ .\package\data\obs-plugins\${{ env.LIB_NAME }}\ /E /XF .gitignore
|
cp UI/frontend-plugins/${{ env.PLUGIN_NAME }}/deps/opencv/build/bin/Release/*dll package/obs-plugins/${{ matrix.arch }}bit
|
||||||
exit 0
|
exit 0
|
||||||
- name: Publish zip
|
- name: Publish zip
|
||||||
if: success()
|
if: success()
|
||||||
uses: actions/upload-artifact@v2.2.1
|
uses: actions/upload-artifact@v2.2.1
|
||||||
with:
|
with:
|
||||||
name: '${{ env.FILE_NAME }}'
|
name: '${{ env.FILE_NAME }}-${{ matrix.arch }}bit'
|
||||||
path: package/*
|
path: package/*
|
||||||
- name: "Package Installer (Prereqs)"
|
windows-installer:
|
||||||
|
needs: [windows]
|
||||||
|
name: 'Create Windows Installer'
|
||||||
|
runs-on: [windows-latest]
|
||||||
|
steps:
|
||||||
|
- name: "Checkout plugin"
|
||||||
|
uses: actions/checkout@v2.3.4
|
||||||
|
- name: Add msbuild to PATH
|
||||||
|
uses: microsoft/setup-msbuild@v1.0.2
|
||||||
|
- name: "Prepare innosetup"
|
||||||
|
run: |
|
||||||
|
curl "-kL" "https://files.jrsoftware.org/is/6/innosetup-6.0.3.exe" "-f" "--retry" "5" "-o" "inno.exe"
|
||||||
|
.\inno.exe /VERYSILENT /SP- /SUPPRESSMSGBOXES /NORESTART
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
continue-on-error: true
|
||||||
|
- name: Download artifacts
|
||||||
|
uses: actions/download-artifact@v2
|
||||||
|
with:
|
||||||
|
path: artifacts
|
||||||
|
- name: "Prepare package dir"
|
||||||
run: |
|
run: |
|
||||||
curl "-kL" "https://github.com/Xaymar/msvc-redist-helper/releases/download/0.1/msvc-redist-helper-64.exe" "-f" "--retry" "5" "-o" "msvc-redist-helper-64.exe"
|
curl "-kL" "https://github.com/Xaymar/msvc-redist-helper/releases/download/0.1/msvc-redist-helper-64.exe" "-f" "--retry" "5" "-o" "msvc-redist-helper-64.exe"
|
||||||
curl "-kL" "https://github.com/Xaymar/msvc-redist-helper/releases/download/0.1/msvc-redist-helper-32.exe" "-f" "--retry" "5" "-o" "msvc-redist-helper-32.exe"
|
curl "-kL" "https://github.com/Xaymar/msvc-redist-helper/releases/download/0.1/msvc-redist-helper-32.exe" "-f" "--retry" "5" "-o" "msvc-redist-helper-32.exe"
|
||||||
curl "-kL" "https://files.jrsoftware.org/is/6/innosetup-6.0.3.exe" "-f" "--retry" "5" "-o" "inno.exe"
|
$env:FILE_DATE=(Get-Date -UFormat "%F")
|
||||||
.\inno.exe /VERYSILENT /SP- /SUPPRESSMSGBOXES /NORESTART
|
$env:FILE_NAME="${{ env.PLUGIN_NAME }}-${env:FILE_DATE}-${{ github.sha }}-windows"
|
||||||
- name: "Package Installer (Compile)"
|
echo "FILE_NAME=${env:FILE_NAME}" >> ${env:GITHUB_ENV}
|
||||||
|
mkdir package
|
||||||
|
cd package
|
||||||
|
cp -r ../artifacts/${env:FILE_NAME}-32bit/* .
|
||||||
|
cp -r ../artifacts/${env:FILE_NAME}-64bit/obs-plugins/* obs-plugins
|
||||||
|
- name: "Compile"
|
||||||
run: |
|
run: |
|
||||||
& 'C:\Program Files (x86)\Inno Setup 6\ISCC.exe' /Qp ".\build64\UI\frontend-plugins\${{ env.PLUGIN_NAME }}\CI\windows\setup.iss"
|
& 'C:\Program Files (x86)\Inno Setup 6\ISCC.exe' /Qp ".\build\CI\windows\setup.iss"
|
||||||
- name: Publish installer
|
- name: "Publish"
|
||||||
if: success()
|
if: success()
|
||||||
uses: actions/upload-artifact@v2.2.0
|
uses: actions/upload-artifact@v2.2.0
|
||||||
with:
|
with:
|
||||||
name: '${{ env.FILE_NAME }}-installer'
|
name: '${{ env.FILE_NAME }}-installer'
|
||||||
path: build64/UI/frontend-plugins/SceneSwitcher/CI/windows/Output/*.exe
|
path: build/CI/windows/Output/*.exe
|
||||||
release:
|
release:
|
||||||
needs: [macos64, ubuntu64, windows]
|
needs: [macos64, ubuntu64, windows, windows-installer]
|
||||||
name: 'Create Release'
|
name: 'Create Release'
|
||||||
runs-on: [ubuntu-18.04]
|
runs-on: [ubuntu-18.04]
|
||||||
steps:
|
steps:
|
||||||
@@ -292,7 +354,8 @@ jobs:
|
|||||||
mkdir -p ${{ env.PLUGIN_NAME }}/Linux ${{ env.PLUGIN_NAME }}/MacOs ${{ env.PLUGIN_NAME }}/Windows
|
mkdir -p ${{ env.PLUGIN_NAME }}/Linux ${{ env.PLUGIN_NAME }}/MacOs ${{ env.PLUGIN_NAME }}/Windows
|
||||||
tar xf artifacts/${{ env.PLUGIN_NAME }}*-linux64.tar.gz/${{ env.PLUGIN_NAME }}*-linux64.tar.gz -C ${{ env.PLUGIN_NAME }}/Linux/
|
tar xf artifacts/${{ env.PLUGIN_NAME }}*-linux64.tar.gz/${{ env.PLUGIN_NAME }}*-linux64.tar.gz -C ${{ env.PLUGIN_NAME }}/Linux/
|
||||||
mv artifacts/${{ env.PLUGIN_NAME }}*-macos.pkg/${{ env.PLUGIN_NAME }}*-macos.pkg ${{ env.PLUGIN_NAME }}/MacOs/${{ env.PLUGIN_NAME }}.pkg
|
mv artifacts/${{ env.PLUGIN_NAME }}*-macos.pkg/${{ env.PLUGIN_NAME }}*-macos.pkg ${{ env.PLUGIN_NAME }}/MacOs/${{ env.PLUGIN_NAME }}.pkg
|
||||||
mv ./artifacts/${{ env.PLUGIN_NAME }}*-windows/* ${{ env.PLUGIN_NAME }}/Windows/
|
mv ./artifacts/${{ env.PLUGIN_NAME }}*-windows-32bit/* ${{ env.PLUGIN_NAME }}/Windows/
|
||||||
|
mv ./artifacts/${{ env.PLUGIN_NAME }}*-windows-64bit/obs-plugins/* ${{ env.PLUGIN_NAME }}/Windows/obs-plugins
|
||||||
mv ./artifacts/${{ env.PLUGIN_NAME }}*-windows-installer/*.exe ${{ env.PLUGIN_NAME }}/Windows/
|
mv ./artifacts/${{ env.PLUGIN_NAME }}*-windows-installer/*.exe ${{ env.PLUGIN_NAME }}/Windows/
|
||||||
rm ${{ env.PLUGIN_NAME }}/Windows/obs-plugins/32bit/advanced-scene-switcher.pdb
|
rm ${{ env.PLUGIN_NAME }}/Windows/obs-plugins/32bit/advanced-scene-switcher.pdb
|
||||||
rm ${{ env.PLUGIN_NAME }}/Windows/obs-plugins/64bit/advanced-scene-switcher.pdb
|
rm ${{ env.PLUGIN_NAME }}/Windows/obs-plugins/64bit/advanced-scene-switcher.pdb
|
||||||
|
|||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -4,3 +4,6 @@
|
|||||||
[submodule "deps/websocketpp"]
|
[submodule "deps/websocketpp"]
|
||||||
path = deps/websocketpp
|
path = deps/websocketpp
|
||||||
url = https://github.com/zaphoyd/websocketpp.git
|
url = https://github.com/zaphoyd/websocketpp.git
|
||||||
|
[submodule "deps/opencv"]
|
||||||
|
path = deps/opencv
|
||||||
|
url = https://github.com/opencv/opencv.git
|
||||||
|
|||||||
152
BUILDING.md
Normal file
152
BUILDING.md
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
# Compiling the plugin
|
||||||
|
|
||||||
|
You have the option to ...
|
||||||
|
- either add the plugin to the OBS source tree directly and build the plugin while building OBS itself. (**in tree**)
|
||||||
|
- or you can move the sources of this plugin outside of the OBS source tree and build it separately from OBS. (**out of tree**)
|
||||||
|
|
||||||
|
As both methods require you to have a working [OBS Studio development environment](https://obsproject.com/wiki/install-instructions), [Qt](https://download.qt.io/official_releases/qt/5.15/5.15.2/) and [CMake](https://cmake.org/download/) it is recommended to build the plugin in tree as it is easier to set up and will enable straightforward debugging.
|
||||||
|
|
||||||
|
Note that your Qt install must include the QtConcurrent module.
|
||||||
|
|
||||||
|
## Compiling in tree (recommended)
|
||||||
|
Add the "SceneSwitcher" source directory to your obs-studio source directory under obs-studio/UI/frontend-plugins/:
|
||||||
|
```
|
||||||
|
cd obs-studio/UI/frontend-plugins/
|
||||||
|
git clone --recursive https://github.com/WarmUpTill/SceneSwitcher.git
|
||||||
|
```
|
||||||
|
|
||||||
|
Then modify the obs-studio/UI/frontend-plugins/CMakeLists.txt file and add an entry for the scene switcher:
|
||||||
|
```
|
||||||
|
add_subdirectory(SceneSwitcher)
|
||||||
|
```
|
||||||
|
|
||||||
|
Now follow the [build instructions for obs-studio](https://obsproject.com/wiki/install-instructions) for your particular platform.
|
||||||
|
|
||||||
|
Note that on Linux systems it might be necessary to additionally install the following packages to fulfill the dependencies to `XTest`, `XScreensaver` and `OpenCV` - exact command may differ:
|
||||||
|
```
|
||||||
|
sudo apt-get install \
|
||||||
|
libxtst-dev \
|
||||||
|
libxss-dev \
|
||||||
|
libopencv-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Compiling out of tree
|
||||||
|
### Prerequisites
|
||||||
|
You'll need [Qt](https://download.qt.io/official_releases/qt/5.15/5.15.2/), [CMake](https://cmake.org/download/) and a working [OBS Studio development environment](https://obsproject.com/wiki/install-instructions) installed on your computer.
|
||||||
|
Once you've set this up, do the following:
|
||||||
|
```
|
||||||
|
git clone --recursive https://github.com/WarmUpTill/SceneSwitcher.git
|
||||||
|
cd SceneSwitcher
|
||||||
|
mkdir build && cd build
|
||||||
|
```
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
In cmake-gui, you'll have to set these CMake variables :
|
||||||
|
- **BUILD_OUT_OF_TREE** (bool) : true
|
||||||
|
|
||||||
|
- **LIBOBS_LIB** (filepath) : location of the obs.lib file
|
||||||
|
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
|
||||||
|
code of OBS Studio, located at [source_directory]/libobs/.
|
||||||
|
|
||||||
|
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the obs-frontend-api.lib file
|
||||||
|
(usually in the same place as LIBOBS_LIB)
|
||||||
|
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api
|
||||||
|
subfolder in the source code of OBS Studio, located at [source_directory]/UI/obs-frontend-api.
|
||||||
|
|
||||||
|
- **CURL_LIBRARY** (filepath) : location of the libcurl.lib file
|
||||||
|
(part of the dependencies2019/win64/bin folder used to build OBS)
|
||||||
|
- **CURL_INCLUDE_DIR** (path) : location of the curl
|
||||||
|
subfolder in OBS dependencies folder: ".../dependencies2019/win64/include/"
|
||||||
|
|
||||||
|
|
||||||
|
Assuming that you set up Qt via QT installer:
|
||||||
|
- **Qt5Core_DIR** (path) : C:/Qt/5.15.2/msvc2019_64/lib/cmake/Qt5Core
|
||||||
|
- **Qt5Gui_DIR** (path): C:/Qt/5.15.2/msvc2019_64/lib/cmake/Qt5Gui
|
||||||
|
- **Qt5Widgets_DIR** (path) : C:/Qt/5.15.2/msvc2019_64/lib/cmake/Qt5Widgets
|
||||||
|
|
||||||
|
Just keep hitting configure until all the vars are filled out. Then hit generate.
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
Install dependencies `XTest`, `XScreensaver` and `OpenCV` - exact command may differ:
|
||||||
|
```
|
||||||
|
sudo apt-get install \
|
||||||
|
libxtst-dev \
|
||||||
|
libxss-dev \
|
||||||
|
libopencv-dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Most versions of Linux you can use cmake-gui or the command line.
|
||||||
|
|
||||||
|
**For the command line:**
|
||||||
|
```
|
||||||
|
# [...] are placeholders
|
||||||
|
cmake -DBUILD_OUT_OF_TREE=1 \
|
||||||
|
-DLIBOBS_INCLUDE_DIR=[...]/obs-studio/libobs/ \
|
||||||
|
-DLIBOBS_LIB=[...]/libobs.so \
|
||||||
|
-DLIBOBS_FRONTEND_INCLUDE_DIR=[...]/obs-studio/UI/obs-frontend-api/ \
|
||||||
|
-DLIBOBS_FRONTEND_API_LIB=[...]/libobs-frontend-api.so \
|
||||||
|
-DCMAKE_INSTALL_PREFIX=/usr ..
|
||||||
|
make -j4
|
||||||
|
sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
For cmake-gui you'll have to set the following variables:
|
||||||
|
- **BUILD_OUT_OF_TREE** (bool) : true
|
||||||
|
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
|
||||||
|
code of OBS Studio, located at [source_directory]/libobs/.
|
||||||
|
- **LIBOBS_LIB** (filepath) : location of the libobs.so file (usually CMake finds
|
||||||
|
this, but if not it'll usually be in /usr/lib/libobs.so)
|
||||||
|
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.so
|
||||||
|
file (usually in the same place as LIBOBS_LIB)
|
||||||
|
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api
|
||||||
|
subfolder in the source code of OBS Studio, located at
|
||||||
|
[source_directory]/UI/obs-frontend-api.
|
||||||
|
|
||||||
|
Assuming that you installed Qt via your system package manager, it should be
|
||||||
|
found automatically. If not, then usually you'll find it in something like:
|
||||||
|
- **Qt5Core_DIR** (path) : /usr/lib64/cmake/Qt5Core
|
||||||
|
- **Qt5Gui_DIR** (path): /usr/lib64/cmake/Qt5Gui
|
||||||
|
- **Qt5Widgets_DIR** (path) : /usr/lib64/cmake/Qt5Widgets
|
||||||
|
|
||||||
|
Just keep hitting configure until all the vars are filled out. Then hit generate.
|
||||||
|
|
||||||
|
Then open a terminal in the build folder and type:
|
||||||
|
```
|
||||||
|
make -j4
|
||||||
|
sudo make install
|
||||||
|
```
|
||||||
|
NOTE: The Linux version of this plugin is dependent on libXScrnSaver, libcurl and libXtst.
|
||||||
|
|
||||||
|
### OS X
|
||||||
|
In cmake-gui, you'll have to set these CMake variables :
|
||||||
|
- **BUILD_OUT_OF_TREE** (bool) : true
|
||||||
|
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
|
||||||
|
code of OBS Studio, located at [source_directory]/libobs/.
|
||||||
|
- **LIBOBS_LIB** (filepath) : location of the libobs.0.dylib file (usually
|
||||||
|
in /Applications/OBS.app/Contents/Resources/bin/libobs.0.dylib)
|
||||||
|
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.0.dylib
|
||||||
|
file (usually in usually in /Applications/OBS.app/Contents/Resources/bin/libobs-frontend-api.0.dylib)
|
||||||
|
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api subfolder
|
||||||
|
in the source code of OBS Studio, located at [source_directory]/UI/obs-frontend-api.
|
||||||
|
|
||||||
|
Assuming that you installed Qt via the regular Qt App way:
|
||||||
|
- **Qt5Core_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5Core
|
||||||
|
- **Qt5Widgets_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5Widgets
|
||||||
|
- **Qt5MacExtras_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5MacExtras
|
||||||
|
|
||||||
|
|
||||||
|
Just keep hitting configure until all the vars are filled out. Then hit generate.
|
||||||
|
|
||||||
|
Open xcode (or a terminal, depending on the build type you chose), build and copy
|
||||||
|
the advanced-scene-switcher.so file to 'Library/Application Support/obs-studio/plugins/advanced-scene-switcher/bin/'
|
||||||
|
And the 'data' folder to 'Library/Application Support/obs-studio/plugins/advanced-scene-switcher/'.
|
||||||
|
|
||||||
|
Note that you might have to adjust the library search paths using the install_name_tool if you want the plugin to run on machines other than your build machine:
|
||||||
|
```
|
||||||
|
install_name_tool -change @rpath/libobs-frontend-api.dylib @executable_path/../Frameworks/libobs-frontend-api.dylib UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||||
|
install_name_tool -change @rpath/libobs.0.dylib @executable_path/../Frameworks/libobs.0.dylib UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||||
|
install_name_tool -change /usr/local/opt/qt5/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||||
|
install_name_tool -change /usr/local/opt/qt5/lib/QtGui.framework/Versions/5/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||||
|
install_name_tool -change /usr/local/opt/qt5/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
||||||
|
```
|
||||||
5
CI/linux/debian/changelog
Normal file
5
CI/linux/debian/changelog
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
obs-scene-switcher (0.1+testonly) focal; urgency=medium
|
||||||
|
|
||||||
|
* Initial release (Closes: #123456)
|
||||||
|
|
||||||
|
-- Joao Eriberto Mota Filho <eriberto@debian.org> Fri, 03 Sep 2021 11:39:52 -0300
|
||||||
22
CI/linux/debian/control
Normal file
22
CI/linux/debian/control
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
Source: obs-scene-switcher
|
||||||
|
Section: video
|
||||||
|
Priority: optional
|
||||||
|
Maintainer: Joao Eriberto Mota Filho <eriberto@debian.org>
|
||||||
|
Build-Depends: cmake,
|
||||||
|
debhelper-compat (= 12),
|
||||||
|
libcurl4-openssl-dev,
|
||||||
|
libobs-dev,
|
||||||
|
libxtst-dev,
|
||||||
|
qtbase5-dev,
|
||||||
|
libxss-dev,
|
||||||
|
libopencv-dev
|
||||||
|
Standards-Version: 4.6.0
|
||||||
|
Homepage: https://obsproject.com/forum/resources/advanced-scene-switcher.395/
|
||||||
|
Rules-Requires-Root: no
|
||||||
|
|
||||||
|
Package: obs-scene-switcher
|
||||||
|
Architecture: any
|
||||||
|
Depends: ${misc:Depends}, ${shlibs:Depends}
|
||||||
|
Description: automated scene switcher for OBS Studio (plugin)
|
||||||
|
Advanced Scene Switcher is based on the built in scene switcher. It extends
|
||||||
|
its functionality by adding several features.
|
||||||
60
CI/linux/debian/copyright
Normal file
60
CI/linux/debian/copyright
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||||
|
Upstream-Name: SceneSwitcher
|
||||||
|
Upstream-Contact: https://github.com/WarmUpTill/SceneSwitcher/issues
|
||||||
|
Source: https://github.com/WarmUpTill/SceneSwitcher
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: 2016-2021 WarmUpTill <WarmUpTill@web.de>
|
||||||
|
License: GPL-2
|
||||||
|
|
||||||
|
Files: cmake/GetGitRevisionDescription.cmake
|
||||||
|
cmake/GetGitRevisionDescription.cmake.in
|
||||||
|
Copyright: 2009-2013 Iowa State University
|
||||||
|
2013-2020 Contributors
|
||||||
|
2013-2020 Ryan Pavlik
|
||||||
|
License: BSL-1.0
|
||||||
|
|
||||||
|
Files: debian/*
|
||||||
|
Copyright: 2021 Joao Eriberto Mota Filho <eriberto@debian.org>
|
||||||
|
License: BSL-1.0
|
||||||
|
|
||||||
|
License: GPL-2
|
||||||
|
This package is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; version 2.
|
||||||
|
.
|
||||||
|
This package is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the GNU General
|
||||||
|
Public License version 2 can be found in "/usr/share/common-licenses/GPL-2".
|
||||||
|
|
||||||
|
License: BSL-1.0
|
||||||
|
Boost Software License - Version 1.0 - August 17th, 2003
|
||||||
|
.
|
||||||
|
Permission is hereby granted, free of charge, to any person or organization
|
||||||
|
obtaining a copy of the software and accompanying documentation covered by
|
||||||
|
this license (the "Software") to use, reproduce, display, distribute,
|
||||||
|
execute, and transmit the Software, and to prepare derivative works of the
|
||||||
|
Software, and to permit third-parties to whom the Software is furnished to
|
||||||
|
do so, all subject to the following:
|
||||||
|
.
|
||||||
|
The copyright notices in the Software and this entire statement, including
|
||||||
|
the above license grant, this restriction and the following disclaimer,
|
||||||
|
must be included in all copies of the Software, in whole or in part, and
|
||||||
|
all derivative works of the Software, unless such copies or derivative
|
||||||
|
works are solely in the form of machine-executable object code generated by
|
||||||
|
a source language processor.
|
||||||
|
.
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
|
||||||
|
SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
|
||||||
|
FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
|
||||||
|
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||||
|
DEALINGS IN THE SOFTWARE.
|
||||||
16
CI/linux/debian/rules
Normal file
16
CI/linux/debian/rules
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
#export DH_VERBOSE = 1
|
||||||
|
|
||||||
|
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||||
|
|
||||||
|
export QT_SELECT = qt5
|
||||||
|
|
||||||
|
%:
|
||||||
|
dh $@
|
||||||
|
|
||||||
|
|
||||||
|
dh_auto_configure -- -DBUILD_OUT_OF_TREE=1 \
|
||||||
|
-DLIBOBS_INCLUDE_DIR=/usr/include/obs \
|
||||||
|
-DLIBOBS_LIB=/usr/lib/${DEB_TARGET_MULTIARCH}/libobs.so \
|
||||||
|
-DLIBOBS_FRONTEND_INCLUDE_DIR=/usr/include/obs \
|
||||||
|
-DLIBOBS_FRONTEND_API_LIB=/usr/lib/${DEB_TARGET_MULTIARCH}/libobs-frontend-api.so
|
||||||
1
CI/linux/debian/source/format
Normal file
1
CI/linux/debian/source/format
Normal file
@@ -0,0 +1 @@
|
|||||||
|
3.0 (native)
|
||||||
@@ -46,6 +46,294 @@
|
|||||||
<key>UID</key>
|
<key>UID</key>
|
||||||
<integer>0</integer>
|
<integer>0</integer>
|
||||||
</dict>
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_objdetect.4.5.3.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_features2d.4.5.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_core.4.5.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_calib3d.4.5.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_calib3d.4.5.3.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_imgproc.4.5.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_features2d.4.5.3.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_core.4.5.3.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_flann.4.5.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_calib3d.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_objdetect.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_imgproc.4.5.3.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_flann.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_imgproc.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_flann.4.5.3.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_features2d.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_core.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CHILDREN</key>
|
||||||
|
<array/>
|
||||||
|
<key>GID</key>
|
||||||
|
<integer>80</integer>
|
||||||
|
<key>PATH</key>
|
||||||
|
<string>../../deps/opencv/build/lib/libopencv_objdetect.4.5.dylib</string>
|
||||||
|
<key>PATH_TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>PERMISSIONS</key>
|
||||||
|
<integer>493</integer>
|
||||||
|
<key>TYPE</key>
|
||||||
|
<integer>3</integer>
|
||||||
|
<key>UID</key>
|
||||||
|
<integer>0</integer>
|
||||||
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>GID</key>
|
<key>GID</key>
|
||||||
<integer>80</integer>
|
<integer>80</integer>
|
||||||
|
|||||||
663
CMakeLists.txt
663
CMakeLists.txt
@@ -1,317 +1,408 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.14)
|
||||||
|
|
||||||
project(advanced-scene-switcher)
|
project(advanced-scene-switcher)
|
||||||
add_definitions(-DASIO_STANDALONE)
|
|
||||||
|
|
||||||
# generate version info
|
if(NOT CMAKE_BUILD_TYPE)
|
||||||
|
set(CMAKE_BUILD_TYPE RELWITHDEBINFO)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Compiler settings
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
set(CMAKE_CXX_STANDARD_REQUIRED YES)
|
||||||
|
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCC
|
||||||
|
OR CMAKE_COMPILER_IS_GNUCXX
|
||||||
|
OR CMAKE_COMPILER_IS_CLANG)
|
||||||
|
set(CMAKE_CXX_FLAGS
|
||||||
|
"-Wall -Wextra -Wvla -Wno-unused-function -Wno-missing-field-initializers ${CMAKE_CXX_FLAGS} -fno-strict-aliasing"
|
||||||
|
)
|
||||||
|
set(CMAKE_C_FLAGS
|
||||||
|
"-Wall -Wextra -Wvla -Wno-unused-function -Werror-implicit-function-declaration -Wno-missing-braces -Wno-missing-field-initializers ${CMAKE_C_FLAGS} -std=gnu99 -fno-strict-aliasing"
|
||||||
|
)
|
||||||
|
|
||||||
|
option(USE_LIBC++ "Use libc++ instead of libstdc++" ${APPLE})
|
||||||
|
if(USE_LIBC++)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libc++")
|
||||||
|
endif()
|
||||||
|
elseif(MSVC)
|
||||||
|
if(CMAKE_CXX_FLAGS MATCHES "/W[0-4]")
|
||||||
|
string(REGEX REPLACE "/W[0-4]" "/W4" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
|
||||||
|
else()
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Disable pointless constant condition warnings
|
||||||
|
set(CMAKE_CXX_FLAGS
|
||||||
|
"${CMAKE_CXX_FLAGS} /wd4127 /wd4201 /wd4456 /wd4457 /wd4458 /wd4459 /wd4595"
|
||||||
|
)
|
||||||
|
add_definitions(-DUNICODE -D_UNICODE -D_CRT_SECURE_NO_WARNINGS
|
||||||
|
-D_CRT_NONSTDC_NO_WARNINGS)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Generate version info
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
||||||
include(GetGitRevisionDescription)
|
include(GetGitRevisionDescription)
|
||||||
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
||||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.cpp.in" "${CMAKE_CURRENT_BINARY_DIR}/src/version.cpp" @ONLY)
|
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/version.cpp.in"
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/src/version.cpp" @ONLY)
|
||||||
|
|
||||||
|
# Windows installer
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
get_filename_component(ISS_PLUGIN_FILES_DIR "${CMAKE_BINARY_DIR}\\..\\package" ABSOLUTE)
|
get_filename_component(ISS_PLUGIN_FILES_DIR
|
||||||
file(TO_NATIVE_PATH "${ISS_PLUGIN_FILES_DIR}" ISS_PLUGIN_FILES_DIR)
|
"${CMAKE_BINARY_DIR}\\..\\package" ABSOLUTE)
|
||||||
get_filename_component(ISS_MSVC_REDIST_HELPER_DIR "${CMAKE_PACKAGE_PREFIX}\\.." ABSOLUTE)
|
file(TO_NATIVE_PATH "${ISS_PLUGIN_FILES_DIR}" ISS_PLUGIN_FILES_DIR)
|
||||||
file(TO_NATIVE_PATH "${ISS_MSVC_REDIST_HELPER_DIR}" ISS_MSVC_REDIST_HELPER_DIR)
|
get_filename_component(ISS_MSVC_REDIST_HELPER_DIR "${CMAKE_BINARY_DIR}\\.."
|
||||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CI/windows/setup.iss.in" "${CMAKE_CURRENT_BINARY_DIR}/CI/windows/setup.iss" @ONLY)
|
ABSOLUTE)
|
||||||
endif()
|
file(TO_NATIVE_PATH "${ISS_MSVC_REDIST_HELPER_DIR}"
|
||||||
|
ISS_MSVC_REDIST_HELPER_DIR)
|
||||||
if(WIN32)
|
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CI/windows/setup.iss.in"
|
||||||
get_filename_component(ISS_PLUGIN_FILES_DIR "${CMAKE_BINARY_DIR}\\..\\package" ABSOLUTE)
|
"${CMAKE_CURRENT_BINARY_DIR}/CI/windows/setup.iss" @ONLY)
|
||||||
file(TO_NATIVE_PATH "${ISS_PLUGIN_FILES_DIR}" ISS_PLUGIN_FILES_DIR)
|
|
||||||
get_filename_component(ISS_MSVC_REDIST_HELPER_DIR "${CMAKE_PACKAGE_PREFIX}\\.." ABSOLUTE)
|
|
||||||
file(TO_NATIVE_PATH "${ISS_MSVC_REDIST_HELPER_DIR}" ISS_MSVC_REDIST_HELPER_DIR)
|
|
||||||
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/CI/windows/setup.iss.in" "${CMAKE_CURRENT_BINARY_DIR}/CI/windows/setup.iss" @ONLY)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Out of tree specific settings
|
||||||
if(BUILD_OUT_OF_TREE)
|
if(BUILD_OUT_OF_TREE)
|
||||||
set(CMAKE_PREFIX_PATH "${QTDIR}")
|
set(CMAKE_PREFIX_PATH "${QTDIR}")
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/external")
|
find_package(Qt5Core REQUIRED)
|
||||||
|
find_package(Qt5Widgets REQUIRED)
|
||||||
|
find_package(LibObs)
|
||||||
|
find_package(LibObs-frontend-api)
|
||||||
|
if(LibObs_FOUND)
|
||||||
|
set(LIBOBS_LIB ${LIBOBS_LIBRARIES})
|
||||||
|
set(LIBOBS_INCLUDE_DIR ${LIBOBS_INCLUDE_DIRS})
|
||||||
|
endif()
|
||||||
|
if(LibObs-frontend-api_FOUND)
|
||||||
|
set(LIBOBS_FRONTEND_API_LIB ${LIBOBS-FRONTEND-API_LIBRARIES})
|
||||||
|
set(LIBOBS_FRONTEND_INCLUDE_DIR ${LIBOBS-FRONTEND-API_INCLUDE_DIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
include(external/FindLibObs.cmake)
|
if(NOT LIBOBS_LIB)
|
||||||
find_package(LibObs REQUIRED)
|
message(FATAL_ERROR "obs library not found - please set LIBOBS_LIB")
|
||||||
find_package(Qt5Core REQUIRED)
|
endif()
|
||||||
find_package(Qt5Widgets REQUIRED)
|
if(NOT LIBOBS_FRONTEND_API_LIB)
|
||||||
find_package(Libcurl REQUIRED)
|
message(
|
||||||
find_path(LIBOBS_FRONTEND_INCLUDE_DIR HINTS ${LIBOBS_INCLUDE_DIRS})
|
FATAL_ERROR
|
||||||
find_file(LIBOBS_FRONTEND_API_LIB NAMES libobs-frontend-api.* HINTS ${LIBOBS_LIB} )
|
"libobs frontend-api library not found - please set LIBOBS_FRONTEND_API_LIB"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if(NOT LIBOBS_INCLUDE_DIR)
|
||||||
|
message(
|
||||||
|
FATAL_ERROR "obs.hpp header not found - please set LIBOBS_INCLUDE_DIR")
|
||||||
|
endif()
|
||||||
|
if(NOT LIBOBS_FRONTEND_INCLUDE_DIR)
|
||||||
|
message(
|
||||||
|
FATAL_ERROR
|
||||||
|
" obs-frontend-api.h not found - please set LIBOBS_FRONTEND_INCLUDE_DIR"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
include_directories("${LIBOBS_INCLUDE_DIR}" "${LIBOBS_FRONTEND_INCLUDE_DIR}"
|
||||||
|
${Qt5Core_INCLUDES} ${Qt5Widgets_INCLUDES})
|
||||||
|
|
||||||
|
find_package(CURL REQUIRED)
|
||||||
|
include_directories("${CURL_INCLUDE_DIRS}")
|
||||||
|
|
||||||
|
# Backwards compatability with older OBS versions
|
||||||
|
if(LibObs_VERSION_MAJOR GREATER_EQUAL 27)
|
||||||
|
add_definitions(-DVCAM_SUPPORTED)
|
||||||
|
else()
|
||||||
|
message(
|
||||||
|
WARNING
|
||||||
|
"OBS version ${LibObs_VERSION_MAJOR} found - disabling virtual camera functionality"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if(LibObs_VERSION_MAJOR GREATER_EQUAL 26)
|
||||||
|
add_definitions(-DREPLAYBUFFER_SUPPORTED)
|
||||||
|
else()
|
||||||
|
message(
|
||||||
|
WARNING
|
||||||
|
"OBS version ${LibObs_VERSION_MAJOR} found - disabling replay buffer functionality"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
find_package(Libcurl REQUIRED)
|
||||||
|
include_directories("${LIBCURL_INCLUDE_DIRS}")
|
||||||
|
add_definitions(-DVCAM_SUPPORTED)
|
||||||
|
add_definitions(-DREPLAYBUFFER_SUPPORTED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# Platform specific settings
|
||||||
if(APPLE)
|
if(APPLE)
|
||||||
find_library(COCOA Cocoa)
|
find_library(COCOA Cocoa)
|
||||||
if(BUILD_OUT_OF_TREE)
|
if(BUILD_OUT_OF_TREE)
|
||||||
find_package(Qt5MacExtras REQUIRED)
|
find_package(Qt5MacExtras REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
include_directories(${COCOA})
|
include_directories(${COCOA})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if(UNIX AND NOT APPLE)
|
if(UNIX AND NOT APPLE)
|
||||||
find_package(X11 REQUIRED)
|
find_package(X11 REQUIRED COMPONENTS Xtst Xss)
|
||||||
link_libraries(${X11_LIBRARIES})
|
link_libraries(${X11_LIBRARIES})
|
||||||
include_directories(${X11_INCLUDE_DIR})
|
include_directories("${X11_INCLUDE_DIR}" "${X11_Xtst_INCLUDE_PATH}"
|
||||||
|
"${X11_Xss_INCLUDE_PATH}")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
include_directories(
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/asio/asio/include"
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/websocketpp"
|
|
||||||
)
|
|
||||||
|
|
||||||
set(advanced-scene-switcher_HEADERS
|
|
||||||
${advanced-scene-switcher_HEADERS}
|
|
||||||
src/headers/advanced-scene-switcher.hpp
|
|
||||||
src/headers/switcher-data-structs.hpp
|
|
||||||
src/headers/scene-group.hpp
|
|
||||||
src/headers/scene-trigger.hpp
|
|
||||||
src/headers/switch-audio.hpp
|
|
||||||
src/headers/switch-executable.hpp
|
|
||||||
src/headers/switch-file.hpp
|
|
||||||
src/headers/switch-idle.hpp
|
|
||||||
src/headers/switch-media.hpp
|
|
||||||
src/headers/switch-network.hpp
|
|
||||||
src/headers/switch-pause.hpp
|
|
||||||
src/headers/switch-random.hpp
|
|
||||||
src/headers/switch-screen-region.hpp
|
|
||||||
src/headers/switch-time.hpp
|
|
||||||
src/headers/switch-transitions.hpp
|
|
||||||
src/headers/switch-window.hpp
|
|
||||||
src/headers/switch-sequence.hpp
|
|
||||||
src/headers/switch-video.hpp
|
|
||||||
src/headers/switch-generic.hpp
|
|
||||||
src/headers/macro-action-edit.hpp
|
|
||||||
src/headers/macro-action-audio.hpp
|
|
||||||
src/headers/macro-action-file.hpp
|
|
||||||
src/headers/macro-action-filter.hpp
|
|
||||||
src/headers/macro-action-hotkey.hpp
|
|
||||||
src/headers/macro-action-macro.hpp
|
|
||||||
src/headers/macro-action-media.hpp
|
|
||||||
src/headers/macro-action-plugin-state.hpp
|
|
||||||
src/headers/macro-action-recording.hpp
|
|
||||||
src/headers/macro-action-replay-buffer.hpp
|
|
||||||
src/headers/macro-action-run.hpp
|
|
||||||
src/headers/macro-action-scene-order.hpp
|
|
||||||
src/headers/macro-action-scene-switch.hpp
|
|
||||||
src/headers/macro-action-scene-transform.hpp
|
|
||||||
src/headers/macro-action-scene-visibility.hpp
|
|
||||||
src/headers/macro-action-source.hpp
|
|
||||||
src/headers/macro-action-streaming.hpp
|
|
||||||
src/headers/macro-action-virtual-cam.hpp
|
|
||||||
src/headers/macro-action-wait.hpp
|
|
||||||
src/headers/macro-condition-edit.hpp
|
|
||||||
src/headers/macro-condition-audio.hpp
|
|
||||||
src/headers/macro-condition-date.hpp
|
|
||||||
src/headers/macro-condition-macro.hpp
|
|
||||||
src/headers/macro-condition-file.hpp
|
|
||||||
src/headers/macro-condition-filter.hpp
|
|
||||||
src/headers/macro-condition-hotkey.hpp
|
|
||||||
src/headers/macro-condition-idle.hpp
|
|
||||||
src/headers/macro-condition-media.hpp
|
|
||||||
src/headers/macro-condition-plugin-state.hpp
|
|
||||||
src/headers/macro-condition-process.hpp
|
|
||||||
src/headers/macro-condition-recording.hpp
|
|
||||||
src/headers/macro-condition-region.hpp
|
|
||||||
src/headers/macro-condition-replay-buffer.hpp
|
|
||||||
src/headers/macro-condition-scene-order.hpp
|
|
||||||
src/headers/macro-condition-scene.hpp
|
|
||||||
src/headers/macro-condition-source.hpp
|
|
||||||
src/headers/macro-condition-streaming.hpp
|
|
||||||
src/headers/macro-condition-timer.hpp
|
|
||||||
src/headers/macro-condition-video.hpp
|
|
||||||
src/headers/macro-condition-virtual-cam.hpp
|
|
||||||
src/headers/macro-condition-window.hpp
|
|
||||||
src/headers/macro.hpp
|
|
||||||
src/headers/macro-selection.hpp
|
|
||||||
src/headers/curl-helper.hpp
|
|
||||||
src/headers/hotkey.hpp
|
|
||||||
src/headers/scene-selection.hpp
|
|
||||||
src/headers/screenshot-helper.hpp
|
|
||||||
src/headers/name-dialog.hpp
|
|
||||||
src/headers/duration-control.hpp
|
|
||||||
src/headers/section.hpp
|
|
||||||
src/headers/platform-funcs.hpp
|
|
||||||
src/headers/utility.hpp
|
|
||||||
src/headers/volume-control.hpp
|
|
||||||
src/headers/version.h
|
|
||||||
)
|
|
||||||
|
|
||||||
set(advanced-scene-switcher_SOURCES
|
|
||||||
${advanced-scene-switcher_SOURCES}
|
|
||||||
src/advanced-scene-switcher.cpp
|
|
||||||
src/advanced-scene-switcher-module.c
|
|
||||||
src/switcher-data-structs.cpp
|
|
||||||
src/scene-group.cpp
|
|
||||||
src/scene-trigger.cpp
|
|
||||||
src/switch-transitions.cpp
|
|
||||||
src/switch-screen-region.cpp
|
|
||||||
src/switch-priority.cpp
|
|
||||||
src/switch-executable.cpp
|
|
||||||
src/switch-idle.cpp
|
|
||||||
src/switch-sequence.cpp
|
|
||||||
src/switch-file.cpp
|
|
||||||
src/switch-window.cpp
|
|
||||||
src/switch-media.cpp
|
|
||||||
src/switch-network.cpp
|
|
||||||
src/hotkey.cpp
|
|
||||||
src/general.cpp
|
|
||||||
src/switch-pause.cpp
|
|
||||||
src/switch-random.cpp
|
|
||||||
src/switch-time.cpp
|
|
||||||
src/switch-audio.cpp
|
|
||||||
src/switch-video.cpp
|
|
||||||
src/switch-generic.cpp
|
|
||||||
src/macro-action-edit.cpp
|
|
||||||
src/macro-action-audio.cpp
|
|
||||||
src/macro-action-file.cpp
|
|
||||||
src/macro-action-filter.cpp
|
|
||||||
src/macro-action-hotkey.cpp
|
|
||||||
src/macro-action-macro.cpp
|
|
||||||
src/macro-action-media.cpp
|
|
||||||
src/macro-action-plugin-state.cpp
|
|
||||||
src/macro-action-recording.cpp
|
|
||||||
src/macro-action-replay-buffer.cpp
|
|
||||||
src/macro-action-run.cpp
|
|
||||||
src/macro-action-scene-order.cpp
|
|
||||||
src/macro-action-scene-switch.cpp
|
|
||||||
src/macro-action-scene-transform.cpp
|
|
||||||
src/macro-action-scene-visibility.cpp
|
|
||||||
src/macro-action-source.cpp
|
|
||||||
src/macro-action-streaming.cpp
|
|
||||||
src/macro-action-virtual-cam.cpp
|
|
||||||
src/macro-action-wait.cpp
|
|
||||||
src/macro-condition-edit.cpp
|
|
||||||
src/macro-condition-audio.cpp
|
|
||||||
src/macro-condition-date.cpp
|
|
||||||
src/macro-condition-macro.cpp
|
|
||||||
src/macro-condition-file.cpp
|
|
||||||
src/macro-condition-filter.cpp
|
|
||||||
src/macro-condition-hotkey.cpp
|
|
||||||
src/macro-condition-idle.cpp
|
|
||||||
src/macro-condition-media.cpp
|
|
||||||
src/macro-condition-plugin-state.cpp
|
|
||||||
src/macro-condition-process.cpp
|
|
||||||
src/macro-condition-recording.cpp
|
|
||||||
src/macro-condition-region.cpp
|
|
||||||
src/macro-condition-replay-buffer.cpp
|
|
||||||
src/macro-condition-scene-order.cpp
|
|
||||||
src/macro-condition-scene.cpp
|
|
||||||
src/macro-condition-source.cpp
|
|
||||||
src/macro-condition-streaming.cpp
|
|
||||||
src/macro-condition-timer.cpp
|
|
||||||
src/macro-condition-video.cpp
|
|
||||||
src/macro-condition-virtual-cam.cpp
|
|
||||||
src/macro-condition-window.cpp
|
|
||||||
src/macro.cpp
|
|
||||||
src/macro-selection.cpp
|
|
||||||
src/macro-tab.cpp
|
|
||||||
src/curl-helper.cpp
|
|
||||||
src/scene-selection.cpp
|
|
||||||
src/screenshot-helper.cpp
|
|
||||||
src/name-dialog.cpp
|
|
||||||
src/duration-control.cpp
|
|
||||||
src/section.cpp
|
|
||||||
src/utility.cpp
|
|
||||||
src/volume-control.cpp
|
|
||||||
src/version.cpp
|
|
||||||
)
|
|
||||||
|
|
||||||
set(advanced-scene-switcher_UI
|
|
||||||
${advanced-scene-switcher_UI}
|
|
||||||
forms/advanced-scene-switcher.ui
|
|
||||||
)
|
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
set(advanced-scene-switcher_PLATFORM_SOURCES
|
||||||
|
src/win/advanced-scene-switcher-win.cpp)
|
||||||
set(advanced-scene-switcher_PLATFORM_SOURCES
|
|
||||||
src/win/advanced-scene-switcher-win.cpp)
|
|
||||||
elseif(APPLE)
|
elseif(APPLE)
|
||||||
set(advanced-scene-switcher_PLATFORM_SOURCES
|
set(advanced-scene-switcher_PLATFORM_SOURCES
|
||||||
src/osx/advanced-scene-switcher-osx.mm)
|
src/osx/advanced-scene-switcher-osx.mm)
|
||||||
set_source_files_properties(advanced-scene-switcher-osx.mm
|
set_source_files_properties(advanced-scene-switcher-osx.mm
|
||||||
PROPERTIES COMPILE_FLAGS "-fobjc-arc")
|
PROPERTIES COMPILE_FLAGS "-fobjc-arc")
|
||||||
set(advanced-scene-switcher_PLATFORM_LIBS
|
set(advanced-scene-switcher_PLATFORM_LIBS ${COCOA})
|
||||||
${COCOA})
|
|
||||||
else()
|
else()
|
||||||
set(advanced-scene-switcher_PLATFORM_SOURCES
|
set(advanced-scene-switcher_PLATFORM_SOURCES
|
||||||
src/linux/advanced-scene-switcher-nix.cpp)
|
src/linux/advanced-scene-switcher-nix.cpp)
|
||||||
set(advanced-scene-switcher_PLATFORM_LIBS
|
set(advanced-scene-switcher_PLATFORM_LIBS Xss)
|
||||||
Xss)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
qt5_wrap_ui(advanced-scene-switcher_UI_HEADERS
|
# asio and websocketpp
|
||||||
${advanced-scene-switcher_UI}
|
add_definitions(-DASIO_STANDALONE)
|
||||||
${advanced-scene-switcher_PLATFORM_UI})
|
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/deps/asio/asio/include"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/deps/websocketpp")
|
||||||
|
if(WIN32)
|
||||||
|
add_definitions(-D_WEBSOCKETPP_CPP11_STL_)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_library(advanced-scene-switcher MODULE
|
# opencv
|
||||||
${advanced-scene-switcher_HEADERS}
|
find_package(OpenCV REQUIRED)
|
||||||
${advanced-scene-switcher_SOURCES}
|
include_directories("${OpenCV_INCLUDE_DIRS}")
|
||||||
${advanced-scene-switcher_UI_HEADERS}
|
|
||||||
${advanced-scene-switcher_PLATFORM_SOURCES}
|
|
||||||
${advanced-scene-switcher_PLATFORM_HEADERS}
|
|
||||||
)
|
|
||||||
|
|
||||||
|
# Setup QT tools
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTOUIC ON)
|
||||||
|
set(CMAKE_AUTOUIC_SEARCH_PATHS "${CMAKE_CURRENT_SOURCE_DIR}/forms")
|
||||||
|
set(advanced-scene-switcher_UI ${advanced-scene-switcher_UI}
|
||||||
|
forms/advanced-scene-switcher.ui)
|
||||||
|
qt5_wrap_ui(advanced-scene-switcher_UI_HEADERS ${advanced-scene-switcher_UI}
|
||||||
|
${advanced-scene-switcher_PLATFORM_UI})
|
||||||
|
|
||||||
|
# The plugin sources
|
||||||
|
set(advanced-scene-switcher_HEADERS
|
||||||
|
${advanced-scene-switcher_HEADERS}
|
||||||
|
src/headers/advanced-scene-switcher.hpp
|
||||||
|
src/headers/switcher-data-structs.hpp
|
||||||
|
src/headers/scene-group.hpp
|
||||||
|
src/headers/scene-trigger.hpp
|
||||||
|
src/headers/switch-audio.hpp
|
||||||
|
src/headers/switch-executable.hpp
|
||||||
|
src/headers/switch-file.hpp
|
||||||
|
src/headers/switch-idle.hpp
|
||||||
|
src/headers/switch-media.hpp
|
||||||
|
src/headers/switch-network.hpp
|
||||||
|
src/headers/switch-pause.hpp
|
||||||
|
src/headers/switch-random.hpp
|
||||||
|
src/headers/switch-screen-region.hpp
|
||||||
|
src/headers/switch-time.hpp
|
||||||
|
src/headers/switch-transitions.hpp
|
||||||
|
src/headers/switch-window.hpp
|
||||||
|
src/headers/switch-sequence.hpp
|
||||||
|
src/headers/switch-video.hpp
|
||||||
|
src/headers/switch-generic.hpp
|
||||||
|
src/headers/macro-action-edit.hpp
|
||||||
|
src/headers/macro-action-audio.hpp
|
||||||
|
src/headers/macro-action-file.hpp
|
||||||
|
src/headers/macro-action-filter.hpp
|
||||||
|
src/headers/macro-action-hotkey.hpp
|
||||||
|
src/headers/macro-action-macro.hpp
|
||||||
|
src/headers/macro-action-media.hpp
|
||||||
|
src/headers/macro-action-plugin-state.hpp
|
||||||
|
src/headers/macro-action-preview-scene.hpp
|
||||||
|
src/headers/macro-action-recording.hpp
|
||||||
|
src/headers/macro-action-replay-buffer.hpp
|
||||||
|
src/headers/macro-action-run.hpp
|
||||||
|
src/headers/macro-action-scene-order.hpp
|
||||||
|
src/headers/macro-action-scene-swap.hpp
|
||||||
|
src/headers/macro-action-scene-switch.hpp
|
||||||
|
src/headers/macro-action-scene-transform.hpp
|
||||||
|
src/headers/macro-action-scene-visibility.hpp
|
||||||
|
src/headers/macro-action-source.hpp
|
||||||
|
src/headers/macro-action-streaming.hpp
|
||||||
|
src/headers/macro-action-transition.hpp
|
||||||
|
src/headers/macro-action-virtual-cam.hpp
|
||||||
|
src/headers/macro-action-wait.hpp
|
||||||
|
src/headers/macro-condition-edit.hpp
|
||||||
|
src/headers/macro-condition-audio.hpp
|
||||||
|
src/headers/macro-condition-cursor.hpp
|
||||||
|
src/headers/macro-condition-date.hpp
|
||||||
|
src/headers/macro-condition-file.hpp
|
||||||
|
src/headers/macro-condition-filter.hpp
|
||||||
|
src/headers/macro-condition-hotkey.hpp
|
||||||
|
src/headers/macro-condition-idle.hpp
|
||||||
|
src/headers/macro-condition-macro.hpp
|
||||||
|
src/headers/macro-condition-media.hpp
|
||||||
|
src/headers/macro-condition-plugin-state.hpp
|
||||||
|
src/headers/macro-condition-process.hpp
|
||||||
|
src/headers/macro-condition-recording.hpp
|
||||||
|
src/headers/macro-condition-replay-buffer.hpp
|
||||||
|
src/headers/macro-condition-scene-order.hpp
|
||||||
|
src/headers/macro-condition-scene-transform.hpp
|
||||||
|
src/headers/macro-condition-scene.hpp
|
||||||
|
src/headers/macro-condition-source.hpp
|
||||||
|
src/headers/macro-condition-streaming.hpp
|
||||||
|
src/headers/macro-condition-timer.hpp
|
||||||
|
src/headers/macro-condition-transition.hpp
|
||||||
|
src/headers/macro-condition-video.hpp
|
||||||
|
src/headers/macro-condition-virtual-cam.hpp
|
||||||
|
src/headers/macro-condition-window.hpp
|
||||||
|
src/headers/macro.hpp
|
||||||
|
src/headers/macro-controls.hpp
|
||||||
|
src/headers/macro-segment.hpp
|
||||||
|
src/headers/macro-selection.hpp
|
||||||
|
src/headers/curl-helper.hpp
|
||||||
|
src/headers/hotkey.hpp
|
||||||
|
src/headers/scene-selection.hpp
|
||||||
|
src/headers/screenshot-helper.hpp
|
||||||
|
src/headers/transition-selection.hpp
|
||||||
|
src/headers/name-dialog.hpp
|
||||||
|
src/headers/duration-control.hpp
|
||||||
|
src/headers/file-selection.hpp
|
||||||
|
src/headers/section.hpp
|
||||||
|
src/headers/platform-funcs.hpp
|
||||||
|
src/headers/utility.hpp
|
||||||
|
src/headers/volume-control.hpp
|
||||||
|
src/headers/version.h)
|
||||||
|
|
||||||
|
set(advanced-scene-switcher_SOURCES
|
||||||
|
${advanced-scene-switcher_SOURCES}
|
||||||
|
src/advanced-scene-switcher.cpp
|
||||||
|
src/advanced-scene-switcher-module.c
|
||||||
|
src/switcher-data-structs.cpp
|
||||||
|
src/scene-group.cpp
|
||||||
|
src/scene-trigger.cpp
|
||||||
|
src/switch-transitions.cpp
|
||||||
|
src/switch-screen-region.cpp
|
||||||
|
src/switch-priority.cpp
|
||||||
|
src/switch-executable.cpp
|
||||||
|
src/switch-idle.cpp
|
||||||
|
src/switch-sequence.cpp
|
||||||
|
src/switch-file.cpp
|
||||||
|
src/switch-window.cpp
|
||||||
|
src/switch-media.cpp
|
||||||
|
src/switch-network.cpp
|
||||||
|
src/file-selection.cpp
|
||||||
|
src/hotkey.cpp
|
||||||
|
src/general.cpp
|
||||||
|
src/switch-pause.cpp
|
||||||
|
src/switch-random.cpp
|
||||||
|
src/switch-time.cpp
|
||||||
|
src/switch-audio.cpp
|
||||||
|
src/switch-video.cpp
|
||||||
|
src/switch-generic.cpp
|
||||||
|
src/macro-action-edit.cpp
|
||||||
|
src/macro-action-audio.cpp
|
||||||
|
src/macro-action-file.cpp
|
||||||
|
src/macro-action-filter.cpp
|
||||||
|
src/macro-action-hotkey.cpp
|
||||||
|
src/macro-action-macro.cpp
|
||||||
|
src/macro-action-media.cpp
|
||||||
|
src/macro-action-plugin-state.cpp
|
||||||
|
src/macro-action-preview-scene.cpp
|
||||||
|
src/macro-action-recording.cpp
|
||||||
|
src/macro-action-replay-buffer.cpp
|
||||||
|
src/macro-action-run.cpp
|
||||||
|
src/macro-action-scene-order.cpp
|
||||||
|
src/macro-action-scene-swap.cpp
|
||||||
|
src/macro-action-scene-switch.cpp
|
||||||
|
src/macro-action-scene-transform.cpp
|
||||||
|
src/macro-action-scene-visibility.cpp
|
||||||
|
src/macro-action-source.cpp
|
||||||
|
src/macro-action-streaming.cpp
|
||||||
|
src/macro-action-transition.cpp
|
||||||
|
src/macro-action-virtual-cam.cpp
|
||||||
|
src/macro-action-wait.cpp
|
||||||
|
src/macro-condition-edit.cpp
|
||||||
|
src/macro-condition-audio.cpp
|
||||||
|
src/macro-condition-cursor.cpp
|
||||||
|
src/macro-condition-date.cpp
|
||||||
|
src/macro-condition-file.cpp
|
||||||
|
src/macro-condition-filter.cpp
|
||||||
|
src/macro-condition-hotkey.cpp
|
||||||
|
src/macro-condition-idle.cpp
|
||||||
|
src/macro-condition-macro.cpp
|
||||||
|
src/macro-condition-media.cpp
|
||||||
|
src/macro-condition-plugin-state.cpp
|
||||||
|
src/macro-condition-process.cpp
|
||||||
|
src/macro-condition-recording.cpp
|
||||||
|
src/macro-condition-replay-buffer.cpp
|
||||||
|
src/macro-condition-scene-order.cpp
|
||||||
|
src/macro-condition-scene-transform.cpp
|
||||||
|
src/macro-condition-scene.cpp
|
||||||
|
src/macro-condition-source.cpp
|
||||||
|
src/macro-condition-streaming.cpp
|
||||||
|
src/macro-condition-timer.cpp
|
||||||
|
src/macro-condition-transition.cpp
|
||||||
|
src/macro-condition-video.cpp
|
||||||
|
src/macro-condition-virtual-cam.cpp
|
||||||
|
src/macro-condition-window.cpp
|
||||||
|
src/macro.cpp
|
||||||
|
src/macro-controls.cpp
|
||||||
|
src/macro-segment.cpp
|
||||||
|
src/macro-selection.cpp
|
||||||
|
src/macro-tab.cpp
|
||||||
|
src/curl-helper.cpp
|
||||||
|
src/scene-selection.cpp
|
||||||
|
src/screenshot-helper.cpp
|
||||||
|
src/transition-selection.cpp
|
||||||
|
src/name-dialog.cpp
|
||||||
|
src/duration-control.cpp
|
||||||
|
src/section.cpp
|
||||||
|
src/utility.cpp
|
||||||
|
src/volume-control.cpp
|
||||||
|
src/version.cpp)
|
||||||
|
|
||||||
|
add_library(
|
||||||
|
advanced-scene-switcher MODULE
|
||||||
|
${advanced-scene-switcher_HEADERS}
|
||||||
|
${advanced-scene-switcher_SOURCES}
|
||||||
|
${advanced-scene-switcher_UI_HEADERS}
|
||||||
|
${advanced-scene-switcher_PLATFORM_SOURCES}
|
||||||
|
${advanced-scene-switcher_PLATFORM_HEADERS})
|
||||||
|
|
||||||
|
# Out of tree build
|
||||||
if(BUILD_OUT_OF_TREE)
|
if(BUILD_OUT_OF_TREE)
|
||||||
include_directories(
|
target_link_libraries(
|
||||||
"${LIBOBS_INCLUDE_DIRS}"
|
advanced-scene-switcher
|
||||||
"${LIBOBS_FRONTEND_INCLUDE_DIR}"
|
${advanced-scene-switcher_PLATFORM_LIBS}
|
||||||
${Qt5Core_INCLUDES}
|
${OpenCV_LIBRARIES}
|
||||||
${Qt5Widgets_INCLUDES}
|
${LIBOBS_LIB}
|
||||||
${LIBCURL_INCLUDE_DIRS})
|
${LIBOBS_FRONTEND_API_LIB}
|
||||||
|
Qt5::Core
|
||||||
|
Qt5::Widgets)
|
||||||
|
|
||||||
target_link_libraries(advanced-scene-switcher
|
# Additional commands to install the module in the correct place. Find all the
|
||||||
${advanced-scene-switcher_PLATFORM_LIBS}
|
# translation files so we can copy them to the correct place later on.
|
||||||
${LIBOBS_LIB}
|
file(GLOB ASS_TRANSLATION_FILES "data/locale/*.ini")
|
||||||
${LIBOBS_FRONTEND_API_LIB}
|
|
||||||
Qt5::Core
|
|
||||||
Qt5::Widgets)
|
|
||||||
|
|
||||||
# Additional commands to install the module in the correct place.
|
# OSX
|
||||||
# Find all the translation files so we can copy them to the correct
|
if(APPLE)
|
||||||
# place later on.
|
set_target_properties(advanced-scene-switcher PROPERTIES PREFIX "")
|
||||||
file(GLOB ASS_TRANSLATION_FILES
|
endif()
|
||||||
"data/locale/*.ini"
|
|
||||||
)
|
|
||||||
|
|
||||||
# Windows
|
# Linux
|
||||||
if(WIN32)
|
if(UNIX AND NOT APPLE)
|
||||||
string(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
|
if(NOT LIB_OUT_DIR)
|
||||||
message("${CMAKE_CXX_FLAGS_RELEASE}")
|
set(LIB_OUT_DIR "/lib/obs-plugins")
|
||||||
|
endif()
|
||||||
find_package(w32-pthreads REQUIRED)
|
if(NOT DATA_OUT_DIR)
|
||||||
|
set(DATA_OUT_DIR "/share/obs/obs-plugins/advanced-scene-switcher")
|
||||||
target_link_libraries(advanced-scene-switcher
|
endif()
|
||||||
w32-pthreads)
|
set_target_properties(advanced-scene-switcher PROPERTIES PREFIX "")
|
||||||
endif()
|
install(TARGETS advanced-scene-switcher
|
||||||
|
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/${LIB_OUT_DIR})
|
||||||
# OSX
|
install(DIRECTORY data/locale
|
||||||
if(APPLE)
|
DESTINATION ${CMAKE_INSTALL_PREFIX}/${DATA_OUT_DIR})
|
||||||
set_target_properties(advanced-scene-switcher PROPERTIES PREFIX "")
|
install(DIRECTORY data/res
|
||||||
endif()
|
DESTINATION ${CMAKE_INSTALL_PREFIX}/${DATA_OUT_DIR})
|
||||||
|
endif()
|
||||||
# Linux
|
|
||||||
if(UNIX AND NOT APPLE)
|
|
||||||
set(CMAKE_C_FLAGS "-Wall -Wextra -Wvla -Wno-unused-function -Werror-implicit-function-declaration -Wno-missing-braces -Wno-missing-field-initializers ${CMAKE_C_FLAGS} -std=c99 -fno-strict-aliasing")
|
|
||||||
|
|
||||||
if(ARCH EQUAL 64)
|
|
||||||
set(ARCH_NAME "x86_64")
|
|
||||||
else()
|
|
||||||
set(ARCH_NAME "i686")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set_target_properties(advanced-scene-switcher PROPERTIES PREFIX "")
|
|
||||||
|
|
||||||
install(TARGETS advanced-scene-switcher
|
|
||||||
LIBRARY DESTINATION ${CMAKE_INSTALL_PREFIX}/lib/obs-plugins)
|
|
||||||
install(FILES ${ASS_TRANSLATION_FILES}
|
|
||||||
DESTINATION "${CMAKE_INSTALL_PREFIX}/share/obs/obs-plugins/advanced-scene-switcher/locale")
|
|
||||||
endif()
|
|
||||||
else()
|
else()
|
||||||
target_link_libraries(advanced-scene-switcher
|
# In tree build
|
||||||
${advanced-scene-switcher_PLATFORM_LIBS}
|
target_link_libraries(
|
||||||
obs-frontend-api
|
advanced-scene-switcher
|
||||||
Qt5::Widgets
|
${advanced-scene-switcher_PLATFORM_LIBS}
|
||||||
libobs)
|
${OpenCV_LIBRARIES}
|
||||||
|
obs-frontend-api
|
||||||
install_obs_plugin_with_data(advanced-scene-switcher data)
|
Qt5::Widgets
|
||||||
|
libobs)
|
||||||
|
install_obs_plugin_with_data(advanced-scene-switcher data)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
128
README.md
128
README.md
@@ -1,119 +1,27 @@
|
|||||||
# SceneSwitcher
|
# SceneSwitcher
|
||||||
An automated scene switcher for OBS Studio
|
An automated scene switcher for OBS Studio.
|
||||||
|
|
||||||
More information can be found on https://obsproject.com/forum/resources/automatic-scene-switching.395/ and see https://github.com/WarmUpTill/SceneSwitcher/blob/master/CI/release/README.txt for installing releases.
|
More information can be found on https://obsproject.com/forum/resources/automatic-scene-switching.395/.
|
||||||
|
|
||||||
## Compiling in tree (recommended)
|
## Downloads
|
||||||
Add the "SceneSwitcher" source directory to your obs-studio source directory under obs-studio/UI/frontend-plugins/:
|
|
||||||
|
Binaries for Windows, MacOS, and Linux are available in the [Releases](https://github.com/WarmUpTill/SceneSwitcher/releases) section.
|
||||||
|
|
||||||
|
## Installing the plugin
|
||||||
|
|
||||||
|
For the Windows and MacOS platforms, it is recommended to run the provided installers.
|
||||||
|
|
||||||
|
For Linux the Snap package manager offers an OBS Studio installation which is bundled with the plugin:
|
||||||
```
|
```
|
||||||
cd obs-studio/UI/frontend-plugins/
|
sudo snap install obs-studio
|
||||||
git clone https://github.com/WarmUpTill/SceneSwitcher.git
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Then modify the obs-studio/UI/frontend-plugins/CMakeLists.txt file and add an entry for the scene switcher:
|
If that is not an option you will have to ...
|
||||||
add_subdirectory(SceneSwitcher)
|
1. Copy the library to the plugins folder of you obs installation.
|
||||||
|
2. Copy the contents of the data directory to its respective folders of your obs installation.
|
||||||
|
|
||||||
## Compiling out of tree
|
Unfortunately the exact location of these folders may vary from system to system.
|
||||||
### Prerequisites
|
|
||||||
You'll need CMake and a working development environment for OBS Studio installed
|
|
||||||
on your computer. Once you've done that, do the following:
|
|
||||||
```
|
|
||||||
git clone https://github.com/WarmUpTill/SceneSwitcher.git
|
|
||||||
cd SceneSwitcher
|
|
||||||
mkdir build && cd build
|
|
||||||
```
|
|
||||||
|
|
||||||
### Windows
|
## Compiling the plugin
|
||||||
In cmake-gui, you'll have to set these CMake variables :
|
|
||||||
- **BUILD_OUT_OF_TREE** (bool) : true
|
|
||||||
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
|
|
||||||
code of OBS Studio, located at [source_directory]/libobs/.
|
|
||||||
- **LIBOBS_LIB** (filepath) : location of the obs.dll file (usually set to
|
|
||||||
C:\Program Files\obs-studio\bin\64bit\obs.dll)
|
|
||||||
|
|
||||||
Assuming that you installed Qt via the regular Qt App way:
|
See the [build instructions](BUILDING.md).
|
||||||
- **Qt5Core_DIR** (path) : C:/Qt/5.10.1/msvc2017_64/lib/cmake/Qt5Core
|
|
||||||
- **Qt5Gui_DIR** (path): C:/Qt/5.10.1/msvc2017_64/lib/cmake/Qt5Gui
|
|
||||||
- **Qt5Widgets_DIR** (path) : C:/Qt/5.10.1/msvc2017_64/lib/cmake/Qt5Widgets
|
|
||||||
|
|
||||||
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.dll
|
|
||||||
file, usually C:/Program Files/obs-studio/bin/64bit/obs-frontend-api.dll
|
|
||||||
(usually in the same place as LIBOBS_LIB)
|
|
||||||
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api
|
|
||||||
subfolder in the source code of OBS Studio, located at [source_directory]/UI/obs-frontend-api.
|
|
||||||
|
|
||||||
Just keep hitting configure until all the vars are filled out. Then hit generate.
|
|
||||||
|
|
||||||
### Linux
|
|
||||||
Most versions of Linux you can use cmake-gui or the command line.
|
|
||||||
|
|
||||||
**For the command line:**
|
|
||||||
```
|
|
||||||
cmake -DBUILD_OUT_OF_TREE=1 -DLIBOBS_INCLUDE_DIR="<path to the libobs/ sub-folder in obs-studio's source code>" \
|
|
||||||
-DLIBOBS_FRONTEND_INCLUDE_DIR="<path to the UI/obs-frontend-api/ sub-folder in obs-studio's source code>" \
|
|
||||||
-DLIBOBS_LIB="<path to the libobs.so file>" \
|
|
||||||
-DLIBOBS_FRONTEND_API_LIB="<path to the libobs-frontend-api.so file (usually in the same place as LIBOBS_LIB)>" \
|
|
||||||
-DCMAKE_INSTALL_PREFIX=/usr ..
|
|
||||||
make -j4
|
|
||||||
sudo make install
|
|
||||||
```
|
|
||||||
|
|
||||||
For cmake-gui you'll have to set the following variables:
|
|
||||||
- **BUILD_OUT_OF_TREE** (bool) : true
|
|
||||||
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
|
|
||||||
code of OBS Studio, located at [source_directory]/libobs/.
|
|
||||||
- **LIBOBS_LIB** (filepath) : location of the libobs.so file (usually CMake finds
|
|
||||||
this, but if not it'll usually be in /usr/lib/libobs.so)
|
|
||||||
|
|
||||||
Assuming that you installed Qt via your system package manager, it should be
|
|
||||||
found automatically. If not, then usually you'll find it in something like:
|
|
||||||
- **Qt5Core_DIR** (path) : /usr/lib64/cmake/Qt5Core
|
|
||||||
- **Qt5Gui_DIR** (path): /usr/lib64/cmake/Qt5Gui
|
|
||||||
- **Qt5Widgets_DIR** (path) : /usr/lib64/cmake/Qt5Widgets
|
|
||||||
|
|
||||||
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.so
|
|
||||||
file (usually in the same place as LIBOBS_LIB)
|
|
||||||
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api
|
|
||||||
subfolder in the source code of OBS Studio, located at
|
|
||||||
[source_directory]/UI/obs-frontend-api.
|
|
||||||
|
|
||||||
Just keep hitting configure until all the vars are filled out. Then hit generate.
|
|
||||||
|
|
||||||
Then open a terminal in the build folder and type:
|
|
||||||
```
|
|
||||||
make -j4
|
|
||||||
sudo make install
|
|
||||||
```
|
|
||||||
NOTE: The Linux version of this plugin is dependent on libXScrnSaver.
|
|
||||||
|
|
||||||
### OS X
|
|
||||||
In cmake-gui, you'll have to set these CMake variables :
|
|
||||||
- **BUILD_OUT_OF_TREE** (bool) : true
|
|
||||||
- **LIBOBS_INCLUDE_DIR** (path) : location of the libobs subfolder in the source
|
|
||||||
code of OBS Studio, located at [source_directory]/libobs/.
|
|
||||||
- **LIBOBS_LIB** (filepath) : location of the libobs.0.dylib file (usually
|
|
||||||
in /Applications/OBS.app/Contents/Resources/bin/libobs.0.dylib)
|
|
||||||
|
|
||||||
Assuming that you installed Qt via the regular Qt App way:
|
|
||||||
- **Qt5Core_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5Core
|
|
||||||
- **Qt5Widgets_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5Widgets
|
|
||||||
- **Qt5MacExtras_DIR** (path) : Usually /Applications/Qt/5.10.1/clang_64/lib/cmake/Qt5MacExtras
|
|
||||||
|
|
||||||
- **LIBOBS_FRONTEND_API_LIB** (filepath) : location of the libobs-frontend-api.0.dylib
|
|
||||||
file (usually in usually in /Applications/OBS.app/Contents/Resources/bin/libobs-frontend-api.0.dylib)
|
|
||||||
- **LIBOBS_FRONTEND_INCLUDE_DIR** (path) : location of the obs-frontend-api subfolder
|
|
||||||
in the source code of OBS Studio, located at [source_directory]/UI/obs-frontend-api.
|
|
||||||
|
|
||||||
Just keep hitting configure until all the vars are filled out. Then hit generate.
|
|
||||||
|
|
||||||
Open xcode (or a terminal, depending on the build type you chose), build and copy
|
|
||||||
the advanced-scene-switcher.so file to /Applications/OBS.app/Contents/PlugIns
|
|
||||||
|
|
||||||
Note that you might have to adjust the library search paths using the install_name_tool if you want the plugin to run on machines other than your build machine:
|
|
||||||
```
|
|
||||||
install_name_tool -change @rpath/libobs-frontend-api.dylib @executable_path/../Frameworks/libobs-frontend-api.dylib UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
|
||||||
install_name_tool -change @rpath/libobs.0.dylib @executable_path/../Frameworks/libobs.0.dylib UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
|
||||||
install_name_tool -change /usr/local/opt/qt5/lib/QtWidgets.framework/Versions/5/QtWidgets @executable_path/../Frameworks/QtWidgets.framework/Versions/5/QtWidgets UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
|
||||||
install_name_tool -change /usr/local/opt/qt5/lib/QtGui.framework/Versions/5/QtGui @executable_path/../Frameworks/QtGui.framework/Versions/5/QtGui UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
|
||||||
install_name_tool -change /usr/local/opt/qt5/lib/QtCore.framework/Versions/5/QtCore @executable_path/../Frameworks/QtCore.framework/Versions/5/QtCore UI/frontend-plugins/SceneSwitcher/advanced-scene-switcher.so
|
|
||||||
```
|
|
||||||
|
|||||||
@@ -68,6 +68,8 @@ AdvSceneSwitcher.macroTab.name="Name:"
|
|||||||
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
||||||
AdvSceneSwitcher.macroTab.exists="Macro name exists already"
|
AdvSceneSwitcher.macroTab.exists="Macro name exists already"
|
||||||
AdvSceneSwitcher.macroTab.copy="Create copy"
|
AdvSceneSwitcher.macroTab.copy="Create copy"
|
||||||
|
AdvSceneSwitcher.macroTab.expandAll="Expand all"
|
||||||
|
AdvSceneSwitcher.macroTab.collapseAll="Collapse all"
|
||||||
|
|
||||||
; Macro Logic
|
; Macro Logic
|
||||||
AdvSceneSwitcher.logic.none="Ignore entry"
|
AdvSceneSwitcher.logic.none="Ignore entry"
|
||||||
@@ -83,17 +85,24 @@ AdvSceneSwitcher.condition.audio="Audio"
|
|||||||
AdvSceneSwitcher.condition.audio.state.below="Below"
|
AdvSceneSwitcher.condition.audio.state.below="Below"
|
||||||
AdvSceneSwitcher.condition.audio.state.above="Above"
|
AdvSceneSwitcher.condition.audio.state.above="Above"
|
||||||
AdvSceneSwitcher.condition.audio.entry="Volume of {{audioSources}} is {{condition}} {{volume}}"
|
AdvSceneSwitcher.condition.audio.entry="Volume of {{audioSources}} is {{condition}} {{volume}}"
|
||||||
AdvSceneSwitcher.condition.region="Screen region"
|
AdvSceneSwitcher.condition.cursor="Cursor"
|
||||||
AdvSceneSwitcher.condition.region.entry="Cursor is in {{minX}} {{minY}} x {{maxX}} {{maxY}}"
|
AdvSceneSwitcher.condition.cursor.type.region="is in region"
|
||||||
|
AdvSceneSwitcher.condition.cursor.type.moving="is moving"
|
||||||
|
AdvSceneSwitcher.condition.cursor.showFrame="Show frame"
|
||||||
|
AdvSceneSwitcher.condition.cursor.hideFrame="Hide frame"
|
||||||
|
AdvSceneSwitcher.condition.cursor.entry.line1="Cursor is {{conditions}} {{minX}} {{minY}} {{maxX}} {{maxY}} - {{toggleFrameButton}}"
|
||||||
|
AdvSceneSwitcher.condition.cursor.entry.line2="Cursor is currently at {{xPos}} x {{yPos}}"
|
||||||
AdvSceneSwitcher.condition.scene="Scene"
|
AdvSceneSwitcher.condition.scene="Scene"
|
||||||
AdvSceneSwitcher.condition.scene.type.current="Current"
|
AdvSceneSwitcher.condition.scene.type.current="Current scene is"
|
||||||
AdvSceneSwitcher.condition.scene.type.previous="Previous"
|
AdvSceneSwitcher.condition.scene.type.previous="Previous scene is"
|
||||||
AdvSceneSwitcher.condition.scene.entry="{{sceneType}} scene is {{scenes}}"
|
AdvSceneSwitcher.condition.scene.type.changed="Scene chagned"
|
||||||
|
AdvSceneSwitcher.condition.scene.type.notChanged="Scene has not changed"
|
||||||
|
AdvSceneSwitcher.condition.scene.entry="{{sceneType}} {{scenes}}"
|
||||||
AdvSceneSwitcher.condition.window="Window"
|
AdvSceneSwitcher.condition.window="Window"
|
||||||
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} exist and ..."
|
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} exist and ..."
|
||||||
AdvSceneSwitcher.condition.window.entry.line2="... is {{fullscreen}} fullscreen {{maximized}} maximized {{focused}} focused {{windowFocusChanged}} foreground window changed"
|
AdvSceneSwitcher.condition.window.entry.line2="... is {{fullscreen}} fullscreen {{maximized}} maximized {{focused}} focused {{windowFocusChanged}} foreground window changed"
|
||||||
AdvSceneSwitcher.condition.file="File"
|
AdvSceneSwitcher.condition.file="File"
|
||||||
AdvSceneSwitcher.condition.file.entry.line1="Content of {{fileType}} {{filePath}} {{browseButton}} matches:"
|
AdvSceneSwitcher.condition.file.entry.line1="Content of {{fileType}} {{filePath}} matches:"
|
||||||
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
|
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
|
||||||
AdvSceneSwitcher.condition.media="Media"
|
AdvSceneSwitcher.condition.media="Media"
|
||||||
@@ -104,10 +113,26 @@ AdvSceneSwitcher.condition.video.condition.differ="does not match"
|
|||||||
AdvSceneSwitcher.condition.video.condition.hasChanged="has changed"
|
AdvSceneSwitcher.condition.video.condition.hasChanged="has changed"
|
||||||
AdvSceneSwitcher.condition.video.condition.hasNotChanged="has not changed"
|
AdvSceneSwitcher.condition.video.condition.hasNotChanged="has not changed"
|
||||||
AdvSceneSwitcher.condition.video.condition.noImage="has no output"
|
AdvSceneSwitcher.condition.video.condition.noImage="has no output"
|
||||||
|
AdvSceneSwitcher.condition.video.condition.pattern="matches pattern"
|
||||||
|
AdvSceneSwitcher.condition.video.condition.object="contains object"
|
||||||
AdvSceneSwitcher.condition.video.askFileAction="Do you want to use an existing file or create a screenshot of the currently selected source?"
|
AdvSceneSwitcher.condition.video.askFileAction="Do you want to use an existing file or create a screenshot of the currently selected source?"
|
||||||
AdvSceneSwitcher.condition.video.askFileAction.file="Use existing file"
|
AdvSceneSwitcher.condition.video.askFileAction.file="Use existing file"
|
||||||
AdvSceneSwitcher.condition.video.askFileAction.screenshot="Create screenshot"
|
AdvSceneSwitcher.condition.video.askFileAction.screenshot="Create screenshot"
|
||||||
AdvSceneSwitcher.condition.video.entry="{{videoSources}} {{condition}} {{filePath}} {{browseButton}}"
|
AdvSceneSwitcher.condition.video.patternThreshold="Threshold: "
|
||||||
|
AdvSceneSwitcher.condition.video.patternThresholdDescription="A higher threshold value means that the pattern needs to match the video source more closely."
|
||||||
|
AdvSceneSwitcher.condition.video.objectScaleThreshold="Scale factor: "
|
||||||
|
AdvSceneSwitcher.condition.video.objectScaleThresholdDescription="A lower scale factor will lead to more matches but higher CPU load."
|
||||||
|
AdvSceneSwitcher.condition.video.showMatch="Show match"
|
||||||
|
AdvSceneSwitcher.condition.video.screenshotFail="Failed to get screenshot of source!"
|
||||||
|
AdvSceneSwitcher.condition.video.patternMatchFail="Pattern was not found!"
|
||||||
|
AdvSceneSwitcher.condition.video.objectMatchFail="Object was not found!"
|
||||||
|
AdvSceneSwitcher.condition.video.modelLoadFail="Model data could not be loaded!"
|
||||||
|
AdvSceneSwitcher.condition.video.entry="{{videoSources}} {{condition}} {{imagePath}}"
|
||||||
|
AdvSceneSwitcher.condition.video.entry.modelPath="Model data (haar cascade classifier): {{modelDataPath}}"
|
||||||
|
AdvSceneSwitcher.condition.video.entry.minNeighbor="Minimum neighbors: {{minNeighbors}}"
|
||||||
|
AdvSceneSwitcher.condition.video.entry.minSize="Minimum size: {{minSizeX}} x {{minSizeY}}"
|
||||||
|
AdvSceneSwitcher.condition.video.entry.maxSize="Maximum size: {{maxSizeX}} x {{maxSizeY}}"
|
||||||
|
AdvSceneSwitcher.condition.video.entry.throttle="{{throttleEnable}}Reduce CPU load by performing check only every {{throttleCount}} milliseconds"
|
||||||
AdvSceneSwitcher.condition.stream="Streaming"
|
AdvSceneSwitcher.condition.stream="Streaming"
|
||||||
AdvSceneSwitcher.condition.stream.state.start="Stream running"
|
AdvSceneSwitcher.condition.stream.state.start="Stream running"
|
||||||
AdvSceneSwitcher.condition.stream.state.stop="Stream stopped"
|
AdvSceneSwitcher.condition.stream.state.stop="Stream stopped"
|
||||||
@@ -178,8 +203,25 @@ AdvSceneSwitcher.condition.replay.state.started="Replay buffer started"
|
|||||||
AdvSceneSwitcher.condition.replay.state.saved="Replay buffer saved"
|
AdvSceneSwitcher.condition.replay.state.saved="Replay buffer saved"
|
||||||
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
||||||
AdvSceneSwitcher.condition.date="Date"
|
AdvSceneSwitcher.condition.date="Date"
|
||||||
AdvSceneSwitcher.condition.date.entry.line1="{{dateTime}} {{ignoreDate}} Ignore date selection {{ignoreTime}} Ignore time selection"
|
AdvSceneSwitcher.condition.date.state.at="At"
|
||||||
AdvSceneSwitcher.condition.date.entry.line2="{{repeat}} Repeat every {{duration}}"
|
AdvSceneSwitcher.condition.date.state.after="After"
|
||||||
|
AdvSceneSwitcher.condition.date.state.before="Before"
|
||||||
|
AdvSceneSwitcher.condition.date.state.between="Between"
|
||||||
|
AdvSceneSwitcher.condition.date.entry.line1="{{condition}} {{dateTime}} {{dateTime2}} {{ignoreDate}} Ignore date component {{ignoreTime}} Ignore time component"
|
||||||
|
AdvSceneSwitcher.condition.date.entry.line2="{{repeat}} Reschedule {{duration}} later when matching"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform="Scene item transform"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform.getTransform="Get transform"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform.regex="Use regular expressions"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform.entry.line1="On {{scenes}} {{sources}} matches transform"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
|
||||||
|
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
|
||||||
|
AdvSceneSwitcher.condition.transition="Transition"
|
||||||
|
AdvSceneSwitcher.condition.transition.type.current="Current transition type is"
|
||||||
|
AdvSceneSwitcher.condition.transition.type.duration="Current transition duration is"
|
||||||
|
AdvSceneSwitcher.condition.transition.type.started="Transition active"
|
||||||
|
AdvSceneSwitcher.condition.transition.type.ended="Transition ended"
|
||||||
|
AdvSceneSwitcher.condition.transition.durationSuffix="seconds"
|
||||||
|
AdvSceneSwitcher.condition.transition.entry="{{conditions}}{{transitions}}{{duration}}{{durationSuffix}}"
|
||||||
|
|
||||||
; Macro Actions
|
; Macro Actions
|
||||||
AdvSceneSwitcher.action.switchScene="Switch scene"
|
AdvSceneSwitcher.action.switchScene="Switch scene"
|
||||||
@@ -215,7 +257,7 @@ AdvSceneSwitcher.action.run="Run"
|
|||||||
AdvSceneSwitcher.action.run.arguments="Arguments:"
|
AdvSceneSwitcher.action.run.arguments="Arguments:"
|
||||||
AdvSceneSwitcher.action.run.addArgument="Add argument"
|
AdvSceneSwitcher.action.run.addArgument="Add argument"
|
||||||
AdvSceneSwitcher.action.run.addArgumentDescription="Add new argument:"
|
AdvSceneSwitcher.action.run.addArgumentDescription="Add new argument:"
|
||||||
AdvSceneSwitcher.action.run.entry="Run {{filePath}} {{browseButton}}"
|
AdvSceneSwitcher.action.run.entry="Run {{filePath}}"
|
||||||
AdvSceneSwitcher.action.sceneVisibility="Scene item visibility"
|
AdvSceneSwitcher.action.sceneVisibility="Scene item visibility"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.show="Show"
|
AdvSceneSwitcher.action.sceneVisibility.type.show="Show"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide"
|
AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide"
|
||||||
@@ -263,8 +305,9 @@ AdvSceneSwitcher.action.hotkey.leftAlt="Left Alt"
|
|||||||
AdvSceneSwitcher.action.hotkey.rightAlt="Right Alt"
|
AdvSceneSwitcher.action.hotkey.rightAlt="Right Alt"
|
||||||
AdvSceneSwitcher.action.hotkey.leftMeta="Left Meta"
|
AdvSceneSwitcher.action.hotkey.leftMeta="Left Meta"
|
||||||
AdvSceneSwitcher.action.hotkey.rightMeta="Right Meta"
|
AdvSceneSwitcher.action.hotkey.rightMeta="Right Meta"
|
||||||
|
AdvSceneSwitcher.action.hotkey.onlyOBS="Send keypress only to OBS"
|
||||||
AdvSceneSwitcher.action.hotkey.disabled="Cannot simulate key presses - functionality disabled!"
|
AdvSceneSwitcher.action.hotkey.disabled="Cannot simulate key presses - functionality disabled!"
|
||||||
AdvSceneSwitcher.action.hotkey.entry="Press {{keys}}"
|
AdvSceneSwitcher.action.hotkey.entry="Press {{keys}} for {{duration}} milliseconds"
|
||||||
AdvSceneSwitcher.action.sceneOrder="Scene item order"
|
AdvSceneSwitcher.action.sceneOrder="Scene item order"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Move up"
|
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Move up"
|
||||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Move down"
|
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Move down"
|
||||||
@@ -278,7 +321,14 @@ AdvSceneSwitcher.action.sceneTransform.entry="On {{scenes}} transform {{sources}
|
|||||||
AdvSceneSwitcher.action.file="File"
|
AdvSceneSwitcher.action.file="File"
|
||||||
AdvSceneSwitcher.action.file.type.write="Write"
|
AdvSceneSwitcher.action.file.type.write="Write"
|
||||||
AdvSceneSwitcher.action.file.type.append="Append"
|
AdvSceneSwitcher.action.file.type.append="Append"
|
||||||
AdvSceneSwitcher.action.file.entry="{{actions}} to {{filePath}} {{browseButton}}:"
|
AdvSceneSwitcher.action.file.entry="{{actions}} to {{filePath}}:"
|
||||||
|
AdvSceneSwitcher.action.previewScene="Switch preview scene"
|
||||||
|
AdvSceneSwitcher.action.previewScene.entry="Switch preview scene to {{scenes}}"
|
||||||
|
AdvSceneSwitcher.action.SceneSwap="Swap scene (Studio mode)"
|
||||||
|
AdvSceneSwitcher.action.SceneSwap.entry="Swap preview and program scene in studio mode"
|
||||||
|
AdvSceneSwitcher.action.transition="Transition"
|
||||||
|
AdvSceneSwitcher.action.transition.entry.line1="{{setType}}Set transition type to {{transitions}}"
|
||||||
|
AdvSceneSwitcher.action.transition.entry.line2="{{setDuration}}Set transition duration to {{duration}}seconds"
|
||||||
|
|
||||||
; Transition Tab
|
; Transition Tab
|
||||||
AdvSceneSwitcher.transitionTab.title="Transition"
|
AdvSceneSwitcher.transitionTab.title="Transition"
|
||||||
@@ -450,6 +500,7 @@ AdvSceneSwitcher.videoTab.help="<html><head/><body><p>This tab will allow you to
|
|||||||
|
|
||||||
; Network Tab
|
; Network Tab
|
||||||
AdvSceneSwitcher.networkTab.title="Network"
|
AdvSceneSwitcher.networkTab.title="Network"
|
||||||
|
AdvSceneSwitcher.networkTab.description="This tab will allow you to remotely control the active scene of another OBS instance.\nPlease note that the scene names have to match exactly on all OBS instances."
|
||||||
AdvSceneSwitcher.networkTab.warning="Running the server outside of a local network will allow third parties to read the active scene."
|
AdvSceneSwitcher.networkTab.warning="Running the server outside of a local network will allow third parties to read the active scene."
|
||||||
AdvSceneSwitcher.networkTab.DisabledWarning="This functionality unfortunately had to be disabled on macOS due to library incompatibilities when running the obs-websocket plugin in parallel."
|
AdvSceneSwitcher.networkTab.DisabledWarning="This functionality unfortunately had to be disabled on macOS due to library incompatibilities when running the obs-websocket plugin in parallel."
|
||||||
AdvSceneSwitcher.networkTab.server="Start server (Sends scene switch messages to all connected clients)"
|
AdvSceneSwitcher.networkTab.server="Start server (Sends scene switch messages to all connected clients)"
|
||||||
@@ -534,6 +585,7 @@ AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
|||||||
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
||||||
AdvSceneSwitcher.selectAnyScene="Any Scene"
|
AdvSceneSwitcher.selectAnyScene="Any Scene"
|
||||||
AdvSceneSwitcher.currentTransition="Current Transition"
|
AdvSceneSwitcher.currentTransition="Current Transition"
|
||||||
|
AdvSceneSwitcher.anyTransition="Any Transition"
|
||||||
AdvSceneSwitcher.selectTransition="--select transition--"
|
AdvSceneSwitcher.selectTransition="--select transition--"
|
||||||
AdvSceneSwitcher.selectWindow="--select window--"
|
AdvSceneSwitcher.selectWindow="--select window--"
|
||||||
AdvSceneSwitcher.selectSource="--select source--"
|
AdvSceneSwitcher.selectSource="--select source--"
|
||||||
|
|||||||
@@ -81,8 +81,7 @@ AdvSceneSwitcher.condition.audio="Аудио"
|
|||||||
AdvSceneSwitcher.ondition.audio.state.below="Ниже"
|
AdvSceneSwitcher.ondition.audio.state.below="Ниже"
|
||||||
AdvSceneSwitcher.ondition.audio.state.above="Выше"
|
AdvSceneSwitcher.ondition.audio.state.above="Выше"
|
||||||
AdvSceneSwitcher.condition.audio.entry="Громкость {{audioSources}} равна {{condition}} {{volume}} в течении {{duration}} секунд"
|
AdvSceneSwitcher.condition.audio.entry="Громкость {{audioSources}} равна {{condition}} {{volume}} в течении {{duration}} секунд"
|
||||||
AdvSceneSwitcher.condition.region="Область экрана"
|
AdvSceneSwitcher.condition.cursor="Область экрана"
|
||||||
AdvSceneSwitcher.condition.region.entry="Курсор находится в {{minX}} {{minY}} x {{maxX}} {{maxY}}"
|
|
||||||
AdvSceneSwitcher.condition.scene="Сцена"
|
AdvSceneSwitcher.condition.scene="Сцена"
|
||||||
AdvSceneSwitcher.condition.scene.type.current="Текущий"
|
AdvSceneSwitcher.condition.scene.type.current="Текущий"
|
||||||
AdvSceneSwitcher.condition.scene.type.previous="Предыдущий"
|
AdvSceneSwitcher.condition.scene.type.previous="Предыдущий"
|
||||||
|
|||||||
15452
data/res/cascadeClassifiers/haarcascade_eye.xml
Normal file
15452
data/res/cascadeClassifiers/haarcascade_eye.xml
Normal file
File diff suppressed because it is too large
Load Diff
33158
data/res/cascadeClassifiers/haarcascade_eye_tree_eyeglasses.xml
Normal file
33158
data/res/cascadeClassifiers/haarcascade_eye_tree_eyeglasses.xml
Normal file
File diff suppressed because it is too large
Load Diff
26161
data/res/cascadeClassifiers/haarcascade_frontalface_alt.xml
Normal file
26161
data/res/cascadeClassifiers/haarcascade_frontalface_alt.xml
Normal file
File diff suppressed because it is too large
Load Diff
23550
data/res/cascadeClassifiers/haarcascade_frontalface_alt2.xml
Normal file
23550
data/res/cascadeClassifiers/haarcascade_frontalface_alt2.xml
Normal file
File diff suppressed because it is too large
Load Diff
103493
data/res/cascadeClassifiers/haarcascade_frontalface_alt_tree.xml
Normal file
103493
data/res/cascadeClassifiers/haarcascade_frontalface_alt_tree.xml
Normal file
File diff suppressed because it is too large
Load Diff
35712
data/res/cascadeClassifiers/haarcascade_frontalface_default.xml
Normal file
35712
data/res/cascadeClassifiers/haarcascade_frontalface_default.xml
Normal file
File diff suppressed because it is too large
Load Diff
18118
data/res/cascadeClassifiers/haarcascade_fullbody.xml
Normal file
18118
data/res/cascadeClassifiers/haarcascade_fullbody.xml
Normal file
File diff suppressed because it is too large
Load Diff
9803
data/res/cascadeClassifiers/haarcascade_lefteye_2splits.xml
Normal file
9803
data/res/cascadeClassifiers/haarcascade_lefteye_2splits.xml
Normal file
File diff suppressed because it is too large
Load Diff
15085
data/res/cascadeClassifiers/haarcascade_lowerbody.xml
Normal file
15085
data/res/cascadeClassifiers/haarcascade_lowerbody.xml
Normal file
File diff suppressed because it is too large
Load Diff
31930
data/res/cascadeClassifiers/haarcascade_profileface.xml
Normal file
31930
data/res/cascadeClassifiers/haarcascade_profileface.xml
Normal file
File diff suppressed because it is too large
Load Diff
9833
data/res/cascadeClassifiers/haarcascade_righteye_2splits.xml
Normal file
9833
data/res/cascadeClassifiers/haarcascade_righteye_2splits.xml
Normal file
File diff suppressed because it is too large
Load Diff
29767
data/res/cascadeClassifiers/haarcascade_upperbody.xml
Normal file
29767
data/res/cascadeClassifiers/haarcascade_upperbody.xml
Normal file
File diff suppressed because it is too large
Load Diff
1
deps/opencv
vendored
Submodule
1
deps/opencv
vendored
Submodule
Submodule deps/opencv added at ad6e82942b
107
external/FindLibObs.cmake
vendored
107
external/FindLibObs.cmake
vendored
@@ -1,107 +0,0 @@
|
|||||||
# This module can be copied and used by external plugins for OBS
|
|
||||||
#
|
|
||||||
# Once done these will be defined:
|
|
||||||
#
|
|
||||||
# LIBOBS_FOUND
|
|
||||||
# LIBOBS_INCLUDE_DIRS
|
|
||||||
# LIBOBS_LIBRARIES
|
|
||||||
|
|
||||||
find_package(PkgConfig QUIET)
|
|
||||||
if (PKG_CONFIG_FOUND)
|
|
||||||
pkg_check_modules(_OBS QUIET obs libobs)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
||||||
set(_lib_suffix 64)
|
|
||||||
else()
|
|
||||||
set(_lib_suffix 32)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
if(DEFINED CMAKE_BUILD_TYPE)
|
|
||||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
|
||||||
set(_build_type_base "debug")
|
|
||||||
else()
|
|
||||||
set(_build_type_base "release")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_path(LIBOBS_INCLUDE_DIR
|
|
||||||
NAMES obs.h
|
|
||||||
HINTS
|
|
||||||
ENV obsPath${_lib_suffix}
|
|
||||||
ENV obsPath
|
|
||||||
${obsPath}
|
|
||||||
PATHS
|
|
||||||
/usr/include /usr/local/include /opt/local/include /sw/include
|
|
||||||
PATH_SUFFIXES
|
|
||||||
libobs
|
|
||||||
)
|
|
||||||
|
|
||||||
function(find_obs_lib base_name repo_build_path lib_name)
|
|
||||||
string(TOUPPER "${base_name}" base_name_u)
|
|
||||||
|
|
||||||
if(DEFINED _build_type_base)
|
|
||||||
set(_build_type_${repo_build_path} "${_build_type_base}/${repo_build_path}")
|
|
||||||
set(_build_type_${repo_build_path}${_lib_suffix} "${_build_type_base}${_lib_suffix}/${repo_build_path}")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
find_library(${base_name_u}_LIB
|
|
||||||
NAMES ${_${base_name_u}_LIBRARIES} ${lib_name} lib${lib_name}
|
|
||||||
HINTS
|
|
||||||
ENV obsPath${_lib_suffix}
|
|
||||||
ENV obsPath
|
|
||||||
${obsPath}
|
|
||||||
${_${base_name_u}_LIBRARY_DIRS}
|
|
||||||
PATHS
|
|
||||||
/usr/lib /usr/local/lib /opt/local/lib /sw/lib
|
|
||||||
PATH_SUFFIXES
|
|
||||||
lib${_lib_suffix} lib
|
|
||||||
libs${_lib_suffix} libs
|
|
||||||
bin${_lib_suffix} bin
|
|
||||||
../lib${_lib_suffix} ../lib
|
|
||||||
../libs${_lib_suffix} ../libs
|
|
||||||
../bin${_lib_suffix} ../bin
|
|
||||||
# base repo non-msvc-specific search paths
|
|
||||||
${_build_type_${repo_build_path}}
|
|
||||||
${_build_type_${repo_build_path}${_lib_suffix}}
|
|
||||||
build/${repo_build_path}
|
|
||||||
build${_lib_suffix}/${repo_build_path}
|
|
||||||
# base repo msvc-specific search paths on windows
|
|
||||||
build${_lib_suffix}/${repo_build_path}/Debug
|
|
||||||
build${_lib_suffix}/${repo_build_path}/RelWithDebInfo
|
|
||||||
build/${repo_build_path}/Debug
|
|
||||||
build/${repo_build_path}/RelWithDebInfo
|
|
||||||
)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
find_obs_lib(LIBOBS libobs obs)
|
|
||||||
|
|
||||||
if(MSVC)
|
|
||||||
find_obs_lib(W32_PTHREADS deps/w32-pthreads w32-pthreads)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include(FindPackageHandleStandardArgs)
|
|
||||||
find_package_handle_standard_args(Libobs DEFAULT_MSG LIBOBS_LIB LIBOBS_INCLUDE_DIR)
|
|
||||||
mark_as_advanced(LIBOBS_INCLUDE_DIR LIBOBS_LIB)
|
|
||||||
|
|
||||||
if(LIBOBS_FOUND)
|
|
||||||
if(MSVC)
|
|
||||||
if (NOT DEFINED W32_PTHREADS_LIB)
|
|
||||||
message(FATAL_ERROR "Could not find the w32-pthreads library" )
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(W32_PTHREADS_INCLUDE_DIR ${LIBOBS_INCLUDE_DIR}/../deps/w32-pthreads)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set(LIBOBS_INCLUDE_DIRS ${LIBOBS_INCLUDE_DIR} ${W32_PTHREADS_INCLUDE_DIR})
|
|
||||||
set(LIBOBS_LIBRARIES ${LIBOBS_LIB} ${W32_PTHREADS_LIB})
|
|
||||||
include(${LIBOBS_INCLUDE_DIR}/../cmake/external/ObsPluginHelpers.cmake)
|
|
||||||
|
|
||||||
# allows external plugins to easily use/share common dependencies that are often included with libobs (such as FFmpeg)
|
|
||||||
if(NOT DEFINED INCLUDED_LIBOBS_CMAKE_MODULES)
|
|
||||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${LIBOBS_INCLUDE_DIR}/../cmake/Modules/")
|
|
||||||
set(INCLUDED_LIBOBS_CMAKE_MODULES true)
|
|
||||||
endif()
|
|
||||||
else()
|
|
||||||
message(FATAL_ERROR "Could not find the libobs library" )
|
|
||||||
endif()
|
|
||||||
163
external/ObsPluginHelpers.cmake
vendored
163
external/ObsPluginHelpers.cmake
vendored
@@ -1,163 +0,0 @@
|
|||||||
# Functions for generating external plugins
|
|
||||||
|
|
||||||
set(EXTERNAL_PLUGIN_OUTPUT_DIR "${CMAKE_BINARY_DIR}/rundir")
|
|
||||||
|
|
||||||
# Fix XCode includes to ignore warnings on system includes
|
|
||||||
function(target_include_directories_system _target)
|
|
||||||
if(XCODE)
|
|
||||||
foreach(_arg ${ARGN})
|
|
||||||
if("${_arg}" STREQUAL "PRIVATE" OR "${_arg}" STREQUAL "PUBLIC" OR "${_arg}" STREQUAL "INTERFACE")
|
|
||||||
set(_scope ${_arg})
|
|
||||||
else()
|
|
||||||
target_compile_options(${_target} ${_scope} -isystem${_arg})
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
else()
|
|
||||||
target_include_directories(${_target} SYSTEM ${_scope} ${ARGN})
|
|
||||||
endif()
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
function(install_external_plugin_data_internal target source_dir target_dir)
|
|
||||||
install(DIRECTORY ${source_dir}/
|
|
||||||
DESTINATION "${target}/${target_dir}"
|
|
||||||
USE_SOURCE_PERMISSIONS)
|
|
||||||
add_custom_command(TARGET ${target} POST_BUILD
|
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy_directory
|
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/${source_dir}" "${EXTERNAL_PLUGIN_OUTPUT_DIR}/$<CONFIGURATION>/${target}/${target_dir}"
|
|
||||||
VERBATIM)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Installs data
|
|
||||||
# 'target' is the destination target project being installed to
|
|
||||||
# 'data_loc' specifies the directory of the data
|
|
||||||
function(install_external_plugin_data target data_loc)
|
|
||||||
install_external_plugin_data_internal(${target} ${data_loc} "data")
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Installs data in an architecture-specific data directory on windows/linux (data/32bit or data/64bit). Does not apply for mac.
|
|
||||||
# 'target' is the destination target project being installed to
|
|
||||||
# 'data_loc' specifies the directory of the data being installed
|
|
||||||
function(install_external_plugin_arch_data target data_loc)
|
|
||||||
if(APPLE)
|
|
||||||
set(_bit_suffix "")
|
|
||||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
||||||
set(_bit_suffix "/64bit")
|
|
||||||
else()
|
|
||||||
set(_bit_suffix "/32bit")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
install_external_plugin_data_internal(${target} ${data_loc} "data${_bit_suffix}")
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Installs data in the target's bin directory
|
|
||||||
# 'target' is the destination target project being installed to
|
|
||||||
# 'data_loc' specifies the directory of the data being installed
|
|
||||||
function(install_external_plugin_data_to_bin target data_loc)
|
|
||||||
if(APPLE)
|
|
||||||
set(_bit_suffix "")
|
|
||||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
||||||
set(_bit_suffix "/64bit")
|
|
||||||
else()
|
|
||||||
set(_bit_suffix "/32bit")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
install_external_plugin_data_internal(${target} ${data_loc} "bin${_bit_suffix}")
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Installs an additional binary to a target
|
|
||||||
# 'target' is the destination target project being installed to
|
|
||||||
# 'additional_target' specifies the additional binary
|
|
||||||
function(install_external_plugin_additional target additional_target)
|
|
||||||
if(APPLE)
|
|
||||||
set(_bit_suffix "")
|
|
||||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
||||||
set(_bit_suffix "64bit/")
|
|
||||||
else()
|
|
||||||
set(_bit_suffix "32bit/")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
set_target_properties(${additional_target} PROPERTIES
|
|
||||||
PREFIX "")
|
|
||||||
|
|
||||||
install(TARGETS ${additional_target}
|
|
||||||
LIBRARY DESTINATION "bin"
|
|
||||||
RUNTIME DESTINATION "bin")
|
|
||||||
add_custom_command(TARGET ${additional_target} POST_BUILD
|
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy
|
|
||||||
"$<TARGET_FILE:${additional_target}>"
|
|
||||||
"${EXTERNAL_PLUGIN_OUTPUT_DIR}/$<CONFIGURATION>/${target}/bin/${_bit_suffix}$<TARGET_FILE_NAME:${additional_target}>"
|
|
||||||
VERBATIM)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Installs the binary of the target
|
|
||||||
# 'target' is the target project being installed
|
|
||||||
function(install_external_plugin target)
|
|
||||||
install_external_plugin_additional(${target} ${target})
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Installs the binary and data of the target
|
|
||||||
# 'target' is the destination target project being installed to
|
|
||||||
function(install_external_plugin_with_data target data_loc)
|
|
||||||
install_external_plugin(${target})
|
|
||||||
install_external_plugin_data(${target} ${data_loc})
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Installs an additional binary to the data of a target
|
|
||||||
# 'target' is the destination target project being installed to
|
|
||||||
# 'additional_target' specifies the additional binary
|
|
||||||
function(install_external_plugin_bin_to_data target additional_target)
|
|
||||||
install(TARGETS ${additional_target}
|
|
||||||
LIBRARY DESTINATION "data"
|
|
||||||
RUNTIME DESTINATION "data")
|
|
||||||
add_custom_command(TARGET ${additional_target} POST_BUILD
|
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy
|
|
||||||
"$<TARGET_FILE:${additional_target}>"
|
|
||||||
"${EXTERNAL_PLUGIN_OUTPUT_DIR}/$<CONFIGURATION>/${target}/data/$<TARGET_FILE_NAME:${additional_target}>"
|
|
||||||
VERBATIM)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Installs an additional binary in an architecture-specific data directory on windows/linux (data/32bit or data/64bit). Does not apply for mac.
|
|
||||||
# 'target' is the destination target project being installed to
|
|
||||||
# 'additional_target' specifies the additional binary
|
|
||||||
function(install_external_plugin_bin_to_arch_data target additional_target)
|
|
||||||
if(APPLE)
|
|
||||||
set(_bit_suffix "")
|
|
||||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
||||||
set(_bit_suffix "/64bit")
|
|
||||||
else()
|
|
||||||
set(_bit_suffix "/32bit")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
install(TARGETS ${additional_target}
|
|
||||||
LIBRARY DESTINATION "data${_bit_suffix}"
|
|
||||||
RUNTIME DESTINATION "data${_bit_suffix}")
|
|
||||||
add_custom_command(TARGET ${additional_target} POST_BUILD
|
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy
|
|
||||||
"$<TARGET_FILE:${additional_target}>"
|
|
||||||
"${EXTERNAL_PLUGIN_OUTPUT_DIR}/$<CONFIGURATION>/${target}/data${_bit_suffix}/$<TARGET_FILE_NAME:${additional_target}>"
|
|
||||||
VERBATIM)
|
|
||||||
endfunction()
|
|
||||||
|
|
||||||
# Installs an additional file in an architecture-specific data directory on windows/linux (data/32bit or data/64bit). Does not apply for mac.
|
|
||||||
# 'target' is the destination target project being installed to
|
|
||||||
# 'additional_target' specifies the additional binary
|
|
||||||
function(install_external_plugin_data_file_to_arch_data target additional_target file_target)
|
|
||||||
if(APPLE)
|
|
||||||
set(_bit_suffix "")
|
|
||||||
elseif(CMAKE_SIZEOF_VOID_P EQUAL 8)
|
|
||||||
set(_bit_suffix "/64bit")
|
|
||||||
else()
|
|
||||||
set(_bit_suffix "/32bit")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
get_filename_component(file_target_name ${file_target} NAME)
|
|
||||||
|
|
||||||
install(TARGETS ${additional_target}
|
|
||||||
LIBRARY DESTINATION "data${_bit_suffix}"
|
|
||||||
RUNTIME DESTINATION "data${_bit_suffix}")
|
|
||||||
add_custom_command(TARGET ${additional_target} POST_BUILD
|
|
||||||
COMMAND "${CMAKE_COMMAND}" -E copy
|
|
||||||
"${file_target}"
|
|
||||||
"${EXTERNAL_PLUGIN_OUTPUT_DIR}/$<CONFIGURATION>/${target}/data${_bit_suffix}/${file_target_name}"
|
|
||||||
VERBATIM)
|
|
||||||
endfunction()
|
|
||||||
@@ -693,13 +693,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="Line" name="line_4">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
<item>
|
||||||
<spacer name="horizontalSpacer_65">
|
<spacer name="horizontalSpacer_65">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
@@ -3723,6 +3716,13 @@
|
|||||||
<string>AdvSceneSwitcher.networkTab.title</string>
|
<string>AdvSceneSwitcher.networkTab.title</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_30">
|
<layout class="QVBoxLayout" name="verticalLayout_30">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="networkTabDescription">
|
||||||
|
<property name="text">
|
||||||
|
<string>AdvSceneSwitcher.networkTab.description</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="networkTabWarningLabel">
|
<widget class="QLabel" name="networkTabWarningLabel">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
|
|||||||
@@ -277,6 +277,12 @@ void SwitcherData::setPreconditions()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
currentTitle = title;
|
currentTitle = title;
|
||||||
|
|
||||||
|
// Cursor
|
||||||
|
std::pair<int, int> cursorPos = getCursorPos();
|
||||||
|
cursorPosChanged = cursorPos.first != switcher->lastCursorPos.first ||
|
||||||
|
cursorPos.second != switcher->lastCursorPos.second;
|
||||||
|
lastCursorPos = getCursorPos();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SwitcherData::checkForMatch(OBSWeakSource &scene,
|
bool SwitcherData::checkForMatch(OBSWeakSource &scene,
|
||||||
@@ -354,8 +360,7 @@ void switchScene(const sceneSwitchInfo &sceneSwitch)
|
|||||||
}
|
}
|
||||||
|
|
||||||
obs_source_t *source = obs_weak_source_get_source(sceneSwitch.scene);
|
obs_source_t *source = obs_weak_source_get_source(sceneSwitch.scene);
|
||||||
obs_source_t *currentSource =
|
obs_source_t *currentSource = obs_frontend_get_current_scene();
|
||||||
obs_weak_source_get_source(switcher->currentScene);
|
|
||||||
|
|
||||||
if (source && source != currentSource) {
|
if (source && source != currentSource) {
|
||||||
transitionData currentTransitionData;
|
transitionData currentTransitionData;
|
||||||
@@ -418,8 +423,9 @@ void SwitcherData::Stop()
|
|||||||
{
|
{
|
||||||
if (th && th->isRunning()) {
|
if (th && th->isRunning()) {
|
||||||
stop = true;
|
stop = true;
|
||||||
transitionCv.notify_one();
|
|
||||||
cv.notify_one();
|
cv.notify_one();
|
||||||
|
abortMacroWait = true;
|
||||||
|
macroWaitCv.notify_one();
|
||||||
th->wait();
|
th->wait();
|
||||||
delete th;
|
delete th;
|
||||||
th = nullptr;
|
th = nullptr;
|
||||||
@@ -469,6 +475,9 @@ extern "C" void FreeSceneSwitcher()
|
|||||||
|
|
||||||
void handleSceneChange()
|
void handleSceneChange()
|
||||||
{
|
{
|
||||||
|
switcher->lastSceneChangeTime =
|
||||||
|
std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
// Stop waiting if scene was changed
|
// Stop waiting if scene was changed
|
||||||
if (switcher->sceneChangedDuringWait()) {
|
if (switcher->sceneChangedDuringWait()) {
|
||||||
switcher->cv.notify_one();
|
switcher->cv.notify_one();
|
||||||
@@ -538,6 +547,12 @@ void setReplayBufferSaved()
|
|||||||
switcher->replayBufferSaved = true;
|
switcher->replayBufferSaved = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setTranstionEnd()
|
||||||
|
{
|
||||||
|
switcher->lastTransitionEndTime =
|
||||||
|
std::chrono::high_resolution_clock::now();
|
||||||
|
}
|
||||||
|
|
||||||
// Note to future self:
|
// Note to future self:
|
||||||
// be careful using switcher->m here as there is potential for deadlocks when using
|
// be careful using switcher->m here as there is potential for deadlocks when using
|
||||||
// frontend functions such as obs_frontend_set_current_scene()
|
// frontend functions such as obs_frontend_set_current_scene()
|
||||||
@@ -569,9 +584,14 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
|||||||
case OBS_FRONTEND_EVENT_STREAMING_STOPPED:
|
case OBS_FRONTEND_EVENT_STREAMING_STOPPED:
|
||||||
resetLiveTime();
|
resetLiveTime();
|
||||||
break;
|
break;
|
||||||
|
#ifdef REPLAYBUFFER_SUPPORTED
|
||||||
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED:
|
case OBS_FRONTEND_EVENT_REPLAY_BUFFER_SAVED:
|
||||||
setReplayBufferSaved();
|
setReplayBufferSaved();
|
||||||
break;
|
break;
|
||||||
|
#endif
|
||||||
|
case OBS_FRONTEND_EVENT_TRANSITION_STOPPED:
|
||||||
|
setTranstionEnd();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|||||||
49
src/file-selection.cpp
Normal file
49
src/file-selection.cpp
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#include "headers/file-selection.hpp"
|
||||||
|
|
||||||
|
#include <obs-module.h>
|
||||||
|
#include <QLayout>
|
||||||
|
#include <QFileDialog>
|
||||||
|
|
||||||
|
FileSelection::FileSelection(FileSelection::Type type, QWidget *parent)
|
||||||
|
: _type(type), QWidget(parent)
|
||||||
|
{
|
||||||
|
_filePath = new QLineEdit();
|
||||||
|
_browseButton =
|
||||||
|
new QPushButton(obs_module_text("AdvSceneSwitcher.browse"));
|
||||||
|
|
||||||
|
QWidget::connect(_filePath, SIGNAL(editingFinished()), this,
|
||||||
|
SLOT(PathChange()));
|
||||||
|
QWidget::connect(_browseButton, SIGNAL(clicked()), this,
|
||||||
|
SLOT(BrowseButtonClicked()));
|
||||||
|
QHBoxLayout *layout = new QHBoxLayout;
|
||||||
|
layout->addWidget(_filePath);
|
||||||
|
layout->addWidget(_browseButton);
|
||||||
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
setLayout(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSelection::SetPath(const QString &path)
|
||||||
|
{
|
||||||
|
_filePath->setText(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSelection::BrowseButtonClicked()
|
||||||
|
{
|
||||||
|
QString path;
|
||||||
|
if (_type == FileSelection::Type::WRITE) {
|
||||||
|
path = QFileDialog::getSaveFileName(this);
|
||||||
|
} else {
|
||||||
|
path = QFileDialog::getOpenFileName(this);
|
||||||
|
}
|
||||||
|
if (path.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_filePath->setText(path);
|
||||||
|
emit PathChanged(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileSelection::PathChange()
|
||||||
|
{
|
||||||
|
emit PathChanged(_filePath->text());
|
||||||
|
}
|
||||||
@@ -3,12 +3,21 @@
|
|||||||
#include "headers/version.h"
|
#include "headers/version.h"
|
||||||
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#if __linux__
|
||||||
|
#include <QDesktopWidget>
|
||||||
|
#endif
|
||||||
|
|
||||||
QMetaObject::Connection inactivePluse;
|
QMetaObject::Connection inactivePluse;
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_close_clicked()
|
void AdvSceneSwitcher::on_close_clicked()
|
||||||
{
|
{
|
||||||
done(0);
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::reject()
|
||||||
|
{
|
||||||
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::UpdateNonMatchingScene(const QString &name)
|
void AdvSceneSwitcher::UpdateNonMatchingScene(const QString &name)
|
||||||
@@ -377,9 +386,23 @@ void AdvSceneSwitcher::setTabOrder()
|
|||||||
connect(bar, &QTabBar::tabMoved, this, &AdvSceneSwitcher::on_tabMoved);
|
connect(bar, &QTabBar::tabMoved, this, &AdvSceneSwitcher::on_tabMoved);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool windowPosValid(QPoint pos)
|
||||||
|
{
|
||||||
|
#if __linux__
|
||||||
|
// QDesktopWidget::availableGeometry() is deprecated.
|
||||||
|
// Switch to QGuiApplication::screenAt() when it is available on most Linux platforms.
|
||||||
|
QDesktopWidget *desktop = QApplication::desktop();
|
||||||
|
auto screen = desktop->availableGeometry(pos);
|
||||||
|
return (pos.x() > screen.x()) && (pos.y() > screen.y()) &&
|
||||||
|
(pos.x() < screen.width() && (pos.y() < screen.height()));
|
||||||
|
#else
|
||||||
|
return !!QGuiApplication::screenAt(pos);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::restoreWindowGeo()
|
void AdvSceneSwitcher::restoreWindowGeo()
|
||||||
{
|
{
|
||||||
if (switcher->saveWindowGeo) {
|
if (switcher->saveWindowGeo && windowPosValid(switcher->windowPos)) {
|
||||||
this->resize(switcher->windowSize);
|
this->resize(switcher->windowSize);
|
||||||
this->move(switcher->windowPos);
|
this->move(switcher->windowPos);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
class QCloseEvent;
|
class QCloseEvent;
|
||||||
|
class MacroActionEdit;
|
||||||
|
class MacroConditionEdit;
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Advanced Scene Switcher window
|
* Advanced Scene Switcher window
|
||||||
@@ -28,6 +30,7 @@ public:
|
|||||||
|
|
||||||
AdvSceneSwitcher(QWidget *parent);
|
AdvSceneSwitcher(QWidget *parent);
|
||||||
|
|
||||||
|
void reject() override;
|
||||||
void closeEvent(QCloseEvent *event) override;
|
void closeEvent(QCloseEvent *event) override;
|
||||||
|
|
||||||
void SetStarted();
|
void SetStarted();
|
||||||
@@ -47,6 +50,12 @@ public:
|
|||||||
bool addNewMacro(std::string &name);
|
bool addNewMacro(std::string &name);
|
||||||
Macro *getSelectedMacro();
|
Macro *getSelectedMacro();
|
||||||
void SetEditMacro(Macro &m);
|
void SetEditMacro(Macro &m);
|
||||||
|
void HighlightAction(int idx);
|
||||||
|
void HighlightCondition(int idx);
|
||||||
|
void ConnectControlSignals(MacroActionEdit *);
|
||||||
|
void ConnectControlSignals(MacroConditionEdit *);
|
||||||
|
void SwapActions(Macro *m, int pos1, int pos2);
|
||||||
|
void SwapConditions(Macro *m, int pos1, int pos2);
|
||||||
|
|
||||||
void loadUI();
|
void loadUI();
|
||||||
void setupGeneralTab();
|
void setupGeneralTab();
|
||||||
@@ -109,8 +118,22 @@ public slots:
|
|||||||
void on_conditionRemove_clicked();
|
void on_conditionRemove_clicked();
|
||||||
void on_actionAdd_clicked();
|
void on_actionAdd_clicked();
|
||||||
void on_actionRemove_clicked();
|
void on_actionRemove_clicked();
|
||||||
void showMacroContextMenu(const QPoint &);
|
void ShowMacroContextMenu(const QPoint &);
|
||||||
void copyMacro();
|
void ShowMacroActionsContextMenu(const QPoint &);
|
||||||
|
void ShowMacroConditionsContextMenu(const QPoint &);
|
||||||
|
void CopyMacro();
|
||||||
|
void ExpandAllActions();
|
||||||
|
void ExpandAllConditions();
|
||||||
|
void CollapseAllActions();
|
||||||
|
void CollapseAllConditions();
|
||||||
|
void AddMacroAction(int idx);
|
||||||
|
void RemoveMacroAction(int idx);
|
||||||
|
void MoveMacroActionUp(int idx);
|
||||||
|
void MoveMacroActionDown(int idx);
|
||||||
|
void AddMacroCondition(int idx);
|
||||||
|
void RemoveMacroCondition(int idx);
|
||||||
|
void MoveMacroConditionUp(int idx);
|
||||||
|
void MoveMacroConditionDown(int idx);
|
||||||
|
|
||||||
void on_screenRegionSwitches_currentRowChanged(int idx);
|
void on_screenRegionSwitches_currentRowChanged(int idx);
|
||||||
void on_showFrame_clicked();
|
void on_showFrame_clicked();
|
||||||
|
|||||||
30
src/headers/file-selection.hpp
Normal file
30
src/headers/file-selection.hpp
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class FileSelection : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum class Type {
|
||||||
|
READ,
|
||||||
|
WRITE,
|
||||||
|
};
|
||||||
|
|
||||||
|
FileSelection(FileSelection::Type type = FileSelection::Type::READ,
|
||||||
|
QWidget *parent = 0);
|
||||||
|
void SetPath(const QString &);
|
||||||
|
QPushButton *Button() { return _browseButton; }
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void BrowseButtonClicked();
|
||||||
|
void PathChange();
|
||||||
|
signals:
|
||||||
|
void PathChanged(const QString &);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Type _type;
|
||||||
|
QLineEdit *_filePath;
|
||||||
|
QPushButton *_browseButton;
|
||||||
|
};
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
|
|
||||||
enum class AudioAction {
|
enum class AudioAction {
|
||||||
|
|||||||
@@ -1,13 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QGroupBox>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <deque>
|
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include "section.hpp"
|
|
||||||
|
|
||||||
struct MacroActionInfo {
|
struct MacroActionInfo {
|
||||||
using TCreateMethod = std::shared_ptr<MacroAction> (*)();
|
using TCreateMethod = std::shared_ptr<MacroAction> (*)();
|
||||||
@@ -33,34 +25,23 @@ private:
|
|||||||
static std::map<std::string, MacroActionInfo> _methods;
|
static std::map<std::string, MacroActionInfo> _methods;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MacroActionEdit : public QWidget {
|
class MacroActionEdit : public MacroSegmentEdit {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MacroActionEdit(QWidget *parent = nullptr,
|
MacroActionEdit(QWidget *parent = nullptr,
|
||||||
std::shared_ptr<MacroAction> * = nullptr,
|
std::shared_ptr<MacroAction> * = nullptr,
|
||||||
const std::string &id = "scene_switch",
|
const std::string &id = "scene_switch");
|
||||||
bool startCollapsed = false);
|
void UpdateEntryData(const std::string &id);
|
||||||
void UpdateEntryData(const std::string &id, bool collapse);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ActionSelectionChanged(const QString &text);
|
void ActionSelectionChanged(const QString &text);
|
||||||
void HeaderInfoChanged(const QString &);
|
|
||||||
signals:
|
|
||||||
void MacroAdded(const QString &name);
|
|
||||||
void MacroRemoved(const QString &name);
|
|
||||||
void MacroRenamed(const QString &oldName, const QString newName);
|
|
||||||
void SceneGroupAdded(const QString &name);
|
|
||||||
void SceneGroupRemoved(const QString &name);
|
|
||||||
void SceneGroupRenamed(const QString &oldName, const QString newName);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QComboBox *_actionSelection;
|
|
||||||
Section *_section;
|
|
||||||
QLabel *_headerInfo;
|
|
||||||
|
|
||||||
std::shared_ptr<MacroAction> *_entryData;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
MacroSegment *Data();
|
||||||
|
|
||||||
|
QComboBox *_actionSelection;
|
||||||
|
|
||||||
|
std::shared_ptr<MacroAction> *_entryData;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
#include <QPlainTextEdit>
|
#include <QPlainTextEdit>
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
|
#include "file-selection.hpp"
|
||||||
|
|
||||||
enum class FileAction {
|
enum class FileAction {
|
||||||
WRITE,
|
WRITE,
|
||||||
@@ -47,16 +48,14 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void FilePathChanged();
|
void PathChanged(const QString &text);
|
||||||
void BrowseButtonClicked();
|
|
||||||
void TextChanged();
|
void TextChanged();
|
||||||
void ActionChanged(int value);
|
void ActionChanged(int value);
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QLineEdit *_filePath;
|
FileSelection *_filePath;
|
||||||
QPushButton *_browseButton;
|
|
||||||
QPlainTextEdit *_text;
|
QPlainTextEdit *_text;
|
||||||
QComboBox *_actions;
|
QComboBox *_actions;
|
||||||
std::shared_ptr<MacroActionFile> _entryData;
|
std::shared_ptr<MacroActionFile> _entryData;
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
#include "hotkey.hpp"
|
#include "hotkey.hpp"
|
||||||
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
class MacroActionHotkey : public MacroAction {
|
class MacroActionHotkey : public MacroAction {
|
||||||
public:
|
public:
|
||||||
@@ -26,6 +28,12 @@ public:
|
|||||||
bool _rightAlt = false;
|
bool _rightAlt = false;
|
||||||
bool _leftMeta = false;
|
bool _leftMeta = false;
|
||||||
bool _rightMeta = false;
|
bool _rightMeta = false;
|
||||||
|
int _duration = 300; // in ms
|
||||||
|
#ifdef __APPLE__
|
||||||
|
bool _onlySendToObs = true;
|
||||||
|
#else
|
||||||
|
bool _onlySendToObs = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
@@ -58,6 +66,8 @@ private slots:
|
|||||||
void RAltChanged(int state);
|
void RAltChanged(int state);
|
||||||
void LMetaChanged(int state);
|
void LMetaChanged(int state);
|
||||||
void RMetaChanged(int state);
|
void RMetaChanged(int state);
|
||||||
|
void DurationChanged(int ms);
|
||||||
|
void OnlySendToOBSChanged(int state);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QComboBox *_keys;
|
QComboBox *_keys;
|
||||||
@@ -69,10 +79,14 @@ protected:
|
|||||||
QCheckBox *_rightAlt;
|
QCheckBox *_rightAlt;
|
||||||
QCheckBox *_leftMeta;
|
QCheckBox *_leftMeta;
|
||||||
QCheckBox *_rightMeta;
|
QCheckBox *_rightMeta;
|
||||||
|
QSpinBox *_duration;
|
||||||
|
QCheckBox *_onlySendToOBS;
|
||||||
|
QLabel *_noKeyPressSimulationWarning;
|
||||||
|
|
||||||
std::shared_ptr<MacroActionHotkey> _entryData;
|
std::shared_ptr<MacroActionHotkey> _entryData;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void SetWarningVisibility();
|
||||||
QHBoxLayout *_mainLayout;
|
QHBoxLayout *_mainLayout;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <QDoubleSpinBox>
|
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
#include "macro-selection.hpp"
|
#include "macro-selection.hpp"
|
||||||
|
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
enum class PerformMacroAction {
|
enum class PerformMacroAction {
|
||||||
PAUSE,
|
PAUSE,
|
||||||
UNPAUSE,
|
UNPAUSE,
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <QSpinBox>
|
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
|
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
enum class MediaAction {
|
enum class MediaAction {
|
||||||
PLAY,
|
PLAY,
|
||||||
PAUSE,
|
PAUSE,
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <QDoubleSpinBox>
|
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
|
|
||||||
|
#include <QDoubleSpinBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
enum class PluginStateAction {
|
enum class PluginStateAction {
|
||||||
STOP,
|
STOP,
|
||||||
NO_MATCH_BEHAVIOUR,
|
NO_MATCH_BEHAVIOUR,
|
||||||
|
|||||||
54
src/headers/macro-action-preview-scene.hpp
Normal file
54
src/headers/macro-action-preview-scene.hpp
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro-action-edit.hpp"
|
||||||
|
#include "scene-selection.hpp"
|
||||||
|
|
||||||
|
class MacroActionPreviewScene : public MacroAction {
|
||||||
|
public:
|
||||||
|
bool PerformAction();
|
||||||
|
void LogAction();
|
||||||
|
bool Save(obs_data_t *obj);
|
||||||
|
bool Load(obs_data_t *obj);
|
||||||
|
std::string GetShortDesc();
|
||||||
|
std::string GetId() { return id; };
|
||||||
|
static std::shared_ptr<MacroAction> Create()
|
||||||
|
{
|
||||||
|
return std::make_shared<MacroActionPreviewScene>();
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneSelection _scene;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool _registered;
|
||||||
|
static const std::string id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroActionPreviewSceneEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroActionPreviewSceneEdit(
|
||||||
|
QWidget *parent,
|
||||||
|
std::shared_ptr<MacroActionPreviewScene> entryData = nullptr);
|
||||||
|
void UpdateEntryData();
|
||||||
|
static QWidget *Create(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroAction> action)
|
||||||
|
{
|
||||||
|
return new MacroActionPreviewSceneEdit(
|
||||||
|
parent,
|
||||||
|
std::dynamic_pointer_cast<MacroActionPreviewScene>(
|
||||||
|
action));
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void SceneChanged(const SceneSelection &);
|
||||||
|
signals:
|
||||||
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SceneSelectionWidget *_scenes;
|
||||||
|
std::shared_ptr<MacroActionPreviewScene> _entryData;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QHBoxLayout *_mainLayout;
|
||||||
|
bool _loading = true;
|
||||||
|
};
|
||||||
@@ -1,8 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <QDoubleSpinBox>
|
|
||||||
#include <QLabel>
|
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
enum class RecordAction {
|
enum class RecordAction {
|
||||||
STOP,
|
STOP,
|
||||||
START,
|
START,
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
|
#ifdef REPLAYBUFFER_SUPPORTED
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <QDoubleSpinBox>
|
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
#include "duration-control.hpp"
|
#include "duration-control.hpp"
|
||||||
|
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
enum class ReplayBufferAction {
|
enum class ReplayBufferAction {
|
||||||
STOP,
|
STOP,
|
||||||
START,
|
START,
|
||||||
@@ -64,3 +67,5 @@ private:
|
|||||||
QHBoxLayout *_mainLayout;
|
QHBoxLayout *_mainLayout;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
|
#include "file-selection.hpp"
|
||||||
|
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
@@ -43,8 +44,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void FilePathChanged();
|
void PathChanged(const QString &text);
|
||||||
void BrowseButtonClicked();
|
|
||||||
void AddArg();
|
void AddArg();
|
||||||
void RemoveArg();
|
void RemoveArg();
|
||||||
void ArgUp();
|
void ArgUp();
|
||||||
@@ -56,8 +56,7 @@ protected:
|
|||||||
std::shared_ptr<MacroActionRun> _entryData;
|
std::shared_ptr<MacroActionRun> _entryData;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QLineEdit *_filePath;
|
FileSelection *_filePath;
|
||||||
QPushButton *_browseButton;
|
|
||||||
QListWidget *_argList;
|
QListWidget *_argList;
|
||||||
QPushButton *_addArg;
|
QPushButton *_addArg;
|
||||||
QPushButton *_removeArg;
|
QPushButton *_removeArg;
|
||||||
|
|||||||
38
src/headers/macro-action-scene-swap.hpp
Normal file
38
src/headers/macro-action-scene-swap.hpp
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro-action-edit.hpp"
|
||||||
|
|
||||||
|
class MacroActionSceneSwap : public MacroAction {
|
||||||
|
public:
|
||||||
|
bool PerformAction();
|
||||||
|
void LogAction();
|
||||||
|
bool Save(obs_data_t *obj);
|
||||||
|
bool Load(obs_data_t *obj);
|
||||||
|
std::string GetId() { return id; };
|
||||||
|
static std::shared_ptr<MacroAction> Create()
|
||||||
|
{
|
||||||
|
return std::make_shared<MacroActionSceneSwap>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool _registered;
|
||||||
|
static const std::string id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroActionSceneSwapEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroActionSceneSwapEdit(
|
||||||
|
QWidget *parent,
|
||||||
|
std::shared_ptr<MacroActionSceneSwap> entryData = nullptr);
|
||||||
|
static QWidget *Create(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroAction> action)
|
||||||
|
{
|
||||||
|
return new MacroActionSceneSwapEdit(
|
||||||
|
parent, std::dynamic_pointer_cast<MacroActionSceneSwap>(
|
||||||
|
action));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<MacroActionSceneSwap> _entryData;
|
||||||
|
};
|
||||||
@@ -1,8 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <QDoubleSpinBox>
|
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
#include "duration-control.hpp"
|
#include "duration-control.hpp"
|
||||||
|
|
||||||
|
#include <QDoubleSpinBox>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
enum class StreamAction {
|
enum class StreamAction {
|
||||||
STOP,
|
STOP,
|
||||||
START,
|
START,
|
||||||
|
|||||||
68
src/headers/macro-action-transition.hpp
Normal file
68
src/headers/macro-action-transition.hpp
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro-action-edit.hpp"
|
||||||
|
#include "duration-control.hpp"
|
||||||
|
#include "transition-selection.hpp"
|
||||||
|
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
|
class MacroActionTransition : public MacroAction {
|
||||||
|
public:
|
||||||
|
bool PerformAction();
|
||||||
|
void LogAction();
|
||||||
|
bool Save(obs_data_t *obj);
|
||||||
|
bool Load(obs_data_t *obj);
|
||||||
|
std::string GetShortDesc();
|
||||||
|
std::string GetId() { return id; };
|
||||||
|
static std::shared_ptr<MacroAction> Create()
|
||||||
|
{
|
||||||
|
return std::make_shared<MacroActionTransition>();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _setDuration = true;
|
||||||
|
bool _setType = true;
|
||||||
|
TransitionSelection _transition;
|
||||||
|
Duration _duration;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool _registered;
|
||||||
|
static const std::string id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroActionTransitionEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroActionTransitionEdit(
|
||||||
|
QWidget *parent,
|
||||||
|
std::shared_ptr<MacroActionTransition> entryData = nullptr);
|
||||||
|
void UpdateEntryData();
|
||||||
|
static QWidget *Create(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroAction> action)
|
||||||
|
{
|
||||||
|
return new MacroActionTransitionEdit(
|
||||||
|
parent,
|
||||||
|
std::dynamic_pointer_cast<MacroActionTransition>(
|
||||||
|
action));
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void SetTypeChanged(int state);
|
||||||
|
void SetDurationChanged(int state);
|
||||||
|
void TransitionChanged(const TransitionSelection &);
|
||||||
|
void DurationChanged(double seconds);
|
||||||
|
signals:
|
||||||
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QCheckBox *_setType;
|
||||||
|
QCheckBox *_setDuration;
|
||||||
|
TransitionSelectionWidget *_transitions;
|
||||||
|
DurationSelection *_duration;
|
||||||
|
QHBoxLayout *_typeLayout;
|
||||||
|
QHBoxLayout *_durationLayout;
|
||||||
|
std::shared_ptr<MacroActionTransition> _entryData;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _loading = true;
|
||||||
|
};
|
||||||
@@ -1,7 +1,11 @@
|
|||||||
|
#ifdef VCAM_SUPPORTED
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <QDoubleSpinBox>
|
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
enum class VCamAction {
|
enum class VCamAction {
|
||||||
STOP,
|
STOP,
|
||||||
START,
|
START,
|
||||||
@@ -53,3 +57,5 @@ private:
|
|||||||
QHBoxLayout *_mainLayout;
|
QHBoxLayout *_mainLayout;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <QDoubleSpinBox>
|
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
#include "duration-control.hpp"
|
#include "duration-control.hpp"
|
||||||
|
|
||||||
|
#include <QDoubleSpinBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
|
||||||
enum class WaitType {
|
enum class WaitType {
|
||||||
FIXED,
|
FIXED,
|
||||||
RANDOM,
|
RANDOM,
|
||||||
|
|||||||
76
src/headers/macro-condition-cursor.hpp
Normal file
76
src/headers/macro-condition-cursor.hpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro.hpp"
|
||||||
|
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QFrame>
|
||||||
|
|
||||||
|
enum class CursorCondition {
|
||||||
|
REGION,
|
||||||
|
MOVING,
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroConditionCursor : public MacroCondition {
|
||||||
|
public:
|
||||||
|
bool CheckCondition();
|
||||||
|
bool Save(obs_data_t *obj);
|
||||||
|
bool Load(obs_data_t *obj);
|
||||||
|
std::string GetId() { return id; };
|
||||||
|
static std::shared_ptr<MacroCondition> Create()
|
||||||
|
{
|
||||||
|
return std::make_shared<MacroConditionCursor>();
|
||||||
|
}
|
||||||
|
|
||||||
|
CursorCondition _condition = CursorCondition::REGION;
|
||||||
|
int _minX = 0, _minY = 0, _maxX = 0, _maxY = 0;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool _registered;
|
||||||
|
static const std::string id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroConditionCursorEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroConditionCursorEdit(
|
||||||
|
QWidget *parent,
|
||||||
|
std::shared_ptr<MacroConditionCursor> cond = nullptr);
|
||||||
|
void UpdateEntryData();
|
||||||
|
static QWidget *Create(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroCondition> cond)
|
||||||
|
{
|
||||||
|
return new MacroConditionCursorEdit(
|
||||||
|
parent,
|
||||||
|
std::dynamic_pointer_cast<MacroConditionCursor>(cond));
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void ConditionChanged(int cond);
|
||||||
|
void MinXChanged(int pos);
|
||||||
|
void MinYChanged(int pos);
|
||||||
|
void MaxXChanged(int pos);
|
||||||
|
void MaxYChanged(int pos);
|
||||||
|
void UpdateCursorPos();
|
||||||
|
void ToggleFrame();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QSpinBox *_minX;
|
||||||
|
QSpinBox *_minY;
|
||||||
|
QSpinBox *_maxX;
|
||||||
|
QSpinBox *_maxY;
|
||||||
|
QComboBox *_conditions;
|
||||||
|
QPushButton *_frameToggle;
|
||||||
|
QLabel *_xPos;
|
||||||
|
QLabel *_yPos;
|
||||||
|
std::shared_ptr<MacroConditionCursor> _entryData;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetRegionSelectionVisible(bool);
|
||||||
|
void SetupFrame();
|
||||||
|
QTimer _timer;
|
||||||
|
QFrame _frame;
|
||||||
|
bool _loading = true;
|
||||||
|
};
|
||||||
@@ -1,10 +1,18 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include <QWidget>
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QDateTimeEdit>
|
|
||||||
#include "duration-control.hpp"
|
#include "duration-control.hpp"
|
||||||
|
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QDateTimeEdit>
|
||||||
|
#include <QComboBox>
|
||||||
|
|
||||||
|
enum class DateCondition {
|
||||||
|
AT,
|
||||||
|
AFTER,
|
||||||
|
BEFORE,
|
||||||
|
BETWEEN,
|
||||||
|
};
|
||||||
|
|
||||||
class MacroConditionDate : public MacroCondition {
|
class MacroConditionDate : public MacroCondition {
|
||||||
public:
|
public:
|
||||||
bool CheckCondition();
|
bool CheckCondition();
|
||||||
@@ -18,10 +26,12 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
QDateTime _dateTime;
|
QDateTime _dateTime;
|
||||||
|
QDateTime _dateTime2;
|
||||||
bool _ignoreDate = false;
|
bool _ignoreDate = false;
|
||||||
bool _ignoreTime = false;
|
bool _ignoreTime = false;
|
||||||
bool _repeat = false;
|
bool _repeat = false;
|
||||||
Duration _duration;
|
Duration _duration;
|
||||||
|
DateCondition _condition = DateCondition::AT;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
@@ -45,7 +55,9 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
void ConditionChanged(int cond);
|
||||||
void DateTimeChanged(const QDateTime &datetime);
|
void DateTimeChanged(const QDateTime &datetime);
|
||||||
|
void DateTime2Changed(const QDateTime &datetime);
|
||||||
void IgnoreDateChanged(int state);
|
void IgnoreDateChanged(int state);
|
||||||
void IgnoreTimeChanged(int state);
|
void IgnoreTimeChanged(int state);
|
||||||
void RepeatChanged(int state);
|
void RepeatChanged(int state);
|
||||||
@@ -55,7 +67,9 @@ signals:
|
|||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
QComboBox *_condition;
|
||||||
QDateTimeEdit *_dateTime;
|
QDateTimeEdit *_dateTime;
|
||||||
|
QDateTimeEdit *_dateTime2;
|
||||||
QCheckBox *_ignoreDate;
|
QCheckBox *_ignoreDate;
|
||||||
QCheckBox *_ignoreTime;
|
QCheckBox *_ignoreTime;
|
||||||
QCheckBox *_repeat;
|
QCheckBox *_repeat;
|
||||||
@@ -63,5 +77,6 @@ protected:
|
|||||||
std::shared_ptr<MacroConditionDate> _entryData;
|
std::shared_ptr<MacroConditionDate> _entryData;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void ShowSecondDateSelection(bool visible);
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,12 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "advanced-scene-switcher.hpp"
|
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include "macro-condition-scene.hpp"
|
|
||||||
#include "section.hpp"
|
|
||||||
#include "utility.hpp"
|
|
||||||
|
|
||||||
#include <QGroupBox>
|
|
||||||
|
|
||||||
struct MacroConditionInfo {
|
struct MacroConditionInfo {
|
||||||
using TCreateMethod = std::shared_ptr<MacroCondition> (*)();
|
using TCreateMethod = std::shared_ptr<MacroCondition> (*)();
|
||||||
@@ -34,16 +27,16 @@ private:
|
|||||||
static std::map<std::string, MacroConditionInfo> _methods;
|
static std::map<std::string, MacroConditionInfo> _methods;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MacroConditionEdit : public QWidget {
|
class MacroConditionEdit : public MacroSegmentEdit {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MacroConditionEdit(QWidget *parent = nullptr,
|
MacroConditionEdit(QWidget *parent = nullptr,
|
||||||
std::shared_ptr<MacroCondition> * = nullptr,
|
std::shared_ptr<MacroCondition> * = nullptr,
|
||||||
const std::string &id = "scene", bool root = true,
|
const std::string &id = "scene", bool root = true);
|
||||||
bool startCollapsed = false);
|
|
||||||
bool IsRootNode();
|
bool IsRootNode();
|
||||||
void UpdateEntryData(const std::string &id, bool collapse);
|
void SetRootNode(bool);
|
||||||
|
void UpdateEntryData(const std::string &id);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void LogicSelectionChanged(int idx);
|
void LogicSelectionChanged(int idx);
|
||||||
@@ -51,25 +44,15 @@ private slots:
|
|||||||
void DurationChanged(double seconds);
|
void DurationChanged(double seconds);
|
||||||
void DurationConditionChanged(DurationCondition cond);
|
void DurationConditionChanged(DurationCondition cond);
|
||||||
void DurationUnitChanged(DurationUnit unit);
|
void DurationUnitChanged(DurationUnit unit);
|
||||||
void HeaderInfoChanged(const QString &);
|
|
||||||
signals:
|
|
||||||
void MacroAdded(const QString &name);
|
|
||||||
void MacroRemoved(const QString &name);
|
|
||||||
void MacroRenamed(const QString &oldName, const QString newName);
|
|
||||||
void SceneGroupAdded(const QString &name);
|
|
||||||
void SceneGroupRemoved(const QString &name);
|
|
||||||
void SceneGroupRenamed(const QString &oldName, const QString newName);
|
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
|
MacroSegment *Data();
|
||||||
|
|
||||||
QComboBox *_logicSelection;
|
QComboBox *_logicSelection;
|
||||||
QComboBox *_conditionSelection;
|
QComboBox *_conditionSelection;
|
||||||
Section *_section;
|
|
||||||
QLabel *_headerInfo;
|
|
||||||
DurationConstraintEdit *_dur;
|
DurationConstraintEdit *_dur;
|
||||||
|
|
||||||
std::shared_ptr<MacroCondition> *_entryData;
|
std::shared_ptr<MacroCondition> *_entryData;
|
||||||
|
|
||||||
private:
|
|
||||||
bool _isRoot = true;
|
bool _isRoot = true;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
|
#include "file-selection.hpp"
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
#include <QDateTime>
|
#include <QDateTime>
|
||||||
@@ -61,8 +63,7 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void FileTypeChanged(int index);
|
void FileTypeChanged(int index);
|
||||||
void FilePathChanged();
|
void PathChanged(const QString &text);
|
||||||
void BrowseButtonClicked();
|
|
||||||
void MatchTextChanged();
|
void MatchTextChanged();
|
||||||
void UseRegexChanged(int state);
|
void UseRegexChanged(int state);
|
||||||
void CheckModificationDateChanged(int state);
|
void CheckModificationDateChanged(int state);
|
||||||
@@ -72,8 +73,7 @@ signals:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
QComboBox *_fileType;
|
QComboBox *_fileType;
|
||||||
QLineEdit *_filePath;
|
FileSelection *_filePath;
|
||||||
QPushButton *_browseButton;
|
|
||||||
QPlainTextEdit *_matchText;
|
QPlainTextEdit *_matchText;
|
||||||
QCheckBox *_useRegex;
|
QCheckBox *_useRegex;
|
||||||
QCheckBox *_checkModificationDate;
|
QCheckBox *_checkModificationDate;
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include <QWidget>
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QPlainTextEdit>
|
||||||
|
#include <QCheckBox>
|
||||||
|
|
||||||
enum class FilterCondition {
|
enum class FilterCondition {
|
||||||
ENABLED,
|
ENABLED,
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include "macro-selection.hpp"
|
#include "macro-selection.hpp"
|
||||||
#include <QWidget>
|
|
||||||
|
#include <QComboBox>
|
||||||
#include <QSpinBox>
|
#include <QSpinBox>
|
||||||
#include <QLabel>
|
#include <QPushButton>
|
||||||
|
#include <QHBoxLayout>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
enum class MacroConditionMacroType {
|
enum class MacroConditionMacroType {
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include <QWidget>
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
#include <QCheckBox>
|
||||||
|
|
||||||
class MacroConditionProcess : public MacroCondition {
|
class MacroConditionProcess : public MacroCondition {
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "macro.hpp"
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QComboBox>
|
|
||||||
|
|
||||||
class MacroConditionRegion : public MacroCondition {
|
|
||||||
public:
|
|
||||||
bool CheckCondition();
|
|
||||||
bool Save(obs_data_t *obj);
|
|
||||||
bool Load(obs_data_t *obj);
|
|
||||||
std::string GetId() { return id; };
|
|
||||||
static std::shared_ptr<MacroCondition> Create()
|
|
||||||
{
|
|
||||||
return std::make_shared<MacroConditionRegion>();
|
|
||||||
}
|
|
||||||
|
|
||||||
int _minX = 0, _minY = 0, _maxX = 0, _maxY = 0;
|
|
||||||
|
|
||||||
private:
|
|
||||||
static bool _registered;
|
|
||||||
static const std::string id;
|
|
||||||
};
|
|
||||||
|
|
||||||
class MacroConditionRegionEdit : public QWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
MacroConditionRegionEdit(
|
|
||||||
QWidget *parent,
|
|
||||||
std::shared_ptr<MacroConditionRegion> cond = nullptr);
|
|
||||||
void UpdateEntryData();
|
|
||||||
static QWidget *Create(QWidget *parent,
|
|
||||||
std::shared_ptr<MacroCondition> cond)
|
|
||||||
{
|
|
||||||
return new MacroConditionRegionEdit(
|
|
||||||
parent,
|
|
||||||
std::dynamic_pointer_cast<MacroConditionRegion>(cond));
|
|
||||||
}
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void MinXChanged(int pos);
|
|
||||||
void MinYChanged(int pos);
|
|
||||||
void MaxXChanged(int pos);
|
|
||||||
void MaxYChanged(int pos);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
QSpinBox *_minX;
|
|
||||||
QSpinBox *_minY;
|
|
||||||
QSpinBox *_maxX;
|
|
||||||
QSpinBox *_maxY;
|
|
||||||
std::shared_ptr<MacroConditionRegion> _entryData;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool _loading = true;
|
|
||||||
};
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef REPLAYBUFFER_SUPPORTED
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
@@ -54,3 +56,5 @@ protected:
|
|||||||
private:
|
private:
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
69
src/headers/macro-condition-scene-transform.hpp
Normal file
69
src/headers/macro-condition-scene-transform.hpp
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro.hpp"
|
||||||
|
#include "scene-selection.hpp"
|
||||||
|
|
||||||
|
#include <QSpinBox>
|
||||||
|
#include <QPlainTextEdit>
|
||||||
|
#include <QCheckBox>
|
||||||
|
|
||||||
|
class MacroConditionSceneTransform : public MacroCondition {
|
||||||
|
public:
|
||||||
|
bool CheckCondition();
|
||||||
|
bool Save(obs_data_t *obj);
|
||||||
|
bool Load(obs_data_t *obj);
|
||||||
|
std::string GetShortDesc();
|
||||||
|
std::string GetId() { return id; };
|
||||||
|
static std::shared_ptr<MacroCondition> Create()
|
||||||
|
{
|
||||||
|
return std::make_shared<MacroConditionSceneTransform>();
|
||||||
|
}
|
||||||
|
|
||||||
|
SceneSelection _scene;
|
||||||
|
OBSWeakSource _source;
|
||||||
|
bool _regex = false;
|
||||||
|
std::string _settings = "";
|
||||||
|
|
||||||
|
private:
|
||||||
|
static bool _registered;
|
||||||
|
static const std::string id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroConditionSceneTransformEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroConditionSceneTransformEdit(
|
||||||
|
QWidget *parent,
|
||||||
|
std::shared_ptr<MacroConditionSceneTransform> entryData =
|
||||||
|
nullptr);
|
||||||
|
void UpdateEntryData();
|
||||||
|
static QWidget *Create(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroCondition> cond)
|
||||||
|
{
|
||||||
|
return new MacroConditionSceneTransformEdit(
|
||||||
|
parent,
|
||||||
|
std::dynamic_pointer_cast<MacroConditionSceneTransform>(
|
||||||
|
cond));
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void SceneChanged(const SceneSelection &);
|
||||||
|
void SourceChanged(const QString &text);
|
||||||
|
void GetSettingsClicked();
|
||||||
|
void SettingsChanged();
|
||||||
|
void RegexChanged(int);
|
||||||
|
signals:
|
||||||
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SceneSelectionWidget *_scenes;
|
||||||
|
QComboBox *_sources;
|
||||||
|
QPushButton *_getSettings;
|
||||||
|
QPlainTextEdit *_settings;
|
||||||
|
QCheckBox *_regex;
|
||||||
|
|
||||||
|
std::shared_ptr<MacroConditionSceneTransform> _entryData;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool _loading = true;
|
||||||
|
};
|
||||||
@@ -8,6 +8,8 @@
|
|||||||
enum class SceneType {
|
enum class SceneType {
|
||||||
CURRENT,
|
CURRENT,
|
||||||
PREVIOUS,
|
PREVIOUS,
|
||||||
|
CHANGED,
|
||||||
|
NOTCHANGED,
|
||||||
};
|
};
|
||||||
|
|
||||||
class MacroConditionScene : public MacroCondition {
|
class MacroConditionScene : public MacroCondition {
|
||||||
@@ -26,6 +28,7 @@ public:
|
|||||||
SceneType _type;
|
SceneType _type;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::chrono::high_resolution_clock::time_point _lastSceneChangeTime{};
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
static const std::string id;
|
static const std::string id;
|
||||||
};
|
};
|
||||||
@@ -58,5 +61,6 @@ protected:
|
|||||||
std::shared_ptr<MacroConditionScene> _entryData;
|
std::shared_ptr<MacroConditionScene> _entryData;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void SetWidgetVisibility();
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include <QWidget>
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QPlainTextEdit>
|
||||||
|
#include <QCheckBox>
|
||||||
|
|
||||||
enum class SourceCondition {
|
enum class SourceCondition {
|
||||||
ACTIVE,
|
ACTIVE,
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include <QWidget>
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QTimer>
|
|
||||||
#include "duration-control.hpp"
|
#include "duration-control.hpp"
|
||||||
|
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
class MacroConditionTimer : public MacroCondition {
|
class MacroConditionTimer : public MacroCondition {
|
||||||
public:
|
public:
|
||||||
bool CheckCondition();
|
bool CheckCondition();
|
||||||
|
|||||||
79
src/headers/macro-condition-transition.hpp
Normal file
79
src/headers/macro-condition-transition.hpp
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro.hpp"
|
||||||
|
#include "duration-control.hpp"
|
||||||
|
#include "transition-selection.hpp"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QComboBox>
|
||||||
|
|
||||||
|
enum class TransitionCondition {
|
||||||
|
CURRENT,
|
||||||
|
DURATION,
|
||||||
|
STARTED,
|
||||||
|
ENDED,
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroConditionTransition : public MacroCondition {
|
||||||
|
public:
|
||||||
|
bool CheckCondition();
|
||||||
|
bool Save(obs_data_t *obj);
|
||||||
|
bool Load(obs_data_t *obj);
|
||||||
|
std::string GetShortDesc();
|
||||||
|
std::string GetId() { return id; };
|
||||||
|
static std::shared_ptr<MacroCondition> Create()
|
||||||
|
{
|
||||||
|
return std::make_shared<MacroConditionTransition>();
|
||||||
|
}
|
||||||
|
void ConnectToTransitionSignals();
|
||||||
|
void DisconnectTransitionSignals();
|
||||||
|
|
||||||
|
TransitionCondition _condition = TransitionCondition::CURRENT;
|
||||||
|
TransitionSelection _transition;
|
||||||
|
Duration _duration;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void TransitionStarted(void *data, calldata_t *);
|
||||||
|
static void TransitionEnded(void *data, calldata_t *);
|
||||||
|
|
||||||
|
bool _started = false;
|
||||||
|
bool _ended = false;
|
||||||
|
std::chrono::high_resolution_clock::time_point _lastTransitionEndTime{};
|
||||||
|
static bool _registered;
|
||||||
|
static const std::string id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroConditionTransitionEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroConditionTransitionEdit(
|
||||||
|
QWidget *parent,
|
||||||
|
std::shared_ptr<MacroConditionTransition> cond = nullptr);
|
||||||
|
void UpdateEntryData();
|
||||||
|
static QWidget *Create(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroCondition> cond)
|
||||||
|
{
|
||||||
|
return new MacroConditionTransitionEdit(
|
||||||
|
parent,
|
||||||
|
std::dynamic_pointer_cast<MacroConditionTransition>(
|
||||||
|
cond));
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void ConditionChanged(int cond);
|
||||||
|
void TransitionChanged(const TransitionSelection &);
|
||||||
|
void DurationChanged(double seconds);
|
||||||
|
signals:
|
||||||
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QComboBox *_conditions;
|
||||||
|
TransitionSelectionWidget *_transitions;
|
||||||
|
DurationSelection *_duration;
|
||||||
|
QLabel *_durationSuffix;
|
||||||
|
std::shared_ptr<MacroConditionTransition> _entryData;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetWidgetVisibility();
|
||||||
|
bool _loading = true;
|
||||||
|
};
|
||||||
@@ -1,10 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include "screenshot-helper.hpp"
|
#include "screenshot-helper.hpp"
|
||||||
|
#include "file-selection.hpp"
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QHBoxLayout>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
|
#include <opencv2/opencv.hpp>
|
||||||
|
|
||||||
enum class VideoCondition {
|
enum class VideoCondition {
|
||||||
MATCH,
|
MATCH,
|
||||||
@@ -12,8 +16,13 @@ enum class VideoCondition {
|
|||||||
HAS_NOT_CHANGED,
|
HAS_NOT_CHANGED,
|
||||||
HAS_CHANGED,
|
HAS_CHANGED,
|
||||||
NO_IMAGE,
|
NO_IMAGE,
|
||||||
|
PATTERN,
|
||||||
|
OBJECT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr int minMinNeighbors = 3;
|
||||||
|
constexpr int maxMinNeighbors = 6;
|
||||||
|
|
||||||
class MacroConditionVideo : public MacroCondition {
|
class MacroConditionVideo : public MacroCondition {
|
||||||
public:
|
public:
|
||||||
bool CheckCondition();
|
bool CheckCondition();
|
||||||
@@ -28,20 +37,65 @@ public:
|
|||||||
}
|
}
|
||||||
void GetScreenshot();
|
void GetScreenshot();
|
||||||
bool LoadImageFromFile();
|
bool LoadImageFromFile();
|
||||||
|
bool LoadModelData(std::string &path);
|
||||||
|
std::string GetModelDataPath() { return _modelDataPath; }
|
||||||
|
void ResetLastMatch() { _lastMatchResult = false; }
|
||||||
|
|
||||||
OBSWeakSource _videoSource;
|
OBSWeakSource _videoSource;
|
||||||
VideoCondition _condition = VideoCondition::MATCH;
|
VideoCondition _condition = VideoCondition::MATCH;
|
||||||
std::string _file = obs_module_text("AdvSceneSwitcher.enterPath");
|
std::string _file = obs_module_text("AdvSceneSwitcher.enterPath");
|
||||||
|
double _patternThreshold = 0.8;
|
||||||
|
cv::CascadeClassifier _objectCascade;
|
||||||
|
double _scaleFactor = 1.1;
|
||||||
|
int _minNeighbors = minMinNeighbors;
|
||||||
|
int _minSizeX = 0;
|
||||||
|
int _minSizeY = 0;
|
||||||
|
int _maxSizeX = 0;
|
||||||
|
int _maxSizeY = 0;
|
||||||
|
|
||||||
|
bool _throttleEnabled = false;
|
||||||
|
int _throttleCount = 3;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool ScreenshotContainsPattern();
|
||||||
|
bool ScreenshotContainsObject();
|
||||||
bool Compare();
|
bool Compare();
|
||||||
|
bool CheckShouldBeSkipped();
|
||||||
|
|
||||||
std::unique_ptr<AdvSSScreenshotObj> _screenshotData = nullptr;
|
std::unique_ptr<AdvSSScreenshotObj> _screenshotData = nullptr;
|
||||||
QImage _matchImage;
|
QImage _matchImage;
|
||||||
|
std::string _modelDataPath =
|
||||||
|
obs_get_module_data_path(obs_current_module()) +
|
||||||
|
std::string(
|
||||||
|
"/res/cascadeClassifiers/haarcascade_frontalface_alt.xml");
|
||||||
|
bool _lastMatchResult = false;
|
||||||
|
int _runCount = 0;
|
||||||
|
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
static const std::string id;
|
static const std::string id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ThresholdSlider : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ThresholdSlider(double min = 0., double max = 1.,
|
||||||
|
const QString &label = "threshold",
|
||||||
|
const QString &description = "", QWidget *parent = 0);
|
||||||
|
void SetDoubleValue(double);
|
||||||
|
public slots:
|
||||||
|
void NotifyValueChanged(int value);
|
||||||
|
signals:
|
||||||
|
void DoubleValueChanged(double value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetDoubleValueText(double);
|
||||||
|
QLabel *_value;
|
||||||
|
QSlider *_slider;
|
||||||
|
double _scale = 100.0;
|
||||||
|
int _precision = 2;
|
||||||
|
};
|
||||||
|
|
||||||
class MacroConditionVideoEdit : public QWidget {
|
class MacroConditionVideoEdit : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@@ -59,23 +113,55 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
void UpdatePreviewTooltip();
|
void UpdatePreviewTooltip();
|
||||||
void SetFilePath(const QString &text);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void SourceChanged(const QString &text);
|
void SourceChanged(const QString &text);
|
||||||
void ConditionChanged(int cond);
|
void ConditionChanged(int cond);
|
||||||
void FilePathChanged();
|
void ImagePathChanged(const QString &text);
|
||||||
void BrowseButtonClicked();
|
void ImageBrowseButtonClicked();
|
||||||
|
void PatternThresholdChanged(double);
|
||||||
|
|
||||||
|
void ModelPathChanged(const QString &text);
|
||||||
|
void ObjectScaleThresholdChanged(double);
|
||||||
|
void MinNeighborsChanged(int value);
|
||||||
|
void MinSizeXChanged(int value);
|
||||||
|
void MinSizeYChanged(int value);
|
||||||
|
void MaxSizeXChanged(int value);
|
||||||
|
void MaxSizeYChanged(int value);
|
||||||
|
|
||||||
|
void ThrottleEnableChanged(int value);
|
||||||
|
void ThrottleCountChanged(int value);
|
||||||
|
void ShowMatchClicked();
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
QComboBox *_videoSelection;
|
QComboBox *_videoSelection;
|
||||||
QComboBox *_condition;
|
QComboBox *_condition;
|
||||||
QLineEdit *_filePath;
|
|
||||||
QPushButton *_browseButton;
|
FileSelection *_imagePath;
|
||||||
|
ThresholdSlider *_patternThreshold;
|
||||||
|
|
||||||
|
FileSelection *_modelDataPath;
|
||||||
|
QHBoxLayout *_modelPathLayout;
|
||||||
|
ThresholdSlider *_objectScaleThreshold;
|
||||||
|
QHBoxLayout *_neighborsControlLayout;
|
||||||
|
QSpinBox *_minNeighbors;
|
||||||
|
QHBoxLayout *_minSizeControlLayout;
|
||||||
|
QSpinBox *_minSizeX;
|
||||||
|
QSpinBox *_minSizeY;
|
||||||
|
QHBoxLayout *_maxSizeControlLayout;
|
||||||
|
QSpinBox *_maxSizeX;
|
||||||
|
QSpinBox *_maxSizeY;
|
||||||
|
|
||||||
|
QHBoxLayout *_throttleControlLayout;
|
||||||
|
QCheckBox *_throttleEnable;
|
||||||
|
QSpinBox *_throttleCount;
|
||||||
|
QPushButton *_showMatch;
|
||||||
|
|
||||||
std::shared_ptr<MacroConditionVideo> _entryData;
|
std::shared_ptr<MacroConditionVideo> _entryData;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void SetWidgetVisibility();
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef VCAM_SUPPORTED
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
@@ -52,3 +54,5 @@ protected:
|
|||||||
private:
|
private:
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include <QWidget>
|
|
||||||
#include <QComboBox>
|
#include <QComboBox>
|
||||||
|
#include <QCheckBox>
|
||||||
|
|
||||||
class MacroConditionWindow : public MacroCondition {
|
class MacroConditionWindow : public MacroCondition {
|
||||||
public:
|
public:
|
||||||
|
|||||||
31
src/headers/macro-controls.hpp
Normal file
31
src/headers/macro-controls.hpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QPropertyAnimation>
|
||||||
|
#include <QScrollArea>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QLayout>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class MacroEntryControls : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit MacroEntryControls(const int animationDuration = 300,
|
||||||
|
QWidget *parent = 0);
|
||||||
|
|
||||||
|
void Show(bool visible = true);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void Add();
|
||||||
|
void Remove();
|
||||||
|
void Up();
|
||||||
|
void Down();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QPushButton *_add;
|
||||||
|
QPushButton *_remove;
|
||||||
|
QPushButton *_up;
|
||||||
|
QPushButton *_down;
|
||||||
|
QPropertyAnimation *_animation = nullptr;
|
||||||
|
};
|
||||||
71
src/headers/macro-segment.hpp
Normal file
71
src/headers/macro-segment.hpp
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <QWidget>
|
||||||
|
#include <obs.hpp>
|
||||||
|
|
||||||
|
class MacroSegment {
|
||||||
|
public:
|
||||||
|
void SetIndex(int idx) { _idx = idx; }
|
||||||
|
int GetIndex() { return _idx; }
|
||||||
|
void SetCollapsed(bool collapsed) { _collapsed = collapsed; }
|
||||||
|
bool GetCollapsed() { return _collapsed; }
|
||||||
|
virtual bool Save(obs_data_t *obj) = 0;
|
||||||
|
virtual bool Load(obs_data_t *obj) = 0;
|
||||||
|
virtual std::string GetShortDesc();
|
||||||
|
virtual std::string GetId() = 0;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
int _idx;
|
||||||
|
bool _collapsed = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Section;
|
||||||
|
class QLabel;
|
||||||
|
class MacroEntryControls;
|
||||||
|
|
||||||
|
class MacroSegmentEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroSegmentEdit(QWidget *parent = nullptr);
|
||||||
|
// Use this function to avoid accidental edits when scrolling through
|
||||||
|
// list of actions and conditions
|
||||||
|
void SetFocusPolicyOfWidgets();
|
||||||
|
|
||||||
|
protected slots:
|
||||||
|
void HeaderInfoChanged(const QString &);
|
||||||
|
void Add();
|
||||||
|
void Remove();
|
||||||
|
void Up();
|
||||||
|
void Down();
|
||||||
|
void Collapsed(bool);
|
||||||
|
signals:
|
||||||
|
void MacroAdded(const QString &name);
|
||||||
|
void MacroRemoved(const QString &name);
|
||||||
|
void MacroRenamed(const QString &oldName, const QString newName);
|
||||||
|
void SceneGroupAdded(const QString &name);
|
||||||
|
void SceneGroupRemoved(const QString &name);
|
||||||
|
void SceneGroupRenamed(const QString &oldName, const QString newName);
|
||||||
|
void AddAt(int idx);
|
||||||
|
void RemoveAt(int idx);
|
||||||
|
void UpAt(int idx);
|
||||||
|
void DownAt(int idx);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void enterEvent(QEvent *e);
|
||||||
|
void leaveEvent(QEvent *e);
|
||||||
|
|
||||||
|
Section *_section;
|
||||||
|
QLabel *_headerInfo;
|
||||||
|
MacroEntryControls *_controls;
|
||||||
|
|
||||||
|
private:
|
||||||
|
virtual MacroSegment *Data() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MouseWheelWidgetAdjustmentGuard : public QObject {
|
||||||
|
public:
|
||||||
|
explicit MouseWheelWidgetAdjustmentGuard(QObject *parent);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *o, QEvent *e) override;
|
||||||
|
};
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "macro-segment.hpp"
|
||||||
#include "duration-control.hpp"
|
#include "duration-control.hpp"
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -36,14 +37,11 @@ struct LogicTypeInfo {
|
|||||||
std::string _name;
|
std::string _name;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MacroCondition {
|
class MacroCondition : public MacroSegment {
|
||||||
public:
|
public:
|
||||||
virtual bool CheckCondition() = 0;
|
virtual bool CheckCondition() = 0;
|
||||||
virtual bool Save(obs_data_t *obj) = 0;
|
virtual bool Save(obs_data_t *obj) = 0;
|
||||||
virtual bool Load(obs_data_t *obj) = 0;
|
virtual bool Load(obs_data_t *obj) = 0;
|
||||||
virtual std::string GetShortDesc();
|
|
||||||
virtual std::string GetId() = 0;
|
|
||||||
|
|
||||||
LogicType GetLogicType() { return _logic; }
|
LogicType GetLogicType() { return _logic; }
|
||||||
void SetLogicType(LogicType logic) { _logic = logic; }
|
void SetLogicType(LogicType logic) { _logic = logic; }
|
||||||
static const std::map<LogicType, LogicTypeInfo> logicTypes;
|
static const std::map<LogicType, LogicTypeInfo> logicTypes;
|
||||||
@@ -61,13 +59,11 @@ private:
|
|||||||
DurationConstraint _duration;
|
DurationConstraint _duration;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MacroAction {
|
class MacroAction : public MacroSegment {
|
||||||
public:
|
public:
|
||||||
virtual bool PerformAction() = 0;
|
virtual bool PerformAction() = 0;
|
||||||
virtual bool Save(obs_data_t *obj) = 0;
|
virtual bool Save(obs_data_t *obj) = 0;
|
||||||
virtual bool Load(obs_data_t *obj) = 0;
|
virtual bool Load(obs_data_t *obj) = 0;
|
||||||
virtual std::string GetShortDesc();
|
|
||||||
virtual std::string GetId() = 0;
|
|
||||||
virtual void LogAction();
|
virtual void LogAction();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -89,6 +85,8 @@ public:
|
|||||||
{
|
{
|
||||||
return _conditions;
|
return _conditions;
|
||||||
}
|
}
|
||||||
|
void UpdateActionIndices();
|
||||||
|
void UpdateConditionIndices();
|
||||||
std::deque<std::shared_ptr<MacroAction>> &Actions() { return _actions; }
|
std::deque<std::shared_ptr<MacroAction>> &Actions() { return _actions; }
|
||||||
|
|
||||||
bool Save(obs_data_t *obj);
|
bool Save(obs_data_t *obj);
|
||||||
|
|||||||
@@ -10,6 +10,6 @@ std::pair<int, int> getCursorPos();
|
|||||||
int secondsSinceLastInput();
|
int secondsSinceLastInput();
|
||||||
void GetProcessList(QStringList &processes);
|
void GetProcessList(QStringList &processes);
|
||||||
bool isInFocus(const QString &executable);
|
bool isInFocus(const QString &executable);
|
||||||
void PressKeys(const std::vector<HotkeyType> keys);
|
void PressKeys(const std::vector<HotkeyType> keys, int duration);
|
||||||
void PlatformInit();
|
void PlatformInit();
|
||||||
void PlatformCleanup();
|
void PlatformCleanup();
|
||||||
|
|||||||
@@ -23,6 +23,8 @@ protected:
|
|||||||
private slots:
|
private slots:
|
||||||
void AnimationFinished();
|
void AnimationFinished();
|
||||||
void Collapse(bool collapse);
|
void Collapse(bool collapse);
|
||||||
|
signals:
|
||||||
|
void Collapsed(bool);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetupAnimations();
|
void SetupAnimations();
|
||||||
|
|||||||
@@ -35,8 +35,7 @@ struct SceneSequenceSwitch : SceneSwitcherEntry {
|
|||||||
bool reduce();
|
bool reduce();
|
||||||
SceneSequenceSwitch *extend();
|
SceneSequenceSwitch *extend();
|
||||||
|
|
||||||
bool checkMatch(OBSWeakSource currentScene, int &linger,
|
bool checkMatch(int &linger, SceneSequenceSwitch *root = nullptr);
|
||||||
SceneSequenceSwitch *root = nullptr);
|
|
||||||
bool checkDurationMatchInterruptible();
|
bool checkDurationMatchInterruptible();
|
||||||
void prepareUninterruptibleMatch(int &linger);
|
void prepareUninterruptibleMatch(int &linger);
|
||||||
void advanceActiveSequence();
|
void advanceActiveSequence();
|
||||||
|
|||||||
@@ -67,7 +67,6 @@ struct SwitcherData {
|
|||||||
std::mutex m;
|
std::mutex m;
|
||||||
bool transitionActive = false;
|
bool transitionActive = false;
|
||||||
bool waitForTransition = false;
|
bool waitForTransition = false;
|
||||||
std::condition_variable transitionCv;
|
|
||||||
bool stop = false;
|
bool stop = false;
|
||||||
bool verbose = false;
|
bool verbose = false;
|
||||||
bool disableHints = false;
|
bool disableHints = false;
|
||||||
@@ -80,6 +79,8 @@ struct SwitcherData {
|
|||||||
obs_source_t *waitScene = nullptr;
|
obs_source_t *waitScene = nullptr;
|
||||||
OBSWeakSource currentScene = nullptr;
|
OBSWeakSource currentScene = nullptr;
|
||||||
OBSWeakSource previousScene = nullptr;
|
OBSWeakSource previousScene = nullptr;
|
||||||
|
std::chrono::high_resolution_clock::time_point lastSceneChangeTime{};
|
||||||
|
std::chrono::high_resolution_clock::time_point lastTransitionEndTime{};
|
||||||
OBSWeakSource lastRandomScene;
|
OBSWeakSource lastRandomScene;
|
||||||
SceneGroup *lastRandomSceneGroup;
|
SceneGroup *lastRandomSceneGroup;
|
||||||
OBSWeakSource nonMatchingScene;
|
OBSWeakSource nonMatchingScene;
|
||||||
@@ -92,6 +93,8 @@ struct SwitcherData {
|
|||||||
std::chrono::high_resolution_clock::time_point lastMatchTime;
|
std::chrono::high_resolution_clock::time_point lastMatchTime;
|
||||||
|
|
||||||
std::deque<Macro> macros;
|
std::deque<Macro> macros;
|
||||||
|
std::condition_variable macroWaitCv;
|
||||||
|
std::atomic_bool abortMacroWait = {false};
|
||||||
bool macroSceneSwitched = false;
|
bool macroSceneSwitched = false;
|
||||||
bool replayBufferSaved = false;
|
bool replayBufferSaved = false;
|
||||||
|
|
||||||
@@ -101,6 +104,8 @@ struct SwitcherData {
|
|||||||
std::string currentTitle;
|
std::string currentTitle;
|
||||||
|
|
||||||
std::deque<ScreenRegionSwitch> screenRegionSwitches;
|
std::deque<ScreenRegionSwitch> screenRegionSwitches;
|
||||||
|
std::pair<int, int> lastCursorPos = {0, 0};
|
||||||
|
bool cursorPosChanged = false;
|
||||||
|
|
||||||
std::vector<std::string> ignoreWindowsSwitches;
|
std::vector<std::string> ignoreWindowsSwitches;
|
||||||
|
|
||||||
|
|||||||
46
src/headers/transition-selection.hpp
Normal file
46
src/headers/transition-selection.hpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
|
||||||
|
enum class TransitionSelectionType {
|
||||||
|
TRANSITION,
|
||||||
|
CURRENT,
|
||||||
|
ANY,
|
||||||
|
};
|
||||||
|
|
||||||
|
class TransitionSelection {
|
||||||
|
public:
|
||||||
|
void Save(obs_data_t *obj, const char *name = "transition",
|
||||||
|
const char *typeName = "transitionType");
|
||||||
|
void Load(obs_data_t *obj, const char *name = "transition",
|
||||||
|
const char *typeName = "transitionType");
|
||||||
|
|
||||||
|
TransitionSelectionType GetType() { return _type; }
|
||||||
|
OBSWeakSource GetTransition();
|
||||||
|
std::string ToString();
|
||||||
|
|
||||||
|
private:
|
||||||
|
OBSWeakSource _transition;
|
||||||
|
TransitionSelectionType _type = TransitionSelectionType::TRANSITION;
|
||||||
|
friend class TransitionSelectionWidget;
|
||||||
|
};
|
||||||
|
|
||||||
|
class TransitionSelectionWidget : public QComboBox {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
TransitionSelectionWidget(QWidget *parent, bool current = true,
|
||||||
|
bool any = false);
|
||||||
|
void SetTransition(TransitionSelection &);
|
||||||
|
void Repopulate(bool current, bool any);
|
||||||
|
signals:
|
||||||
|
void TransitionChanged(const TransitionSelection &);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void SelectionChanged(const QString &name);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool IsCurrentTransitionSelected(const QString &name);
|
||||||
|
bool IsAnyTransitionSelected(const QString &name);
|
||||||
|
};
|
||||||
@@ -30,24 +30,25 @@ bool compareSourceSettings(const OBSWeakSource &source,
|
|||||||
std::vector<obs_scene_item *> getSceneItemsWithName(OBSScene scene,
|
std::vector<obs_scene_item *> getSceneItemsWithName(OBSScene scene,
|
||||||
std::string &name);
|
std::string &name);
|
||||||
std::string getDataFilePath(const std::string &file);
|
std::string getDataFilePath(const std::string &file);
|
||||||
QString fromatJsonString(std::string);
|
bool matchJson(const std::string &json1, const std::string &json2,
|
||||||
QString fromatJsonString(const char *);
|
bool useRegex);
|
||||||
|
QString formatJsonString(std::string);
|
||||||
/**
|
QString formatJsonString(const char *);
|
||||||
* Populate layout with labels and widgets based on provided text
|
QString escapeForRegex(QString &s);
|
||||||
*
|
void loadTransformState(obs_data_t *obj, struct obs_transform_info &info,
|
||||||
* @param text Text based on which labels are generated and widgets are placed.
|
struct obs_sceneitem_crop &crop);
|
||||||
* @param layout Layout in which the widgets and labels will be placed.
|
bool saveTransformState(obs_data_t *obj, struct obs_transform_info &info,
|
||||||
* @param placeholders Map containing a mapping of placeholder strings to widgets.
|
struct obs_sceneitem_crop &crop);
|
||||||
* @param addStretch Add addStretch() to layout.
|
std::string getSceneItemTransform(obs_scene_item *item);
|
||||||
*/
|
|
||||||
void placeWidgets(std::string text, QBoxLayout *layout,
|
void placeWidgets(std::string text, QBoxLayout *layout,
|
||||||
std::unordered_map<std::string, QWidget *> placeholders,
|
std::unordered_map<std::string, QWidget *> placeholders,
|
||||||
bool addStretch = true);
|
bool addStretch = true);
|
||||||
|
void deleteLayoutItem(QLayoutItem *item);
|
||||||
void clearLayout(QLayout *layout);
|
void clearLayout(QLayout *layout);
|
||||||
QMetaObject::Connection PulseWidget(QWidget *widget, QColor endColor,
|
QMetaObject::Connection PulseWidget(QWidget *widget, QColor startColor,
|
||||||
QColor = QColor(0, 0, 0, 0),
|
QColor = QColor(0, 0, 0, 0),
|
||||||
QString specifier = "QLabel ");
|
QString specifier = "QLabel ",
|
||||||
|
bool once = false);
|
||||||
void listAddClicked(QListWidget *list, QWidget *newWidget,
|
void listAddClicked(QListWidget *list, QWidget *newWidget,
|
||||||
QPushButton *addButton = nullptr,
|
QPushButton *addButton = nullptr,
|
||||||
QMetaObject::Connection *addHighlight = nullptr);
|
QMetaObject::Connection *addHighlight = nullptr);
|
||||||
@@ -57,8 +58,7 @@ bool DisplayMessage(const QString &msg, bool question = false);
|
|||||||
void addSelectionEntry(QComboBox *sel, const char *description,
|
void addSelectionEntry(QComboBox *sel, const char *description,
|
||||||
bool selectable = false, const char *tooltip = "");
|
bool selectable = false, const char *tooltip = "");
|
||||||
void populateTransitionSelection(QComboBox *sel, bool addCurrent = true,
|
void populateTransitionSelection(QComboBox *sel, bool addCurrent = true,
|
||||||
bool addSelect = true,
|
bool addAny = false);
|
||||||
bool selectable = false);
|
|
||||||
void populateWindowSelection(QComboBox *sel, bool addSelect = true);
|
void populateWindowSelection(QComboBox *sel, bool addSelect = true);
|
||||||
void populateAudioSelection(QComboBox *sel, bool addSelect = true);
|
void populateAudioSelection(QComboBox *sel, bool addSelect = true);
|
||||||
void populateVideoSelection(QComboBox *sel, bool addSelect = true);
|
void populateVideoSelection(QComboBox *sel, bool addSelect = true);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <util/platform.h>
|
#include <util/platform.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include <unordered_map>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QLibrary>
|
#include <QLibrary>
|
||||||
@@ -222,7 +223,7 @@ void GetCurrentWindowTitle(std::string &title)
|
|||||||
|
|
||||||
int status = 0;
|
int status = 0;
|
||||||
XTextProperty text;
|
XTextProperty text;
|
||||||
if (xstatus == Success) {
|
if (xstatus == Success && data[0]) {
|
||||||
status = XGetTextProperty(disp(), data[0], &text,
|
status = XGetTextProperty(disp(), data[0], &text,
|
||||||
XInternAtom(disp(), "_NET_WM_NAME",
|
XInternAtom(disp(), "_NET_WM_NAME",
|
||||||
true));
|
true));
|
||||||
@@ -523,7 +524,7 @@ static std::unordered_map<HotkeyType, long> keyTable = {
|
|||||||
{HotkeyType::Key_NumpadEnter, XK_KP_Enter},
|
{HotkeyType::Key_NumpadEnter, XK_KP_Enter},
|
||||||
};
|
};
|
||||||
|
|
||||||
void PressKeys(const std::vector<HotkeyType> keys)
|
void PressKeys(const std::vector<HotkeyType> keys, int duration)
|
||||||
{
|
{
|
||||||
if (!canSimulateKeyPresses) {
|
if (!canSimulateKeyPresses) {
|
||||||
return;
|
return;
|
||||||
@@ -544,7 +545,7 @@ void PressKeys(const std::vector<HotkeyType> keys)
|
|||||||
}
|
}
|
||||||
XFlush(display);
|
XFlush(display);
|
||||||
|
|
||||||
std::this_thread::sleep_for(std::chrono::milliseconds(300));
|
std::this_thread::sleep_for(std::chrono::milliseconds(duration));
|
||||||
|
|
||||||
// Release keys
|
// Release keys
|
||||||
for (auto &key : keys) {
|
for (auto &key : keys) {
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
#include "headers/macro-action-edit.hpp"
|
#include "headers/macro-action-edit.hpp"
|
||||||
#include "headers/macro-action-scene-switch.hpp"
|
#include "headers/macro-action-scene-switch.hpp"
|
||||||
|
#include "headers/section.hpp"
|
||||||
|
#include "headers/macro-controls.hpp"
|
||||||
#include "headers/utility.hpp"
|
#include "headers/utility.hpp"
|
||||||
#include "headers/advanced-scene-switcher.hpp"
|
|
||||||
|
|
||||||
std::map<std::string, MacroActionInfo> MacroActionFactory::_methods;
|
std::map<std::string, MacroActionInfo> MacroActionFactory::_methods;
|
||||||
|
|
||||||
@@ -59,32 +61,14 @@ static inline void populateActionSelection(QComboBox *list)
|
|||||||
|
|
||||||
MacroActionEdit::MacroActionEdit(QWidget *parent,
|
MacroActionEdit::MacroActionEdit(QWidget *parent,
|
||||||
std::shared_ptr<MacroAction> *entryData,
|
std::shared_ptr<MacroAction> *entryData,
|
||||||
const std::string &id, bool startCollapsed)
|
const std::string &id)
|
||||||
: QWidget(parent)
|
: MacroSegmentEdit(parent), _entryData(entryData)
|
||||||
{
|
{
|
||||||
_actionSelection = new QComboBox();
|
_actionSelection = new QComboBox();
|
||||||
_section = new Section(300);
|
|
||||||
_headerInfo = new QLabel();
|
|
||||||
|
|
||||||
QWidget::connect(_actionSelection,
|
QWidget::connect(_actionSelection,
|
||||||
SIGNAL(currentTextChanged(const QString &)), this,
|
SIGNAL(currentTextChanged(const QString &)), this,
|
||||||
SLOT(ActionSelectionChanged(const QString &)));
|
SLOT(ActionSelectionChanged(const QString &)));
|
||||||
QWidget::connect(parent, SIGNAL(MacroAdded(const QString &)), this,
|
|
||||||
SIGNAL(MacroAdded(const QString &)));
|
|
||||||
QWidget::connect(parent, SIGNAL(MacroRemoved(const QString &)), this,
|
|
||||||
SIGNAL(MacroRemoved(const QString &)));
|
|
||||||
QWidget::connect(parent,
|
|
||||||
SIGNAL(MacroRenamed(const QString &, const QString)),
|
|
||||||
this,
|
|
||||||
SIGNAL(MacroRenamed(const QString &, const QString)));
|
|
||||||
QWidget::connect(parent, SIGNAL(SceneGroupAdded(const QString &)), this,
|
|
||||||
SIGNAL(SceneGroupAdded(const QString &)));
|
|
||||||
QWidget::connect(parent, SIGNAL(SceneGroupRemoved(const QString &)),
|
|
||||||
this, SIGNAL(SceneGroupRemoved(const QString &)));
|
|
||||||
QWidget::connect(
|
|
||||||
parent,
|
|
||||||
SIGNAL(SceneGroupRenamed(const QString &, const QString)), this,
|
|
||||||
SIGNAL(SceneGroupRenamed(const QString &, const QString)));
|
|
||||||
|
|
||||||
populateActionSelection(_actionSelection);
|
populateActionSelection(_actionSelection);
|
||||||
|
|
||||||
@@ -93,10 +77,11 @@ MacroActionEdit::MacroActionEdit(QWidget *parent,
|
|||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
mainLayout->addWidget(_section);
|
mainLayout->addWidget(_section);
|
||||||
|
mainLayout->addWidget(_controls);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
_entryData = entryData;
|
_entryData = entryData;
|
||||||
UpdateEntryData(id, startCollapsed);
|
UpdateEntryData(id);
|
||||||
|
|
||||||
_loading = false;
|
_loading = false;
|
||||||
}
|
}
|
||||||
@@ -117,9 +102,10 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text)
|
|||||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||||
_section->SetContent(widget, false);
|
_section->SetContent(widget, false);
|
||||||
|
SetFocusPolicyOfWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionEdit::UpdateEntryData(const std::string &id, bool collapse)
|
void MacroActionEdit::UpdateEntryData(const std::string &id)
|
||||||
{
|
{
|
||||||
_actionSelection->setCurrentText(
|
_actionSelection->setCurrentText(
|
||||||
obs_module_text(MacroActionFactory::GetActionName(id).c_str()));
|
obs_module_text(MacroActionFactory::GetActionName(id).c_str()));
|
||||||
@@ -128,13 +114,51 @@ void MacroActionEdit::UpdateEntryData(const std::string &id, bool collapse)
|
|||||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||||
HeaderInfoChanged(
|
HeaderInfoChanged(
|
||||||
QString::fromStdString((*_entryData)->GetShortDesc()));
|
QString::fromStdString((*_entryData)->GetShortDesc()));
|
||||||
_section->SetContent(widget, collapse);
|
_section->SetContent(widget, (*_entryData)->GetCollapsed());
|
||||||
|
SetFocusPolicyOfWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionEdit::HeaderInfoChanged(const QString &text)
|
MacroSegment *MacroActionEdit::Data()
|
||||||
{
|
{
|
||||||
_headerInfo->setVisible(!text.isEmpty());
|
return _entryData->get();
|
||||||
_headerInfo->setText(text);
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::AddMacroAction(int idx)
|
||||||
|
{
|
||||||
|
auto macro = getSelectedMacro();
|
||||||
|
if (!macro) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx < 0 || idx > (int)macro->Actions().size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string id;
|
||||||
|
if (idx - 1 >= 0) {
|
||||||
|
id = macro->Actions().at(idx - 1)->GetId();
|
||||||
|
} else {
|
||||||
|
MacroActionSwitchScene temp;
|
||||||
|
id = temp.GetId();
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
macro->Actions().emplace(macro->Actions().begin() + idx,
|
||||||
|
MacroActionFactory::Create(id));
|
||||||
|
if (idx - 1 >= 0) {
|
||||||
|
auto data = obs_data_create();
|
||||||
|
macro->Actions().at(idx - 1)->Save(data);
|
||||||
|
macro->Actions().at(idx)->Load(data);
|
||||||
|
obs_data_release(data);
|
||||||
|
}
|
||||||
|
macro->UpdateActionIndices();
|
||||||
|
|
||||||
|
// All entry pointers in existing edit widgets after the new entry will
|
||||||
|
// be invalidated by adding the new entry so we have to recreate them
|
||||||
|
// and because I am lazy I am recreating every widget.
|
||||||
|
//
|
||||||
|
// If performance should become a concern this has to be revisited.
|
||||||
|
SetEditMacro(*macro);
|
||||||
|
HighlightAction(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_actionAdd_clicked()
|
void AdvSceneSwitcher::on_actionAdd_clicked()
|
||||||
@@ -144,15 +168,33 @@ void AdvSceneSwitcher::on_actionAdd_clicked()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroActionSwitchScene temp;
|
AddMacroAction((int)macro->Actions().size());
|
||||||
std::string id = temp.GetId();
|
ui->macroEditActionHelp->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::RemoveMacroAction(int idx)
|
||||||
|
{
|
||||||
|
auto macro = getSelectedMacro();
|
||||||
|
if (!macro) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx < 0 || idx >= (int)macro->Actions().size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
macro->Actions().emplace_back(MacroActionFactory::Create(id));
|
macro->Actions().erase(macro->Actions().begin() + idx);
|
||||||
auto newEntry =
|
switcher->abortMacroWait = true;
|
||||||
new MacroActionEdit(this, ¯o->Actions().back(), id, false);
|
switcher->macroWaitCv.notify_one();
|
||||||
ui->macroEditActionLayout->addWidget(newEntry);
|
macro->UpdateActionIndices();
|
||||||
ui->macroEditActionHelp->setVisible(false);
|
|
||||||
|
// All entry pointers in existing edit widgets after the new entry will
|
||||||
|
// be invalidated by adding the new entry so we have to recreate them
|
||||||
|
// and because I am lazy I am recreating every widget.
|
||||||
|
//
|
||||||
|
// If performance should become a concern this has to be revisited.
|
||||||
|
SetEditMacro(*macro);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_actionRemove_clicked()
|
void AdvSceneSwitcher::on_actionRemove_clicked()
|
||||||
@@ -161,24 +203,61 @@ void AdvSceneSwitcher::on_actionRemove_clicked()
|
|||||||
if (!macro) {
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
RemoveMacroAction((int)macro->Actions().size() - 1);
|
||||||
if (macro->Actions().empty()) {
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::SwapActions(Macro *m, int pos1, int pos2)
|
||||||
|
{
|
||||||
|
if (pos1 == pos2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
macro->Actions().pop_back();
|
if (pos1 > pos2) {
|
||||||
|
std::swap(pos1, pos2);
|
||||||
int count = ui->macroEditActionLayout->count();
|
|
||||||
auto item = ui->macroEditActionLayout->takeAt(count - 1);
|
|
||||||
|
|
||||||
if (item) {
|
|
||||||
auto widget = item->widget();
|
|
||||||
if (widget) {
|
|
||||||
widget->setVisible(false);
|
|
||||||
}
|
|
||||||
delete item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count == 1) {
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
ui->macroEditActionHelp->setVisible(true);
|
iter_swap(m->Actions().begin() + pos1, m->Actions().begin() + pos2);
|
||||||
}
|
m->UpdateActionIndices();
|
||||||
|
|
||||||
|
auto a1 = m->Actions().begin() + pos1;
|
||||||
|
auto a2 = m->Actions().begin() + pos2;
|
||||||
|
|
||||||
|
auto item1 = ui->macroEditActionLayout->takeAt(pos1);
|
||||||
|
auto item2 = ui->macroEditActionLayout->takeAt(pos2 - 1);
|
||||||
|
deleteLayoutItem(item1);
|
||||||
|
deleteLayoutItem(item2);
|
||||||
|
auto widget1 = new MacroActionEdit(this, &(*a1), (*a1)->GetId());
|
||||||
|
auto widget2 = new MacroActionEdit(this, &(*a2), (*a2)->GetId());
|
||||||
|
ConnectControlSignals(widget1);
|
||||||
|
ConnectControlSignals(widget2);
|
||||||
|
ui->macroEditActionLayout->insertWidget(pos1, widget1);
|
||||||
|
ui->macroEditActionLayout->insertWidget(pos2, widget2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::MoveMacroActionUp(int idx)
|
||||||
|
{
|
||||||
|
auto macro = getSelectedMacro();
|
||||||
|
if (!macro) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx < 1 || idx >= (int)macro->Actions().size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwapActions(macro, idx, idx - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::MoveMacroActionDown(int idx)
|
||||||
|
{
|
||||||
|
auto macro = getSelectedMacro();
|
||||||
|
if (!macro) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx < 0 || idx >= (int)macro->Actions().size() - 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwapActions(macro, idx, idx + 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -86,9 +86,7 @@ MacroActionFileEdit::MacroActionFileEdit(
|
|||||||
QWidget *parent, std::shared_ptr<MacroActionFile> entryData)
|
QWidget *parent, std::shared_ptr<MacroActionFile> entryData)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
_filePath = new QLineEdit();
|
_filePath = new FileSelection(FileSelection::Type::WRITE);
|
||||||
_browseButton =
|
|
||||||
new QPushButton(obs_module_text("AdvSceneSwitcher.browse"));
|
|
||||||
_text = new QPlainTextEdit();
|
_text = new QPlainTextEdit();
|
||||||
_actions = new QComboBox();
|
_actions = new QComboBox();
|
||||||
|
|
||||||
@@ -96,10 +94,8 @@ MacroActionFileEdit::MacroActionFileEdit(
|
|||||||
|
|
||||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(ActionChanged(int)));
|
SLOT(ActionChanged(int)));
|
||||||
QWidget::connect(_filePath, SIGNAL(editingFinished()), this,
|
QWidget::connect(_filePath, SIGNAL(PathChanged(const QString &)), this,
|
||||||
SLOT(FilePathChanged()));
|
SLOT(PathChanged(const QString &)));
|
||||||
QWidget::connect(_browseButton, SIGNAL(clicked()), this,
|
|
||||||
SLOT(BrowseButtonClicked()));
|
|
||||||
QWidget::connect(_text, SIGNAL(textChanged()), this,
|
QWidget::connect(_text, SIGNAL(textChanged()), this,
|
||||||
SLOT(TextChanged()));
|
SLOT(TextChanged()));
|
||||||
;
|
;
|
||||||
@@ -107,7 +103,6 @@ MacroActionFileEdit::MacroActionFileEdit(
|
|||||||
QHBoxLayout *entryLayout = new QHBoxLayout;
|
QHBoxLayout *entryLayout = new QHBoxLayout;
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{filePath}}", _filePath},
|
{"{{filePath}}", _filePath},
|
||||||
{"{{browseButton}}", _browseButton},
|
|
||||||
{"{{matchText}}", _text},
|
{"{{matchText}}", _text},
|
||||||
{"{{actions}}", _actions},
|
{"{{actions}}", _actions},
|
||||||
};
|
};
|
||||||
@@ -131,41 +126,22 @@ void MacroActionFileEdit::UpdateEntryData()
|
|||||||
}
|
}
|
||||||
|
|
||||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||||
_filePath->setText(QString::fromStdString(_entryData->_file));
|
_filePath->SetPath(QString::fromStdString(_entryData->_file));
|
||||||
_text->setPlainText(QString::fromStdString(_entryData->_text));
|
_text->setPlainText(QString::fromStdString(_entryData->_text));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionFileEdit::FilePathChanged()
|
void MacroActionFileEdit::PathChanged(const QString &text)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_file = _filePath->text().toUtf8().constData();
|
_entryData->_file = text.toUtf8().constData();
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionFileEdit::BrowseButtonClicked()
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString path = QFileDialog::getSaveFileName(
|
|
||||||
this,
|
|
||||||
tr(obs_module_text("AdvSceneSwitcher.fileTab.selectWrite")),
|
|
||||||
QDir::currentPath(),
|
|
||||||
tr(obs_module_text("AdvSceneSwitcher.fileTab.anyFileType")));
|
|
||||||
if (path.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_filePath->setText(path);
|
|
||||||
FilePathChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroActionFileEdit::TextChanged()
|
void MacroActionFileEdit::TextChanged()
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
|
|||||||
@@ -198,7 +198,7 @@ void MacroActionFilterEdit::GetSettingsClicked()
|
|||||||
}
|
}
|
||||||
|
|
||||||
_settings->setPlainText(
|
_settings->setPlainText(
|
||||||
fromatJsonString(getSourceSettings(_entryData->_filter)));
|
formatJsonString(getSourceSettings(_entryData->_filter)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionFilterEdit::SettingsChanged()
|
void MacroActionFilterEdit::SettingsChanged()
|
||||||
|
|||||||
@@ -1,18 +1,196 @@
|
|||||||
#include "headers/macro-action-hotkey.hpp"
|
#include "headers/macro-action-hotkey.hpp"
|
||||||
#include "headers/advanced-scene-switcher.hpp"
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
#include "headers/utility.hpp"
|
#include "headers/utility.hpp"
|
||||||
|
#include <obs-interaction.h>
|
||||||
|
|
||||||
const std::string MacroActionHotkey::id = "hotkey";
|
const std::string MacroActionHotkey::id = "hotkey";
|
||||||
|
|
||||||
// TODO:
|
|
||||||
// I can't seem to get this to work so drop support for this functionality
|
|
||||||
// on MacOS
|
|
||||||
#if !__APPLE__
|
|
||||||
bool MacroActionHotkey::_registered = MacroActionFactory::Register(
|
bool MacroActionHotkey::_registered = MacroActionFactory::Register(
|
||||||
MacroActionHotkey::id,
|
MacroActionHotkey::id,
|
||||||
{MacroActionHotkey::Create, MacroActionHotkeyEdit::Create,
|
{MacroActionHotkey::Create, MacroActionHotkeyEdit::Create,
|
||||||
"AdvSceneSwitcher.action.hotkey"});
|
"AdvSceneSwitcher.action.hotkey"});
|
||||||
#endif
|
|
||||||
|
static std::unordered_map<HotkeyType, long> keyTable = {
|
||||||
|
// Chars
|
||||||
|
{HotkeyType::Key_A, OBS_KEY_A},
|
||||||
|
{HotkeyType::Key_B, OBS_KEY_B},
|
||||||
|
{HotkeyType::Key_C, OBS_KEY_C},
|
||||||
|
{HotkeyType::Key_D, OBS_KEY_D},
|
||||||
|
{HotkeyType::Key_E, OBS_KEY_E},
|
||||||
|
{HotkeyType::Key_F, OBS_KEY_F},
|
||||||
|
{HotkeyType::Key_G, OBS_KEY_G},
|
||||||
|
{HotkeyType::Key_H, OBS_KEY_H},
|
||||||
|
{HotkeyType::Key_I, OBS_KEY_I},
|
||||||
|
{HotkeyType::Key_J, OBS_KEY_J},
|
||||||
|
{HotkeyType::Key_K, OBS_KEY_K},
|
||||||
|
{HotkeyType::Key_L, OBS_KEY_L},
|
||||||
|
{HotkeyType::Key_M, OBS_KEY_M},
|
||||||
|
{HotkeyType::Key_N, OBS_KEY_N},
|
||||||
|
{HotkeyType::Key_O, OBS_KEY_O},
|
||||||
|
{HotkeyType::Key_P, OBS_KEY_P},
|
||||||
|
{HotkeyType::Key_Q, OBS_KEY_Q},
|
||||||
|
{HotkeyType::Key_R, OBS_KEY_R},
|
||||||
|
{HotkeyType::Key_S, OBS_KEY_S},
|
||||||
|
{HotkeyType::Key_T, OBS_KEY_T},
|
||||||
|
{HotkeyType::Key_U, OBS_KEY_U},
|
||||||
|
{HotkeyType::Key_V, OBS_KEY_V},
|
||||||
|
{HotkeyType::Key_W, OBS_KEY_W},
|
||||||
|
{HotkeyType::Key_X, OBS_KEY_X},
|
||||||
|
{HotkeyType::Key_Y, OBS_KEY_Y},
|
||||||
|
{HotkeyType::Key_Z, OBS_KEY_Z},
|
||||||
|
|
||||||
|
// Numbers
|
||||||
|
{HotkeyType::Key_0, OBS_KEY_0},
|
||||||
|
{HotkeyType::Key_1, OBS_KEY_1},
|
||||||
|
{HotkeyType::Key_2, OBS_KEY_2},
|
||||||
|
{HotkeyType::Key_3, OBS_KEY_3},
|
||||||
|
{HotkeyType::Key_4, OBS_KEY_4},
|
||||||
|
{HotkeyType::Key_5, OBS_KEY_5},
|
||||||
|
{HotkeyType::Key_6, OBS_KEY_6},
|
||||||
|
{HotkeyType::Key_7, OBS_KEY_7},
|
||||||
|
{HotkeyType::Key_8, OBS_KEY_8},
|
||||||
|
{HotkeyType::Key_9, OBS_KEY_9},
|
||||||
|
|
||||||
|
{HotkeyType::Key_F1, OBS_KEY_F1},
|
||||||
|
{HotkeyType::Key_F2, OBS_KEY_F2},
|
||||||
|
{HotkeyType::Key_F3, OBS_KEY_F3},
|
||||||
|
{HotkeyType::Key_F4, OBS_KEY_F4},
|
||||||
|
{HotkeyType::Key_F5, OBS_KEY_F5},
|
||||||
|
{HotkeyType::Key_F6, OBS_KEY_F6},
|
||||||
|
{HotkeyType::Key_F7, OBS_KEY_F7},
|
||||||
|
{HotkeyType::Key_F8, OBS_KEY_F8},
|
||||||
|
{HotkeyType::Key_F9, OBS_KEY_F9},
|
||||||
|
{HotkeyType::Key_F10, OBS_KEY_F10},
|
||||||
|
{HotkeyType::Key_F11, OBS_KEY_F11},
|
||||||
|
{HotkeyType::Key_F12, OBS_KEY_F12},
|
||||||
|
{HotkeyType::Key_F13, OBS_KEY_F13},
|
||||||
|
{HotkeyType::Key_F14, OBS_KEY_F14},
|
||||||
|
{HotkeyType::Key_F15, OBS_KEY_F15},
|
||||||
|
{HotkeyType::Key_F16, OBS_KEY_F16},
|
||||||
|
{HotkeyType::Key_F17, OBS_KEY_F17},
|
||||||
|
{HotkeyType::Key_F18, OBS_KEY_F18},
|
||||||
|
{HotkeyType::Key_F19, OBS_KEY_F19},
|
||||||
|
{HotkeyType::Key_F20, OBS_KEY_F20},
|
||||||
|
{HotkeyType::Key_F21, OBS_KEY_F21},
|
||||||
|
{HotkeyType::Key_F22, OBS_KEY_F22},
|
||||||
|
{HotkeyType::Key_F23, OBS_KEY_F23},
|
||||||
|
{HotkeyType::Key_F24, OBS_KEY_F24},
|
||||||
|
|
||||||
|
{HotkeyType::Key_Escape, OBS_KEY_ESCAPE},
|
||||||
|
{HotkeyType::Key_Space, OBS_KEY_SPACE},
|
||||||
|
{HotkeyType::Key_Return, OBS_KEY_RETURN},
|
||||||
|
{HotkeyType::Key_Backspace, OBS_KEY_BACKSPACE},
|
||||||
|
{HotkeyType::Key_Tab, OBS_KEY_TAB},
|
||||||
|
|
||||||
|
{HotkeyType::Key_Shift_L, OBS_KEY_SHIFT},
|
||||||
|
{HotkeyType::Key_Shift_R, OBS_KEY_SHIFT},
|
||||||
|
{HotkeyType::Key_Control_L, OBS_KEY_CONTROL},
|
||||||
|
{HotkeyType::Key_Control_R, OBS_KEY_CONTROL},
|
||||||
|
{HotkeyType::Key_Alt_L, OBS_KEY_ALT},
|
||||||
|
{HotkeyType::Key_Alt_R, OBS_KEY_ALT},
|
||||||
|
{HotkeyType::Key_Win_L, OBS_KEY_META},
|
||||||
|
{HotkeyType::Key_Win_R, OBS_KEY_META},
|
||||||
|
{HotkeyType::Key_Apps, OBS_KEY_APPLICATIONLEFT},
|
||||||
|
|
||||||
|
{HotkeyType::Key_CapsLock, OBS_KEY_CAPSLOCK},
|
||||||
|
{HotkeyType::Key_NumLock, OBS_KEY_NUMLOCK},
|
||||||
|
{HotkeyType::Key_ScrollLock, OBS_KEY_SCROLLLOCK},
|
||||||
|
|
||||||
|
{HotkeyType::Key_PrintScreen, OBS_KEY_PRINT},
|
||||||
|
{HotkeyType::Key_Pause, OBS_KEY_PAUSE},
|
||||||
|
|
||||||
|
{HotkeyType::Key_Insert, OBS_KEY_INSERT},
|
||||||
|
{HotkeyType::Key_Delete, OBS_KEY_DELETE},
|
||||||
|
{HotkeyType::Key_PageUP, OBS_KEY_PAGEUP},
|
||||||
|
{HotkeyType::Key_PageDown, OBS_KEY_PAGEDOWN},
|
||||||
|
{HotkeyType::Key_Home, OBS_KEY_HOME},
|
||||||
|
{HotkeyType::Key_End, OBS_KEY_END},
|
||||||
|
|
||||||
|
{HotkeyType::Key_Left, OBS_KEY_LEFT},
|
||||||
|
{HotkeyType::Key_Up, OBS_KEY_UP},
|
||||||
|
{HotkeyType::Key_Right, OBS_KEY_RIGHT},
|
||||||
|
{HotkeyType::Key_Down, OBS_KEY_DOWN},
|
||||||
|
|
||||||
|
{HotkeyType::Key_Numpad0, OBS_KEY_NUM0},
|
||||||
|
{HotkeyType::Key_Numpad1, OBS_KEY_NUM1},
|
||||||
|
{HotkeyType::Key_Numpad2, OBS_KEY_NUM2},
|
||||||
|
{HotkeyType::Key_Numpad3, OBS_KEY_NUM3},
|
||||||
|
{HotkeyType::Key_Numpad4, OBS_KEY_NUM4},
|
||||||
|
{HotkeyType::Key_Numpad5, OBS_KEY_NUM5},
|
||||||
|
{HotkeyType::Key_Numpad6, OBS_KEY_NUM6},
|
||||||
|
{HotkeyType::Key_Numpad7, OBS_KEY_NUM7},
|
||||||
|
{HotkeyType::Key_Numpad8, OBS_KEY_NUM8},
|
||||||
|
{HotkeyType::Key_Numpad9, OBS_KEY_NUM9},
|
||||||
|
|
||||||
|
{HotkeyType::Key_NumpadAdd, OBS_KEY_NUMPLUS},
|
||||||
|
{HotkeyType::Key_NumpadSubtract, OBS_KEY_NUMMINUS},
|
||||||
|
{HotkeyType::Key_NumpadMultiply, OBS_KEY_NUMASTERISK},
|
||||||
|
{HotkeyType::Key_NumpadDivide, OBS_KEY_NUMSLASH},
|
||||||
|
{HotkeyType::Key_NumpadDecimal, OBS_KEY_NUMPERIOD},
|
||||||
|
//{HotkeyType::Key_NumpadEnter, ???},
|
||||||
|
};
|
||||||
|
|
||||||
|
obs_key_combination keysToOBSKeycombo(const std::vector<HotkeyType> &keys)
|
||||||
|
{
|
||||||
|
obs_key_combination combo{};
|
||||||
|
auto it = keyTable.find(keys.back());
|
||||||
|
if (it != keyTable.end()) {
|
||||||
|
combo.key = (obs_key_t)it->second;
|
||||||
|
}
|
||||||
|
if (keys.size() == 1) {
|
||||||
|
return combo;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < keys.size() - 1; i++) {
|
||||||
|
switch (keys[i]) {
|
||||||
|
case HotkeyType::Key_Shift_L:
|
||||||
|
combo.modifiers |= INTERACT_SHIFT_KEY;
|
||||||
|
break;
|
||||||
|
case HotkeyType::Key_Shift_R:
|
||||||
|
combo.modifiers |= INTERACT_SHIFT_KEY;
|
||||||
|
break;
|
||||||
|
case HotkeyType::Key_Control_L:
|
||||||
|
combo.modifiers |= INTERACT_CONTROL_KEY;
|
||||||
|
break;
|
||||||
|
case HotkeyType::Key_Control_R:
|
||||||
|
combo.modifiers |= INTERACT_CONTROL_KEY;
|
||||||
|
break;
|
||||||
|
case HotkeyType::Key_Alt_L:
|
||||||
|
combo.modifiers |= INTERACT_ALT_KEY;
|
||||||
|
break;
|
||||||
|
case HotkeyType::Key_Alt_R:
|
||||||
|
combo.modifiers |= INTERACT_ALT_KEY;
|
||||||
|
break;
|
||||||
|
case HotkeyType::Key_Win_L:
|
||||||
|
combo.modifiers |= INTERACT_COMMAND_KEY;
|
||||||
|
break;
|
||||||
|
case HotkeyType::Key_Win_R:
|
||||||
|
combo.modifiers |= INTERACT_COMMAND_KEY;
|
||||||
|
break;
|
||||||
|
case HotkeyType::Key_CapsLock:
|
||||||
|
combo.modifiers |= INTERACT_CAPS_KEY;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return combo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InjectKeys(const std::vector<HotkeyType> &keys, int duration)
|
||||||
|
{
|
||||||
|
auto combo = keysToOBSKeycombo(keys);
|
||||||
|
if (obs_key_combination_is_empty(combo)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// I am not sure why this is necessary
|
||||||
|
obs_hotkey_inject_event(combo, false);
|
||||||
|
|
||||||
|
obs_hotkey_inject_event(combo, true);
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(duration));
|
||||||
|
obs_hotkey_inject_event(combo, false);
|
||||||
|
}
|
||||||
|
|
||||||
bool MacroActionHotkey::PerformAction()
|
bool MacroActionHotkey::PerformAction()
|
||||||
{
|
{
|
||||||
@@ -35,13 +213,25 @@ bool MacroActionHotkey::PerformAction()
|
|||||||
if (_rightAlt) {
|
if (_rightAlt) {
|
||||||
keys.push_back(HotkeyType::Key_Alt_R);
|
keys.push_back(HotkeyType::Key_Alt_R);
|
||||||
}
|
}
|
||||||
|
if (_leftMeta) {
|
||||||
|
keys.push_back(HotkeyType::Key_Win_L);
|
||||||
|
}
|
||||||
|
if (_rightMeta) {
|
||||||
|
keys.push_back(HotkeyType::Key_Win_R);
|
||||||
|
}
|
||||||
if (_key != HotkeyType::Key_NoKey) {
|
if (_key != HotkeyType::Key_NoKey) {
|
||||||
keys.push_back(_key);
|
keys.push_back(_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!keys.empty()) {
|
if (!keys.empty()) {
|
||||||
std::thread t([keys]() { PressKeys(keys); });
|
int dur = _duration;
|
||||||
t.detach();
|
if (_onlySendToObs) {
|
||||||
|
std::thread t([keys, dur]() { InjectKeys(keys, dur); });
|
||||||
|
t.detach();
|
||||||
|
} else {
|
||||||
|
std::thread t([keys, dur]() { PressKeys(keys, dur); });
|
||||||
|
t.detach();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -64,6 +254,8 @@ bool MacroActionHotkey::Save(obs_data_t *obj)
|
|||||||
obs_data_set_bool(obj, "right_alt", _rightAlt);
|
obs_data_set_bool(obj, "right_alt", _rightAlt);
|
||||||
obs_data_set_bool(obj, "left_meta", _leftMeta);
|
obs_data_set_bool(obj, "left_meta", _leftMeta);
|
||||||
obs_data_set_bool(obj, "right_meta", _rightMeta);
|
obs_data_set_bool(obj, "right_meta", _rightMeta);
|
||||||
|
obs_data_set_int(obj, "duration", _duration);
|
||||||
|
obs_data_set_bool(obj, "onlyOBS", _onlySendToObs);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,6 +271,8 @@ bool MacroActionHotkey::Load(obs_data_t *obj)
|
|||||||
_rightAlt = obs_data_get_bool(obj, "right_alt");
|
_rightAlt = obs_data_get_bool(obj, "right_alt");
|
||||||
_leftMeta = obs_data_get_bool(obj, "left_meta");
|
_leftMeta = obs_data_get_bool(obj, "left_meta");
|
||||||
_rightMeta = obs_data_get_bool(obj, "right_meta");
|
_rightMeta = obs_data_get_bool(obj, "right_meta");
|
||||||
|
_duration = obs_data_get_int(obj, "duration");
|
||||||
|
_onlySendToObs = obs_data_get_bool(obj, "onlyOBS");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -213,6 +407,12 @@ MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
|||||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftMeta"));
|
obs_module_text("AdvSceneSwitcher.action.hotkey.leftMeta"));
|
||||||
_rightMeta = new QCheckBox(
|
_rightMeta = new QCheckBox(
|
||||||
obs_module_text("AdvSceneSwitcher.action.hotkey.rightMeta"));
|
obs_module_text("AdvSceneSwitcher.action.hotkey.rightMeta"));
|
||||||
|
_duration = new QSpinBox();
|
||||||
|
_duration->setMaximum(5000);
|
||||||
|
_onlySendToOBS = new QCheckBox(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.hotkey.onlyOBS"));
|
||||||
|
_noKeyPressSimulationWarning = new QLabel(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.hotkey.disabled"));
|
||||||
|
|
||||||
populateKeySelection(_keys);
|
populateKeySelection(_keys);
|
||||||
|
|
||||||
@@ -234,10 +434,15 @@ MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
|||||||
SLOT(LMetaChanged(int)));
|
SLOT(LMetaChanged(int)));
|
||||||
QWidget::connect(_rightMeta, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_rightMeta, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(RMetaChanged(int)));
|
SLOT(RMetaChanged(int)));
|
||||||
|
QWidget::connect(_duration, SIGNAL(valueChanged(int)), this,
|
||||||
|
SLOT(DurationChanged(int)));
|
||||||
|
QWidget::connect(_onlySendToOBS, SIGNAL(stateChanged(int)), this,
|
||||||
|
SLOT(OnlySendToOBSChanged(int)));
|
||||||
|
|
||||||
QHBoxLayout *line1Layout = new QHBoxLayout;
|
QHBoxLayout *line1Layout = new QHBoxLayout;
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{keys}}", _keys},
|
{"{{keys}}", _keys},
|
||||||
|
{"{{duration}}", _duration},
|
||||||
};
|
};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.hotkey.entry"),
|
placeWidgets(obs_module_text("AdvSceneSwitcher.action.hotkey.entry"),
|
||||||
line1Layout, widgetPlaceholders);
|
line1Layout, widgetPlaceholders);
|
||||||
@@ -256,11 +461,8 @@ MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
|||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
mainLayout->addLayout(line1Layout);
|
mainLayout->addLayout(line1Layout);
|
||||||
mainLayout->addLayout(line2Layout);
|
mainLayout->addLayout(line2Layout);
|
||||||
|
mainLayout->addWidget(_onlySendToOBS);
|
||||||
if (!canSimulateKeyPresses) {
|
mainLayout->addWidget(_noKeyPressSimulationWarning);
|
||||||
mainLayout->addWidget(new QLabel(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.action.hotkey.disabled")));
|
|
||||||
}
|
|
||||||
|
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
@@ -269,6 +471,12 @@ MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
|||||||
_loading = false;
|
_loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionHotkeyEdit::SetWarningVisibility()
|
||||||
|
{
|
||||||
|
_noKeyPressSimulationWarning->setVisible(!_entryData->_onlySendToObs &&
|
||||||
|
!canSimulateKeyPresses);
|
||||||
|
}
|
||||||
|
|
||||||
void MacroActionHotkeyEdit::UpdateEntryData()
|
void MacroActionHotkeyEdit::UpdateEntryData()
|
||||||
{
|
{
|
||||||
if (!_entryData) {
|
if (!_entryData) {
|
||||||
@@ -284,6 +492,9 @@ void MacroActionHotkeyEdit::UpdateEntryData()
|
|||||||
_rightAlt->setChecked(_entryData->_rightAlt);
|
_rightAlt->setChecked(_entryData->_rightAlt);
|
||||||
_leftMeta->setChecked(_entryData->_leftMeta);
|
_leftMeta->setChecked(_entryData->_leftMeta);
|
||||||
_rightMeta->setChecked(_entryData->_rightMeta);
|
_rightMeta->setChecked(_entryData->_rightMeta);
|
||||||
|
_duration->setValue(_entryData->_duration);
|
||||||
|
_onlySendToOBS->setChecked(_entryData->_onlySendToObs);
|
||||||
|
SetWarningVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionHotkeyEdit::LShiftChanged(int state)
|
void MacroActionHotkeyEdit::LShiftChanged(int state)
|
||||||
@@ -366,6 +577,27 @@ void MacroActionHotkeyEdit::RMetaChanged(int state)
|
|||||||
_entryData->_rightMeta = state;
|
_entryData->_rightMeta = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionHotkeyEdit::DurationChanged(int ms)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_duration = ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionHotkeyEdit::OnlySendToOBSChanged(int state)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_onlySendToObs = state;
|
||||||
|
SetWarningVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
void MacroActionHotkeyEdit::KeyChanged(int key)
|
void MacroActionHotkeyEdit::KeyChanged(int key)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
|
|||||||
87
src/macro-action-preview-scene.cpp
Normal file
87
src/macro-action-preview-scene.cpp
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
#include "headers/macro-action-preview-scene.hpp"
|
||||||
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
|
#include "headers/utility.hpp"
|
||||||
|
|
||||||
|
const std::string MacroActionPreviewScene::id = "preview_scene";
|
||||||
|
|
||||||
|
bool MacroActionPreviewScene::_registered = MacroActionFactory::Register(
|
||||||
|
MacroActionPreviewScene::id,
|
||||||
|
{MacroActionPreviewScene::Create, MacroActionPreviewSceneEdit::Create,
|
||||||
|
"AdvSceneSwitcher.action.previewScene"});
|
||||||
|
|
||||||
|
bool MacroActionPreviewScene::PerformAction()
|
||||||
|
{
|
||||||
|
auto s = obs_weak_source_get_source(_scene.GetScene());
|
||||||
|
obs_frontend_set_current_preview_scene(s);
|
||||||
|
obs_source_release(s);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionPreviewScene::LogAction()
|
||||||
|
{
|
||||||
|
vblog(LOG_INFO, "set preview scene to \"%s\"",
|
||||||
|
_scene.ToString().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionPreviewScene::Save(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroAction::Save(obj);
|
||||||
|
_scene.Save(obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionPreviewScene::Load(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroAction::Load(obj);
|
||||||
|
_scene.Load(obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MacroActionPreviewScene::GetShortDesc()
|
||||||
|
{
|
||||||
|
return _scene.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroActionPreviewSceneEdit::MacroActionPreviewSceneEdit(
|
||||||
|
QWidget *parent, std::shared_ptr<MacroActionPreviewScene> entryData)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
_scenes = new SceneSelectionWidget(window(), false, false, false);
|
||||||
|
|
||||||
|
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||||
|
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||||
|
|
||||||
|
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||||
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
|
{"{{scenes}}", _scenes},
|
||||||
|
};
|
||||||
|
placeWidgets(
|
||||||
|
obs_module_text("AdvSceneSwitcher.action.previewScene.entry"),
|
||||||
|
mainLayout, widgetPlaceholders);
|
||||||
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
_entryData = entryData;
|
||||||
|
UpdateEntryData();
|
||||||
|
_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionPreviewSceneEdit::UpdateEntryData()
|
||||||
|
{
|
||||||
|
if (!_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_scenes->SetScene(_entryData->_scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionPreviewSceneEdit::SceneChanged(const SceneSelection &s)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_scene = s;
|
||||||
|
emit HeaderInfoChanged(
|
||||||
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef REPLAYBUFFER_SUPPORTED
|
||||||
|
|
||||||
#include "headers/macro-action-replay-buffer.hpp"
|
#include "headers/macro-action-replay-buffer.hpp"
|
||||||
#include "headers/advanced-scene-switcher.hpp"
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
#include "headers/utility.hpp"
|
#include "headers/utility.hpp"
|
||||||
@@ -119,3 +121,5 @@ void MacroActionReplayBufferEdit::ActionChanged(int value)
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_action = static_cast<ReplayBufferAction>(value);
|
_entryData->_action = static_cast<ReplayBufferAction>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -65,31 +65,31 @@ MacroActionRunEdit::MacroActionRunEdit(
|
|||||||
QWidget *parent, std::shared_ptr<MacroActionRun> entryData)
|
QWidget *parent, std::shared_ptr<MacroActionRun> entryData)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
_filePath = new QLineEdit();
|
_filePath = new FileSelection();
|
||||||
_browseButton =
|
|
||||||
new QPushButton(obs_module_text("AdvSceneSwitcher.browse"));
|
|
||||||
_argList = new QListWidget();
|
_argList = new QListWidget();
|
||||||
_addArg = new QPushButton();
|
_addArg = new QPushButton();
|
||||||
_addArg->setMaximumSize(QSize(22, 22));
|
_addArg->setMaximumSize(QSize(22, 22));
|
||||||
_addArg->setProperty("themeID",
|
_addArg->setProperty("themeID",
|
||||||
QVariant(QString::fromUtf8("addIconSmall")));
|
QVariant(QString::fromUtf8("addIconSmall")));
|
||||||
|
_addArg->setFlat(true);
|
||||||
_removeArg = new QPushButton();
|
_removeArg = new QPushButton();
|
||||||
_removeArg->setMaximumSize(QSize(22, 22));
|
_removeArg->setMaximumSize(QSize(22, 22));
|
||||||
_removeArg->setProperty("themeID",
|
_removeArg->setProperty("themeID",
|
||||||
QVariant(QString::fromUtf8("removeIconSmall")));
|
QVariant(QString::fromUtf8("removeIconSmall")));
|
||||||
|
_removeArg->setFlat(true);
|
||||||
_argUp = new QPushButton();
|
_argUp = new QPushButton();
|
||||||
_argUp->setMaximumSize(QSize(22, 22));
|
_argUp->setMaximumSize(QSize(22, 22));
|
||||||
_argUp->setProperty("themeID",
|
_argUp->setProperty("themeID",
|
||||||
QVariant(QString::fromUtf8("upArrowIconSmall")));
|
QVariant(QString::fromUtf8("upArrowIconSmall")));
|
||||||
|
_argUp->setFlat(true);
|
||||||
_argDown = new QPushButton();
|
_argDown = new QPushButton();
|
||||||
_argDown->setMaximumSize(QSize(22, 22));
|
_argDown->setMaximumSize(QSize(22, 22));
|
||||||
_argDown->setProperty(
|
_argDown->setProperty(
|
||||||
"themeID", QVariant(QString::fromUtf8("downArrowIconSmall")));
|
"themeID", QVariant(QString::fromUtf8("downArrowIconSmall")));
|
||||||
|
_argDown->setFlat(true);
|
||||||
|
|
||||||
QWidget::connect(_filePath, SIGNAL(editingFinished()), this,
|
QWidget::connect(_filePath, SIGNAL(PathChanged(const QString &)), this,
|
||||||
SLOT(FilePathChanged()));
|
SLOT(PathChanged(const QString &)));
|
||||||
QWidget::connect(_browseButton, SIGNAL(clicked()), this,
|
|
||||||
SLOT(BrowseButtonClicked()));
|
|
||||||
QWidget::connect(_addArg, SIGNAL(clicked()), this, SLOT(AddArg()));
|
QWidget::connect(_addArg, SIGNAL(clicked()), this, SLOT(AddArg()));
|
||||||
QWidget::connect(_removeArg, SIGNAL(clicked()), this,
|
QWidget::connect(_removeArg, SIGNAL(clicked()), this,
|
||||||
SLOT(RemoveArg()));
|
SLOT(RemoveArg()));
|
||||||
@@ -99,7 +99,6 @@ MacroActionRunEdit::MacroActionRunEdit(
|
|||||||
auto *entryLayout = new QHBoxLayout;
|
auto *entryLayout = new QHBoxLayout;
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{filePath}}", _filePath},
|
{"{{filePath}}", _filePath},
|
||||||
{"{{browseButton}}", _browseButton},
|
|
||||||
};
|
};
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.action.run.entry"),
|
placeWidgets(obs_module_text("AdvSceneSwitcher.action.run.entry"),
|
||||||
entryLayout, widgetPlaceholders);
|
entryLayout, widgetPlaceholders);
|
||||||
@@ -133,40 +132,25 @@ void MacroActionRunEdit::UpdateEntryData()
|
|||||||
if (!_entryData) {
|
if (!_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_filePath->setText(QString::fromStdString(_entryData->_path));
|
_filePath->SetPath(QString::fromStdString(_entryData->_path));
|
||||||
for (auto &arg : _entryData->_args) {
|
for (auto &arg : _entryData->_args) {
|
||||||
QListWidgetItem *item = new QListWidgetItem(arg, _argList);
|
QListWidgetItem *item = new QListWidgetItem(arg, _argList);
|
||||||
item->setData(Qt::UserRole, arg);
|
item->setData(Qt::UserRole, arg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionRunEdit::FilePathChanged()
|
void MacroActionRunEdit::PathChanged(const QString &text)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_path = _filePath->text().toUtf8().constData();
|
_entryData->_path = text.toUtf8().constData();
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionRunEdit::BrowseButtonClicked()
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString path = QFileDialog::getOpenFileName(this);
|
|
||||||
if (path.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_filePath->setText(path);
|
|
||||||
FilePathChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroActionRunEdit::AddArg()
|
void MacroActionRunEdit::AddArg()
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
|
|||||||
46
src/macro-action-scene-swap.cpp
Normal file
46
src/macro-action-scene-swap.cpp
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
#include "headers/macro-action-scene-swap.hpp"
|
||||||
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
|
#include "headers/utility.hpp"
|
||||||
|
|
||||||
|
const std::string MacroActionSceneSwap::id = "scene_swap";
|
||||||
|
|
||||||
|
bool MacroActionSceneSwap::_registered = MacroActionFactory::Register(
|
||||||
|
MacroActionSceneSwap::id,
|
||||||
|
{MacroActionSceneSwap::Create, MacroActionSceneSwapEdit::Create,
|
||||||
|
"AdvSceneSwitcher.action.sceneSwap"});
|
||||||
|
|
||||||
|
bool MacroActionSceneSwap::PerformAction()
|
||||||
|
{
|
||||||
|
obs_frontend_preview_program_trigger_transition();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionSceneSwap::LogAction()
|
||||||
|
{
|
||||||
|
vblog(LOG_INFO, "trigger preview to active scene transition");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionSceneSwap::Save(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroAction::Save(obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionSceneSwap::Load(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroAction::Load(obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroActionSceneSwapEdit::MacroActionSceneSwapEdit(
|
||||||
|
QWidget *parent, std::shared_ptr<MacroActionSceneSwap> entryData)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||||
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {};
|
||||||
|
placeWidgets(obs_module_text("AdvSceneSwitcher.action.SceneSwap.entry"),
|
||||||
|
mainLayout, widgetPlaceholders);
|
||||||
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
_entryData = entryData;
|
||||||
|
}
|
||||||
@@ -10,51 +10,6 @@ bool MacroActionSceneTransform::_registered = MacroActionFactory::Register(
|
|||||||
MacroActionSceneTransformEdit::Create,
|
MacroActionSceneTransformEdit::Create,
|
||||||
"AdvSceneSwitcher.action.sceneTransform"});
|
"AdvSceneSwitcher.action.sceneTransform"});
|
||||||
|
|
||||||
static void load_transform_state(obs_data_t *obj,
|
|
||||||
struct obs_transform_info &info,
|
|
||||||
struct obs_sceneitem_crop &crop)
|
|
||||||
{
|
|
||||||
obs_data_get_vec2(obj, "pos", &info.pos);
|
|
||||||
obs_data_get_vec2(obj, "scale", &info.scale);
|
|
||||||
info.rot = (float)obs_data_get_double(obj, "rot");
|
|
||||||
info.alignment = (uint32_t)obs_data_get_int(obj, "alignment");
|
|
||||||
info.bounds_type =
|
|
||||||
(enum obs_bounds_type)obs_data_get_int(obj, "bounds_type");
|
|
||||||
info.bounds_alignment =
|
|
||||||
(uint32_t)obs_data_get_int(obj, "bounds_alignment");
|
|
||||||
obs_data_get_vec2(obj, "bounds", &info.bounds);
|
|
||||||
crop.top = (int)obs_data_get_int(obj, "top");
|
|
||||||
crop.bottom = (int)obs_data_get_int(obj, "bottom");
|
|
||||||
crop.left = (int)obs_data_get_int(obj, "left");
|
|
||||||
crop.right = (int)obs_data_get_int(obj, "right");
|
|
||||||
}
|
|
||||||
|
|
||||||
bool save_transform_state(obs_data_t *obj, struct obs_transform_info &info,
|
|
||||||
struct obs_sceneitem_crop &crop)
|
|
||||||
{
|
|
||||||
struct vec2 pos = info.pos;
|
|
||||||
struct vec2 scale = info.scale;
|
|
||||||
float rot = info.rot;
|
|
||||||
uint32_t alignment = info.alignment;
|
|
||||||
uint32_t bounds_type = info.bounds_type;
|
|
||||||
uint32_t bounds_alignment = info.bounds_alignment;
|
|
||||||
struct vec2 bounds = info.bounds;
|
|
||||||
|
|
||||||
obs_data_set_vec2(obj, "pos", &pos);
|
|
||||||
obs_data_set_vec2(obj, "scale", &scale);
|
|
||||||
obs_data_set_double(obj, "rot", rot);
|
|
||||||
obs_data_set_int(obj, "alignment", alignment);
|
|
||||||
obs_data_set_int(obj, "bounds_type", bounds_type);
|
|
||||||
obs_data_set_vec2(obj, "bounds", &bounds);
|
|
||||||
obs_data_set_int(obj, "bounds_alignment", bounds_alignment);
|
|
||||||
obs_data_set_int(obj, "top", crop.top);
|
|
||||||
obs_data_set_int(obj, "bottom", crop.bottom);
|
|
||||||
obs_data_set_int(obj, "left", crop.left);
|
|
||||||
obs_data_set_int(obj, "right", crop.right);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroActionSceneTransform::PerformAction()
|
bool MacroActionSceneTransform::PerformAction()
|
||||||
{
|
{
|
||||||
auto s = obs_weak_source_get_source(_scene.GetScene(false));
|
auto s = obs_weak_source_get_source(_scene.GetScene(false));
|
||||||
@@ -63,24 +18,10 @@ bool MacroActionSceneTransform::PerformAction()
|
|||||||
auto items = getSceneItemsWithName(scene, name);
|
auto items = getSceneItemsWithName(scene, name);
|
||||||
|
|
||||||
for (auto &item : items) {
|
for (auto &item : items) {
|
||||||
// Merge new settings with current settings
|
|
||||||
struct obs_transform_info info;
|
|
||||||
struct obs_sceneitem_crop crop;
|
|
||||||
obs_sceneitem_get_info(item, &info);
|
|
||||||
obs_sceneitem_get_crop(item, &crop);
|
|
||||||
auto temp = obs_data_create();
|
|
||||||
save_transform_state(temp, info, crop);
|
|
||||||
auto temp2 = obs_data_create();
|
|
||||||
save_transform_state(temp, _info, _crop);
|
|
||||||
obs_data_apply(temp, temp2);
|
|
||||||
load_transform_state(temp, info, crop);
|
|
||||||
obs_data_release(temp);
|
|
||||||
obs_data_release(temp2);
|
|
||||||
|
|
||||||
// Apply settings
|
// Apply settings
|
||||||
obs_sceneitem_defer_update_begin(item);
|
obs_sceneitem_defer_update_begin(item);
|
||||||
obs_sceneitem_set_info(item, &info);
|
obs_sceneitem_set_info(item, &_info);
|
||||||
obs_sceneitem_set_crop(item, &crop);
|
obs_sceneitem_set_crop(item, &_crop);
|
||||||
obs_sceneitem_defer_update_end(item);
|
obs_sceneitem_defer_update_end(item);
|
||||||
|
|
||||||
obs_sceneitem_release(item);
|
obs_sceneitem_release(item);
|
||||||
@@ -102,7 +43,7 @@ bool MacroActionSceneTransform::Save(obs_data_t *obj)
|
|||||||
MacroAction::Save(obj);
|
MacroAction::Save(obj);
|
||||||
_scene.Save(obj);
|
_scene.Save(obj);
|
||||||
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
|
obs_data_set_string(obj, "source", GetWeakSourceName(_source).c_str());
|
||||||
save_transform_state(obj, _info, _crop);
|
saveTransformState(obj, _info, _crop);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +53,7 @@ bool MacroActionSceneTransform::Load(obs_data_t *obj)
|
|||||||
_scene.Load(obj);
|
_scene.Load(obj);
|
||||||
const char *sourceName = obs_data_get_string(obj, "source");
|
const char *sourceName = obs_data_get_string(obj, "source");
|
||||||
_source = GetWeakSourceByName(sourceName);
|
_source = GetWeakSourceByName(sourceName);
|
||||||
load_transform_state(obj, _info, _crop);
|
loadTransformState(obj, _info, _crop);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,7 +68,7 @@ std::string MacroActionSceneTransform::GetShortDesc()
|
|||||||
std::string MacroActionSceneTransform::GetSettings()
|
std::string MacroActionSceneTransform::GetSettings()
|
||||||
{
|
{
|
||||||
auto data = obs_data_create();
|
auto data = obs_data_create();
|
||||||
save_transform_state(data, _info, _crop);
|
saveTransformState(data, _info, _crop);
|
||||||
std::string json = obs_data_get_json(data);
|
std::string json = obs_data_get_json(data);
|
||||||
obs_data_release(data);
|
obs_data_release(data);
|
||||||
return json;
|
return json;
|
||||||
@@ -139,7 +80,22 @@ void MacroActionSceneTransform::SetSettings(std::string &settings)
|
|||||||
if (!data) {
|
if (!data) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
load_transform_state(data, _info, _crop);
|
loadTransformState(data, _info, _crop);
|
||||||
|
if (obs_data_has_user_value(data, "size")) {
|
||||||
|
auto obj = obs_data_get_obj(data, "size");
|
||||||
|
auto source = obs_weak_source_get_source(_source);
|
||||||
|
if (double h = obs_data_get_double(obj, "height")) {
|
||||||
|
_info.scale.y =
|
||||||
|
h / double(obs_source_get_height(source));
|
||||||
|
}
|
||||||
|
if (double w = obs_data_get_double(obj, "width")) {
|
||||||
|
_info.scale.x =
|
||||||
|
w / double(obs_source_get_width(source));
|
||||||
|
}
|
||||||
|
obs_data_release(obj);
|
||||||
|
obs_source_release(source);
|
||||||
|
}
|
||||||
|
|
||||||
obs_data_release(data);
|
obs_data_release(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +157,7 @@ void MacroActionSceneTransformEdit::UpdateEntryData()
|
|||||||
GetWeakSourceName(_entryData->_source).c_str());
|
GetWeakSourceName(_entryData->_source).c_str());
|
||||||
if (_entryData->_source) {
|
if (_entryData->_source) {
|
||||||
_settings->setPlainText(
|
_settings->setPlainText(
|
||||||
fromatJsonString(_entryData->GetSettings()));
|
formatJsonString(_entryData->GetSettings()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -247,16 +203,7 @@ void MacroActionSceneTransformEdit::GetSettingsClicked()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct obs_transform_info info;
|
_settings->setPlainText(formatJsonString(getSceneItemTransform(item)));
|
||||||
struct obs_sceneitem_crop crop;
|
|
||||||
obs_sceneitem_get_info(item, &info);
|
|
||||||
obs_sceneitem_get_crop(item, &crop);
|
|
||||||
|
|
||||||
auto data = obs_data_create();
|
|
||||||
save_transform_state(data, info, crop);
|
|
||||||
auto json = obs_data_get_json(data);
|
|
||||||
_settings->setPlainText(fromatJsonString(json));
|
|
||||||
obs_data_release(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionSceneTransformEdit::SettingsChanged()
|
void MacroActionSceneTransformEdit::SettingsChanged()
|
||||||
|
|||||||
@@ -173,7 +173,7 @@ void MacroActionSourceEdit::GetSettingsClicked()
|
|||||||
}
|
}
|
||||||
|
|
||||||
_settings->setPlainText(
|
_settings->setPlainText(
|
||||||
fromatJsonString(getSourceSettings(_entryData->_source)));
|
formatJsonString(getSourceSettings(_entryData->_source)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionSourceEdit::SettingsChanged()
|
void MacroActionSourceEdit::SettingsChanged()
|
||||||
|
|||||||
169
src/macro-action-transition.cpp
Normal file
169
src/macro-action-transition.cpp
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
#include "headers/macro-action-transition.hpp"
|
||||||
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
|
#include "headers/utility.hpp"
|
||||||
|
|
||||||
|
const std::string MacroActionTransition::id = "transition";
|
||||||
|
|
||||||
|
bool MacroActionTransition::_registered = MacroActionFactory::Register(
|
||||||
|
MacroActionTransition::id,
|
||||||
|
{MacroActionTransition::Create, MacroActionTransitionEdit::Create,
|
||||||
|
"AdvSceneSwitcher.action.transition"});
|
||||||
|
|
||||||
|
bool MacroActionTransition::PerformAction()
|
||||||
|
{
|
||||||
|
if (_setType) {
|
||||||
|
auto t =
|
||||||
|
obs_weak_source_get_source(_transition.GetTransition());
|
||||||
|
obs_frontend_set_current_transition(t);
|
||||||
|
obs_source_release(t);
|
||||||
|
}
|
||||||
|
if (_setDuration) {
|
||||||
|
obs_frontend_set_transition_duration(_duration.seconds * 1000);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionTransition::LogAction()
|
||||||
|
{
|
||||||
|
if (_setDuration) {
|
||||||
|
vblog(LOG_INFO, "set transition duration to %s",
|
||||||
|
_duration.ToString().c_str());
|
||||||
|
}
|
||||||
|
if (_setType) {
|
||||||
|
vblog(LOG_INFO, "set transition type to \"%s\"",
|
||||||
|
_transition.ToString().c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionTransition::Save(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroAction::Save(obj);
|
||||||
|
_duration.Save(obj);
|
||||||
|
_transition.Save(obj);
|
||||||
|
obs_data_set_bool(obj, "setDuration", _setDuration);
|
||||||
|
obs_data_set_bool(obj, "setType", _setType);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionTransition::Load(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroAction::Load(obj);
|
||||||
|
_duration.Load(obj);
|
||||||
|
_transition.Load(obj);
|
||||||
|
_setDuration = obs_data_get_bool(obj, "setDuration");
|
||||||
|
_setType = obs_data_get_bool(obj, "setType");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MacroActionTransition::GetShortDesc()
|
||||||
|
{
|
||||||
|
return _transition.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroActionTransitionEdit::MacroActionTransitionEdit(
|
||||||
|
QWidget *parent, std::shared_ptr<MacroActionTransition> entryData)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
_transitions = new TransitionSelectionWidget(this, false);
|
||||||
|
_duration = new DurationSelection(this, false);
|
||||||
|
_setType = new QCheckBox();
|
||||||
|
_setDuration = new QCheckBox();
|
||||||
|
|
||||||
|
QWidget::connect(_transitions,
|
||||||
|
SIGNAL(TransitionChanged(const TransitionSelection &)),
|
||||||
|
this,
|
||||||
|
SLOT(TransitionChanged(const TransitionSelection &)));
|
||||||
|
QWidget::connect(_duration, SIGNAL(DurationChanged(double)), this,
|
||||||
|
SLOT(DurationChanged(double)));
|
||||||
|
QWidget::connect(_setType, SIGNAL(stateChanged(int)), this,
|
||||||
|
SLOT(SetTypeChanged(int)));
|
||||||
|
QWidget::connect(_setDuration, SIGNAL(stateChanged(int)), this,
|
||||||
|
SLOT(SetDurationChanged(int)));
|
||||||
|
|
||||||
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
|
{"{{transitions}}", _transitions},
|
||||||
|
{"{{duration}}", _duration},
|
||||||
|
{"{{setType}}", _setType},
|
||||||
|
{"{{setDuration}}", _setDuration},
|
||||||
|
};
|
||||||
|
_typeLayout = new QHBoxLayout;
|
||||||
|
placeWidgets(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.transition.entry.line1"),
|
||||||
|
_typeLayout, widgetPlaceholders);
|
||||||
|
_durationLayout = new QHBoxLayout;
|
||||||
|
placeWidgets(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.transition.entry.line2"),
|
||||||
|
_durationLayout, widgetPlaceholders);
|
||||||
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
|
mainLayout->addLayout(_typeLayout);
|
||||||
|
mainLayout->addLayout(_durationLayout);
|
||||||
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
_entryData = entryData;
|
||||||
|
UpdateEntryData();
|
||||||
|
_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionTransitionEdit::UpdateEntryData()
|
||||||
|
{
|
||||||
|
if (!_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_setDuration->setChecked(_entryData->_setDuration);
|
||||||
|
_duration->SetDuration(_entryData->_duration);
|
||||||
|
_setType->setChecked(_entryData->_setType);
|
||||||
|
_transitions->SetTransition(_entryData->_transition);
|
||||||
|
_transitions->setEnabled(_entryData->_setType);
|
||||||
|
_duration->setEnabled(_entryData->_setDuration);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionTransitionEdit::TransitionChanged(const TransitionSelection &t)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_transition = t;
|
||||||
|
emit HeaderInfoChanged(
|
||||||
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionTransitionEdit::DurationChanged(double seconds)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_duration.seconds = seconds;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionTransitionEdit::SetTypeChanged(int state)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_setType = state;
|
||||||
|
_transitions->setEnabled(state);
|
||||||
|
if (state) {
|
||||||
|
emit HeaderInfoChanged(
|
||||||
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
|
} else {
|
||||||
|
emit HeaderInfoChanged("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionTransitionEdit::SetDurationChanged(int state)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_setDuration = state;
|
||||||
|
_duration->setEnabled(state);
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef VCAM_SUPPORTED
|
||||||
|
|
||||||
#include "headers/macro-action-virtual-cam.hpp"
|
#include "headers/macro-action-virtual-cam.hpp"
|
||||||
#include "headers/advanced-scene-switcher.hpp"
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
#include "headers/utility.hpp"
|
#include "headers/utility.hpp"
|
||||||
@@ -107,3 +109,5 @@ void MacroActionVCamEdit::ActionChanged(int value)
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_action = static_cast<VCamAction>(value);
|
_entryData->_action = static_cast<VCamAction>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -38,10 +38,12 @@ bool MacroActionWait::PerformAction()
|
|||||||
sleep_duration);
|
sleep_duration);
|
||||||
|
|
||||||
std::unique_lock<std::mutex> lock(switcher->m);
|
std::unique_lock<std::mutex> lock(switcher->m);
|
||||||
auto r = switcher->cv.wait_for(
|
switcher->abortMacroWait = false;
|
||||||
|
switcher->macroWaitCv.wait_for(
|
||||||
lock,
|
lock,
|
||||||
std::chrono::milliseconds((long long)(sleep_duration * 1000)));
|
std::chrono::milliseconds((long long)(sleep_duration * 1000)),
|
||||||
return r == std::cv_status::timeout;
|
[] { return switcher->abortMacroWait.load(); });
|
||||||
|
return !switcher->abortMacroWait;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroActionWait::Save(obs_data_t *obj)
|
bool MacroActionWait::Save(obs_data_t *obj)
|
||||||
|
|||||||
261
src/macro-condition-cursor.cpp
Normal file
261
src/macro-condition-cursor.cpp
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
#include "headers/macro-condition-edit.hpp"
|
||||||
|
#include "headers/macro-condition-cursor.hpp"
|
||||||
|
#include "headers/utility.hpp"
|
||||||
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
|
|
||||||
|
const std::string MacroConditionCursor::id = "cursor";
|
||||||
|
|
||||||
|
bool MacroConditionCursor::_registered = MacroConditionFactory::Register(
|
||||||
|
MacroConditionCursor::id,
|
||||||
|
{MacroConditionCursor::Create, MacroConditionCursorEdit::Create,
|
||||||
|
"AdvSceneSwitcher.condition.cursor"});
|
||||||
|
|
||||||
|
static std::map<CursorCondition, std::string> cursorConditionTypes = {
|
||||||
|
{CursorCondition::REGION,
|
||||||
|
"AdvSceneSwitcher.condition.cursor.type.region"},
|
||||||
|
{CursorCondition::MOVING,
|
||||||
|
"AdvSceneSwitcher.condition.cursor.type.moving"},
|
||||||
|
};
|
||||||
|
|
||||||
|
bool MacroConditionCursor::CheckCondition()
|
||||||
|
{
|
||||||
|
std::pair<int, int> cursorPos = getCursorPos();
|
||||||
|
switch (_condition) {
|
||||||
|
case CursorCondition::REGION:
|
||||||
|
return cursorPos.first >= _minX && cursorPos.second >= _minY &&
|
||||||
|
cursorPos.first <= _maxX && cursorPos.second <= _maxY;
|
||||||
|
case CursorCondition::MOVING:
|
||||||
|
return switcher->cursorPosChanged;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionCursor::Save(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroCondition::Save(obj);
|
||||||
|
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||||
|
obs_data_set_int(obj, "minX", _minX);
|
||||||
|
obs_data_set_int(obj, "minY", _minY);
|
||||||
|
obs_data_set_int(obj, "maxX", _maxX);
|
||||||
|
obs_data_set_int(obj, "maxY", _maxY);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionCursor::Load(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroCondition::Load(obj);
|
||||||
|
_condition = static_cast<CursorCondition>(
|
||||||
|
obs_data_get_int(obj, "condition"));
|
||||||
|
_minX = obs_data_get_int(obj, "minX");
|
||||||
|
_minY = obs_data_get_int(obj, "minY");
|
||||||
|
_maxX = obs_data_get_int(obj, "maxX");
|
||||||
|
_maxY = obs_data_get_int(obj, "maxY");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void populateConditionSelection(QComboBox *list)
|
||||||
|
{
|
||||||
|
for (auto entry : cursorConditionTypes) {
|
||||||
|
list->addItem(obs_module_text(entry.second.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroConditionCursorEdit::MacroConditionCursorEdit(
|
||||||
|
QWidget *parent, std::shared_ptr<MacroConditionCursor> entryData)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
_conditions = new QComboBox();
|
||||||
|
_minX = new QSpinBox();
|
||||||
|
_minY = new QSpinBox();
|
||||||
|
_maxX = new QSpinBox();
|
||||||
|
_maxY = new QSpinBox();
|
||||||
|
_frameToggle = new QPushButton(
|
||||||
|
obs_module_text("AdvSceneSwitcher.condition.cursor.showFrame"));
|
||||||
|
_xPos = new QLabel("-");
|
||||||
|
_yPos = new QLabel("-");
|
||||||
|
|
||||||
|
populateConditionSelection(_conditions);
|
||||||
|
|
||||||
|
_minX->setPrefix("Min X: ");
|
||||||
|
_minY->setPrefix("Min Y: ");
|
||||||
|
_maxX->setPrefix("Max X: ");
|
||||||
|
_maxY->setPrefix("Max Y: ");
|
||||||
|
|
||||||
|
_minX->setMinimum(-1000000);
|
||||||
|
_minY->setMinimum(-1000000);
|
||||||
|
_maxX->setMinimum(-1000000);
|
||||||
|
_maxY->setMinimum(-1000000);
|
||||||
|
|
||||||
|
_minX->setMaximum(1000000);
|
||||||
|
_minY->setMaximum(1000000);
|
||||||
|
_maxX->setMaximum(1000000);
|
||||||
|
_maxY->setMaximum(1000000);
|
||||||
|
|
||||||
|
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
|
||||||
|
SLOT(ConditionChanged(int)));
|
||||||
|
QWidget::connect(_minX, SIGNAL(valueChanged(int)), this,
|
||||||
|
SLOT(MinXChanged(int)));
|
||||||
|
QWidget::connect(_minY, SIGNAL(valueChanged(int)), this,
|
||||||
|
SLOT(MinYChanged(int)));
|
||||||
|
QWidget::connect(_maxX, SIGNAL(valueChanged(int)), this,
|
||||||
|
SLOT(MaxXChanged(int)));
|
||||||
|
QWidget::connect(_maxY, SIGNAL(valueChanged(int)), this,
|
||||||
|
SLOT(MaxYChanged(int)));
|
||||||
|
QWidget::connect(_frameToggle, SIGNAL(clicked()), this,
|
||||||
|
SLOT(ToggleFrame()));
|
||||||
|
|
||||||
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
|
{"{{conditions}}", _conditions},
|
||||||
|
{"{{minX}}", _minX},
|
||||||
|
{"{{minY}}", _minY},
|
||||||
|
{"{{maxX}}", _maxX},
|
||||||
|
{"{{maxY}}", _maxY},
|
||||||
|
{"{{xPos}}", _xPos},
|
||||||
|
{"{{yPos}}", _yPos},
|
||||||
|
{"{{toggleFrameButton}}", _frameToggle},
|
||||||
|
};
|
||||||
|
QHBoxLayout *line1 = new QHBoxLayout;
|
||||||
|
placeWidgets(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.condition.cursor.entry.line1"),
|
||||||
|
line1, widgetPlaceholders);
|
||||||
|
QHBoxLayout *line2 = new QHBoxLayout;
|
||||||
|
placeWidgets(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.condition.cursor.entry.line2"),
|
||||||
|
line2, widgetPlaceholders);
|
||||||
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
|
mainLayout->addLayout(line1);
|
||||||
|
mainLayout->addLayout(line2);
|
||||||
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
connect(&_timer, &QTimer::timeout, this,
|
||||||
|
&MacroConditionCursorEdit::UpdateCursorPos);
|
||||||
|
_timer.start(1000);
|
||||||
|
|
||||||
|
_entryData = entryData;
|
||||||
|
UpdateEntryData();
|
||||||
|
_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionCursorEdit::ConditionChanged(int index)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_condition = static_cast<CursorCondition>(index);
|
||||||
|
SetRegionSelectionVisible(_entryData->_condition ==
|
||||||
|
CursorCondition::REGION);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionCursorEdit::MinXChanged(int pos)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_minX = pos;
|
||||||
|
SetupFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionCursorEdit::MinYChanged(int pos)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_minY = pos;
|
||||||
|
SetupFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionCursorEdit::MaxXChanged(int pos)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_maxX = pos;
|
||||||
|
SetupFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionCursorEdit::MaxYChanged(int pos)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_maxY = pos;
|
||||||
|
SetupFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionCursorEdit::UpdateCursorPos()
|
||||||
|
{
|
||||||
|
std::pair<int, int> position = getCursorPos();
|
||||||
|
_xPos->setText(QString::number(position.first));
|
||||||
|
_yPos->setText(QString::number(position.second));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionCursorEdit::ToggleFrame()
|
||||||
|
{
|
||||||
|
SetupFrame();
|
||||||
|
if (_frame.isVisible()) {
|
||||||
|
_frameToggle->setText(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.condition.cursor.showFrame"));
|
||||||
|
_frame.hide();
|
||||||
|
} else {
|
||||||
|
_frameToggle->setText(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.condition.cursor.hideFrame"));
|
||||||
|
_frame.show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionCursorEdit::SetRegionSelectionVisible(bool visible)
|
||||||
|
{
|
||||||
|
_minX->setVisible(visible);
|
||||||
|
_minY->setVisible(visible);
|
||||||
|
_maxX->setVisible(visible);
|
||||||
|
_maxY->setVisible(visible);
|
||||||
|
_frameToggle->setVisible(visible);
|
||||||
|
if (_frame.isVisible()) {
|
||||||
|
ToggleFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
adjustSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionCursorEdit::SetupFrame()
|
||||||
|
{
|
||||||
|
_frame.setFrameStyle(QFrame::Box | QFrame::Plain);
|
||||||
|
_frame.setWindowFlags(Qt::FramelessWindowHint | Qt::Tool |
|
||||||
|
Qt::WindowTransparentForInput |
|
||||||
|
Qt::WindowDoesNotAcceptFocus |
|
||||||
|
Qt::WindowStaysOnTopHint);
|
||||||
|
_frame.setAttribute(Qt::WA_TranslucentBackground, true);
|
||||||
|
|
||||||
|
if (_entryData) {
|
||||||
|
_frame.setGeometry(_entryData->_minX, _entryData->_minY,
|
||||||
|
_entryData->_maxX - _entryData->_minX,
|
||||||
|
_entryData->_maxY - _entryData->_minY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionCursorEdit::UpdateEntryData()
|
||||||
|
{
|
||||||
|
if (!_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||||
|
_minX->setValue(_entryData->_minX);
|
||||||
|
_minY->setValue(_entryData->_minY);
|
||||||
|
_maxX->setValue(_entryData->_maxX);
|
||||||
|
_maxY->setValue(_entryData->_maxY);
|
||||||
|
SetRegionSelectionVisible(_entryData->_condition ==
|
||||||
|
CursorCondition::REGION);
|
||||||
|
}
|
||||||
@@ -10,21 +10,52 @@ bool MacroConditionDate::_registered = MacroConditionFactory::Register(
|
|||||||
{MacroConditionDate::Create, MacroConditionDateEdit::Create,
|
{MacroConditionDate::Create, MacroConditionDateEdit::Create,
|
||||||
"AdvSceneSwitcher.condition.date", false});
|
"AdvSceneSwitcher.condition.date", false});
|
||||||
|
|
||||||
|
static std::map<DateCondition, std::string> dateConditionTypes = {
|
||||||
|
{DateCondition::AT, "AdvSceneSwitcher.condition.date.state.at"},
|
||||||
|
{DateCondition::AFTER, "AdvSceneSwitcher.condition.date.state.after"},
|
||||||
|
{DateCondition::BEFORE, "AdvSceneSwitcher.condition.date.state.before"},
|
||||||
|
{DateCondition::BETWEEN,
|
||||||
|
"AdvSceneSwitcher.condition.date.state.between"},
|
||||||
|
};
|
||||||
|
|
||||||
bool MacroConditionDate::CheckCondition()
|
bool MacroConditionDate::CheckCondition()
|
||||||
{
|
{
|
||||||
bool match = false;
|
bool match = false;
|
||||||
QDateTime cur = QDateTime::currentDateTime();
|
QDateTime cur = QDateTime::currentDateTime();
|
||||||
if (_ignoreDate) {
|
if (_ignoreDate) {
|
||||||
_dateTime.setDate(cur.date());
|
_dateTime.setDate(cur.date());
|
||||||
|
_dateTime2.setDate(cur.date());
|
||||||
}
|
}
|
||||||
if (_ignoreTime) {
|
if (_ignoreTime) {
|
||||||
_dateTime.setTime(cur.time());
|
_dateTime.setTime(cur.time());
|
||||||
|
_dateTime2.setTime(cur.time());
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (_condition) {
|
||||||
|
case DateCondition::AT:
|
||||||
|
match = _dateTime >= cur &&
|
||||||
|
_dateTime <= cur.addMSecs(switcher->interval);
|
||||||
|
break;
|
||||||
|
case DateCondition::AFTER:
|
||||||
|
match = cur >= _dateTime;
|
||||||
|
break;
|
||||||
|
case DateCondition::BEFORE:
|
||||||
|
match = cur <= _dateTime;
|
||||||
|
break;
|
||||||
|
case DateCondition::BETWEEN:
|
||||||
|
if (_dateTime2 > _dateTime) {
|
||||||
|
match = cur >= _dateTime && cur <= _dateTime2;
|
||||||
|
} else {
|
||||||
|
match = cur >= _dateTime2 && cur <= _dateTime;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
match = _dateTime >= cur &&
|
|
||||||
_dateTime <= cur.addMSecs(switcher->interval);
|
|
||||||
if (match && _repeat) {
|
if (match && _repeat) {
|
||||||
_dateTime = _dateTime.addSecs(_duration.seconds);
|
_dateTime = _dateTime.addSecs(_duration.seconds);
|
||||||
|
_dateTime2 = _dateTime2.addSecs(_duration.seconds);
|
||||||
}
|
}
|
||||||
|
|
||||||
return match;
|
return match;
|
||||||
@@ -33,8 +64,11 @@ bool MacroConditionDate::CheckCondition()
|
|||||||
bool MacroConditionDate::Save(obs_data_t *obj)
|
bool MacroConditionDate::Save(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
MacroCondition::Save(obj);
|
MacroCondition::Save(obj);
|
||||||
|
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||||
obs_data_set_string(obj, "dateTime",
|
obs_data_set_string(obj, "dateTime",
|
||||||
_dateTime.toString().toStdString().c_str());
|
_dateTime.toString().toStdString().c_str());
|
||||||
|
obs_data_set_string(obj, "dateTime2",
|
||||||
|
_dateTime2.toString().toStdString().c_str());
|
||||||
obs_data_set_bool(obj, "ignoreDate", _ignoreDate);
|
obs_data_set_bool(obj, "ignoreDate", _ignoreDate);
|
||||||
obs_data_set_bool(obj, "ignoreTime", _ignoreTime);
|
obs_data_set_bool(obj, "ignoreTime", _ignoreTime);
|
||||||
obs_data_set_bool(obj, "repeat", _repeat);
|
obs_data_set_bool(obj, "repeat", _repeat);
|
||||||
@@ -46,8 +80,12 @@ bool MacroConditionDate::Save(obs_data_t *obj)
|
|||||||
bool MacroConditionDate::Load(obs_data_t *obj)
|
bool MacroConditionDate::Load(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
MacroCondition::Load(obj);
|
MacroCondition::Load(obj);
|
||||||
|
_condition =
|
||||||
|
static_cast<DateCondition>(obs_data_get_int(obj, "condition"));
|
||||||
_dateTime = QDateTime::fromString(
|
_dateTime = QDateTime::fromString(
|
||||||
QString::fromStdString(obs_data_get_string(obj, "dateTime")));
|
QString::fromStdString(obs_data_get_string(obj, "dateTime")));
|
||||||
|
_dateTime2 = QDateTime::fromString(
|
||||||
|
QString::fromStdString(obs_data_get_string(obj, "dateTime2")));
|
||||||
_ignoreDate = obs_data_get_bool(obj, "ignoreDate");
|
_ignoreDate = obs_data_get_bool(obj, "ignoreDate");
|
||||||
_ignoreTime = obs_data_get_bool(obj, "ignoreTime");
|
_ignoreTime = obs_data_get_bool(obj, "ignoreTime");
|
||||||
_repeat = obs_data_get_bool(obj, "repeat");
|
_repeat = obs_data_get_bool(obj, "repeat");
|
||||||
@@ -60,20 +98,35 @@ std::string MacroConditionDate::GetShortDesc()
|
|||||||
return _dateTime.toString().toStdString();
|
return _dateTime.toString().toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void populateConditionSelection(QComboBox *list)
|
||||||
|
{
|
||||||
|
for (auto entry : dateConditionTypes) {
|
||||||
|
list->addItem(obs_module_text(entry.second.c_str()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MacroConditionDateEdit::MacroConditionDateEdit(
|
MacroConditionDateEdit::MacroConditionDateEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroConditionDate> entryData)
|
QWidget *parent, std::shared_ptr<MacroConditionDate> entryData)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
|
_condition = new QComboBox();
|
||||||
_dateTime = new QDateTimeEdit();
|
_dateTime = new QDateTimeEdit();
|
||||||
_dateTime->setCalendarPopup(true);
|
_dateTime->setCalendarPopup(true);
|
||||||
_dateTime->setDisplayFormat("yyyy.MM.dd hh:mm:ss");
|
_dateTime->setDisplayFormat("yyyy.MM.dd hh:mm:ss");
|
||||||
|
_dateTime2 = new QDateTimeEdit();
|
||||||
|
_dateTime2->setCalendarPopup(true);
|
||||||
|
_dateTime2->setDisplayFormat("yyyy.MM.dd hh:mm:ss");
|
||||||
_ignoreDate = new QCheckBox();
|
_ignoreDate = new QCheckBox();
|
||||||
_ignoreTime = new QCheckBox();
|
_ignoreTime = new QCheckBox();
|
||||||
_repeat = new QCheckBox();
|
_repeat = new QCheckBox();
|
||||||
_duration = new DurationSelection();
|
_duration = new DurationSelection();
|
||||||
|
|
||||||
|
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this,
|
||||||
|
SLOT(ConditionChanged(int)));
|
||||||
QWidget::connect(_dateTime, SIGNAL(dateTimeChanged(const QDateTime &)),
|
QWidget::connect(_dateTime, SIGNAL(dateTimeChanged(const QDateTime &)),
|
||||||
this, SLOT(DateTimeChanged(const QDateTime &)));
|
this, SLOT(DateTimeChanged(const QDateTime &)));
|
||||||
|
QWidget::connect(_dateTime2, SIGNAL(dateTimeChanged(const QDateTime &)),
|
||||||
|
this, SLOT(DateTime2Changed(const QDateTime &)));
|
||||||
QWidget::connect(_ignoreDate, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_ignoreDate, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(IgnoreDateChanged(int)));
|
SLOT(IgnoreDateChanged(int)));
|
||||||
QWidget::connect(_ignoreTime, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_ignoreTime, SIGNAL(stateChanged(int)), this,
|
||||||
@@ -85,9 +138,13 @@ MacroConditionDateEdit::MacroConditionDateEdit(
|
|||||||
QWidget::connect(_duration, SIGNAL(UnitChanged(DurationUnit)), this,
|
QWidget::connect(_duration, SIGNAL(UnitChanged(DurationUnit)), this,
|
||||||
SLOT(DurationUnitChanged(DurationUnit)));
|
SLOT(DurationUnitChanged(DurationUnit)));
|
||||||
|
|
||||||
|
populateConditionSelection(_condition);
|
||||||
|
|
||||||
auto line1Layout = new QHBoxLayout;
|
auto line1Layout = new QHBoxLayout;
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
|
{"{{condition}}", _condition},
|
||||||
{"{{dateTime}}", _dateTime},
|
{"{{dateTime}}", _dateTime},
|
||||||
|
{"{{dateTime2}}", _dateTime2},
|
||||||
{"{{ignoreDate}}", _ignoreDate},
|
{"{{ignoreDate}}", _ignoreDate},
|
||||||
{"{{ignoreTime}}", _ignoreTime},
|
{"{{ignoreTime}}", _ignoreTime},
|
||||||
{"{{repeat}}", _repeat},
|
{"{{repeat}}", _repeat},
|
||||||
@@ -111,6 +168,18 @@ MacroConditionDateEdit::MacroConditionDateEdit(
|
|||||||
_loading = false;
|
_loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroConditionDateEdit::ConditionChanged(int cond)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_condition = static_cast<DateCondition>(cond);
|
||||||
|
ShowSecondDateSelection(_entryData->_condition ==
|
||||||
|
DateCondition::BETWEEN);
|
||||||
|
}
|
||||||
|
|
||||||
void MacroConditionDateEdit::DateTimeChanged(const QDateTime &datetime)
|
void MacroConditionDateEdit::DateTimeChanged(const QDateTime &datetime)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
@@ -124,6 +193,16 @@ void MacroConditionDateEdit::DateTimeChanged(const QDateTime &datetime)
|
|||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroConditionDateEdit::DateTime2Changed(const QDateTime &datetime)
|
||||||
|
{
|
||||||
|
if (_loading || !_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
_entryData->_dateTime2 = datetime;
|
||||||
|
}
|
||||||
|
|
||||||
void MacroConditionDateEdit::IgnoreDateChanged(int state)
|
void MacroConditionDateEdit::IgnoreDateChanged(int state)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
@@ -180,10 +259,21 @@ void MacroConditionDateEdit::UpdateEntryData()
|
|||||||
if (!_entryData) {
|
if (!_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_condition->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||||
_dateTime->setDateTime(_entryData->_dateTime);
|
_dateTime->setDateTime(_entryData->_dateTime);
|
||||||
|
_dateTime2->setDateTime(_entryData->_dateTime2);
|
||||||
_ignoreDate->setChecked(_entryData->_ignoreDate);
|
_ignoreDate->setChecked(_entryData->_ignoreDate);
|
||||||
_ignoreTime->setChecked(_entryData->_ignoreTime);
|
_ignoreTime->setChecked(_entryData->_ignoreTime);
|
||||||
_repeat->setChecked(_entryData->_repeat);
|
_repeat->setChecked(_entryData->_repeat);
|
||||||
_duration->SetDuration(_entryData->_duration);
|
_duration->SetDuration(_entryData->_duration);
|
||||||
_duration->setDisabled(!_entryData->_repeat);
|
_duration->setDisabled(!_entryData->_repeat);
|
||||||
|
ShowSecondDateSelection(_entryData->_condition ==
|
||||||
|
DateCondition::BETWEEN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionDateEdit::ShowSecondDateSelection(bool visible)
|
||||||
|
{
|
||||||
|
_dateTime2->setVisible(visible);
|
||||||
|
adjustSize();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
#include "headers/macro-condition-edit.hpp"
|
#include "headers/macro-condition-edit.hpp"
|
||||||
#include "headers/macro-condition-scene.hpp"
|
#include "headers/macro-condition-scene.hpp"
|
||||||
|
#include "headers/section.hpp"
|
||||||
|
#include "headers/macro-controls.hpp"
|
||||||
|
#include "headers/utility.hpp"
|
||||||
|
|
||||||
std::map<std::string, MacroConditionInfo> MacroConditionFactory::_methods;
|
std::map<std::string, MacroConditionInfo> MacroConditionFactory::_methods;
|
||||||
|
|
||||||
@@ -87,13 +91,11 @@ static inline void populateConditionSelection(QComboBox *list)
|
|||||||
|
|
||||||
MacroConditionEdit::MacroConditionEdit(
|
MacroConditionEdit::MacroConditionEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroCondition> *entryData,
|
QWidget *parent, std::shared_ptr<MacroCondition> *entryData,
|
||||||
const std::string &id, bool root, bool startCollapsed)
|
const std::string &id, bool root)
|
||||||
: QWidget(parent)
|
: MacroSegmentEdit(parent), _entryData(entryData), _isRoot(root)
|
||||||
{
|
{
|
||||||
_logicSelection = new QComboBox();
|
_logicSelection = new QComboBox();
|
||||||
_conditionSelection = new QComboBox();
|
_conditionSelection = new QComboBox();
|
||||||
_section = new Section(300);
|
|
||||||
_headerInfo = new QLabel();
|
|
||||||
_dur = new DurationConstraintEdit();
|
_dur = new DurationConstraintEdit();
|
||||||
|
|
||||||
QWidget::connect(_logicSelection, SIGNAL(currentIndexChanged(int)),
|
QWidget::connect(_logicSelection, SIGNAL(currentIndexChanged(int)),
|
||||||
@@ -108,22 +110,6 @@ MacroConditionEdit::MacroConditionEdit(
|
|||||||
QWidget::connect(_dur, SIGNAL(ConditionChanged(DurationCondition)),
|
QWidget::connect(_dur, SIGNAL(ConditionChanged(DurationCondition)),
|
||||||
this,
|
this,
|
||||||
SLOT(DurationConditionChanged(DurationCondition)));
|
SLOT(DurationConditionChanged(DurationCondition)));
|
||||||
QWidget::connect(parent, SIGNAL(MacroAdded(const QString &)), this,
|
|
||||||
SIGNAL(MacroAdded(const QString &)));
|
|
||||||
QWidget::connect(parent, SIGNAL(MacroRemoved(const QString &)), this,
|
|
||||||
SIGNAL(MacroRemoved(const QString &)));
|
|
||||||
QWidget::connect(parent,
|
|
||||||
SIGNAL(MacroRenamed(const QString &, const QString)),
|
|
||||||
this,
|
|
||||||
SIGNAL(MacroRenamed(const QString &, const QString)));
|
|
||||||
QWidget::connect(parent, SIGNAL(SceneGroupAdded(const QString &)), this,
|
|
||||||
SIGNAL(SceneGroupAdded(const QString &)));
|
|
||||||
QWidget::connect(parent, SIGNAL(SceneGroupRemoved(const QString &)),
|
|
||||||
this, SIGNAL(SceneGroupRemoved(const QString &)));
|
|
||||||
QWidget::connect(
|
|
||||||
parent,
|
|
||||||
SIGNAL(SceneGroupRenamed(const QString &, const QString)), this,
|
|
||||||
SIGNAL(SceneGroupRenamed(const QString &, const QString)));
|
|
||||||
|
|
||||||
populateLogicSelection(_logicSelection, root);
|
populateLogicSelection(_logicSelection, root);
|
||||||
populateConditionSelection(_conditionSelection);
|
populateConditionSelection(_conditionSelection);
|
||||||
@@ -135,11 +121,10 @@ MacroConditionEdit::MacroConditionEdit(
|
|||||||
|
|
||||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||||
mainLayout->addWidget(_section);
|
mainLayout->addWidget(_section);
|
||||||
|
mainLayout->addWidget(_controls);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
_entryData = entryData;
|
UpdateEntryData(id);
|
||||||
_isRoot = root;
|
|
||||||
UpdateEntryData(id, startCollapsed);
|
|
||||||
_loading = false;
|
_loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -165,7 +150,14 @@ bool MacroConditionEdit::IsRootNode()
|
|||||||
return _isRoot;
|
return _isRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionEdit::UpdateEntryData(const std::string &id, bool collapse)
|
void MacroConditionEdit::SetRootNode(bool root)
|
||||||
|
{
|
||||||
|
const QSignalBlocker blocker(_logicSelection);
|
||||||
|
_logicSelection->clear();
|
||||||
|
populateLogicSelection(_logicSelection, root);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionEdit::UpdateEntryData(const std::string &id)
|
||||||
{
|
{
|
||||||
_conditionSelection->setCurrentText(obs_module_text(
|
_conditionSelection->setCurrentText(obs_module_text(
|
||||||
MacroConditionFactory::GetConditionName(id).c_str()));
|
MacroConditionFactory::GetConditionName(id).c_str()));
|
||||||
@@ -182,11 +174,12 @@ void MacroConditionEdit::UpdateEntryData(const std::string &id, bool collapse)
|
|||||||
_logicSelection->setCurrentIndex(static_cast<int>(logic) -
|
_logicSelection->setCurrentIndex(static_cast<int>(logic) -
|
||||||
logic_root_offset);
|
logic_root_offset);
|
||||||
}
|
}
|
||||||
_section->SetContent(widget, collapse);
|
_section->SetContent(widget, (*_entryData)->GetCollapsed());
|
||||||
|
|
||||||
_dur->setVisible(MacroConditionFactory::UsesDurationConstraint(id));
|
_dur->setVisible(MacroConditionFactory::UsesDurationConstraint(id));
|
||||||
auto constraint = (*_entryData)->GetDurationConstraint();
|
auto constraint = (*_entryData)->GetDurationConstraint();
|
||||||
_dur->SetValue(constraint);
|
_dur->SetValue(constraint);
|
||||||
|
SetFocusPolicyOfWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
||||||
@@ -212,6 +205,7 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
|||||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||||
_section->SetContent(widget, false);
|
_section->SetContent(widget, false);
|
||||||
_dur->setVisible(MacroConditionFactory::UsesDurationConstraint(id));
|
_dur->setVisible(MacroConditionFactory::UsesDurationConstraint(id));
|
||||||
|
SetFocusPolicyOfWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionEdit::DurationChanged(double seconds)
|
void MacroConditionEdit::DurationChanged(double seconds)
|
||||||
@@ -244,10 +238,51 @@ void MacroConditionEdit::DurationUnitChanged(DurationUnit unit)
|
|||||||
(*_entryData)->SetDurationUnit(unit);
|
(*_entryData)->SetDurationUnit(unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionEdit::HeaderInfoChanged(const QString &text)
|
MacroSegment *MacroConditionEdit::Data()
|
||||||
{
|
{
|
||||||
_headerInfo->setVisible(!text.isEmpty());
|
return _entryData->get();
|
||||||
_headerInfo->setText(text);
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::AddMacroCondition(int idx)
|
||||||
|
{
|
||||||
|
auto macro = getSelectedMacro();
|
||||||
|
if (!macro) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx < 0 || idx > (int)macro->Conditions().size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string id;
|
||||||
|
if (idx - 1 >= 0) {
|
||||||
|
id = macro->Conditions().at(idx - 1)->GetId();
|
||||||
|
} else {
|
||||||
|
MacroConditionScene temp;
|
||||||
|
id = temp.GetId();
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
bool root = idx == 0;
|
||||||
|
auto cond =
|
||||||
|
macro->Conditions().emplace(macro->Conditions().begin() + idx,
|
||||||
|
MacroConditionFactory::Create(id));
|
||||||
|
if (idx - 1 >= 0) {
|
||||||
|
auto data = obs_data_create();
|
||||||
|
macro->Conditions().at(idx - 1)->Save(data);
|
||||||
|
macro->Conditions().at(idx)->Load(data);
|
||||||
|
obs_data_release(data);
|
||||||
|
}
|
||||||
|
auto logic = root ? LogicType::ROOT_NONE : LogicType::NONE;
|
||||||
|
(*cond)->SetLogicType(logic);
|
||||||
|
macro->UpdateConditionIndices();
|
||||||
|
|
||||||
|
// All entry pointers in existing edit widgets after the new entry will
|
||||||
|
// be invalidated by adding the new entry so we have to recreate them
|
||||||
|
// and because I am lazy I am recreating every widget.
|
||||||
|
//
|
||||||
|
// If performance should become a concern this has to be revisited.
|
||||||
|
SetEditMacro(*macro);
|
||||||
|
HighlightCondition(idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_conditionAdd_clicked()
|
void AdvSceneSwitcher::on_conditionAdd_clicked()
|
||||||
@@ -256,18 +291,41 @@ void AdvSceneSwitcher::on_conditionAdd_clicked()
|
|||||||
if (!macro) {
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
MacroConditionScene temp;
|
|
||||||
std::string id = temp.GetId();
|
AddMacroCondition((int)macro->Conditions().size());
|
||||||
|
ui->macroEditConditionHelp->setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::RemoveMacroCondition(int idx)
|
||||||
|
{
|
||||||
|
auto macro = getSelectedMacro();
|
||||||
|
if (!macro) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx < 0 || idx >= (int)macro->Conditions().size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
bool root = macro->Conditions().size() == 0;
|
macro->Conditions().erase(macro->Conditions().begin() + idx);
|
||||||
macro->Conditions().emplace_back(MacroConditionFactory::Create(id));
|
macro->UpdateConditionIndices();
|
||||||
auto logic = root ? LogicType::ROOT_NONE : LogicType::NONE;
|
|
||||||
macro->Conditions().back()->SetLogicType(logic);
|
if (macro->Conditions().size() == 0) {
|
||||||
auto newEntry = new MacroConditionEdit(
|
ui->macroEditConditionHelp->setVisible(true);
|
||||||
this, ¯o->Conditions().back(), id, root, false);
|
}
|
||||||
ui->macroEditConditionLayout->addWidget(newEntry);
|
|
||||||
ui->macroEditConditionHelp->setVisible(false);
|
if (idx == 0 && macro->Conditions().size() > 0) {
|
||||||
|
auto newRoot = macro->Conditions().at(0);
|
||||||
|
newRoot->SetLogicType(LogicType::ROOT_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// All entry pointers in existing edit widgets after the new entry will
|
||||||
|
// be invalidated by adding the new entry so we have to recreate them
|
||||||
|
// and because I am lazy I am recreating every widget.
|
||||||
|
//
|
||||||
|
// If performance should become a concern this has to be revisited.
|
||||||
|
SetEditMacro(*macro);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_conditionRemove_clicked()
|
void AdvSceneSwitcher::on_conditionRemove_clicked()
|
||||||
@@ -276,24 +334,71 @@ void AdvSceneSwitcher::on_conditionRemove_clicked()
|
|||||||
if (!macro) {
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
RemoveMacroCondition((int)macro->Conditions().size() - 1);
|
||||||
if (macro->Conditions().empty()) {
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::SwapConditions(Macro *m, int pos1, int pos2)
|
||||||
|
{
|
||||||
|
if (pos1 == pos2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
macro->Conditions().pop_back();
|
if (pos1 > pos2) {
|
||||||
|
std::swap(pos1, pos2);
|
||||||
int count = ui->macroEditConditionLayout->count();
|
|
||||||
auto item = ui->macroEditConditionLayout->takeAt(count - 1);
|
|
||||||
|
|
||||||
if (item) {
|
|
||||||
auto widget = item->widget();
|
|
||||||
if (widget) {
|
|
||||||
widget->setVisible(false);
|
|
||||||
}
|
|
||||||
delete item;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (count == 1) {
|
bool root = pos1 == 0;
|
||||||
ui->macroEditConditionHelp->setVisible(true);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
iter_swap(m->Conditions().begin() + pos1,
|
||||||
|
m->Conditions().begin() + pos2);
|
||||||
|
m->UpdateConditionIndices();
|
||||||
|
|
||||||
|
auto c1 = m->Conditions().begin() + pos1;
|
||||||
|
auto c2 = m->Conditions().begin() + pos2;
|
||||||
|
if (root) {
|
||||||
|
auto logic1 = (*c1)->GetLogicType();
|
||||||
|
auto logic2 = (*c2)->GetLogicType();
|
||||||
|
(*c1)->SetLogicType(logic2);
|
||||||
|
(*c2)->SetLogicType(logic1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto item1 = ui->macroEditConditionLayout->takeAt(pos1);
|
||||||
|
auto item2 = ui->macroEditConditionLayout->takeAt(pos2 - 1);
|
||||||
|
deleteLayoutItem(item1);
|
||||||
|
deleteLayoutItem(item2);
|
||||||
|
auto widget1 =
|
||||||
|
new MacroConditionEdit(this, &(*c1), (*c1)->GetId(), root);
|
||||||
|
auto widget2 =
|
||||||
|
new MacroConditionEdit(this, &(*c2), (*c2)->GetId(), false);
|
||||||
|
ConnectControlSignals(widget1);
|
||||||
|
ConnectControlSignals(widget2);
|
||||||
|
ui->macroEditConditionLayout->insertWidget(pos1, widget1);
|
||||||
|
ui->macroEditConditionLayout->insertWidget(pos2, widget2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::MoveMacroConditionUp(int idx)
|
||||||
|
{
|
||||||
|
auto macro = getSelectedMacro();
|
||||||
|
if (!macro) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx < 1 || idx >= (int)macro->Conditions().size()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwapConditions(macro, idx, idx - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::MoveMacroConditionDown(int idx)
|
||||||
|
{
|
||||||
|
auto macro = getSelectedMacro();
|
||||||
|
if (!macro) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx < 0 || idx >= (int)macro->Conditions().size() - 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SwapConditions(macro, idx, idx + 1);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -137,10 +137,7 @@ MacroConditionFileEdit::MacroConditionFileEdit(
|
|||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
{
|
{
|
||||||
_fileType = new QComboBox();
|
_fileType = new QComboBox();
|
||||||
_filePath = new QLineEdit();
|
_filePath = new FileSelection();
|
||||||
_browseButton =
|
|
||||||
new QPushButton(obs_module_text("AdvSceneSwitcher.browse"));
|
|
||||||
_browseButton->setStyleSheet("border:1px solid gray;");
|
|
||||||
_matchText = new QPlainTextEdit();
|
_matchText = new QPlainTextEdit();
|
||||||
_useRegex = new QCheckBox(
|
_useRegex = new QCheckBox(
|
||||||
obs_module_text("AdvSceneSwitcher.fileTab.useRegExp"));
|
obs_module_text("AdvSceneSwitcher.fileTab.useRegExp"));
|
||||||
@@ -151,10 +148,8 @@ MacroConditionFileEdit::MacroConditionFileEdit(
|
|||||||
|
|
||||||
QWidget::connect(_fileType, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_fileType, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(FileTypeChanged(int)));
|
SLOT(FileTypeChanged(int)));
|
||||||
QWidget::connect(_filePath, SIGNAL(editingFinished()), this,
|
QWidget::connect(_filePath, SIGNAL(PathChanged(const QString &)), this,
|
||||||
SLOT(FilePathChanged()));
|
SLOT(PathChanged(const QString &)));
|
||||||
QWidget::connect(_browseButton, SIGNAL(clicked()), this,
|
|
||||||
SLOT(BrowseButtonClicked()));
|
|
||||||
QWidget::connect(_matchText, SIGNAL(textChanged()), this,
|
QWidget::connect(_matchText, SIGNAL(textChanged()), this,
|
||||||
SLOT(MatchTextChanged()));
|
SLOT(MatchTextChanged()));
|
||||||
QWidget::connect(_useRegex, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_useRegex, SIGNAL(stateChanged(int)), this,
|
||||||
@@ -170,7 +165,6 @@ MacroConditionFileEdit::MacroConditionFileEdit(
|
|||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{fileType}}", _fileType},
|
{"{{fileType}}", _fileType},
|
||||||
{"{{filePath}}", _filePath},
|
{"{{filePath}}", _filePath},
|
||||||
{"{{browseButton}}", _browseButton},
|
|
||||||
{"{{matchText}}", _matchText},
|
{"{{matchText}}", _matchText},
|
||||||
{"{{useRegex}}", _useRegex},
|
{"{{useRegex}}", _useRegex},
|
||||||
{"{{checkModificationDate}}", _checkModificationDate},
|
{"{{checkModificationDate}}", _checkModificationDate},
|
||||||
@@ -209,7 +203,7 @@ void MacroConditionFileEdit::UpdateEntryData()
|
|||||||
|
|
||||||
_fileType->setCurrentIndex(static_cast<int>(_entryData->_fileType));
|
_fileType->setCurrentIndex(static_cast<int>(_entryData->_fileType));
|
||||||
|
|
||||||
_filePath->setText(QString::fromStdString(_entryData->_file));
|
_filePath->SetPath(QString::fromStdString(_entryData->_file));
|
||||||
_matchText->setPlainText(QString::fromStdString(_entryData->_text));
|
_matchText->setPlainText(QString::fromStdString(_entryData->_text));
|
||||||
_useRegex->setChecked(_entryData->_useRegex);
|
_useRegex->setChecked(_entryData->_useRegex);
|
||||||
_checkModificationDate->setChecked(_entryData->_useTime);
|
_checkModificationDate->setChecked(_entryData->_useTime);
|
||||||
@@ -225,10 +219,10 @@ void MacroConditionFileEdit::FileTypeChanged(int index)
|
|||||||
FileType type = static_cast<FileType>(index);
|
FileType type = static_cast<FileType>(index);
|
||||||
|
|
||||||
if (type == FileType::LOCAL) {
|
if (type == FileType::LOCAL) {
|
||||||
_browseButton->setDisabled(false);
|
_filePath->Button()->setDisabled(false);
|
||||||
_checkModificationDate->setDisabled(false);
|
_checkModificationDate->setDisabled(false);
|
||||||
} else {
|
} else {
|
||||||
_browseButton->setDisabled(true);
|
_filePath->Button()->setDisabled(true);
|
||||||
_checkModificationDate->setDisabled(true);
|
_checkModificationDate->setDisabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,37 +230,18 @@ void MacroConditionFileEdit::FileTypeChanged(int index)
|
|||||||
_entryData->_fileType = type;
|
_entryData->_fileType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionFileEdit::FilePathChanged()
|
void MacroConditionFileEdit::PathChanged(const QString &text)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
_entryData->_file = _filePath->text().toUtf8().constData();
|
_entryData->_file = text.toUtf8().constData();
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionFileEdit::BrowseButtonClicked()
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString path = QFileDialog::getOpenFileName(
|
|
||||||
this,
|
|
||||||
tr(obs_module_text("AdvSceneSwitcher.fileTab.selectRead")),
|
|
||||||
QDir::currentPath(),
|
|
||||||
tr(obs_module_text("AdvSceneSwitcher.fileTab.anyFileType")));
|
|
||||||
if (path.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_filePath->setText(path);
|
|
||||||
FilePathChanged();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroConditionFileEdit::MatchTextChanged()
|
void MacroConditionFileEdit::MatchTextChanged()
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
|
|||||||
@@ -191,8 +191,11 @@ void MacroConditionFilterEdit::GetSettingsClicked()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_settings->setPlainText(
|
QString json = formatJsonString(getSourceSettings(_entryData->_filter));
|
||||||
fromatJsonString(getSourceSettings(_entryData->_filter)));
|
if (_entryData->_regex) {
|
||||||
|
json = escapeForRegex(json);
|
||||||
|
}
|
||||||
|
_settings->setPlainText(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionFilterEdit::SettingsChanged()
|
void MacroConditionFilterEdit::SettingsChanged()
|
||||||
|
|||||||
@@ -10,12 +10,6 @@ bool MacroConditionMacro::_registered = MacroConditionFactory::Register(
|
|||||||
{MacroConditionMacro::Create, MacroConditionMacroEdit::Create,
|
{MacroConditionMacro::Create, MacroConditionMacroEdit::Create,
|
||||||
"AdvSceneSwitcher.condition.macro"});
|
"AdvSceneSwitcher.condition.macro"});
|
||||||
|
|
||||||
// TODO: Remove in future version - just added for backward compatibility
|
|
||||||
static std::string idOld = "counter";
|
|
||||||
static bool oldRegisterd = MacroConditionFactory::Register(
|
|
||||||
idOld, {MacroConditionMacro::Create, MacroConditionMacroEdit::Create,
|
|
||||||
"AdvSceneSwitcher.condition.macro"});
|
|
||||||
|
|
||||||
static std::map<MacroConditionMacroType, std::string> macroConditionTypes = {
|
static std::map<MacroConditionMacroType, std::string> macroConditionTypes = {
|
||||||
{MacroConditionMacroType::COUNT,
|
{MacroConditionMacroType::COUNT,
|
||||||
"AdvSceneSwitcher.condition.macro.type.count"},
|
"AdvSceneSwitcher.condition.macro.type.count"},
|
||||||
|
|||||||
@@ -1,140 +0,0 @@
|
|||||||
#include "headers/macro-condition-edit.hpp"
|
|
||||||
#include "headers/macro-condition-region.hpp"
|
|
||||||
#include "headers/utility.hpp"
|
|
||||||
#include "headers/advanced-scene-switcher.hpp"
|
|
||||||
|
|
||||||
const std::string MacroConditionRegion::id = "region";
|
|
||||||
|
|
||||||
bool MacroConditionRegion::_registered = MacroConditionFactory::Register(
|
|
||||||
MacroConditionRegion::id,
|
|
||||||
{MacroConditionRegion::Create, MacroConditionRegionEdit::Create,
|
|
||||||
"AdvSceneSwitcher.condition.region"});
|
|
||||||
|
|
||||||
bool MacroConditionRegion::CheckCondition()
|
|
||||||
{
|
|
||||||
std::pair<int, int> cursorPos = getCursorPos();
|
|
||||||
return cursorPos.first >= _minX && cursorPos.second >= _minY &&
|
|
||||||
cursorPos.first <= _maxX && cursorPos.second <= _maxY;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroConditionRegion::Save(obs_data_t *obj)
|
|
||||||
{
|
|
||||||
MacroCondition::Save(obj);
|
|
||||||
obs_data_set_int(obj, "minX", _minX);
|
|
||||||
obs_data_set_int(obj, "minY", _minY);
|
|
||||||
obs_data_set_int(obj, "maxX", _maxX);
|
|
||||||
obs_data_set_int(obj, "maxY", _maxY);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroConditionRegion::Load(obs_data_t *obj)
|
|
||||||
{
|
|
||||||
MacroCondition::Load(obj);
|
|
||||||
_minX = obs_data_get_int(obj, "minX");
|
|
||||||
_minY = obs_data_get_int(obj, "minY");
|
|
||||||
_maxX = obs_data_get_int(obj, "maxX");
|
|
||||||
_maxY = obs_data_get_int(obj, "maxY");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
MacroConditionRegionEdit::MacroConditionRegionEdit(
|
|
||||||
QWidget *parent, std::shared_ptr<MacroConditionRegion> entryData)
|
|
||||||
: QWidget(parent)
|
|
||||||
{
|
|
||||||
_minX = new QSpinBox();
|
|
||||||
_minY = new QSpinBox();
|
|
||||||
_maxX = new QSpinBox();
|
|
||||||
_maxY = new QSpinBox();
|
|
||||||
|
|
||||||
_minX->setPrefix("Min X: ");
|
|
||||||
_minY->setPrefix("Min Y: ");
|
|
||||||
_maxX->setPrefix("Max X: ");
|
|
||||||
_maxY->setPrefix("Max Y: ");
|
|
||||||
|
|
||||||
_minX->setMinimum(-1000000);
|
|
||||||
_minY->setMinimum(-1000000);
|
|
||||||
_maxX->setMinimum(-1000000);
|
|
||||||
_maxY->setMinimum(-1000000);
|
|
||||||
|
|
||||||
_minX->setMaximum(1000000);
|
|
||||||
_minY->setMaximum(1000000);
|
|
||||||
_maxX->setMaximum(1000000);
|
|
||||||
_maxY->setMaximum(1000000);
|
|
||||||
|
|
||||||
QWidget::connect(_minX, SIGNAL(valueChanged(int)), this,
|
|
||||||
SLOT(MinXChanged(int)));
|
|
||||||
QWidget::connect(_minY, SIGNAL(valueChanged(int)), this,
|
|
||||||
SLOT(MinYChanged(int)));
|
|
||||||
QWidget::connect(_maxX, SIGNAL(valueChanged(int)), this,
|
|
||||||
SLOT(MaxXChanged(int)));
|
|
||||||
QWidget::connect(_maxY, SIGNAL(valueChanged(int)), this,
|
|
||||||
SLOT(MaxYChanged(int)));
|
|
||||||
|
|
||||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
|
||||||
|
|
||||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
|
||||||
{"{{minX}}", _minX},
|
|
||||||
{"{{minY}}", _minY},
|
|
||||||
{"{{maxX}}", _maxX},
|
|
||||||
{"{{maxY}}", _maxY}};
|
|
||||||
|
|
||||||
placeWidgets(obs_module_text("AdvSceneSwitcher.condition.region.entry"),
|
|
||||||
mainLayout, widgetPlaceholders);
|
|
||||||
setLayout(mainLayout);
|
|
||||||
|
|
||||||
_entryData = entryData;
|
|
||||||
UpdateEntryData();
|
|
||||||
_loading = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroConditionRegionEdit::MinXChanged(int pos)
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
_entryData->_minX = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroConditionRegionEdit::MinYChanged(int pos)
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
_entryData->_minY = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroConditionRegionEdit::MaxXChanged(int pos)
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
_entryData->_maxX = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroConditionRegionEdit::MaxYChanged(int pos)
|
|
||||||
{
|
|
||||||
if (_loading || !_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
_entryData->_maxY = pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroConditionRegionEdit::UpdateEntryData()
|
|
||||||
{
|
|
||||||
if (!_entryData) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_minX->setValue(_entryData->_minX);
|
|
||||||
_minY->setValue(_entryData->_minY);
|
|
||||||
_maxX->setValue(_entryData->_maxX);
|
|
||||||
_maxY->setValue(_entryData->_maxY);
|
|
||||||
}
|
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
#ifdef REPLAYBUFFER_SUPPORTED
|
||||||
|
|
||||||
#include "headers/macro-condition-edit.hpp"
|
#include "headers/macro-condition-edit.hpp"
|
||||||
#include "headers/macro-condition-replay-buffer.hpp"
|
#include "headers/macro-condition-replay-buffer.hpp"
|
||||||
#include "headers/utility.hpp"
|
#include "headers/utility.hpp"
|
||||||
@@ -106,3 +108,5 @@ void MacroConditionReplayBufferEdit::UpdateEntryData()
|
|||||||
|
|
||||||
_state->setCurrentIndex(static_cast<int>(_entryData->_state));
|
_state->setCurrentIndex(static_cast<int>(_entryData->_state));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|||||||
@@ -3,8 +3,6 @@
|
|||||||
#include "headers/utility.hpp"
|
#include "headers/utility.hpp"
|
||||||
#include "headers/advanced-scene-switcher.hpp"
|
#include "headers/advanced-scene-switcher.hpp"
|
||||||
|
|
||||||
#include <regex>
|
|
||||||
|
|
||||||
const std::string MacroConditionSceneOrder::id = "scene_order";
|
const std::string MacroConditionSceneOrder::id = "scene_order";
|
||||||
|
|
||||||
bool MacroConditionSceneOrder::_registered = MacroConditionFactory::Register(
|
bool MacroConditionSceneOrder::_registered = MacroConditionFactory::Register(
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user