mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-30 13:15:43 -05:00
Compare commits
114 Commits
websocket-
...
record-pat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a69e774c2 | ||
|
|
2389f37ed6 | ||
|
|
de20c93b14 | ||
|
|
b0d877db8c | ||
|
|
caf9e59475 | ||
|
|
5f6982b5bb | ||
|
|
ce399cc647 | ||
|
|
03f67534c7 | ||
|
|
246667e65e | ||
|
|
68fe7716e7 | ||
|
|
98cc710b4a | ||
|
|
c602c30c54 | ||
|
|
cc1b89fe1d | ||
|
|
1de4ef7ec2 | ||
|
|
e29060fdea | ||
|
|
a0e6e6f528 | ||
|
|
e30d5845fa | ||
|
|
d12911cd02 | ||
|
|
b8ecc40e8c | ||
|
|
8ec4849b1d | ||
|
|
e6e9f3a831 | ||
|
|
555f7c1381 | ||
|
|
f0f8b0fd92 | ||
|
|
661e83162f | ||
|
|
4606f80a9d | ||
|
|
9c109742fb | ||
|
|
b8b0682aaf | ||
|
|
f93175db77 | ||
|
|
8f92ba3ffa | ||
|
|
0d56de11d1 | ||
|
|
e1020a1909 | ||
|
|
8b0bd4193b | ||
|
|
d55bb6bc86 | ||
|
|
0583331bfd | ||
|
|
6932de866d | ||
|
|
00db0cf7c4 | ||
|
|
e9baf27ca2 | ||
|
|
b1a5db0c9c | ||
|
|
8f3b868fd9 | ||
|
|
b3bf89840b | ||
|
|
84f7d0d214 | ||
|
|
e1164c4fa3 | ||
|
|
4534b23bad | ||
|
|
5d6a693f36 | ||
|
|
a82662c8f4 | ||
|
|
602675b3b3 | ||
|
|
9551519cb9 | ||
|
|
badce063eb | ||
|
|
10d45c67d6 | ||
|
|
0b77ef5081 | ||
|
|
8f54e71e61 | ||
|
|
16136b8741 | ||
|
|
02d5051974 | ||
|
|
078d62fa18 | ||
|
|
8aa6a7df2c | ||
|
|
1494b1db6c | ||
|
|
b4b3dc5a2b | ||
|
|
ee41a8d58b | ||
|
|
5f2237ac2a | ||
|
|
6fb76e7e07 | ||
|
|
ba094372a9 | ||
|
|
0c886c8679 | ||
|
|
d9f05d3f7b | ||
|
|
c99b5f1feb | ||
|
|
a3b3cf9818 | ||
|
|
ca3bbf5660 | ||
|
|
18524761a6 | ||
|
|
85222aed33 | ||
|
|
84132f7c37 | ||
|
|
ead664763f | ||
|
|
a2fa16f2d7 | ||
|
|
75edcffac9 | ||
|
|
dd5bcf425a | ||
|
|
de32e1b18e | ||
|
|
1d412a818d | ||
|
|
c8e5b561ef | ||
|
|
a1702dc798 | ||
|
|
ae571583fc | ||
|
|
c4f70657d9 | ||
|
|
7901a988af | ||
|
|
d2b70bbc6b | ||
|
|
4d22a539f0 | ||
|
|
4e561320f7 | ||
|
|
0dfa4fe2c0 | ||
|
|
4cac4584f3 | ||
|
|
d20a975c4f | ||
|
|
756d7bbd3c | ||
|
|
395a18fa4c | ||
|
|
2ea00d94c5 | ||
|
|
058e941a46 | ||
|
|
ea4a951554 | ||
|
|
3c355ac6fe | ||
|
|
37606e274c | ||
|
|
3e8d6e103a | ||
|
|
4cae420ade | ||
|
|
b27a11931a | ||
|
|
92616bed6b | ||
|
|
b3f38851b6 | ||
|
|
bf7fe71ae3 | ||
|
|
12a6b26d9a | ||
|
|
373e74c080 | ||
|
|
f3e7eaf212 | ||
|
|
b036736547 | ||
|
|
817de13e9d | ||
|
|
0b774c171d | ||
|
|
be8f7bd70f | ||
|
|
5f963b5b7d | ||
|
|
c6155c9fea | ||
|
|
be809dbfab | ||
|
|
7478c149b3 | ||
|
|
f4eaa9785d | ||
|
|
49c0de3f1b | ||
|
|
101ef4e973 | ||
|
|
82568b23e8 |
@@ -22,7 +22,7 @@ runs:
|
|||||||
- name: Setup cmake
|
- name: Setup cmake
|
||||||
uses: jwlawson/actions-setup-cmake@v1.13
|
uses: jwlawson/actions-setup-cmake@v1.13
|
||||||
with:
|
with:
|
||||||
cmake-version: '3.24.x'
|
cmake-version: '3.x.x'
|
||||||
|
|
||||||
- name: Restore cached dependencies
|
- name: Restore cached dependencies
|
||||||
id: restore-cache
|
id: restore-cache
|
||||||
|
|||||||
44
.github/scripts/.build-deps.zsh
vendored
44
.github/scripts/.build-deps.zsh
vendored
@@ -394,8 +394,11 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
|||||||
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
pushd ${advss_dep_path}
|
|
||||||
log_info "Prepare openssl ..."
|
log_info "Prepare openssl ..."
|
||||||
|
rm -rf ${advss_dep_path}/openssl ${advss_dep_path}/openssl_build
|
||||||
|
mkdir ${advss_dep_path}/openssl_build
|
||||||
|
pushd ${advss_dep_path}/openssl_build
|
||||||
|
|
||||||
rm -rf openssl
|
rm -rf openssl
|
||||||
git clone https://github.com/openssl/openssl.git --branch openssl-3.1.2 --depth 1
|
git clone https://github.com/openssl/openssl.git --branch openssl-3.1.2 --depth 1
|
||||||
mv openssl openssl_x86
|
mv openssl openssl_x86
|
||||||
@@ -403,25 +406,27 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
|||||||
|
|
||||||
log_info "Building openssl x86 ..."
|
log_info "Building openssl x86 ..."
|
||||||
export MACOSX_DEPLOYMENT_TARGET=10.9
|
export MACOSX_DEPLOYMENT_TARGET=10.9
|
||||||
cd openssl_x86
|
pushd openssl_x86
|
||||||
./Configure darwin64-x86_64-cc shared
|
./Configure darwin64-x86_64-cc no-shared no-module no-zlib --prefix=${advss_dep_path}
|
||||||
make
|
make -j$(nproc)
|
||||||
|
popd
|
||||||
|
|
||||||
log_info "Building openssl arm ..."
|
log_info "Building openssl arm ..."
|
||||||
export MACOSX_DEPLOYMENT_TARGET=10.15
|
export MACOSX_DEPLOYMENT_TARGET=10.15
|
||||||
cd ../openssl_arm
|
pushd openssl_arm
|
||||||
./Configure enable-rc5 zlib darwin64-arm64-cc no-asm
|
./Configure enable-rc5 darwin64-arm64-cc no-shared no-module no-asm no-zlib --prefix=${advss_dep_path}
|
||||||
make
|
make -j$(nproc)
|
||||||
|
|
||||||
|
log_info "Install openssl ..."
|
||||||
|
make install
|
||||||
|
popd
|
||||||
|
|
||||||
log_info "Combine arm and x86 openssl binaries ..."
|
log_info "Combine arm and x86 openssl binaries ..."
|
||||||
cd ..
|
lipo -create openssl_x86/libcrypto.a openssl_arm/libcrypto.a -output ${advss_dep_path}/lib/libcrypto.a
|
||||||
mkdir openssl-combined
|
lipo -create openssl_x86/libssl.a openssl_arm/libssl.a -output ${advss_dep_path}/lib/libssl.a
|
||||||
lipo -create openssl_x86/libcrypto.a openssl_arm/libcrypto.a -output openssl-combined/libcrypto.a
|
|
||||||
lipo -create openssl_x86/libssl.a openssl_arm/libssl.a -output openssl-combined/libssl.a
|
|
||||||
|
|
||||||
log_info "Clean up openssl dir ..."
|
log_info "Clean up openssl dir ..."
|
||||||
mv openssl_x86 openssl
|
rm -rf openssl_x86 openssl_arm
|
||||||
rm -rf openssl_arm
|
|
||||||
popd
|
popd
|
||||||
|
|
||||||
pushd ${project_root}/deps/libusb
|
pushd ${project_root}/deps/libusb
|
||||||
@@ -439,14 +444,16 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
|||||||
mkdir ${project_root}/deps/libusb/out_x86
|
mkdir ${project_root}/deps/libusb/out_x86
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
./configure --host=x86_64-apple-darwin --prefix=${advss_dep_path}
|
./configure --host=x86_64-apple-darwin --prefix=${advss_dep_path}
|
||||||
make && make install
|
make -j$(nproc)
|
||||||
|
make install
|
||||||
|
|
||||||
log_info "Configure libusb arm ..."
|
log_info "Configure libusb arm ..."
|
||||||
make clean
|
make clean
|
||||||
rm -r ${project_root}/deps/libusb/out_x86
|
rm -r ${project_root}/deps/libusb/out_x86
|
||||||
mkdir ${project_root}/deps/libusb/out_x86
|
mkdir ${project_root}/deps/libusb/out_x86
|
||||||
./configure --host=aarch64-apple-darwin --prefix=${project_root}/deps/libusb/out_x86
|
./configure --host=aarch64-apple-darwin --prefix=${project_root}/deps/libusb/out_x86
|
||||||
make && make install
|
make -j$(nproc)
|
||||||
|
make install
|
||||||
|
|
||||||
log_info "Building libusb arm ..."
|
log_info "Building libusb arm ..."
|
||||||
make clean
|
make clean
|
||||||
@@ -459,7 +466,8 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
|||||||
export MACOSX_DEPLOYMENT_TARGET=10.15
|
export MACOSX_DEPLOYMENT_TARGET=10.15
|
||||||
mkdir ${project_root}/deps/libusb/out_arm
|
mkdir ${project_root}/deps/libusb/out_arm
|
||||||
./configure --host=aarch64-apple-darwin --prefix=${project_root}/deps/libusb/out_arm
|
./configure --host=aarch64-apple-darwin --prefix=${project_root}/deps/libusb/out_arm
|
||||||
make && make install
|
make -j$(nproc)
|
||||||
|
make install
|
||||||
|
|
||||||
log_info "Combine arm and x86 libusb binaries ..."
|
log_info "Combine arm and x86 libusb binaries ..."
|
||||||
lipo -create ${project_root}/deps/libusb/out_x86/lib/libusb-1.0.0.dylib \
|
lipo -create ${project_root}/deps/libusb/out_x86/lib/libusb-1.0.0.dylib \
|
||||||
@@ -491,8 +499,8 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
|||||||
-DPAHO_BUILD_SHARED=OFF
|
-DPAHO_BUILD_SHARED=OFF
|
||||||
-DPAHO_BUILD_STATIC=ON
|
-DPAHO_BUILD_STATIC=ON
|
||||||
-DPAHO_WITH_MQTT_C=ON
|
-DPAHO_WITH_MQTT_C=ON
|
||||||
-DOPENSSL_ROOT_DIR="${advss_dep_path}"
|
-DPAHO_WITH_SSL=ON
|
||||||
-DPAHO_WITH_SSL=OFF # TODO: figure out linking issues with openssl
|
-DOPENSSL_USE_STATIC_LIBS=ON
|
||||||
)
|
)
|
||||||
|
|
||||||
pushd ${mqtt_dir}
|
pushd ${mqtt_dir}
|
||||||
|
|||||||
6
.github/scripts/.build.zsh
vendored
6
.github/scripts/.build.zsh
vendored
@@ -253,12 +253,8 @@ ${_usage_host:-}"
|
|||||||
macos-*)
|
macos-*)
|
||||||
if (( ${+CI} )) typeset -gx NSUnbufferedIO=YES
|
if (( ${+CI} )) typeset -gx NSUnbufferedIO=YES
|
||||||
|
|
||||||
local openssl_lib_dir="${advss_deps_path}/openssl-combined/"
|
|
||||||
local openssl_include_dir="${advss_deps_path}/openssl/include"
|
|
||||||
|
|
||||||
cmake_args+=(
|
cmake_args+=(
|
||||||
-DOPENSSL_INCLUDE_DIR="${openssl_include_dir}"
|
-DCMAKE_PREFIX_PATH="${advss_deps_path}"
|
||||||
-DOPENSSL_LIBRARIES="${openssl_lib_dir}/libcrypto.a;${openssl_lib_dir}/libssl.a"
|
|
||||||
--preset ${_preset}
|
--preset ${_preset}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
3
.github/scripts/.package.zsh
vendored
3
.github/scripts/.package.zsh
vendored
@@ -258,6 +258,9 @@ ${_usage_host:-}"
|
|||||||
pushd ${project_root}
|
pushd ${project_root}
|
||||||
cmake --build build_${target##*-} --config ${config} -t package ${cmake_args}
|
cmake --build build_${target##*-} --config ${config} -t package ${cmake_args}
|
||||||
|
|
||||||
|
# Mark certain deps as optional
|
||||||
|
build-aux/CI/linux/demote-deps.sh ${project_root}/release/*.deb Recommends '(mqtt)|(opencv)|(tesseract)|(usb)|(x11)'
|
||||||
|
|
||||||
if [ ! -e ${project_root}/release/${output_name}.deb ]; then
|
if [ ! -e ${project_root}/release/${output_name}.deb ]; then
|
||||||
mv ${project_root}/release/*.deb ${project_root}/release/${output_name}.deb
|
mv ${project_root}/release/*.deb ${project_root}/release/${output_name}.deb
|
||||||
mv ${project_root}/release/*.ddeb ${project_root}/release/${output_name}.ddeb
|
mv ${project_root}/release/*.ddeb ${project_root}/release/${output_name}.ddeb
|
||||||
|
|||||||
18
.github/scripts/Build-Deps-Windows.ps1
vendored
18
.github/scripts/Build-Deps-Windows.ps1
vendored
@@ -209,7 +209,9 @@ function Build {
|
|||||||
$msbuildExe = vswhere -latest -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe | select-object -first 1
|
$msbuildExe = vswhere -latest -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe | select-object -first 1
|
||||||
|
|
||||||
if ($msbuildExe) {
|
if ($msbuildExe) {
|
||||||
|
$env:CL="/wd5287"
|
||||||
Invoke-External $msbuildExe "${LibusbPath}/msvc/libusb.sln" /property:Configuration=Release /property:Platform=x64
|
Invoke-External $msbuildExe "${LibusbPath}/msvc/libusb.sln" /property:Configuration=Release /property:Platform=x64
|
||||||
|
Remove-Item Env:CL
|
||||||
|
|
||||||
$libusbBuildResultDirectory = "${LibusbPath}/build/v143/x64/Release"
|
$libusbBuildResultDirectory = "${LibusbPath}/build/v143/x64/Release"
|
||||||
if (-not (Test-Path -Path $libusbBuildResultDirectory)) {
|
if (-not (Test-Path -Path $libusbBuildResultDirectory)) {
|
||||||
@@ -232,8 +234,24 @@ function Build {
|
|||||||
"-DCMAKE_PREFIX_PATH:PATH=${OBSDepPath}"
|
"-DCMAKE_PREFIX_PATH:PATH=${OBSDepPath}"
|
||||||
"-DCMAKE_INSTALL_PREFIX:PATH=${ADVSSDepPath}"
|
"-DCMAKE_INSTALL_PREFIX:PATH=${ADVSSDepPath}"
|
||||||
"-DPAHO_WITH_MQTT_C=ON"
|
"-DPAHO_WITH_MQTT_C=ON"
|
||||||
|
"-DPAHO_WITH_SSL=ON"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Try to find OpenSSL installed via winget
|
||||||
|
$pf64 = Join-Path $Env:ProgramFiles "OpenSSL-Win64"
|
||||||
|
$pf = Join-Path $Env:ProgramFiles "OpenSSL"
|
||||||
|
$possibleDirs = @($pf64, $pf)
|
||||||
|
$opensslDir = $possibleDirs | Where-Object { Test-Path (Join-Path $_ "include\openssl\ssl.h") } | Select-Object -First 1
|
||||||
|
|
||||||
|
if ($opensslDir) {
|
||||||
|
Write-Host "Detected OpenSSL at: $opensslDir"
|
||||||
|
$MqttCmakeArgs += "-DOPENSSL_ROOT_DIR=$opensslDir"
|
||||||
|
$MqttCmakeArgs += "-DOPENSSL_CRYPTO_LIBRARY=$opensslDir\lib\VC\x64\MD\libcrypto.lib"
|
||||||
|
$MqttCmakeArgs += "-DOPENSSL_SSL_LIBRARY=$opensslDir\lib\VC\x64\MD\libssl.lib"
|
||||||
|
} else {
|
||||||
|
Write-Warning "OpenSSL not found - maybe cmake will find it ..."
|
||||||
|
}
|
||||||
|
|
||||||
Log-Information "Configuring paho.mqtt.cpp..."
|
Log-Information "Configuring paho.mqtt.cpp..."
|
||||||
Invoke-External cmake -S ${MqttPath} -B ${MqttBuildPath} @MqttCmakeArgs
|
Invoke-External cmake -S ${MqttPath} -B ${MqttBuildPath} @MqttCmakeArgs
|
||||||
|
|
||||||
|
|||||||
4
.github/scripts/utils.zsh/check_macos
vendored
4
.github/scripts/utils.zsh/check_macos
vendored
@@ -18,5 +18,7 @@ if (( ! ${+commands[brew]} )) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
brew bundle --file ${SCRIPT_HOME}/.Brewfile
|
brew bundle --file ${SCRIPT_HOME}/.Brewfile
|
||||||
rehash
|
# Workaround to make sure locally built openssl is picked up by cmake
|
||||||
|
brew uninstall --ignore-dependencies openssl@3 || true
|
||||||
|
rehash || true
|
||||||
log_group
|
log_group
|
||||||
|
|||||||
1
.github/scripts/utils.zsh/setup_ccache
vendored
1
.github/scripts/utils.zsh/setup_ccache
vendored
@@ -10,7 +10,6 @@ if (( ${+commands[ccache]} )) {
|
|||||||
|
|
||||||
typeset -gx CCACHE_CONFIGPATH="${project_root}/.ccache.conf"
|
typeset -gx CCACHE_CONFIGPATH="${project_root}/.ccache.conf"
|
||||||
|
|
||||||
ccache --set-config=run_second_cpp=true
|
|
||||||
ccache --set-config=direct_mode=true
|
ccache --set-config=direct_mode=true
|
||||||
ccache --set-config=inode_cache=true
|
ccache --set-config=inode_cache=true
|
||||||
ccache --set-config=compiler_check=content
|
ccache --set-config=compiler_check=content
|
||||||
|
|||||||
1
.github/scripts/utils.zsh/setup_linux
vendored
1
.github/scripts/utils.zsh/setup_linux
vendored
@@ -41,6 +41,7 @@ if (( ! (${skips[(Ie)all]} + ${skips[(Ie)deps]}) )) {
|
|||||||
sudo apt-get install ${apt_args} \
|
sudo apt-get install ${apt_args} \
|
||||||
build-essential \
|
build-essential \
|
||||||
libgles2-mesa-dev \
|
libgles2-mesa-dev \
|
||||||
|
libsimde-dev \
|
||||||
obs-studio
|
obs-studio
|
||||||
|
|
||||||
local -a _qt_packages=()
|
local -a _qt_packages=()
|
||||||
|
|||||||
10
.github/workflows/build-project.yaml
vendored
10
.github/workflows/build-project.yaml
vendored
@@ -6,7 +6,7 @@ on:
|
|||||||
description: "Project name detected by parsing build spec file"
|
description: "Project name detected by parsing build spec file"
|
||||||
value: ${{ jobs.check-event.outputs.pluginName }}
|
value: ${{ jobs.check-event.outputs.pluginName }}
|
||||||
env:
|
env:
|
||||||
DEP_DIR: .deps/advss-build-dependencies
|
DEP_DIR: .deps/advss-build-dependencies-3
|
||||||
jobs:
|
jobs:
|
||||||
check-event:
|
check-event:
|
||||||
name: Check GitHub Event Data 🔎
|
name: Check GitHub Event Data 🔎
|
||||||
@@ -75,7 +75,7 @@ jobs:
|
|||||||
|
|
||||||
macos-build:
|
macos-build:
|
||||||
name: Build for macOS 🍏
|
name: Build for macOS 🍏
|
||||||
runs-on: macos-14
|
runs-on: macos-15
|
||||||
needs: check-event
|
needs: check-event
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
@@ -107,8 +107,8 @@ jobs:
|
|||||||
print "pluginName=${product_name}" >> $GITHUB_OUTPUT
|
print "pluginName=${product_name}" >> $GITHUB_OUTPUT
|
||||||
print "pluginVersion=${git_tag}" >> $GITHUB_OUTPUT
|
print "pluginVersion=${git_tag}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
print '::group::Enable Xcode 15.2'
|
print '::group::Enable Xcode 16.1'
|
||||||
sudo xcode-select --switch /Applications/Xcode_15.2.app/Contents/Developer
|
sudo xcode-select --switch /Applications/Xcode_16.1.0.app/Contents/Developer
|
||||||
print '::endgroup::'
|
print '::endgroup::'
|
||||||
|
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v4
|
||||||
@@ -213,7 +213,7 @@ jobs:
|
|||||||
- name: Set up CMake 🏗️
|
- name: Set up CMake 🏗️
|
||||||
uses: jwlawson/actions-setup-cmake@v1.13
|
uses: jwlawson/actions-setup-cmake@v1.13
|
||||||
with:
|
with:
|
||||||
cmake-version: '3.24.x'
|
cmake-version: '3.x.x'
|
||||||
|
|
||||||
- name: Set up Homebrew 🍺
|
- name: Set up Homebrew 🍺
|
||||||
uses: Homebrew/actions/setup-homebrew@master
|
uses: Homebrew/actions/setup-homebrew@master
|
||||||
|
|||||||
@@ -34,6 +34,11 @@ include(cmake/common/get_git_revision_description.cmake)
|
|||||||
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
get_git_head_revision(GIT_REFSPEC GIT_SHA1)
|
||||||
git_describe(GIT_TAG)
|
git_describe(GIT_TAG)
|
||||||
|
|
||||||
|
# Helper for OpenSSL
|
||||||
|
if(OS_WINDOWS)
|
||||||
|
include(cmake/windows/wingetssl.cmake)
|
||||||
|
endif()
|
||||||
|
|
||||||
if(${GIT_TAG} STREQUAL "GIT-NOTFOUND")
|
if(${GIT_TAG} STREQUAL "GIT-NOTFOUND")
|
||||||
set(GIT_TAG ${PROJECT_VERSION})
|
set(GIT_TAG ${PROJECT_VERSION})
|
||||||
endif()
|
endif()
|
||||||
@@ -123,6 +128,12 @@ target_sources(
|
|||||||
lib/macro/macro-condition.hpp
|
lib/macro/macro-condition.hpp
|
||||||
lib/macro/macro-dock.cpp
|
lib/macro/macro-dock.cpp
|
||||||
lib/macro/macro-dock.hpp
|
lib/macro/macro-dock.hpp
|
||||||
|
lib/macro/macro-dock-settings.hpp
|
||||||
|
lib/macro/macro-dock-settings.cpp
|
||||||
|
lib/macro/macro-dock-window.cpp
|
||||||
|
lib/macro/macro-dock-window.hpp
|
||||||
|
lib/macro/macro-edit.cpp
|
||||||
|
lib/macro/macro-edit.hpp
|
||||||
lib/macro/macro-export-import-dialog.cpp
|
lib/macro/macro-export-import-dialog.cpp
|
||||||
lib/macro/macro-export-import-dialog.hpp
|
lib/macro/macro-export-import-dialog.hpp
|
||||||
lib/macro/macro-helpers.cpp
|
lib/macro/macro-helpers.cpp
|
||||||
@@ -135,18 +146,23 @@ target_sources(
|
|||||||
lib/macro/macro-ref.hpp
|
lib/macro/macro-ref.hpp
|
||||||
lib/macro/macro-run-button.cpp
|
lib/macro/macro-run-button.cpp
|
||||||
lib/macro/macro-run-button.hpp
|
lib/macro/macro-run-button.hpp
|
||||||
|
lib/macro/macro-search.cpp
|
||||||
|
lib/macro/macro-search.hpp
|
||||||
lib/macro/macro-segment-copy-paste.cpp
|
lib/macro/macro-segment-copy-paste.cpp
|
||||||
lib/macro/macro-segment-copy-paste.hpp
|
lib/macro/macro-segment-copy-paste.hpp
|
||||||
lib/macro/macro-segment-list.cpp
|
lib/macro/macro-segment-list.cpp
|
||||||
lib/macro/macro-segment-list.hpp
|
lib/macro/macro-segment-list.hpp
|
||||||
lib/macro/macro-segment-selection.cpp
|
lib/macro/macro-segment-selection.cpp
|
||||||
lib/macro/macro-segment-selection.hpp
|
lib/macro/macro-segment-selection.hpp
|
||||||
|
lib/macro/macro-segment-unknown.hpp
|
||||||
lib/macro/macro-segment.cpp
|
lib/macro/macro-segment.cpp
|
||||||
lib/macro/macro-segment.hpp
|
lib/macro/macro-segment.hpp
|
||||||
lib/macro/macro-selection.cpp
|
lib/macro/macro-selection.cpp
|
||||||
lib/macro/macro-selection.hpp
|
lib/macro/macro-selection.hpp
|
||||||
lib/macro/macro-settings.cpp
|
lib/macro/macro-settings.cpp
|
||||||
lib/macro/macro-settings.hpp
|
lib/macro/macro-settings.hpp
|
||||||
|
lib/macro/macro-signals.cpp
|
||||||
|
lib/macro/macro-signals.hpp
|
||||||
lib/macro/macro-tab.cpp
|
lib/macro/macro-tab.cpp
|
||||||
lib/macro/macro-tree.cpp
|
lib/macro/macro-tree.cpp
|
||||||
lib/macro/macro-tree.hpp
|
lib/macro/macro-tree.hpp
|
||||||
@@ -164,6 +180,8 @@ target_sources(
|
|||||||
lib/utils/auto-update-tooltip-label.hpp
|
lib/utils/auto-update-tooltip-label.hpp
|
||||||
lib/utils/backup.cpp
|
lib/utils/backup.cpp
|
||||||
lib/utils/backup.hpp
|
lib/utils/backup.hpp
|
||||||
|
lib/utils/canvas-helpers.cpp
|
||||||
|
lib/utils/canvas-helpers.hpp
|
||||||
lib/utils/condition-logic.cpp
|
lib/utils/condition-logic.cpp
|
||||||
lib/utils/condition-logic.hpp
|
lib/utils/condition-logic.hpp
|
||||||
lib/utils/curl-helper.cpp
|
lib/utils/curl-helper.cpp
|
||||||
@@ -217,6 +235,8 @@ target_sources(
|
|||||||
lib/utils/priority-helper.hpp
|
lib/utils/priority-helper.hpp
|
||||||
lib/utils/regex-config.cpp
|
lib/utils/regex-config.cpp
|
||||||
lib/utils/regex-config.hpp
|
lib/utils/regex-config.hpp
|
||||||
|
lib/utils/resizable-widget.cpp
|
||||||
|
lib/utils/resizable-widget.hpp
|
||||||
lib/utils/resizing-text-edit.cpp
|
lib/utils/resizing-text-edit.cpp
|
||||||
lib/utils/resizing-text-edit.hpp
|
lib/utils/resizing-text-edit.hpp
|
||||||
lib/utils/resource-table.cpp
|
lib/utils/resource-table.cpp
|
||||||
|
|||||||
126
build-aux/CI/linux/demote-deps.sh
Executable file
126
build-aux/CI/linux/demote-deps.sh
Executable file
@@ -0,0 +1,126 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# Usage: demote_deps.sh <in.deb> [Recommends|Suggests] [regex]
|
||||||
|
# Example: demote_deps.sh build/advanced-scene-switcher_1.31.0_amd64.deb Recommends 'opencv'
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [[ $# -lt 1 ]]; then
|
||||||
|
echo "Usage: $0 <in.deb> [Recommends|Suggests] [regex]" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
IN_DEB="$1"
|
||||||
|
DEST_FIELD="${2:-Recommends}" # Recommends or Suggests
|
||||||
|
MATCH_REGEX="${3:-opencv}" # regex to match packages to demote
|
||||||
|
|
||||||
|
echo "Demoting dependencies matching '${MATCH_REGEX}' to ${DEST_FIELD}"
|
||||||
|
|
||||||
|
TMPDIR="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$TMPDIR"' EXIT
|
||||||
|
|
||||||
|
dpkg-deb -R "$IN_DEB" "$TMPDIR"
|
||||||
|
CONTROL="$TMPDIR/DEBIAN/control"
|
||||||
|
|
||||||
|
# Read a field (single line value), handling continuation lines starting with a space.
|
||||||
|
get_field() {
|
||||||
|
local key="$1"
|
||||||
|
awk -v key="$key" '
|
||||||
|
BEGIN { val=""; collecting=0 }
|
||||||
|
$0 ~ "^" key ":" {
|
||||||
|
collecting=1
|
||||||
|
sub("^" key ":[[:space:]]*", "", $0)
|
||||||
|
val=$0
|
||||||
|
next
|
||||||
|
}
|
||||||
|
collecting==1 {
|
||||||
|
if ($0 ~ "^[[:space:]]") {
|
||||||
|
sub("^[[:space:]]+", "", $0)
|
||||||
|
val = val " " $0
|
||||||
|
next
|
||||||
|
} else {
|
||||||
|
collecting=0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
END { print val }
|
||||||
|
' "$CONTROL"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Split a comma-separated list into lines, trimming whitespace
|
||||||
|
split_csv() {
|
||||||
|
tr ',' '\n' | sed -E 's/^[[:space:]]+//; s/[[:space:]]+$//' | sed '/^$/d'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Join with ", "
|
||||||
|
join_csv() {
|
||||||
|
awk 'BEGIN{first=1}{ if(!first) printf(", "); printf("%s",$0); first=0 } END{print ""}'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Deduplicate while preserving order
|
||||||
|
dedup() {
|
||||||
|
awk '!seen[$0]++'
|
||||||
|
}
|
||||||
|
|
||||||
|
DEPENDS_VAL="$(get_field Depends)"
|
||||||
|
EXIST_DEST_VAL="$(get_field "$DEST_FIELD")"
|
||||||
|
|
||||||
|
# Separate opencv-matching vs the rest (preserve tokens exactly)
|
||||||
|
mapfile -t DEPENDS_ARR < <(printf "%s\n" "$DEPENDS_VAL" | split_csv)
|
||||||
|
declare -a MOVED=()
|
||||||
|
declare -a KEPT=()
|
||||||
|
for item in "${DEPENDS_ARR[@]}"; do
|
||||||
|
# Skip empty just in case
|
||||||
|
[[ -z "$item" ]] && continue
|
||||||
|
if [[ "$item" =~ $MATCH_REGEX ]]; then
|
||||||
|
MOVED+=("$item")
|
||||||
|
else
|
||||||
|
KEPT+=("$item")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Merge with existing dest field
|
||||||
|
if [[ -n "$EXIST_DEST_VAL" ]]; then
|
||||||
|
mapfile -t EXIST_DEST_ARR < <(printf "%s\n" "$EXIST_DEST_VAL" | split_csv)
|
||||||
|
MOVED+=("${EXIST_DEST_ARR[@]}")
|
||||||
|
fi
|
||||||
|
|
||||||
|
# De-duplicate
|
||||||
|
mapfile -t MOVED < <(printf "%s\n" "${MOVED[@]:-}" | sed '/^$/d' | dedup)
|
||||||
|
mapfile -t KEPT < <(printf "%s\n" "${KEPT[@]:-}" | sed '/^$/d' | dedup)
|
||||||
|
|
||||||
|
# Rebuild values
|
||||||
|
NEW_DEPENDS="$(printf "%s\n" "${KEPT[@]:-}" | join_csv || true)"
|
||||||
|
NEW_DEST="$(printf "%s\n" "${MOVED[@]:-}" | join_csv || true)"
|
||||||
|
|
||||||
|
# Write a cleaned control (remove existing Depends/Recommends/Suggests incl. continuations)
|
||||||
|
awk '
|
||||||
|
BEGIN { skip=0 }
|
||||||
|
{
|
||||||
|
if ($0 ~ "^(Depends|Recommends|Suggests):") { skip=1; next }
|
||||||
|
if (skip==1) {
|
||||||
|
if ($0 ~ "^[[:space:]]") { next } else { skip=0 }
|
||||||
|
}
|
||||||
|
print
|
||||||
|
}
|
||||||
|
' "$CONTROL" > "$CONTROL.clean"
|
||||||
|
|
||||||
|
# Append the rebuilt fields
|
||||||
|
{
|
||||||
|
cat "$CONTROL.clean"
|
||||||
|
if [[ -n "$NEW_DEPENDS" ]]; then
|
||||||
|
echo "Depends: $NEW_DEPENDS"
|
||||||
|
fi
|
||||||
|
if [[ -n "$NEW_DEST" ]]; then
|
||||||
|
echo "$DEST_FIELD: $NEW_DEST"
|
||||||
|
fi
|
||||||
|
} > "$CONTROL.new"
|
||||||
|
|
||||||
|
# Clean up empty lines
|
||||||
|
sed -i '/^[[:space:]]*$/d' "$CONTROL.new"
|
||||||
|
|
||||||
|
mv "$CONTROL.new" "$CONTROL"
|
||||||
|
rm -f "$CONTROL.clean"
|
||||||
|
|
||||||
|
# Repack
|
||||||
|
rm -f "${IN_DEB}"
|
||||||
|
OUT_DEB="${IN_DEB}"
|
||||||
|
dpkg-deb -b "$TMPDIR" "$OUT_DEB" >/dev/null
|
||||||
|
echo "$OUT_DEB"
|
||||||
@@ -1,33 +1,33 @@
|
|||||||
{
|
{
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"obs-studio": {
|
"obs-studio": {
|
||||||
"version": "30.1.2",
|
"version": "31.1.1",
|
||||||
"baseUrl": "https://github.com/obsproject/obs-studio/archive/refs/tags",
|
"baseUrl": "https://github.com/obsproject/obs-studio/archive/refs/tags",
|
||||||
"label": "OBS sources",
|
"label": "OBS sources",
|
||||||
"hashes": {
|
"hashes": {
|
||||||
"macos": "490bae1c392b3b344b0270afd8cb887da4bc50bd92c0c426e96713c1ccb9701a",
|
"macos": "39751f067bacc13d44b116c5138491b5f1391f91516d3d590d874edd21292291",
|
||||||
"windows-x64": "c2dd03fa7fd01fad5beafce8f7156da11f9ed9a588373fd40b44a06f4c03b867"
|
"windows-x64": "2c8427c10b55ac6d68008df2e9a3e82f4647aaad18f105e30d4713c2de678ccf"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"prebuilt": {
|
"prebuilt": {
|
||||||
"version": "2024-03-19",
|
"version": "2025-07-11",
|
||||||
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
|
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
|
||||||
"label": "Pre-Built obs-deps",
|
"label": "Pre-Built obs-deps",
|
||||||
"hashes": {
|
"hashes": {
|
||||||
"macos": "2e9bfb55a5e0e4c1086fa1fda4cf268debfead473089df2aaea80e1c7a3ca7ff",
|
"macos": "495687e63383d1a287684b6e2e9bfe246bb8f156fe265926afb1a325af1edd2a",
|
||||||
"windows-x64": "6e86068371526a967e805f6f9903f9407adb683c21820db5f07da8f30d11e998"
|
"windows-x64": "c8c642c1070dc31ce9a0f1e4cef5bb992f4bff4882255788b5da12129e85caa7"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"qt6": {
|
"qt6": {
|
||||||
"version": "2024-03-19",
|
"version": "2025-07-11",
|
||||||
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
|
"baseUrl": "https://github.com/obsproject/obs-deps/releases/download",
|
||||||
"label": "Pre-Built Qt6",
|
"label": "Pre-Built Qt6",
|
||||||
"hashes": {
|
"hashes": {
|
||||||
"macos": "694f1e639c017e3b1f456f735330dc5afae287cbea85757101af1368de3142c8",
|
"macos": "d3f5f04b6ea486e032530bdf0187cbda9a54e0a49621a4c8ba984c5023998867",
|
||||||
"windows-x64": "72d1df34a0ef7413a681d5fcc88cae81da60adc03dcd23ef17862ab170bcc0dd"
|
"windows-x64": "0e76bf0555dd5382838850b748d3dcfab44a1e1058441309ab54e1a65b156d0a"
|
||||||
},
|
},
|
||||||
"debugSymbols": {
|
"debugSymbols": {
|
||||||
"windows-x64": "fbddd1f659c360f2291911ac5709b67b6f8182e6bca519d24712e4f6fd3cc865"
|
"windows-x64": "11b7be92cf66a273299b8f3515c07a5cfb61614b59a4e67f7fc5ecba5e2bdf21"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -65,17 +65,16 @@ function(_setup_obs_studio)
|
|||||||
|
|
||||||
if(OS_WINDOWS)
|
if(OS_WINDOWS)
|
||||||
set(_cmake_generator "${CMAKE_GENERATOR}")
|
set(_cmake_generator "${CMAKE_GENERATOR}")
|
||||||
set(_cmake_arch "-A ${arch}")
|
set(_cmake_arch
|
||||||
|
"-A ${arch},version=${CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION}")
|
||||||
set(_cmake_extra
|
set(_cmake_extra
|
||||||
"-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION} -DCMAKE_ENABLE_SCRIPTING=OFF"
|
"-DCMAKE_SYSTEM_VERSION=${CMAKE_SYSTEM_VERSION} -DCMAKE_ENABLE_SCRIPTING=OFF"
|
||||||
)
|
)
|
||||||
set(_cmake_version "2.0.0")
|
|
||||||
elseif(OS_MACOS)
|
elseif(OS_MACOS)
|
||||||
set(_cmake_generator "Xcode")
|
set(_cmake_generator "Xcode")
|
||||||
set(_cmake_arch "-DCMAKE_OSX_ARCHITECTURES:STRING='arm64;x86_64'")
|
set(_cmake_arch "-DCMAKE_OSX_ARCHITECTURES:STRING='arm64;x86_64'")
|
||||||
set(_cmake_extra
|
set(_cmake_extra
|
||||||
"-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")
|
"-DCMAKE_OSX_DEPLOYMENT_TARGET=${CMAKE_OSX_DEPLOYMENT_TARGET}")
|
||||||
set(_cmake_version "3.0.0")
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message(STATUS "Configure ${label} (${arch})")
|
message(STATUS "Configure ${label} (${arch})")
|
||||||
@@ -83,32 +82,42 @@ function(_setup_obs_studio)
|
|||||||
COMMAND
|
COMMAND
|
||||||
"${CMAKE_COMMAND}" -S "${dependencies_dir}/${_obs_destination}" -B
|
"${CMAKE_COMMAND}" -S "${dependencies_dir}/${_obs_destination}" -B
|
||||||
"${dependencies_dir}/${_obs_destination}/build_${arch}" -G
|
"${dependencies_dir}/${_obs_destination}/build_${arch}" -G
|
||||||
${_cmake_generator} "${_cmake_arch}"
|
${_cmake_generator} "${_cmake_arch}" -DOBS_CMAKE_VERSION:STRING=3.0.0
|
||||||
-DOBS_CMAKE_VERSION:STRING=${_cmake_version} -DENABLE_PLUGINS:BOOL=OFF
|
-DENABLE_PLUGINS:BOOL=OFF -DENABLE_FRONTEND:BOOL=OFF
|
||||||
-DENABLE_UI:BOOL=OFF -DOBS_VERSION_OVERRIDE:STRING=${_obs_version}
|
-DOBS_VERSION_OVERRIDE:STRING=${_obs_version}
|
||||||
"-DCMAKE_PREFIX_PATH='${CMAKE_PREFIX_PATH}'" ${_is_fresh} ${_cmake_extra}
|
"-DCMAKE_PREFIX_PATH='${CMAKE_PREFIX_PATH}'" ${_is_fresh} ${_cmake_extra}
|
||||||
RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
|
RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
|
||||||
OUTPUT_QUIET)
|
OUTPUT_QUIET)
|
||||||
message(STATUS "Configure ${label} (${arch}) - done")
|
message(STATUS "Configure ${label} (${arch}) - done")
|
||||||
|
|
||||||
message(STATUS "Build ${label} (${arch})")
|
message(STATUS "Build ${label} (Debug - ${arch})")
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND "${CMAKE_COMMAND}" --build build_${arch} --target obs-frontend-api
|
COMMAND "${CMAKE_COMMAND}" --build build_${arch} --target obs-frontend-api
|
||||||
--config Debug --parallel
|
--config Debug --parallel
|
||||||
WORKING_DIRECTORY "${dependencies_dir}/${_obs_destination}"
|
WORKING_DIRECTORY "${dependencies_dir}/${_obs_destination}"
|
||||||
RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
|
RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
|
||||||
OUTPUT_QUIET)
|
OUTPUT_QUIET)
|
||||||
message(STATUS "Build ${label} (${arch}) - done")
|
message(STATUS "Build ${label} (Debug - ${arch}) - done")
|
||||||
|
|
||||||
|
message(STATUS "Build ${label} (Release - ${arch})")
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${CMAKE_COMMAND}" --build build_${arch} --target obs-frontend-api
|
||||||
|
--config Release --parallel
|
||||||
|
WORKING_DIRECTORY "${dependencies_dir}/${_obs_destination}"
|
||||||
|
RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
|
||||||
|
OUTPUT_QUIET)
|
||||||
|
message(STATUS "Build ${label} (Reelase - ${arch}) - done")
|
||||||
|
|
||||||
message(STATUS "Install ${label} (${arch})")
|
message(STATUS "Install ${label} (${arch})")
|
||||||
if(OS_WINDOWS)
|
|
||||||
set(_cmake_extra "--component obs_libraries")
|
|
||||||
else()
|
|
||||||
set(_cmake_extra "")
|
|
||||||
endif()
|
|
||||||
execute_process(
|
execute_process(
|
||||||
COMMAND "${CMAKE_COMMAND}" --install build_${arch} --component Development
|
COMMAND "${CMAKE_COMMAND}" --install build_${arch} --component Development
|
||||||
--config Debug --prefix "${dependencies_dir}" ${_cmake_extra}
|
--config Debug --prefix "${dependencies_dir}"
|
||||||
|
WORKING_DIRECTORY "${dependencies_dir}/${_obs_destination}"
|
||||||
|
RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
|
||||||
|
OUTPUT_QUIET)
|
||||||
|
execute_process(
|
||||||
|
COMMAND "${CMAKE_COMMAND}" --install build_${arch} --component Development
|
||||||
|
--config Release --prefix "${dependencies_dir}"
|
||||||
WORKING_DIRECTORY "${dependencies_dir}/${_obs_destination}"
|
WORKING_DIRECTORY "${dependencies_dir}/${_obs_destination}"
|
||||||
RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
|
RESULT_VARIABLE _process_result COMMAND_ERROR_IS_FATAL ANY
|
||||||
OUTPUT_QUIET)
|
OUTPUT_QUIET)
|
||||||
@@ -171,24 +180,46 @@ function(_check_dependencies)
|
|||||||
set(url ${url}/${version}/${file})
|
set(url ${url}/${version}/${file})
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
set(MAX_DOWNLOAD_RETRIES 3)
|
||||||
|
set(RETRY_DELAY 60) # seconds
|
||||||
|
|
||||||
if(NOT EXISTS "${dependencies_dir}/${file}")
|
if(NOT EXISTS "${dependencies_dir}/${file}")
|
||||||
message(STATUS "Downloading ${url}")
|
message(STATUS "Downloading ${url}")
|
||||||
file(
|
|
||||||
DOWNLOAD "${url}" "${dependencies_dir}/${file}"
|
|
||||||
STATUS download_status
|
|
||||||
EXPECTED_HASH SHA256=${hash})
|
|
||||||
|
|
||||||
list(GET download_status 0 error_code)
|
set(download_success FALSE)
|
||||||
list(GET download_status 1 error_message)
|
|
||||||
if(error_code GREATER 0)
|
foreach(i RANGE 1 ${MAX_DOWNLOAD_RETRIES})
|
||||||
message(STATUS "Downloading ${url} - Failure")
|
message(STATUS "Attempt ${i}/${MAX_DOWNLOAD_RETRIES} for ${url}")
|
||||||
|
|
||||||
|
file(
|
||||||
|
DOWNLOAD "${url}" "${dependencies_dir}/${file}"
|
||||||
|
STATUS download_status
|
||||||
|
EXPECTED_HASH SHA256=${hash})
|
||||||
|
|
||||||
|
list(GET download_status 0 error_code)
|
||||||
|
list(GET download_status 1 error_message)
|
||||||
|
|
||||||
|
if(error_code EQUAL 0)
|
||||||
|
message(STATUS "Downloading ${url} - success on attempt ${i}")
|
||||||
|
set(download_success TRUE)
|
||||||
|
break()
|
||||||
|
else()
|
||||||
|
message(WARNING "Download failed (attempt ${i}): ${error_message}")
|
||||||
|
file(REMOVE "${dependencies_dir}/${file}")
|
||||||
|
|
||||||
|
if(NOT i EQUAL MAX_DOWNLOAD_RETRIES)
|
||||||
|
message(STATUS "Retrying in ${RETRY_DELAY} seconds...")
|
||||||
|
execute_process(COMMAND ${CMAKE_COMMAND} -E sleep ${RETRY_DELAY})
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if(NOT download_success)
|
||||||
message(
|
message(
|
||||||
FATAL_ERROR
|
FATAL_ERROR
|
||||||
"Unable to download ${url}, failed with error: ${error_message}")
|
"Unable to download ${url} after ${MAX_DOWNLOAD_RETRIES} attempts")
|
||||||
file(REMOVE "${dependencies_dir}/${file}")
|
|
||||||
else()
|
|
||||||
message(STATUS "Downloading ${url} - done")
|
|
||||||
endif()
|
endif()
|
||||||
|
message(STATUS "Downloading ${url} - done")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT EXISTS "${dependencies_dir}/${destination}")
|
if(NOT EXISTS "${dependencies_dir}/${destination}")
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ SolidCompression=yes
|
|||||||
DirExistsWarning=no
|
DirExistsWarning=no
|
||||||
SetupIconFile=installer.ico
|
SetupIconFile=installer.ico
|
||||||
UninstallDisplayIcon={app}\data\obs-plugins\advanced-scene-switcher\res\images\logo.ico
|
UninstallDisplayIcon={app}\data\obs-plugins\advanced-scene-switcher\res\images\logo.ico
|
||||||
|
DisableDirPage=no
|
||||||
|
|
||||||
[Languages]
|
[Languages]
|
||||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||||
|
|||||||
78
cmake/windows/wingetssl.cmake
Normal file
78
cmake/windows/wingetssl.cmake
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
# Detects OpenSSL installed via winget or other common Windows locations,
|
||||||
|
# without requiring the user to manually set OPENSSL_ROOT_DIR.
|
||||||
|
# ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if(WIN32 AND (NOT OpenSSL_FOUND))
|
||||||
|
|
||||||
|
set(_openssl_roots
|
||||||
|
"$ENV{ProgramFiles}/OpenSSL-Win64" "$ENV{ProgramFiles}/OpenSSL"
|
||||||
|
"$ENV{ProgramW6432}/OpenSSL-Win64")
|
||||||
|
|
||||||
|
set(_openssl_lib_suffixes "lib/VC/x64/MD" "lib/VC/x64/MDd" "lib/VC/x64/MT"
|
||||||
|
"lib/VC/x64/MTd" "lib")
|
||||||
|
|
||||||
|
# Determine which configuration we're building
|
||||||
|
if(CMAKE_BUILD_TYPE MATCHES "Debug")
|
||||||
|
set(_is_debug TRUE)
|
||||||
|
else()
|
||||||
|
set(_is_debug FALSE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Determine which runtime we use Default to /MD (shared CRT)
|
||||||
|
set(_crt_kind "MD")
|
||||||
|
if(MSVC)
|
||||||
|
if(CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "MultiThreaded")
|
||||||
|
if(CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "Debug")
|
||||||
|
set(_crt_kind "MTd")
|
||||||
|
else()
|
||||||
|
set(_crt_kind "MT")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
if(_is_debug)
|
||||||
|
set(_crt_kind "MDd")
|
||||||
|
else()
|
||||||
|
set(_crt_kind "MD")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "Looking for OpenSSL built with CRT variant: ${_crt_kind}")
|
||||||
|
|
||||||
|
# Try to find the root and corresponding lib path
|
||||||
|
foreach(_root ${_openssl_roots})
|
||||||
|
if(EXISTS "${_root}/include/openssl/ssl.h")
|
||||||
|
foreach(_suffix ${_openssl_lib_suffixes})
|
||||||
|
if(_suffix MATCHES "${_crt_kind}$"
|
||||||
|
AND EXISTS "${_root}/${_suffix}/libcrypto.lib")
|
||||||
|
set(OPENSSL_ROOT_DIR
|
||||||
|
"${_root}"
|
||||||
|
CACHE PATH "Path to OpenSSL root")
|
||||||
|
set(OPENSSL_CRYPTO_LIBRARY
|
||||||
|
"${_root}/${_suffix}/libcrypto.lib"
|
||||||
|
CACHE FILEPATH "OpenSSL crypto lib")
|
||||||
|
set(OPENSSL_SSL_LIBRARY
|
||||||
|
"${_root}/${_suffix}/libssl.lib"
|
||||||
|
CACHE FILEPATH "OpenSSL ssl lib")
|
||||||
|
set(OPENSSL_INCLUDE_DIR
|
||||||
|
"${_root}/include"
|
||||||
|
CACHE PATH "OpenSSL include dir")
|
||||||
|
set(OpenSSL_FOUND
|
||||||
|
TRUE
|
||||||
|
CACHE BOOL "Whether OpenSSL was found")
|
||||||
|
message(STATUS "Found OpenSSL at: ${_root}/${_suffix}")
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
endif()
|
||||||
|
if(OpenSSL_FOUND)
|
||||||
|
break()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
|
|
||||||
|
if(NOT OpenSSL_FOUND)
|
||||||
|
message(WARNING "Could not auto-detect OpenSSL under Program Files. "
|
||||||
|
"Might have to set OPENSSL_ROOT_DIR manually.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
endif()
|
||||||
@@ -12,7 +12,7 @@ AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart="Aktiviere den Szenenwe
|
|||||||
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Aktiviere den Szenenwechsler nicht"
|
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Aktiviere den Szenenwechsler nicht"
|
||||||
AdvSceneSwitcher.generalTab.status.start="Start"
|
AdvSceneSwitcher.generalTab.status.start="Start"
|
||||||
AdvSceneSwitcher.generalTab.status.stop="Stop"
|
AdvSceneSwitcher.generalTab.status.stop="Stop"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart="Starte auotmatischen den Szenenwechsler beim:"
|
AdvSceneSwitcher.generalTab.status.autoStart.startup="Starte auotmatischen den Szenenwechsler beim:"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.never="Niemals"
|
AdvSceneSwitcher.generalTab.status.autoStart.never="Niemals"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.recording="Aufnehmen"
|
AdvSceneSwitcher.generalTab.status.autoStart.recording="Aufnehmen"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Streamen"
|
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Streamen"
|
||||||
@@ -383,8 +383,6 @@ AdvSceneSwitcher.condition.variable.type.greaterThanVariable="ist größer als d
|
|||||||
|
|
||||||
; Macro Actions
|
; Macro Actions
|
||||||
AdvSceneSwitcher.action.scene="Szene wechseln"
|
AdvSceneSwitcher.action.scene="Szene wechseln"
|
||||||
AdvSceneSwitcher.action.scene.entry="Wechsle{{sceneTypes}}Szene zu{{scenes}}mittels{{transitions}}mit einer Dauer von{{duration}}Sekunden"
|
|
||||||
AdvSceneSwitcher.action.scene.entry.noDuration="Wechsle{{sceneTypes}}Szene zu{{scenes}}mittels{{transitions}}"
|
|
||||||
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Warten, bis der Übergang zur Zielszene abgeschlossen ist"
|
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Warten, bis der Übergang zur Zielszene abgeschlossen ist"
|
||||||
AdvSceneSwitcher.action.wait="Warten"
|
AdvSceneSwitcher.action.wait="Warten"
|
||||||
AdvSceneSwitcher.action.wait.type.fixed="fixe"
|
AdvSceneSwitcher.action.wait.type.fixed="fixe"
|
||||||
@@ -466,7 +464,7 @@ AdvSceneSwitcher.action.pluginState.type.stop="Erweiterten Automatischen Szenenw
|
|||||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Ändern des Nichtübereinstimmungsverhaltens:"
|
AdvSceneSwitcher.action.pluginState.type.noMatch="Ändern des Nichtübereinstimmungsverhaltens:"
|
||||||
AdvSceneSwitcher.action.pluginState.type.import="Einstellungen importieren aus"
|
AdvSceneSwitcher.action.pluginState.type.import="Einstellungen importieren aus"
|
||||||
AdvSceneSwitcher.action.pluginState.importWarning="Hinweis: Die Aktion wird ignoriert, solange das Einstellungsfenster geöffnet ist."
|
AdvSceneSwitcher.action.pluginState.importWarning="Hinweis: Die Aktion wird ignoriert, solange das Einstellungsfenster geöffnet ist."
|
||||||
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
|
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}"
|
||||||
AdvSceneSwitcher.action.virtualCamera="Virtuelle Kamera"
|
AdvSceneSwitcher.action.virtualCamera="Virtuelle Kamera"
|
||||||
AdvSceneSwitcher.action.virtualCamera.type.stop="Virtuelle Kamera stoppen"
|
AdvSceneSwitcher.action.virtualCamera.type.stop="Virtuelle Kamera stoppen"
|
||||||
AdvSceneSwitcher.action.virtualCamera.type.start="Virtuelle Kamera starten"
|
AdvSceneSwitcher.action.virtualCamera.type.start="Virtuelle Kamera starten"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ AdvSceneSwitcher.windowTitle="Advanced Scene Switcher"
|
|||||||
# General Tab
|
# General Tab
|
||||||
AdvSceneSwitcher.generalTab.title="General"
|
AdvSceneSwitcher.generalTab.title="General"
|
||||||
AdvSceneSwitcher.generalTab.status="Status"
|
AdvSceneSwitcher.generalTab.status="Status"
|
||||||
AdvSceneSwitcher.generalTab.status.hotkeytips="Hotkeys can be defined in the OBS settings"
|
AdvSceneSwitcher.generalTab.status.hotkeytips="Start/stop hotkeys can be defined in the OBS settings"
|
||||||
AdvSceneSwitcher.generalTab.status.currentStatus="Advanced Scene Switcher is:"
|
AdvSceneSwitcher.generalTab.status.currentStatus="Advanced Scene Switcher is:"
|
||||||
AdvSceneSwitcher.generalTab.status.onStartup="On startup of OBS:"
|
AdvSceneSwitcher.generalTab.status.onStartup="On startup of OBS:"
|
||||||
AdvSceneSwitcher.generalTab.status.onStartup.asLastRun="Start the scene switcher if it was running"
|
AdvSceneSwitcher.generalTab.status.onStartup.asLastRun="Start the scene switcher if it was running"
|
||||||
@@ -12,11 +12,12 @@ AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart="Always start the scene
|
|||||||
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Do not start the scene switcher"
|
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Do not start the scene switcher"
|
||||||
AdvSceneSwitcher.generalTab.status.start="Start"
|
AdvSceneSwitcher.generalTab.status.start="Start"
|
||||||
AdvSceneSwitcher.generalTab.status.stop="Stop"
|
AdvSceneSwitcher.generalTab.status.stop="Stop"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart="Automatically start the scene switcher when:"
|
AdvSceneSwitcher.generalTab.status.autoStart.startup="Automatically start the scene switcher when:"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.never="Never"
|
AdvSceneSwitcher.generalTab.status.autoStart.never="Never"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.recording="Recording"
|
AdvSceneSwitcher.generalTab.status.autoStart.recording="Recording"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Streaming"
|
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Streaming"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Recording or Streaming"
|
AdvSceneSwitcher.generalTab.status.autoStart.recordingAndStreaming="Recording or Streaming"
|
||||||
|
AdvSceneSwitcher.generalTab.status.autoStart.scene="Automatically start the scene switcher on scene:"
|
||||||
AdvSceneSwitcher.generalTab.status.checkInterval="Check conditions every"
|
AdvSceneSwitcher.generalTab.status.checkInterval="Check conditions every"
|
||||||
AdvSceneSwitcher.generalTab.status.checkIntervalTooLow="⚠️ Conflict with macro \"%1\"!"
|
AdvSceneSwitcher.generalTab.status.checkIntervalTooLow="⚠️ Conflict with macro \"%1\"!"
|
||||||
AdvSceneSwitcher.generalTab.status.checkIntervalTooLow.tooltip="Macro \"%1\" won't be able to check its condition at the desired interval of %2.\nEither change the condition check value on the General tab or in the settings of macro \"%3\"."
|
AdvSceneSwitcher.generalTab.status.checkIntervalTooLow.tooltip="Macro \"%1\" won't be able to check its condition at the desired interval of %2.\nEither change the condition check value on the General tab or in the settings of macro \"%3\"."
|
||||||
@@ -42,7 +43,7 @@ AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailure="Display warni
|
|||||||
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailureMessage="<html><body>Loading of the following plugin libraries was unsuccessful, which could result in some Advanced Scene Switcher functions not being available:%1Check the OBS logs for details.<br>This message can be disabled on the General tab.</body></html>"
|
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailureMessage="<html><body>Loading of the following plugin libraries was unsuccessful, which could result in some Advanced Scene Switcher functions not being available:%1Check the OBS logs for details.<br>This message can be disabled on the General tab.</body></html>"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.warnCorruptedInstallMessage="The plugin installation seems to be corrupted and might crash!\nPlease make sure the plugin was installed correctly!"
|
AdvSceneSwitcher.generalTab.generalBehavior.warnCorruptedInstallMessage="The plugin installation seems to be corrupted and might crash!\nPlease make sure the plugin was installed correctly!"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="Hide tabs which can be represented via macros"
|
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="Hide tabs which can be represented via macros"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.disableMacroWidgetCache="Disable macro widget caching"
|
AdvSceneSwitcher.generalTab.generalBehavior.alwaysShowMacroSearch="Always show macro search"
|
||||||
AdvSceneSwitcher.generalTab.matchBehavior="Match behavior"
|
AdvSceneSwitcher.generalTab.matchBehavior="Match behavior"
|
||||||
AdvSceneSwitcher.generalTab.priority="Priority"
|
AdvSceneSwitcher.generalTab.priority="Priority"
|
||||||
AdvSceneSwitcher.generalTab.priority.description="Switching methods priority (Highest priority is at the top)"
|
AdvSceneSwitcher.generalTab.priority.description="Switching methods priority (Highest priority is at the top)"
|
||||||
@@ -73,6 +74,7 @@ AdvSceneSwitcher.generalTab.setTransitionBy="When changing transitions:"
|
|||||||
AdvSceneSwitcher.generalTab.transitionOverride="Set transition overrides"
|
AdvSceneSwitcher.generalTab.transitionOverride="Set transition overrides"
|
||||||
AdvSceneSwitcher.generalTab.adjustActiveTransitionType="Change active transition type"
|
AdvSceneSwitcher.generalTab.adjustActiveTransitionType="Change active transition type"
|
||||||
AdvSceneSwitcher.generalTab.transitionBehaviorSelectionError="At least one option must be enabled:\n\n - Use transition overrides\n\n - Change active transition type"
|
AdvSceneSwitcher.generalTab.transitionBehaviorSelectionError="At least one option must be enabled:\n\n - Use transition overrides\n\n - Change active transition type"
|
||||||
|
AdvSceneSwitcher.generalTab.uiBehavior="UI settings"
|
||||||
|
|
||||||
# Variables Tab
|
# Variables Tab
|
||||||
AdvSceneSwitcher.variableTab.title="Variables"
|
AdvSceneSwitcher.variableTab.title="Variables"
|
||||||
@@ -90,6 +92,12 @@ AdvSceneSwitcher.variableTab.lastUsed.text.never="Never"
|
|||||||
AdvSceneSwitcher.variableTab.lastChanged.header="Last changed"
|
AdvSceneSwitcher.variableTab.lastChanged.header="Last changed"
|
||||||
AdvSceneSwitcher.variableTab.lastChanged.text.none="No change since launch"
|
AdvSceneSwitcher.variableTab.lastChanged.text.none="No change since launch"
|
||||||
AdvSceneSwitcher.variableTab.lastChanged.tooltip="Times changed: %1\n\nPrevious value: %2"
|
AdvSceneSwitcher.variableTab.lastChanged.tooltip="Times changed: %1\n\nPrevious value: %2"
|
||||||
|
AdvSceneSwitcher.variableTab.search.placeholder="Search ..."
|
||||||
|
AdvSceneSwitcher.variableTab.search.all="All columns"
|
||||||
|
AdvSceneSwitcher.variableTab.search.name="Name column"
|
||||||
|
AdvSceneSwitcher.variableTab.search.value="Value column"
|
||||||
|
AdvSceneSwitcher.variableTab.addDock="Add dock"
|
||||||
|
AdvSceneSwitcher.variableTab.clear="Clear"
|
||||||
|
|
||||||
# Action Queue Tab
|
# Action Queue Tab
|
||||||
AdvSceneSwitcher.actionQueueTab.title="Action Queues"
|
AdvSceneSwitcher.actionQueueTab.title="Action Queues"
|
||||||
@@ -150,9 +158,9 @@ AdvSceneSwitcher.macroTab.title="Macro"
|
|||||||
AdvSceneSwitcher.macroTab.macros="Macros"
|
AdvSceneSwitcher.macroTab.macros="Macros"
|
||||||
AdvSceneSwitcher.macroTab.priorityWarning="Note: It is recommended to configure macros to be the highest priority functionality.\nThis setting can be changed on the General tab."
|
AdvSceneSwitcher.macroTab.priorityWarning="Note: It is recommended to configure macros to be the highest priority functionality.\nThis setting can be changed on the General tab."
|
||||||
AdvSceneSwitcher.macroTab.help="Macros allow you to execute a string of actions depending on multiple conditions.\n\nClick on the highlighted plus symbol to add a new Macro."
|
AdvSceneSwitcher.macroTab.help="Macros allow you to execute a string of actions depending on multiple conditions.\n\nClick on the highlighted plus symbol to add a new Macro."
|
||||||
AdvSceneSwitcher.macroTab.editConditionHelp="This section allows you to define Macro conditions.\n\nSelect an existing or add a new Macro on the left.\nThen click the plus button below to add a new condition."
|
AdvSceneSwitcher.macroTab.editConditionHelp="This section allows you to define macro conditions.\n\nSelect an existing or add a new macro on the left.\nThen click the plus button below to add a new condition."
|
||||||
AdvSceneSwitcher.macroTab.editActionHelp="This section allows you to define Macro actions.\n\nSelect an existing or add a new Macro on the left.\nThen click the plus button below to add a new action."
|
AdvSceneSwitcher.macroTab.editActionHelp="This section allows you to define macro actions.\nThe actions in this section will be performed when the conditions are met.\n\nSelect an existing or add a new macro on the left.\nThen click the plus button below to add a new action."
|
||||||
AdvSceneSwitcher.macroTab.editElseActionHelp="This section allows you to define Macro actions, which are executed if the conditions are *not* met.\n\nSelect an existing or add a new Macro on the left.\nThen click the plus button below to add a new action."
|
AdvSceneSwitcher.macroTab.editElseActionHelp="This section allows you to define macro actions.\nThe actions in this section will be performed when the conditions are *not* met.\n\nSelect an existing or add a new macro on the left.\nThen click the plus button below to add a new action."
|
||||||
AdvSceneSwitcher.macroTab.edit="Edit macro"
|
AdvSceneSwitcher.macroTab.edit="Edit macro"
|
||||||
AdvSceneSwitcher.macroTab.edit.logic="Logic type:"
|
AdvSceneSwitcher.macroTab.edit.logic="Logic type:"
|
||||||
AdvSceneSwitcher.macroTab.edit.condition="Condition type:"
|
AdvSceneSwitcher.macroTab.edit.condition="Condition type:"
|
||||||
@@ -177,6 +185,8 @@ AdvSceneSwitcher.macroTab.contextMenuAdd="Add"
|
|||||||
AdvSceneSwitcher.macroTab.copy="Duplicate Macro"
|
AdvSceneSwitcher.macroTab.copy="Duplicate Macro"
|
||||||
AdvSceneSwitcher.macroTab.group="Group Selected Macros"
|
AdvSceneSwitcher.macroTab.group="Group Selected Macros"
|
||||||
AdvSceneSwitcher.macroTab.ungroup="Ungroup Selected Groups"
|
AdvSceneSwitcher.macroTab.ungroup="Ungroup Selected Groups"
|
||||||
|
AdvSceneSwitcher.macroTab.expandAllGroups="Expand all Groups"
|
||||||
|
AdvSceneSwitcher.macroTab.collapseAllGroups="Collapse all Groups"
|
||||||
AdvSceneSwitcher.macroTab.rename="Rename"
|
AdvSceneSwitcher.macroTab.rename="Rename"
|
||||||
AdvSceneSwitcher.macroTab.remove="Remove"
|
AdvSceneSwitcher.macroTab.remove="Remove"
|
||||||
AdvSceneSwitcher.macroTab.export="Export"
|
AdvSceneSwitcher.macroTab.export="Export"
|
||||||
@@ -229,6 +239,8 @@ AdvSceneSwitcher.macroTab.pauseStateSaveBehavior.persist="The state the macro wa
|
|||||||
AdvSceneSwitcher.macroTab.pauseStateSaveBehavior.pause="Paused"
|
AdvSceneSwitcher.macroTab.pauseStateSaveBehavior.pause="Paused"
|
||||||
AdvSceneSwitcher.macroTab.pauseStateSaveBehavior.unpause="Unpaused"
|
AdvSceneSwitcher.macroTab.pauseStateSaveBehavior.unpause="Unpaused"
|
||||||
AdvSceneSwitcher.macroTab.currentRegisterDock="Register dock widget to control the pause state of selected macro or run it manually"
|
AdvSceneSwitcher.macroTab.currentRegisterDock="Register dock widget to control the pause state of selected macro or run it manually"
|
||||||
|
AdvSceneSwitcher.macroTab.currentIsStandaloneDock="Is standalone dock"
|
||||||
|
AdvSceneSwitcher.macroTab.currentDockWindowName="Add to macro dock with name:"
|
||||||
AdvSceneSwitcher.macroTab.currentDockAddRunButton="Add button to run the macro"
|
AdvSceneSwitcher.macroTab.currentDockAddRunButton="Add button to run the macro"
|
||||||
AdvSceneSwitcher.macroTab.currentDockAddPauseButton="Add button to pause or unpause the macro"
|
AdvSceneSwitcher.macroTab.currentDockAddPauseButton="Add button to pause or unpause the macro"
|
||||||
AdvSceneSwitcher.macroTab.currentDockAddStatusLabel="Add status label"
|
AdvSceneSwitcher.macroTab.currentDockAddStatusLabel="Add status label"
|
||||||
@@ -265,6 +277,13 @@ AdvSceneSwitcher.macroTab.tooltip.elseActionUpButton="Move selected action up in
|
|||||||
AdvSceneSwitcher.macroTab.tooltip.elseActionDownButton="Move selected action down in the else section"
|
AdvSceneSwitcher.macroTab.tooltip.elseActionDownButton="Move selected action down in the else section"
|
||||||
AdvSceneSwitcher.macroTab.tooltip.elseActionBottomButton="Move selected action to the bottom in the else section"
|
AdvSceneSwitcher.macroTab.tooltip.elseActionBottomButton="Move selected action to the bottom in the else section"
|
||||||
AdvSceneSwitcher.macroTab.tooltip.openMacroSettingsButton="Open macro settings"
|
AdvSceneSwitcher.macroTab.tooltip.openMacroSettingsButton="Open macro settings"
|
||||||
|
AdvSceneSwitcher.macroTab.search.placeholder="Search ..."
|
||||||
|
AdvSceneSwitcher.macroTab.search.showSettings="Show search settings"
|
||||||
|
AdvSceneSwitcher.macroTab.search.name="Name"
|
||||||
|
AdvSceneSwitcher.macroTab.search.allSegments="Segment type"
|
||||||
|
AdvSceneSwitcher.macroTab.search.conditions="Condition type"
|
||||||
|
AdvSceneSwitcher.macroTab.search.actions="Action type"
|
||||||
|
AdvSceneSwitcher.macroTab.search.label="Segment label"
|
||||||
|
|
||||||
AdvSceneSwitcher.macroDock.pause="Pause"
|
AdvSceneSwitcher.macroDock.pause="Pause"
|
||||||
AdvSceneSwitcher.macroDock.unpause="Unpause"
|
AdvSceneSwitcher.macroDock.unpause="Unpause"
|
||||||
@@ -321,6 +340,7 @@ AdvSceneSwitcher.condition.scene.type.previousPattern="Previous scene matches"
|
|||||||
AdvSceneSwitcher.condition.scene.type.previewPattern="Preview scene matches"
|
AdvSceneSwitcher.condition.scene.type.previewPattern="Preview scene matches"
|
||||||
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="During transition check for transition target scene"
|
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="During transition check for transition target scene"
|
||||||
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="During transition check for transition source scene"
|
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="During transition check for transition source scene"
|
||||||
|
AdvSceneSwitcher.condition.scene.canvasNotSupported="This check is not supported for the currently selected canvas \"%1\""
|
||||||
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}{{regex}}"
|
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}{{regex}}"
|
||||||
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
||||||
AdvSceneSwitcher.condition.window="Window"
|
AdvSceneSwitcher.condition.window="Window"
|
||||||
@@ -336,6 +356,9 @@ AdvSceneSwitcher.condition.file="File"
|
|||||||
AdvSceneSwitcher.condition.file.type.match="matches"
|
AdvSceneSwitcher.condition.file.type.match="matches"
|
||||||
AdvSceneSwitcher.condition.file.type.contentChange="content changed"
|
AdvSceneSwitcher.condition.file.type.contentChange="content changed"
|
||||||
AdvSceneSwitcher.condition.file.type.dateChange="modification date changed"
|
AdvSceneSwitcher.condition.file.type.dateChange="modification date changed"
|
||||||
|
AdvSceneSwitcher.condition.file.type.exists="exists"
|
||||||
|
AdvSceneSwitcher.condition.file.type.isFile="is a file"
|
||||||
|
AdvSceneSwitcher.condition.file.type.isFolder="is a folder"
|
||||||
AdvSceneSwitcher.condition.file.remote="Remote file"
|
AdvSceneSwitcher.condition.file.remote="Remote file"
|
||||||
AdvSceneSwitcher.condition.file.local="Local file"
|
AdvSceneSwitcher.condition.file.local="Local file"
|
||||||
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||||
@@ -485,6 +508,7 @@ AdvSceneSwitcher.condition.macro.type.multiState="Multiple macro condition state
|
|||||||
AdvSceneSwitcher.condition.macro.type.actionDisabled="Macro action disabled"
|
AdvSceneSwitcher.condition.macro.type.actionDisabled="Macro action disabled"
|
||||||
AdvSceneSwitcher.condition.macro.type.actionEnabled="Macro action enabled"
|
AdvSceneSwitcher.condition.macro.type.actionEnabled="Macro action enabled"
|
||||||
AdvSceneSwitcher.condition.macro.type.paused="Macro is paused"
|
AdvSceneSwitcher.condition.macro.type.paused="Macro is paused"
|
||||||
|
AdvSceneSwitcher.condition.macro.type.actionsPerformed="Macro actions were executed"
|
||||||
AdvSceneSwitcher.condition.macro.type.selection="{{types}}"
|
AdvSceneSwitcher.condition.macro.type.selection="{{types}}"
|
||||||
AdvSceneSwitcher.condition.macro.count.type.below="Less than"
|
AdvSceneSwitcher.condition.macro.count.type.below="Less than"
|
||||||
AdvSceneSwitcher.condition.macro.count.type.above="More than"
|
AdvSceneSwitcher.condition.macro.count.type.above="More than"
|
||||||
@@ -501,6 +525,7 @@ AdvSceneSwitcher.condition.macro.count.entry.line2="Current count:{{currentCount
|
|||||||
AdvSceneSwitcher.condition.macro.actionState.disabled.entry="Action{{actionIndex}}of{{macros}}is disabled"
|
AdvSceneSwitcher.condition.macro.actionState.disabled.entry="Action{{actionIndex}}of{{macros}}is disabled"
|
||||||
AdvSceneSwitcher.condition.macro.actionState.enabled.entry="Action{{actionIndex}}of{{macros}}is enabled"
|
AdvSceneSwitcher.condition.macro.actionState.enabled.entry="Action{{actionIndex}}of{{macros}}is enabled"
|
||||||
AdvSceneSwitcher.condition.macro.paused.entry="Macro{{macros}}is paused"
|
AdvSceneSwitcher.condition.macro.paused.entry="Macro{{macros}}is paused"
|
||||||
|
AdvSceneSwitcher.condition.macro.actionsPerformed.entry="The actions of macro{{macros}}were performed"
|
||||||
AdvSceneSwitcher.condition.source="Source"
|
AdvSceneSwitcher.condition.source="Source"
|
||||||
AdvSceneSwitcher.condition.source.type.active="Is active"
|
AdvSceneSwitcher.condition.source.type.active="Is active"
|
||||||
AdvSceneSwitcher.condition.source.type.showing="Is showing"
|
AdvSceneSwitcher.condition.source.type.showing="Is showing"
|
||||||
@@ -516,6 +541,7 @@ AdvSceneSwitcher.condition.source.sizeCompare.equal="Equals"
|
|||||||
AdvSceneSwitcher.condition.source.sizeCompare.more="Bigger than"
|
AdvSceneSwitcher.condition.source.sizeCompare.more="Bigger than"
|
||||||
AdvSceneSwitcher.condition.source.refresh="Refresh"
|
AdvSceneSwitcher.condition.source.refresh="Refresh"
|
||||||
AdvSceneSwitcher.condition.source.refresh.tooltip="Repopulate the source settings selection with the settings of the source which's name matches the variable value."
|
AdvSceneSwitcher.condition.source.refresh.tooltip="Repopulate the source settings selection with the settings of the source which's name matches the variable value."
|
||||||
|
AdvSceneSwitcher.condition.source.includeDefaults="Include default settings values"
|
||||||
AdvSceneSwitcher.condition.source.sceneVisibilityHint="Scene specific visibility can be checked using the \"Scene item visibility\" condition"
|
AdvSceneSwitcher.condition.source.sceneVisibilityHint="Scene specific visibility can be checked using the \"Scene item visibility\" condition"
|
||||||
AdvSceneSwitcher.condition.source.getSettings="Get current settings"
|
AdvSceneSwitcher.condition.source.getSettings="Get current settings"
|
||||||
AdvSceneSwitcher.condition.source.entry.line1="{{sources}}{{conditions}}{{settingSelection}}{{refresh}}{{sizeCompareMethods}}{{size}}"
|
AdvSceneSwitcher.condition.source.entry.line1="{{sources}}{{conditions}}{{settingSelection}}{{refresh}}{{sizeCompareMethods}}{{size}}"
|
||||||
@@ -535,6 +561,7 @@ AdvSceneSwitcher.condition.filter.type.individualSettingListSelectionMatches="Se
|
|||||||
AdvSceneSwitcher.condition.filter.type.individualSettingChanged="Settings value changed"
|
AdvSceneSwitcher.condition.filter.type.individualSettingChanged="Settings value changed"
|
||||||
AdvSceneSwitcher.condition.filter.refresh="Refresh"
|
AdvSceneSwitcher.condition.filter.refresh="Refresh"
|
||||||
AdvSceneSwitcher.condition.filter.refresh.tooltip="Repopulate the filter settings selection with the settings of the filter which's name matches the variable value."
|
AdvSceneSwitcher.condition.filter.refresh.tooltip="Repopulate the filter settings selection with the settings of the filter which's name matches the variable value."
|
||||||
|
AdvSceneSwitcher.condition.filter.includeDefaults="Include default settings values"
|
||||||
AdvSceneSwitcher.condition.filter.getSettings="Get current settings"
|
AdvSceneSwitcher.condition.filter.getSettings="Get current settings"
|
||||||
AdvSceneSwitcher.condition.filter.entry.line1="On{{sources}}{{filters}}{{conditions}}{{settingSelection}}{{refresh}}"
|
AdvSceneSwitcher.condition.filter.entry.line1="On{{sources}}{{filters}}{{conditions}}{{settingSelection}}{{refresh}}"
|
||||||
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
AdvSceneSwitcher.condition.filter.entry.line2="{{settings}}"
|
||||||
@@ -695,6 +722,7 @@ AdvSceneSwitcher.condition.twitch.type.event.channel.raid.outbound="Raided someo
|
|||||||
AdvSceneSwitcher.condition.twitch.type.event.channel.raid.inbound="Raid to your channel occured"
|
AdvSceneSwitcher.condition.twitch.type.event.channel.raid.inbound="Raid to your channel occured"
|
||||||
AdvSceneSwitcher.condition.twitch.type.event.channel.shoutout.outbound="Shoutout to someone's channel given"
|
AdvSceneSwitcher.condition.twitch.type.event.channel.shoutout.outbound="Shoutout to someone's channel given"
|
||||||
AdvSceneSwitcher.condition.twitch.type.event.channel.shoutout.inbound="Shoutout to your channel received"
|
AdvSceneSwitcher.condition.twitch.type.event.channel.shoutout.inbound="Shoutout to your channel received"
|
||||||
|
AdvSceneSwitcher.condition.twitch.type.event.channel.commercial.start="Commercial break started"
|
||||||
AdvSceneSwitcher.condition.twitch.type.event.channel.poll.start="Poll started"
|
AdvSceneSwitcher.condition.twitch.type.event.channel.poll.start="Poll started"
|
||||||
AdvSceneSwitcher.condition.twitch.type.event.channel.poll.progress="Poll votes changed (progress)"
|
AdvSceneSwitcher.condition.twitch.type.event.channel.poll.progress="Poll votes changed (progress)"
|
||||||
AdvSceneSwitcher.condition.twitch.type.event.channel.poll.end="Poll ended"
|
AdvSceneSwitcher.condition.twitch.type.event.channel.poll.end="Poll ended"
|
||||||
@@ -810,12 +838,21 @@ AdvSceneSwitcher.condition.script="Script"
|
|||||||
# Macro Actions
|
# Macro Actions
|
||||||
AdvSceneSwitcher.action.unknown="Unknown action"
|
AdvSceneSwitcher.action.unknown="Unknown action"
|
||||||
AdvSceneSwitcher.action.scene="Switch scene"
|
AdvSceneSwitcher.action.scene="Switch scene"
|
||||||
|
AdvSceneSwitcher.action.scene.action.fixed="Scene with name"
|
||||||
|
AdvSceneSwitcher.action.scene.action.sceneListNext="Next scene in scene list"
|
||||||
|
AdvSceneSwitcher.action.scene.action.sceneListPrevious="Previous scene in scene list"
|
||||||
|
AdvSceneSwitcher.action.scene.action.sceneListIndex="Scene in scene list at position"
|
||||||
AdvSceneSwitcher.action.scene.type.program="Program"
|
AdvSceneSwitcher.action.scene.type.program="Program"
|
||||||
AdvSceneSwitcher.action.scene.type.preview="Preview"
|
AdvSceneSwitcher.action.scene.type.preview="Preview"
|
||||||
AdvSceneSwitcher.action.scene.entry="Switch{{sceneTypes}}scene to{{scenes}}using{{transitions}}with a duration of{{duration}}seconds"
|
AdvSceneSwitcher.action.scene.layout.action.fixed="Switch{{sceneTypes}}to{{actions}}{{scenes}}"
|
||||||
AdvSceneSwitcher.action.scene.entry.noDuration="Switch{{sceneTypes}}scene to{{scenes}}using{{transitions}}"
|
AdvSceneSwitcher.action.scene.layout.action.list="Switch{{sceneTypes}}to{{actions}}on{{canvas}}"
|
||||||
AdvSceneSwitcher.action.scene.entry.preview="Switch{{sceneTypes}}scene to{{scenes}}"
|
AdvSceneSwitcher.action.scene.layout.action.list.noCanvasSelection="Switch{{sceneTypes}}to{{actions}}"
|
||||||
|
AdvSceneSwitcher.action.scene.layout.action.listIndex="Switch{{sceneTypes}}to{{actions}}{{index}}on{{canvas}}{{sceneNameAtIndex}}"
|
||||||
|
AdvSceneSwitcher.action.scene.layout.action.listIndex.noCanvasSelection="Switch{{sceneTypes}}to{{actions}}{{index}}{{sceneNameAtIndex}}"
|
||||||
|
AdvSceneSwitcher.action.scene.layout.transition="Use transition{{transitions}}"
|
||||||
|
AdvSceneSwitcher.action.scene.layout.transitionWithDuration="Use transition{{transitions}}with a duration of{{duration}}seconds"
|
||||||
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Wait until transition to target scene is complete"
|
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Wait until transition to target scene is complete"
|
||||||
|
AdvSceneSwitcher.action.scene.canvasNotSupported="Not supported by the currently selected canvas \"%1\""
|
||||||
AdvSceneSwitcher.action.wait="Wait"
|
AdvSceneSwitcher.action.wait="Wait"
|
||||||
AdvSceneSwitcher.action.wait.type.fixed="fixed"
|
AdvSceneSwitcher.action.wait.type.fixed="fixed"
|
||||||
AdvSceneSwitcher.action.wait.type.random="random"
|
AdvSceneSwitcher.action.wait.type.random="random"
|
||||||
@@ -824,6 +861,7 @@ AdvSceneSwitcher.action.wait.entry.random="Wait for{{waitType}}duration from{{du
|
|||||||
AdvSceneSwitcher.action.audio="Audio"
|
AdvSceneSwitcher.action.audio="Audio"
|
||||||
AdvSceneSwitcher.action.audio.type.mute="Mute"
|
AdvSceneSwitcher.action.audio.type.mute="Mute"
|
||||||
AdvSceneSwitcher.action.audio.type.unmute="Unmute"
|
AdvSceneSwitcher.action.audio.type.unmute="Unmute"
|
||||||
|
AdvSceneSwitcher.action.audio.type.toggleMute="Toggle mute"
|
||||||
AdvSceneSwitcher.action.audio.type.sourceVolume="Set source volume"
|
AdvSceneSwitcher.action.audio.type.sourceVolume="Set source volume"
|
||||||
AdvSceneSwitcher.action.audio.type.masterVolume="Set master volume"
|
AdvSceneSwitcher.action.audio.type.masterVolume="Set master volume"
|
||||||
AdvSceneSwitcher.action.audio.type.syncOffset="Set sync offset"
|
AdvSceneSwitcher.action.audio.type.syncOffset="Set sync offset"
|
||||||
@@ -904,6 +942,9 @@ AdvSceneSwitcher.action.source.type.deinterlaceOrder="Set deinterlace field orde
|
|||||||
AdvSceneSwitcher.action.source.type.openInteractionDialog="Open interaction dialog"
|
AdvSceneSwitcher.action.source.type.openInteractionDialog="Open interaction dialog"
|
||||||
AdvSceneSwitcher.action.source.type.openFilterDialog="Open filter dialog"
|
AdvSceneSwitcher.action.source.type.openFilterDialog="Open filter dialog"
|
||||||
AdvSceneSwitcher.action.source.type.openPropertiesDialog="Open properties dialog"
|
AdvSceneSwitcher.action.source.type.openPropertiesDialog="Open properties dialog"
|
||||||
|
AdvSceneSwitcher.action.source.type.closeInteractionDialog="Close interaction dialog"
|
||||||
|
AdvSceneSwitcher.action.source.type.closeFilterDialog="Close filter dialog"
|
||||||
|
AdvSceneSwitcher.action.source.type.closePropertiesDialog="Close properties dialog"
|
||||||
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}{{deinterlaceMode}}{{deinterlaceOrder}}{{refresh}}"
|
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}{{deinterlaceMode}}{{deinterlaceOrder}}{{refresh}}"
|
||||||
AdvSceneSwitcher.action.source.entry.settings="{{settings}}{{settingsInputMethod}}{{settingValue}}{{tempVar}}"
|
AdvSceneSwitcher.action.source.entry.settings="{{settings}}{{settingsInputMethod}}{{settingValue}}{{tempVar}}"
|
||||||
AdvSceneSwitcher.action.source.warning="Warning: Enabling and disabling sources globally cannot be controlled by the OBS UI\nYou might be looking for \"Scene item visibility\""
|
AdvSceneSwitcher.action.source.warning="Warning: Enabling and disabling sources globally cannot be controlled by the OBS UI\nYou might be looking for \"Scene item visibility\""
|
||||||
@@ -925,6 +966,7 @@ AdvSceneSwitcher.action.source.inputMethod.individualTempvar="Set to macro prope
|
|||||||
AdvSceneSwitcher.action.source.inputMethod.json="Set setting JSON string"
|
AdvSceneSwitcher.action.source.inputMethod.json="Set setting JSON string"
|
||||||
AdvSceneSwitcher.action.source.refresh="Refresh"
|
AdvSceneSwitcher.action.source.refresh="Refresh"
|
||||||
AdvSceneSwitcher.action.source.refresh.tooltip="Repopulate the source settings selection with the settings of the source which's name matches the variable value."
|
AdvSceneSwitcher.action.source.refresh.tooltip="Repopulate the source settings selection with the settings of the source which's name matches the variable value."
|
||||||
|
AdvSceneSwitcher.action.source.dialog.accept="Accept changes"
|
||||||
AdvSceneSwitcher.action.media="Media"
|
AdvSceneSwitcher.action.media="Media"
|
||||||
AdvSceneSwitcher.action.media.type.play="Play"
|
AdvSceneSwitcher.action.media.type.play="Play"
|
||||||
AdvSceneSwitcher.action.media.type.pause="Pause"
|
AdvSceneSwitcher.action.media.type.pause="Pause"
|
||||||
@@ -959,9 +1001,17 @@ AdvSceneSwitcher.action.macro.type.stop="Stop actions"
|
|||||||
AdvSceneSwitcher.action.macro.type.disableAction="Disable action"
|
AdvSceneSwitcher.action.macro.type.disableAction="Disable action"
|
||||||
AdvSceneSwitcher.action.macro.type.enableAction="Enable action"
|
AdvSceneSwitcher.action.macro.type.enableAction="Enable action"
|
||||||
AdvSceneSwitcher.action.macro.type.toggleAction="Toggle action"
|
AdvSceneSwitcher.action.macro.type.toggleAction="Toggle action"
|
||||||
AdvSceneSwitcher.action.macro.entry.run="{{actions}}{{actionTypes}}of{{macros}}"
|
AdvSceneSwitcher.action.macro.type.nestedMacro="Nested macro"
|
||||||
AdvSceneSwitcher.action.macro.entry.run.condition="{{conditionBehaviors}}of{{conditionMacros}}"
|
AdvSceneSwitcher.action.macro.actionSelectionType.index="at index"
|
||||||
AdvSceneSwitcher.action.macro.entry.other="{{actions}}{{actionIndex}}{{macros}}"
|
AdvSceneSwitcher.action.macro.actionSelectionType.label="with label"
|
||||||
|
AdvSceneSwitcher.action.macro.actionSelectionType.id="of action type"
|
||||||
|
AdvSceneSwitcher.action.macro.type.nestedMacro.conditionHelp="This section allows you to define macro conditions.\n\nClick the plus button below to add a new condition."
|
||||||
|
AdvSceneSwitcher.action.macro.type.nestedMacro.actionHelp="This section allows you to define macro actions.\nThe actions in this section will be performed when the conditions are met.\n\nClick the plus button below to add a new action."
|
||||||
|
AdvSceneSwitcher.action.macro.type.nestedMacro.elseActionHelp="This section allows you to define macro actions.\nThe actions in this section will be performed when the conditions are *not* met.\n\nClick the plus button below to add a new action."
|
||||||
|
AdvSceneSwitcher.action.macro.layout.run="{{actions}}{{actionSections}}of{{macros}}"
|
||||||
|
AdvSceneSwitcher.action.macro.layout.run.condition="{{conditionBehaviors}}of{{conditionMacros}}"
|
||||||
|
AdvSceneSwitcher.action.macro.layout.actionState="{{actions}}{{actionSelectionType}}{{actionIndex}}{{label}}{{regex}}{{actionTypes}}in{{actionSections}}section of{{macros}}"
|
||||||
|
AdvSceneSwitcher.action.macro.layout.other="{{actions}}{{macros}}"
|
||||||
AdvSceneSwitcher.action.pluginState="Plugin state"
|
AdvSceneSwitcher.action.pluginState="Plugin state"
|
||||||
AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher plugin"
|
AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher plugin"
|
||||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Change the no-match behaviour:"
|
AdvSceneSwitcher.action.pluginState.type.noMatch="Change the no-match behaviour:"
|
||||||
@@ -969,7 +1019,11 @@ AdvSceneSwitcher.action.pluginState.type.import="Import settings from"
|
|||||||
AdvSceneSwitcher.action.pluginState.importWarning="Note: Action will be ignored while settings window is opened."
|
AdvSceneSwitcher.action.pluginState.importWarning="Note: Action will be ignored while settings window is opened."
|
||||||
AdvSceneSwitcher.action.pluginState.type.terminate="Shut down OBS"
|
AdvSceneSwitcher.action.pluginState.type.terminate="Shut down OBS"
|
||||||
AdvSceneSwitcher.action.pluginState.terminateConfirm="OBS will be shut down automatically in 10 seconds!\nDo you want to continue shutting down OBS?"
|
AdvSceneSwitcher.action.pluginState.terminateConfirm="OBS will be shut down automatically in 10 seconds!\nDo you want to continue shutting down OBS?"
|
||||||
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
|
AdvSceneSwitcher.action.pluginState.type.enableMacroHighlighting="Enable macro highlighting"
|
||||||
|
AdvSceneSwitcher.action.pluginState.type.disableMacroHighlighting="Disable macro highlighting"
|
||||||
|
AdvSceneSwitcher.action.pluginState.type.toggleMacroHighlighting="Toggle macro highlighting"
|
||||||
|
AdvSceneSwitcher.action.pluginState.confirmShutdown="Ask for shutdown confirmation"
|
||||||
|
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}"
|
||||||
AdvSceneSwitcher.action.virtualCamera="Virtual camera"
|
AdvSceneSwitcher.action.virtualCamera="Virtual camera"
|
||||||
AdvSceneSwitcher.action.virtualCamera.type.stop="Stop virtual camera"
|
AdvSceneSwitcher.action.virtualCamera.type.stop="Stop virtual camera"
|
||||||
AdvSceneSwitcher.action.virtualCamera.type.start="Start virtual camera"
|
AdvSceneSwitcher.action.virtualCamera.type.start="Start virtual camera"
|
||||||
@@ -1080,7 +1134,7 @@ AdvSceneSwitcher.action.websocket.api.genericWebsocket="Generic websocket messag
|
|||||||
AdvSceneSwitcher.action.websocket.type.request="Request"
|
AdvSceneSwitcher.action.websocket.type.request="Request"
|
||||||
AdvSceneSwitcher.action.websocket.type.event="Event"
|
AdvSceneSwitcher.action.websocket.type.event="Event"
|
||||||
AdvSceneSwitcher.action.websocket.settingsConflictGeneric="Possible settings conflict: Generic websocket message selection with connection which follows the OBS protocol!"
|
AdvSceneSwitcher.action.websocket.settingsConflictGeneric="Possible settings conflict: Generic websocket message selection with connection which follows the OBS protocol!"
|
||||||
AdvSceneSwitcher.action.websocket.settingsConflictOBS="Possible settings conflict: Connection selected which only supports generic websockte messages while message type requires OBS protocol!"
|
AdvSceneSwitcher.action.websocket.settingsConflictOBS="Possible settings conflict: Connection selected which only supports generic websocket messages while message type requires OBS protocol!"
|
||||||
AdvSceneSwitcher.action.websocket.entry.sceneSwitcher.request="Send{{api}}of type{{type}}via{{connection}}"
|
AdvSceneSwitcher.action.websocket.entry.sceneSwitcher.request="Send{{api}}of type{{type}}via{{connection}}"
|
||||||
AdvSceneSwitcher.action.websocket.entry.sceneSwitcher.event="Send{{api}}of type{{type}}to connected clients"
|
AdvSceneSwitcher.action.websocket.entry.sceneSwitcher.event="Send{{api}}of type{{type}}to connected clients"
|
||||||
AdvSceneSwitcher.action.websocket.entry.generic="Send{{api}}via{{connection}}"
|
AdvSceneSwitcher.action.websocket.entry.generic="Send{{api}}via{{connection}}"
|
||||||
@@ -1109,6 +1163,7 @@ AdvSceneSwitcher.action.http.entry.line2="Timeout:{{timeout}}seconds"
|
|||||||
AdvSceneSwitcher.action.variable="Variable"
|
AdvSceneSwitcher.action.variable="Variable"
|
||||||
AdvSceneSwitcher.action.variable.type.set="Set to value"
|
AdvSceneSwitcher.action.variable.type.set="Set to value"
|
||||||
AdvSceneSwitcher.action.variable.type.append="Append"
|
AdvSceneSwitcher.action.variable.type.append="Append"
|
||||||
|
AdvSceneSwitcher.action.variable.type.copy="Copy variable"
|
||||||
AdvSceneSwitcher.action.variable.type.appendVar="Append variable"
|
AdvSceneSwitcher.action.variable.type.appendVar="Append variable"
|
||||||
AdvSceneSwitcher.action.variable.type.increment="Increment"
|
AdvSceneSwitcher.action.variable.type.increment="Increment"
|
||||||
AdvSceneSwitcher.action.variable.type.decrement="Decrement"
|
AdvSceneSwitcher.action.variable.type.decrement="Decrement"
|
||||||
@@ -1189,6 +1244,8 @@ AdvSceneSwitcher.action.sceneLock.entry="On{{scenes}}{{actions}}{{sources}}"
|
|||||||
AdvSceneSwitcher.action.twitch="Twitch"
|
AdvSceneSwitcher.action.twitch="Twitch"
|
||||||
AdvSceneSwitcher.action.twitch.type.channel.info.title.set="Set stream title"
|
AdvSceneSwitcher.action.twitch.type.channel.info.title.set="Set stream title"
|
||||||
AdvSceneSwitcher.action.twitch.type.channel.info.category.set="Set stream category"
|
AdvSceneSwitcher.action.twitch.type.channel.info.category.set="Set stream category"
|
||||||
|
AdvSceneSwitcher.action.twitch.type.channel.info.tags.set="Set stream tags"
|
||||||
|
AdvSceneSwitcher.action.twitch.type.channel.info.language.set="Set stream language"
|
||||||
AdvSceneSwitcher.action.twitch.type.raid.start="Start raid"
|
AdvSceneSwitcher.action.twitch.type.raid.start="Start raid"
|
||||||
AdvSceneSwitcher.action.twitch.type.commercial.start="Start commercial"
|
AdvSceneSwitcher.action.twitch.type.commercial.start="Start commercial"
|
||||||
AdvSceneSwitcher.action.twitch.type.marker.create="Create stream marker"
|
AdvSceneSwitcher.action.twitch.type.marker.create="Create stream marker"
|
||||||
@@ -1216,6 +1273,58 @@ AdvSceneSwitcher.action.twitch.announcement.orange="Orange"
|
|||||||
AdvSceneSwitcher.action.twitch.announcement.purple="Purple"
|
AdvSceneSwitcher.action.twitch.announcement.purple="Purple"
|
||||||
AdvSceneSwitcher.action.twitch.user.getInfo.queryType.id="User Id"
|
AdvSceneSwitcher.action.twitch.user.getInfo.queryType.id="User Id"
|
||||||
AdvSceneSwitcher.action.twitch.user.getInfo.queryType.login="User login"
|
AdvSceneSwitcher.action.twitch.user.getInfo.queryType.login="User login"
|
||||||
|
AdvSceneSwitcher.action.twitch.tags.add="Add Channel Tag"
|
||||||
|
AdvSceneSwitcher.action.twitch.tags.getCurrent="Get current channel tags"
|
||||||
|
AdvSceneSwitcher.action.twitch.tags.invalid="Invalid Tag"
|
||||||
|
AdvSceneSwitcher.action.twitch.tags.invalid.info="Tags must be 1–%1 characters long, contain only letters or numbers, and have no spaces or special characters."
|
||||||
|
AdvSceneSwitcher.action.twitch.tags.duplicate="Duplicate Tag"
|
||||||
|
AdvSceneSwitcher.action.twitch.tags.duplicate.info="This tag is already in the list."
|
||||||
|
AdvSceneSwitcher.action.twitch.tags.limit="Tag Limit Reached"
|
||||||
|
AdvSceneSwitcher.action.twitch.tags.limit.info="You can only have up to %1 tags."
|
||||||
|
AdvSceneSwitcher.action.twitch.type.channel.info.contentClassification.set="Set content classification labels"
|
||||||
|
AdvSceneSwitcher.action.twitch.contentClassification.debatedSocialIssuesAndPolitics="Discussions or debates about politics or sensitive social issues such as elections, civic integrity, military conflict, and civil rights."
|
||||||
|
AdvSceneSwitcher.action.twitch.contentClassification.drugsIntoxication="Excessive tobacco glorification or promotion, any marijuana consumption/use, legal drug and alcohol induced intoxication, discussions of illegal drugs."
|
||||||
|
AdvSceneSwitcher.action.twitch.contentClassification.sexualThemes="Content that focuses on sexualized activities, sexual topics, or experiences."
|
||||||
|
AdvSceneSwitcher.action.twitch.contentClassification.violentGraphic="Simulations and/or depictions of realistic violence, gore, extreme injury, or death."
|
||||||
|
AdvSceneSwitcher.action.twitch.contentClassification.gambling="Participating in or promoting online or in-person gambling, poker, or fantasy sports that involve the exchange of real money."
|
||||||
|
AdvSceneSwitcher.action.twitch.contentClassification.profanityVulgarity="Prolonged and repeated use of obscenities, profanities, and vulgarities, especially as a regular part of speech."
|
||||||
|
AdvSceneSwitcher.action.twitch.contentClassification.getCurrent="Get current content classification labels"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.english="English"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.indonesian="Bahasa Indonesia"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.catalan="Català"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.danish="Dansk"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.german="Deutsch"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.spanish="Español"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.french="Français"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.italian="Italiano"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.hungarian="Magyar"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.dutch="Nederlands"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.norwegian="Norsk"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.polish="Polski"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.portuguese="Português"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.romanian="Română"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.slovak="Slovenčina"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.finnish="Suomi"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.swedish="Svenska"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.tagalog="Tagalog"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.vietnamese="Tiếng Việt"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.turkish="Türkçe"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.czech="Čeština"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.greek="Ελληνικά"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.bulgarian="Български"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.russian="Русский"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.ukrainian="Українська"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.arabic="العربية"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.malay="بهاس ملايو"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.hindi="मानक हिन्दी"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.thai="ภาษาไทย"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.chinese="中文"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.japanese="日本語"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.cantonese="粵語"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.korean="한국어"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.asl="American Sign Language"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.other="Other"
|
||||||
|
AdvSceneSwitcher.action.twitch.language.getCurrent="Get current language"
|
||||||
AdvSceneSwitcher.action.clipboard="Clipboard"
|
AdvSceneSwitcher.action.clipboard="Clipboard"
|
||||||
AdvSceneSwitcher.action.clipboard.type.copy.text="Copy text"
|
AdvSceneSwitcher.action.clipboard.type.copy.text="Copy text"
|
||||||
AdvSceneSwitcher.action.clipboard.type.copy.image="Copy image"
|
AdvSceneSwitcher.action.clipboard.type.copy.image="Copy image"
|
||||||
@@ -1255,6 +1364,9 @@ AdvSceneSwitcher.action.obsSetting.action.setBaseCanvasX="Set base resolution X
|
|||||||
AdvSceneSwitcher.action.obsSetting.action.setBaseCanvasY="Set base resolution Y value"
|
AdvSceneSwitcher.action.obsSetting.action.setBaseCanvasY="Set base resolution Y value"
|
||||||
AdvSceneSwitcher.action.obsSetting.action.setOutputCanvasX="Set output resolution X value"
|
AdvSceneSwitcher.action.obsSetting.action.setOutputCanvasX="Set output resolution X value"
|
||||||
AdvSceneSwitcher.action.obsSetting.action.setOutputCanvasY="Set output resolution Y value"
|
AdvSceneSwitcher.action.obsSetting.action.setOutputCanvasY="Set output resolution Y value"
|
||||||
|
AdvSceneSwitcher.action.obsSetting.action.enablePreview="Enable preview"
|
||||||
|
AdvSceneSwitcher.action.obsSetting.action.disablePreview="Disable preview"
|
||||||
|
AdvSceneSwitcher.action.obsSetting.action.togglePreview="Toggle preview enable"
|
||||||
AdvSceneSwitcher.action.obsSetting.getCurrentValue="Get current value"
|
AdvSceneSwitcher.action.obsSetting.getCurrentValue="Get current value"
|
||||||
AdvSceneSwitcher.action.obsSettings.layout="{{actions}}{{fpsType}}{{fpsIntValue}}{{fpsStringValue}}{{canvasSizeValue}}{{getCurrentValue}}"
|
AdvSceneSwitcher.action.obsSettings.layout="{{actions}}{{fpsType}}{{fpsIntValue}}{{fpsStringValue}}{{canvasSizeValue}}{{getCurrentValue}}"
|
||||||
AdvSceneSwitcher.action.script="Script"
|
AdvSceneSwitcher.action.script="Script"
|
||||||
@@ -1425,6 +1537,13 @@ AdvSceneSwitcher.mqttConnection.name="Name:"
|
|||||||
AdvSceneSwitcher.mqttConnection.address="Address:"
|
AdvSceneSwitcher.mqttConnection.address="Address:"
|
||||||
AdvSceneSwitcher.mqttConnection.username="Username:"
|
AdvSceneSwitcher.mqttConnection.username="Username:"
|
||||||
AdvSceneSwitcher.mqttConnection.password="Password:"
|
AdvSceneSwitcher.mqttConnection.password="Password:"
|
||||||
|
AdvSceneSwitcher.mqttConnection.trustStore="Trust store:"
|
||||||
|
AdvSceneSwitcher.mqttConnection.trustStore.help="The file in PEM format containing the public digital certificates trusted by the client."
|
||||||
|
AdvSceneSwitcher.mqttConnection.keyStore="Key store:"
|
||||||
|
AdvSceneSwitcher.mqttConnection.keyStore.help="The file in PEM format containing the public certificate chain of the client.\nIt may also include the client's private key."
|
||||||
|
AdvSceneSwitcher.mqttConnection.privateKey="Private key:"
|
||||||
|
AdvSceneSwitcher.mqttConnection.privateKey.help="If not included in the key store, this is the file in PEM format containing the client's private key."
|
||||||
|
AdvSceneSwitcher.mqttConnection.verifyServerCert="Verify server certificate"
|
||||||
AdvSceneSwitcher.mqttConnection.reconnect="Reconnect automatically:"
|
AdvSceneSwitcher.mqttConnection.reconnect="Reconnect automatically:"
|
||||||
AdvSceneSwitcher.mqttConnection.reconnectDelay="Automatically reconnect after:"
|
AdvSceneSwitcher.mqttConnection.reconnectDelay="Automatically reconnect after:"
|
||||||
AdvSceneSwitcher.mqttConnection.connectOnStart="Connect on startup:"
|
AdvSceneSwitcher.mqttConnection.connectOnStart="Connect on startup:"
|
||||||
@@ -1470,6 +1589,7 @@ AdvSceneSwitcher.twitchToken.bits.read="Read channel's Bits information."
|
|||||||
AdvSceneSwitcher.twitchToken.channel.raids.manage="Manage channel's raids."
|
AdvSceneSwitcher.twitchToken.channel.raids.manage="Manage channel's raids."
|
||||||
AdvSceneSwitcher.twitchToken.moderator.shoutouts.read="Read channel's shoutouts."
|
AdvSceneSwitcher.twitchToken.moderator.shoutouts.read="Read channel's shoutouts."
|
||||||
AdvSceneSwitcher.twitchToken.moderator.shoutouts.manage="Manage channel's shoutouts."
|
AdvSceneSwitcher.twitchToken.moderator.shoutouts.manage="Manage channel's shoutouts."
|
||||||
|
AdvSceneSwitcher.twitchToken.channel.ads.read="Read the ads schedule and details on your channel."
|
||||||
AdvSceneSwitcher.twitchToken.channel.polls.read="Read channel's polls' state."
|
AdvSceneSwitcher.twitchToken.channel.polls.read="Read channel's polls' state."
|
||||||
AdvSceneSwitcher.twitchToken.channel.polls.manage="Manage channel's polls."
|
AdvSceneSwitcher.twitchToken.channel.polls.manage="Manage channel's polls."
|
||||||
AdvSceneSwitcher.twitchToken.channel.predictions.read="Read channel's predictions' state."
|
AdvSceneSwitcher.twitchToken.channel.predictions.read="Read channel's predictions' state."
|
||||||
@@ -1495,7 +1615,11 @@ AdvSceneSwitcher.twitchToken.moderator.chat.settings.manage="Manage channel's ch
|
|||||||
AdvSceneSwitcher.twitchToken.user.whispers.manage="Manage user's whispers."
|
AdvSceneSwitcher.twitchToken.user.whispers.manage="Manage user's whispers."
|
||||||
AdvSceneSwitcher.twitchToken.chat.read="View live stream chat messages."
|
AdvSceneSwitcher.twitchToken.chat.read="View live stream chat messages."
|
||||||
AdvSceneSwitcher.twitchToken.chat.edit="Send live stream chat messages."
|
AdvSceneSwitcher.twitchToken.chat.edit="Send live stream chat messages."
|
||||||
AdvSceneSwitcher.twitchToken.validateTimestamps="Validate timestamps of received Twitch event messages. (Recommended)"
|
AdvSceneSwitcher.twitchToken.validateTimestamps="Validate timestamps of received Twitch event messages."
|
||||||
|
AdvSceneSwitcher.twitchToken.validateTimestamps.tooltip="Verifies that incoming Twitch messages have valid timestamps to prevent replayed or spoofed messages.\nDisabling this won’t affect normal functionality, and you can try turning it off if you experience issues with the Twitch connection."
|
||||||
|
AdvSceneSwitcher.twitchToken.warnIfInvalid="Display warning if the token expired or is invalid."
|
||||||
|
AdvSceneSwitcher.twitchToken.warnIfInvalid.doNotShowAgain="Don't show again for this connection"
|
||||||
|
AdvSceneSwitcher.twitchToken.warnIfInvalid.message="The Twitch connection \"%1\" is invalid.\nOpen connection settings or ignore?"
|
||||||
|
|
||||||
AdvSceneSwitcher.twitch.selection.channel.open="Open channel"
|
AdvSceneSwitcher.twitch.selection.channel.open="Open channel"
|
||||||
AdvSceneSwitcher.twitch.selection.channel.open.tooltip.details="Open channel in external application handling the HTTPS protocol."
|
AdvSceneSwitcher.twitch.selection.channel.open.tooltip.details="Open channel in external application handling the HTTPS protocol."
|
||||||
@@ -1531,6 +1655,9 @@ AdvSceneSwitcher.script.language.select="--select language--"
|
|||||||
AdvSceneSwitcher.script.language.layout="Script language:{{language}}"
|
AdvSceneSwitcher.script.language.layout="Script language:{{language}}"
|
||||||
AdvSceneSwitcher.script.file.open="Open"
|
AdvSceneSwitcher.script.file.open="Open"
|
||||||
AdvSceneSwitcher.script.file.open.failed="Could not open script file!"
|
AdvSceneSwitcher.script.file.open.failed="Could not open script file!"
|
||||||
|
AdvSceneSwitcher.script.file.warning.notFound="Warning: The given file path was not found!"
|
||||||
|
AdvSceneSwitcher.script.file.warning.openFail="Warning: Could not open the script file!"
|
||||||
|
AdvSceneSwitcher.script.file.warning.loadMissing="Warning: The script is missing a 'script_load' function!"
|
||||||
AdvSceneSwitcher.script.file.layout="Script file:{{path}}{{open}}"
|
AdvSceneSwitcher.script.file.layout="Script file:{{path}}{{open}}"
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.select="--select value--"
|
AdvSceneSwitcher.tempVar.select="--select value--"
|
||||||
@@ -1982,6 +2109,18 @@ AdvSceneSwitcher.tempVar.twitch.offline_image_url.user.getInfo="Offline image UR
|
|||||||
AdvSceneSwitcher.tempVar.twitch.created_at.user.getInfo="Account creation date"
|
AdvSceneSwitcher.tempVar.twitch.created_at.user.getInfo="Account creation date"
|
||||||
AdvSceneSwitcher.tempVar.twitch.created_at.user.getInfo.description="The UTC date and time that the user's account was created. The timestamp is in RFC3339 format."
|
AdvSceneSwitcher.tempVar.twitch.created_at.user.getInfo.description="The UTC date and time that the user's account was created. The timestamp is in RFC3339 format."
|
||||||
|
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.duration_seconds.commercial="Duration"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.duration_seconds.commercial.description="Length in seconds of the mid-roll ad break requested."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.started_at.commercial="Started at"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.started_at.commercial.description="The UTC timestamp of when the ad break began, in RFC3339 format. Note that there is potential delay between this event, when the streamer requested the ad break, and when the viewers will see ads."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.is_automatic.commercial="Was automatic"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.is_automatic.commercial.description="Indicates if the ad was automatically scheduled via Ads Manager"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.requester_user_id.commercial="Requester user ID"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.requester_user_id.commercial.description="The ID of the user that requested the ad. For automatic ads, this will be the ID of the broadcaster."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.requester_user_login.commercial="Requester user login"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.requester_user_login.commercial.description="The login of the user that requested the ad."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.requester_user_name.commercial="Requester user name"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.requester_user_name.commercial.description="The display name of the user that requested the ad."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.audio.output_volume="Output volume"
|
AdvSceneSwitcher.tempVar.audio.output_volume="Output volume"
|
||||||
AdvSceneSwitcher.tempVar.audio.output_volume.description="The volume the audio source is outputting."
|
AdvSceneSwitcher.tempVar.audio.output_volume.description="The volume the audio source is outputting."
|
||||||
@@ -2000,6 +2139,7 @@ AdvSceneSwitcher.tempVar.clipboard.mimeType.all.description="All MIME types of t
|
|||||||
AdvSceneSwitcher.tempVar.scene.current="Current scene"
|
AdvSceneSwitcher.tempVar.scene.current="Current scene"
|
||||||
AdvSceneSwitcher.tempVar.scene.previous="Previous scene"
|
AdvSceneSwitcher.tempVar.scene.previous="Previous scene"
|
||||||
AdvSceneSwitcher.tempVar.scene.preview="Preview scene"
|
AdvSceneSwitcher.tempVar.scene.preview="Preview scene"
|
||||||
|
AdvSceneSwitcher.tempVar.scene.position="Position in scenes list"
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.window.window="Window title"
|
AdvSceneSwitcher.tempVar.window.window="Window title"
|
||||||
AdvSceneSwitcher.tempVar.window.window.description="The window title of the matching window."
|
AdvSceneSwitcher.tempVar.window.window.description="The window title of the matching window."
|
||||||
@@ -2046,6 +2186,8 @@ AdvSceneSwitcher.tempVar.run.process.none.description="When not waiting for the
|
|||||||
|
|
||||||
AdvSceneSwitcher.tempVar.recording.durationSeconds="Recording duration"
|
AdvSceneSwitcher.tempVar.recording.durationSeconds="Recording duration"
|
||||||
AdvSceneSwitcher.tempVar.recording.durationSeconds.description="Recording duration in seconds.\nThis value does not change while the recording is paused and will be reset to zero if the recording is stopped."
|
AdvSceneSwitcher.tempVar.recording.durationSeconds.description="Recording duration in seconds.\nThis value does not change while the recording is paused and will be reset to zero if the recording is stopped."
|
||||||
|
AdvSceneSwitcher.tempVar.recording.lastSavePath="Last save path"
|
||||||
|
AdvSceneSwitcher.tempVar.recording.lastSavePath.description="The file path of the last saved recording."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.video.patternCount="Pattern count"
|
AdvSceneSwitcher.tempVar.video.patternCount="Pattern count"
|
||||||
AdvSceneSwitcher.tempVar.video.patternCount.description="The number of times the given pattern has been found in a given video input frame."
|
AdvSceneSwitcher.tempVar.video.patternCount.description="The number of times the given pattern has been found in a given video input frame."
|
||||||
@@ -2083,6 +2225,19 @@ AdvSceneSwitcher.tempVar.clipboard.text.description="The text contained in the c
|
|||||||
|
|
||||||
AdvSceneSwitcher.tempVar.file.content="File content"
|
AdvSceneSwitcher.tempVar.file.content="File content"
|
||||||
AdvSceneSwitcher.tempVar.file.date="File modification date"
|
AdvSceneSwitcher.tempVar.file.date="File modification date"
|
||||||
|
AdvSceneSwitcher.tempVar.file.basename="File basename"
|
||||||
|
AdvSceneSwitcher.tempVar.file.basename.description="Returns the base name of the file without the path.\nThe base name consists of all characters in the file up to (but not including) the first '.' character."
|
||||||
|
AdvSceneSwitcher.tempVar.file.basenameComplete="File basename (complete)"
|
||||||
|
AdvSceneSwitcher.tempVar.file.basenameComplete.description="Returns the complete base name of the file without the path.\nThe complete base name consists of all characters in the file up to (but not including) the last '.' character."
|
||||||
|
AdvSceneSwitcher.tempVar.file.suffix="File suffix"
|
||||||
|
AdvSceneSwitcher.tempVar.file.suffix.description="Returns the suffix (extension) of the file.\nThe suffix consists of all characters in the file after (but not including) the last '.'."
|
||||||
|
AdvSceneSwitcher.tempVar.file.suffixComplete="File suffix (complete)"
|
||||||
|
AdvSceneSwitcher.tempVar.file.suffixComplete.description="Returns the complete suffix (extension) of the file.\nThe complete suffix consists of all characters in the file after (but not including) the first '.'."
|
||||||
|
AdvSceneSwitcher.tempVar.file.filename="File name"
|
||||||
|
AdvSceneSwitcher.tempVar.file.absoluteFilePath="Absolute file path"
|
||||||
|
AdvSceneSwitcher.tempVar.file.absolutePath="Absolute path"
|
||||||
|
AdvSceneSwitcher.tempVar.file.isAbsolutePath="Path is absolute"
|
||||||
|
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.folder.newFiles="New files"
|
AdvSceneSwitcher.tempVar.folder.newFiles="New files"
|
||||||
AdvSceneSwitcher.tempVar.folder.changedFiles="Changed files"
|
AdvSceneSwitcher.tempVar.folder.changedFiles="Changed files"
|
||||||
@@ -2116,6 +2271,8 @@ AdvSceneSwitcher.tempVar.usb.serialNumber="Serial Number"
|
|||||||
AdvSceneSwitcher.tempVar.transform.setting="Setting value"
|
AdvSceneSwitcher.tempVar.transform.setting="Setting value"
|
||||||
AdvSceneSwitcher.tempVar.transform.settings="Settings string"
|
AdvSceneSwitcher.tempVar.transform.settings="Settings string"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.tempVar.media.source="Source"
|
||||||
|
AdvSceneSwitcher.tempVar.media.source.description="The name of the source which matched.\nIf multiple sources matched the last one is returned."
|
||||||
AdvSceneSwitcher.tempVar.media.state="State"
|
AdvSceneSwitcher.tempVar.media.state="State"
|
||||||
AdvSceneSwitcher.tempVar.media.state.description="The current media state represented as an integer value:\n0 being 'None'\n1 being 'Playing'\n2 being 'Opening'\n3 being 'Buffering'\n4 being 'Paused'\n5 being 'Stopped'\n6 being 'Ended'\n7 being 'Error'"
|
AdvSceneSwitcher.tempVar.media.state.description="The current media state represented as an integer value:\n0 being 'None'\n1 being 'Playing'\n2 being 'Opening'\n3 being 'Buffering'\n4 being 'Paused'\n5 being 'Stopped'\n6 being 'Ended'\n7 being 'Error'"
|
||||||
AdvSceneSwitcher.tempVar.media.time="Current time"
|
AdvSceneSwitcher.tempVar.media.time="Current time"
|
||||||
@@ -2180,7 +2337,11 @@ AdvSceneSwitcher.tempVar.mqtt.message="Message"
|
|||||||
AdvSceneSwitcher.tempVar.cursor.x="Cursor position (X)"
|
AdvSceneSwitcher.tempVar.cursor.x="Cursor position (X)"
|
||||||
AdvSceneSwitcher.tempVar.cursor.y="Cursor position (Y)"
|
AdvSceneSwitcher.tempVar.cursor.y="Cursor position (Y)"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.tempVar.replay.lastSavePath="Last save path"
|
||||||
|
AdvSceneSwitcher.tempVar.replay.lastSavePath.description="The file path of the last replay buffer saved."
|
||||||
|
|
||||||
AdvSceneSwitcher.selectScene="--select scene--"
|
AdvSceneSwitcher.selectScene="--select scene--"
|
||||||
|
AdvSceneSwitcher.selectCanvas="--select canvas--"
|
||||||
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
||||||
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
||||||
AdvSceneSwitcher.selectPreviewScene="Preview Scene"
|
AdvSceneSwitcher.selectPreviewScene="Preview Scene"
|
||||||
@@ -2241,21 +2402,23 @@ AdvSceneSwitcher.setting.transform.width="Width"
|
|||||||
|
|
||||||
AdvSceneSwitcher.sceneItemSelection.configure="Configure scene item selection type"
|
AdvSceneSwitcher.sceneItemSelection.configure="Configure scene item selection type"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceName="Source name"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceName="Source name"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceName.entry="{{nameConflictIndex}}{{sourceName}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceName.layout="{{nameConflictIndex}}{{sourceName}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable="Variable name"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable="Variable name"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable.entry="{{nameConflictIndex}}{{variable}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable.layout="{{nameConflictIndex}}{{variable}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="Source name matches pattern"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="Source name matches pattern"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.entry="{{nameConflictIndex}}matching{{pattern}}{{regex}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.layout="{{nameConflictIndex}}matching{{pattern}}{{regex}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup="Sources in source group"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup="Sources in source group"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup.entry="Sources in{{sourceGroups}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup.layout="{{nameConflictIndex}}Sources in{{sourceGroups}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceType="Sources of type"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType="Sources of type"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceType.entry="Source type{{nameConflictIndex}}{{sourceTypes}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType.layout="Source type{{nameConflictIndex}}{{sourceTypes}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index="Source with index"
|
AdvSceneSwitcher.sceneItemSelection.type.index="Source with index"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index.entry="{{index}}source"
|
AdvSceneSwitcher.sceneItemSelection.type.index.layout="{{index}}source"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.indexRange="Sources in index range"
|
AdvSceneSwitcher.sceneItemSelection.type.indexRange="Sources in index range"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.indexRange.entry="Sources from{{index}}to{{indexEnd}}"
|
AdvSceneSwitcher.sceneItemSelection.type.indexRange.layout="Sources from{{index}}to{{indexEnd}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.all="All sources"
|
AdvSceneSwitcher.sceneItemSelection.type.all="All sources"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.all.entry="All sources"
|
AdvSceneSwitcher.sceneItemSelection.type.all.layout="All sources"
|
||||||
|
AdvSceneSwitcher.sceneItemSelection.type.any="Any source"
|
||||||
|
AdvSceneSwitcher.sceneItemSelection.type.any.layout="Any source"
|
||||||
AdvSceneSwitcher.sceneItemSelection.all="All"
|
AdvSceneSwitcher.sceneItemSelection.all="All"
|
||||||
AdvSceneSwitcher.sceneItemSelection.any="Any"
|
AdvSceneSwitcher.sceneItemSelection.any="Any"
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart="Siempre iniciar el sel
|
|||||||
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="No iniciar el selector de escenas"
|
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="No iniciar el selector de escenas"
|
||||||
AdvSceneSwitcher.generalTab.status.start="Iniciar"
|
AdvSceneSwitcher.generalTab.status.start="Iniciar"
|
||||||
AdvSceneSwitcher.generalTab.status.stop="Detener"
|
AdvSceneSwitcher.generalTab.status.stop="Detener"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart="Iniciar automáticamente el selector de escenas cuando:"
|
AdvSceneSwitcher.generalTab.status.autoStart.startup="Iniciar automáticamente el selector de escenas cuando:"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.never="Nunca"
|
AdvSceneSwitcher.generalTab.status.autoStart.never="Nunca"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.recording="Grabando"
|
AdvSceneSwitcher.generalTab.status.autoStart.recording="Grabando"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Emitiendo"
|
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Emitiendo"
|
||||||
@@ -311,7 +311,6 @@ AdvSceneSwitcher.condition.stats.entry="{{stats}} esta {{condition}} {{value}}"
|
|||||||
|
|
||||||
; Macro Actions
|
; Macro Actions
|
||||||
AdvSceneSwitcher.action.scene="Cambiar escena"
|
AdvSceneSwitcher.action.scene="Cambiar escena"
|
||||||
AdvSceneSwitcher.action.scene.entry="Cambiar a la{{sceneTypes}}escena{{scenes}}usando{{transitions}}con una duración de{{duration}} segundos"
|
|
||||||
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Espere hasta que se complete la transición a la escena de destino"
|
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Espere hasta que se complete la transición a la escena de destino"
|
||||||
AdvSceneSwitcher.action.wait="Esperar"
|
AdvSceneSwitcher.action.wait="Esperar"
|
||||||
AdvSceneSwitcher.action.wait.type.fixed="fijo"
|
AdvSceneSwitcher.action.wait.type.fixed="fijo"
|
||||||
@@ -383,7 +382,7 @@ AdvSceneSwitcher.action.pluginState.type.stop="Detener el complemento Advanced S
|
|||||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Cambiar el comportamiento de no coincidencia:"
|
AdvSceneSwitcher.action.pluginState.type.noMatch="Cambiar el comportamiento de no coincidencia:"
|
||||||
AdvSceneSwitcher.action.pluginState.type.import="Importar configuración desde"
|
AdvSceneSwitcher.action.pluginState.type.import="Importar configuración desde"
|
||||||
AdvSceneSwitcher.action.pluginState.importWarning="Nota: la acción se ignorará mientras se abra la ventana de configuración."
|
AdvSceneSwitcher.action.pluginState.importWarning="Nota: la acción se ignorará mientras se abra la ventana de configuración."
|
||||||
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
|
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}"
|
||||||
AdvSceneSwitcher.action.virtualCamera="Cámara virtual"
|
AdvSceneSwitcher.action.virtualCamera="Cámara virtual"
|
||||||
AdvSceneSwitcher.action.virtualCamera.type.stop="Detener cámara virtual"
|
AdvSceneSwitcher.action.virtualCamera.type.stop="Detener cámara virtual"
|
||||||
AdvSceneSwitcher.action.virtualCamera.type.start="Iniciar cámara virtual"
|
AdvSceneSwitcher.action.virtualCamera.type.start="Iniciar cámara virtual"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart="Toujours démarrer le
|
|||||||
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Ne pas démarrer le sélecteur de scène"
|
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Ne pas démarrer le sélecteur de scène"
|
||||||
AdvSceneSwitcher.generalTab.status.start="Démarrer"
|
AdvSceneSwitcher.generalTab.status.start="Démarrer"
|
||||||
AdvSceneSwitcher.generalTab.status.stop="Arrêter"
|
AdvSceneSwitcher.generalTab.status.stop="Arrêter"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart="Démarrer automatiquement le sélecteur de scène lorsque :"
|
AdvSceneSwitcher.generalTab.status.autoStart.startup="Démarrer automatiquement le sélecteur de scène lorsque :"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.never="Jamais"
|
AdvSceneSwitcher.generalTab.status.autoStart.never="Jamais"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.recording="Enregistrement"
|
AdvSceneSwitcher.generalTab.status.autoStart.recording="Enregistrement"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Diffusion en continu"
|
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Diffusion en continu"
|
||||||
@@ -459,8 +459,6 @@ AdvSceneSwitcher.condition.slideshow.updateInterval.tooltip="Les informations su
|
|||||||
AdvSceneSwitcher.action.scene="Changer de scène"
|
AdvSceneSwitcher.action.scene="Changer de scène"
|
||||||
AdvSceneSwitcher.action.scene.type.program="Programme"
|
AdvSceneSwitcher.action.scene.type.program="Programme"
|
||||||
AdvSceneSwitcher.action.scene.type.preview="Aperçu"
|
AdvSceneSwitcher.action.scene.type.preview="Aperçu"
|
||||||
AdvSceneSwitcher.action.scene.entry="Changer la scène{{sceneTypes}}{{scenes}}en utilisant{{transitions}}avec une durée de{{duration}}secondes"
|
|
||||||
AdvSceneSwitcher.action.scene.entry.noDuration="Changer la scène{{sceneTypes}}{{scenes}}en utilisant{{transitions}}"
|
|
||||||
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Attendre que la transition vers la scène cible soit terminée"
|
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Attendre que la transition vers la scène cible soit terminée"
|
||||||
AdvSceneSwitcher.action.wait="Attendre"
|
AdvSceneSwitcher.action.wait="Attendre"
|
||||||
AdvSceneSwitcher.action.wait.type.fixed="fixe"
|
AdvSceneSwitcher.action.wait.type.fixed="fixe"
|
||||||
@@ -1107,15 +1105,15 @@ AdvSceneSwitcher.sceneItemSelection.configure="Configurer le type de sélection
|
|||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceName="Nom de la source"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceName="Nom de la source"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable="Nom de la variable"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable="Nom de la variable"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="Le nom de la source correspond au motif"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="Le nom de la source correspond au motif"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.entry="{{nameConflictIndex}}correspondant à{{pattern}}{{regex}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.layout="{{nameConflictIndex}}correspondant à{{pattern}}{{regex}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceType="Sources de type"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType="Sources de type"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceType.entry="{{nameConflictIndex}}Type de source{{sourceTypes}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType.layout="{{nameConflictIndex}}Type de source{{sourceTypes}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index="Source avec index"
|
AdvSceneSwitcher.sceneItemSelection.type.index="Source avec index"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index.entry="{{index}}source"
|
AdvSceneSwitcher.sceneItemSelection.type.index.layout="{{index}}source"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.indexRange="Sources dans la plage d'index"
|
AdvSceneSwitcher.sceneItemSelection.type.indexRange="Sources dans la plage d'index"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.indexRange.entry="Sources de{{index}}à{{indexEnd}}"
|
AdvSceneSwitcher.sceneItemSelection.type.indexRange.layout="Sources de{{index}}à{{indexEnd}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.all="Toutes les sources"
|
AdvSceneSwitcher.sceneItemSelection.type.all="Toutes les sources"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.all.entry="Toutes les sources"
|
AdvSceneSwitcher.sceneItemSelection.type.all.layout="Toutes les sources"
|
||||||
AdvSceneSwitcher.sceneItemSelection.all="Tout"
|
AdvSceneSwitcher.sceneItemSelection.all="Tout"
|
||||||
AdvSceneSwitcher.sceneItemSelection.any="N'importe lequel"
|
AdvSceneSwitcher.sceneItemSelection.any="N'importe lequel"
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -12,7 +12,7 @@ AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart="Sempre iniciar o switc
|
|||||||
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Não iniciar o switcher de cenas"
|
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Não iniciar o switcher de cenas"
|
||||||
AdvSceneSwitcher.generalTab.status.start="Iniciar"
|
AdvSceneSwitcher.generalTab.status.start="Iniciar"
|
||||||
AdvSceneSwitcher.generalTab.status.stop="Parar"
|
AdvSceneSwitcher.generalTab.status.stop="Parar"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart="Iniciar automaticamente o switcher de cenas quando:"
|
AdvSceneSwitcher.generalTab.status.autoStart.startup="Iniciar automaticamente o switcher de cenas quando:"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.never="Nunca"
|
AdvSceneSwitcher.generalTab.status.autoStart.never="Nunca"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.recording="Gravando"
|
AdvSceneSwitcher.generalTab.status.autoStart.recording="Gravando"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Transmitindo"
|
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Transmitindo"
|
||||||
@@ -720,9 +720,6 @@ AdvSceneSwitcher.condition.noDevicesFoundWarning="Nenhum dispositivo USB detecta
|
|||||||
AdvSceneSwitcher.action.scene="Trocar cena"
|
AdvSceneSwitcher.action.scene="Trocar cena"
|
||||||
AdvSceneSwitcher.action.scene.type.program="Programa"
|
AdvSceneSwitcher.action.scene.type.program="Programa"
|
||||||
AdvSceneSwitcher.action.scene.type.preview="Pré-visualização"
|
AdvSceneSwitcher.action.scene.type.preview="Pré-visualização"
|
||||||
AdvSceneSwitcher.action.scene.entry="Trocar{{sceneTypes}}cena para{{scenes}}usando{{transitions}}com duração de{{duration}}segundos"
|
|
||||||
AdvSceneSwitcher.action.scene.entry.noDuration="Trocar{{sceneTypes}}cena para{{scenes}}usando{{transitions}}"
|
|
||||||
AdvSceneSwitcher.action.scene.entry.preview="Trocar{{sceneTypes}}cena para{{scenes}}"
|
|
||||||
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Aguardar até que a transição para a cena de destino seja concluída"
|
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Aguardar até que a transição para a cena de destino seja concluída"
|
||||||
AdvSceneSwitcher.action.wait="Aguardar"
|
AdvSceneSwitcher.action.wait="Aguardar"
|
||||||
AdvSceneSwitcher.action.wait.type.fixed="fixo"
|
AdvSceneSwitcher.action.wait.type.fixed="fixo"
|
||||||
@@ -864,9 +861,9 @@ AdvSceneSwitcher.action.macro.type.stop="Parar ações"
|
|||||||
AdvSceneSwitcher.action.macro.type.disableAction="Desabilitar ação"
|
AdvSceneSwitcher.action.macro.type.disableAction="Desabilitar ação"
|
||||||
AdvSceneSwitcher.action.macro.type.enableAction="Habilitar ação"
|
AdvSceneSwitcher.action.macro.type.enableAction="Habilitar ação"
|
||||||
AdvSceneSwitcher.action.macro.type.toggleAction="Alternar ação"
|
AdvSceneSwitcher.action.macro.type.toggleAction="Alternar ação"
|
||||||
AdvSceneSwitcher.action.macro.entry.run="{{actions}}{{actionTypes}}de{{macros}}"
|
AdvSceneSwitcher.action.macro.layout.run="{{actions}}{{actionSections}}de{{macros}}"
|
||||||
AdvSceneSwitcher.action.macro.entry.run.condition="{{conditionBehaviors}}de{{conditionMacros}}"
|
AdvSceneSwitcher.action.macro.layout.run.condition="{{conditionBehaviors}}de{{conditionMacros}}"
|
||||||
AdvSceneSwitcher.action.macro.entry.other="{{actions}}{{actionIndex}}{{macros}}"
|
AdvSceneSwitcher.action.macro.layout.other="{{actions}}{{macros}}"
|
||||||
AdvSceneSwitcher.action.pluginState="Estado do plugin"
|
AdvSceneSwitcher.action.pluginState="Estado do plugin"
|
||||||
AdvSceneSwitcher.action.pluginState.type.stop="Parar o plugin Advanced Scene Switcher"
|
AdvSceneSwitcher.action.pluginState.type.stop="Parar o plugin Advanced Scene Switcher"
|
||||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Alterar o comportamento em caso de não correspondência:"
|
AdvSceneSwitcher.action.pluginState.type.noMatch="Alterar o comportamento em caso de não correspondência:"
|
||||||
@@ -874,7 +871,7 @@ AdvSceneSwitcher.action.pluginState.type.import="Importar configurações de"
|
|||||||
AdvSceneSwitcher.action.pluginState.importWarning="Nota: Ação será ignorada enquanto a janela de configurações estiver aberta."
|
AdvSceneSwitcher.action.pluginState.importWarning="Nota: Ação será ignorada enquanto a janela de configurações estiver aberta."
|
||||||
AdvSceneSwitcher.action.pluginState.type.terminate="Desligar OBS"
|
AdvSceneSwitcher.action.pluginState.type.terminate="Desligar OBS"
|
||||||
AdvSceneSwitcher.action.pluginState.terminateConfirm="O OBS será desligado automaticamente em 10 segundos!\nDeseja continuar com o desligamento do OBS?"
|
AdvSceneSwitcher.action.pluginState.terminateConfirm="O OBS será desligado automaticamente em 10 segundos!\nDeseja continuar com o desligamento do OBS?"
|
||||||
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
|
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}"
|
||||||
AdvSceneSwitcher.action.virtualCamera="Câmera virtual"
|
AdvSceneSwitcher.action.virtualCamera="Câmera virtual"
|
||||||
AdvSceneSwitcher.action.virtualCamera.type.stop="Parar câmera virtual"
|
AdvSceneSwitcher.action.virtualCamera.type.stop="Parar câmera virtual"
|
||||||
AdvSceneSwitcher.action.virtualCamera.type.start="Iniciar câmera virtual"
|
AdvSceneSwitcher.action.virtualCamera.type.start="Iniciar câmera virtual"
|
||||||
@@ -1851,19 +1848,19 @@ AdvSceneSwitcher.setting.transform.width="Largura"
|
|||||||
|
|
||||||
AdvSceneSwitcher.sceneItemSelection.configure="Configurar tipo de seleção de item de cena"
|
AdvSceneSwitcher.sceneItemSelection.configure="Configurar tipo de seleção de item de cena"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceName="Nome da fonte"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceName="Nome da fonte"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceName.entry="{{nameConflictIndex}}{{sourceName}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceName.layout="{{nameConflictIndex}}{{sourceName}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable="Nome da variável"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable="Nome da variável"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable.entry="{{nameConflictIndex}}{{variable}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable.layout="{{nameConflictIndex}}{{variable}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="Nome da fonte corresponde ao padrão"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="Nome da fonte corresponde ao padrão"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.entry="{{nameConflictIndex}}correspondendo{{pattern}}{{regex}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.layout="{{nameConflictIndex}}correspondendo{{pattern}}{{regex}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceType="Fontes do tipo"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType="Fontes do tipo"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceType.entry="Tipo de fonte{{nameConflictIndex}}{{sourceTypes}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType.layout="Tipo de fonte{{nameConflictIndex}}{{sourceTypes}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index="Fonte com índice"
|
AdvSceneSwitcher.sceneItemSelection.type.index="Fonte com índice"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index.entry="{{index}}fonte"
|
AdvSceneSwitcher.sceneItemSelection.type.index.layout="{{index}}fonte"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.indexRange="Fontes no intervalo de índices"
|
AdvSceneSwitcher.sceneItemSelection.type.indexRange="Fontes no intervalo de índices"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.indexRange.entry="Fontes de{{index}}para{{indexEnd}}"
|
AdvSceneSwitcher.sceneItemSelection.type.indexRange.layout="Fontes de{{index}}para{{indexEnd}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.all="Todas as fontes"
|
AdvSceneSwitcher.sceneItemSelection.type.all="Todas as fontes"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.all.entry="Todas as fontes"
|
AdvSceneSwitcher.sceneItemSelection.type.all.layout="Todas as fontes"
|
||||||
AdvSceneSwitcher.sceneItemSelection.all="Todas"
|
AdvSceneSwitcher.sceneItemSelection.all="Todas"
|
||||||
AdvSceneSwitcher.sceneItemSelection.any="Qualquer"
|
AdvSceneSwitcher.sceneItemSelection.any="Qualquer"
|
||||||
|
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart="Всегда запу
|
|||||||
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Не запускать переключатель сцен"
|
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Не запускать переключатель сцен"
|
||||||
AdvSceneSwitcher.generalTab.status.start="Старт"
|
AdvSceneSwitcher.generalTab.status.start="Старт"
|
||||||
AdvSceneSwitcher.generalTab.status.stop="Стоп"
|
AdvSceneSwitcher.generalTab.status.stop="Стоп"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart="Автоматически запускать переключатель сцен, когда:"
|
AdvSceneSwitcher.generalTab.status.autoStart.startup="Автоматически запускать переключатель сцен, когда:"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.never="Никогда"
|
AdvSceneSwitcher.generalTab.status.autoStart.never="Никогда"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.recording="Запись"
|
AdvSceneSwitcher.generalTab.status.autoStart.recording="Запись"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Вещание"
|
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Вещание"
|
||||||
@@ -114,7 +114,6 @@ AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
|
|||||||
|
|
||||||
; Macro Actions
|
; Macro Actions
|
||||||
AdvSceneSwitcher.action.scene="Переключить сцену"
|
AdvSceneSwitcher.action.scene="Переключить сцену"
|
||||||
AdvSceneSwitcher.action.scene.entry="Перейти к сцене{{sceneTypes}}{{scenes}}используя{{transitions}}с продолжительностью{{duration}}секунд"
|
|
||||||
AdvSceneSwitcher.action.wait="Подождать"
|
AdvSceneSwitcher.action.wait="Подождать"
|
||||||
AdvSceneSwitcher.action.wait.type.fixed="фиксированный"
|
AdvSceneSwitcher.action.wait.type.fixed="фиксированный"
|
||||||
AdvSceneSwitcher.action.wait.type.random="случайный"
|
AdvSceneSwitcher.action.wait.type.random="случайный"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart="Her zaman sahne deği
|
|||||||
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Sahne değiştiriciyi başlatma"
|
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="Sahne değiştiriciyi başlatma"
|
||||||
AdvSceneSwitcher.generalTab.status.start="Başlat"
|
AdvSceneSwitcher.generalTab.status.start="Başlat"
|
||||||
AdvSceneSwitcher.generalTab.status.stop="Durdur"
|
AdvSceneSwitcher.generalTab.status.stop="Durdur"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart="Aşağıdaki durumlarda sahne değiştiriciyi otomatik olarak başlatın:"
|
AdvSceneSwitcher.generalTab.status.autoStart.startup="Aşağıdaki durumlarda sahne değiştiriciyi otomatik olarak başlatın:"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.never="Asla"
|
AdvSceneSwitcher.generalTab.status.autoStart.never="Asla"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.recording="Kayıt"
|
AdvSceneSwitcher.generalTab.status.autoStart.recording="Kayıt"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Yayın"
|
AdvSceneSwitcher.generalTab.status.autoStart.streaming="Yayın"
|
||||||
@@ -249,7 +249,6 @@ AdvSceneSwitcher.condition.openvr.entry.line3="HMD mevcut {{xPos}} x {{yPos}} x
|
|||||||
|
|
||||||
; Macro Actions
|
; Macro Actions
|
||||||
AdvSceneSwitcher.action.scene="Sahne Degistirici"
|
AdvSceneSwitcher.action.scene="Sahne Degistirici"
|
||||||
AdvSceneSwitcher.action.scene.entry="Sahneyi{{sceneTypes}}{{scenes}}kullanarak{{transitions}}süresi olan{{duration}}saniye"
|
|
||||||
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Hedef sahneye geçiş tamamlanana kadar bekleyin"
|
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="Hedef sahneye geçiş tamamlanana kadar bekleyin"
|
||||||
AdvSceneSwitcher.action.wait="Bekle"
|
AdvSceneSwitcher.action.wait="Bekle"
|
||||||
AdvSceneSwitcher.action.wait.type.fixed="sabit"
|
AdvSceneSwitcher.action.wait.type.fixed="sabit"
|
||||||
@@ -312,7 +311,7 @@ AdvSceneSwitcher.action.pluginState.type.stop="Advanced Scene Switcher eklentisi
|
|||||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Eşleşmeme davranışını değiştirin:"
|
AdvSceneSwitcher.action.pluginState.type.noMatch="Eşleşmeme davranışını değiştirin:"
|
||||||
AdvSceneSwitcher.action.pluginState.type.import="Ayarları şuradan içe aktar:"
|
AdvSceneSwitcher.action.pluginState.type.import="Ayarları şuradan içe aktar:"
|
||||||
AdvSceneSwitcher.action.pluginState.importWarning="Not: Ayarlar penceresi açılırken eylem göz ardı edilecektir."
|
AdvSceneSwitcher.action.pluginState.importWarning="Not: Ayarlar penceresi açılırken eylem göz ardı edilecektir."
|
||||||
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
|
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}"
|
||||||
AdvSceneSwitcher.action.virtualCamera="Sanal Kamera"
|
AdvSceneSwitcher.action.virtualCamera="Sanal Kamera"
|
||||||
AdvSceneSwitcher.action.virtualCamera.type.stop="Sanal Kamerayı Durdur"
|
AdvSceneSwitcher.action.virtualCamera.type.stop="Sanal Kamerayı Durdur"
|
||||||
AdvSceneSwitcher.action.virtualCamera.type.start="Sanal Kamerayı Başlat"
|
AdvSceneSwitcher.action.virtualCamera.type.start="Sanal Kamerayı Başlat"
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ AdvSceneSwitcher.generalTab.status.onStartup.alwaysStart="总是自动启动"
|
|||||||
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="不要启动"
|
AdvSceneSwitcher.generalTab.status.onStartup.doNotStart="不要启动"
|
||||||
AdvSceneSwitcher.generalTab.status.start="启动"
|
AdvSceneSwitcher.generalTab.status.start="启动"
|
||||||
AdvSceneSwitcher.generalTab.status.stop="停止"
|
AdvSceneSwitcher.generalTab.status.stop="停止"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart="在以下情况下自动启动场景切换器:"
|
AdvSceneSwitcher.generalTab.status.autoStart.startup="在以下情况下自动启动场景切换器:"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.never="从不"
|
AdvSceneSwitcher.generalTab.status.autoStart.never="从不"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.recording="录制"
|
AdvSceneSwitcher.generalTab.status.autoStart.recording="录制"
|
||||||
AdvSceneSwitcher.generalTab.status.autoStart.streaming="直播"
|
AdvSceneSwitcher.generalTab.status.autoStart.streaming="直播"
|
||||||
@@ -698,7 +698,7 @@ AdvSceneSwitcher.condition.twitch.type.event.channel.user.moderator.deletion="
|
|||||||
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.live="开始直播"
|
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.live="开始直播"
|
||||||
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.playlist="开始播放列表"
|
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.playlist="开始播放列表"
|
||||||
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.watchParty="开始观看派对"
|
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.watchParty="开始观看派对"
|
||||||
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.premiere="开始首播
|
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.premiere="开始首播"
|
||||||
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.rerun="开始重播"
|
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online.rerun="开始重播"
|
||||||
AdvSceneSwitcher.condition.twitch.type.polling.channel.live="当前正在直播"
|
AdvSceneSwitcher.condition.twitch.type.polling.channel.live="当前正在直播"
|
||||||
AdvSceneSwitcher.condition.twitch.type.polling.channel.title="当前为头衔赛"
|
AdvSceneSwitcher.condition.twitch.type.polling.channel.title="当前为头衔赛"
|
||||||
@@ -779,9 +779,6 @@ AdvSceneSwitcher.action.unknown="未知操作"
|
|||||||
AdvSceneSwitcher.action.scene="切换场景"
|
AdvSceneSwitcher.action.scene="切换场景"
|
||||||
AdvSceneSwitcher.action.scene.type.program="程序"
|
AdvSceneSwitcher.action.scene.type.program="程序"
|
||||||
AdvSceneSwitcher.action.scene.type.preview="预览"
|
AdvSceneSwitcher.action.scene.type.preview="预览"
|
||||||
AdvSceneSwitcher.action.scene.entry="切换到场景{{sceneTypes}}{{scenes}}使用{{transitions}}时长{{duration}}秒"
|
|
||||||
AdvSceneSwitcher.action.scene.entry.noDuration="切换到场景{{sceneTypes}}{{scenes}}使用{{transitions}}"
|
|
||||||
AdvSceneSwitcher.action.scene.entry.preview="将{{sceneTypes}}场景切换到{{scenes}}"
|
|
||||||
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="等待转场到目标场景的动画完成"
|
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="等待转场到目标场景的动画完成"
|
||||||
AdvSceneSwitcher.action.wait="等待"
|
AdvSceneSwitcher.action.wait="等待"
|
||||||
AdvSceneSwitcher.action.wait.type.fixed="固定"
|
AdvSceneSwitcher.action.wait.type.fixed="固定"
|
||||||
@@ -923,9 +920,9 @@ AdvSceneSwitcher.action.macro.type.stop="停止操作"
|
|||||||
AdvSceneSwitcher.action.macro.type.disableAction="停用操作"
|
AdvSceneSwitcher.action.macro.type.disableAction="停用操作"
|
||||||
AdvSceneSwitcher.action.macro.type.enableAction="启用操作"
|
AdvSceneSwitcher.action.macro.type.enableAction="启用操作"
|
||||||
AdvSceneSwitcher.action.macro.type.toggleAction="切换操作开关"
|
AdvSceneSwitcher.action.macro.type.toggleAction="切换操作开关"
|
||||||
AdvSceneSwitcher.action.macro.entry.run="{{actions}}{{actionTypes}}{{macros}}"
|
AdvSceneSwitcher.action.macro.layout.run="{{actions}}{{actionSections}}{{macros}}"
|
||||||
AdvSceneSwitcher.action.macro.entry.run.condition="{{conditionBehaviors}}{{conditionMacros}}"
|
AdvSceneSwitcher.action.macro.layout.run.condition="{{conditionBehaviors}}{{conditionMacros}}"
|
||||||
AdvSceneSwitcher.action.macro.entry.other="{{actions}}{{actionIndex}}{{macros}}"
|
AdvSceneSwitcher.action.macro.layout.other="{{actions}}{{macros}}"
|
||||||
AdvSceneSwitcher.action.pluginState="插件状态"
|
AdvSceneSwitcher.action.pluginState="插件状态"
|
||||||
AdvSceneSwitcher.action.pluginState.type.stop="停止高级场景切换插件"
|
AdvSceneSwitcher.action.pluginState.type.stop="停止高级场景切换插件"
|
||||||
AdvSceneSwitcher.action.pluginState.type.noMatch="没有匹配项时:"
|
AdvSceneSwitcher.action.pluginState.type.noMatch="没有匹配项时:"
|
||||||
@@ -933,7 +930,7 @@ AdvSceneSwitcher.action.pluginState.type.import="导入设置"
|
|||||||
AdvSceneSwitcher.action.pluginState.importWarning="注意:当设置窗口打开时,操作将被忽略."
|
AdvSceneSwitcher.action.pluginState.importWarning="注意:当设置窗口打开时,操作将被忽略."
|
||||||
AdvSceneSwitcher.action.pluginState.type.terminate="关闭OBS"
|
AdvSceneSwitcher.action.pluginState.type.terminate="关闭OBS"
|
||||||
AdvSceneSwitcher.action.pluginState.terminateConfirm="OBS将在10秒后自动关闭!\n你想继续关闭OBS吗?"
|
AdvSceneSwitcher.action.pluginState.terminateConfirm="OBS将在10秒后自动关闭!\n你想继续关闭OBS吗?"
|
||||||
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}{{settingsWarning}}"
|
AdvSceneSwitcher.action.pluginState.entry="{{actions}}{{values}}{{scenes}}{{settings}}"
|
||||||
AdvSceneSwitcher.action.virtualCamera="虚拟摄像机"
|
AdvSceneSwitcher.action.virtualCamera="虚拟摄像机"
|
||||||
AdvSceneSwitcher.action.virtualCamera.type.stop="停止虚拟摄像机"
|
AdvSceneSwitcher.action.virtualCamera.type.stop="停止虚拟摄像机"
|
||||||
AdvSceneSwitcher.action.virtualCamera.type.start="启动虚拟摄像机"
|
AdvSceneSwitcher.action.virtualCamera.type.start="启动虚拟摄像机"
|
||||||
@@ -2095,21 +2092,19 @@ AdvSceneSwitcher.setting.transform.width="宽度"
|
|||||||
|
|
||||||
AdvSceneSwitcher.sceneItemSelection.configure="配置场景项目选择类型"
|
AdvSceneSwitcher.sceneItemSelection.configure="配置场景项目选择类型"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceName="源名称"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceName="源名称"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceName.entry="{{nameConflictIndex}}{{sourceName}}"
|
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable="变量名称"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable="变量名称"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceVariable.entry="{{nameConflictIndex}}{{variable}}"
|
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="源名称与匹配相符"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern="源名称与匹配相符"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.entry="{{nameConflictIndex}}匹配{{pattern}}{{regex}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceNamePattern.layout="{{nameConflictIndex}}匹配{{pattern}}{{regex}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup="源分组中的来源"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup="源分组中的来源"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup.entry="{{sourceGroups}}中的源"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceGroup.layout="{{nameConflictIndex}}{{sourceGroups}}中的源"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceType="源类型"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType="源类型"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.sourceType.entry="源类型{{nameConflictIndex}}{{sourceTypes}}"
|
AdvSceneSwitcher.sceneItemSelection.type.sourceType.layout="源类型{{nameConflictIndex}}{{sourceTypes}}"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index="附有索引的源"
|
AdvSceneSwitcher.sceneItemSelection.type.index="附有索引的源"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.index.entry="{{index}}源"
|
AdvSceneSwitcher.sceneItemSelection.type.index.layout="{{index}}源"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.indexRange="索引范围内的源"
|
AdvSceneSwitcher.sceneItemSelection.type.indexRange="索引范围内的源"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.indexRange.entry="从{{index}}到{{indexEnd}}的源"
|
AdvSceneSwitcher.sceneItemSelection.type.indexRange.layout="从{{index}}到{{indexEnd}}的源"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.all="所有源"
|
AdvSceneSwitcher.sceneItemSelection.type.all="所有源"
|
||||||
AdvSceneSwitcher.sceneItemSelection.type.all.entry="所有源"
|
AdvSceneSwitcher.sceneItemSelection.type.all.layout="所有源"
|
||||||
AdvSceneSwitcher.sceneItemSelection.all="全部"
|
AdvSceneSwitcher.sceneItemSelection.all="全部"
|
||||||
AdvSceneSwitcher.sceneItemSelection.any="任何"
|
AdvSceneSwitcher.sceneItemSelection.any="任何"
|
||||||
|
|
||||||
@@ -2133,9 +2128,9 @@ AdvSceneSwitcher.unit.weeks="周"
|
|||||||
AdvSceneSwitcher.unit.months="月"
|
AdvSceneSwitcher.unit.months="月"
|
||||||
AdvSceneSwitcher.unit.years="年"
|
AdvSceneSwitcher.unit.years="年"
|
||||||
AdvSceneSwitcher.duration.condition.none="没有时间限制"
|
AdvSceneSwitcher.duration.condition.none="没有时间限制"
|
||||||
AdvSceneSwitcher.duration.condition.more="时间少于"
|
AdvSceneSwitcher.duration.condition.more="时间大于"
|
||||||
AdvSceneSwitcher.duration.condition.equal="时间等于"
|
AdvSceneSwitcher.duration.condition.equal="时间等于"
|
||||||
AdvSceneSwitcher.duration.condition.less="时间大于"
|
AdvSceneSwitcher.duration.condition.less="时间少于"
|
||||||
AdvSceneSwitcher.duration.condition.within="最后"
|
AdvSceneSwitcher.duration.condition.within="最后"
|
||||||
|
|
||||||
AdvSceneSwitcher.time.relative="%1 %2 之前"
|
AdvSceneSwitcher.time.relative="%1 %2 之前"
|
||||||
|
|||||||
2
deps/json
vendored
2
deps/json
vendored
Submodule deps/json updated: bc889afb4c...55f93686c0
2
deps/libusb
vendored
2
deps/libusb
vendored
Submodule deps/libusb updated: d52e355daa...15a7ebb4d4
File diff suppressed because it is too large
Load Diff
388
forms/macro-edit.ui
Normal file
388
forms/macro-edit.ui
Normal file
@@ -0,0 +1,388 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>MacroEdit</class>
|
||||||
|
<widget class="QWidget" name="MacroEdit">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>400</width>
|
||||||
|
<height>300</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QSplitter" name="macroActionConditionSplitter">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="macroConditions" native="true">
|
||||||
|
<layout class="QVBoxLayout" name="macroConditionsLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="advss::MacroSegmentList" name="conditionsList">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>1</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="conditionControlsLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>9</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="conditionAdd">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.conditionAddButton</string>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string notr="true">addIconSmall</string>
|
||||||
|
</property>
|
||||||
|
<property name="class" stdset="0">
|
||||||
|
<string notr="true">icon-plus</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="conditionRemove">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.conditionRemoveButton</string>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string notr="true">removeIconSmall</string>
|
||||||
|
</property>
|
||||||
|
<property name="class" stdset="0">
|
||||||
|
<string notr="true">icon-trash</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="conditionTop">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.conditionTopButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="conditionUp">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.conditionUpButton</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string/>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string notr="true">upArrowIconSmall</string>
|
||||||
|
</property>
|
||||||
|
<property name="class" stdset="0">
|
||||||
|
<string notr="true">icon-up</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="conditionDown">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.conditionDownButton</string>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string notr="true">downArrowIconSmall</string>
|
||||||
|
</property>
|
||||||
|
<property name="class" stdset="0">
|
||||||
|
<string notr="true">icon-down</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="conditionBottom">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.conditionBottomButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QSplitter" name="macroElseActionSplitter">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<widget class="QWidget" name="macroActions" native="true">
|
||||||
|
<layout class="QVBoxLayout" name="macroActionsLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="advss::MacroSegmentList" name="actionsList">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>1</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="actionControlsLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>9</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="actionAdd">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.actionAddButton</string>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string notr="true">addIconSmall</string>
|
||||||
|
</property>
|
||||||
|
<property name="class" stdset="0">
|
||||||
|
<string notr="true">icon-plus</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="actionRemove">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.actionRemoveButton</string>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string notr="true">removeIconSmall</string>
|
||||||
|
</property>
|
||||||
|
<property name="class" stdset="0">
|
||||||
|
<string notr="true">icon-trash</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="actionTop">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.actionTopButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="actionUp">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.actionUpButton</string>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string notr="true">upArrowIconSmall</string>
|
||||||
|
</property>
|
||||||
|
<property name="class" stdset="0">
|
||||||
|
<string notr="true">icon-up</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="actionDown">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.actionDownButton</string>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string notr="true">downArrowIconSmall</string>
|
||||||
|
</property>
|
||||||
|
<property name="class" stdset="0">
|
||||||
|
<string notr="true">icon-down</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="actionBottom">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.actionBottomButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_14">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="toggleElseActions">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.toggleShowElseSection</string>
|
||||||
|
</property>
|
||||||
|
<property name="checkable">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<widget class="QWidget" name="macroElseActions" native="true">
|
||||||
|
<layout class="QVBoxLayout" name="macroElseActionsLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="topMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="rightMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<property name="bottomMargin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="advss::MacroSegmentList" name="elseActionsList">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>1</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="elseActionControlsLayout">
|
||||||
|
<property name="leftMargin">
|
||||||
|
<number>9</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="elseActionAdd">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.elseActionAddButton</string>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string notr="true">addIconSmall</string>
|
||||||
|
</property>
|
||||||
|
<property name="class" stdset="0">
|
||||||
|
<string notr="true">icon-plus</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="elseActionRemove">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.elseActionRemoveButton</string>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string notr="true">removeIconSmall</string>
|
||||||
|
</property>
|
||||||
|
<property name="class" stdset="0">
|
||||||
|
<string notr="true">icon-trash</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="elseActionTop">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.elseActionTopButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="elseActionUp">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.elseActionUpButton</string>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string notr="true">upArrowIconSmall</string>
|
||||||
|
</property>
|
||||||
|
<property name="class" stdset="0">
|
||||||
|
<string notr="true">icon-up</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="elseActionDown">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.elseActionDownButton</string>
|
||||||
|
</property>
|
||||||
|
<property name="themeID" stdset="0">
|
||||||
|
<string notr="true">downArrowIconSmall</string>
|
||||||
|
</property>
|
||||||
|
<property name="class" stdset="0">
|
||||||
|
<string notr="true">icon-down</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QToolButton" name="elseActionBottom">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.tooltip.elseActionBottomButton</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>advss::MacroSegmentList</class>
|
||||||
|
<extends>QScrollArea</extends>
|
||||||
|
<header>macro-segment-list.hpp</header>
|
||||||
|
<container>1</container>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
|
<tabstops>
|
||||||
|
<tabstop>conditionsList</tabstop>
|
||||||
|
<tabstop>conditionAdd</tabstop>
|
||||||
|
<tabstop>conditionRemove</tabstop>
|
||||||
|
<tabstop>conditionTop</tabstop>
|
||||||
|
<tabstop>conditionUp</tabstop>
|
||||||
|
<tabstop>conditionDown</tabstop>
|
||||||
|
<tabstop>conditionBottom</tabstop>
|
||||||
|
<tabstop>actionsList</tabstop>
|
||||||
|
<tabstop>actionAdd</tabstop>
|
||||||
|
<tabstop>actionRemove</tabstop>
|
||||||
|
<tabstop>actionTop</tabstop>
|
||||||
|
<tabstop>actionUp</tabstop>
|
||||||
|
<tabstop>actionDown</tabstop>
|
||||||
|
<tabstop>actionBottom</tabstop>
|
||||||
|
<tabstop>toggleElseActions</tabstop>
|
||||||
|
<tabstop>elseActionsList</tabstop>
|
||||||
|
<tabstop>elseActionAdd</tabstop>
|
||||||
|
<tabstop>elseActionRemove</tabstop>
|
||||||
|
<tabstop>elseActionTop</tabstop>
|
||||||
|
<tabstop>elseActionUp</tabstop>
|
||||||
|
<tabstop>elseActionDown</tabstop>
|
||||||
|
<tabstop>elseActionBottom</tabstop>
|
||||||
|
</tabstops>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
@@ -146,16 +146,7 @@ void AdvSceneSwitcher::LoadUI()
|
|||||||
bool AdvSceneSwitcher::eventFilter(QObject *obj, QEvent *event)
|
bool AdvSceneSwitcher::eventFilter(QObject *obj, QEvent *event)
|
||||||
{
|
{
|
||||||
auto eventType = event->type();
|
auto eventType = event->type();
|
||||||
if (obj == ui->macroElseActions && eventType == QEvent::Resize) {
|
if (eventType == QEvent::KeyPress) {
|
||||||
QResizeEvent *resizeEvent = static_cast<QResizeEvent *>(event);
|
|
||||||
|
|
||||||
if (resizeEvent->size().height() == 0) {
|
|
||||||
SetElseActionsStateToHidden();
|
|
||||||
return QDialog::eventFilter(obj, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
SetElseActionsStateToVisible();
|
|
||||||
} else if (eventType == QEvent::KeyPress) {
|
|
||||||
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
|
||||||
auto pressedKey = keyEvent->key();
|
auto pressedKey = keyEvent->key();
|
||||||
|
|
||||||
@@ -430,7 +421,7 @@ bool SwitcherData::CheckForMatch(OBSWeakSource &scene,
|
|||||||
|
|
||||||
static void ResetMacros()
|
static void ResetMacros()
|
||||||
{
|
{
|
||||||
for (auto &m : GetMacros()) {
|
for (auto &m : GetTopLevelMacros()) {
|
||||||
ResetMacroRunCount(m.get());
|
ResetMacroRunCount(m.get());
|
||||||
ResetMacroConditionTimers(m.get());
|
ResetMacroConditionTimers(m.get());
|
||||||
}
|
}
|
||||||
@@ -547,6 +538,7 @@ static void handleSceneChange()
|
|||||||
}
|
}
|
||||||
|
|
||||||
switcher->checkDefaultSceneTransitions();
|
switcher->checkDefaultSceneTransitions();
|
||||||
|
switcher->CheckAutoStart();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setLiveTime()
|
static void setLiveTime()
|
||||||
@@ -561,18 +553,28 @@ static void resetLiveTime()
|
|||||||
|
|
||||||
static void checkAutoStartRecording()
|
static void checkAutoStartRecording()
|
||||||
{
|
{
|
||||||
|
if (switcher->obsIsShuttingDown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (switcher->autoStartEvent == SwitcherData::AutoStart::RECORDING ||
|
if (switcher->autoStartEvent == SwitcherData::AutoStart::RECORDING ||
|
||||||
switcher->autoStartEvent ==
|
switcher->autoStartEvent ==
|
||||||
SwitcherData::AutoStart::RECORINDG_OR_STREAMING)
|
SwitcherData::AutoStart::RECORINDG_OR_STREAMING) {
|
||||||
switcher->Start();
|
switcher->Start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void checkAutoStartStreaming()
|
static void checkAutoStartStreaming()
|
||||||
{
|
{
|
||||||
|
if (switcher->obsIsShuttingDown) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (switcher->autoStartEvent == SwitcherData::AutoStart::STREAMING ||
|
if (switcher->autoStartEvent == SwitcherData::AutoStart::STREAMING ||
|
||||||
switcher->autoStartEvent ==
|
switcher->autoStartEvent ==
|
||||||
SwitcherData::AutoStart::RECORINDG_OR_STREAMING)
|
SwitcherData::AutoStart::RECORINDG_OR_STREAMING) {
|
||||||
switcher->Start();
|
switcher->Start();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void handleTransitionEnd()
|
static void handleTransitionEnd()
|
||||||
@@ -608,7 +610,7 @@ static void handleSceneCollectionChanging()
|
|||||||
AdvSceneSwitcher::window->close();
|
AdvSceneSwitcher::window->close();
|
||||||
}
|
}
|
||||||
if (!switcher->stop) {
|
if (!switcher->stop) {
|
||||||
switcher->sceneColletionStop = true;
|
switcher->sceneCollectionStop = true;
|
||||||
switcher->Stop();
|
switcher->Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -744,6 +746,21 @@ void AdvSceneSwitcher::HighlightMacroSettingsButton(bool enable)
|
|||||||
highlight = HighlightWidget(ui->macroSettings, Qt::green);
|
highlight = HighlightWidget(ui->macroSettings, Qt::green);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::HighlightAction(int idx, QColor color) const
|
||||||
|
{
|
||||||
|
ui->macroEdit->HighlightAction(idx, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::HighlightElseAction(int idx, QColor color) const
|
||||||
|
{
|
||||||
|
ui->macroEdit->HighlightElseAction(idx, color);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AdvSceneSwitcher::HighlightCondition(int idx, QColor color) const
|
||||||
|
{
|
||||||
|
ui->macroEdit->HighlightCondition(idx, color);
|
||||||
|
}
|
||||||
|
|
||||||
void HighlightMacroSettingsButton(bool enable)
|
void HighlightMacroSettingsButton(bool enable)
|
||||||
{
|
{
|
||||||
auto window = GetSettingsWindow();
|
auto window = GetSettingsWindow();
|
||||||
|
|||||||
@@ -45,7 +45,6 @@ protected:
|
|||||||
/* --- Begin of general tab section --- */
|
/* --- Begin of general tab section --- */
|
||||||
public:
|
public:
|
||||||
void SetupGeneralTab();
|
void SetupGeneralTab();
|
||||||
void UpdateNonMatchingScene(const QString &name);
|
|
||||||
void SetDeprecationWarnings();
|
void SetDeprecationWarnings();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
@@ -58,7 +57,6 @@ public slots:
|
|||||||
void on_startupBehavior_currentIndexChanged(int index);
|
void on_startupBehavior_currentIndexChanged(int index);
|
||||||
void on_logLevel_currentIndexChanged(int index);
|
void on_logLevel_currentIndexChanged(int index);
|
||||||
void on_autoStartEvent_currentIndexChanged(int index);
|
void on_autoStartEvent_currentIndexChanged(int index);
|
||||||
void on_noMatchSwitchScene_currentTextChanged(const QString &text);
|
|
||||||
void on_checkInterval_valueChanged(int value);
|
void on_checkInterval_valueChanged(int value);
|
||||||
void on_tabWidget_currentChanged(int index);
|
void on_tabWidget_currentChanged(int index);
|
||||||
void on_exportSettings_clicked();
|
void on_exportSettings_clicked();
|
||||||
@@ -67,7 +65,6 @@ public slots:
|
|||||||
void on_showTrayNotifications_stateChanged(int state);
|
void on_showTrayNotifications_stateChanged(int state);
|
||||||
void on_uiHintsDisable_stateChanged(int state);
|
void on_uiHintsDisable_stateChanged(int state);
|
||||||
void on_disableComboBoxFilter_stateChanged(int state);
|
void on_disableComboBoxFilter_stateChanged(int state);
|
||||||
void on_disableMacroWidgetCache_stateChanged(int state);
|
|
||||||
void on_warnPluginLoadFailure_stateChanged(int state);
|
void on_warnPluginLoadFailure_stateChanged(int state);
|
||||||
void on_hideLegacyTabs_stateChanged(int state);
|
void on_hideLegacyTabs_stateChanged(int state);
|
||||||
void on_priorityUp_clicked();
|
void on_priorityUp_clicked();
|
||||||
@@ -79,6 +76,7 @@ public slots:
|
|||||||
/* --- Begin of macro tab section --- */
|
/* --- Begin of macro tab section --- */
|
||||||
public:
|
public:
|
||||||
void SetupMacroTab();
|
void SetupMacroTab();
|
||||||
|
bool MacroTabIsInFocus();
|
||||||
bool AddNewMacro(std::shared_ptr<Macro> &res, std::string &name,
|
bool AddNewMacro(std::shared_ptr<Macro> &res, std::string &name,
|
||||||
std::string format = "");
|
std::string format = "");
|
||||||
void RemoveMacro(std::shared_ptr<Macro> &);
|
void RemoveMacro(std::shared_ptr<Macro> &);
|
||||||
@@ -86,7 +84,6 @@ public:
|
|||||||
void RenameMacro(std::shared_ptr<Macro> &, const QString &name);
|
void RenameMacro(std::shared_ptr<Macro> &, const QString &name);
|
||||||
std::shared_ptr<Macro> GetSelectedMacro() const;
|
std::shared_ptr<Macro> GetSelectedMacro() const;
|
||||||
std::vector<std::shared_ptr<Macro>> GetSelectedMacros() const;
|
std::vector<std::shared_ptr<Macro>> GetSelectedMacros() const;
|
||||||
void SetEditMacro(Macro &m);
|
|
||||||
void SetMacroEditAreaDisabled(bool) const;
|
void SetMacroEditAreaDisabled(bool) const;
|
||||||
void HighlightAction(int idx, QColor color = QColor(Qt::green)) const;
|
void HighlightAction(int idx, QColor color = QColor(Qt::green)) const;
|
||||||
void HighlightElseAction(int idx,
|
void HighlightElseAction(int idx,
|
||||||
@@ -111,106 +108,17 @@ public slots:
|
|||||||
void on_macroName_editingFinished();
|
void on_macroName_editingFinished();
|
||||||
void on_runMacroInParallel_stateChanged(int value) const;
|
void on_runMacroInParallel_stateChanged(int value) const;
|
||||||
void on_runMacroOnChange_stateChanged(int value) const;
|
void on_runMacroOnChange_stateChanged(int value) const;
|
||||||
void on_conditionAdd_clicked();
|
|
||||||
void on_conditionRemove_clicked();
|
|
||||||
void on_conditionTop_clicked();
|
|
||||||
void on_conditionUp_clicked();
|
|
||||||
void on_conditionDown_clicked();
|
|
||||||
void on_conditionBottom_clicked();
|
|
||||||
void on_actionAdd_clicked();
|
|
||||||
void on_actionRemove_clicked();
|
|
||||||
void on_actionTop_clicked();
|
|
||||||
void on_actionUp_clicked();
|
|
||||||
void on_actionDown_clicked();
|
|
||||||
void on_actionBottom_clicked();
|
|
||||||
void on_toggleElseActions_clicked() const;
|
|
||||||
void on_elseActionAdd_clicked();
|
|
||||||
void on_elseActionRemove_clicked();
|
|
||||||
void on_elseActionTop_clicked();
|
|
||||||
void on_elseActionUp_clicked();
|
|
||||||
void on_elseActionDown_clicked();
|
|
||||||
void on_elseActionBottom_clicked();
|
|
||||||
void MacroSelectionAboutToChange() const;
|
|
||||||
void MacroSelectionChanged();
|
void MacroSelectionChanged();
|
||||||
void UpMacroSegementHotkey();
|
|
||||||
void DownMacroSegementHotkey();
|
|
||||||
void DeleteMacroSegementHotkey();
|
|
||||||
void ShowMacroContextMenu(const QPoint &);
|
void ShowMacroContextMenu(const QPoint &);
|
||||||
void ShowMacroActionsContextMenu(const QPoint &);
|
|
||||||
void ShowMacroElseActionsContextMenu(const QPoint &);
|
|
||||||
void ShowMacroConditionsContextMenu(const QPoint &);
|
|
||||||
void CopyMacro();
|
void CopyMacro();
|
||||||
void RenameSelectedMacro();
|
void RenameSelectedMacro();
|
||||||
void ExportMacros() const;
|
void ExportMacros() const;
|
||||||
void ImportMacros();
|
void ImportMacros();
|
||||||
void ExpandAllActions() const;
|
|
||||||
void ExpandAllElseActions() const;
|
|
||||||
void ExpandAllConditions() const;
|
|
||||||
void CollapseAllActions() const;
|
|
||||||
void CollapseAllElseActions() const;
|
|
||||||
void CollapseAllConditions() const;
|
|
||||||
void MinimizeActions() const;
|
|
||||||
void MaximizeActions() const;
|
|
||||||
void MinimizeElseActions() const;
|
|
||||||
void MaximizeElseActions() const;
|
|
||||||
void MinimizeConditions() const;
|
|
||||||
void MaximizeConditions() const;
|
|
||||||
void SetElseActionsStateToHidden() const;
|
|
||||||
void SetElseActionsStateToVisible() const;
|
|
||||||
void MacroActionSelectionChanged(int idx);
|
|
||||||
void MacroActionReorder(int to, int target);
|
|
||||||
void AddMacroAction(Macro *macro, int idx, const std::string &id,
|
|
||||||
obs_data_t *data);
|
|
||||||
void AddMacroAction(int idx);
|
|
||||||
void RemoveMacroAction(int idx);
|
|
||||||
void MoveMacroActionUp(int idx);
|
|
||||||
void MoveMacroActionDown(int idx);
|
|
||||||
void MacroElseActionSelectionChanged(int idx);
|
|
||||||
void MacroElseActionReorder(int to, int target);
|
|
||||||
void AddMacroElseAction(Macro *macro, int idx, const std::string &id,
|
|
||||||
obs_data_t *data);
|
|
||||||
void AddMacroElseAction(int idx);
|
|
||||||
void RemoveMacroElseAction(int idx);
|
|
||||||
void SwapElseActions(Macro *m, int pos1, int pos2);
|
|
||||||
void MoveMacroElseActionUp(int idx);
|
|
||||||
void MoveMacroElseActionDown(int idx);
|
|
||||||
void MacroConditionSelectionChanged(int idx);
|
|
||||||
void MacroConditionReorder(int to, int target);
|
|
||||||
void AddMacroCondition(int idx);
|
|
||||||
void AddMacroCondition(Macro *macro, int idx, const std::string &id,
|
|
||||||
obs_data_t *data, Logic::Type logic);
|
|
||||||
void RemoveMacroCondition(int idx);
|
|
||||||
void MoveMacroConditionUp(int idx);
|
|
||||||
void MoveMacroConditionDown(int idx);
|
|
||||||
void HighlightControls() const;
|
|
||||||
void HighlightOnChange() const;
|
void HighlightOnChange() const;
|
||||||
void on_macroSettings_clicked();
|
void on_macroSettings_clicked();
|
||||||
void CopyMacroSegment();
|
|
||||||
void PasteMacroSegment();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void MacroAdded(const QString &name);
|
|
||||||
void MacroRemoved(const QString &name);
|
|
||||||
void MacroRenamed(const QString &oldName, const QString &newName);
|
|
||||||
void MacroSegmentOrderChanged();
|
|
||||||
void SegmentTempVarsChanged(MacroSegment *);
|
|
||||||
void HighlightMacrosChanged(bool value);
|
|
||||||
|
|
||||||
void ConnectionAdded(const QString &);
|
|
||||||
void ConnectionRenamed(const QString &oldName, const QString &newName);
|
|
||||||
void ConnectionRemoved(const QString &);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class MacroSection { CONDITIONS, ACTIONS, ELSE_ACTIONS };
|
|
||||||
|
|
||||||
void SetupMacroSegmentSelection(MacroSection type, int idx);
|
|
||||||
bool ResolveMacroImportNameConflict(std::shared_ptr<Macro> &);
|
bool ResolveMacroImportNameConflict(std::shared_ptr<Macro> &);
|
||||||
bool MacroTabIsInFocus();
|
|
||||||
|
|
||||||
MacroSection lastInteracted = MacroSection::CONDITIONS;
|
|
||||||
int currentConditionIdx = -1;
|
|
||||||
int currentActionIdx = -1;
|
|
||||||
int currentElseActionIdx = -1;
|
|
||||||
|
|
||||||
/* --- End of macro tab section --- */
|
/* --- End of macro tab section --- */
|
||||||
|
|
||||||
|
|||||||
221
lib/general.cpp
221
lib/general.cpp
@@ -3,6 +3,8 @@
|
|||||||
#include "filter-combo-box.hpp"
|
#include "filter-combo-box.hpp"
|
||||||
#include "layout-helpers.hpp"
|
#include "layout-helpers.hpp"
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
|
#include "macro-search.hpp"
|
||||||
|
#include "macro-settings.hpp"
|
||||||
#include "path-helpers.hpp"
|
#include "path-helpers.hpp"
|
||||||
#include "selection-helpers.hpp"
|
#include "selection-helpers.hpp"
|
||||||
#include "source-helpers.hpp"
|
#include "source-helpers.hpp"
|
||||||
@@ -25,15 +27,6 @@ void AdvSceneSwitcher::reject()
|
|||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::UpdateNonMatchingScene(const QString &name)
|
|
||||||
{
|
|
||||||
OBSSourceAutoRelease scene =
|
|
||||||
obs_get_source_by_name(name.toUtf8().constData());
|
|
||||||
OBSWeakSourceAutoRelease ws = obs_source_get_weak_source(scene);
|
|
||||||
|
|
||||||
switcher->nonMatchingScene = ws;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_noMatchDontSwitch_clicked()
|
void AdvSceneSwitcher::on_noMatchDontSwitch_clicked()
|
||||||
{
|
{
|
||||||
if (loading) {
|
if (loading) {
|
||||||
@@ -55,7 +48,6 @@ void AdvSceneSwitcher::on_noMatchSwitch_clicked()
|
|||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->switchIfNotMatching = NoMatchBehavior::SWITCH;
|
switcher->switchIfNotMatching = NoMatchBehavior::SWITCH;
|
||||||
ui->noMatchSwitchScene->setEnabled(true);
|
ui->noMatchSwitchScene->setEnabled(true);
|
||||||
UpdateNonMatchingScene(ui->noMatchSwitchScene->currentText());
|
|
||||||
ui->randomDisabledWarning->setVisible(true);
|
ui->randomDisabledWarning->setVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,17 +123,6 @@ void AdvSceneSwitcher::on_autoStartEvent_currentIndexChanged(int index)
|
|||||||
switcher->autoStartEvent = static_cast<SwitcherData::AutoStart>(index);
|
switcher->autoStartEvent = static_cast<SwitcherData::AutoStart>(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_noMatchSwitchScene_currentTextChanged(
|
|
||||||
const QString &text)
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
UpdateNonMatchingScene(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_checkInterval_valueChanged(int value)
|
void AdvSceneSwitcher::on_checkInterval_valueChanged(int value)
|
||||||
{
|
{
|
||||||
if (loading) {
|
if (loading) {
|
||||||
@@ -163,7 +144,7 @@ void AdvSceneSwitcher::closeEvent(QCloseEvent *)
|
|||||||
switcher->windowSize = this->size();
|
switcher->windowSize = this->size();
|
||||||
switcher->macroListMacroEditSplitterPosition =
|
switcher->macroListMacroEditSplitterPosition =
|
||||||
ui->macroListMacroEditSplitter->sizes();
|
ui->macroListMacroEditSplitter->sizes();
|
||||||
MacroSelectionAboutToChange(); // Trigger saving of splitter states
|
ui->macroEdit->SetMacro(nullptr); // Trigger saving of splitter states
|
||||||
|
|
||||||
obs_frontend_save();
|
obs_frontend_save();
|
||||||
}
|
}
|
||||||
@@ -205,16 +186,6 @@ void AdvSceneSwitcher::on_disableComboBoxFilter_stateChanged(int state)
|
|||||||
FilterComboBox::SetFilterBehaviourEnabled(!state);
|
FilterComboBox::SetFilterBehaviourEnabled(!state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_disableMacroWidgetCache_stateChanged(int state)
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switcher->disableMacroWidgetCache = state;
|
|
||||||
MacroSegmentList::SetCachingEnabled(!state);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_warnPluginLoadFailure_stateChanged(int state)
|
void AdvSceneSwitcher::on_warnPluginLoadFailure_stateChanged(int state)
|
||||||
{
|
{
|
||||||
if (loading) {
|
if (loading) {
|
||||||
@@ -451,16 +422,14 @@ void SwitcherData::LoadSettings(obs_data_t *obj)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// New post load steps to be declared during load
|
// New post load steps to be declared during load
|
||||||
postLoadSteps.clear();
|
ClearPostLoadSteps();
|
||||||
|
|
||||||
// Needs to be loaded before any entries which might rely on scene group
|
// Needs to be loaded before any entries which might rely on scene group
|
||||||
// selections to be available.
|
// selections to be available.
|
||||||
loadSceneGroups(obj);
|
loadSceneGroups(obj);
|
||||||
LoadVariables(obj);
|
LoadVariables(obj);
|
||||||
|
|
||||||
for (const auto &func : loadSteps) {
|
RunLoadSteps(obj);
|
||||||
func(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadMacros(obj);
|
LoadMacros(obj);
|
||||||
LoadGlobalMacroSettings(obj);
|
LoadGlobalMacroSettings(obj);
|
||||||
@@ -481,7 +450,7 @@ void SwitcherData::LoadSettings(obs_data_t *obj)
|
|||||||
LoadHotkeys(obj);
|
LoadHotkeys(obj);
|
||||||
LoadUISettings(obj);
|
LoadUISettings(obj);
|
||||||
|
|
||||||
RunPostLoadSteps();
|
RunAndClearPostLoadSteps();
|
||||||
|
|
||||||
// Reset on startup and scene collection change
|
// Reset on startup and scene collection change
|
||||||
ResetLastOpenedTab();
|
ResetLastOpenedTab();
|
||||||
@@ -516,18 +485,16 @@ void SwitcherData::SaveSettings(obs_data_t *obj)
|
|||||||
SaveUISettings(obj);
|
SaveUISettings(obj);
|
||||||
SaveVersion(obj, g_GIT_SHA1);
|
SaveVersion(obj, g_GIT_SHA1);
|
||||||
|
|
||||||
for (const auto &func : saveSteps) {
|
RunSaveSteps(obj);
|
||||||
func(obj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::SaveGeneralSettings(obs_data_t *obj)
|
void SwitcherData::SaveGeneralSettings(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
obs_data_set_int(obj, "interval", interval);
|
obs_data_set_int(obj, "interval", interval);
|
||||||
|
|
||||||
std::string nonMatchingSceneName = GetWeakSourceName(nonMatchingScene);
|
OBSDataAutoRelease noMatchScene = obs_data_create();
|
||||||
obs_data_set_string(obj, "non_matching_scene",
|
nonMatchingScene.Save(noMatchScene);
|
||||||
nonMatchingSceneName.c_str());
|
obs_data_set_obj(obj, "noMatchScene", noMatchScene);
|
||||||
obs_data_set_int(obj, "switch_if_not_matching",
|
obs_data_set_int(obj, "switch_if_not_matching",
|
||||||
static_cast<int>(switchIfNotMatching));
|
static_cast<int>(switchIfNotMatching));
|
||||||
noMatchDelay.Save(obj, "noMatchDelay");
|
noMatchDelay.Save(obj, "noMatchDelay");
|
||||||
@@ -535,13 +502,18 @@ void SwitcherData::SaveGeneralSettings(obs_data_t *obj)
|
|||||||
cooldown.Save(obj, "cooldown");
|
cooldown.Save(obj, "cooldown");
|
||||||
obs_data_set_bool(obj, "enableCooldown", enableCooldown);
|
obs_data_set_bool(obj, "enableCooldown", enableCooldown);
|
||||||
|
|
||||||
obs_data_set_bool(obj, "active", sceneColletionStop ? true : !stop);
|
obs_data_set_bool(obj, "active", sceneCollectionStop ? true : !stop);
|
||||||
sceneColletionStop = false;
|
sceneCollectionStop = false;
|
||||||
obs_data_set_int(obj, "startup_behavior",
|
obs_data_set_int(obj, "startup_behavior",
|
||||||
static_cast<int>(startupBehavior));
|
static_cast<int>(startupBehavior));
|
||||||
|
|
||||||
obs_data_set_int(obj, "autoStartEvent",
|
OBSDataAutoRelease autoStart = obs_data_create();
|
||||||
static_cast<int>(autoStartEvent));
|
obs_data_set_int(autoStart, "event", static_cast<int>(autoStartEvent));
|
||||||
|
obs_data_set_bool(autoStart, "useAutoStartScene", useAutoStartScene);
|
||||||
|
autoStartScene.Save(autoStart);
|
||||||
|
autoStartSceneName.Save(autoStart, "name");
|
||||||
|
autoStartSceneRegex.Save(autoStart);
|
||||||
|
obs_data_set_obj(obj, "autoStart", autoStart);
|
||||||
|
|
||||||
SaveLogLevel(obj);
|
SaveLogLevel(obj);
|
||||||
|
|
||||||
@@ -550,8 +522,6 @@ void SwitcherData::SaveGeneralSettings(obs_data_t *obj)
|
|||||||
obs_data_set_bool(obj, "disableHints", disableHints);
|
obs_data_set_bool(obj, "disableHints", disableHints);
|
||||||
obs_data_set_bool(obj, "disableFilterComboboxFilter",
|
obs_data_set_bool(obj, "disableFilterComboboxFilter",
|
||||||
disableFilterComboboxFilter);
|
disableFilterComboboxFilter);
|
||||||
obs_data_set_bool(obj, "disableMacroWidgetCache",
|
|
||||||
disableMacroWidgetCache);
|
|
||||||
obs_data_set_bool(obj, "warnPluginLoadFailure", warnPluginLoadFailure);
|
obs_data_set_bool(obj, "warnPluginLoadFailure", warnPluginLoadFailure);
|
||||||
obs_data_set_bool(obj, "hideLegacyTabs", hideLegacyTabs);
|
obs_data_set_bool(obj, "hideLegacyTabs", hideLegacyTabs);
|
||||||
|
|
||||||
@@ -576,9 +546,14 @@ void SwitcherData::LoadGeneralSettings(obs_data_t *obj)
|
|||||||
static_cast<int>(NoMatchBehavior::NO_SWITCH));
|
static_cast<int>(NoMatchBehavior::NO_SWITCH));
|
||||||
switchIfNotMatching = static_cast<NoMatchBehavior>(
|
switchIfNotMatching = static_cast<NoMatchBehavior>(
|
||||||
obs_data_get_int(obj, "switch_if_not_matching"));
|
obs_data_get_int(obj, "switch_if_not_matching"));
|
||||||
std::string nonMatchingSceneName =
|
|
||||||
obs_data_get_string(obj, "non_matching_scene");
|
if (obs_data_has_user_value(obj, "noMatchScene")) {
|
||||||
nonMatchingScene = GetWeakSourceByName(nonMatchingSceneName.c_str());
|
OBSDataAutoRelease noMatchScene =
|
||||||
|
obs_data_get_obj(obj, "noMatchScene");
|
||||||
|
nonMatchingScene.Load(noMatchScene);
|
||||||
|
} else {
|
||||||
|
nonMatchingScene.Load(obj, "non_matching_scene");
|
||||||
|
}
|
||||||
noMatchDelay.Load(obj, "noMatchDelay");
|
noMatchDelay.Load(obj, "noMatchDelay");
|
||||||
|
|
||||||
cooldown.Load(obj, "cooldown");
|
cooldown.Load(obj, "cooldown");
|
||||||
@@ -599,8 +574,15 @@ void SwitcherData::LoadGeneralSettings(obs_data_t *obj)
|
|||||||
stop = true;
|
stop = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
autoStartEvent =
|
OBSDataAutoRelease autoStart = obs_data_get_obj(obj, "autoStart");
|
||||||
static_cast<AutoStart>(obs_data_get_int(obj, "autoStartEvent"));
|
autoStartEvent = static_cast<AutoStart>(
|
||||||
|
obs_data_has_user_value(obj, "autoStart")
|
||||||
|
? obs_data_get_int(autoStart, "event")
|
||||||
|
: obs_data_get_int(obj, "autoStartEvent"));
|
||||||
|
useAutoStartScene = obs_data_get_bool(autoStart, "useAutoStartScene");
|
||||||
|
autoStartScene.Load(autoStart);
|
||||||
|
autoStartSceneName.Load(autoStart, "name");
|
||||||
|
autoStartSceneRegex.Load(autoStart);
|
||||||
|
|
||||||
LoadLogLevel(obj);
|
LoadLogLevel(obj);
|
||||||
|
|
||||||
@@ -609,8 +591,6 @@ void SwitcherData::LoadGeneralSettings(obs_data_t *obj)
|
|||||||
disableHints = obs_data_get_bool(obj, "disableHints");
|
disableHints = obs_data_get_bool(obj, "disableHints");
|
||||||
disableFilterComboboxFilter =
|
disableFilterComboboxFilter =
|
||||||
obs_data_get_bool(obj, "disableFilterComboboxFilter");
|
obs_data_get_bool(obj, "disableFilterComboboxFilter");
|
||||||
disableMacroWidgetCache =
|
|
||||||
obs_data_get_bool(obj, "disableMacroWidgetCache");
|
|
||||||
obs_data_set_default_bool(obj, "warnPluginLoadFailure", true);
|
obs_data_set_default_bool(obj, "warnPluginLoadFailure", true);
|
||||||
warnPluginLoadFailure = obs_data_get_bool(obj, "warnPluginLoadFailure");
|
warnPluginLoadFailure = obs_data_get_bool(obj, "warnPluginLoadFailure");
|
||||||
obs_data_set_default_bool(obj, "hideLegacyTabs", true);
|
obs_data_set_default_bool(obj, "hideLegacyTabs", true);
|
||||||
@@ -680,10 +660,10 @@ void SwitcherData::CheckNoMatchSwitch(bool &match, OBSWeakSource &scene,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (switchIfNotMatching == NoMatchBehavior::SWITCH &&
|
auto noMatchScene = nonMatchingScene.GetScene(false);
|
||||||
nonMatchingScene) {
|
if (switchIfNotMatching == NoMatchBehavior::SWITCH && noMatchScene) {
|
||||||
match = true;
|
match = true;
|
||||||
scene = nonMatchingScene;
|
scene = noMatchScene;
|
||||||
transition = nullptr;
|
transition = nullptr;
|
||||||
}
|
}
|
||||||
if (switchIfNotMatching == NoMatchBehavior::RANDOM_SWITCH) {
|
if (switchIfNotMatching == NoMatchBehavior::RANDOM_SWITCH) {
|
||||||
@@ -691,6 +671,27 @@ void SwitcherData::CheckNoMatchSwitch(bool &match, OBSWeakSource &scene,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SwitcherData::CheckAutoStart()
|
||||||
|
{
|
||||||
|
if (!useAutoStartScene) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool shouldStartPlugin = false;
|
||||||
|
if (autoStartSceneRegex.Enabled()) {
|
||||||
|
const auto currentSceneName = GetWeakSourceName(currentScene);
|
||||||
|
shouldStartPlugin = autoStartSceneRegex.Matches(
|
||||||
|
currentSceneName, autoStartSceneName);
|
||||||
|
} else {
|
||||||
|
shouldStartPlugin = autoStartScene.GetScene(false) ==
|
||||||
|
currentScene;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldStartPlugin) {
|
||||||
|
Start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void SwitcherData::checkSwitchCooldown(bool &match)
|
void SwitcherData::checkSwitchCooldown(bool &match)
|
||||||
{
|
{
|
||||||
if (!match || !enableCooldown) {
|
if (!match || !enableCooldown) {
|
||||||
@@ -833,7 +834,7 @@ static void setupGeneralTabInactiveWarning(QTabWidget *tabs)
|
|||||||
inactiveTimer->start();
|
inactiveTimer->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
void advss::AdvSceneSwitcher::SetCheckIntervalTooLowVisibility() const
|
void AdvSceneSwitcher::SetCheckIntervalTooLowVisibility() const
|
||||||
{
|
{
|
||||||
auto macro = GetMacroWithInvalidConditionInterval();
|
auto macro = GetMacroWithInvalidConditionInterval();
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
@@ -857,8 +858,6 @@ void advss::AdvSceneSwitcher::SetCheckIntervalTooLowVisibility() const
|
|||||||
|
|
||||||
void AdvSceneSwitcher::SetupGeneralTab()
|
void AdvSceneSwitcher::SetupGeneralTab()
|
||||||
{
|
{
|
||||||
PopulateSceneSelection(ui->noMatchSwitchScene, false);
|
|
||||||
|
|
||||||
if (switcher->switchIfNotMatching == NoMatchBehavior::SWITCH) {
|
if (switcher->switchIfNotMatching == NoMatchBehavior::SWITCH) {
|
||||||
ui->noMatchSwitch->setChecked(true);
|
ui->noMatchSwitch->setChecked(true);
|
||||||
ui->noMatchSwitchScene->setEnabled(true);
|
ui->noMatchSwitchScene->setEnabled(true);
|
||||||
@@ -870,8 +869,17 @@ void AdvSceneSwitcher::SetupGeneralTab()
|
|||||||
ui->noMatchRandomSwitch->setChecked(true);
|
ui->noMatchRandomSwitch->setChecked(true);
|
||||||
ui->noMatchSwitchScene->setEnabled(false);
|
ui->noMatchSwitchScene->setEnabled(false);
|
||||||
}
|
}
|
||||||
ui->noMatchSwitchScene->setCurrentText(
|
ui->noMatchSwitchScene->SetScene(switcher->nonMatchingScene);
|
||||||
GetWeakSourceName(switcher->nonMatchingScene).c_str());
|
ui->noMatchSwitchScene->LockToMainCanvas();
|
||||||
|
|
||||||
|
connect(ui->noMatchSwitchScene, &SceneSelectionWidget::SceneChanged,
|
||||||
|
this, [this](const SceneSelection &scene) {
|
||||||
|
if (loading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
switcher->nonMatchingScene = scene;
|
||||||
|
});
|
||||||
|
|
||||||
DurationSelection *noMatchDelay = new DurationSelection();
|
DurationSelection *noMatchDelay = new DurationSelection();
|
||||||
noMatchDelay->SetDuration(switcher->noMatchDelay);
|
noMatchDelay->SetDuration(switcher->noMatchDelay);
|
||||||
@@ -906,9 +914,6 @@ void AdvSceneSwitcher::SetupGeneralTab()
|
|||||||
switcher->disableFilterComboboxFilter);
|
switcher->disableFilterComboboxFilter);
|
||||||
FilterComboBox::SetFilterBehaviourEnabled(
|
FilterComboBox::SetFilterBehaviourEnabled(
|
||||||
!switcher->disableFilterComboboxFilter);
|
!switcher->disableFilterComboboxFilter);
|
||||||
ui->disableMacroWidgetCache->setChecked(
|
|
||||||
switcher->disableMacroWidgetCache);
|
|
||||||
MacroSegmentList::SetCachingEnabled(!switcher->disableMacroWidgetCache);
|
|
||||||
ui->warnPluginLoadFailure->setChecked(switcher->warnPluginLoadFailure);
|
ui->warnPluginLoadFailure->setChecked(switcher->warnPluginLoadFailure);
|
||||||
ui->hideLegacyTabs->setChecked(switcher->hideLegacyTabs);
|
ui->hideLegacyTabs->setChecked(switcher->hideLegacyTabs);
|
||||||
|
|
||||||
@@ -922,6 +927,88 @@ void AdvSceneSwitcher::SetupGeneralTab()
|
|||||||
populateAutoStartEventSelection(ui->autoStartEvent);
|
populateAutoStartEventSelection(ui->autoStartEvent);
|
||||||
ui->autoStartEvent->setCurrentIndex(
|
ui->autoStartEvent->setCurrentIndex(
|
||||||
static_cast<int>(switcher->autoStartEvent));
|
static_cast<int>(switcher->autoStartEvent));
|
||||||
|
ui->autoStartSceneEnable->setChecked(switcher->useAutoStartScene);
|
||||||
|
ui->autoStartScene->SetScene(switcher->autoStartScene);
|
||||||
|
ui->autoStartScene->LockToMainCanvas();
|
||||||
|
ui->autoStartSceneName->setText(switcher->autoStartSceneName);
|
||||||
|
ui->autoStartSceneNameRegex->SetRegexConfig(
|
||||||
|
switcher->autoStartSceneRegex);
|
||||||
|
|
||||||
|
const auto setupAutoStartSceneLayoutVisibility = [this](bool useRegex) {
|
||||||
|
ui->autoStartSceneName->setVisible(useRegex);
|
||||||
|
ui->autoStartScene->setVisible(!useRegex);
|
||||||
|
if (useRegex) {
|
||||||
|
RemoveStretchIfPresent(ui->autoStartSceneLayout);
|
||||||
|
} else {
|
||||||
|
AddStretchIfNecessary(ui->autoStartSceneLayout);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
setupAutoStartSceneLayoutVisibility(
|
||||||
|
switcher->autoStartSceneRegex.Enabled());
|
||||||
|
|
||||||
|
const auto setupAutoStartSceneWidgetState =
|
||||||
|
[this](bool useAutoStartScene) {
|
||||||
|
ui->autoStartScene->setEnabled(useAutoStartScene);
|
||||||
|
ui->autoStartSceneName->setEnabled(useAutoStartScene);
|
||||||
|
ui->autoStartSceneNameRegex->setEnabled(
|
||||||
|
useAutoStartScene);
|
||||||
|
};
|
||||||
|
setupAutoStartSceneWidgetState(switcher->useAutoStartScene);
|
||||||
|
|
||||||
|
connect(ui->autoStartSceneEnable, &QCheckBox::stateChanged, this,
|
||||||
|
[this, setupAutoStartSceneWidgetState](int enabled) {
|
||||||
|
if (loading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
switcher->useAutoStartScene = enabled;
|
||||||
|
setupAutoStartSceneWidgetState(enabled);
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(ui->autoStartScene, &SceneSelectionWidget::SceneChanged, this,
|
||||||
|
[this](const SceneSelection &scene) {
|
||||||
|
if (loading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
switcher->autoStartScene = scene;
|
||||||
|
switcher->CheckAutoStart();
|
||||||
|
});
|
||||||
|
connect(ui->autoStartSceneName, &VariableLineEdit::editingFinished,
|
||||||
|
this, [this]() {
|
||||||
|
if (loading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
switcher->autoStartSceneName =
|
||||||
|
ui->autoStartSceneName->text().toStdString();
|
||||||
|
switcher->CheckAutoStart();
|
||||||
|
});
|
||||||
|
connect(ui->autoStartSceneNameRegex,
|
||||||
|
&RegexConfigWidget::RegexConfigChanged, this,
|
||||||
|
[this, setupAutoStartSceneLayoutVisibility](
|
||||||
|
const RegexConfig ®ex) {
|
||||||
|
if (loading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
|
switcher->autoStartSceneRegex = regex;
|
||||||
|
setupAutoStartSceneLayoutVisibility(regex.Enabled());
|
||||||
|
switcher->CheckAutoStart();
|
||||||
|
});
|
||||||
|
|
||||||
|
ui->alwaysShowMacroSearch->setChecked(
|
||||||
|
GetMacroSearchSettings().showAlways);
|
||||||
|
|
||||||
|
connect(ui->alwaysShowMacroSearch, &QCheckBox::stateChanged, this,
|
||||||
|
[this](int enabled) {
|
||||||
|
GetMacroSearchSettings().showAlways = enabled;
|
||||||
|
|
||||||
|
if (loading) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
CheckMacroSearchVisibility();
|
||||||
|
});
|
||||||
|
|
||||||
// Set up status control
|
// Set up status control
|
||||||
auto statusControl = new StatusControl(this, true);
|
auto statusControl = new StatusControl(this, true);
|
||||||
|
|||||||
@@ -28,8 +28,7 @@ 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)
|
|
||||||
: MacroSegmentEdit(parent),
|
: MacroSegmentEdit(parent),
|
||||||
_actionSelection(new FilterComboBox()),
|
_actionSelection(new FilterComboBox()),
|
||||||
_enable(new SwitchButton()),
|
_enable(new SwitchButton()),
|
||||||
@@ -117,7 +116,7 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text)
|
|||||||
*_entryData = MacroActionFactory::Create(id, macro);
|
*_entryData = MacroActionFactory::Create(id, macro);
|
||||||
(*_entryData)->SetIndex(idx);
|
(*_entryData)->SetIndex(idx);
|
||||||
(*_entryData)->PostLoad();
|
(*_entryData)->PostLoad();
|
||||||
RunPostLoadSteps();
|
RunAndClearPostLoadSteps();
|
||||||
}
|
}
|
||||||
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
|
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
|
||||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||||
@@ -158,473 +157,4 @@ std::shared_ptr<MacroSegment> MacroActionEdit::Data() const
|
|||||||
return *_entryData;
|
return *_entryData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::AddMacroAction(Macro *macro, int idx,
|
|
||||||
const std::string &id, obs_data_t *data)
|
|
||||||
{
|
|
||||||
if (idx < 0 || idx > (int)macro->Actions().size()) {
|
|
||||||
assert(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto lock = LockContext();
|
|
||||||
macro->Actions().emplace(macro->Actions().begin() + idx,
|
|
||||||
MacroActionFactory::Create(id, macro));
|
|
||||||
if (data) {
|
|
||||||
macro->Actions().at(idx)->Load(data);
|
|
||||||
}
|
|
||||||
macro->Actions().at(idx)->PostLoad();
|
|
||||||
RunPostLoadSteps();
|
|
||||||
macro->UpdateActionIndices();
|
|
||||||
ui->actionsList->Insert(
|
|
||||||
idx,
|
|
||||||
new MacroActionEdit(this, ¯o->Actions()[idx], id));
|
|
||||||
SetActionData(*macro);
|
|
||||||
}
|
|
||||||
HighlightAction(idx);
|
|
||||||
ui->actionsList->SetHelpMsgVisible(false);
|
|
||||||
emit(MacroSegmentOrderChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::AddMacroAction(int idx)
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx < 0 || idx > (int)macro->Actions().size()) {
|
|
||||||
assert(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string id;
|
|
||||||
if (idx - 1 >= 0) {
|
|
||||||
id = macro->Actions().at(idx - 1)->GetId();
|
|
||||||
} else {
|
|
||||||
id = MacroAction::GetDefaultID();
|
|
||||||
}
|
|
||||||
|
|
||||||
OBSDataAutoRelease data;
|
|
||||||
if (idx - 1 >= 0) {
|
|
||||||
data = obs_data_create();
|
|
||||||
macro->Actions().at(idx - 1)->Save(data);
|
|
||||||
}
|
|
||||||
AddMacroAction(macro.get(), idx, id, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_actionAdd_clicked()
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentActionIdx == -1) {
|
|
||||||
AddMacroAction((int)macro->Actions().size());
|
|
||||||
} else {
|
|
||||||
AddMacroAction(currentActionIdx + 1);
|
|
||||||
}
|
|
||||||
if (currentActionIdx != -1) {
|
|
||||||
MacroActionSelectionChanged(currentActionIdx + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::RemoveMacroAction(int idx)
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx < 0 || idx >= (int)macro->Actions().size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto lock = LockContext();
|
|
||||||
ui->actionsList->Remove(idx);
|
|
||||||
macro->Actions().erase(macro->Actions().begin() + idx);
|
|
||||||
SetMacroAbortWait(true);
|
|
||||||
GetMacroWaitCV().notify_all();
|
|
||||||
macro->UpdateActionIndices();
|
|
||||||
SetActionData(*macro);
|
|
||||||
}
|
|
||||||
MacroActionSelectionChanged(-1);
|
|
||||||
lastInteracted = MacroSection::ACTIONS;
|
|
||||||
emit(MacroSegmentOrderChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_actionRemove_clicked()
|
|
||||||
{
|
|
||||||
if (currentActionIdx == -1) {
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RemoveMacroAction((int)macro->Actions().size() - 1);
|
|
||||||
} else {
|
|
||||||
RemoveMacroAction(currentActionIdx);
|
|
||||||
}
|
|
||||||
MacroActionSelectionChanged(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_actionTop_clicked()
|
|
||||||
{
|
|
||||||
if (currentActionIdx == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MacroActionReorder(0, currentActionIdx);
|
|
||||||
MacroActionSelectionChanged(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_actionUp_clicked()
|
|
||||||
{
|
|
||||||
if (currentActionIdx == -1 || currentActionIdx == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MoveMacroActionUp(currentActionIdx);
|
|
||||||
MacroActionSelectionChanged(currentActionIdx - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_actionDown_clicked()
|
|
||||||
{
|
|
||||||
if (currentActionIdx == -1 ||
|
|
||||||
currentActionIdx == ui->actionsList->ContentLayout()->count() - 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MoveMacroActionDown(currentActionIdx);
|
|
||||||
MacroActionSelectionChanged(currentActionIdx + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_actionBottom_clicked()
|
|
||||||
{
|
|
||||||
if (currentActionIdx == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const int newIdx = ui->actionsList->ContentLayout()->count() - 1;
|
|
||||||
MacroActionReorder(newIdx, currentActionIdx);
|
|
||||||
MacroActionSelectionChanged(newIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_elseActionAdd_clicked()
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentElseActionIdx == -1) {
|
|
||||||
AddMacroElseAction((int)macro->ElseActions().size());
|
|
||||||
} else {
|
|
||||||
AddMacroElseAction(currentElseActionIdx + 1);
|
|
||||||
}
|
|
||||||
if (currentElseActionIdx != -1) {
|
|
||||||
MacroElseActionSelectionChanged(currentElseActionIdx + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_elseActionRemove_clicked()
|
|
||||||
{
|
|
||||||
if (currentElseActionIdx == -1) {
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RemoveMacroElseAction((int)macro->ElseActions().size() - 1);
|
|
||||||
} else {
|
|
||||||
RemoveMacroElseAction(currentElseActionIdx);
|
|
||||||
}
|
|
||||||
MacroElseActionSelectionChanged(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_elseActionTop_clicked()
|
|
||||||
{
|
|
||||||
if (currentElseActionIdx == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MacroElseActionReorder(0, currentElseActionIdx);
|
|
||||||
MacroElseActionSelectionChanged(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_elseActionUp_clicked()
|
|
||||||
{
|
|
||||||
if (currentElseActionIdx == -1 || currentElseActionIdx == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MoveMacroElseActionUp(currentElseActionIdx);
|
|
||||||
MacroElseActionSelectionChanged(currentElseActionIdx - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_elseActionDown_clicked()
|
|
||||||
{
|
|
||||||
if (currentElseActionIdx == -1 ||
|
|
||||||
currentElseActionIdx ==
|
|
||||||
ui->elseActionsList->ContentLayout()->count() - 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MoveMacroElseActionDown(currentElseActionIdx);
|
|
||||||
MacroElseActionSelectionChanged(currentElseActionIdx + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_elseActionBottom_clicked()
|
|
||||||
{
|
|
||||||
if (currentElseActionIdx == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const int newIdx = ui->elseActionsList->ContentLayout()->count() - 1;
|
|
||||||
MacroElseActionReorder(newIdx, currentElseActionIdx);
|
|
||||||
MacroElseActionSelectionChanged(newIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::SwapActions(Macro *m, int pos1, int pos2)
|
|
||||||
{
|
|
||||||
if (pos1 == pos2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pos1 > pos2) {
|
|
||||||
std::swap(pos1, pos2);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
iter_swap(m->Actions().begin() + pos1, m->Actions().begin() + pos2);
|
|
||||||
m->UpdateActionIndices();
|
|
||||||
auto widget1 = static_cast<MacroActionEdit *>(
|
|
||||||
ui->actionsList->ContentLayout()->takeAt(pos1)->widget());
|
|
||||||
auto widget2 = static_cast<MacroActionEdit *>(
|
|
||||||
ui->actionsList->ContentLayout()->takeAt(pos2 - 1)->widget());
|
|
||||||
ui->actionsList->Insert(pos1, widget2);
|
|
||||||
ui->actionsList->Insert(pos2, widget1);
|
|
||||||
SetActionData(*m);
|
|
||||||
emit(MacroSegmentOrderChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::MoveMacroActionUp(int idx)
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx < 1 || idx >= (int)macro->Actions().size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SwapActions(macro.get(), idx, idx - 1);
|
|
||||||
HighlightAction(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.get(), idx, idx + 1);
|
|
||||||
HighlightAction(idx + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::MacroElseActionSelectionChanged(int idx)
|
|
||||||
{
|
|
||||||
SetupMacroSegmentSelection(MacroSection::ELSE_ACTIONS, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::MacroElseActionReorder(int to, int from)
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (to == from || from < 0 || from > (int)macro->ElseActions().size() ||
|
|
||||||
to < 0 || to > (int)macro->ElseActions().size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto lock = LockContext();
|
|
||||||
auto action = macro->ElseActions().at(from);
|
|
||||||
macro->ElseActions().erase(macro->ElseActions().begin() + from);
|
|
||||||
macro->ElseActions().insert(macro->ElseActions().begin() + to,
|
|
||||||
action);
|
|
||||||
macro->UpdateElseActionIndices();
|
|
||||||
ui->elseActionsList->ContentLayout()->insertItem(
|
|
||||||
to, ui->elseActionsList->ContentLayout()->takeAt(from));
|
|
||||||
SetElseActionData(*macro);
|
|
||||||
}
|
|
||||||
HighlightElseAction(to);
|
|
||||||
emit(MacroSegmentOrderChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::AddMacroElseAction(Macro *macro, int idx,
|
|
||||||
const std::string &id,
|
|
||||||
obs_data_t *data)
|
|
||||||
{
|
|
||||||
if (idx < 0 || idx > (int)macro->ElseActions().size()) {
|
|
||||||
assert(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto lock = LockContext();
|
|
||||||
macro->ElseActions().emplace(macro->ElseActions().begin() + idx,
|
|
||||||
MacroActionFactory::Create(id,
|
|
||||||
macro));
|
|
||||||
if (data) {
|
|
||||||
macro->ElseActions().at(idx)->Load(data);
|
|
||||||
}
|
|
||||||
macro->ElseActions().at(idx)->PostLoad();
|
|
||||||
RunPostLoadSteps();
|
|
||||||
macro->UpdateElseActionIndices();
|
|
||||||
ui->elseActionsList->Insert(
|
|
||||||
idx, new MacroActionEdit(
|
|
||||||
this, ¯o->ElseActions()[idx], id));
|
|
||||||
SetElseActionData(*macro);
|
|
||||||
}
|
|
||||||
HighlightElseAction(idx);
|
|
||||||
ui->elseActionsList->SetHelpMsgVisible(false);
|
|
||||||
emit(MacroSegmentOrderChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::AddMacroElseAction(int idx)
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx < 0 || idx > (int)macro->ElseActions().size()) {
|
|
||||||
assert(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string id;
|
|
||||||
if (idx - 1 >= 0) {
|
|
||||||
id = macro->ElseActions().at(idx - 1)->GetId();
|
|
||||||
} else {
|
|
||||||
id = MacroAction::GetDefaultID();
|
|
||||||
}
|
|
||||||
|
|
||||||
OBSDataAutoRelease data;
|
|
||||||
if (idx - 1 >= 0) {
|
|
||||||
data = obs_data_create();
|
|
||||||
macro->ElseActions().at(idx - 1)->Save(data);
|
|
||||||
}
|
|
||||||
AddMacroElseAction(macro.get(), idx, id, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::RemoveMacroElseAction(int idx)
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx < 0 || idx >= (int)macro->ElseActions().size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto lock = LockContext();
|
|
||||||
ui->elseActionsList->Remove(idx);
|
|
||||||
macro->ElseActions().erase(macro->ElseActions().begin() + idx);
|
|
||||||
SetMacroAbortWait(true);
|
|
||||||
GetMacroWaitCV().notify_all();
|
|
||||||
macro->UpdateElseActionIndices();
|
|
||||||
SetElseActionData(*macro);
|
|
||||||
}
|
|
||||||
MacroElseActionSelectionChanged(-1);
|
|
||||||
lastInteracted = MacroSection::ELSE_ACTIONS;
|
|
||||||
emit(MacroSegmentOrderChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::SwapElseActions(Macro *m, int pos1, int pos2)
|
|
||||||
{
|
|
||||||
if (pos1 == pos2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pos1 > pos2) {
|
|
||||||
std::swap(pos1, pos2);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
iter_swap(m->ElseActions().begin() + pos1,
|
|
||||||
m->ElseActions().begin() + pos2);
|
|
||||||
m->UpdateElseActionIndices();
|
|
||||||
auto widget1 = static_cast<MacroActionEdit *>(
|
|
||||||
ui->elseActionsList->ContentLayout()->takeAt(pos1)->widget());
|
|
||||||
auto widget2 = static_cast<MacroActionEdit *>(
|
|
||||||
ui->elseActionsList->ContentLayout()
|
|
||||||
->takeAt(pos2 - 1)
|
|
||||||
->widget());
|
|
||||||
ui->elseActionsList->Insert(pos1, widget2);
|
|
||||||
ui->elseActionsList->Insert(pos2, widget1);
|
|
||||||
SetElseActionData(*m);
|
|
||||||
emit(MacroSegmentOrderChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::MoveMacroElseActionUp(int idx)
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx < 1 || idx >= (int)macro->ElseActions().size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SwapElseActions(macro.get(), idx, idx - 1);
|
|
||||||
HighlightElseAction(idx - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::MoveMacroElseActionDown(int idx)
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx < 0 || idx >= (int)macro->ElseActions().size() - 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SwapElseActions(macro.get(), idx, idx + 1);
|
|
||||||
HighlightElseAction(idx + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::MacroActionSelectionChanged(int idx)
|
|
||||||
{
|
|
||||||
SetupMacroSegmentSelection(MacroSection::ACTIONS, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::MacroActionReorder(int to, int from)
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (to == from || from < 0 || from > (int)macro->Actions().size() ||
|
|
||||||
to < 0 || to > (int)macro->Actions().size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto lock = LockContext();
|
|
||||||
auto action = macro->Actions().at(from);
|
|
||||||
macro->Actions().erase(macro->Actions().begin() + from);
|
|
||||||
macro->Actions().insert(macro->Actions().begin() + to, action);
|
|
||||||
macro->UpdateActionIndices();
|
|
||||||
ui->actionsList->ContentLayout()->insertItem(
|
|
||||||
to, ui->actionsList->ContentLayout()->takeAt(from));
|
|
||||||
SetActionData(*macro);
|
|
||||||
}
|
|
||||||
HighlightAction(to);
|
|
||||||
emit(MacroSegmentOrderChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -13,10 +13,8 @@ class MacroActionEdit : public MacroSegmentEdit {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MacroActionEdit(
|
MacroActionEdit(QWidget *parent = nullptr,
|
||||||
QWidget *parent = nullptr,
|
std::shared_ptr<MacroAction> * = nullptr);
|
||||||
std::shared_ptr<MacroAction> * = nullptr,
|
|
||||||
const std::string &id = MacroAction::GetDefaultID().data());
|
|
||||||
void SetupWidgets(bool basicSetup = false);
|
void SetupWidgets(bool basicSetup = false);
|
||||||
void SetEntryData(std::shared_ptr<MacroAction> *);
|
void SetEntryData(std::shared_ptr<MacroAction> *);
|
||||||
|
|
||||||
|
|||||||
@@ -1,25 +1,11 @@
|
|||||||
#include "macro-action-factory.hpp"
|
#include "macro-action-factory.hpp"
|
||||||
|
#include "macro-segment-unknown.hpp"
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
namespace {
|
using MacroActionUnknown = MacroSegmentUnknown<MacroAction>;
|
||||||
|
|
||||||
class MacroActionUnknown : public MacroAction {
|
|
||||||
public:
|
|
||||||
MacroActionUnknown(Macro *m) : MacroAction(m) {}
|
|
||||||
std::shared_ptr<MacroAction> Copy() const
|
|
||||||
{
|
|
||||||
return std::make_shared<MacroActionUnknown>(GetMacro());
|
|
||||||
}
|
|
||||||
bool PerformAction() { return true; };
|
|
||||||
bool Save(obs_data_t *obj) const { return MacroAction::Save(obj); };
|
|
||||||
bool Load(obs_data_t *obj) { return MacroAction::Load(obj); };
|
|
||||||
std::string GetId() const { return "unknown"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
static std::recursive_mutex mutex;
|
static std::recursive_mutex mutex;
|
||||||
|
|
||||||
@@ -49,9 +35,10 @@ bool MacroActionFactory::Deregister(const std::string &id)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<MacroAction> createUnknownAction(Macro *m)
|
static std::shared_ptr<MacroAction> createUnknownAction(Macro *m,
|
||||||
|
const std::string &id)
|
||||||
{
|
{
|
||||||
return std::make_shared<MacroActionUnknown>(m);
|
return std::make_shared<MacroActionUnknown>(m, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<MacroAction> MacroActionFactory::Create(const std::string &id,
|
std::shared_ptr<MacroAction> MacroActionFactory::Create(const std::string &id,
|
||||||
@@ -62,12 +49,7 @@ std::shared_ptr<MacroAction> MacroActionFactory::Create(const std::string &id,
|
|||||||
return it->second._create(m);
|
return it->second._create(m);
|
||||||
}
|
}
|
||||||
|
|
||||||
return createUnknownAction(m);
|
return createUnknownAction(m, id);
|
||||||
}
|
|
||||||
|
|
||||||
static QWidget *createUnknownActionWidget()
|
|
||||||
{
|
|
||||||
return new QLabel(obs_module_text("AdvSceneSwitcher.action.unknown"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *MacroActionFactory::CreateWidget(const std::string &id,
|
QWidget *MacroActionFactory::CreateWidget(const std::string &id,
|
||||||
@@ -79,7 +61,7 @@ QWidget *MacroActionFactory::CreateWidget(const std::string &id,
|
|||||||
return it->second._createWidget(parent, action);
|
return it->second._createWidget(parent, action);
|
||||||
}
|
}
|
||||||
|
|
||||||
return createUnknownActionWidget();
|
return CreateUnknownSegmentWidget(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MacroActionFactory::GetActionName(const std::string &id)
|
std::string MacroActionFactory::GetActionName(const std::string &id)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "help-icon.hpp"
|
#include "help-icon.hpp"
|
||||||
#include "layout-helpers.hpp"
|
#include "layout-helpers.hpp"
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
|
#include "macro-action-factory.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -12,8 +13,81 @@ bool MacroActionMacro::_registered = MacroActionFactory::Register(
|
|||||||
{MacroActionMacro::Create, MacroActionMacroEdit::Create,
|
{MacroActionMacro::Create, MacroActionMacroEdit::Create,
|
||||||
"AdvSceneSwitcher.action.macro"});
|
"AdvSceneSwitcher.action.macro"});
|
||||||
|
|
||||||
|
void MacroActionMacro::AdjustActionState(Macro *macro) const
|
||||||
|
{
|
||||||
|
const auto ¯oActions = _useElseSection ? macro->ElseActions()
|
||||||
|
: macro->Actions();
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<MacroAction>> actionsToModify;
|
||||||
|
switch (_actionSelectionType) {
|
||||||
|
case SelectionType::INDEX: {
|
||||||
|
const bool isValidAction =
|
||||||
|
(_useElseSection &&
|
||||||
|
IsValidElseActionIndex(macro, _actionIndex - 1)) ||
|
||||||
|
(!_useElseSection &&
|
||||||
|
IsValidActionIndex(macro, _actionIndex - 1));
|
||||||
|
|
||||||
|
if (isValidAction) {
|
||||||
|
actionsToModify.emplace_back(
|
||||||
|
macroActions.at(_actionIndex - 1));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SelectionType::LABEL:
|
||||||
|
for (const auto &action : macroActions) {
|
||||||
|
if (!action->GetUseCustomLabel()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto label = action->GetCustomLabel();
|
||||||
|
|
||||||
|
if (_regex.Enabled()) {
|
||||||
|
if (_regex.Matches(label, _label)) {
|
||||||
|
actionsToModify.emplace_back(action);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (label == std::string(_label)) {
|
||||||
|
actionsToModify.emplace_back(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case SelectionType::ID:
|
||||||
|
for (const auto &action : macroActions) {
|
||||||
|
if (action->GetId() == _actionId) {
|
||||||
|
actionsToModify.emplace_back(action);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &action : actionsToModify) {
|
||||||
|
switch (_action) {
|
||||||
|
case Action::DISABLE_ACTION:
|
||||||
|
action->SetEnabled(false);
|
||||||
|
break;
|
||||||
|
case Action::ENABLE_ACTION:
|
||||||
|
action->SetEnabled(true);
|
||||||
|
break;
|
||||||
|
case Action::TOGGLE_ACTION:
|
||||||
|
action->SetEnabled(!action->Enabled());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool MacroActionMacro::PerformAction()
|
bool MacroActionMacro::PerformAction()
|
||||||
{
|
{
|
||||||
|
if (_action == Action::NESTED_MACRO) {
|
||||||
|
const bool conditionsMatched = _nestedMacro->CheckConditions();
|
||||||
|
return _nestedMacro->PerformActions(conditionsMatched);
|
||||||
|
}
|
||||||
|
|
||||||
auto macro = _macro.GetMacro();
|
auto macro = _macro.GetMacro();
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
return true;
|
return true;
|
||||||
@@ -32,30 +106,16 @@ bool MacroActionMacro::PerformAction()
|
|||||||
case Action::RESET_COUNTER:
|
case Action::RESET_COUNTER:
|
||||||
macro->ResetRunCount();
|
macro->ResetRunCount();
|
||||||
break;
|
break;
|
||||||
case Action::RUN:
|
case Action::RUN_ACTIONS:
|
||||||
RunActions(macro.get());
|
RunActions(macro.get());
|
||||||
break;
|
break;
|
||||||
case Action::STOP:
|
case Action::STOP:
|
||||||
macro->Stop();
|
macro->Stop();
|
||||||
break;
|
break;
|
||||||
case Action::DISABLE_ACTION:
|
case Action::DISABLE_ACTION:
|
||||||
if (IsValidMacroSegmentIndex(macro.get(), _actionIndex - 1,
|
|
||||||
false)) {
|
|
||||||
macro->Actions().at(_actionIndex - 1)->SetEnabled(false);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Action::ENABLE_ACTION:
|
case Action::ENABLE_ACTION:
|
||||||
if (IsValidMacroSegmentIndex(macro.get(), _actionIndex - 1,
|
|
||||||
false)) {
|
|
||||||
macro->Actions().at(_actionIndex - 1)->SetEnabled(true);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Action::TOGGLE_ACTION:
|
case Action::TOGGLE_ACTION:
|
||||||
if (IsValidMacroSegmentIndex(macro.get(), _actionIndex - 1,
|
AdjustActionState(macro.get());
|
||||||
false)) {
|
|
||||||
auto action = macro->Actions().at(_actionIndex - 1);
|
|
||||||
action->SetEnabled(!action->Enabled());
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -80,7 +140,7 @@ void MacroActionMacro::LogAction() const
|
|||||||
ablog(LOG_INFO, "reset counter for \"%s\"",
|
ablog(LOG_INFO, "reset counter for \"%s\"",
|
||||||
macro->Name().c_str());
|
macro->Name().c_str());
|
||||||
break;
|
break;
|
||||||
case Action::RUN:
|
case Action::RUN_ACTIONS:
|
||||||
ablog(LOG_INFO, "run nested macro \"%s\"",
|
ablog(LOG_INFO, "run nested macro \"%s\"",
|
||||||
macro->Name().c_str());
|
macro->Name().c_str());
|
||||||
break;
|
break;
|
||||||
@@ -99,6 +159,9 @@ void MacroActionMacro::LogAction() const
|
|||||||
ablog(LOG_INFO, "toggled action %d of macro \"%s\"",
|
ablog(LOG_INFO, "toggled action %d of macro \"%s\"",
|
||||||
_actionIndex.GetValue(), macro->Name().c_str());
|
_actionIndex.GetValue(), macro->Name().c_str());
|
||||||
break;
|
break;
|
||||||
|
case Action::NESTED_MACRO:
|
||||||
|
ablog(LOG_INFO, "run nested macro");
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -107,21 +170,44 @@ void MacroActionMacro::LogAction() const
|
|||||||
bool MacroActionMacro::Save(obs_data_t *obj) const
|
bool MacroActionMacro::Save(obs_data_t *obj) const
|
||||||
{
|
{
|
||||||
MacroAction::Save(obj);
|
MacroAction::Save(obj);
|
||||||
_macro.Save(obj);
|
|
||||||
_actionIndex.Save(obj, "actionIndex");
|
|
||||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||||
|
_macro.Save(obj);
|
||||||
|
obs_data_set_int(obj, "actionSelectionType",
|
||||||
|
static_cast<int>(_actionSelectionType));
|
||||||
|
_actionIndex.Save(obj, "actionIndex");
|
||||||
|
_label.Save(obj, "label");
|
||||||
|
obs_data_set_string(obj, "actionId", _actionId.c_str());
|
||||||
|
_regex.Save(obj);
|
||||||
_runOptions.Save(obj);
|
_runOptions.Save(obj);
|
||||||
|
OBSDataAutoRelease nestedMacroData = obs_data_create();
|
||||||
|
_nestedMacro->Save(nestedMacroData);
|
||||||
|
obs_data_set_obj(obj, "nestedMacro", nestedMacroData);
|
||||||
|
obs_data_set_int(obj, "customWidgetHeight", _customWidgetHeight);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroActionMacro::Load(obs_data_t *obj)
|
bool MacroActionMacro::Load(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
MacroAction::Load(obj);
|
MacroAction::Load(obj);
|
||||||
_macro.Load(obj);
|
|
||||||
_actionIndex.Load(obj, "actionIndex");
|
|
||||||
_action = static_cast<MacroActionMacro::Action>(
|
_action = static_cast<MacroActionMacro::Action>(
|
||||||
obs_data_get_int(obj, "action"));
|
obs_data_get_int(obj, "action"));
|
||||||
|
_macro.Load(obj);
|
||||||
|
_actionSelectionType = static_cast<SelectionType>(
|
||||||
|
obs_data_get_int(obj, "actionSelectionType"));
|
||||||
|
_actionIndex.Load(obj, "actionIndex");
|
||||||
|
_label.Load(obj, "label");
|
||||||
|
_actionId = obs_data_get_string(obj, "actionId");
|
||||||
|
_regex.Load(obj);
|
||||||
_runOptions.Load(obj);
|
_runOptions.Load(obj);
|
||||||
|
|
||||||
|
if (obs_data_has_user_value(obj, "nestedMacro")) {
|
||||||
|
OBSDataAutoRelease nestedMacroData =
|
||||||
|
obs_data_get_obj(obj, "nestedMacro");
|
||||||
|
_nestedMacro->Load(nestedMacroData);
|
||||||
|
}
|
||||||
|
|
||||||
|
_customWidgetHeight = obs_data_get_int(obj, "customWidgetHeight");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,6 +216,7 @@ bool MacroActionMacro::PostLoad()
|
|||||||
MacroRefAction::PostLoad();
|
MacroRefAction::PostLoad();
|
||||||
MacroAction::PostLoad();
|
MacroAction::PostLoad();
|
||||||
_runOptions.macro.PostLoad();
|
_runOptions.macro.PostLoad();
|
||||||
|
_nestedMacro->PostLoad();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,12 +232,23 @@ std::shared_ptr<MacroAction> MacroActionMacro::Create(Macro *m)
|
|||||||
|
|
||||||
std::shared_ptr<MacroAction> MacroActionMacro::Copy() const
|
std::shared_ptr<MacroAction> MacroActionMacro::Copy() const
|
||||||
{
|
{
|
||||||
return std::make_shared<MacroActionMacro>(*this);
|
auto copy = std::make_shared<MacroActionMacro>(*this);
|
||||||
|
|
||||||
|
// Create a new nested macro
|
||||||
|
OBSDataAutoRelease data = obs_data_create();
|
||||||
|
_nestedMacro->Save(data);
|
||||||
|
|
||||||
|
copy->_nestedMacro = std::make_shared<Macro>();
|
||||||
|
copy->_nestedMacro->Load(data);
|
||||||
|
copy->_nestedMacro->PostLoad();
|
||||||
|
|
||||||
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionMacro::ResolveVariablesToFixedValues()
|
void MacroActionMacro::ResolveVariablesToFixedValues()
|
||||||
{
|
{
|
||||||
_actionIndex.ResolveVariables();
|
_actionIndex.ResolveVariables();
|
||||||
|
_label.ResolveVariables();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void runActionsHelper(Macro *macro, bool runElseActions, bool setInputs,
|
static void runActionsHelper(Macro *macro, bool runElseActions, bool setInputs,
|
||||||
@@ -204,7 +302,9 @@ static void populateActionSelection(QComboBox *list)
|
|||||||
"AdvSceneSwitcher.action.macro.type.togglePause"},
|
"AdvSceneSwitcher.action.macro.type.togglePause"},
|
||||||
{MacroActionMacro::Action::RESET_COUNTER,
|
{MacroActionMacro::Action::RESET_COUNTER,
|
||||||
"AdvSceneSwitcher.action.macro.type.resetCounter"},
|
"AdvSceneSwitcher.action.macro.type.resetCounter"},
|
||||||
{MacroActionMacro::Action::RUN,
|
{MacroActionMacro::Action::NESTED_MACRO,
|
||||||
|
"AdvSceneSwitcher.action.macro.type.nestedMacro"},
|
||||||
|
{MacroActionMacro::Action::RUN_ACTIONS,
|
||||||
"AdvSceneSwitcher.action.macro.type.run"},
|
"AdvSceneSwitcher.action.macro.type.run"},
|
||||||
{MacroActionMacro::Action::STOP,
|
{MacroActionMacro::Action::STOP,
|
||||||
"AdvSceneSwitcher.action.macro.type.stop"},
|
"AdvSceneSwitcher.action.macro.type.stop"},
|
||||||
@@ -232,7 +332,7 @@ static void populateConditionBehaviorSelection(QComboBox *list)
|
|||||||
"AdvSceneSwitcher.action.macro.type.run.conditions.false"));
|
"AdvSceneSwitcher.action.macro.type.run.conditions.false"));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void populateActionTypeSelection(QComboBox *list)
|
static void populateActionSectionSelection(QComboBox *list)
|
||||||
{
|
{
|
||||||
list->addItem(obs_module_text(
|
list->addItem(obs_module_text(
|
||||||
"AdvSceneSwitcher.action.macro.type.run.actionType.regular"));
|
"AdvSceneSwitcher.action.macro.type.run.actionType.regular"));
|
||||||
@@ -240,19 +340,47 @@ static void populateActionTypeSelection(QComboBox *list)
|
|||||||
"AdvSceneSwitcher.action.macro.type.run.actionType.else"));
|
"AdvSceneSwitcher.action.macro.type.run.actionType.else"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void populateActionTypes(QComboBox *list)
|
||||||
|
{
|
||||||
|
for (const auto &[id, info] : MacroActionFactory::GetActionTypes()) {
|
||||||
|
list->addItem(obs_module_text(info._name.c_str()),
|
||||||
|
QString::fromStdString(id));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void populateActionSelectionTypes(QComboBox *list)
|
||||||
|
{
|
||||||
|
list->addItem(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.macro.actionSelectionType.index"),
|
||||||
|
static_cast<int>(MacroActionMacro::SelectionType::INDEX));
|
||||||
|
list->addItem(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.macro.actionSelectionType.label"),
|
||||||
|
static_cast<int>(MacroActionMacro::SelectionType::LABEL));
|
||||||
|
list->addItem(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.macro.actionSelectionType.id"),
|
||||||
|
static_cast<int>(MacroActionMacro::SelectionType::ID));
|
||||||
|
}
|
||||||
|
|
||||||
MacroActionMacroEdit::MacroActionMacroEdit(
|
MacroActionMacroEdit::MacroActionMacroEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroActionMacro> entryData)
|
QWidget *parent, std::shared_ptr<MacroActionMacro> entryData)
|
||||||
: QWidget(parent),
|
: ResizableWidget(parent),
|
||||||
|
_actions(new QComboBox()),
|
||||||
_macros(new MacroSelection(parent)),
|
_macros(new MacroSelection(parent)),
|
||||||
|
_actionSelectionType(new QComboBox(this)),
|
||||||
_actionIndex(new MacroSegmentSelection(
|
_actionIndex(new MacroSegmentSelection(
|
||||||
this, MacroSegmentSelection::Type::ACTION)),
|
this, MacroSegmentSelection::Type::ACTION)),
|
||||||
_actions(new QComboBox()),
|
_label(new VariableLineEdit(this)),
|
||||||
|
_actionTypes(new FilterComboBox(this)),
|
||||||
|
_regex(new RegexConfigWidget(this)),
|
||||||
_conditionMacros(new MacroSelection(parent)),
|
_conditionMacros(new MacroSelection(parent)),
|
||||||
_conditionBehaviors(new QComboBox()),
|
_conditionBehaviors(new QComboBox()),
|
||||||
_reevaluateConditionState(new QCheckBox(
|
_reevaluateConditionState(new QCheckBox(
|
||||||
obs_module_text("AdvSceneSwitcher.action.macro.type.run."
|
obs_module_text("AdvSceneSwitcher.action.macro.type.run."
|
||||||
"updateConditionMatchState"))),
|
"updateConditionMatchState"))),
|
||||||
_actionTypes(new QComboBox()),
|
_actionSections(new QComboBox(this)),
|
||||||
_skipWhenPaused(new QCheckBox(obs_module_text(
|
_skipWhenPaused(new QCheckBox(obs_module_text(
|
||||||
"AdvSceneSwitcher.action.macro.type.run.skipWhenPaused"))),
|
"AdvSceneSwitcher.action.macro.type.run.skipWhenPaused"))),
|
||||||
_setInputs(new QCheckBox(obs_module_text(
|
_setInputs(new QCheckBox(obs_module_text(
|
||||||
@@ -261,11 +389,19 @@ MacroActionMacroEdit::MacroActionMacroEdit(
|
|||||||
_entryLayout(new QHBoxLayout()),
|
_entryLayout(new QHBoxLayout()),
|
||||||
_conditionLayout(new QHBoxLayout()),
|
_conditionLayout(new QHBoxLayout()),
|
||||||
_reevaluateConditionStateLayout(new QHBoxLayout()),
|
_reevaluateConditionStateLayout(new QHBoxLayout()),
|
||||||
_setInputsLayout(new QHBoxLayout())
|
_setInputsLayout(new QHBoxLayout()),
|
||||||
|
_nestedMacro(new MacroEdit(
|
||||||
|
this,
|
||||||
|
QStringList()
|
||||||
|
<< "AdvSceneSwitcher.action.macro.type.nestedMacro.conditionHelp"
|
||||||
|
<< "AdvSceneSwitcher.action.macro.type.nestedMacro.actionHelp"
|
||||||
|
<< "AdvSceneSwitcher.action.macro.type.nestedMacro.elseActionHelp"))
|
||||||
{
|
{
|
||||||
populateActionSelection(_actions);
|
populateActionSelection(_actions);
|
||||||
populateConditionBehaviorSelection(_conditionBehaviors);
|
populateConditionBehaviorSelection(_conditionBehaviors);
|
||||||
populateActionTypeSelection(_actionTypes);
|
populateActionSectionSelection(_actionSections);
|
||||||
|
populateActionSelectionTypes(_actionSelectionType);
|
||||||
|
populateActionTypes(_actionTypes);
|
||||||
|
|
||||||
_conditionMacros->HideSelectedMacro();
|
_conditionMacros->HideSelectedMacro();
|
||||||
|
|
||||||
@@ -273,16 +409,25 @@ MacroActionMacroEdit::MacroActionMacroEdit(
|
|||||||
this, SLOT(MacroChanged(const QString &)));
|
this, SLOT(MacroChanged(const QString &)));
|
||||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(ActionChanged(int)));
|
SLOT(ActionChanged(int)));
|
||||||
|
QWidget::connect(_actionSelectionType, SIGNAL(currentIndexChanged(int)),
|
||||||
|
this, SLOT(ActionSelectionTypeChanged(int)));
|
||||||
QWidget::connect(_actionIndex,
|
QWidget::connect(_actionIndex,
|
||||||
SIGNAL(SelectionChanged(const IntVariable &)), this,
|
SIGNAL(SelectionChanged(const IntVariable &)), this,
|
||||||
SLOT(ActionIndexChanged(const IntVariable &)));
|
SLOT(ActionIndexChanged(const IntVariable &)));
|
||||||
|
QWidget::connect(_label, SIGNAL(editingFinished()), this,
|
||||||
|
SLOT(LabelChanged()));
|
||||||
|
QWidget::connect(_actionTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||||
|
SLOT(ActionTypeChanged(int)));
|
||||||
|
QWidget::connect(_regex,
|
||||||
|
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
|
||||||
|
SLOT(RegexChanged(const RegexConfig &)));
|
||||||
QWidget::connect(_conditionMacros,
|
QWidget::connect(_conditionMacros,
|
||||||
SIGNAL(currentTextChanged(const QString &)), this,
|
SIGNAL(currentTextChanged(const QString &)), this,
|
||||||
SLOT(ConditionMacroChanged(const QString &)));
|
SLOT(ConditionMacroChanged(const QString &)));
|
||||||
QWidget::connect(_conditionBehaviors, SIGNAL(currentIndexChanged(int)),
|
QWidget::connect(_conditionBehaviors, SIGNAL(currentIndexChanged(int)),
|
||||||
this, SLOT(ConditionBehaviorChanged(int)));
|
this, SLOT(ConditionBehaviorChanged(int)));
|
||||||
QWidget::connect(_actionTypes, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_actionSections, SIGNAL(currentIndexChanged(int)),
|
||||||
SLOT(ActionTypeChanged(int)));
|
this, SLOT(ActionSectionChanged(int)));
|
||||||
QWidget::connect(_skipWhenPaused, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_skipWhenPaused, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(SkipWhenPausedChanged(int)));
|
SLOT(SkipWhenPausedChanged(int)));
|
||||||
QWidget::connect(_setInputs, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_setInputs, SIGNAL(stateChanged(int)), this,
|
||||||
@@ -310,6 +455,7 @@ MacroActionMacroEdit::MacroActionMacroEdit(
|
|||||||
layout->addLayout(_setInputsLayout);
|
layout->addLayout(_setInputsLayout);
|
||||||
layout->addWidget(_inputs);
|
layout->addWidget(_inputs);
|
||||||
layout->addWidget(_skipWhenPaused);
|
layout->addWidget(_skipWhenPaused);
|
||||||
|
layout->addWidget(_nestedMacro);
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
_entryData = entryData;
|
_entryData = entryData;
|
||||||
UpdateEntryData();
|
UpdateEntryData();
|
||||||
@@ -321,6 +467,12 @@ void HighlightMacroSettingsButton(bool enable);
|
|||||||
MacroActionMacroEdit::~MacroActionMacroEdit()
|
MacroActionMacroEdit::~MacroActionMacroEdit()
|
||||||
{
|
{
|
||||||
HighlightMacroSettingsButton(false);
|
HighlightMacroSettingsButton(false);
|
||||||
|
|
||||||
|
if (!_entryData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_entryData->_customWidgetHeight = GetCustomHeight();
|
||||||
|
_nestedMacro->SetMacro({}); // Save splitter states
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionMacroEdit::UpdateEntryData()
|
void MacroActionMacroEdit::UpdateEntryData()
|
||||||
@@ -328,24 +480,42 @@ void MacroActionMacroEdit::UpdateEntryData()
|
|||||||
if (!_entryData) {
|
if (!_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_actions->setCurrentIndex(
|
_actions->setCurrentIndex(
|
||||||
_actions->findData(static_cast<int>(_entryData->_action)));
|
_actions->findData(static_cast<int>(_entryData->_action)));
|
||||||
|
_actionSelectionType->setCurrentIndex(_actionSelectionType->findData(
|
||||||
|
static_cast<int>(_entryData->_actionSelectionType)));
|
||||||
_actionIndex->SetValue(_entryData->_actionIndex);
|
_actionIndex->SetValue(_entryData->_actionIndex);
|
||||||
_actionIndex->SetMacro(_entryData->_macro.GetMacro());
|
_actionIndex->SetMacro(_entryData->_macro.GetMacro());
|
||||||
|
_label->setText(_entryData->_label);
|
||||||
|
_actionTypes->setCurrentIndex(_actionTypes->findData(
|
||||||
|
QString::fromStdString(_entryData->_actionId)));
|
||||||
|
_regex->SetRegexConfig(_entryData->_regex);
|
||||||
_macros->SetCurrentMacro(_entryData->_macro);
|
_macros->SetCurrentMacro(_entryData->_macro);
|
||||||
_conditionMacros->SetCurrentMacro(_entryData->_runOptions.macro);
|
_conditionMacros->SetCurrentMacro(_entryData->_runOptions.macro);
|
||||||
_conditionBehaviors->setCurrentIndex(
|
_conditionBehaviors->setCurrentIndex(
|
||||||
static_cast<int>(_entryData->_runOptions.logic));
|
static_cast<int>(_entryData->_runOptions.logic));
|
||||||
_reevaluateConditionState->setChecked(
|
_reevaluateConditionState->setChecked(
|
||||||
_entryData->_runOptions.reevaluateConditionState);
|
_entryData->_runOptions.reevaluateConditionState);
|
||||||
_actionTypes->setCurrentIndex(
|
_actionSections->setCurrentIndex(
|
||||||
_entryData->_runOptions.runElseActions ? 1 : 0);
|
_entryData->_runOptions.runElseActions ? 1 : 0);
|
||||||
_skipWhenPaused->setChecked(_entryData->_runOptions.skipWhenPaused);
|
_skipWhenPaused->setChecked(_entryData->_runOptions.skipWhenPaused);
|
||||||
_setInputs->setChecked(_entryData->_runOptions.setInputs);
|
_setInputs->setChecked(_entryData->_runOptions.setInputs);
|
||||||
SetupMacroInput(_entryData->_macro.GetMacro().get());
|
SetupMacroInput(_entryData->_macro.GetMacro().get());
|
||||||
|
|
||||||
|
const auto ¯o = _entryData->_nestedMacro;
|
||||||
|
_nestedMacro->SetMacro(macro);
|
||||||
|
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWidget *MacroActionMacroEdit::Create(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroAction> action)
|
||||||
|
{
|
||||||
|
return new MacroActionMacroEdit(
|
||||||
|
parent, std::dynamic_pointer_cast<MacroActionMacro>(action));
|
||||||
|
}
|
||||||
|
|
||||||
void MacroActionMacroEdit::MacroChanged(const QString &text)
|
void MacroActionMacroEdit::MacroChanged(const QString &text)
|
||||||
{
|
{
|
||||||
GUARD_LOADING_AND_LOCK();
|
GUARD_LOADING_AND_LOCK();
|
||||||
@@ -366,12 +536,40 @@ void MacroActionMacroEdit::ActionChanged(int idx)
|
|||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionMacroEdit::ActionSelectionTypeChanged(int idx)
|
||||||
|
{
|
||||||
|
GUARD_LOADING_AND_LOCK();
|
||||||
|
_entryData->_actionSelectionType =
|
||||||
|
static_cast<MacroActionMacro::SelectionType>(
|
||||||
|
_actionSelectionType->itemData(idx).toInt());
|
||||||
|
SetWidgetVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
void MacroActionMacroEdit::ActionIndexChanged(const IntVariable &value)
|
void MacroActionMacroEdit::ActionIndexChanged(const IntVariable &value)
|
||||||
{
|
{
|
||||||
GUARD_LOADING_AND_LOCK();
|
GUARD_LOADING_AND_LOCK();
|
||||||
_entryData->_actionIndex = value;
|
_entryData->_actionIndex = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionMacroEdit::LabelChanged()
|
||||||
|
{
|
||||||
|
GUARD_LOADING_AND_LOCK();
|
||||||
|
_entryData->_label = _label->text().toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionMacroEdit::ActionTypeChanged(int idx)
|
||||||
|
{
|
||||||
|
GUARD_LOADING_AND_LOCK();
|
||||||
|
_entryData->_actionId =
|
||||||
|
_actionTypes->itemData(idx).toString().toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionMacroEdit::RegexChanged(const RegexConfig ®ex)
|
||||||
|
{
|
||||||
|
GUARD_LOADING_AND_LOCK();
|
||||||
|
_entryData->_regex = regex;
|
||||||
|
}
|
||||||
|
|
||||||
void MacroActionMacroEdit::ConditionMacroChanged(const QString &text)
|
void MacroActionMacroEdit::ConditionMacroChanged(const QString &text)
|
||||||
{
|
{
|
||||||
GUARD_LOADING_AND_LOCK();
|
GUARD_LOADING_AND_LOCK();
|
||||||
@@ -393,10 +591,13 @@ void MacroActionMacroEdit::ReevaluateConditionStateChanged(int value)
|
|||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionMacroEdit::ActionTypeChanged(int value)
|
void MacroActionMacroEdit::ActionSectionChanged(int useElse)
|
||||||
{
|
{
|
||||||
GUARD_LOADING_AND_LOCK();
|
GUARD_LOADING_AND_LOCK();
|
||||||
_entryData->_runOptions.runElseActions = value;
|
_entryData->_runOptions.runElseActions = useElse;
|
||||||
|
_entryData->_useElseSection = useElse;
|
||||||
|
_actionIndex->SetType(useElse ? MacroSegmentSelection::Type::ELSE_ACTION
|
||||||
|
: MacroSegmentSelection::Type::ACTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionMacroEdit::SkipWhenPausedChanged(int value)
|
void MacroActionMacroEdit::SkipWhenPausedChanged(int value)
|
||||||
@@ -425,7 +626,11 @@ void MacroActionMacroEdit::SetWidgetVisibility()
|
|||||||
_entryLayout->removeWidget(_actions);
|
_entryLayout->removeWidget(_actions);
|
||||||
_entryLayout->removeWidget(_actionIndex);
|
_entryLayout->removeWidget(_actionIndex);
|
||||||
_entryLayout->removeWidget(_macros);
|
_entryLayout->removeWidget(_macros);
|
||||||
|
_entryLayout->removeWidget(_actionSections);
|
||||||
|
_entryLayout->removeWidget(_label);
|
||||||
|
_entryLayout->removeWidget(_regex);
|
||||||
_entryLayout->removeWidget(_actionTypes);
|
_entryLayout->removeWidget(_actionTypes);
|
||||||
|
_entryLayout->removeWidget(_actionSelectionType);
|
||||||
_conditionLayout->removeWidget(_conditionBehaviors);
|
_conditionLayout->removeWidget(_conditionBehaviors);
|
||||||
_conditionLayout->removeWidget(_conditionMacros);
|
_conditionLayout->removeWidget(_conditionMacros);
|
||||||
|
|
||||||
@@ -436,18 +641,40 @@ void MacroActionMacroEdit::SetWidgetVisibility()
|
|||||||
{"{{actions}}", _actions},
|
{"{{actions}}", _actions},
|
||||||
{"{{actionIndex}}", _actionIndex},
|
{"{{actionIndex}}", _actionIndex},
|
||||||
{"{{macros}}", _macros},
|
{"{{macros}}", _macros},
|
||||||
{"{{actionTypes}}", _actionTypes},
|
{"{{actionSections}}", _actionSections},
|
||||||
{"{{conditionBehaviors}}", _conditionBehaviors},
|
{"{{conditionBehaviors}}", _conditionBehaviors},
|
||||||
{"{{conditionMacros}}", _conditionMacros},
|
{"{{conditionMacros}}", _conditionMacros},
|
||||||
|
{"{{actionSelectionType}}", _actionSelectionType},
|
||||||
|
{"{{label}}", _label},
|
||||||
|
{"{{regex}}", _regex},
|
||||||
|
{"{{actionTypes}}", _actionTypes},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
PlaceWidgets(
|
const auto action = _entryData->_action;
|
||||||
obs_module_text(
|
const char *layoutText = "";
|
||||||
_entryData->_action == MacroActionMacro::Action::RUN
|
switch (action) {
|
||||||
? "AdvSceneSwitcher.action.macro.entry.run"
|
case MacroActionMacro::Action::PAUSE:
|
||||||
: "AdvSceneSwitcher.action.macro.entry.other"),
|
case MacroActionMacro::Action::UNPAUSE:
|
||||||
_entryLayout, placeholders);
|
case MacroActionMacro::Action::TOGGLE_PAUSE:
|
||||||
|
case MacroActionMacro::Action::RESET_COUNTER:
|
||||||
|
case MacroActionMacro::Action::STOP:
|
||||||
|
case MacroActionMacro::Action::NESTED_MACRO:
|
||||||
|
layoutText = "AdvSceneSwitcher.action.macro.layout.other";
|
||||||
|
break;
|
||||||
|
case MacroActionMacro::Action::RUN_ACTIONS:
|
||||||
|
layoutText = "AdvSceneSwitcher.action.macro.layout.run";
|
||||||
|
break;
|
||||||
|
case MacroActionMacro::Action::DISABLE_ACTION:
|
||||||
|
case MacroActionMacro::Action::ENABLE_ACTION:
|
||||||
|
case MacroActionMacro::Action::TOGGLE_ACTION:
|
||||||
|
layoutText = "AdvSceneSwitcher.action.macro.layout.actionState";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
PlaceWidgets(obs_module_text(layoutText), _entryLayout, placeholders);
|
||||||
|
|
||||||
if (_entryData->_runOptions.logic ==
|
if (_entryData->_runOptions.logic ==
|
||||||
MacroActionMacro::RunOptions::Logic::IGNORE_CONDITIONS) {
|
MacroActionMacro::RunOptions::Logic::IGNORE_CONDITIONS) {
|
||||||
@@ -456,47 +683,70 @@ void MacroActionMacroEdit::SetWidgetVisibility()
|
|||||||
} else {
|
} else {
|
||||||
PlaceWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text(
|
obs_module_text(
|
||||||
"AdvSceneSwitcher.action.macro.entry.run.condition"),
|
"AdvSceneSwitcher.action.macro.layout.run.condition"),
|
||||||
_conditionLayout, placeholders);
|
_conditionLayout, placeholders);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_entryData->_action == MacroActionMacro::Action::RUN ||
|
if (action == MacroActionMacro::Action::RUN_ACTIONS ||
|
||||||
_entryData->_action == MacroActionMacro::Action::STOP) {
|
action == MacroActionMacro::Action::STOP) {
|
||||||
_macros->HideSelectedMacro();
|
_macros->HideSelectedMacro();
|
||||||
} else {
|
} else {
|
||||||
_macros->ShowAllMacros();
|
_macros->ShowAllMacros();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const auto actionSelectionType = _entryData->_actionSelectionType;
|
||||||
const bool isModifyingActionState =
|
const bool isModifyingActionState =
|
||||||
_entryData->_action ==
|
action == MacroActionMacro::Action::DISABLE_ACTION ||
|
||||||
MacroActionMacro::Action::DISABLE_ACTION ||
|
action == MacroActionMacro::Action::ENABLE_ACTION ||
|
||||||
_entryData->_action ==
|
action == MacroActionMacro::Action::TOGGLE_ACTION;
|
||||||
MacroActionMacro::Action::ENABLE_ACTION ||
|
_actionSelectionType->setVisible(isModifyingActionState);
|
||||||
_entryData->_action == MacroActionMacro::Action::TOGGLE_ACTION;
|
_actionIndex->setVisible(
|
||||||
_actionIndex->setVisible(isModifyingActionState);
|
isModifyingActionState &&
|
||||||
|
actionSelectionType == MacroActionMacro::SelectionType::INDEX);
|
||||||
|
_label->setVisible(isModifyingActionState &&
|
||||||
|
actionSelectionType ==
|
||||||
|
MacroActionMacro::SelectionType::LABEL);
|
||||||
|
_regex->setVisible(isModifyingActionState &&
|
||||||
|
actionSelectionType ==
|
||||||
|
MacroActionMacro::SelectionType::LABEL);
|
||||||
|
_actionTypes->setVisible(isModifyingActionState &&
|
||||||
|
actionSelectionType ==
|
||||||
|
MacroActionMacro::SelectionType::ID);
|
||||||
|
|
||||||
SetLayoutVisible(_conditionLayout,
|
SetLayoutVisible(_conditionLayout,
|
||||||
_entryData->_action == MacroActionMacro::Action::RUN);
|
action == MacroActionMacro::Action::RUN_ACTIONS);
|
||||||
const bool needsAdditionalConditionWidgets =
|
const bool needsAdditionalConditionWidgets =
|
||||||
_entryData->_action == MacroActionMacro::Action::RUN &&
|
action == MacroActionMacro::Action::RUN_ACTIONS &&
|
||||||
_entryData->_runOptions.logic !=
|
_entryData->_runOptions.logic !=
|
||||||
MacroActionMacro::RunOptions::Logic::IGNORE_CONDITIONS;
|
MacroActionMacro::RunOptions::Logic::IGNORE_CONDITIONS;
|
||||||
_conditionMacros->setVisible(needsAdditionalConditionWidgets);
|
_conditionMacros->setVisible(needsAdditionalConditionWidgets);
|
||||||
SetLayoutVisible(_reevaluateConditionStateLayout,
|
SetLayoutVisible(_reevaluateConditionStateLayout,
|
||||||
needsAdditionalConditionWidgets);
|
needsAdditionalConditionWidgets);
|
||||||
SetLayoutVisible(_setInputsLayout,
|
SetLayoutVisible(_setInputsLayout,
|
||||||
_entryData->_action == MacroActionMacro::Action::RUN);
|
action == MacroActionMacro::Action::RUN_ACTIONS);
|
||||||
_inputs->setVisible(_entryData->_action ==
|
_inputs->setVisible(action == MacroActionMacro::Action::RUN_ACTIONS &&
|
||||||
MacroActionMacro::Action::RUN &&
|
|
||||||
_entryData->_runOptions.setInputs);
|
_entryData->_runOptions.setInputs);
|
||||||
HighlightMacroSettingsButton(_entryData->_action ==
|
HighlightMacroSettingsButton(
|
||||||
MacroActionMacro::Action::RUN &&
|
action == MacroActionMacro::Action::RUN_ACTIONS &&
|
||||||
_entryData->_runOptions.setInputs &&
|
_entryData->_runOptions.setInputs &&
|
||||||
!_inputs->HasInputsToSet());
|
!_inputs->HasInputsToSet());
|
||||||
_actionTypes->setVisible(_entryData->_action ==
|
_actionSections->setVisible(
|
||||||
MacroActionMacro::Action::RUN);
|
action == MacroActionMacro::Action::RUN_ACTIONS ||
|
||||||
_skipWhenPaused->setVisible(_entryData->_action ==
|
isModifyingActionState);
|
||||||
MacroActionMacro::Action::RUN);
|
_skipWhenPaused->setVisible(action ==
|
||||||
|
MacroActionMacro::Action::RUN_ACTIONS);
|
||||||
|
|
||||||
|
_nestedMacro->setVisible(action ==
|
||||||
|
MacroActionMacro::Action::NESTED_MACRO);
|
||||||
|
_macros->setVisible(action != MacroActionMacro::Action::NESTED_MACRO);
|
||||||
|
SetResizingEnabled(action == MacroActionMacro::Action::NESTED_MACRO);
|
||||||
|
|
||||||
|
if (_nestedMacro->IsEmpty()) {
|
||||||
|
_nestedMacro->ShowAllMacroSections();
|
||||||
|
// TODO: find a better solution than setting a fixed height
|
||||||
|
_entryData->_customWidgetHeight = 600;
|
||||||
|
}
|
||||||
|
SetCustomHeight(_entryData->_customWidgetHeight);
|
||||||
|
|
||||||
adjustSize();
|
adjustSize();
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
|
#include "macro.hpp"
|
||||||
|
#include "macro-edit.hpp"
|
||||||
#include "macro-input.hpp"
|
#include "macro-input.hpp"
|
||||||
#include "macro-selection.hpp"
|
#include "macro-selection.hpp"
|
||||||
#include "macro-segment-selection.hpp"
|
#include "macro-segment-selection.hpp"
|
||||||
|
#include "regex-config.hpp"
|
||||||
|
#include "resizable-widget.hpp"
|
||||||
|
#include "variable-line-edit.hpp"
|
||||||
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
@@ -44,25 +49,37 @@ public:
|
|||||||
PAUSE,
|
PAUSE,
|
||||||
UNPAUSE,
|
UNPAUSE,
|
||||||
RESET_COUNTER,
|
RESET_COUNTER,
|
||||||
RUN,
|
RUN_ACTIONS,
|
||||||
STOP,
|
STOP,
|
||||||
DISABLE_ACTION,
|
DISABLE_ACTION,
|
||||||
ENABLE_ACTION,
|
ENABLE_ACTION,
|
||||||
TOGGLE_ACTION,
|
TOGGLE_ACTION,
|
||||||
TOGGLE_PAUSE,
|
TOGGLE_PAUSE,
|
||||||
|
NESTED_MACRO,
|
||||||
};
|
};
|
||||||
Action _action = Action::RUN;
|
|
||||||
|
enum class SelectionType { INDEX, LABEL, ID };
|
||||||
|
|
||||||
|
Action _action = Action::NESTED_MACRO;
|
||||||
|
SelectionType _actionSelectionType = SelectionType::INDEX;
|
||||||
|
bool _useElseSection = false;
|
||||||
IntVariable _actionIndex = 1;
|
IntVariable _actionIndex = 1;
|
||||||
|
StringVariable _label = "Custom label";
|
||||||
|
std::string _actionId;
|
||||||
|
RegexConfig _regex;
|
||||||
RunOptions _runOptions = {};
|
RunOptions _runOptions = {};
|
||||||
|
std::shared_ptr<Macro> _nestedMacro = std::make_shared<Macro>();
|
||||||
|
int _customWidgetHeight = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void RunActions(Macro *actionMacro) const;
|
void RunActions(Macro *actionMacro) const;
|
||||||
|
void AdjustActionState(Macro *) const;
|
||||||
|
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
static const std::string id;
|
static const std::string id;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MacroActionMacroEdit final : public QWidget {
|
class MacroActionMacroEdit final : public ResizableWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -71,22 +88,20 @@ public:
|
|||||||
std::shared_ptr<MacroActionMacro> entryData = nullptr);
|
std::shared_ptr<MacroActionMacro> entryData = nullptr);
|
||||||
~MacroActionMacroEdit();
|
~MacroActionMacroEdit();
|
||||||
void UpdateEntryData();
|
void UpdateEntryData();
|
||||||
static QWidget *Create(QWidget *parent,
|
static QWidget *Create(QWidget *, std::shared_ptr<MacroAction>);
|
||||||
std::shared_ptr<MacroAction> action)
|
|
||||||
{
|
|
||||||
return new MacroActionMacroEdit(
|
|
||||||
parent,
|
|
||||||
std::dynamic_pointer_cast<MacroActionMacro>(action));
|
|
||||||
}
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void MacroChanged(const QString &text);
|
void MacroChanged(const QString &text);
|
||||||
void ActionChanged(int value);
|
void ActionChanged(int value);
|
||||||
|
void ActionSelectionTypeChanged(int value);
|
||||||
void ActionIndexChanged(const IntVariable &value);
|
void ActionIndexChanged(const IntVariable &value);
|
||||||
|
void LabelChanged();
|
||||||
|
void ActionTypeChanged(int value);
|
||||||
|
void RegexChanged(const RegexConfig &);
|
||||||
void ConditionMacroChanged(const QString &text);
|
void ConditionMacroChanged(const QString &text);
|
||||||
void ConditionBehaviorChanged(int value);
|
void ConditionBehaviorChanged(int value);
|
||||||
void ReevaluateConditionStateChanged(int value);
|
void ReevaluateConditionStateChanged(int value);
|
||||||
void ActionTypeChanged(int value);
|
void ActionSectionChanged(int value);
|
||||||
void SkipWhenPausedChanged(int value);
|
void SkipWhenPausedChanged(int value);
|
||||||
void SetInputsChanged(int value);
|
void SetInputsChanged(int value);
|
||||||
void InputsChanged(const StringList &);
|
void InputsChanged(const StringList &);
|
||||||
@@ -98,13 +113,17 @@ private:
|
|||||||
void SetWidgetVisibility();
|
void SetWidgetVisibility();
|
||||||
void SetupMacroInput(Macro *) const;
|
void SetupMacroInput(Macro *) const;
|
||||||
|
|
||||||
MacroSelection *_macros;
|
|
||||||
MacroSegmentSelection *_actionIndex;
|
|
||||||
QComboBox *_actions;
|
QComboBox *_actions;
|
||||||
|
MacroSelection *_macros;
|
||||||
|
QComboBox *_actionSelectionType;
|
||||||
|
MacroSegmentSelection *_actionIndex;
|
||||||
|
VariableLineEdit *_label;
|
||||||
|
FilterComboBox *_actionTypes;
|
||||||
|
RegexConfigWidget *_regex;
|
||||||
MacroSelection *_conditionMacros;
|
MacroSelection *_conditionMacros;
|
||||||
QComboBox *_conditionBehaviors;
|
QComboBox *_conditionBehaviors;
|
||||||
QCheckBox *_reevaluateConditionState;
|
QCheckBox *_reevaluateConditionState;
|
||||||
QComboBox *_actionTypes;
|
QComboBox *_actionSections;
|
||||||
QCheckBox *_skipWhenPaused;
|
QCheckBox *_skipWhenPaused;
|
||||||
QCheckBox *_setInputs;
|
QCheckBox *_setInputs;
|
||||||
MacroInputEdit *_inputs;
|
MacroInputEdit *_inputs;
|
||||||
@@ -112,6 +131,7 @@ private:
|
|||||||
QHBoxLayout *_conditionLayout;
|
QHBoxLayout *_conditionLayout;
|
||||||
QHBoxLayout *_reevaluateConditionStateLayout;
|
QHBoxLayout *_reevaluateConditionStateLayout;
|
||||||
QHBoxLayout *_setInputsLayout;
|
QHBoxLayout *_setInputsLayout;
|
||||||
|
MacroEdit *_nestedMacro;
|
||||||
|
|
||||||
std::shared_ptr<MacroActionMacro> _entryData;
|
std::shared_ptr<MacroActionMacro> _entryData;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
#include "macro-action-variable.hpp"
|
#include "macro-action-variable.hpp"
|
||||||
#include "advanced-scene-switcher.hpp"
|
#include "help-icon.hpp"
|
||||||
#include "json-helpers.hpp"
|
#include "json-helpers.hpp"
|
||||||
#include "layout-helpers.hpp"
|
#include "layout-helpers.hpp"
|
||||||
#include "math-helpers.hpp"
|
|
||||||
#include "macro-condition-edit.hpp"
|
#include "macro-condition-edit.hpp"
|
||||||
|
#include "macro-signals.hpp"
|
||||||
|
#include "math-helpers.hpp"
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include "non-modal-dialog.hpp"
|
#include "non-modal-dialog.hpp"
|
||||||
#include "source-helpers.hpp"
|
#include "source-helpers.hpp"
|
||||||
@@ -285,6 +286,14 @@ bool MacroActionVariable::PerformAction()
|
|||||||
case Action::APPEND:
|
case Action::APPEND:
|
||||||
apppend(*var, _strValue);
|
apppend(*var, _strValue);
|
||||||
break;
|
break;
|
||||||
|
case Action::COPY_VAR: {
|
||||||
|
auto var2 = _variable2.lock();
|
||||||
|
if (!var2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
var->SetValue(var2->Value());
|
||||||
|
break;
|
||||||
|
}
|
||||||
case Action::APPEND_VAR: {
|
case Action::APPEND_VAR: {
|
||||||
auto var2 = _variable2.lock();
|
auto var2 = _variable2.lock();
|
||||||
if (!var2) {
|
if (!var2) {
|
||||||
@@ -480,7 +489,7 @@ bool MacroActionVariable::Save(obs_data_t *obj) const
|
|||||||
_inputPlaceholder.Save(obj, "inputPlaceholder");
|
_inputPlaceholder.Save(obj, "inputPlaceholder");
|
||||||
_envVariableName.Save(obj, "environmentVariableName");
|
_envVariableName.Save(obj, "environmentVariableName");
|
||||||
_scene.Save(obj);
|
_scene.Save(obj);
|
||||||
_tempVar.Save(obj);
|
_tempVar.Save(obj, GetMacro());
|
||||||
_sceneItemIndex.Save(obj, "sceneItemIndex");
|
_sceneItemIndex.Save(obj, "sceneItemIndex");
|
||||||
obs_data_set_int(obj, "direction", static_cast<int>(_direction));
|
obs_data_set_int(obj, "direction", static_cast<int>(_direction));
|
||||||
_stringLength.Save(obj, "stringLength");
|
_stringLength.Save(obj, "stringLength");
|
||||||
@@ -669,6 +678,8 @@ static inline void populateActionSelection(QComboBox *list)
|
|||||||
actions = {
|
actions = {
|
||||||
{MacroActionVariable::Action::SET_VALUE,
|
{MacroActionVariable::Action::SET_VALUE,
|
||||||
"AdvSceneSwitcher.action.variable.type.set"},
|
"AdvSceneSwitcher.action.variable.type.set"},
|
||||||
|
{MacroActionVariable::Action::COPY_VAR,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.copy"},
|
||||||
{MacroActionVariable::Action::APPEND,
|
{MacroActionVariable::Action::APPEND,
|
||||||
"AdvSceneSwitcher.action.variable.type.append"},
|
"AdvSceneSwitcher.action.variable.type.append"},
|
||||||
{MacroActionVariable::Action::PAD,
|
{MacroActionVariable::Action::PAD,
|
||||||
@@ -828,7 +839,10 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
this)),
|
this)),
|
||||||
_randomLayout(new QVBoxLayout()),
|
_randomLayout(new QVBoxLayout()),
|
||||||
_jsonQuery(new VariableLineEdit(this)),
|
_jsonQuery(new VariableLineEdit(this)),
|
||||||
_jsonQueryHelp(new QLabel(this)),
|
_jsonQueryHelp(new HelpIcon(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.variable.type.queryJson.info"),
|
||||||
|
this)),
|
||||||
_jsonIndex(new VariableSpinBox(this)),
|
_jsonIndex(new VariableSpinBox(this)),
|
||||||
_entryLayout(new QHBoxLayout())
|
_entryLayout(new QHBoxLayout())
|
||||||
{
|
{
|
||||||
@@ -859,14 +873,6 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
_randomNumberStart->setMaximum(9999999999);
|
_randomNumberStart->setMaximum(9999999999);
|
||||||
_randomNumberEnd->setMinimum(-9999999999);
|
_randomNumberEnd->setMinimum(-9999999999);
|
||||||
_randomNumberEnd->setMaximum(9999999999);
|
_randomNumberEnd->setMaximum(9999999999);
|
||||||
const QString path = GetThemeTypeName() == "Light"
|
|
||||||
? ":/res/images/help.svg"
|
|
||||||
: ":/res/images/help_light.svg";
|
|
||||||
const QIcon icon(path);
|
|
||||||
const QPixmap pixmap = icon.pixmap(QSize(16, 16));
|
|
||||||
_jsonQueryHelp->setPixmap(pixmap);
|
|
||||||
_jsonQueryHelp->setToolTip(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.action.variable.type.queryJson.info"));
|
|
||||||
_jsonIndex->setMaximum(999);
|
_jsonIndex->setMaximum(999);
|
||||||
|
|
||||||
QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)),
|
QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)),
|
||||||
@@ -884,7 +890,8 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
QWidget::connect(_segmentIdx,
|
QWidget::connect(_segmentIdx,
|
||||||
SIGNAL(SelectionChanged(const IntVariable &)), this,
|
SIGNAL(SelectionChanged(const IntVariable &)), this,
|
||||||
SLOT(SegmentIndexChanged(const IntVariable &)));
|
SLOT(SegmentIndexChanged(const IntVariable &)));
|
||||||
QWidget::connect(window(), SIGNAL(MacroSegmentOrderChanged()), this,
|
QWidget::connect(MacroSignalManager::Instance(),
|
||||||
|
SIGNAL(SegmentOrderChanged()), this,
|
||||||
SLOT(MacroSegmentOrderChanged()));
|
SLOT(MacroSegmentOrderChanged()));
|
||||||
QWidget::connect(
|
QWidget::connect(
|
||||||
_subStringStart,
|
_subStringStart,
|
||||||
@@ -1524,6 +1531,7 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
|||||||
}
|
}
|
||||||
|
|
||||||
_variables2->setVisible(
|
_variables2->setVisible(
|
||||||
|
_entryData->_action == MacroActionVariable::Action::COPY_VAR ||
|
||||||
_entryData->_action ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Action::APPEND_VAR ||
|
MacroActionVariable::Action::APPEND_VAR ||
|
||||||
_entryData->_action ==
|
_entryData->_action ==
|
||||||
|
|||||||
@@ -55,6 +55,7 @@ public:
|
|||||||
RANDOM_NUMBER,
|
RANDOM_NUMBER,
|
||||||
QUERY_JSON,
|
QUERY_JSON,
|
||||||
ARRAY_JSON,
|
ARRAY_JSON,
|
||||||
|
COPY_VAR,
|
||||||
};
|
};
|
||||||
|
|
||||||
Action _action = Action::SET_VALUE;
|
Action _action = Action::SET_VALUE;
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ void DurationModifierEdit::Collapse(bool collapse)
|
|||||||
|
|
||||||
MacroConditionEdit::MacroConditionEdit(
|
MacroConditionEdit::MacroConditionEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroCondition> *entryData,
|
QWidget *parent, std::shared_ptr<MacroCondition> *entryData,
|
||||||
const std::string &id, bool isRootCondition)
|
bool isRootCondition)
|
||||||
: MacroSegmentEdit(parent),
|
: MacroSegmentEdit(parent),
|
||||||
_logicSelection(new QComboBox()),
|
_logicSelection(new QComboBox()),
|
||||||
_conditionSelection(new FilterComboBox()),
|
_conditionSelection(new FilterComboBox()),
|
||||||
@@ -239,7 +239,7 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
|||||||
(*_entryData)->SetIndex(idx);
|
(*_entryData)->SetIndex(idx);
|
||||||
(*_entryData)->SetLogicType(logic);
|
(*_entryData)->SetLogicType(logic);
|
||||||
(*_entryData)->PostLoad();
|
(*_entryData)->PostLoad();
|
||||||
RunPostLoadSteps();
|
RunAndClearPostLoadSteps();
|
||||||
}
|
}
|
||||||
auto widget =
|
auto widget =
|
||||||
MacroConditionFactory::CreateWidget(id, this, *_entryData);
|
MacroConditionFactory::CreateWidget(id, this, *_entryData);
|
||||||
@@ -275,289 +275,4 @@ std::shared_ptr<MacroSegment> MacroConditionEdit::Data() const
|
|||||||
return *_entryData;
|
return *_entryData;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::AddMacroCondition(int idx)
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx < 0 || idx > (int)macro->Conditions().size()) {
|
|
||||||
assert(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string id;
|
|
||||||
Logic::Type logic;
|
|
||||||
if (idx >= 1) {
|
|
||||||
id = macro->Conditions().at(idx - 1)->GetId();
|
|
||||||
if (idx == 1) {
|
|
||||||
logic = Logic::Type::OR;
|
|
||||||
} else {
|
|
||||||
logic = macro->Conditions().at(idx - 1)->GetLogicType();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
id = MacroCondition::GetDefaultID();
|
|
||||||
logic = Logic::Type::ROOT_NONE;
|
|
||||||
}
|
|
||||||
|
|
||||||
OBSDataAutoRelease data;
|
|
||||||
if (idx - 1 >= 0) {
|
|
||||||
data = obs_data_create();
|
|
||||||
macro->Conditions().at(idx - 1)->Save(data);
|
|
||||||
}
|
|
||||||
AddMacroCondition(macro.get(), idx, id, data.Get(), logic);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::AddMacroCondition(Macro *macro, int idx,
|
|
||||||
const std::string &id,
|
|
||||||
obs_data_t *data, Logic::Type logic)
|
|
||||||
{
|
|
||||||
if (idx < 0 || idx > (int)macro->Conditions().size()) {
|
|
||||||
assert(false);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto lock = LockContext();
|
|
||||||
auto cond = macro->Conditions().emplace(
|
|
||||||
macro->Conditions().begin() + idx,
|
|
||||||
MacroConditionFactory::Create(id, macro));
|
|
||||||
if (data) {
|
|
||||||
macro->Conditions().at(idx)->Load(data);
|
|
||||||
}
|
|
||||||
macro->Conditions().at(idx)->PostLoad();
|
|
||||||
RunPostLoadSteps();
|
|
||||||
(*cond)->SetLogicType(logic);
|
|
||||||
macro->UpdateConditionIndices();
|
|
||||||
ui->conditionsList->Insert(
|
|
||||||
idx,
|
|
||||||
new MacroConditionEdit(this, ¯o->Conditions()[idx],
|
|
||||||
id, idx == 0));
|
|
||||||
SetConditionData(*macro);
|
|
||||||
}
|
|
||||||
HighlightCondition(idx);
|
|
||||||
ui->conditionsList->SetHelpMsgVisible(false);
|
|
||||||
emit(MacroSegmentOrderChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_conditionAdd_clicked()
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentConditionIdx == -1) {
|
|
||||||
AddMacroCondition((int)macro->Conditions().size());
|
|
||||||
} else {
|
|
||||||
AddMacroCondition(currentConditionIdx + 1);
|
|
||||||
}
|
|
||||||
if (currentConditionIdx != -1) {
|
|
||||||
MacroConditionSelectionChanged(currentConditionIdx + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::RemoveMacroCondition(int idx)
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx < 0 || idx >= (int)macro->Conditions().size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
auto lock = LockContext();
|
|
||||||
ui->conditionsList->Remove(idx);
|
|
||||||
macro->Conditions().erase(macro->Conditions().begin() + idx);
|
|
||||||
macro->UpdateConditionIndices();
|
|
||||||
if (idx == 0 && macro->Conditions().size() > 0) {
|
|
||||||
auto newRoot = macro->Conditions().at(0);
|
|
||||||
newRoot->SetLogicType(Logic::Type::ROOT_NONE);
|
|
||||||
static_cast<MacroConditionEdit *>(
|
|
||||||
ui->conditionsList->WidgetAt(0))
|
|
||||||
->SetRootNode(true);
|
|
||||||
}
|
|
||||||
SetConditionData(*macro);
|
|
||||||
}
|
|
||||||
MacroConditionSelectionChanged(-1);
|
|
||||||
lastInteracted = MacroSection::CONDITIONS;
|
|
||||||
emit(MacroSegmentOrderChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_conditionRemove_clicked()
|
|
||||||
{
|
|
||||||
if (currentConditionIdx == -1) {
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
RemoveMacroCondition((int)macro->Conditions().size() - 1);
|
|
||||||
} else {
|
|
||||||
RemoveMacroCondition(currentConditionIdx);
|
|
||||||
}
|
|
||||||
MacroConditionSelectionChanged(-1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_conditionTop_clicked()
|
|
||||||
{
|
|
||||||
if (currentConditionIdx == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MacroConditionReorder(0, currentConditionIdx);
|
|
||||||
MacroConditionSelectionChanged(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_conditionUp_clicked()
|
|
||||||
{
|
|
||||||
if (currentConditionIdx == -1 || currentConditionIdx == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MoveMacroConditionUp(currentConditionIdx);
|
|
||||||
MacroConditionSelectionChanged(currentConditionIdx - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_conditionDown_clicked()
|
|
||||||
{
|
|
||||||
if (currentConditionIdx == -1 ||
|
|
||||||
currentConditionIdx ==
|
|
||||||
ui->conditionsList->ContentLayout()->count() - 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
MoveMacroConditionDown(currentConditionIdx);
|
|
||||||
MacroConditionSelectionChanged(currentConditionIdx + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_conditionBottom_clicked()
|
|
||||||
{
|
|
||||||
if (currentConditionIdx == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const int newIdx = ui->conditionsList->ContentLayout()->count() - 1;
|
|
||||||
MacroConditionReorder(newIdx, currentConditionIdx);
|
|
||||||
MacroConditionSelectionChanged(newIdx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::SwapConditions(Macro *m, int pos1, int pos2)
|
|
||||||
{
|
|
||||||
if (pos1 == pos2) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pos1 > pos2) {
|
|
||||||
std::swap(pos1, pos2);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool root = pos1 == 0;
|
|
||||||
auto lock = LockContext();
|
|
||||||
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 widget1 = static_cast<MacroConditionEdit *>(
|
|
||||||
ui->conditionsList->ContentLayout()->takeAt(pos1)->widget());
|
|
||||||
auto widget2 = static_cast<MacroConditionEdit *>(
|
|
||||||
ui->conditionsList->ContentLayout()->takeAt(pos2 - 1)->widget());
|
|
||||||
ui->conditionsList->Insert(pos1, widget2);
|
|
||||||
ui->conditionsList->Insert(pos2, widget1);
|
|
||||||
SetConditionData(*m);
|
|
||||||
widget2->SetRootNode(root);
|
|
||||||
widget1->SetRootNode(false);
|
|
||||||
emit(MacroSegmentOrderChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::MoveMacroConditionUp(int idx)
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (idx < 1 || idx >= (int)macro->Conditions().size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SwapConditions(macro.get(), idx, idx - 1);
|
|
||||||
HighlightCondition(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.get(), idx, idx + 1);
|
|
||||||
HighlightCondition(idx + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::MacroConditionSelectionChanged(int idx)
|
|
||||||
{
|
|
||||||
SetupMacroSegmentSelection(MacroSection::CONDITIONS, idx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::MacroConditionReorder(int to, int from)
|
|
||||||
{
|
|
||||||
auto macro = GetSelectedMacro();
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (to == from || from < 0 || from > (int)macro->Conditions().size() ||
|
|
||||||
to < 0 || to > (int)macro->Conditions().size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
auto lock = LockContext();
|
|
||||||
auto condition = macro->Conditions().at(from);
|
|
||||||
if (to == 0) {
|
|
||||||
condition->SetLogicType(Logic::Type::ROOT_NONE);
|
|
||||||
static_cast<MacroConditionEdit *>(
|
|
||||||
ui->conditionsList->WidgetAt(from))
|
|
||||||
->SetRootNode(true);
|
|
||||||
macro->Conditions().at(0)->SetLogicType(
|
|
||||||
Logic::Type::AND);
|
|
||||||
static_cast<MacroConditionEdit *>(
|
|
||||||
ui->conditionsList->WidgetAt(0))
|
|
||||||
->SetRootNode(false);
|
|
||||||
}
|
|
||||||
if (from == 0) {
|
|
||||||
condition->SetLogicType(Logic::Type::AND);
|
|
||||||
static_cast<MacroConditionEdit *>(
|
|
||||||
ui->conditionsList->WidgetAt(from))
|
|
||||||
->SetRootNode(false);
|
|
||||||
macro->Conditions().at(1)->SetLogicType(
|
|
||||||
Logic::Type::ROOT_NONE);
|
|
||||||
static_cast<MacroConditionEdit *>(
|
|
||||||
ui->conditionsList->WidgetAt(1))
|
|
||||||
->SetRootNode(true);
|
|
||||||
}
|
|
||||||
macro->Conditions().erase(macro->Conditions().begin() + from);
|
|
||||||
macro->Conditions().insert(macro->Conditions().begin() + to,
|
|
||||||
condition);
|
|
||||||
macro->UpdateConditionIndices();
|
|
||||||
ui->conditionsList->ContentLayout()->insertItem(
|
|
||||||
to, ui->conditionsList->ContentLayout()->takeAt(from));
|
|
||||||
SetConditionData(*macro);
|
|
||||||
}
|
|
||||||
HighlightCondition(to);
|
|
||||||
emit(MacroSegmentOrderChanged());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -34,11 +34,9 @@ class MacroConditionEdit : public MacroSegmentEdit {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MacroConditionEdit(
|
MacroConditionEdit(QWidget *parent = nullptr,
|
||||||
QWidget *parent = nullptr,
|
std::shared_ptr<MacroCondition> * = nullptr,
|
||||||
std::shared_ptr<MacroCondition> * = nullptr,
|
bool root = true);
|
||||||
const std::string &id = MacroCondition::GetDefaultID().data(),
|
|
||||||
bool root = true);
|
|
||||||
bool IsRootNode() const;
|
bool IsRootNode() const;
|
||||||
void SetRootNode(bool);
|
void SetRootNode(bool);
|
||||||
void SetupWidgets(bool basicSetup = false);
|
void SetupWidgets(bool basicSetup = false);
|
||||||
|
|||||||
@@ -1,21 +1,11 @@
|
|||||||
#include "macro-condition-factory.hpp"
|
#include "macro-condition-factory.hpp"
|
||||||
|
#include "macro-segment-unknown.hpp"
|
||||||
|
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
namespace {
|
using MacroConditionUnknown = MacroSegmentUnknown<MacroCondition>;
|
||||||
|
|
||||||
class MacroConditionUnknown : public MacroCondition {
|
|
||||||
public:
|
|
||||||
MacroConditionUnknown(Macro *m) : MacroCondition(m) {}
|
|
||||||
bool CheckCondition() { return false; }
|
|
||||||
bool Save(obs_data_t *obj) const { return MacroCondition::Save(obj); };
|
|
||||||
bool Load(obs_data_t *obj) { return MacroCondition::Load(obj); };
|
|
||||||
std::string GetId() const { return "unknown"; }
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
static std::recursive_mutex mutex;
|
static std::recursive_mutex mutex;
|
||||||
|
|
||||||
@@ -46,9 +36,10 @@ bool MacroConditionFactory::Deregister(const std::string &id)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::shared_ptr<MacroCondition> createUnknownCondition(Macro *m)
|
static std::shared_ptr<MacroCondition>
|
||||||
|
createUnknownCondition(Macro *m, const std::string &id)
|
||||||
{
|
{
|
||||||
return std::make_shared<MacroConditionUnknown>(m);
|
return std::make_shared<MacroConditionUnknown>(m, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<MacroCondition>
|
std::shared_ptr<MacroCondition>
|
||||||
@@ -58,13 +49,7 @@ MacroConditionFactory::Create(const std::string &id, Macro *m)
|
|||||||
if (auto it = GetMap().find(id); it != GetMap().end()) {
|
if (auto it = GetMap().find(id); it != GetMap().end()) {
|
||||||
return it->second._create(m);
|
return it->second._create(m);
|
||||||
}
|
}
|
||||||
return createUnknownCondition(m);
|
return createUnknownCondition(m, id);
|
||||||
}
|
|
||||||
|
|
||||||
static QWidget *createUnknownConditionWidget()
|
|
||||||
{
|
|
||||||
return new QLabel(
|
|
||||||
obs_module_text("AdvSceneSwitcher.condition.unknown"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *
|
QWidget *
|
||||||
@@ -75,7 +60,7 @@ MacroConditionFactory::CreateWidget(const std::string &id, QWidget *parent,
|
|||||||
if (auto it = GetMap().find(id); it != GetMap().end()) {
|
if (auto it = GetMap().find(id); it != GetMap().end()) {
|
||||||
return it->second._createWidget(parent, cond);
|
return it->second._createWidget(parent, cond);
|
||||||
}
|
}
|
||||||
return createUnknownConditionWidget();
|
return CreateUnknownSegmentWidget(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MacroConditionFactory::GetConditionName(const std::string &id)
|
std::string MacroConditionFactory::GetConditionName(const std::string &id)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "macro-condition-macro.hpp"
|
#include "macro-condition-macro.hpp"
|
||||||
#include "layout-helpers.hpp"
|
#include "layout-helpers.hpp"
|
||||||
#include "macro-action-edit.hpp"
|
#include "macro-action-edit.hpp"
|
||||||
|
#include "macro-signals.hpp"
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -26,6 +27,8 @@ const static std::map<MacroConditionMacro::Type, std::string>
|
|||||||
"AdvSceneSwitcher.condition.macro.type.actionEnabled"},
|
"AdvSceneSwitcher.condition.macro.type.actionEnabled"},
|
||||||
{MacroConditionMacro::Type::PAUSED,
|
{MacroConditionMacro::Type::PAUSED,
|
||||||
"AdvSceneSwitcher.condition.macro.type.paused"},
|
"AdvSceneSwitcher.condition.macro.type.paused"},
|
||||||
|
{MacroConditionMacro::Type::ACTIONS_PERFORMED,
|
||||||
|
"AdvSceneSwitcher.condition.macro.type.actionsPerformed"},
|
||||||
};
|
};
|
||||||
|
|
||||||
const static std::map<MacroConditionMacro::CounterCondition, std::string>
|
const static std::map<MacroConditionMacro::CounterCondition, std::string>
|
||||||
@@ -99,7 +102,7 @@ bool MacroConditionMacro::CheckActionStateCondition()
|
|||||||
if (!macro) {
|
if (!macro) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!IsValidMacroSegmentIndex(macro.get(), _actionIndex - 1, false)) {
|
if (!IsValidActionIndex(macro.get(), _actionIndex - 1)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (_type == Type::ACTION_DISABLED) {
|
if (_type == Type::ACTION_DISABLED) {
|
||||||
@@ -121,6 +124,16 @@ bool MacroConditionMacro::CheckPauseState()
|
|||||||
return macro->Paused();
|
return macro->Paused();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MacroConditionMacro::CheckActionsPerformed()
|
||||||
|
{
|
||||||
|
auto macro = _macro.GetMacro();
|
||||||
|
if (!macro) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return macro->WasExecutedSince(macro->LastConditionCheckTime());
|
||||||
|
}
|
||||||
|
|
||||||
bool MacroConditionMacro::CheckCountCondition()
|
bool MacroConditionMacro::CheckCountCondition()
|
||||||
{
|
{
|
||||||
auto macro = _macro.GetMacro();
|
auto macro = _macro.GetMacro();
|
||||||
@@ -158,6 +171,8 @@ bool MacroConditionMacro::CheckCondition()
|
|||||||
return CheckActionStateCondition();
|
return CheckActionStateCondition();
|
||||||
case Type::PAUSED:
|
case Type::PAUSED:
|
||||||
return CheckPauseState();
|
return CheckPauseState();
|
||||||
|
case Type::ACTIONS_PERFORMED:
|
||||||
|
return CheckActionsPerformed();
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -307,7 +322,8 @@ MacroConditionMacroEdit::MacroConditionMacroEdit(
|
|||||||
|
|
||||||
QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)),
|
QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)),
|
||||||
this, SLOT(MacroChanged(const QString &)));
|
this, SLOT(MacroChanged(const QString &)));
|
||||||
QWidget::connect(parent, SIGNAL(MacroRemoved(const QString &)), this,
|
QWidget::connect(MacroSignalManager::Instance(),
|
||||||
|
SIGNAL(Remove(const QString &)), this,
|
||||||
SLOT(MacroRemove(const QString &)));
|
SLOT(MacroRemove(const QString &)));
|
||||||
QWidget::connect(_types, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_types, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(TypeChanged(int)));
|
SLOT(TypeChanged(int)));
|
||||||
@@ -414,6 +430,9 @@ void MacroConditionMacroEdit::SetupWidgets()
|
|||||||
case MacroConditionMacro::Type::PAUSED:
|
case MacroConditionMacro::Type::PAUSED:
|
||||||
SetupPauseWidgets();
|
SetupPauseWidgets();
|
||||||
break;
|
break;
|
||||||
|
case MacroConditionMacro::Type::ACTIONS_PERFORMED:
|
||||||
|
SetupActionsPerformedWidgets();
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -472,6 +491,14 @@ void MacroConditionMacroEdit::SetupPauseWidgets()
|
|||||||
_settingsLine1, {{"{{macros}}", _macros}});
|
_settingsLine1, {{"{{macros}}", _macros}});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroConditionMacroEdit::SetupActionsPerformedWidgets()
|
||||||
|
{
|
||||||
|
PlaceWidgets(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.condition.macro.actionsPerformed.entry"),
|
||||||
|
_settingsLine1, {{"{{macros}}", _macros}});
|
||||||
|
}
|
||||||
|
|
||||||
void MacroConditionMacroEdit::SetWidgetVisibility()
|
void MacroConditionMacroEdit::SetWidgetVisibility()
|
||||||
{
|
{
|
||||||
_macros->setVisible(
|
_macros->setVisible(
|
||||||
@@ -481,7 +508,9 @@ void MacroConditionMacroEdit::SetWidgetVisibility()
|
|||||||
MacroConditionMacro::Type::ACTION_DISABLED ||
|
MacroConditionMacro::Type::ACTION_DISABLED ||
|
||||||
_entryData->GetType() ==
|
_entryData->GetType() ==
|
||||||
MacroConditionMacro::Type::ACTION_ENABLED ||
|
MacroConditionMacro::Type::ACTION_ENABLED ||
|
||||||
_entryData->GetType() == MacroConditionMacro::Type::PAUSED);
|
_entryData->GetType() == MacroConditionMacro::Type::PAUSED ||
|
||||||
|
_entryData->GetType() ==
|
||||||
|
MacroConditionMacro::Type::ACTIONS_PERFORMED);
|
||||||
_counterConditions->setVisible(_entryData->GetType() ==
|
_counterConditions->setVisible(_entryData->GetType() ==
|
||||||
MacroConditionMacro::Type::COUNT);
|
MacroConditionMacro::Type::COUNT);
|
||||||
_count->setVisible(_entryData->GetType() ==
|
_count->setVisible(_entryData->GetType() ==
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ public:
|
|||||||
ACTION_DISABLED,
|
ACTION_DISABLED,
|
||||||
ACTION_ENABLED,
|
ACTION_ENABLED,
|
||||||
PAUSED,
|
PAUSED,
|
||||||
|
ACTIONS_PERFORMED,
|
||||||
};
|
};
|
||||||
void SetType(Type);
|
void SetType(Type);
|
||||||
Type GetType() const { return _type; }
|
Type GetType() const { return _type; }
|
||||||
@@ -66,6 +67,7 @@ private:
|
|||||||
bool CheckMultiStateCondition();
|
bool CheckMultiStateCondition();
|
||||||
bool CheckActionStateCondition();
|
bool CheckActionStateCondition();
|
||||||
bool CheckPauseState();
|
bool CheckPauseState();
|
||||||
|
bool CheckActionsPerformed();
|
||||||
|
|
||||||
void SetupTempVars();
|
void SetupTempVars();
|
||||||
|
|
||||||
@@ -134,6 +136,7 @@ private:
|
|||||||
void SetupCountWidgets();
|
void SetupCountWidgets();
|
||||||
void SetupActionStateWidgets(bool enable);
|
void SetupActionStateWidgets(bool enable);
|
||||||
void SetupPauseWidgets();
|
void SetupPauseWidgets();
|
||||||
|
void SetupActionsPerformedWidgets();
|
||||||
void SetWidgetVisibility();
|
void SetWidgetVisibility();
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ bool MacroConditionTempVar::CheckCondition()
|
|||||||
bool MacroConditionTempVar::Save(obs_data_t *obj) const
|
bool MacroConditionTempVar::Save(obs_data_t *obj) const
|
||||||
{
|
{
|
||||||
MacroCondition::Save(obj);
|
MacroCondition::Save(obj);
|
||||||
_tempVar.Save(obj);
|
_tempVar.Save(obj, GetMacro());
|
||||||
obs_data_set_string(obj, "variableName",
|
obs_data_set_string(obj, "variableName",
|
||||||
GetWeakVariableName(_variable2).c_str());
|
GetWeakVariableName(_variable2).c_str());
|
||||||
_strValue.Save(obj, "strValue");
|
_strValue.Save(obj, "strValue");
|
||||||
|
|||||||
394
lib/macro/macro-dock-settings.cpp
Normal file
394
lib/macro/macro-dock-settings.cpp
Normal file
@@ -0,0 +1,394 @@
|
|||||||
|
#include "macro-dock-settings.hpp"
|
||||||
|
#include "macro-dock.hpp"
|
||||||
|
#include "macro-dock-window.hpp"
|
||||||
|
#include "macro.hpp"
|
||||||
|
#include "plugin-state-helpers.hpp"
|
||||||
|
|
||||||
|
#include <obs-frontend-api.h>
|
||||||
|
#include <util/platform.h>
|
||||||
|
|
||||||
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(30, 0, 0)
|
||||||
|
#include <QDockWidget>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct DockMapEntry {
|
||||||
|
QAction *action = nullptr;
|
||||||
|
QWidget *dock = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
static std::unordered_map<const char *, DockMapEntry> dockIds;
|
||||||
|
static std::mutex dockMutex;
|
||||||
|
|
||||||
|
static bool obs_frontend_add_dock_by_id(const char *id, const char *title,
|
||||||
|
QWidget *widget)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(dockMutex);
|
||||||
|
if (dockIds.count(id) > 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
widget->setObjectName(id);
|
||||||
|
|
||||||
|
auto dock = new QDockWidget();
|
||||||
|
dock->setWindowTitle(title);
|
||||||
|
dock->setWidget(widget);
|
||||||
|
dock->setFloating(true);
|
||||||
|
dock->setVisible(false);
|
||||||
|
dock->setFeatures(QDockWidget::DockWidgetClosable |
|
||||||
|
QDockWidget::DockWidgetMovable |
|
||||||
|
QDockWidget::DockWidgetFloatable);
|
||||||
|
|
||||||
|
auto action = static_cast<QAction *>(obs_frontend_add_dock(dock));
|
||||||
|
if (!action) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
dockIds[id] = {action, dock};
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void obs_frontend_remove_dock(const char *id)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(dockMutex);
|
||||||
|
auto it = dockIds.find(id);
|
||||||
|
if (it == dockIds.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
it->second.action->deleteLater();
|
||||||
|
it->second.dock->deleteLater();
|
||||||
|
dockIds.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
MacroDockSettings::MacroDockSettings(Macro *macro) : _macro(macro) {}
|
||||||
|
|
||||||
|
MacroDockSettings::~MacroDockSettings()
|
||||||
|
{
|
||||||
|
// Keep the dock widgets in case of shutdown so they can be restored by
|
||||||
|
// OBS on startup
|
||||||
|
if (!OBSIsShuttingDown()) {
|
||||||
|
RemoveDock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::Save(obs_data_t *obj, bool saveForCopy) const
|
||||||
|
{
|
||||||
|
OBSDataAutoRelease dockSettings = obs_data_create();
|
||||||
|
obs_data_set_bool(dockSettings, "register", _registerDock);
|
||||||
|
obs_data_set_bool(dockSettings, "standaloneDock", _standaloneDock);
|
||||||
|
obs_data_set_string(dockSettings, "dockWindow", _dockWindow.c_str());
|
||||||
|
obs_data_set_bool(dockSettings, "hasRunButton", _hasRunButton);
|
||||||
|
obs_data_set_bool(dockSettings, "hasPauseButton", _hasPauseButton);
|
||||||
|
obs_data_set_bool(dockSettings, "hasStatusLabel", _hasStatusLabel);
|
||||||
|
obs_data_set_bool(dockSettings, "highlightIfConditionsTrue",
|
||||||
|
_highlight);
|
||||||
|
_runButtonText.Save(dockSettings, "runButtonText");
|
||||||
|
_pauseButtonText.Save(dockSettings, "pauseButtonText");
|
||||||
|
_unpauseButtonText.Save(dockSettings, "unpauseButtonText");
|
||||||
|
_conditionsTrueStatusText.Save(dockSettings,
|
||||||
|
"conditionsTrueStatusText");
|
||||||
|
_conditionsFalseStatusText.Save(dockSettings,
|
||||||
|
"conditionsFalseStatusText");
|
||||||
|
if (saveForCopy) {
|
||||||
|
auto uuid = GenerateId();
|
||||||
|
obs_data_set_string(dockSettings, "dockId", uuid.c_str());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
obs_data_set_string(dockSettings, "dockId", _id.c_str());
|
||||||
|
}
|
||||||
|
obs_data_set_int(dockSettings, "version", 1);
|
||||||
|
obs_data_set_obj(obj, "dockSettings", dockSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::Load(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
OBSDataAutoRelease dockSettings = obs_data_get_obj(obj, "dockSettings");
|
||||||
|
if (!dockSettings) {
|
||||||
|
// TODO: Remove this fallback
|
||||||
|
_hasRunButton = obs_data_get_bool(obj, "dockHasRunButton");
|
||||||
|
_hasPauseButton = obs_data_get_bool(obj, "dockHasPauseButton");
|
||||||
|
_registerDock = obs_data_get_bool(obj, "registerDock");
|
||||||
|
ResetDockIfEnabled();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_macroName = _macro->Name();
|
||||||
|
if (!obs_data_has_user_value(dockSettings, "version")) {
|
||||||
|
assert(_macro);
|
||||||
|
_id = std::string("ADVSS-") + _macroName;
|
||||||
|
} else {
|
||||||
|
_id = obs_data_get_string(dockSettings, "dockId");
|
||||||
|
}
|
||||||
|
|
||||||
|
_registerDock = obs_data_get_bool(dockSettings, "register");
|
||||||
|
|
||||||
|
// TODO: remove these default settings in a future version
|
||||||
|
obs_data_set_default_bool(dockSettings, "standaloneDock", true);
|
||||||
|
obs_data_set_default_string(dockSettings, "dockWindow", "Dock");
|
||||||
|
obs_data_set_default_string(
|
||||||
|
dockSettings, "runButtonText",
|
||||||
|
obs_module_text("AdvSceneSwitcher.macroDock.run"));
|
||||||
|
obs_data_set_default_string(
|
||||||
|
dockSettings, "pauseButtonText",
|
||||||
|
obs_module_text("AdvSceneSwitcher.macroDock.pause"));
|
||||||
|
obs_data_set_default_string(
|
||||||
|
dockSettings, "unpauseButtonText",
|
||||||
|
obs_module_text("AdvSceneSwitcher.macroDock.unpause"));
|
||||||
|
_standaloneDock = obs_data_get_bool(dockSettings, "standaloneDock");
|
||||||
|
_dockWindow = obs_data_get_string(dockSettings, "dockWindow");
|
||||||
|
_runButtonText.Load(dockSettings, "runButtonText");
|
||||||
|
_pauseButtonText.Load(dockSettings, "pauseButtonText");
|
||||||
|
_unpauseButtonText.Load(dockSettings, "unpauseButtonText");
|
||||||
|
_conditionsTrueStatusText.Load(dockSettings,
|
||||||
|
"conditionsTrueStatusText");
|
||||||
|
_conditionsFalseStatusText.Load(dockSettings,
|
||||||
|
"conditionsFalseStatusText");
|
||||||
|
if (_registerDock) {
|
||||||
|
_hasRunButton = obs_data_get_bool(dockSettings, "hasRunButton");
|
||||||
|
_hasPauseButton =
|
||||||
|
obs_data_get_bool(dockSettings, "hasPauseButton");
|
||||||
|
_hasStatusLabel =
|
||||||
|
obs_data_get_bool(dockSettings, "hasStatusLabel");
|
||||||
|
_highlight = obs_data_get_bool(dockSettings,
|
||||||
|
"highlightIfConditionsTrue");
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetDockIfEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::EnableDock(bool enable)
|
||||||
|
{
|
||||||
|
// Only apply "on change" to avoid recreation of the dock widget
|
||||||
|
if (_registerDock == enable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveDock();
|
||||||
|
|
||||||
|
if (!enable) {
|
||||||
|
_registerDock = enable;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(_macro);
|
||||||
|
_macroName = _macro->Name();
|
||||||
|
_dock = new MacroDock(GetWeakMacroByName(_macroName.c_str()),
|
||||||
|
_runButtonText, _pauseButtonText,
|
||||||
|
_unpauseButtonText, _conditionsTrueStatusText,
|
||||||
|
_conditionsFalseStatusText, _highlight);
|
||||||
|
|
||||||
|
if (!_standaloneDock) {
|
||||||
|
auto window = GetDockWindowByName(_dockWindow);
|
||||||
|
if (!window) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
window->AddMacroDock(_dock, QString::fromStdString(_macroName));
|
||||||
|
_registerDock = enable;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!obs_frontend_add_dock_by_id(_id.c_str(), _macroName.c_str(),
|
||||||
|
_dock)) {
|
||||||
|
blog(LOG_INFO, "failed to add macro dock for macro %s",
|
||||||
|
_macroName.c_str());
|
||||||
|
_dock->deleteLater();
|
||||||
|
_dock = nullptr;
|
||||||
|
_registerDock = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_registerDock = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::SetIsStandaloneDock(bool value)
|
||||||
|
{
|
||||||
|
if (_standaloneDock == value) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveDock();
|
||||||
|
_standaloneDock = value;
|
||||||
|
ResetDockIfEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::SetDockWindowName(const std::string &name)
|
||||||
|
{
|
||||||
|
if (_dockWindow == name) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveDock();
|
||||||
|
_dockWindow = name;
|
||||||
|
ResetDockIfEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::SetHasRunButton(bool value)
|
||||||
|
{
|
||||||
|
_hasRunButton = value;
|
||||||
|
if (!_dock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dock->ShowRunButton(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::SetHasPauseButton(bool value)
|
||||||
|
{
|
||||||
|
_hasPauseButton = value;
|
||||||
|
if (!_dock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dock->ShowPauseButton(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::SetHasStatusLabel(bool value)
|
||||||
|
{
|
||||||
|
_hasStatusLabel = value;
|
||||||
|
if (!_dock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dock->ShowStatusLabel(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::SetHighlightEnable(bool value)
|
||||||
|
{
|
||||||
|
_highlight = value;
|
||||||
|
if (!_dock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dock->EnableHighlight(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::SetRunButtonText(const std::string &text)
|
||||||
|
{
|
||||||
|
_runButtonText = text;
|
||||||
|
if (!_dock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dock->SetRunButtonText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::SetPauseButtonText(const std::string &text)
|
||||||
|
{
|
||||||
|
_pauseButtonText = text;
|
||||||
|
if (!_dock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dock->SetPauseButtonText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::SetUnpauseButtonText(const std::string &text)
|
||||||
|
{
|
||||||
|
_unpauseButtonText = text;
|
||||||
|
if (!_dock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dock->SetUnpauseButtonText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::SetConditionsTrueStatusText(const std::string &text)
|
||||||
|
{
|
||||||
|
_conditionsTrueStatusText = text;
|
||||||
|
if (!_dock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dock->SetConditionsTrueText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringVariable MacroDockSettings::ConditionsTrueStatusText() const
|
||||||
|
{
|
||||||
|
return _conditionsTrueStatusText;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::SetConditionsFalseStatusText(const std::string &text)
|
||||||
|
{
|
||||||
|
_conditionsFalseStatusText = text;
|
||||||
|
if (!_dock) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_dock->SetConditionsFalseText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
StringVariable MacroDockSettings::ConditionsFalseStatusText() const
|
||||||
|
{
|
||||||
|
return _conditionsFalseStatusText;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::HandleMacroNameChange()
|
||||||
|
{
|
||||||
|
const auto newName = _macro->Name();
|
||||||
|
|
||||||
|
if (!_standaloneDock) {
|
||||||
|
auto window = GetDockWindowByName(_dockWindow);
|
||||||
|
if (!window) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
window->RenameMacro(_macroName, newName);
|
||||||
|
_macroName = newName;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_macroName != newName) {
|
||||||
|
RemoveDock();
|
||||||
|
_id = GenerateId();
|
||||||
|
_macroName = newName;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResetDockIfEnabled();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::ResetDockIfEnabled()
|
||||||
|
{
|
||||||
|
if (_registerDock) {
|
||||||
|
_registerDock = false;
|
||||||
|
EnableDock(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockSettings::RemoveDock()
|
||||||
|
{
|
||||||
|
if (_standaloneDock) {
|
||||||
|
obs_frontend_remove_dock(_id.c_str());
|
||||||
|
_dock = nullptr;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto window = GetDockWindowByName(_dockWindow);
|
||||||
|
if (window) {
|
||||||
|
window->RemoveMacroDock(_dock);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_dock) {
|
||||||
|
_dock = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string MacroDockSettings::GenerateId()
|
||||||
|
{
|
||||||
|
#if LIBOBS_API_VER > MAKE_SEMANTIC_VERSION(30, 0, 0)
|
||||||
|
auto uuid = os_generate_uuid();
|
||||||
|
auto id = std::string("advss-macro-dock-") + std::string(uuid);
|
||||||
|
bfree(uuid);
|
||||||
|
return id;
|
||||||
|
|
||||||
|
#else
|
||||||
|
static std::atomic_int16_t idCounter = 0;
|
||||||
|
return std::to_string(++idCounter);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
76
lib/macro/macro-dock-settings.hpp
Normal file
76
lib/macro/macro-dock-settings.hpp
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "obs-module-helper.hpp"
|
||||||
|
#include "variable-string.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
class Macro;
|
||||||
|
class MacroDock;
|
||||||
|
|
||||||
|
class MacroDockSettings {
|
||||||
|
public:
|
||||||
|
MacroDockSettings(Macro *macro);
|
||||||
|
~MacroDockSettings();
|
||||||
|
|
||||||
|
void Save(obs_data_t *obj, bool saveForCopy) const;
|
||||||
|
void Load(obs_data_t *obj);
|
||||||
|
|
||||||
|
void EnableDock(bool);
|
||||||
|
bool DockEnabled() const { return _registerDock; }
|
||||||
|
|
||||||
|
bool IsStandaloneDock() const { return _standaloneDock; }
|
||||||
|
void SetIsStandaloneDock(bool value);
|
||||||
|
std::string DockWindowName() const { return _dockWindow; }
|
||||||
|
void SetDockWindowName(const std::string &name);
|
||||||
|
|
||||||
|
void SetHasRunButton(bool value);
|
||||||
|
bool HasRunButton() const { return _hasRunButton; }
|
||||||
|
void SetHasPauseButton(bool value);
|
||||||
|
bool HasPauseButton() const { return _hasPauseButton; }
|
||||||
|
void SetHasStatusLabel(bool value);
|
||||||
|
bool HasStatusLabel() const { return _hasStatusLabel; }
|
||||||
|
void SetHighlightEnable(bool value);
|
||||||
|
bool HighlightEnabled() const { return _highlight; }
|
||||||
|
StringVariable RunButtonText() const { return _runButtonText; }
|
||||||
|
void SetRunButtonText(const std::string &text);
|
||||||
|
StringVariable PauseButtonText() const { return _pauseButtonText; }
|
||||||
|
void SetPauseButtonText(const std::string &text);
|
||||||
|
StringVariable UnpauseButtonText() const { return _unpauseButtonText; }
|
||||||
|
void SetUnpauseButtonText(const std::string &text);
|
||||||
|
void SetConditionsTrueStatusText(const std::string &text);
|
||||||
|
StringVariable ConditionsTrueStatusText() const;
|
||||||
|
void SetConditionsFalseStatusText(const std::string &text);
|
||||||
|
StringVariable ConditionsFalseStatusText() const;
|
||||||
|
|
||||||
|
void HandleMacroNameChange();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void ResetDockIfEnabled();
|
||||||
|
void RemoveDock();
|
||||||
|
static std::string GenerateId();
|
||||||
|
|
||||||
|
bool _registerDock = false;
|
||||||
|
bool _standaloneDock = true;
|
||||||
|
std::string _dockWindow = "Dock";
|
||||||
|
bool _hasRunButton = true;
|
||||||
|
bool _hasPauseButton = true;
|
||||||
|
bool _hasStatusLabel = false;
|
||||||
|
bool _highlight = false;
|
||||||
|
StringVariable _runButtonText =
|
||||||
|
obs_module_text("AdvSceneSwitcher.macroDock.run");
|
||||||
|
StringVariable _pauseButtonText =
|
||||||
|
obs_module_text("AdvSceneSwitcher.macroDock.pause");
|
||||||
|
StringVariable _unpauseButtonText =
|
||||||
|
obs_module_text("AdvSceneSwitcher.macroDock.unpause");
|
||||||
|
StringVariable _conditionsTrueStatusText =
|
||||||
|
obs_module_text("AdvSceneSwitcher.macroDock.statusLabel.true");
|
||||||
|
StringVariable _conditionsFalseStatusText =
|
||||||
|
obs_module_text("AdvSceneSwitcher.macroDock.statusLabel.false");
|
||||||
|
std::string _id = GenerateId();
|
||||||
|
std::string _macroName = "";
|
||||||
|
|
||||||
|
Macro *_macro = nullptr;
|
||||||
|
MacroDock *_dock = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
170
lib/macro/macro-dock-window.cpp
Normal file
170
lib/macro/macro-dock-window.cpp
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
#include "macro-dock-window.hpp"
|
||||||
|
#include "log-helper.hpp"
|
||||||
|
#include "plugin-state-helpers.hpp"
|
||||||
|
|
||||||
|
#include <obs-frontend-api.h>
|
||||||
|
|
||||||
|
#include <QDockWidget>
|
||||||
|
#include <QLayout>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
static std::unordered_map<std::string, MacroDockWindow *> windows;
|
||||||
|
static std::unordered_map<std::string, QByteArray> windowGeometries;
|
||||||
|
static std::mutex mutex;
|
||||||
|
|
||||||
|
static void saveDocks(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
OBSDataAutoRelease data = obs_data_create();
|
||||||
|
OBSDataArrayAutoRelease array = obs_data_array_create();
|
||||||
|
for (const auto &[name, window] : windows) {
|
||||||
|
OBSDataAutoRelease dockData = obs_data_create();
|
||||||
|
obs_data_set_string(dockData, "name", name.c_str());
|
||||||
|
obs_data_set_string(dockData, "geometry",
|
||||||
|
window->GetWindow()
|
||||||
|
->saveState()
|
||||||
|
.toBase64()
|
||||||
|
.toStdString()
|
||||||
|
.c_str());
|
||||||
|
obs_data_array_push_back(array, dockData);
|
||||||
|
}
|
||||||
|
obs_data_set_array(data, "docks", array);
|
||||||
|
obs_data_set_obj(obj, "dockWindows", data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void restoreDockGeometry()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
for (const auto &[name, dock] : windows) {
|
||||||
|
const auto it = windowGeometries.find(name);
|
||||||
|
if (it == windowGeometries.end()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
dock->GetWindow()->restoreState(it->second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void loadDocks(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
windowGeometries.clear();
|
||||||
|
OBSDataAutoRelease data = obs_data_get_obj(obj, "dockWindows");
|
||||||
|
OBSDataArrayAutoRelease array = obs_data_get_array(data, "docks");
|
||||||
|
auto size = obs_data_array_count(array);
|
||||||
|
for (size_t i = 0; i < size; ++i) {
|
||||||
|
OBSDataAutoRelease dockData = obs_data_array_item(array, i);
|
||||||
|
const auto name = obs_data_get_string(dockData, "name");
|
||||||
|
const auto geometry = QByteArray::fromBase64(
|
||||||
|
obs_data_get_string(dockData, "geometry"));
|
||||||
|
windowGeometries[name] = geometry;
|
||||||
|
}
|
||||||
|
AddPostLoadStep(restoreDockGeometry);
|
||||||
|
}
|
||||||
|
|
||||||
|
[[maybe_unused]] static bool _ = []() {
|
||||||
|
AddPluginInitStep([]() {
|
||||||
|
AddSaveStep(saveDocks);
|
||||||
|
AddLoadStep(loadDocks);
|
||||||
|
});
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
|
||||||
|
MacroDockWindow::MacroDockWindow(const std::string &name)
|
||||||
|
: QFrame(),
|
||||||
|
_name(name),
|
||||||
|
_window(new QMainWindow())
|
||||||
|
{
|
||||||
|
setFrameShape(QFrame::StyledPanel);
|
||||||
|
setFrameShadow(QFrame::Sunken);
|
||||||
|
_window->setDockNestingEnabled(true);
|
||||||
|
auto layout = new QVBoxLayout;
|
||||||
|
layout->addWidget(_window);
|
||||||
|
setLayout(layout);
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidget *MacroDockWindow::AddMacroDock(QWidget *widget, const QString &title)
|
||||||
|
{
|
||||||
|
auto dock = new QDockWidget();
|
||||||
|
dock->setWindowTitle(title);
|
||||||
|
dock->setWidget(widget);
|
||||||
|
dock->setVisible(true);
|
||||||
|
dock->setFeatures(QDockWidget::DockWidgetMovable);
|
||||||
|
dock->setObjectName(title);
|
||||||
|
_window->addDockWidget(Qt::RightDockWidgetArea, dock);
|
||||||
|
return dock;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockWindow::RenameMacro(const std::string &oldName,
|
||||||
|
const std::string &newName)
|
||||||
|
{
|
||||||
|
auto docks = _window->findChildren<QDockWidget *>();
|
||||||
|
for (const auto dock : docks) {
|
||||||
|
if (dock->windowTitle() == QString::fromStdString(oldName)) {
|
||||||
|
dock->setWindowTitle(QString::fromStdString(newName));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroDockWindow::RemoveMacroDock(QWidget *widget)
|
||||||
|
{
|
||||||
|
bool removedDock = false;
|
||||||
|
auto docks = _window->findChildren<QDockWidget *>();
|
||||||
|
for (const auto dock : docks) {
|
||||||
|
if (dock->widget() == widget) {
|
||||||
|
_window->removeDockWidget(dock);
|
||||||
|
dock->deleteLater();
|
||||||
|
removedDock = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (OBSIsShuttingDown()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool shouldRemoveDockWindow = docks.isEmpty() ||
|
||||||
|
(removedDock && docks.count() == 1);
|
||||||
|
if (!shouldRemoveDockWindow) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
auto it = windows.find(_name);
|
||||||
|
if (it != windows.end()) {
|
||||||
|
windows.erase(it);
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto id = "advss-dock-window-" + _name;
|
||||||
|
obs_frontend_remove_dock(id.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
QMainWindow *MacroDockWindow::GetWindow() const
|
||||||
|
{
|
||||||
|
return _window;
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroDockWindow *GetDockWindowByName(const std::string &name)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
auto it = windows.find(name);
|
||||||
|
if (it != windows.end()) {
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto window = new MacroDockWindow(name);
|
||||||
|
const auto id = "advss-dock-window-" + name;
|
||||||
|
if (!obs_frontend_add_dock_by_id(id.c_str(), name.c_str(), window)) {
|
||||||
|
blog(LOG_INFO, "failed to add macro dock window '%s'",
|
||||||
|
id.c_str());
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
windows[name] = window;
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
29
lib/macro/macro-dock-window.hpp
Normal file
29
lib/macro/macro-dock-window.hpp
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QMainWindow>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
class MacroDockWindow : public QFrame {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroDockWindow(const std::string &name);
|
||||||
|
QWidget *AddMacroDock(QWidget *, const QString &title);
|
||||||
|
void RenameMacro(const std::string &oldName,
|
||||||
|
const std::string &newName);
|
||||||
|
void RemoveMacroDock(QWidget *);
|
||||||
|
QMainWindow *GetWindow() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string _name;
|
||||||
|
QMainWindow *_window;
|
||||||
|
};
|
||||||
|
|
||||||
|
MacroDockWindow *GetDockWindowByName(const std::string &name);
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -30,9 +30,10 @@ MacroDock::MacroDock(std::weak_ptr<Macro> m,
|
|||||||
|
|
||||||
auto macro = _macro.lock();
|
auto macro = _macro.lock();
|
||||||
if (macro) {
|
if (macro) {
|
||||||
_run->setVisible(macro->DockHasRunButton());
|
const auto &settings = macro->GetDockSettings();
|
||||||
_pauseToggle->setVisible(macro->DockHasPauseButton());
|
_run->setVisible(settings.HasRunButton());
|
||||||
_statusText->setVisible(macro->DockHasStatusLabel());
|
_pauseToggle->setVisible(settings.HasPauseButton());
|
||||||
|
_statusText->setVisible(settings.HasStatusLabel());
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget::connect(_run, SIGNAL(clicked()), this, SLOT(RunClicked()));
|
QWidget::connect(_run, SIGNAL(clicked()), this, SLOT(RunClicked()));
|
||||||
@@ -109,7 +110,7 @@ void MacroDock::RunClicked()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto ret = macro->PerformActions(true);
|
auto ret = macro->PerformActions(true, true, true);
|
||||||
if (!ret) {
|
if (!ret) {
|
||||||
QString err =
|
QString err =
|
||||||
obs_module_text("AdvSceneSwitcher.macroTab.runFail");
|
obs_module_text("AdvSceneSwitcher.macroTab.runFail");
|
||||||
|
|||||||
1838
lib/macro/macro-edit.cpp
Normal file
1838
lib/macro/macro-edit.cpp
Normal file
File diff suppressed because it is too large
Load Diff
144
lib/macro/macro-edit.hpp
Normal file
144
lib/macro/macro-edit.hpp
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "condition-logic.hpp"
|
||||||
|
|
||||||
|
#include <ui_macro-edit.h>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
class Macro;
|
||||||
|
class MacroSegment;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Advanced Scene Switcher window
|
||||||
|
*******************************************************************************/
|
||||||
|
class MacroEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroEdit(QWidget *parent, QStringList helpMsg = {});
|
||||||
|
void SetMacro(const std::shared_ptr<Macro> &);
|
||||||
|
std::shared_ptr<Macro> GetMacro() const;
|
||||||
|
void ClearSegmentWidgetCacheFor(Macro *) const;
|
||||||
|
void SetControlsDisabled(bool disable) const;
|
||||||
|
void HighlightAction(int idx, QColor color = QColor(Qt::green)) const;
|
||||||
|
void HighlightElseAction(int idx,
|
||||||
|
QColor color = QColor(Qt::green)) const;
|
||||||
|
void HighlightCondition(int idx,
|
||||||
|
QColor color = QColor(Qt::green)) const;
|
||||||
|
void ResetConditionHighlights();
|
||||||
|
void ResetActionHighlights();
|
||||||
|
void SetActionData(Macro &m) const;
|
||||||
|
void SetElseActionData(Macro &m) const;
|
||||||
|
void SetConditionData(Macro &m) const;
|
||||||
|
void SwapActions(Macro *m, int pos1, int pos2);
|
||||||
|
void SwapElseActions(Macro *m, int pos1, int pos2);
|
||||||
|
void SwapConditions(Macro *m, int pos1, int pos2);
|
||||||
|
void CopyMacroSegment();
|
||||||
|
void PasteMacroSegment();
|
||||||
|
bool IsEmpty() const;
|
||||||
|
void ShowAllMacroSections();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void on_conditionAdd_clicked();
|
||||||
|
void on_conditionRemove_clicked();
|
||||||
|
void on_conditionTop_clicked();
|
||||||
|
void on_conditionUp_clicked();
|
||||||
|
void on_conditionDown_clicked();
|
||||||
|
void on_conditionBottom_clicked();
|
||||||
|
void on_actionAdd_clicked();
|
||||||
|
void on_actionRemove_clicked();
|
||||||
|
void on_actionTop_clicked();
|
||||||
|
void on_actionUp_clicked();
|
||||||
|
void on_actionDown_clicked();
|
||||||
|
void on_actionBottom_clicked();
|
||||||
|
void on_toggleElseActions_clicked() const;
|
||||||
|
void on_elseActionAdd_clicked();
|
||||||
|
void on_elseActionRemove_clicked();
|
||||||
|
void on_elseActionTop_clicked();
|
||||||
|
void on_elseActionUp_clicked();
|
||||||
|
void on_elseActionDown_clicked();
|
||||||
|
void on_elseActionBottom_clicked();
|
||||||
|
void UpMacroSegmentHotkey();
|
||||||
|
void DownMacroSegmentHotkey();
|
||||||
|
void DeleteMacroSegmentHotkey();
|
||||||
|
void ShowMacroActionsContextMenu(const QPoint &);
|
||||||
|
void ShowMacroElseActionsContextMenu(const QPoint &);
|
||||||
|
void ShowMacroConditionsContextMenu(const QPoint &);
|
||||||
|
void ExpandAllActions() const;
|
||||||
|
void ExpandAllElseActions() const;
|
||||||
|
void ExpandAllConditions() const;
|
||||||
|
void CollapseAllActions() const;
|
||||||
|
void CollapseAllElseActions() const;
|
||||||
|
void CollapseAllConditions() const;
|
||||||
|
void MinimizeActions() const;
|
||||||
|
void MaximizeActions() const;
|
||||||
|
void MinimizeElseActions() const;
|
||||||
|
void MaximizeElseActions() const;
|
||||||
|
void MinimizeConditions() const;
|
||||||
|
void MaximizeConditions() const;
|
||||||
|
void SetElseActionsStateToHidden() const;
|
||||||
|
void SetElseActionsStateToVisible() const;
|
||||||
|
void MacroActionSelectionChanged(int idx);
|
||||||
|
void MacroActionReorder(int to, int target);
|
||||||
|
void AddMacroAction(Macro *macro, int idx, const std::string &id,
|
||||||
|
obs_data_t *data);
|
||||||
|
void AddMacroAction(int idx);
|
||||||
|
void RemoveMacroAction(int idx);
|
||||||
|
void MoveMacroActionUp(int idx);
|
||||||
|
void MoveMacroActionDown(int idx);
|
||||||
|
void MacroElseActionSelectionChanged(int idx);
|
||||||
|
void MacroElseActionReorder(int to, int target);
|
||||||
|
void AddMacroElseAction(Macro *macro, int idx, const std::string &id,
|
||||||
|
obs_data_t *data);
|
||||||
|
void AddMacroElseAction(int idx);
|
||||||
|
void RemoveMacroElseAction(int idx);
|
||||||
|
void MoveMacroElseActionUp(int idx);
|
||||||
|
void MoveMacroElseActionDown(int idx);
|
||||||
|
void MacroConditionSelectionChanged(int idx);
|
||||||
|
void MacroConditionReorder(int to, int target);
|
||||||
|
void AddMacroCondition(int idx);
|
||||||
|
void AddMacroCondition(Macro *macro, int idx, const std::string &id,
|
||||||
|
obs_data_t *data, Logic::Type logic);
|
||||||
|
void RemoveMacroCondition(int idx);
|
||||||
|
void MoveMacroConditionUp(int idx);
|
||||||
|
void MoveMacroConditionDown(int idx);
|
||||||
|
void HighlightControls() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void MacroAdded(const QString &name);
|
||||||
|
void MacroRemoved(const QString &name);
|
||||||
|
void MacroRenamed(const QString &oldName, const QString &newName);
|
||||||
|
void MacroSegmentOrderChanged();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
bool eventFilter(QObject *obj, QEvent *event) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class MacroSection { CONDITIONS, ACTIONS, ELSE_ACTIONS };
|
||||||
|
|
||||||
|
void PopulateMacroActions(Macro &m, uint32_t afterIdx = 0);
|
||||||
|
void PopulateMacroElseActions(Macro &m, uint32_t afterIdx = 0);
|
||||||
|
void PopulateMacroConditions(Macro &m, uint32_t afterIdx = 0);
|
||||||
|
void SetupMacroSegmentSelection(MacroSection type, int idx);
|
||||||
|
void
|
||||||
|
SetupContextMenu(const QPoint &pos,
|
||||||
|
const std::function<void(MacroEdit *, int)> &remove,
|
||||||
|
const std::function<void(MacroEdit *)> &expand,
|
||||||
|
const std::function<void(MacroEdit *)> &collapse,
|
||||||
|
const std::function<void(MacroEdit *)> &maximize,
|
||||||
|
const std::function<void(MacroEdit *)> &minimize,
|
||||||
|
MacroSegmentList *list);
|
||||||
|
void RunSegmentHighlightChecks();
|
||||||
|
bool ElseSectionIsVisible() const;
|
||||||
|
|
||||||
|
MacroSection lastInteracted = MacroSection::CONDITIONS;
|
||||||
|
int currentConditionIdx = -1;
|
||||||
|
int currentActionIdx = -1;
|
||||||
|
int currentElseActionIdx = -1;
|
||||||
|
|
||||||
|
std::shared_ptr<Macro> _currentMacro;
|
||||||
|
|
||||||
|
std::unique_ptr<Ui_MacroEdit> ui;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#include "macro-helpers.hpp"
|
#include "macro-helpers.hpp"
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
|
#include "macro-action-macro.hpp"
|
||||||
#include "plugin-state-helpers.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -8,6 +9,87 @@ static std::atomic_bool abortMacroWait = {false};
|
|||||||
static std::atomic_bool macroSceneSwitched = {false};
|
static std::atomic_bool macroSceneSwitched = {false};
|
||||||
static std::atomic_int shutdownConditionCount = {0};
|
static std::atomic_int shutdownConditionCount = {0};
|
||||||
|
|
||||||
|
static void appendNestedMacros(std::deque<std::shared_ptr<Macro>> ¯os,
|
||||||
|
Macro *macro)
|
||||||
|
{
|
||||||
|
if (!macro) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto iterate = [¯os](const std::deque<
|
||||||
|
std::shared_ptr<MacroAction>> &actions) {
|
||||||
|
for (const auto &action : actions) {
|
||||||
|
const auto nestedMacroAction =
|
||||||
|
dynamic_cast<MacroActionMacro *>(action.get());
|
||||||
|
if (!nestedMacroAction) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
macros.push_back(nestedMacroAction->_nestedMacro);
|
||||||
|
appendNestedMacros(
|
||||||
|
macros, nestedMacroAction->_nestedMacro.get());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
iterate(macro->Actions());
|
||||||
|
iterate(macro->ElseActions());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::deque<std::shared_ptr<Macro>> &GetTopLevelMacros()
|
||||||
|
{
|
||||||
|
static std::deque<std::shared_ptr<Macro>> macros;
|
||||||
|
return macros;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::deque<std::shared_ptr<Macro>> &GetTemporaryMacros()
|
||||||
|
{
|
||||||
|
static std::deque<std::shared_ptr<Macro>> tempMacros;
|
||||||
|
return tempMacros;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::deque<std::shared_ptr<Macro>> GetAllMacros()
|
||||||
|
{
|
||||||
|
auto macros = GetTopLevelMacros();
|
||||||
|
for (const auto &topLevelMacro : macros) {
|
||||||
|
appendNestedMacros(macros, topLevelMacro.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &tempMacros = GetTemporaryMacros();
|
||||||
|
macros.insert(macros.end(), tempMacros.begin(), tempMacros.end());
|
||||||
|
for (const auto &tempMacro : tempMacros) {
|
||||||
|
appendNestedMacros(macros, tempMacro.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
return macros;
|
||||||
|
}
|
||||||
|
|
||||||
|
Macro *GetMacroByName(const char *name)
|
||||||
|
{
|
||||||
|
for (const auto &m : GetTopLevelMacros()) {
|
||||||
|
if (m->Name() == name) {
|
||||||
|
return m.get();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Macro *GetMacroByQString(const QString &name)
|
||||||
|
{
|
||||||
|
return GetMacroByName(name.toUtf8().constData());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::weak_ptr<Macro> GetWeakMacroByName(const char *name)
|
||||||
|
{
|
||||||
|
for (const auto &m : GetTopLevelMacros()) {
|
||||||
|
if (m->Name() == name) {
|
||||||
|
return m;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<std::deque<std::shared_ptr<MacroAction>>>
|
std::optional<std::deque<std::shared_ptr<MacroAction>>>
|
||||||
GetMacroActions(Macro *macro)
|
GetMacroActions(Macro *macro)
|
||||||
{
|
{
|
||||||
@@ -17,6 +99,15 @@ GetMacroActions(Macro *macro)
|
|||||||
return macro->Actions();
|
return macro->Actions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::deque<std::shared_ptr<MacroAction>>>
|
||||||
|
GetMacroElseActions(Macro *macro)
|
||||||
|
{
|
||||||
|
if (!macro) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
return macro->ElseActions();
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<std::deque<std::shared_ptr<MacroCondition>>>
|
std::optional<std::deque<std::shared_ptr<MacroCondition>>>
|
||||||
GetMacroConditions(Macro *macro)
|
GetMacroConditions(Macro *macro)
|
||||||
{
|
{
|
||||||
@@ -144,20 +235,42 @@ void ResetMacroRunCount(Macro *macro)
|
|||||||
macro->ResetRunCount();
|
macro->ResetRunCount();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsValidMacroSegmentIndex(const Macro *m, const int idx, bool isCondition)
|
bool IsValidActionIndex(const Macro *m, const int idx)
|
||||||
{
|
{
|
||||||
if (!m || idx < 0) {
|
if (!m || idx < 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (isCondition) {
|
|
||||||
if (idx >= (int)m->Conditions().size()) {
|
if (idx >= (int)m->Actions().size()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (idx >= (int)m->Actions().size()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValidElseActionIndex(const Macro *m, const int idx)
|
||||||
|
{
|
||||||
|
if (!m || idx < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx >= (int)m->ElseActions().size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsValidConditionIndex(const Macro *m, const int idx)
|
||||||
|
{
|
||||||
|
if (!m || idx < 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (idx >= (int)m->Conditions().size()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "export-symbol-helper.hpp"
|
#include "export-symbol-helper.hpp"
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
#include <atomic>
|
#include <atomic>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
@@ -18,10 +20,18 @@ class Macro;
|
|||||||
class MacroAction;
|
class MacroAction;
|
||||||
class MacroCondition;
|
class MacroCondition;
|
||||||
|
|
||||||
EXPORT std::deque<std::shared_ptr<Macro>> &GetMacros();
|
EXPORT std::deque<std::shared_ptr<Macro>> &GetTopLevelMacros();
|
||||||
|
std::deque<std::shared_ptr<Macro>> &GetTemporaryMacros();
|
||||||
|
EXPORT std::deque<std::shared_ptr<Macro>> GetAllMacros();
|
||||||
|
|
||||||
|
Macro *GetMacroByName(const char *name);
|
||||||
|
Macro *GetMacroByQString(const QString &name);
|
||||||
|
std::weak_ptr<Macro> GetWeakMacroByName(const char *name);
|
||||||
|
|
||||||
EXPORT std::optional<std::deque<std::shared_ptr<MacroAction>>>
|
EXPORT std::optional<std::deque<std::shared_ptr<MacroAction>>>
|
||||||
GetMacroActions(Macro *);
|
GetMacroActions(Macro *);
|
||||||
|
EXPORT std::optional<std::deque<std::shared_ptr<MacroAction>>>
|
||||||
|
GetMacroElseActions(Macro *);
|
||||||
EXPORT std::optional<std::deque<std::shared_ptr<MacroCondition>>>
|
EXPORT std::optional<std::deque<std::shared_ptr<MacroCondition>>>
|
||||||
GetMacroConditions(Macro *);
|
GetMacroConditions(Macro *);
|
||||||
|
|
||||||
@@ -68,6 +78,8 @@ EXPORT void InvalidateMacroTempVarValues();
|
|||||||
EXPORT void ResetMacroConditionTimers(Macro *);
|
EXPORT void ResetMacroConditionTimers(Macro *);
|
||||||
EXPORT void ResetMacroRunCount(Macro *);
|
EXPORT void ResetMacroRunCount(Macro *);
|
||||||
|
|
||||||
bool IsValidMacroSegmentIndex(const Macro *m, const int idx, bool isCondition);
|
bool IsValidActionIndex(const Macro *m, const int idx);
|
||||||
|
bool IsValidElseActionIndex(const Macro *m, const int idx);
|
||||||
|
bool IsValidConditionIndex(const Macro *m, const int idx);
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#include "macro-list.hpp"
|
#include "macro-list.hpp"
|
||||||
#include "macro-helpers.hpp"
|
#include "macro-helpers.hpp"
|
||||||
#include "macro-selection.hpp"
|
#include "macro-selection.hpp"
|
||||||
|
#include "macro-signals.hpp"
|
||||||
#include "obs-module-helper.hpp"
|
#include "obs-module-helper.hpp"
|
||||||
#include "ui-helpers.hpp"
|
#include "ui-helpers.hpp"
|
||||||
|
|
||||||
@@ -10,11 +11,11 @@ MacroList::MacroList(QWidget *parent, bool allowDuplicates, bool reorder)
|
|||||||
: ListEditor(parent, reorder),
|
: ListEditor(parent, reorder),
|
||||||
_allowDuplicates(allowDuplicates)
|
_allowDuplicates(allowDuplicates)
|
||||||
{
|
{
|
||||||
QWidget::connect(window(),
|
QWidget::connect(MacroSignalManager::Instance(),
|
||||||
SIGNAL(MacroRenamed(const QString &, const QString &)),
|
SIGNAL(Rename(const QString &, const QString &)), this,
|
||||||
this,
|
|
||||||
SLOT(MacroRename(const QString &, const QString &)));
|
SLOT(MacroRename(const QString &, const QString &)));
|
||||||
QWidget::connect(window(), SIGNAL(MacroRemoved(const QString &)), this,
|
QWidget::connect(MacroSignalManager::Instance(),
|
||||||
|
SIGNAL(Remove(const QString &)), this,
|
||||||
SLOT(MacroRemove(const QString &)));
|
SLOT(MacroRemove(const QString &)));
|
||||||
UpdateListSize();
|
UpdateListSize();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,14 @@ namespace advss {
|
|||||||
MacroRunButton::MacroRunButton(QWidget *parent) : QPushButton(parent)
|
MacroRunButton::MacroRunButton(QWidget *parent) : QPushButton(parent)
|
||||||
{
|
{
|
||||||
installEventFilter(this);
|
installEventFilter(this);
|
||||||
auto parentWindow = window();
|
|
||||||
if (parentWindow) {
|
// GetSettingsWindow() might still return null while this constructor is called
|
||||||
parentWindow->installEventFilter(this);
|
QTimer::singleShot(0, this, [this]() {
|
||||||
}
|
auto parentWindow = GetSettingsWindow();
|
||||||
|
if (parentWindow) {
|
||||||
|
parentWindow->installEventFilter(this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
setToolTip(obs_module_text("AdvSceneSwitcher.macroTab.run.tooltip"));
|
setToolTip(obs_module_text("AdvSceneSwitcher.macroTab.run.tooltip"));
|
||||||
|
|
||||||
|
|||||||
336
lib/macro/macro-search.cpp
Normal file
336
lib/macro/macro-search.cpp
Normal file
@@ -0,0 +1,336 @@
|
|||||||
|
#include "macro-search.hpp"
|
||||||
|
#include "layout-helpers.hpp"
|
||||||
|
#include "macro.hpp"
|
||||||
|
#include "macro-action-factory.hpp"
|
||||||
|
#include "macro-condition-factory.hpp"
|
||||||
|
#include "macro-helpers.hpp"
|
||||||
|
#include "macro-signals.hpp"
|
||||||
|
#include "plugin-state-helpers.hpp"
|
||||||
|
#include "ui-helpers.hpp"
|
||||||
|
|
||||||
|
#include <obs.hpp>
|
||||||
|
|
||||||
|
#include <QComboBox>
|
||||||
|
#include <QLayout>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QPushButton>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
static bool searchEnabled = false;
|
||||||
|
static bool setup();
|
||||||
|
static bool setupDone = setup();
|
||||||
|
|
||||||
|
static QLayout *searchLayout = nullptr;
|
||||||
|
static QComboBox *searchType = nullptr;
|
||||||
|
static RegexConfigWidget *searchRegex = nullptr;
|
||||||
|
static QPushButton *showSettings = nullptr;
|
||||||
|
static std::function<void()> refreshFilter;
|
||||||
|
|
||||||
|
static void save(obs_data_t *data)
|
||||||
|
{
|
||||||
|
GetMacroSearchSettings().Save(data, "macroSearchSettings");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load(obs_data_t *data)
|
||||||
|
{
|
||||||
|
GetMacroSearchSettings().Load(data, "macroSearchSettings");
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool setup()
|
||||||
|
{
|
||||||
|
AddSaveStep(save);
|
||||||
|
AddLoadStep(load);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroSearchSettings::Save(obs_data_t *data, const char *name)
|
||||||
|
{
|
||||||
|
OBSDataAutoRelease settings = obs_data_create();
|
||||||
|
obs_data_set_bool(settings, "showAlways", showAlways);
|
||||||
|
obs_data_set_int(settings, "searchType", static_cast<int>(searchType));
|
||||||
|
obs_data_set_string(settings, "searchString", searchString.c_str());
|
||||||
|
regex.Save(settings);
|
||||||
|
obs_data_set_obj(data, name, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroSearchSettings::Load(obs_data_t *data, const char *name)
|
||||||
|
{
|
||||||
|
OBSDataAutoRelease settings = obs_data_get_obj(data, name);
|
||||||
|
showAlways = obs_data_get_bool(settings, "showAlways");
|
||||||
|
searchType = static_cast<SearchType>(
|
||||||
|
obs_data_get_int(settings, "searchType"));
|
||||||
|
searchString = obs_data_get_string(settings, "searchString");
|
||||||
|
regex.Load(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void showAdvancedSearchSettings(bool show)
|
||||||
|
{
|
||||||
|
assert(searchType);
|
||||||
|
assert(searchRegex);
|
||||||
|
|
||||||
|
searchType->setVisible(show);
|
||||||
|
searchRegex->setVisible(show);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool shouldShowSearch()
|
||||||
|
{
|
||||||
|
static const int showSearchThreshold = 10;
|
||||||
|
return GetMacroSearchSettings().showAlways ||
|
||||||
|
GetTopLevelMacros().size() >= showSearchThreshold;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckMacroSearchVisibility()
|
||||||
|
{
|
||||||
|
assert(searchLayout);
|
||||||
|
assert(searchType);
|
||||||
|
assert(searchRegex);
|
||||||
|
assert(showSettings);
|
||||||
|
|
||||||
|
searchEnabled = shouldShowSearch();
|
||||||
|
SetLayoutVisible(searchLayout, searchEnabled);
|
||||||
|
showAdvancedSearchSettings(false);
|
||||||
|
showSettings->setChecked(false);
|
||||||
|
refreshFilter();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetupMacroSearchWidgets(QLayout *searchLayoutArg, QLineEdit *searchText,
|
||||||
|
QPushButton *searchClear, QComboBox *searchTypeArg,
|
||||||
|
RegexConfigWidget *searchRegexArg,
|
||||||
|
QPushButton *showSettingsArg,
|
||||||
|
const std::function<void()> &refreshArg)
|
||||||
|
{
|
||||||
|
searchLayout = searchLayoutArg;
|
||||||
|
searchType = searchTypeArg;
|
||||||
|
searchRegex = searchRegexArg;
|
||||||
|
refreshFilter = refreshArg;
|
||||||
|
showSettings = showSettingsArg;
|
||||||
|
|
||||||
|
searchClear->setMaximumWidth(22);
|
||||||
|
SetButtonIcon(searchClear, GetThemeTypeName() == "Light"
|
||||||
|
? "theme:Light/close.svg"
|
||||||
|
: "theme:Dark/close.svg");
|
||||||
|
searchClear->setDisabled(GetMacroSearchSettings().searchString.empty());
|
||||||
|
|
||||||
|
QWidget::connect(searchClear, &QPushButton::clicked, searchClear,
|
||||||
|
[=]() {
|
||||||
|
searchText->setText("");
|
||||||
|
searchClear->setDisabled(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
const auto ph = searchText->placeholderText();
|
||||||
|
const QFontMetrics fm(searchText->font());
|
||||||
|
const int width = fm.horizontalAdvance(ph);
|
||||||
|
// Add a little padding so the text isn't cramped
|
||||||
|
searchText->setMinimumWidth(width + 10);
|
||||||
|
|
||||||
|
searchText->setText(
|
||||||
|
QString::fromStdString(GetMacroSearchSettings().searchString));
|
||||||
|
QWidget::connect(searchText, &QLineEdit::textChanged, searchText,
|
||||||
|
[searchClear](const QString &text) {
|
||||||
|
GetMacroSearchSettings().searchString =
|
||||||
|
text.toStdString();
|
||||||
|
searchClear->setDisabled(text.isEmpty());
|
||||||
|
refreshFilter();
|
||||||
|
});
|
||||||
|
|
||||||
|
searchType->addItem(
|
||||||
|
obs_module_text("AdvSceneSwitcher.macroTab.search.name"),
|
||||||
|
static_cast<int>(MacroSearchSettings::SearchType::NAME));
|
||||||
|
searchType->addItem(
|
||||||
|
obs_module_text("AdvSceneSwitcher.macroTab.search.allSegments"),
|
||||||
|
static_cast<int>(
|
||||||
|
MacroSearchSettings::SearchType::ALL_SEGMENTS));
|
||||||
|
searchType->addItem(
|
||||||
|
obs_module_text("AdvSceneSwitcher.macroTab.search.conditions"),
|
||||||
|
static_cast<int>(MacroSearchSettings::SearchType::CONDITIONS));
|
||||||
|
searchType->addItem(
|
||||||
|
obs_module_text("AdvSceneSwitcher.macroTab.search.actions"),
|
||||||
|
static_cast<int>(MacroSearchSettings::SearchType::ACTIONS));
|
||||||
|
searchType->addItem(
|
||||||
|
obs_module_text("AdvSceneSwitcher.macroTab.search.label"),
|
||||||
|
static_cast<int>(MacroSearchSettings::SearchType::LABEL));
|
||||||
|
searchType->setCurrentIndex(searchType->findData(
|
||||||
|
static_cast<int>(GetMacroSearchSettings().searchType)));
|
||||||
|
QWidget::connect(
|
||||||
|
searchType, &QComboBox::currentIndexChanged, searchType, []() {
|
||||||
|
GetMacroSearchSettings().searchType =
|
||||||
|
static_cast<MacroSearchSettings::SearchType>(
|
||||||
|
searchType->currentData().toInt());
|
||||||
|
refreshFilter();
|
||||||
|
});
|
||||||
|
|
||||||
|
searchRegex->SetRegexConfig(GetMacroSearchSettings().regex);
|
||||||
|
QWidget::connect(searchRegex, &RegexConfigWidget::RegexConfigChanged,
|
||||||
|
searchRegex, [](const RegexConfig ®ex) {
|
||||||
|
GetMacroSearchSettings().regex = regex;
|
||||||
|
refreshFilter();
|
||||||
|
});
|
||||||
|
|
||||||
|
showSettings->setCheckable(true);
|
||||||
|
showSettings->setMaximumWidth(11);
|
||||||
|
SetButtonIcon(showSettings, GetThemeTypeName() == "Light"
|
||||||
|
? ":/res/images/dots-vert.svg"
|
||||||
|
: "theme:Dark/dots-vert.svg");
|
||||||
|
QWidget::connect(showSettings, &QPushButton::toggled, showSettings,
|
||||||
|
showAdvancedSearchSettings);
|
||||||
|
|
||||||
|
QWidget::connect(MacroSignalManager::Instance(),
|
||||||
|
&MacroSignalManager::Rename, searchText,
|
||||||
|
[]() { refreshFilter(); });
|
||||||
|
|
||||||
|
CheckMacroSearchVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroSearchSettings &GetMacroSearchSettings()
|
||||||
|
{
|
||||||
|
static MacroSearchSettings settings;
|
||||||
|
return settings;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool stringMatches(const std::string &text)
|
||||||
|
{
|
||||||
|
const auto &settings = GetMacroSearchSettings();
|
||||||
|
const auto ®ex = settings.regex;
|
||||||
|
const auto &searchString = settings.searchString;
|
||||||
|
|
||||||
|
if (regex.Enabled()) {
|
||||||
|
return regex.Matches(text, searchString);
|
||||||
|
}
|
||||||
|
|
||||||
|
return QString::fromStdString(text).contains(
|
||||||
|
QString::fromStdString(searchString), Qt::CaseInsensitive);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool segmentTypeMatches(MacroSegment *segment, bool isCondition)
|
||||||
|
{
|
||||||
|
if (!segment) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto getNameFromId =
|
||||||
|
isCondition ? MacroConditionFactory::GetConditionName
|
||||||
|
: MacroActionFactory::GetActionName;
|
||||||
|
const auto name = getNameFromId(segment->GetId());
|
||||||
|
return stringMatches(obs_module_text(name.c_str()));
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool segmentLabelMatches(MacroSegment *segment)
|
||||||
|
{
|
||||||
|
if (!segment) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!segment->GetUseCustomLabel()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto label = segment->GetCustomLabel();
|
||||||
|
return stringMatches(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroMatchesSearchFilter(Macro *macro)
|
||||||
|
{
|
||||||
|
assert(macro);
|
||||||
|
|
||||||
|
if (!searchEnabled) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &settings = GetMacroSearchSettings();
|
||||||
|
|
||||||
|
if (settings.searchString.empty()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (macro->IsGroup()) {
|
||||||
|
std::vector<std::shared_ptr<Macro>> subItems;
|
||||||
|
subItems.reserve(macro->GroupSize());
|
||||||
|
|
||||||
|
const auto ¯os = GetTopLevelMacros();
|
||||||
|
for (auto it = macros.begin(); it < macros.end(); it++) {
|
||||||
|
if ((*it)->Name() != macro->Name()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (uint32_t i = 1; i <= macro->GroupSize(); i++) {
|
||||||
|
subItems.emplace_back(*std::next(it, i));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &item : subItems) {
|
||||||
|
if (MacroMatchesSearchFilter(item.get())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (settings.searchType) {
|
||||||
|
case MacroSearchSettings::SearchType::NAME: {
|
||||||
|
const auto name = macro->Name();
|
||||||
|
return stringMatches(name);
|
||||||
|
}
|
||||||
|
case MacroSearchSettings::SearchType::ALL_SEGMENTS:
|
||||||
|
for (const auto &condition : macro->Conditions()) {
|
||||||
|
if (segmentTypeMatches(condition.get(), true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto &action : macro->Actions()) {
|
||||||
|
if (segmentTypeMatches(action.get(), false)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto &action : macro->ElseActions()) {
|
||||||
|
if (segmentTypeMatches(action.get(), false)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case MacroSearchSettings::SearchType::CONDITIONS:
|
||||||
|
for (const auto &condition : macro->Conditions()) {
|
||||||
|
if (segmentTypeMatches(condition.get(), true)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case MacroSearchSettings::SearchType::ACTIONS:
|
||||||
|
for (const auto &action : macro->Actions()) {
|
||||||
|
if (segmentTypeMatches(action.get(), false)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto &action : macro->ElseActions()) {
|
||||||
|
if (segmentTypeMatches(action.get(), false)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
case MacroSearchSettings::SearchType::LABEL:
|
||||||
|
for (const auto &condition : macro->Conditions()) {
|
||||||
|
if (segmentLabelMatches(condition.get())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto &action : macro->Actions()) {
|
||||||
|
if (segmentLabelMatches(action.get())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const auto &action : macro->ElseActions()) {
|
||||||
|
if (segmentLabelMatches(action.get())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unhandled search type
|
||||||
|
assert(false);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
43
lib/macro/macro-search.hpp
Normal file
43
lib/macro/macro-search.hpp
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "regex-config.hpp"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
class QComboBox;
|
||||||
|
class QLayout;
|
||||||
|
class QLineEdit;
|
||||||
|
class QPushButton;
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
class Macro;
|
||||||
|
|
||||||
|
struct MacroSearchSettings {
|
||||||
|
void Save(obs_data_t *data, const char *name);
|
||||||
|
void Load(obs_data_t *data, const char *name);
|
||||||
|
|
||||||
|
enum class SearchType {
|
||||||
|
NAME = 0,
|
||||||
|
ALL_SEGMENTS = 10,
|
||||||
|
CONDITIONS = 20,
|
||||||
|
ACTIONS = 30,
|
||||||
|
LABEL = 40,
|
||||||
|
};
|
||||||
|
|
||||||
|
SearchType searchType = SearchType::NAME;
|
||||||
|
std::string searchString;
|
||||||
|
RegexConfig regex;
|
||||||
|
bool showAlways = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
void CheckMacroSearchVisibility();
|
||||||
|
void SetupMacroSearchWidgets(QLayout *searchLayout, QLineEdit *searchText,
|
||||||
|
QPushButton *searchClear, QComboBox *searchType,
|
||||||
|
RegexConfigWidget *searchRegex,
|
||||||
|
QPushButton *showSettings,
|
||||||
|
const std::function<void()> &refresh);
|
||||||
|
MacroSearchSettings &GetMacroSearchSettings();
|
||||||
|
bool MacroMatchesSearchFilter(Macro *macro);
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -13,7 +13,7 @@ struct MacroSegmentCopyInfo {
|
|||||||
};
|
};
|
||||||
static MacroSegmentCopyInfo copyInfo;
|
static MacroSegmentCopyInfo copyInfo;
|
||||||
|
|
||||||
void AdvSceneSwitcher::CopyMacroSegment()
|
void MacroEdit::CopyMacroSegment()
|
||||||
{
|
{
|
||||||
copyInfo.segment.reset();
|
copyInfo.segment.reset();
|
||||||
copyInfo.type = MacroSegmentCopyInfo::Type::NONE;
|
copyInfo.type = MacroSegmentCopyInfo::Type::NONE;
|
||||||
@@ -23,7 +23,7 @@ void AdvSceneSwitcher::CopyMacroSegment()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto macro = GetSelectedMacro();
|
auto macro = _currentMacro;
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -43,13 +43,13 @@ void AdvSceneSwitcher::CopyMacroSegment()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::PasteMacroSegment()
|
void MacroEdit::PasteMacroSegment()
|
||||||
{
|
{
|
||||||
if (copyInfo.type == MacroSegmentCopyInfo::Type::NONE) {
|
if (copyInfo.type == MacroSegmentCopyInfo::Type::NONE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto macro = GetSelectedMacro();
|
auto macro = _currentMacro;
|
||||||
if (!macro || !copyInfo.segment) {
|
if (!macro || !copyInfo.segment) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -113,14 +113,14 @@ void SetCopySegmentTargetActionType(bool setToElseAction)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupSegmentCopyPasteShortcutHandlers(AdvSceneSwitcher *window)
|
void SetupSegmentCopyPasteShortcutHandlers(MacroEdit *edit)
|
||||||
{
|
{
|
||||||
auto copyShortcut = new QShortcut(QKeySequence("Ctrl+C"), window);
|
auto copyShortcut = new QShortcut(QKeySequence("Ctrl+C"), edit);
|
||||||
QWidget::connect(copyShortcut, &QShortcut::activated, window,
|
QWidget::connect(copyShortcut, &QShortcut::activated, edit,
|
||||||
&AdvSceneSwitcher::CopyMacroSegment);
|
&MacroEdit::CopyMacroSegment);
|
||||||
auto pasteShortcut = new QShortcut(QKeySequence("Ctrl+V"), window);
|
auto pasteShortcut = new QShortcut(QKeySequence("Ctrl+V"), edit);
|
||||||
QWidget::connect(pasteShortcut, &QShortcut::activated, window,
|
QWidget::connect(pasteShortcut, &QShortcut::activated, edit,
|
||||||
&AdvSceneSwitcher::PasteMacroSegment);
|
&MacroEdit::PasteMacroSegment);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
class AdvSceneSwitcher;
|
class MacroEdit;
|
||||||
|
|
||||||
bool MacroSegmentIsInClipboard();
|
bool MacroSegmentIsInClipboard();
|
||||||
bool MacroActionIsInClipboard();
|
bool MacroActionIsInClipboard();
|
||||||
void SetCopySegmentTargetActionType(bool setToElseAction);
|
void SetCopySegmentTargetActionType(bool setToElseAction);
|
||||||
void SetupSegmentCopyPasteShortcutHandlers(AdvSceneSwitcher *window);
|
void SetupSegmentCopyPasteShortcutHandlers(MacroEdit *edit);
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -17,27 +17,39 @@ bool MacroSegmentList::_useCache = true;
|
|||||||
|
|
||||||
MacroSegmentList::MacroSegmentList(QWidget *parent)
|
MacroSegmentList::MacroSegmentList(QWidget *parent)
|
||||||
: QScrollArea(parent),
|
: QScrollArea(parent),
|
||||||
|
_stackedWidget(new QStackedWidget(this)),
|
||||||
_layout(new QVBoxLayout),
|
_layout(new QVBoxLayout),
|
||||||
_contentLayout(new QVBoxLayout),
|
_contentLayout(new QVBoxLayout),
|
||||||
_helpMsg(new QLabel)
|
_helpMsg(new QLabel(this))
|
||||||
{
|
{
|
||||||
_helpMsg->setWordWrap(true);
|
_helpMsg->setWordWrap(true);
|
||||||
_helpMsg->setAlignment(Qt::AlignCenter);
|
_helpMsg->setAlignment(Qt::AlignCenter);
|
||||||
|
auto helpWidget = new QWidget(this);
|
||||||
|
auto helpLayout = new QVBoxLayout(helpWidget);
|
||||||
|
helpLayout->addWidget(_helpMsg);
|
||||||
|
helpLayout->setAlignment(Qt::AlignCenter);
|
||||||
|
|
||||||
|
auto contentWidget = new QWidget(this);
|
||||||
|
contentWidget->setLayout(_contentLayout);
|
||||||
_contentLayout->setSpacing(0);
|
_contentLayout->setSpacing(0);
|
||||||
auto helperLayout = new QGridLayout();
|
|
||||||
helperLayout->addWidget(_helpMsg, 0, 0,
|
auto contentWrapper = new QWidget(this);
|
||||||
Qt::AlignHCenter | Qt::AlignVCenter);
|
auto wrapperLayout = new QVBoxLayout(contentWrapper);
|
||||||
helperLayout->addLayout(_contentLayout, 0, 0);
|
wrapperLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
helperLayout->setSizeConstraint(QLayout::SetMinAndMaxSize);
|
wrapperLayout->addWidget(contentWidget);
|
||||||
_layout->addLayout(helperLayout, 10);
|
// Move macro segments to the top of the list
|
||||||
_layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding,
|
wrapperLayout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding,
|
||||||
QSizePolicy::Expanding));
|
QSizePolicy::Expanding));
|
||||||
auto wrapper = new QWidget;
|
|
||||||
wrapper->setLayout(_layout);
|
_stackedWidget->addWidget(helpWidget);
|
||||||
setWidget(wrapper);
|
_stackedWidget->addWidget(contentWrapper);
|
||||||
|
|
||||||
|
setWidget(_stackedWidget);
|
||||||
setWidgetResizable(true);
|
setWidgetResizable(true);
|
||||||
setAcceptDrops(true);
|
setAcceptDrops(true);
|
||||||
|
|
||||||
|
SetHelpMsgVisible(true);
|
||||||
|
|
||||||
connect(verticalScrollBar(), &QScrollBar::valueChanged, this,
|
connect(verticalScrollBar(), &QScrollBar::valueChanged, this,
|
||||||
[this]() { SetupVisibleMacroSegmentWidgets(); });
|
[this]() { SetupVisibleMacroSegmentWidgets(); });
|
||||||
}
|
}
|
||||||
@@ -107,9 +119,11 @@ void MacroSegmentList::SetHelpMsg(const QString &msg) const
|
|||||||
_helpMsg->setText(msg);
|
_helpMsg->setText(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSegmentList::SetHelpMsgVisible(bool visible) const
|
void MacroSegmentList::SetHelpMsgVisible(bool visible)
|
||||||
{
|
{
|
||||||
_helpMsg->setVisible(visible);
|
_stackedWidget->setCurrentIndex(visible ? 0 : 1);
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSegmentList::Insert(int idx, QWidget *widget)
|
void MacroSegmentList::Insert(int idx, QWidget *widget)
|
||||||
@@ -117,23 +131,33 @@ void MacroSegmentList::Insert(int idx, QWidget *widget)
|
|||||||
widget->installEventFilter(this);
|
widget->installEventFilter(this);
|
||||||
_contentLayout->insertWidget(idx, widget);
|
_contentLayout->insertWidget(idx, widget);
|
||||||
SetupVisibleMacroSegmentWidgets();
|
SetupVisibleMacroSegmentWidgets();
|
||||||
|
SetHelpMsgVisible(false);
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSegmentList::Add(QWidget *widget)
|
void MacroSegmentList::Add(QWidget *widget)
|
||||||
{
|
{
|
||||||
widget->installEventFilter(this);
|
Insert(_contentLayout->count(), widget);
|
||||||
_contentLayout->addWidget(widget);
|
|
||||||
SetupVisibleMacroSegmentWidgets();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSegmentList::Remove(int idx) const
|
void MacroSegmentList::Remove(int idx)
|
||||||
{
|
{
|
||||||
DeleteLayoutItemWidget(_contentLayout->takeAt(idx));
|
DeleteLayoutItemWidget(_contentLayout->takeAt(idx));
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
|
if (IsEmpty()) {
|
||||||
|
SetHelpMsgVisible(true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSegmentList::Clear(int idx) const
|
void MacroSegmentList::Clear(int idx)
|
||||||
{
|
{
|
||||||
ClearLayout(_contentLayout, idx);
|
ClearLayout(_contentLayout, idx);
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
|
|
||||||
|
SetHelpMsgVisible(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSegmentList::SetCachingEnabled(bool enable)
|
void MacroSegmentList::SetCachingEnabled(bool enable)
|
||||||
@@ -178,6 +202,8 @@ bool MacroSegmentList::PopulateWidgetsFromCache(const Macro *macro)
|
|||||||
widget->show();
|
widget->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -411,6 +437,24 @@ void MacroSegmentList::SetVisibilityCheckEnable(bool enable)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MacroSegmentList::IsEmpty() const
|
||||||
|
{
|
||||||
|
return _contentLayout->count() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize MacroSegmentList::minimumSizeHint() const
|
||||||
|
{
|
||||||
|
return _stackedWidget->currentWidget()->minimumSizeHint();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize MacroSegmentList::sizeHint() const
|
||||||
|
{
|
||||||
|
const auto contentSize = _stackedWidget->currentWidget()->sizeHint();
|
||||||
|
const auto hint =
|
||||||
|
QSize(width(), contentSize.height() + 2 * frameWidth());
|
||||||
|
return hint;
|
||||||
|
}
|
||||||
|
|
||||||
void MacroSegmentList::SetupVisibleMacroSegmentWidgets()
|
void MacroSegmentList::SetupVisibleMacroSegmentWidgets()
|
||||||
{
|
{
|
||||||
if (!_checkVisibility) {
|
if (!_checkVisibility) {
|
||||||
@@ -428,6 +472,7 @@ void MacroSegmentList::SetupVisibleMacroSegmentWidgets()
|
|||||||
|
|
||||||
segment->SetupWidgets();
|
segment->SetupWidgets();
|
||||||
}
|
}
|
||||||
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
int MacroSegmentList::GetSegmentIndexFromPos(const QPoint &pos) const
|
int MacroSegmentList::GetSegmentIndexFromPos(const QPoint &pos) const
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro-segment.hpp"
|
#include "macro-segment.hpp"
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QScrollArea>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QScrollArea>
|
||||||
|
#include <QStackedWidget>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
class Macro;
|
class Macro;
|
||||||
@@ -17,51 +19,63 @@ class MacroSegmentList : public QScrollArea {
|
|||||||
public:
|
public:
|
||||||
MacroSegmentList(QWidget *parent = nullptr);
|
MacroSegmentList(QWidget *parent = nullptr);
|
||||||
~MacroSegmentList();
|
~MacroSegmentList();
|
||||||
|
|
||||||
void SetHelpMsg(const QString &msg) const;
|
void SetHelpMsg(const QString &msg) const;
|
||||||
void SetHelpMsgVisible(bool visible) const;
|
void SetHelpMsgVisible(bool visible);
|
||||||
|
|
||||||
MacroSegmentEdit *WidgetAt(int idx) const;
|
MacroSegmentEdit *WidgetAt(int idx) const;
|
||||||
MacroSegmentEdit *WidgetAt(const QPoint &) const;
|
MacroSegmentEdit *WidgetAt(const QPoint &) const;
|
||||||
|
|
||||||
int IndexAt(const QPoint &) const;
|
int IndexAt(const QPoint &) const;
|
||||||
void Insert(int idx, QWidget *widget);
|
void Insert(int idx, QWidget *widget);
|
||||||
void Add(QWidget *widget);
|
void Add(QWidget *widget);
|
||||||
void Remove(int idx) const;
|
void Remove(int idx);
|
||||||
void Clear(int idx = 0) const; // Clear all elements >= idx
|
void Clear(int idx = 0); // Clear all elements >= idx
|
||||||
|
bool IsEmpty() const;
|
||||||
|
|
||||||
static void SetCachingEnabled(bool enable);
|
static void SetCachingEnabled(bool enable);
|
||||||
void CacheCurrentWidgetsFor(const Macro *);
|
void CacheCurrentWidgetsFor(const Macro *);
|
||||||
bool PopulateWidgetsFromCache(const Macro *);
|
bool PopulateWidgetsFromCache(const Macro *);
|
||||||
void ClearWidgetsFromCacheFor(const Macro *);
|
void ClearWidgetsFromCacheFor(const Macro *);
|
||||||
|
void SetVisibilityCheckEnable(bool enable);
|
||||||
|
|
||||||
void Highlight(int idx, QColor color = QColor(Qt::green));
|
void Highlight(int idx, QColor color = QColor(Qt::green));
|
||||||
|
|
||||||
void SetCollapsed(bool) const;
|
void SetCollapsed(bool) const;
|
||||||
void SetSelection(int idx) const;
|
void SetSelection(int idx) const;
|
||||||
QVBoxLayout *ContentLayout() const { return _contentLayout; }
|
QVBoxLayout *ContentLayout() const { return _contentLayout; }
|
||||||
void SetVisibilityCheckEnable(bool enable);
|
|
||||||
|
QSize minimumSizeHint() const override;
|
||||||
|
QSize sizeHint() const override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void SelectionChanged(int idx);
|
void SelectionChanged(int idx);
|
||||||
void Reorder(int source, int target);
|
void Reorder(int source, int target);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool eventFilter(QObject *object, QEvent *event);
|
bool eventFilter(QObject *object, QEvent *event) override;
|
||||||
void mousePressEvent(QMouseEvent *event);
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
void mouseMoveEvent(QMouseEvent *event);
|
void mouseMoveEvent(QMouseEvent *event) override;
|
||||||
void mouseReleaseEvent(QMouseEvent *event);
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||||
void dragLeaveEvent(QDragLeaveEvent *event);
|
void dragLeaveEvent(QDragLeaveEvent *event) override;
|
||||||
void dragEnterEvent(QDragEnterEvent *event);
|
void dragEnterEvent(QDragEnterEvent *event) override;
|
||||||
void dragMoveEvent(QDragMoveEvent *event);
|
void dragMoveEvent(QDragMoveEvent *event) override;
|
||||||
void dropEvent(QDropEvent *event);
|
void dropEvent(QDropEvent *event) override;
|
||||||
void resizeEvent(QResizeEvent *event);
|
void resizeEvent(QResizeEvent *event) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetupVisibleMacroSegmentWidgets();
|
void SetupVisibleMacroSegmentWidgets();
|
||||||
|
void ClearWidgetCache();
|
||||||
|
|
||||||
int GetSegmentIndexFromPos(const QPoint &) const;
|
int GetSegmentIndexFromPos(const QPoint &) const;
|
||||||
|
bool IsInListArea(const QPoint &) const;
|
||||||
|
QRect GetContentItemRectWithPadding(int idx) const;
|
||||||
|
|
||||||
int GetDragIndex(const QPoint &) const;
|
int GetDragIndex(const QPoint &) const;
|
||||||
int GetDropIndex(const QPoint &) const;
|
int GetDropIndex(const QPoint &) const;
|
||||||
void CheckScroll() const;
|
void CheckScroll() const;
|
||||||
void CheckDropLine(const QPoint &);
|
void CheckDropLine(const QPoint &);
|
||||||
bool IsInListArea(const QPoint &) const;
|
|
||||||
QRect GetContentItemRectWithPadding(int idx) const;
|
|
||||||
void HideLastDropLine();
|
void HideLastDropLine();
|
||||||
void ClearWidgetCache();
|
|
||||||
|
|
||||||
int _dragPosition = -1;
|
int _dragPosition = -1;
|
||||||
int _dropLineIdx = -1;
|
int _dropLineIdx = -1;
|
||||||
@@ -69,6 +83,7 @@ private:
|
|||||||
std::thread _autoScrollThread;
|
std::thread _autoScrollThread;
|
||||||
std::atomic_bool _autoScroll{false};
|
std::atomic_bool _autoScroll{false};
|
||||||
|
|
||||||
|
QStackedWidget *_stackedWidget;
|
||||||
QVBoxLayout *_layout;
|
QVBoxLayout *_layout;
|
||||||
QVBoxLayout *_contentLayout;
|
QVBoxLayout *_contentLayout;
|
||||||
QLabel *_helpMsg;
|
QLabel *_helpMsg;
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
#include "macro-condition-factory.hpp"
|
#include "macro-condition-factory.hpp"
|
||||||
#include "macro-helpers.hpp"
|
#include "macro-helpers.hpp"
|
||||||
#include "macro-segment.hpp"
|
#include "macro-segment.hpp"
|
||||||
|
#include "macro-signals.hpp"
|
||||||
#include "obs-module-helper.hpp"
|
#include "obs-module-helper.hpp"
|
||||||
#include "plugin-state-helpers.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
#include "ui-helpers.hpp"
|
#include "ui-helpers.hpp"
|
||||||
@@ -31,7 +32,8 @@ MacroSegmentSelection::MacroSegmentSelection(QWidget *parent, Type type,
|
|||||||
_index,
|
_index,
|
||||||
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
this, SLOT(IndexChanged(const NumberVariable<int> &)));
|
this, SLOT(IndexChanged(const NumberVariable<int> &)));
|
||||||
QWidget::connect(window(), SIGNAL(MacroSegmentOrderChanged()), this,
|
QWidget::connect(MacroSignalManager::Instance(),
|
||||||
|
SIGNAL(SegmentOrderChanged()), this,
|
||||||
SLOT(MacroSegmentOrderChanged()));
|
SLOT(MacroSegmentOrderChanged()));
|
||||||
|
|
||||||
auto layout = new QHBoxLayout;
|
auto layout = new QHBoxLayout;
|
||||||
@@ -71,35 +73,46 @@ void MacroSegmentSelection::MacroSegmentOrderChanged()
|
|||||||
}
|
}
|
||||||
|
|
||||||
static QString GetMacroSegmentDescription(Macro *macro, int idx,
|
static QString GetMacroSegmentDescription(Macro *macro, int idx,
|
||||||
bool isCondition)
|
MacroSegmentSelection::Type type)
|
||||||
{
|
{
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
if (!IsValidMacroSegmentIndex(macro, idx, isCondition)) {
|
|
||||||
|
MacroSegment *segment;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
case MacroSegmentSelection::Type::CONDITION:
|
||||||
|
if (!IsValidConditionIndex(macro, idx)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
segment = GetMacroConditions(macro)->at(idx).get();
|
||||||
|
break;
|
||||||
|
case MacroSegmentSelection::Type::ACTION:
|
||||||
|
if (!IsValidActionIndex(macro, idx)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
segment = GetMacroActions(macro)->at(idx).get();
|
||||||
|
break;
|
||||||
|
case MacroSegmentSelection::Type::ELSE_ACTION:
|
||||||
|
if (!IsValidElseActionIndex(macro, idx)) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
segment = GetMacroElseActions(macro)->at(idx).get();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroSegment *segment;
|
const auto idToName = type == MacroSegmentSelection::Type::CONDITION
|
||||||
if (isCondition) {
|
? MacroConditionFactory::GetConditionName
|
||||||
segment = GetMacroConditions(macro)->at(idx).get();
|
: MacroActionFactory::GetActionName;
|
||||||
} else {
|
const QString typeStr =
|
||||||
segment = GetMacroActions(macro)->at(idx).get();
|
obs_module_text(idToName(segment->GetId()).c_str());
|
||||||
}
|
const QString description =
|
||||||
|
QString::fromStdString(segment->GetShortDesc());
|
||||||
|
|
||||||
QString description = QString::fromStdString(segment->GetShortDesc());
|
QString result = typeStr;
|
||||||
QString type;
|
|
||||||
if (isCondition) {
|
|
||||||
type = obs_module_text(MacroConditionFactory::GetConditionName(
|
|
||||||
segment->GetId())
|
|
||||||
.c_str());
|
|
||||||
} else {
|
|
||||||
type = obs_module_text(
|
|
||||||
MacroActionFactory::GetActionName(segment->GetId())
|
|
||||||
.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
QString result = type;
|
|
||||||
if (!description.isEmpty()) {
|
if (!description.isEmpty()) {
|
||||||
result += ": " + description;
|
result += ": " + description;
|
||||||
}
|
}
|
||||||
@@ -121,11 +134,25 @@ void MacroSegmentSelection::SetupDescription() const
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool validIndex = false;
|
||||||
|
switch (_type) {
|
||||||
|
case Type::CONDITION:
|
||||||
|
validIndex = IsValidConditionIndex(_macro, index - 1);
|
||||||
|
break;
|
||||||
|
case Type::ACTION:
|
||||||
|
validIndex = IsValidActionIndex(_macro, index - 1);
|
||||||
|
break;
|
||||||
|
case Type::ELSE_ACTION:
|
||||||
|
validIndex = IsValidElseActionIndex(_macro, index - 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
QString description;
|
QString description;
|
||||||
if (IsValidMacroSegmentIndex(_macro, index - 1,
|
if (validIndex) {
|
||||||
_type == Type::CONDITION)) {
|
description =
|
||||||
description = GetMacroSegmentDescription(
|
GetMacroSegmentDescription(_macro, index - 1, _type);
|
||||||
_macro, index - 1, _type == Type::CONDITION);
|
|
||||||
} else {
|
} else {
|
||||||
description = obs_module_text(
|
description = obs_module_text(
|
||||||
"AdvSceneSwitcher.macroSegmentSelection.invalid");
|
"AdvSceneSwitcher.macroSegmentSelection.invalid");
|
||||||
@@ -163,8 +190,23 @@ void MacroSegmentSelection::MarkSelectedSegment()
|
|||||||
if (index.GetType() == IntVariable::Type::VARIABLE) {
|
if (index.GetType() == IntVariable::Type::VARIABLE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!IsValidMacroSegmentIndex(_macro, index - 1,
|
|
||||||
_type == Type::CONDITION)) {
|
bool validIndex = false;
|
||||||
|
switch (_type) {
|
||||||
|
case Type::CONDITION:
|
||||||
|
validIndex = IsValidConditionIndex(_macro, index - 1);
|
||||||
|
break;
|
||||||
|
case Type::ACTION:
|
||||||
|
validIndex = IsValidActionIndex(_macro, index - 1);
|
||||||
|
break;
|
||||||
|
case Type::ELSE_ACTION:
|
||||||
|
validIndex = IsValidElseActionIndex(_macro, index - 1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!validIndex) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ class Macro;
|
|||||||
class MacroSegmentSelection : public QWidget {
|
class MacroSegmentSelection : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum class Type { CONDITION, ACTION };
|
enum class Type { CONDITION, ACTION, ELSE_ACTION };
|
||||||
|
|
||||||
MacroSegmentSelection(QWidget *parent, Type type,
|
MacroSegmentSelection(QWidget *parent, Type type,
|
||||||
bool allowVariables = true);
|
bool allowVariables = true);
|
||||||
|
|||||||
74
lib/macro/macro-segment-unknown.hpp
Normal file
74
lib/macro/macro-segment-unknown.hpp
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro-action.hpp"
|
||||||
|
#include "macro-condition.hpp"
|
||||||
|
|
||||||
|
#include <obs.hpp>
|
||||||
|
|
||||||
|
#include <QLabel>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
// Retains the settings and ID of the macro segment even if they can't be
|
||||||
|
// interpreted correctly right now.
|
||||||
|
//
|
||||||
|
// As soon as a version of the plugin supporting the original ID is running it
|
||||||
|
// will take over again
|
||||||
|
template<typename T> class MacroSegmentUnknown : public T {
|
||||||
|
public:
|
||||||
|
MacroSegmentUnknown(Macro *macro, const std::string &originalId);
|
||||||
|
bool CheckCondition() { return false; }
|
||||||
|
std::shared_ptr<MacroAction> Copy() const;
|
||||||
|
bool PerformAction() { return true; };
|
||||||
|
bool Save(obs_data_t *data) const;
|
||||||
|
bool Load(obs_data_t *data);
|
||||||
|
std::string GetId() const { return "unknown"; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string _id;
|
||||||
|
OBSData _settings;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline MacroSegmentUnknown<T>::MacroSegmentUnknown(
|
||||||
|
Macro *macro, const std::string &originalId)
|
||||||
|
: T(macro),
|
||||||
|
_id(originalId),
|
||||||
|
_settings(obs_data_create())
|
||||||
|
{
|
||||||
|
obs_data_release(_settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline std::shared_ptr<MacroAction> MacroSegmentUnknown<T>::Copy() const
|
||||||
|
{
|
||||||
|
if constexpr (std::is_same_v<T, MacroAction>) {
|
||||||
|
return std::make_shared<MacroSegmentUnknown<T>>(
|
||||||
|
MacroAction::GetMacro(), _id);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
inline bool MacroSegmentUnknown<T>::Save(obs_data_t *data) const
|
||||||
|
{
|
||||||
|
T::Save(data);
|
||||||
|
obs_data_apply(data, _settings);
|
||||||
|
obs_data_set_string(_settings, "id", _id.c_str());
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> inline bool MacroSegmentUnknown<T>::Load(obs_data_t *data)
|
||||||
|
{
|
||||||
|
T::Load(data);
|
||||||
|
obs_data_apply(_settings, data);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline QWidget *CreateUnknownSegmentWidget(bool isAction)
|
||||||
|
{
|
||||||
|
return new QLabel(obs_module_text(
|
||||||
|
isAction ? "AdvSceneSwitcher.action.unknown"
|
||||||
|
: "AdvSceneSwitcher.condition.unknown"));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -256,23 +256,6 @@ MacroSegmentEdit::MacroSegmentEdit(QWidget *parent)
|
|||||||
|
|
||||||
QWidget::connect(_section, &Section::Collapsed, this,
|
QWidget::connect(_section, &Section::Collapsed, this,
|
||||||
&MacroSegmentEdit::Collapsed);
|
&MacroSegmentEdit::Collapsed);
|
||||||
// Macro signals
|
|
||||||
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 &)));
|
|
||||||
// Scene group signals
|
|
||||||
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)));
|
|
||||||
|
|
||||||
auto frameLayout = new QGridLayout;
|
auto frameLayout = new QGridLayout;
|
||||||
frameLayout->setContentsMargins(0, 0, 0, 0);
|
frameLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|||||||
@@ -113,13 +113,6 @@ public slots:
|
|||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void Collapsed(bool) const;
|
void Collapsed(bool) const;
|
||||||
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:
|
protected:
|
||||||
void SetDisableEffect(bool);
|
void SetDisableEffect(bool);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "layout-helpers.hpp"
|
#include "layout-helpers.hpp"
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
|
#include "macro-signals.hpp"
|
||||||
#include "ui-helpers.hpp"
|
#include "ui-helpers.hpp"
|
||||||
|
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
@@ -13,22 +14,21 @@ MacroSelection::MacroSelection(QWidget *parent)
|
|||||||
: FilterComboBox(parent,
|
: FilterComboBox(parent,
|
||||||
obs_module_text("AdvSceneSwitcher.selectMacro"))
|
obs_module_text("AdvSceneSwitcher.selectMacro"))
|
||||||
{
|
{
|
||||||
for (const auto &m : GetMacros()) {
|
for (const auto &m : GetTopLevelMacros()) {
|
||||||
if (m->IsGroup()) {
|
if (m->IsGroup()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
addItem(QString::fromStdString(m->Name()));
|
addItem(QString::fromStdString(m->Name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget::connect(GetSettingsWindow(),
|
QWidget::connect(MacroSignalManager::Instance(),
|
||||||
SIGNAL(MacroAdded(const QString &)), this,
|
SIGNAL(Add(const QString &)), this,
|
||||||
SLOT(MacroAdd(const QString &)));
|
SLOT(MacroAdd(const QString &)));
|
||||||
QWidget::connect(GetSettingsWindow(),
|
QWidget::connect(MacroSignalManager::Instance(),
|
||||||
SIGNAL(MacroRemoved(const QString &)), this,
|
SIGNAL(Remove(const QString &)), this,
|
||||||
SLOT(MacroRemove(const QString &)));
|
SLOT(MacroRemove(const QString &)));
|
||||||
QWidget::connect(GetSettingsWindow(),
|
QWidget::connect(MacroSignalManager::Instance(),
|
||||||
SIGNAL(MacroRenamed(const QString &, const QString &)),
|
SIGNAL(Rename(const QString &, const QString &)), this,
|
||||||
this,
|
|
||||||
SLOT(MacroRename(const QString &, const QString &)));
|
SLOT(MacroRename(const QString &, const QString &)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ void MacroSelection::SetCurrentMacro(const MacroRef ¯o)
|
|||||||
|
|
||||||
void MacroSelection::HideSelectedMacro()
|
void MacroSelection::HideSelectedMacro()
|
||||||
{
|
{
|
||||||
auto ssWindow = static_cast<AdvSceneSwitcher *>(window());
|
auto ssWindow = static_cast<AdvSceneSwitcher *>(GetSettingsWindow());
|
||||||
if (!ssWindow) {
|
if (!ssWindow) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,9 @@ MacroSettingsDialog::MacroSettingsDialog(QWidget *parent,
|
|||||||
_currentInputs(new MacroInputSelection()),
|
_currentInputs(new MacroInputSelection()),
|
||||||
_currentMacroRegisterDock(new QCheckBox(obs_module_text(
|
_currentMacroRegisterDock(new QCheckBox(obs_module_text(
|
||||||
"AdvSceneSwitcher.macroTab.currentRegisterDock"))),
|
"AdvSceneSwitcher.macroTab.currentRegisterDock"))),
|
||||||
|
_currentMacroIsStandaloneDock(new QCheckBox(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.macroTab.currentIsStandaloneDock"))),
|
||||||
|
_currentMacroDockWindowName(new QLineEdit(this)),
|
||||||
_currentMacroDockAddRunButton(new QCheckBox(obs_module_text(
|
_currentMacroDockAddRunButton(new QCheckBox(obs_module_text(
|
||||||
"AdvSceneSwitcher.macroTab.currentDockAddRunButton"))),
|
"AdvSceneSwitcher.macroTab.currentDockAddRunButton"))),
|
||||||
_currentMacroDockAddPauseButton(new QCheckBox(obs_module_text(
|
_currentMacroDockAddPauseButton(new QCheckBox(obs_module_text(
|
||||||
@@ -198,6 +201,15 @@ MacroSettingsDialog::MacroSettingsDialog(QWidget *parent,
|
|||||||
int row = 0;
|
int row = 0;
|
||||||
_dockLayout->addWidget(_currentMacroRegisterDock, row, 1, 1, 2);
|
_dockLayout->addWidget(_currentMacroRegisterDock, row, 1, 1, 2);
|
||||||
row++;
|
row++;
|
||||||
|
_dockLayout->addWidget(_currentMacroIsStandaloneDock, row, 1, 1, 2);
|
||||||
|
row++;
|
||||||
|
_dockLayout->addWidget(
|
||||||
|
new QLabel(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.macroTab.currentDockWindowName")),
|
||||||
|
row, 1);
|
||||||
|
_dockLayout->addWidget(_currentMacroDockWindowName, row, 2);
|
||||||
|
_dockWindowNameRow = row;
|
||||||
|
row++;
|
||||||
_dockLayout->addWidget(_currentMacroDockAddRunButton, row, 1, 1, 2);
|
_dockLayout->addWidget(_currentMacroDockAddRunButton, row, 1, 1, 2);
|
||||||
row++;
|
row++;
|
||||||
_dockLayout->addWidget(
|
_dockLayout->addWidget(
|
||||||
@@ -252,6 +264,8 @@ MacroSettingsDialog::MacroSettingsDialog(QWidget *parent,
|
|||||||
|
|
||||||
connect(_currentMacroRegisterDock, &QCheckBox::stateChanged, this,
|
connect(_currentMacroRegisterDock, &QCheckBox::stateChanged, this,
|
||||||
&MacroSettingsDialog::DockEnableChanged);
|
&MacroSettingsDialog::DockEnableChanged);
|
||||||
|
connect(_currentMacroIsStandaloneDock, &QCheckBox::stateChanged, this,
|
||||||
|
&MacroSettingsDialog::IsStandaloneDockChanged);
|
||||||
connect(_currentMacroDockAddRunButton, &QCheckBox::stateChanged, this,
|
connect(_currentMacroDockAddRunButton, &QCheckBox::stateChanged, this,
|
||||||
&MacroSettingsDialog::RunButtonEnableChanged);
|
&MacroSettingsDialog::RunButtonEnableChanged);
|
||||||
connect(_currentMacroDockAddPauseButton, &QCheckBox::stateChanged, this,
|
connect(_currentMacroDockAddPauseButton, &QCheckBox::stateChanged, this,
|
||||||
@@ -329,55 +343,37 @@ MacroSettingsDialog::MacroSettingsDialog(QWidget *parent,
|
|||||||
_currentSkipOnStartup->setChecked(macro->SkipExecOnStart());
|
_currentSkipOnStartup->setChecked(macro->SkipExecOnStart());
|
||||||
_currentStopActionsIfNotDone->setChecked(macro->StopActionsIfNotDone());
|
_currentStopActionsIfNotDone->setChecked(macro->StopActionsIfNotDone());
|
||||||
_currentInputs->SetInputs(macro->GetInputVariables());
|
_currentInputs->SetInputs(macro->GetInputVariables());
|
||||||
const bool dockEnabled = macro->DockEnabled();
|
const auto &dockSettings = macro->GetDockSettings();
|
||||||
|
const bool dockEnabled = dockSettings.DockEnabled();
|
||||||
_currentMacroRegisterDock->setChecked(dockEnabled);
|
_currentMacroRegisterDock->setChecked(dockEnabled);
|
||||||
_currentMacroDockAddRunButton->setChecked(macro->DockHasRunButton());
|
_currentMacroIsStandaloneDock->setChecked(
|
||||||
|
dockSettings.IsStandaloneDock());
|
||||||
|
_currentMacroDockWindowName->setText(
|
||||||
|
QString::fromStdString(dockSettings.DockWindowName()));
|
||||||
|
_currentMacroDockAddRunButton->setChecked(dockSettings.HasRunButton());
|
||||||
_currentMacroDockAddPauseButton->setChecked(
|
_currentMacroDockAddPauseButton->setChecked(
|
||||||
macro->DockHasPauseButton());
|
dockSettings.HasPauseButton());
|
||||||
_currentMacroDockAddStatusLabel->setChecked(
|
_currentMacroDockAddStatusLabel->setChecked(
|
||||||
macro->DockHasStatusLabel());
|
dockSettings.HasStatusLabel());
|
||||||
_currentMacroDockHighlightIfConditionsTrue->setChecked(
|
_currentMacroDockHighlightIfConditionsTrue->setChecked(
|
||||||
macro->DockHighlightEnabled());
|
dockSettings.HighlightEnabled());
|
||||||
_runButtonText->setText(macro->RunButtonText());
|
_runButtonText->setText(dockSettings.RunButtonText());
|
||||||
_pauseButtonText->setText(macro->PauseButtonText());
|
_pauseButtonText->setText(dockSettings.PauseButtonText());
|
||||||
_unpauseButtonText->setText(macro->UnpauseButtonText());
|
_unpauseButtonText->setText(dockSettings.UnpauseButtonText());
|
||||||
_conditionsTrueStatusText->setText(macro->ConditionsTrueStatusText());
|
_conditionsTrueStatusText->setText(
|
||||||
_conditionsFalseStatusText->setText(macro->ConditionsFalseStatusText());
|
dockSettings.ConditionsTrueStatusText());
|
||||||
|
_conditionsFalseStatusText->setText(
|
||||||
|
dockSettings.ConditionsFalseStatusText());
|
||||||
|
|
||||||
_currentMacroDockAddRunButton->setVisible(dockEnabled);
|
DockEnableChanged(dockEnabled);
|
||||||
_currentMacroDockAddPauseButton->setVisible(dockEnabled);
|
|
||||||
_currentMacroDockAddStatusLabel->setVisible(dockEnabled);
|
|
||||||
_currentMacroDockHighlightIfConditionsTrue->setVisible(dockEnabled);
|
|
||||||
SetGridLayoutRowVisible(_dockLayout, _runButtonTextRow,
|
|
||||||
dockEnabled && macro->DockHasRunButton());
|
|
||||||
SetGridLayoutRowVisible(_dockLayout, _pauseButtonTextRow,
|
|
||||||
dockEnabled && macro->DockHasPauseButton());
|
|
||||||
SetGridLayoutRowVisible(_dockLayout, _unpauseButtonTextRow,
|
|
||||||
dockEnabled && macro->DockHasPauseButton());
|
|
||||||
SetGridLayoutRowVisible(_dockLayout, _conditionsTrueTextRow,
|
|
||||||
dockEnabled && macro->DockHasStatusLabel());
|
|
||||||
SetGridLayoutRowVisible(_dockLayout, _conditionsFalseTextRow,
|
|
||||||
dockEnabled && macro->DockHasStatusLabel());
|
|
||||||
MinimizeSizeOfColumn(_dockLayout, 0);
|
MinimizeSizeOfColumn(_dockLayout, 0);
|
||||||
Resize();
|
|
||||||
|
|
||||||
// Try to set sensible initial size for the dialog window
|
Resize();
|
||||||
QSize contentSize = contentWidget->sizeHint();
|
|
||||||
resize(contentSize.width() + layout->contentsMargins().left() +
|
|
||||||
layout->contentsMargins().right() +
|
|
||||||
dialogLayout->contentsMargins().left() +
|
|
||||||
dialogLayout->contentsMargins().right() +
|
|
||||||
scrollArea->verticalScrollBar()->sizeHint().width() + 20,
|
|
||||||
contentSize.height() + dialogLayout->spacing() +
|
|
||||||
buttonbox->sizeHint().height() +
|
|
||||||
dialogLayout->contentsMargins().top() +
|
|
||||||
dialogLayout->contentsMargins().bottom() +
|
|
||||||
scrollArea->horizontalScrollBar()->sizeHint().height() +
|
|
||||||
20);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSettingsDialog::DockEnableChanged(int enabled)
|
void MacroSettingsDialog::DockEnableChanged(int enabled)
|
||||||
{
|
{
|
||||||
|
_currentMacroIsStandaloneDock->setVisible(enabled);
|
||||||
_currentMacroDockAddRunButton->setVisible(enabled);
|
_currentMacroDockAddRunButton->setVisible(enabled);
|
||||||
_currentMacroDockAddPauseButton->setVisible(enabled);
|
_currentMacroDockAddPauseButton->setVisible(enabled);
|
||||||
_currentMacroDockAddStatusLabel->setVisible(enabled);
|
_currentMacroDockAddStatusLabel->setVisible(enabled);
|
||||||
@@ -401,6 +397,12 @@ void MacroSettingsDialog::DockEnableChanged(int enabled)
|
|||||||
Resize();
|
Resize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroSettingsDialog::IsStandaloneDockChanged(int enabled)
|
||||||
|
{
|
||||||
|
SetGridLayoutRowVisible(_dockLayout, _dockWindowNameRow, !enabled);
|
||||||
|
Resize();
|
||||||
|
}
|
||||||
|
|
||||||
void MacroSettingsDialog::RunButtonEnableChanged(int enabled)
|
void MacroSettingsDialog::RunButtonEnableChanged(int enabled)
|
||||||
{
|
{
|
||||||
SetGridLayoutRowVisible(_dockLayout, _runButtonTextRow, enabled);
|
SetGridLayoutRowVisible(_dockLayout, _runButtonTextRow, enabled);
|
||||||
@@ -478,23 +480,30 @@ bool MacroSettingsDialog::AskForSettings(QWidget *parent,
|
|||||||
macro->SetSkipExecOnStart(dialog._currentSkipOnStartup->isChecked());
|
macro->SetSkipExecOnStart(dialog._currentSkipOnStartup->isChecked());
|
||||||
macro->SetStopActionsIfNotDone(
|
macro->SetStopActionsIfNotDone(
|
||||||
dialog._currentStopActionsIfNotDone->isChecked());
|
dialog._currentStopActionsIfNotDone->isChecked());
|
||||||
macro->EnableDock(dialog._currentMacroRegisterDock->isChecked());
|
|
||||||
macro->SetDockHasRunButton(
|
auto &dockSettings = macro->GetDockSettings();
|
||||||
|
dockSettings.EnableDock(dialog._currentMacroRegisterDock->isChecked());
|
||||||
|
dockSettings.SetIsStandaloneDock(
|
||||||
|
dialog._currentMacroIsStandaloneDock->isChecked());
|
||||||
|
dockSettings.SetDockWindowName(
|
||||||
|
dialog._currentMacroDockWindowName->text().toStdString());
|
||||||
|
dockSettings.SetHasRunButton(
|
||||||
dialog._currentMacroDockAddRunButton->isChecked());
|
dialog._currentMacroDockAddRunButton->isChecked());
|
||||||
macro->SetDockHasPauseButton(
|
dockSettings.SetHasPauseButton(
|
||||||
dialog._currentMacroDockAddPauseButton->isChecked());
|
dialog._currentMacroDockAddPauseButton->isChecked());
|
||||||
macro->SetDockHasStatusLabel(
|
dockSettings.SetHasStatusLabel(
|
||||||
dialog._currentMacroDockAddStatusLabel->isChecked());
|
dialog._currentMacroDockAddStatusLabel->isChecked());
|
||||||
macro->SetHighlightEnable(
|
dockSettings.SetHighlightEnable(
|
||||||
dialog._currentMacroDockHighlightIfConditionsTrue->isChecked());
|
dialog._currentMacroDockHighlightIfConditionsTrue->isChecked());
|
||||||
macro->SetRunButtonText(dialog._runButtonText->text().toStdString());
|
dockSettings.SetRunButtonText(
|
||||||
macro->SetPauseButtonText(
|
dialog._runButtonText->text().toStdString());
|
||||||
|
dockSettings.SetPauseButtonText(
|
||||||
dialog._pauseButtonText->text().toStdString());
|
dialog._pauseButtonText->text().toStdString());
|
||||||
macro->SetUnpauseButtonText(
|
dockSettings.SetUnpauseButtonText(
|
||||||
dialog._unpauseButtonText->text().toStdString());
|
dialog._unpauseButtonText->text().toStdString());
|
||||||
macro->SetConditionsTrueStatusText(
|
dockSettings.SetConditionsTrueStatusText(
|
||||||
dialog._conditionsTrueStatusText->text().toStdString());
|
dialog._conditionsTrueStatusText->text().toStdString());
|
||||||
macro->SetConditionsFalseStatusText(
|
dockSettings.SetConditionsFalseStatusText(
|
||||||
dialog._conditionsFalseStatusText->text().toStdString());
|
dialog._conditionsFalseStatusText->text().toStdString());
|
||||||
macro->SetInputVariables(dialog._currentInputs->GetInputs());
|
macro->SetInputVariables(dialog._currentInputs->GetInputs());
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ public:
|
|||||||
Macro *macro);
|
Macro *macro);
|
||||||
private slots:
|
private slots:
|
||||||
void DockEnableChanged(int);
|
void DockEnableChanged(int);
|
||||||
|
void IsStandaloneDockChanged(int);
|
||||||
void RunButtonEnableChanged(int);
|
void RunButtonEnableChanged(int);
|
||||||
void PauseButtonEnableChanged(int);
|
void PauseButtonEnableChanged(int);
|
||||||
void StatusLabelEnableChanged(int);
|
void StatusLabelEnableChanged(int);
|
||||||
@@ -69,6 +70,8 @@ private:
|
|||||||
QCheckBox *_currentStopActionsIfNotDone;
|
QCheckBox *_currentStopActionsIfNotDone;
|
||||||
MacroInputSelection *_currentInputs;
|
MacroInputSelection *_currentInputs;
|
||||||
QCheckBox *_currentMacroRegisterDock;
|
QCheckBox *_currentMacroRegisterDock;
|
||||||
|
QCheckBox *_currentMacroIsStandaloneDock;
|
||||||
|
QLineEdit *_currentMacroDockWindowName;
|
||||||
QCheckBox *_currentMacroDockAddRunButton;
|
QCheckBox *_currentMacroDockAddRunButton;
|
||||||
QCheckBox *_currentMacroDockAddPauseButton;
|
QCheckBox *_currentMacroDockAddPauseButton;
|
||||||
QCheckBox *_currentMacroDockAddStatusLabel;
|
QCheckBox *_currentMacroDockAddStatusLabel;
|
||||||
@@ -81,6 +84,7 @@ private:
|
|||||||
QGroupBox *_dockOptions;
|
QGroupBox *_dockOptions;
|
||||||
QGridLayout *_dockLayout;
|
QGridLayout *_dockLayout;
|
||||||
|
|
||||||
|
int _dockWindowNameRow = -1;
|
||||||
int _runButtonTextRow = -1;
|
int _runButtonTextRow = -1;
|
||||||
int _pauseButtonTextRow = -1;
|
int _pauseButtonTextRow = -1;
|
||||||
int _unpauseButtonTextRow = -1;
|
int _unpauseButtonTextRow = -1;
|
||||||
|
|||||||
13
lib/macro/macro-signals.cpp
Normal file
13
lib/macro/macro-signals.cpp
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
#include "macro-signals.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
MacroSignalManager::MacroSignalManager(QObject *parent) : QObject(parent) {}
|
||||||
|
|
||||||
|
MacroSignalManager *MacroSignalManager::Instance()
|
||||||
|
{
|
||||||
|
static MacroSignalManager manager;
|
||||||
|
return &manager;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
26
lib/macro/macro-signals.hpp
Normal file
26
lib/macro/macro-signals.hpp
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "export-symbol-helper.hpp"
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
class ADVSS_EXPORT MacroSignalManager : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static MacroSignalManager *Instance();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void Rename(const QString &, const QString &);
|
||||||
|
void Add(const QString &);
|
||||||
|
void Remove(const QString &);
|
||||||
|
void SegmentOrderChanged();
|
||||||
|
void HighlightChanged(bool value);
|
||||||
|
|
||||||
|
private:
|
||||||
|
MacroSignalManager(QObject *parent = nullptr);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,7 @@
|
|||||||
#include "macro-tree.hpp"
|
#include "macro-tree.hpp"
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
|
#include "macro-search.hpp"
|
||||||
|
#include "macro-signals.hpp"
|
||||||
#include "path-helpers.hpp"
|
#include "path-helpers.hpp"
|
||||||
#include "sync-helpers.hpp"
|
#include "sync-helpers.hpp"
|
||||||
#include "ui-helpers.hpp"
|
#include "ui-helpers.hpp"
|
||||||
@@ -79,10 +81,10 @@ MacroTreeItem::MacroTreeItem(MacroTree *tree, std::shared_ptr<Macro> macroItem,
|
|||||||
_macro->SetPaused(!val);
|
_macro->SetPaused(!val);
|
||||||
};
|
};
|
||||||
connect(_running, &QAbstractButton::clicked, setRunning);
|
connect(_running, &QAbstractButton::clicked, setRunning);
|
||||||
connect(_tree->window(), SIGNAL(HighlightMacrosChanged(bool)), this,
|
connect(MacroSignalManager::Instance(), SIGNAL(HighlightChanged(bool)),
|
||||||
SLOT(EnableHighlight(bool)));
|
this, SLOT(EnableHighlight(bool)));
|
||||||
connect(_tree->window(),
|
connect(MacroSignalManager::Instance(),
|
||||||
SIGNAL(MacroRenamed(const QString &, const QString &)), this,
|
SIGNAL(Rename(const QString &, const QString &)), this,
|
||||||
SLOT(MacroRenamed(const QString &, const QString &)));
|
SLOT(MacroRenamed(const QString &, const QString &)));
|
||||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(HighlightIfExecuted()));
|
connect(&_timer, SIGNAL(timeout()), this, SLOT(HighlightIfExecuted()));
|
||||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(UpdatePaused()));
|
connect(&_timer, SIGNAL(timeout()), this, SLOT(UpdatePaused()));
|
||||||
@@ -414,6 +416,20 @@ void MacroTreeModel::Add(std::shared_ptr<Macro> item)
|
|||||||
QItemSelectionModel::Select);
|
QItemSelectionModel::Select);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroTreeModel::MoveToBeginningOfGroup(std::shared_ptr<Macro> item,
|
||||||
|
std::shared_ptr<Macro> group)
|
||||||
|
{
|
||||||
|
auto it = std::find(_macros.begin(), _macros.end(), item);
|
||||||
|
assert(it != _macros.end());
|
||||||
|
std::shared_ptr<Macro> tmp = *it;
|
||||||
|
_macros.erase(it);
|
||||||
|
it = std::find(_macros.begin(), _macros.end(), group);
|
||||||
|
assert(it != _macros.end());
|
||||||
|
_macros.insert(std::next(it), tmp);
|
||||||
|
|
||||||
|
Reset(_macros);
|
||||||
|
}
|
||||||
|
|
||||||
void MacroTreeModel::Remove(std::shared_ptr<Macro> item)
|
void MacroTreeModel::Remove(std::shared_ptr<Macro> item)
|
||||||
{
|
{
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
@@ -768,7 +784,8 @@ void MacroTree::Reset(std::deque<std::shared_ptr<Macro>> ¯os,
|
|||||||
bool highlight)
|
bool highlight)
|
||||||
{
|
{
|
||||||
_highlight = highlight;
|
_highlight = highlight;
|
||||||
MacroTreeModel *mtm = new MacroTreeModel(this, macros);
|
|
||||||
|
auto mtm = new MacroTreeModel(this, macros);
|
||||||
setModel(mtm);
|
setModel(mtm);
|
||||||
GetModel()->Reset(macros);
|
GetModel()->Reset(macros);
|
||||||
connect(selectionModel(),
|
connect(selectionModel(),
|
||||||
@@ -789,6 +806,13 @@ void MacroTree::Add(std::shared_ptr<Macro> item,
|
|||||||
assert(GetModel()->IsInValidState());
|
assert(GetModel()->IsInValidState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroTree::AddToGroup(std::shared_ptr<Macro> item,
|
||||||
|
std::shared_ptr<Macro> group) const
|
||||||
|
{
|
||||||
|
GetModel()->Add(item);
|
||||||
|
GetModel()->MoveToBeginningOfGroup(item, group);
|
||||||
|
}
|
||||||
|
|
||||||
std::shared_ptr<Macro> MacroTree::GetCurrentMacro() const
|
std::shared_ptr<Macro> MacroTree::GetCurrentMacro() const
|
||||||
{
|
{
|
||||||
return GetModel()->GetCurrentMacro();
|
return GetModel()->GetCurrentMacro();
|
||||||
@@ -847,7 +871,7 @@ void MacroTree::UpdateWidgets(bool force)
|
|||||||
|
|
||||||
for (int i = 0; i < (int)mtm->_macros.size(); i++) {
|
for (int i = 0; i < (int)mtm->_macros.size(); i++) {
|
||||||
std::shared_ptr<Macro> item = mtm->_macros[i];
|
std::shared_ptr<Macro> item = mtm->_macros[i];
|
||||||
MacroTreeItem *widget = GetItemWidget(i);
|
auto widget = GetItemWidget(i);
|
||||||
|
|
||||||
if (!widget) {
|
if (!widget) {
|
||||||
UpdateWidget(mtm->createIndex(i, 0, nullptr), item);
|
UpdateWidget(mtm->createIndex(i, 0, nullptr), item);
|
||||||
@@ -1160,6 +1184,34 @@ bool MacroTree::SelectionEmpty() const
|
|||||||
return selectedIndexes().empty();
|
return selectedIndexes().empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MacroTree::GroupsExist() const
|
||||||
|
{
|
||||||
|
for (const auto ¯o : GetTopLevelMacros()) {
|
||||||
|
if (macro->IsGroup()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroTree::ExpandGroup(std::shared_ptr<Macro> item) const
|
||||||
|
{
|
||||||
|
auto *mtm = GetModel();
|
||||||
|
mtm->ExpandGroup(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroTree::CollapseGroup(std::shared_ptr<Macro> item) const
|
||||||
|
{
|
||||||
|
auto *mtm = GetModel();
|
||||||
|
mtm->CollapseGroup(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroTree::RefreshFilter()
|
||||||
|
{
|
||||||
|
UpdateWidgets();
|
||||||
|
doItemsLayout();
|
||||||
|
}
|
||||||
|
|
||||||
void MacroTree::MoveItemBefore(const std::shared_ptr<Macro> &item,
|
void MacroTree::MoveItemBefore(const std::shared_ptr<Macro> &item,
|
||||||
const std::shared_ptr<Macro> &after) const
|
const std::shared_ptr<Macro> &after) const
|
||||||
{
|
{
|
||||||
@@ -1174,7 +1226,7 @@ void MacroTree::MoveItemAfter(const std::shared_ptr<Macro> &item,
|
|||||||
|
|
||||||
MacroTreeModel *MacroTree::GetModel() const
|
MacroTreeModel *MacroTree::GetModel() const
|
||||||
{
|
{
|
||||||
return reinterpret_cast<MacroTreeModel *>(model());
|
return qobject_cast<MacroTreeModel *>(model());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroTree::Remove(std::shared_ptr<Macro> item) const
|
void MacroTree::Remove(std::shared_ptr<Macro> item) const
|
||||||
@@ -1260,6 +1312,26 @@ void MacroTree::UngroupSelectedGroups()
|
|||||||
assert(GetModel()->IsInValidState());
|
assert(GetModel()->IsInValidState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroTree::ExpandAll()
|
||||||
|
{
|
||||||
|
for (const auto ¯o : GetTopLevelMacros()) {
|
||||||
|
if (!macro->IsGroup()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
ExpandGroup(macro);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroTree::CollapseAll()
|
||||||
|
{
|
||||||
|
for (const auto ¯o : GetTopLevelMacros()) {
|
||||||
|
if (!macro->IsGroup()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
CollapseGroup(macro);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MacroTree::SelectionChangedHelper(const QItemSelection &,
|
void MacroTree::SelectionChangedHelper(const QItemSelection &,
|
||||||
const QItemSelection &)
|
const QItemSelection &)
|
||||||
{
|
{
|
||||||
@@ -1269,8 +1341,8 @@ void MacroTree::SelectionChangedHelper(const QItemSelection &,
|
|||||||
|
|
||||||
inline MacroTreeItem *MacroTree::GetItemWidget(int idx) const
|
inline MacroTreeItem *MacroTree::GetItemWidget(int idx) const
|
||||||
{
|
{
|
||||||
QWidget *widget = indexWidget(GetModel()->createIndex(idx, 0, nullptr));
|
auto widget = indexWidget(GetModel()->createIndex(idx, 0, nullptr));
|
||||||
return reinterpret_cast<MacroTreeItem *>(widget);
|
return qobject_cast<MacroTreeItem *>(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroTree::paintEvent(QPaintEvent *event)
|
void MacroTree::paintEvent(QPaintEvent *event)
|
||||||
@@ -1297,14 +1369,25 @@ MacroTreeDelegate::MacroTreeDelegate(QObject *parent)
|
|||||||
QSize MacroTreeDelegate::sizeHint(const QStyleOptionViewItem &option,
|
QSize MacroTreeDelegate::sizeHint(const QStyleOptionViewItem &option,
|
||||||
const QModelIndex &index) const
|
const QModelIndex &index) const
|
||||||
{
|
{
|
||||||
MacroTree *tree = qobject_cast<MacroTree *>(parent());
|
auto tree = qobject_cast<MacroTree *>(parent());
|
||||||
QWidget *item = tree->indexWidget(index);
|
auto widget = tree->indexWidget(index);
|
||||||
|
|
||||||
if (!item) {
|
if (!widget) {
|
||||||
return QStyledItemDelegate::sizeHint(option, index);
|
return QStyledItemDelegate::sizeHint(option, index);
|
||||||
}
|
}
|
||||||
|
|
||||||
return QSize(item->sizeHint());
|
auto name = index.data(Qt::AccessibleTextRole).toString();
|
||||||
|
auto macro = GetMacroByQString(name);
|
||||||
|
|
||||||
|
if (!macro) {
|
||||||
|
return QStyledItemDelegate::sizeHint(option, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MacroMatchesSearchFilter(macro)) {
|
||||||
|
return QSize(widget->sizeHint());
|
||||||
|
}
|
||||||
|
|
||||||
|
return QSize(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -91,6 +91,8 @@ private:
|
|||||||
void MoveItemAfter(const std::shared_ptr<Macro> &item,
|
void MoveItemAfter(const std::shared_ptr<Macro> &item,
|
||||||
const std::shared_ptr<Macro> &after);
|
const std::shared_ptr<Macro> &after);
|
||||||
void Add(std::shared_ptr<Macro> item);
|
void Add(std::shared_ptr<Macro> item);
|
||||||
|
void MoveToBeginningOfGroup(std::shared_ptr<Macro> item,
|
||||||
|
std::shared_ptr<Macro>);
|
||||||
void Remove(std::shared_ptr<Macro> item);
|
void Remove(std::shared_ptr<Macro> item);
|
||||||
std::shared_ptr<Macro> Neighbor(const std::shared_ptr<Macro> &m,
|
std::shared_ptr<Macro> Neighbor(const std::shared_ptr<Macro> &m,
|
||||||
bool above) const;
|
bool above) const;
|
||||||
@@ -126,6 +128,8 @@ public:
|
|||||||
void Reset(std::deque<std::shared_ptr<Macro>> &, bool highlight);
|
void Reset(std::deque<std::shared_ptr<Macro>> &, bool highlight);
|
||||||
void Add(std::shared_ptr<Macro> item,
|
void Add(std::shared_ptr<Macro> item,
|
||||||
std::shared_ptr<Macro> after = {}) const;
|
std::shared_ptr<Macro> after = {}) const;
|
||||||
|
void AddToGroup(std::shared_ptr<Macro> item,
|
||||||
|
std::shared_ptr<Macro> group) const;
|
||||||
void Remove(std::shared_ptr<Macro> item) const;
|
void Remove(std::shared_ptr<Macro> item) const;
|
||||||
void Up(std::shared_ptr<Macro> item) const;
|
void Up(std::shared_ptr<Macro> item) const;
|
||||||
void Down(std::shared_ptr<Macro> item) const;
|
void Down(std::shared_ptr<Macro> item) const;
|
||||||
@@ -135,10 +139,16 @@ public:
|
|||||||
bool GroupedItemsSelected() const;
|
bool GroupedItemsSelected() const;
|
||||||
bool SingleItemSelected() const;
|
bool SingleItemSelected() const;
|
||||||
bool SelectionEmpty() const;
|
bool SelectionEmpty() const;
|
||||||
|
bool GroupsExist() const;
|
||||||
|
void ExpandGroup(std::shared_ptr<Macro> item) const;
|
||||||
|
void CollapseGroup(std::shared_ptr<Macro> item) const;
|
||||||
|
void RefreshFilter();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void GroupSelectedItems();
|
void GroupSelectedItems();
|
||||||
void UngroupSelectedGroups();
|
void UngroupSelectedGroups();
|
||||||
|
void ExpandAll();
|
||||||
|
void CollapseAll();
|
||||||
void SelectionChangedHelper(const QItemSelection &,
|
void SelectionChangedHelper(const QItemSelection &,
|
||||||
const QItemSelection &);
|
const QItemSelection &);
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include "macro-action-factory.hpp"
|
#include "macro-action-factory.hpp"
|
||||||
#include "macro-condition-factory.hpp"
|
#include "macro-condition-factory.hpp"
|
||||||
#include "macro-dock.hpp"
|
|
||||||
#include "macro-helpers.hpp"
|
#include "macro-helpers.hpp"
|
||||||
#include "macro-settings.hpp"
|
#include "macro-settings.hpp"
|
||||||
#include "plugin-state-helpers.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
@@ -15,69 +14,10 @@
|
|||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
#include <util/platform.h>
|
|
||||||
|
|
||||||
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(30, 0, 0)
|
|
||||||
#include <QDockWidget>
|
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
struct DockMapEntry {
|
|
||||||
QAction *action = nullptr;
|
|
||||||
QWidget *dock = nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
static std::unordered_map<const char *, DockMapEntry> dockIds;
|
|
||||||
static std::mutex dockMutex;
|
|
||||||
|
|
||||||
static bool obs_frontend_add_dock_by_id(const char *id, const char *title,
|
|
||||||
QWidget *widget)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(dockMutex);
|
|
||||||
if (dockIds.count(id) > 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
widget->setObjectName(id);
|
|
||||||
|
|
||||||
auto dock = new QDockWidget();
|
|
||||||
dock->setWindowTitle(title);
|
|
||||||
dock->setWidget(widget);
|
|
||||||
dock->setFloating(true);
|
|
||||||
dock->setVisible(false);
|
|
||||||
dock->setFeatures(QDockWidget::DockWidgetClosable |
|
|
||||||
QDockWidget::DockWidgetMovable |
|
|
||||||
QDockWidget::DockWidgetFloatable);
|
|
||||||
|
|
||||||
auto action = static_cast<QAction *>(obs_frontend_add_dock(dock));
|
|
||||||
if (!action) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
dockIds[id] = {action, dock};
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void obs_frontend_remove_dock(const char *id)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(dockMutex);
|
|
||||||
auto it = dockIds.find(id);
|
|
||||||
if (it == dockIds.end()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
it->second.action->deleteLater();
|
|
||||||
it->second.dock->deleteLater();
|
|
||||||
dockIds.erase(it);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
static std::deque<std::shared_ptr<Macro>> macros;
|
Macro::Macro(const std::string &name) : _dockSettings(this)
|
||||||
|
|
||||||
Macro::Macro(const std::string &name)
|
|
||||||
{
|
{
|
||||||
SetName(name);
|
SetName(name);
|
||||||
}
|
}
|
||||||
@@ -99,12 +39,6 @@ Macro::~Macro()
|
|||||||
_die = true;
|
_die = true;
|
||||||
Stop();
|
Stop();
|
||||||
ClearHotkeys();
|
ClearHotkeys();
|
||||||
|
|
||||||
// Keep the dock widgets in case of shutdown so they can be restored by
|
|
||||||
// OBS on startup
|
|
||||||
if (!OBSIsShuttingDown()) {
|
|
||||||
RemoveDock();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<Macro>
|
std::shared_ptr<Macro>
|
||||||
@@ -123,6 +57,7 @@ Macro::CreateGroup(const std::string &name,
|
|||||||
|
|
||||||
void Macro::RemoveGroup(std::shared_ptr<Macro> group)
|
void Macro::RemoveGroup(std::shared_ptr<Macro> group)
|
||||||
{
|
{
|
||||||
|
auto ¯os = GetTopLevelMacros();
|
||||||
auto it = std::find(macros.begin(), macros.end(), group);
|
auto it = std::find(macros.begin(), macros.end(), group);
|
||||||
if (it == macros.end()) {
|
if (it == macros.end()) {
|
||||||
return;
|
return;
|
||||||
@@ -139,6 +74,7 @@ void Macro::RemoveGroup(std::shared_ptr<Macro> group)
|
|||||||
|
|
||||||
void Macro::PrepareMoveToGroup(Macro *group, std::shared_ptr<Macro> item)
|
void Macro::PrepareMoveToGroup(Macro *group, std::shared_ptr<Macro> item)
|
||||||
{
|
{
|
||||||
|
auto ¯os = GetTopLevelMacros();
|
||||||
for (const auto &m : macros) {
|
for (const auto &m : macros) {
|
||||||
if (m.get() == group) {
|
if (m.get() == group) {
|
||||||
PrepareMoveToGroup(m, item);
|
PrepareMoveToGroup(m, item);
|
||||||
@@ -412,15 +348,9 @@ bool Macro::ShouldRunActions() const
|
|||||||
|
|
||||||
void Macro::SetName(const std::string &name)
|
void Macro::SetName(const std::string &name)
|
||||||
{
|
{
|
||||||
const bool nameChanged = _name == name;
|
|
||||||
_name = name;
|
_name = name;
|
||||||
|
|
||||||
SetHotkeysDesc();
|
SetHotkeysDesc();
|
||||||
|
_dockSettings.HandleMacroNameChange();
|
||||||
if (nameChanged) {
|
|
||||||
_dockId = GenerateDockId();
|
|
||||||
}
|
|
||||||
EnableDock(_registerDock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Macro::ResetTimers()
|
void Macro::ResetTimers()
|
||||||
@@ -605,7 +535,7 @@ void Macro::SetInputVariables(const MacroInputVariables &inputVariables)
|
|||||||
_inputVariables = inputVariables;
|
_inputVariables = inputVariables;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<TempVariable> Macro::GetTempVars(MacroSegment *filter) const
|
std::vector<TempVariable> Macro::GetTempVars(const MacroSegment *filter) const
|
||||||
{
|
{
|
||||||
std::vector<TempVariable> res;
|
std::vector<TempVariable> res;
|
||||||
|
|
||||||
@@ -633,7 +563,7 @@ std::vector<TempVariable> Macro::GetTempVars(MacroSegment *filter) const
|
|||||||
return ptr.get() == segment;
|
return ptr.get() == segment;
|
||||||
}) != _conditions.end();
|
}) != _conditions.end();
|
||||||
};
|
};
|
||||||
auto isAction = [this](MacroSegment *segment) -> bool {
|
auto isAction = [this](const MacroSegment *segment) -> bool {
|
||||||
return std::find_if(_actions.begin(), _actions.end(),
|
return std::find_if(_actions.begin(), _actions.end(),
|
||||||
[segment](
|
[segment](
|
||||||
const std::shared_ptr<MacroSegment>
|
const std::shared_ptr<MacroSegment>
|
||||||
@@ -641,7 +571,7 @@ std::vector<TempVariable> Macro::GetTempVars(MacroSegment *filter) const
|
|||||||
return ptr.get() == segment;
|
return ptr.get() == segment;
|
||||||
}) != _actions.end();
|
}) != _actions.end();
|
||||||
};
|
};
|
||||||
auto isElseAction = [this](MacroSegment *segment) -> bool {
|
auto isElseAction = [this](const MacroSegment *segment) -> bool {
|
||||||
return std::find_if(_elseActions.begin(), _elseActions.end(),
|
return std::find_if(_elseActions.begin(), _elseActions.end(),
|
||||||
[segment](
|
[segment](
|
||||||
const std::shared_ptr<MacroSegment>
|
const std::shared_ptr<MacroSegment>
|
||||||
@@ -819,7 +749,7 @@ bool Macro::Save(obs_data_t *obj, bool saveForCopy) const
|
|||||||
_useCustomConditionCheckInterval);
|
_useCustomConditionCheckInterval);
|
||||||
_customConditionCheckInterval.Save(obj, "customConditionCheckInterval");
|
_customConditionCheckInterval.Save(obj, "customConditionCheckInterval");
|
||||||
|
|
||||||
SaveDockSettings(obj, saveForCopy);
|
_dockSettings.Save(obj, saveForCopy);
|
||||||
|
|
||||||
SaveSplitterPos(_actionConditionSplitterPosition, obj,
|
SaveSplitterPos(_actionConditionSplitterPosition, obj,
|
||||||
"macroActionConditionSplitterPosition");
|
"macroActionConditionSplitterPosition");
|
||||||
@@ -905,7 +835,7 @@ bool Macro::Load(obs_data_t *obj)
|
|||||||
obs_data_get_bool(obj, "useCustomConditionCheckInterval");
|
obs_data_get_bool(obj, "useCustomConditionCheckInterval");
|
||||||
_customConditionCheckInterval.Load(obj, "customConditionCheckInterval");
|
_customConditionCheckInterval.Load(obj, "customConditionCheckInterval");
|
||||||
|
|
||||||
LoadDockSettings(obj);
|
_dockSettings.Load(obj);
|
||||||
|
|
||||||
LoadSplitterPos(_actionConditionSplitterPosition, obj,
|
LoadSplitterPos(_actionConditionSplitterPosition, obj,
|
||||||
"macroActionConditionSplitterPosition");
|
"macroActionConditionSplitterPosition");
|
||||||
@@ -984,7 +914,7 @@ bool Macro::Load(obs_data_t *obj)
|
|||||||
auto newEntry = MacroActionFactory::Create(id, this);
|
auto newEntry = MacroActionFactory::Create(id, this);
|
||||||
if (newEntry) {
|
if (newEntry) {
|
||||||
_elseActions.emplace_back(newEntry);
|
_elseActions.emplace_back(newEntry);
|
||||||
auto action = _actions.back().get();
|
auto action = _elseActions.back().get();
|
||||||
action->WithLock([action, &arrayObj]() {
|
action->WithLock([action, &arrayObj]() {
|
||||||
action->Load(arrayObj);
|
action->Load(arrayObj);
|
||||||
});
|
});
|
||||||
@@ -1095,224 +1025,6 @@ bool Macro::PauseHotkeysEnabled() const
|
|||||||
return _registerHotkeys;
|
return _registerHotkeys;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Macro::SaveDockSettings(obs_data_t *obj, bool saveForCopy) const
|
|
||||||
{
|
|
||||||
auto dockSettings = obs_data_create();
|
|
||||||
obs_data_set_bool(dockSettings, "register", _registerDock);
|
|
||||||
obs_data_set_bool(dockSettings, "hasRunButton", _dockHasRunButton);
|
|
||||||
obs_data_set_bool(dockSettings, "hasPauseButton", _dockHasPauseButton);
|
|
||||||
obs_data_set_bool(dockSettings, "hasStatusLabel", _dockHasStatusLabel);
|
|
||||||
obs_data_set_bool(dockSettings, "highlightIfConditionsTrue",
|
|
||||||
_dockHighlight);
|
|
||||||
_runButtonText.Save(dockSettings, "runButtonText");
|
|
||||||
_pauseButtonText.Save(dockSettings, "pauseButtonText");
|
|
||||||
_unpauseButtonText.Save(dockSettings, "unpauseButtonText");
|
|
||||||
_conditionsTrueStatusText.Save(dockSettings,
|
|
||||||
"conditionsTrueStatusText");
|
|
||||||
_conditionsFalseStatusText.Save(dockSettings,
|
|
||||||
"conditionsFalseStatusText");
|
|
||||||
if (saveForCopy) {
|
|
||||||
auto uuid = GenerateDockId();
|
|
||||||
obs_data_set_string(dockSettings, "dockId", uuid.c_str());
|
|
||||||
|
|
||||||
} else {
|
|
||||||
obs_data_set_string(dockSettings, "dockId", _dockId.c_str());
|
|
||||||
}
|
|
||||||
obs_data_set_int(dockSettings, "version", 1);
|
|
||||||
obs_data_set_obj(obj, "dockSettings", dockSettings);
|
|
||||||
obs_data_release(dockSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Macro::LoadDockSettings(obs_data_t *obj)
|
|
||||||
{
|
|
||||||
auto dockSettings = obs_data_get_obj(obj, "dockSettings");
|
|
||||||
if (!dockSettings) {
|
|
||||||
// TODO: Remove this fallback
|
|
||||||
_dockHasRunButton = obs_data_get_bool(obj, "dockHasRunButton");
|
|
||||||
_dockHasPauseButton =
|
|
||||||
obs_data_get_bool(obj, "dockHasPauseButton");
|
|
||||||
EnableDock(obs_data_get_bool(obj, "registerDock"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!obs_data_has_user_value(dockSettings, "version")) {
|
|
||||||
_dockId = std::string("ADVSS-") + _name;
|
|
||||||
} else {
|
|
||||||
_dockId = obs_data_get_string(dockSettings, "dockId");
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool dockEnabled = obs_data_get_bool(dockSettings, "register");
|
|
||||||
|
|
||||||
// TODO: remove these default settings in a future version
|
|
||||||
obs_data_set_default_string(
|
|
||||||
dockSettings, "runButtonText",
|
|
||||||
obs_module_text("AdvSceneSwitcher.macroDock.run"));
|
|
||||||
obs_data_set_default_string(
|
|
||||||
dockSettings, "pauseButtonText",
|
|
||||||
obs_module_text("AdvSceneSwitcher.macroDock.pause"));
|
|
||||||
obs_data_set_default_string(
|
|
||||||
dockSettings, "unpauseButtonText",
|
|
||||||
obs_module_text("AdvSceneSwitcher.macroDock.unpause"));
|
|
||||||
_runButtonText.Load(dockSettings, "runButtonText");
|
|
||||||
_pauseButtonText.Load(dockSettings, "pauseButtonText");
|
|
||||||
_unpauseButtonText.Load(dockSettings, "unpauseButtonText");
|
|
||||||
_conditionsTrueStatusText.Load(dockSettings,
|
|
||||||
"conditionsTrueStatusText");
|
|
||||||
_conditionsFalseStatusText.Load(dockSettings,
|
|
||||||
"conditionsFalseStatusText");
|
|
||||||
if (dockEnabled) {
|
|
||||||
_dockHasRunButton =
|
|
||||||
obs_data_get_bool(dockSettings, "hasRunButton");
|
|
||||||
_dockHasPauseButton =
|
|
||||||
obs_data_get_bool(dockSettings, "hasPauseButton");
|
|
||||||
_dockHasStatusLabel =
|
|
||||||
obs_data_get_bool(dockSettings, "hasStatusLabel");
|
|
||||||
_dockHighlight = obs_data_get_bool(dockSettings,
|
|
||||||
"highlightIfConditionsTrue");
|
|
||||||
}
|
|
||||||
EnableDock(dockEnabled);
|
|
||||||
obs_data_release(dockSettings);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Macro::EnableDock(bool value)
|
|
||||||
{
|
|
||||||
// Reset dock regardless
|
|
||||||
RemoveDock();
|
|
||||||
|
|
||||||
if (!value) {
|
|
||||||
_registerDock = value;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_dock = new MacroDock(GetWeakMacroByName(_name.c_str()), _runButtonText,
|
|
||||||
_pauseButtonText, _unpauseButtonText,
|
|
||||||
_conditionsTrueStatusText,
|
|
||||||
_conditionsFalseStatusText, _dockHighlight);
|
|
||||||
|
|
||||||
if (!obs_frontend_add_dock_by_id(_dockId.c_str(), _name.c_str(),
|
|
||||||
_dock)) {
|
|
||||||
blog(LOG_INFO, "failed to add macro dock for macro %s",
|
|
||||||
_name.c_str());
|
|
||||||
_dock->deleteLater();
|
|
||||||
_dock = nullptr;
|
|
||||||
_registerDock = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_registerDock = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Macro::SetDockHasRunButton(bool value)
|
|
||||||
{
|
|
||||||
_dockHasRunButton = value;
|
|
||||||
if (!_dock) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_dock->ShowRunButton(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Macro::SetDockHasPauseButton(bool value)
|
|
||||||
{
|
|
||||||
_dockHasPauseButton = value;
|
|
||||||
if (!_dock) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_dock->ShowPauseButton(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Macro::SetDockHasStatusLabel(bool value)
|
|
||||||
{
|
|
||||||
_dockHasStatusLabel = value;
|
|
||||||
if (!_dock) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_dock->ShowStatusLabel(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Macro::SetHighlightEnable(bool value)
|
|
||||||
{
|
|
||||||
_dockHighlight = value;
|
|
||||||
if (!_dock) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_dock->EnableHighlight(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Macro::SetRunButtonText(const std::string &text)
|
|
||||||
{
|
|
||||||
_runButtonText = text;
|
|
||||||
if (!_dock) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_dock->SetRunButtonText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Macro::SetPauseButtonText(const std::string &text)
|
|
||||||
{
|
|
||||||
_pauseButtonText = text;
|
|
||||||
if (!_dock) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_dock->SetPauseButtonText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Macro::SetUnpauseButtonText(const std::string &text)
|
|
||||||
{
|
|
||||||
_unpauseButtonText = text;
|
|
||||||
if (!_dock) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_dock->SetUnpauseButtonText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void Macro::SetConditionsTrueStatusText(const std::string &text)
|
|
||||||
{
|
|
||||||
_conditionsTrueStatusText = text;
|
|
||||||
if (!_dock) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_dock->SetConditionsTrueText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
StringVariable Macro::ConditionsTrueStatusText() const
|
|
||||||
{
|
|
||||||
return _conditionsTrueStatusText;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Macro::SetConditionsFalseStatusText(const std::string &text)
|
|
||||||
{
|
|
||||||
_conditionsFalseStatusText = text;
|
|
||||||
if (!_dock) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
_dock->SetConditionsFalseText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
StringVariable Macro::ConditionsFalseStatusText() const
|
|
||||||
{
|
|
||||||
return _conditionsFalseStatusText;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Macro::RemoveDock()
|
|
||||||
{
|
|
||||||
obs_frontend_remove_dock(_dockId.c_str());
|
|
||||||
_dock = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string Macro::GenerateDockId()
|
|
||||||
{
|
|
||||||
#if LIBOBS_API_VER > MAKE_SEMANTIC_VERSION(30, 0, 0)
|
|
||||||
auto uuid = os_generate_uuid();
|
|
||||||
auto id = std::string("advss-macro-dock-") + std::string(uuid);
|
|
||||||
bfree(uuid);
|
|
||||||
return id;
|
|
||||||
|
|
||||||
#else
|
|
||||||
static std::atomic_int16_t idCounter = 0;
|
|
||||||
return std::to_string(++idCounter);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pauseCB(void *data, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
static void pauseCB(void *data, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
||||||
{
|
{
|
||||||
if (pressed) {
|
if (pressed) {
|
||||||
@@ -1402,7 +1114,7 @@ void Macro::SetHotkeysDesc() const
|
|||||||
void SaveMacros(obs_data_t *obj)
|
void SaveMacros(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
obs_data_array_t *macroArray = obs_data_array_create();
|
obs_data_array_t *macroArray = obs_data_array_create();
|
||||||
for (const auto &m : macros) {
|
for (const auto &m : GetTopLevelMacros()) {
|
||||||
obs_data_t *array_obj = obs_data_create();
|
obs_data_t *array_obj = obs_data_create();
|
||||||
|
|
||||||
m->Save(array_obj);
|
m->Save(array_obj);
|
||||||
@@ -1416,7 +1128,9 @@ void SaveMacros(obs_data_t *obj)
|
|||||||
|
|
||||||
void LoadMacros(obs_data_t *obj)
|
void LoadMacros(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
|
auto ¯os = GetTopLevelMacros();
|
||||||
macros.clear();
|
macros.clear();
|
||||||
|
|
||||||
obs_data_array_t *macroArray = obs_data_get_array(obj, "macros");
|
obs_data_array_t *macroArray = obs_data_get_array(obj, "macros");
|
||||||
size_t count = obs_data_array_count(macroArray);
|
size_t count = obs_data_array_count(macroArray);
|
||||||
|
|
||||||
@@ -1466,15 +1180,10 @@ void LoadMacros(obs_data_t *obj)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::deque<std::shared_ptr<Macro>> &GetMacros()
|
|
||||||
{
|
|
||||||
return macros;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CheckMacros()
|
bool CheckMacros()
|
||||||
{
|
{
|
||||||
bool matchFound = false;
|
bool matchFound = false;
|
||||||
for (const auto &m : macros) {
|
for (const auto &m : GetTopLevelMacros()) {
|
||||||
if (!m->ConditionsShouldBeChecked()) {
|
if (!m->ConditionsShouldBeChecked()) {
|
||||||
vblog(LOG_INFO,
|
vblog(LOG_INFO,
|
||||||
"skipping condition check for macro \"%s\" "
|
"skipping condition check for macro \"%s\" "
|
||||||
@@ -1501,7 +1210,7 @@ bool RunMacros()
|
|||||||
// reordered while macros are currently being executed.
|
// reordered while macros are currently being executed.
|
||||||
// For example, this can happen if a macro is performing a wait action,
|
// For example, this can happen if a macro is performing a wait action,
|
||||||
// as the main lock will be unlocked during this time.
|
// as the main lock will be unlocked during this time.
|
||||||
auto runPhaseMacros = macros;
|
auto runPhaseMacros = GetTopLevelMacros();
|
||||||
|
|
||||||
// Avoid deadlocks when opening settings window and calling frontend
|
// Avoid deadlocks when opening settings window and calling frontend
|
||||||
// API functions at the same time.
|
// API functions at the same time.
|
||||||
@@ -1541,41 +1250,14 @@ bool RunMacros()
|
|||||||
|
|
||||||
void StopAllMacros()
|
void StopAllMacros()
|
||||||
{
|
{
|
||||||
for (const auto &m : macros) {
|
for (const auto &m : GetAllMacros()) {
|
||||||
m->Stop();
|
m->Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Macro *GetMacroByName(const char *name)
|
|
||||||
{
|
|
||||||
for (const auto &m : macros) {
|
|
||||||
if (m->Name() == name) {
|
|
||||||
return m.get();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Macro *GetMacroByQString(const QString &name)
|
|
||||||
{
|
|
||||||
return GetMacroByName(name.toUtf8().constData());
|
|
||||||
}
|
|
||||||
|
|
||||||
std::weak_ptr<Macro> GetWeakMacroByName(const char *name)
|
|
||||||
{
|
|
||||||
for (const auto &m : macros) {
|
|
||||||
if (m->Name() == name) {
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
void InvalidateMacroTempVarValues()
|
void InvalidateMacroTempVarValues()
|
||||||
{
|
{
|
||||||
for (const auto &m : macros) {
|
for (const auto &m : GetTopLevelMacros()) {
|
||||||
// Do not invalidate the temp vars set during condition checks
|
// Do not invalidate the temp vars set during condition checks
|
||||||
// or action executions running in parallel to the "main" macro
|
// or action executions running in parallel to the "main" macro
|
||||||
// loop, as otherwise access to the information stored in those
|
// loop, as otherwise access to the information stored in those
|
||||||
@@ -1590,6 +1272,8 @@ void InvalidateMacroTempVarValues()
|
|||||||
|
|
||||||
std::shared_ptr<Macro> GetMacroWithInvalidConditionInterval()
|
std::shared_ptr<Macro> GetMacroWithInvalidConditionInterval()
|
||||||
{
|
{
|
||||||
|
auto ¯os = GetTopLevelMacros();
|
||||||
|
|
||||||
if (macros.empty()) {
|
if (macros.empty()) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "macro-action.hpp"
|
#include "macro-action.hpp"
|
||||||
#include "macro-condition.hpp"
|
#include "macro-condition.hpp"
|
||||||
|
#include "macro-dock-settings.hpp"
|
||||||
#include "macro-helpers.hpp"
|
#include "macro-helpers.hpp"
|
||||||
#include "macro-input.hpp"
|
#include "macro-input.hpp"
|
||||||
#include "macro-ref.hpp"
|
#include "macro-ref.hpp"
|
||||||
@@ -8,8 +9,6 @@
|
|||||||
#include "temp-variable.hpp"
|
#include "temp-variable.hpp"
|
||||||
|
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <QString>
|
|
||||||
#include <QByteArray>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -20,7 +19,6 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
class MacroDock;
|
|
||||||
class GlobalMacroSettings;
|
class GlobalMacroSettings;
|
||||||
|
|
||||||
class Macro {
|
class Macro {
|
||||||
@@ -88,7 +86,7 @@ public:
|
|||||||
void SetInputVariables(const MacroInputVariables &);
|
void SetInputVariables(const MacroInputVariables &);
|
||||||
|
|
||||||
// Temporary variable helpers
|
// Temporary variable helpers
|
||||||
std::vector<TempVariable> GetTempVars(MacroSegment *filter) const;
|
std::vector<TempVariable> GetTempVars(const MacroSegment *filter) const;
|
||||||
std::optional<const TempVariable>
|
std::optional<const TempVariable>
|
||||||
GetTempVar(const MacroSegment *, const std::string &id) const;
|
GetTempVar(const MacroSegment *, const std::string &id) const;
|
||||||
void InvalidateTempVarValues() const;
|
void InvalidateTempVarValues() const;
|
||||||
@@ -147,26 +145,7 @@ public:
|
|||||||
bool PauseHotkeysEnabled() const;
|
bool PauseHotkeysEnabled() const;
|
||||||
|
|
||||||
// Docks
|
// Docks
|
||||||
void EnableDock(bool);
|
MacroDockSettings &GetDockSettings() { return _dockSettings; }
|
||||||
bool DockEnabled() const { return _registerDock; }
|
|
||||||
void SetDockHasRunButton(bool value);
|
|
||||||
bool DockHasRunButton() const { return _dockHasRunButton; }
|
|
||||||
void SetDockHasPauseButton(bool value);
|
|
||||||
bool DockHasPauseButton() const { return _dockHasPauseButton; }
|
|
||||||
void SetDockHasStatusLabel(bool value);
|
|
||||||
bool DockHasStatusLabel() const { return _dockHasStatusLabel; }
|
|
||||||
void SetHighlightEnable(bool value);
|
|
||||||
bool DockHighlightEnabled() const { return _dockHighlight; }
|
|
||||||
StringVariable RunButtonText() const { return _runButtonText; }
|
|
||||||
void SetRunButtonText(const std::string &text);
|
|
||||||
StringVariable PauseButtonText() const { return _pauseButtonText; }
|
|
||||||
void SetPauseButtonText(const std::string &text);
|
|
||||||
StringVariable UnpauseButtonText() const { return _unpauseButtonText; }
|
|
||||||
void SetUnpauseButtonText(const std::string &text);
|
|
||||||
void SetConditionsTrueStatusText(const std::string &text);
|
|
||||||
StringVariable ConditionsTrueStatusText() const;
|
|
||||||
void SetConditionsFalseStatusText(const std::string &text);
|
|
||||||
StringVariable ConditionsFalseStatusText() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetupHotkeys();
|
void SetupHotkeys();
|
||||||
@@ -182,11 +161,6 @@ private:
|
|||||||
bool RunActions(bool ignorePause);
|
bool RunActions(bool ignorePause);
|
||||||
bool RunElseActions(bool ignorePause);
|
bool RunElseActions(bool ignorePause);
|
||||||
|
|
||||||
void SaveDockSettings(obs_data_t *obj, bool saveForCopy) const;
|
|
||||||
void LoadDockSettings(obs_data_t *obj);
|
|
||||||
void RemoveDock();
|
|
||||||
static std::string GenerateDockId();
|
|
||||||
|
|
||||||
std::string _name = "";
|
std::string _name = "";
|
||||||
bool _die = false;
|
bool _die = false;
|
||||||
bool _stop = false;
|
bool _stop = false;
|
||||||
@@ -236,34 +210,14 @@ private:
|
|||||||
QList<int> _actionConditionSplitterPosition;
|
QList<int> _actionConditionSplitterPosition;
|
||||||
QList<int> _elseActionSplitterPosition;
|
QList<int> _elseActionSplitterPosition;
|
||||||
|
|
||||||
bool _registerDock = false;
|
MacroDockSettings _dockSettings;
|
||||||
bool _dockHasRunButton = true;
|
|
||||||
bool _dockHasPauseButton = true;
|
|
||||||
bool _dockHasStatusLabel = false;
|
|
||||||
bool _dockHighlight = false;
|
|
||||||
StringVariable _runButtonText =
|
|
||||||
obs_module_text("AdvSceneSwitcher.macroDock.run");
|
|
||||||
StringVariable _pauseButtonText =
|
|
||||||
obs_module_text("AdvSceneSwitcher.macroDock.pause");
|
|
||||||
StringVariable _unpauseButtonText =
|
|
||||||
obs_module_text("AdvSceneSwitcher.macroDock.unpause");
|
|
||||||
StringVariable _conditionsTrueStatusText =
|
|
||||||
obs_module_text("AdvSceneSwitcher.macroDock.statusLabel.true");
|
|
||||||
StringVariable _conditionsFalseStatusText =
|
|
||||||
obs_module_text("AdvSceneSwitcher.macroDock.statusLabel.false");
|
|
||||||
MacroDock *_dock = nullptr;
|
|
||||||
std::string _dockId = GenerateDockId();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void LoadMacros(obs_data_t *obj);
|
void LoadMacros(obs_data_t *obj);
|
||||||
void SaveMacros(obs_data_t *obj);
|
void SaveMacros(obs_data_t *obj);
|
||||||
std::deque<std::shared_ptr<Macro>> &GetMacros();
|
|
||||||
bool CheckMacros();
|
bool CheckMacros();
|
||||||
bool RunMacros();
|
bool RunMacros();
|
||||||
void StopAllMacros();
|
void StopAllMacros();
|
||||||
Macro *GetMacroByName(const char *name);
|
|
||||||
Macro *GetMacroByQString(const QString &name);
|
|
||||||
std::weak_ptr<Macro> GetWeakMacroByName(const char *name);
|
|
||||||
void InvalidateMacroTempVarValues();
|
void InvalidateMacroTempVarValues();
|
||||||
std::shared_ptr<Macro> GetMacroWithInvalidConditionInterval();
|
std::shared_ptr<Macro> GetMacroWithInvalidConditionInterval();
|
||||||
|
|
||||||
|
|||||||
@@ -258,7 +258,7 @@ bool IsFullscreen(const std::string &title)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> GetTextInWindow(const std::string &window)
|
std::optional<std::string> GetTextInWindow(const std::string &)
|
||||||
{
|
{
|
||||||
// Not implemented
|
// Not implemented
|
||||||
return {};
|
return {};
|
||||||
|
|||||||
@@ -113,7 +113,7 @@ void ActionQueue::Add(const std::shared_ptr<MacroAction> &action)
|
|||||||
action->Save(data);
|
action->Save(data);
|
||||||
copy->Load(data);
|
copy->Load(data);
|
||||||
copy->PostLoad();
|
copy->PostLoad();
|
||||||
RunPostLoadSteps();
|
RunAndClearPostLoadSteps();
|
||||||
copy->ResolveVariablesToFixedValues();
|
copy->ResolveVariablesToFixedValues();
|
||||||
_actions.emplace_back(copy);
|
_actions.emplace_back(copy);
|
||||||
} else {
|
} else {
|
||||||
@@ -423,7 +423,7 @@ void ImportQueues(obs_data_t *data)
|
|||||||
importedQueues->emplace_back(queue);
|
importedQueues->emplace_back(queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
QeueUITask(signalImportedQueues, importedQueues);
|
QueueUITask(signalImportedQueues, importedQueues);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::weak_ptr<ActionQueue> GetWeakActionQueueByName(const std::string &name)
|
std::weak_ptr<ActionQueue> GetWeakActionQueueByName(const std::string &name)
|
||||||
|
|||||||
@@ -44,11 +44,6 @@ void SwitcherData::Prune()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nonMatchingScene && !WeakSourceValid(nonMatchingScene)) {
|
|
||||||
switchIfNotMatching = NoMatchBehavior::NO_SWITCH;
|
|
||||||
nonMatchingScene = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < randomSwitches.size(); i++) {
|
for (size_t i = 0; i < randomSwitches.size(); i++) {
|
||||||
RandomSwitch &s = randomSwitches[i];
|
RandomSwitch &s = randomSwitches[i];
|
||||||
if (!s.valid()) {
|
if (!s.valid()) {
|
||||||
@@ -168,31 +163,6 @@ void SwitcherData::SaveVersion(obs_data_t *obj,
|
|||||||
obs_data_set_string(obj, "version", currentVersion.c_str());
|
obs_data_set_string(obj, "version", currentVersion.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SwitcherData::RunPostLoadSteps()
|
|
||||||
{
|
|
||||||
for (const auto &func : postLoadSteps) {
|
|
||||||
func();
|
|
||||||
}
|
|
||||||
postLoadSteps.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitcherData::AddSaveStep(std::function<void(obs_data_t *)> function)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
saveSteps.emplace_back(function);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitcherData::AddLoadStep(std::function<void(obs_data_t *)> function)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
|
||||||
loadSteps.emplace_back(function);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SwitcherData::AddPostLoadStep(std::function<void()> function)
|
|
||||||
{
|
|
||||||
postLoadSteps.emplace_back(function);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void startHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
static void startHotkeyFunc(void *, obs_hotkey_id, obs_hotkey_t *, bool pressed)
|
||||||
{
|
{
|
||||||
if (pressed) {
|
if (pressed) {
|
||||||
|
|||||||
@@ -14,10 +14,12 @@
|
|||||||
#include "switch-sequence.hpp"
|
#include "switch-sequence.hpp"
|
||||||
#include "switch-video.hpp"
|
#include "switch-video.hpp"
|
||||||
|
|
||||||
#include "macro-settings.hpp"
|
|
||||||
#include "duration-control.hpp"
|
#include "duration-control.hpp"
|
||||||
#include "priority-helper.hpp"
|
|
||||||
#include "plugin-state-helpers.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
|
#include "priority-helper.hpp"
|
||||||
|
#include "regex-config.hpp"
|
||||||
|
#include "scene-selection.hpp"
|
||||||
|
#include "variable-string.hpp"
|
||||||
|
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@@ -57,15 +59,12 @@ public:
|
|||||||
bool AnySceneTransitionStarted();
|
bool AnySceneTransitionStarted();
|
||||||
|
|
||||||
void SetPreconditions();
|
void SetPreconditions();
|
||||||
void AddSaveStep(std::function<void(obs_data_t *)>);
|
|
||||||
void AddLoadStep(std::function<void(obs_data_t *)>);
|
|
||||||
void AddPostLoadStep(std::function<void()>);
|
|
||||||
void RunPostLoadSteps();
|
|
||||||
bool CheckForMatch(OBSWeakSource &scene, OBSWeakSource &transition,
|
bool CheckForMatch(OBSWeakSource &scene, OBSWeakSource &transition,
|
||||||
int &linger, bool &setPreviousSceneAsMatch,
|
int &linger, bool &setPreviousSceneAsMatch,
|
||||||
bool ¯oMatch);
|
bool ¯oMatch);
|
||||||
void CheckNoMatchSwitch(bool &match, OBSWeakSource &scene,
|
void CheckNoMatchSwitch(bool &match, OBSWeakSource &scene,
|
||||||
OBSWeakSource &transition, int &sleep);
|
OBSWeakSource &transition, int &sleep);
|
||||||
|
void CheckAutoStart();
|
||||||
|
|
||||||
/* --- Start of saving / loading section --- */
|
/* --- Start of saving / loading section --- */
|
||||||
|
|
||||||
@@ -95,13 +94,9 @@ public:
|
|||||||
bool stop = false;
|
bool stop = false;
|
||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
|
|
||||||
std::vector<std::function<void(obs_data_t *)>> saveSteps;
|
|
||||||
std::vector<std::function<void(obs_data_t *)>> loadSteps;
|
|
||||||
std::vector<std::function<void()>> postLoadSteps;
|
|
||||||
|
|
||||||
bool firstBoot = true;
|
bool firstBoot = true;
|
||||||
bool transitionActive = false;
|
bool transitionActive = false;
|
||||||
bool sceneColletionStop = false;
|
bool sceneCollectionStop = false;
|
||||||
bool obsIsShuttingDown = false;
|
bool obsIsShuttingDown = false;
|
||||||
bool firstInterval = true;
|
bool firstInterval = true;
|
||||||
bool firstIntervalAfterStop = true;
|
bool firstIntervalAfterStop = true;
|
||||||
@@ -114,7 +109,7 @@ public:
|
|||||||
/* --- Start of General tab section --- */
|
/* --- Start of General tab section --- */
|
||||||
|
|
||||||
int interval = default_interval;
|
int interval = default_interval;
|
||||||
OBSWeakSource nonMatchingScene;
|
SceneSelection nonMatchingScene;
|
||||||
NoMatchBehavior switchIfNotMatching = NoMatchBehavior::NO_SWITCH;
|
NoMatchBehavior switchIfNotMatching = NoMatchBehavior::NO_SWITCH;
|
||||||
Duration noMatchDelay;
|
Duration noMatchDelay;
|
||||||
enum class StartupBehavior { PERSIST = 0, START = 1, STOP = 2 };
|
enum class StartupBehavior { PERSIST = 0, START = 1, STOP = 2 };
|
||||||
@@ -126,6 +121,10 @@ public:
|
|||||||
RECORINDG_OR_STREAMING
|
RECORINDG_OR_STREAMING
|
||||||
};
|
};
|
||||||
AutoStart autoStartEvent = AutoStart::NEVER;
|
AutoStart autoStartEvent = AutoStart::NEVER;
|
||||||
|
bool useAutoStartScene = false;
|
||||||
|
SceneSelection autoStartScene;
|
||||||
|
StringVariable autoStartSceneName;
|
||||||
|
RegexConfig autoStartSceneRegex;
|
||||||
bool enableCooldown = false;
|
bool enableCooldown = false;
|
||||||
Duration cooldown;
|
Duration cooldown;
|
||||||
bool showSystemTrayNotifications = false;
|
bool showSystemTrayNotifications = false;
|
||||||
@@ -164,7 +163,6 @@ public:
|
|||||||
bool warnPluginLoadFailure = true;
|
bool warnPluginLoadFailure = true;
|
||||||
bool disableHints = false;
|
bool disableHints = false;
|
||||||
bool disableFilterComboboxFilter = false;
|
bool disableFilterComboboxFilter = false;
|
||||||
bool disableMacroWidgetCache = false;
|
|
||||||
bool hideLegacyTabs = true;
|
bool hideLegacyTabs = true;
|
||||||
bool saveWindowGeo = false;
|
bool saveWindowGeo = false;
|
||||||
QPoint windowPos = {};
|
QPoint windowPos = {};
|
||||||
|
|||||||
@@ -2,31 +2,31 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
AutoUpdateTooltipLabel::AutoUpdateTooltipLabel(
|
AutoUpdateHelpIcon::AutoUpdateHelpIcon(
|
||||||
QWidget *parent, const std::function<QString()> &updateTooltipCallback,
|
QWidget *parent, const std::function<QString()> &updateTooltipCallback,
|
||||||
int updateIntervalMs)
|
int updateIntervalMs)
|
||||||
: QLabel(parent),
|
: HelpIcon("", parent),
|
||||||
_callback(updateTooltipCallback),
|
_callback(updateTooltipCallback),
|
||||||
_timer(new QTimer(this)),
|
_timer(new QTimer(this)),
|
||||||
_updateIntervalMs(updateIntervalMs)
|
_updateIntervalMs(updateIntervalMs)
|
||||||
{
|
{
|
||||||
connect(_timer, &QTimer::timeout, this,
|
connect(_timer, &QTimer::timeout, this,
|
||||||
&AutoUpdateTooltipLabel::UpdateTooltip);
|
&AutoUpdateHelpIcon::UpdateTooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoUpdateTooltipLabel::enterEvent(QEnterEvent *event)
|
void AutoUpdateHelpIcon::enterEvent(QEnterEvent *event)
|
||||||
{
|
{
|
||||||
_timer->start(_updateIntervalMs);
|
_timer->start(_updateIntervalMs);
|
||||||
QLabel::enterEvent(event);
|
QLabel::enterEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoUpdateTooltipLabel::leaveEvent(QEvent *event)
|
void AutoUpdateHelpIcon::leaveEvent(QEvent *event)
|
||||||
{
|
{
|
||||||
_timer->stop();
|
_timer->stop();
|
||||||
QLabel::leaveEvent(event);
|
QLabel::leaveEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoUpdateTooltipLabel::UpdateTooltip()
|
void AutoUpdateHelpIcon::UpdateTooltip()
|
||||||
{
|
{
|
||||||
setToolTip(_callback());
|
setToolTip(_callback());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "export-symbol-helper.hpp"
|
#include "export-symbol-helper.hpp"
|
||||||
|
#include "help-icon.hpp"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <QLabel>
|
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
class ADVSS_EXPORT AutoUpdateTooltipLabel : public QLabel {
|
class ADVSS_EXPORT AutoUpdateHelpIcon : public HelpIcon {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AutoUpdateTooltipLabel(
|
AutoUpdateHelpIcon(QWidget *parent,
|
||||||
QWidget *parent,
|
const std::function<QString()> &updateTooltipCallback,
|
||||||
const std::function<QString()> &updateTooltipCallback,
|
int updateIntervalMs = 300);
|
||||||
int updateIntervalMs = 300);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void enterEvent(QEnterEvent *event) override;
|
void enterEvent(QEnterEvent *event) override;
|
||||||
|
|||||||
353
lib/utils/canvas-helpers.cpp
Normal file
353
lib/utils/canvas-helpers.cpp
Normal file
@@ -0,0 +1,353 @@
|
|||||||
|
#include "canvas-helpers.hpp"
|
||||||
|
#include "obs-module-helper.hpp"
|
||||||
|
#include "scene-group.hpp"
|
||||||
|
#include "scene-switch-helpers.hpp"
|
||||||
|
#include "selection-helpers.hpp"
|
||||||
|
#include "source-helpers.hpp"
|
||||||
|
#include "ui-helpers.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
#include "variable.hpp"
|
||||||
|
|
||||||
|
#include <obs-frontend-api.h>
|
||||||
|
|
||||||
|
#include <QLayout>
|
||||||
|
|
||||||
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
||||||
|
Q_DECLARE_METATYPE(advss::OBSWeakCanvas);
|
||||||
|
#else
|
||||||
|
Q_DECLARE_METATYPE(OBSWeakCanvas);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
void CanvasSelection::Populate()
|
||||||
|
{
|
||||||
|
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(31, 1, 0)
|
||||||
|
static const auto enumCanvases = [](void *listPtr,
|
||||||
|
obs_canvas_t *canvas) -> bool {
|
||||||
|
auto list = static_cast<FilterComboBox *>(listPtr);
|
||||||
|
OBSWeakCanvas weakCanvas = obs_canvas_get_weak_canvas(canvas);
|
||||||
|
obs_weak_canvas_release(weakCanvas);
|
||||||
|
QVariant variant;
|
||||||
|
variant.setValue(weakCanvas);
|
||||||
|
list->addItem(obs_canvas_get_name(canvas), variant);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
obs_enum_canvases(enumCanvases, this);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
CanvasSelection::CanvasSelection(QWidget *parent)
|
||||||
|
: FilterComboBox(parent,
|
||||||
|
obs_module_text("AdvSceneSwitcher.selectScene"))
|
||||||
|
{
|
||||||
|
setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||||
|
|
||||||
|
Populate();
|
||||||
|
|
||||||
|
connect(this, &FilterComboBox::currentIndexChanged, this,
|
||||||
|
[this]() { emit CanvasChanged(GetCanvas()); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void CanvasSelection::SetCanvas(const OBSWeakCanvas &canvas)
|
||||||
|
{
|
||||||
|
QVariant variant;
|
||||||
|
variant.setValue(canvas);
|
||||||
|
setCurrentIndex(findData(variant));
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSWeakCanvas CanvasSelection::GetCanvas()
|
||||||
|
{
|
||||||
|
return itemData(currentIndex()).value<OBSWeakCanvas>();
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetCanvasCount()
|
||||||
|
{
|
||||||
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
||||||
|
return 1;
|
||||||
|
#else
|
||||||
|
static const auto enumCanvases = [](void *countPtr,
|
||||||
|
obs_canvas_t *) -> bool {
|
||||||
|
auto count = static_cast<int *>(countPtr);
|
||||||
|
(*count)++;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
int count = 0;
|
||||||
|
obs_enum_canvases(enumCanvases, &count);
|
||||||
|
return count;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSWeakCanvas GetWeakCanvasByName(const char *name)
|
||||||
|
{
|
||||||
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
||||||
|
return OBSWeakCanvas();
|
||||||
|
#else
|
||||||
|
struct Data {
|
||||||
|
OBSWeakCanvas canvas;
|
||||||
|
const std::string name;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const auto enumCanvases = [](void *dataPtr,
|
||||||
|
obs_canvas_t *canvas) -> bool {
|
||||||
|
auto data = static_cast<Data *>(dataPtr);
|
||||||
|
if (data->name != obs_canvas_get_name(canvas)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->canvas = obs_canvas_get_weak_canvas(canvas);
|
||||||
|
obs_weak_canvas_release(data->canvas);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
Data data{nullptr, name};
|
||||||
|
obs_enum_canvases(enumCanvases, &data);
|
||||||
|
return data.canvas;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string GetWeakCanvasName(const OBSWeakCanvas &weakCanvas)
|
||||||
|
{
|
||||||
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
||||||
|
return "Main";
|
||||||
|
#else
|
||||||
|
OBSCanvasAutoRelease canvas = obs_weak_canvas_get_canvas(weakCanvas);
|
||||||
|
return canvas ? obs_canvas_get_name(canvas) : "";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsMainCanvas(obs_weak_canvas_t *weakCanvas)
|
||||||
|
{
|
||||||
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
if (!weakCanvas) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSCanvasAutoRelease canvas = obs_weak_canvas_get_canvas(weakCanvas);
|
||||||
|
OBSCanvasAutoRelease main = obs_get_main_canvas();
|
||||||
|
return canvas == main;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSWeakSource GetActiveCanvasScene(const OBSWeakCanvas &weakCanvas)
|
||||||
|
{
|
||||||
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
||||||
|
OBSCanvasAutoRelease canvas;
|
||||||
|
#else
|
||||||
|
if (!weakCanvas) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSCanvasAutoRelease canvas = obs_weak_canvas_get_canvas(weakCanvas);
|
||||||
|
if (!canvas) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OBSCanvasAutoRelease mainCanvas = obs_get_main_canvas();
|
||||||
|
|
||||||
|
// The frontend scene order does not necessarily match the order of the
|
||||||
|
// scenes in the canvas.
|
||||||
|
if (canvas == mainCanvas) {
|
||||||
|
OBSSourceAutoRelease scene = obs_frontend_get_current_scene();
|
||||||
|
return OBSGetWeakRef(scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const auto enumCanvasScenes = [](void *scenePtr,
|
||||||
|
obs_source_t *source) -> bool {
|
||||||
|
auto scene = static_cast<OBSWeakSource *>(scenePtr);
|
||||||
|
if (!obs_source_active(source)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*scene = obs_source_get_weak_source(source);
|
||||||
|
obs_weak_source_release(*scene);
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
OBSWeakSource scene;
|
||||||
|
obs_canvas_enum_scenes(canvas, enumCanvasScenes, &scene);
|
||||||
|
return scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSWeakSource GetSceneAtIndex(const OBSWeakCanvas &weakCanvas, int idx)
|
||||||
|
{
|
||||||
|
if (idx < 0) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
||||||
|
OBSCanvas canvas;
|
||||||
|
#else
|
||||||
|
if (!weakCanvas) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSCanvas canvas = OBSGetStrongRef(weakCanvas);
|
||||||
|
if (!canvas) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OBSCanvasAutoRelease mainCanvas = obs_get_main_canvas();
|
||||||
|
|
||||||
|
// The frontend scene order does not necessarily match the order of the
|
||||||
|
// scenes in the canvas.
|
||||||
|
// So, rely on obs_frontend_get_scenes() in case of the main canvas
|
||||||
|
// instead.
|
||||||
|
if (canvas == mainCanvas) {
|
||||||
|
struct obs_frontend_source_list scenes = {0};
|
||||||
|
obs_frontend_get_scenes(&scenes);
|
||||||
|
if (idx >= (int)scenes.sources.num) {
|
||||||
|
obs_frontend_source_list_free(&scenes);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto scene = OBSGetWeakRef(scenes.sources.array[idx]);
|
||||||
|
obs_frontend_source_list_free(&scenes);
|
||||||
|
return scene;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
const int idx;
|
||||||
|
int currentIdx;
|
||||||
|
OBSSource scene;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const auto enumCanvasScenes = [](void *dataPtr,
|
||||||
|
obs_source_t *source) -> bool {
|
||||||
|
auto data = static_cast<Data *>(dataPtr);
|
||||||
|
if (data->idx != data->currentIdx) {
|
||||||
|
data->currentIdx++;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->scene = source;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
Data data{idx, 0, nullptr};
|
||||||
|
obs_canvas_enum_scenes(canvas, enumCanvasScenes, &data);
|
||||||
|
|
||||||
|
return OBSGetWeakRef(data.scene);
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetIndexOfScene(const OBSWeakCanvas &weakCanvas, const OBSWeakSource &scene)
|
||||||
|
{
|
||||||
|
if (!scene) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
||||||
|
OBSCanvas canvas;
|
||||||
|
#else
|
||||||
|
if (!weakCanvas) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSCanvas canvas = OBSGetStrongRef(weakCanvas);
|
||||||
|
if (!canvas) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
OBSCanvasAutoRelease mainCanvas = obs_get_main_canvas();
|
||||||
|
|
||||||
|
// The frontend scene order does not necessarily match the order of the
|
||||||
|
// scenes in the canvas.
|
||||||
|
// So, rely on obs_frontend_get_scenes() in case of the main canvas
|
||||||
|
// instead.
|
||||||
|
if (canvas == mainCanvas) {
|
||||||
|
struct obs_frontend_source_list scenes = {0};
|
||||||
|
obs_frontend_get_scenes(&scenes);
|
||||||
|
|
||||||
|
OBSSourceAutoRelease sceneSource = OBSGetStrongRef(scene);
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < scenes.sources.num; i++) {
|
||||||
|
if (scenes.sources.array[i] == sceneSource) {
|
||||||
|
idx = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_frontend_source_list_free(&scenes);
|
||||||
|
return idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Data {
|
||||||
|
int idx;
|
||||||
|
OBSSource scene;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const auto enumCanvasScenes = [](void *dataPtr,
|
||||||
|
obs_source_t *source) -> bool {
|
||||||
|
auto data = static_cast<Data *>(dataPtr);
|
||||||
|
if (source == data->scene) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->idx++;
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
Data data{0, OBSGetStrongRef(scene)};
|
||||||
|
obs_canvas_enum_scenes(canvas, enumCanvasScenes, &data);
|
||||||
|
|
||||||
|
return data.idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSWeakCanvas GetMainCanvas()
|
||||||
|
{
|
||||||
|
OBSCanvasAutoRelease mainCanvas = obs_get_main_canvas();
|
||||||
|
return OBSGetWeakRef(mainCanvas);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
||||||
|
|
||||||
|
obs_canvas_t *obs_canvas_get_ref(obs_canvas_t *)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void obs_canvas_release(obs_canvas_t *) {}
|
||||||
|
|
||||||
|
void obs_weak_canvas_addref(obs_weak_canvas_t *) {}
|
||||||
|
|
||||||
|
void obs_weak_canvas_release(obs_weak_canvas_t *) {}
|
||||||
|
|
||||||
|
OBSCanvas OBSGetStrongRef(obs_weak_object_t *weak)
|
||||||
|
{
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_weak_canvas_t *obs_canvas_get_weak_canvas(obs_canvas_t *)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_canvas_t *obs_weak_canvas_get_canvas(obs_weak_canvas_t *)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void obs_canvas_enum_scenes(obs_canvas_t *,
|
||||||
|
bool (*enum_proc)(void *, obs_source_t *),
|
||||||
|
void *param)
|
||||||
|
{
|
||||||
|
obs_enum_scenes(enum_proc, param);
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSCanvas OBSGetStrongRef(obs_weak_canvas_t *)
|
||||||
|
{
|
||||||
|
return OBSCanvas();
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_canvas_t *obs_get_main_canvas()
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
62
lib/utils/canvas-helpers.hpp
Normal file
62
lib/utils/canvas-helpers.hpp
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "filter-combo-box.hpp"
|
||||||
|
|
||||||
|
#include <obs.hpp>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
||||||
|
class EXPORT obs_canvas_t {};
|
||||||
|
class EXPORT obs_weak_canvas_t {};
|
||||||
|
|
||||||
|
EXPORT obs_canvas_t *obs_canvas_get_ref(obs_canvas_t *);
|
||||||
|
EXPORT void obs_canvas_release(obs_canvas_t *);
|
||||||
|
EXPORT void obs_weak_canvas_addref(obs_weak_canvas_t *);
|
||||||
|
EXPORT void obs_weak_canvas_release(obs_weak_canvas_t *);
|
||||||
|
|
||||||
|
using OBSCanvas =
|
||||||
|
OBSSafeRef<obs_canvas_t *, obs_canvas_get_ref, obs_canvas_release>;
|
||||||
|
using OBSWeakCanvas = OBSRef<obs_weak_canvas_t *, obs_weak_canvas_addref,
|
||||||
|
obs_weak_canvas_release>;
|
||||||
|
using OBSCanvasAutoRelease =
|
||||||
|
OBSRefAutoRelease<obs_canvas_t *, obs_canvas_release>;
|
||||||
|
using OBSWeakCanvasAutoRelease =
|
||||||
|
OBSRefAutoRelease<obs_weak_canvas_t *, obs_weak_canvas_release>;
|
||||||
|
|
||||||
|
EXPORT obs_weak_canvas_t *obs_canvas_get_weak_canvas(obs_canvas_t *);
|
||||||
|
EXPORT obs_canvas_t *obs_weak_canvas_get_canvas(obs_weak_canvas_t *);
|
||||||
|
EXPORT void obs_canvas_enum_scenes(obs_canvas_t *,
|
||||||
|
bool (*enum_proc)(void *, obs_source_t *),
|
||||||
|
void *param);
|
||||||
|
EXPORT OBSCanvas OBSGetStrongRef(obs_weak_canvas_t *);
|
||||||
|
EXPORT OBSWeakCanvas OBSGetWeakRef(obs_canvas_t *);
|
||||||
|
EXPORT obs_canvas_t *obs_get_main_canvas();
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
EXPORT int GetCanvasCount();
|
||||||
|
EXPORT OBSWeakCanvas GetWeakCanvasByName(const char *name);
|
||||||
|
EXPORT std::string GetWeakCanvasName(const OBSWeakCanvas &canvas);
|
||||||
|
EXPORT bool IsMainCanvas(obs_weak_canvas_t *canvas);
|
||||||
|
EXPORT OBSWeakSource GetActiveCanvasScene(const OBSWeakCanvas &canvas);
|
||||||
|
EXPORT OBSWeakSource GetSceneAtIndex(const OBSWeakCanvas &weakCanvas, int idx);
|
||||||
|
EXPORT int GetIndexOfScene(const OBSWeakCanvas &weakCanvas,
|
||||||
|
const OBSWeakSource &scene);
|
||||||
|
EXPORT OBSWeakCanvas GetMainCanvas();
|
||||||
|
|
||||||
|
class CanvasSelection : public FilterComboBox {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
EXPORT CanvasSelection(QWidget *parent);
|
||||||
|
EXPORT void SetCanvas(const OBSWeakCanvas &);
|
||||||
|
EXPORT OBSWeakCanvas GetCanvas();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void CanvasChanged(const OBSWeakCanvas &);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void Populate();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -35,6 +35,11 @@ void FileSelection::SetPath(const QString &path)
|
|||||||
_filePath->setText(path);
|
_filePath->setText(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString FileSelection::GetPath() const
|
||||||
|
{
|
||||||
|
return _filePath->text();
|
||||||
|
}
|
||||||
|
|
||||||
QString FileSelection::ValidPathOrDesktop(const QString &path)
|
QString FileSelection::ValidPathOrDesktop(const QString &path)
|
||||||
{
|
{
|
||||||
QFileInfo fileInfo(path);
|
QFileInfo fileInfo(path);
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ public:
|
|||||||
QWidget *parent = 0);
|
QWidget *parent = 0);
|
||||||
EXPORT void SetPath(const StringVariable &);
|
EXPORT void SetPath(const StringVariable &);
|
||||||
EXPORT void SetPath(const QString &);
|
EXPORT void SetPath(const QString &);
|
||||||
|
EXPORT QString GetPath() const;
|
||||||
EXPORT QPushButton *Button() { return _browseButton; }
|
EXPORT QPushButton *Button() { return _browseButton; }
|
||||||
EXPORT static QString ValidPathOrDesktop(const QString &path);
|
EXPORT static QString ValidPathOrDesktop(const QString &path);
|
||||||
|
|
||||||
|
|||||||
@@ -84,6 +84,21 @@ void FilterComboBox::setItemText(int index, const QString &text)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSize FilterComboBox::sizeHint() const
|
||||||
|
{
|
||||||
|
QSize size = QComboBox::sizeHint();
|
||||||
|
|
||||||
|
if (!_filteringEnabled) {
|
||||||
|
return QComboBox::sizeHint();
|
||||||
|
}
|
||||||
|
|
||||||
|
QFontMetrics fm(font());
|
||||||
|
int extra = fm.horizontalAdvance("X") * 2; // Add padding
|
||||||
|
size.setWidth(size.width() + extra);
|
||||||
|
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
void FilterComboBox::focusOutEvent(QFocusEvent *event)
|
void FilterComboBox::focusOutEvent(QFocusEvent *event)
|
||||||
{
|
{
|
||||||
// Reset on invalid selection
|
// Reset on invalid selection
|
||||||
@@ -96,7 +111,7 @@ void FilterComboBox::focusOutEvent(QFocusEvent *event)
|
|||||||
_lastCompleterHighlightRow = -1;
|
_lastCompleterHighlightRow = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int findXthOccurance(QComboBox *list, int count, const QString &value)
|
static int findXthOccurrence(QComboBox *list, int count, const QString &value)
|
||||||
{
|
{
|
||||||
if (value.isEmpty() || count < 1) {
|
if (value.isEmpty() || count < 1) {
|
||||||
return -1;
|
return -1;
|
||||||
@@ -121,7 +136,7 @@ void FilterComboBox::CompleterHighlightChanged(const QModelIndex &index)
|
|||||||
{
|
{
|
||||||
_lastCompleterHighlightRow = index.row();
|
_lastCompleterHighlightRow = index.row();
|
||||||
const auto text = currentText();
|
const auto text = currentText();
|
||||||
int idx = findXthOccurance(this, _lastCompleterHighlightRow, text);
|
int idx = findXthOccurrence(this, _lastCompleterHighlightRow, text);
|
||||||
if (idx == -1) {
|
if (idx == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -133,7 +148,7 @@ void FilterComboBox::TextChanged(const QString &text)
|
|||||||
auto c = completer();
|
auto c = completer();
|
||||||
const bool completerActive = c->completionCount() > 0;
|
const bool completerActive = c->completionCount() > 0;
|
||||||
int count = completerActive ? _lastCompleterHighlightRow + 1 : 1;
|
int count = completerActive ? _lastCompleterHighlightRow + 1 : 1;
|
||||||
int idx = findXthOccurance(this, count, text);
|
int idx = findXthOccurrence(this, count, text);
|
||||||
if (idx == -1) {
|
if (idx == -1) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ public:
|
|||||||
void setCurrentText(const QString &text);
|
void setCurrentText(const QString &text);
|
||||||
void setItemText(int index, const QString &text);
|
void setItemText(int index, const QString &text);
|
||||||
|
|
||||||
|
QSize sizeHint() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void focusOutEvent(QFocusEvent *event) override;
|
void focusOutEvent(QFocusEvent *event) override;
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ class ADVSS_EXPORT ListEditor : public QWidget {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
ListEditor(QWidget *parent = nullptr, bool reorder = true);
|
ListEditor(QWidget *parent = nullptr, bool reorder = true);
|
||||||
|
int count() const { return _list->count(); };
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void showEvent(QShowEvent *);
|
void showEvent(QShowEvent *);
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ std::optional<double> GetDouble(const std::string &str)
|
|||||||
std::optional<int> GetInt(const std::string &str)
|
std::optional<int> GetInt(const std::string &str)
|
||||||
{
|
{
|
||||||
char *end = nullptr;
|
char *end = nullptr;
|
||||||
int value = std::strtol(str.c_str(), &end, 10);
|
int value = (int)std::strtol(str.c_str(), &end, 10);
|
||||||
|
|
||||||
if (end != str.c_str() && *end == '\0' && value != INT_MAX &&
|
if (end != str.c_str() && *end == '\0' && value != INT_MAX &&
|
||||||
value != INT_MIN) {
|
value != INT_MIN) {
|
||||||
|
|||||||
@@ -45,7 +45,10 @@ NonModalMessageDialog::NonModalMessageDialog(const QString &message, Type type,
|
|||||||
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
|
||||||
|
|
||||||
auto layout = new QVBoxLayout(this);
|
auto layout = new QVBoxLayout(this);
|
||||||
layout->addWidget(new QLabel(message, this));
|
auto label = new QLabel(message, this);
|
||||||
|
label->setTextInteractionFlags(Qt::TextBrowserInteraction);
|
||||||
|
label->setOpenExternalLinks(true);
|
||||||
|
layout->addWidget(label);
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Type::INFO: {
|
case Type::INFO: {
|
||||||
|
|||||||
@@ -1,8 +1,14 @@
|
|||||||
#include "plugin-state-helpers.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
|
#include "macro-settings.hpp"
|
||||||
|
#include "macro-signals.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "switcher-data.hpp"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
|
static std::mutex initMutex;
|
||||||
|
static std::mutex postLoadMutex;
|
||||||
|
static std::mutex mutex;
|
||||||
|
|
||||||
static std::vector<std::function<void()>> &getPluginInitSteps()
|
static std::vector<std::function<void()>> &getPluginInitSteps()
|
||||||
{
|
{
|
||||||
static std::vector<std::function<void()>> steps;
|
static std::vector<std::function<void()>> steps;
|
||||||
@@ -39,7 +45,23 @@ static std::vector<std::function<void()>> &getStopSteps()
|
|||||||
return steps;
|
return steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::mutex mutex;
|
static std::vector<std::function<void(obs_data_t *)>> &getSaveSteps()
|
||||||
|
{
|
||||||
|
static std::vector<std::function<void(obs_data_t *)>> steps;
|
||||||
|
return steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::function<void(obs_data_t *)>> &getLoadSteps()
|
||||||
|
{
|
||||||
|
static std::vector<std::function<void(obs_data_t *)>> steps;
|
||||||
|
return steps;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::function<void()>> &getPostLoadSteps()
|
||||||
|
{
|
||||||
|
static std::vector<std::function<void()>> steps;
|
||||||
|
return steps;
|
||||||
|
}
|
||||||
|
|
||||||
void SavePluginSettings(obs_data_t *obj)
|
void SavePluginSettings(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
@@ -53,17 +75,20 @@ void LoadPluginSettings(obs_data_t *obj)
|
|||||||
|
|
||||||
void AddSaveStep(std::function<void(obs_data_t *)> step)
|
void AddSaveStep(std::function<void(obs_data_t *)> step)
|
||||||
{
|
{
|
||||||
GetSwitcher()->AddSaveStep(step);
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
getSaveSteps().emplace_back(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddLoadStep(std::function<void(obs_data_t *)> step)
|
void AddLoadStep(std::function<void(obs_data_t *)> step)
|
||||||
{
|
{
|
||||||
GetSwitcher()->AddLoadStep(step);
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
getLoadSteps().emplace_back(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddPostLoadStep(std::function<void()> step)
|
void AddPostLoadStep(std::function<void()> step)
|
||||||
{
|
{
|
||||||
GetSwitcher()->AddPostLoadStep(step);
|
std::lock_guard<std::mutex> lock(postLoadMutex);
|
||||||
|
getPostLoadSteps().emplace_back(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddIntervalResetStep(std::function<void()> step)
|
void AddIntervalResetStep(std::function<void()> step)
|
||||||
@@ -72,20 +97,46 @@ void AddIntervalResetStep(std::function<void()> step)
|
|||||||
getResetIntervalSteps().emplace_back(step);
|
getResetIntervalSteps().emplace_back(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void RunPostLoadSteps()
|
void RunSaveSteps(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
GetSwitcher()->RunPostLoadSteps();
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
for (const auto &func : getSaveSteps()) {
|
||||||
|
func(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunLoadSteps(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
for (const auto &func : getLoadSteps()) {
|
||||||
|
func(obj);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void RunAndClearPostLoadSteps()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(postLoadMutex);
|
||||||
|
for (const auto &func : getPostLoadSteps()) {
|
||||||
|
func();
|
||||||
|
}
|
||||||
|
getPostLoadSteps().clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearPostLoadSteps()
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(postLoadMutex);
|
||||||
|
getPostLoadSteps().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddPluginInitStep(std::function<void()> step)
|
void AddPluginInitStep(std::function<void()> step)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
std::lock_guard<std::mutex> lock(initMutex);
|
||||||
getPluginInitSteps().emplace_back(step);
|
getPluginInitSteps().emplace_back(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddPluginPostLoadStep(std::function<void()> step)
|
void AddPluginPostLoadStep(std::function<void()> step)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
std::lock_guard<std::mutex> lock(initMutex);
|
||||||
getPluginPostLoadSteps().emplace_back(step);
|
getPluginPostLoadSteps().emplace_back(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +148,7 @@ void AddPluginCleanupStep(std::function<void()> step)
|
|||||||
|
|
||||||
void RunPluginInitSteps()
|
void RunPluginInitSteps()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
std::lock_guard<std::mutex> lock(initMutex);
|
||||||
for (const auto &step : getPluginInitSteps()) {
|
for (const auto &step : getPluginInitSteps()) {
|
||||||
step();
|
step();
|
||||||
}
|
}
|
||||||
@@ -188,7 +239,7 @@ NoMatchBehavior GetPluginNoMatchBehavior()
|
|||||||
|
|
||||||
void SetNoMatchScene(const OBSWeakSource &scene)
|
void SetNoMatchScene(const OBSWeakSource &scene)
|
||||||
{
|
{
|
||||||
GetSwitcher()->nonMatchingScene = scene;
|
GetSwitcher()->nonMatchingScene.SetScene(scene);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ForegroundWindowTitle()
|
std::string ForegroundWindowTitle()
|
||||||
@@ -231,4 +282,30 @@ bool IsFirstIntervalAfterStop()
|
|||||||
return GetSwitcher()->firstIntervalAfterStop;
|
return GetSwitcher()->firstIntervalAfterStop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetMacroHighlightingEnabled(bool enable)
|
||||||
|
{
|
||||||
|
auto &settings = GetGlobalMacroSettings();
|
||||||
|
settings._highlightActions = enable;
|
||||||
|
settings._highlightConditions = enable;
|
||||||
|
settings._highlightExecuted = enable;
|
||||||
|
|
||||||
|
obs_queue_task(
|
||||||
|
OBS_TASK_UI,
|
||||||
|
[](void *) {
|
||||||
|
if (!SettingsWindowIsOpened()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
MacroSignalManager::Instance()->HighlightChanged(
|
||||||
|
GetGlobalMacroSettings()._highlightExecuted);
|
||||||
|
},
|
||||||
|
nullptr, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsMacroHighlightingEnabled()
|
||||||
|
{
|
||||||
|
const auto &settings = GetGlobalMacroSettings();
|
||||||
|
return settings._highlightActions || settings._highlightConditions ||
|
||||||
|
settings._highlightExecuted;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -12,7 +12,10 @@ EXPORT void AddSaveStep(std::function<void(obs_data_t *)>);
|
|||||||
EXPORT void AddLoadStep(std::function<void(obs_data_t *)>);
|
EXPORT void AddLoadStep(std::function<void(obs_data_t *)>);
|
||||||
EXPORT void AddPostLoadStep(std::function<void()>);
|
EXPORT void AddPostLoadStep(std::function<void()>);
|
||||||
EXPORT void AddIntervalResetStep(std::function<void()>);
|
EXPORT void AddIntervalResetStep(std::function<void()>);
|
||||||
EXPORT void RunPostLoadSteps();
|
void RunSaveSteps(obs_data_t *);
|
||||||
|
void RunLoadSteps(obs_data_t *);
|
||||||
|
EXPORT void RunAndClearPostLoadSteps();
|
||||||
|
void ClearPostLoadSteps();
|
||||||
|
|
||||||
EXPORT void AddPluginInitStep(std::function<void()>);
|
EXPORT void AddPluginInitStep(std::function<void()>);
|
||||||
EXPORT void AddPluginPostLoadStep(std::function<void()>);
|
EXPORT void AddPluginPostLoadStep(std::function<void()>);
|
||||||
@@ -47,4 +50,7 @@ EXPORT bool InitialLoadIsComplete();
|
|||||||
EXPORT bool IsFirstInterval();
|
EXPORT bool IsFirstInterval();
|
||||||
EXPORT bool IsFirstIntervalAfterStop();
|
EXPORT bool IsFirstIntervalAfterStop();
|
||||||
|
|
||||||
|
EXPORT void SetMacroHighlightingEnabled(bool enable);
|
||||||
|
EXPORT bool IsMacroHighlightingEnabled();
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -111,6 +111,10 @@ std::vector<ThreadPrio> GetThreadPrioMapping()
|
|||||||
|
|
||||||
bool SwitcherData::PrioFuncsValid()
|
bool SwitcherData::PrioFuncsValid()
|
||||||
{
|
{
|
||||||
|
if (functionNamesByPriority.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto fNBPCopy = functionNamesByPriority;
|
auto fNBPCopy = functionNamesByPriority;
|
||||||
|
|
||||||
std::sort(fNBPCopy.begin(), fNBPCopy.end());
|
std::sort(fNBPCopy.begin(), fNBPCopy.end());
|
||||||
|
|||||||
106
lib/utils/resizable-widget.cpp
Normal file
106
lib/utils/resizable-widget.cpp
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
#include "resizable-widget.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
ResizableWidget::ResizableWidget(QWidget *parent) : QWidget(parent) {}
|
||||||
|
|
||||||
|
void ResizableWidget::SetResizingEnabled(bool enable)
|
||||||
|
{
|
||||||
|
setMouseTracking(enable);
|
||||||
|
_customHeight = enable ? sizeHint().height() : 0;
|
||||||
|
auto pol = sizePolicy();
|
||||||
|
pol.setVerticalPolicy(enable ? QSizePolicy::Fixed
|
||||||
|
: QSizePolicy::Preferred);
|
||||||
|
_resizingEnabled = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResizableWidget::mousePressEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (!_resizingEnabled) {
|
||||||
|
QWidget::mousePressEvent(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IsInResizeArea(event->pos())) {
|
||||||
|
_resizing = true;
|
||||||
|
_lastMousePos = event->globalPosition().toPoint();
|
||||||
|
event->accept();
|
||||||
|
} else {
|
||||||
|
QWidget::mousePressEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResizableWidget::mouseMoveEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (!_resizingEnabled) {
|
||||||
|
QWidget::mouseMoveEvent(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_resizing) {
|
||||||
|
const int dy = event->globalPosition().toPoint().y() -
|
||||||
|
_lastMousePos.y();
|
||||||
|
const int baseHeight = _customHeight == 0 ? height()
|
||||||
|
: _customHeight;
|
||||||
|
const int newHeight = baseHeight + dy;
|
||||||
|
_customHeight =
|
||||||
|
std::clamp(newHeight, minimumHeight(), maximumHeight());
|
||||||
|
updateGeometry();
|
||||||
|
_lastMousePos = event->globalPosition().toPoint();
|
||||||
|
event->accept();
|
||||||
|
} else {
|
||||||
|
setCursor(IsInResizeArea(event->pos()) ? Qt::SizeVerCursor
|
||||||
|
: Qt::ArrowCursor);
|
||||||
|
QWidget::mouseMoveEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResizableWidget::mouseReleaseEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (_resizing) {
|
||||||
|
event->accept();
|
||||||
|
_resizing = false;
|
||||||
|
} else {
|
||||||
|
QWidget::mouseReleaseEvent(event);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ResizableWidget::paintEvent(QPaintEvent *event)
|
||||||
|
{
|
||||||
|
QWidget::paintEvent(event);
|
||||||
|
|
||||||
|
if (!_resizingEnabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Draw a triangle in bottom-right as resize indicator
|
||||||
|
QPainter painter(this);
|
||||||
|
QPolygon triangle;
|
||||||
|
triangle << QPoint(width() - 1, height() - _gripSize)
|
||||||
|
<< QPoint(width() - _gripSize, height() - 1)
|
||||||
|
<< QPoint(width() - 1, height() - 1);
|
||||||
|
painter.setBrush(Qt::gray);
|
||||||
|
painter.drawPolygon(triangle);
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize ResizableWidget::sizeHint() const
|
||||||
|
{
|
||||||
|
if (!_resizingEnabled) {
|
||||||
|
return QWidget::sizeHint();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_customHeight == 0) {
|
||||||
|
return QWidget::sizeHint();
|
||||||
|
}
|
||||||
|
|
||||||
|
return QSize(width(), _customHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ResizableWidget::IsInResizeArea(const QPoint &pos) const
|
||||||
|
{
|
||||||
|
return QRect(width() - _gripSize, height() - _gripSize, _gripSize,
|
||||||
|
_gripSize)
|
||||||
|
.contains(pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
34
lib/utils/resizable-widget.hpp
Normal file
34
lib/utils/resizable-widget.hpp
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
class ResizableWidget : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
ResizableWidget(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void SetResizingEnabled(bool enable);
|
||||||
|
void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
void mouseMoveEvent(QMouseEvent *event) override;
|
||||||
|
void mouseReleaseEvent(QMouseEvent *event) override;
|
||||||
|
void paintEvent(QPaintEvent *event) override;
|
||||||
|
QSize sizeHint() const override;
|
||||||
|
int GetCustomHeight() const { return _customHeight; }
|
||||||
|
void SetCustomHeight(int value) { _customHeight = value; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool IsInResizeArea(const QPoint &pos) const;
|
||||||
|
|
||||||
|
bool _resizingEnabled = false;
|
||||||
|
bool _resizing = false;
|
||||||
|
QPoint _lastMousePos;
|
||||||
|
int _customHeight = 0;
|
||||||
|
const int _gripSize = 15;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
ResourceTable::ResourceTable(QTabWidget *parent, const QString &help,
|
ResourceTable::ResourceTable(QWidget *parent, const QString &help,
|
||||||
const QString &addToolTip,
|
const QString &addToolTip,
|
||||||
const QString &removeToolTip,
|
const QString &removeToolTip,
|
||||||
const QStringList &headers,
|
const QStringList &headers,
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class ADVSS_EXPORT ResourceTable : public QWidget {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
ResourceTable(QTabWidget *parent, const QString &help,
|
ResourceTable(QWidget *parent, const QString &help,
|
||||||
const QString &addToolTip, const QString &removeToolTip,
|
const QString &addToolTip, const QString &removeToolTip,
|
||||||
const QStringList &headers,
|
const QStringList &headers,
|
||||||
const std::function<void()> &openSettings);
|
const std::function<void()> &openSettings);
|
||||||
|
|||||||
@@ -10,15 +10,18 @@
|
|||||||
|
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
|
|
||||||
|
#include <QLayout>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
constexpr std::string_view typeSaveName = "type";
|
constexpr std::string_view typeSaveName = "type";
|
||||||
constexpr std::string_view nameSaveName = "name";
|
constexpr std::string_view nameSaveName = "name";
|
||||||
constexpr std::string_view selectionSaveName = "sceneSelection";
|
constexpr std::string_view selectionSaveName = "sceneSelection";
|
||||||
|
constexpr std::string_view canvasSaveName = "canvasSelection";
|
||||||
|
|
||||||
void SceneSelection::Save(obs_data_t *obj) const
|
void SceneSelection::Save(obs_data_t *obj) const
|
||||||
{
|
{
|
||||||
auto data = obs_data_create();
|
OBSDataAutoRelease data = obs_data_create();
|
||||||
obs_data_set_int(data, typeSaveName.data(), static_cast<int>(_type));
|
obs_data_set_int(data, typeSaveName.data(), static_cast<int>(_type));
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case Type::SCENE:
|
case Type::SCENE:
|
||||||
@@ -41,8 +44,31 @@ void SceneSelection::Save(obs_data_t *obj) const
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
obs_data_set_string(data, canvasSaveName.data(),
|
||||||
|
GetWeakCanvasName(_canvas).c_str());
|
||||||
obs_data_set_obj(obj, selectionSaveName.data(), data);
|
obs_data_set_obj(obj, selectionSaveName.data(), data);
|
||||||
obs_data_release(data);
|
}
|
||||||
|
|
||||||
|
static OBSWeakSource getWeakSceneSourceByName(const OBSWeakCanvas &weakCanvas,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
#if LIBOBS_API_VER < MAKE_SEMANTIC_VERSION(31, 1, 0)
|
||||||
|
return GetWeakSourceByName(name);
|
||||||
|
#else
|
||||||
|
if (!weakCanvas) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSCanvasAutoRelease canvas = obs_weak_canvas_get_canvas(weakCanvas);
|
||||||
|
if (!canvas) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSSourceAutoRelease source =
|
||||||
|
obs_canvas_get_source_by_name(canvas, name);
|
||||||
|
OBSWeakSource scene = OBSGetWeakRef(source);
|
||||||
|
return scene;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneSelection::Load(obs_data_t *obj, const char *name,
|
void SceneSelection::Load(obs_data_t *obj, const char *name,
|
||||||
@@ -51,10 +77,15 @@ void SceneSelection::Load(obs_data_t *obj, const char *name,
|
|||||||
// TODO: Remove in future version
|
// TODO: Remove in future version
|
||||||
if (!obs_data_has_user_value(obj, selectionSaveName.data())) {
|
if (!obs_data_has_user_value(obj, selectionSaveName.data())) {
|
||||||
_type = static_cast<Type>(obs_data_get_int(obj, typeName));
|
_type = static_cast<Type>(obs_data_get_int(obj, typeName));
|
||||||
|
|
||||||
|
OBSCanvasAutoRelease mainCanvas = obs_get_main_canvas();
|
||||||
|
_canvas = obs_canvas_get_weak_canvas(mainCanvas);
|
||||||
|
obs_weak_canvas_release(_canvas);
|
||||||
|
|
||||||
auto targetName = obs_data_get_string(obj, name);
|
auto targetName = obs_data_get_string(obj, name);
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case Type::SCENE:
|
case Type::SCENE:
|
||||||
_scene = GetWeakSourceByName(targetName);
|
_scene = getWeakSceneSourceByName(_canvas, targetName);
|
||||||
break;
|
break;
|
||||||
case Type::GROUP:
|
case Type::GROUP:
|
||||||
_group = GetSceneGroupByName(targetName);
|
_group = GetSceneGroupByName(targetName);
|
||||||
@@ -69,12 +100,24 @@ void SceneSelection::Load(obs_data_t *obj, const char *name,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto data = obs_data_get_obj(obj, selectionSaveName.data());
|
OBSDataAutoRelease data =
|
||||||
|
obs_data_get_obj(obj, selectionSaveName.data());
|
||||||
|
|
||||||
|
const char *canvasName =
|
||||||
|
obs_data_get_string(data, canvasSaveName.data());
|
||||||
|
_canvas = GetWeakCanvasByName(
|
||||||
|
obs_data_get_string(data, canvasSaveName.data()));
|
||||||
|
if (strcmp(canvasName, "") == 0) {
|
||||||
|
OBSCanvasAutoRelease mainCanvas = obs_get_main_canvas();
|
||||||
|
_canvas = obs_canvas_get_weak_canvas(mainCanvas);
|
||||||
|
obs_weak_canvas_release(_canvas);
|
||||||
|
}
|
||||||
|
|
||||||
_type = static_cast<Type>(obs_data_get_int(data, typeSaveName.data()));
|
_type = static_cast<Type>(obs_data_get_int(data, typeSaveName.data()));
|
||||||
auto targetName = obs_data_get_string(data, nameSaveName.data());
|
auto targetName = obs_data_get_string(data, nameSaveName.data());
|
||||||
switch (_type) {
|
switch (_type) {
|
||||||
case Type::SCENE:
|
case Type::SCENE:
|
||||||
_scene = GetWeakSourceByName(targetName);
|
_scene = getWeakSceneSourceByName(_canvas, targetName);
|
||||||
break;
|
break;
|
||||||
case Type::GROUP:
|
case Type::GROUP:
|
||||||
_group = GetSceneGroupByName(targetName);
|
_group = GetSceneGroupByName(targetName);
|
||||||
@@ -91,15 +134,18 @@ void SceneSelection::Load(obs_data_t *obj, const char *name,
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
obs_data_release(data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool IsScene(const OBSWeakSource &source)
|
static bool isScene(const OBSWeakSource &source)
|
||||||
{
|
{
|
||||||
auto s = obs_weak_source_get_source(source);
|
OBSSourceAutoRelease s = obs_weak_source_get_source(source);
|
||||||
bool ret = !!obs_scene_from_source(s);
|
return !!obs_scene_from_source(s);
|
||||||
obs_source_release(s);
|
}
|
||||||
return ret;
|
|
||||||
|
void SceneSelection::SetScene(const OBSWeakSource &scene)
|
||||||
|
{
|
||||||
|
_type = Type::SCENE;
|
||||||
|
_scene = scene;
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSWeakSource SceneSelection::GetScene(bool advance) const
|
OBSWeakSource SceneSelection::GetScene(bool advance) const
|
||||||
@@ -116,23 +162,30 @@ OBSWeakSource SceneSelection::GetScene(bool advance) const
|
|||||||
}
|
}
|
||||||
return _group->getCurrentScene();
|
return _group->getCurrentScene();
|
||||||
case Type::PREVIOUS:
|
case Type::PREVIOUS:
|
||||||
|
if (!IsMainCanvas(_canvas)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
return GetPreviousScene();
|
return GetPreviousScene();
|
||||||
case Type::CURRENT:
|
case Type::CURRENT:
|
||||||
return GetCurrentScene();
|
if (IsMainCanvas(_canvas)) {
|
||||||
|
return GetCurrentScene();
|
||||||
|
} else {
|
||||||
|
return GetActiveCanvasScene(_canvas);
|
||||||
|
}
|
||||||
case Type::PREVIEW: {
|
case Type::PREVIEW: {
|
||||||
auto s = obs_frontend_get_current_preview_scene();
|
OBSSourceAutoRelease s =
|
||||||
auto scene = obs_source_get_weak_source(s);
|
obs_frontend_get_current_preview_scene();
|
||||||
obs_weak_source_release(scene);
|
OBSWeakSourceAutoRelease scene = obs_source_get_weak_source(s);
|
||||||
obs_source_release(s);
|
return scene.Get();
|
||||||
return scene;
|
|
||||||
}
|
}
|
||||||
case Type::VARIABLE: {
|
case Type::VARIABLE: {
|
||||||
auto var = _variable.lock();
|
auto var = _variable.lock();
|
||||||
if (!var) {
|
if (!var) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
auto scene = GetWeakSourceByName(var->Value().c_str());
|
auto scene =
|
||||||
if (IsScene(scene)) {
|
getWeakSceneSourceByName(_canvas, var->Value().c_str());
|
||||||
|
if (isScene(scene)) {
|
||||||
return scene;
|
return scene;
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -187,11 +240,30 @@ void SceneSelection::ResolveVariables()
|
|||||||
_type = Type::SCENE;
|
_type = Type::SCENE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static obs_weak_canvas_t *getWeakRefToMainCanvas()
|
||||||
|
{
|
||||||
|
static auto canvas = obs_get_main_canvas();
|
||||||
|
static auto weakCanvas = obs_canvas_get_weak_canvas(canvas);
|
||||||
|
[[maybe_unused]] static const bool _ = []() {
|
||||||
|
// Let's just hope we don't have to deal with selecting scenes
|
||||||
|
// when the OBS main canvas gets deleted and release the
|
||||||
|
// references here already to avoid reporting leaks on shutdown
|
||||||
|
obs_canvas_release(canvas);
|
||||||
|
obs_weak_canvas_release(weakCanvas);
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
return weakCanvas;
|
||||||
|
}
|
||||||
|
|
||||||
SceneSelection SceneSelectionWidget::CurrentSelection()
|
SceneSelection SceneSelectionWidget::CurrentSelection()
|
||||||
{
|
{
|
||||||
SceneSelection s;
|
SceneSelection s;
|
||||||
const int idx = currentIndex();
|
|
||||||
const auto name = currentText();
|
s._canvas = _forceMainCanvas ? OBSWeakCanvas(getWeakRefToMainCanvas())
|
||||||
|
: _canvas->GetCanvas();
|
||||||
|
|
||||||
|
const int idx = _scenes->currentIndex();
|
||||||
|
const auto name = _scenes->currentText();
|
||||||
if (idx == -1 || name.isEmpty()) {
|
if (idx == -1 || name.isEmpty()) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@@ -214,7 +286,8 @@ SceneSelection SceneSelectionWidget::CurrentSelection()
|
|||||||
s._group = GetSceneGroupByQString(name);
|
s._group = GetSceneGroupByQString(name);
|
||||||
} else if (idx < _scenesEndIdx) {
|
} else if (idx < _scenesEndIdx) {
|
||||||
s._type = SceneSelection::Type::SCENE;
|
s._type = SceneSelection::Type::SCENE;
|
||||||
s._scene = GetWeakSourceByQString(name);
|
s._scene = getWeakSceneSourceByName(s._canvas,
|
||||||
|
name.toStdString().c_str());
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@@ -234,20 +307,6 @@ static QStringList getOrderList(bool current, bool previous, bool preview)
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
static QStringList getScenesList()
|
|
||||||
{
|
|
||||||
QStringList list;
|
|
||||||
char **scenes = obs_frontend_get_scene_names();
|
|
||||||
char **temp = scenes;
|
|
||||||
while (*temp) {
|
|
||||||
const char *name = *temp;
|
|
||||||
list << name;
|
|
||||||
temp++;
|
|
||||||
}
|
|
||||||
bfree(scenes);
|
|
||||||
return list;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QStringList getSceneGroupsList()
|
static QStringList getSceneGroupsList()
|
||||||
{
|
{
|
||||||
QStringList list;
|
QStringList list;
|
||||||
@@ -258,70 +317,97 @@ static QStringList getSceneGroupsList()
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QStringList getCanvasScenesList(obs_weak_canvas_t *weakCanvas)
|
||||||
|
{
|
||||||
|
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(31, 1, 0)
|
||||||
|
if (!weakCanvas) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
OBSCanvasAutoRelease canvas = obs_weak_canvas_get_canvas(weakCanvas);
|
||||||
|
static const auto enumCanvasScenes = [](void *listPtr,
|
||||||
|
obs_source_t *source) -> bool {
|
||||||
|
auto list = static_cast<QStringList *>(listPtr);
|
||||||
|
*list << obs_source_get_name(source);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
QStringList list;
|
||||||
|
obs_canvas_enum_scenes(canvas, enumCanvasScenes, &list);
|
||||||
|
list.sort();
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
void SceneSelectionWidget::Reset()
|
void SceneSelectionWidget::Reset()
|
||||||
{
|
{
|
||||||
auto previousSel = _currentSelection;
|
auto previousSel = _currentSelection;
|
||||||
PopulateSelection();
|
PopulateSceneSelection(_currentSelection._canvas);
|
||||||
SetScene(previousSel);
|
SetScene(previousSel);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneSelectionWidget::PopulateSelection()
|
void SceneSelectionWidget::PopulateSceneSelection(obs_weak_canvas_t *canvas)
|
||||||
{
|
{
|
||||||
clear();
|
if (_forceMainCanvas) {
|
||||||
if (_current || _previous) {
|
canvas = getWeakRefToMainCanvas();
|
||||||
const QStringList order =
|
|
||||||
getOrderList(_current, _previous, _preview);
|
|
||||||
AddSelectionGroup(this, order);
|
|
||||||
}
|
}
|
||||||
_placeholderEndIdx = count();
|
|
||||||
|
_scenes->clear();
|
||||||
|
if ((_current || _previous)) {
|
||||||
|
const bool isMain = IsMainCanvas(canvas);
|
||||||
|
const QStringList order = getOrderList(
|
||||||
|
_current, _previous && isMain, _preview && isMain);
|
||||||
|
AddSelectionGroup(_scenes, order);
|
||||||
|
}
|
||||||
|
_placeholderEndIdx = _scenes->count();
|
||||||
|
|
||||||
if (_variables) {
|
if (_variables) {
|
||||||
const QStringList variables = GetVariablesNameList();
|
const QStringList variables = GetVariablesNameList();
|
||||||
AddSelectionGroup(this, variables);
|
AddSelectionGroup(_scenes, variables);
|
||||||
}
|
}
|
||||||
_variablesEndIdx = count();
|
_variablesEndIdx = _scenes->count();
|
||||||
|
|
||||||
if (_sceneGroups) {
|
if (_sceneGroups) {
|
||||||
const QStringList sceneGroups = getSceneGroupsList();
|
const QStringList sceneGroups = getSceneGroupsList();
|
||||||
AddSelectionGroup(this, sceneGroups);
|
AddSelectionGroup(_scenes, sceneGroups);
|
||||||
}
|
}
|
||||||
_groupsEndIdx = count();
|
_groupsEndIdx = _scenes->count();
|
||||||
|
|
||||||
const QStringList scenes = getScenesList();
|
const QStringList scenes = getCanvasScenesList(canvas);
|
||||||
AddSelectionGroup(this, scenes);
|
AddSelectionGroup(_scenes, scenes);
|
||||||
_scenesEndIdx = count();
|
_scenesEndIdx = _scenes->count();
|
||||||
|
|
||||||
// Remove last separator
|
// Remove last separator
|
||||||
removeItem(count() - 1);
|
_scenes->removeItem(_scenes->count() - 1);
|
||||||
setCurrentIndex(-1);
|
_scenes->setCurrentIndex(-1);
|
||||||
|
|
||||||
|
_isPopulated = true;
|
||||||
|
|
||||||
|
Resize();
|
||||||
}
|
}
|
||||||
|
|
||||||
SceneSelectionWidget::SceneSelectionWidget(QWidget *parent, bool variables,
|
SceneSelectionWidget::SceneSelectionWidget(QWidget *parent, bool variables,
|
||||||
bool sceneGroups, bool previous,
|
bool sceneGroups, bool previous,
|
||||||
bool current, bool preview)
|
bool current, bool preview)
|
||||||
: FilterComboBox(parent,
|
: QWidget(parent),
|
||||||
obs_module_text("AdvSceneSwitcher.selectScene")),
|
_scenes(new FilterComboBox(
|
||||||
|
this, obs_module_text("AdvSceneSwitcher.selectScene"))),
|
||||||
|
_canvas(new CanvasSelection(this)),
|
||||||
_current(current),
|
_current(current),
|
||||||
_previous(previous),
|
_previous(previous),
|
||||||
_preview(preview),
|
_preview(preview),
|
||||||
_variables(variables),
|
_variables(variables),
|
||||||
_sceneGroups(sceneGroups)
|
_sceneGroups(sceneGroups)
|
||||||
{
|
{
|
||||||
setDuplicatesEnabled(true);
|
_scenes->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||||
PopulateSelection();
|
_scenes->setDuplicatesEnabled(true);
|
||||||
|
|
||||||
QWidget::connect(this, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_scenes, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(SelectionChanged(int)));
|
SLOT(SelectionChanged(int)));
|
||||||
|
QWidget::connect(_canvas, SIGNAL(CanvasChanged(const OBSWeakCanvas &)),
|
||||||
// Scene groups
|
this, SLOT(CanvasChangedSlot(const OBSWeakCanvas &)));
|
||||||
QWidget::connect(window(), SIGNAL(SceneGroupAdded(const QString &)),
|
QWidget::connect(_canvas, SIGNAL(CanvasChanged(const OBSWeakCanvas &)),
|
||||||
this, SLOT(ItemAdd(const QString &)));
|
this, SIGNAL(CanvasChanged(const OBSWeakCanvas &)));
|
||||||
QWidget::connect(window(), SIGNAL(SceneGroupRemoved(const QString &)),
|
|
||||||
this, SLOT(ItemRemove(const QString &)));
|
|
||||||
QWidget::connect(
|
|
||||||
window(),
|
|
||||||
SIGNAL(SceneGroupRenamed(const QString &, const QString &)),
|
|
||||||
this, SLOT(ItemRename(const QString &, const QString &)));
|
|
||||||
|
|
||||||
// Variables
|
// Variables
|
||||||
QWidget::connect(VariableSignalManager::Instance(),
|
QWidget::connect(VariableSignalManager::Instance(),
|
||||||
@@ -333,19 +419,37 @@ SceneSelectionWidget::SceneSelectionWidget(QWidget *parent, bool variables,
|
|||||||
QWidget::connect(VariableSignalManager::Instance(),
|
QWidget::connect(VariableSignalManager::Instance(),
|
||||||
SIGNAL(Rename(const QString &, const QString &)), this,
|
SIGNAL(Rename(const QString &, const QString &)), this,
|
||||||
SLOT(ItemRename(const QString &, const QString &)));
|
SLOT(ItemRename(const QString &, const QString &)));
|
||||||
|
|
||||||
|
auto layout = new QHBoxLayout();
|
||||||
|
layout->addWidget(_canvas);
|
||||||
|
layout->addWidget(_scenes);
|
||||||
|
setLayout(layout);
|
||||||
|
setContentsMargins(0, 0, 0, 0);
|
||||||
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|
||||||
|
if (GetCanvasCount() <= 1) {
|
||||||
|
LockToMainCanvas();
|
||||||
|
}
|
||||||
|
|
||||||
|
Resize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneSelectionWidget::SetScene(const SceneSelection &s)
|
void SceneSelectionWidget::SetScene(const SceneSelection &s)
|
||||||
{
|
{
|
||||||
int idx = -1;
|
int idx = -1;
|
||||||
|
|
||||||
|
_canvas->SetCanvas(s._canvas);
|
||||||
|
if (!_isPopulated) {
|
||||||
|
PopulateSceneSelection(s._canvas);
|
||||||
|
}
|
||||||
|
|
||||||
switch (s.GetType()) {
|
switch (s.GetType()) {
|
||||||
case SceneSelection::Type::SCENE: {
|
case SceneSelection::Type::SCENE: {
|
||||||
if (_scenesEndIdx == -1) {
|
if (_scenesEndIdx == -1) {
|
||||||
idx = -1;
|
idx = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
idx = FindIdxInRagne(this, _groupsEndIdx, _scenesEndIdx,
|
idx = FindIdxInRagne(_scenes, _groupsEndIdx, _scenesEndIdx,
|
||||||
s.ToString());
|
s.ToString());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -354,7 +458,7 @@ void SceneSelectionWidget::SetScene(const SceneSelection &s)
|
|||||||
idx = -1;
|
idx = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
idx = FindIdxInRagne(this, _variablesEndIdx, _groupsEndIdx,
|
idx = FindIdxInRagne(_scenes, _variablesEndIdx, _groupsEndIdx,
|
||||||
s.ToString());
|
s.ToString());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -365,7 +469,7 @@ void SceneSelectionWidget::SetScene(const SceneSelection &s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
idx = FindIdxInRagne(
|
idx = FindIdxInRagne(
|
||||||
this, _selectIdx, _placeholderEndIdx,
|
_scenes, _selectIdx, _placeholderEndIdx,
|
||||||
obs_module_text(
|
obs_module_text(
|
||||||
"AdvSceneSwitcher.selectPreviousScene"));
|
"AdvSceneSwitcher.selectPreviousScene"));
|
||||||
break;
|
break;
|
||||||
@@ -377,7 +481,7 @@ void SceneSelectionWidget::SetScene(const SceneSelection &s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
idx = FindIdxInRagne(
|
idx = FindIdxInRagne(
|
||||||
this, _selectIdx, _placeholderEndIdx,
|
_scenes, _selectIdx, _placeholderEndIdx,
|
||||||
obs_module_text("AdvSceneSwitcher.selectCurrentScene"));
|
obs_module_text("AdvSceneSwitcher.selectCurrentScene"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -388,7 +492,7 @@ void SceneSelectionWidget::SetScene(const SceneSelection &s)
|
|||||||
}
|
}
|
||||||
|
|
||||||
idx = FindIdxInRagne(
|
idx = FindIdxInRagne(
|
||||||
this, _selectIdx, _placeholderEndIdx,
|
_scenes, _selectIdx, _placeholderEndIdx,
|
||||||
obs_module_text("AdvSceneSwitcher.selectPreviewScene"));
|
obs_module_text("AdvSceneSwitcher.selectPreviewScene"));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -397,22 +501,31 @@ void SceneSelectionWidget::SetScene(const SceneSelection &s)
|
|||||||
idx = -1;
|
idx = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
idx = FindIdxInRagne(this, _placeholderEndIdx, _variablesEndIdx,
|
idx = FindIdxInRagne(_scenes, _placeholderEndIdx,
|
||||||
s.ToString());
|
_variablesEndIdx, s.ToString());
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
idx = -1;
|
idx = -1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setCurrentIndex(idx);
|
_scenes->setCurrentIndex(idx);
|
||||||
_currentSelection = s;
|
_currentSelection = s;
|
||||||
|
|
||||||
|
Resize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SceneSelectionWidget::LockToMainCanvas()
|
||||||
|
{
|
||||||
|
_forceMainCanvas = true;
|
||||||
|
_canvas->hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneSelectionWidget::showEvent(QShowEvent *event)
|
void SceneSelectionWidget::showEvent(QShowEvent *event)
|
||||||
{
|
{
|
||||||
FilterComboBox::showEvent(event);
|
QWidget::showEvent(event);
|
||||||
const QSignalBlocker b(this);
|
const QSignalBlocker b1(_scenes);
|
||||||
|
const QSignalBlocker b2(_canvas);
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -440,9 +553,16 @@ void SceneSelectionWidget::SelectionChanged(int)
|
|||||||
emit SceneChanged(_currentSelection);
|
emit SceneChanged(_currentSelection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneSelectionWidget::CanvasChangedSlot(const OBSWeakCanvas &)
|
||||||
|
{
|
||||||
|
_currentSelection = CurrentSelection();
|
||||||
|
Reset();
|
||||||
|
}
|
||||||
|
|
||||||
void SceneSelectionWidget::ItemAdd(const QString &)
|
void SceneSelectionWidget::ItemAdd(const QString &)
|
||||||
{
|
{
|
||||||
const QSignalBlocker b(this);
|
const QSignalBlocker b1(_scenes);
|
||||||
|
const QSignalBlocker b2(_canvas);
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -454,7 +574,7 @@ bool SceneSelectionWidget::NameUsed(const QString &name)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return _currentSelection._type == SceneSelection::Type::VARIABLE &&
|
return _currentSelection._type == SceneSelection::Type::VARIABLE &&
|
||||||
currentText() == name;
|
_scenes->currentText() == name;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SceneSelectionWidget::ItemRemove(const QString &name)
|
void SceneSelectionWidget::ItemRemove(const QString &name)
|
||||||
@@ -468,8 +588,19 @@ void SceneSelectionWidget::ItemRemove(const QString &name)
|
|||||||
|
|
||||||
void SceneSelectionWidget::ItemRename(const QString &, const QString &)
|
void SceneSelectionWidget::ItemRename(const QString &, const QString &)
|
||||||
{
|
{
|
||||||
const QSignalBlocker b(this);
|
const QSignalBlocker b1(_scenes);
|
||||||
|
const QSignalBlocker b2(_canvas);
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SceneSelectionWidget::Resize()
|
||||||
|
{
|
||||||
|
_scenes->adjustSize();
|
||||||
|
_scenes->updateGeometry();
|
||||||
|
_canvas->adjustSize();
|
||||||
|
_canvas->updateGeometry();
|
||||||
|
adjustSize();
|
||||||
|
updateGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "filter-combo-box.hpp"
|
#include "canvas-helpers.hpp"
|
||||||
|
|
||||||
#include <obs.hpp>
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -24,19 +22,22 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
EXPORT Type GetType() const { return _type; }
|
EXPORT Type GetType() const { return _type; }
|
||||||
|
EXPORT void SetScene(const OBSWeakSource &scene);
|
||||||
EXPORT OBSWeakSource GetScene(bool advance = true) const;
|
EXPORT OBSWeakSource GetScene(bool advance = true) const;
|
||||||
|
EXPORT OBSWeakCanvas GetCanvas() const { return _canvas; };
|
||||||
EXPORT std::string ToString(bool resolve = false) const;
|
EXPORT std::string ToString(bool resolve = false) const;
|
||||||
EXPORT void ResolveVariables();
|
EXPORT void ResolveVariables();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
OBSWeakSource _scene;
|
OBSWeakSource _scene;
|
||||||
|
OBSWeakCanvas _canvas = GetMainCanvas();
|
||||||
SceneGroup *_group = nullptr;
|
SceneGroup *_group = nullptr;
|
||||||
std::weak_ptr<Variable> _variable;
|
std::weak_ptr<Variable> _variable;
|
||||||
Type _type = Type::SCENE;
|
Type _type = Type::SCENE;
|
||||||
friend class SceneSelectionWidget;
|
friend class SceneSelectionWidget;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SceneSelectionWidget : public FilterComboBox {
|
class SceneSelectionWidget : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -45,15 +46,18 @@ public:
|
|||||||
bool previous = false, bool current = false,
|
bool previous = false, bool current = false,
|
||||||
bool preview = false);
|
bool preview = false);
|
||||||
EXPORT void SetScene(const SceneSelection &);
|
EXPORT void SetScene(const SceneSelection &);
|
||||||
|
EXPORT void LockToMainCanvas();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void showEvent(QShowEvent *event) override;
|
void showEvent(QShowEvent *event) override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void SceneChanged(const SceneSelection &);
|
void SceneChanged(const SceneSelection &);
|
||||||
|
void CanvasChanged(const OBSWeakCanvas &);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
EXPORT void SelectionChanged(int);
|
EXPORT void SelectionChanged(int);
|
||||||
|
EXPORT void CanvasChangedSlot(const OBSWeakCanvas &);
|
||||||
EXPORT void ItemAdd(const QString &name);
|
EXPORT void ItemAdd(const QString &name);
|
||||||
EXPORT void ItemRemove(const QString &name);
|
EXPORT void ItemRemove(const QString &name);
|
||||||
EXPORT void ItemRename(const QString &oldName, const QString &newName);
|
EXPORT void ItemRename(const QString &oldName, const QString &newName);
|
||||||
@@ -61,11 +65,15 @@ private slots:
|
|||||||
private:
|
private:
|
||||||
void Reset();
|
void Reset();
|
||||||
SceneSelection CurrentSelection();
|
SceneSelection CurrentSelection();
|
||||||
void PopulateSelection();
|
void PopulateSceneSelection(obs_weak_canvas_t *canvas);
|
||||||
bool IsCurrentSceneSelected(const QString &name);
|
bool IsCurrentSceneSelected(const QString &name);
|
||||||
bool IsPreviousSceneSelected(const QString &name);
|
bool IsPreviousSceneSelected(const QString &name);
|
||||||
bool IsPreviewSceneSelected(const QString &name);
|
bool IsPreviewSceneSelected(const QString &name);
|
||||||
bool NameUsed(const QString &name);
|
bool NameUsed(const QString &name);
|
||||||
|
void Resize();
|
||||||
|
|
||||||
|
FilterComboBox *_scenes;
|
||||||
|
CanvasSelection *_canvas;
|
||||||
|
|
||||||
bool _current;
|
bool _current;
|
||||||
bool _previous;
|
bool _previous;
|
||||||
@@ -73,7 +81,10 @@ private:
|
|||||||
bool _variables;
|
bool _variables;
|
||||||
bool _sceneGroups;
|
bool _sceneGroups;
|
||||||
|
|
||||||
|
bool _forceMainCanvas = false;
|
||||||
|
|
||||||
SceneSelection _currentSelection;
|
SceneSelection _currentSelection;
|
||||||
|
bool _isPopulated = false;
|
||||||
|
|
||||||
// Order of entries
|
// Order of entries
|
||||||
// 1. "select entry" entry
|
// 1. "select entry" entry
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user