mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-29 04:36:21 -05:00
Compare commits
125 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb7ee17362 | ||
|
|
70854ef012 | ||
|
|
053c14056d | ||
|
|
9397d50764 | ||
|
|
473e24cc42 | ||
|
|
d9394605f4 | ||
|
|
d2b9074852 | ||
|
|
b525eb7a0e | ||
|
|
3805aaeeec | ||
|
|
50dc404689 | ||
|
|
975eacbc7e | ||
|
|
7e56dc35b8 | ||
|
|
b3566d98bf | ||
|
|
15379a8e20 | ||
|
|
1e178f4223 | ||
|
|
c16a7b93ea | ||
|
|
f89bb1a750 | ||
|
|
79961aabe4 | ||
|
|
4686fc2b01 | ||
|
|
569b915c07 | ||
|
|
324d3fe7a5 | ||
|
|
ae8d0bf5cb | ||
|
|
17efa82057 | ||
|
|
c17523a476 | ||
|
|
33635d6991 | ||
|
|
d290dbe86b | ||
|
|
c1f5c49eda | ||
|
|
c3f4caa6f3 | ||
|
|
d4c7b0e455 | ||
|
|
b0cb52fe90 | ||
|
|
386f831cd4 | ||
|
|
449daa80cc | ||
|
|
3003547b83 | ||
|
|
1664eb672f | ||
|
|
0939dcacb6 | ||
|
|
54b81d1a42 | ||
|
|
626606100f | ||
|
|
53a0b76e8c | ||
|
|
e16ac9400a | ||
|
|
94060c236b | ||
|
|
890792c270 | ||
|
|
7bc1fc3d0d | ||
|
|
9ea90ed61b | ||
|
|
ce40b80d90 | ||
|
|
53fcd94c5a | ||
|
|
ecb6247959 | ||
|
|
3b4cb6934d | ||
|
|
babe93a6ce | ||
|
|
1e9173699c | ||
|
|
37ba7aa2ca | ||
|
|
a83d2d9910 | ||
|
|
0449064f5d | ||
|
|
6cf1073a3c | ||
|
|
9ac9171206 | ||
|
|
25ce8cd2e4 | ||
|
|
e50522ab89 | ||
|
|
4801502f32 | ||
|
|
e13e4b5ddd | ||
|
|
de8da553f1 | ||
|
|
6558792e73 | ||
|
|
ea5e92017e | ||
|
|
46199efb58 | ||
|
|
8a6eae6c97 | ||
|
|
67eef8a004 | ||
|
|
b5341e5cde | ||
|
|
ac6140b17a | ||
|
|
b1489d98f0 | ||
|
|
3b7119ec58 | ||
|
|
efa34d080e | ||
|
|
19a6277841 | ||
|
|
107e1413ed | ||
|
|
94416dd881 | ||
|
|
8efc39958f | ||
|
|
569f794e33 | ||
|
|
fc1460e592 | ||
|
|
d6e4ee0203 | ||
|
|
0c8135078d | ||
|
|
24f4b864c4 | ||
|
|
41e47f32b6 | ||
|
|
a73ccb15a1 | ||
|
|
36a78f49a5 | ||
|
|
cbd459b0a5 | ||
|
|
03bb1fd089 | ||
|
|
4e2c254717 | ||
|
|
fffb6c5f29 | ||
|
|
81f669e226 | ||
|
|
6484ae54c0 | ||
|
|
1c52caf5e9 | ||
|
|
ce1d4cce57 | ||
|
|
8246197ae6 | ||
|
|
8f90bf8846 | ||
|
|
b955e8a0ea | ||
|
|
81da32f7a2 | ||
|
|
5324fa9350 | ||
|
|
c375daa258 | ||
|
|
4f3bd699c8 | ||
|
|
f5024621c0 | ||
|
|
8308506d71 | ||
|
|
6605c19202 | ||
|
|
fdf1a94f97 | ||
|
|
6b6e37da92 | ||
|
|
0f0fc8ae4e | ||
|
|
4d7e2992e5 | ||
|
|
a5050d4810 | ||
|
|
9df6963f08 | ||
|
|
b833dd4576 | ||
|
|
39378ae20f | ||
|
|
5a2cb943f7 | ||
|
|
b88209f63d | ||
|
|
9c848938f8 | ||
|
|
07b86dda41 | ||
|
|
49e8bf7639 | ||
|
|
a2d0a7f544 | ||
|
|
1a8c894ddf | ||
|
|
3f51f63298 | ||
|
|
a0b4df574b | ||
|
|
68c6492c3f | ||
|
|
0ba7ba77d8 | ||
|
|
04b2b3474d | ||
|
|
ecbb5ebbd7 | ||
|
|
b62757b65d | ||
|
|
b1a3ab5493 | ||
|
|
abc3357180 | ||
|
|
29f9cba236 | ||
|
|
9a62522140 |
1
.github/ISSUE_TEMPLATE/bug_report.md
vendored
1
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -22,6 +22,7 @@ A clear and concise description of what you expected to happen.
|
||||
|
||||
**Logs**
|
||||
Please provide a log of your issue with verbose logging enabled (See General tab of the plugin).
|
||||
In case of a crash, please also include the corresponding crash log.
|
||||
See [here](https://obsproject.com/forum/threads/please-post-a-log-with-your-issue-heres-how.23074/) for a description where to find the log files and how to share them.
|
||||
Please share the currently used plugin settings by exporting them them to a file (See General tab of the plugin).
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
79
.github/actions/build-dependencies/action.yml
vendored
Normal file
79
.github/actions/build-dependencies/action.yml
vendored
Normal file
@@ -0,0 +1,79 @@
|
||||
name: 'Setup plugin build dependencies'
|
||||
description: 'Builds the plugin build dependencies'
|
||||
inputs:
|
||||
target:
|
||||
description: 'Build target for dependencies'
|
||||
required: true
|
||||
config:
|
||||
description: 'Build configuration'
|
||||
required: false
|
||||
default: 'Release'
|
||||
visualStudio:
|
||||
description: 'Visual Studio version (Windows only)'
|
||||
required: false
|
||||
default: 'Visual Studio 16 2019'
|
||||
workingDirectory:
|
||||
description: 'Working directory for packaging'
|
||||
required: false
|
||||
default: ${{ github.workspace }}
|
||||
runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Setup cmake
|
||||
uses: jwlawson/actions-setup-cmake@v1.13
|
||||
with:
|
||||
cmake-version: '3.24.x'
|
||||
|
||||
- name: Restore cached dependencies
|
||||
id: restore-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: ${{ env.DEP_DIR }}
|
||||
key: ${{ env.DEP_DIR }}-${{ runner.os }}-${{ inputs.target }}
|
||||
|
||||
- name: Run macOS Build
|
||||
if: ${{ runner.os == 'macOS' && steps.restore-cache.outputs.cache-hit != 'true' }}
|
||||
shell: zsh {0}
|
||||
run: |
|
||||
build_args=(
|
||||
-c ${{ inputs.config }}
|
||||
-t macos-${{ inputs.target }}
|
||||
)
|
||||
|
||||
if (( ${+CI} && ${+RUNNER_DEBUG} )) build_args+=(--debug)
|
||||
|
||||
${{ inputs.workingDirectory }}/.github/scripts/build-deps-macos.zsh -o ${{ env.DEP_DIR }} ${build_args}
|
||||
|
||||
- name: Run Linux Build
|
||||
if: ${{ runner.os == 'Linux' && steps.restore-cache.outputs.cache-hit != 'true' }}
|
||||
shell: bash
|
||||
run: |
|
||||
build_args=(
|
||||
-c ${{ inputs.config }}
|
||||
-t linux-${{ inputs.target }}
|
||||
)
|
||||
|
||||
if [[ -n "${CI}" && -n "${RUNNER_DEBUG}" ]]; then
|
||||
build_args+=(--debug)
|
||||
fi
|
||||
|
||||
${{ inputs.workingDirectory }}/.github/scripts/build-deps-linux.sh -o ${{ env.DEP_DIR }} "${build_args[@]}"
|
||||
|
||||
- name: Run Windows Build
|
||||
if: ${{ runner.os == 'Windows' && steps.restore-cache.outputs.cache-hit != 'true' }}
|
||||
shell: pwsh
|
||||
run: |
|
||||
$BuildArgs = @{
|
||||
Target = '${{ inputs.target }}'
|
||||
Configuration = '${{ inputs.config }}'
|
||||
CMakeGenerator = '${{ inputs.visualStudio }}'
|
||||
}
|
||||
|
||||
if ( ( Test-Path env:CI ) -and ( Test-Path env:RUNNER_DEBUG ) ) {
|
||||
$BuildArgs += @{
|
||||
Debug = $true
|
||||
}
|
||||
}
|
||||
|
||||
${{ inputs.workingDirectory }}/.github/scripts/Build-Deps-Windows.ps1 -OutDirName ${{ env.DEP_DIR }} @BuildArgs
|
||||
|
||||
6
.github/actions/build-plugin/action.yml
vendored
6
.github/actions/build-plugin/action.yml
vendored
@@ -49,7 +49,7 @@ runs:
|
||||
if [[ '${{ inputs.codesign }}' == 'true' ]] build_args+=(-s)
|
||||
if (( ${+CI} && ${+RUNNER_DEBUG} )) build_args+=(--debug)
|
||||
|
||||
${{ inputs.workingDirectory }}/.github/scripts/build-macos.zsh ${build_args}
|
||||
${{ inputs.workingDirectory }}/.github/scripts/build-macos.zsh -d ${{ env.DEP_DIR }} ${build_args}
|
||||
|
||||
- name: Run Linux Build
|
||||
if: ${{ runner.os == 'Linux' }}
|
||||
@@ -68,7 +68,7 @@ runs:
|
||||
build_args+=(-p)
|
||||
fi
|
||||
|
||||
${{ inputs.workingDirectory }}/.github/scripts/build-linux.sh "${build_args[@]}"
|
||||
${{ inputs.workingDirectory }}/.github/scripts/build-linux.sh -d ${{ env.DEP_DIR }} "${build_args[@]}"
|
||||
|
||||
- name: Run Windows Build
|
||||
if: ${{ runner.os == 'Windows' }}
|
||||
@@ -86,4 +86,4 @@ runs:
|
||||
}
|
||||
}
|
||||
|
||||
${{ inputs.workingDirectory }}/.github/scripts/Build-Windows.ps1 @BuildArgs
|
||||
${{ inputs.workingDirectory }}/.github/scripts/Build-Windows.ps1 -ADVSSDepName ${{ env.DEP_DIR }} @BuildArgs
|
||||
|
||||
1
.github/scripts/.Wingetfile
vendored
1
.github/scripts/.Wingetfile
vendored
@@ -1,3 +1,4 @@
|
||||
package '7zip.7zip', path: '7-zip', bin: '7z'
|
||||
package 'cmake', path: 'Cmake\bin', bin: 'cmake'
|
||||
package 'innosetup', path: 'Inno Setup 6', bin: 'iscc'
|
||||
package 'OpenSSL', path: 'OpenSSL', bin: 'openssl'
|
||||
|
||||
324
.github/scripts/.build-deps.zsh
vendored
Executable file
324
.github/scripts/.build-deps.zsh
vendored
Executable file
@@ -0,0 +1,324 @@
|
||||
#!/usr/bin/env zsh
|
||||
|
||||
builtin emulate -L zsh
|
||||
setopt EXTENDED_GLOB
|
||||
setopt PUSHD_SILENT
|
||||
setopt ERR_EXIT
|
||||
setopt ERR_RETURN
|
||||
setopt NO_UNSET
|
||||
setopt PIPE_FAIL
|
||||
setopt NO_AUTO_PUSHD
|
||||
setopt NO_PUSHD_IGNORE_DUPS
|
||||
setopt FUNCTION_ARGZERO
|
||||
|
||||
## Enable for script debugging
|
||||
# setopt WARN_CREATE_GLOBAL
|
||||
# setopt WARN_NESTED_VAR
|
||||
# setopt XTRACE
|
||||
|
||||
autoload -Uz is-at-least && if ! is-at-least 5.2; then
|
||||
print -u2 -PR "%F{1}${funcstack[1]##*/}:%f Running on Zsh version %B${ZSH_VERSION}%b, but Zsh %B5.2%b is the minimum supported version. Upgrade Zsh to fix this issue."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
_trap_error() {
|
||||
print -u2 -PR '%F{1} ✖︎ script execution error%f'
|
||||
print -PR -e "
|
||||
Callstack:
|
||||
${(j:\n :)funcfiletrace}
|
||||
"
|
||||
exit 2
|
||||
}
|
||||
|
||||
build() {
|
||||
if (( ! ${+SCRIPT_HOME} )) typeset -g SCRIPT_HOME=${ZSH_ARGZERO:A:h}
|
||||
local host_os=${${(s:-:)ZSH_ARGZERO:t:r}[3]}
|
||||
local target="${host_os}-${CPUTYPE}"
|
||||
local project_root=${SCRIPT_HOME:A:h:h}
|
||||
local buildspec_file="${project_root}/buildspec.json"
|
||||
|
||||
trap '_trap_error' ZERR
|
||||
|
||||
fpath=("${SCRIPT_HOME}/utils.zsh" ${fpath})
|
||||
autoload -Uz log_info log_error log_output set_loglevel check_${host_os} setup_${host_os} setup_obs setup_ccache
|
||||
|
||||
if [[ ! -r ${buildspec_file} ]] {
|
||||
log_error \
|
||||
'No buildspec.json found. Please create a build specification for your project.' \
|
||||
'A buildspec.json.template file is provided in the repository to get you started.'
|
||||
return 2
|
||||
}
|
||||
|
||||
typeset -g -a skips=()
|
||||
local -i _verbosity=1
|
||||
local -r _version='1.0.0'
|
||||
local -r -a _valid_targets=(
|
||||
macos-x86_64
|
||||
macos-arm64
|
||||
macos-universal
|
||||
linux-x86_64
|
||||
)
|
||||
local -r -a _valid_configs=(Debug RelWithDebInfo Release MinSizeRel)
|
||||
if [[ ${host_os} == 'macos' ]] {
|
||||
local -r -a _valid_generators=(Xcode Ninja 'Unix Makefiles')
|
||||
local generator="${${CI:+Ninja}:-Xcode}"
|
||||
} else {
|
||||
local -r -a _valid_generators=(Ninja 'Unix Makefiles')
|
||||
local generator='Ninja'
|
||||
}
|
||||
local -r _usage="
|
||||
Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
||||
|
||||
%BOptions%b:
|
||||
|
||||
%F{yellow} Build configuration options%f
|
||||
-----------------------------------------------------------------------------
|
||||
%B-t | --target%b Specify target - default: %B%F{green}${host_os}-${CPUTYPE}%f%b
|
||||
%B-c | --config%b Build configuration - default: %B%F{green}RelWithDebInfo%f%b
|
||||
%B-o | --out%b Output directory - default: %B%F{green}RelWithDebInfo%f%b
|
||||
%B--generator%b Specify build system to generate - default: %B%F{green}Ninja%f%b
|
||||
Available generators:
|
||||
- Ninja
|
||||
- Unix Makefiles
|
||||
- Xcode (macOS only)
|
||||
|
||||
%F{yellow} Output options%f
|
||||
-----------------------------------------------------------------------------
|
||||
%B-q | --quiet%b Quiet (error output only)
|
||||
%B-v | --verbose%b Verbose (more detailed output)
|
||||
%B--skip-[all|build|deps|unpack]%b Skip all|building OBS|checking for dependencies|unpacking dependencies
|
||||
%B--debug%b Debug (very detailed and added output)
|
||||
|
||||
%F{yellow} General options%f
|
||||
-----------------------------------------------------------------------------
|
||||
%B-h | --help%b Print this usage help
|
||||
%B-V | --version%b Print script version information"
|
||||
|
||||
local -a args
|
||||
while (( # )) {
|
||||
case ${1} {
|
||||
-t|--target|-c|--config|--generator)
|
||||
if (( # == 1 )) || [[ ${2:0:1} == '-' ]] {
|
||||
log_error "Missing value for option %B${1}%b"
|
||||
log_output ${_usage}
|
||||
exit 2
|
||||
}
|
||||
;;
|
||||
}
|
||||
case ${1} {
|
||||
--)
|
||||
shift
|
||||
args+=($@)
|
||||
break
|
||||
;;
|
||||
-t|--target)
|
||||
if (( ! ${_valid_targets[(Ie)${2}]} )) {
|
||||
log_error "Invalid value %B${2}%b for option %B${1}%b"
|
||||
log_output ${_usage}
|
||||
exit 2
|
||||
}
|
||||
target=${2}
|
||||
shift 2
|
||||
;;
|
||||
-c|--config)
|
||||
if (( ! ${_valid_configs[(Ie)${2}]} )) {
|
||||
log_error "Invalid value %B${2}%b for option %B${1}%b"
|
||||
log_output ${_usage}
|
||||
exit 2
|
||||
}
|
||||
BUILD_CONFIG=${2}
|
||||
shift 2
|
||||
;;
|
||||
-o|--out)
|
||||
OUT_DIR="${2}"
|
||||
shift 2
|
||||
;;
|
||||
-q|--quiet) (( _verbosity -= 1 )) || true; shift ;;
|
||||
-v|--verbose) (( _verbosity += 1 )); shift ;;
|
||||
-h|--help) log_output ${_usage}; exit 0 ;;
|
||||
-V|--version) print -Pr "${_version}"; exit 0 ;;
|
||||
--debug) _verbosity=3; shift ;;
|
||||
--generator)
|
||||
if (( ! ${_valid_generators[(Ie)${2}]} )) {
|
||||
log_error "Invalid value %B${2}%b for option %B${1}%b"
|
||||
log_output ${_usage}
|
||||
exit 2
|
||||
}
|
||||
generator=${2}
|
||||
shift 2
|
||||
;;
|
||||
--skip-*)
|
||||
local _skip="${${(s:-:)1}[-1]}"
|
||||
local _check=(all deps unpack build)
|
||||
(( ${_check[(Ie)${_skip}]} )) || log_warning "Invalid skip mode %B${_skip}%b supplied"
|
||||
typeset -g -a skips=(${skips} ${_skip})
|
||||
shift
|
||||
;;
|
||||
*) log_error "Unknown option: %B${1}%b"; log_output ${_usage}; exit 2 ;;
|
||||
}
|
||||
}
|
||||
|
||||
set -- ${(@)args}
|
||||
set_loglevel ${_verbosity}
|
||||
|
||||
check_${host_os}
|
||||
setup_ccache
|
||||
|
||||
typeset -g QT_VERSION
|
||||
typeset -g DEPLOYMENT_TARGET
|
||||
typeset -g OBS_DEPS_VERSION
|
||||
setup_${host_os}
|
||||
|
||||
local product_name
|
||||
local product_version
|
||||
local git_tag="$(git describe --tags)"
|
||||
|
||||
read -r product_name product_version <<< \
|
||||
"$(jq -r '. | {name, version} | join(" ")' ${buildspec_file})"
|
||||
|
||||
if [[ "${git_tag}" =~ '^([0-9]+\.){0,2}(\*|[0-9]+)$' ]] {
|
||||
log_info "Using git tag as version identifier '${git_tag}'"
|
||||
product_version="${git_tag}"
|
||||
} else {
|
||||
log_info "Using buildspec.json version identifier '${product_version}'"
|
||||
}
|
||||
|
||||
if [[ -z "${OUT_DIR}" ]] {
|
||||
OUT_DIR="advss-build-dependencies"
|
||||
}
|
||||
mkdir -p "${project_root}/../${OUT_DIR}"
|
||||
local advss_dep_path="$(realpath ${project_root}/../${OUT_DIR})"
|
||||
local _plugin_deps="${project_root:h}/obs-build-dependencies/plugin-deps-${OBS_DEPS_VERSION}-qt${QT_VERSION}-${target##*-}"
|
||||
|
||||
case ${host_os} {
|
||||
macos)
|
||||
local opencv_dir="${project_root}/deps/opencv"
|
||||
local opencv_build_dir="${opencv_dir}/build_${target##*-}"
|
||||
|
||||
local -a opencv_cmake_args=(
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DBUILD_LIST=core,imgproc,objdetect
|
||||
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
|
||||
-DCMAKE_PREFIX_PATH="${advss_dep_path};${_plugin_deps}"
|
||||
-DCMAKE_INSTALL_PREFIX="${advss_dep_path}"
|
||||
)
|
||||
|
||||
if [ "${target}" != "macos-x86_64" ]; then
|
||||
opencv_cmake_args+=(-DWITH_IPP=OFF)
|
||||
fi
|
||||
|
||||
pushd ${opencv_dir}
|
||||
log_info "Configure OpenCV ..."
|
||||
cmake -S . -B ${opencv_build_dir} -G ${generator} ${opencv_cmake_args}
|
||||
|
||||
log_info "Building OpenCV ..."
|
||||
cmake --build ${opencv_build_dir} --config Release
|
||||
|
||||
log_info "Installing OpenCV..."
|
||||
cmake --install ${opencv_build_dir} --prefix "${advss_dep_path}" --config Release || true
|
||||
popd
|
||||
|
||||
local leptonica_dir="${project_root}/deps/leptonica"
|
||||
local leptonica_build_dir="${leptonica_dir}/build_${target##*-}"
|
||||
|
||||
local -a leptonica_cmake_args=(
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
|
||||
-DSW_BUILD=OFF
|
||||
-DOPENJPEG_SUPPORT=OFF
|
||||
-DLIBWEBP_SUPPORT=OFF
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_GIF=TRUE
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_JPEG=TRUE
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_TIFF=TRUE
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_PNG=TRUE
|
||||
-DCMAKE_PREFIX_PATH="${advss_dep_path};${_plugin_deps}"
|
||||
-DCMAKE_INSTALL_PREFIX="${advss_dep_path}"
|
||||
)
|
||||
|
||||
pushd ${leptonica_dir}
|
||||
log_info "Configure Leptonica ..."
|
||||
cmake -S . -B ${leptonica_build_dir} -G ${generator} ${leptonica_cmake_args}
|
||||
|
||||
log_info "Building Leptonica ..."
|
||||
cmake --build ${leptonica_build_dir} --config Release
|
||||
|
||||
log_info "Installing Leptonica..."
|
||||
# Workaround for "unknown file attribute: H" errors when running install
|
||||
cmake --install ${leptonica_build_dir} --prefix "${advss_dep_path}" --config Release || :
|
||||
popd
|
||||
|
||||
local tesseract_dir="${project_root}/deps/tesseract"
|
||||
local tesseract_build_dir="${tesseract_dir}/build_${target##*-}"
|
||||
|
||||
local -a tesseract_cmake_args=(
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
|
||||
-DSW_BUILD=OFF
|
||||
-DBUILD_TRAINING_TOOLS=OFF
|
||||
-DCMAKE_PREFIX_PATH="${advss_dep_path};${_plugin_deps}"
|
||||
-DCMAKE_INSTALL_PREFIX="${advss_dep_path}"
|
||||
)
|
||||
|
||||
if [ "${target}" != "macos-x86_64" ]; then
|
||||
tesseract_cmake_args+=(
|
||||
-DCMAKE_SYSTEM_PROCESSOR=aarch64
|
||||
-DHAVE_AVX=FALSE
|
||||
-DHAVE_AVX2=FALSE
|
||||
-DHAVE_AVX512F=FALSE
|
||||
-DHAVE_FMA=FALSE
|
||||
-DHAVE_SSE4_1=FALSE
|
||||
-DHAVE_NEON=TRUE
|
||||
)
|
||||
sed -i'.original' 's/HAVE_NEON FALSE/HAVE_NEON TRUE/g' "${tesseract_dir}/CMakeLists.txt"
|
||||
fi
|
||||
|
||||
pushd ${tesseract_dir}
|
||||
log_info "Configure Tesseract ..."
|
||||
cmake -S . -B ${tesseract_build_dir} -G ${generator} ${tesseract_cmake_args}
|
||||
|
||||
log_info "Building Tesseract ..."
|
||||
cmake --build ${tesseract_build_dir} --config Release
|
||||
|
||||
log_info "Installing Tesseract..."
|
||||
cmake --install ${tesseract_build_dir} --prefix "${advss_dep_path}" --config Release
|
||||
popd
|
||||
|
||||
pushd ${advss_dep_path}
|
||||
log_info "Prepare openssl ..."
|
||||
rm -rf openssl
|
||||
git clone git://git.openssl.org/openssl.git --branch openssl-3.1.2 --depth 1
|
||||
mv openssl openssl_x86
|
||||
cp -r openssl_x86 openssl_arm
|
||||
|
||||
log_info "Building openssl x86 ..."
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.9
|
||||
cd openssl_x86
|
||||
./Configure darwin64-x86_64-cc shared
|
||||
make
|
||||
|
||||
log_info "Building openssl arm ..."
|
||||
export MACOSX_DEPLOYMENT_TARGET=10.15
|
||||
cd ../openssl_arm
|
||||
./Configure enable-rc5 zlib darwin64-arm64-cc no-asm
|
||||
make
|
||||
|
||||
log_info "Combine arm and x86 openssl binaries ..."
|
||||
cd ..
|
||||
mkdir openssl-combined
|
||||
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..."
|
||||
mv openssl_x86 openssl
|
||||
rm -rf openssl_arm
|
||||
;;
|
||||
linux)
|
||||
# Nothing to do for now
|
||||
;;
|
||||
}
|
||||
}
|
||||
|
||||
build ${@}
|
||||
112
.github/scripts/.build.zsh
vendored
112
.github/scripts/.build.zsh
vendored
@@ -36,6 +36,7 @@ build() {
|
||||
local target="${host_os}-${CPUTYPE}"
|
||||
local project_root=${SCRIPT_HOME:A:h:h}
|
||||
local buildspec_file="${project_root}/buildspec.json"
|
||||
local dep_dir=""
|
||||
|
||||
trap '_trap_error' ZERR
|
||||
|
||||
@@ -77,6 +78,7 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
||||
%B-c | --config%b Build configuration - default: %B%F{green}RelWithDebInfo%f%b
|
||||
%B-s | --codesign%b Enable codesigning (macOS only)
|
||||
%B-p | --portable%b Enable portable mode (Linux only)
|
||||
%B-d | --dep%b Dependency directory name - default: %B%F{green}advss-build-dependencies%f%b
|
||||
%B--generator%b Specify build system to generate - default: %B%F{green}Ninja%f%b
|
||||
Available generators:
|
||||
- Ninja
|
||||
@@ -130,6 +132,10 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
||||
BUILD_CONFIG=${2}
|
||||
shift 2
|
||||
;;
|
||||
-d|--dep)
|
||||
dep_dir="${2}"
|
||||
shift 2
|
||||
;;
|
||||
-s|--codesign) CODESIGN=1; shift ;;
|
||||
-p|--portable) typeset -g PORTABLE=1; shift ;;
|
||||
-q|--quiet) (( _verbosity -= 1 )) || true; shift ;;
|
||||
@@ -168,6 +174,15 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
||||
typeset -g OBS_DEPS_VERSION
|
||||
setup_${host_os}
|
||||
|
||||
local advss_deps_path
|
||||
if [[ -z "${dep_dir}" ]] {
|
||||
log_info "Building advss deps ..."
|
||||
dep_dir="advss-build-dependencies"
|
||||
${SCRIPT_HOME}/build-deps-${host_os}.zsh -c "${BUILD_CONFIG:-RelWithDebInfo}" -t "${target}" --generator "${generator}" -o "${dep_dir}" --skip-deps --skip-unpack
|
||||
}
|
||||
advss_deps_path=$(realpath ${project_root}/../${dep_dir})
|
||||
log_info "Using advss deps at $advss_deps_path ..."
|
||||
|
||||
local product_name
|
||||
local product_version
|
||||
local git_tag="$(git describe --tags)"
|
||||
@@ -187,96 +202,6 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
||||
sed -i '' \
|
||||
"s/project(\(.*\) VERSION \(.*\))/project(${product_name} VERSION ${product_version})/" \
|
||||
"${project_root}/CMakeLists.txt"
|
||||
|
||||
local opencv_dir="${project_root}/deps/opencv"
|
||||
local opencv_build_dir="${opencv_dir}/build_${target##*-}"
|
||||
|
||||
local -a opencv_cmake_args=(
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DBUILD_LIST=core,imgproc,objdetect
|
||||
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
|
||||
)
|
||||
|
||||
if [ "${target}" != "macos-x86_64" ]; then
|
||||
opencv_cmake_args+=(-DWITH_IPP=OFF)
|
||||
fi
|
||||
|
||||
pushd ${opencv_dir}
|
||||
log_info "Configure OpenCV ..."
|
||||
cmake -S . -B ${opencv_build_dir} -G ${generator} ${opencv_cmake_args}
|
||||
|
||||
log_info "Building OpenCV ..."
|
||||
cmake --build ${opencv_build_dir} --config Release
|
||||
|
||||
log_info "Installing OpenCV..."
|
||||
cmake --install ${opencv_build_dir} --config Release || true
|
||||
popd
|
||||
|
||||
local leptonica_dir="${project_root}/deps/leptonica"
|
||||
local leptonica_build_dir="${leptonica_dir}/build_${target##*-}"
|
||||
|
||||
local -a leptonica_cmake_args=(
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
|
||||
-DSW_BUILD=OFF
|
||||
-DOPENJPEG_SUPPORT=OFF
|
||||
-DLIBWEBP_SUPPORT=OFF
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_GIF=TRUE
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_JPEG=TRUE
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_TIFF=TRUE
|
||||
-DCMAKE_DISABLE_FIND_PACKAGE_PNG=TRUE
|
||||
)
|
||||
|
||||
pushd ${leptonica_dir}
|
||||
log_info "Configure Leptonica ..."
|
||||
cmake -S . -B ${leptonica_build_dir} -G ${generator} ${leptonica_cmake_args}
|
||||
|
||||
log_info "Building Leptonica ..."
|
||||
cmake --build ${leptonica_build_dir} --config Release
|
||||
|
||||
log_info "Installing Leptonica..."
|
||||
# Workaround for "unknown file attribute: H" errors when running install
|
||||
cmake --install ${leptonica_build_dir} --config Release || :
|
||||
popd
|
||||
|
||||
local tesseract_dir="${project_root}/deps/tesseract"
|
||||
local tesseract_build_dir="${tesseract_dir}/build_${target##*-}"
|
||||
|
||||
local -a tesseract_cmake_args=(
|
||||
-DCMAKE_BUILD_TYPE=Release
|
||||
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
|
||||
-DSW_BUILD=OFF
|
||||
-DBUILD_TRAINING_TOOLS=OFF
|
||||
)
|
||||
|
||||
if [ "${target}" != "macos-x86_64" ]; then
|
||||
tesseract_cmake_args+=(
|
||||
-DCMAKE_SYSTEM_PROCESSOR=aarch64
|
||||
-DHAVE_AVX=FALSE
|
||||
-DHAVE_AVX2=FALSE
|
||||
-DHAVE_AVX512F=FALSE
|
||||
-DHAVE_FMA=FALSE
|
||||
-DHAVE_SSE4_1=FALSE
|
||||
-DHAVE_NEON=TRUE
|
||||
)
|
||||
sed -i'.original' 's/HAVE_NEON FALSE/HAVE_NEON TRUE/g' "${tesseract_dir}/CMakeLists.txt"
|
||||
fi
|
||||
|
||||
pushd ${tesseract_dir}
|
||||
log_info "Configure Tesseract ..."
|
||||
cmake -S . -B ${tesseract_build_dir} -G ${generator} ${tesseract_cmake_args}
|
||||
|
||||
log_info "Building Tesseract ..."
|
||||
#cmake --build ${tesseract_build_dir} --config Release --target libtesseract
|
||||
cmake --build ${tesseract_build_dir} --config Release
|
||||
|
||||
log_info "Installing Tesseract..."
|
||||
#cmake --install ${tesseract_build_dir} --config Release --component libtesseract
|
||||
cmake --install ${tesseract_build_dir} --config Release
|
||||
popd
|
||||
;;
|
||||
linux)
|
||||
sed -i'' \
|
||||
@@ -295,7 +220,7 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
||||
local -a cmake_args=(
|
||||
-DCMAKE_BUILD_TYPE=${BUILD_CONFIG:-RelWithDebInfo}
|
||||
-DQT_VERSION=${QT_VERSION}
|
||||
-DCMAKE_PREFIX_PATH="${_plugin_deps}"
|
||||
-DCMAKE_PREFIX_PATH="${_plugin_deps};${advss_deps_path}"
|
||||
)
|
||||
|
||||
if (( _loglevel == 0 )) cmake_args+=(-Wno_deprecated -Wno-dev --log-level=ERROR)
|
||||
@@ -312,12 +237,17 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
||||
|
||||
num_procs=$(( $(sysctl -n hw.ncpu) + 1 ))
|
||||
|
||||
local openssl_lib_dir="${advss_deps_path}/openssl-combined/"
|
||||
local openssl_include_dir="${advss_deps_path}/openssl/include"
|
||||
|
||||
cmake_args+=(
|
||||
-DCMAKE_FRAMEWORK_PATH="${_plugin_deps}/Frameworks"
|
||||
-DCMAKE_OSX_ARCHITECTURES=${${target##*-}//universal/x86_64;arm64}
|
||||
-DCMAKE_OSX_DEPLOYMENT_TARGET=${DEPLOYMENT_TARGET:-10.15}
|
||||
-DOBS_CODESIGN_LINKER=ON
|
||||
-DOBS_BUNDLE_CODESIGN_IDENTITY="${CODESIGN_IDENT:--}"
|
||||
-DOPENSSL_INCLUDE_DIR="${openssl_include_dir}"
|
||||
-DOPENSSL_LIBRARIES="${openssl_lib_dir}/libcrypto.a;${openssl_lib_dir}/libssl.a"
|
||||
)
|
||||
|
||||
;;
|
||||
|
||||
172
.github/scripts/Build-Deps-Windows.ps1
vendored
Normal file
172
.github/scripts/Build-Deps-Windows.ps1
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[ValidateSet('Debug', 'RelWithDebInfo', 'Release', 'MinSizeRel')]
|
||||
[string] $Configuration = 'RelWithDebInfo',
|
||||
[ValidateSet('x86', 'x64')]
|
||||
[string] $Target,
|
||||
[ValidateSet('Visual Studio 17 2022', 'Visual Studio 16 2019')]
|
||||
[string] $CMakeGenerator,
|
||||
[string] $OutDirName,
|
||||
[switch] $SkipDeps,
|
||||
[switch] $SkipUnpack
|
||||
)
|
||||
|
||||
$ErrorActionPreference = 'Stop'
|
||||
|
||||
if ( $DebugPreference -eq 'Continue' ) {
|
||||
$VerbosePreference = 'Continue'
|
||||
$InformationPreference = 'Continue'
|
||||
}
|
||||
|
||||
if ( $PSVersionTable.PSVersion -lt '7.0.0' ) {
|
||||
Write-Warning 'The obs-deps PowerShell build script requires PowerShell Core 7. Install or upgrade your PowerShell version: https://aka.ms/pscore6'
|
||||
exit 2
|
||||
}
|
||||
|
||||
function Build {
|
||||
trap {
|
||||
Pop-Location -Stack BuildTemp -ErrorAction 'SilentlyContinue'
|
||||
Write-Error $_
|
||||
exit 2
|
||||
}
|
||||
|
||||
$ScriptHome = $PSScriptRoot
|
||||
$ProjectRoot = Resolve-Path -Path "$PSScriptRoot/../.."
|
||||
$BuildSpecFile = "${ProjectRoot}/buildspec.json"
|
||||
|
||||
$UtilityFunctions = Get-ChildItem -Path $PSScriptRoot/utils.pwsh/*.ps1 -Recurse
|
||||
|
||||
foreach ($Utility in $UtilityFunctions) {
|
||||
Write-Debug "Loading $($Utility.FullName)"
|
||||
. $Utility.FullName
|
||||
}
|
||||
|
||||
$BuildSpec = Get-Content -Path ${BuildSpecFile} -Raw | ConvertFrom-Json
|
||||
$ProductName = $BuildSpec.name
|
||||
$ProductVersion = $BuildSpec.version
|
||||
|
||||
$script:VisualStudioVersion = ''
|
||||
$script:PlatformSDK = '10.0.18363.657'
|
||||
|
||||
Setup-Host
|
||||
|
||||
if ( $CmakeGenerator -eq '' ) {
|
||||
$CmakeGenerator = $script:VisualStudioVersion
|
||||
}
|
||||
|
||||
$DepsPath = "plugin-deps-${script:DepsVersion}-*-${script:Target}"
|
||||
$OBSDepPath = "$(Resolve-Path -Path ${ProjectRoot}/../obs-build-dependencies/${DepsPath})"
|
||||
|
||||
if ( $OutDirName -eq '' ) {
|
||||
$OutDirName = "advss-build-dependencies"
|
||||
}
|
||||
New-Item -ItemType Directory -Force -Path ${ProjectRoot}/../${OutDirName}
|
||||
|
||||
$ADVSSDepPath = "$(Resolve-Path -Path ${ProjectRoot}/../${OutDirName})"
|
||||
|
||||
$OpenCVPath = "${ProjectRoot}/deps/opencv"
|
||||
$OpenCVBuildPath = "${OpenCVPath}/build"
|
||||
|
||||
Push-Location -Stack BuildOpenCVTemp
|
||||
Ensure-Location $ProjectRoot
|
||||
|
||||
$OpenCVCmakeArgs = @(
|
||||
'-G', $CmakeGenerator
|
||||
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
|
||||
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
|
||||
"-DCMAKE_BUILD_TYPE=Release"
|
||||
"-DCMAKE_PREFIX_PATH:PATH=${OBSDepPath}"
|
||||
"-DCMAKE_INSTALL_PREFIX:PATH=${ADVSSDepPath}"
|
||||
"-DBUILD_LIST=core,imgproc,objdetect"
|
||||
)
|
||||
|
||||
Log-Information "Configuring OpenCV..."
|
||||
Invoke-External cmake -S ${OpenCVPath} -B ${OpenCVBuildPath} @OpenCVCmakeArgs
|
||||
|
||||
$OpenCVCmakeArgs = @(
|
||||
'--config', "Release"
|
||||
)
|
||||
|
||||
if ( $VerbosePreference -eq 'Continue' ) {
|
||||
$OpenCVCmakeArgs += ('--verbose')
|
||||
}
|
||||
|
||||
Log-Information "Building OpenCV..."
|
||||
Invoke-External cmake --build "${OpenCVBuildPath}" @OpenCVCmakeArgs
|
||||
Log-Information "Install OpenCV}..."
|
||||
Invoke-External cmake --install "${OpenCVBuildPath}" --prefix "${ADVSSDepPath}" @OpenCVCmakeArgs
|
||||
|
||||
$LeptonicaPath = "${ProjectRoot}/deps/leptonica"
|
||||
$LeptonicaBuildPath = "${LeptonicaPath}/build"
|
||||
|
||||
Push-Location -Stack BuildLeptonicaTemp
|
||||
Ensure-Location $ProjectRoot
|
||||
|
||||
$LeptonicaCmakeArgs = @(
|
||||
'-G', $CmakeGenerator
|
||||
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
|
||||
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
|
||||
"-DCMAKE_BUILD_TYPE=${Configuration}"
|
||||
"-DCMAKE_PREFIX_PATH:PATH=${OBSDepPath}"
|
||||
"-DCMAKE_INSTALL_PREFIX:PATH=${ADVSSDepPath}"
|
||||
"-DSW_BUILD=OFF"
|
||||
"-DLIBWEBP_SUPPORT=OFF"
|
||||
)
|
||||
|
||||
Log-Information "Configuring leptonica..."
|
||||
Invoke-External cmake -S ${LeptonicaPath} -B ${LeptonicaBuildPath} @LeptonicaCmakeArgs
|
||||
|
||||
$LeptonicaCmakeArgs = @(
|
||||
'--config', "${Configuration}"
|
||||
)
|
||||
|
||||
if ( $VerbosePreference -eq 'Continue' ) {
|
||||
$LeptonicaCmakeArgs += ('--verbose')
|
||||
}
|
||||
|
||||
Log-Information "Building leptonica..."
|
||||
Invoke-External cmake --build "${LeptonicaBuildPath}" @LeptonicaCmakeArgs
|
||||
|
||||
Log-Information "Install leptonica..."
|
||||
Invoke-External cmake --install "${LeptonicaBuildPath}" --prefix "${ADVSSDepPath}" @LeptonicaCmakeArgs
|
||||
|
||||
Push-Location -Stack BuildTesseractTemp
|
||||
Ensure-Location $ProjectRoot
|
||||
|
||||
$TesseractPath = "${ProjectRoot}/deps/tesseract"
|
||||
$TesseractBuildPath = "${TesseractPath}/build"
|
||||
|
||||
# Explicitly disable PkgConfig and tiff as it will lead build errors
|
||||
$TesseractCmakeArgs = @(
|
||||
'-G', $CmakeGenerator
|
||||
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
|
||||
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
|
||||
"-DCMAKE_BUILD_TYPE=${Configuration}"
|
||||
"-DCMAKE_PREFIX_PATH:PATH=${OBSDepPath}"
|
||||
"-DCMAKE_INSTALL_PREFIX:PATH=${ADVSSDepPath}"
|
||||
"-DSW_BUILD=OFF"
|
||||
"-DDISABLE_CURL=ON"
|
||||
"-DBUILD_TRAINING_TOOLS=OFF"
|
||||
"-DCMAKE_DISABLE_FIND_PACKAGE_TIFF=TRUE"
|
||||
"-DCMAKE_DISABLE_FIND_PACKAGE_PkgConfig=TRUE"
|
||||
)
|
||||
|
||||
Log-Information "Configuring tesseract..."
|
||||
Invoke-External cmake -S ${TesseractPath} -B ${TesseractBuildPath} @TesseractCmakeArgs
|
||||
|
||||
$TesseractCmakeArgs = @(
|
||||
'--config', "${Configuration}"
|
||||
)
|
||||
|
||||
if ( $VerbosePreference -eq 'Continue' ) {
|
||||
$TesseractCmakeArgs += ('--verbose')
|
||||
}
|
||||
|
||||
Log-Information "Building tesseract..."
|
||||
Invoke-External cmake --build "${TesseractBuildPath}" @TesseractCmakeArgs
|
||||
|
||||
Log-Information "Install tesseract..."
|
||||
Invoke-External cmake --install "${TesseractBuildPath}" --prefix "${ADVSSDepPath}" @TesseractCmakeArgs
|
||||
}
|
||||
|
||||
Build
|
||||
116
.github/scripts/Build-Windows.ps1
vendored
116
.github/scripts/Build-Windows.ps1
vendored
@@ -6,6 +6,7 @@ param(
|
||||
[string] $Target,
|
||||
[ValidateSet('Visual Studio 17 2022', 'Visual Studio 16 2019')]
|
||||
[string] $CMakeGenerator,
|
||||
[string] $ADVSSDepName,
|
||||
[switch] $SkipAll,
|
||||
[switch] $SkipBuild,
|
||||
[switch] $SkipDeps,
|
||||
@@ -60,116 +61,17 @@ function Build {
|
||||
$DepsPath = "plugin-deps-${script:DepsVersion}-qt${script:QtVersion}-${script:Target}"
|
||||
$DepInstallPath = "$(Resolve-Path -Path ${ProjectRoot}/../obs-build-dependencies/${DepsPath})"
|
||||
|
||||
$OpenCVPath = "${ProjectRoot}/deps/opencv"
|
||||
$OpenCVBuildPath = "${OpenCVPath}/build"
|
||||
|
||||
Push-Location -Stack BuildOpenCVTemp
|
||||
if ( ! ( ( $SkipAll ) -or ( $SkipBuild ) ) ) {
|
||||
Ensure-Location $ProjectRoot
|
||||
|
||||
$OpenCVCmakeArgs = @(
|
||||
'-G', $CmakeGenerator
|
||||
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
|
||||
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
|
||||
"-DCMAKE_BUILD_TYPE=Release"
|
||||
"-DCMAKE_PREFIX_PATH:PATH=${DepInstallPath}"
|
||||
"-DBUILD_LIST=core,imgproc,objdetect"
|
||||
)
|
||||
|
||||
Log-Information "Configuring OpenCV..."
|
||||
Invoke-External cmake -S ${OpenCVPath} -B ${OpenCVBuildPath} @OpenCVCmakeArgs
|
||||
|
||||
$OpenCVCmakeArgs = @(
|
||||
'--config', "Release"
|
||||
)
|
||||
|
||||
if ( $VerbosePreference -eq 'Continue' ) {
|
||||
$OpenCVCmakeArgs += ('--verbose')
|
||||
}
|
||||
|
||||
Log-Information "Building OpenCV..."
|
||||
Invoke-External cmake --build "${OpenCVBuildPath}" @OpenCVCmakeArgs
|
||||
if ( $ADVSSDepName -eq '' ) {
|
||||
Log-Information "Building advss deps ..."
|
||||
$ADVSSDepName = "advss-build-dependencies"
|
||||
invoke-expression -Command "$PSScriptRoot/Build-Deps-Windows.ps1 -Configuration $Configuration -Target $Target -CMakeGenerator `"$CMakeGenerator`" -OutDirName $ADVSSDepName -SkipDeps -SkipUnpack"
|
||||
}
|
||||
Log-Information "Install OpenCV}..."
|
||||
Invoke-External cmake --install "${OpenCVBuildPath}" --prefix "${DepInstallPath}" @OpenCVCmakeArgs
|
||||
|
||||
$LeptonicaPath = "${ProjectRoot}/deps/leptonica"
|
||||
$LeptonicaBuildPath = "${LeptonicaPath}/build"
|
||||
|
||||
Push-Location -Stack BuildLeptonicaTemp
|
||||
if ( ! ( ( $SkipAll ) -or ( $SkipBuild ) ) ) {
|
||||
Ensure-Location $ProjectRoot
|
||||
|
||||
$LeptonicaCmakeArgs = @(
|
||||
'-G', $CmakeGenerator
|
||||
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
|
||||
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
|
||||
"-DCMAKE_BUILD_TYPE=${Configuration}"
|
||||
"-DCMAKE_PREFIX_PATH:PATH=${DepInstallPath}"
|
||||
"-DCMAKE_INSTALL_PREFIX:PATH=${DepInstallPath}"
|
||||
"-DSW_BUILD=OFF"
|
||||
"-DLIBWEBP_SUPPORT=OFF"
|
||||
)
|
||||
|
||||
Log-Information "Configuring leptonica..."
|
||||
Invoke-External cmake -S ${LeptonicaPath} -B ${LeptonicaBuildPath} @LeptonicaCmakeArgs
|
||||
|
||||
$LeptonicaCmakeArgs = @(
|
||||
'--config', "${Configuration}"
|
||||
)
|
||||
|
||||
if ( $VerbosePreference -eq 'Continue' ) {
|
||||
$LeptonicaCmakeArgs += ('--verbose')
|
||||
}
|
||||
|
||||
Log-Information "Building leptonica..."
|
||||
Invoke-External cmake --build "${LeptonicaBuildPath}" @LeptonicaCmakeArgs
|
||||
}
|
||||
Log-Information "Install leptonica..."
|
||||
Invoke-External cmake --install "${LeptonicaBuildPath}" --prefix "${DepInstallPath}" @LeptonicaCmakeArgs
|
||||
|
||||
Push-Location -Stack BuildTesseractTemp
|
||||
if ( ! ( ( $SkipAll ) -or ( $SkipBuild ) ) ) {
|
||||
Ensure-Location $ProjectRoot
|
||||
|
||||
$TesseractPath = "${ProjectRoot}/deps/tesseract"
|
||||
$TesseractBuildPath = "${TesseractPath}/build"
|
||||
|
||||
# Explicitly disable PkgConfig and tiff as it will lead build errors
|
||||
$TesseractCmakeArgs = @(
|
||||
'-G', $CmakeGenerator
|
||||
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
|
||||
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
|
||||
"-DCMAKE_BUILD_TYPE=${Configuration}"
|
||||
"-DCMAKE_PREFIX_PATH:PATH=${DepInstallPath}"
|
||||
"-DCMAKE_INSTALL_PREFIX:PATH=${DepInstallPath}"
|
||||
"-DSW_BUILD=OFF"
|
||||
"-DDISABLE_CURL=ON"
|
||||
"-DBUILD_TRAINING_TOOLS=OFF"
|
||||
"-DCMAKE_DISABLE_FIND_PACKAGE_TIFF=TRUE"
|
||||
"-DCMAKE_DISABLE_FIND_PACKAGE_PkgConfig=TRUE"
|
||||
)
|
||||
|
||||
Log-Information "Configuring tesseract..."
|
||||
Invoke-External cmake -S ${TesseractPath} -B ${TesseractBuildPath} @TesseractCmakeArgs
|
||||
|
||||
$TesseractCmakeArgs = @(
|
||||
'--config', "${Configuration}"
|
||||
)
|
||||
|
||||
if ( $VerbosePreference -eq 'Continue' ) {
|
||||
$TesseractCmakeArgs += ('--verbose')
|
||||
}
|
||||
|
||||
Log-Information "Building tesseract..."
|
||||
Invoke-External cmake --build "${TesseractBuildPath}" @TesseractCmakeArgs
|
||||
}
|
||||
Log-Information "Install tesseract..."
|
||||
Invoke-External cmake --install "${TesseractBuildPath}" --prefix "${DepInstallPath}" @TesseractCmakeArgs
|
||||
$ADVSSDepPath = "$(Resolve-Path -Path ${ProjectRoot}/../${script:ADVSSDepName})"
|
||||
Log-Information "Using advss deps at $ADVSSDepPath ..."
|
||||
|
||||
(Get-Content -Path ${ProjectRoot}/CMakeLists.txt -Raw) `
|
||||
-replace "project\((.*) VERSION (.*)\)", "project(${ProductName} VERSION ${ProductVersion})" `
|
||||
| Out-File -Path ${ProjectRoot}/CMakeLists.txt
|
||||
| Out-File -Path ${ProjectRoot}/CMakeLists.txt -NoNewline
|
||||
|
||||
Setup-Obs
|
||||
|
||||
@@ -182,7 +84,7 @@ function Build {
|
||||
"-DCMAKE_SYSTEM_VERSION=${script:PlatformSDK}"
|
||||
"-DCMAKE_GENERATOR_PLATFORM=$(if (${script:Target} -eq "x86") { "Win32" } else { "x64" })"
|
||||
"-DCMAKE_BUILD_TYPE=${Configuration}"
|
||||
"-DCMAKE_PREFIX_PATH:PATH=${DepInstallPath}"
|
||||
"-DCMAKE_PREFIX_PATH:PATH=${DepInstallPath};${ADVSSDepPath}"
|
||||
"-DQT_VERSION=${script:QtVersion}"
|
||||
)
|
||||
|
||||
|
||||
13
.github/scripts/build-deps-linux.sh
vendored
Executable file
13
.github/scripts/build-deps-linux.sh
vendored
Executable file
@@ -0,0 +1,13 @@
|
||||
#!/bin/sh
|
||||
|
||||
if ! type zsh > /dev/null 2>&1; then
|
||||
echo ' => Installing script dependency Zsh.'
|
||||
|
||||
sudo apt-get -y update
|
||||
sudo apt-get -y install zsh
|
||||
fi
|
||||
|
||||
SCRIPT=$(readlink -f "${0}")
|
||||
SCRIPT_DIR=$(dirname "${SCRIPT}")
|
||||
|
||||
zsh ${SCRIPT_DIR}/build-deps-linux.zsh "${@}"
|
||||
1
.github/scripts/build-deps-linux.zsh
vendored
Symbolic link
1
.github/scripts/build-deps-linux.zsh
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
.build-deps.zsh
|
||||
1
.github/scripts/build-deps-macos.zsh
vendored
Symbolic link
1
.github/scripts/build-deps-macos.zsh
vendored
Symbolic link
@@ -0,0 +1 @@
|
||||
.build-deps.zsh
|
||||
2
.github/scripts/utils.zsh/check_packages
vendored
2
.github/scripts/utils.zsh/check_packages
vendored
@@ -24,7 +24,7 @@ if (( ! ${+commands[packagesbuild]} )) {
|
||||
pushd
|
||||
mkcd ${project_root:h}/obs-build-dependencies
|
||||
|
||||
local packages_url='http://s.sudre.free.fr/Software/files/Packages.dmg'
|
||||
local packages_url='https://web.archive.org/web/20230727054218/http://s.sudre.free.fr/Software/files/Packages.dmg'
|
||||
local packages_hash='6afdd25386295974dad8f078b8f1e41cabebd08e72d970bf92f707c7e48b16c9'
|
||||
|
||||
if [[ ! -f Packages.dmg ]] {
|
||||
|
||||
29
.github/workflows/main.yml
vendored
29
.github/workflows/main.yml
vendored
@@ -17,6 +17,7 @@ on:
|
||||
env:
|
||||
PLUGIN_NAME: SceneSwitcher
|
||||
LIB_NAME: advanced-scene-switcher
|
||||
DEP_DIR: advss-build-dependencies-1
|
||||
|
||||
jobs:
|
||||
clang_check:
|
||||
@@ -115,9 +116,6 @@ jobs:
|
||||
with:
|
||||
path: |
|
||||
${{ github.workspace }}/.ccache
|
||||
${{ github.workspace }}/plugin/deps/opencv/build_*
|
||||
${{ github.workspace }}/plugin/deps/leptonica/build_*
|
||||
${{ github.workspace }}/plugin/deps/tesseract/build*
|
||||
key: macos-${{ matrix.arch }}-ccache-plugin-${{ steps.setup.outputs.ccacheDate }}
|
||||
restore-keys: |
|
||||
macos-${{ matrix.arch }}-ccache-plugin-
|
||||
@@ -146,6 +144,13 @@ jobs:
|
||||
print "CODESIGN_IDENT=${{ secrets.MACOS_SIGNING_APPLICATION_IDENTITY }}" >> $GITHUB_ENV
|
||||
print "CODESIGN_IDENT_INSTALLER=${{ secrets.MACOS_SIGNING_INSTALLER_IDENTITY }}" >> $GITHUB_ENV
|
||||
|
||||
- name: Build Dependencies
|
||||
uses: ./plugin/.github/actions/build-dependencies
|
||||
with:
|
||||
workingDirectory: ${{ github.workspace }}/plugin
|
||||
target: ${{ matrix.arch }}
|
||||
config: RelWithDebInfo
|
||||
|
||||
- name: Build Plugin
|
||||
uses: ./plugin/.github/actions/build-plugin
|
||||
with:
|
||||
@@ -248,6 +253,13 @@ jobs:
|
||||
echo 'found=false' >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Build Dependencies
|
||||
uses: ./plugin/.github/actions/build-dependencies
|
||||
with:
|
||||
workingDirectory: ${{ github.workspace }}/plugin
|
||||
target: ${{ matrix.arch }}
|
||||
config: RelWithDebInfo
|
||||
|
||||
- name: Build Plugin
|
||||
uses: ./plugin/.github/actions/build-plugin
|
||||
with:
|
||||
@@ -329,9 +341,6 @@ jobs:
|
||||
with:
|
||||
path: |
|
||||
${{ github.workspace }}/.ccache
|
||||
${{ github.workspace }}/plugin/deps/opencv/build_*
|
||||
${{ github.workspace }}/plugin/deps/leptonica/build_*
|
||||
${{ github.workspace }}/plugin/deps/tesseract/build*
|
||||
key: windows-${{ matrix.arch }}-ccache-plugin-${{ steps.setup.outputs.ccacheDate }}
|
||||
restore-keys: |
|
||||
windows-${{ matrix.arch }}-ccache-plugin-
|
||||
@@ -357,6 +366,14 @@ jobs:
|
||||
|
||||
"found=$(([string]${LabelFound}).ToLower())" >> $env:GITHUB_OUTPUT
|
||||
|
||||
- name: Build Dependencies
|
||||
uses: ./plugin/.github/actions/build-dependencies
|
||||
with:
|
||||
workingDirectory: ${{ github.workspace }}/plugin
|
||||
target: ${{ matrix.arch }}
|
||||
config: RelWithDebInfo
|
||||
visualStudio: 'Visual Studio 17 2022'
|
||||
|
||||
- name: Build Plugin
|
||||
uses: ./plugin/.github/actions/build-plugin
|
||||
with:
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -91,6 +91,7 @@ Thumbs.db
|
||||
.settings
|
||||
.idea
|
||||
.metadata
|
||||
.vscode
|
||||
*.iml
|
||||
*.ipr
|
||||
*.sublime*
|
||||
|
||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -19,3 +19,9 @@
|
||||
[submodule "deps/libremidi"]
|
||||
path = deps/libremidi
|
||||
url = https://github.com/jcelerier/libremidi.git
|
||||
[submodule "deps/cpp-httplib"]
|
||||
path = deps/cpp-httplib
|
||||
url = https://github.com/yhirose/cpp-httplib.git
|
||||
[submodule "deps/json"]
|
||||
path = deps/json
|
||||
url = https://github.com/nlohmann/json.git
|
||||
|
||||
@@ -213,6 +213,8 @@ target_sources(
|
||||
src/macro-core/macro-condition-streaming.hpp
|
||||
src/macro-core/macro-condition-studio-mode.cpp
|
||||
src/macro-core/macro-condition-studio-mode.hpp
|
||||
src/macro-core/macro-condition-tempvar.cpp
|
||||
src/macro-core/macro-condition-tempvar.hpp
|
||||
src/macro-core/macro-condition-timer.cpp
|
||||
src/macro-core/macro-condition-timer.hpp
|
||||
src/macro-core/macro-condition-transition.cpp
|
||||
@@ -254,6 +256,7 @@ target_sources(
|
||||
src/utils/curl-helper.hpp
|
||||
src/utils/duration-control.cpp
|
||||
src/utils/duration-control.hpp
|
||||
src/utils/export-symbol-helper.hpp
|
||||
src/utils/item-selection-helpers.cpp
|
||||
src/utils/item-selection-helpers.hpp
|
||||
src/utils/log-helper.hpp
|
||||
@@ -267,6 +270,8 @@ target_sources(
|
||||
src/utils/macro-export-import-dialog.hpp
|
||||
src/utils/macro-list.cpp
|
||||
src/utils/macro-list.hpp
|
||||
src/utils/macro-run-button.cpp
|
||||
src/utils/macro-run-button.hpp
|
||||
src/utils/macro-segment-selection.cpp
|
||||
src/utils/macro-segment-selection.hpp
|
||||
src/utils/math-helpers.cpp
|
||||
@@ -304,6 +309,8 @@ target_sources(
|
||||
src/utils/slider-spinbox.hpp
|
||||
src/utils/source-selection.cpp
|
||||
src/utils/source-selection.hpp
|
||||
src/utils/source-setting.cpp
|
||||
src/utils/source-setting.hpp
|
||||
src/utils/string-list.cpp
|
||||
src/utils/string-list.hpp
|
||||
src/utils/striped-frame.cpp
|
||||
@@ -312,6 +319,8 @@ target_sources(
|
||||
src/utils/switch-button.hpp
|
||||
src/utils/sync-helper.cpp
|
||||
src/utils/sync-helper.hpp
|
||||
src/utils/temp-variable.cpp
|
||||
src/utils/temp-variable.hpp
|
||||
src/utils/transition-selection.cpp
|
||||
src/utils/transition-selection.hpp
|
||||
src/utils/utility.cpp
|
||||
@@ -375,6 +384,14 @@ target_include_directories(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/obs-websocket/lib"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/exprtk")
|
||||
|
||||
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/deps/json/CMakeLists.txt")
|
||||
add_subdirectory(deps/json)
|
||||
else()
|
||||
find_package(nlohmann_json REQUIRED)
|
||||
endif()
|
||||
target_link_libraries(${LIB_NAME} PUBLIC nlohmann_json::nlohmann_json)
|
||||
target_compile_definitions(${LIB_NAME} PRIVATE ADVSS_EXPORT_SYMBOLS=1)
|
||||
|
||||
# --- End of section ---
|
||||
|
||||
# --- Windows-specific build settings and tasks ---
|
||||
|
||||
@@ -146,18 +146,15 @@ AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="Während des
|
||||
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
|
||||
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
||||
AdvSceneSwitcher.condition.window="Fenster"
|
||||
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} existiert und ..."
|
||||
AdvSceneSwitcher.condition.window.entry.line2="... ist {{fullscreen}} Vollbild {{maximized}} Maximiert {{focused}} Fokusiert {{windowFocusChanged}} Vordergrundfenster geändert"
|
||||
AdvSceneSwitcher.condition.window.entry.line3="Aktuelles Vordergrundfenster: {{focusWindow}}"
|
||||
AdvSceneSwitcher.condition.file="Datei"
|
||||
AdvSceneSwitcher.condition.file.type.match="entspricht"
|
||||
AdvSceneSwitcher.condition.file.type.contentChange="Inhalt geändert"
|
||||
AdvSceneSwitcher.condition.file.type.dateChange="Änderungsdatum geändert"
|
||||
AdvSceneSwitcher.condition.file.remote="Entfernte Datei"
|
||||
AdvSceneSwitcher.condition.file.local="Lokale Datei"
|
||||
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||
AdvSceneSwitcher.condition.media="Medien"
|
||||
AdvSceneSwitcher.condition.media.source="Quelle"
|
||||
AdvSceneSwitcher.condition.media.anyOnScene="Beliebige Medienquelle in"
|
||||
@@ -328,7 +325,9 @@ AdvSceneSwitcher.condition.date.entry.nextMatchDate="Nächster Treffer bei: %1"
|
||||
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} Bei Wiederholung ausgewähltes Datum auf Wiederholungsdatum aktualisieren"
|
||||
AdvSceneSwitcher.condition.sceneTransform="Szenenelement transformieren"
|
||||
AdvSceneSwitcher.condition.sceneTransform.getTransform="Transformation erhalten"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line1="Auf{{scenes}}{{sources}}passt zur Transformation"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line1="Auf{{scenes}}{{sources}}{{types}}"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.type.matches="entspricht Transformation"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.type.changed="hat sich geändert"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
|
||||
AdvSceneSwitcher.condition.transition="Übergang"
|
||||
@@ -392,12 +391,11 @@ AdvSceneSwitcher.condition.variable.type.valueChanged="Wert verändert"
|
||||
AdvSceneSwitcher.condition.variable.type.equalsVariable="entspricht Variable"
|
||||
AdvSceneSwitcher.condition.variable.type.lessThanVariable="ist kleiner als die Variable"
|
||||
AdvSceneSwitcher.condition.variable.type.greaterThanVariable="ist größer als die Variable"
|
||||
AdvSceneSwitcher.condition.variable.entry="{{variables}}{{conditions}}{{strValue}}{{numValue}}{{variables2}}"
|
||||
|
||||
; Macro Actions
|
||||
AdvSceneSwitcher.action.switchScene="Szene wechseln"
|
||||
AdvSceneSwitcher.action.scene.entry="Wechsle zu Szene{{scenes}}mittels{{transitions}}mit einer Dauer von{{duration}}Sekunden"
|
||||
AdvSceneSwitcher.action.scene.entry.noDuration="Wechsle zu Szene{{scenes}}mittels{{transitions}}"
|
||||
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.wait="Warten"
|
||||
AdvSceneSwitcher.action.wait.type.fixed="fixe"
|
||||
@@ -440,11 +438,6 @@ AdvSceneSwitcher.action.streaming.type.stop="Stream stoppen"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Stream starten"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}"
|
||||
AdvSceneSwitcher.action.run="Ausführen"
|
||||
AdvSceneSwitcher.action.run.arguments="Argumente:"
|
||||
AdvSceneSwitcher.action.run.addArgument="Argument hinzufügen"
|
||||
AdvSceneSwitcher.action.run.addArgumentDescription="Neues Argument hinzufügen:"
|
||||
AdvSceneSwitcher.action.run.entry="Ausführen {{filePath}}"
|
||||
AdvSceneSwitcher.action.run.entry.workingDirectory="Arbeitsverzeichnis:{{workingDirectory}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility="Sichtbarkeit von Szenenelementen"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.show="Anzeigen"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.hide="Verstecken"
|
||||
@@ -476,8 +469,7 @@ AdvSceneSwitcher.action.media.type.stop="Stoppen"
|
||||
AdvSceneSwitcher.action.media.type.restart="Neu starten"
|
||||
AdvSceneSwitcher.action.media.type.next="Nächste"
|
||||
AdvSceneSwitcher.action.media.type.previous="Vorherige"
|
||||
AdvSceneSwitcher.action.media.type.seek="Suche nach"
|
||||
AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}"
|
||||
AdvSceneSwitcher.action.media.type.seek.duration="Suche nach"
|
||||
AdvSceneSwitcher.action.macro="Makro"
|
||||
AdvSceneSwitcher.action.macro.type.pause="Pausieren"
|
||||
AdvSceneSwitcher.action.macro.type.unpause="Nicht mehr pausieren"
|
||||
@@ -506,7 +498,6 @@ AdvSceneSwitcher.action.hotkey.leftMeta="Linke Meta-Taste"
|
||||
AdvSceneSwitcher.action.hotkey.rightMeta="Rechte Meta-Taste"
|
||||
AdvSceneSwitcher.action.hotkey.onlyOBS="Tastendruck nur an OBS senden"
|
||||
AdvSceneSwitcher.action.hotkey.disabled="Globale Tastendrücke können nicht simuliert werden - die Funktionalität beschränkt sich auf das Senden von Tastendrücken an OBS!"
|
||||
AdvSceneSwitcher.action.hotkey.entry="Drücke {{keys}} für {{duration}}"
|
||||
AdvSceneSwitcher.action.sceneOrder="Reihenfolge der Szenenelemente"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Nach oben verschieben"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Nach unten verschieben"
|
||||
@@ -567,8 +558,6 @@ AdvSceneSwitcher.action.sequence.continueFrom="Weiter mit ausgewähltem Element"
|
||||
AdvSceneSwitcher.action.websocket="Websocket"
|
||||
AdvSceneSwitcher.action.websocket.type.request="Anfrage"
|
||||
AdvSceneSwitcher.action.websocket.type.event="Ereignis"
|
||||
AdvSceneSwitcher.action.websocket.entry.request="Szenenwechsler {{type}} via {{connection}} senden"
|
||||
AdvSceneSwitcher.action.websocket.entry.event="Szenenwechsler {{type}} an verbundene Clients senden"
|
||||
AdvSceneSwitcher.action.http="HTTP"
|
||||
AdvSceneSwitcher.action.http.type.get="GET"
|
||||
AdvSceneSwitcher.action.http.type.post="POST"
|
||||
@@ -586,7 +575,7 @@ AdvSceneSwitcher.action.variable.invalidSelection="Ungültige Auswahl!"
|
||||
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Das Abrufen von Variablenwerten aus %1 Aktionen wird nicht unterstützt!"
|
||||
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Das Abrufen von Variablenwerten aus %1 Bedingungen wird nicht unterstützt!"
|
||||
AdvSceneSwitcher.action.variable.currentSegmentValue="Aktueller Wert:"
|
||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}"
|
||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}"
|
||||
|
||||
|
||||
; Transition Tab
|
||||
@@ -724,7 +713,7 @@ AdvSceneSwitcher.sceneSequenceTab.loadFail="Laden der Einstellungen ist fehlgesc
|
||||
AdvSceneSwitcher.sceneSequenceTab.loadSuccess="Laden der Einstellungen war erfolgreich!"
|
||||
AdvSceneSwitcher.sceneSequenceTab.fileType="Text Dateien (*.txt)"
|
||||
AdvSceneSwitcher.sceneSequenceTab.interruptible="kann unterbrochen werden"
|
||||
AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="Andere Szenenwechselmethoden können diese Sequenz unterbrechen"
|
||||
AdvSceneSwitcher.sceneSequenceTab.interruptibleHint="Andere Szenenwechselmethoden können diese Sequenz unterbrechen"
|
||||
AdvSceneSwitcher.sceneSequenceTab.entry="Wenn {{startScenes}} aktiv ist wechsle zu {{scenes}} nach {{delay}} mit {{transitions}} {{interruptible}}"
|
||||
AdvSceneSwitcher.sceneSequenceTab.extendEdit="Szenenfolge erweitern"
|
||||
AdvSceneSwitcher.sceneSequenceTab.extendEntry="Nach {{delay}} wechsle zu {{scenes}} mit {{transitions}}"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -41,17 +41,17 @@ AdvSceneSwitcher.generalTab.saveOrLoadsettings.exportWindowTitle="Exportar los a
|
||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.importWindowTitle="Importar los ajustes para Advanced Scene Switcher ..."
|
||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.textType="Archivos de texto (*.txt)"
|
||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadFail="La importacion la configuracion de escenas fallo"
|
||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadSuccess="Configuración de escenas importada correctamente"
|
||||
AdvSceneSwitcher.generalTab.priority.fileContent="Contenido del archivo"
|
||||
AdvSceneSwitcher.generalTab.priority.sceneSequence="Secuencia de escenas"
|
||||
AdvSceneSwitcher.generalTab.priority.idleDetection="Detección de inactivos"
|
||||
AdvSceneSwitcher.generalTab.priority.executable="Ejecutable"
|
||||
AdvSceneSwitcher.generalTab.priority.screenRegion="Región de pantalla"
|
||||
AdvSceneSwitcher.generalTab.priority.windowTitle="Título de la ventana"
|
||||
AdvSceneSwitcher.generalTab.priority.media="Medios"
|
||||
AdvSceneSwitcher.generalTab.priority.time="Tiempo"
|
||||
AdvSceneSwitcher.generalTab.priority.audio="Audio"
|
||||
AdvSceneSwitcher.generalTab.priority.video="Video"
|
||||
AdvSceneSwitcher.generalTab.saveOrLoadsettings.loadSuccess="Configuración de escenas importada correctamente"
|
||||
AdvSceneSwitcher.generalTab.priority.fileContent="Contenido del archivo"
|
||||
AdvSceneSwitcher.generalTab.priority.sceneSequence="Secuencia de escenas"
|
||||
AdvSceneSwitcher.generalTab.priority.idleDetection="Detección de inactivos"
|
||||
AdvSceneSwitcher.generalTab.priority.executable="Ejecutable"
|
||||
AdvSceneSwitcher.generalTab.priority.screenRegion="Región de pantalla"
|
||||
AdvSceneSwitcher.generalTab.priority.windowTitle="Título de la ventana"
|
||||
AdvSceneSwitcher.generalTab.priority.media="Medios"
|
||||
AdvSceneSwitcher.generalTab.priority.time="Tiempo"
|
||||
AdvSceneSwitcher.generalTab.priority.audio="Audio"
|
||||
AdvSceneSwitcher.generalTab.priority.video="Video"
|
||||
AdvSceneSwitcher.generalTab.priority.macro="Macro"
|
||||
AdvSceneSwitcher.generalTab.setTransitionBy="Al cambiar las transiciones:"
|
||||
AdvSceneSwitcher.generalTab.transitionOverride="Establecer anulaciones de transición"
|
||||
@@ -61,38 +61,38 @@ AdvSceneSwitcher.generalTab.transitionBehaviorSelectionError="Al menos una opci
|
||||
; Macro Tab
|
||||
AdvSceneSwitcher.macroTab.title="Macro"
|
||||
AdvSceneSwitcher.macroTab.macros="Macros"
|
||||
AdvSceneSwitcher.macroTab.priorityWarning="Nota: Se recomienda configurar las macros para que sean la funcionalidad de máxima prioridad.\nEsta configuración se puede cambiar en la ficha General."
|
||||
AdvSceneSwitcher.macroTab.help="Las macros le permiten ejecutar una cadena de acciones en función de varias condiciones.\n\nHaga clic en el símbolo más resaltado para agregar una nueva macro."
|
||||
AdvSceneSwitcher.macroTab.editConditionHelp="Esta sección le permite definir las condiciones de la macro.\n\nSeleccione una macro existente o agregue una nueva a la izquierda.\nLuego haga clic en el botón más a continuación para agregar una nueva condición."
|
||||
AdvSceneSwitcher.macroTab.priorityWarning="Nota: Se recomienda configurar las macros para que sean la funcionalidad de máxima prioridad.\nEsta configuración se puede cambiar en la ficha General."
|
||||
AdvSceneSwitcher.macroTab.help="Las macros le permiten ejecutar una cadena de acciones en función de varias condiciones.\n\nHaga clic en el símbolo más resaltado para agregar una nueva macro."
|
||||
AdvSceneSwitcher.macroTab.editConditionHelp="Esta sección le permite definir las condiciones de la macro.\n\nSeleccione una macro existente o agregue una nueva a la izquierda.\nLuego haga clic en el botón más a continuación para agregar una nueva condición."
|
||||
AdvSceneSwitcher.macroTab.editActionHelp="Esta sección le permite definir acciones de la macro.\n\nSeleccione una macro existente o agregue una nueva a la izquierda.\nLuego haga clic en el botón más a continuación para agregar una nueva acción"
|
||||
AdvSceneSwitcher.macroTab.edit="Editar macro"
|
||||
AdvSceneSwitcher.macroTab.edit.logic="Tipo de lógica:"
|
||||
AdvSceneSwitcher.macroTab.edit.condition="Tipo de condición:"
|
||||
AdvSceneSwitcher.macroTab.edit.logic="Tipo de lógica:"
|
||||
AdvSceneSwitcher.macroTab.edit.condition="Tipo de condición:"
|
||||
AdvSceneSwitcher.macroTab.edit.action="Tipo de acción:"
|
||||
AdvSceneSwitcher.macroTab.add="Agregar nueva macro"
|
||||
AdvSceneSwitcher.macroTab.name="Nombre:"
|
||||
AdvSceneSwitcher.macroTab.run="Ejecutar macro"
|
||||
AdvSceneSwitcher.macroTab.runFail="Error al ejecutar \"%1\" si se ha producido un error en una de las acciones o si la macro ya se está ejecutando."
|
||||
AdvSceneSwitcher.macroTab.runInParallel="Ejecutar macro en paralelo a otras macros"
|
||||
AdvSceneSwitcher.macroTab.onChange="Realizar acciones solo en el cambio de condición"
|
||||
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
||||
AdvSceneSwitcher.macroTab.exists="El nombre de la macro ya existe"
|
||||
AdvSceneSwitcher.macroTab.copy="Crear copia"
|
||||
AdvSceneSwitcher.macroTab.expandAll="Expandir todo"
|
||||
AdvSceneSwitcher.macroTab.collapseAll="Contraer todo"
|
||||
AdvSceneSwitcher.macroTab.maximize="Maximizar"
|
||||
AdvSceneSwitcher.macroTab.add="Agregar nueva macro"
|
||||
AdvSceneSwitcher.macroTab.name="Nombre:"
|
||||
AdvSceneSwitcher.macroTab.run="Ejecutar macro"
|
||||
AdvSceneSwitcher.macroTab.runFail="Error al ejecutar \"%1\" si se ha producido un error en una de las acciones o si la macro ya se está ejecutando."
|
||||
AdvSceneSwitcher.macroTab.runInParallel="Ejecutar macro en paralelo a otras macros"
|
||||
AdvSceneSwitcher.macroTab.onChange="Realizar acciones solo en el cambio de condición"
|
||||
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
||||
AdvSceneSwitcher.macroTab.exists="El nombre de la macro ya existe"
|
||||
AdvSceneSwitcher.macroTab.copy="Crear copia"
|
||||
AdvSceneSwitcher.macroTab.expandAll="Expandir todo"
|
||||
AdvSceneSwitcher.macroTab.collapseAll="Contraer todo"
|
||||
AdvSceneSwitcher.macroTab.maximize="Maximizar"
|
||||
AdvSceneSwitcher.macroTab.minimize="Minimizar"
|
||||
AdvSceneSwitcher.macroTab.highlightExecutedMacros="Resaltar macros ejecutadas recientemente"
|
||||
AdvSceneSwitcher.macroTab.highlightTrueConditions="Resaltar condiciones de la macro seleccionada, que se evaluaron como verdaderas recientemente"
|
||||
AdvSceneSwitcher.macroTab.highlightPerformedActions="Resaltar acciones realizadas recientemente de la macro seleccionada actualmente"
|
||||
AdvSceneSwitcher.macroTab.highlightExecutedMacros="Resaltar macros ejecutadas recientemente"
|
||||
AdvSceneSwitcher.macroTab.highlightTrueConditions="Resaltar condiciones de la macro seleccionada, que se evaluaron como verdaderas recientemente"
|
||||
AdvSceneSwitcher.macroTab.highlightPerformedActions="Resaltar acciones realizadas recientemente de la macro seleccionada actualmente"
|
||||
|
||||
; Lógica de macros
|
||||
AdvSceneSwitcher.logic.none="Omitir entrada"
|
||||
AdvSceneSwitcher.logic.and="Y"
|
||||
AdvSceneSwitcher.logic.or="O"
|
||||
AdvSceneSwitcher.logic.andNot="Y no"
|
||||
AdvSceneSwitcher.logic.orNot="O no"
|
||||
AdvSceneSwitcher.logic.rootNone="Si"
|
||||
; Lógica de macros
|
||||
AdvSceneSwitcher.logic.none="Omitir entrada"
|
||||
AdvSceneSwitcher.logic.and="Y"
|
||||
AdvSceneSwitcher.logic.or="O"
|
||||
AdvSceneSwitcher.logic.andNot="Y no"
|
||||
AdvSceneSwitcher.logic.orNot="O no"
|
||||
AdvSceneSwitcher.logic.rootNone="Si"
|
||||
AdvSceneSwitcher.logic.not="Si no"
|
||||
|
||||
; Macro Conditions
|
||||
@@ -122,12 +122,10 @@ AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="Durante la tr
|
||||
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
|
||||
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
||||
AdvSceneSwitcher.condition.window="Ventana"
|
||||
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} existen y ..."
|
||||
AdvSceneSwitcher.condition.window.entry.line2="... es {{fullscreen}} pantalla completa {{maximized}} maximizada {{focused}} enfocada {{windowFocusChanged}} ventana de primer plano cambiada"
|
||||
AdvSceneSwitcher.condition.file="Archivo"
|
||||
AdvSceneSwitcher.condition.file.entry.line1="Contenido de{{fileType}}{{filePath}}{{conditions}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line1="Contenido de{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||
AdvSceneSwitcher.condition.media="Medios"
|
||||
AdvSceneSwitcher.condition.media.anyOnScene="Cualquier fuente multimedia activada"
|
||||
AdvSceneSwitcher.condition.media.allOnScene="Todas las fuentes de medios activadas"
|
||||
@@ -277,7 +275,8 @@ AdvSceneSwitcher.condition.date.entry.nextMatchDate="Próxima coincidencia en: %
|
||||
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} Al repetir actualizar la fecha seleccionada para repetir la fecha"
|
||||
AdvSceneSwitcher.condition.sceneTransform="Transformar elemento de escena"
|
||||
AdvSceneSwitcher.condition.sceneTransform.getTransform="Obtener transformación"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line1="En{{scenes}}{{sources}}coincide con la transformación"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line1="En{{scenes}}{{sources}}{{types}}"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.type.matches="coincide con la transformación"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
|
||||
AdvSceneSwitcher.condition.transition="Transición"
|
||||
@@ -324,8 +323,8 @@ AdvSceneSwitcher.condition.stats.dockHint="Puede abrir el panel de \"Estadístic
|
||||
AdvSceneSwitcher.condition.stats.entry="{{stats}} esta {{condition}} {{value}}"
|
||||
|
||||
; Macro Actions
|
||||
AdvSceneSwitcher.action.switchScene="Cambiar escena"
|
||||
AdvSceneSwitcher.action.scene.entry="Cambiar a la escena {{scenes}} usando {{transitions}} con una duración de {{duration}} segundos"
|
||||
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.wait="Esperar"
|
||||
AdvSceneSwitcher.action.wait.type.fixed="fijo"
|
||||
@@ -362,10 +361,6 @@ AdvSceneSwitcher.action.streaming.type.stop="Detener transmisión"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Iniciar transmisión"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}"
|
||||
AdvSceneSwitcher.action.run="Ejecutar"
|
||||
AdvSceneSwitcher.action.run.arguments="Argumentos:"
|
||||
AdvSceneSwitcher.action.run.addArgument="Agregar argumento"
|
||||
AdvSceneSwitcher.action.run.addArgumentDescription="Añadir nuevo argumento:"
|
||||
AdvSceneSwitcher.action.run.entry="Ejecutar {{filePath}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility="Visibilidad del elemento de escena"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.show="Mostrar"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.hide="Ocultar"
|
||||
@@ -392,8 +387,7 @@ AdvSceneSwitcher.action.media.type.stop="Detener"
|
||||
AdvSceneSwitcher.action.media.type.restart="Reiniciar"
|
||||
AdvSceneSwitcher.action.media.type.next="Siguiente"
|
||||
AdvSceneSwitcher.action.media.type.previous="Anterior"
|
||||
AdvSceneSwitcher.action.media.type.seek="Buscar"
|
||||
AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}"
|
||||
AdvSceneSwitcher.action.media.type.seek.duration="Buscar"
|
||||
AdvSceneSwitcher.action.macro="Macro"
|
||||
AdvSceneSwitcher.action.macro.type.pause="Pausa"
|
||||
AdvSceneSwitcher.action.macro.type.unpause="Reanudar"
|
||||
@@ -422,7 +416,6 @@ AdvSceneSwitcher.action.hotkey.leftMeta="Meta izquierda"
|
||||
AdvSceneSwitcher.action.hotkey.rightMeta="Meta derecho"
|
||||
AdvSceneSwitcher.action.hotkey.onlyOBS="Enviar pulsación de tecla solo a OBS"
|
||||
AdvSceneSwitcher.action.hotkey.disabled="No se puede simular la pulsación de teclas: ¡funcionalidad desactivada!"
|
||||
AdvSceneSwitcher.action.hotkey.entry="Presione {{keys}} durante {{duration}}"
|
||||
AdvSceneSwitcher.action.sceneOrder="Orden de elementos de escena"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Mover hacia arriba"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Mover hacia abajo"
|
||||
@@ -573,7 +566,7 @@ AdvSceneSwitcher.fileTab.help="Esta pestaña te permitirá cambiar escenas autom
|
||||
; Random Tab
|
||||
AdvSceneSwitcher.randomTab.title="Aleatorio"
|
||||
AdvSceneSwitcher.randomTab.randomDisabledWarning="Funcionalidad deshabilitada - para activarla, selecciona \"Si no se cumple ninguna condición de cambio, cambiar a cualquier escena en la pestaña Aleatorio\" en la pestaña General"
|
||||
AdvSceneSwitcher.randomTab.entry="Si no se cumple ninguna condición de cambio, cambiar a {{scenes}} usando {{transitions}} después de {{delay}}"
|
||||
AdvSceneSwitcher.randomTab.entry="Si no se cumple ninguna condición de cambio, cambiar a {{scenes}} usando {{transitions}} después de {{delay}}"
|
||||
AdvSceneSwitcher.randomTab.help="El selector de escenas elegirá aleatoriamente una entrada en esta pestaña para cambiar durante el tiempo configurado.\nTen en cuenta que la misma entrada no se elegirá dos veces seguidas.\n\nHaz clic en el símbolo más resaltado para continuar."
|
||||
|
||||
; Time Tab
|
||||
|
||||
1201
data/locale/fr-FR.ini
Normal file
1201
data/locale/fr-FR.ini
Normal file
File diff suppressed because it is too large
Load Diff
@@ -86,10 +86,9 @@ AdvSceneSwitcher.condition.scene="Сцена"
|
||||
AdvSceneSwitcher.condition.scene.type.current="Текущий"
|
||||
AdvSceneSwitcher.condition.scene.type.previous="Предыдущий"
|
||||
AdvSceneSwitcher.condition.window="Окно"
|
||||
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} существует и ..."
|
||||
AdvSceneSwitcher.condition.file="Файл"
|
||||
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||
AdvSceneSwitcher.condition.media="Медиа"
|
||||
AdvSceneSwitcher.condition.video="Видео"
|
||||
AdvSceneSwitcher.condition.video.condition.match="точно соответствует"
|
||||
@@ -116,8 +115,8 @@ AdvSceneSwitcher.condition.pluginState.state.sceneSwitched="Автоматиче
|
||||
AdvSceneSwitcher.condition.pluginState.entry="{{condition}}"
|
||||
|
||||
; Macro Actions
|
||||
AdvSceneSwitcher.action.switchScene="Переключить сцену"
|
||||
AdvSceneSwitcher.action.scene.entry="Перейти к сцене {{scenes}} используя {{transitions}} с продолжительностью {{duration}} секунд"
|
||||
AdvSceneSwitcher.action.scene="Переключить сцену"
|
||||
AdvSceneSwitcher.action.scene.entry="Перейти к сцене{{sceneTypes}}{{scenes}}используя{{transitions}}с продолжительностью{{duration}}секунд"
|
||||
AdvSceneSwitcher.action.wait="Подождать"
|
||||
AdvSceneSwitcher.action.wait.type.fixed="фиксированный"
|
||||
AdvSceneSwitcher.action.wait.type.random="случайный"
|
||||
|
||||
@@ -112,12 +112,10 @@ AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Geçiş hedefi
|
||||
AdvSceneSwitcher.condition.scene.entry.line1="{{sceneType}}{{scenes}}{{pattern}}"
|
||||
AdvSceneSwitcher.condition.scene.entry.line2="{{useTransitionTargetScene}}"
|
||||
AdvSceneSwitcher.condition.window="Pencere"
|
||||
AdvSceneSwitcher.condition.window.entry.line1="{{windows}} Varolan ve ..."
|
||||
AdvSceneSwitcher.condition.window.entry.line2="... {{fullscreen}} Tam ekran {{maximized}} büyütüldü {{focused}} odaklanıldı {{windowFocusChanged}} ön plan penceresi değişikliği"
|
||||
AdvSceneSwitcher.condition.file="Dosya"
|
||||
AdvSceneSwitcher.condition.file.entry.line1="İçerik{{fileType}}{{filePath}}{{conditions}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line1="İçerik{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||
AdvSceneSwitcher.condition.media="Medya"
|
||||
AdvSceneSwitcher.condition.media.anyOnScene="Herhangi bir medya kaynağı"
|
||||
AdvSceneSwitcher.condition.media.allOnScene="Tüm medya kaynakları "
|
||||
@@ -233,7 +231,8 @@ AdvSceneSwitcher.condition.date.state.before="Önce"
|
||||
AdvSceneSwitcher.condition.date.state.between="Arasında"
|
||||
AdvSceneSwitcher.condition.sceneTransform="Sahne öğesi dönüşümü"
|
||||
AdvSceneSwitcher.condition.sceneTransform.getTransform="Dönüşümü al"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line1="Açık{{scenes}}{{sources}} dönüşümle eşleşir"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line1="Açık{{scenes}}{{sources}}{{types}}"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.type.matches="dönüşümle eşleşir"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
|
||||
AdvSceneSwitcher.condition.transition="Geçiş"
|
||||
@@ -261,8 +260,8 @@ AdvSceneSwitcher.condition.openvr.entry.line2="{{controls}}"
|
||||
AdvSceneSwitcher.condition.openvr.entry.line3="HMD mevcut {{xPos}} x {{yPos}} x {{zPos}}"
|
||||
|
||||
; Macro Actions
|
||||
AdvSceneSwitcher.action.switchScene="Sahne Degistirici"
|
||||
AdvSceneSwitcher.action.scene.entry="Sahneyi {{scenes}} kullanarak {{transitions}} süresi olan {{duration}} saniye"
|
||||
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.wait="Bekle"
|
||||
AdvSceneSwitcher.action.wait.type.fixed="sabit"
|
||||
@@ -292,10 +291,6 @@ AdvSceneSwitcher.action.streaming.type.stop="Yayın durdur"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Yayın başlat"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}"
|
||||
AdvSceneSwitcher.action.run="Çalıştır"
|
||||
AdvSceneSwitcher.action.run.arguments="Argümanlar:"
|
||||
AdvSceneSwitcher.action.run.addArgument="Argüman ekle"
|
||||
AdvSceneSwitcher.action.run.addArgumentDescription="Yeni Argüman ekle:"
|
||||
AdvSceneSwitcher.action.run.entry="Çalıştır {{filePath}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility="Sahne öğesi görünürlüğü"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.show="Göster"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.hide="Gizle"
|
||||
@@ -322,7 +317,6 @@ AdvSceneSwitcher.action.media.type.stop="Dur"
|
||||
AdvSceneSwitcher.action.media.type.restart="Yeniden Başlat"
|
||||
AdvSceneSwitcher.action.media.type.next="Sonraki"
|
||||
AdvSceneSwitcher.action.media.type.previous="Önceki"
|
||||
AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}"
|
||||
AdvSceneSwitcher.action.macro="Makro"
|
||||
AdvSceneSwitcher.action.macro.type.pause="Duraklat"
|
||||
AdvSceneSwitcher.action.macro.type.unpause="Duraklatma"
|
||||
@@ -350,7 +344,6 @@ AdvSceneSwitcher.action.hotkey.leftMeta="Sol Meta"
|
||||
AdvSceneSwitcher.action.hotkey.rightMeta="Sağ Meta"
|
||||
AdvSceneSwitcher.action.hotkey.onlyOBS="Tuşa basımı yalnızca OBS'ye gönder"
|
||||
AdvSceneSwitcher.action.hotkey.disabled="Tuşa basma simülasyonu yapılamıyor - işlevsellik devre dışı!"
|
||||
AdvSceneSwitcher.action.hotkey.entry="Bas {{keys}} uygun {{duration}}"
|
||||
AdvSceneSwitcher.action.sceneOrder="Sahne öğesi sırası"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="Yukarı taşı"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="Aşağı indir"
|
||||
|
||||
@@ -178,9 +178,9 @@ AdvSceneSwitcher.condition.file.type.contentChange="内容已更改"
|
||||
AdvSceneSwitcher.condition.file.type.dateChange="修改日期已更改"
|
||||
AdvSceneSwitcher.condition.file.remote="远程文件"
|
||||
AdvSceneSwitcher.condition.file.local="本地文件"
|
||||
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line3="{{useRegex}} {{checkModificationDate}} {{checkFileContent}}"
|
||||
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||
AdvSceneSwitcher.condition.media="媒体"
|
||||
AdvSceneSwitcher.condition.media.source="源"
|
||||
AdvSceneSwitcher.condition.media.anyOnScene="任何媒体源"
|
||||
@@ -371,7 +371,8 @@ AdvSceneSwitcher.condition.date.entry.nextMatchDate="下一次匹配 在: %1"
|
||||
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} 重复时,将选定的日期更新为重复日期"
|
||||
AdvSceneSwitcher.condition.sceneTransform="场景项目被改变"
|
||||
AdvSceneSwitcher.condition.sceneTransform.getTransform="内容或者设置被改变了"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line1="在 {{scenes}} {{sources}} 匹配变换"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line1="在 {{scenes}} {{sources}} {{types}}"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.type.matches="匹配变换"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line2="{{settings}}"
|
||||
AdvSceneSwitcher.condition.sceneTransform.entry.line3="{{regex}} {{getSettings}}"
|
||||
AdvSceneSwitcher.condition.transition="转场"
|
||||
@@ -435,7 +436,6 @@ AdvSceneSwitcher.condition.variable.type.valueChanged="值已更改"
|
||||
AdvSceneSwitcher.condition.variable.type.equalsVariable="等于变量"
|
||||
AdvSceneSwitcher.condition.variable.type.lessThanVariable="小于变量"
|
||||
AdvSceneSwitcher.condition.variable.type.greaterThanVariable="大于变量"
|
||||
AdvSceneSwitcher.condition.variable.entry="{{variables}}{{conditions}}{{strValue}}{{numValue}}{{variables2}}"
|
||||
AdvSceneSwitcher.condition.run="运行"
|
||||
AdvSceneSwitcher.condition.run.entry="进程在超时 {{timeout}} 秒之前退出"
|
||||
AdvSceneSwitcher.condition.run.entry.exit="{{checkExitCode}}检查退出代码{{exitCode}}"
|
||||
@@ -448,9 +448,9 @@ AdvSceneSwitcher.condition.display.type.displayCount="连接的显示器的数
|
||||
AdvSceneSwitcher.condition.display.entry="{{conditions}}{{displays}}{{regex}}{{displayCount}}"
|
||||
|
||||
; Macro Actions
|
||||
AdvSceneSwitcher.action.switchScene="切换场景"
|
||||
AdvSceneSwitcher.action.scene.entry="切换场景 {{scenes}} 使用 {{transitions}} 时长 {{duration}} 秒"
|
||||
AdvSceneSwitcher.action.scene.entry.noDuration="切换到场景{{scenes}}使用{{transitions}}"
|
||||
AdvSceneSwitcher.action.scene="切换场景"
|
||||
AdvSceneSwitcher.action.scene.entry="切换场景{{sceneTypes}}{{scenes}}使用{{transitions}}时长{{duration}}秒"
|
||||
AdvSceneSwitcher.action.scene.entry.noDuration="切换到场景{{sceneTypes}}{{scenes}}使用{{transitions}}"
|
||||
AdvSceneSwitcher.action.scene.blockUntilTransitionDone="等待目标场景的过渡完成"
|
||||
AdvSceneSwitcher.action.wait="等待"
|
||||
AdvSceneSwitcher.action.wait.type.fixed="固定数值"
|
||||
@@ -527,8 +527,7 @@ AdvSceneSwitcher.action.media.type.stop="停止"
|
||||
AdvSceneSwitcher.action.media.type.restart="重新启动"
|
||||
AdvSceneSwitcher.action.media.type.next="下一个"
|
||||
AdvSceneSwitcher.action.media.type.previous="上一个"
|
||||
AdvSceneSwitcher.action.media.type.seek="时间轴定位"
|
||||
AdvSceneSwitcher.action.media.entry="{{actions}}{{duration}}{{mediaSources}}"
|
||||
AdvSceneSwitcher.action.media.type.seek.duration="时间轴定位"
|
||||
AdvSceneSwitcher.action.macro="宏"
|
||||
AdvSceneSwitcher.action.macro.type.pause="暂停"
|
||||
AdvSceneSwitcher.action.macro.type.unpause="取消暂停"
|
||||
@@ -559,7 +558,6 @@ AdvSceneSwitcher.action.hotkey.leftMeta="左 Meta"
|
||||
AdvSceneSwitcher.action.hotkey.rightMeta="右 Meta"
|
||||
AdvSceneSwitcher.action.hotkey.onlyOBS="仅向OBS发送按键"
|
||||
AdvSceneSwitcher.action.hotkey.disabled="无法模拟按键-功能已禁用!"
|
||||
AdvSceneSwitcher.action.hotkey.entry="按下 {{keys}} 在 {{duration}} 秒"
|
||||
AdvSceneSwitcher.action.sceneOrder="场景项目顺序"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveUp="上移"
|
||||
AdvSceneSwitcher.action.sceneOrder.type.moveDown="下移"
|
||||
@@ -624,8 +622,6 @@ AdvSceneSwitcher.action.sequence.continueFrom="继续所选项目"
|
||||
AdvSceneSwitcher.action.websocket="websocket"
|
||||
AdvSceneSwitcher.action.websocket.type.request="request"
|
||||
AdvSceneSwitcher.action.websocket.type.event="event"
|
||||
AdvSceneSwitcher.action.websocket.entry.request="通过{{connection}} 发送场景切换器 {{type}}"
|
||||
AdvSceneSwitcher.action.websocket.entry.event="发送场景切换器 {{type}} 到连接的客户端"
|
||||
AdvSceneSwitcher.action.http="Http"
|
||||
AdvSceneSwitcher.action.http.setHeaders="设置头信息(SET headers)"
|
||||
AdvSceneSwitcher.action.http.headers="头信息(headers):"
|
||||
@@ -655,7 +651,7 @@ AdvSceneSwitcher.action.variable.invalidSelection="无效选择!"
|
||||
AdvSceneSwitcher.action.variable.actionNoVariableSupport="不支持从 %1 个操作获取变量值!"
|
||||
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="不支持从 %1 条件中获取变量值!"
|
||||
AdvSceneSwitcher.action.variable.currentSegmentValue="当前值:"
|
||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}"
|
||||
AdvSceneSwitcher.action.variable.entry="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}"
|
||||
AdvSceneSwitcher.action.variable.entry.substringIndex="子字符串开始:{{subStringStart}} 子字符串大小:{{subStringSize}}"
|
||||
AdvSceneSwitcher.action.variable.entry.substringRegex="使用正则表达式为 {{regexMatchIdx}} 匹配的值:"
|
||||
AdvSceneSwitcher.action.variable.entry.findAndReplace="{{findStr}}{{replaceStr}}"
|
||||
|
||||
8
data/res/images/DarkSearch.svg
Normal file
8
data/res/images/DarkSearch.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="256" height="256" viewBox="0 0 256 256" xml:space="preserve">
|
||||
|
||||
<defs>
|
||||
</defs>
|
||||
<g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;" transform="translate(1.4065934065934016 1.4065934065934016) scale(2.81 2.81)" >
|
||||
<path d="M 87.803 77.194 L 68.212 57.602 c 9.5 -14.422 7.912 -34.054 -4.766 -46.732 c 0 0 -0.001 0 -0.001 0 c -14.495 -14.493 -38.08 -14.494 -52.574 0 c -14.494 14.495 -14.494 38.079 0 52.575 c 7.248 7.247 16.767 10.87 26.287 10.87 c 7.134 0 14.267 -2.035 20.445 -6.104 l 19.591 19.591 C 78.659 89.267 80.579 90 82.498 90 s 3.84 -0.733 5.305 -2.197 C 90.732 84.873 90.732 80.124 87.803 77.194 z M 21.48 52.837 c -8.645 -8.646 -8.645 -22.713 0 -31.358 c 4.323 -4.322 10 -6.483 15.679 -6.483 c 5.678 0 11.356 2.161 15.678 6.483 c 8.644 8.644 8.645 22.707 0.005 31.352 c -0.002 0.002 -0.004 0.003 -0.005 0.005 c -0.002 0.002 -0.003 0.003 -0.004 0.005 C 44.184 61.481 30.123 61.48 21.48 52.837 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: #fefefe; fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
8
data/res/images/LightSearch.svg
Normal file
8
data/res/images/LightSearch.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="256" height="256" viewBox="0 0 256 256" xml:space="preserve">
|
||||
|
||||
<defs>
|
||||
</defs>
|
||||
<g style="stroke: none; stroke-width: 0; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: none; fill-rule: nonzero; opacity: 1;" transform="translate(1.4065934065934016 1.4065934065934016) scale(2.81 2.81)" >
|
||||
<path d="M 87.803 77.194 L 68.212 57.602 c 9.5 -14.422 7.912 -34.054 -4.766 -46.732 c 0 0 -0.001 0 -0.001 0 c -14.495 -14.493 -38.08 -14.494 -52.574 0 c -14.494 14.495 -14.494 38.079 0 52.575 c 7.248 7.247 16.767 10.87 26.287 10.87 c 7.134 0 14.267 -2.035 20.445 -6.104 l 19.591 19.591 C 78.659 89.267 80.579 90 82.498 90 s 3.84 -0.733 5.305 -2.197 C 90.732 84.873 90.732 80.124 87.803 77.194 z M 21.48 52.837 c -8.645 -8.646 -8.645 -22.713 0 -31.358 c 4.323 -4.322 10 -6.483 15.679 -6.483 c 5.678 0 11.356 2.161 15.678 6.483 c 8.644 8.644 8.645 22.707 0.005 31.352 c -0.002 0.002 -0.004 0.003 -0.005 0.005 c -0.002 0.002 -0.003 0.003 -0.004 0.005 C 44.184 61.481 30.123 61.48 21.48 52.837 z" style="stroke: none; stroke-width: 1; stroke-dasharray: none; stroke-linecap: butt; stroke-linejoin: miter; stroke-miterlimit: 10; fill: #202020; fill-rule: nonzero; opacity: 1;" transform=" matrix(1 0 0 1 0 0) " stroke-linecap="round" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
2
deps/asio
vendored
2
deps/asio
vendored
Submodule deps/asio updated: b73dc1d2c0...c465349fa5
1
deps/cpp-httplib
vendored
Submodule
1
deps/cpp-httplib
vendored
Submodule
Submodule deps/cpp-httplib added at c7ed1796a7
1
deps/json
vendored
Submodule
1
deps/json
vendored
Submodule
Submodule deps/json added at bc889afb4c
2
deps/websocketpp
vendored
2
deps/websocketpp
vendored
Submodule deps/websocketpp updated: c6d7e295bf...56123c8759
@@ -67,8 +67,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>957</width>
|
||||
<height>905</height>
|
||||
<width>962</width>
|
||||
<height>1033</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_19">
|
||||
@@ -256,6 +256,30 @@
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_11">
|
||||
<item>
|
||||
<widget class="QCheckBox" name="disableComboBoxFilter">
|
||||
<property name="text">
|
||||
<string>AdvSceneSwitcher.generalTab.generalBehavior.comboBoxFilterDisable</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_13">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_26">
|
||||
<item>
|
||||
@@ -805,7 +829,7 @@
|
||||
<property name="title">
|
||||
<string>AdvSceneSwitcher.macroTab.edit</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_33">
|
||||
<layout class="QVBoxLayout" name="verticalLayout_38">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_18" stretch="0,0,0,0,0,0,0,0,0">
|
||||
<item>
|
||||
@@ -819,7 +843,7 @@
|
||||
<widget class="QLineEdit" name="macroName"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="runMacro">
|
||||
<widget class="advss::MacroRunButton" name="runMacro">
|
||||
<property name="text">
|
||||
<string>AdvSceneSwitcher.macroTab.run</string>
|
||||
</property>
|
||||
@@ -912,6 +936,16 @@
|
||||
<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="horizontalLayout_12">
|
||||
<property name="leftMargin">
|
||||
@@ -1066,170 +1100,360 @@
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<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>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_21">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="actionAdd">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">addIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="actionRemove">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">removeIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_133">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>5</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_47">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_132">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>5</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="actionTop">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="actionUp">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">upArrowIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="actionDown">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">downArrowIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="actionBottom">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</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>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
<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="horizontalLayout_21">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="actionAdd">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">addIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="actionRemove">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">removeIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_133">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>5</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_47">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_132">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>5</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="actionTop">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="actionUp">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">upArrowIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="actionDown">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">downArrowIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="actionBottom">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</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>
|
||||
</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="horizontalLayout_33">
|
||||
<property name="leftMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="elseActionAdd">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">addIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="elseActionRemove">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">removeIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_138">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>5</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_50">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_139">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>5</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="elseActionTop">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="elseActionUp">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">upArrowIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="elseActionDown">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="themeID" stdset="0">
|
||||
<string notr="true">downArrowIconSmall</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="elseActionBottom">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>22</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_22">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -4619,6 +4843,17 @@
|
||||
<extends>QListView</extends>
|
||||
<header>macro-tree.hpp</header>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>advss::MacroSegmentList</class>
|
||||
<extends>QScrollArea</extends>
|
||||
<header>macro-segment-list.hpp</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>advss::MacroRunButton</class>
|
||||
<extends>QPushButton</extends>
|
||||
<header>macro-run-button.hpp</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
@@ -1,13 +1,3 @@
|
||||
#include <QMainWindow>
|
||||
#include <QAction>
|
||||
#include <QFileDialog>
|
||||
#include <QDirIterator>
|
||||
#include <regex>
|
||||
#include <filesystem>
|
||||
|
||||
#include <obs-module.h>
|
||||
#include <obs-frontend-api.h>
|
||||
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "switcher-data.hpp"
|
||||
#include "status-control.hpp"
|
||||
@@ -17,6 +7,15 @@
|
||||
#include "utility.hpp"
|
||||
#include "version.h"
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QAction>
|
||||
#include <QFileDialog>
|
||||
#include <QDirIterator>
|
||||
#include <regex>
|
||||
#include <filesystem>
|
||||
#include <obs-module.h>
|
||||
#include <obs-frontend-api.h>
|
||||
|
||||
namespace advss {
|
||||
|
||||
AdvSceneSwitcher *AdvSceneSwitcher::window = nullptr;
|
||||
@@ -326,14 +325,19 @@ void SwitcherData::SetPreconditions()
|
||||
cursorPosChanged = cursorPos.first != switcher->lastCursorPos.first ||
|
||||
cursorPos.second != switcher->lastCursorPos.second;
|
||||
lastCursorPos = GetCursorPos();
|
||||
|
||||
// Macro
|
||||
InvalidateMacroTempVarValues();
|
||||
}
|
||||
|
||||
void ClearWebsocketMessages();
|
||||
|
||||
void SwitcherData::ResetForNextInterval()
|
||||
{
|
||||
// Core reset functions
|
||||
ClearWebsocketMessages();
|
||||
// Plugin reset functions
|
||||
for (const auto &func : resetForNextIntervalFuncs) {
|
||||
for (const auto &func : resetIntervalSteps) {
|
||||
func();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@ public slots:
|
||||
void on_saveWindowGeo_stateChanged(int state);
|
||||
void on_showTrayNotifications_stateChanged(int state);
|
||||
void on_uiHintsDisable_stateChanged(int state);
|
||||
void on_disableComboBoxFilter_stateChanged(int state);
|
||||
void on_warnPluginLoadFailure_stateChanged(int state);
|
||||
void on_hideLegacyTabs_stateChanged(int state);
|
||||
void on_priorityUp_clicked();
|
||||
@@ -83,10 +84,13 @@ public:
|
||||
void SetEditMacro(Macro &m);
|
||||
void SetMacroEditAreaDisabled(bool);
|
||||
void HighlightAction(int idx, QColor color = QColor(Qt::green));
|
||||
void HighlightElseAction(int idx, QColor color = QColor(Qt::green));
|
||||
void HighlightCondition(int idx, QColor color = QColor(Qt::green));
|
||||
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 SetActionData(Macro &m);
|
||||
void SetElseActionData(Macro &m);
|
||||
void SetConditionData(Macro &m);
|
||||
void SwapActions(Macro *m, int pos1, int pos2);
|
||||
void SwapConditions(Macro *m, int pos1, int pos2);
|
||||
@@ -97,7 +101,6 @@ public slots:
|
||||
void on_macroUp_clicked();
|
||||
void on_macroDown_clicked();
|
||||
void on_macroName_editingFinished();
|
||||
void on_runMacro_clicked();
|
||||
void on_runMacroInParallel_stateChanged(int value);
|
||||
void on_runMacroOnChange_stateChanged(int value);
|
||||
void on_conditionAdd_clicked();
|
||||
@@ -112,29 +115,50 @@ public slots:
|
||||
void on_actionUp_clicked();
|
||||
void on_actionDown_clicked();
|
||||
void on_actionBottom_clicked();
|
||||
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();
|
||||
void MacroSelectionChanged();
|
||||
void UpMacroSegementHotkey();
|
||||
void DownMacroSegementHotkey();
|
||||
void DeleteMacroSegementHotkey();
|
||||
void ShowMacroContextMenu(const QPoint &);
|
||||
void ShowMacroActionsContextMenu(const QPoint &);
|
||||
void ShowMacroElseActionsContextMenu(const QPoint &);
|
||||
void ShowMacroConditionsContextMenu(const QPoint &);
|
||||
void CopyMacro();
|
||||
void RenameCurrentMacro();
|
||||
void ExportMacros();
|
||||
void ImportMacros();
|
||||
void ExpandAllActions();
|
||||
void ExpandAllElseActions();
|
||||
void ExpandAllConditions();
|
||||
void CollapseAllActions();
|
||||
void CollapseAllElseActions();
|
||||
void CollapseAllConditions();
|
||||
void MinimizeActions();
|
||||
void MaximizeActions();
|
||||
void MinimizeElseActions();
|
||||
void MaximizeElseActions();
|
||||
void MinimizeConditions();
|
||||
void MaximizeConditions();
|
||||
void MacroActionSelectionChanged(int idx);
|
||||
void MacroActionReorder(int to, int target);
|
||||
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(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);
|
||||
@@ -154,8 +178,10 @@ signals:
|
||||
void MacroRemoved(const QString &name);
|
||||
void MacroRenamed(const QString &oldName, const QString &newName);
|
||||
void MacroSegmentOrderChanged();
|
||||
void SegmentTempVarsChanged();
|
||||
void HighlightMacrosChanged(bool value);
|
||||
void HighlightActionsChanged(bool value);
|
||||
void HighlightElseActionsChanged(bool value);
|
||||
void HighlightConditionsChanged(bool value);
|
||||
|
||||
void ConnectionAdded(const QString &);
|
||||
@@ -166,19 +192,16 @@ signals:
|
||||
void VariableRemoved(const QString &);
|
||||
|
||||
private:
|
||||
enum class MacroSection { CONDITIONS, ACTIONS, ELSE_ACTIONS };
|
||||
|
||||
void SetupMacroSegmentSelection(MacroSection type, int idx);
|
||||
bool ResolveMacroImportNameConflict(std::shared_ptr<Macro> &);
|
||||
bool MacroTabIsInFocus();
|
||||
|
||||
MacroSegmentList *conditionsList = nullptr;
|
||||
MacroSegmentList *actionsList = nullptr;
|
||||
|
||||
enum class MacroSection {
|
||||
CONDITIONS,
|
||||
ACTIONS,
|
||||
};
|
||||
MacroSection lastInteracted = MacroSection::CONDITIONS;
|
||||
int currentConditionIdx = -1;
|
||||
int currentActionIdx = -1;
|
||||
int currentElseActionIdx = -1;
|
||||
|
||||
/* --- End of macro tab section --- */
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "switcher-data.hpp"
|
||||
#include "status-control.hpp"
|
||||
#include "file-selection.hpp"
|
||||
#include "filter-combo-box.hpp"
|
||||
#include "utility.hpp"
|
||||
#include "version.h"
|
||||
|
||||
@@ -131,10 +132,9 @@ void AdvSceneSwitcher::closeEvent(QCloseEvent *)
|
||||
}
|
||||
switcher->windowPos = this->pos();
|
||||
switcher->windowSize = this->size();
|
||||
switcher->macroActionConditionSplitterPosition =
|
||||
ui->macroActionConditionSplitter->sizes();
|
||||
switcher->macroListMacroEditSplitterPosition =
|
||||
ui->macroListMacroEditSplitter->sizes();
|
||||
MacroSelectionAboutToChange(); // Trigger saving of splitter states
|
||||
|
||||
obs_frontend_save();
|
||||
}
|
||||
@@ -175,6 +175,16 @@ void AdvSceneSwitcher::on_uiHintsDisable_stateChanged(int state)
|
||||
switcher->disableHints = state;
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_disableComboBoxFilter_stateChanged(int state)
|
||||
{
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
switcher->disableFilterComboboxFilter = state;
|
||||
FilterComboBox::SetFilterBehaviourEnabled(!state);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_warnPluginLoadFailure_stateChanged(int state)
|
||||
{
|
||||
if (loading) {
|
||||
@@ -489,11 +499,19 @@ void SwitcherData::LoadSettings(obs_data_t *obj)
|
||||
return;
|
||||
}
|
||||
|
||||
// New post load steps to be declared during load
|
||||
postLoadSteps.clear();
|
||||
|
||||
// Needs to be loaded before any entries which might rely on scene group
|
||||
// selections to be available.
|
||||
loadSceneGroups(obj);
|
||||
LoadVariables(obj);
|
||||
LoadConnections(obj);
|
||||
|
||||
for (const auto &func : loadSteps) {
|
||||
func(obj);
|
||||
}
|
||||
|
||||
LoadMacros(obj);
|
||||
loadWindowTitleSwitches(obj);
|
||||
loadScreenRegionSwitches(obj);
|
||||
@@ -514,6 +532,10 @@ void SwitcherData::LoadSettings(obs_data_t *obj)
|
||||
LoadHotkeys(obj);
|
||||
LoadUISettings(obj);
|
||||
|
||||
for (const auto &func : postLoadSteps) {
|
||||
func();
|
||||
}
|
||||
|
||||
// Reset on startup and scene collection change
|
||||
switcher->lastOpenedTab = -1;
|
||||
startupLoadDone = true;
|
||||
@@ -548,6 +570,10 @@ void SwitcherData::SaveSettings(obs_data_t *obj)
|
||||
SaveHotkeys(obj);
|
||||
SaveUISettings(obj);
|
||||
SaveVersion(obj, g_GIT_SHA1);
|
||||
|
||||
for (const auto &func : saveSteps) {
|
||||
func(obj);
|
||||
}
|
||||
}
|
||||
|
||||
void SwitcherData::SaveGeneralSettings(obs_data_t *obj)
|
||||
@@ -575,6 +601,8 @@ void SwitcherData::SaveGeneralSettings(obs_data_t *obj)
|
||||
obs_data_set_bool(obj, "showSystemTrayNotifications",
|
||||
showSystemTrayNotifications);
|
||||
obs_data_set_bool(obj, "disableHints", disableHints);
|
||||
obs_data_set_bool(obj, "disableFilterComboboxFilter",
|
||||
disableFilterComboboxFilter);
|
||||
obs_data_set_bool(obj, "warnPluginLoadFailure", warnPluginLoadFailure);
|
||||
obs_data_set_bool(obj, "hideLegacyTabs", hideLegacyTabs);
|
||||
|
||||
@@ -623,6 +651,8 @@ void SwitcherData::LoadGeneralSettings(obs_data_t *obj)
|
||||
showSystemTrayNotifications =
|
||||
obs_data_get_bool(obj, "showSystemTrayNotifications");
|
||||
disableHints = obs_data_get_bool(obj, "disableHints");
|
||||
disableFilterComboboxFilter =
|
||||
obs_data_get_bool(obj, "disableFilterComboboxFilter");
|
||||
obs_data_set_default_bool(obj, "warnPluginLoadFailure", true);
|
||||
warnPluginLoadFailure = obs_data_get_bool(obj, "warnPluginLoadFailure");
|
||||
obs_data_set_default_bool(obj, "hideLegacyTabs", true);
|
||||
@@ -652,34 +682,6 @@ void SwitcherData::LoadGeneralSettings(obs_data_t *obj)
|
||||
lastImportPath = obs_data_get_string(obj, "lastImportPath");
|
||||
}
|
||||
|
||||
static void saveSplitterPos(QList<int> &sizes, obs_data_t *obj,
|
||||
const std::string name)
|
||||
{
|
||||
auto array = obs_data_array_create();
|
||||
for (int i = 0; i < sizes.count(); ++i) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
obs_data_set_int(array_obj, "pos", sizes[i]);
|
||||
obs_data_array_push_back(array, array_obj);
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_set_array(obj, name.c_str(), array);
|
||||
obs_data_array_release(array);
|
||||
}
|
||||
|
||||
static void loadSplitterPos(QList<int> &sizes, obs_data_t *obj,
|
||||
const std::string name)
|
||||
{
|
||||
sizes.clear();
|
||||
obs_data_array_t *array = obs_data_get_array(obj, name.c_str());
|
||||
size_t count = obs_data_array_count(array);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *item = obs_data_array_item(array, i);
|
||||
sizes << obs_data_get_int(item, "pos");
|
||||
obs_data_release(item);
|
||||
}
|
||||
obs_data_array_release(array);
|
||||
}
|
||||
|
||||
void SwitcherData::SaveUISettings(obs_data_t *obj)
|
||||
{
|
||||
obs_data_set_int(obj, "generalTabPos", tabOrder[0]);
|
||||
@@ -707,9 +709,7 @@ void SwitcherData::SaveUISettings(obs_data_t *obj)
|
||||
obs_data_set_int(obj, "windowWidth", windowSize.width());
|
||||
obs_data_set_int(obj, "windowHeight", windowSize.height());
|
||||
|
||||
saveSplitterPos(macroActionConditionSplitterPosition, obj,
|
||||
"macroActionConditionSplitterPosition");
|
||||
saveSplitterPos(macroListMacroEditSplitterPosition, obj,
|
||||
SaveSplitterPos(macroListMacroEditSplitterPosition, obj,
|
||||
"macroListMacroEditSplitterPosition");
|
||||
}
|
||||
|
||||
@@ -763,9 +763,8 @@ void SwitcherData::LoadUISettings(obs_data_t *obj)
|
||||
(int)obs_data_get_int(obj, "windowPosY")};
|
||||
windowSize = {(int)obs_data_get_int(obj, "windowWidth"),
|
||||
(int)obs_data_get_int(obj, "windowHeight")};
|
||||
loadSplitterPos(macroActionConditionSplitterPosition, obj,
|
||||
"macroActionConditionSplitterPosition");
|
||||
loadSplitterPos(macroListMacroEditSplitterPosition, obj,
|
||||
|
||||
LoadSplitterPos(macroListMacroEditSplitterPosition, obj,
|
||||
"macroListMacroEditSplitterPosition");
|
||||
}
|
||||
|
||||
@@ -997,6 +996,10 @@ void AdvSceneSwitcher::SetupGeneralTab()
|
||||
ui->showTrayNotifications->setChecked(
|
||||
switcher->showSystemTrayNotifications);
|
||||
ui->uiHintsDisable->setChecked(switcher->disableHints);
|
||||
ui->disableComboBoxFilter->setChecked(
|
||||
switcher->disableFilterComboboxFilter);
|
||||
FilterComboBox::SetFilterBehaviourEnabled(
|
||||
!switcher->disableFilterComboboxFilter);
|
||||
ui->warnPluginLoadFailure->setChecked(switcher->warnPluginLoadFailure);
|
||||
ui->hideLegacyTabs->setChecked(switcher->hideLegacyTabs);
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ void SwitcherData::writeToStatusFile(const QString &msg)
|
||||
if (file.open(QIODevice::ReadWrite)) {
|
||||
QTextStream stream(&file);
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
stream << msg << endl;
|
||||
stream << msg << "\n";
|
||||
#else
|
||||
stream << msg << Qt::endl;
|
||||
#endif
|
||||
|
||||
@@ -332,7 +332,7 @@ bool IsFullscreen(const std::string &title)
|
||||
return windowStatesAreSet(title, states);
|
||||
}
|
||||
|
||||
std::optional<std::string> GetTextInWindow(const std::string &window)
|
||||
std::optional<std::string> GetTextInWindow(const std::string &)
|
||||
{
|
||||
// Not implemented
|
||||
return {};
|
||||
|
||||
@@ -39,6 +39,22 @@ const static std::map<MacroActionAudio::FadeType, std::string> fadeTypes = {
|
||||
constexpr auto fadeInterval = std::chrono::milliseconds(100);
|
||||
constexpr float minFade = 0.000001f;
|
||||
|
||||
// For backwards compatibility
|
||||
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(29, 0, 0)
|
||||
static float get_master_volume()
|
||||
{
|
||||
return 1.f;
|
||||
}
|
||||
|
||||
static void set_master_volume(float)
|
||||
{
|
||||
return;
|
||||
}
|
||||
#else
|
||||
auto get_master_volume = obs_get_master_volume;
|
||||
auto set_master_volume = obs_set_master_volume;
|
||||
#endif
|
||||
|
||||
void MacroActionAudio::SetFadeActive(bool value)
|
||||
{
|
||||
if (_action == Action::SOURCE_VOLUME) {
|
||||
@@ -87,7 +103,7 @@ void MacroActionAudio::SetVolume(float vol)
|
||||
obs_source_set_volume(s, vol);
|
||||
obs_source_release(s);
|
||||
} else {
|
||||
obs_set_master_volume(vol);
|
||||
set_master_volume(vol);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -102,7 +118,7 @@ float MacroActionAudio::GetVolume()
|
||||
curVol = obs_source_get_volume(s);
|
||||
obs_source_release(s);
|
||||
} else {
|
||||
curVol = obs_get_master_volume();
|
||||
curVol = get_master_volume();
|
||||
}
|
||||
return curVol;
|
||||
}
|
||||
@@ -287,15 +303,13 @@ std::string MacroActionAudio::GetShortDesc() const
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (const auto &[action, name] : actionTypes) {
|
||||
if (action == MacroActionAudio::Action::MONITOR) {
|
||||
if (obs_audio_monitoring_available()) {
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(action));
|
||||
}
|
||||
} else {
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(action));
|
||||
if (action == MacroActionAudio::Action::MONITOR &&
|
||||
!obs_audio_monitoring_available()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(action));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -473,6 +487,14 @@ void MacroActionAudioEdit::SetWidgetVisibility()
|
||||
_wait->setVisible(hasVolumeControl(_entryData->_action) &&
|
||||
_entryData->_fade);
|
||||
|
||||
// TODO: Remove this in a future version:
|
||||
if (_entryData->_action != MacroActionAudio::Action::MASTER_VOLUME &&
|
||||
obs_get_version() >= MAKE_SEMANTIC_VERSION(29, 0, 0)) {
|
||||
_actions->removeItem(_actions->findText(obs_module_text(
|
||||
actionTypes.at(MacroActionAudio::Action::MASTER_VOLUME)
|
||||
.c_str())));
|
||||
}
|
||||
|
||||
updateGeometry();
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
@@ -138,6 +138,7 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text)
|
||||
_entryData->reset();
|
||||
*_entryData = MacroActionFactory::Create(id, macro);
|
||||
(*_entryData)->SetIndex(idx);
|
||||
(*_entryData)->PostLoad();
|
||||
}
|
||||
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
|
||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||
@@ -204,7 +205,7 @@ void MacroActionEdit::SetEnableAppearance(bool value)
|
||||
SetDisableEffect(!value);
|
||||
}
|
||||
|
||||
std::shared_ptr<MacroSegment> MacroActionEdit::Data()
|
||||
std::shared_ptr<MacroSegment> MacroActionEdit::Data() const
|
||||
{
|
||||
return *_entryData;
|
||||
}
|
||||
@@ -236,10 +237,11 @@ void AdvSceneSwitcher::AddMacroAction(int idx)
|
||||
auto data = obs_data_create();
|
||||
macro->Actions().at(idx - 1)->Save(data);
|
||||
macro->Actions().at(idx)->Load(data);
|
||||
macro->Actions().at(idx)->PostLoad();
|
||||
obs_data_release(data);
|
||||
}
|
||||
macro->UpdateActionIndices();
|
||||
actionsList->Insert(
|
||||
ui->actionsList->Insert(
|
||||
idx,
|
||||
new MacroActionEdit(this, ¯o->Actions()[idx], id));
|
||||
SetActionData(*macro);
|
||||
@@ -263,7 +265,7 @@ void AdvSceneSwitcher::on_actionAdd_clicked()
|
||||
if (currentActionIdx != -1) {
|
||||
MacroActionSelectionChanged(currentActionIdx + 1);
|
||||
}
|
||||
actionsList->SetHelpMsgVisible(false);
|
||||
ui->actionsList->SetHelpMsgVisible(false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::RemoveMacroAction(int idx)
|
||||
@@ -279,7 +281,7 @@ void AdvSceneSwitcher::RemoveMacroAction(int idx)
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
actionsList->Remove(idx);
|
||||
ui->actionsList->Remove(idx);
|
||||
macro->Actions().erase(macro->Actions().begin() + idx);
|
||||
switcher->abortMacroWait = true;
|
||||
switcher->macroWaitCv.notify_all();
|
||||
@@ -322,10 +324,11 @@ void AdvSceneSwitcher::on_actionUp_clicked()
|
||||
MoveMacroActionUp(currentActionIdx);
|
||||
MacroActionSelectionChanged(currentActionIdx - 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_actionDown_clicked()
|
||||
{
|
||||
if (currentActionIdx == -1 ||
|
||||
currentActionIdx == actionsList->ContentLayout()->count() - 1) {
|
||||
currentActionIdx == ui->actionsList->ContentLayout()->count() - 1) {
|
||||
return;
|
||||
}
|
||||
MoveMacroActionDown(currentActionIdx);
|
||||
@@ -337,11 +340,82 @@ void AdvSceneSwitcher::on_actionBottom_clicked()
|
||||
if (currentActionIdx == -1) {
|
||||
return;
|
||||
}
|
||||
const int newIdx = actionsList->ContentLayout()->count() - 1;
|
||||
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);
|
||||
}
|
||||
ui->elseActionsList->SetHelpMsgVisible(false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_elseActionRemove_clicked()
|
||||
{
|
||||
if (currentElseActionIdx == -1) {
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
RemoveMacroElseAction((int)macro->Actions().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) {
|
||||
@@ -355,11 +429,11 @@ void AdvSceneSwitcher::SwapActions(Macro *m, int pos1, int pos2)
|
||||
iter_swap(m->Actions().begin() + pos1, m->Actions().begin() + pos2);
|
||||
m->UpdateActionIndices();
|
||||
auto widget1 = static_cast<MacroActionEdit *>(
|
||||
actionsList->ContentLayout()->takeAt(pos1)->widget());
|
||||
ui->actionsList->ContentLayout()->takeAt(pos1)->widget());
|
||||
auto widget2 = static_cast<MacroActionEdit *>(
|
||||
actionsList->ContentLayout()->takeAt(pos2 - 1)->widget());
|
||||
actionsList->Insert(pos1, widget2);
|
||||
actionsList->Insert(pos2, widget1);
|
||||
ui->actionsList->ContentLayout()->takeAt(pos2 - 1)->widget());
|
||||
ui->actionsList->Insert(pos1, widget2);
|
||||
ui->actionsList->Insert(pos2, widget1);
|
||||
SetActionData(*m);
|
||||
emit(MacroSegmentOrderChanged());
|
||||
}
|
||||
@@ -394,24 +468,159 @@ void AdvSceneSwitcher::MoveMacroActionDown(int idx)
|
||||
HighlightAction(idx + 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MacroActionSelectionChanged(int idx)
|
||||
void AdvSceneSwitcher::MacroElseActionSelectionChanged(int idx)
|
||||
{
|
||||
SetupMacroSegmentSelection(MacroSection::ELSE_ACTIONS, idx);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MacroElseActionReorder(int to, int from)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
actionsList->SetSelection(idx);
|
||||
conditionsList->SetSelection(-1);
|
||||
|
||||
if (idx < 0 || (unsigned)idx >= macro->Actions().size()) {
|
||||
currentActionIdx = -1;
|
||||
} else {
|
||||
currentActionIdx = idx;
|
||||
lastInteracted = MacroSection::ACTIONS;
|
||||
if (to == from || from < 0 || from > (int)macro->ElseActions().size() ||
|
||||
to < 0 || to > (int)macro->ElseActions().size()) {
|
||||
return;
|
||||
}
|
||||
currentConditionIdx = -1;
|
||||
HighlightControls();
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
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(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx > (int)macro->ElseActions().size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string id;
|
||||
if (idx - 1 >= 0) {
|
||||
id = macro->ElseActions().at(idx - 1)->GetId();
|
||||
} else {
|
||||
MacroActionSwitchScene temp(nullptr);
|
||||
id = temp.GetId();
|
||||
}
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
macro->ElseActions().emplace(
|
||||
macro->ElseActions().begin() + idx,
|
||||
MacroActionFactory::Create(id, macro.get()));
|
||||
if (idx - 1 >= 0) {
|
||||
OBSDataAutoRelease data = obs_data_create();
|
||||
macro->ElseActions().at(idx - 1)->Save(data);
|
||||
macro->ElseActions().at(idx)->Load(data);
|
||||
}
|
||||
macro->ElseActions().at(idx)->PostLoad();
|
||||
macro->UpdateElseActionIndices();
|
||||
ui->elseActionsList->Insert(
|
||||
idx, new MacroActionEdit(
|
||||
this, ¯o->ElseActions()[idx], id));
|
||||
SetElseActionData(*macro);
|
||||
}
|
||||
HighlightElseAction(idx);
|
||||
emit(MacroSegmentOrderChanged());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::RemoveMacroElseAction(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idx < 0 || idx >= (int)macro->ElseActions().size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
ui->elseActionsList->Remove(idx);
|
||||
macro->ElseActions().erase(macro->ElseActions().begin() + idx);
|
||||
switcher->abortMacroWait = true;
|
||||
switcher->macroWaitCv.notify_all();
|
||||
macro->UpdateElseActionIndices();
|
||||
SetActionData(*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);
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
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)
|
||||
@@ -431,8 +640,8 @@ void AdvSceneSwitcher::MacroActionReorder(int to, int from)
|
||||
macro->Actions().erase(macro->Actions().begin() + from);
|
||||
macro->Actions().insert(macro->Actions().begin() + to, action);
|
||||
macro->UpdateActionIndices();
|
||||
actionsList->ContentLayout()->insertItem(
|
||||
to, actionsList->ContentLayout()->takeAt(from));
|
||||
ui->actionsList->ContentLayout()->insertItem(
|
||||
to, ui->actionsList->ContentLayout()->takeAt(from));
|
||||
SetActionData(*macro);
|
||||
}
|
||||
HighlightAction(to);
|
||||
|
||||
@@ -50,7 +50,7 @@ private slots:
|
||||
void UpdateActionState();
|
||||
|
||||
private:
|
||||
std::shared_ptr<MacroSegment> Data();
|
||||
std::shared_ptr<MacroSegment> Data() const;
|
||||
void SetDisableEffect(bool);
|
||||
void SetEnableAppearance(bool);
|
||||
|
||||
|
||||
@@ -21,26 +21,69 @@ const static std::map<MacroActionFilter::Action, std::string> actionTypes = {
|
||||
"AdvSceneSwitcher.action.filter.type.settings"},
|
||||
};
|
||||
|
||||
bool MacroActionFilter::PerformAction()
|
||||
const static std::map<MacroActionFilter::SettingsInputMethod, std::string>
|
||||
inputMethods = {
|
||||
{MacroActionFilter::SettingsInputMethod::INDIVIDUAL_MANUAL,
|
||||
"AdvSceneSwitcher.action.filter.inputMethod.individualManual"},
|
||||
{MacroActionFilter::SettingsInputMethod::INDIVIDUAL_TEMPVAR,
|
||||
"AdvSceneSwitcher.action.filter.inputMethod.individualTempvar"},
|
||||
{MacroActionFilter::SettingsInputMethod::JSON_STRING,
|
||||
"AdvSceneSwitcher.action.filter.inputMethod.json"},
|
||||
};
|
||||
|
||||
static void performActionHelper(
|
||||
MacroActionFilter::Action action, const OBSWeakSource &filter,
|
||||
MacroActionFilter::SettingsInputMethod settingsInputMethod,
|
||||
const SourceSetting &setting, const std::string &manualSettingValue,
|
||||
const TempVariableRef &tempVar, Macro *macro,
|
||||
const StringVariable &settingsString)
|
||||
{
|
||||
auto s = obs_weak_source_get_source(_filter.GetFilter(_source));
|
||||
switch (_action) {
|
||||
case Action::ENABLE:
|
||||
obs_source_set_enabled(s, true);
|
||||
OBSSourceAutoRelease source = obs_weak_source_get_source(filter);
|
||||
switch (action) {
|
||||
case MacroActionFilter::Action::ENABLE:
|
||||
obs_source_set_enabled(source, true);
|
||||
break;
|
||||
case Action::DISABLE:
|
||||
obs_source_set_enabled(s, false);
|
||||
case MacroActionFilter::Action::DISABLE:
|
||||
obs_source_set_enabled(source, false);
|
||||
break;
|
||||
case Action::TOGGLE:
|
||||
obs_source_set_enabled(s, !obs_source_enabled(s));
|
||||
case MacroActionFilter::Action::TOGGLE:
|
||||
obs_source_set_enabled(source, !obs_source_enabled(source));
|
||||
break;
|
||||
case Action::SETTINGS:
|
||||
SetSourceSettings(s, _settings);
|
||||
case MacroActionFilter::Action::SETTINGS:
|
||||
switch (settingsInputMethod) {
|
||||
case MacroActionFilter::SettingsInputMethod::INDIVIDUAL_MANUAL:
|
||||
SetSourceSetting(source, setting, manualSettingValue);
|
||||
break;
|
||||
case MacroActionFilter::SettingsInputMethod::INDIVIDUAL_TEMPVAR: {
|
||||
auto var = tempVar.GetTempVariable(macro);
|
||||
if (!var) {
|
||||
break;
|
||||
}
|
||||
auto value = var->Value();
|
||||
if (!value) {
|
||||
break;
|
||||
}
|
||||
SetSourceSetting(source, setting, *value);
|
||||
break;
|
||||
}
|
||||
case MacroActionFilter::SettingsInputMethod::JSON_STRING:
|
||||
SetSourceSettings(source, settingsString);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
obs_source_release(s);
|
||||
}
|
||||
|
||||
bool MacroActionFilter::PerformAction()
|
||||
{
|
||||
auto filters = _filter.GetFilters(_source);
|
||||
for (const auto &filter : filters) {
|
||||
performActionHelper(_action, filter, _settingsInputMethod,
|
||||
_setting, _manualSettingValue, _tempVar,
|
||||
GetMacro(), _settingsString);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -64,7 +107,12 @@ bool MacroActionFilter::Save(obs_data_t *obj) const
|
||||
_source.Save(obj);
|
||||
_filter.Save(obj, "filter");
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
_settings.Save(obj, "settings");
|
||||
obs_data_set_int(obj, "inputMethod",
|
||||
static_cast<int>(_settingsInputMethod));
|
||||
_setting.Save(obj);
|
||||
_manualSettingValue.Save(obj, "manualSettingValue");
|
||||
_tempVar.Save(obj);
|
||||
_settingsString.Save(obj, "settings");
|
||||
obs_data_set_int(obj, "version", 1);
|
||||
return true;
|
||||
}
|
||||
@@ -85,7 +133,17 @@ bool MacroActionFilter::Load(obs_data_t *obj)
|
||||
} else {
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
}
|
||||
_settings.Load(obj, "settings");
|
||||
// TODO: Remove fallback in future version
|
||||
if (obs_data_has_user_value(obj, "inputMethod")) {
|
||||
_settingsInputMethod = static_cast<SettingsInputMethod>(
|
||||
obs_data_get_int(obj, "inputMethod"));
|
||||
} else {
|
||||
_settingsInputMethod = SettingsInputMethod::JSON_STRING;
|
||||
}
|
||||
_setting.Load(obj);
|
||||
_settingsString.Load(obj, "settings");
|
||||
_manualSettingValue.Load(obj, "manualSettingValue");
|
||||
_tempVar.Load(obj, GetMacro());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -104,6 +162,15 @@ static inline void populateActionSelection(QComboBox *list)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void populateSettingsInputMethods(QComboBox *list)
|
||||
{
|
||||
list->clear();
|
||||
for (const auto &[value, name] : inputMethods) {
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(value));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionFilter> entryData)
|
||||
: QWidget(parent),
|
||||
@@ -112,7 +179,12 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
_actions(new QComboBox()),
|
||||
_getSettings(new QPushButton(obs_module_text(
|
||||
"AdvSceneSwitcher.action.filter.getSettings"))),
|
||||
_settings(new VariableTextEdit(this))
|
||||
_settingsLayout(new QHBoxLayout()),
|
||||
_settingsInputMethods(new QComboBox(this)),
|
||||
_manualSettingValue(new VariableTextEdit(this, 5, 1, 1)),
|
||||
_tempVars(new TempVariableSelection(this)),
|
||||
_filterSettings(new SourceSettingSelection(this)),
|
||||
_settingsString(new VariableTextEdit(this))
|
||||
{
|
||||
_filters->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||
|
||||
@@ -121,6 +193,8 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
sources.sort();
|
||||
_sources->SetSourceNameList(sources);
|
||||
|
||||
populateSettingsInputMethods(_settingsInputMethods);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_sources,
|
||||
@@ -131,27 +205,48 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
||||
SLOT(FilterChanged(const FilterSelection &)));
|
||||
QWidget::connect(_getSettings, SIGNAL(clicked()), this,
|
||||
SLOT(GetSettingsClicked()));
|
||||
QWidget::connect(_settings, SIGNAL(textChanged()), this,
|
||||
SLOT(SettingsChanged()));
|
||||
QWidget::connect(_settingsString, SIGNAL(textChanged()), this,
|
||||
SLOT(SettingsStringChanged()));
|
||||
QWidget::connect(_tempVars,
|
||||
SIGNAL(SelectionChanged(const TempVariableRef &)),
|
||||
this, SLOT(SelectionChanged(const TempVariableRef &)));
|
||||
QWidget::connect(_settingsInputMethods,
|
||||
SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(SettingsInputMethodChanged(int)));
|
||||
QWidget::connect(_manualSettingValue, SIGNAL(textChanged()), this,
|
||||
SLOT(ManualSettingsValueChanged()));
|
||||
QWidget::connect(_filterSettings,
|
||||
SIGNAL(SelectionChanged(const SourceSetting &)), this,
|
||||
SLOT(SelectionChanged(const SourceSetting &)));
|
||||
|
||||
QHBoxLayout *entryLayout = new QHBoxLayout;
|
||||
auto entrylayout = new QHBoxLayout;
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{sources}}", _sources}, {"{{filters}}", _filters},
|
||||
{"{{actions}}", _actions}, {"{{settings}}", _settings},
|
||||
{"{{sources}}", _sources},
|
||||
{"{{filters}}", _filters},
|
||||
{"{{actions}}", _actions},
|
||||
{"{{settings}}", _filterSettings},
|
||||
{"{{settingsInputMethod}}", _settingsInputMethods},
|
||||
{"{{settingValue}}", _manualSettingValue},
|
||||
{"{{tempVar}}", _tempVars},
|
||||
{"{{getSettings}}", _getSettings},
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.filter.entry"),
|
||||
entryLayout, widgetPlaceholders);
|
||||
entrylayout, widgetPlaceholders);
|
||||
_settingsLayout->setContentsMargins(0, 0, 0, 0);
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.action.filter.entry.settings"),
|
||||
_settingsLayout, widgetPlaceholders);
|
||||
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||
auto buttonLayout = new QHBoxLayout;
|
||||
buttonLayout->addWidget(_getSettings);
|
||||
buttonLayout->addStretch();
|
||||
buttonLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
mainLayout->addWidget(_settings);
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entrylayout);
|
||||
mainLayout->addLayout(_settingsLayout);
|
||||
mainLayout->addWidget(_settingsString);
|
||||
mainLayout->addLayout(buttonLayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
@@ -169,12 +264,16 @@ void MacroActionFilterEdit::UpdateEntryData()
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_sources->SetSource(_entryData->_source);
|
||||
_filters->SetFilter(_entryData->_source, _entryData->_filter);
|
||||
_settings->setPlainText(_entryData->_settings);
|
||||
SetWidgetVisibility(_entryData->_action ==
|
||||
MacroActionFilter::Action::SETTINGS);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
_settingsString->setPlainText(_entryData->_settingsString);
|
||||
const auto filters =
|
||||
_entryData->_filter.GetFilters(_entryData->_source);
|
||||
_filterSettings->SetSource(filters.empty() ? nullptr : filters.at(0));
|
||||
_filterSettings->SetSetting(_entryData->_setting);
|
||||
_settingsInputMethods->setCurrentIndex(_settingsInputMethods->findData(
|
||||
static_cast<int>(_entryData->_settingsInputMethod)));
|
||||
_tempVars->SetVariable(_entryData->_tempVar);
|
||||
_manualSettingValue->setPlainText(_entryData->_manualSettingValue);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::SourceChanged(const SourceSelection &source)
|
||||
@@ -193,8 +292,13 @@ void MacroActionFilterEdit::FilterChanged(const FilterSelection &filter)
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_filter = filter;
|
||||
{
|
||||
auto lock = LockContext();
|
||||
_entryData->_filter = filter;
|
||||
}
|
||||
const auto filters =
|
||||
_entryData->_filter.GetFilters(_entryData->_source);
|
||||
_filterSettings->SetSource(filters.empty() ? nullptr : filters.at(0));
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
@@ -207,38 +311,125 @@ void MacroActionFilterEdit::ActionChanged(int value)
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_action = static_cast<MacroActionFilter::Action>(value);
|
||||
SetWidgetVisibility(_entryData->_action ==
|
||||
MacroActionFilter::Action::SETTINGS);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::GetSettingsClicked()
|
||||
{
|
||||
if (_loading || !_entryData ||
|
||||
!_entryData->_filter.GetFilter(_entryData->_source)) {
|
||||
_entryData->_filter.GetFilters(_entryData->_source).empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
_settings->setPlainText(FormatJsonString(GetSourceSettings(
|
||||
_entryData->_filter.GetFilter(_entryData->_source))));
|
||||
switch (_entryData->_settingsInputMethod) {
|
||||
case MacroActionFilter::SettingsInputMethod::INDIVIDUAL_MANUAL: {
|
||||
const auto filters =
|
||||
_entryData->_filter.GetFilters(_entryData->_source);
|
||||
_manualSettingValue->setPlainText(GetSourceSettingValue(
|
||||
filters.empty() ? nullptr : filters.at(0),
|
||||
_entryData->_setting));
|
||||
break;
|
||||
}
|
||||
case MacroActionFilter::SettingsInputMethod::INDIVIDUAL_TEMPVAR:
|
||||
break;
|
||||
case MacroActionFilter::SettingsInputMethod::JSON_STRING: {
|
||||
const auto filters =
|
||||
_entryData->_filter.GetFilters(_entryData->_source);
|
||||
_settingsString->setPlainText(
|
||||
FormatJsonString(GetSourceSettings(
|
||||
filters.empty() ? nullptr : filters.at(0))));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::SettingsChanged()
|
||||
void MacroActionFilterEdit::SettingsStringChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_settings = _settings->toPlainText().toStdString();
|
||||
_entryData->_settingsString =
|
||||
_settingsString->toPlainText().toStdString();
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::SetWidgetVisibility(bool showSettings)
|
||||
void MacroActionFilterEdit::SettingsInputMethodChanged(int idx)
|
||||
{
|
||||
_settings->setVisible(showSettings);
|
||||
_getSettings->setVisible(showSettings);
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_settingsInputMethod =
|
||||
static_cast<MacroActionFilter::SettingsInputMethod>(
|
||||
_settingsInputMethods->itemData(idx).toInt());
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::SelectionChanged(const TempVariableRef &var)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_tempVar = var;
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::SelectionChanged(const SourceSetting &setting)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_setting = setting;
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::ManualSettingsValueChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_manualSettingValue =
|
||||
_manualSettingValue->toPlainText().toStdString();
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionFilterEdit::SetWidgetVisibility()
|
||||
{
|
||||
SetLayoutVisible(_settingsLayout,
|
||||
_entryData->_action ==
|
||||
MacroActionFilter::Action::SETTINGS);
|
||||
_filterSettings->setVisible(
|
||||
_entryData->_action == MacroActionFilter::Action::SETTINGS &&
|
||||
_entryData->_settingsInputMethod !=
|
||||
MacroActionFilter::SettingsInputMethod::JSON_STRING);
|
||||
_settingsString->setVisible(
|
||||
_entryData->_action == MacroActionFilter::Action::SETTINGS &&
|
||||
_entryData->_settingsInputMethod ==
|
||||
MacroActionFilter::SettingsInputMethod::JSON_STRING);
|
||||
_getSettings->setVisible(_entryData->_action ==
|
||||
MacroActionFilter::Action::SETTINGS);
|
||||
_tempVars->setVisible(_entryData->_action ==
|
||||
MacroActionFilter::Action::SETTINGS &&
|
||||
_entryData->_settingsInputMethod ==
|
||||
MacroActionFilter::SettingsInputMethod::
|
||||
INDIVIDUAL_TEMPVAR);
|
||||
_manualSettingValue->setVisible(
|
||||
_entryData->_action == MacroActionFilter::Action::SETTINGS &&
|
||||
_entryData->_settingsInputMethod ==
|
||||
MacroActionFilter::SettingsInputMethod::
|
||||
INDIVIDUAL_MANUAL);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "variable-text-edit.hpp"
|
||||
#include "source-selection.hpp"
|
||||
#include "filter-selection.hpp"
|
||||
#include "source-setting.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QSpinBox>
|
||||
@@ -31,10 +32,21 @@ public:
|
||||
SETTINGS,
|
||||
};
|
||||
|
||||
enum class SettingsInputMethod {
|
||||
INDIVIDUAL_MANUAL,
|
||||
INDIVIDUAL_TEMPVAR,
|
||||
JSON_STRING,
|
||||
};
|
||||
SettingsInputMethod _settingsInputMethod =
|
||||
SettingsInputMethod::INDIVIDUAL_MANUAL;
|
||||
|
||||
SourceSelection _source;
|
||||
FilterSelection _filter;
|
||||
Action _action = Action::ENABLE;
|
||||
StringVariable _settings = "";
|
||||
StringVariable _settingsString = "";
|
||||
TempVariableRef _tempVar;
|
||||
StringVariable _manualSettingValue = "";
|
||||
SourceSetting _setting;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
@@ -62,7 +74,11 @@ private slots:
|
||||
void FilterChanged(const FilterSelection &);
|
||||
void ActionChanged(int value);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
void SettingsStringChanged();
|
||||
void SettingsInputMethodChanged(int);
|
||||
void SelectionChanged(const TempVariableRef &);
|
||||
void SelectionChanged(const SourceSetting &);
|
||||
void ManualSettingsValueChanged();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
@@ -71,11 +87,17 @@ protected:
|
||||
FilterSelectionWidget *_filters;
|
||||
QComboBox *_actions;
|
||||
QPushButton *_getSettings;
|
||||
VariableTextEdit *_settings;
|
||||
QHBoxLayout *_settingsLayout;
|
||||
QComboBox *_settingsInputMethods;
|
||||
VariableTextEdit *_manualSettingValue;
|
||||
TempVariableSelection *_tempVars;
|
||||
SourceSettingSelection *_filterSettings;
|
||||
VariableTextEdit *_settingsString;
|
||||
|
||||
std::shared_ptr<MacroActionFilter> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility(bool);
|
||||
void SetWidgetVisibility();
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "platform-funcs.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <thread>
|
||||
#include <obs-interaction.h>
|
||||
|
||||
namespace advss {
|
||||
@@ -723,7 +724,7 @@ static QString getHotkeyDescriptionByName(const std::string &name)
|
||||
QString description = "";
|
||||
} params;
|
||||
|
||||
auto func = [](void *param, obs_hotkey_id id, obs_hotkey_t *hotkey) {
|
||||
auto func = [](void *param, obs_hotkey_id, obs_hotkey_t *hotkey) {
|
||||
auto params = static_cast<Parameters *>(param);
|
||||
std::string name = obs_hotkey_get_name(hotkey);
|
||||
addNamePrefix(name, hotkey);
|
||||
|
||||
@@ -49,7 +49,7 @@ bool MacroActionMacro::PerformAction()
|
||||
break;
|
||||
case Action::RUN:
|
||||
if (!macro->Paused()) {
|
||||
macro->PerformActions();
|
||||
macro->PerformActions(true, false, true);
|
||||
}
|
||||
break;
|
||||
case Action::STOP:
|
||||
|
||||
@@ -10,22 +10,45 @@ bool MacroActionMedia::_registered = MacroActionFactory::Register(
|
||||
{MacroActionMedia::Create, MacroActionMediaEdit::Create,
|
||||
"AdvSceneSwitcher.action.media"});
|
||||
|
||||
const static std::map<MediaAction, std::string> actionTypes = {
|
||||
{MediaAction::PLAY, "AdvSceneSwitcher.action.media.type.play"},
|
||||
{MediaAction::PAUSE, "AdvSceneSwitcher.action.media.type.pause"},
|
||||
{MediaAction::STOP, "AdvSceneSwitcher.action.media.type.stop"},
|
||||
{MediaAction::RESTART, "AdvSceneSwitcher.action.media.type.restart"},
|
||||
{MediaAction::NEXT, "AdvSceneSwitcher.action.media.type.next"},
|
||||
{MediaAction::PREVIOUS, "AdvSceneSwitcher.action.media.type.previous"},
|
||||
{MediaAction::SEEK, "AdvSceneSwitcher.action.media.type.seek"},
|
||||
const static std::map<MacroActionMedia::Action, std::string> actionTypes = {
|
||||
{MacroActionMedia::Action::PLAY,
|
||||
"AdvSceneSwitcher.action.media.type.play"},
|
||||
{MacroActionMedia::Action::PAUSE,
|
||||
"AdvSceneSwitcher.action.media.type.pause"},
|
||||
{MacroActionMedia::Action::STOP,
|
||||
"AdvSceneSwitcher.action.media.type.stop"},
|
||||
{MacroActionMedia::Action::RESTART,
|
||||
"AdvSceneSwitcher.action.media.type.restart"},
|
||||
{MacroActionMedia::Action::NEXT,
|
||||
"AdvSceneSwitcher.action.media.type.next"},
|
||||
{MacroActionMedia::Action::PREVIOUS,
|
||||
"AdvSceneSwitcher.action.media.type.previous"},
|
||||
{MacroActionMedia::Action::SEEK_DURATION,
|
||||
"AdvSceneSwitcher.action.media.type.seek.duration"},
|
||||
{MacroActionMedia::Action::SEEK_PERCENTAGE,
|
||||
"AdvSceneSwitcher.action.media.type.seek.percentage"},
|
||||
};
|
||||
|
||||
std::string MacroActionMedia::GetShortDesc() const
|
||||
{
|
||||
return _mediaSource.ToString();
|
||||
}
|
||||
|
||||
void MacroActionMedia::SeekToPercentage(obs_source_t *source) const
|
||||
{
|
||||
auto totalTimeMs = obs_source_media_get_duration(source);
|
||||
auto percentageTimeMs = round(totalTimeMs * _seekPercentage / 100);
|
||||
|
||||
obs_source_media_set_time(source, percentageTimeMs);
|
||||
}
|
||||
|
||||
bool MacroActionMedia::PerformAction()
|
||||
{
|
||||
auto source = obs_weak_source_get_source(_mediaSource.GetSource());
|
||||
obs_media_state state = obs_source_media_get_state(source);
|
||||
|
||||
switch (_action) {
|
||||
case MediaAction::PLAY:
|
||||
case Action::PLAY:
|
||||
if (state == OBS_MEDIA_STATE_STOPPED ||
|
||||
state == OBS_MEDIA_STATE_ENDED) {
|
||||
obs_source_media_restart(source);
|
||||
@@ -33,27 +56,31 @@ bool MacroActionMedia::PerformAction()
|
||||
obs_source_media_play_pause(source, false);
|
||||
}
|
||||
break;
|
||||
case MediaAction::PAUSE:
|
||||
case Action::PAUSE:
|
||||
obs_source_media_play_pause(source, true);
|
||||
break;
|
||||
case MediaAction::STOP:
|
||||
case Action::STOP:
|
||||
obs_source_media_stop(source);
|
||||
break;
|
||||
case MediaAction::RESTART:
|
||||
case Action::RESTART:
|
||||
obs_source_media_restart(source);
|
||||
break;
|
||||
case MediaAction::NEXT:
|
||||
case Action::NEXT:
|
||||
obs_source_media_next(source);
|
||||
break;
|
||||
case MediaAction::PREVIOUS:
|
||||
case Action::PREVIOUS:
|
||||
obs_source_media_previous(source);
|
||||
break;
|
||||
case MediaAction::SEEK:
|
||||
obs_source_media_set_time(source, _seek.Milliseconds());
|
||||
case Action::SEEK_DURATION:
|
||||
obs_source_media_set_time(source, _seekDuration.Milliseconds());
|
||||
break;
|
||||
case Action::SEEK_PERCENTAGE:
|
||||
SeekToPercentage(source);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
obs_source_release(source);
|
||||
return true;
|
||||
}
|
||||
@@ -73,39 +100,42 @@ void MacroActionMedia::LogAction() const
|
||||
bool MacroActionMedia::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
_mediaSource.Save(obj, "mediaSource");
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
_seek.Save(obj);
|
||||
_seekDuration.Save(obj);
|
||||
_seekPercentage.Save(obj, "seekPercentage");
|
||||
_mediaSource.Save(obj, "mediaSource");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionMedia::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
_seekDuration.Load(obj);
|
||||
_seekPercentage.Load(obj, "seekPercentage");
|
||||
_mediaSource.Load(obj, "mediaSource");
|
||||
_action = static_cast<MediaAction>(obs_data_get_int(obj, "action"));
|
||||
_seek.Load(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionMedia::GetShortDesc() const
|
||||
{
|
||||
return _mediaSource.ToString();
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
for (const auto &[_, name] : actionTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionMediaEdit::MacroActionMediaEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionMedia> entryData)
|
||||
: QWidget(parent),
|
||||
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
||||
_actions(new QComboBox()),
|
||||
_seek(new DurationSelection())
|
||||
_seekDuration(new DurationSelection()),
|
||||
_seekPercentage(new SliderSpinBox(
|
||||
0, 100,
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.media.seek.percentage.label"))),
|
||||
_sources(new SourceSelectionWidget(this, QStringList(), true))
|
||||
{
|
||||
populateActionSelection(_actions);
|
||||
auto sources = GetMediaSourceNames();
|
||||
@@ -114,39 +144,67 @@ MacroActionMediaEdit::MacroActionMediaEdit(
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_seekDuration,
|
||||
SIGNAL(DurationChanged(const Duration &)), this,
|
||||
SLOT(SeekDurationChanged(const Duration &)));
|
||||
QWidget::connect(
|
||||
_seekPercentage,
|
||||
SIGNAL(DoubleValueChanged(const NumberVariable<double> &)),
|
||||
this,
|
||||
SLOT(SeekPercentageChanged(const NumberVariable<double> &)));
|
||||
QWidget::connect(_sources,
|
||||
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||
SLOT(SourceChanged(const SourceSelection &)));
|
||||
QWidget::connect(_seek, SIGNAL(DurationChanged(const Duration &)), this,
|
||||
SLOT(DurationChanged(const Duration &)));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
auto layout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{mediaSources}}", _sources},
|
||||
{"{{actions}}", _actions},
|
||||
{"{{duration}}", _seek},
|
||||
{"{{seekDuration}}", _seekDuration},
|
||||
{"{{seekPercentage}}", _seekPercentage},
|
||||
{"{{mediaSources}}", _sources},
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.media.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
layout, widgetPlaceholders);
|
||||
setLayout(layout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionMediaEdit::UpdateEntryData()
|
||||
void MacroActionMediaEdit::ActionChanged(int value)
|
||||
{
|
||||
if (!_entryData) {
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_sources->SetSource(_entryData->_mediaSource);
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_seek->SetDuration(_entryData->_seek);
|
||||
auto lock = LockContext();
|
||||
_entryData->_action = static_cast<MacroActionMedia::Action>(value);
|
||||
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionMediaEdit::SeekDurationChanged(const Duration &seekDuration)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_seekDuration = seekDuration;
|
||||
}
|
||||
|
||||
void MacroActionMediaEdit::SeekPercentageChanged(
|
||||
const NumberVariable<double> &seekPercentage)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_seekPercentage = seekPercentage;
|
||||
}
|
||||
|
||||
void MacroActionMediaEdit::SourceChanged(const SourceSelection &source)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
@@ -159,34 +217,32 @@ void MacroActionMediaEdit::SourceChanged(const SourceSelection &source)
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionMediaEdit::ActionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_action = static_cast<MediaAction>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionMediaEdit::DurationChanged(const Duration &dur)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_seek = dur;
|
||||
}
|
||||
|
||||
void MacroActionMediaEdit::SetWidgetVisibility()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
_seek->setVisible(_entryData->_action == MediaAction::SEEK);
|
||||
|
||||
_seekDuration->setVisible(_entryData->_action ==
|
||||
MacroActionMedia::Action::SEEK_DURATION);
|
||||
_seekPercentage->setVisible(_entryData->_action ==
|
||||
MacroActionMedia::Action::SEEK_PERCENTAGE);
|
||||
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
void MacroActionMediaEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_seekDuration->SetDuration(_entryData->_seekDuration);
|
||||
_seekPercentage->SetDoubleValue(_entryData->_seekPercentage);
|
||||
_sources->SetSource(_entryData->_mediaSource);
|
||||
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,42 +1,45 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "duration-control.hpp"
|
||||
#include "slider-spinbox.hpp"
|
||||
#include "source-selection.hpp"
|
||||
|
||||
#include <QSpinBox>
|
||||
#include <QHBoxLayout>
|
||||
|
||||
namespace advss {
|
||||
|
||||
enum class MediaAction {
|
||||
PLAY,
|
||||
PAUSE,
|
||||
STOP,
|
||||
RESTART,
|
||||
NEXT,
|
||||
PREVIOUS,
|
||||
SEEK,
|
||||
};
|
||||
|
||||
class MacroActionMedia : public MacroAction {
|
||||
public:
|
||||
MacroActionMedia(Macro *m) : MacroAction(m) {}
|
||||
bool PerformAction();
|
||||
void LogAction() const;
|
||||
bool Save(obs_data_t *obj) const;
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc() const;
|
||||
std::string GetId() const { return id; };
|
||||
static std::shared_ptr<MacroAction> Create(Macro *m)
|
||||
{
|
||||
return std::make_shared<MacroActionMedia>(m);
|
||||
}
|
||||
std::string GetId() const { return id; };
|
||||
std::string GetShortDesc() const;
|
||||
|
||||
bool PerformAction();
|
||||
void LogAction() const;
|
||||
bool Save(obs_data_t *obj) const;
|
||||
bool Load(obs_data_t *obj);
|
||||
|
||||
enum class Action {
|
||||
PLAY,
|
||||
PAUSE,
|
||||
STOP,
|
||||
RESTART,
|
||||
NEXT,
|
||||
PREVIOUS,
|
||||
SEEK_DURATION,
|
||||
SEEK_PERCENTAGE,
|
||||
};
|
||||
|
||||
Action _action = Action::PLAY;
|
||||
Duration _seekDuration;
|
||||
DoubleVariable _seekPercentage = 50;
|
||||
SourceSelection _mediaSource;
|
||||
MediaAction _action = MediaAction::PLAY;
|
||||
Duration _seek;
|
||||
|
||||
private:
|
||||
void SeekToPercentage(obs_source_t *source) const;
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
@@ -48,7 +51,6 @@ public:
|
||||
MacroActionMediaEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionMedia> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
@@ -56,24 +58,27 @@ public:
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroActionMedia>(action));
|
||||
}
|
||||
void UpdateEntryData();
|
||||
|
||||
private slots:
|
||||
void SourceChanged(const SourceSelection &);
|
||||
void ActionChanged(int value);
|
||||
void DurationChanged(const Duration &value);
|
||||
void SeekDurationChanged(const Duration &seekDuration);
|
||||
void
|
||||
SeekPercentageChanged(const NumberVariable<double> &seekPercentage);
|
||||
void SourceChanged(const SourceSelection &source);
|
||||
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SourceSelectionWidget *_sources;
|
||||
QComboBox *_actions;
|
||||
DurationSelection *_seek;
|
||||
std::shared_ptr<MacroActionMedia> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
|
||||
QHBoxLayout *_mainLayout;
|
||||
QComboBox *_actions;
|
||||
DurationSelection *_seekDuration;
|
||||
SliderSpinBox *_seekPercentage;
|
||||
SourceSelectionWidget *_sources;
|
||||
|
||||
std::shared_ptr<MacroActionMedia> _entryData;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -57,6 +57,12 @@ bool MacroActionProjector::PerformAction()
|
||||
break;
|
||||
}
|
||||
|
||||
if (_fullscreen && _monitor == -1) {
|
||||
blog(LOG_INFO, "refusing to open fullscreen projector"
|
||||
" with invalid display selection");
|
||||
return true;
|
||||
}
|
||||
|
||||
obs_frontend_open_projector(type, _fullscreen ? _monitor : -1, "",
|
||||
name.c_str());
|
||||
|
||||
@@ -85,6 +91,7 @@ bool MacroActionProjector::Save(obs_data_t *obj) const
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_int(obj, "type", static_cast<int>(_type));
|
||||
obs_data_set_int(obj, "monitor", _monitor);
|
||||
obs_data_set_string(obj, "monitorName", _monitorName.c_str());
|
||||
obs_data_set_bool(obj, "fullscreen", _fullscreen);
|
||||
_scene.Save(obj);
|
||||
_source.Save(obj);
|
||||
@@ -96,12 +103,50 @@ bool MacroActionProjector::Load(obs_data_t *obj)
|
||||
MacroAction::Load(obj);
|
||||
_type = static_cast<Type>(obs_data_get_int(obj, "type"));
|
||||
_monitor = obs_data_get_int(obj, "monitor");
|
||||
_monitorName = obs_data_get_string(obj, "monitorName");
|
||||
_fullscreen = obs_data_get_bool(obj, "fullscreen");
|
||||
_scene.Load(obj);
|
||||
_source.Load(obj);
|
||||
|
||||
if (MonitorSetupChanged()) {
|
||||
blog(LOG_INFO, "monitor setup seems to have changed! "
|
||||
"resetting projector action monitor selection!");
|
||||
_monitor = -1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionProjector::SetMonitor(int idx)
|
||||
{
|
||||
_monitor = idx;
|
||||
auto monitorNames = GetMonitorNames();
|
||||
if (_monitor < 0 || _monitor >= monitorNames.size()) {
|
||||
// Monitor setup changed while settings were selected?
|
||||
_monitorName = "";
|
||||
return;
|
||||
}
|
||||
_monitorName = monitorNames.at(_monitor).toStdString();
|
||||
}
|
||||
|
||||
int MacroActionProjector::GetMonitor() const
|
||||
{
|
||||
return _monitor;
|
||||
}
|
||||
|
||||
bool MacroActionProjector::MonitorSetupChanged()
|
||||
{
|
||||
if (_monitorName.empty()) {
|
||||
return false;
|
||||
}
|
||||
auto monitorNames = GetMonitorNames();
|
||||
if (_monitor < 0 || _monitor >= monitorNames.size()) {
|
||||
return true;
|
||||
}
|
||||
return monitorNames.at(_monitor) !=
|
||||
QString::fromStdString(_monitorName);
|
||||
}
|
||||
|
||||
static inline void populateSelectionTypes(QComboBox *list)
|
||||
{
|
||||
for (auto entry : selectionTypes) {
|
||||
@@ -134,6 +179,8 @@ MacroActionProjectorEdit::MacroActionProjectorEdit(
|
||||
sources.sort();
|
||||
_sources->SetSourceNameList(sources);
|
||||
_monitors->addItems(GetMonitorNames());
|
||||
_monitors->setPlaceholderText(
|
||||
obs_module_text("AdvSceneSwitcher.selectDisplay"));
|
||||
|
||||
QWidget::connect(_windowTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(WindowTypeChanged(int)));
|
||||
@@ -177,7 +224,7 @@ void MacroActionProjectorEdit::UpdateEntryData()
|
||||
_types->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
_sources->SetSource(_entryData->_source);
|
||||
_monitors->setCurrentIndex(_entryData->_monitor);
|
||||
_monitors->setCurrentIndex(_entryData->GetMonitor());
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
@@ -208,7 +255,7 @@ void MacroActionProjectorEdit::MonitorChanged(int value)
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_monitor = value;
|
||||
_entryData->SetMonitor(value);
|
||||
}
|
||||
|
||||
void MacroActionProjectorEdit::WindowTypeChanged(int)
|
||||
|
||||
@@ -17,6 +17,8 @@ public:
|
||||
{
|
||||
return std::make_shared<MacroActionProjector>(m);
|
||||
}
|
||||
void SetMonitor(int);
|
||||
int GetMonitor() const;
|
||||
|
||||
enum class Type {
|
||||
SOURCE,
|
||||
@@ -29,10 +31,15 @@ public:
|
||||
Type _type = Type::SCENE;
|
||||
SourceSelection _source;
|
||||
SceneSelection _scene;
|
||||
int _monitor = 0;
|
||||
bool _fullscreen = true;
|
||||
|
||||
private:
|
||||
bool MonitorSetupChanged();
|
||||
|
||||
int _monitor = -1;
|
||||
// Only used to detect display setup changes
|
||||
std::string _monitorName = "";
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
@@ -54,12 +54,12 @@ bool MacroActionRandom::PerformAction()
|
||||
}
|
||||
if (macros.size() == 1) {
|
||||
lastRandomMacro = macros[0];
|
||||
return macros[0]->PerformActions();
|
||||
return macros[0]->PerformActions(true);
|
||||
}
|
||||
srand((unsigned int)time(0));
|
||||
size_t idx = std::rand() % (macros.size());
|
||||
lastRandomMacro = macros[idx];
|
||||
return macros[idx]->PerformActions();
|
||||
return macros[idx]->PerformActions(true);
|
||||
}
|
||||
|
||||
void MacroActionRandom::LogAction() const
|
||||
|
||||
@@ -12,7 +12,15 @@ const std::string MacroActionSwitchScene::id = "scene_switch";
|
||||
bool MacroActionSwitchScene::_registered = MacroActionFactory::Register(
|
||||
MacroActionSwitchScene::id,
|
||||
{MacroActionSwitchScene::Create, MacroActionSwitchSceneEdit::Create,
|
||||
"AdvSceneSwitcher.action.switchScene"});
|
||||
"AdvSceneSwitcher.action.scene"});
|
||||
|
||||
const static std::map<MacroActionSwitchScene::SceneType, std::string>
|
||||
sceneTypes = {
|
||||
{MacroActionSwitchScene::SceneType::PROGRAM,
|
||||
"AdvSceneSwitcher.action.scene.type.program"},
|
||||
{MacroActionSwitchScene::SceneType::PREVIEW,
|
||||
"AdvSceneSwitcher.action.scene.type.preview"},
|
||||
};
|
||||
|
||||
static void waitForTransitionChange(OBSWeakSource &transition,
|
||||
std::unique_lock<std::mutex> *lock,
|
||||
@@ -126,6 +134,14 @@ bool MacroActionSwitchScene::WaitForTransition(OBSWeakSource &scene,
|
||||
bool MacroActionSwitchScene::PerformAction()
|
||||
{
|
||||
auto scene = _scene.GetScene();
|
||||
|
||||
if (_sceneType == SceneType::PREVIEW) {
|
||||
OBSSourceAutoRelease previewScneSource =
|
||||
obs_weak_source_get_source(scene);
|
||||
obs_frontend_set_current_preview_scene(previewScneSource);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto transition = _transition.GetTransition();
|
||||
SwitchScene({scene, transition, (int)(_duration.Milliseconds())},
|
||||
obs_frontend_preview_program_mode_active());
|
||||
@@ -137,24 +153,9 @@ bool MacroActionSwitchScene::PerformAction()
|
||||
|
||||
void MacroActionSwitchScene::LogAction() const
|
||||
{
|
||||
auto t = _scene.GetType();
|
||||
auto sceneName = GetWeakSourceName(_scene.GetScene(false));
|
||||
switch (t) {
|
||||
case SceneSelection::Type::SCENE:
|
||||
vblog(LOG_INFO, "switch to scene '%s'",
|
||||
_scene.ToString(true).c_str());
|
||||
break;
|
||||
case SceneSelection::Type::GROUP:
|
||||
vblog(LOG_INFO, "switch to scene '%s' (scene group '%s')",
|
||||
sceneName.c_str(), _scene.ToString(true).c_str());
|
||||
break;
|
||||
case SceneSelection::Type::PREVIOUS:
|
||||
vblog(LOG_INFO, "switch to previous scene '%s'",
|
||||
sceneName.c_str());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
vblog(LOG_INFO, "switch%s scene to '%s'",
|
||||
_sceneType == SceneType::PREVIEW ? " preview" : "",
|
||||
_scene.ToString(true).c_str());
|
||||
}
|
||||
|
||||
bool MacroActionSwitchScene::Save(obs_data_t *obj) const
|
||||
@@ -165,6 +166,7 @@ bool MacroActionSwitchScene::Save(obs_data_t *obj) const
|
||||
_duration.Save(obj);
|
||||
obs_data_set_bool(obj, "blockUntilTransitionDone",
|
||||
_blockUntilTransitionDone);
|
||||
obs_data_set_int(obj, "sceneType", static_cast<int>(_sceneType));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -176,6 +178,7 @@ bool MacroActionSwitchScene::Load(obs_data_t *obj)
|
||||
_duration.Load(obj);
|
||||
_blockUntilTransitionDone =
|
||||
obs_data_get_bool(obj, "blockUntilTransitionDone");
|
||||
_sceneType = static_cast<SceneType>(obs_data_get_int(obj, "sceneType"));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -184,6 +187,13 @@ std::string MacroActionSwitchScene::GetShortDesc() const
|
||||
return _scene.ToString();
|
||||
}
|
||||
|
||||
static inline void populateTypeSelection(QComboBox *list)
|
||||
{
|
||||
for (const auto &[_, name] : sceneTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionSwitchSceneEdit::MacroActionSwitchSceneEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionSwitchScene> entryData)
|
||||
: QWidget(parent),
|
||||
@@ -192,9 +202,11 @@ MacroActionSwitchSceneEdit::MacroActionSwitchSceneEdit(
|
||||
_duration(new DurationSelection(parent, false)),
|
||||
_blockUntilTransitionDone(new QCheckBox(obs_module_text(
|
||||
"AdvSceneSwitcher.action.scene.blockUntilTransitionDone"))),
|
||||
_sceneTypes(new QComboBox()),
|
||||
_entryLayout(new QHBoxLayout())
|
||||
{
|
||||
_duration->SpinBox()->setSpecialValueText("-");
|
||||
populateTypeSelection(_sceneTypes);
|
||||
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||
@@ -206,28 +218,29 @@ MacroActionSwitchSceneEdit::MacroActionSwitchSceneEdit(
|
||||
this, SLOT(DurationChanged(const Duration &)));
|
||||
QWidget::connect(_blockUntilTransitionDone, SIGNAL(stateChanged(int)),
|
||||
this, SLOT(BlockUntilTransitionDoneChanged(int)));
|
||||
QWidget::connect(_sceneTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(SceneTypeChanged(int)));
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{transitions}}", _transitions},
|
||||
{"{{duration}}", _duration},
|
||||
{"{{blockUntilTransitionDone}}", _blockUntilTransitionDone},
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.scene.entry"),
|
||||
_entryLayout, widgetPlaceholders);
|
||||
_entryLayout,
|
||||
{{"{{scenes}}", _scenes},
|
||||
{"{{transitions}}", _transitions},
|
||||
{"{{duration}}", _duration},
|
||||
{"{{sceneTypes}}", _sceneTypes}});
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(_entryLayout);
|
||||
mainLayout->addWidget(_blockUntilTransitionDone);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
_sceneTypes->setCurrentIndex(static_cast<int>(_entryData->_sceneType));
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
_transitions->SetTransition(_entryData->_transition);
|
||||
_duration->SetDuration(_entryData->_duration);
|
||||
_blockUntilTransitionDone->setChecked(
|
||||
_entryData->_blockUntilTransitionDone);
|
||||
SetDurationVisibility();
|
||||
SetWidgetVisibility();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
@@ -251,8 +264,44 @@ void MacroActionSwitchSceneEdit::BlockUntilTransitionDoneChanged(int state)
|
||||
_entryData->_blockUntilTransitionDone = state;
|
||||
}
|
||||
|
||||
void MacroActionSwitchSceneEdit::SetDurationVisibility()
|
||||
void MacroActionSwitchSceneEdit::SceneTypeChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_sceneType =
|
||||
static_cast<MacroActionSwitchScene::SceneType>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionSwitchSceneEdit::SetWidgetVisibility()
|
||||
{
|
||||
_entryLayout->removeWidget(_scenes);
|
||||
_entryLayout->removeWidget(_transitions);
|
||||
_entryLayout->removeWidget(_duration);
|
||||
_entryLayout->removeWidget(_sceneTypes);
|
||||
ClearLayout(_entryLayout);
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{transitions}}", _transitions},
|
||||
{"{{duration}}", _duration},
|
||||
{"{{sceneTypes}}", _sceneTypes},
|
||||
};
|
||||
|
||||
if (_entryData->_sceneType ==
|
||||
MacroActionSwitchScene::SceneType::PREVIEW) {
|
||||
_transitions->hide();
|
||||
_duration->hide();
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.scene.entry.preview"),
|
||||
_entryLayout, widgetPlaceholders);
|
||||
return;
|
||||
}
|
||||
|
||||
_transitions->show();
|
||||
if (_entryData->_transition.GetType() !=
|
||||
TransitionSelection::Type::TRANSITION) {
|
||||
_duration->show();
|
||||
@@ -261,15 +310,6 @@ void MacroActionSwitchSceneEdit::SetDurationVisibility()
|
||||
_entryData->_transition.GetTransition());
|
||||
_duration->setVisible(!fixedDuration);
|
||||
|
||||
_entryLayout->removeWidget(_scenes);
|
||||
_entryLayout->removeWidget(_transitions);
|
||||
_entryLayout->removeWidget(_duration);
|
||||
ClearLayout(_entryLayout);
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{transitions}}", _transitions},
|
||||
{"{{duration}}", _duration},
|
||||
};
|
||||
if (fixedDuration) {
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
@@ -302,7 +342,7 @@ void MacroActionSwitchSceneEdit::TransitionChanged(const TransitionSelection &t)
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_transition = t;
|
||||
SetDurationVisibility();
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -22,6 +22,9 @@ public:
|
||||
{
|
||||
return std::make_shared<MacroActionSwitchScene>(m);
|
||||
}
|
||||
|
||||
enum class SceneType { PROGRAM, PREVIEW };
|
||||
SceneType _sceneType = SceneType::PROGRAM;
|
||||
SceneSelection _scene;
|
||||
TransitionSelection _transition;
|
||||
Duration _duration;
|
||||
@@ -55,20 +58,21 @@ private slots:
|
||||
void TransitionChanged(const TransitionSelection &);
|
||||
void DurationChanged(const Duration &seconds);
|
||||
void BlockUntilTransitionDoneChanged(int state);
|
||||
void SceneTypeChanged(int);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
|
||||
SceneSelectionWidget *_scenes;
|
||||
TransitionSelectionWidget *_transitions;
|
||||
DurationSelection *_duration;
|
||||
QCheckBox *_blockUntilTransitionDone;
|
||||
QComboBox *_sceneTypes;
|
||||
QHBoxLayout *_entryLayout;
|
||||
|
||||
std::shared_ptr<MacroActionSwitchScene> _entryData;
|
||||
|
||||
private:
|
||||
void SetDurationVisibility();
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ bool MacroActionSequence::PerformAction()
|
||||
return true;
|
||||
}
|
||||
|
||||
return macro->PerformActions();
|
||||
return macro->PerformActions(true);
|
||||
}
|
||||
|
||||
void MacroActionSequence::LogAction() const
|
||||
|
||||
@@ -27,6 +27,12 @@ const static std::map<MacroActionSource::Action, std::string> actionTypes = {
|
||||
"AdvSceneSwitcher.action.source.type.deinterlaceMode"},
|
||||
{MacroActionSource::Action::DEINTERLACE_FIELD_ORDER,
|
||||
"AdvSceneSwitcher.action.source.type.deinterlaceOrder"},
|
||||
{MacroActionSource::Action::OPEN_INTERACTION_DIALOG,
|
||||
"AdvSceneSwitcher.action.source.type.openInteractionDialog"},
|
||||
{MacroActionSource::Action::OPEN_FILTER_DIALOG,
|
||||
"AdvSceneSwitcher.action.source.type.openFilterDialog"},
|
||||
{MacroActionSource::Action::OPEN_PROPERTIES_DIALOG,
|
||||
"AdvSceneSwitcher.action.source.type.openPropertiesDialog"},
|
||||
};
|
||||
|
||||
const static std::map<obs_deinterlace_mode, std::string> deinterlaceModes = {
|
||||
@@ -58,6 +64,16 @@ const static std::map<obs_deinterlace_field_order, std::string>
|
||||
"AdvSceneSwitcher.action.source.deinterlaceOrder.bottomFieldFirst"},
|
||||
};
|
||||
|
||||
const static std::map<MacroActionSource::SettingsInputMethod, std::string>
|
||||
inputMethods = {
|
||||
{MacroActionSource::SettingsInputMethod::INDIVIDUAL_MANUAL,
|
||||
"AdvSceneSwitcher.action.source.inputMethod.individualManual"},
|
||||
{MacroActionSource::SettingsInputMethod::INDIVIDUAL_TEMPVAR,
|
||||
"AdvSceneSwitcher.action.source.inputMethod.individualTempvar"},
|
||||
{MacroActionSource::SettingsInputMethod::JSON_STRING,
|
||||
"AdvSceneSwitcher.action.source.inputMethod.json"},
|
||||
};
|
||||
|
||||
static std::vector<SourceSettingButton> getSourceButtons(OBSWeakSource source)
|
||||
{
|
||||
auto s = obs_weak_source_get_source(source);
|
||||
@@ -73,6 +89,7 @@ static std::vector<SourceSettingButton> getSourceButtons(OBSWeakSource source)
|
||||
buttons.emplace_back(button);
|
||||
} while (obs_property_next(&it));
|
||||
obs_source_release(s);
|
||||
obs_properties_destroy(sourceProperties);
|
||||
return buttons;
|
||||
}
|
||||
|
||||
@@ -110,6 +127,12 @@ static void refreshSourceSettings(obs_source_t *s)
|
||||
}
|
||||
}
|
||||
|
||||
static bool isInteractable(obs_source_t *source)
|
||||
{
|
||||
uint32_t flags = obs_source_get_output_flags(source);
|
||||
return (flags & OBS_SOURCE_INTERACTION) != 0;
|
||||
}
|
||||
|
||||
bool MacroActionSource::PerformAction()
|
||||
{
|
||||
auto s = obs_weak_source_get_source(_source.GetSource());
|
||||
@@ -121,7 +144,26 @@ bool MacroActionSource::PerformAction()
|
||||
obs_source_set_enabled(s, false);
|
||||
break;
|
||||
case Action::SETTINGS:
|
||||
SetSourceSettings(s, _settings);
|
||||
switch (_settingsInputMethod) {
|
||||
case SettingsInputMethod::INDIVIDUAL_MANUAL:
|
||||
SetSourceSetting(s, _setting, _manualSettingValue);
|
||||
break;
|
||||
case SettingsInputMethod::INDIVIDUAL_TEMPVAR: {
|
||||
auto var = _tempVar.GetTempVariable(GetMacro());
|
||||
if (!var) {
|
||||
break;
|
||||
}
|
||||
auto value = var->Value();
|
||||
if (!value) {
|
||||
break;
|
||||
}
|
||||
SetSourceSetting(s, _setting, *value);
|
||||
break;
|
||||
}
|
||||
case SettingsInputMethod::JSON_STRING:
|
||||
SetSourceSettings(s, _settingsString);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case Action::REFRESH_SETTINGS:
|
||||
refreshSourceSettings(s);
|
||||
@@ -135,6 +177,22 @@ bool MacroActionSource::PerformAction()
|
||||
case Action::DEINTERLACE_FIELD_ORDER:
|
||||
obs_source_set_deinterlace_field_order(s, _deinterlaceOrder);
|
||||
break;
|
||||
case Action::OPEN_INTERACTION_DIALOG:
|
||||
if (isInteractable(s)) {
|
||||
obs_frontend_open_source_interaction(s);
|
||||
} else {
|
||||
blog(LOG_INFO,
|
||||
"refusing to open interaction dialog "
|
||||
"for non intractable source \"%s\"",
|
||||
_source.ToString().c_str());
|
||||
}
|
||||
break;
|
||||
case Action::OPEN_FILTER_DIALOG:
|
||||
obs_frontend_open_source_filters(s);
|
||||
break;
|
||||
case Action::OPEN_PROPERTIES_DIALOG:
|
||||
obs_frontend_open_source_properties(s);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -160,7 +218,12 @@ bool MacroActionSource::Save(obs_data_t *obj) const
|
||||
_source.Save(obj);
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
_button.Save(obj);
|
||||
_settings.Save(obj, "settings");
|
||||
obs_data_set_int(obj, "inputMethod",
|
||||
static_cast<int>(_settingsInputMethod));
|
||||
_setting.Save(obj);
|
||||
_manualSettingValue.Save(obj, "manualSettingValue");
|
||||
_tempVar.Save(obj);
|
||||
_settingsString.Save(obj, "settings");
|
||||
obs_data_set_int(obj, "deinterlaceMode",
|
||||
static_cast<int>(_deinterlaceMode));
|
||||
obs_data_set_int(obj, "deinterlaceOrder",
|
||||
@@ -174,7 +237,17 @@ bool MacroActionSource::Load(obs_data_t *obj)
|
||||
_source.Load(obj);
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
_button.Load(obj);
|
||||
_settings.Load(obj, "settings");
|
||||
// TODO: Remove fallback in future version
|
||||
if (obs_data_has_user_value(obj, "inputMethod")) {
|
||||
_settingsInputMethod = static_cast<SettingsInputMethod>(
|
||||
obs_data_get_int(obj, "inputMethod"));
|
||||
} else {
|
||||
_settingsInputMethod = SettingsInputMethod::JSON_STRING;
|
||||
}
|
||||
_setting.Load(obj);
|
||||
_settingsString.Load(obj, "settings");
|
||||
_manualSettingValue.Load(obj, "manualSettingValue");
|
||||
_tempVar.Load(obj, GetMacro());
|
||||
_deinterlaceMode = static_cast<obs_deinterlace_mode>(
|
||||
obs_data_get_int(obj, "deinterlaceMode"));
|
||||
_deinterlaceOrder = static_cast<obs_deinterlace_field_order>(
|
||||
@@ -237,19 +310,34 @@ static inline void populateDeinterlaceFieldOrderSelection(QComboBox *list)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void populateSettingsInputMethods(QComboBox *list)
|
||||
{
|
||||
list->clear();
|
||||
for (const auto &[value, name] : inputMethods) {
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(value));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionSourceEdit::MacroActionSourceEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionSource> entryData)
|
||||
: QWidget(parent),
|
||||
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
||||
_actions(new QComboBox()),
|
||||
_settingsButtons(new QComboBox()),
|
||||
_settingsLayout(new QHBoxLayout()),
|
||||
_settingsInputMethods(new QComboBox(this)),
|
||||
_manualSettingValue(new VariableTextEdit(this, 5, 1, 1)),
|
||||
_tempVars(new TempVariableSelection(this)),
|
||||
_sourceSettings(new SourceSettingSelection(this)),
|
||||
_settingsString(new VariableTextEdit(this)),
|
||||
_getSettings(new QPushButton(obs_module_text(
|
||||
"AdvSceneSwitcher.action.source.getSettings"))),
|
||||
_settings(new VariableTextEdit(this)),
|
||||
_deinterlaceMode(new QComboBox()),
|
||||
_deinterlaceOrder(new QComboBox()),
|
||||
_warning(new QLabel(
|
||||
obs_module_text("AdvSceneSwitcher.action.source.warning")))
|
||||
|
||||
{
|
||||
populateActionSelection(_actions);
|
||||
auto sources = GetSourceNames();
|
||||
@@ -257,6 +345,7 @@ MacroActionSourceEdit::MacroActionSourceEdit(
|
||||
_sources->SetSourceNameList(sources);
|
||||
populateDeinterlaceModeSelection(_deinterlaceMode);
|
||||
populateDeinterlaceFieldOrderSelection(_deinterlaceOrder);
|
||||
populateSettingsInputMethods(_settingsInputMethods);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
@@ -267,20 +356,33 @@ MacroActionSourceEdit::MacroActionSourceEdit(
|
||||
SLOT(SourceChanged(const SourceSelection &)));
|
||||
QWidget::connect(_getSettings, SIGNAL(clicked()), this,
|
||||
SLOT(GetSettingsClicked()));
|
||||
QWidget::connect(_settings, SIGNAL(textChanged()), this,
|
||||
SLOT(SettingsChanged()));
|
||||
QWidget::connect(_settingsString, SIGNAL(textChanged()), this,
|
||||
SLOT(SettingsStringChanged()));
|
||||
QWidget::connect(_deinterlaceMode, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(DeinterlaceModeChanged(int)));
|
||||
QWidget::connect(_deinterlaceOrder, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(DeinterlaceOrderChanged(int)));
|
||||
QWidget::connect(_tempVars,
|
||||
SIGNAL(SelectionChanged(const TempVariableRef &)),
|
||||
this, SLOT(SelectionChanged(const TempVariableRef &)));
|
||||
QWidget::connect(_settingsInputMethods,
|
||||
SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(SettingsInputMethodChanged(int)));
|
||||
QWidget::connect(_manualSettingValue, SIGNAL(textChanged()), this,
|
||||
SLOT(ManualSettingsValueChanged()));
|
||||
QWidget::connect(_sourceSettings,
|
||||
SIGNAL(SelectionChanged(const SourceSetting &)), this,
|
||||
SLOT(SelectionChanged(const SourceSetting &)));
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
QHBoxLayout *entryLayout = new QHBoxLayout;
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||
auto entryLayout = new QHBoxLayout;
|
||||
entryLayout->setContentsMargins(0, 0, 0, 0);
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{sources}}", _sources},
|
||||
{"{{actions}}", _actions},
|
||||
{"{{settings}}", _settings},
|
||||
{"{{settings}}", _sourceSettings},
|
||||
{"{{settingsInputMethod}}", _settingsInputMethods},
|
||||
{"{{settingValue}}", _manualSettingValue},
|
||||
{"{{tempVar}}", _tempVars},
|
||||
{"{{getSettings}}", _getSettings},
|
||||
{"{{settingsButtons}}", _settingsButtons},
|
||||
{"{{deinterlaceMode}}", _deinterlaceMode},
|
||||
@@ -288,9 +390,17 @@ MacroActionSourceEdit::MacroActionSourceEdit(
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.source.entry"),
|
||||
entryLayout, widgetPlaceholders);
|
||||
_settingsLayout->setContentsMargins(0, 0, 0, 0);
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.action.source.entry.settings"),
|
||||
_settingsLayout, widgetPlaceholders);
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
mainLayout->addLayout(_settingsLayout);
|
||||
mainLayout->addWidget(_warning);
|
||||
mainLayout->addWidget(_settings);
|
||||
mainLayout->addWidget(_settingsString);
|
||||
auto buttonLayout = new QHBoxLayout;
|
||||
buttonLayout->setContentsMargins(0, 0, 0, 0);
|
||||
buttonLayout->addWidget(_getSettings);
|
||||
buttonLayout->addStretch();
|
||||
mainLayout->addLayout(buttonLayout);
|
||||
@@ -311,13 +421,20 @@ void MacroActionSourceEdit::UpdateEntryData()
|
||||
_entryData->_source.GetSource());
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_sources->SetSource(_entryData->_source);
|
||||
_sourceSettings->SetSource(_entryData->_source.GetSource());
|
||||
_sourceSettings->SetSetting(_entryData->_setting);
|
||||
_settingsButtons->setCurrentText(
|
||||
QString::fromStdString(_entryData->_button.ToString()));
|
||||
_settings->setPlainText(_entryData->_settings);
|
||||
_settingsString->setPlainText(_entryData->_settingsString);
|
||||
_deinterlaceMode->setCurrentIndex(_deinterlaceMode->findData(
|
||||
static_cast<int>(_entryData->_deinterlaceMode)));
|
||||
_deinterlaceOrder->setCurrentIndex(_deinterlaceOrder->findData(
|
||||
static_cast<int>(_entryData->_deinterlaceOrder)));
|
||||
_settingsInputMethods->setCurrentIndex(_settingsInputMethods->findData(
|
||||
static_cast<int>(_entryData->_settingsInputMethod)));
|
||||
_tempVars->SetVariable(_entryData->_tempVar);
|
||||
_manualSettingValue->setPlainText(_entryData->_manualSettingValue);
|
||||
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
@@ -333,6 +450,7 @@ void MacroActionSourceEdit::SourceChanged(const SourceSelection &source)
|
||||
}
|
||||
populateSourceButtonSelection(_settingsButtons,
|
||||
_entryData->_source.GetSource());
|
||||
_sourceSettings->SetSource(_entryData->_source.GetSource());
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
@@ -365,18 +483,29 @@ void MacroActionSourceEdit::GetSettingsClicked()
|
||||
return;
|
||||
}
|
||||
|
||||
_settings->setPlainText(FormatJsonString(
|
||||
GetSourceSettings(_entryData->_source.GetSource())));
|
||||
switch (_entryData->_settingsInputMethod) {
|
||||
case MacroActionSource::SettingsInputMethod::INDIVIDUAL_MANUAL:
|
||||
_manualSettingValue->setPlainText(GetSourceSettingValue(
|
||||
_entryData->_source.GetSource(), _entryData->_setting));
|
||||
break;
|
||||
case MacroActionSource::SettingsInputMethod::INDIVIDUAL_TEMPVAR:
|
||||
break;
|
||||
case MacroActionSource::SettingsInputMethod::JSON_STRING:
|
||||
_settingsString->setPlainText(FormatJsonString(
|
||||
GetSourceSettings(_entryData->_source.GetSource())));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionSourceEdit::SettingsChanged()
|
||||
void MacroActionSourceEdit::SettingsStringChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_settings = _settings->toPlainText().toStdString();
|
||||
_entryData->_settingsString =
|
||||
_settingsString->toPlainText().toStdString();
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
@@ -405,15 +534,81 @@ void MacroActionSourceEdit::DeinterlaceOrderChanged(int idx)
|
||||
_deinterlaceOrder->itemData(idx).toInt());
|
||||
}
|
||||
|
||||
void MacroActionSourceEdit::SelectionChanged(const TempVariableRef &var)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_tempVar = var;
|
||||
}
|
||||
|
||||
void MacroActionSourceEdit::SettingsInputMethodChanged(int idx)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_settingsInputMethod =
|
||||
static_cast<MacroActionSource::SettingsInputMethod>(
|
||||
_settingsInputMethods->itemData(idx).toInt());
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionSourceEdit::SelectionChanged(const SourceSetting &setting)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_setting = setting;
|
||||
}
|
||||
|
||||
void MacroActionSourceEdit::ManualSettingsValueChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_manualSettingValue =
|
||||
_manualSettingValue->toPlainText().toStdString();
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionSourceEdit::SetWidgetVisibility()
|
||||
{
|
||||
const bool showSettings = _entryData->_action ==
|
||||
MacroActionSource::Action::SETTINGS;
|
||||
SetLayoutVisible(_settingsLayout,
|
||||
_entryData->_action ==
|
||||
MacroActionSource::Action::SETTINGS);
|
||||
_sourceSettings->setVisible(
|
||||
_entryData->_action == MacroActionSource::Action::SETTINGS &&
|
||||
_entryData->_settingsInputMethod !=
|
||||
MacroActionSource::SettingsInputMethod::JSON_STRING);
|
||||
_settingsString->setVisible(
|
||||
_entryData->_action == MacroActionSource::Action::SETTINGS &&
|
||||
_entryData->_settingsInputMethod ==
|
||||
MacroActionSource::SettingsInputMethod::JSON_STRING);
|
||||
_getSettings->setVisible(_entryData->_action ==
|
||||
MacroActionSource::Action::SETTINGS);
|
||||
_tempVars->setVisible(_entryData->_action ==
|
||||
MacroActionSource::Action::SETTINGS &&
|
||||
_entryData->_settingsInputMethod ==
|
||||
MacroActionSource::SettingsInputMethod::
|
||||
INDIVIDUAL_TEMPVAR);
|
||||
_manualSettingValue->setVisible(
|
||||
_entryData->_action == MacroActionSource::Action::SETTINGS &&
|
||||
_entryData->_settingsInputMethod ==
|
||||
MacroActionSource::SettingsInputMethod::
|
||||
INDIVIDUAL_MANUAL);
|
||||
const bool showWarning =
|
||||
_entryData->_action == MacroActionSource::Action::ENABLE ||
|
||||
_entryData->_action == MacroActionSource::Action::DISABLE;
|
||||
_settings->setVisible(showSettings);
|
||||
_getSettings->setVisible(showSettings);
|
||||
_warning->setVisible(showWarning);
|
||||
_settingsButtons->setVisible(
|
||||
_entryData->_action ==
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "variable-text-edit.hpp"
|
||||
#include "source-selection.hpp"
|
||||
#include "source-setting.hpp"
|
||||
|
||||
#include <QSpinBox>
|
||||
#include <QLabel>
|
||||
@@ -35,10 +36,13 @@ public:
|
||||
|
||||
SourceSelection _source;
|
||||
SourceSettingButton _button;
|
||||
StringVariable _settings = "";
|
||||
StringVariable _settingsString = "";
|
||||
StringVariable _manualSettingValue = "";
|
||||
obs_deinterlace_mode _deinterlaceMode = OBS_DEINTERLACE_MODE_DISABLE;
|
||||
obs_deinterlace_field_order _deinterlaceOrder =
|
||||
OBS_DEINTERLACE_FIELD_ORDER_TOP;
|
||||
TempVariableRef _tempVar;
|
||||
SourceSetting _setting;
|
||||
|
||||
enum class Action {
|
||||
ENABLE,
|
||||
@@ -48,8 +52,19 @@ public:
|
||||
SETTINGS_BUTTON,
|
||||
DEINTERLACE_MODE,
|
||||
DEINTERLACE_FIELD_ORDER,
|
||||
OPEN_INTERACTION_DIALOG,
|
||||
OPEN_FILTER_DIALOG,
|
||||
OPEN_PROPERTIES_DIALOG,
|
||||
};
|
||||
Action _action = Action::ENABLE;
|
||||
Action _action = Action::SETTINGS;
|
||||
|
||||
enum class SettingsInputMethod {
|
||||
INDIVIDUAL_MANUAL,
|
||||
INDIVIDUAL_TEMPVAR,
|
||||
JSON_STRING,
|
||||
};
|
||||
SettingsInputMethod _settingsInputMethod =
|
||||
SettingsInputMethod::INDIVIDUAL_MANUAL;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
@@ -77,9 +92,13 @@ private slots:
|
||||
void ActionChanged(int value);
|
||||
void ButtonChanged(int idx);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
void SettingsStringChanged();
|
||||
void DeinterlaceModeChanged(int);
|
||||
void DeinterlaceOrderChanged(int);
|
||||
void SelectionChanged(const TempVariableRef &);
|
||||
void SettingsInputMethodChanged(int);
|
||||
void SelectionChanged(const SourceSetting &);
|
||||
void ManualSettingsValueChanged();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
@@ -87,11 +106,17 @@ protected:
|
||||
SourceSelectionWidget *_sources;
|
||||
QComboBox *_actions;
|
||||
QComboBox *_settingsButtons;
|
||||
QHBoxLayout *_settingsLayout;
|
||||
QComboBox *_settingsInputMethods;
|
||||
VariableTextEdit *_manualSettingValue;
|
||||
TempVariableSelection *_tempVars;
|
||||
SourceSettingSelection *_sourceSettings;
|
||||
VariableTextEdit *_settingsString;
|
||||
QPushButton *_getSettings;
|
||||
VariableTextEdit *_settings;
|
||||
QComboBox *_deinterlaceMode;
|
||||
QComboBox *_deinterlaceOrder;
|
||||
QLabel *_warning;
|
||||
|
||||
std::shared_ptr<MacroActionSource> _entryData;
|
||||
|
||||
private:
|
||||
|
||||
@@ -10,14 +10,14 @@ bool MacroActionSudioMode::_registered = MacroActionFactory::Register(
|
||||
{MacroActionSudioMode::Create, MacroActionSudioModeEdit::Create,
|
||||
"AdvSceneSwitcher.action.studioMode"});
|
||||
|
||||
const static std::map<StudioModeAction, std::string> actionTypes = {
|
||||
{StudioModeAction::SWAP_SCENE,
|
||||
const static std::map<MacroActionSudioMode::Action, std::string> actionTypes = {
|
||||
{MacroActionSudioMode::Action::SWAP_SCENE,
|
||||
"AdvSceneSwitcher.action.studioMode.type.swap"},
|
||||
{StudioModeAction::SET_SCENE,
|
||||
{MacroActionSudioMode::Action::SET_SCENE,
|
||||
"AdvSceneSwitcher.action.studioMode.type.setScene"},
|
||||
{StudioModeAction::ENABLE_STUDIO_MODE,
|
||||
{MacroActionSudioMode::Action::ENABLE_STUDIO_MODE,
|
||||
"AdvSceneSwitcher.action.studioMode.type.enable"},
|
||||
{StudioModeAction::DISABLE_STUDIO_MODE,
|
||||
{MacroActionSudioMode::Action::DISABLE_STUDIO_MODE,
|
||||
"AdvSceneSwitcher.action.studioMode.type.disable"},
|
||||
};
|
||||
|
||||
@@ -41,19 +41,19 @@ static void enableStudioMode(bool enable)
|
||||
bool MacroActionSudioMode::PerformAction()
|
||||
{
|
||||
switch (_action) {
|
||||
case StudioModeAction::SWAP_SCENE:
|
||||
case Action::SWAP_SCENE:
|
||||
obs_frontend_preview_program_trigger_transition();
|
||||
break;
|
||||
case StudioModeAction::SET_SCENE: {
|
||||
case Action::SET_SCENE: {
|
||||
auto s = obs_weak_source_get_source(_scene.GetScene());
|
||||
obs_frontend_set_current_preview_scene(s);
|
||||
obs_source_release(s);
|
||||
break;
|
||||
}
|
||||
case StudioModeAction::ENABLE_STUDIO_MODE:
|
||||
case Action::ENABLE_STUDIO_MODE:
|
||||
enableStudioMode(true);
|
||||
break;
|
||||
case StudioModeAction::DISABLE_STUDIO_MODE:
|
||||
case Action::DISABLE_STUDIO_MODE:
|
||||
enableStudioMode(false);
|
||||
break;
|
||||
default:
|
||||
@@ -86,15 +86,14 @@ bool MacroActionSudioMode::Save(obs_data_t *obj) const
|
||||
bool MacroActionSudioMode::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_action =
|
||||
static_cast<StudioModeAction>(obs_data_get_int(obj, "action"));
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
_scene.Load(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionSudioMode::GetShortDesc() const
|
||||
{
|
||||
if (_action == StudioModeAction::SET_SCENE) {
|
||||
if (_action == Action::SET_SCENE) {
|
||||
return _scene.ToString();
|
||||
}
|
||||
return "";
|
||||
@@ -102,8 +101,9 @@ std::string MacroActionSudioMode::GetShortDesc() const
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
for (const auto &[id, name] : actionTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,9 +139,10 @@ void MacroActionSudioModeEdit::UpdateEntryData()
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_actions->setCurrentIndex(
|
||||
_actions->findData(static_cast<int>(_entryData->_action)));
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
_scenes->setVisible(_entryData->_action == StudioModeAction::SET_SCENE);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionSudioModeEdit::SceneChanged(const SceneSelection &s)
|
||||
@@ -156,15 +157,27 @@ void MacroActionSudioModeEdit::SceneChanged(const SceneSelection &s)
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionSudioModeEdit::ActionChanged(int value)
|
||||
void MacroActionSudioModeEdit::SetWidgetVisibility()
|
||||
{
|
||||
_scenes->setVisible(_entryData->_action ==
|
||||
MacroActionSudioMode::Action::SET_SCENE);
|
||||
|
||||
if (_entryData->_action != MacroActionSudioMode::Action::SET_SCENE) {
|
||||
_actions->removeItem(_actions->findData(static_cast<int>(
|
||||
MacroActionSudioMode::Action::SET_SCENE)));
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionSudioModeEdit::ActionChanged(int index)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_action = static_cast<StudioModeAction>(value);
|
||||
_scenes->setVisible(_entryData->_action == StudioModeAction::SET_SCENE);
|
||||
_entryData->_action = static_cast<MacroActionSudioMode::Action>(
|
||||
_actions->itemData(index).toInt());
|
||||
SetWidgetVisibility();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
@@ -4,13 +4,6 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
enum class StudioModeAction {
|
||||
SWAP_SCENE,
|
||||
SET_SCENE,
|
||||
ENABLE_STUDIO_MODE,
|
||||
DISABLE_STUDIO_MODE,
|
||||
};
|
||||
|
||||
class MacroActionSudioMode : public MacroAction {
|
||||
public:
|
||||
MacroActionSudioMode(Macro *m) : MacroAction(m) {}
|
||||
@@ -25,7 +18,14 @@ public:
|
||||
return std::make_shared<MacroActionSudioMode>(m);
|
||||
}
|
||||
|
||||
StudioModeAction _action = StudioModeAction::SWAP_SCENE;
|
||||
enum class Action {
|
||||
SWAP_SCENE,
|
||||
SET_SCENE, // TODO: Remove in future version as the
|
||||
// functionality moved to the scene switch action
|
||||
ENABLE_STUDIO_MODE,
|
||||
DISABLE_STUDIO_MODE,
|
||||
};
|
||||
Action _action = Action::SWAP_SCENE;
|
||||
SceneSelection _scene;
|
||||
|
||||
private:
|
||||
@@ -55,12 +55,13 @@ private slots:
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
|
||||
QComboBox *_actions;
|
||||
SceneSelectionWidget *_scenes;
|
||||
std::shared_ptr<MacroActionSudioMode> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -41,6 +41,16 @@ const static std::map<MacroActionVariable::Type, std::string> actionTypes = {
|
||||
"AdvSceneSwitcher.action.variable.type.mathExpression"},
|
||||
{MacroActionVariable::Type::USER_INPUT,
|
||||
"AdvSceneSwitcher.action.variable.type.askForValue"},
|
||||
{MacroActionVariable::Type::ENV_VARIABLE,
|
||||
"AdvSceneSwitcher.action.variable.type.environmentVariable"},
|
||||
{MacroActionVariable::Type::SCENE_ITEM_COUNT,
|
||||
"AdvSceneSwitcher.action.variable.type.sceneItemCount"},
|
||||
{MacroActionVariable::Type::STRING_LENGTH,
|
||||
"AdvSceneSwitcher.action.variable.type.stringLength"},
|
||||
{MacroActionVariable::Type::EXTRACT_JSON,
|
||||
"AdvSceneSwitcher.action.variable.type.extractJson"},
|
||||
{MacroActionVariable::Type::SET_TO_TEMPVAR,
|
||||
"AdvSceneSwitcher.action.variable.type.setToTempvar"},
|
||||
};
|
||||
|
||||
static void apppend(Variable &var, const std::string &value)
|
||||
@@ -126,6 +136,7 @@ void MacroActionVariable::HandleMathExpression(Variable *var)
|
||||
|
||||
struct AskForInputParams {
|
||||
QString prompt;
|
||||
QString placeholder;
|
||||
std::optional<std::string> result;
|
||||
};
|
||||
|
||||
@@ -134,6 +145,7 @@ static void askForInput(void *param)
|
||||
auto parameters = static_cast<AskForInputParams *>(param);
|
||||
auto dialog = new NonModalMessageDialog(
|
||||
parameters->prompt, NonModalMessageDialog::Type::INPUT);
|
||||
dialog->SetInput(parameters->placeholder);
|
||||
parameters->result = dialog->GetInput();
|
||||
}
|
||||
|
||||
@@ -213,6 +225,9 @@ bool MacroActionVariable::PerformAction()
|
||||
"AdvSceneSwitcher.action.variable.askForValuePromptDefault"))
|
||||
.arg(QString::fromStdString(
|
||||
var->Name())),
|
||||
_useCustomPrompt && _useInputPlaceholder
|
||||
? QString::fromStdString(_inputPlaceholder)
|
||||
: "",
|
||||
{}};
|
||||
obs_queue_task(OBS_TASK_UI, askForInput, ¶ms, true);
|
||||
if (!params.result.has_value()) {
|
||||
@@ -221,6 +236,38 @@ bool MacroActionVariable::PerformAction()
|
||||
var->SetValue(*params.result);
|
||||
return true;
|
||||
}
|
||||
case Type::ENV_VARIABLE: {
|
||||
var->SetValue(std::getenv(_envVariableName.c_str()));
|
||||
return true;
|
||||
}
|
||||
case Type::SCENE_ITEM_COUNT: {
|
||||
var->SetValue(GetSceneItemCount(_scene.GetScene(false)));
|
||||
return true;
|
||||
}
|
||||
case Type::STRING_LENGTH: {
|
||||
var->SetValue(std::string(_strValue).length());
|
||||
return true;
|
||||
}
|
||||
case Type::EXTRACT_JSON: {
|
||||
auto value = GetJsonField(var->Value(), _strValue);
|
||||
if (!value.has_value()) {
|
||||
return true;
|
||||
}
|
||||
var->SetValue(*value);
|
||||
return true;
|
||||
}
|
||||
case Type::SET_TO_TEMPVAR: {
|
||||
auto tempVar = _tempVar.GetTempVariable(GetMacro());
|
||||
if (!tempVar) {
|
||||
return true;
|
||||
}
|
||||
auto value = tempVar->Value();
|
||||
if (!value) {
|
||||
return true;
|
||||
}
|
||||
var->SetValue(*value);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -233,7 +280,7 @@ bool MacroActionVariable::Save(obs_data_t *obj) const
|
||||
GetWeakVariableName(_variable).c_str());
|
||||
obs_data_set_string(obj, "variable2Name",
|
||||
GetWeakVariableName(_variable2).c_str());
|
||||
obs_data_set_string(obj, "strValue", _strValue.c_str());
|
||||
_strValue.Save(obj, "strValue");
|
||||
obs_data_set_double(obj, "numValue", _numValue);
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_type));
|
||||
obs_data_set_int(obj, "segmentIdx", GetSegmentIndexValue());
|
||||
@@ -241,12 +288,17 @@ bool MacroActionVariable::Save(obs_data_t *obj) const
|
||||
obs_data_set_int(obj, "subStringSize", _subStringSize);
|
||||
obs_data_set_string(obj, "regexPattern", _regexPattern.c_str());
|
||||
obs_data_set_int(obj, "regexMatchIdx", _regexMatchIdx);
|
||||
obs_data_set_string(obj, "findStr", _findStr.c_str());
|
||||
obs_data_set_string(obj, "replaceStr", _replaceStr.c_str());
|
||||
_findStr.Save(obj, "findStr");
|
||||
_replaceStr.Save(obj, "replaceStr");
|
||||
_regex.Save(obj);
|
||||
_mathExpression.Save(obj, "mathExpression");
|
||||
obs_data_set_bool(obj, "useCustomPrompt", _useCustomPrompt);
|
||||
_inputPrompt.Save(obj, "inputPrompt");
|
||||
obs_data_set_bool(obj, "useInputPlaceholder", _useInputPlaceholder);
|
||||
_inputPlaceholder.Save(obj, "inputPlaceholder");
|
||||
_envVariableName.Save(obj, "environmentVariableName");
|
||||
_scene.Save(obj);
|
||||
_tempVar.Save(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -257,7 +309,7 @@ bool MacroActionVariable::Load(obs_data_t *obj)
|
||||
GetWeakVariableByName(obs_data_get_string(obj, "variableName"));
|
||||
_variable2 = GetWeakVariableByName(
|
||||
obs_data_get_string(obj, "variable2Name"));
|
||||
_strValue = obs_data_get_string(obj, "strValue");
|
||||
_strValue.Load(obj, "strValue");
|
||||
_numValue = obs_data_get_double(obj, "numValue");
|
||||
_type = static_cast<Type>(obs_data_get_int(obj, "condition"));
|
||||
_segmentIdxLoadValue = obs_data_get_int(obj, "segmentIdx");
|
||||
@@ -266,11 +318,16 @@ bool MacroActionVariable::Load(obs_data_t *obj)
|
||||
_regex.Load(obj);
|
||||
_regexPattern = obs_data_get_string(obj, "regexPattern");
|
||||
_regexMatchIdx = obs_data_get_int(obj, "regexMatchIdx");
|
||||
_findStr = obs_data_get_string(obj, "findStr");
|
||||
_replaceStr = obs_data_get_string(obj, "replaceStr");
|
||||
_findStr.Load(obj, "findStr");
|
||||
_replaceStr.Load(obj, "replaceStr");
|
||||
_mathExpression.Load(obj, "mathExpression");
|
||||
_useCustomPrompt = obs_data_get_bool(obj, "useCustomPrompt");
|
||||
_inputPrompt.Load(obj, "inputPrompt");
|
||||
_useInputPlaceholder = obs_data_get_bool(obj, "useInputPlaceholder");
|
||||
_inputPlaceholder.Load(obj, "inputPlaceholder");
|
||||
_envVariableName.Load(obj, "environmentVariableName");
|
||||
_scene.Load(obj);
|
||||
_tempVar.Load(obj, GetMacro());
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -313,7 +370,7 @@ void MacroActionVariable::SetSegmentIndexValue(int value)
|
||||
|
||||
_macroSegment = segment;
|
||||
if (segment) {
|
||||
segment->IncrementVariableRef();
|
||||
IncrementVariableRef(segment.get());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -355,13 +412,14 @@ void MacroActionVariable::DecrementCurrentSegmentVariableRef()
|
||||
return;
|
||||
}
|
||||
|
||||
segment->DecrementVariableRef();
|
||||
DecrementVariableRef(segment.get());
|
||||
}
|
||||
|
||||
static inline void populateTypeSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
for (const auto &[action, name] : actionTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(action));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -370,8 +428,8 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
: QWidget(parent),
|
||||
_variables(new VariableSelection(this)),
|
||||
_variables2(new VariableSelection(this)),
|
||||
_actions(new QComboBox()),
|
||||
_strValue(new ResizingPlainTextEdit(this, 5, 1, 1)),
|
||||
_actions(new FilterComboBox(this)),
|
||||
_strValue(new VariableTextEdit(this, 5, 1, 1)),
|
||||
_numValue(new QDoubleSpinBox()),
|
||||
_segmentIdx(new MacroSegmentSelection(
|
||||
this, MacroSegmentSelection::Type::CONDITION, false)),
|
||||
@@ -386,13 +444,20 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
_regexPattern(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
||||
_regexMatchIdx(new QSpinBox()),
|
||||
_findReplaceLayout(new QHBoxLayout()),
|
||||
_findStr(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
||||
_replaceStr(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
||||
_findStr(new VariableTextEdit(this, 10, 1, 1)),
|
||||
_replaceStr(new VariableTextEdit(this, 10, 1, 1)),
|
||||
_mathExpression(new VariableLineEdit(this)),
|
||||
_mathExpressionResult(new QLabel()),
|
||||
_promptLayout(new QHBoxLayout()),
|
||||
_useCustomPrompt(new QCheckBox()),
|
||||
_inputPrompt(new VariableLineEdit(this))
|
||||
_inputPrompt(new VariableLineEdit(this)),
|
||||
_placeholderLayout(new QHBoxLayout()),
|
||||
_useInputPlaceholder(new QCheckBox()),
|
||||
_inputPlaceholder(new VariableLineEdit(this)),
|
||||
_envVariable(new VariableLineEdit(this)),
|
||||
_scenes(new SceneSelectionWidget(this, true, false, true, true,
|
||||
true)),
|
||||
_tempVars(new TempVariableSelection(this))
|
||||
{
|
||||
_numValue->setMinimum(-9999999999);
|
||||
_numValue->setMaximum(9999999999);
|
||||
@@ -447,6 +512,17 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
SLOT(UseCustomPromptChanged(int)));
|
||||
QWidget::connect(_inputPrompt, SIGNAL(editingFinished()), this,
|
||||
SLOT(InputPromptChanged()));
|
||||
QWidget::connect(_useInputPlaceholder, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(UseInputPlaceholderChanged(int)));
|
||||
QWidget::connect(_inputPlaceholder, SIGNAL(editingFinished()), this,
|
||||
SLOT(InputPlaceholderChanged()));
|
||||
QWidget::connect(_envVariable, SIGNAL(editingFinished()), this,
|
||||
SLOT(EnvVariableChanged()));
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||
QWidget::connect(_tempVars,
|
||||
SIGNAL(SelectionChanged(const TempVariableRef &)),
|
||||
this, SLOT(SelectionChanged(const TempVariableRef &)));
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{variables}}", _variables},
|
||||
@@ -463,6 +539,11 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
{"{{mathExpression}}", _mathExpression},
|
||||
{"{{useCustomPrompt}}", _useCustomPrompt},
|
||||
{"{{inputPrompt}}", _inputPrompt},
|
||||
{"{{useInputPlaceholder}}", _useInputPlaceholder},
|
||||
{"{{inputPlaceholder}}", _inputPlaceholder},
|
||||
{"{{envVariableName}}", _envVariable},
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{tempVars}}", _tempVars},
|
||||
};
|
||||
auto entryLayout = new QHBoxLayout;
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.variable.entry"),
|
||||
@@ -485,8 +566,12 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.entry.userInput"),
|
||||
"AdvSceneSwitcher.action.variable.entry.userInput.customPrompt"),
|
||||
_promptLayout, widgetPlaceholders);
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.entry.userInput.placeholder"),
|
||||
_placeholderLayout, widgetPlaceholders);
|
||||
|
||||
auto regexConfigLayout = new QHBoxLayout;
|
||||
regexConfigLayout->addWidget(_regex);
|
||||
@@ -505,6 +590,7 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
layout->addLayout(_findReplaceLayout);
|
||||
layout->addWidget(_mathExpressionResult);
|
||||
layout->addLayout(_promptLayout);
|
||||
layout->addLayout(_placeholderLayout);
|
||||
setLayout(layout);
|
||||
|
||||
_entryData = entryData;
|
||||
@@ -525,8 +611,9 @@ void MacroActionVariableEdit::UpdateEntryData()
|
||||
|
||||
_variables->SetVariable(_entryData->_variable);
|
||||
_variables2->SetVariable(_entryData->_variable2);
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||
_strValue->setPlainText(QString::fromStdString(_entryData->_strValue));
|
||||
_actions->setCurrentIndex(
|
||||
_actions->findData(static_cast<int>(_entryData->_type)));
|
||||
_strValue->setPlainText(_entryData->_strValue);
|
||||
_numValue->setValue(_entryData->_numValue);
|
||||
_segmentIdx->SetValue(_entryData->GetSegmentIndexValue() + 1);
|
||||
_segmentIdx->SetMacro(_entryData->GetMacro());
|
||||
@@ -541,12 +628,16 @@ void MacroActionVariableEdit::UpdateEntryData()
|
||||
_regexPattern->setPlainText(
|
||||
QString::fromStdString(_entryData->_regexPattern));
|
||||
_regexMatchIdx->setValue(_entryData->_regexMatchIdx + 1);
|
||||
_findStr->setPlainText(QString::fromStdString(_entryData->_findStr));
|
||||
_replaceStr->setPlainText(
|
||||
QString::fromStdString(_entryData->_replaceStr));
|
||||
_findStr->setPlainText(_entryData->_findStr);
|
||||
_replaceStr->setPlainText(_entryData->_replaceStr);
|
||||
_mathExpression->setText(_entryData->_mathExpression);
|
||||
_useCustomPrompt->setChecked(_entryData->_useCustomPrompt);
|
||||
_inputPrompt->setText(_entryData->_inputPrompt);
|
||||
_useInputPlaceholder->setChecked(_entryData->_useInputPlaceholder);
|
||||
_inputPlaceholder->setText(_entryData->_inputPlaceholder);
|
||||
_envVariable->setText(_entryData->_envVariableName);
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
_tempVars->SetVariable(_entryData->_tempVar);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
@@ -570,14 +661,15 @@ void MacroActionVariableEdit::Variable2Changed(const QString &text)
|
||||
_entryData->_variable2 = GetWeakVariableByQString(text);
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::ActionChanged(int value)
|
||||
void MacroActionVariableEdit::ActionChanged(int idx)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
if (_loading || !_entryData || idx == -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_type = static_cast<MacroActionVariable::Type>(value);
|
||||
_entryData->_type = static_cast<MacroActionVariable::Type>(
|
||||
_actions->itemData(idx).toInt());
|
||||
|
||||
if (_entryData->_type == MacroActionVariable::Type::SET_ACTION_VALUE) {
|
||||
_segmentIdx->SetType(MacroSegmentSelection::Type::ACTION);
|
||||
@@ -674,7 +766,7 @@ void MacroActionVariableEdit::UpdateSegmentVariableValue()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!segment->SupportsVariableValue()) {
|
||||
if (!SupportsVariableValue(segment.get())) {
|
||||
std::string type;
|
||||
QString fmt;
|
||||
|
||||
@@ -699,8 +791,14 @@ void MacroActionVariableEdit::UpdateSegmentVariableValue()
|
||||
_segmentValueStatus->setText(obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.currentSegmentValue"));
|
||||
_segmentValue->show();
|
||||
_segmentValue->setPlainText(
|
||||
QString::fromStdString(segment->GetVariableValue()));
|
||||
|
||||
// Only update the text if the value changed to prevent possible text
|
||||
// selections being lost
|
||||
auto previousText = _segmentValue->toPlainText();
|
||||
auto newText = QString::fromStdString(segment->GetVariableValue());
|
||||
if (newText != previousText) {
|
||||
_segmentValue->setPlainText(newText);
|
||||
}
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
@@ -818,15 +916,9 @@ void MacroActionVariableEdit::UseCustomPromptChanged(int value)
|
||||
return;
|
||||
}
|
||||
|
||||
_inputPrompt->setVisible(value);
|
||||
if (value) {
|
||||
RemoveStretchIfPresent(_promptLayout);
|
||||
} else {
|
||||
AddStretchIfNecessary(_promptLayout);
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_useCustomPrompt = value;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::InputPromptChanged()
|
||||
@@ -839,6 +931,57 @@ void MacroActionVariableEdit::InputPromptChanged()
|
||||
_entryData->_inputPrompt = _inputPrompt->text().toStdString();
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::UseInputPlaceholderChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_useInputPlaceholder = value;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::InputPlaceholderChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_inputPlaceholder = _inputPlaceholder->text().toStdString();
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::EnvVariableChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_envVariableName = _envVariable->text().toStdString();
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::SceneChanged(const SceneSelection &scene)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_scene = scene;
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::SelectionChanged(const TempVariableRef &var)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_tempVar = var;
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::SetWidgetVisibility()
|
||||
{
|
||||
if (!_entryData) {
|
||||
@@ -850,7 +993,9 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
||||
_strValue->setVisible(
|
||||
_entryData->_type ==
|
||||
MacroActionVariable::Type::SET_FIXED_VALUE ||
|
||||
_entryData->_type == MacroActionVariable::Type::APPEND);
|
||||
_entryData->_type == MacroActionVariable::Type::APPEND ||
|
||||
_entryData->_type == MacroActionVariable::Type::STRING_LENGTH ||
|
||||
_entryData->_type == MacroActionVariable::Type::EXTRACT_JSON);
|
||||
_numValue->setVisible(
|
||||
_entryData->_type == MacroActionVariable::Type::INCREMENT ||
|
||||
_entryData->_type == MacroActionVariable::Type::DECREMENT);
|
||||
@@ -887,7 +1032,36 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
||||
SetLayoutVisible(_promptLayout,
|
||||
_entryData->_type ==
|
||||
MacroActionVariable::Type::USER_INPUT);
|
||||
_inputPrompt->setVisible(_entryData->_useCustomPrompt);
|
||||
_inputPrompt->setVisible(
|
||||
_entryData->_type == MacroActionVariable::Type::USER_INPUT &&
|
||||
_entryData->_useCustomPrompt);
|
||||
if (_entryData->_useCustomPrompt) {
|
||||
RemoveStretchIfPresent(_promptLayout);
|
||||
} else {
|
||||
AddStretchIfNecessary(_promptLayout);
|
||||
}
|
||||
SetLayoutVisible(
|
||||
_placeholderLayout,
|
||||
_entryData->_type == MacroActionVariable::Type::USER_INPUT &&
|
||||
_entryData->_useCustomPrompt);
|
||||
_useInputPlaceholder->setVisible(
|
||||
_entryData->_type == MacroActionVariable::Type::USER_INPUT &&
|
||||
_entryData->_useCustomPrompt);
|
||||
_inputPlaceholder->setVisible(
|
||||
_entryData->_type == MacroActionVariable::Type::USER_INPUT &&
|
||||
_entryData->_useCustomPrompt &&
|
||||
_entryData->_useInputPlaceholder);
|
||||
if (_entryData->_useInputPlaceholder) {
|
||||
RemoveStretchIfPresent(_placeholderLayout);
|
||||
} else {
|
||||
AddStretchIfNecessary(_placeholderLayout);
|
||||
}
|
||||
_envVariable->setVisible(_entryData->_type ==
|
||||
MacroActionVariable::Type::ENV_VARIABLE);
|
||||
_scenes->setVisible(_entryData->_type ==
|
||||
MacroActionVariable::Type::SCENE_ITEM_COUNT);
|
||||
_tempVars->setVisible(_entryData->_type ==
|
||||
MacroActionVariable::Type::SET_TO_TEMPVAR);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
#include "macro-segment-selection.hpp"
|
||||
#include "regex-config.hpp"
|
||||
#include "resizing-text-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
#include "variable-text-edit.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
@@ -37,27 +39,42 @@ public:
|
||||
FIND_AND_REPLACE,
|
||||
MATH_EXPRESSION,
|
||||
USER_INPUT,
|
||||
ENV_VARIABLE,
|
||||
SCENE_ITEM_COUNT,
|
||||
STRING_LENGTH,
|
||||
EXTRACT_JSON,
|
||||
SET_TO_TEMPVAR,
|
||||
};
|
||||
|
||||
Type _type = Type::SET_FIXED_VALUE;
|
||||
std::weak_ptr<Variable> _variable;
|
||||
std::weak_ptr<Variable> _variable2;
|
||||
std::string _strValue = "";
|
||||
StringVariable _strValue = "";
|
||||
double _numValue = 0;
|
||||
int _subStringStart = 0;
|
||||
int _subStringSize = 0;
|
||||
RegexConfig _regex = RegexConfig::PartialMatchRegexConfig();
|
||||
std::string _regexPattern = ".*";
|
||||
int _regexMatchIdx = 0;
|
||||
std::string _findStr = obs_module_text(
|
||||
StringVariable _findStr = obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.findAndReplace.find");
|
||||
std::string _replaceStr = obs_module_text(
|
||||
StringVariable _replaceStr = obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.findAndReplace.replace");
|
||||
StringVariable _mathExpression = obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.mathExpression.example");
|
||||
bool _useCustomPrompt = false;
|
||||
StringVariable _inputPrompt = obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.askForValuePrompt");
|
||||
bool _useInputPlaceholder = false;
|
||||
StringVariable _inputPlaceholder =
|
||||
obs_module_text("AdvSceneSwitcher.enterText");
|
||||
#ifdef _WIN32
|
||||
StringVariable _envVariableName = "USERPROFILE";
|
||||
#else
|
||||
StringVariable _envVariableName = "HOME";
|
||||
#endif
|
||||
SceneSelection _scene;
|
||||
TempVariableRef _tempVar;
|
||||
|
||||
private:
|
||||
void DecrementCurrentSegmentVariableRef();
|
||||
@@ -107,15 +124,23 @@ private slots:
|
||||
void MathExpressionChanged();
|
||||
void UseCustomPromptChanged(int);
|
||||
void InputPromptChanged();
|
||||
void UseInputPlaceholderChanged(int);
|
||||
void InputPlaceholderChanged();
|
||||
void EnvVariableChanged();
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SelectionChanged(const TempVariableRef &var);
|
||||
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
void SetSegmentValueError(const QString &);
|
||||
|
||||
VariableSelection *_variables;
|
||||
VariableSelection *_variables2;
|
||||
QComboBox *_actions;
|
||||
ResizingPlainTextEdit *_strValue;
|
||||
FilterComboBox *_actions;
|
||||
VariableTextEdit *_strValue;
|
||||
QDoubleSpinBox *_numValue;
|
||||
MacroSegmentSelection *_segmentIdx;
|
||||
QLabel *_segmentValueStatus;
|
||||
@@ -129,19 +154,21 @@ protected:
|
||||
ResizingPlainTextEdit *_regexPattern;
|
||||
QSpinBox *_regexMatchIdx;
|
||||
QHBoxLayout *_findReplaceLayout;
|
||||
ResizingPlainTextEdit *_findStr;
|
||||
ResizingPlainTextEdit *_replaceStr;
|
||||
VariableTextEdit *_findStr;
|
||||
VariableTextEdit *_replaceStr;
|
||||
VariableLineEdit *_mathExpression;
|
||||
QLabel *_mathExpressionResult;
|
||||
QHBoxLayout *_promptLayout;
|
||||
QCheckBox *_useCustomPrompt;
|
||||
VariableLineEdit *_inputPrompt;
|
||||
QHBoxLayout *_placeholderLayout;
|
||||
QCheckBox *_useInputPlaceholder;
|
||||
VariableLineEdit *_inputPlaceholder;
|
||||
VariableLineEdit *_envVariable;
|
||||
SceneSelectionWidget *_scenes;
|
||||
TempVariableSelection *_tempVars;
|
||||
|
||||
std::shared_ptr<MacroActionVariable> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
void SetSegmentValueError(const QString &);
|
||||
|
||||
QTimer _timer;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
@@ -192,7 +192,7 @@ void MacroActionWebsocketEdit::CheckForSettingsConflict()
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionWebsocketEdit::SetupWidgetVisibility()
|
||||
void MacroActionWebsocketEdit::SetWidgetVisibility()
|
||||
{
|
||||
_messageType->setVisible(_entryData->_api ==
|
||||
MacroActionWebsocket::API::SCENE_SWITCHER);
|
||||
@@ -283,7 +283,7 @@ void MacroActionWebsocketEdit::UpdateEntryData()
|
||||
_message->setPlainText(_entryData->_message);
|
||||
_connection->SetConnection(_entryData->_connection);
|
||||
|
||||
SetupWidgetVisibility();
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionWebsocketEdit::APITypeChanged(int index)
|
||||
@@ -294,7 +294,7 @@ void MacroActionWebsocketEdit::APITypeChanged(int index)
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_api = static_cast<MacroActionWebsocket::API>(index);
|
||||
SetupWidgetVisibility();
|
||||
SetWidgetVisibility();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
@@ -308,7 +308,7 @@ void MacroActionWebsocketEdit::MessageTypeChanged(int index)
|
||||
auto lock = LockContext();
|
||||
_entryData->_type =
|
||||
static_cast<MacroActionWebsocket::MessageType>(index);
|
||||
SetupWidgetVisibility();
|
||||
SetWidgetVisibility();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ protected:
|
||||
|
||||
private:
|
||||
void CheckForSettingsConflict();
|
||||
void SetupWidgetVisibility();
|
||||
void SetWidgetVisibility();
|
||||
void SetupRequestEdit();
|
||||
void SetupEventEdit();
|
||||
void SetupGenericEdit();
|
||||
|
||||
@@ -47,6 +47,12 @@ const static std::map<MacroConditionAudio::VolumeCondition, std::string>
|
||||
"AdvSceneSwitcher.condition.audio.state.unmute"},
|
||||
};
|
||||
|
||||
void MacroConditionAudio::SetType(const Type &type)
|
||||
{
|
||||
_checkType = type;
|
||||
SetupTempVars();
|
||||
}
|
||||
|
||||
MacroConditionAudio::~MacroConditionAudio()
|
||||
{
|
||||
obs_volmeter_remove_callback(_volmeter, SetVolumeLevel, this);
|
||||
@@ -74,6 +80,7 @@ bool MacroConditionAudio::CheckOutputCondition()
|
||||
}
|
||||
|
||||
SetVariableValue(std::to_string(curVolume));
|
||||
SetTempVarValue("output_volume", std::to_string(curVolume));
|
||||
|
||||
// Reset for next check
|
||||
_peak = -std::numeric_limits<float>::infinity();
|
||||
@@ -118,6 +125,9 @@ bool MacroConditionAudio::CheckVolumeCondition()
|
||||
break;
|
||||
}
|
||||
|
||||
SetTempVarValue("configured_volume", std::to_string(curVolume));
|
||||
SetTempVarValue("muted", muted ? "true" : "false");
|
||||
|
||||
obs_source_release(s);
|
||||
return ret;
|
||||
}
|
||||
@@ -137,6 +147,7 @@ bool MacroConditionAudio::CheckSyncOffset()
|
||||
ret = curOffset < _syncOffset;
|
||||
}
|
||||
SetVariableValue(std::to_string(curOffset));
|
||||
SetTempVarValue("sync_offset", std::to_string(curOffset));
|
||||
obs_source_release(s);
|
||||
return ret;
|
||||
}
|
||||
@@ -151,6 +162,8 @@ bool MacroConditionAudio::CheckMonitor()
|
||||
auto s = obs_weak_source_get_source(_audioSource.GetSource());
|
||||
ret = obs_source_get_monitoring_type(s) == _monitorType;
|
||||
SetVariableValue("");
|
||||
SetTempVarValue("monitor",
|
||||
std::to_string(obs_source_get_monitoring_type(s)));
|
||||
obs_source_release(s);
|
||||
return ret;
|
||||
}
|
||||
@@ -170,6 +183,7 @@ bool MacroConditionAudio::CheckBalance()
|
||||
ret = curBalance < _balance;
|
||||
}
|
||||
SetVariableValue(std::to_string(curBalance));
|
||||
SetTempVarValue("balance", std::to_string(curBalance));
|
||||
obs_source_release(s);
|
||||
return ret;
|
||||
}
|
||||
@@ -290,6 +304,50 @@ void MacroConditionAudio::ResetVolmeter()
|
||||
_volmeter = AddVolmeterToSource(this, _audioSource.GetSource());
|
||||
}
|
||||
|
||||
void MacroConditionAudio::SetupTempVars()
|
||||
{
|
||||
MacroCondition::SetupTempVars();
|
||||
switch (_checkType) {
|
||||
case Type::OUTPUT_VOLUME:
|
||||
AddTempvar(
|
||||
"output_volume",
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.audio.output_volume"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.audio.output_volume.description"));
|
||||
break;
|
||||
case Type::CONFIGURED_VOLUME:
|
||||
AddTempvar(
|
||||
"configured_volume",
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.audio.configured_volume"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.audio.configured_volume.description"));
|
||||
AddTempvar("muted",
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.audio.muted"));
|
||||
break;
|
||||
case Type::SYNC_OFFSET:
|
||||
AddTempvar(
|
||||
"sync_offset",
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.audio.sync_offset"));
|
||||
break;
|
||||
case Type::MONITOR:
|
||||
AddTempvar("monitor",
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.audio.monitor"));
|
||||
break;
|
||||
case Type::BALANCE:
|
||||
AddTempvar("balance",
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.audio.balance"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void populateCheckTypes(QComboBox *list)
|
||||
{
|
||||
list->clear();
|
||||
@@ -479,10 +537,9 @@ void MacroConditionAudioEdit::ConditionChanged(int cond)
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
if (_entryData->_checkType ==
|
||||
MacroConditionAudio::Type::OUTPUT_VOLUME ||
|
||||
_entryData->_checkType == MacroConditionAudio::Type::BALANCE ||
|
||||
_entryData->_checkType == MacroConditionAudio::Type::SYNC_OFFSET) {
|
||||
if (_entryData->GetType() == MacroConditionAudio::Type::OUTPUT_VOLUME ||
|
||||
_entryData->GetType() == MacroConditionAudio::Type::BALANCE ||
|
||||
_entryData->GetType() == MacroConditionAudio::Type::SYNC_OFFSET) {
|
||||
_entryData->_outputCondition =
|
||||
static_cast<MacroConditionAudio::OutputCondition>(cond);
|
||||
} else {
|
||||
@@ -499,16 +556,15 @@ void MacroConditionAudioEdit::CheckTypeChanged(int idx)
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_checkType = static_cast<MacroConditionAudio::Type>(
|
||||
_checkTypes->itemData(idx).toInt());
|
||||
_entryData->SetType(static_cast<MacroConditionAudio::Type>(
|
||||
_checkTypes->itemData(idx).toInt()));
|
||||
|
||||
const QSignalBlocker b(_condition);
|
||||
if (_entryData->_checkType ==
|
||||
MacroConditionAudio::Type::OUTPUT_VOLUME ||
|
||||
_entryData->_checkType == MacroConditionAudio::Type::BALANCE ||
|
||||
_entryData->_checkType == MacroConditionAudio::Type::SYNC_OFFSET) {
|
||||
if (_entryData->GetType() == MacroConditionAudio::Type::OUTPUT_VOLUME ||
|
||||
_entryData->GetType() == MacroConditionAudio::Type::BALANCE ||
|
||||
_entryData->GetType() == MacroConditionAudio::Type::SYNC_OFFSET) {
|
||||
populateOutputConditionSelection(_condition);
|
||||
} else if (_entryData->_checkType ==
|
||||
} else if (_entryData->GetType() ==
|
||||
MacroConditionAudio::Type::CONFIGURED_VOLUME) {
|
||||
populateVolumeConditionSelection(_condition);
|
||||
}
|
||||
@@ -526,17 +582,16 @@ void MacroConditionAudioEdit::UpdateEntryData()
|
||||
_syncOffset->SetValue(_entryData->_syncOffset);
|
||||
_monitorTypes->setCurrentIndex(_entryData->_monitorType);
|
||||
_balance->SetDoubleValue(_entryData->_balance);
|
||||
_checkTypes->setCurrentIndex(_checkTypes->findData(
|
||||
static_cast<int>(_entryData->_checkType)));
|
||||
_checkTypes->setCurrentIndex(
|
||||
_checkTypes->findData(static_cast<int>(_entryData->GetType())));
|
||||
|
||||
if (_entryData->_checkType ==
|
||||
MacroConditionAudio::Type::OUTPUT_VOLUME ||
|
||||
_entryData->_checkType == MacroConditionAudio::Type::BALANCE ||
|
||||
_entryData->_checkType == MacroConditionAudio::Type::SYNC_OFFSET) {
|
||||
if (_entryData->GetType() == MacroConditionAudio::Type::OUTPUT_VOLUME ||
|
||||
_entryData->GetType() == MacroConditionAudio::Type::BALANCE ||
|
||||
_entryData->GetType() == MacroConditionAudio::Type::SYNC_OFFSET) {
|
||||
populateOutputConditionSelection(_condition);
|
||||
_condition->setCurrentIndex(
|
||||
static_cast<int>(_entryData->_outputCondition));
|
||||
} else if (_entryData->_checkType ==
|
||||
} else if (_entryData->GetType() ==
|
||||
MacroConditionAudio::Type::CONFIGURED_VOLUME) {
|
||||
populateVolumeConditionSelection(_condition);
|
||||
_condition->setCurrentIndex(
|
||||
@@ -554,9 +609,9 @@ void MacroConditionAudioEdit::SetWidgetVisibility()
|
||||
}
|
||||
|
||||
_volume->setVisible(
|
||||
_entryData->_checkType ==
|
||||
_entryData->GetType() ==
|
||||
MacroConditionAudio::Type::OUTPUT_VOLUME ||
|
||||
(_entryData->_checkType ==
|
||||
(_entryData->GetType() ==
|
||||
MacroConditionAudio::Type::CONFIGURED_VOLUME &&
|
||||
(_entryData->_volumeCondition ==
|
||||
MacroConditionAudio::VolumeCondition::ABOVE ||
|
||||
@@ -565,20 +620,20 @@ void MacroConditionAudioEdit::SetWidgetVisibility()
|
||||
_entryData->_volumeCondition ==
|
||||
MacroConditionAudio::VolumeCondition::BELOW)));
|
||||
_condition->setVisible(
|
||||
_entryData->_checkType ==
|
||||
_entryData->GetType() ==
|
||||
MacroConditionAudio::Type::OUTPUT_VOLUME ||
|
||||
_entryData->_checkType ==
|
||||
_entryData->GetType() ==
|
||||
MacroConditionAudio::Type::CONFIGURED_VOLUME ||
|
||||
_entryData->_checkType == MacroConditionAudio::Type::BALANCE ||
|
||||
_entryData->_checkType ==
|
||||
_entryData->GetType() == MacroConditionAudio::Type::BALANCE ||
|
||||
_entryData->GetType() ==
|
||||
MacroConditionAudio::Type::SYNC_OFFSET);
|
||||
_syncOffset->setVisible(_entryData->_checkType ==
|
||||
_syncOffset->setVisible(_entryData->GetType() ==
|
||||
MacroConditionAudio::Type::SYNC_OFFSET);
|
||||
_monitorTypes->setVisible(_entryData->_checkType ==
|
||||
_monitorTypes->setVisible(_entryData->GetType() ==
|
||||
MacroConditionAudio::Type::MONITOR);
|
||||
_balance->setVisible(_entryData->_checkType ==
|
||||
_balance->setVisible(_entryData->GetType() ==
|
||||
MacroConditionAudio::Type::BALANCE);
|
||||
_volMeter->setVisible(_entryData->_checkType ==
|
||||
_volMeter->setVisible(_entryData->GetType() ==
|
||||
MacroConditionAudio::Type::OUTPUT_VOLUME);
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
@@ -37,6 +37,8 @@ public:
|
||||
MONITOR,
|
||||
BALANCE,
|
||||
};
|
||||
void SetType(const Type &);
|
||||
Type GetType() const { return _checkType; }
|
||||
|
||||
enum class OutputCondition {
|
||||
ABOVE,
|
||||
@@ -56,7 +58,6 @@ public:
|
||||
NumberVariable<int> _syncOffset = 0;
|
||||
obs_monitoring_type _monitorType = OBS_MONITORING_TYPE_NONE;
|
||||
NumberVariable<double> _balance = 0.5;
|
||||
Type _checkType = Type::OUTPUT_VOLUME;
|
||||
OutputCondition _outputCondition = OutputCondition::ABOVE;
|
||||
VolumeCondition _volumeCondition = VolumeCondition::ABOVE;
|
||||
obs_volmeter_t *_volmeter = nullptr;
|
||||
@@ -67,7 +68,9 @@ private:
|
||||
bool CheckSyncOffset();
|
||||
bool CheckMonitor();
|
||||
bool CheckBalance();
|
||||
void SetupTempVars();
|
||||
|
||||
Type _checkType = Type::OUTPUT_VOLUME;
|
||||
float _peak = -std::numeric_limits<float>::infinity();
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
|
||||
@@ -60,7 +60,8 @@ const static std::map<MacroConditionDate::Day, std::string> dayOfWeekNames = {
|
||||
bool MacroConditionDate::CheckDayOfWeek(int64_t msSinceLastCheck)
|
||||
{
|
||||
QDateTime cur = QDateTime::currentDateTime();
|
||||
SetVariableValue(cur.toString().toStdString());
|
||||
SetVariables(cur);
|
||||
|
||||
if (_dayOfWeek != Day::ANY &&
|
||||
cur.date().dayOfWeek() != static_cast<int>(_dayOfWeek)) {
|
||||
return false;
|
||||
@@ -133,7 +134,7 @@ bool MacroConditionDate::CheckRegularDate(int64_t msSinceLastCheck)
|
||||
{
|
||||
bool match = false;
|
||||
QDateTime cur = QDateTime::currentDateTime();
|
||||
SetVariableValue(cur.toString().toStdString());
|
||||
SetVariables(cur);
|
||||
|
||||
if (_ignoreDate) {
|
||||
_dateTime.setDate(cur.date());
|
||||
@@ -304,6 +305,37 @@ QDateTime MacroConditionDate::GetNextMatchDateTime() const
|
||||
return _dateTime;
|
||||
}
|
||||
|
||||
void MacroConditionDate::SetVariables(const QDateTime &date)
|
||||
{
|
||||
SetVariableValue(date.toString().toStdString());
|
||||
|
||||
SetTempVarValue("year", std::to_string(date.date().year()));
|
||||
SetTempVarValue("month", std::to_string(date.date().month()));
|
||||
SetTempVarValue("day", std::to_string(date.date().day()));
|
||||
SetTempVarValue("hour", std::to_string(date.time().hour()));
|
||||
SetTempVarValue("minute", std::to_string(date.time().minute()));
|
||||
SetTempVarValue("second", std::to_string(date.time().second()));
|
||||
SetTempVarValue("dayOfWeek", std::to_string(date.date().dayOfWeek()));
|
||||
}
|
||||
|
||||
void MacroConditionDate::SetupTempVars()
|
||||
{
|
||||
MacroCondition::SetupTempVars();
|
||||
AddTempvar("year",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.date.year"));
|
||||
AddTempvar("month",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.date.month"));
|
||||
AddTempvar("day", obs_module_text("AdvSceneSwitcher.tempVar.date.day"));
|
||||
AddTempvar("hour",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.date.hour"));
|
||||
AddTempvar("minute",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.date.minute"));
|
||||
AddTempvar("second",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.date.second"));
|
||||
AddTempvar("dayOfWeek",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.date.dayOfWeek"));
|
||||
}
|
||||
|
||||
static inline void populateDaySelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : dayOfWeekNames) {
|
||||
|
||||
@@ -64,6 +64,8 @@ private:
|
||||
bool CheckRegularDate(int64_t);
|
||||
bool CheckBetween(const QDateTime &now);
|
||||
bool CheckPattern(QDateTime now, int64_t secondsSinceLastCheck);
|
||||
void SetVariables(const QDateTime &date);
|
||||
void SetupTempVars();
|
||||
|
||||
QDateTime _dateTime = QDateTime::currentDateTime();
|
||||
QDateTime _dateTime2 = QDateTime::currentDateTime();
|
||||
|
||||
@@ -312,6 +312,7 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
||||
*_entryData = MacroConditionFactory::Create(id, macro);
|
||||
(*_entryData)->SetIndex(idx);
|
||||
(*_entryData)->SetLogicType(logic);
|
||||
(*_entryData)->PostLoad();
|
||||
}
|
||||
auto widget =
|
||||
MacroConditionFactory::CreateWidget(id, this, *_entryData);
|
||||
@@ -342,7 +343,7 @@ void MacroConditionEdit::DurationModifierChanged(DurationModifier::Type m)
|
||||
(*_entryData)->SetDurationModifier(m);
|
||||
}
|
||||
|
||||
std::shared_ptr<MacroSegment> MacroConditionEdit::Data()
|
||||
std::shared_ptr<MacroSegment> MacroConditionEdit::Data() const
|
||||
{
|
||||
return *_entryData;
|
||||
}
|
||||
@@ -383,9 +384,10 @@ void AdvSceneSwitcher::AddMacroCondition(int idx)
|
||||
macro->Conditions().at(idx)->Load(data);
|
||||
obs_data_release(data);
|
||||
}
|
||||
macro->Conditions().at(idx)->PostLoad();
|
||||
(*cond)->SetLogicType(logic);
|
||||
macro->UpdateConditionIndices();
|
||||
conditionsList->Insert(
|
||||
ui->conditionsList->Insert(
|
||||
idx,
|
||||
new MacroConditionEdit(this, ¯o->Conditions()[idx],
|
||||
id, idx == 0));
|
||||
@@ -410,7 +412,7 @@ void AdvSceneSwitcher::on_conditionAdd_clicked()
|
||||
if (currentConditionIdx != -1) {
|
||||
MacroConditionSelectionChanged(currentConditionIdx + 1);
|
||||
}
|
||||
conditionsList->SetHelpMsgVisible(false);
|
||||
ui->conditionsList->SetHelpMsgVisible(false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::RemoveMacroCondition(int idx)
|
||||
@@ -426,14 +428,14 @@ void AdvSceneSwitcher::RemoveMacroCondition(int idx)
|
||||
|
||||
{
|
||||
auto lock = LockContext();
|
||||
conditionsList->Remove(idx);
|
||||
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(LogicType::ROOT_NONE);
|
||||
static_cast<MacroConditionEdit *>(
|
||||
conditionsList->WidgetAt(0))
|
||||
ui->conditionsList->WidgetAt(0))
|
||||
->SetRootNode(true);
|
||||
}
|
||||
SetConditionData(*macro);
|
||||
@@ -479,7 +481,7 @@ void AdvSceneSwitcher::on_conditionDown_clicked()
|
||||
{
|
||||
if (currentConditionIdx == -1 ||
|
||||
currentConditionIdx ==
|
||||
conditionsList->ContentLayout()->count() - 1) {
|
||||
ui->conditionsList->ContentLayout()->count() - 1) {
|
||||
return;
|
||||
}
|
||||
MoveMacroConditionDown(currentConditionIdx);
|
||||
@@ -491,7 +493,7 @@ void AdvSceneSwitcher::on_conditionBottom_clicked()
|
||||
if (currentConditionIdx == -1) {
|
||||
return;
|
||||
}
|
||||
const int newIdx = conditionsList->ContentLayout()->count() - 1;
|
||||
const int newIdx = ui->conditionsList->ContentLayout()->count() - 1;
|
||||
MacroConditionReorder(newIdx, currentConditionIdx);
|
||||
MacroConditionSelectionChanged(newIdx);
|
||||
}
|
||||
@@ -521,11 +523,11 @@ void AdvSceneSwitcher::SwapConditions(Macro *m, int pos1, int pos2)
|
||||
}
|
||||
|
||||
auto widget1 = static_cast<MacroConditionEdit *>(
|
||||
conditionsList->ContentLayout()->takeAt(pos1)->widget());
|
||||
ui->conditionsList->ContentLayout()->takeAt(pos1)->widget());
|
||||
auto widget2 = static_cast<MacroConditionEdit *>(
|
||||
conditionsList->ContentLayout()->takeAt(pos2 - 1)->widget());
|
||||
conditionsList->Insert(pos1, widget2);
|
||||
conditionsList->Insert(pos2, widget1);
|
||||
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);
|
||||
@@ -564,22 +566,7 @@ void AdvSceneSwitcher::MoveMacroConditionDown(int idx)
|
||||
|
||||
void AdvSceneSwitcher::MacroConditionSelectionChanged(int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
conditionsList->SetSelection(idx);
|
||||
actionsList->SetSelection(-1);
|
||||
|
||||
if (idx < 0 || (unsigned)idx >= macro->Conditions().size()) {
|
||||
currentConditionIdx = -1;
|
||||
} else {
|
||||
currentConditionIdx = idx;
|
||||
lastInteracted = MacroSection::CONDITIONS;
|
||||
}
|
||||
currentActionIdx = -1;
|
||||
HighlightControls();
|
||||
SetupMacroSegmentSelection(MacroSection::CONDITIONS, idx);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MacroConditionReorder(int to, int from)
|
||||
@@ -599,30 +586,30 @@ void AdvSceneSwitcher::MacroConditionReorder(int to, int from)
|
||||
if (to == 0) {
|
||||
condition->SetLogicType(LogicType::ROOT_NONE);
|
||||
static_cast<MacroConditionEdit *>(
|
||||
conditionsList->WidgetAt(from))
|
||||
ui->conditionsList->WidgetAt(from))
|
||||
->SetRootNode(true);
|
||||
macro->Conditions().at(0)->SetLogicType(LogicType::AND);
|
||||
static_cast<MacroConditionEdit *>(
|
||||
conditionsList->WidgetAt(0))
|
||||
ui->conditionsList->WidgetAt(0))
|
||||
->SetRootNode(false);
|
||||
}
|
||||
if (from == 0) {
|
||||
condition->SetLogicType(LogicType::AND);
|
||||
static_cast<MacroConditionEdit *>(
|
||||
conditionsList->WidgetAt(from))
|
||||
ui->conditionsList->WidgetAt(from))
|
||||
->SetRootNode(false);
|
||||
macro->Conditions().at(1)->SetLogicType(
|
||||
LogicType::ROOT_NONE);
|
||||
static_cast<MacroConditionEdit *>(
|
||||
conditionsList->WidgetAt(1))
|
||||
ui->conditionsList->WidgetAt(1))
|
||||
->SetRootNode(true);
|
||||
}
|
||||
macro->Conditions().erase(macro->Conditions().begin() + from);
|
||||
macro->Conditions().insert(macro->Conditions().begin() + to,
|
||||
condition);
|
||||
macro->UpdateConditionIndices();
|
||||
conditionsList->ContentLayout()->insertItem(
|
||||
to, conditionsList->ContentLayout()->takeAt(from));
|
||||
ui->conditionsList->ContentLayout()->insertItem(
|
||||
to, ui->conditionsList->ContentLayout()->takeAt(from));
|
||||
SetConditionData(*macro);
|
||||
}
|
||||
HighlightCondition(to);
|
||||
|
||||
@@ -75,7 +75,7 @@ private slots:
|
||||
|
||||
private:
|
||||
void SetLogicSelection();
|
||||
std::shared_ptr<MacroSegment> Data();
|
||||
std::shared_ptr<MacroSegment> Data() const;
|
||||
|
||||
QComboBox *_logicSelection;
|
||||
FilterComboBox *_conditionSelection;
|
||||
|
||||
@@ -18,19 +18,20 @@ const static std::map<MacroConditionFilter::Condition, std::string>
|
||||
"AdvSceneSwitcher.condition.filter.type.active"},
|
||||
{MacroConditionFilter::Condition::DISABLED,
|
||||
"AdvSceneSwitcher.condition.filter.type.showing"},
|
||||
{MacroConditionFilter::Condition::SETTINGS,
|
||||
{MacroConditionFilter::Condition::SETTINGS_MATCH,
|
||||
"AdvSceneSwitcher.condition.filter.type.settings"},
|
||||
{MacroConditionFilter::Condition::SETTINGS_CHANGED,
|
||||
"AdvSceneSwitcher.condition.filter.type.settingsChanged"},
|
||||
};
|
||||
|
||||
bool MacroConditionFilter::CheckCondition()
|
||||
bool MacroConditionFilter::CheckConditionHelper(const OBSWeakSource &filter)
|
||||
{
|
||||
auto filterWeakSource = _filter.GetFilter(_source);
|
||||
if (!filterWeakSource) {
|
||||
bool ret = false;
|
||||
OBSSourceAutoRelease filterSource = obs_weak_source_get_source(filter);
|
||||
if (!filterSource.Get()) {
|
||||
return false;
|
||||
}
|
||||
auto filterSource = obs_weak_source_get_source(filterWeakSource);
|
||||
|
||||
bool ret = false;
|
||||
switch (_condition) {
|
||||
case Condition::ENABLED:
|
||||
ret = obs_source_enabled(filterSource);
|
||||
@@ -38,18 +39,36 @@ bool MacroConditionFilter::CheckCondition()
|
||||
case Condition::DISABLED:
|
||||
ret = !obs_source_enabled(filterSource);
|
||||
break;
|
||||
case Condition::SETTINGS:
|
||||
ret = CompareSourceSettings(filterWeakSource, _settings,
|
||||
_regex);
|
||||
case Condition::SETTINGS_MATCH:
|
||||
ret = CompareSourceSettings(filter, _settings, _regex);
|
||||
if (IsReferencedInVars()) {
|
||||
SetVariableValue(GetSourceSettings(filterWeakSource));
|
||||
SetVariableValue(GetSourceSettings(filter));
|
||||
}
|
||||
break;
|
||||
case Condition::SETTINGS_CHANGED: {
|
||||
std::string settings = GetSourceSettings(_source.GetSource());
|
||||
ret = !_currentSettings.empty() && settings != _currentSettings;
|
||||
_currentSettings = settings;
|
||||
SetVariableValue(settings);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
obs_source_release(filterSource);
|
||||
bool MacroConditionFilter::CheckCondition()
|
||||
{
|
||||
auto filters = _filter.GetFilters(_source);
|
||||
if (filters.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = true;
|
||||
for (const auto &filter : filters) {
|
||||
ret = ret && CheckConditionHelper(filter);
|
||||
}
|
||||
|
||||
if (GetVariableValue().empty()) {
|
||||
SetVariableValue(ret ? "true" : "false");
|
||||
@@ -95,8 +114,8 @@ std::string MacroConditionFilter::GetShortDesc() const
|
||||
|
||||
static inline void populateConditionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : filterConditionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
for (const auto &[_, name] : filterConditionTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -194,19 +213,20 @@ void MacroConditionFilterEdit::ConditionChanged(int index)
|
||||
auto lock = LockContext();
|
||||
_entryData->_condition =
|
||||
static_cast<MacroConditionFilter::Condition>(index);
|
||||
SetSettingsSelectionVisible(_entryData->_condition ==
|
||||
MacroConditionFilter::Condition::SETTINGS);
|
||||
SetSettingsSelectionVisible(
|
||||
_entryData->_condition ==
|
||||
MacroConditionFilter::Condition::SETTINGS_MATCH);
|
||||
}
|
||||
|
||||
void MacroConditionFilterEdit::GetSettingsClicked()
|
||||
{
|
||||
if (_loading || !_entryData ||
|
||||
!_entryData->_filter.GetFilter(_entryData->_source)) {
|
||||
_entryData->_filter.GetFilters(_entryData->_source).empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QString json = FormatJsonString(GetSourceSettings(
|
||||
_entryData->_filter.GetFilter(_entryData->_source)));
|
||||
_entryData->_filter.GetFilters(_entryData->_source).at(0)));
|
||||
if (_entryData->_regex.Enabled()) {
|
||||
json = EscapeForRegex(json);
|
||||
}
|
||||
@@ -259,8 +279,9 @@ void MacroConditionFilterEdit::UpdateEntryData()
|
||||
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||
_settings->setPlainText(_entryData->_settings);
|
||||
_regex->SetRegexConfig(_entryData->_regex);
|
||||
SetSettingsSelectionVisible(_entryData->_condition ==
|
||||
MacroConditionFilter::Condition::SETTINGS);
|
||||
SetSettingsSelectionVisible(
|
||||
_entryData->_condition ==
|
||||
MacroConditionFilter::Condition::SETTINGS_MATCH);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
|
||||
@@ -27,7 +27,8 @@ public:
|
||||
enum class Condition {
|
||||
ENABLED,
|
||||
DISABLED,
|
||||
SETTINGS,
|
||||
SETTINGS_MATCH,
|
||||
SETTINGS_CHANGED,
|
||||
};
|
||||
|
||||
SourceSelection _source;
|
||||
@@ -37,6 +38,9 @@ public:
|
||||
RegexConfig _regex;
|
||||
|
||||
private:
|
||||
bool CheckConditionHelper(const OBSWeakSource &);
|
||||
|
||||
std::string _currentSettings;
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "process-config.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <thread>
|
||||
#include <QCheckBox>
|
||||
#include <QSpinBox>
|
||||
|
||||
|
||||
@@ -12,19 +12,79 @@ bool MacroConditionSceneTransform::_registered =
|
||||
MacroConditionSceneTransformEdit::Create,
|
||||
"AdvSceneSwitcher.condition.sceneTransform"});
|
||||
|
||||
bool MacroConditionSceneTransform::CheckCondition()
|
||||
const static std::map<MacroConditionSceneTransform::CondType, std::string>
|
||||
conditionTypes = {
|
||||
{MacroConditionSceneTransform::CondType::MATCHES,
|
||||
"AdvSceneSwitcher.condition.sceneTransform.entry.type.matches"},
|
||||
{MacroConditionSceneTransform::CondType::CHANGED,
|
||||
"AdvSceneSwitcher.condition.sceneTransform.entry.type.changed"},
|
||||
};
|
||||
|
||||
static bool doesTransformOfAnySceneItemMatch(
|
||||
const std::vector<OBSSceneItem> &items, const std::string &jsonCompare,
|
||||
const RegexConfig ®ex, std::string &newVariable)
|
||||
{
|
||||
bool ret = false;
|
||||
auto items = _source.GetSceneItems(_scene);
|
||||
|
||||
std::string json;
|
||||
for (const auto &item : items) {
|
||||
json = GetSceneItemTransform(item);
|
||||
if (MatchJson(json, _settings, _regex)) {
|
||||
if (MatchJson(json, jsonCompare, regex)) {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
SetVariableValue(json);
|
||||
newVariable = json;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
didTransformOfAnySceneItemChange(const std::vector<OBSSceneItem> &items,
|
||||
std::vector<std::string> &previousTransform,
|
||||
std::string &newVariable)
|
||||
{
|
||||
bool ret = false;
|
||||
std::string json;
|
||||
RegexConfig regex;
|
||||
auto numItems = items.size();
|
||||
if (previousTransform.size() < numItems) {
|
||||
ret = true;
|
||||
previousTransform.resize(numItems);
|
||||
}
|
||||
for (size_t idx = 0; idx < numItems; ++idx) {
|
||||
auto const &item = items[idx];
|
||||
json = GetSceneItemTransform(item);
|
||||
if (!MatchJson(json, previousTransform[idx], regex)) {
|
||||
ret = true;
|
||||
previousTransform[idx] = json;
|
||||
}
|
||||
}
|
||||
newVariable = json;
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool MacroConditionSceneTransform::CheckCondition()
|
||||
{
|
||||
auto items = _source.GetSceneItems(_scene);
|
||||
if (items.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string newVariable = "";
|
||||
bool ret = false;
|
||||
switch (_type) {
|
||||
case CondType::MATCHES:
|
||||
ret = doesTransformOfAnySceneItemMatch(items, _settings, _regex,
|
||||
newVariable);
|
||||
break;
|
||||
case CondType::CHANGED:
|
||||
ret = didTransformOfAnySceneItemChange(
|
||||
items, _previousTransform, newVariable);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
SetVariableValue(newVariable);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -35,6 +95,7 @@ bool MacroConditionSceneTransform::Save(obs_data_t *obj) const
|
||||
_source.Save(obj);
|
||||
_settings.Save(obj, "settings");
|
||||
_regex.Save(obj);
|
||||
obs_data_set_int(obj, "type", static_cast<int>(_type));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -52,6 +113,7 @@ bool MacroConditionSceneTransform::Load(obs_data_t *obj)
|
||||
_source.Load(obj);
|
||||
_settings.Load(obj, "settings");
|
||||
_regex.Load(obj);
|
||||
_type = static_cast<CondType>(obs_data_get_int(obj, "type"));
|
||||
// TOOD: remove in future version
|
||||
if (obs_data_has_user_value(obj, "regex")) {
|
||||
_regex.CreateBackwardsCompatibleRegex(
|
||||
@@ -69,6 +131,13 @@ std::string MacroConditionSceneTransform::GetShortDesc() const
|
||||
return _scene.ToString() + " - " + _source.ToString();
|
||||
}
|
||||
|
||||
static inline void populateTypesSelection(QComboBox *list)
|
||||
{
|
||||
for (const auto &entry : conditionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroConditionSceneTransformEdit::MacroConditionSceneTransformEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionSceneTransform> entryData)
|
||||
@@ -76,11 +145,14 @@ MacroConditionSceneTransformEdit::MacroConditionSceneTransformEdit(
|
||||
_scenes(new SceneSelectionWidget(window(), true, false, false, true)),
|
||||
_sources(new SceneItemSelectionWidget(
|
||||
parent, true, SceneItemSelectionWidget::Placeholder::ANY)),
|
||||
_types(new QComboBox()),
|
||||
_getSettings(new QPushButton(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.sceneTransform.getTransform"))),
|
||||
_settings(new VariableTextEdit(this)),
|
||||
_regex(new RegexConfigWidget(parent))
|
||||
{
|
||||
populateTypesSelection(_types);
|
||||
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
@@ -88,6 +160,8 @@ MacroConditionSceneTransformEdit::MacroConditionSceneTransformEdit(
|
||||
QWidget::connect(_sources,
|
||||
SIGNAL(SceneItemChanged(const SceneItemSelection &)),
|
||||
this, SLOT(SourceChanged(const SceneItemSelection &)));
|
||||
QWidget::connect(_types, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(TypeChanged(int)));
|
||||
QWidget::connect(_getSettings, SIGNAL(clicked()), this,
|
||||
SLOT(GetSettingsClicked()));
|
||||
QWidget::connect(_settings, SIGNAL(textChanged()), this,
|
||||
@@ -96,8 +170,11 @@ MacroConditionSceneTransformEdit::MacroConditionSceneTransformEdit(
|
||||
SLOT(RegexChanged(RegexConfig)));
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{scenes}}", _scenes}, {"{{sources}}", _sources},
|
||||
{"{{settings}}", _settings}, {"{{getSettings}}", _getSettings},
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{sources}}", _sources},
|
||||
{"{{types}}", _types},
|
||||
{"{{settings}}", _settings},
|
||||
{"{{getSettings}}", _getSettings},
|
||||
{"{{regex}}", _regex},
|
||||
};
|
||||
|
||||
@@ -136,11 +213,10 @@ void MacroConditionSceneTransformEdit::UpdateEntryData()
|
||||
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
_sources->SetSceneItem(_entryData->_source);
|
||||
_types->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||
_regex->SetRegexConfig(_entryData->_regex);
|
||||
_settings->setPlainText(_entryData->_settings);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionSceneTransformEdit::SceneChanged(const SceneSelection &s)
|
||||
@@ -168,6 +244,18 @@ void MacroConditionSceneTransformEdit::SourceChanged(
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionSceneTransformEdit::TypeChanged(int index)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_type =
|
||||
static_cast<MacroConditionSceneTransform::CondType>(index);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionSceneTransformEdit::GetSettingsClicked()
|
||||
{
|
||||
|
||||
@@ -213,4 +301,16 @@ void MacroConditionSceneTransformEdit::RegexChanged(RegexConfig conf)
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionSceneTransformEdit::SetWidgetVisibility()
|
||||
{
|
||||
const bool showSettingsAndRegex =
|
||||
_entryData->_type ==
|
||||
MacroConditionSceneTransform::CondType::MATCHES;
|
||||
_settings->setVisible(showSettingsAndRegex);
|
||||
_getSettings->setVisible(showSettingsAndRegex);
|
||||
_regex->setVisible(showSettingsAndRegex);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -23,12 +23,20 @@ public:
|
||||
return std::make_shared<MacroConditionSceneTransform>(m);
|
||||
}
|
||||
|
||||
enum class CondType {
|
||||
MATCHES,
|
||||
CHANGED,
|
||||
};
|
||||
|
||||
SceneSelection _scene;
|
||||
SceneItemSelection _source;
|
||||
CondType _type = CondType::MATCHES;
|
||||
RegexConfig _regex;
|
||||
StringVariable _settings = "";
|
||||
|
||||
private:
|
||||
std::vector<std::string> _previousTransform;
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
@@ -54,6 +62,7 @@ public:
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const SceneItemSelection &);
|
||||
void TypeChanged(int type);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
void RegexChanged(RegexConfig);
|
||||
@@ -63,6 +72,7 @@ signals:
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
SceneItemSelectionWidget *_sources;
|
||||
QComboBox *_types;
|
||||
QPushButton *_getSettings;
|
||||
VariableTextEdit *_settings;
|
||||
RegexConfigWidget *_regex;
|
||||
@@ -70,6 +80,7 @@ protected:
|
||||
std::shared_ptr<MacroConditionSceneTransform> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ const static std::map<MacroConditionScene::Type, std::string> sceneTypes = {
|
||||
"AdvSceneSwitcher.condition.scene.type.current"},
|
||||
{MacroConditionScene::Type::PREVIOUS,
|
||||
"AdvSceneSwitcher.condition.scene.type.previous"},
|
||||
{MacroConditionScene::Type::PREVIEW,
|
||||
"AdvSceneSwitcher.condition.scene.type.preview"},
|
||||
{MacroConditionScene::Type::CHANGED,
|
||||
"AdvSceneSwitcher.condition.scene.type.changed"},
|
||||
{MacroConditionScene::Type::NOT_CHANGED,
|
||||
@@ -24,6 +26,8 @@ const static std::map<MacroConditionScene::Type, std::string> sceneTypes = {
|
||||
"AdvSceneSwitcher.condition.scene.type.currentPattern"},
|
||||
{MacroConditionScene::Type::PREVIOUS_PATTERN,
|
||||
"AdvSceneSwitcher.condition.scene.type.previousPattern"},
|
||||
{MacroConditionScene::Type::PREVIEW_PATTERN,
|
||||
"AdvSceneSwitcher.condition.scene.type.previewPattern"},
|
||||
};
|
||||
|
||||
static bool sceneNameMatchesRegex(const OBSWeakSource &scene,
|
||||
@@ -72,29 +76,55 @@ bool MacroConditionScene::CheckCondition()
|
||||
case Type::CURRENT: {
|
||||
auto scene = getCurrentSceneHelper(_useTransitionTargetScene);
|
||||
SetVariableValue(GetWeakSourceName(scene));
|
||||
SetTempVarValue("current", GetWeakSourceName(scene));
|
||||
return scene == _scene.GetScene(false);
|
||||
}
|
||||
case Type::PREVIOUS: {
|
||||
auto scene = getPreviousSceneHelper(_useTransitionTargetScene);
|
||||
SetVariableValue(GetWeakSourceName(scene));
|
||||
SetTempVarValue("previous", GetWeakSourceName(scene));
|
||||
return scene == _scene.GetScene(false);
|
||||
}
|
||||
case Type::PREVIEW: {
|
||||
OBSSourceAutoRelease source =
|
||||
obs_frontend_get_current_preview_scene();
|
||||
OBSWeakSourceAutoRelease scene =
|
||||
obs_source_get_weak_source(source);
|
||||
SetVariableValue(GetWeakSourceName(scene));
|
||||
SetTempVarValue("preview", GetWeakSourceName(scene));
|
||||
return scene == _scene.GetScene(false);
|
||||
}
|
||||
case Type::CHANGED:
|
||||
SetVariableValue(GetWeakSourceName(switcher->currentScene));
|
||||
SetTempVarValue("current",
|
||||
GetWeakSourceName(switcher->currentScene));
|
||||
return sceneChanged;
|
||||
case Type::NOT_CHANGED:
|
||||
SetVariableValue(GetWeakSourceName(switcher->currentScene));
|
||||
SetTempVarValue("current",
|
||||
GetWeakSourceName(switcher->currentScene));
|
||||
return !sceneChanged;
|
||||
case Type::CURRENT_PATTERN: {
|
||||
auto scene = getCurrentSceneHelper(_useTransitionTargetScene);
|
||||
SetVariableValue(GetWeakSourceName(scene));
|
||||
SetTempVarValue("current", GetWeakSourceName(scene));
|
||||
return sceneNameMatchesRegex(scene, _pattern);
|
||||
}
|
||||
case Type::PREVIOUS_PATTERN: {
|
||||
auto scene = getPreviousSceneHelper(_useTransitionTargetScene);
|
||||
SetVariableValue(GetWeakSourceName(scene));
|
||||
SetTempVarValue("previous", GetWeakSourceName(scene));
|
||||
return sceneNameMatchesRegex(scene, _pattern);
|
||||
}
|
||||
case Type::PREVIEW_PATTERN: {
|
||||
OBSSourceAutoRelease source =
|
||||
obs_frontend_get_current_preview_scene();
|
||||
OBSWeakSourceAutoRelease scene =
|
||||
obs_source_get_weak_source(source);
|
||||
SetVariableValue(GetWeakSourceName(scene));
|
||||
SetTempVarValue("preview", GetWeakSourceName(scene));
|
||||
return sceneNameMatchesRegex(scene.Get(), _pattern);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -108,6 +138,7 @@ bool MacroConditionScene::Save(obs_data_t *obj) const
|
||||
obs_data_set_string(obj, "pattern", _pattern.c_str());
|
||||
obs_data_set_bool(obj, "useTransitionTargetScene",
|
||||
_useTransitionTargetScene);
|
||||
obs_data_set_int(obj, "version", 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -124,6 +155,46 @@ bool MacroConditionScene::Load(obs_data_t *obj)
|
||||
_useTransitionTargetScene =
|
||||
obs_data_get_bool(obj, "useTransitionTargetScene");
|
||||
}
|
||||
|
||||
// TODO: Remove fallback in future version
|
||||
if (!obs_data_has_user_value(obj, "version")) {
|
||||
enum {
|
||||
CURRENT,
|
||||
PREVIOUS,
|
||||
CHANGED,
|
||||
NOT_CHANGED,
|
||||
CURRENT_PATTERN,
|
||||
PREVIOUS_PATTERN,
|
||||
};
|
||||
|
||||
int oldType = obs_data_get_int(obj, "type");
|
||||
switch (oldType) {
|
||||
case CURRENT:
|
||||
_type = Type::CURRENT;
|
||||
break;
|
||||
case PREVIOUS:
|
||||
_type = Type::PREVIOUS;
|
||||
break;
|
||||
case CHANGED:
|
||||
_type = Type::CHANGED;
|
||||
break;
|
||||
case NOT_CHANGED:
|
||||
_type = Type::NOT_CHANGED;
|
||||
break;
|
||||
case CURRENT_PATTERN:
|
||||
_type = Type::CURRENT_PATTERN;
|
||||
break;
|
||||
case PREVIOUS_PATTERN:
|
||||
_type = Type::PREVIOUS_PATTERN;
|
||||
break;
|
||||
default:
|
||||
blog(LOG_WARNING,
|
||||
"failed to convert scene condition type (%d) for macro %s",
|
||||
oldType, GetMacro()->Name().c_str());
|
||||
_type = Type::CURRENT;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -135,10 +206,46 @@ std::string MacroConditionScene::GetShortDesc() const
|
||||
return "";
|
||||
}
|
||||
|
||||
void MacroConditionScene::SetupTempVars()
|
||||
{
|
||||
MacroCondition::SetupTempVars();
|
||||
switch (_type) {
|
||||
case Type::CURRENT:
|
||||
case Type::CHANGED:
|
||||
case Type::NOT_CHANGED:
|
||||
case Type::CURRENT_PATTERN:
|
||||
AddTempvar("current",
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.scene.current"));
|
||||
break;
|
||||
case Type::PREVIOUS:
|
||||
case Type::PREVIOUS_PATTERN:
|
||||
AddTempvar("previous",
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.scene.previous"));
|
||||
break;
|
||||
case Type::PREVIEW:
|
||||
case Type::PREVIEW_PATTERN:
|
||||
AddTempvar("preview",
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.scene.preview"));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionScene::SetType(const Type &type)
|
||||
{
|
||||
_type = type;
|
||||
SetupTempVars();
|
||||
}
|
||||
|
||||
static inline void populateTypeSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : sceneTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
for (const auto &[id, name] : sceneTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -199,14 +306,15 @@ void MacroConditionSceneEdit::SceneChanged(const SceneSelection &s)
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionSceneEdit::TypeChanged(int value)
|
||||
void MacroConditionSceneEdit::TypeChanged(int index)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_type = static_cast<MacroConditionScene::Type>(value);
|
||||
_entryData->SetType(static_cast<MacroConditionScene::Type>(
|
||||
_sceneType->itemData(index).toInt()));
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
@@ -233,32 +341,38 @@ void MacroConditionSceneEdit::UseTransitionTargetSceneChanged(int state)
|
||||
void MacroConditionSceneEdit::SetWidgetVisibility()
|
||||
{
|
||||
_scenes->setVisible(
|
||||
_entryData->_type == MacroConditionScene::Type::CURRENT ||
|
||||
_entryData->_type == MacroConditionScene::Type::PREVIOUS);
|
||||
_entryData->GetType() == MacroConditionScene::Type::CURRENT ||
|
||||
_entryData->GetType() == MacroConditionScene::Type::PREVIOUS ||
|
||||
_entryData->GetType() == MacroConditionScene::Type::PREVIEW);
|
||||
_useTransitionTargetScene->setVisible(
|
||||
_entryData->_type == MacroConditionScene::Type::CURRENT ||
|
||||
_entryData->_type == MacroConditionScene::Type::PREVIOUS ||
|
||||
_entryData->_type ==
|
||||
_entryData->GetType() == MacroConditionScene::Type::CURRENT ||
|
||||
_entryData->GetType() == MacroConditionScene::Type::PREVIOUS ||
|
||||
_entryData->GetType() ==
|
||||
MacroConditionScene::Type::CURRENT_PATTERN ||
|
||||
_entryData->_type ==
|
||||
_entryData->GetType() ==
|
||||
MacroConditionScene::Type::PREVIOUS_PATTERN);
|
||||
_pattern->setVisible(
|
||||
_entryData->_type ==
|
||||
_entryData->GetType() ==
|
||||
MacroConditionScene::Type::CURRENT_PATTERN ||
|
||||
_entryData->_type ==
|
||||
MacroConditionScene::Type::PREVIOUS_PATTERN);
|
||||
_entryData->GetType() ==
|
||||
MacroConditionScene::Type::PREVIOUS_PATTERN ||
|
||||
_entryData->GetType() ==
|
||||
MacroConditionScene::Type::PREVIEW_PATTERN);
|
||||
|
||||
if (_entryData->_type == MacroConditionScene::Type::PREVIOUS ||
|
||||
_entryData->_type == MacroConditionScene::Type::PREVIOUS_PATTERN) {
|
||||
if (_entryData->GetType() == MacroConditionScene::Type::PREVIOUS ||
|
||||
_entryData->GetType() ==
|
||||
MacroConditionScene::Type::PREVIOUS_PATTERN) {
|
||||
_useTransitionTargetScene->setText(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour"));
|
||||
}
|
||||
if (_entryData->_type == MacroConditionScene::Type::CURRENT ||
|
||||
_entryData->_type == MacroConditionScene::Type::CURRENT_PATTERN) {
|
||||
if (_entryData->GetType() == MacroConditionScene::Type::CURRENT ||
|
||||
_entryData->GetType() ==
|
||||
MacroConditionScene::Type::CURRENT_PATTERN) {
|
||||
_useTransitionTargetScene->setText(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour"));
|
||||
}
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionSceneEdit::UpdateEntryData()
|
||||
@@ -268,7 +382,8 @@ void MacroConditionSceneEdit::UpdateEntryData()
|
||||
}
|
||||
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
_sceneType->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||
_sceneType->setCurrentIndex(
|
||||
_sceneType->findData(static_cast<int>(_entryData->GetType())));
|
||||
_pattern->setText(QString::fromStdString(_entryData->_pattern));
|
||||
_useTransitionTargetScene->setChecked(
|
||||
_entryData->_useTransitionTargetScene);
|
||||
|
||||
@@ -23,16 +23,19 @@ public:
|
||||
}
|
||||
|
||||
enum class Type {
|
||||
CURRENT,
|
||||
PREVIOUS,
|
||||
CHANGED,
|
||||
NOT_CHANGED,
|
||||
CURRENT_PATTERN,
|
||||
PREVIOUS_PATTERN,
|
||||
CURRENT = 10,
|
||||
PREVIOUS = 20,
|
||||
PREVIEW = 30,
|
||||
CHANGED = 40,
|
||||
NOT_CHANGED = 50,
|
||||
CURRENT_PATTERN = 60,
|
||||
PREVIOUS_PATTERN = 70,
|
||||
PREVIEW_PATTERN = 80,
|
||||
};
|
||||
void SetType(const Type &);
|
||||
Type GetType() const { return _type; }
|
||||
|
||||
SceneSelection _scene;
|
||||
Type _type = Type::CURRENT;
|
||||
std::string _pattern = ".*Scene.*";
|
||||
// During a transition "current" scene could either stand for the scene
|
||||
// being transitioned to or the scene still being transitioned away
|
||||
@@ -40,6 +43,9 @@ public:
|
||||
bool _useTransitionTargetScene = false;
|
||||
|
||||
private:
|
||||
void SetupTempVars();
|
||||
|
||||
Type _type = Type::CURRENT;
|
||||
std::chrono::high_resolution_clock::time_point _lastSceneChangeTime{};
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
|
||||
@@ -6,10 +6,13 @@ namespace advss {
|
||||
|
||||
const std::string MacroConditionSlideshow::id = "slideshow";
|
||||
|
||||
bool MacroConditionSlideshow::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionSlideshow::id,
|
||||
{MacroConditionSlideshow::Create, MacroConditionSlideshowEdit::Create,
|
||||
"AdvSceneSwitcher.condition.slideshow"});
|
||||
bool MacroConditionSlideshow::_registered =
|
||||
obs_get_version() >= MAKE_SEMANTIC_VERSION(29, 1, 0) &&
|
||||
MacroConditionFactory::Register(
|
||||
MacroConditionSlideshow::id,
|
||||
{MacroConditionSlideshow::Create,
|
||||
MacroConditionSlideshowEdit::Create,
|
||||
"AdvSceneSwitcher.condition.slideshow"});
|
||||
|
||||
static const std::map<MacroConditionSlideshow::Condition, std::string>
|
||||
conditions = {
|
||||
@@ -200,9 +203,9 @@ MacroConditionSlideshowEdit::MacroConditionSlideshowEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionSlideshow> entryData)
|
||||
: QWidget(parent),
|
||||
_conditions(new QComboBox(this)),
|
||||
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
||||
_index(new VariableSpinBox(this)),
|
||||
_path(new VariableLineEdit(this))
|
||||
_path(new VariableLineEdit(this)),
|
||||
_sources(new SourceSelectionWidget(this, QStringList(), true))
|
||||
{
|
||||
setToolTip(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.slideshow.updateIntervalTooltip"));
|
||||
|
||||
@@ -10,13 +10,16 @@ bool MacroConditionSource::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionSource::Create, MacroConditionSourceEdit::Create,
|
||||
"AdvSceneSwitcher.condition.source"});
|
||||
|
||||
const static std::map<SourceCondition, std::string> sourceConditionTypes = {
|
||||
{SourceCondition::ACTIVE,
|
||||
"AdvSceneSwitcher.condition.source.type.active"},
|
||||
{SourceCondition::SHOWING,
|
||||
"AdvSceneSwitcher.condition.source.type.showing"},
|
||||
{SourceCondition::SETTINGS,
|
||||
"AdvSceneSwitcher.condition.source.type.settings"},
|
||||
const static std::map<MacroConditionSource::Condition, std::string>
|
||||
sourceCnditionTypes = {
|
||||
{MacroConditionSource::Condition::ACTIVE,
|
||||
"AdvSceneSwitcher.condition.source.type.active"},
|
||||
{MacroConditionSource::Condition::SHOWING,
|
||||
"AdvSceneSwitcher.condition.source.type.showing"},
|
||||
{MacroConditionSource::Condition::SETTINGS_MATCH,
|
||||
"AdvSceneSwitcher.condition.source.type.settings"},
|
||||
{MacroConditionSource::Condition::SETTINGS_CHANGED,
|
||||
"AdvSceneSwitcher.condition.source.type.settingsChanged"},
|
||||
};
|
||||
|
||||
bool MacroConditionSource::CheckCondition()
|
||||
@@ -29,13 +32,13 @@ bool MacroConditionSource::CheckCondition()
|
||||
auto s = obs_weak_source_get_source(_source.GetSource());
|
||||
|
||||
switch (_condition) {
|
||||
case SourceCondition::ACTIVE:
|
||||
case Condition::ACTIVE:
|
||||
ret = obs_source_active(s);
|
||||
break;
|
||||
case SourceCondition::SHOWING:
|
||||
case Condition::SHOWING:
|
||||
ret = obs_source_showing(s);
|
||||
break;
|
||||
case SourceCondition::SETTINGS:
|
||||
case Condition::SETTINGS_MATCH:
|
||||
ret = CompareSourceSettings(_source.GetSource(), _settings,
|
||||
_regex);
|
||||
if (IsReferencedInVars()) {
|
||||
@@ -43,6 +46,13 @@ bool MacroConditionSource::CheckCondition()
|
||||
GetSourceSettings(_source.GetSource()));
|
||||
}
|
||||
break;
|
||||
case Condition::SETTINGS_CHANGED: {
|
||||
std::string settings = GetSourceSettings(_source.GetSource());
|
||||
ret = !_currentSettings.empty() && settings != _currentSettings;
|
||||
_currentSettings = settings;
|
||||
SetVariableValue(settings);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -70,8 +80,7 @@ bool MacroConditionSource::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_source.Load(obj);
|
||||
_condition = static_cast<SourceCondition>(
|
||||
obs_data_get_int(obj, "condition"));
|
||||
_condition = static_cast<Condition>(obs_data_get_int(obj, "condition"));
|
||||
_settings.Load(obj, "settings");
|
||||
_regex.Load(obj);
|
||||
// TOOD: remove in future version
|
||||
@@ -89,8 +98,8 @@ std::string MacroConditionSource::GetShortDesc() const
|
||||
|
||||
static inline void populateConditionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : sourceConditionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
for (const auto &[_, name] : sourceCnditionTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,7 +182,8 @@ void MacroConditionSourceEdit::ConditionChanged(int index)
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_condition = static_cast<SourceCondition>(index);
|
||||
_entryData->_condition =
|
||||
static_cast<MacroConditionSource::Condition>(index);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
@@ -220,14 +230,18 @@ void MacroConditionSourceEdit::RegexChanged(RegexConfig conf)
|
||||
void MacroConditionSourceEdit::SetWidgetVisibility()
|
||||
{
|
||||
_settings->setVisible(_entryData->_condition ==
|
||||
SourceCondition::SETTINGS);
|
||||
_getSettings->setVisible(_entryData->_condition ==
|
||||
SourceCondition::SETTINGS);
|
||||
_regex->setVisible(_entryData->_condition == SourceCondition::SETTINGS);
|
||||
MacroConditionSource::Condition::SETTINGS_MATCH);
|
||||
_getSettings->setVisible(
|
||||
_entryData->_condition ==
|
||||
MacroConditionSource::Condition::SETTINGS_MATCH);
|
||||
_regex->setVisible(_entryData->_condition ==
|
||||
MacroConditionSource::Condition::SETTINGS_MATCH);
|
||||
|
||||
setToolTip(
|
||||
(_entryData->_condition == SourceCondition::ACTIVE ||
|
||||
_entryData->_condition == SourceCondition::SHOWING)
|
||||
(_entryData->_condition ==
|
||||
MacroConditionSource::Condition::ACTIVE ||
|
||||
_entryData->_condition ==
|
||||
MacroConditionSource::Condition::SHOWING)
|
||||
? obs_module_text(
|
||||
"AdvSceneSwitcher.condition.source.sceneVisibilityHint")
|
||||
: "");
|
||||
|
||||
@@ -10,12 +10,6 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
enum class SourceCondition {
|
||||
ACTIVE,
|
||||
SHOWING,
|
||||
SETTINGS,
|
||||
};
|
||||
|
||||
class MacroConditionSource : public MacroCondition {
|
||||
public:
|
||||
MacroConditionSource(Macro *m) : MacroCondition(m, true) {}
|
||||
@@ -29,12 +23,21 @@ public:
|
||||
return std::make_shared<MacroConditionSource>(m);
|
||||
}
|
||||
|
||||
enum class Condition {
|
||||
ACTIVE,
|
||||
SHOWING,
|
||||
SETTINGS_MATCH,
|
||||
SETTINGS_CHANGED,
|
||||
};
|
||||
|
||||
SourceSelection _source;
|
||||
SourceCondition _condition = SourceCondition::ACTIVE;
|
||||
Condition _condition = Condition::ACTIVE;
|
||||
StringVariable _settings = "";
|
||||
RegexConfig _regex;
|
||||
|
||||
private:
|
||||
std::string _currentSettings;
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
@@ -155,6 +155,13 @@ void MacroConditionStudioModeEdit::SetWidgetVisibility()
|
||||
|
||||
_scenes->setVisible(_entryData->_condition ==
|
||||
StudioModeCondition::PREVIEW_SCENE);
|
||||
|
||||
// TODO: Remove this workaround once the PREVIEW_SCENE condition type
|
||||
// has been removed
|
||||
if (_entryData->_condition != StudioModeCondition::PREVIEW_SCENE) {
|
||||
_condition->removeItem(
|
||||
static_cast<int>(StudioModeCondition::PREVIEW_SCENE));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -10,7 +10,8 @@ namespace advss {
|
||||
enum class StudioModeCondition {
|
||||
STUDIO_MODE_ACTIVE,
|
||||
STUDIO_MODE_NOT_ACTIVE,
|
||||
PREVIEW_SCENE,
|
||||
PREVIEW_SCENE, // TODO: Remove in future version as the functionality
|
||||
// moved to the scene condition
|
||||
};
|
||||
|
||||
class MacroConditionStudioMode : public MacroCondition {
|
||||
|
||||
368
src/macro-core/macro-condition-tempvar.cpp
Normal file
368
src/macro-core/macro-condition-tempvar.cpp
Normal file
@@ -0,0 +1,368 @@
|
||||
#include "macro-condition-tempvar.hpp"
|
||||
#include "math-helpers.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroConditionTempVar::id = "temp_var";
|
||||
|
||||
bool MacroConditionTempVar::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionTempVar::id,
|
||||
{MacroConditionTempVar::Create, MacroConditionTempVarEdit::Create,
|
||||
"AdvSceneSwitcher.condition.temporaryVariable"});
|
||||
|
||||
const static std::map<MacroConditionTempVar::Condition, std::string>
|
||||
conditionTypes = {
|
||||
{MacroConditionTempVar::Condition::EQUALS,
|
||||
"AdvSceneSwitcher.condition.variable.type.compare"},
|
||||
{MacroConditionTempVar::Condition::IS_EMPTY,
|
||||
"AdvSceneSwitcher.condition.variable.type.empty"},
|
||||
{MacroConditionTempVar::Condition::IS_NUMBER,
|
||||
"AdvSceneSwitcher.condition.variable.type.number"},
|
||||
{MacroConditionTempVar::Condition::LESS_THAN,
|
||||
"AdvSceneSwitcher.condition.variable.type.lessThan"},
|
||||
{MacroConditionTempVar::Condition::GREATER_THAN,
|
||||
"AdvSceneSwitcher.condition.variable.type.greaterThan"},
|
||||
{MacroConditionTempVar::Condition::VALUE_CHANGED,
|
||||
"AdvSceneSwitcher.condition.variable.type.valueChanged"},
|
||||
{MacroConditionTempVar::Condition::EQUALS_VARIABLE,
|
||||
"AdvSceneSwitcher.condition.variable.type.equalsVariable"},
|
||||
{MacroConditionTempVar::Condition::LESS_THAN_VARIABLE,
|
||||
"AdvSceneSwitcher.condition.variable.type.lessThanVariable"},
|
||||
{MacroConditionTempVar::Condition::GREATER_THAN_VARIABLE,
|
||||
"AdvSceneSwitcher.condition.variable.type.greaterThanVariable"},
|
||||
};
|
||||
|
||||
static bool isNumber(const TempVariable &var)
|
||||
{
|
||||
auto value = var.Value();
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return GetDouble(*value).has_value();
|
||||
}
|
||||
|
||||
static bool compareNumber(const TempVariable &var, double value, bool less)
|
||||
{
|
||||
auto tempVarValue = var.Value();
|
||||
if (!tempVarValue) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto doubleValue = GetDouble(*tempVarValue);
|
||||
if (!doubleValue.has_value()) {
|
||||
return false;
|
||||
}
|
||||
if (less) {
|
||||
return doubleValue < value;
|
||||
}
|
||||
return doubleValue > value;
|
||||
}
|
||||
|
||||
bool MacroConditionTempVar::Compare(const TempVariable &var) const
|
||||
{
|
||||
auto value = var.Value();
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_regex.Enabled()) {
|
||||
auto expr = _regex.GetRegularExpression(_strValue);
|
||||
if (!expr.isValid()) {
|
||||
return false;
|
||||
}
|
||||
auto match = expr.match(QString::fromStdString(*value));
|
||||
return match.hasMatch();
|
||||
}
|
||||
|
||||
return std::string(_strValue) == *value;
|
||||
}
|
||||
|
||||
bool MacroConditionTempVar::ValueChanged(const TempVariable &var)
|
||||
{
|
||||
auto value = var.Value();
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
bool changed = *value != _lastValue;
|
||||
if (changed) {
|
||||
_lastValue = *value;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
bool MacroConditionTempVar::CompareVariables()
|
||||
{
|
||||
auto var1 = _tempVar.GetTempVariable(GetMacro());
|
||||
auto var2 = _variable2.lock();
|
||||
if (!var1 || !var2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto tempVarValue = var1->Value();
|
||||
if (!tempVarValue) {
|
||||
return false;
|
||||
}
|
||||
auto val1 = GetDouble(*tempVarValue);
|
||||
auto val2 = var2->DoubleValue();
|
||||
bool validNumbers = val1.has_value() && val2.has_value();
|
||||
|
||||
switch (_type) {
|
||||
case MacroConditionTempVar::Condition::EQUALS_VARIABLE:
|
||||
return *tempVarValue == var2->Value() ||
|
||||
(validNumbers && val1 == val2);
|
||||
case MacroConditionTempVar::Condition::LESS_THAN_VARIABLE:
|
||||
return validNumbers && val1 < val2;
|
||||
case MacroConditionTempVar::Condition::GREATER_THAN_VARIABLE:
|
||||
return validNumbers && val1 > val2;
|
||||
default:
|
||||
blog(LOG_WARNING,
|
||||
"Unexpected call of %s with condition type %d", __func__,
|
||||
static_cast<int>(_type));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionTempVar::CheckCondition()
|
||||
{
|
||||
auto var = _tempVar.GetTempVariable(GetMacro());
|
||||
if (!var) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
case MacroConditionTempVar::Condition::EQUALS:
|
||||
return Compare(*var);
|
||||
case MacroConditionTempVar::Condition::IS_EMPTY:
|
||||
return var->Value().has_value() && var->Value()->empty();
|
||||
case MacroConditionTempVar::Condition::IS_NUMBER:
|
||||
return isNumber(*var);
|
||||
case MacroConditionTempVar::Condition::LESS_THAN:
|
||||
return compareNumber(*var, _numValue, true);
|
||||
case MacroConditionTempVar::Condition::GREATER_THAN:
|
||||
return compareNumber(*var, _numValue, false);
|
||||
case MacroConditionTempVar::Condition::VALUE_CHANGED:
|
||||
return ValueChanged(*var);
|
||||
case MacroConditionTempVar::Condition::EQUALS_VARIABLE:
|
||||
return CompareVariables();
|
||||
case MacroConditionTempVar::Condition::LESS_THAN_VARIABLE:
|
||||
return CompareVariables();
|
||||
case MacroConditionTempVar::Condition::GREATER_THAN_VARIABLE:
|
||||
return CompareVariables();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionTempVar::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
_tempVar.Save(obj);
|
||||
obs_data_set_string(obj, "variableName",
|
||||
GetWeakVariableName(_variable2).c_str());
|
||||
_strValue.Save(obj, "strValue");
|
||||
obs_data_set_double(obj, "numValue", _numValue);
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_type));
|
||||
_regex.Save(obj);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionTempVar::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_tempVar.Load(obj, GetMacro());
|
||||
_variable2 =
|
||||
GetWeakVariableByName(obs_data_get_string(obj, "variableName"));
|
||||
_strValue.Load(obj, "strValue");
|
||||
_numValue = obs_data_get_double(obj, "numValue");
|
||||
_type = static_cast<Condition>(obs_data_get_int(obj, "condition"));
|
||||
_regex.Load(obj);
|
||||
// TODO: remove in future version
|
||||
if (obs_data_has_user_value(obj, "regex")) {
|
||||
_regex.CreateBackwardsCompatibleRegex(
|
||||
obs_data_get_bool(obj, "regex"));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionTempVar::GetShortDesc() const
|
||||
{
|
||||
auto var = _tempVar.GetTempVariable(GetMacro());
|
||||
if (!var) {
|
||||
return "";
|
||||
}
|
||||
return var->Name();
|
||||
}
|
||||
|
||||
static inline void populateConditionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : conditionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroConditionTempVarEdit::MacroConditionTempVarEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionTempVar> entryData)
|
||||
: QWidget(parent),
|
||||
_tempVars(new TempVariableSelection(this)),
|
||||
_variables2(new VariableSelection(this)),
|
||||
_conditions(new QComboBox()),
|
||||
_strValue(new VariableTextEdit(this, 5, 1, 1)),
|
||||
_numValue(new QDoubleSpinBox()),
|
||||
_regex(new RegexConfigWidget(parent))
|
||||
{
|
||||
_numValue->setMinimum(-9999999999);
|
||||
_numValue->setMaximum(9999999999);
|
||||
populateConditionSelection(_conditions);
|
||||
|
||||
QWidget::connect(_tempVars,
|
||||
SIGNAL(SelectionChanged(const TempVariableRef &)),
|
||||
this, SLOT(VariableChanged(const TempVariableRef &)));
|
||||
QWidget::connect(_variables2, SIGNAL(SelectionChanged(const QString &)),
|
||||
this, SLOT(Variable2Changed(const QString &)));
|
||||
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ConditionChanged(int)));
|
||||
QWidget::connect(_strValue, SIGNAL(textChanged()), this,
|
||||
SLOT(StrValueChanged()));
|
||||
QWidget::connect(_numValue, SIGNAL(valueChanged(double)), this,
|
||||
SLOT(NumValueChanged(double)));
|
||||
QWidget::connect(_regex, SIGNAL(RegexConfigChanged(RegexConfig)), this,
|
||||
SLOT(RegexChanged(RegexConfig)));
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{variables}}", _tempVars},
|
||||
{"{{variables2}}", _variables2},
|
||||
{"{{conditions}}", _conditions},
|
||||
{"{{strValue}}", _strValue},
|
||||
{"{{numValue}}", _numValue},
|
||||
{"{{regex}}", _regex},
|
||||
};
|
||||
|
||||
auto layout = new QHBoxLayout;
|
||||
PlaceWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.variable.entry"),
|
||||
layout, widgetPlaceholders);
|
||||
setLayout(layout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionTempVarEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_tempVars->SetVariable(_entryData->_tempVar);
|
||||
_variables2->SetVariable(_entryData->_variable2);
|
||||
_conditions->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||
_strValue->setPlainText(_entryData->_strValue);
|
||||
_numValue->setValue(_entryData->_numValue);
|
||||
_regex->SetRegexConfig(_entryData->_regex);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionTempVarEdit::VariableChanged(const TempVariableRef &var)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_tempVar = var;
|
||||
}
|
||||
|
||||
void MacroConditionTempVarEdit::Variable2Changed(const QString &text)
|
||||
{
|
||||
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_variable2 = GetWeakVariableByQString(text);
|
||||
}
|
||||
|
||||
void MacroConditionTempVarEdit::ConditionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_type =
|
||||
static_cast<MacroConditionTempVar::Condition>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionTempVarEdit::StrValueChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_strValue = _strValue->toPlainText().toStdString();
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionTempVarEdit::NumValueChanged(double val)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_numValue = val;
|
||||
}
|
||||
|
||||
void MacroConditionTempVarEdit::RegexChanged(RegexConfig conf)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_regex = conf;
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionTempVarEdit::SetWidgetVisibility()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_regex->setVisible(_entryData->_type ==
|
||||
MacroConditionTempVar::Condition::EQUALS);
|
||||
_strValue->setVisible(_entryData->_type ==
|
||||
MacroConditionTempVar::Condition::EQUALS);
|
||||
_numValue->setVisible(
|
||||
_entryData->_type ==
|
||||
MacroConditionTempVar::Condition::LESS_THAN ||
|
||||
_entryData->_type ==
|
||||
MacroConditionTempVar::Condition::GREATER_THAN);
|
||||
_numValue->setVisible(
|
||||
_entryData->_type ==
|
||||
MacroConditionTempVar::Condition::LESS_THAN ||
|
||||
_entryData->_type ==
|
||||
MacroConditionTempVar::Condition::GREATER_THAN);
|
||||
_variables2->setVisible(
|
||||
_entryData->_type ==
|
||||
MacroConditionTempVar::Condition::EQUALS_VARIABLE ||
|
||||
_entryData->_type ==
|
||||
MacroConditionTempVar::Condition::LESS_THAN_VARIABLE ||
|
||||
_entryData->_type ==
|
||||
MacroConditionTempVar::Condition::GREATER_THAN_VARIABLE);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
100
src/macro-core/macro-condition-tempvar.hpp
Normal file
100
src/macro-core/macro-condition-tempvar.hpp
Normal file
@@ -0,0 +1,100 @@
|
||||
#pragma once
|
||||
#include "macro-condition-edit.hpp"
|
||||
#include "resizing-text-edit.hpp"
|
||||
#include "variable.hpp"
|
||||
#include "regex-config.hpp"
|
||||
#include "variable-text-edit.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
#include <QLineEdit>
|
||||
#include <QCheckBox>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroConditionTempVar : public MacroCondition {
|
||||
public:
|
||||
MacroConditionTempVar(Macro *m) : MacroCondition(m) {}
|
||||
bool CheckCondition();
|
||||
bool Save(obs_data_t *obj) const;
|
||||
bool Load(obs_data_t *obj);
|
||||
std::string GetShortDesc() const;
|
||||
std::string GetId() const { return id; };
|
||||
static std::shared_ptr<MacroCondition> Create(Macro *m)
|
||||
{
|
||||
return std::make_shared<MacroConditionTempVar>(m);
|
||||
}
|
||||
|
||||
enum class Condition {
|
||||
EQUALS,
|
||||
IS_EMPTY,
|
||||
IS_NUMBER,
|
||||
LESS_THAN,
|
||||
GREATER_THAN,
|
||||
VALUE_CHANGED,
|
||||
EQUALS_VARIABLE,
|
||||
LESS_THAN_VARIABLE,
|
||||
GREATER_THAN_VARIABLE,
|
||||
};
|
||||
|
||||
Condition _type = Condition::EQUALS;
|
||||
TempVariableRef _tempVar;
|
||||
std::weak_ptr<Variable> _variable2;
|
||||
StringVariable _strValue = "";
|
||||
double _numValue = 0;
|
||||
RegexConfig _regex;
|
||||
|
||||
private:
|
||||
bool Compare(const TempVariable &) const;
|
||||
bool ValueChanged(const TempVariable &);
|
||||
bool CompareVariables();
|
||||
|
||||
std::string _lastValue = "";
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionTempVarEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionTempVarEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionTempVar> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionTempVarEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionTempVar>(cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void VariableChanged(const TempVariableRef &);
|
||||
void Variable2Changed(const QString &);
|
||||
void ConditionChanged(int);
|
||||
void StrValueChanged();
|
||||
void NumValueChanged(double);
|
||||
void RegexChanged(RegexConfig);
|
||||
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
TempVariableSelection *_tempVars;
|
||||
VariableSelection *_variables2;
|
||||
QComboBox *_conditions;
|
||||
VariableTextEdit *_strValue;
|
||||
QDoubleSpinBox *_numValue;
|
||||
RegexConfigWidget *_regex;
|
||||
std::shared_ptr<MacroConditionTempVar> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
@@ -10,18 +10,20 @@ bool MacroConditionTimer::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionTimer::Create, MacroConditionTimerEdit::Create,
|
||||
"AdvSceneSwitcher.condition.timer", false});
|
||||
|
||||
const static std::map<TimerType, std::string> timerTypes = {
|
||||
{TimerType::FIXED, "AdvSceneSwitcher.condition.timer.type.fixed"},
|
||||
{TimerType::RANDOM, "AdvSceneSwitcher.condition.timer.type.random"},
|
||||
const static std::map<MacroConditionTimer::TimerType, std::string> timerTypes = {
|
||||
{MacroConditionTimer::TimerType::FIXED,
|
||||
"AdvSceneSwitcher.condition.timer.type.fixed"},
|
||||
{MacroConditionTimer::TimerType::RANDOM,
|
||||
"AdvSceneSwitcher.condition.timer.type.random"},
|
||||
};
|
||||
|
||||
bool MacroConditionTimer::CheckCondition()
|
||||
{
|
||||
if (_paused) {
|
||||
SetVariableValue(std::to_string(_remaining));
|
||||
SetVariables(_remaining);
|
||||
return _remaining == 0.;
|
||||
}
|
||||
SetVariableValue(std::to_string(_duration.TimeRemaining()));
|
||||
SetVariables(_duration.TimeRemaining());
|
||||
if (_duration.DurationReached()) {
|
||||
if (!_oneshot) {
|
||||
_duration.Reset();
|
||||
@@ -120,6 +122,29 @@ void MacroConditionTimer::Reset()
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionTimer::SetVariables(double seconds)
|
||||
{
|
||||
SetVariableValue(std::to_string(seconds));
|
||||
SetTempVarValue("seconds", std::to_string((int)seconds));
|
||||
SetTempVarValue("minutes", std::to_string((int)(seconds / 60)));
|
||||
SetTempVarValue("hours", std::to_string((int)(seconds / (60 * 60))));
|
||||
SetTempVarValue("days",
|
||||
std::to_string((int)(seconds / (60 * 60 * 24))));
|
||||
}
|
||||
|
||||
void MacroConditionTimer::SetupTempVars()
|
||||
{
|
||||
MacroCondition::SetupTempVars();
|
||||
AddTempvar("seconds",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.timer.seconds"));
|
||||
AddTempvar("minutes",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.timer.minutes"));
|
||||
AddTempvar("hours",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.timer.hours"));
|
||||
AddTempvar("days",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.timer.days"));
|
||||
}
|
||||
|
||||
static inline void populateTimerTypeSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : timerTypes) {
|
||||
@@ -203,7 +228,7 @@ void MacroConditionTimerEdit::TimerTypeChanged(int type)
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_type = static_cast<TimerType>(type);
|
||||
_entryData->_type = static_cast<MacroConditionTimer::TimerType>(type);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
@@ -337,7 +362,7 @@ void MacroConditionTimerEdit::SetWidgetVisibility()
|
||||
{"{{duration2}}", _duration2},
|
||||
};
|
||||
|
||||
if (_entryData->_type == TimerType::RANDOM) {
|
||||
if (_entryData->_type == MacroConditionTimer::TimerType::RANDOM) {
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.condition.timer.entry.line1.random"),
|
||||
|
||||
@@ -12,11 +12,6 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
enum class TimerType {
|
||||
FIXED,
|
||||
RANDOM,
|
||||
};
|
||||
|
||||
class MacroConditionTimer : public MacroCondition {
|
||||
public:
|
||||
MacroConditionTimer(Macro *m) : MacroCondition(m, true) {}
|
||||
@@ -32,6 +27,7 @@ public:
|
||||
void Continue();
|
||||
void Reset();
|
||||
|
||||
enum class TimerType { FIXED, RANDOM };
|
||||
TimerType _type = TimerType::FIXED;
|
||||
Duration _duration;
|
||||
Duration _duration2;
|
||||
@@ -42,6 +38,9 @@ public:
|
||||
|
||||
private:
|
||||
void SetRandomTimeRemaining();
|
||||
void SetVariables(double seconds);
|
||||
void SetupTempVars();
|
||||
|
||||
std::default_random_engine _re;
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#include "macro-condition-variable.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <regex>
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroConditionVariable::id = "variable";
|
||||
@@ -12,25 +10,25 @@ bool MacroConditionVariable::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionVariable::Create, MacroConditionVariableEdit::Create,
|
||||
"AdvSceneSwitcher.condition.variable"});
|
||||
|
||||
const static std::map<MacroConditionVariable::Type, std::string>
|
||||
const static std::map<MacroConditionVariable::Condition, std::string>
|
||||
conditionTypes = {
|
||||
{MacroConditionVariable::Type::EQUALS,
|
||||
{MacroConditionVariable::Condition::EQUALS,
|
||||
"AdvSceneSwitcher.condition.variable.type.compare"},
|
||||
{MacroConditionVariable::Type::IS_EMPTY,
|
||||
{MacroConditionVariable::Condition::IS_EMPTY,
|
||||
"AdvSceneSwitcher.condition.variable.type.empty"},
|
||||
{MacroConditionVariable::Type::IS_NUMBER,
|
||||
{MacroConditionVariable::Condition::IS_NUMBER,
|
||||
"AdvSceneSwitcher.condition.variable.type.number"},
|
||||
{MacroConditionVariable::Type::LESS_THAN,
|
||||
{MacroConditionVariable::Condition::LESS_THAN,
|
||||
"AdvSceneSwitcher.condition.variable.type.lessThan"},
|
||||
{MacroConditionVariable::Type::GREATER_THAN,
|
||||
{MacroConditionVariable::Condition::GREATER_THAN,
|
||||
"AdvSceneSwitcher.condition.variable.type.greaterThan"},
|
||||
{MacroConditionVariable::Type::VALUE_CHANGED,
|
||||
{MacroConditionVariable::Condition::VALUE_CHANGED,
|
||||
"AdvSceneSwitcher.condition.variable.type.valueChanged"},
|
||||
{MacroConditionVariable::Type::EQUALS_VARIABLE,
|
||||
{MacroConditionVariable::Condition::EQUALS_VARIABLE,
|
||||
"AdvSceneSwitcher.condition.variable.type.equalsVariable"},
|
||||
{MacroConditionVariable::Type::LESS_THAN_VARIABLE,
|
||||
{MacroConditionVariable::Condition::LESS_THAN_VARIABLE,
|
||||
"AdvSceneSwitcher.condition.variable.type.lessThanVariable"},
|
||||
{MacroConditionVariable::Type::GREATER_THAN_VARIABLE,
|
||||
{MacroConditionVariable::Condition::GREATER_THAN_VARIABLE,
|
||||
"AdvSceneSwitcher.condition.variable.type.greaterThanVariable"},
|
||||
};
|
||||
|
||||
@@ -62,7 +60,7 @@ bool MacroConditionVariable::Compare(const Variable &var) const
|
||||
return match.hasMatch();
|
||||
}
|
||||
|
||||
return _strValue == var.Value();
|
||||
return std::string(_strValue) == var.Value();
|
||||
}
|
||||
|
||||
bool MacroConditionVariable::ValueChanged(const Variable &var)
|
||||
@@ -87,12 +85,12 @@ bool MacroConditionVariable::CompareVariables()
|
||||
bool validNumbers = val1.has_value() && val2.has_value();
|
||||
|
||||
switch (_type) {
|
||||
case MacroConditionVariable::Type::EQUALS_VARIABLE:
|
||||
case MacroConditionVariable::Condition::EQUALS_VARIABLE:
|
||||
return var1->Value() == var2->Value() ||
|
||||
(validNumbers && val1 == val2);
|
||||
case MacroConditionVariable::Type::LESS_THAN_VARIABLE:
|
||||
case MacroConditionVariable::Condition::LESS_THAN_VARIABLE:
|
||||
return validNumbers && val1 < val2;
|
||||
case MacroConditionVariable::Type::GREATER_THAN_VARIABLE:
|
||||
case MacroConditionVariable::Condition::GREATER_THAN_VARIABLE:
|
||||
return validNumbers && val1 > val2;
|
||||
default:
|
||||
blog(LOG_WARNING,
|
||||
@@ -111,23 +109,23 @@ bool MacroConditionVariable::CheckCondition()
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
case MacroConditionVariable::Type::EQUALS:
|
||||
case MacroConditionVariable::Condition::EQUALS:
|
||||
return Compare(*var);
|
||||
case MacroConditionVariable::Type::IS_EMPTY:
|
||||
case MacroConditionVariable::Condition::IS_EMPTY:
|
||||
return var->Value().empty();
|
||||
case MacroConditionVariable::Type::IS_NUMBER:
|
||||
case MacroConditionVariable::Condition::IS_NUMBER:
|
||||
return isNumber(*var);
|
||||
case MacroConditionVariable::Type::LESS_THAN:
|
||||
case MacroConditionVariable::Condition::LESS_THAN:
|
||||
return compareNumber(*var, _numValue, true);
|
||||
case MacroConditionVariable::Type::GREATER_THAN:
|
||||
case MacroConditionVariable::Condition::GREATER_THAN:
|
||||
return compareNumber(*var, _numValue, false);
|
||||
case MacroConditionVariable::Type::VALUE_CHANGED:
|
||||
case MacroConditionVariable::Condition::VALUE_CHANGED:
|
||||
return ValueChanged(*var);
|
||||
case MacroConditionVariable::Type::EQUALS_VARIABLE:
|
||||
case MacroConditionVariable::Condition::EQUALS_VARIABLE:
|
||||
return CompareVariables();
|
||||
case MacroConditionVariable::Type::LESS_THAN_VARIABLE:
|
||||
case MacroConditionVariable::Condition::LESS_THAN_VARIABLE:
|
||||
return CompareVariables();
|
||||
case MacroConditionVariable::Type::GREATER_THAN_VARIABLE:
|
||||
case MacroConditionVariable::Condition::GREATER_THAN_VARIABLE:
|
||||
return CompareVariables();
|
||||
}
|
||||
|
||||
@@ -141,7 +139,7 @@ bool MacroConditionVariable::Save(obs_data_t *obj) const
|
||||
GetWeakVariableName(_variable).c_str());
|
||||
obs_data_set_string(obj, "variable2Name",
|
||||
GetWeakVariableName(_variable2).c_str());
|
||||
obs_data_set_string(obj, "strValue", _strValue.c_str());
|
||||
_strValue.Save(obj, "strValue");
|
||||
obs_data_set_double(obj, "numValue", _numValue);
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_type));
|
||||
_regex.Save(obj);
|
||||
@@ -155,9 +153,9 @@ bool MacroConditionVariable::Load(obs_data_t *obj)
|
||||
GetWeakVariableByName(obs_data_get_string(obj, "variableName"));
|
||||
_variable2 = GetWeakVariableByName(
|
||||
obs_data_get_string(obj, "variable2Name"));
|
||||
_strValue = obs_data_get_string(obj, "strValue");
|
||||
_strValue.Load(obj, "strValue");
|
||||
_numValue = obs_data_get_double(obj, "numValue");
|
||||
_type = static_cast<Type>(obs_data_get_int(obj, "condition"));
|
||||
_type = static_cast<Condition>(obs_data_get_int(obj, "condition"));
|
||||
_regex.Load(obj);
|
||||
// TODO: remove in future version
|
||||
if (obs_data_has_user_value(obj, "regex")) {
|
||||
@@ -185,7 +183,7 @@ MacroConditionVariableEdit::MacroConditionVariableEdit(
|
||||
_variables(new VariableSelection(this)),
|
||||
_variables2(new VariableSelection(this)),
|
||||
_conditions(new QComboBox()),
|
||||
_strValue(new ResizingPlainTextEdit(this, 5, 1, 1)),
|
||||
_strValue(new VariableTextEdit(this, 5, 1, 1)),
|
||||
_numValue(new QDoubleSpinBox()),
|
||||
_regex(new RegexConfigWidget(parent))
|
||||
{
|
||||
@@ -215,19 +213,11 @@ MacroConditionVariableEdit::MacroConditionVariableEdit(
|
||||
{"{{regex}}", _regex},
|
||||
};
|
||||
|
||||
QHBoxLayout *layout = new QHBoxLayout;
|
||||
auto layout = new QHBoxLayout;
|
||||
PlaceWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.variable.entry"),
|
||||
layout, widgetPlaceholders);
|
||||
|
||||
auto *regexLayout = new QHBoxLayout;
|
||||
regexLayout->addWidget(_regex);
|
||||
regexLayout->addStretch();
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(layout);
|
||||
mainLayout->addLayout(regexLayout);
|
||||
setLayout(mainLayout);
|
||||
setLayout(layout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
@@ -243,7 +233,7 @@ void MacroConditionVariableEdit::UpdateEntryData()
|
||||
_variables->SetVariable(_entryData->_variable);
|
||||
_variables2->SetVariable(_entryData->_variable2);
|
||||
_conditions->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||
_strValue->setPlainText(QString::fromStdString(_entryData->_strValue));
|
||||
_strValue->setPlainText(_entryData->_strValue);
|
||||
_numValue->setValue(_entryData->_numValue);
|
||||
_regex->SetRegexConfig(_entryData->_regex);
|
||||
SetWidgetVisibility();
|
||||
@@ -277,7 +267,8 @@ void MacroConditionVariableEdit::ConditionChanged(int value)
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_type = static_cast<MacroConditionVariable::Type>(value);
|
||||
_entryData->_type =
|
||||
static_cast<MacroConditionVariable::Condition>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
@@ -290,6 +281,7 @@ void MacroConditionVariableEdit::StrValueChanged()
|
||||
auto lock = LockContext();
|
||||
_entryData->_strValue = _strValue->toPlainText().toStdString();
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionVariableEdit::NumValueChanged(double val)
|
||||
@@ -321,24 +313,26 @@ void MacroConditionVariableEdit::SetWidgetVisibility()
|
||||
}
|
||||
|
||||
_regex->setVisible(_entryData->_type ==
|
||||
MacroConditionVariable::Type::EQUALS);
|
||||
MacroConditionVariable::Condition::EQUALS);
|
||||
_strValue->setVisible(_entryData->_type ==
|
||||
MacroConditionVariable::Type::EQUALS);
|
||||
MacroConditionVariable::Condition::EQUALS);
|
||||
_numValue->setVisible(
|
||||
_entryData->_type == MacroConditionVariable::Type::LESS_THAN ||
|
||||
_entryData->_type ==
|
||||
MacroConditionVariable::Type::GREATER_THAN);
|
||||
MacroConditionVariable::Condition::LESS_THAN ||
|
||||
_entryData->_type ==
|
||||
MacroConditionVariable::Condition::GREATER_THAN);
|
||||
_numValue->setVisible(
|
||||
_entryData->_type == MacroConditionVariable::Type::LESS_THAN ||
|
||||
_entryData->_type ==
|
||||
MacroConditionVariable::Type::GREATER_THAN);
|
||||
MacroConditionVariable::Condition::LESS_THAN ||
|
||||
_entryData->_type ==
|
||||
MacroConditionVariable::Condition::GREATER_THAN);
|
||||
_variables2->setVisible(
|
||||
_entryData->_type ==
|
||||
MacroConditionVariable::Type::EQUALS_VARIABLE ||
|
||||
MacroConditionVariable::Condition::EQUALS_VARIABLE ||
|
||||
_entryData->_type ==
|
||||
MacroConditionVariable::Type::LESS_THAN_VARIABLE ||
|
||||
MacroConditionVariable::Condition::LESS_THAN_VARIABLE ||
|
||||
_entryData->_type ==
|
||||
MacroConditionVariable::Type::GREATER_THAN_VARIABLE);
|
||||
MacroConditionVariable::Condition::GREATER_THAN_VARIABLE);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "resizing-text-edit.hpp"
|
||||
#include "variable.hpp"
|
||||
#include "regex-config.hpp"
|
||||
#include "variable-text-edit.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QComboBox>
|
||||
@@ -24,7 +25,7 @@ public:
|
||||
return std::make_shared<MacroConditionVariable>(m);
|
||||
}
|
||||
|
||||
enum class Type {
|
||||
enum class Condition {
|
||||
EQUALS,
|
||||
IS_EMPTY,
|
||||
IS_NUMBER,
|
||||
@@ -36,10 +37,10 @@ public:
|
||||
GREATER_THAN_VARIABLE,
|
||||
};
|
||||
|
||||
Type _type = Type::EQUALS;
|
||||
Condition _type = Condition::EQUALS;
|
||||
std::weak_ptr<Variable> _variable;
|
||||
std::weak_ptr<Variable> _variable2;
|
||||
std::string _strValue = "";
|
||||
StringVariable _strValue = "";
|
||||
double _numValue = 0;
|
||||
RegexConfig _regex;
|
||||
|
||||
@@ -86,7 +87,7 @@ protected:
|
||||
VariableSelection *_variables;
|
||||
VariableSelection *_variables2;
|
||||
QComboBox *_conditions;
|
||||
ResizingPlainTextEdit *_strValue;
|
||||
VariableTextEdit *_strValue;
|
||||
QDoubleSpinBox *_numValue;
|
||||
RegexConfigWidget *_regex;
|
||||
std::shared_ptr<MacroConditionVariable> _entryData;
|
||||
|
||||
@@ -40,7 +40,8 @@ static bool windowContainsText(const std::string &window,
|
||||
return text == matchText;
|
||||
}
|
||||
|
||||
bool MacroConditionWindow::WindowMatches(const std::string &window)
|
||||
bool MacroConditionWindow::WindowMatchesRequirements(
|
||||
const std::string &window) const
|
||||
{
|
||||
const bool focusCheckOK = (!_focus || window == switcher->currentTitle);
|
||||
if (!focusCheckOK) {
|
||||
@@ -60,26 +61,53 @@ bool MacroConditionWindow::WindowMatches(const std::string &window)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_checkText) {
|
||||
auto text = GetTextInWindow(window);
|
||||
SetVariableValue(text.value_or(""));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionWindow::WindowMatches(
|
||||
const std::vector<std::string> &windowList)
|
||||
{
|
||||
bool match = !_checkTitle ||
|
||||
std::find(windowList.begin(), windowList.end(),
|
||||
std::string(_window)) != windowList.end();
|
||||
match = match && WindowMatchesRequirements(_window);
|
||||
SetVariableValueBasedOnMatch(_window);
|
||||
return match;
|
||||
}
|
||||
|
||||
bool MacroConditionWindow::WindowRegexMatches(
|
||||
const std::vector<std::string> &windowList)
|
||||
{
|
||||
// No need to test if checking for window title is required as if the
|
||||
// user has disabled window title matching the option will always be
|
||||
// enabled in the backend and use the regular expression ".*".
|
||||
|
||||
for (const auto &window : windowList) {
|
||||
if (matchRegex(_windowRegex, window, _window) &&
|
||||
WindowMatches(window)) {
|
||||
WindowMatchesRequirements(window)) {
|
||||
SetVariableValueBasedOnMatch(window);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
SetVariableValueBasedOnMatch("");
|
||||
return false;
|
||||
}
|
||||
|
||||
void MacroConditionWindow::SetVariableValueBasedOnMatch(
|
||||
const std::string &matchWindow)
|
||||
{
|
||||
SetTempVarValue("window", matchWindow);
|
||||
if (!IsReferencedInVars()) {
|
||||
return;
|
||||
}
|
||||
if (_checkText) {
|
||||
auto text = GetTextInWindow(matchWindow);
|
||||
SetVariableValue(text.value_or(""));
|
||||
} else {
|
||||
SetVariableValue(switcher->currentTitle);
|
||||
}
|
||||
}
|
||||
|
||||
static bool foregroundWindowChanged()
|
||||
{
|
||||
return switcher->currentTitle != switcher->lastTitle;
|
||||
@@ -87,19 +115,13 @@ static bool foregroundWindowChanged()
|
||||
|
||||
bool MacroConditionWindow::CheckCondition()
|
||||
{
|
||||
SetVariableValue("");
|
||||
if (!_checkText) {
|
||||
SetVariableValue(switcher->currentTitle);
|
||||
}
|
||||
|
||||
std::vector<std::string> windowList;
|
||||
GetWindowList(windowList);
|
||||
|
||||
bool match = false;
|
||||
if (_windowRegex.Enabled()) {
|
||||
match = WindowRegexMatches(windowList);
|
||||
} else {
|
||||
match = WindowMatches(_window);
|
||||
match = WindowMatches(windowList);
|
||||
}
|
||||
match = match && (!_windowFocusChanged || foregroundWindowChanged());
|
||||
return match;
|
||||
@@ -152,6 +174,15 @@ std::string MacroConditionWindow::GetShortDesc() const
|
||||
return _window;
|
||||
}
|
||||
|
||||
void MacroConditionWindow::SetupTempVars()
|
||||
{
|
||||
AddTempvar(
|
||||
"window",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.window.window"),
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.tempVar.window.window.description"));
|
||||
}
|
||||
|
||||
MacroConditionWindowEdit::MacroConditionWindowEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionWindow> entryData)
|
||||
: QWidget(parent),
|
||||
|
||||
@@ -21,11 +21,6 @@ public:
|
||||
return std::make_shared<MacroConditionWindow>(m);
|
||||
}
|
||||
|
||||
private:
|
||||
bool WindowMatches(const std::string &window);
|
||||
bool WindowRegexMatches(const std::vector<std::string> &windowList);
|
||||
|
||||
public:
|
||||
StringVariable _window;
|
||||
RegexConfig _windowRegex;
|
||||
bool _checkTitle = true;
|
||||
@@ -40,6 +35,12 @@ public:
|
||||
RegexConfig _textRegex = RegexConfig::PartialMatchRegexConfig();
|
||||
|
||||
private:
|
||||
bool WindowMatchesRequirements(const std::string &window) const;
|
||||
bool WindowMatches(const std::vector<std::string> &windowList);
|
||||
bool WindowRegexMatches(const std::vector<std::string> &windowList);
|
||||
void SetVariableValueBasedOnMatch(const std::string &matchWindow);
|
||||
void SetupTempVars();
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ void DurationModifier::Save(obs_data_t *obj, const char *condName,
|
||||
void DurationModifier::Load(obs_data_t *obj, const char *condName,
|
||||
const char *duration)
|
||||
{
|
||||
// For backwards compatability check if duration value exist without
|
||||
// For backwards compatibility check if duration value exist without
|
||||
// time constraint condition - if so assume DurationCondition::MORE
|
||||
if (!obs_data_has_user_value(obj, condName) &&
|
||||
obs_data_has_user_value(obj, duration)) {
|
||||
@@ -105,7 +105,7 @@ bool MacroCondition::Load(obs_data_t *obj)
|
||||
_duration.Load(durObj);
|
||||
obs_data_release(durObj);
|
||||
} else {
|
||||
// For backwards compatability
|
||||
// For backwards compatibility
|
||||
_duration.Load(obj);
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
MacroDock::MacroDock(Macro *m, QWidget *parent,
|
||||
MacroDock::MacroDock(std::weak_ptr<Macro> m, QWidget *parent,
|
||||
const StringVariable &runButtonText,
|
||||
const StringVariable &pauseButtonText,
|
||||
const StringVariable &unpauseButtonText,
|
||||
@@ -25,11 +25,12 @@ MacroDock::MacroDock(Macro *m, QWidget *parent,
|
||||
_statusText(new QLabel(conditionsFalseText.c_str())),
|
||||
_macro(m)
|
||||
{
|
||||
if (_macro) {
|
||||
setWindowTitle(QString::fromStdString(_macro->Name()));
|
||||
_run->setVisible(_macro->DockHasRunButton());
|
||||
_pauseToggle->setVisible(_macro->DockHasPauseButton());
|
||||
_statusText->setVisible(_macro->DockHasStatusLabel());
|
||||
auto macro = _macro.lock();
|
||||
if (macro) {
|
||||
setWindowTitle(QString::fromStdString(macro->Name()));
|
||||
_run->setVisible(macro->DockHasRunButton());
|
||||
_pauseToggle->setVisible(macro->DockHasPauseButton());
|
||||
_statusText->setVisible(macro->DockHasStatusLabel());
|
||||
} else {
|
||||
setWindowTitle("<deleted macro>");
|
||||
}
|
||||
@@ -120,49 +121,52 @@ void MacroDock::EnableHighlight(bool value)
|
||||
|
||||
void MacroDock::RunClicked()
|
||||
{
|
||||
if (!_macro) {
|
||||
auto macro = _macro.lock();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto ret = _macro->PerformActions();
|
||||
auto ret = macro->PerformActions(true);
|
||||
if (!ret) {
|
||||
QString err =
|
||||
obs_module_text("AdvSceneSwitcher.macroTab.runFail");
|
||||
DisplayMessage(err.arg(QString::fromStdString(_macro->Name())));
|
||||
DisplayMessage(err.arg(QString::fromStdString(macro->Name())));
|
||||
}
|
||||
}
|
||||
|
||||
void MacroDock::PauseToggleClicked()
|
||||
{
|
||||
if (!_macro) {
|
||||
auto macro = _macro.lock();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
_macro->SetPaused(!_macro->Paused());
|
||||
macro->SetPaused(!macro->Paused());
|
||||
UpdateText();
|
||||
}
|
||||
|
||||
void MacroDock::UpdateText()
|
||||
{
|
||||
_run->setText(_runButtonText.c_str());
|
||||
|
||||
if (!_macro) {
|
||||
auto macro = _macro.lock();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
_pauseToggle->setText(_macro->Paused() ? _unpauseButtonText.c_str()
|
||||
: _pauseButtonText.c_str());
|
||||
_statusText->setText(_macro->Matched() ? _conditionsTrueText.c_str()
|
||||
: _conditionsFalseText.c_str());
|
||||
_pauseToggle->setText(macro->Paused() ? _unpauseButtonText.c_str()
|
||||
: _pauseButtonText.c_str());
|
||||
_statusText->setText(macro->Matched() ? _conditionsTrueText.c_str()
|
||||
: _conditionsFalseText.c_str());
|
||||
}
|
||||
|
||||
void MacroDock::Highlight()
|
||||
{
|
||||
if (!_highlight || !_macro) {
|
||||
auto macro = _macro.lock();
|
||||
if (!_highlight || !macro) {
|
||||
return;
|
||||
}
|
||||
if (_lastHighlightCheckTime.time_since_epoch().count() != 0 &&
|
||||
_macro->ExecutedSince(_lastHighlightCheckTime)) {
|
||||
macro->ExecutedSince(_lastHighlightCheckTime)) {
|
||||
PulseWidget(this, Qt::green, QColor(0, 0, 0, 0), true);
|
||||
}
|
||||
_lastHighlightCheckTime = std::chrono::high_resolution_clock::now();
|
||||
|
||||
@@ -16,7 +16,8 @@ class MacroDock : public OBSDock {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroDock(Macro *, QWidget *parent, const StringVariable &runButtonText,
|
||||
MacroDock(std::weak_ptr<Macro>, QWidget *parent,
|
||||
const StringVariable &runButtonText,
|
||||
const StringVariable &pauseButtonText,
|
||||
const StringVariable &unpauseButtonText,
|
||||
const StringVariable &conditionsTrueText,
|
||||
@@ -53,7 +54,7 @@ private:
|
||||
QTimer _timer;
|
||||
std::chrono::high_resolution_clock::time_point _lastHighlightCheckTime{};
|
||||
|
||||
Macro *_macro;
|
||||
std::weak_ptr<Macro> _macro;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QDialogButtonBox>
|
||||
#include <QScrollArea>
|
||||
#include <QScrollBar>
|
||||
|
||||
namespace advss {
|
||||
|
||||
@@ -44,6 +46,8 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
||||
"AdvSceneSwitcher.macroTab.newMacroRegisterHotkey"))),
|
||||
_currentMacroRegisterHotkeys(new QCheckBox(obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.currentDisableHotkeys"))),
|
||||
_currentSkipOnStartup(new QCheckBox(obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup"))),
|
||||
_currentMacroRegisterDock(new QCheckBox(obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.currentRegisterDock"))),
|
||||
_currentMacroDockAddRunButton(new QCheckBox(obs_module_text(
|
||||
@@ -82,6 +86,12 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
||||
hotkeyLayout->addWidget(_currentMacroRegisterHotkeys);
|
||||
hotkeyOptions->setLayout(hotkeyLayout);
|
||||
|
||||
auto generalOptions = new QGroupBox(
|
||||
obs_module_text("AdvSceneSwitcher.macroTab.generalSettings"));
|
||||
auto generalLayout = new QVBoxLayout;
|
||||
generalLayout->addWidget(_currentSkipOnStartup);
|
||||
generalOptions->setLayout(generalLayout);
|
||||
|
||||
int row = 0;
|
||||
_dockLayout->addWidget(_currentMacroRegisterDock, row, 1, 1, 2);
|
||||
row++;
|
||||
@@ -146,12 +156,23 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
||||
connect(_currentMacroDockAddStatusLabel, &QCheckBox::stateChanged, this,
|
||||
&MacroPropertiesDialog::StatusLabelEnableChanged);
|
||||
|
||||
auto layout = new QVBoxLayout;
|
||||
auto scrollArea = new QScrollArea(this);
|
||||
scrollArea->setWidgetResizable(true);
|
||||
scrollArea->setFrameShape(QFrame::NoFrame);
|
||||
|
||||
auto contentWidget = new QWidget(scrollArea);
|
||||
auto layout = new QVBoxLayout(contentWidget);
|
||||
layout->addWidget(highlightOptions);
|
||||
layout->addWidget(hotkeyOptions);
|
||||
layout->addWidget(generalOptions);
|
||||
layout->addWidget(_dockOptions);
|
||||
layout->addWidget(buttonbox);
|
||||
setLayout(layout);
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
scrollArea->setWidget(contentWidget);
|
||||
|
||||
auto dialogLayout = new QVBoxLayout();
|
||||
dialogLayout->addWidget(scrollArea);
|
||||
dialogLayout->addWidget(buttonbox);
|
||||
setLayout(dialogLayout);
|
||||
|
||||
_executed->setChecked(prop._highlightExecuted);
|
||||
_conditions->setChecked(prop._highlightConditions);
|
||||
@@ -159,10 +180,12 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
||||
_newMacroRegisterHotkeys->setChecked(prop._newMacroRegisterHotkeys);
|
||||
if (!macro || macro->IsGroup()) {
|
||||
hotkeyOptions->hide();
|
||||
generalOptions->hide();
|
||||
_dockOptions->hide();
|
||||
return;
|
||||
}
|
||||
_currentMacroRegisterHotkeys->setChecked(macro->PauseHotkeysEnabled());
|
||||
_currentSkipOnStartup->setChecked(macro->SkipExecOnStart());
|
||||
const bool dockEnabled = macro->DockEnabled();
|
||||
_currentMacroRegisterDock->setChecked(dockEnabled);
|
||||
_currentMacroDockAddRunButton->setChecked(macro->DockHasRunButton());
|
||||
@@ -194,6 +217,20 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
|
||||
dockEnabled && macro->DockHasStatusLabel());
|
||||
MinimizeSizeOfColumn(_dockLayout, 0);
|
||||
Resize();
|
||||
|
||||
// Try to set sensible initial size for the dialog window
|
||||
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 MacroPropertiesDialog::DockEnableChanged(int enabled)
|
||||
@@ -244,8 +281,6 @@ void MacroPropertiesDialog::Resize()
|
||||
{
|
||||
_dockOptions->adjustSize();
|
||||
_dockOptions->updateGeometry();
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
bool MacroPropertiesDialog::AskForSettings(QWidget *parent,
|
||||
@@ -268,6 +303,7 @@ bool MacroPropertiesDialog::AskForSettings(QWidget *parent,
|
||||
|
||||
macro->EnablePauseHotkeys(
|
||||
dialog._currentMacroRegisterHotkeys->isChecked());
|
||||
macro->SetSkipExecOnStart(dialog._currentSkipOnStartup->isChecked());
|
||||
macro->EnableDock(dialog._currentMacroRegisterDock->isChecked());
|
||||
macro->SetDockHasRunButton(
|
||||
dialog._currentMacroDockAddRunButton->isChecked());
|
||||
|
||||
@@ -47,6 +47,7 @@ private:
|
||||
QCheckBox *_newMacroRegisterHotkeys;
|
||||
// Current macro specific settings
|
||||
QCheckBox *_currentMacroRegisterHotkeys;
|
||||
QCheckBox *_currentSkipOnStartup;
|
||||
QCheckBox *_currentMacroRegisterDock;
|
||||
QCheckBox *_currentMacroDockAddRunButton;
|
||||
QCheckBox *_currentMacroDockAddPauseButton;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#include "macro-segment.hpp"
|
||||
#include "macro.hpp"
|
||||
#include "section.hpp"
|
||||
#include "utility.hpp"
|
||||
#include "mouse-wheel-guard.hpp"
|
||||
@@ -26,11 +27,13 @@ bool MacroSegment::Save(obs_data_t *obj) const
|
||||
bool MacroSegment::Load(obs_data_t *obj)
|
||||
{
|
||||
_collapsed = obs_data_get_bool(obj, "collapsed");
|
||||
ClearAvailableTempvars();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroSegment::PostLoad()
|
||||
{
|
||||
SetupTempVars();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -68,20 +71,111 @@ void MacroSegment::SetVariableValue(const std::string &value)
|
||||
}
|
||||
}
|
||||
|
||||
void MacroSegment::IncrementVariableRef()
|
||||
void MacroSegment::SetupTempVars()
|
||||
{
|
||||
if (!_supportsVariableValue) {
|
||||
return;
|
||||
}
|
||||
_variableRefs++;
|
||||
ClearAvailableTempvars();
|
||||
}
|
||||
|
||||
void MacroSegment::DecrementVariableRef()
|
||||
void MacroSegment::ClearAvailableTempvars()
|
||||
{
|
||||
if (!_supportsVariableValue || _variableRefs == 0) {
|
||||
_tempVariables.clear();
|
||||
NotifyUIAboutTempVarChange();
|
||||
}
|
||||
|
||||
static std::shared_ptr<MacroSegment>
|
||||
getSharedSegmentFromMacro(Macro *macro, const MacroSegment *segment)
|
||||
{
|
||||
auto matches = [segment](const std::shared_ptr<MacroSegment> &s) {
|
||||
return s.get() == segment;
|
||||
};
|
||||
auto condIt = std::find_if(macro->Conditions().begin(),
|
||||
macro->Conditions().end(), matches);
|
||||
if (condIt != macro->Conditions().end()) {
|
||||
return *condIt;
|
||||
}
|
||||
auto actionIt = std::find_if(macro->Actions().begin(),
|
||||
macro->Actions().end(), matches);
|
||||
if (actionIt != macro->Actions().end()) {
|
||||
return *actionIt;
|
||||
}
|
||||
auto elseIt = std::find_if(macro->ElseActions().begin(),
|
||||
macro->ElseActions().end(), matches);
|
||||
if (elseIt != macro->ElseActions().end()) {
|
||||
return *elseIt;
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
void MacroSegment::AddTempvar(const std::string &id, const std::string &name,
|
||||
const std::string &description)
|
||||
{
|
||||
auto macro = GetMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
_variableRefs--;
|
||||
|
||||
auto sharedSegment = getSharedSegmentFromMacro(macro, this);
|
||||
if (!sharedSegment) {
|
||||
return;
|
||||
}
|
||||
|
||||
TempVariable var(id, name, description, sharedSegment);
|
||||
_tempVariables.emplace_back(std::move(var));
|
||||
NotifyUIAboutTempVarChange();
|
||||
}
|
||||
|
||||
void MacroSegment::SetTempVarValue(const std::string &id,
|
||||
const std::string &value)
|
||||
{
|
||||
for (auto &var : _tempVariables) {
|
||||
if (var.ID() != id) {
|
||||
continue;
|
||||
}
|
||||
var.SetValue(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MacroSegment::InvalidateTempVarValues()
|
||||
{
|
||||
for (auto &var : _tempVariables) {
|
||||
var.InvalidateValue();
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<const TempVariable>
|
||||
MacroSegment::GetTempVar(const std::string &id) const
|
||||
{
|
||||
TempVariable *result = nullptr;
|
||||
for (auto &var : _tempVariables) {
|
||||
if (var.ID() == id) {
|
||||
return var;
|
||||
}
|
||||
}
|
||||
vblog(LOG_INFO, "cannot get value of unknown tempvar %s", id.c_str());
|
||||
return {};
|
||||
}
|
||||
|
||||
bool SupportsVariableValue(MacroSegment *segment)
|
||||
{
|
||||
return segment && segment->_supportsVariableValue;
|
||||
}
|
||||
|
||||
void IncrementVariableRef(MacroSegment *segment)
|
||||
{
|
||||
if (!segment || !segment->_supportsVariableValue) {
|
||||
return;
|
||||
}
|
||||
segment->_variableRefs++;
|
||||
}
|
||||
|
||||
void DecrementVariableRef(MacroSegment *segment)
|
||||
{
|
||||
if (!segment || !segment->_supportsVariableValue ||
|
||||
segment->_variableRefs == 0) {
|
||||
return;
|
||||
}
|
||||
segment->_variableRefs--;
|
||||
}
|
||||
|
||||
MacroSegmentEdit::MacroSegmentEdit(bool highlight, QWidget *parent)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
#pragma once
|
||||
|
||||
// The following helpers are used by all macro seements,
|
||||
// The following helpers are used by all macro segments,
|
||||
// so it makes sense to include them here:
|
||||
#include "log-helper.hpp"
|
||||
#include "obs-module-helper.hpp"
|
||||
#include "sync-helper.hpp"
|
||||
#include "temp-variable.hpp"
|
||||
|
||||
#include <QWidget>
|
||||
#include <QFrame>
|
||||
@@ -34,16 +35,26 @@ public:
|
||||
virtual std::string GetId() const = 0;
|
||||
void SetHighlight();
|
||||
bool Highlight();
|
||||
bool SupportsVariableValue() const { return _supportsVariableValue; }
|
||||
virtual std::string GetVariableValue() const;
|
||||
void IncrementVariableRef();
|
||||
void DecrementVariableRef();
|
||||
|
||||
protected:
|
||||
friend bool SupportsVariableValue(MacroSegment *);
|
||||
friend void IncrementVariableRef(MacroSegment *);
|
||||
friend void DecrementVariableRef(MacroSegment *);
|
||||
void SetVariableValue(const std::string &value);
|
||||
bool IsReferencedInVars() { return _variableRefs != 0; }
|
||||
|
||||
virtual void SetupTempVars();
|
||||
void AddTempvar(const std::string &id, const std::string &name,
|
||||
const std::string &description = "");
|
||||
void SetTempVarValue(const std::string &id, const std::string &value);
|
||||
|
||||
private:
|
||||
void ClearAvailableTempvars();
|
||||
std::optional<const TempVariable>
|
||||
GetTempVar(const std::string &id) const;
|
||||
void InvalidateTempVarValues();
|
||||
|
||||
// Macro helpers
|
||||
Macro *_macro = nullptr;
|
||||
int _idx = 0;
|
||||
@@ -56,6 +67,9 @@ private:
|
||||
const bool _supportsVariableValue = false;
|
||||
int _variableRefs = 0;
|
||||
std::string _variableValue;
|
||||
std::vector<TempVariable> _tempVariables;
|
||||
|
||||
friend class Macro;
|
||||
};
|
||||
|
||||
class Section;
|
||||
@@ -70,6 +84,7 @@ public:
|
||||
void SetFocusPolicyOfWidgets();
|
||||
void SetCollapsed(bool collapsed);
|
||||
void SetSelected(bool);
|
||||
virtual std::shared_ptr<MacroSegment> Data() const = 0;
|
||||
|
||||
protected slots:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
@@ -99,7 +114,6 @@ private:
|
||||
BELOW,
|
||||
};
|
||||
|
||||
virtual std::shared_ptr<MacroSegment> Data() = 0;
|
||||
void ShowDropLine(DropLineState);
|
||||
|
||||
// The reason for using two separate frame widget each with their own
|
||||
|
||||
@@ -244,6 +244,7 @@ void AdvSceneSwitcher::ExportMacros()
|
||||
obs_data_release(obj);
|
||||
}
|
||||
obs_data_set_array(data, "macros", macroArray);
|
||||
switcher->SaveVariables(data);
|
||||
obs_data_array_release(macroArray);
|
||||
obs_data_set_string(data, "version", g_GIT_TAG);
|
||||
auto json = obs_data_get_json(data);
|
||||
@@ -253,6 +254,76 @@ void AdvSceneSwitcher::ExportMacros()
|
||||
MacroExportImportDialog::ExportMacros(exportString);
|
||||
}
|
||||
|
||||
static bool
|
||||
isValidMacroSegmentIdx(const std::deque<std::shared_ptr<MacroSegment>> &list,
|
||||
int idx)
|
||||
{
|
||||
return (idx > 0 || (unsigned)idx < list.size());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetupMacroSegmentSelection(MacroSection type, int idx)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
MacroSegmentList *setList, *resetList1, *resetList2;
|
||||
int *setIdx, *resetIdx1, *resetIdx2;
|
||||
std::deque<std::shared_ptr<MacroSegment>> segements;
|
||||
|
||||
switch (type) {
|
||||
case AdvSceneSwitcher::MacroSection::CONDITIONS:
|
||||
setList = ui->conditionsList;
|
||||
setIdx = ¤tConditionIdx;
|
||||
segements = {macro->Conditions().begin(),
|
||||
macro->Conditions().end()};
|
||||
|
||||
resetList1 = ui->actionsList;
|
||||
resetList2 = ui->elseActionsList;
|
||||
resetIdx1 = ¤tActionIdx;
|
||||
resetIdx2 = ¤tElseActionIdx;
|
||||
break;
|
||||
case AdvSceneSwitcher::MacroSection::ACTIONS:
|
||||
setList = ui->actionsList;
|
||||
setIdx = ¤tActionIdx;
|
||||
segements = {macro->Actions().begin(), macro->Actions().end()};
|
||||
|
||||
resetList1 = ui->conditionsList;
|
||||
resetList2 = ui->elseActionsList;
|
||||
resetIdx1 = ¤tConditionIdx;
|
||||
resetIdx2 = ¤tElseActionIdx;
|
||||
break;
|
||||
case AdvSceneSwitcher::MacroSection::ELSE_ACTIONS:
|
||||
setList = ui->elseActionsList;
|
||||
setIdx = ¤tElseActionIdx;
|
||||
segements = {macro->ElseActions().begin(),
|
||||
macro->ElseActions().end()};
|
||||
|
||||
resetList1 = ui->actionsList;
|
||||
resetList2 = ui->conditionsList;
|
||||
resetIdx1 = ¤tActionIdx;
|
||||
resetIdx2 = ¤tConditionIdx;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
setList->SetSelection(idx);
|
||||
resetList1->SetSelection(-1);
|
||||
resetList2->SetSelection(-1);
|
||||
if (isValidMacroSegmentIdx(segements, idx)) {
|
||||
*setIdx = idx;
|
||||
} else {
|
||||
*setIdx = -1;
|
||||
}
|
||||
*resetIdx1 = -1;
|
||||
*resetIdx2 = -1;
|
||||
|
||||
lastInteracted = type;
|
||||
HighlightControls();
|
||||
}
|
||||
|
||||
bool AdvSceneSwitcher::ResolveMacroImportNameConflict(
|
||||
std::shared_ptr<Macro> ¯o)
|
||||
{
|
||||
@@ -297,6 +368,26 @@ bool AdvSceneSwitcher::ResolveMacroImportNameConflict(
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool variableWithNameExists(const std::string &name)
|
||||
{
|
||||
return !!GetVariableByName(name);
|
||||
}
|
||||
|
||||
static void importVariables(obs_data_t *obj)
|
||||
{
|
||||
OBSDataArrayAutoRelease array = obs_data_get_array(obj, "variables");
|
||||
size_t count = obs_data_array_count(array);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
OBSDataAutoRelease data = obs_data_array_item(array, i);
|
||||
auto var = Variable::Create();
|
||||
var->Load(data);
|
||||
if (variableWithNameExists(var->Name())) {
|
||||
continue;
|
||||
}
|
||||
switcher->variables.emplace_back(var);
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ImportMacros()
|
||||
{
|
||||
QString json;
|
||||
@@ -310,6 +401,7 @@ void AdvSceneSwitcher::ImportMacros()
|
||||
ImportMacros();
|
||||
return;
|
||||
}
|
||||
importVariables(data);
|
||||
|
||||
auto version = obs_data_get_string(data, "version");
|
||||
if (strcmp(version, g_GIT_TAG) != 0) {
|
||||
@@ -381,21 +473,6 @@ void AdvSceneSwitcher::on_macroName_editingFinished()
|
||||
RenameMacro(macro, newName);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_runMacro_clicked()
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool ret = macro->PerformActions(true, true);
|
||||
if (!ret) {
|
||||
QString err =
|
||||
obs_module_text("AdvSceneSwitcher.macroTab.runFail");
|
||||
DisplayMessage(err.arg(QString::fromStdString(macro->Name())));
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_runMacroInParallel_stateChanged(int value)
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
@@ -422,9 +499,20 @@ void AdvSceneSwitcher::PopulateMacroActions(Macro &m, uint32_t afterIdx)
|
||||
for (; afterIdx < actions.size(); afterIdx++) {
|
||||
auto newEntry = new MacroActionEdit(this, &actions[afterIdx],
|
||||
actions[afterIdx]->GetId());
|
||||
actionsList->Add(newEntry);
|
||||
ui->actionsList->Add(newEntry);
|
||||
}
|
||||
actionsList->SetHelpMsgVisible(actions.size() == 0);
|
||||
ui->actionsList->SetHelpMsgVisible(actions.size() == 0);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::PopulateMacroElseActions(Macro &m, uint32_t afterIdx)
|
||||
{
|
||||
auto &actions = m.ElseActions();
|
||||
for (; afterIdx < actions.size(); afterIdx++) {
|
||||
auto newEntry = new MacroActionEdit(this, &actions[afterIdx],
|
||||
actions[afterIdx]->GetId());
|
||||
ui->elseActionsList->Add(newEntry);
|
||||
}
|
||||
ui->elseActionsList->SetHelpMsgVisible(actions.size() == 0);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::PopulateMacroConditions(Macro &m, uint32_t afterIdx)
|
||||
@@ -435,17 +523,35 @@ void AdvSceneSwitcher::PopulateMacroConditions(Macro &m, uint32_t afterIdx)
|
||||
auto newEntry = new MacroConditionEdit(
|
||||
this, &conditions[afterIdx],
|
||||
conditions[afterIdx]->GetId(), root);
|
||||
conditionsList->Add(newEntry);
|
||||
ui->conditionsList->Add(newEntry);
|
||||
root = false;
|
||||
}
|
||||
conditionsList->SetHelpMsgVisible(conditions.size() == 0);
|
||||
ui->conditionsList->SetHelpMsgVisible(conditions.size() == 0);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetActionData(Macro &m)
|
||||
{
|
||||
auto &actions = m.Actions();
|
||||
for (int idx = 0; idx < actionsList->ContentLayout()->count(); idx++) {
|
||||
auto item = actionsList->ContentLayout()->itemAt(idx);
|
||||
for (int idx = 0; idx < ui->actionsList->ContentLayout()->count();
|
||||
idx++) {
|
||||
auto item = ui->actionsList->ContentLayout()->itemAt(idx);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
auto widget = static_cast<MacroActionEdit *>(item->widget());
|
||||
if (!widget) {
|
||||
continue;
|
||||
}
|
||||
widget->SetEntryData(&*(actions.begin() + idx));
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetElseActionData(Macro &m)
|
||||
{
|
||||
auto &actions = m.ElseActions();
|
||||
for (int idx = 0; idx < ui->elseActionsList->ContentLayout()->count();
|
||||
idx++) {
|
||||
auto item = ui->elseActionsList->ContentLayout()->itemAt(idx);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
@@ -460,9 +566,9 @@ void AdvSceneSwitcher::SetActionData(Macro &m)
|
||||
void AdvSceneSwitcher::SetConditionData(Macro &m)
|
||||
{
|
||||
auto &conditions = m.Conditions();
|
||||
for (int idx = 0; idx < conditionsList->ContentLayout()->count();
|
||||
for (int idx = 0; idx < ui->conditionsList->ContentLayout()->count();
|
||||
idx++) {
|
||||
auto item = conditionsList->ContentLayout()->itemAt(idx);
|
||||
auto item = ui->conditionsList->ContentLayout()->itemAt(idx);
|
||||
if (!item) {
|
||||
continue;
|
||||
}
|
||||
@@ -474,6 +580,21 @@ void AdvSceneSwitcher::SetConditionData(Macro &m)
|
||||
}
|
||||
}
|
||||
|
||||
static void maximizeFirstSplitterEntry(QSplitter *splitter)
|
||||
{
|
||||
QList<int> newSizes;
|
||||
newSizes << 999999;
|
||||
for (int i = 0; i < splitter->sizes().size() - 1; i++) {
|
||||
newSizes << 0;
|
||||
}
|
||||
splitter->setSizes(newSizes);
|
||||
}
|
||||
|
||||
static void centerSplitterPosition(QSplitter *splitter)
|
||||
{
|
||||
splitter->setSizes(QList<int>() << 999999 << 999999);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetEditMacro(Macro &m)
|
||||
{
|
||||
{
|
||||
@@ -484,22 +605,40 @@ void AdvSceneSwitcher::SetEditMacro(Macro &m)
|
||||
ui->runMacroInParallel->setChecked(m.RunInParallel());
|
||||
ui->runMacroOnChange->setChecked(m.MatchOnChange());
|
||||
}
|
||||
conditionsList->Clear();
|
||||
actionsList->Clear();
|
||||
ui->conditionsList->Clear();
|
||||
ui->actionsList->Clear();
|
||||
ui->elseActionsList->Clear();
|
||||
|
||||
m.ResetUIHelpers();
|
||||
|
||||
PopulateMacroConditions(m);
|
||||
PopulateMacroActions(m);
|
||||
PopulateMacroElseActions(m);
|
||||
SetMacroEditAreaDisabled(false);
|
||||
|
||||
currentActionIdx = -1;
|
||||
currentElseActionIdx = -1;
|
||||
currentConditionIdx = -1;
|
||||
HighlightControls();
|
||||
|
||||
if (m.IsGroup()) {
|
||||
SetMacroEditAreaDisabled(true);
|
||||
ui->macroName->setEnabled(true);
|
||||
centerSplitterPosition(ui->macroActionConditionSplitter);
|
||||
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
||||
return;
|
||||
}
|
||||
|
||||
currentActionIdx = -1;
|
||||
currentConditionIdx = -1;
|
||||
HighlightControls();
|
||||
if (!m.HasValidSplitterPositions()) {
|
||||
centerSplitterPosition(ui->macroActionConditionSplitter);
|
||||
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
||||
return;
|
||||
}
|
||||
|
||||
ui->macroActionConditionSplitter->setSizes(
|
||||
m.GetActionConditionSplitterPosition());
|
||||
ui->macroElseActionSplitter->setSizes(
|
||||
m.GetElseActionSplitterPosition());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SetMacroEditAreaDisabled(bool disable)
|
||||
@@ -515,12 +654,17 @@ void AdvSceneSwitcher::SetMacroEditAreaDisabled(bool disable)
|
||||
|
||||
void AdvSceneSwitcher::HighlightAction(int idx, QColor color)
|
||||
{
|
||||
actionsList->Highlight(idx, color);
|
||||
ui->actionsList->Highlight(idx, color);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::HighlightElseAction(int idx, QColor color)
|
||||
{
|
||||
ui->elseActionsList->Highlight(idx, color);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::HighlightCondition(int idx, QColor color)
|
||||
{
|
||||
conditionsList->Highlight(idx, color);
|
||||
ui->conditionsList->Highlight(idx, color);
|
||||
}
|
||||
|
||||
std::shared_ptr<Macro> AdvSceneSwitcher::GetSelectedMacro()
|
||||
@@ -533,6 +677,37 @@ std::vector<std::shared_ptr<Macro>> AdvSceneSwitcher::GetSelectedMacros()
|
||||
return ui->macros->GetCurrentMacros();
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MacroSelectionAboutToChange()
|
||||
{
|
||||
if (loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!ui->macroName->isEnabled()) { // No macro is selected
|
||||
return;
|
||||
}
|
||||
|
||||
auto macro = GetMacroByQString(ui->macroName->text());
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
macro->SetActionConditionSplitterPosition(
|
||||
ui->macroActionConditionSplitter->sizes());
|
||||
|
||||
auto elsePos = ui->macroElseActionSplitter->sizes();
|
||||
// If only conditions are visible maximize the actions to avoid neither
|
||||
// actions nor elseActions being visible when the condition <-> action
|
||||
// splitter is moved
|
||||
if (elsePos[0] == 0 && elsePos[1] == 0) {
|
||||
macro->SetElseActionSplitterPosition(QList<int>()
|
||||
<< 999999 << 0);
|
||||
return;
|
||||
}
|
||||
macro->SetElseActionSplitterPosition(
|
||||
ui->macroElseActionSplitter->sizes());
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MacroSelectionChanged()
|
||||
{
|
||||
if (loading) {
|
||||
@@ -542,10 +717,14 @@ void AdvSceneSwitcher::MacroSelectionChanged()
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
SetMacroEditAreaDisabled(true);
|
||||
conditionsList->Clear();
|
||||
actionsList->Clear();
|
||||
conditionsList->SetHelpMsgVisible(true);
|
||||
actionsList->SetHelpMsgVisible(true);
|
||||
ui->conditionsList->Clear();
|
||||
ui->actionsList->Clear();
|
||||
ui->elseActionsList->Clear();
|
||||
ui->conditionsList->SetHelpMsgVisible(true);
|
||||
ui->actionsList->SetHelpMsgVisible(true);
|
||||
ui->elseActionsList->SetHelpMsgVisible(true);
|
||||
centerSplitterPosition(ui->macroActionConditionSplitter);
|
||||
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
||||
return;
|
||||
}
|
||||
SetEditMacro(*macro);
|
||||
@@ -583,8 +762,19 @@ void AdvSceneSwitcher::on_macroProperties_clicked()
|
||||
emit HighlightConditionsChanged(prop._highlightConditions);
|
||||
}
|
||||
|
||||
// Don't restore splitter pos if an element is not visible at all
|
||||
bool shouldResotreSplitterPos(const QList<int> &pos)
|
||||
static void moveControlsToSplitter(QSplitter *splitter, int idx,
|
||||
QLayoutItem *item)
|
||||
{
|
||||
static int splitterHandleWidth = 38;
|
||||
auto handle = splitter->handle(idx);
|
||||
auto layout = item->layout();
|
||||
layout->setContentsMargins(7, 7, 7, 7);
|
||||
handle->setLayout(layout);
|
||||
splitter->setHandleWidth(splitterHandleWidth);
|
||||
splitter->setStyleSheet("QSplitter::handle {background: transparent;}");
|
||||
}
|
||||
|
||||
bool shouldRestoreSplitter(const QList<int> &pos)
|
||||
{
|
||||
if (pos.size() == 0) {
|
||||
return false;
|
||||
@@ -605,37 +795,44 @@ void AdvSceneSwitcher::SetupMacroTab()
|
||||
}
|
||||
ui->macros->Reset(switcher->macros,
|
||||
switcher->macroProperties._highlightExecuted);
|
||||
connect(ui->macros, SIGNAL(MacroSelectionAboutToChange()), this,
|
||||
SLOT(MacroSelectionAboutToChange()));
|
||||
connect(ui->macros, SIGNAL(MacroSelectionChanged()), this,
|
||||
SLOT(MacroSelectionChanged()));
|
||||
ui->runMacro->SetMacroTree(ui->macros);
|
||||
|
||||
delete conditionsList;
|
||||
conditionsList = new MacroSegmentList(this);
|
||||
conditionsList->SetHelpMsg(
|
||||
ui->conditionsList->SetHelpMsg(
|
||||
obs_module_text("AdvSceneSwitcher.macroTab.editConditionHelp"));
|
||||
connect(conditionsList, &MacroSegmentList::SelectionChagned, this,
|
||||
connect(ui->conditionsList, &MacroSegmentList::SelectionChagned, this,
|
||||
&AdvSceneSwitcher::MacroConditionSelectionChanged);
|
||||
connect(conditionsList, &MacroSegmentList::Reorder, this,
|
||||
connect(ui->conditionsList, &MacroSegmentList::Reorder, this,
|
||||
&AdvSceneSwitcher::MacroConditionReorder);
|
||||
ui->macroConditionsLayout->insertWidget(0, conditionsList);
|
||||
|
||||
delete actionsList;
|
||||
actionsList = new MacroSegmentList(this);
|
||||
actionsList->SetHelpMsg(
|
||||
ui->actionsList->SetHelpMsg(
|
||||
obs_module_text("AdvSceneSwitcher.macroTab.editActionHelp"));
|
||||
connect(actionsList, &MacroSegmentList::SelectionChagned, this,
|
||||
connect(ui->actionsList, &MacroSegmentList::SelectionChagned, this,
|
||||
&AdvSceneSwitcher::MacroActionSelectionChanged);
|
||||
connect(actionsList, &MacroSegmentList::Reorder, this,
|
||||
connect(ui->actionsList, &MacroSegmentList::Reorder, this,
|
||||
&AdvSceneSwitcher::MacroActionReorder);
|
||||
ui->macroActionsLayout->insertWidget(0, actionsList);
|
||||
|
||||
ui->elseActionsList->SetHelpMsg(obs_module_text(
|
||||
"AdvSceneSwitcher.macroTab.editElseActionHelp"));
|
||||
connect(ui->elseActionsList, &MacroSegmentList::SelectionChagned, this,
|
||||
&AdvSceneSwitcher::MacroElseActionSelectionChanged);
|
||||
connect(ui->elseActionsList, &MacroSegmentList::Reorder, this,
|
||||
&AdvSceneSwitcher::MacroElseActionReorder);
|
||||
|
||||
ui->macros->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->macros, &QWidget::customContextMenuRequested, this,
|
||||
&AdvSceneSwitcher::ShowMacroContextMenu);
|
||||
actionsList->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(actionsList, &QWidget::customContextMenuRequested, this,
|
||||
ui->actionsList->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->actionsList, &QWidget::customContextMenuRequested, this,
|
||||
&AdvSceneSwitcher::ShowMacroActionsContextMenu);
|
||||
conditionsList->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(conditionsList, &QWidget::customContextMenuRequested, this,
|
||||
ui->elseActionsList->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->elseActionsList, &QWidget::customContextMenuRequested, this,
|
||||
&AdvSceneSwitcher::ShowMacroElseActionsContextMenu);
|
||||
ui->conditionsList->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(ui->conditionsList, &QWidget::customContextMenuRequested, this,
|
||||
&AdvSceneSwitcher::ShowMacroConditionsContextMenu);
|
||||
|
||||
SetMacroEditAreaDisabled(true);
|
||||
@@ -648,16 +845,10 @@ void AdvSceneSwitcher::SetupMacroTab()
|
||||
onChangeHighlightTimer.start();
|
||||
|
||||
// Move condition controls into splitter handle layout
|
||||
auto handle = ui->macroActionConditionSplitter->handle(1);
|
||||
auto item = ui->macroConditionsLayout->takeAt(1);
|
||||
if (item) {
|
||||
auto layout = item->layout();
|
||||
layout->setContentsMargins(7, 7, 7, 7);
|
||||
handle->setLayout(layout);
|
||||
ui->macroActionConditionSplitter->setHandleWidth(38);
|
||||
}
|
||||
ui->macroActionConditionSplitter->setStyleSheet(
|
||||
"QSplitter::handle {background: transparent;}");
|
||||
moveControlsToSplitter(ui->macroActionConditionSplitter, 1,
|
||||
ui->macroConditionsLayout->takeAt(1));
|
||||
moveControlsToSplitter(ui->macroElseActionSplitter, 1,
|
||||
ui->macroActionsLayout->takeAt(1));
|
||||
|
||||
// Set action and condition control icons
|
||||
const std::string pathPrefix =
|
||||
@@ -665,6 +856,9 @@ void AdvSceneSwitcher::SetupMacroTab()
|
||||
SetButtonIcon(ui->actionTop, (pathPrefix + "DoubleUp.svg").c_str());
|
||||
SetButtonIcon(ui->actionBottom,
|
||||
(pathPrefix + "DoubleDown.svg").c_str());
|
||||
SetButtonIcon(ui->elseActionTop, (pathPrefix + "DoubleUp.svg").c_str());
|
||||
SetButtonIcon(ui->elseActionBottom,
|
||||
(pathPrefix + "DoubleDown.svg").c_str());
|
||||
SetButtonIcon(ui->conditionTop, (pathPrefix + "DoubleUp.svg").c_str());
|
||||
SetButtonIcon(ui->conditionBottom,
|
||||
(pathPrefix + "DoubleDown.svg").c_str());
|
||||
@@ -673,13 +867,11 @@ void AdvSceneSwitcher::SetupMacroTab()
|
||||
ui->macroListMacroEditSplitter->setStretchFactor(0, 1);
|
||||
ui->macroListMacroEditSplitter->setStretchFactor(1, 4);
|
||||
|
||||
centerSplitterPosition(ui->macroActionConditionSplitter);
|
||||
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
||||
|
||||
if (switcher->saveWindowGeo) {
|
||||
if (shouldResotreSplitterPos(
|
||||
switcher->macroActionConditionSplitterPosition)) {
|
||||
ui->macroActionConditionSplitter->setSizes(
|
||||
switcher->macroActionConditionSplitterPosition);
|
||||
}
|
||||
if (shouldResotreSplitterPos(
|
||||
if (shouldRestoreSplitter(
|
||||
switcher->macroListMacroEditSplitterPosition)) {
|
||||
ui->macroListMacroEditSplitter->setSizes(
|
||||
switcher->macroListMacroEditSplitterPosition);
|
||||
@@ -731,41 +923,55 @@ void AdvSceneSwitcher::ShowMacroContextMenu(const QPoint &pos)
|
||||
obs_module_text("AdvSceneSwitcher.macroTab.export"), this,
|
||||
&AdvSceneSwitcher::ExportMacros);
|
||||
exportAction->setDisabled(ui->macros->SelectionEmpty());
|
||||
auto import = menu.addAction(
|
||||
obs_module_text("AdvSceneSwitcher.macroTab.import"), this,
|
||||
&AdvSceneSwitcher::ImportMacros);
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.import"),
|
||||
this, &AdvSceneSwitcher::ImportMacros);
|
||||
|
||||
menu.exec(globalPos);
|
||||
}
|
||||
|
||||
static void setupConextMenu(AdvSceneSwitcher *ss, const QPoint &pos,
|
||||
std::function<void(AdvSceneSwitcher *)> expand,
|
||||
std::function<void(AdvSceneSwitcher *)> collapse,
|
||||
std::function<void(AdvSceneSwitcher *)> maximize,
|
||||
std::function<void(AdvSceneSwitcher *)> minimize)
|
||||
{
|
||||
QMenu menu;
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.expandAll"),
|
||||
ss, [ss, expand]() { expand(ss); });
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.collapseAll"),
|
||||
ss, [ss, collapse]() { collapse(ss); });
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.maximize"),
|
||||
ss, [ss, maximize]() { maximize(ss); });
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.minimize"),
|
||||
ss, [ss, minimize]() { minimize(ss); });
|
||||
menu.exec(pos);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ShowMacroActionsContextMenu(const QPoint &pos)
|
||||
{
|
||||
QPoint globalPos = actionsList->mapToGlobal(pos);
|
||||
QMenu menu;
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.expandAll"),
|
||||
this, &AdvSceneSwitcher::ExpandAllActions);
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.collapseAll"),
|
||||
this, &AdvSceneSwitcher::CollapseAllActions);
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.maximize"),
|
||||
this, &AdvSceneSwitcher::MinimizeConditions);
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.minimize"),
|
||||
this, &AdvSceneSwitcher::MinimizeActions);
|
||||
menu.exec(globalPos);
|
||||
setupConextMenu(this, ui->actionsList->mapToGlobal(pos),
|
||||
&AdvSceneSwitcher::ExpandAllActions,
|
||||
&AdvSceneSwitcher::CollapseAllActions,
|
||||
&AdvSceneSwitcher::MaximizeActions,
|
||||
&AdvSceneSwitcher::MinimizeActions);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ShowMacroElseActionsContextMenu(const QPoint &pos)
|
||||
{
|
||||
setupConextMenu(this, ui->elseActionsList->mapToGlobal(pos),
|
||||
&AdvSceneSwitcher::ExpandAllElseActions,
|
||||
&AdvSceneSwitcher::CollapseAllElseActions,
|
||||
&AdvSceneSwitcher::MaximizeElseActions,
|
||||
&AdvSceneSwitcher::MinimizeElseActions);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ShowMacroConditionsContextMenu(const QPoint &pos)
|
||||
{
|
||||
QPoint globalPos = conditionsList->mapToGlobal(pos);
|
||||
QMenu menu;
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.expandAll"),
|
||||
this, &AdvSceneSwitcher::ExpandAllConditions);
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.collapseAll"),
|
||||
this, &AdvSceneSwitcher::CollapseAllConditions);
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.maximize"),
|
||||
this, &AdvSceneSwitcher::MinimizeActions);
|
||||
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.minimize"),
|
||||
this, &AdvSceneSwitcher::MinimizeConditions);
|
||||
menu.exec(globalPos);
|
||||
setupConextMenu(this, ui->conditionsList->mapToGlobal(pos),
|
||||
&AdvSceneSwitcher::ExpandAllConditions,
|
||||
&AdvSceneSwitcher::CollapseAllConditions,
|
||||
&AdvSceneSwitcher::MaximizeConditions,
|
||||
&AdvSceneSwitcher::MinimizeConditions);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::CopyMacro()
|
||||
@@ -795,60 +1001,103 @@ void AdvSceneSwitcher::CopyMacro()
|
||||
emit MacroAdded(QString::fromStdString(name));
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ExpandAllActions()
|
||||
void setCollapsedHelper(const std::shared_ptr<Macro> &m, MacroSegmentList *list,
|
||||
bool collapsed)
|
||||
{
|
||||
auto m = GetSelectedMacro();
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
actionsList->SetCollapsed(false);
|
||||
list->SetCollapsed(collapsed);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ExpandAllActions()
|
||||
{
|
||||
setCollapsedHelper(GetSelectedMacro(), ui->actionsList, false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ExpandAllElseActions()
|
||||
{
|
||||
setCollapsedHelper(GetSelectedMacro(), ui->elseActionsList, false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::ExpandAllConditions()
|
||||
{
|
||||
auto m = GetSelectedMacro();
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
conditionsList->SetCollapsed(false);
|
||||
setCollapsedHelper(GetSelectedMacro(), ui->conditionsList, false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::CollapseAllActions()
|
||||
{
|
||||
auto m = GetSelectedMacro();
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
actionsList->SetCollapsed(true);
|
||||
setCollapsedHelper(GetSelectedMacro(), ui->actionsList, true);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::CollapseAllElseActions()
|
||||
{
|
||||
setCollapsedHelper(GetSelectedMacro(), ui->elseActionsList, true);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::CollapseAllConditions()
|
||||
{
|
||||
auto m = GetSelectedMacro();
|
||||
if (!m) {
|
||||
return;
|
||||
}
|
||||
conditionsList->SetCollapsed(true);
|
||||
setCollapsedHelper(GetSelectedMacro(), ui->conditionsList, true);
|
||||
}
|
||||
|
||||
static void reduceSizeOfSplitterIdx(QSplitter *splitter, int idx)
|
||||
{
|
||||
auto sizes = splitter->sizes();
|
||||
int sum = sizes[0] + sizes[1];
|
||||
int reducedSize = sum / 10;
|
||||
sizes[idx] = reducedSize;
|
||||
sizes[(idx + 1) % 2] = sum - reducedSize;
|
||||
splitter->setSizes(sizes);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MinimizeActions()
|
||||
{
|
||||
QList<int> sizes = ui->macroActionConditionSplitter->sizes();
|
||||
int sum = sizes[0] + sizes[1];
|
||||
int actionsHeight = sum / 10;
|
||||
sizes[1] = actionsHeight;
|
||||
sizes[0] = sum - actionsHeight;
|
||||
ui->macroActionConditionSplitter->setSizes(sizes);
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
if (macro->ElseActions().size() == 0) {
|
||||
reduceSizeOfSplitterIdx(ui->macroActionConditionSplitter, 1);
|
||||
} else {
|
||||
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
||||
reduceSizeOfSplitterIdx(ui->macroActionConditionSplitter, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MaximizeActions()
|
||||
{
|
||||
MinimizeElseActions();
|
||||
MinimizeConditions();
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MinimizeElseActions()
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
if (macro->ElseActions().size() == 0) {
|
||||
maximizeFirstSplitterEntry(ui->macroElseActionSplitter);
|
||||
} else {
|
||||
reduceSizeOfSplitterIdx(ui->macroElseActionSplitter, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MaximizeElseActions()
|
||||
{
|
||||
MinimizeConditions();
|
||||
reduceSizeOfSplitterIdx(ui->macroElseActionSplitter, 0);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MinimizeConditions()
|
||||
{
|
||||
QList<int> sizes = ui->macroActionConditionSplitter->sizes();
|
||||
int sum = sizes[0] + sizes[1];
|
||||
int conditionsHeight = sum / 10;
|
||||
sizes[0] = conditionsHeight;
|
||||
sizes[1] = sum - conditionsHeight;
|
||||
ui->macroActionConditionSplitter->setSizes(sizes);
|
||||
reduceSizeOfSplitterIdx(ui->macroActionConditionSplitter, 0);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::MaximizeConditions()
|
||||
{
|
||||
MinimizeElseActions();
|
||||
MinimizeActions();
|
||||
}
|
||||
|
||||
bool AdvSceneSwitcher::MacroTabIsInFocus()
|
||||
|
||||
@@ -212,7 +212,7 @@ static inline int
|
||||
ModelIndexToMacroIndex(int modelIdx,
|
||||
const std::deque<std::shared_ptr<Macro>> ¯os)
|
||||
{
|
||||
assert(macros.size() >= modelIdx);
|
||||
assert((int)macros.size() >= modelIdx);
|
||||
int realIdx = 0;
|
||||
const auto &m = macros[0];
|
||||
bool inCollapsedGroup = m->IsGroup() && m->IsCollapsed();
|
||||
@@ -609,7 +609,7 @@ bool MacroTreeModel::IsLastItem(std::shared_ptr<Macro> item) const
|
||||
bool MacroTreeModel::IsInValidState()
|
||||
{
|
||||
// Check for reordering erros
|
||||
for (int i = 0, j = 0; i < _macros.size(); i++) {
|
||||
for (size_t i = 0, j = 0; i < _macros.size(); i++) {
|
||||
const auto &m = _macros[i];
|
||||
if (QString::fromStdString(m->Name()) !=
|
||||
data(index(j, 0), Qt::AccessibleTextRole)) {
|
||||
@@ -622,7 +622,7 @@ bool MacroTreeModel::IsInValidState()
|
||||
}
|
||||
|
||||
// Check for group errors
|
||||
for (int i = 0; i < _macros.size(); i++) {
|
||||
for (size_t i = 0; i < _macros.size(); i++) {
|
||||
const auto &m = _macros[i];
|
||||
if (!m->IsGroup()) {
|
||||
continue;
|
||||
@@ -1260,6 +1260,7 @@ void MacroTree::UngroupSelectedGroups()
|
||||
void MacroTree::SelectionChangedHelper(const QItemSelection &,
|
||||
const QItemSelection &)
|
||||
{
|
||||
emit MacroSelectionAboutToChange();
|
||||
emit MacroSelectionChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -142,6 +142,7 @@ public slots:
|
||||
const QItemSelection &);
|
||||
|
||||
signals:
|
||||
void MacroSelectionAboutToChange();
|
||||
void MacroSelectionChanged();
|
||||
|
||||
protected:
|
||||
|
||||
@@ -31,7 +31,7 @@ Macro::~Macro()
|
||||
Stop();
|
||||
ClearHotkeys();
|
||||
|
||||
// Keep the dock widgets in case of shutdown so they can be rostored by
|
||||
// Keep the dock widgets in case of shutdown so they can be restored by
|
||||
// OBS on startup
|
||||
if (!switcher->obsIsShuttingDown) {
|
||||
RemoveDock();
|
||||
@@ -176,24 +176,26 @@ bool Macro::CeckMatch()
|
||||
}
|
||||
vblog(LOG_INFO, "Macro %s returned %d", _name.c_str(), _matched);
|
||||
|
||||
bool matchedBeforeOnChangeCheck = _matched;
|
||||
if (_matched && _matchOnChange && _lastMatched) {
|
||||
vblog(LOG_INFO, "ignore match for Macro %s (on change)",
|
||||
_name.c_str());
|
||||
_matched = false;
|
||||
SetOnChangeHighlight();
|
||||
_conditionSateChanged = _lastMatched != _matched;
|
||||
if (!_conditionSateChanged && _performActionsOnChange) {
|
||||
_onPreventedActionExecution = true;
|
||||
}
|
||||
_lastMatched = matchedBeforeOnChangeCheck;
|
||||
_lastMatched = _matched;
|
||||
_lastCheckTime = std::chrono::high_resolution_clock::now();
|
||||
return _matched;
|
||||
}
|
||||
|
||||
bool Macro::PerformActions(bool forceParallel, bool ignorePause)
|
||||
bool Macro::PerformActions(bool match, bool forceParallel, bool ignorePause)
|
||||
{
|
||||
if (!_done) {
|
||||
vblog(LOG_INFO, "macro %s already running", _name.c_str());
|
||||
return !forceParallel;
|
||||
}
|
||||
std::function<bool(bool)> runFunc =
|
||||
match ? std::bind(&Macro::RunActions, this,
|
||||
std::placeholders::_1)
|
||||
: std::bind(&Macro::RunElseActions, this,
|
||||
std::placeholders::_1);
|
||||
_stop = false;
|
||||
_done = false;
|
||||
bool ret = true;
|
||||
@@ -202,9 +204,9 @@ bool Macro::PerformActions(bool forceParallel, bool ignorePause)
|
||||
_backgroundThread.join();
|
||||
}
|
||||
_backgroundThread = std::thread(
|
||||
[this, ignorePause] { RunActions(ignorePause); });
|
||||
[this, runFunc, ignorePause] { runFunc(ignorePause); });
|
||||
} else {
|
||||
RunActions(ret, ignorePause);
|
||||
ret = runFunc(ignorePause);
|
||||
}
|
||||
_lastExecutionTime = std::chrono::high_resolution_clock::now();
|
||||
auto group = _parent.lock();
|
||||
@@ -223,6 +225,28 @@ bool Macro::ExecutedSince(
|
||||
return _lastExecutionTime > time;
|
||||
}
|
||||
|
||||
bool Macro::ShouldRunActions() const
|
||||
{
|
||||
const bool hasActionsToExecute =
|
||||
(_matched || _elseActions.size() > 0) &&
|
||||
(!_performActionsOnChange || _conditionSateChanged);
|
||||
|
||||
if (VerboseLoggingEnabled() && _performActionsOnChange &&
|
||||
!_conditionSateChanged) {
|
||||
if (_matched && _actions.size() > 0) {
|
||||
blog(LOG_INFO, "skip actions for Macro %s (on change)",
|
||||
_name.c_str());
|
||||
}
|
||||
if (!_matched && _elseActions.size() > 0) {
|
||||
blog(LOG_INFO,
|
||||
"skip else actions for Macro %s (on change)",
|
||||
_name.c_str());
|
||||
}
|
||||
}
|
||||
|
||||
return hasActionsToExecute;
|
||||
}
|
||||
|
||||
int64_t Macro::MsSinceLastCheck() const
|
||||
{
|
||||
if (_lastCheckTime.time_since_epoch().count() == 0) {
|
||||
@@ -251,37 +275,47 @@ void Macro::ResetTimers()
|
||||
_lastExecutionTime = {};
|
||||
}
|
||||
|
||||
void Macro::RunActions(bool &retVal, bool ignorePause)
|
||||
bool Macro::RunActionsHelper(
|
||||
const std::deque<std::shared_ptr<MacroAction>> &actionsToRun,
|
||||
bool ignorePause)
|
||||
{
|
||||
bool ret = true;
|
||||
for (auto &a : _actions) {
|
||||
if (a->Enabled()) {
|
||||
a->LogAction();
|
||||
ret = ret && a->PerformAction();
|
||||
// Create copy of action list as elements might be removed, inserted, or
|
||||
// reordered while actions are currently being executed.
|
||||
auto actions = actionsToRun;
|
||||
|
||||
bool actionsExecutedSuccessfully = true;
|
||||
for (auto &action : actions) {
|
||||
if (action->Enabled()) {
|
||||
action->LogAction();
|
||||
actionsExecutedSuccessfully =
|
||||
actionsExecutedSuccessfully &&
|
||||
action->PerformAction();
|
||||
} else {
|
||||
vblog(LOG_INFO, "skipping disabled action %s",
|
||||
a->GetId().c_str());
|
||||
action->GetId().c_str());
|
||||
}
|
||||
if (!ret || (_paused && !ignorePause) || _stop || _die) {
|
||||
retVal = ret;
|
||||
if (!actionsExecutedSuccessfully || (_paused && !ignorePause) ||
|
||||
_stop || _die) {
|
||||
break;
|
||||
}
|
||||
if (a->Enabled()) {
|
||||
a->SetHighlight();
|
||||
if (action->Enabled()) {
|
||||
action->SetHighlight();
|
||||
}
|
||||
}
|
||||
_done = true;
|
||||
return actionsExecutedSuccessfully;
|
||||
}
|
||||
|
||||
void Macro::RunActions(bool ignorePause)
|
||||
bool Macro::RunActions(bool ignorePause)
|
||||
{
|
||||
bool unused;
|
||||
RunActions(unused, ignorePause);
|
||||
vblog(LOG_INFO, "running actions of %s", _name.c_str());
|
||||
return RunActionsHelper(_actions, ignorePause);
|
||||
}
|
||||
|
||||
void Macro::SetOnChangeHighlight()
|
||||
bool Macro::RunElseActions(bool ignorePause)
|
||||
{
|
||||
_onChangeTriggered = true;
|
||||
vblog(LOG_INFO, "running else actions of %s", _name.c_str());
|
||||
return RunActionsHelper(_elseActions, ignorePause);
|
||||
}
|
||||
|
||||
bool Macro::DockIsVisible() const
|
||||
@@ -289,6 +323,11 @@ bool Macro::DockIsVisible() const
|
||||
return _dock && _dockAction && _dock->isVisible();
|
||||
}
|
||||
|
||||
void Macro::SetMatchOnChange(bool onChange)
|
||||
{
|
||||
_performActionsOnChange = onChange;
|
||||
}
|
||||
|
||||
void Macro::SetPaused(bool pause)
|
||||
{
|
||||
if (_paused && !pause) {
|
||||
@@ -322,6 +361,126 @@ void Macro::Stop()
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<TempVariable> Macro::GetTempVars(MacroSegment *filter) const
|
||||
{
|
||||
std::vector<TempVariable> res;
|
||||
|
||||
auto addTempVars = [&res](const std::deque<std::shared_ptr<MacroSegment>>
|
||||
&segments) {
|
||||
for (const auto &s : segments) {
|
||||
const auto &tempVars = s->_tempVariables;
|
||||
res.insert(res.end(), tempVars.begin(), tempVars.end());
|
||||
}
|
||||
};
|
||||
|
||||
addTempVars({_conditions.begin(), _conditions.end()});
|
||||
addTempVars({_actions.begin(), _actions.end()});
|
||||
addTempVars({_elseActions.begin(), _elseActions.end()});
|
||||
|
||||
if (!filter) {
|
||||
return res;
|
||||
}
|
||||
|
||||
auto isCondition = [this](const MacroSegment *segment) -> bool {
|
||||
return std::find_if(_conditions.begin(), _conditions.end(),
|
||||
[segment](
|
||||
const std::shared_ptr<MacroSegment>
|
||||
&ptr) {
|
||||
return ptr.get() == segment;
|
||||
}) != _conditions.end();
|
||||
};
|
||||
auto isAction = [this](MacroSegment *segment) -> bool {
|
||||
return std::find_if(_actions.begin(), _actions.end(),
|
||||
[segment](
|
||||
const std::shared_ptr<MacroSegment>
|
||||
&ptr) {
|
||||
return ptr.get() == segment;
|
||||
}) != _actions.end();
|
||||
};
|
||||
auto isElseAction = [this](MacroSegment *segment) -> bool {
|
||||
return std::find_if(_elseActions.begin(), _elseActions.end(),
|
||||
[segment](
|
||||
const std::shared_ptr<MacroSegment>
|
||||
&ptr) {
|
||||
return ptr.get() == segment;
|
||||
}) != _elseActions.end();
|
||||
};
|
||||
|
||||
const int filterIndex = filter->GetIndex();
|
||||
// Remove all actions and else actions and conditions after filterIndex
|
||||
if (isCondition(filter)) {
|
||||
for (auto it = res.begin(); it != res.end();) {
|
||||
auto segment = it->Segment().lock().get();
|
||||
if (isCondition(segment) &&
|
||||
segment->GetIndex() >= filterIndex) {
|
||||
it = res.erase(it);
|
||||
continue;
|
||||
}
|
||||
if (isAction(segment) || isElseAction(segment)) {
|
||||
it = res.erase(it);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
// Remove all else actions and actions after filterIndex
|
||||
if (isAction(filter)) {
|
||||
for (auto it = res.begin(); it != res.end();) {
|
||||
auto segment = it->Segment().lock().get();
|
||||
if (isAction(segment) &&
|
||||
segment->GetIndex() >= filterIndex) {
|
||||
it = res.erase(it);
|
||||
continue;
|
||||
}
|
||||
if (isElseAction(segment)) {
|
||||
it = res.erase(it);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
// Remove all actions and elseActions after filterIndex
|
||||
for (auto it = res.begin(); it != res.end();) {
|
||||
auto segment = it->Segment().lock().get();
|
||||
if (isElseAction(segment) &&
|
||||
segment->GetIndex() >= filterIndex) {
|
||||
it = res.erase(it);
|
||||
continue;
|
||||
}
|
||||
if (isAction(segment)) {
|
||||
it = res.erase(it);
|
||||
continue;
|
||||
}
|
||||
++it;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
std::optional<const TempVariable> Macro::GetTempVar(const MacroSegment *segment,
|
||||
const std::string &id) const
|
||||
{
|
||||
if (!segment) {
|
||||
return {};
|
||||
}
|
||||
return segment->GetTempVar(id);
|
||||
}
|
||||
|
||||
void Macro::InvalidateTempVarValues() const
|
||||
{
|
||||
auto invalidateHelper =
|
||||
[](const std::deque<std::shared_ptr<MacroSegment>> &segments) {
|
||||
for (const auto &s : segments) {
|
||||
s->InvalidateTempVarValues();
|
||||
}
|
||||
};
|
||||
|
||||
invalidateHelper({_conditions.begin(), _conditions.end()});
|
||||
invalidateHelper({_actions.begin(), _actions.end()});
|
||||
invalidateHelper({_elseActions.begin(), _elseActions.end()});
|
||||
}
|
||||
|
||||
std::deque<std::shared_ptr<MacroCondition>> &Macro::Conditions()
|
||||
{
|
||||
return _conditions;
|
||||
@@ -332,22 +491,39 @@ std::deque<std::shared_ptr<MacroAction>> &Macro::Actions()
|
||||
return _actions;
|
||||
}
|
||||
|
||||
void Macro::UpdateActionIndices()
|
||||
std::deque<std::shared_ptr<MacroAction>> &Macro::ElseActions()
|
||||
{
|
||||
return _elseActions;
|
||||
}
|
||||
|
||||
static void updateIndicesHelper(std::deque<std::shared_ptr<MacroSegment>> &list)
|
||||
{
|
||||
int idx = 0;
|
||||
for (auto a : _actions) {
|
||||
a->SetIndex(idx);
|
||||
for (auto segment : list) {
|
||||
segment->SetIndex(idx);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
void Macro::UpdateActionIndices()
|
||||
{
|
||||
std::deque<std::shared_ptr<MacroSegment>> list(_actions.begin(),
|
||||
_actions.end());
|
||||
updateIndicesHelper(list);
|
||||
}
|
||||
|
||||
void Macro::UpdateElseActionIndices()
|
||||
{
|
||||
std::deque<std::shared_ptr<MacroSegment>> list(_elseActions.begin(),
|
||||
_elseActions.end());
|
||||
updateIndicesHelper(list);
|
||||
}
|
||||
|
||||
void Macro::UpdateConditionIndices()
|
||||
{
|
||||
int idx = 0;
|
||||
for (auto c : _conditions) {
|
||||
c->SetIndex(idx);
|
||||
idx++;
|
||||
}
|
||||
std::deque<std::shared_ptr<MacroSegment>> list(_conditions.begin(),
|
||||
_conditions.end());
|
||||
updateIndicesHelper(list);
|
||||
}
|
||||
|
||||
std::shared_ptr<Macro> Macro::Parent() const
|
||||
@@ -360,55 +536,57 @@ bool Macro::Save(obs_data_t *obj) const
|
||||
obs_data_set_string(obj, "name", _name.c_str());
|
||||
obs_data_set_bool(obj, "pause", _paused);
|
||||
obs_data_set_bool(obj, "parallel", _runInParallel);
|
||||
obs_data_set_bool(obj, "onChange", _matchOnChange);
|
||||
obs_data_set_bool(obj, "onChange", _performActionsOnChange);
|
||||
obs_data_set_bool(obj, "skipExecOnStart", _skipExecOnStart);
|
||||
|
||||
obs_data_set_bool(obj, "group", _isGroup);
|
||||
if (_isGroup) {
|
||||
auto groupData = obs_data_create();
|
||||
OBSDataAutoRelease groupData = obs_data_create();
|
||||
obs_data_set_bool(groupData, "collapsed", _isCollapsed);
|
||||
obs_data_set_int(groupData, "size", _groupSize);
|
||||
obs_data_set_obj(obj, "groupData", groupData);
|
||||
obs_data_release(groupData);
|
||||
return true;
|
||||
}
|
||||
|
||||
SaveDockSettings(obj);
|
||||
|
||||
SaveSplitterPos(_actionConditionSplitterPosition, obj,
|
||||
"macroActionConditionSplitterPosition");
|
||||
SaveSplitterPos(_elseActionSplitterPosition, obj,
|
||||
"macroElseActionSplitterPosition");
|
||||
|
||||
obs_data_set_bool(obj, "registerHotkeys", _registerHotkeys);
|
||||
obs_data_array_t *pauseHotkey = obs_hotkey_save(_pauseHotkey);
|
||||
OBSDataArrayAutoRelease pauseHotkey = obs_hotkey_save(_pauseHotkey);
|
||||
obs_data_set_array(obj, "pauseHotkey", pauseHotkey);
|
||||
obs_data_array_release(pauseHotkey);
|
||||
obs_data_array_t *unpauseHotkey = obs_hotkey_save(_unpauseHotkey);
|
||||
OBSDataArrayAutoRelease unpauseHotkey = obs_hotkey_save(_unpauseHotkey);
|
||||
obs_data_set_array(obj, "unpauseHotkey", unpauseHotkey);
|
||||
obs_data_array_release(unpauseHotkey);
|
||||
obs_data_array_t *togglePauseHotkey =
|
||||
OBSDataArrayAutoRelease togglePauseHotkey =
|
||||
obs_hotkey_save(_togglePauseHotkey);
|
||||
obs_data_set_array(obj, "togglePauseHotkey", togglePauseHotkey);
|
||||
obs_data_array_release(togglePauseHotkey);
|
||||
|
||||
obs_data_array_t *conditions = obs_data_array_create();
|
||||
OBSDataArrayAutoRelease conditions = obs_data_array_create();
|
||||
for (auto &c : _conditions) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
|
||||
c->Save(array_obj);
|
||||
obs_data_array_push_back(conditions, array_obj);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
OBSDataAutoRelease arrayObj = obs_data_create();
|
||||
c->Save(arrayObj);
|
||||
obs_data_array_push_back(conditions, arrayObj);
|
||||
}
|
||||
obs_data_set_array(obj, "conditions", conditions);
|
||||
obs_data_array_release(conditions);
|
||||
|
||||
obs_data_array_t *actions = obs_data_array_create();
|
||||
OBSDataArrayAutoRelease actions = obs_data_array_create();
|
||||
for (auto &a : _actions) {
|
||||
obs_data_t *array_obj = obs_data_create();
|
||||
|
||||
a->Save(array_obj);
|
||||
obs_data_array_push_back(actions, array_obj);
|
||||
|
||||
obs_data_release(array_obj);
|
||||
OBSDataAutoRelease arrayObj = obs_data_create();
|
||||
a->Save(arrayObj);
|
||||
obs_data_array_push_back(actions, arrayObj);
|
||||
}
|
||||
obs_data_set_array(obj, "actions", actions);
|
||||
obs_data_array_release(actions);
|
||||
|
||||
OBSDataArrayAutoRelease elseActions = obs_data_array_create();
|
||||
for (auto &a : _elseActions) {
|
||||
OBSDataAutoRelease arrayObj = obs_data_create();
|
||||
a->Save(arrayObj);
|
||||
obs_data_array_push_back(elseActions, arrayObj);
|
||||
}
|
||||
obs_data_set_array(obj, "elseActions", elseActions);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -452,72 +630,69 @@ bool Macro::Load(obs_data_t *obj)
|
||||
_name = obs_data_get_string(obj, "name");
|
||||
_paused = obs_data_get_bool(obj, "pause");
|
||||
_runInParallel = obs_data_get_bool(obj, "parallel");
|
||||
_matchOnChange = obs_data_get_bool(obj, "onChange");
|
||||
_performActionsOnChange = obs_data_get_bool(obj, "onChange");
|
||||
_skipExecOnStart = obs_data_get_bool(obj, "skipExecOnStart");
|
||||
|
||||
_isGroup = obs_data_get_bool(obj, "group");
|
||||
if (_isGroup) {
|
||||
auto groupData = obs_data_get_obj(obj, "groupData");
|
||||
OBSDataAutoRelease groupData =
|
||||
obs_data_get_obj(obj, "groupData");
|
||||
_isCollapsed = obs_data_get_bool(groupData, "collapsed");
|
||||
_groupSize = obs_data_get_int(groupData, "size");
|
||||
obs_data_release(groupData);
|
||||
return true;
|
||||
}
|
||||
|
||||
LoadDockSettings(obj);
|
||||
|
||||
LoadSplitterPos(_actionConditionSplitterPosition, obj,
|
||||
"macroActionConditionSplitterPosition");
|
||||
LoadSplitterPos(_elseActionSplitterPosition, obj,
|
||||
"macroElseActionSplitterPosition");
|
||||
|
||||
obs_data_set_default_bool(obj, "registerHotkeys", true);
|
||||
_registerHotkeys = obs_data_get_bool(obj, "registerHotkeys");
|
||||
if (_registerHotkeys) {
|
||||
SetupHotkeys();
|
||||
}
|
||||
obs_data_array_t *pauseHotkey = obs_data_get_array(obj, "pauseHotkey");
|
||||
OBSDataArrayAutoRelease pauseHotkey =
|
||||
obs_data_get_array(obj, "pauseHotkey");
|
||||
obs_hotkey_load(_pauseHotkey, pauseHotkey);
|
||||
obs_data_array_release(pauseHotkey);
|
||||
obs_data_array_t *unpauseHotkey =
|
||||
OBSDataArrayAutoRelease unpauseHotkey =
|
||||
obs_data_get_array(obj, "unpauseHotkey");
|
||||
obs_hotkey_load(_unpauseHotkey, unpauseHotkey);
|
||||
obs_data_array_release(unpauseHotkey);
|
||||
obs_data_array_t *togglePauseHotkey =
|
||||
OBSDataArrayAutoRelease togglePauseHotkey =
|
||||
obs_data_get_array(obj, "togglePauseHotkey");
|
||||
obs_hotkey_load(_togglePauseHotkey, togglePauseHotkey);
|
||||
obs_data_array_release(togglePauseHotkey);
|
||||
SetHotkeysDesc();
|
||||
|
||||
bool root = true;
|
||||
obs_data_array_t *conditions = obs_data_get_array(obj, "conditions");
|
||||
OBSDataArrayAutoRelease conditions =
|
||||
obs_data_get_array(obj, "conditions");
|
||||
size_t count = obs_data_array_count(conditions);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj = obs_data_array_item(conditions, i);
|
||||
|
||||
std::string id = obs_data_get_string(array_obj, "id");
|
||||
|
||||
OBSDataAutoRelease arrayObj =
|
||||
obs_data_array_item(conditions, i);
|
||||
std::string id = obs_data_get_string(arrayObj, "id");
|
||||
auto newEntry = MacroConditionFactory::Create(id, this);
|
||||
if (newEntry) {
|
||||
_conditions.emplace_back(newEntry);
|
||||
auto c = _conditions.back().get();
|
||||
c->Load(array_obj);
|
||||
c->Load(arrayObj);
|
||||
setValidLogic(c, root, _name);
|
||||
} else {
|
||||
blog(LOG_WARNING,
|
||||
"discarding condition entry with unknown id (%s) for macro %s",
|
||||
id.c_str(), _name.c_str());
|
||||
}
|
||||
|
||||
obs_data_release(array_obj);
|
||||
root = false;
|
||||
}
|
||||
obs_data_array_release(conditions);
|
||||
UpdateConditionIndices();
|
||||
|
||||
obs_data_array_t *actions = obs_data_get_array(obj, "actions");
|
||||
OBSDataArrayAutoRelease actions = obs_data_get_array(obj, "actions");
|
||||
count = obs_data_array_count(actions);
|
||||
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
obs_data_t *array_obj = obs_data_array_item(actions, i);
|
||||
|
||||
OBSDataAutoRelease array_obj = obs_data_array_item(actions, i);
|
||||
std::string id = obs_data_get_string(array_obj, "id");
|
||||
|
||||
auto newEntry = MacroActionFactory::Create(id, this);
|
||||
if (newEntry) {
|
||||
_actions.emplace_back(newEntry);
|
||||
@@ -527,11 +702,27 @@ bool Macro::Load(obs_data_t *obj)
|
||||
"discarding action entry with unknown id (%s) for macro %s",
|
||||
id.c_str(), _name.c_str());
|
||||
}
|
||||
|
||||
obs_data_release(array_obj);
|
||||
}
|
||||
obs_data_array_release(actions);
|
||||
UpdateActionIndices();
|
||||
|
||||
OBSDataArrayAutoRelease elseActions =
|
||||
obs_data_get_array(obj, "elseActions");
|
||||
count = obs_data_array_count(elseActions);
|
||||
for (size_t i = 0; i < count; i++) {
|
||||
OBSDataAutoRelease array_obj =
|
||||
obs_data_array_item(elseActions, i);
|
||||
std::string id = obs_data_get_string(array_obj, "id");
|
||||
auto newEntry = MacroActionFactory::Create(id, this);
|
||||
if (newEntry) {
|
||||
_elseActions.emplace_back(newEntry);
|
||||
_elseActions.back()->Load(array_obj);
|
||||
} else {
|
||||
blog(LOG_WARNING,
|
||||
"discarding elseAction entry with unknown id (%s) for macro %s",
|
||||
id.c_str(), _name.c_str());
|
||||
}
|
||||
}
|
||||
UpdateElseActionIndices();
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -543,6 +734,9 @@ bool Macro::PostLoad()
|
||||
for (auto &a : _actions) {
|
||||
a->PostLoad();
|
||||
}
|
||||
for (auto &a : _elseActions) {
|
||||
a->PostLoad();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -550,7 +744,12 @@ bool Macro::SwitchesScene() const
|
||||
{
|
||||
MacroActionSwitchScene temp(nullptr);
|
||||
auto sceneSwitchId = temp.GetId();
|
||||
for (auto &a : _actions) {
|
||||
for (const auto &a : _actions) {
|
||||
if (a->GetId() == sceneSwitchId) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (const auto &a : _elseActions) {
|
||||
if (a->GetId() == sceneSwitchId) {
|
||||
return true;
|
||||
}
|
||||
@@ -558,18 +757,44 @@ bool Macro::SwitchesScene() const
|
||||
return false;
|
||||
}
|
||||
|
||||
const QList<int> &Macro::GetActionConditionSplitterPosition() const
|
||||
{
|
||||
return _actionConditionSplitterPosition;
|
||||
}
|
||||
|
||||
void Macro::SetActionConditionSplitterPosition(const QList<int> sizes)
|
||||
{
|
||||
_actionConditionSplitterPosition = sizes;
|
||||
}
|
||||
|
||||
const QList<int> &Macro::GetElseActionSplitterPosition() const
|
||||
{
|
||||
return _elseActionSplitterPosition;
|
||||
}
|
||||
|
||||
void Macro::SetElseActionSplitterPosition(const QList<int> sizes)
|
||||
{
|
||||
_elseActionSplitterPosition = sizes;
|
||||
}
|
||||
|
||||
bool Macro::HasValidSplitterPositions() const
|
||||
{
|
||||
return !_actionConditionSplitterPosition.empty() &&
|
||||
!_elseActionSplitterPosition.empty();
|
||||
}
|
||||
|
||||
bool Macro::OnChangePreventedActionsRecently()
|
||||
{
|
||||
if (_onChangeTriggered) {
|
||||
_onChangeTriggered = false;
|
||||
return true;
|
||||
if (_onPreventedActionExecution) {
|
||||
_onPreventedActionExecution = false;
|
||||
return _matched ? _actions.size() > 0 : _elseActions.size() > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Macro::ResetUIHelpers()
|
||||
{
|
||||
_onChangeTriggered = false;
|
||||
_onPreventedActionExecution = false;
|
||||
for (auto c : _conditions) {
|
||||
c->Highlight();
|
||||
}
|
||||
@@ -708,7 +933,8 @@ void Macro::EnableDock(bool value)
|
||||
// Create new dock widget
|
||||
auto window =
|
||||
static_cast<QMainWindow *>(obs_frontend_get_main_window());
|
||||
_dock = new MacroDock(this, window, _runButtonText, _pauseButtonText,
|
||||
_dock = new MacroDock(GetWeakMacroByName(_name.c_str()), window,
|
||||
_runButtonText, _pauseButtonText,
|
||||
_unpauseButtonText, _conditionsTrueStatusText,
|
||||
_conditionsFalseStatusText, _dockHighlight);
|
||||
SetDockWidgetName(); // Used by OBS to restore position
|
||||
@@ -1012,7 +1238,7 @@ bool SwitcherData::CheckMacros()
|
||||
{
|
||||
bool ret = false;
|
||||
for (auto &m : macros) {
|
||||
if (m->CeckMatch()) {
|
||||
if (m->CeckMatch() || m->ElseActions().size() > 0) {
|
||||
ret = true;
|
||||
// This has to be performed here for now as actions are
|
||||
// not performed immediately after checking conditions.
|
||||
@@ -1026,7 +1252,7 @@ bool SwitcherData::CheckMacros()
|
||||
|
||||
bool SwitcherData::RunMacros()
|
||||
{
|
||||
// Create copy of macor list as elements might be removed, inserted, or
|
||||
// Create copy of macro list as elements might be removed, inserted, or
|
||||
// reordered while macros are currently being executed.
|
||||
// For example, this can happen if a macro is performing a wait action,
|
||||
// as the main lock will be unlocked during this time.
|
||||
@@ -1047,12 +1273,18 @@ bool SwitcherData::RunMacros()
|
||||
}
|
||||
|
||||
for (auto &m : runPhaseMacros) {
|
||||
if (m && m->Matched()) {
|
||||
vblog(LOG_INFO, "running macro: %s", m->Name().c_str());
|
||||
if (!m->PerformActions()) {
|
||||
blog(LOG_WARNING, "abort macro: %s",
|
||||
m->Name().c_str());
|
||||
}
|
||||
if (!m || !m->ShouldRunActions()) {
|
||||
continue;
|
||||
}
|
||||
if (firstInterval && m->SkipExecOnStart()) {
|
||||
blog(LOG_INFO,
|
||||
"skip execution of macro \"%s\" at startup",
|
||||
m->Name().c_str());
|
||||
continue;
|
||||
}
|
||||
vblog(LOG_INFO, "running macro: %s", m->Name().c_str());
|
||||
if (!m->PerformActions(m->Matched())) {
|
||||
blog(LOG_WARNING, "abort macro: %s", m->Name().c_str());
|
||||
}
|
||||
}
|
||||
if (GetLock()) {
|
||||
@@ -1088,4 +1320,11 @@ std::weak_ptr<Macro> GetWeakMacroByName(const char *name)
|
||||
return {};
|
||||
}
|
||||
|
||||
void InvalidateMacroTempVarValues()
|
||||
{
|
||||
for (auto &m : switcher->macros) {
|
||||
m->InvalidateTempVarValues();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "macro-condition.hpp"
|
||||
#include "macro-ref.hpp"
|
||||
#include "variable-string.hpp"
|
||||
#include "temp-variable.hpp"
|
||||
|
||||
#include <QString>
|
||||
#include <QByteArray>
|
||||
@@ -25,9 +26,10 @@ public:
|
||||
Macro(const std::string &name = "", const bool addHotkey = false);
|
||||
virtual ~Macro();
|
||||
bool CeckMatch();
|
||||
bool PerformActions(bool forceParallel = false,
|
||||
bool PerformActions(bool match, bool forceParallel = false,
|
||||
bool ignorePause = false);
|
||||
bool Matched() const { return _matched; }
|
||||
bool ShouldRunActions() const;
|
||||
int64_t MsSinceLastCheck() const;
|
||||
std::string Name() const { return _name; }
|
||||
void SetName(const std::string &name);
|
||||
@@ -35,8 +37,10 @@ public:
|
||||
bool RunInParallel() const { return _runInParallel; }
|
||||
void SetPaused(bool pause = true);
|
||||
bool Paused() const { return _paused; }
|
||||
void SetMatchOnChange(bool onChange) { _matchOnChange = onChange; }
|
||||
bool MatchOnChange() const { return _matchOnChange; }
|
||||
void SetMatchOnChange(bool onChange);
|
||||
bool MatchOnChange() const { return _performActionsOnChange; }
|
||||
void SetSkipExecOnStart(bool skip) { _skipExecOnStart = skip; }
|
||||
bool SkipExecOnStart() const { return _skipExecOnStart; }
|
||||
int RunCount() const { return _runCount; };
|
||||
void ResetRunCount() { _runCount = 0; };
|
||||
void ResetTimers();
|
||||
@@ -44,9 +48,18 @@ public:
|
||||
bool GetStop() const { return _stop; }
|
||||
void Stop();
|
||||
|
||||
// Temporary variable helpers
|
||||
std::vector<TempVariable> GetTempVars(MacroSegment *filter) const;
|
||||
std::optional<const TempVariable>
|
||||
GetTempVar(const MacroSegment *, const std::string &id) const;
|
||||
void InvalidateTempVarValues() const;
|
||||
|
||||
// Macro segments
|
||||
std::deque<std::shared_ptr<MacroCondition>> &Conditions();
|
||||
std::deque<std::shared_ptr<MacroAction>> &Actions();
|
||||
std::deque<std::shared_ptr<MacroAction>> &ElseActions();
|
||||
void UpdateActionIndices();
|
||||
void UpdateElseActionIndices();
|
||||
void UpdateConditionIndices();
|
||||
|
||||
// Group controls
|
||||
@@ -78,6 +91,11 @@ public:
|
||||
bool SwitchesScene() const;
|
||||
|
||||
// UI helpers
|
||||
const QList<int> &GetActionConditionSplitterPosition() const;
|
||||
void SetActionConditionSplitterPosition(const QList<int>);
|
||||
const QList<int> &GetElseActionSplitterPosition() const;
|
||||
void SetElseActionSplitterPosition(const QList<int>);
|
||||
bool HasValidSplitterPositions() const;
|
||||
bool
|
||||
ExecutedSince(const std::chrono::high_resolution_clock::time_point &);
|
||||
bool OnChangePreventedActionsRecently();
|
||||
@@ -111,9 +129,13 @@ private:
|
||||
void SetupHotkeys();
|
||||
void ClearHotkeys() const;
|
||||
void SetHotkeysDesc() const;
|
||||
void RunActions(bool &ret, bool ignorePause);
|
||||
void RunActions(bool ignorePause);
|
||||
void SetOnChangeHighlight();
|
||||
|
||||
bool RunActionsHelper(
|
||||
const std::deque<std::shared_ptr<MacroAction>> &actions,
|
||||
bool ignorePause);
|
||||
bool RunActions(bool ignorePause);
|
||||
bool RunElseActions(bool ignorePause);
|
||||
|
||||
bool DockIsVisible() const;
|
||||
void SetDockWidgetName() const;
|
||||
void SaveDockSettings(obs_data_t *obj) const;
|
||||
@@ -131,6 +153,7 @@ private:
|
||||
|
||||
std::deque<std::shared_ptr<MacroCondition>> _conditions;
|
||||
std::deque<std::shared_ptr<MacroAction>> _actions;
|
||||
std::deque<std::shared_ptr<MacroAction>> _elseActions;
|
||||
|
||||
std::weak_ptr<Macro> _parent;
|
||||
uint32_t _groupSize = 0;
|
||||
@@ -140,7 +163,9 @@ private:
|
||||
bool _runInParallel = false;
|
||||
bool _matched = false;
|
||||
bool _lastMatched = false;
|
||||
bool _matchOnChange = true;
|
||||
bool _conditionSateChanged = false;
|
||||
bool _performActionsOnChange = true;
|
||||
bool _skipExecOnStart = false;
|
||||
bool _paused = false;
|
||||
int _runCount = 0;
|
||||
bool _registerHotkeys = true;
|
||||
@@ -148,7 +173,11 @@ private:
|
||||
obs_hotkey_id _unpauseHotkey = OBS_INVALID_HOTKEY_ID;
|
||||
obs_hotkey_id _togglePauseHotkey = OBS_INVALID_HOTKEY_ID;
|
||||
|
||||
bool _onChangeTriggered = false;
|
||||
// UI helpers
|
||||
bool _onPreventedActionExecution = false;
|
||||
|
||||
QList<int> _actionConditionSplitterPosition;
|
||||
QList<int> _elseActionSplitterPosition;
|
||||
|
||||
bool _registerDock = false;
|
||||
bool _dockHasRunButton = true;
|
||||
@@ -176,5 +205,6 @@ private:
|
||||
Macro *GetMacroByName(const char *name);
|
||||
Macro *GetMacroByQString(const QString &name);
|
||||
std::weak_ptr<Macro> GetWeakMacroByName(const char *name);
|
||||
void InvalidateMacroTempVarValues();
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -27,6 +27,11 @@ if(ENABLE_OPENVR_PLUGIN)
|
||||
add_subdirectory(openvr)
|
||||
endif()
|
||||
|
||||
option(ENABLE_TWITCH_PLUGIN "Enable the twitch plugin" ON)
|
||||
if(ENABLE_TWITCH_PLUGIN)
|
||||
add_subdirectory(twitch)
|
||||
endif()
|
||||
|
||||
option(ENABLE_VIDEO_PLUGIN "Enable the video plugin" ON)
|
||||
if(ENABLE_VIDEO_PLUGIN)
|
||||
add_subdirectory(video)
|
||||
|
||||
@@ -5,7 +5,7 @@ project(advanced-scene-switcher-midi)
|
||||
|
||||
get_target_property(ADVSS_SOURCE_DIR advanced-scene-switcher-lib SOURCE_DIR)
|
||||
set(LIBREMIDI_DIR "${ADVSS_SOURCE_DIR}/deps/libremidi")
|
||||
if(NOT EXISTS "${LIBREMIDI_DIR}")
|
||||
if(NOT EXISTS "${LIBREMIDI_DIR}/CMakeLists.txt")
|
||||
message(WARNING "libremidi directory \"${LIBREMIDI_DIR}\" not found!\n"
|
||||
"MIDI support will be disabled!")
|
||||
return()
|
||||
|
||||
@@ -19,8 +19,7 @@ bool MacroConditionMidi::CheckCondition()
|
||||
|
||||
for (const auto &m : *messages) {
|
||||
if (m.Matches(_message)) {
|
||||
SetVariableValue(std::to_string(m.Note()) + " " +
|
||||
std::to_string(m.Value()));
|
||||
SetVariableValues(m);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -49,6 +48,36 @@ std::string MacroConditionMidi::GetShortDesc() const
|
||||
return _device.Name();
|
||||
}
|
||||
|
||||
void MacroConditionMidi::SetupTempVars()
|
||||
{
|
||||
MacroCondition::SetupTempVars();
|
||||
AddTempvar("type",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.midi.type"));
|
||||
AddTempvar("channel",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.midi.channel"));
|
||||
AddTempvar("note",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.midi.note"));
|
||||
AddTempvar("value1",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.midi.value1"));
|
||||
AddTempvar("value2",
|
||||
obs_module_text("AdvSceneSwitcher.tempVar.midi.value2"));
|
||||
}
|
||||
|
||||
void MacroConditionMidi::SetVariableValues(const MidiMessage &m)
|
||||
{
|
||||
SetVariableValue(std::to_string(m.Note()) + " " +
|
||||
std::to_string(m.Value()));
|
||||
SetTempVarValue("type", m.MidiTypeToString(m.Type()));
|
||||
SetTempVarValue("channel", std::to_string(m.Channel()));
|
||||
try {
|
||||
SetTempVarValue("note",
|
||||
GetAllNotes().at(m.Note()).toStdString());
|
||||
} catch (...) {
|
||||
}
|
||||
SetTempVarValue("value1", std::to_string(m.Note()));
|
||||
SetTempVarValue("value2", std::to_string(m.Value()));
|
||||
}
|
||||
|
||||
MacroConditionMidiEdit::MacroConditionMidiEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionMidi> entryData)
|
||||
: QWidget(parent),
|
||||
|
||||
@@ -24,6 +24,9 @@ public:
|
||||
MidiMessage _message;
|
||||
|
||||
private:
|
||||
void SetupTempVars();
|
||||
void SetVariableValues(const MidiMessage &);
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user