mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-29 04:36:21 -05:00
Compare commits
139 Commits
1.22.1
...
1.24.0-bet
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
666c52556e | ||
|
|
1c0734d1cb | ||
|
|
1304ac7336 | ||
|
|
884fb1b637 | ||
|
|
a82bce947f | ||
|
|
d5241f0700 | ||
|
|
f24f258c9c | ||
|
|
eddd9fa8ab | ||
|
|
6cc224aeec | ||
|
|
4b0a631987 | ||
|
|
dcae0e8e8b | ||
|
|
29f810a2a0 | ||
|
|
719dfa7b72 | ||
|
|
259aac8fcd | ||
|
|
5be2cd278f | ||
|
|
211eac5313 | ||
|
|
f92ed3139d | ||
|
|
bdff84c605 | ||
|
|
08e430396a | ||
|
|
df7fc7ec01 | ||
|
|
9eef581161 | ||
|
|
52811e44f4 | ||
|
|
7b1c56877e | ||
|
|
78d73af589 | ||
|
|
d9c1ef4c22 | ||
|
|
93f96ee660 | ||
|
|
d25a8d4efb | ||
|
|
1f22278496 | ||
|
|
70b705e0fd | ||
|
|
9e1dfdc3f0 | ||
|
|
47d6d4ac06 | ||
|
|
fe3586b6f4 | ||
|
|
650881204f | ||
|
|
8c0ba112e2 | ||
|
|
a17d8f7e09 | ||
|
|
371b4ae05d | ||
|
|
1d7ce510f7 | ||
|
|
d759ded64d | ||
|
|
0b2e1b88cc | ||
|
|
72a11eedfc | ||
|
|
1f02226620 | ||
|
|
ad8c29997c | ||
|
|
2c7c40c3f0 | ||
|
|
c9c0e4db2e | ||
|
|
dd880b13c0 | ||
|
|
76c759c8f4 | ||
|
|
284c8020b2 | ||
|
|
f506600b8c | ||
|
|
339418b5f3 | ||
|
|
2eca2cc2e9 | ||
|
|
4315d309f2 | ||
|
|
8d18bb363a | ||
|
|
592f31f059 | ||
|
|
300ad15ad0 | ||
|
|
91f93169eb | ||
|
|
5d95069291 | ||
|
|
e5bb9162ef | ||
|
|
6869cc8a01 | ||
|
|
55c7ac8a32 | ||
|
|
101a85b063 | ||
|
|
e7c6afbc6a | ||
|
|
18e19fb6c8 | ||
|
|
a7ccfc3282 | ||
|
|
85eb2a4235 | ||
|
|
3e3805b542 | ||
|
|
c59acd836a | ||
|
|
1e81181312 | ||
|
|
8a796efdb3 | ||
|
|
1a07a93552 | ||
|
|
bd74629420 | ||
|
|
dabb293cc0 | ||
|
|
b6031bd29a | ||
|
|
05fa3af2ac | ||
|
|
c52166bfec | ||
|
|
6d3964fa5d | ||
|
|
65545d85ba | ||
|
|
dea4ff47cd | ||
|
|
258a5f6ab7 | ||
|
|
2048ca2816 | ||
|
|
eb9e2e8062 | ||
|
|
3229bf0150 | ||
|
|
dfa12f9807 |
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
|
||||
114
.github/scripts/Build-Windows.ps1
vendored
114
.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,112 +61,13 @@ 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=Release"
|
||||
"-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', "Release"
|
||||
)
|
||||
|
||||
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=Release"
|
||||
"-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', "Release"
|
||||
)
|
||||
|
||||
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})" `
|
||||
@@ -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
|
||||
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*
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -19,3 +19,6 @@
|
||||
[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
|
||||
|
||||
@@ -125,6 +125,8 @@ target_sources(
|
||||
src/macro-core/macro-action-run.hpp
|
||||
src/macro-core/macro-action-scene-collection.cpp
|
||||
src/macro-core/macro-action-scene-collection.hpp
|
||||
src/macro-core/macro-action-scene-lock.cpp
|
||||
src/macro-core/macro-action-scene-lock.hpp
|
||||
src/macro-core/macro-action-scene-order.cpp
|
||||
src/macro-core/macro-action-scene-order.hpp
|
||||
src/macro-core/macro-action-scene-switch.cpp
|
||||
@@ -201,6 +203,8 @@ target_sources(
|
||||
src/macro-core/macro-condition-scene-transform.hpp
|
||||
src/macro-core/macro-condition-scene-visibility.cpp
|
||||
src/macro-core/macro-condition-scene-visibility.hpp
|
||||
src/macro-core/macro-condition-slideshow.cpp
|
||||
src/macro-core/macro-condition-slideshow.hpp
|
||||
src/macro-core/macro-condition-scene.cpp
|
||||
src/macro-core/macro-condition-scene.hpp
|
||||
src/macro-core/macro-condition-source.cpp
|
||||
@@ -250,21 +254,32 @@ 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
|
||||
src/utils/file-selection.cpp
|
||||
src/utils/file-selection.hpp
|
||||
src/utils/filter-combo-box.cpp
|
||||
src/utils/filter-combo-box.hpp
|
||||
src/utils/filter-selection.cpp
|
||||
src/utils/filter-selection.hpp
|
||||
src/utils/macro-export-import-dialog.cpp
|
||||
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
|
||||
src/utils/math-helpers.hpp
|
||||
src/utils/mouse-wheel-guard.cpp
|
||||
src/utils/mouse-wheel-guard.hpp
|
||||
src/utils/name-dialog.cpp
|
||||
src/utils/name-dialog.hpp
|
||||
src/utils/non-modal-dialog.cpp
|
||||
src/utils/non-modal-dialog.hpp
|
||||
src/utils/obs-dock.hpp
|
||||
src/utils/obs-module-helper.cpp
|
||||
src/utils/obs-module-helper.hpp
|
||||
@@ -296,6 +311,8 @@ target_sources(
|
||||
src/utils/string-list.hpp
|
||||
src/utils/striped-frame.cpp
|
||||
src/utils/striped-frame.hpp
|
||||
src/utils/switch-button.cpp
|
||||
src/utils/switch-button.hpp
|
||||
src/utils/sync-helper.cpp
|
||||
src/utils/sync-helper.hpp
|
||||
src/utils/transition-selection.cpp
|
||||
@@ -361,6 +378,8 @@ target_include_directories(
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/obs-websocket/lib"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/deps/exprtk")
|
||||
|
||||
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"
|
||||
@@ -395,9 +392,9 @@ AdvSceneSwitcher.condition.variable.type.greaterThanVariable="ist größer als d
|
||||
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"
|
||||
@@ -438,20 +435,15 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.streaming="Stream"
|
||||
AdvSceneSwitcher.action.streaming.type.stop="Stream stoppen"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Stream starten"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||
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"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Umschalten"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Quelle"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Beliebig"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="Auf{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="Auf{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.filter="Filter"
|
||||
AdvSceneSwitcher.action.filter.type.enable="Aktivieren"
|
||||
AdvSceneSwitcher.action.filter.type.disable="Deaktivieren"
|
||||
@@ -466,7 +458,7 @@ AdvSceneSwitcher.action.source.type.refreshSettings="Aktualisieren der Quellenei
|
||||
AdvSceneSwitcher.action.source.type.pressSettingsButton="Drücken der Einstellungstaste"
|
||||
AdvSceneSwitcher.action.source.type.refreshSettings.tooltip="Kann verwendet werden, um Browser-, Medien- usw. Quellen zu aktualisieren"
|
||||
AdvSceneSwitcher.action.source.noSettingsButtons="Keine Buttons gefunden!"
|
||||
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}"
|
||||
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}{{deinterlaceMode}}{{deinterlaceOrder}}"
|
||||
AdvSceneSwitcher.action.source.warning="Warnung: Das globale Aktivieren und Deaktivieren von Quellen kann nicht über die OBS-Benutzeroberfläche gesteuert werden"
|
||||
AdvSceneSwitcher.action.source.getSettings="Aktuelle Einstellungen abfragen"
|
||||
AdvSceneSwitcher.action.media="Medien"
|
||||
@@ -484,7 +476,7 @@ AdvSceneSwitcher.action.macro.type.unpause="Nicht mehr pausieren"
|
||||
AdvSceneSwitcher.action.macro.type.resetCounter="Zähler zurücksetzen"
|
||||
AdvSceneSwitcher.action.macro.type.run="Aktionen ausführen"
|
||||
AdvSceneSwitcher.action.macro.type.stop="Aktionen stoppen"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}"
|
||||
AdvSceneSwitcher.action.pluginState="Plugin-Status"
|
||||
AdvSceneSwitcher.action.pluginState.type.stop="Erweiterten Automatischen Szenenwechsler stoppen"
|
||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Ändern des Nichtübereinstimmungsverhaltens:"
|
||||
@@ -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"
|
||||
@@ -516,7 +507,7 @@ AdvSceneSwitcher.action.sceneOrder.type.movePosition="An Position verschieben"
|
||||
AdvSceneSwitcher.action.sceneOrder.entry="Auf{{scenes}}{{actions}}{{sources}}{{position}}"
|
||||
AdvSceneSwitcher.action.sceneTransform="Szenenelement transformieren"
|
||||
AdvSceneSwitcher.action.sceneTransform.getTransform="Transformation erhalten"
|
||||
AdvSceneSwitcher.action.sceneTransform.entry="Auf{{scenes}}transformieren{{sources}}"
|
||||
AdvSceneSwitcher.action.sceneTransform.entry="Auf{{scenes}}{{action}}{{rotation}}{{sources}}"
|
||||
AdvSceneSwitcher.action.file="Datei"
|
||||
AdvSceneSwitcher.action.file.type.write="Schreiben"
|
||||
AdvSceneSwitcher.action.file.type.append="Anhängen"
|
||||
@@ -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}}"
|
||||
|
||||
|
||||
; Transition Tab
|
||||
@@ -646,7 +635,7 @@ AdvSceneSwitcher.mediaTab.states.none="Keine Auswahl"
|
||||
AdvSceneSwitcher.mediaTab.states.playing="Abspielen"
|
||||
AdvSceneSwitcher.mediaTab.states.opening="Öffnen"
|
||||
AdvSceneSwitcher.mediaTab.states.buffering="Buffern"
|
||||
AdvSceneSwitcher.mediaTab.states.Paused="Pausiert"
|
||||
AdvSceneSwitcher.mediaTab.states.paused="Pausiert"
|
||||
AdvSceneSwitcher.mediaTab.states.stopped="Gestoppt"
|
||||
AdvSceneSwitcher.mediaTab.states.ended="Beendet"
|
||||
AdvSceneSwitcher.mediaTab.states.error="Fehler"
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -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"
|
||||
@@ -324,8 +322,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"
|
||||
@@ -360,18 +358,14 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.streaming="Transmisión"
|
||||
AdvSceneSwitcher.action.streaming.type.stop="Detener transmisión"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Iniciar transmisión"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||
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"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Fuente"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Cualquiera"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="En{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="En{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.filter="Filtro"
|
||||
AdvSceneSwitcher.action.filter.type.enable="Habilitar"
|
||||
AdvSceneSwitcher.action.filter.type.disable="Deshabilitar"
|
||||
@@ -382,7 +376,7 @@ AdvSceneSwitcher.action.source="Fuente"
|
||||
AdvSceneSwitcher.action.source.type.enable="Habilitar"
|
||||
AdvSceneSwitcher.action.source.type.disable="Deshabilitar"
|
||||
AdvSceneSwitcher.action.source.type.settings="Establecer configuración"
|
||||
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}"
|
||||
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}{{deinterlaceMode}}{{deinterlaceOrder}}"
|
||||
AdvSceneSwitcher.action.source.warning="Advertencia: la IU de OBS no puede controlar la habilitación y deshabilitación global de fuentes"
|
||||
AdvSceneSwitcher.action.source.getSettings="Obtener la configuración actual"
|
||||
AdvSceneSwitcher.action.media="Medios"
|
||||
@@ -400,7 +394,7 @@ AdvSceneSwitcher.action.macro.type.unpause="Reanudar"
|
||||
AdvSceneSwitcher.action.macro.type.resetCounter="Reiniciar contador"
|
||||
AdvSceneSwitcher.action.macro.type.run="Ejecutar"
|
||||
AdvSceneSwitcher.action.macro.type.stop="Detener"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}"
|
||||
AdvSceneSwitcher.action.pluginState="Estado del complemento"
|
||||
AdvSceneSwitcher.action.pluginState.type.stop="Detener el complemento Advanced Scene Switcher"
|
||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Cambiar el comportamiento de no coincidencia:"
|
||||
@@ -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"
|
||||
@@ -432,7 +425,7 @@ AdvSceneSwitcher.action.sceneOrder.type.movePosition="Mover a la posición"
|
||||
AdvSceneSwitcher.action.sceneOrder.entry="En{{scenes}}{{actions}}{{sources}}{{position}}"
|
||||
AdvSceneSwitcher.action.sceneTransform="Transformar elemento de escena"
|
||||
AdvSceneSwitcher.action.sceneTransform.getTransform="Obtener transformación"
|
||||
AdvSceneSwitcher.action.sceneTransform.entry="En{{scenes}}transformar{{sources}}"
|
||||
AdvSceneSwitcher.action.sceneTransform.entry="En{{scenes}}{{action}}{{rotation}}{{sources}}"
|
||||
AdvSceneSwitcher.action.file="Archivo"
|
||||
AdvSceneSwitcher.action.file.type.write="Escribir"
|
||||
AdvSceneSwitcher.action.file.type.append="Agregar"
|
||||
@@ -531,7 +524,7 @@ AdvSceneSwitcher.mediaTab.states.none="Ninguno"
|
||||
AdvSceneSwitcher.mediaTab.states.playing="Reproduciéndose"
|
||||
AdvSceneSwitcher.mediaTab.states.opening="Abriendo"
|
||||
AdvSceneSwitcher.mediaTab.states.buffering="Almacenando en búfer"
|
||||
AdvSceneSwitcher.mediaTab.states.Paused="Pausado"
|
||||
AdvSceneSwitcher.mediaTab.states.paused="Pausado"
|
||||
AdvSceneSwitcher.mediaTab.states.stopped="Detenido"
|
||||
AdvSceneSwitcher.mediaTab.states.ended="Finalizado"
|
||||
AdvSceneSwitcher.mediaTab.states.error="Error"
|
||||
|
||||
1209
data/locale/fr-FR.ini
Normal file
1209
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="случайный"
|
||||
@@ -144,7 +143,7 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.streaming="Потоковое вещание"
|
||||
AdvSceneSwitcher.action.streaming.type.stop="Остановить потоковое вещание"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Начать потоковое вещание"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}"
|
||||
AdvSceneSwitcher.action.run="Запустить"
|
||||
|
||||
|
||||
@@ -205,7 +204,7 @@ AdvSceneSwitcher.mediaTab.states.none="Нет"
|
||||
AdvSceneSwitcher.mediaTab.states.playing="Играет"
|
||||
AdvSceneSwitcher.mediaTab.states.opening="Открытие"
|
||||
AdvSceneSwitcher.mediaTab.states.buffering="Буферизация"
|
||||
AdvSceneSwitcher.mediaTab.states.Paused="Приостановлено"
|
||||
AdvSceneSwitcher.mediaTab.states.paused="Приостановлено"
|
||||
AdvSceneSwitcher.mediaTab.states.stopped="Остановлено"
|
||||
AdvSceneSwitcher.mediaTab.states.ended="Закончилось"
|
||||
AdvSceneSwitcher.mediaTab.states.error="Ошибка"
|
||||
|
||||
@@ -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ı "
|
||||
@@ -261,8 +259,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"
|
||||
@@ -290,18 +288,14 @@ AdvSceneSwitcher.action.replay.entry="{{actions}}"
|
||||
AdvSceneSwitcher.action.streaming="Yayın"
|
||||
AdvSceneSwitcher.action.streaming.type.stop="Yayın durdur"
|
||||
AdvSceneSwitcher.action.streaming.type.start="Yayın başlat"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||
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"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Kayıt"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Herhangi"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="Açık{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="Açık{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.filter="Filtrele"
|
||||
AdvSceneSwitcher.action.filter.type.enable="Etkin"
|
||||
AdvSceneSwitcher.action.filter.type.disable="Etkisiz"
|
||||
@@ -312,7 +306,7 @@ AdvSceneSwitcher.action.source="Kaynak"
|
||||
AdvSceneSwitcher.action.source.type.enable="Etkin"
|
||||
AdvSceneSwitcher.action.source.type.disable="Etkisiz"
|
||||
AdvSceneSwitcher.action.source.type.settings="Ayarları yap"
|
||||
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}"
|
||||
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}{{deinterlaceMode}}{{deinterlaceOrder}}"
|
||||
AdvSceneSwitcher.action.source.warning="Uyarı: Kaynakların global olarak etkinleştirilmesi ve devre dışı bırakılması, OBS UI tarafından kontrol edilemez"
|
||||
AdvSceneSwitcher.action.source.getSettings="Mevcut Ayarları yap"
|
||||
AdvSceneSwitcher.action.media="Medya"
|
||||
@@ -328,7 +322,7 @@ AdvSceneSwitcher.action.macro.type.pause="Duraklat"
|
||||
AdvSceneSwitcher.action.macro.type.unpause="Duraklatma"
|
||||
AdvSceneSwitcher.action.macro.type.resetCounter="Sayacı sıfırla"
|
||||
AdvSceneSwitcher.action.macro.type.run="Çalıştır"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}"
|
||||
AdvSceneSwitcher.action.pluginState="Eklenti durumu"
|
||||
AdvSceneSwitcher.action.pluginState.type.stop="Advanced Scene Switcher eklentisini durdurun"
|
||||
AdvSceneSwitcher.action.pluginState.type.noMatch="Eşleşmeme davranışını değiştirin:"
|
||||
@@ -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"
|
||||
@@ -360,7 +353,7 @@ AdvSceneSwitcher.action.sceneOrder.type.movePosition="Konuma taşı"
|
||||
AdvSceneSwitcher.action.sceneOrder.entry="Açık{{scenes}}{{actions}}{{sources}}{{position}}"
|
||||
AdvSceneSwitcher.action.sceneTransform="Sahne öğesi dönüşümü"
|
||||
AdvSceneSwitcher.action.sceneTransform.getTransform="Dönüşümü al"
|
||||
AdvSceneSwitcher.action.sceneTransform.entry="Açık{{scenes}}transform{{sources}}"
|
||||
AdvSceneSwitcher.action.sceneTransform.entry="Açık{{scenes}}{{action}}{{rotation}}{{sources}}"
|
||||
AdvSceneSwitcher.action.file="Dosya"
|
||||
AdvSceneSwitcher.action.file.type.write="Yaz"
|
||||
AdvSceneSwitcher.action.file.type.append="Ekle"
|
||||
@@ -442,7 +435,7 @@ AdvSceneSwitcher.mediaTab.states.none="Yok"
|
||||
AdvSceneSwitcher.mediaTab.states.playing="Oynamak"
|
||||
AdvSceneSwitcher.mediaTab.states.opening="Açmak"
|
||||
AdvSceneSwitcher.mediaTab.states.buffering="Arabelleğe alma"
|
||||
AdvSceneSwitcher.mediaTab.states.Paused="Duraklatıldı"
|
||||
AdvSceneSwitcher.mediaTab.states.paused="Duraklatıldı"
|
||||
AdvSceneSwitcher.mediaTab.states.stopped="Durduruldu"
|
||||
AdvSceneSwitcher.mediaTab.states.ended="Bitti"
|
||||
AdvSceneSwitcher.mediaTab.states.error="Hata"
|
||||
|
||||
@@ -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="任何媒体源"
|
||||
@@ -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="固定数值"
|
||||
@@ -494,7 +494,7 @@ AdvSceneSwitcher.action.streaming="推流"
|
||||
AdvSceneSwitcher.action.streaming.type.stop="停止推流"
|
||||
AdvSceneSwitcher.action.streaming.type.start="开始推流"
|
||||
AdvSceneSwitcher.action.streaming.type.keyFrameInterval="设置关键帧间隔"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}"
|
||||
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}"
|
||||
AdvSceneSwitcher.action.run="运行"
|
||||
AdvSceneSwitcher.action.sceneVisibility="场景项目可见性"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.show="显示"
|
||||
@@ -502,7 +502,7 @@ AdvSceneSwitcher.action.sceneVisibility.type.hide="隐藏"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.toggle="切换"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.source="来源"
|
||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="全部"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="置{{scenes}}{{actions}}{{sourceTypes}}{{sources}}{{sourceGroups}}"
|
||||
AdvSceneSwitcher.action.sceneVisibility.entry="置{{scenes}}{{actions}}{{sources}}"
|
||||
AdvSceneSwitcher.action.filter="滤镜"
|
||||
AdvSceneSwitcher.action.filter.type.enable="开启"
|
||||
AdvSceneSwitcher.action.filter.type.disable="关闭"
|
||||
@@ -517,7 +517,7 @@ AdvSceneSwitcher.action.source.type.refreshSettings="刷新源设置"
|
||||
AdvSceneSwitcher.action.source.type.pressSettingsButton="按下设置按钮"
|
||||
AdvSceneSwitcher.action.source.type.refreshSettings.tooltip="可用于刷新浏览器、媒体、源、etc"
|
||||
AdvSceneSwitcher.action.source.noSettingsButtons="未找到按钮!"
|
||||
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}"
|
||||
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}{{deinterlaceMode}}{{deinterlaceOrder}}"
|
||||
AdvSceneSwitcher.action.source.warning="警告:OBS UI无法控制全局启用和禁用源,注意,通过这个设置禁用,我测试,你必须通过这个在启用才行,不然点击小眼睛你无法显示!"
|
||||
AdvSceneSwitcher.action.source.getSettings="获取当前设置"
|
||||
AdvSceneSwitcher.action.media="媒体"
|
||||
@@ -535,7 +535,7 @@ AdvSceneSwitcher.action.macro.type.unpause="取消暂停"
|
||||
AdvSceneSwitcher.action.macro.type.resetCounter="复位计数器"
|
||||
AdvSceneSwitcher.action.macro.type.run="运行操作"
|
||||
AdvSceneSwitcher.action.macro.type.stop="停止操作"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}} {{macros}}"
|
||||
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}"
|
||||
AdvSceneSwitcher.action.pluginState="插件状态"
|
||||
AdvSceneSwitcher.action.pluginState.type.stop="停止高级场景切换插件"
|
||||
AdvSceneSwitcher.action.pluginState.type.noMatch="没有匹配项时:"
|
||||
@@ -559,7 +559,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="下移"
|
||||
@@ -569,7 +568,7 @@ AdvSceneSwitcher.action.sceneOrder.type.movePosition="移动到数值位置"
|
||||
AdvSceneSwitcher.action.sceneOrder.entry="在 {{scenes}} {{actions}} {{sources}} {{position}}"
|
||||
AdvSceneSwitcher.action.sceneTransform="场景项目转换"
|
||||
AdvSceneSwitcher.action.sceneTransform.getTransform="获得转换"
|
||||
AdvSceneSwitcher.action.sceneTransform.entry="在 {{scenes}} 上转换 {{sources}}"
|
||||
AdvSceneSwitcher.action.sceneTransform.entry="在 {{scenes}}{{action}}{{rotation}}{{sources}}"
|
||||
AdvSceneSwitcher.action.file="文件"
|
||||
AdvSceneSwitcher.action.file.type.write="写入"
|
||||
AdvSceneSwitcher.action.file.type.append="追加写入"
|
||||
@@ -624,8 +623,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 +652,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}}"
|
||||
AdvSceneSwitcher.action.variable.entry.substringIndex="子字符串开始:{{subStringStart}} 子字符串大小:{{subStringSize}}"
|
||||
AdvSceneSwitcher.action.variable.entry.substringRegex="使用正则表达式为 {{regexMatchIdx}} 匹配的值:"
|
||||
AdvSceneSwitcher.action.variable.entry.findAndReplace="{{findStr}}{{replaceStr}}"
|
||||
@@ -732,7 +729,7 @@ AdvSceneSwitcher.mediaTab.states.none="无"
|
||||
AdvSceneSwitcher.mediaTab.states.playing="播放中"
|
||||
AdvSceneSwitcher.mediaTab.states.opening="打开中"
|
||||
AdvSceneSwitcher.mediaTab.states.buffering="缓冲中"
|
||||
AdvSceneSwitcher.mediaTab.states.Paused="暂停"
|
||||
AdvSceneSwitcher.mediaTab.states.paused="暂停"
|
||||
AdvSceneSwitcher.mediaTab.states.stopped="停止"
|
||||
AdvSceneSwitcher.mediaTab.states.ended="结束"
|
||||
AdvSceneSwitcher.mediaTab.states.error="错误"
|
||||
|
||||
9
data/res/images/DarkDoubleDown.svg
Normal file
9
data/res/images/DarkDoubleDown.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<path d="m1,2c0,-0.27 0.11,-0.52 0.29,-0.71c0.39,-0.39 1.03,-0.39 1.42,0l5.29,5.3l5.29,-5.3c0.39,-0.39 1.03,-0.39 1.42,0c0.18,0.19 0.29,0.44 0.29,0.71s-0.11,0.52 -0.29,0.71l-6,6c-0.39,0.39 -1.03,0.39 -1.42,0l-6,-6c-0.18,-0.19 -0.29,-0.44 -0.29,-0.71zm0,0" fill="#fefefe" id="svg_1" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||
<path d="m1,8c0,-0.27 0.09,-0.52 0.28,-0.71c0.38,-0.39 1.03,-0.39 1.41,0l5.31,5.3l5.28,-5.3c0.38,-0.39 1.03,-0.39 1.41,0c0.19,0.19 0.31,0.44 0.31,0.71s-0.13,0.52 -0.31,0.71l-6,6c-0.38,0.39 -1.03,0.39 -1.41,0l-6,-6c-0.19,-0.19 -0.28,-0.44 -0.28,-0.71zm0,0" fill="#fefefe" id="svg_2"/>
|
||||
</g>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 791 B |
9
data/res/images/DarkDoubleUp.svg
Normal file
9
data/res/images/DarkDoubleUp.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
|
||||
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<path d="m1,8c0,-0.27 0.11,-0.52 0.29,-0.71l6,-6c0.39,-0.39 1.03,-0.39 1.42,0l6,6c0.18,0.19 0.29,0.44 0.29,0.71s-0.11,0.52 -0.29,0.71c-0.39,0.39 -1.03,0.39 -1.42,0l-5.29,-5.3l-5.29,5.3c-0.39,0.39 -1.03,0.39 -1.42,0c-0.18,-0.19 -0.29,-0.44 -0.29,-0.71zm0,0" fill="#fefefe" id="svg_1"/>
|
||||
<path d="m1,14c0,-0.27 0.11,-0.52 0.28,-0.71l6,-6c0.39,-0.39 1.03,-0.39 1.42,0l6,6c0.19,0.19 0.3,0.44 0.3,0.71s-0.11,0.52 -0.3,0.71c-0.39,0.39 -1.03,0.39 -1.42,0l-5.28,-5.3l-5.3,5.3c-0.39,0.39 -1.03,0.39 -1.42,0c-0.17,-0.19 -0.28,-0.44 -0.28,-0.71zm0,0" fill="#fefefe" id="svg_2"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 753 B |
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 |
9
data/res/images/LightDoubleDown.svg
Normal file
9
data/res/images/LightDoubleDown.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<path d="m1,2c0,-0.27 0.11,-0.52 0.29,-0.71c0.39,-0.39 1.03,-0.39 1.42,0l5.29,5.3l5.29,-5.3c0.39,-0.39 1.03,-0.39 1.42,0c0.18,0.19 0.29,0.44 0.29,0.71s-0.11,0.52 -0.29,0.71l-6,6c-0.39,0.39 -1.03,0.39 -1.42,0l-6,-6c-0.18,-0.19 -0.29,-0.44 -0.29,-0.71zm0,0" fill="#202020" id="svg_1"/>
|
||||
<path d="m1,8c0,-0.27 0.11,-0.52 0.29,-0.71c0.39,-0.39 1.03,-0.39 1.42,0l5.29,5.3l5.29,-5.3c0.39,-0.39 1.03,-0.39 1.42,0c0.18,0.19 0.29,0.44 0.29,0.71s-0.11,0.52 -0.29,0.71l-6,6c-0.39,0.39 -1.03,0.39 -1.42,0l-6,-6c-0.18,-0.19 -0.29,-0.44 -0.29,-0.71zm0,0" fill="#202020" id="svg_4" transform="matrix(1, 0, 0, 1, 0, 0)"/>
|
||||
</g>
|
||||
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 791 B |
9
data/res/images/LightDoubleUp.svg
Normal file
9
data/res/images/LightDoubleUp.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0"?>
|
||||
<svg width="16" height="16" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg">
|
||||
|
||||
<g class="layer">
|
||||
<title>Layer 1</title>
|
||||
<path d="m1,8c0,-0.27 0.11,-0.52 0.29,-0.71l6,-6c0.39,-0.39 1.03,-0.39 1.42,0l6,6c0.18,0.19 0.29,0.44 0.29,0.71s-0.11,0.52 -0.29,0.71c-0.39,0.39 -1.03,0.39 -1.42,0l-5.29,-5.3l-5.29,5.3c-0.39,0.39 -1.03,0.39 -1.42,0c-0.18,-0.19 -0.29,-0.44 -0.29,-0.71zm0,0" fill="#202020" id="svg_1"/>
|
||||
<path d="m1,14c0,-0.27 0.11,-0.52 0.29,-0.71l6,-6c0.39,-0.39 1.03,-0.39 1.42,0l6,6c0.18,0.19 0.29,0.44 0.29,0.71s-0.11,0.52 -0.29,0.71c-0.39,0.39 -1.03,0.39 -1.42,0l-5.29,-5.3l-5.29,5.3c-0.39,0.39 -1.03,0.39 -1.42,0c-0.18,-0.19 -0.29,-0.44 -0.29,-0.71zm0,0" fill="#202020" id="svg_2"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 757 B |
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 |
1
deps/cpp-httplib
vendored
Submodule
1
deps/cpp-httplib
vendored
Submodule
Submodule deps/cpp-httplib added at c7ed1796a7
@@ -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">
|
||||
@@ -988,6 +1022,19 @@
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="conditionTop">
|
||||
<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="conditionUp">
|
||||
<property name="maximumSize">
|
||||
@@ -1023,6 +1070,19 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="conditionBottom">
|
||||
<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_15">
|
||||
<property name="orientation">
|
||||
@@ -1040,144 +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="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>
|
||||
<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>
|
||||
@@ -4567,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;
|
||||
@@ -123,6 +122,10 @@ static void AskForBackup(obs_data_t *obj);
|
||||
|
||||
static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
||||
{
|
||||
if (!switcher) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (saving) {
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
switcher->Prune();
|
||||
@@ -324,12 +327,14 @@ void SwitcherData::SetPreconditions()
|
||||
lastCursorPos = GetCursorPos();
|
||||
}
|
||||
|
||||
void ClearWebsocketMessages();
|
||||
|
||||
void SwitcherData::ResetForNextInterval()
|
||||
{
|
||||
// Core reset functions
|
||||
ClearWebsocketMessages();
|
||||
// Plugin reset functions
|
||||
for (const auto &func : resetForNextIntervalFuncs) {
|
||||
for (const auto &func : resetIntervalSteps) {
|
||||
func();
|
||||
}
|
||||
}
|
||||
@@ -439,6 +444,8 @@ void SwitcherData::Start()
|
||||
}
|
||||
}
|
||||
|
||||
bool CloseAllInputDialogs();
|
||||
|
||||
void SwitcherData::Stop()
|
||||
{
|
||||
if (th && th->isRunning()) {
|
||||
@@ -447,10 +454,23 @@ void SwitcherData::Stop()
|
||||
abortMacroWait = true;
|
||||
macroWaitCv.notify_all();
|
||||
macroTransitionCv.notify_all();
|
||||
th->wait();
|
||||
delete th;
|
||||
th = nullptr;
|
||||
|
||||
// Not waiting if a dialog was closed is a workaround to avoid
|
||||
// deadlocks when a variable input dialog is opened while Stop()
|
||||
// is called.
|
||||
//
|
||||
// The QEventLoop handling the dialog would not exit until Stop()
|
||||
// would return, which itself would wait for the switcher thread
|
||||
// to complete, which itself is blocked by the variable input
|
||||
// dialog.
|
||||
//
|
||||
// Must be reworked in the future, as this will not go well when
|
||||
// OBS is shutting down and a dialog is still opened.
|
||||
if (!CloseAllInputDialogs()) {
|
||||
th->wait();
|
||||
delete th;
|
||||
th = nullptr;
|
||||
}
|
||||
writeToStatusFile("Advanced Scene Switcher stopped");
|
||||
}
|
||||
|
||||
@@ -599,7 +619,7 @@ static void setStreamStopping()
|
||||
std::chrono::high_resolution_clock::now();
|
||||
}
|
||||
|
||||
static void handleExit()
|
||||
static void handleShutdown()
|
||||
{
|
||||
if (!switcher) {
|
||||
return;
|
||||
@@ -609,8 +629,14 @@ static void handleExit()
|
||||
switcher->Stop();
|
||||
switcher->CheckMacros();
|
||||
switcher->RunMacros();
|
||||
|
||||
// Unfortunately this will not work as OBS will now allow saving
|
||||
// the scene collection data at this point, So any OBS specific
|
||||
// changes done during shutdown will be lost
|
||||
//
|
||||
// TODO: Look for a way to possibly resolve this
|
||||
obs_frontend_save();
|
||||
}
|
||||
FreeSceneSwitcher();
|
||||
}
|
||||
|
||||
static void handleSceneCollectionChanging()
|
||||
@@ -634,8 +660,12 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case OBS_FRONTEND_EVENT_EXIT:
|
||||
handleExit();
|
||||
case OBS_FRONTEND_EVENT_SCRIPTING_SHUTDOWN:
|
||||
// Note: We are intentionally not listening for
|
||||
// OBS_FRONTEND_EVENT_EXIT here as at that point all scene
|
||||
// collection data will already have been cleared and thus all
|
||||
// macros will have already been cleared
|
||||
handleShutdown();
|
||||
break;
|
||||
case OBS_FRONTEND_EVENT_SCENE_CHANGED:
|
||||
handleSceneChange();
|
||||
@@ -673,6 +703,9 @@ static void OBSEvent(enum obs_frontend_event event, void *switcher)
|
||||
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CHANGING:
|
||||
handleSceneCollectionChanging();
|
||||
break;
|
||||
case OBS_FRONTEND_EVENT_SCENE_COLLECTION_CLEANUP:
|
||||
SaveSceneSwitcher(nullptr, false, nullptr);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -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,39 +101,64 @@ 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();
|
||||
void on_conditionRemove_clicked();
|
||||
void on_conditionTop_clicked();
|
||||
void on_conditionUp_clicked();
|
||||
void on_conditionDown_clicked();
|
||||
void on_conditionBottom_clicked();
|
||||
void on_actionAdd_clicked();
|
||||
void on_actionRemove_clicked();
|
||||
void on_actionTop_clicked();
|
||||
void on_actionUp_clicked();
|
||||
void on_actionDown_clicked();
|
||||
void MacroSelectionChanged(const QItemSelection &,
|
||||
const QItemSelection &);
|
||||
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);
|
||||
@@ -151,6 +180,7 @@ signals:
|
||||
void MacroSegmentOrderChanged();
|
||||
void HighlightMacrosChanged(bool value);
|
||||
void HighlightActionsChanged(bool value);
|
||||
void HighlightElseActionsChanged(bool value);
|
||||
void HighlightConditionsChanged(bool value);
|
||||
|
||||
void ConnectionAdded(const QString &);
|
||||
@@ -161,18 +191,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) {
|
||||
@@ -494,6 +504,11 @@ void SwitcherData::LoadSettings(obs_data_t *obj)
|
||||
loadSceneGroups(obj);
|
||||
LoadVariables(obj);
|
||||
LoadConnections(obj);
|
||||
|
||||
for (const auto &func : loadSteps) {
|
||||
func(obj);
|
||||
}
|
||||
|
||||
LoadMacros(obj);
|
||||
loadWindowTitleSwitches(obj);
|
||||
loadScreenRegionSwitches(obj);
|
||||
@@ -516,6 +531,7 @@ void SwitcherData::LoadSettings(obs_data_t *obj)
|
||||
|
||||
// Reset on startup and scene collection change
|
||||
switcher->lastOpenedTab = -1;
|
||||
startupLoadDone = true;
|
||||
}
|
||||
|
||||
void SwitcherData::SaveSettings(obs_data_t *obj)
|
||||
@@ -547,6 +563,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)
|
||||
@@ -574,6 +594,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);
|
||||
|
||||
@@ -622,6 +644,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);
|
||||
@@ -651,34 +675,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]);
|
||||
@@ -706,9 +702,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");
|
||||
}
|
||||
|
||||
@@ -762,9 +756,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");
|
||||
}
|
||||
|
||||
@@ -996,6 +989,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);
|
||||
|
||||
|
||||
@@ -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 {};
|
||||
|
||||
@@ -437,12 +437,6 @@ void MacroActionAudioEdit::SetWidgetVisibility()
|
||||
_balance->setVisible(_entryData->_action ==
|
||||
MacroActionAudio::Action::BALANCE);
|
||||
|
||||
_fadeTypes->setDisabled(!_entryData->_fade);
|
||||
_wait->setDisabled(!_entryData->_fade);
|
||||
_abortActiveFade->setDisabled(!_entryData->_fade);
|
||||
_duration->setDisabled(!_entryData->_fade);
|
||||
_rate->setDisabled(!_entryData->_fade);
|
||||
|
||||
_fadeTypeLayout->removeWidget(_fade);
|
||||
_fadeTypeLayout->removeWidget(_fadeTypes);
|
||||
_fadeTypeLayout->removeWidget(_duration);
|
||||
@@ -474,6 +468,12 @@ void MacroActionAudioEdit::SetWidgetVisibility()
|
||||
hasVolumeControl(_entryData->_action));
|
||||
SetLayoutVisible(_fadeOptionsLayout,
|
||||
hasVolumeControl(_entryData->_action));
|
||||
_abortActiveFade->setVisible(hasVolumeControl(_entryData->_action) &&
|
||||
_entryData->_fade);
|
||||
_wait->setVisible(hasVolumeControl(_entryData->_action) &&
|
||||
_entryData->_fade);
|
||||
|
||||
updateGeometry();
|
||||
adjustSize();
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "macro-action-scene-switch.hpp"
|
||||
#include "section.hpp"
|
||||
#include "switch-button.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <QGraphicsOpacityEffect>
|
||||
|
||||
namespace advss {
|
||||
|
||||
std::map<std::string, MacroActionInfo> &MacroActionFactory::GetMap()
|
||||
@@ -78,26 +81,32 @@ MacroActionEdit::MacroActionEdit(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> *entryData,
|
||||
const std::string &id)
|
||||
: MacroSegmentEdit(switcher->macroProperties._highlightActions, parent),
|
||||
_actionSelection(new QComboBox()),
|
||||
_actionSelection(new FilterComboBox()),
|
||||
_enable(new SwitchButton()),
|
||||
_entryData(entryData)
|
||||
{
|
||||
QWidget::connect(_actionSelection,
|
||||
SIGNAL(currentTextChanged(const QString &)), this,
|
||||
SLOT(ActionSelectionChanged(const QString &)));
|
||||
QWidget::connect(_enable, SIGNAL(checked(bool)), this,
|
||||
SLOT(ActionEnableChanged(bool)));
|
||||
QWidget::connect(window(), SIGNAL(HighlightActionsChanged(bool)), this,
|
||||
SLOT(EnableHighlight(bool)));
|
||||
QWidget::connect(&_actionStateTimer, SIGNAL(timeout()), this,
|
||||
SLOT(UpdateActionState()));
|
||||
|
||||
populateActionSelection(_actionSelection);
|
||||
|
||||
_section->AddHeaderWidget(_enable);
|
||||
_section->AddHeaderWidget(_actionSelection);
|
||||
_section->AddHeaderWidget(_headerInfo);
|
||||
|
||||
QVBoxLayout *actionLayout = new QVBoxLayout;
|
||||
auto actionLayout = new QVBoxLayout;
|
||||
actionLayout->setContentsMargins({7, 7, 7, 7});
|
||||
actionLayout->addWidget(_section);
|
||||
_contentLayout->addLayout(actionLayout);
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
auto mainLayout = new QHBoxLayout;
|
||||
mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||
mainLayout->setSpacing(0);
|
||||
mainLayout->addWidget(_frame);
|
||||
@@ -106,6 +115,7 @@ MacroActionEdit::MacroActionEdit(QWidget *parent,
|
||||
_entryData = entryData;
|
||||
UpdateEntryData(id);
|
||||
|
||||
_actionStateTimer.start(300);
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
@@ -115,10 +125,14 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text)
|
||||
return;
|
||||
}
|
||||
|
||||
std::string id = MacroActionFactory::GetIdByName(text);
|
||||
if (id.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
HeaderInfoChanged("");
|
||||
auto idx = _entryData->get()->GetIndex();
|
||||
auto macro = _entryData->get()->GetMacro();
|
||||
std::string id = MacroActionFactory::GetIdByName(text);
|
||||
HeaderInfoChanged("");
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
_entryData->reset();
|
||||
@@ -136,6 +150,9 @@ void MacroActionEdit::UpdateEntryData(const std::string &id)
|
||||
{
|
||||
_actionSelection->setCurrentText(
|
||||
obs_module_text(MacroActionFactory::GetActionName(id).c_str()));
|
||||
const bool enabled = (*_entryData)->Enabled();
|
||||
_enable->setChecked(enabled);
|
||||
SetDisableEffect(!enabled);
|
||||
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
|
||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||
@@ -150,6 +167,43 @@ void MacroActionEdit::SetEntryData(std::shared_ptr<MacroAction> *data)
|
||||
_entryData = data;
|
||||
}
|
||||
|
||||
void MacroActionEdit::SetDisableEffect(bool value)
|
||||
{
|
||||
if (value) {
|
||||
auto effect = new QGraphicsOpacityEffect(this);
|
||||
effect->setOpacity(0.5);
|
||||
_section->setGraphicsEffect(effect);
|
||||
} else {
|
||||
_section->setGraphicsEffect(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionEdit::ActionEnableChanged(bool value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(switcher->m);
|
||||
(*_entryData)->SetEnabled(value);
|
||||
SetDisableEffect(!value);
|
||||
}
|
||||
|
||||
void MacroActionEdit::UpdateActionState()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetEnableAppearance((*_entryData)->Enabled());
|
||||
}
|
||||
|
||||
void MacroActionEdit::SetEnableAppearance(bool value)
|
||||
{
|
||||
_enable->setChecked(value);
|
||||
SetDisableEffect(!value);
|
||||
}
|
||||
|
||||
std::shared_ptr<MacroSegment> MacroActionEdit::Data()
|
||||
{
|
||||
return *_entryData;
|
||||
@@ -185,7 +239,7 @@ void AdvSceneSwitcher::AddMacroAction(int idx)
|
||||
obs_data_release(data);
|
||||
}
|
||||
macro->UpdateActionIndices();
|
||||
actionsList->Insert(
|
||||
ui->actionsList->Insert(
|
||||
idx,
|
||||
new MacroActionEdit(this, ¯o->Actions()[idx], id));
|
||||
SetActionData(*macro);
|
||||
@@ -209,7 +263,7 @@ void AdvSceneSwitcher::on_actionAdd_clicked()
|
||||
if (currentActionIdx != -1) {
|
||||
MacroActionSelectionChanged(currentActionIdx + 1);
|
||||
}
|
||||
actionsList->SetHelpMsgVisible(false);
|
||||
ui->actionsList->SetHelpMsgVisible(false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::RemoveMacroAction(int idx)
|
||||
@@ -225,7 +279,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();
|
||||
@@ -251,23 +305,115 @@ void AdvSceneSwitcher::on_actionRemove_clicked()
|
||||
MacroActionSelectionChanged(-1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_actionUp_clicked()
|
||||
void AdvSceneSwitcher::on_actionTop_clicked()
|
||||
{
|
||||
if (currentActionIdx == -1) {
|
||||
return;
|
||||
}
|
||||
MacroActionReorder(0, currentActionIdx);
|
||||
MacroActionSelectionChanged(0);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_actionUp_clicked()
|
||||
{
|
||||
if (currentActionIdx == -1 || currentActionIdx == 0) {
|
||||
return;
|
||||
}
|
||||
MoveMacroActionUp(currentActionIdx);
|
||||
MacroActionSelectionChanged(currentActionIdx - 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_actionDown_clicked()
|
||||
{
|
||||
if (currentActionIdx == -1) {
|
||||
if (currentActionIdx == -1 ||
|
||||
currentActionIdx == ui->actionsList->ContentLayout()->count() - 1) {
|
||||
return;
|
||||
}
|
||||
MoveMacroActionDown(currentActionIdx);
|
||||
MacroActionSelectionChanged(currentActionIdx + 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_actionBottom_clicked()
|
||||
{
|
||||
if (currentActionIdx == -1) {
|
||||
return;
|
||||
}
|
||||
const int newIdx = ui->actionsList->ContentLayout()->count() - 1;
|
||||
MacroActionReorder(newIdx, currentActionIdx);
|
||||
MacroActionSelectionChanged(newIdx);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_elseActionAdd_clicked()
|
||||
{
|
||||
auto macro = GetSelectedMacro();
|
||||
if (!macro) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (currentElseActionIdx == -1) {
|
||||
AddMacroElseAction((int)macro->ElseActions().size());
|
||||
} else {
|
||||
AddMacroElseAction(currentElseActionIdx + 1);
|
||||
}
|
||||
if (currentElseActionIdx != -1) {
|
||||
MacroElseActionSelectionChanged(currentElseActionIdx + 1);
|
||||
}
|
||||
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) {
|
||||
@@ -281,11 +427,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());
|
||||
}
|
||||
@@ -320,24 +466,158 @@ 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->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)
|
||||
@@ -347,8 +627,8 @@ void AdvSceneSwitcher::MacroActionReorder(int to, int from)
|
||||
return;
|
||||
}
|
||||
|
||||
if (from < 0 || from > (int)macro->Actions().size() || to < 0 ||
|
||||
to > (int)macro->Actions().size()) {
|
||||
if (to == from || from < 0 || from > (int)macro->Actions().size() ||
|
||||
to < 0 || to > (int)macro->Actions().size()) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
@@ -357,8 +637,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);
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
#pragma once
|
||||
#include "macro-action.hpp"
|
||||
#include "filter-combo-box.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <memory>
|
||||
|
||||
namespace advss {
|
||||
|
||||
class SwitchButton;
|
||||
|
||||
struct MacroActionInfo {
|
||||
using TCreateMethod = std::shared_ptr<MacroAction> (*)(Macro *m);
|
||||
using TCreateWidgetMethod = QWidget *(*)(QWidget *parent,
|
||||
@@ -44,13 +46,19 @@ public:
|
||||
|
||||
private slots:
|
||||
void ActionSelectionChanged(const QString &text);
|
||||
void ActionEnableChanged(bool);
|
||||
void UpdateActionState();
|
||||
|
||||
private:
|
||||
std::shared_ptr<MacroSegment> Data();
|
||||
void SetDisableEffect(bool);
|
||||
void SetEnableAppearance(bool);
|
||||
|
||||
QComboBox *_actionSelection;
|
||||
FilterComboBox *_actionSelection;
|
||||
SwitchButton *_enable;
|
||||
|
||||
std::shared_ptr<MacroAction> *_entryData;
|
||||
QTimer _actionStateTimer;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -15,6 +15,8 @@ const static std::map<MacroActionFilter::Action, std::string> actionTypes = {
|
||||
"AdvSceneSwitcher.action.filter.type.enable"},
|
||||
{MacroActionFilter::Action::DISABLE,
|
||||
"AdvSceneSwitcher.action.filter.type.disable"},
|
||||
{MacroActionFilter::Action::TOGGLE,
|
||||
"AdvSceneSwitcher.action.filter.type.toggle"},
|
||||
{MacroActionFilter::Action::SETTINGS,
|
||||
"AdvSceneSwitcher.action.filter.type.settings"},
|
||||
};
|
||||
@@ -29,6 +31,9 @@ bool MacroActionFilter::PerformAction()
|
||||
case Action::DISABLE:
|
||||
obs_source_set_enabled(s, false);
|
||||
break;
|
||||
case Action::TOGGLE:
|
||||
obs_source_set_enabled(s, !obs_source_enabled(s));
|
||||
break;
|
||||
case Action::SETTINGS:
|
||||
SetSourceSettings(s, _settings);
|
||||
break;
|
||||
@@ -60,6 +65,7 @@ bool MacroActionFilter::Save(obs_data_t *obj) const
|
||||
_filter.Save(obj, "filter");
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
_settings.Save(obj, "settings");
|
||||
obs_data_set_int(obj, "version", 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -68,7 +74,17 @@ bool MacroActionFilter::Load(obs_data_t *obj)
|
||||
MacroAction::Load(obj);
|
||||
_source.Load(obj);
|
||||
_filter.Load(obj, _source, "filter");
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
// TODO: Remove this fallback in future version
|
||||
if (!obs_data_has_user_value(obj, "version")) {
|
||||
const auto value = obs_data_get_int(obj, "action");
|
||||
if (value == 2) {
|
||||
_action = Action::SETTINGS;
|
||||
} else {
|
||||
_action = static_cast<Action>(value);
|
||||
}
|
||||
} else {
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
}
|
||||
_settings.Load(obj, "settings");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ public:
|
||||
enum class Action {
|
||||
ENABLE,
|
||||
DISABLE,
|
||||
TOGGLE,
|
||||
SETTINGS,
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#include "platform-funcs.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <thread>
|
||||
#include <obs-interaction.h>
|
||||
|
||||
namespace advss {
|
||||
@@ -13,6 +14,26 @@ bool MacroActionHotkey::_registered = MacroActionFactory::Register(
|
||||
{MacroActionHotkey::Create, MacroActionHotkeyEdit::Create,
|
||||
"AdvSceneSwitcher.action.hotkey"});
|
||||
|
||||
const static std::map<MacroActionHotkey::Action, std::string> actionTypes = {
|
||||
{MacroActionHotkey::Action::OBS_HOTKEY,
|
||||
"AdvSceneSwitcher.action.hotkey.type.obs"},
|
||||
{MacroActionHotkey::Action::CUSTOM,
|
||||
"AdvSceneSwitcher.action.hotkey.type.custom"},
|
||||
};
|
||||
|
||||
const static std::map<obs_hotkey_registerer_type, std::string> hotkeyTypes = {
|
||||
{OBS_HOTKEY_REGISTERER_FRONTEND,
|
||||
"AdvSceneSwitcher.action.hotkey.type.obs.type.frontend"},
|
||||
{OBS_HOTKEY_REGISTERER_SOURCE,
|
||||
"AdvSceneSwitcher.action.hotkey.type.obs.type.soruce"},
|
||||
{OBS_HOTKEY_REGISTERER_OUTPUT,
|
||||
"AdvSceneSwitcher.action.hotkey.type.obs.type.output"},
|
||||
{OBS_HOTKEY_REGISTERER_ENCODER,
|
||||
"AdvSceneSwitcher.action.hotkey.type.obs.type.encoder"},
|
||||
{OBS_HOTKEY_REGISTERER_SERVICE,
|
||||
"AdvSceneSwitcher.action.hotkey.type.obs.type.service"},
|
||||
};
|
||||
|
||||
static std::unordered_map<HotkeyType, long> keyTable = {
|
||||
// Chars
|
||||
{HotkeyType::Key_A, OBS_KEY_A},
|
||||
@@ -196,7 +217,92 @@ static void InjectKeys(const std::vector<HotkeyType> &keys, int duration)
|
||||
obs_hotkey_inject_event(combo, false);
|
||||
}
|
||||
|
||||
bool MacroActionHotkey::PerformAction()
|
||||
static void addNamePrefix(std::string &name, obs_hotkey_t *hotkey)
|
||||
{
|
||||
const auto type = obs_hotkey_get_registerer_type(hotkey);
|
||||
std::string prefix;
|
||||
if (type == OBS_HOTKEY_REGISTERER_SOURCE) {
|
||||
auto source = reinterpret_cast<obs_weak_source_t *>(
|
||||
obs_hotkey_get_registerer(hotkey));
|
||||
prefix = "[" + GetWeakSourceName(source) + "] ";
|
||||
} else if (type == OBS_HOTKEY_REGISTERER_OUTPUT) {
|
||||
auto weakOutput = reinterpret_cast<obs_weak_output_t *>(
|
||||
obs_hotkey_get_registerer(hotkey));
|
||||
std::string name;
|
||||
auto output = obs_weak_output_get_output(weakOutput);
|
||||
if (output) {
|
||||
name = obs_output_get_name(output);
|
||||
obs_output_release(output);
|
||||
}
|
||||
prefix = "[" + name + "] ";
|
||||
} else if (type == OBS_HOTKEY_REGISTERER_ENCODER) {
|
||||
auto weakEncoder = reinterpret_cast<obs_weak_encoder_t *>(
|
||||
obs_hotkey_get_registerer(hotkey));
|
||||
std::string name;
|
||||
auto encoder = obs_weak_encoder_get_encoder(weakEncoder);
|
||||
if (encoder) {
|
||||
name = obs_encoder_get_name(encoder);
|
||||
obs_encoder_release(encoder);
|
||||
}
|
||||
prefix = "[" + name + "] ";
|
||||
} else if (type == OBS_HOTKEY_REGISTERER_SERVICE) {
|
||||
auto weakService = reinterpret_cast<obs_weak_service_t *>(
|
||||
obs_hotkey_get_registerer(hotkey));
|
||||
std::string name;
|
||||
auto service = obs_weak_service_get_service(weakService);
|
||||
if (service) {
|
||||
name = obs_service_get_name(service);
|
||||
obs_service_release(service);
|
||||
}
|
||||
prefix = "[" + name + "] ";
|
||||
}
|
||||
name = prefix + name;
|
||||
}
|
||||
|
||||
static obs_hotkey_id getHotkeyIdByName(const std::string &name)
|
||||
{
|
||||
struct Parameters {
|
||||
std::string name;
|
||||
obs_hotkey_id id = OBS_INVALID_HOTKEY_ID;
|
||||
} params;
|
||||
|
||||
auto func = [](void *param, obs_hotkey_id id, obs_hotkey_t *hotkey) {
|
||||
auto params = static_cast<Parameters *>(param);
|
||||
std::string name = obs_hotkey_get_name(hotkey);
|
||||
addNamePrefix(name, hotkey);
|
||||
if (name == params->name) {
|
||||
params->id = id;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
params.name = name;
|
||||
obs_enum_hotkeys(func, ¶ms);
|
||||
return params.id;
|
||||
}
|
||||
|
||||
void MacroActionHotkey::SendOBSHotkey()
|
||||
{
|
||||
auto id = getHotkeyIdByName(_hotkeyName);
|
||||
if (id == OBS_INVALID_HOTKEY_ID) {
|
||||
blog(LOG_WARNING,
|
||||
"failed to get hotkey id for \"%s\" - key will not be pressed",
|
||||
_hotkeyName.c_str());
|
||||
return;
|
||||
}
|
||||
obs_queue_task(
|
||||
OBS_TASK_UI,
|
||||
[](void *param) {
|
||||
auto id = (size_t *)param;
|
||||
obs_hotkey_trigger_routed_callback(*id, false);
|
||||
obs_hotkey_trigger_routed_callback(*id, true);
|
||||
obs_hotkey_trigger_routed_callback(*id, false);
|
||||
},
|
||||
&id, true);
|
||||
}
|
||||
|
||||
void MacroActionHotkey::SendCustomHotkey()
|
||||
{
|
||||
std::vector<HotkeyType> keys;
|
||||
if (_leftShift) {
|
||||
@@ -237,18 +343,35 @@ bool MacroActionHotkey::PerformAction()
|
||||
t.detach();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool MacroActionHotkey::PerformAction()
|
||||
{
|
||||
switch (_action) {
|
||||
case advss::MacroActionHotkey::Action::OBS_HOTKEY:
|
||||
SendOBSHotkey();
|
||||
break;
|
||||
case advss::MacroActionHotkey::Action::CUSTOM:
|
||||
SendCustomHotkey();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionHotkey::LogAction() const
|
||||
{
|
||||
vblog(LOG_INFO, "sent hotkey");
|
||||
vblog(LOG_INFO, "sent hotkey type %d", static_cast<int>(_action));
|
||||
}
|
||||
|
||||
bool MacroActionHotkey::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
obs_data_set_int(obj, "hotkeyType", _hotkeyType);
|
||||
obs_data_set_string(obj, "hotkeyName", _hotkeyName.c_str());
|
||||
obs_data_set_int(obj, "key", static_cast<int>(_key));
|
||||
obs_data_set_bool(obj, "left_shift", _leftShift);
|
||||
obs_data_set_bool(obj, "right_shift", _rightShift);
|
||||
@@ -260,13 +383,22 @@ bool MacroActionHotkey::Save(obs_data_t *obj) const
|
||||
obs_data_set_bool(obj, "right_meta", _rightMeta);
|
||||
_duration.Save(obj);
|
||||
obs_data_set_bool(obj, "onlyOBS", _onlySendToObs);
|
||||
obs_data_set_int(obj, "version", 1);
|
||||
obs_data_set_int(obj, "version", 2);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionHotkey::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
int version = obs_data_get_int(obj, "version");
|
||||
if (version != 2) {
|
||||
_action = Action::CUSTOM;
|
||||
} else {
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
}
|
||||
_hotkeyType = static_cast<obs_hotkey_registerer_type>(
|
||||
obs_data_get_int(obj, "hotkeyType"));
|
||||
_hotkeyName = obs_data_get_string(obj, "hotkeyName");
|
||||
_key = static_cast<HotkeyType>(obs_data_get_int(obj, "key"));
|
||||
_leftShift = obs_data_get_bool(obj, "left_shift");
|
||||
_rightShift = obs_data_get_bool(obj, "right_shift");
|
||||
@@ -276,7 +408,7 @@ bool MacroActionHotkey::Load(obs_data_t *obj)
|
||||
_rightAlt = obs_data_get_bool(obj, "right_alt");
|
||||
_leftMeta = obs_data_get_bool(obj, "left_meta");
|
||||
_rightMeta = obs_data_get_bool(obj, "right_meta");
|
||||
if (!obs_data_has_user_value(obj, "version")) {
|
||||
if (version == 0) {
|
||||
_duration = obs_data_get_int(obj, "duration") / 1000.0;
|
||||
} else {
|
||||
_duration.Load(obj);
|
||||
@@ -395,9 +527,65 @@ static inline void populateKeySelection(QComboBox *list)
|
||||
list->addItem("NumpadEnter");
|
||||
}
|
||||
|
||||
static void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (const auto &[_, value] : actionTypes) {
|
||||
list->addItem(obs_module_text(value.c_str()));
|
||||
}
|
||||
}
|
||||
static void populateHotkeyTypeSelection(QComboBox *list)
|
||||
{
|
||||
for (const auto &[_, value] : hotkeyTypes) {
|
||||
list->addItem(obs_module_text(value.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
static void addNamePrefix(QString &name, obs_hotkey_t *hotkey)
|
||||
{
|
||||
auto temp = name.toStdString();
|
||||
addNamePrefix(temp, hotkey);
|
||||
name = QString::fromStdString(temp);
|
||||
}
|
||||
|
||||
static void populateHotkeyNames(QComboBox *list,
|
||||
obs_hotkey_registerer_type type)
|
||||
{
|
||||
struct Parameters {
|
||||
QStringList names;
|
||||
QStringList descriptions;
|
||||
obs_hotkey_registerer_type type;
|
||||
} params;
|
||||
|
||||
auto func = [](void *param, obs_hotkey_id, obs_hotkey_t *hotkey) {
|
||||
auto params = static_cast<Parameters *>(param);
|
||||
if (obs_hotkey_get_registerer_type(hotkey) == params->type) {
|
||||
QString description(obs_hotkey_get_description(hotkey));
|
||||
addNamePrefix(description, hotkey);
|
||||
params->descriptions.append(description);
|
||||
QString name(obs_hotkey_get_name(hotkey));
|
||||
addNamePrefix(name, hotkey);
|
||||
params->names.append(name);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
params.type = type;
|
||||
obs_enum_hotkeys(func, ¶ms);
|
||||
|
||||
list->clear();
|
||||
for (int i = 0; i < params.names.size(); i++) {
|
||||
list->addItem(params.descriptions.at(i), params.names.at(i));
|
||||
}
|
||||
AddSelectionEntry(list,
|
||||
obs_module_text("AdvSceneSwitcher.selectHotkey"));
|
||||
}
|
||||
|
||||
MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionHotkey> entryData)
|
||||
: QWidget(parent),
|
||||
_actionType(new QComboBox()),
|
||||
_hotkeyType(new QComboBox()),
|
||||
_obsHotkeys(new QComboBox()),
|
||||
_keys(new QComboBox()),
|
||||
_leftShift(new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.leftShift"))),
|
||||
@@ -419,10 +607,20 @@ MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
||||
_onlySendToOBS(new QCheckBox(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.onlyOBS"))),
|
||||
_noKeyPressSimulationWarning(new QLabel(
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.disabled")))
|
||||
obs_module_text("AdvSceneSwitcher.action.hotkey.disabled"))),
|
||||
_entryLayout(new QHBoxLayout()),
|
||||
_keyConfigLayout(new QHBoxLayout())
|
||||
{
|
||||
populateKeySelection(_keys);
|
||||
populateActionSelection(_actionType);
|
||||
populateHotkeyTypeSelection(_hotkeyType);
|
||||
|
||||
QWidget::connect(_actionType, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_hotkeyType, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(HotkeyTypeChanged(int)));
|
||||
QWidget::connect(_obsHotkeys, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(OBSHotkeyChanged(int)));
|
||||
QWidget::connect(_keys, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(KeyChanged(int)));
|
||||
QWidget::connect(_leftShift, SIGNAL(stateChanged(int)), this,
|
||||
@@ -446,28 +644,21 @@ MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
||||
QWidget::connect(_onlySendToOBS, SIGNAL(stateChanged(int)), this,
|
||||
SLOT(OnlySendToOBSChanged(int)));
|
||||
|
||||
QHBoxLayout *line1Layout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{keys}}", _keys},
|
||||
{"{{duration}}", _duration},
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.hotkey.entry"),
|
||||
line1Layout, widgetPlaceholders);
|
||||
_entryLayout->setContentsMargins(0, 0, 0, 0);
|
||||
_keyConfigLayout->setContentsMargins(0, 0, 0, 0);
|
||||
_keyConfigLayout->addWidget(_leftShift);
|
||||
_keyConfigLayout->addWidget(_rightShift);
|
||||
_keyConfigLayout->addWidget(_leftCtrl);
|
||||
_keyConfigLayout->addWidget(_rightCtrl);
|
||||
_keyConfigLayout->addWidget(_leftAlt);
|
||||
_keyConfigLayout->addWidget(_rightAlt);
|
||||
_keyConfigLayout->addWidget(_leftMeta);
|
||||
_keyConfigLayout->addWidget(_rightMeta);
|
||||
_keyConfigLayout->addStretch();
|
||||
|
||||
QHBoxLayout *line2Layout = new QHBoxLayout;
|
||||
line2Layout->addWidget(_leftShift);
|
||||
line2Layout->addWidget(_rightShift);
|
||||
line2Layout->addWidget(_leftCtrl);
|
||||
line2Layout->addWidget(_rightCtrl);
|
||||
line2Layout->addWidget(_leftAlt);
|
||||
line2Layout->addWidget(_rightAlt);
|
||||
line2Layout->addWidget(_leftMeta);
|
||||
line2Layout->addWidget(_rightMeta);
|
||||
line2Layout->addStretch();
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(line1Layout);
|
||||
mainLayout->addLayout(line2Layout);
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(_entryLayout);
|
||||
mainLayout->addLayout(_keyConfigLayout);
|
||||
mainLayout->addWidget(_onlySendToOBS);
|
||||
mainLayout->addWidget(_noKeyPressSimulationWarning);
|
||||
setLayout(mainLayout);
|
||||
@@ -479,10 +670,76 @@ MacroActionHotkeyEdit::MacroActionHotkeyEdit(
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::SetWarningVisibility()
|
||||
void MacroActionHotkeyEdit::RepopulateOBSHotkeySelection()
|
||||
{
|
||||
populateHotkeyNames(_obsHotkeys, _entryData->_hotkeyType);
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::SetWidgetVisibility()
|
||||
{
|
||||
_entryLayout->removeWidget(_actionType);
|
||||
_entryLayout->removeWidget(_hotkeyType);
|
||||
_entryLayout->removeWidget(_obsHotkeys);
|
||||
_entryLayout->removeWidget(_keys);
|
||||
_entryLayout->removeWidget(_duration);
|
||||
ClearLayout(_entryLayout);
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
_entryData->_action ==
|
||||
MacroActionHotkey::Action::OBS_HOTKEY
|
||||
? "AdvSceneSwitcher.action.hotkey.entry.obs"
|
||||
: "AdvSceneSwitcher.action.hotkey.entry.custom"),
|
||||
_entryLayout,
|
||||
{
|
||||
{"{{actionType}}", _actionType},
|
||||
{"{{hotkeyType}}", _hotkeyType},
|
||||
{"{{obsHotkeys}}", _obsHotkeys},
|
||||
{"{{keys}}", _keys},
|
||||
{"{{duration}}", _duration},
|
||||
});
|
||||
|
||||
_noKeyPressSimulationWarning->setVisible(!_entryData->_onlySendToObs &&
|
||||
!canSimulateKeyPresses);
|
||||
SetLayoutVisible(_keyConfigLayout,
|
||||
_entryData->_action ==
|
||||
MacroActionHotkey::Action::CUSTOM);
|
||||
_duration->setVisible(_entryData->_action ==
|
||||
MacroActionHotkey::Action::CUSTOM);
|
||||
_keys->setVisible(_entryData->_action ==
|
||||
MacroActionHotkey::Action::CUSTOM);
|
||||
_onlySendToOBS->setVisible(_entryData->_action ==
|
||||
MacroActionHotkey::Action::CUSTOM);
|
||||
_hotkeyType->setVisible(_entryData->_action ==
|
||||
MacroActionHotkey::Action::OBS_HOTKEY);
|
||||
_obsHotkeys->setVisible(_entryData->_action ==
|
||||
MacroActionHotkey::Action::OBS_HOTKEY);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
static QString getHotkeyDescriptionByName(const std::string &name)
|
||||
{
|
||||
struct Parameters {
|
||||
std::string name;
|
||||
QString description = "";
|
||||
} params;
|
||||
|
||||
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);
|
||||
if (name == params->name) {
|
||||
params->description =
|
||||
obs_hotkey_get_description(hotkey);
|
||||
addNamePrefix(params->description, hotkey);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
params.name = name;
|
||||
obs_enum_hotkeys(func, ¶ms);
|
||||
return params.description;
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::UpdateEntryData()
|
||||
@@ -491,6 +748,11 @@ void MacroActionHotkeyEdit::UpdateEntryData()
|
||||
return;
|
||||
}
|
||||
|
||||
_actionType->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_hotkeyType->setCurrentIndex(static_cast<int>(_entryData->_hotkeyType));
|
||||
RepopulateOBSHotkeySelection();
|
||||
_obsHotkeys->setCurrentText(
|
||||
getHotkeyDescriptionByName(_entryData->_hotkeyName));
|
||||
_keys->setCurrentIndex(static_cast<int>(_entryData->_key));
|
||||
_leftShift->setChecked(_entryData->_leftShift);
|
||||
_rightShift->setChecked(_entryData->_rightShift);
|
||||
@@ -503,7 +765,7 @@ void MacroActionHotkeyEdit::UpdateEntryData()
|
||||
_duration->SetDuration(_entryData->_duration);
|
||||
_onlySendToOBS->setChecked(_entryData->_onlySendToObs ||
|
||||
!canSimulateKeyPresses);
|
||||
SetWarningVisibility();
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::LShiftChanged(int state)
|
||||
@@ -604,7 +866,7 @@ void MacroActionHotkeyEdit::OnlySendToOBSChanged(int state)
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_onlySendToObs = state;
|
||||
SetWarningVisibility();
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::KeyChanged(int key)
|
||||
@@ -617,4 +879,43 @@ void MacroActionHotkeyEdit::KeyChanged(int key)
|
||||
_entryData->_key = static_cast<HotkeyType>(key);
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::ActionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_action = static_cast<MacroActionHotkey::Action>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::HotkeyTypeChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
auto lock = LockContext();
|
||||
_entryData->_hotkeyType =
|
||||
static_cast<obs_hotkey_registerer_type>(value);
|
||||
}
|
||||
RepopulateOBSHotkeySelection();
|
||||
}
|
||||
|
||||
void MacroActionHotkeyEdit::OBSHotkeyChanged(int idx)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
if (idx == -1) {
|
||||
_entryData->_hotkeyName = "";
|
||||
return;
|
||||
}
|
||||
_entryData->_hotkeyName =
|
||||
_obsHotkeys->itemData(idx).toString().toStdString();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -23,7 +23,15 @@ public:
|
||||
return std::make_shared<MacroActionHotkey>(m);
|
||||
}
|
||||
|
||||
OBSWeakSource _HotkeySource;
|
||||
enum class Action {
|
||||
OBS_HOTKEY,
|
||||
CUSTOM,
|
||||
};
|
||||
Action _action = Action::OBS_HOTKEY;
|
||||
|
||||
obs_hotkey_registerer_type _hotkeyType = OBS_HOTKEY_REGISTERER_FRONTEND;
|
||||
std::string _hotkeyName;
|
||||
|
||||
HotkeyType _key = HotkeyType::Key_NoKey;
|
||||
bool _leftShift = false;
|
||||
bool _rightShift = false;
|
||||
@@ -41,6 +49,9 @@ public:
|
||||
#endif
|
||||
|
||||
private:
|
||||
void SendOBSHotkey();
|
||||
void SendCustomHotkey();
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
@@ -62,6 +73,9 @@ public:
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ActionChanged(int key);
|
||||
void HotkeyTypeChanged(int key);
|
||||
void OBSHotkeyChanged(int);
|
||||
void KeyChanged(int key);
|
||||
void LShiftChanged(int state);
|
||||
void RShiftChanged(int state);
|
||||
@@ -75,6 +89,9 @@ private slots:
|
||||
void OnlySendToOBSChanged(int state);
|
||||
|
||||
protected:
|
||||
QComboBox *_actionType;
|
||||
QComboBox *_hotkeyType;
|
||||
QComboBox *_obsHotkeys;
|
||||
QComboBox *_keys;
|
||||
QCheckBox *_leftShift;
|
||||
QCheckBox *_rightShift;
|
||||
@@ -91,8 +108,11 @@ protected:
|
||||
std::shared_ptr<MacroActionHotkey> _entryData;
|
||||
|
||||
private:
|
||||
void SetWarningVisibility();
|
||||
QHBoxLayout *_mainLayout;
|
||||
void RepopulateOBSHotkeySelection();
|
||||
void SetWidgetVisibility();
|
||||
|
||||
QHBoxLayout *_entryLayout;
|
||||
QHBoxLayout *_keyConfigLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -156,6 +156,7 @@ MacroActionHttpEdit::MacroActionHttpEdit(
|
||||
_timeout(new DurationSelection(this, false))
|
||||
{
|
||||
populateMethodSelection(_methods);
|
||||
_headerList->SetMaxStringSize(4096);
|
||||
|
||||
QWidget::connect(_url, SIGNAL(editingFinished()), this,
|
||||
SLOT(URLChanged()));
|
||||
|
||||
@@ -11,14 +11,23 @@ bool MacroActionMacro::_registered = MacroActionFactory::Register(
|
||||
{MacroActionMacro::Create, MacroActionMacroEdit::Create,
|
||||
"AdvSceneSwitcher.action.macro"});
|
||||
|
||||
const static std::map<PerformMacroAction, std::string> actionTypes = {
|
||||
{PerformMacroAction::PAUSE, "AdvSceneSwitcher.action.macro.type.pause"},
|
||||
{PerformMacroAction::UNPAUSE,
|
||||
const static std::map<MacroActionMacro::Action, std::string> actionTypes = {
|
||||
{MacroActionMacro::Action::PAUSE,
|
||||
"AdvSceneSwitcher.action.macro.type.pause"},
|
||||
{MacroActionMacro::Action::UNPAUSE,
|
||||
"AdvSceneSwitcher.action.macro.type.unpause"},
|
||||
{PerformMacroAction::RESET_COUNTER,
|
||||
{MacroActionMacro::Action::RESET_COUNTER,
|
||||
"AdvSceneSwitcher.action.macro.type.resetCounter"},
|
||||
{PerformMacroAction::RUN, "AdvSceneSwitcher.action.macro.type.run"},
|
||||
{PerformMacroAction::STOP, "AdvSceneSwitcher.action.macro.type.stop"},
|
||||
{MacroActionMacro::Action::RUN,
|
||||
"AdvSceneSwitcher.action.macro.type.run"},
|
||||
{MacroActionMacro::Action::STOP,
|
||||
"AdvSceneSwitcher.action.macro.type.stop"},
|
||||
{MacroActionMacro::Action::DISABLE_ACTION,
|
||||
"AdvSceneSwitcher.action.macro.type.disableAction"},
|
||||
{MacroActionMacro::Action::ENABLE_ACTION,
|
||||
"AdvSceneSwitcher.action.macro.type.enableAction"},
|
||||
{MacroActionMacro::Action::TOGGLE_ACTION,
|
||||
"AdvSceneSwitcher.action.macro.type.toggleAction"},
|
||||
};
|
||||
|
||||
bool MacroActionMacro::PerformAction()
|
||||
@@ -29,23 +38,42 @@ bool MacroActionMacro::PerformAction()
|
||||
}
|
||||
|
||||
switch (_action) {
|
||||
case PerformMacroAction::PAUSE:
|
||||
case Action::PAUSE:
|
||||
macro->SetPaused();
|
||||
break;
|
||||
case PerformMacroAction::UNPAUSE:
|
||||
case Action::UNPAUSE:
|
||||
macro->SetPaused(false);
|
||||
break;
|
||||
case PerformMacroAction::RESET_COUNTER:
|
||||
case Action::RESET_COUNTER:
|
||||
macro->ResetRunCount();
|
||||
break;
|
||||
case PerformMacroAction::RUN:
|
||||
case Action::RUN:
|
||||
if (!macro->Paused()) {
|
||||
macro->PerformActions();
|
||||
macro->PerformActions(true, false, true);
|
||||
}
|
||||
break;
|
||||
case PerformMacroAction::STOP:
|
||||
case Action::STOP:
|
||||
macro->Stop();
|
||||
break;
|
||||
case Action::DISABLE_ACTION:
|
||||
if (IsValidMacroSegmentIndex(macro.get(), _actionIndex - 1,
|
||||
false)) {
|
||||
macro->Actions().at(_actionIndex - 1)->SetEnabled(false);
|
||||
}
|
||||
break;
|
||||
case Action::ENABLE_ACTION:
|
||||
if (IsValidMacroSegmentIndex(macro.get(), _actionIndex - 1,
|
||||
false)) {
|
||||
macro->Actions().at(_actionIndex - 1)->SetEnabled(true);
|
||||
}
|
||||
break;
|
||||
case Action::TOGGLE_ACTION:
|
||||
if (IsValidMacroSegmentIndex(macro.get(), _actionIndex - 1,
|
||||
false)) {
|
||||
auto action = macro->Actions().at(_actionIndex - 1);
|
||||
action->SetEnabled(!action->Enabled());
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -59,23 +87,35 @@ void MacroActionMacro::LogAction() const
|
||||
return;
|
||||
}
|
||||
switch (_action) {
|
||||
case PerformMacroAction::PAUSE:
|
||||
case Action::PAUSE:
|
||||
vblog(LOG_INFO, "paused \"%s\"", macro->Name().c_str());
|
||||
break;
|
||||
case PerformMacroAction::UNPAUSE:
|
||||
case Action::UNPAUSE:
|
||||
vblog(LOG_INFO, "unpaused \"%s\"", macro->Name().c_str());
|
||||
break;
|
||||
case PerformMacroAction::RESET_COUNTER:
|
||||
case Action::RESET_COUNTER:
|
||||
vblog(LOG_INFO, "reset counter for \"%s\"",
|
||||
macro->Name().c_str());
|
||||
break;
|
||||
case PerformMacroAction::RUN:
|
||||
case Action::RUN:
|
||||
vblog(LOG_INFO, "run nested macro \"%s\"",
|
||||
macro->Name().c_str());
|
||||
break;
|
||||
case PerformMacroAction::STOP:
|
||||
case Action::STOP:
|
||||
vblog(LOG_INFO, "stopped macro \"%s\"", macro->Name().c_str());
|
||||
break;
|
||||
case Action::DISABLE_ACTION:
|
||||
vblog(LOG_INFO, "disabled action %d of macro \"%s\"",
|
||||
_actionIndex.GetValue(), macro->Name().c_str());
|
||||
break;
|
||||
case Action::ENABLE_ACTION:
|
||||
vblog(LOG_INFO, "enabled action %d of macro \"%s\"",
|
||||
_actionIndex.GetValue(), macro->Name().c_str());
|
||||
break;
|
||||
case Action::TOGGLE_ACTION:
|
||||
vblog(LOG_INFO, "toggled action %d of macro \"%s\"",
|
||||
_actionIndex.GetValue(), macro->Name().c_str());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -85,6 +125,7 @@ bool MacroActionMacro::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
_macro.Save(obj);
|
||||
_actionIndex.Save(obj, "actionIndex");
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
return true;
|
||||
}
|
||||
@@ -93,7 +134,8 @@ bool MacroActionMacro::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_macro.Load(obj);
|
||||
_action = static_cast<PerformMacroAction>(
|
||||
_actionIndex.Load(obj, "actionIndex");
|
||||
_action = static_cast<MacroActionMacro::Action>(
|
||||
obs_data_get_int(obj, "action"));
|
||||
return true;
|
||||
}
|
||||
@@ -112,25 +154,28 @@ static inline void populateActionSelection(QComboBox *list)
|
||||
|
||||
MacroActionMacroEdit::MacroActionMacroEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionMacro> entryData)
|
||||
: QWidget(parent)
|
||||
: QWidget(parent),
|
||||
_macros(new MacroSelection(parent)),
|
||||
_actionIndex(new MacroSegmentSelection(
|
||||
this, MacroSegmentSelection::Type::ACTION)),
|
||||
_actions(new QComboBox())
|
||||
{
|
||||
_macros = new MacroSelection(parent);
|
||||
_actions = new QComboBox();
|
||||
|
||||
populateActionSelection(_actions);
|
||||
|
||||
QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)),
|
||||
this, SLOT(MacroChanged(const QString &)));
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_actionIndex,
|
||||
SIGNAL(SelectionChanged(const IntVariable &)), this,
|
||||
SLOT(ActionIndexChanged(const IntVariable &)));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{actions}}", _actions},
|
||||
{"{{macros}}", _macros},
|
||||
};
|
||||
auto mainLayout = new QHBoxLayout;
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.macro.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
mainLayout,
|
||||
{{"{{actions}}", _actions},
|
||||
{"{{actionIndex}}", _actionIndex},
|
||||
{"{{macros}}", _macros}});
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
@@ -144,11 +189,10 @@ void MacroActionMacroEdit::UpdateEntryData()
|
||||
return;
|
||||
}
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_actionIndex->SetValue(_entryData->_actionIndex);
|
||||
_actionIndex->SetMacro(_entryData->_macro.GetMacro());
|
||||
_macros->SetCurrentMacro(_entryData->_macro);
|
||||
if (_entryData->_action == PerformMacroAction::RUN ||
|
||||
_entryData->_action == PerformMacroAction::STOP) {
|
||||
_macros->HideSelectedMacro();
|
||||
}
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::MacroChanged(const QString &text)
|
||||
@@ -159,6 +203,7 @@ void MacroActionMacroEdit::MacroChanged(const QString &text)
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_macro = text;
|
||||
_actionIndex->SetMacro(_entryData->_macro.GetMacro());
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
@@ -170,14 +215,36 @@ void MacroActionMacroEdit::ActionChanged(int value)
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_action = static_cast<PerformMacroAction>(value);
|
||||
_entryData->_action = static_cast<MacroActionMacro::Action>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
if (_entryData->_action == PerformMacroAction::RUN ||
|
||||
_entryData->_action == PerformMacroAction::STOP) {
|
||||
void MacroActionMacroEdit::ActionIndexChanged(const IntVariable &value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_actionIndex = value;
|
||||
}
|
||||
|
||||
void MacroActionMacroEdit::SetWidgetVisibility()
|
||||
{
|
||||
if (_entryData->_action == MacroActionMacro::Action::RUN ||
|
||||
_entryData->_action == MacroActionMacro::Action::STOP) {
|
||||
_macros->HideSelectedMacro();
|
||||
} else {
|
||||
_macros->ShowAllMacros();
|
||||
}
|
||||
|
||||
const bool isModifyingActionState =
|
||||
_entryData->_action ==
|
||||
MacroActionMacro::Action::DISABLE_ACTION ||
|
||||
_entryData->_action ==
|
||||
MacroActionMacro::Action::ENABLE_ACTION ||
|
||||
_entryData->_action == MacroActionMacro::Action::TOGGLE_ACTION;
|
||||
_actionIndex->setVisible(isModifyingActionState);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -1,19 +1,12 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "macro-selection.hpp"
|
||||
#include "macro-segment-selection.hpp"
|
||||
|
||||
#include <QHBoxLayout>
|
||||
|
||||
namespace advss {
|
||||
|
||||
enum class PerformMacroAction {
|
||||
PAUSE,
|
||||
UNPAUSE,
|
||||
RESET_COUNTER,
|
||||
RUN,
|
||||
STOP,
|
||||
};
|
||||
|
||||
class MacroActionMacro : public MacroRefAction {
|
||||
public:
|
||||
MacroActionMacro(Macro *m) : MacroAction(m), MacroRefAction(m) {}
|
||||
@@ -28,7 +21,18 @@ public:
|
||||
return std::make_shared<MacroActionMacro>(m);
|
||||
}
|
||||
|
||||
PerformMacroAction _action = PerformMacroAction::PAUSE;
|
||||
enum class Action {
|
||||
PAUSE,
|
||||
UNPAUSE,
|
||||
RESET_COUNTER,
|
||||
RUN,
|
||||
STOP,
|
||||
DISABLE_ACTION,
|
||||
ENABLE_ACTION,
|
||||
TOGGLE_ACTION,
|
||||
};
|
||||
Action _action = Action::PAUSE;
|
||||
IntVariable _actionIndex = 1;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
@@ -54,16 +58,19 @@ public:
|
||||
private slots:
|
||||
void MacroChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
void ActionIndexChanged(const IntVariable &value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
MacroSelection *_macros;
|
||||
MacroSegmentSelection *_actionIndex;
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionMacro> _entryData;
|
||||
|
||||
private:
|
||||
QHBoxLayout *_mainLayout;
|
||||
void SetWidgetVisibility();
|
||||
|
||||
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
|
||||
|
||||
176
src/macro-core/macro-action-scene-lock.cpp
Normal file
176
src/macro-core/macro-action-scene-lock.cpp
Normal file
@@ -0,0 +1,176 @@
|
||||
#include "macro-action-scene-lock.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionSceneLock::id = "scene_lock";
|
||||
|
||||
bool MacroActionSceneLock::_registered = MacroActionFactory::Register(
|
||||
MacroActionSceneLock::id,
|
||||
{MacroActionSceneLock::Create, MacroActionSceneLockEdit::Create,
|
||||
"AdvSceneSwitcher.action.sceneLock"});
|
||||
|
||||
const static std::map<MacroActionSceneLock::Action, std::string> actionTypes = {
|
||||
{MacroActionSceneLock::Action::LOCK,
|
||||
"AdvSceneSwitcher.action.sceneLock.type.lock"},
|
||||
{MacroActionSceneLock::Action::UNLOCK,
|
||||
"AdvSceneSwitcher.action.sceneLock.type.unlock"},
|
||||
{MacroActionSceneLock::Action::TOGGLE,
|
||||
"AdvSceneSwitcher.action.sceneLock.type.toggle"},
|
||||
};
|
||||
|
||||
static void setSceneItemLock(obs_sceneitem_t *item,
|
||||
MacroActionSceneLock::Action action)
|
||||
{
|
||||
switch (action) {
|
||||
case MacroActionSceneLock::Action::LOCK:
|
||||
obs_sceneitem_set_locked(item, true);
|
||||
break;
|
||||
case MacroActionSceneLock::Action::UNLOCK:
|
||||
obs_sceneitem_set_locked(item, false);
|
||||
break;
|
||||
case MacroActionSceneLock::Action::TOGGLE:
|
||||
obs_sceneitem_set_locked(item, !obs_sceneitem_locked(item));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool MacroActionSceneLock::PerformAction()
|
||||
{
|
||||
|
||||
auto items = _source.GetSceneItems(_scene);
|
||||
for (const auto &item : items) {
|
||||
setSceneItemLock(item, _action);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionSceneLock::LogAction() const
|
||||
{
|
||||
auto it = actionTypes.find(_action);
|
||||
if (it != actionTypes.end()) {
|
||||
vblog(LOG_INFO,
|
||||
"performed action \"%s\" for source \"%s\" on scene \"%s\"",
|
||||
it->second.c_str(), _source.ToString(true).c_str(),
|
||||
_scene.ToString(true).c_str());
|
||||
|
||||
} else {
|
||||
blog(LOG_WARNING, "ignored unknown scene lock action %d",
|
||||
static_cast<int>(_action));
|
||||
}
|
||||
}
|
||||
|
||||
bool MacroActionSceneLock::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
_scene.Save(obj);
|
||||
_source.Save(obj);
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionSceneLock::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_scene.Load(obj);
|
||||
_source.Load(obj);
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionSceneLock::GetShortDesc() const
|
||||
{
|
||||
if (!_source.ToString().empty()) {
|
||||
return _scene.ToString() + " - " + _source.ToString();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (const auto &[_, name] : actionTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionSceneLockEdit::MacroActionSceneLockEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionSceneLock> entryData)
|
||||
: QWidget(parent),
|
||||
_scenes(new SceneSelectionWidget(window(), true, false, true, true)),
|
||||
_sources(new SceneItemSelectionWidget(parent)),
|
||||
_actions(new QComboBox())
|
||||
{
|
||||
populateActionSelection(_actions);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
_sources, SLOT(SceneChanged(const SceneSelection &)));
|
||||
QWidget::connect(_sources,
|
||||
SIGNAL(SceneItemChanged(const SceneItemSelection &)),
|
||||
this, SLOT(SourceChanged(const SceneItemSelection &)));
|
||||
|
||||
auto layout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{sources}}", _sources},
|
||||
{"{{actions}}", _actions},
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.sceneLock.entry"),
|
||||
layout, widgetPlaceholders);
|
||||
setLayout(layout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionSceneLockEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
_sources->SetSceneItem((_entryData->_source));
|
||||
}
|
||||
|
||||
void MacroActionSceneLockEdit::SceneChanged(const SceneSelection &s)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_scene = s;
|
||||
}
|
||||
|
||||
void MacroActionSceneLockEdit::SourceChanged(const SceneItemSelection &item)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_source = item;
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionSceneLockEdit::ActionChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_action = static_cast<MacroActionSceneLock::Action>(value);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
69
src/macro-core/macro-action-scene-lock.hpp
Normal file
69
src/macro-core/macro-action-scene-lock.hpp
Normal file
@@ -0,0 +1,69 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
#include "scene-item-selection.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroActionSceneLock : public MacroAction {
|
||||
public:
|
||||
MacroActionSceneLock(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<MacroActionSceneLock>(m);
|
||||
}
|
||||
|
||||
enum class Action {
|
||||
LOCK,
|
||||
UNLOCK,
|
||||
TOGGLE,
|
||||
};
|
||||
Action _action = Action::LOCK;
|
||||
SceneSelection _scene;
|
||||
SceneItemSelection _source;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroActionSceneLockEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroActionSceneLockEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroActionSceneLock> entryData = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroAction> action)
|
||||
{
|
||||
return new MacroActionSceneLockEdit(
|
||||
parent, std::dynamic_pointer_cast<MacroActionSceneLock>(
|
||||
action));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const SceneItemSelection &);
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
SceneItemSelectionWidget *_sources;
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionSceneLock> _entryData;
|
||||
|
||||
private:
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
@@ -23,7 +23,7 @@ const static std::map<SceneOrderAction, std::string> actionTypes = {
|
||||
"AdvSceneSwitcher.action.sceneOrder.type.movePosition"},
|
||||
};
|
||||
|
||||
static void moveSceneItemsUp(std::vector<obs_scene_item *> &items)
|
||||
static void moveSceneItemsUp(std::vector<OBSSceneItem> &items)
|
||||
{
|
||||
// In the case of the same source being in two sequential positions
|
||||
// moving the sources up will cause the sources to swap positions due to
|
||||
@@ -33,41 +33,36 @@ static void moveSceneItemsUp(std::vector<obs_scene_item *> &items)
|
||||
// will be moved up.
|
||||
std::reverse(items.begin(), items.end());
|
||||
|
||||
for (auto &i : items) {
|
||||
for (const auto &i : items) {
|
||||
obs_sceneitem_set_order(i, OBS_ORDER_MOVE_UP);
|
||||
obs_sceneitem_release(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void moveSceneItemsDown(std::vector<obs_scene_item *> &items)
|
||||
static void moveSceneItemsDown(std::vector<OBSSceneItem> &items)
|
||||
{
|
||||
for (auto &i : items) {
|
||||
for (const auto &i : items) {
|
||||
obs_sceneitem_set_order(i, OBS_ORDER_MOVE_DOWN);
|
||||
obs_sceneitem_release(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void moveSceneItemsTop(std::vector<obs_scene_item *> &items)
|
||||
static void moveSceneItemsTop(std::vector<OBSSceneItem> &items)
|
||||
{
|
||||
for (auto &i : items) {
|
||||
for (const auto &i : items) {
|
||||
obs_sceneitem_set_order(i, OBS_ORDER_MOVE_TOP);
|
||||
obs_sceneitem_release(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void moveSceneItemsBottom(std::vector<obs_scene_item *> &items)
|
||||
static void moveSceneItemsBottom(std::vector<OBSSceneItem> &items)
|
||||
{
|
||||
for (auto &i : items) {
|
||||
for (const auto &i : items) {
|
||||
obs_sceneitem_set_order(i, OBS_ORDER_MOVE_BOTTOM);
|
||||
obs_sceneitem_release(i);
|
||||
}
|
||||
}
|
||||
|
||||
static void moveSceneItemsPos(std::vector<obs_scene_item *> &items, int pos)
|
||||
static void moveSceneItemsPos(std::vector<OBSSceneItem> &items, int pos)
|
||||
{
|
||||
for (auto &i : items) {
|
||||
for (const auto &i : items) {
|
||||
obs_sceneitem_set_order_position(i, pos);
|
||||
obs_sceneitem_release(i);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,7 +144,7 @@ std::string MacroActionSceneOrder::GetShortDesc() const
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
for (const auto &entry : actionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
@@ -228,6 +223,8 @@ void MacroActionSceneOrderEdit::SourceChanged(const SceneItemSelection &item)
|
||||
_entryData->_source = item;
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionSceneOrderEdit::ActionChanged(int value)
|
||||
|
||||
@@ -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,
|
||||
@@ -20,6 +28,9 @@ static void waitForTransitionChange(OBSWeakSource &transition,
|
||||
{
|
||||
const auto time = 100ms;
|
||||
obs_source_t *source = obs_weak_source_get_source(transition);
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
|
||||
bool stillTransitioning = true;
|
||||
while (stillTransitioning && !switcher->abortMacroWait &&
|
||||
@@ -123,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());
|
||||
@@ -134,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
|
||||
@@ -162,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;
|
||||
}
|
||||
|
||||
@@ -173,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;
|
||||
}
|
||||
|
||||
@@ -181,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),
|
||||
@@ -189,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 &)));
|
||||
@@ -203,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;
|
||||
}
|
||||
|
||||
@@ -248,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();
|
||||
@@ -258,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(
|
||||
@@ -299,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;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "macro-action-scene-transform.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include <graphics/matrix4.h>
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroActionSceneTransform::id = "scene_transform";
|
||||
@@ -11,18 +13,242 @@ bool MacroActionSceneTransform::_registered = MacroActionFactory::Register(
|
||||
MacroActionSceneTransformEdit::Create,
|
||||
"AdvSceneSwitcher.action.sceneTransform"});
|
||||
|
||||
bool MacroActionSceneTransform::PerformAction()
|
||||
{
|
||||
ApplySettings(_settings); // Resolves variables
|
||||
const static std::map<MacroActionSceneTransform::Action, std::string> actions = {
|
||||
{MacroActionSceneTransform::Action::MANUAL_TRANSFORM,
|
||||
"AdvSceneSwitcher.action.sceneTransform.type.manual"},
|
||||
{MacroActionSceneTransform::Action::RESET,
|
||||
"AdvSceneSwitcher.action.sceneTransform.type.reset"},
|
||||
{MacroActionSceneTransform::Action::ROTATE,
|
||||
"AdvSceneSwitcher.action.sceneTransform.type.rotate"},
|
||||
{MacroActionSceneTransform::Action::FLIP_HORIZONTAL,
|
||||
"AdvSceneSwitcher.action.sceneTransform.type.flipHorizontal"},
|
||||
{MacroActionSceneTransform::Action::FLIP_VERTICAL,
|
||||
"AdvSceneSwitcher.action.sceneTransform.type.flipVertical"},
|
||||
{MacroActionSceneTransform::Action::FIT_TO_SCREEN,
|
||||
"AdvSceneSwitcher.action.sceneTransform.type.fitToScreen"},
|
||||
{MacroActionSceneTransform::Action::STRETCH_TO_SCREEN,
|
||||
"AdvSceneSwitcher.action.sceneTransform.type.stretchToScreen"},
|
||||
{MacroActionSceneTransform::Action::CENTER_TO_SCREEN,
|
||||
"AdvSceneSwitcher.action.sceneTransform.type.centerToScreen"},
|
||||
{MacroActionSceneTransform::Action::CENTER_VERTICALLY,
|
||||
"AdvSceneSwitcher.action.sceneTransform.type.centerVertically"},
|
||||
{MacroActionSceneTransform::Action::CENTER_HORIZONTALLY,
|
||||
"AdvSceneSwitcher.action.sceneTransform.type.centerHorizontally"},
|
||||
};
|
||||
|
||||
auto items = _source.GetSceneItems(_scene);
|
||||
for (auto &item : items) {
|
||||
/* --------------- Helpers based on OBS window-basic-main.cpp --------------- */
|
||||
|
||||
static void getItemBox(obs_sceneitem_t *item, vec3 &tl, vec3 &br)
|
||||
{
|
||||
matrix4 boxTransform;
|
||||
obs_sceneitem_get_box_transform(item, &boxTransform);
|
||||
|
||||
vec3_set(&tl, M_INFINITE, M_INFINITE, 0.0f);
|
||||
vec3_set(&br, -M_INFINITE, -M_INFINITE, 0.0f);
|
||||
|
||||
auto GetMinPos = [&](float x, float y) {
|
||||
vec3 pos;
|
||||
vec3_set(&pos, x, y, 0.0f);
|
||||
vec3_transform(&pos, &pos, &boxTransform);
|
||||
vec3_min(&tl, &tl, &pos);
|
||||
vec3_max(&br, &br, &pos);
|
||||
};
|
||||
|
||||
GetMinPos(0.0f, 0.0f);
|
||||
GetMinPos(1.0f, 0.0f);
|
||||
GetMinPos(0.0f, 1.0f);
|
||||
GetMinPos(1.0f, 1.0f);
|
||||
}
|
||||
|
||||
static vec3 getItemTL(obs_sceneitem_t *item)
|
||||
{
|
||||
vec3 tl, br;
|
||||
getItemBox(item, tl, br);
|
||||
return tl;
|
||||
}
|
||||
|
||||
static void setItemTL(obs_sceneitem_t *item, const vec3 &tl)
|
||||
{
|
||||
vec3 newTL;
|
||||
vec2 pos;
|
||||
|
||||
obs_sceneitem_get_pos(item, &pos);
|
||||
newTL = getItemTL(item);
|
||||
pos.x += tl.x - newTL.x;
|
||||
pos.y += tl.y - newTL.y;
|
||||
obs_sceneitem_set_pos(item, &pos);
|
||||
}
|
||||
|
||||
static void reset(obs_sceneitem_t *item)
|
||||
{
|
||||
obs_transform_info info;
|
||||
vec2_set(&info.pos, 0.0f, 0.0f);
|
||||
vec2_set(&info.scale, 1.0f, 1.0f);
|
||||
info.rot = 0.0f;
|
||||
info.alignment = OBS_ALIGN_TOP | OBS_ALIGN_LEFT;
|
||||
info.bounds_type = OBS_BOUNDS_NONE;
|
||||
info.bounds_alignment = OBS_ALIGN_CENTER;
|
||||
vec2_set(&info.bounds, 0.0f, 0.0f);
|
||||
obs_sceneitem_set_info(item, &info);
|
||||
|
||||
obs_sceneitem_crop crop = {};
|
||||
obs_sceneitem_set_crop(item, &crop);
|
||||
}
|
||||
|
||||
static void rotate(obs_sceneitem_t *item, float rot)
|
||||
{
|
||||
vec3 tl = getItemTL(item);
|
||||
rot += obs_sceneitem_get_rot(item);
|
||||
if (rot >= 360.0f) {
|
||||
rot -= 360.0f;
|
||||
} else if (rot <= -360.0f) {
|
||||
rot += 360.0f;
|
||||
}
|
||||
obs_sceneitem_set_rot(item, rot);
|
||||
obs_sceneitem_force_update_transform(item);
|
||||
setItemTL(item, tl);
|
||||
};
|
||||
|
||||
static void flip(obs_sceneitem_t *item, const vec2 &mul)
|
||||
{
|
||||
vec3 tl = getItemTL(item);
|
||||
vec2 scale;
|
||||
obs_sceneitem_get_scale(item, &scale);
|
||||
vec2_mul(&scale, &scale, &mul);
|
||||
obs_sceneitem_set_scale(item, &scale);
|
||||
obs_sceneitem_force_update_transform(item);
|
||||
setItemTL(item, tl);
|
||||
}
|
||||
|
||||
static void centerAlign(obs_sceneitem_t *item, obs_bounds_type boundsType)
|
||||
{
|
||||
obs_video_info ovi;
|
||||
obs_get_video_info(&ovi);
|
||||
|
||||
obs_transform_info itemInfo;
|
||||
vec2_set(&itemInfo.pos, 0.0f, 0.0f);
|
||||
vec2_set(&itemInfo.scale, 1.0f, 1.0f);
|
||||
itemInfo.alignment = OBS_ALIGN_LEFT | OBS_ALIGN_TOP;
|
||||
itemInfo.rot = 0.0f;
|
||||
|
||||
vec2_set(&itemInfo.bounds, float(ovi.base_width),
|
||||
float(ovi.base_height));
|
||||
itemInfo.bounds_type = boundsType;
|
||||
itemInfo.bounds_alignment = OBS_ALIGN_CENTER;
|
||||
|
||||
obs_sceneitem_set_info(item, &itemInfo);
|
||||
}
|
||||
|
||||
enum class CenterType {
|
||||
SCREEN,
|
||||
VERTICAL,
|
||||
HORIZONTAL,
|
||||
};
|
||||
|
||||
static void center(obs_sceneitem_t *item, const CenterType ¢erType)
|
||||
{
|
||||
// Get center x, y coordinates of items
|
||||
vec3 tl, br;
|
||||
getItemBox(item, tl, br);
|
||||
|
||||
float left = tl.x;
|
||||
float top = tl.y;
|
||||
float right = br.x;
|
||||
float bottom = br.y;
|
||||
|
||||
vec3 center;
|
||||
center.x = (right + left) / 2.0f;
|
||||
center.y = (top + bottom) / 2.0f;
|
||||
center.z = 0.0f;
|
||||
|
||||
// Get coordinates of screen center
|
||||
obs_video_info ovi;
|
||||
obs_get_video_info(&ovi);
|
||||
|
||||
vec3 screenCenter;
|
||||
vec3_set(&screenCenter, float(ovi.base_width), float(ovi.base_height),
|
||||
0.0f);
|
||||
|
||||
vec3_mulf(&screenCenter, &screenCenter, 0.5f);
|
||||
|
||||
// Calculate difference between screen center and item center
|
||||
vec3 offset;
|
||||
vec3_sub(&offset, &screenCenter, ¢er);
|
||||
|
||||
// Shift item by offset
|
||||
vec3_add(&tl, &tl, &offset);
|
||||
|
||||
vec3 itemTL = getItemTL(item);
|
||||
|
||||
if (centerType == CenterType::VERTICAL) {
|
||||
tl.x = itemTL.x;
|
||||
} else if (centerType == CenterType::HORIZONTAL) {
|
||||
tl.y = itemTL.y;
|
||||
}
|
||||
|
||||
setItemTL(item, tl);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
void MacroActionSceneTransform::Transform(obs_scene_item *item)
|
||||
{
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_action) {
|
||||
case MacroActionSceneTransform::Action::RESET:
|
||||
obs_sceneitem_defer_update_begin(item);
|
||||
reset(item);
|
||||
obs_sceneitem_defer_update_end(item);
|
||||
|
||||
break;
|
||||
case MacroActionSceneTransform::Action::ROTATE:
|
||||
rotate(item, _rotation);
|
||||
break;
|
||||
case MacroActionSceneTransform::Action::FLIP_HORIZONTAL: {
|
||||
vec2 scale;
|
||||
vec2_set(&scale, -1.0f, 1.0f);
|
||||
flip(item, scale);
|
||||
break;
|
||||
}
|
||||
case MacroActionSceneTransform::Action::FLIP_VERTICAL: {
|
||||
vec2 scale;
|
||||
vec2_set(&scale, 1.0f, -1.0f);
|
||||
flip(item, scale);
|
||||
break;
|
||||
}
|
||||
case MacroActionSceneTransform::Action::FIT_TO_SCREEN:
|
||||
centerAlign(item, OBS_BOUNDS_SCALE_INNER);
|
||||
break;
|
||||
case MacroActionSceneTransform::Action::STRETCH_TO_SCREEN:
|
||||
centerAlign(item, OBS_BOUNDS_STRETCH);
|
||||
break;
|
||||
case MacroActionSceneTransform::Action::CENTER_TO_SCREEN:
|
||||
center(item, CenterType::SCREEN);
|
||||
break;
|
||||
case MacroActionSceneTransform::Action::CENTER_VERTICALLY:
|
||||
center(item, CenterType::VERTICAL);
|
||||
break;
|
||||
case MacroActionSceneTransform::Action::CENTER_HORIZONTALLY:
|
||||
center(item, CenterType::HORIZONTAL);
|
||||
break;
|
||||
case MacroActionSceneTransform::Action::MANUAL_TRANSFORM:
|
||||
ApplySettings(_settings); // Resolves variables
|
||||
obs_sceneitem_defer_update_begin(item);
|
||||
obs_sceneitem_set_info(item, &_info);
|
||||
obs_sceneitem_set_crop(item, &_crop);
|
||||
obs_sceneitem_defer_update_end(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
obs_sceneitem_release(item);
|
||||
bool MacroActionSceneTransform::PerformAction()
|
||||
{
|
||||
auto items = _source.GetSceneItems(_scene);
|
||||
for (const auto &item : items) {
|
||||
Transform(item);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -30,15 +256,18 @@ bool MacroActionSceneTransform::PerformAction()
|
||||
void MacroActionSceneTransform::LogAction() const
|
||||
{
|
||||
vblog(LOG_INFO,
|
||||
"performed transform action for source \"%s\" on scene \"%s\"",
|
||||
_source.ToString(true).c_str(), _scene.ToString(true).c_str());
|
||||
"performed transform action %d for source \"%s\" on scene \"%s\"",
|
||||
static_cast<int>(_action), _source.ToString(true).c_str(),
|
||||
_scene.ToString(true).c_str());
|
||||
}
|
||||
|
||||
bool MacroActionSceneTransform::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
_scene.Save(obj);
|
||||
_source.Save(obj);
|
||||
_rotation.Save(obj, "rotation");
|
||||
_settings.Save(obj, "settings");
|
||||
return true;
|
||||
}
|
||||
@@ -53,8 +282,15 @@ bool MacroActionSceneTransform::Load(obs_data_t *obj)
|
||||
}
|
||||
|
||||
MacroAction::Load(obj);
|
||||
if (!obs_data_has_user_value(obj, "action")) {
|
||||
_action =
|
||||
Action::MANUAL_TRANSFORM; // TODO: Remove fallback in future
|
||||
} else {
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
}
|
||||
_scene.Load(obj);
|
||||
_source.Load(obj);
|
||||
_rotation.Load(obj, "rotation");
|
||||
_settings.Load(obj, "settings");
|
||||
|
||||
// Convert old data format
|
||||
@@ -107,21 +343,34 @@ void MacroActionSceneTransform::ApplySettings(const std::string &settings)
|
||||
}
|
||||
obs_data_release(obj);
|
||||
}
|
||||
for (auto item : items) {
|
||||
obs_sceneitem_release(item);
|
||||
}
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (const auto &[type, name] : actions) {
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(type));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionSceneTransformEdit::MacroActionSceneTransformEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionSceneTransform> entryData)
|
||||
: QWidget(parent)
|
||||
: QWidget(parent),
|
||||
_scenes(new SceneSelectionWidget(window(), true, false, false, true)),
|
||||
_sources(new SceneItemSelectionWidget(parent)),
|
||||
_action(new QComboBox()),
|
||||
_rotation(new VariableDoubleSpinBox()),
|
||||
_getSettings(new QPushButton(obs_module_text(
|
||||
"AdvSceneSwitcher.action.sceneTransform.getTransform"))),
|
||||
_settings(new VariableTextEdit(this)),
|
||||
_buttonLayout(new QHBoxLayout())
|
||||
{
|
||||
_scenes = new SceneSelectionWidget(window(), true, false, false, true);
|
||||
_sources = new SceneItemSelectionWidget(parent);
|
||||
_getSettings = new QPushButton(obs_module_text(
|
||||
"AdvSceneSwitcher.action.sceneTransform.getTransform"));
|
||||
_settings = new VariableTextEdit(this);
|
||||
_rotation->setMinimum(-360);
|
||||
_rotation->setMaximum(360);
|
||||
_rotation->setSuffix("°");
|
||||
|
||||
populateActionSelection(_action);
|
||||
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||
@@ -130,6 +379,12 @@ MacroActionSceneTransformEdit::MacroActionSceneTransformEdit(
|
||||
QWidget::connect(_sources,
|
||||
SIGNAL(SceneItemChanged(const SceneItemSelection &)),
|
||||
this, SLOT(SourceChanged(const SceneItemSelection &)));
|
||||
QWidget::connect(_action, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(
|
||||
_rotation,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<double> &)),
|
||||
this, SLOT(RotationChanged(const NumberVariable<double> &)));
|
||||
QWidget::connect(_getSettings, SIGNAL(clicked()), this,
|
||||
SLOT(GetSettingsClicked()));
|
||||
QWidget::connect(_settings, SIGNAL(textChanged()), this,
|
||||
@@ -138,23 +393,21 @@ MacroActionSceneTransformEdit::MacroActionSceneTransformEdit(
|
||||
QHBoxLayout *entryLayout = new QHBoxLayout;
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{scenes}}", _scenes},
|
||||
{"{{sources}}", _sources},
|
||||
{"{{settings}}", _settings},
|
||||
{"{{getSettings}}", _getSettings},
|
||||
{"{{scenes}}", _scenes}, {"{{rotation}}", _rotation},
|
||||
{"{{sources}}", _sources}, {"{{action}}", _action},
|
||||
{"{{settings}}", _settings}, {"{{getSettings}}", _getSettings},
|
||||
};
|
||||
PlaceWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.action.sceneTransform.entry"),
|
||||
entryLayout, widgetPlaceholders);
|
||||
|
||||
QHBoxLayout *buttonLayout = new QHBoxLayout;
|
||||
buttonLayout->addWidget(_getSettings);
|
||||
buttonLayout->addStretch();
|
||||
_buttonLayout->addWidget(_getSettings);
|
||||
_buttonLayout->addStretch();
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
mainLayout->addWidget(_settings);
|
||||
mainLayout->addLayout(buttonLayout);
|
||||
mainLayout->addLayout(_buttonLayout);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
@@ -170,10 +423,11 @@ void MacroActionSceneTransformEdit::UpdateEntryData()
|
||||
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
_sources->SetSceneItem(_entryData->_source);
|
||||
_action->setCurrentIndex(
|
||||
_action->findData(static_cast<int>(_entryData->_action)));
|
||||
_rotation->SetValue(_entryData->_rotation);
|
||||
_settings->setPlainText(_entryData->_settings);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::SceneChanged(const SceneSelection &s)
|
||||
@@ -196,6 +450,30 @@ void MacroActionSceneTransformEdit::SourceChanged(const SceneItemSelection &item
|
||||
_entryData->_source = item;
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::ActionChanged(int idx)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_action = static_cast<MacroActionSceneTransform::Action>(
|
||||
_action->itemData(idx).toInt());
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::RotationChanged(const DoubleVariable &value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_rotation = value;
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::GetSettingsClicked()
|
||||
@@ -211,9 +489,6 @@ void MacroActionSceneTransformEdit::GetSettingsClicked()
|
||||
|
||||
auto settings = GetSceneItemTransform(items[0]);
|
||||
_settings->setPlainText(FormatJsonString(settings));
|
||||
for (auto item : items) {
|
||||
obs_sceneitem_release(item);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::SettingsChanged()
|
||||
@@ -229,4 +504,19 @@ void MacroActionSceneTransformEdit::SettingsChanged()
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionSceneTransformEdit::SetWidgetVisibility()
|
||||
{
|
||||
SetLayoutVisible(
|
||||
_buttonLayout,
|
||||
_entryData->_action ==
|
||||
MacroActionSceneTransform::Action::MANUAL_TRANSFORM);
|
||||
_settings->setVisible(
|
||||
_entryData->_action ==
|
||||
MacroActionSceneTransform::Action::MANUAL_TRANSFORM);
|
||||
_rotation->setVisible(_entryData->_action ==
|
||||
MacroActionSceneTransform::Action::ROTATE);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "scene-selection.hpp"
|
||||
#include "scene-item-selection.hpp"
|
||||
#include "variable-text-edit.hpp"
|
||||
#include "variable-spinbox.hpp"
|
||||
|
||||
#include <QSpinBox>
|
||||
|
||||
@@ -22,11 +23,27 @@ public:
|
||||
return std::make_shared<MacroActionSceneTransform>(m);
|
||||
}
|
||||
|
||||
enum class Action {
|
||||
RESET,
|
||||
ROTATE,
|
||||
FLIP_HORIZONTAL,
|
||||
FLIP_VERTICAL,
|
||||
FIT_TO_SCREEN,
|
||||
STRETCH_TO_SCREEN,
|
||||
CENTER_TO_SCREEN,
|
||||
CENTER_VERTICALLY,
|
||||
CENTER_HORIZONTALLY,
|
||||
MANUAL_TRANSFORM = 100,
|
||||
};
|
||||
|
||||
Action _action = Action::RESET;
|
||||
SceneSelection _scene;
|
||||
SceneItemSelection _source;
|
||||
StringVariable _settings = "";
|
||||
DoubleVariable _rotation = 90.0;
|
||||
|
||||
private:
|
||||
void Transform(obs_scene_item *);
|
||||
void ApplySettings(const std::string &);
|
||||
std::string ConvertSettings();
|
||||
|
||||
@@ -57,19 +74,25 @@ public:
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceChanged(const SceneItemSelection &);
|
||||
void ActionChanged(int);
|
||||
void RotationChanged(const NumberVariable<double> &value);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
|
||||
SceneSelectionWidget *_scenes;
|
||||
SceneItemSelectionWidget *_sources;
|
||||
QComboBox *_action;
|
||||
VariableDoubleSpinBox *_rotation;
|
||||
QPushButton *_getSettings;
|
||||
VariableTextEdit *_settings;
|
||||
std::shared_ptr<MacroActionSceneTransform> _entryData;
|
||||
QHBoxLayout *_buttonLayout;
|
||||
|
||||
private:
|
||||
std::shared_ptr<MacroActionSceneTransform> _entryData;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -11,85 +11,38 @@ bool MacroActionSceneVisibility::_registered = MacroActionFactory::Register(
|
||||
MacroActionSceneVisibilityEdit::Create,
|
||||
"AdvSceneSwitcher.action.sceneVisibility"});
|
||||
|
||||
const static std::map<SceneVisibilityAction, std::string> actionTypes = {
|
||||
{SceneVisibilityAction::SHOW,
|
||||
"AdvSceneSwitcher.action.sceneVisibility.type.show"},
|
||||
{SceneVisibilityAction::HIDE,
|
||||
"AdvSceneSwitcher.action.sceneVisibility.type.hide"},
|
||||
{SceneVisibilityAction::TOGGLE,
|
||||
"AdvSceneSwitcher.action.sceneVisibility.type.toggle"},
|
||||
};
|
||||
|
||||
const static std::map<SceneItemSourceType, std::string> sourceItemSourceTypes = {
|
||||
{SceneItemSourceType::SOURCE,
|
||||
"AdvSceneSwitcher.action.sceneVisibility.type.source"},
|
||||
{SceneItemSourceType::SOURCE_GROUP,
|
||||
"AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup"},
|
||||
};
|
||||
|
||||
struct VisibilityData {
|
||||
std::string name;
|
||||
SceneVisibilityAction action;
|
||||
const static std::map<MacroActionSceneVisibility::Action, std::string>
|
||||
actionTypes = {
|
||||
{MacroActionSceneVisibility::Action::SHOW,
|
||||
"AdvSceneSwitcher.action.sceneVisibility.type.show"},
|
||||
{MacroActionSceneVisibility::Action::HIDE,
|
||||
"AdvSceneSwitcher.action.sceneVisibility.type.hide"},
|
||||
{MacroActionSceneVisibility::Action::TOGGLE,
|
||||
"AdvSceneSwitcher.action.sceneVisibility.type.toggle"},
|
||||
};
|
||||
|
||||
static void setSceneItemVisibility(obs_sceneitem_t *item,
|
||||
SceneVisibilityAction action)
|
||||
MacroActionSceneVisibility::Action action)
|
||||
{
|
||||
switch (action) {
|
||||
case SceneVisibilityAction::SHOW:
|
||||
case MacroActionSceneVisibility::Action::SHOW:
|
||||
obs_sceneitem_set_visible(item, true);
|
||||
break;
|
||||
case SceneVisibilityAction::HIDE:
|
||||
case MacroActionSceneVisibility::Action::HIDE:
|
||||
obs_sceneitem_set_visible(item, false);
|
||||
break;
|
||||
case SceneVisibilityAction::TOGGLE:
|
||||
case MacroActionSceneVisibility::Action::TOGGLE:
|
||||
obs_sceneitem_set_visible(item, !obs_sceneitem_visible(item));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static bool visibilitySourceTypeEnum(obs_scene_t *, obs_sceneitem_t *item,
|
||||
void *ptr)
|
||||
{
|
||||
VisibilityData *vInfo = reinterpret_cast<VisibilityData *>(ptr);
|
||||
|
||||
auto sourceTypeName = obs_source_get_display_name(
|
||||
obs_source_get_id(obs_sceneitem_get_source(item)));
|
||||
if (sourceTypeName && vInfo->name == sourceTypeName) {
|
||||
setSceneItemVisibility(item, vInfo->action);
|
||||
}
|
||||
|
||||
if (obs_sceneitem_is_group(item)) {
|
||||
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
||||
obs_scene_enum_items(scene, visibilitySourceTypeEnum, ptr);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroActionSceneVisibility::PerformAction()
|
||||
{
|
||||
switch (_sourceType) {
|
||||
case SceneItemSourceType::SOURCE: {
|
||||
auto items = _source.GetSceneItems(_scene);
|
||||
for (auto item : items) {
|
||||
setSceneItemVisibility(item, _action);
|
||||
obs_sceneitem_release(item);
|
||||
}
|
||||
break;
|
||||
auto items = _source.GetSceneItems(_scene);
|
||||
for (const auto &item : items) {
|
||||
setSceneItemVisibility(item, _action);
|
||||
}
|
||||
case SceneItemSourceType::SOURCE_GROUP: {
|
||||
auto s = obs_weak_source_get_source(_scene.GetScene());
|
||||
auto scene = obs_scene_from_source(s);
|
||||
VisibilityData vInfo = {_sourceGroup, _action};
|
||||
obs_scene_enum_items(scene, visibilitySourceTypeEnum, &vInfo);
|
||||
obs_source_release(s);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -97,18 +50,11 @@ void MacroActionSceneVisibility::LogAction() const
|
||||
{
|
||||
auto it = actionTypes.find(_action);
|
||||
if (it != actionTypes.end()) {
|
||||
if (_sourceType == SceneItemSourceType::SOURCE) {
|
||||
vblog(LOG_INFO,
|
||||
"performed visibility action \"%s\" for source \"%s\" on scene \"%s\"",
|
||||
it->second.c_str(),
|
||||
_source.ToString(true).c_str(),
|
||||
_scene.ToString(true).c_str());
|
||||
} else {
|
||||
vblog(LOG_INFO,
|
||||
"performed visibility action \"%s\" for any source type \"%s\" on scene \"%s\"",
|
||||
it->second.c_str(), _sourceGroup.c_str(),
|
||||
_scene.ToString(true).c_str());
|
||||
}
|
||||
vblog(LOG_INFO,
|
||||
"performed visibility action \"%s\" for source \"%s\" on scene \"%s\"",
|
||||
it->second.c_str(), _source.ToString(true).c_str(),
|
||||
_scene.ToString(true).c_str());
|
||||
|
||||
} else {
|
||||
blog(LOG_WARNING, "ignored unknown SceneVisibility action %d",
|
||||
static_cast<int>(_action));
|
||||
@@ -119,13 +65,8 @@ bool MacroActionSceneVisibility::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
_scene.Save(obj);
|
||||
if (_sourceType == SceneItemSourceType::SOURCE) {
|
||||
_source.Save(obj);
|
||||
} else {
|
||||
obs_data_set_string(obj, "sourceGroup", _sourceGroup.c_str());
|
||||
}
|
||||
_source.Save(obj);
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
obs_data_set_int(obj, "sourceType", static_cast<int>(_sourceType));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -136,89 +77,64 @@ bool MacroActionSceneVisibility::Load(obs_data_t *obj)
|
||||
if (obs_data_has_user_value(obj, "source")) {
|
||||
auto sourceName = obs_data_get_string(obj, "source");
|
||||
obs_data_set_string(obj, "sceneItem", sourceName);
|
||||
obs_data_set_string(obj, "sourceGroup", sourceName);
|
||||
}
|
||||
|
||||
MacroAction::Load(obj);
|
||||
_scene.Load(obj);
|
||||
_source.Load(obj);
|
||||
_sourceType = static_cast<SceneItemSourceType>(
|
||||
obs_data_get_int(obj, "sourceType"));
|
||||
_sourceGroup = obs_data_get_string(obj, "sourceGroup");
|
||||
_action = static_cast<SceneVisibilityAction>(
|
||||
_action = static_cast<MacroActionSceneVisibility::Action>(
|
||||
obs_data_get_int(obj, "action"));
|
||||
|
||||
// TODO: Remove in future version
|
||||
if (obs_data_get_int(obj, "sourceType") != 0) {
|
||||
auto sourceGroup = obs_data_get_string(obj, "sourceGroup");
|
||||
_source.SetSourceTypeSelection(sourceGroup);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroActionSceneVisibility::GetShortDesc() const
|
||||
{
|
||||
if (_sourceType == SceneItemSourceType::SOURCE &&
|
||||
!_source.ToString().empty()) {
|
||||
if (!_source.ToString().empty()) {
|
||||
return _scene.ToString() + " - " + _source.ToString();
|
||||
}
|
||||
if (_sourceType == SceneItemSourceType::SOURCE_GROUP &&
|
||||
!_sourceGroup.empty()) {
|
||||
return _scene.ToString() + " - " +
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup") +
|
||||
" " + _sourceGroup;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void populateSourceItemTypeSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : sourceItemSourceTypes) {
|
||||
for (const auto &entry : actionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionSceneVisibilityEdit::MacroActionSceneVisibilityEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionSceneVisibility> entryData)
|
||||
: QWidget(parent)
|
||||
: QWidget(parent),
|
||||
_scenes(new SceneSelectionWidget(window(), true, false, true, true)),
|
||||
_sources(new SceneItemSelectionWidget(parent)),
|
||||
_actions(new QComboBox())
|
||||
{
|
||||
_scenes = new SceneSelectionWidget(window(), true, false, true, true);
|
||||
_sourceTypes = new QComboBox();
|
||||
_sources = new SceneItemSelectionWidget(parent);
|
||||
_sourceGroups = new QComboBox();
|
||||
_actions = new QComboBox();
|
||||
|
||||
populateSourceItemTypeSelection(_sourceTypes);
|
||||
PopulateSourceGroupSelection(_sourceGroups);
|
||||
populateActionSelection(_actions);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
this, SLOT(SceneChanged(const SceneSelection &)));
|
||||
QWidget::connect(_sourceTypes, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(SourceTypeChanged(int)));
|
||||
QWidget::connect(_scenes, SIGNAL(SceneChanged(const SceneSelection &)),
|
||||
_sources, SLOT(SceneChanged(const SceneSelection &)));
|
||||
QWidget::connect(_sources,
|
||||
SIGNAL(SceneItemChanged(const SceneItemSelection &)),
|
||||
this, SLOT(SourceChanged(const SceneItemSelection &)));
|
||||
QWidget::connect(_sourceGroups,
|
||||
SIGNAL(currentTextChanged(const QString &)), this,
|
||||
SLOT(SourceGroupChanged(const QString &)));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{scenes}}", _scenes}, {"{{sourceTypes}}", _sourceTypes},
|
||||
{"{{sources}}", _sources}, {"{{sourceGroups}}", _sourceGroups},
|
||||
{"{{actions}}", _actions},
|
||||
};
|
||||
auto layout = new QHBoxLayout;
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.action.sceneVisibility.entry"),
|
||||
mainLayout, widgetPlaceholders);
|
||||
setLayout(mainLayout);
|
||||
layout,
|
||||
{{"{{scenes}}", _scenes},
|
||||
{"{{sources}}", _sources},
|
||||
{"{{actions}}", _actions}});
|
||||
setLayout(layout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
@@ -232,13 +148,8 @@ void MacroActionSceneVisibilityEdit::UpdateEntryData()
|
||||
}
|
||||
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_sourceTypes->setCurrentIndex(
|
||||
static_cast<int>(_entryData->_sourceType));
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
_sources->SetSceneItem((_entryData->_source));
|
||||
_sourceGroups->setCurrentText(
|
||||
QString::fromStdString(_entryData->_sourceGroup));
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::SceneChanged(const SceneSelection &s)
|
||||
@@ -251,17 +162,6 @@ void MacroActionSceneVisibilityEdit::SceneChanged(const SceneSelection &s)
|
||||
_entryData->_scene = s;
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::SourceTypeChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_sourceType = static_cast<SceneItemSourceType>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::SourceChanged(
|
||||
const SceneItemSelection &item)
|
||||
{
|
||||
@@ -273,22 +173,8 @@ void MacroActionSceneVisibilityEdit::SourceChanged(
|
||||
_entryData->_source = item;
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::SourceGroupChanged(const QString &text)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
if (text == obs_module_text("AdvSceneSwitcher.selectItem")) {
|
||||
_entryData->_sourceGroup = "";
|
||||
} else {
|
||||
_entryData->_sourceGroup = text.toStdString();
|
||||
}
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::ActionChanged(int value)
|
||||
@@ -298,19 +184,8 @@ void MacroActionSceneVisibilityEdit::ActionChanged(int value)
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_action = static_cast<SceneVisibilityAction>(value);
|
||||
}
|
||||
|
||||
void MacroActionSceneVisibilityEdit::SetWidgetVisibility()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
_sources->setVisible(_entryData->_sourceType ==
|
||||
SceneItemSourceType::SOURCE);
|
||||
_sourceGroups->setVisible(_entryData->_sourceType ==
|
||||
SceneItemSourceType::SOURCE_GROUP);
|
||||
adjustSize();
|
||||
_entryData->_action =
|
||||
static_cast<MacroActionSceneVisibility::Action>(value);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -7,17 +7,6 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
enum class SceneVisibilityAction {
|
||||
SHOW,
|
||||
HIDE,
|
||||
TOGGLE,
|
||||
};
|
||||
|
||||
enum class SceneItemSourceType {
|
||||
SOURCE,
|
||||
SOURCE_GROUP,
|
||||
};
|
||||
|
||||
class MacroActionSceneVisibility : public MacroAction {
|
||||
public:
|
||||
MacroActionSceneVisibility(Macro *m) : MacroAction(m) {}
|
||||
@@ -33,10 +22,14 @@ public:
|
||||
}
|
||||
|
||||
SceneSelection _scene;
|
||||
SceneItemSourceType _sourceType = SceneItemSourceType::SOURCE;
|
||||
SceneItemSelection _source;
|
||||
std::string _sourceGroup = "";
|
||||
SceneVisibilityAction _action = SceneVisibilityAction::SHOW;
|
||||
|
||||
enum class Action {
|
||||
SHOW,
|
||||
HIDE,
|
||||
TOGGLE,
|
||||
};
|
||||
Action _action = Action::SHOW;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
@@ -62,25 +55,18 @@ public:
|
||||
|
||||
private slots:
|
||||
void SceneChanged(const SceneSelection &);
|
||||
void SourceTypeChanged(int value);
|
||||
void SourceChanged(const SceneItemSelection &);
|
||||
void SourceGroupChanged(const QString &text);
|
||||
void ActionChanged(int value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
SceneSelectionWidget *_scenes;
|
||||
QComboBox *_sourceTypes;
|
||||
SceneItemSelectionWidget *_sources;
|
||||
QComboBox *_sourceGroups;
|
||||
QComboBox *_actions;
|
||||
std::shared_ptr<MacroActionSceneVisibility> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
|
||||
QHBoxLayout *_mainLayout;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ bool MacroActionSequence::PerformAction()
|
||||
return true;
|
||||
}
|
||||
|
||||
return macro->PerformActions();
|
||||
return macro->PerformActions(true);
|
||||
}
|
||||
|
||||
void MacroActionSequence::LogAction() const
|
||||
|
||||
@@ -12,15 +12,52 @@ bool MacroActionSource::_registered = MacroActionFactory::Register(
|
||||
{MacroActionSource::Create, MacroActionSourceEdit::Create,
|
||||
"AdvSceneSwitcher.action.source"});
|
||||
|
||||
const static std::map<SourceAction, std::string> actionTypes = {
|
||||
{SourceAction::ENABLE, "AdvSceneSwitcher.action.source.type.enable"},
|
||||
{SourceAction::DISABLE, "AdvSceneSwitcher.action.source.type.disable"},
|
||||
{SourceAction::SETTINGS,
|
||||
const static std::map<MacroActionSource::Action, std::string> actionTypes = {
|
||||
{MacroActionSource::Action::ENABLE,
|
||||
"AdvSceneSwitcher.action.source.type.enable"},
|
||||
{MacroActionSource::Action::DISABLE,
|
||||
"AdvSceneSwitcher.action.source.type.disable"},
|
||||
{MacroActionSource::Action::SETTINGS,
|
||||
"AdvSceneSwitcher.action.source.type.settings"},
|
||||
{SourceAction::REFRESH_SETTINGS,
|
||||
{MacroActionSource::Action::REFRESH_SETTINGS,
|
||||
"AdvSceneSwitcher.action.source.type.refreshSettings"},
|
||||
{SourceAction::SETTINGS_BUTTON,
|
||||
{MacroActionSource::Action::SETTINGS_BUTTON,
|
||||
"AdvSceneSwitcher.action.source.type.pressSettingsButton"},
|
||||
{MacroActionSource::Action::DEINTERLACE_MODE,
|
||||
"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"},
|
||||
};
|
||||
|
||||
const static std::map<obs_deinterlace_mode, std::string> deinterlaceModes = {
|
||||
{OBS_DEINTERLACE_MODE_DISABLE,
|
||||
"AdvSceneSwitcher.action.source.deinterlaceMode.disable"},
|
||||
{OBS_DEINTERLACE_MODE_DISCARD,
|
||||
"AdvSceneSwitcher.action.source.deinterlaceMode.disable"},
|
||||
{OBS_DEINTERLACE_MODE_RETRO,
|
||||
"AdvSceneSwitcher.action.source.deinterlaceMode.retro"},
|
||||
{OBS_DEINTERLACE_MODE_BLEND,
|
||||
"AdvSceneSwitcher.action.source.deinterlaceMode.blend"},
|
||||
{OBS_DEINTERLACE_MODE_BLEND_2X,
|
||||
"AdvSceneSwitcher.action.source.deinterlaceMode.blend2x"},
|
||||
{OBS_DEINTERLACE_MODE_LINEAR,
|
||||
"AdvSceneSwitcher.action.source.deinterlaceMode.linear"},
|
||||
{OBS_DEINTERLACE_MODE_LINEAR_2X,
|
||||
"AdvSceneSwitcher.action.source.deinterlaceMode.linear2x"},
|
||||
{OBS_DEINTERLACE_MODE_YADIF,
|
||||
"AdvSceneSwitcher.action.source.deinterlaceMode.yadif"},
|
||||
{OBS_DEINTERLACE_MODE_YADIF_2X,
|
||||
"AdvSceneSwitcher.action.source.deinterlaceMode.yadif2x"},
|
||||
};
|
||||
|
||||
const static std::map<obs_deinterlace_field_order, std::string>
|
||||
deinterlaceFieldOrders = {
|
||||
{OBS_DEINTERLACE_FIELD_ORDER_TOP,
|
||||
"AdvSceneSwitcher.action.source.deinterlaceOrder.topFieldFirst"},
|
||||
{OBS_DEINTERLACE_FIELD_ORDER_BOTTOM,
|
||||
"AdvSceneSwitcher.action.source.deinterlaceOrder.bottomFieldFirst"},
|
||||
};
|
||||
|
||||
static std::vector<SourceSettingButton> getSourceButtons(OBSWeakSource source)
|
||||
@@ -75,25 +112,47 @@ 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());
|
||||
switch (_action) {
|
||||
case SourceAction::ENABLE:
|
||||
case Action::ENABLE:
|
||||
obs_source_set_enabled(s, true);
|
||||
break;
|
||||
case SourceAction::DISABLE:
|
||||
case Action::DISABLE:
|
||||
obs_source_set_enabled(s, false);
|
||||
break;
|
||||
case SourceAction::SETTINGS:
|
||||
case Action::SETTINGS:
|
||||
SetSourceSettings(s, _settings);
|
||||
break;
|
||||
case SourceAction::REFRESH_SETTINGS:
|
||||
case Action::REFRESH_SETTINGS:
|
||||
refreshSourceSettings(s);
|
||||
break;
|
||||
case SourceAction::SETTINGS_BUTTON:
|
||||
case Action::SETTINGS_BUTTON:
|
||||
pressSourceButton(_button, s);
|
||||
break;
|
||||
case Action::DEINTERLACE_MODE:
|
||||
obs_source_set_deinterlace_mode(s, _deinterlaceMode);
|
||||
break;
|
||||
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;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -120,6 +179,10 @@ bool MacroActionSource::Save(obs_data_t *obj) const
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
_button.Save(obj);
|
||||
_settings.Save(obj, "settings");
|
||||
obs_data_set_int(obj, "deinterlaceMode",
|
||||
static_cast<int>(_deinterlaceMode));
|
||||
obs_data_set_int(obj, "deinterlaceOrder",
|
||||
static_cast<int>(_deinterlaceOrder));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -127,9 +190,13 @@ bool MacroActionSource::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_source.Load(obj);
|
||||
_action = static_cast<SourceAction>(obs_data_get_int(obj, "action"));
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
_button.Load(obj);
|
||||
_settings.Load(obj, "settings");
|
||||
_deinterlaceMode = static_cast<obs_deinterlace_mode>(
|
||||
obs_data_get_int(obj, "deinterlaceMode"));
|
||||
_deinterlaceOrder = static_cast<obs_deinterlace_field_order>(
|
||||
obs_data_get_int(obj, "deinterlaceOrder"));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -143,7 +210,7 @@ static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto &[actionType, name] : actionTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()));
|
||||
if (actionType == SourceAction::REFRESH_SETTINGS) {
|
||||
if (actionType == MacroActionSource::Action::REFRESH_SETTINGS) {
|
||||
list->setItemData(
|
||||
list->count() - 1,
|
||||
obs_module_text(
|
||||
@@ -170,23 +237,44 @@ static inline void populateSourceButtonSelection(QComboBox *list,
|
||||
}
|
||||
}
|
||||
|
||||
static inline void populateDeinterlaceModeSelection(QComboBox *list)
|
||||
{
|
||||
list->clear();
|
||||
for (const auto &[value, name] : deinterlaceModes) {
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(value));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void populateDeinterlaceFieldOrderSelection(QComboBox *list)
|
||||
{
|
||||
list->clear();
|
||||
for (const auto &[value, name] : deinterlaceFieldOrders) {
|
||||
list->addItem(obs_module_text(name.c_str()),
|
||||
static_cast<int>(value));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionSourceEdit::MacroActionSourceEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionSource> entryData)
|
||||
: QWidget(parent)
|
||||
: QWidget(parent),
|
||||
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
||||
_actions(new QComboBox()),
|
||||
_settingsButtons(new QComboBox()),
|
||||
_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")))
|
||||
{
|
||||
_sources = new SourceSelectionWidget(this, QStringList(), true);
|
||||
_actions = new QComboBox();
|
||||
_settingsButtons = new QComboBox();
|
||||
_getSettings = new QPushButton(
|
||||
obs_module_text("AdvSceneSwitcher.action.source.getSettings"));
|
||||
_settings = new VariableTextEdit(this);
|
||||
_warning = new QLabel(
|
||||
obs_module_text("AdvSceneSwitcher.action.source.warning"));
|
||||
|
||||
populateActionSelection(_actions);
|
||||
auto sources = GetSourceNames();
|
||||
sources.sort();
|
||||
_sources->SetSourceNameList(sources);
|
||||
populateDeinterlaceModeSelection(_deinterlaceMode);
|
||||
populateDeinterlaceFieldOrderSelection(_deinterlaceOrder);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
@@ -199,6 +287,10 @@ MacroActionSourceEdit::MacroActionSourceEdit(
|
||||
SLOT(GetSettingsClicked()));
|
||||
QWidget::connect(_settings, SIGNAL(textChanged()), this,
|
||||
SLOT(SettingsChanged()));
|
||||
QWidget::connect(_deinterlaceMode, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(DeinterlaceModeChanged(int)));
|
||||
QWidget::connect(_deinterlaceOrder, SIGNAL(currentIndexChanged(int)),
|
||||
this, SLOT(DeinterlaceOrderChanged(int)));
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
QHBoxLayout *entryLayout = new QHBoxLayout;
|
||||
@@ -209,6 +301,8 @@ MacroActionSourceEdit::MacroActionSourceEdit(
|
||||
{"{{settings}}", _settings},
|
||||
{"{{getSettings}}", _getSettings},
|
||||
{"{{settingsButtons}}", _settingsButtons},
|
||||
{"{{deinterlaceMode}}", _deinterlaceMode},
|
||||
{"{{deinterlaceOrder}}", _deinterlaceOrder},
|
||||
};
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.source.entry"),
|
||||
entryLayout, widgetPlaceholders);
|
||||
@@ -238,10 +332,11 @@ void MacroActionSourceEdit::UpdateEntryData()
|
||||
_settingsButtons->setCurrentText(
|
||||
QString::fromStdString(_entryData->_button.ToString()));
|
||||
_settings->setPlainText(_entryData->_settings);
|
||||
_deinterlaceMode->setCurrentIndex(_deinterlaceMode->findData(
|
||||
static_cast<int>(_entryData->_deinterlaceMode)));
|
||||
_deinterlaceOrder->setCurrentIndex(_deinterlaceOrder->findData(
|
||||
static_cast<int>(_entryData->_deinterlaceOrder)));
|
||||
SetWidgetVisibility();
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionSourceEdit::SourceChanged(const SourceSelection &source)
|
||||
@@ -267,7 +362,7 @@ void MacroActionSourceEdit::ActionChanged(int value)
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_action = static_cast<SourceAction>(value);
|
||||
_entryData->_action = static_cast<MacroActionSource::Action>(value);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
@@ -305,17 +400,50 @@ void MacroActionSourceEdit::SettingsChanged()
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionSourceEdit::DeinterlaceModeChanged(int idx)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_deinterlaceMode = static_cast<obs_deinterlace_mode>(
|
||||
_deinterlaceMode->itemData(idx).toInt());
|
||||
}
|
||||
|
||||
void MacroActionSourceEdit::DeinterlaceOrderChanged(int idx)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_deinterlaceOrder =
|
||||
static_cast<obs_deinterlace_field_order>(
|
||||
_deinterlaceOrder->itemData(idx).toInt());
|
||||
}
|
||||
|
||||
void MacroActionSourceEdit::SetWidgetVisibility()
|
||||
{
|
||||
const bool showSettings = _entryData->_action == SourceAction::SETTINGS;
|
||||
const bool showWarning = _entryData->_action == SourceAction::ENABLE ||
|
||||
_entryData->_action == SourceAction::DISABLE;
|
||||
const bool showSettings = _entryData->_action ==
|
||||
MacroActionSource::Action::SETTINGS;
|
||||
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 ==
|
||||
SourceAction::SETTINGS_BUTTON);
|
||||
_settingsButtons->setVisible(
|
||||
_entryData->_action ==
|
||||
MacroActionSource::Action::SETTINGS_BUTTON);
|
||||
_deinterlaceMode->setVisible(
|
||||
_entryData->_action ==
|
||||
MacroActionSource::Action::DEINTERLACE_MODE);
|
||||
_deinterlaceOrder->setVisible(
|
||||
_entryData->_action ==
|
||||
MacroActionSource::Action::DEINTERLACE_FIELD_ORDER);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
bool SourceSettingButton::Save(obs_data_t *obj) const
|
||||
|
||||
@@ -10,14 +10,6 @@
|
||||
|
||||
namespace advss {
|
||||
|
||||
enum class SourceAction {
|
||||
ENABLE,
|
||||
DISABLE,
|
||||
SETTINGS,
|
||||
REFRESH_SETTINGS,
|
||||
SETTINGS_BUTTON,
|
||||
};
|
||||
|
||||
struct SourceSettingButton {
|
||||
bool Save(obs_data_t *obj) const;
|
||||
bool Load(obs_data_t *obj);
|
||||
@@ -44,7 +36,21 @@ public:
|
||||
SourceSelection _source;
|
||||
SourceSettingButton _button;
|
||||
StringVariable _settings = "";
|
||||
SourceAction _action = SourceAction::ENABLE;
|
||||
obs_deinterlace_mode _deinterlaceMode = OBS_DEINTERLACE_MODE_DISABLE;
|
||||
obs_deinterlace_field_order _deinterlaceOrder =
|
||||
OBS_DEINTERLACE_FIELD_ORDER_TOP;
|
||||
|
||||
enum class Action {
|
||||
ENABLE,
|
||||
DISABLE,
|
||||
SETTINGS,
|
||||
REFRESH_SETTINGS,
|
||||
SETTINGS_BUTTON,
|
||||
DEINTERLACE_MODE,
|
||||
DEINTERLACE_FIELD_ORDER,
|
||||
OPEN_INTERACTION_DIALOG,
|
||||
};
|
||||
Action _action = Action::ENABLE;
|
||||
|
||||
private:
|
||||
static bool _registered;
|
||||
@@ -73,6 +79,8 @@ private slots:
|
||||
void ButtonChanged(int idx);
|
||||
void GetSettingsClicked();
|
||||
void SettingsChanged();
|
||||
void DeinterlaceModeChanged(int);
|
||||
void DeinterlaceOrderChanged(int);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
@@ -82,6 +90,8 @@ protected:
|
||||
QComboBox *_settingsButtons;
|
||||
QPushButton *_getSettings;
|
||||
VariableTextEdit *_settings;
|
||||
QComboBox *_deinterlaceMode;
|
||||
QComboBox *_deinterlaceOrder;
|
||||
QLabel *_warning;
|
||||
std::shared_ptr<MacroActionSource> _entryData;
|
||||
|
||||
|
||||
@@ -19,26 +19,65 @@ const static std::map<MacroActionStream::Action, std::string> actionTypes = {
|
||||
"AdvSceneSwitcher.action.streaming.type.start"},
|
||||
{MacroActionStream::Action::KEYFRAME_INTERVAL,
|
||||
"AdvSceneSwitcher.action.streaming.type.keyFrameInterval"},
|
||||
{MacroActionStream::Action::SERVER,
|
||||
"AdvSceneSwitcher.action.streaming.type.server"},
|
||||
{MacroActionStream::Action::STREAM_KEY,
|
||||
"AdvSceneSwitcher.action.streaming.type.streamKey"},
|
||||
{MacroActionStream::Action::USERNAME,
|
||||
"AdvSceneSwitcher.action.streaming.type.username"},
|
||||
{MacroActionStream::Action::PASSWORD,
|
||||
"AdvSceneSwitcher.action.streaming.type.password"},
|
||||
};
|
||||
|
||||
constexpr int streamStartCooldown = 5;
|
||||
std::chrono::high_resolution_clock::time_point MacroActionStream::s_lastAttempt =
|
||||
std::chrono::high_resolution_clock::now();
|
||||
|
||||
void MacroActionStream::SetKeyFrameInterval()
|
||||
void MacroActionStream::SetKeyFrameInterval() const
|
||||
{
|
||||
const auto configPath = GetPathInProfileDir("streamEncoder.json");
|
||||
obs_data_t *settings =
|
||||
auto settings =
|
||||
obs_data_create_from_json_file_safe(configPath.c_str(), "bak");
|
||||
obs_data_set_int(settings, "keyint_sec", _keyFrameInterval);
|
||||
if (settings) {
|
||||
obs_data_save_json_safe(settings, configPath.c_str(), "tmp",
|
||||
"bak");
|
||||
obs_data_release(settings);
|
||||
if (!settings) {
|
||||
blog(LOG_WARNING, "failed to set key frame interval");
|
||||
return;
|
||||
}
|
||||
obs_data_set_int(settings, "keyint_sec", _keyFrameInterval);
|
||||
obs_data_save_json_safe(settings, configPath.c_str(), "tmp", "bak");
|
||||
obs_data_release(settings);
|
||||
}
|
||||
|
||||
bool MacroActionStream::CooldownDurationReached()
|
||||
void MacroActionStream::SetStreamSettingsValue(const char *name,
|
||||
const std::string &value,
|
||||
bool enableAuth) const
|
||||
{
|
||||
const auto configPath = GetPathInProfileDir("service.json");
|
||||
auto data =
|
||||
obs_data_create_from_json_file_safe(configPath.c_str(), "bak");
|
||||
if (!data) {
|
||||
blog(LOG_WARNING, "failed to set %s", name);
|
||||
return;
|
||||
}
|
||||
auto settings = obs_data_get_obj(data, "settings");
|
||||
if (!settings) {
|
||||
blog(LOG_WARNING, "failed to set %s", name);
|
||||
obs_data_release(data);
|
||||
return;
|
||||
}
|
||||
obs_data_set_string(settings, name, value.c_str());
|
||||
if (enableAuth) {
|
||||
obs_data_set_bool(settings, "use_auth", true);
|
||||
}
|
||||
obs_data_set_obj(data, "settings", settings);
|
||||
auto service = obs_frontend_get_streaming_service();
|
||||
obs_service_update(service, settings);
|
||||
obs_frontend_save_streaming_service();
|
||||
obs_frontend_set_streaming_service(service);
|
||||
obs_data_release(settings);
|
||||
obs_data_release(data);
|
||||
}
|
||||
|
||||
bool MacroActionStream::CooldownDurationReached() const
|
||||
{
|
||||
auto timePassed = std::chrono::duration_cast<std::chrono::seconds>(
|
||||
std::chrono::high_resolution_clock::now() - s_lastAttempt);
|
||||
@@ -64,6 +103,18 @@ bool MacroActionStream::PerformAction()
|
||||
case Action::KEYFRAME_INTERVAL:
|
||||
SetKeyFrameInterval();
|
||||
break;
|
||||
case Action::SERVER:
|
||||
SetStreamSettingsValue("server", _stringValue);
|
||||
break;
|
||||
case Action::STREAM_KEY:
|
||||
SetStreamSettingsValue("key", _stringValue);
|
||||
break;
|
||||
case Action::USERNAME:
|
||||
SetStreamSettingsValue("username", _stringValue, true);
|
||||
break;
|
||||
case Action::PASSWORD:
|
||||
SetStreamSettingsValue("password", _stringValue, true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -86,6 +137,7 @@ bool MacroActionStream::Save(obs_data_t *obj) const
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_int(obj, "action", static_cast<int>(_action));
|
||||
_keyFrameInterval.Save(obj, "keyFrameInterval");
|
||||
_stringValue.Save(obj, "stringValue");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -94,6 +146,7 @@ bool MacroActionStream::Load(obs_data_t *obj)
|
||||
MacroAction::Load(obj);
|
||||
_action = static_cast<Action>(obs_data_get_int(obj, "action"));
|
||||
_keyFrameInterval.Load(obj, "keyFrameInterval");
|
||||
_stringValue.Load(obj, "stringValue");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -108,11 +161,19 @@ MacroActionStreamEdit::MacroActionStreamEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionStream> entryData)
|
||||
: QWidget(parent),
|
||||
_actions(new QComboBox()),
|
||||
_keyFrameInterval(new VariableSpinBox())
|
||||
_keyFrameInterval(new VariableSpinBox()),
|
||||
_stringValue(new VariableLineEdit(this)),
|
||||
_showPassword(new QPushButton()),
|
||||
_layout(new QHBoxLayout())
|
||||
{
|
||||
_keyFrameInterval->setMinimum(0);
|
||||
_keyFrameInterval->setMaximum(25);
|
||||
|
||||
_showPassword->setMaximumWidth(22);
|
||||
_showPassword->setFlat(true);
|
||||
_showPassword->setStyleSheet(
|
||||
"QPushButton { background-color: transparent; border: 0px }");
|
||||
|
||||
populateActionSelection(_actions);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
@@ -122,13 +183,20 @@ MacroActionStreamEdit::MacroActionStreamEdit(
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||
this,
|
||||
SLOT(KeyFrameIntervalChanged(const NumberVariable<int> &)));
|
||||
QWidget::connect(_stringValue, SIGNAL(editingFinished()), this,
|
||||
SLOT(StringValueChanged()));
|
||||
QWidget::connect(_showPassword, SIGNAL(pressed()), this,
|
||||
SLOT(ShowPassword()));
|
||||
QWidget::connect(_showPassword, SIGNAL(released()), this,
|
||||
SLOT(HidePassword()));
|
||||
|
||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.streaming.entry"),
|
||||
mainLayout,
|
||||
_layout,
|
||||
{{"{{actions}}", _actions},
|
||||
{"{{keyFrameInterval}}", _keyFrameInterval}});
|
||||
setLayout(mainLayout);
|
||||
{"{{keyFrameInterval}}", _keyFrameInterval},
|
||||
{"{{stringValue}}", _stringValue},
|
||||
{"{{showPassword}}", _showPassword}});
|
||||
setLayout(_layout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
@@ -142,6 +210,7 @@ void MacroActionStreamEdit::UpdateEntryData()
|
||||
}
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||
_keyFrameInterval->SetValue(_entryData->_keyFrameInterval);
|
||||
_stringValue->setText(_entryData->_stringValue);
|
||||
SetWidgetVisiblity();
|
||||
}
|
||||
|
||||
@@ -156,15 +225,59 @@ void MacroActionStreamEdit::KeyFrameIntervalChanged(
|
||||
_entryData->_keyFrameInterval = value;
|
||||
}
|
||||
|
||||
void MacroActionStreamEdit::StringValueChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_stringValue = _stringValue->text().toStdString();
|
||||
SetWidgetVisiblity();
|
||||
}
|
||||
|
||||
void MacroActionStreamEdit::ShowPassword()
|
||||
{
|
||||
SetButtonIcon(_showPassword, ":res/images/visible.svg");
|
||||
_stringValue->setEchoMode(QLineEdit::Normal);
|
||||
}
|
||||
|
||||
void MacroActionStreamEdit::HidePassword()
|
||||
{
|
||||
SetButtonIcon(_showPassword, ":res/images/invisible.svg");
|
||||
_stringValue->setEchoMode(QLineEdit::PasswordEchoOnEdit);
|
||||
}
|
||||
|
||||
void MacroActionStreamEdit::SetWidgetVisiblity()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
const auto action = _entryData->_action;
|
||||
_keyFrameInterval->setVisible(
|
||||
_entryData->_action ==
|
||||
MacroActionStream::Action::KEYFRAME_INTERVAL);
|
||||
action == MacroActionStream::Action::KEYFRAME_INTERVAL);
|
||||
const bool modifyingStringValue =
|
||||
action == MacroActionStream::Action::SERVER ||
|
||||
action == MacroActionStream::Action::STREAM_KEY ||
|
||||
action == MacroActionStream::Action::USERNAME ||
|
||||
action == MacroActionStream::Action::PASSWORD;
|
||||
_stringValue->setVisible(modifyingStringValue);
|
||||
if (modifyingStringValue) {
|
||||
// Give as much space to string value line edit as posssible
|
||||
RemoveStretchIfPresent(_layout);
|
||||
} else {
|
||||
AddStretchIfNecessary(_layout);
|
||||
}
|
||||
if (action == MacroActionStream::Action::PASSWORD ||
|
||||
action == MacroActionStream::Action::STREAM_KEY) {
|
||||
_stringValue->setEchoMode(QLineEdit::PasswordEchoOnEdit);
|
||||
_showPassword->show();
|
||||
HidePassword();
|
||||
} else {
|
||||
_stringValue->setEchoMode(QLineEdit::Normal);
|
||||
_showPassword->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void MacroActionStreamEdit::ActionChanged(int value)
|
||||
@@ -172,9 +285,12 @@ void MacroActionStreamEdit::ActionChanged(int value)
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_action = static_cast<MacroActionStream::Action>(value);
|
||||
{
|
||||
auto lock = LockContext();
|
||||
_entryData->_action =
|
||||
static_cast<MacroActionStream::Action>(value);
|
||||
}
|
||||
_stringValue->setText(QString(""));
|
||||
SetWidgetVisiblity();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "variable-spinbox.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
|
||||
#include <QDoubleSpinBox>
|
||||
#include <QComboBox>
|
||||
@@ -26,13 +27,20 @@ public:
|
||||
STOP,
|
||||
START,
|
||||
KEYFRAME_INTERVAL,
|
||||
SERVER,
|
||||
STREAM_KEY,
|
||||
USERNAME,
|
||||
PASSWORD,
|
||||
};
|
||||
Action _action = Action::STOP;
|
||||
NumberVariable<int> _keyFrameInterval = 0;
|
||||
IntVariable _keyFrameInterval = 0;
|
||||
StringVariable _stringValue;
|
||||
|
||||
private:
|
||||
void SetKeyFrameInterval();
|
||||
bool CooldownDurationReached();
|
||||
void SetKeyFrameInterval() const;
|
||||
void SetStreamSettingsValue(const char *name, const std::string &value,
|
||||
bool enableAuth = false) const;
|
||||
bool CooldownDurationReached() const;
|
||||
static std::chrono::high_resolution_clock::time_point s_lastAttempt;
|
||||
|
||||
static bool _registered;
|
||||
@@ -58,16 +66,21 @@ public:
|
||||
private slots:
|
||||
void ActionChanged(int value);
|
||||
void KeyFrameIntervalChanged(const NumberVariable<int> &);
|
||||
void StringValueChanged();
|
||||
void ShowPassword();
|
||||
void HidePassword();
|
||||
|
||||
protected:
|
||||
QComboBox *_actions;
|
||||
VariableSpinBox *_keyFrameInterval;
|
||||
VariableLineEdit *_stringValue;
|
||||
QPushButton *_showPassword;
|
||||
std::shared_ptr<MacroActionStream> _entryData;
|
||||
|
||||
private:
|
||||
void SetWidgetVisiblity();
|
||||
|
||||
QHBoxLayout *_mainLayout;
|
||||
QHBoxLayout *_layout;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ bool MacroActionTimer::_registered = MacroActionFactory::Register(
|
||||
{MacroActionTimer::Create, MacroActionTimerEdit::Create,
|
||||
"AdvSceneSwitcher.action.timer"});
|
||||
|
||||
static std::map<TimerAction, std::string> timerActions = {
|
||||
const static std::map<TimerAction, std::string> timerActions = {
|
||||
{TimerAction::PAUSE, "AdvSceneSwitcher.action.timer.type.pause"},
|
||||
{TimerAction::CONTINUE, "AdvSceneSwitcher.action.timer.type.continue"},
|
||||
{TimerAction::RESET, "AdvSceneSwitcher.action.timer.type.reset"},
|
||||
|
||||
@@ -88,7 +88,7 @@ void MacroActionTransition::SetSourceTransition(bool show)
|
||||
obs_source_release(transition);
|
||||
|
||||
const auto items = _source.GetSceneItems(_scene);
|
||||
for (auto &item : items) {
|
||||
for (const auto &item : items) {
|
||||
if (_setTransitionType) {
|
||||
obs_sceneitem_set_transition(item, show, t);
|
||||
}
|
||||
@@ -96,7 +96,6 @@ void MacroActionTransition::SetSourceTransition(bool show)
|
||||
obs_sceneitem_set_transition_duration(
|
||||
item, show, _duration.Milliseconds());
|
||||
}
|
||||
obs_sceneitem_release(item);
|
||||
}
|
||||
|
||||
obs_source_release(t);
|
||||
@@ -200,7 +199,7 @@ std::string MacroActionTransition::GetShortDesc() const
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
for (const auto &entry : actionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
@@ -298,6 +297,8 @@ void MacroActionTransitionEdit::SourceChanged(const SceneItemSelection &item)
|
||||
_entryData->_source = item;
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionTransitionEdit::ActionChanged(int value)
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include "advanced-scene-switcher.hpp"
|
||||
#include "macro.hpp"
|
||||
#include "math-helpers.hpp"
|
||||
#include "non-modal-dialog.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
@@ -15,7 +16,7 @@ bool MacroActionVariable::_registered = MacroActionFactory::Register(
|
||||
{MacroActionVariable::Create, MacroActionVariableEdit::Create,
|
||||
"AdvSceneSwitcher.action.variable"});
|
||||
|
||||
static std::map<MacroActionVariable::Type, std::string> actionTypes = {
|
||||
const static std::map<MacroActionVariable::Type, std::string> actionTypes = {
|
||||
{MacroActionVariable::Type::SET_FIXED_VALUE,
|
||||
"AdvSceneSwitcher.action.variable.type.set"},
|
||||
{MacroActionVariable::Type::APPEND,
|
||||
@@ -38,6 +39,12 @@ static std::map<MacroActionVariable::Type, std::string> actionTypes = {
|
||||
"AdvSceneSwitcher.action.variable.type.findAndReplace"},
|
||||
{MacroActionVariable::Type::MATH_EXPRESSION,
|
||||
"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"},
|
||||
};
|
||||
|
||||
static void apppend(Variable &var, const std::string &value)
|
||||
@@ -121,6 +128,21 @@ void MacroActionVariable::HandleMathExpression(Variable *var)
|
||||
var->SetValue(std::get<double>(result));
|
||||
}
|
||||
|
||||
struct AskForInputParams {
|
||||
QString prompt;
|
||||
QString placeholder;
|
||||
std::optional<std::string> result;
|
||||
};
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
bool MacroActionVariable::PerformAction()
|
||||
{
|
||||
auto var = _variable.lock();
|
||||
@@ -189,6 +211,33 @@ bool MacroActionVariable::PerformAction()
|
||||
HandleMathExpression(var.get());
|
||||
return true;
|
||||
}
|
||||
case Type::USER_INPUT: {
|
||||
AskForInputParams params{
|
||||
_useCustomPrompt
|
||||
? QString::fromStdString(_inputPrompt)
|
||||
: QString(obs_module_text(
|
||||
"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()) {
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -213,6 +262,12 @@ bool MacroActionVariable::Save(obs_data_t *obj) const
|
||||
obs_data_set_string(obj, "replaceStr", _replaceStr.c_str());
|
||||
_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);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -235,6 +290,12 @@ bool MacroActionVariable::Load(obs_data_t *obj)
|
||||
_findStr = obs_data_get_string(obj, "findStr");
|
||||
_replaceStr = obs_data_get_string(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);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -337,7 +398,8 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
_actions(new QComboBox()),
|
||||
_strValue(new ResizingPlainTextEdit(this, 5, 1, 1)),
|
||||
_numValue(new QDoubleSpinBox()),
|
||||
_segmentIdx(new QSpinBox()),
|
||||
_segmentIdx(new MacroSegmentSelection(
|
||||
this, MacroSegmentSelection::Type::CONDITION, false)),
|
||||
_segmentValueStatus(new QLabel()),
|
||||
_segmentValue(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
||||
_substringLayout(new QVBoxLayout()),
|
||||
@@ -352,13 +414,18 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
_findStr(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
||||
_replaceStr(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
||||
_mathExpression(new VariableLineEdit(this)),
|
||||
_mathExpressionResult(new QLabel())
|
||||
_mathExpressionResult(new QLabel()),
|
||||
_promptLayout(new QHBoxLayout()),
|
||||
_useCustomPrompt(new QCheckBox()),
|
||||
_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))
|
||||
{
|
||||
_numValue->setMinimum(-9999999999);
|
||||
_numValue->setMaximum(9999999999);
|
||||
_segmentIdx->setMinimum(0);
|
||||
_segmentIdx->setMaximum(99);
|
||||
_segmentIdx->setSpecialValueText("-");
|
||||
_segmentValue->setReadOnly(true);
|
||||
_subStringStart->setMinimum(1);
|
||||
_subStringStart->setMaximum(99999);
|
||||
@@ -371,6 +438,8 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
_regexMatchIdx->setMinimum(1);
|
||||
_regexMatchIdx->setMaximum(999);
|
||||
_regexMatchIdx->setSuffix(".");
|
||||
_inputPrompt->setSizePolicy(QSizePolicy::MinimumExpanding,
|
||||
QSizePolicy::Preferred);
|
||||
populateTypeSelection(_actions);
|
||||
|
||||
QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)),
|
||||
@@ -383,8 +452,9 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
SLOT(StrValueChanged()));
|
||||
QWidget::connect(_numValue, SIGNAL(valueChanged(double)), this,
|
||||
SLOT(NumValueChanged(double)));
|
||||
QWidget::connect(_segmentIdx, SIGNAL(valueChanged(int)), this,
|
||||
SLOT(SegmentIndexChanged(int)));
|
||||
QWidget::connect(_segmentIdx,
|
||||
SIGNAL(SelectionChanged(const IntVariable &)), this,
|
||||
SLOT(SegmentIndexChanged(const IntVariable &)));
|
||||
QWidget::connect(window(), SIGNAL(MacroSegmentOrderChanged()), this,
|
||||
SLOT(MacroSegmentOrderChanged()));
|
||||
QWidget::connect(_subStringStart, SIGNAL(valueChanged(int)), this,
|
||||
@@ -403,6 +473,18 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
SLOT(ReplaceStrValueChanged()));
|
||||
QWidget::connect(_mathExpression, SIGNAL(editingFinished()), this,
|
||||
SLOT(MathExpressionChanged()));
|
||||
QWidget::connect(_useCustomPrompt, SIGNAL(stateChanged(int)), this,
|
||||
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 &)));
|
||||
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{variables}}", _variables},
|
||||
@@ -417,6 +499,12 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
{"{{findStr}}", _findStr},
|
||||
{"{{replaceStr}}", _replaceStr},
|
||||
{"{{mathExpression}}", _mathExpression},
|
||||
{"{{useCustomPrompt}}", _useCustomPrompt},
|
||||
{"{{inputPrompt}}", _inputPrompt},
|
||||
{"{{useInputPlaceholder}}", _useInputPlaceholder},
|
||||
{"{{inputPlaceholder}}", _inputPlaceholder},
|
||||
{"{{envVariableName}}", _envVariable},
|
||||
{"{{scenes}}", _scenes},
|
||||
};
|
||||
auto entryLayout = new QHBoxLayout;
|
||||
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.variable.entry"),
|
||||
@@ -437,6 +525,15 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
"AdvSceneSwitcher.action.variable.entry.findAndReplace"),
|
||||
_findReplaceLayout, widgetPlaceholders, false);
|
||||
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"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);
|
||||
regexConfigLayout->addStretch();
|
||||
@@ -453,6 +550,8 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
||||
layout->addWidget(_segmentValue);
|
||||
layout->addLayout(_findReplaceLayout);
|
||||
layout->addWidget(_mathExpressionResult);
|
||||
layout->addLayout(_promptLayout);
|
||||
layout->addLayout(_placeholderLayout);
|
||||
setLayout(layout);
|
||||
|
||||
_entryData = entryData;
|
||||
@@ -476,7 +575,13 @@ void MacroActionVariableEdit::UpdateEntryData()
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||
_strValue->setPlainText(QString::fromStdString(_entryData->_strValue));
|
||||
_numValue->setValue(_entryData->_numValue);
|
||||
_segmentIdx->setValue(_entryData->GetSegmentIndexValue() + 1);
|
||||
_segmentIdx->SetValue(_entryData->GetSegmentIndexValue() + 1);
|
||||
_segmentIdx->SetMacro(_entryData->GetMacro());
|
||||
_segmentIdx->SetType(
|
||||
_entryData->_type ==
|
||||
MacroActionVariable::Type::SET_CONDITION_VALUE
|
||||
? MacroSegmentSelection::Type::CONDITION
|
||||
: MacroSegmentSelection::Type::ACTION);
|
||||
_subStringStart->setValue(_entryData->_subStringStart + 1);
|
||||
_subStringSize->setValue(_entryData->_subStringSize);
|
||||
_regex->SetRegexConfig(_entryData->_regex);
|
||||
@@ -487,6 +592,12 @@ void MacroActionVariableEdit::UpdateEntryData()
|
||||
_replaceStr->setPlainText(
|
||||
QString::fromStdString(_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);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
@@ -518,13 +629,14 @@ void MacroActionVariableEdit::ActionChanged(int value)
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_type = static_cast<MacroActionVariable::Type>(value);
|
||||
SetWidgetVisibility();
|
||||
|
||||
if (_entryData->_type == MacroActionVariable::Type::SET_ACTION_VALUE ||
|
||||
_entryData->_type ==
|
||||
MacroActionVariable::Type::SET_CONDITION_VALUE) {
|
||||
MarkSelectedSegment();
|
||||
if (_entryData->_type == MacroActionVariable::Type::SET_ACTION_VALUE) {
|
||||
_segmentIdx->SetType(MacroSegmentSelection::Type::ACTION);
|
||||
} else if (_entryData->_type ==
|
||||
MacroActionVariable::Type::SET_CONDITION_VALUE) {
|
||||
_segmentIdx->SetType(MacroSegmentSelection::Type::CONDITION);
|
||||
}
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::StrValueChanged()
|
||||
@@ -549,7 +661,7 @@ void MacroActionVariableEdit::NumValueChanged(double val)
|
||||
_entryData->_numValue = val;
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::SegmentIndexChanged(int val)
|
||||
void MacroActionVariableEdit::SegmentIndexChanged(const IntVariable &val)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
@@ -557,7 +669,6 @@ void MacroActionVariableEdit::SegmentIndexChanged(int val)
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->SetSegmentIndexValue(val - 1);
|
||||
MarkSelectedSegment();
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::SetSegmentValueError(const QString &text)
|
||||
@@ -590,7 +701,7 @@ void MacroActionVariableEdit::UpdateSegmentVariableValue()
|
||||
SetSegmentValueError(obs_module_text(
|
||||
"AdvSceneSwitcher.action.variable.invalidSelection"));
|
||||
const QSignalBlocker b(_segmentIdx);
|
||||
_segmentIdx->setValue(index);
|
||||
_segmentIdx->SetValue(0);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -649,7 +760,7 @@ void MacroActionVariableEdit::UpdateSegmentVariableValue()
|
||||
void MacroActionVariableEdit::MacroSegmentOrderChanged()
|
||||
{
|
||||
const QSignalBlocker b(_segmentIdx);
|
||||
_segmentIdx->setValue(_entryData->GetSegmentIndexValue() + 1);
|
||||
_segmentIdx->SetValue(_entryData->GetSegmentIndexValue() + 1);
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::SubStringStartChanged(int val)
|
||||
@@ -752,40 +863,66 @@ void MacroActionVariableEdit::MathExpressionChanged()
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::MarkSelectedSegment()
|
||||
void MacroActionVariableEdit::UseCustomPromptChanged(int value)
|
||||
{
|
||||
if (switcher->disableHints) {
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto m = _entryData->GetMacro();
|
||||
if (!m) {
|
||||
auto lock = LockContext();
|
||||
_entryData->_useCustomPrompt = value;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::InputPromptChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
int index = _entryData->GetSegmentIndexValue();
|
||||
if (index < 0) {
|
||||
auto lock = LockContext();
|
||||
_entryData->_inputPrompt = _inputPrompt->text().toStdString();
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::UseInputPlaceholderChanged(int value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_entryData->_type == MacroActionVariable::Type::SET_ACTION_VALUE) {
|
||||
const auto &actions = m->Actions();
|
||||
if (index >= (int)actions.size()) {
|
||||
return;
|
||||
}
|
||||
AdvSceneSwitcher::window->HighlightAction(
|
||||
index, QColor(Qt::lightGray));
|
||||
} else {
|
||||
const auto &conditions = m->Conditions();
|
||||
if (index >= (int)conditions.size()) {
|
||||
return;
|
||||
}
|
||||
AdvSceneSwitcher::window->HighlightCondition(
|
||||
index, QColor(Qt::lightGray));
|
||||
auto lock = LockContext();
|
||||
_entryData->_useInputPlaceholder = value;
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionVariableEdit::InputPlaceholderChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
PulseWidget(_segmentIdx, QColor(Qt::lightGray), QColor(0, 0, 0, 0),
|
||||
true);
|
||||
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::SetWidgetVisibility()
|
||||
@@ -833,7 +970,37 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
||||
_mathExpression->setVisible(_entryData->_type ==
|
||||
MacroActionVariable::Type::MATH_EXPRESSION);
|
||||
_mathExpressionResult->hide();
|
||||
|
||||
SetLayoutVisible(_promptLayout,
|
||||
_entryData->_type ==
|
||||
MacroActionVariable::Type::USER_INPUT);
|
||||
_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);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "macro-segment-selection.hpp"
|
||||
#include "regex-config.hpp"
|
||||
#include "resizing-text-edit.hpp"
|
||||
#include "scene-selection.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
|
||||
namespace advss {
|
||||
@@ -35,6 +37,9 @@ public:
|
||||
SUBSTRING,
|
||||
FIND_AND_REPLACE,
|
||||
MATH_EXPRESSION,
|
||||
USER_INPUT,
|
||||
ENV_VARIABLE,
|
||||
SCENE_ITEM_COUNT,
|
||||
};
|
||||
|
||||
Type _type = Type::SET_FIXED_VALUE;
|
||||
@@ -53,6 +58,18 @@ public:
|
||||
"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;
|
||||
|
||||
private:
|
||||
void DecrementCurrentSegmentVariableRef();
|
||||
@@ -89,7 +106,7 @@ private slots:
|
||||
void ActionChanged(int);
|
||||
void StrValueChanged();
|
||||
void NumValueChanged(double);
|
||||
void SegmentIndexChanged(int val);
|
||||
void SegmentIndexChanged(const IntVariable &);
|
||||
void UpdateSegmentVariableValue();
|
||||
void MacroSegmentOrderChanged();
|
||||
void SubStringStartChanged(int val);
|
||||
@@ -100,17 +117,26 @@ private slots:
|
||||
void FindStrValueChanged();
|
||||
void ReplaceStrValueChanged();
|
||||
void MathExpressionChanged();
|
||||
void UseCustomPromptChanged(int);
|
||||
void InputPromptChanged();
|
||||
void UseInputPlaceholderChanged(int);
|
||||
void InputPlaceholderChanged();
|
||||
void EnvVariableChanged();
|
||||
void SceneChanged(const SceneSelection &);
|
||||
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
protected:
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
void SetSegmentValueError(const QString &);
|
||||
|
||||
VariableSelection *_variables;
|
||||
VariableSelection *_variables2;
|
||||
QComboBox *_actions;
|
||||
ResizingPlainTextEdit *_strValue;
|
||||
QDoubleSpinBox *_numValue;
|
||||
QSpinBox *_segmentIdx;
|
||||
MacroSegmentSelection *_segmentIdx;
|
||||
QLabel *_segmentValueStatus;
|
||||
ResizingPlainTextEdit *_segmentValue;
|
||||
QVBoxLayout *_substringLayout;
|
||||
@@ -126,13 +152,16 @@ protected:
|
||||
ResizingPlainTextEdit *_replaceStr;
|
||||
VariableLineEdit *_mathExpression;
|
||||
QLabel *_mathExpressionResult;
|
||||
QHBoxLayout *_promptLayout;
|
||||
QCheckBox *_useCustomPrompt;
|
||||
VariableLineEdit *_inputPrompt;
|
||||
QHBoxLayout *_placeholderLayout;
|
||||
QCheckBox *_useInputPlaceholder;
|
||||
VariableLineEdit *_inputPlaceholder;
|
||||
VariableLineEdit *_envVariable;
|
||||
SceneSelectionWidget *_scenes;
|
||||
|
||||
std::shared_ptr<MacroActionVariable> _entryData;
|
||||
|
||||
private:
|
||||
void MarkSelectedSegment();
|
||||
void SetWidgetVisibility();
|
||||
void SetSegmentValueError(const QString &);
|
||||
|
||||
QTimer _timer;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
@@ -13,7 +13,7 @@ bool MacroActionWait::_registered = MacroActionFactory::Register(
|
||||
{MacroActionWait::Create, MacroActionWaitEdit::Create,
|
||||
"AdvSceneSwitcher.action.wait"});
|
||||
|
||||
static std::map<WaitType, std::string> waitTypes = {
|
||||
const static std::map<WaitType, std::string> waitTypes = {
|
||||
{WaitType::FIXED, "AdvSceneSwitcher.action.wait.type.fixed"},
|
||||
{WaitType::RANDOM, "AdvSceneSwitcher.action.wait.type.random"},
|
||||
};
|
||||
|
||||
@@ -10,47 +10,75 @@ bool MacroActionWebsocket::_registered = MacroActionFactory::Register(
|
||||
{MacroActionWebsocket::Create, MacroActionWebsocketEdit::Create,
|
||||
"AdvSceneSwitcher.action.websocket"});
|
||||
|
||||
static std::map<MacroActionWebsocket::Type, std::string> actionTypes = {
|
||||
{MacroActionWebsocket::Type::REQUEST,
|
||||
"AdvSceneSwitcher.action.websocket.type.request"},
|
||||
{MacroActionWebsocket::Type::EVENT,
|
||||
"AdvSceneSwitcher.action.websocket.type.event"},
|
||||
const static std::map<MacroActionWebsocket::API, std::string> apiTypes = {
|
||||
{MacroActionWebsocket::API::SCENE_SWITCHER,
|
||||
"AdvSceneSwitcher.action.websocket.api.sceneSwitcher"},
|
||||
{MacroActionWebsocket::API::OBS_WEBSOCKET,
|
||||
"AdvSceneSwitcher.action.websocket.api.obsWebsocket"},
|
||||
{MacroActionWebsocket::API::GENERIC_WEBSOCKET,
|
||||
"AdvSceneSwitcher.action.websocket.api.genericWebsocket"},
|
||||
};
|
||||
|
||||
void MacroActionWebsocket::SendRequest()
|
||||
const static std::map<MacroActionWebsocket::MessageType, std::string>
|
||||
messageTypes = {
|
||||
{MacroActionWebsocket::MessageType::REQUEST,
|
||||
"AdvSceneSwitcher.action.websocket.type.request"},
|
||||
{MacroActionWebsocket::MessageType::EVENT,
|
||||
"AdvSceneSwitcher.action.websocket.type.event"},
|
||||
};
|
||||
|
||||
void MacroActionWebsocket::SendRequest(const std::string &msg)
|
||||
{
|
||||
auto connection = _connection.lock();
|
||||
if (!connection) {
|
||||
return;
|
||||
}
|
||||
connection->SendMsg(_message);
|
||||
|
||||
connection->SendMsg(msg);
|
||||
}
|
||||
|
||||
bool MacroActionWebsocket::PerformAction()
|
||||
{
|
||||
switch (_type) {
|
||||
case MacroActionWebsocket::Type::REQUEST:
|
||||
SendRequest();
|
||||
break;
|
||||
case MacroActionWebsocket::Type::EVENT:
|
||||
SendWebsocketEvent(_message);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (_api != MacroActionWebsocket::API::SCENE_SWITCHER) {
|
||||
SendRequest(_message);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_type == MacroActionWebsocket::MessageType::REQUEST) {
|
||||
auto vendorRequest = ConstructVendorRequestMessage(_message);
|
||||
SendRequest(vendorRequest);
|
||||
} else {
|
||||
SendWebsocketEvent(_message);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void MacroActionWebsocket::LogAction() const
|
||||
{
|
||||
if (_api == API::GENERIC_WEBSOCKET) {
|
||||
vblog(LOG_INFO,
|
||||
"sent generic websocket message \"%s\" via \"%s\"",
|
||||
_message.c_str(),
|
||||
GetWeakConnectionName(_connection).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
if (_api == API::OBS_WEBSOCKET) {
|
||||
vblog(LOG_INFO, "sent obs websocket message \"%s\" via \"%s\"",
|
||||
_message.c_str(),
|
||||
GetWeakConnectionName(_connection).c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_type) {
|
||||
case MacroActionWebsocket::Type::REQUEST:
|
||||
vblog(LOG_INFO, "sent msg \"%s\" via \"%s\"", _message.c_str(),
|
||||
case MacroActionWebsocket::MessageType::REQUEST:
|
||||
vblog(LOG_INFO, "sent scene switcher message \"%s\" via \"%s\"",
|
||||
_message.c_str(),
|
||||
GetWeakConnectionName(_connection).c_str());
|
||||
break;
|
||||
case MacroActionWebsocket::Type::EVENT:
|
||||
vblog(LOG_INFO, "sent event \"%s\" to connected clients",
|
||||
case MacroActionWebsocket::MessageType::EVENT:
|
||||
vblog(LOG_INFO,
|
||||
"sent scene switcher event \"%s\" to connected clients",
|
||||
_message.c_str());
|
||||
break;
|
||||
default:
|
||||
@@ -61,6 +89,7 @@ void MacroActionWebsocket::LogAction() const
|
||||
bool MacroActionWebsocket::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroAction::Save(obj);
|
||||
obs_data_set_int(obj, "api", static_cast<int>(_api));
|
||||
obs_data_set_int(obj, "type", static_cast<int>(_type));
|
||||
_message.Save(obj, "message");
|
||||
obs_data_set_string(obj, "connection",
|
||||
@@ -71,7 +100,8 @@ bool MacroActionWebsocket::Save(obs_data_t *obj) const
|
||||
bool MacroActionWebsocket::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroAction::Load(obj);
|
||||
_type = static_cast<Type>(obs_data_get_int(obj, "type"));
|
||||
_api = static_cast<API>(obs_data_get_int(obj, "api"));
|
||||
_type = static_cast<MessageType>(obs_data_get_int(obj, "type"));
|
||||
_message.Load(obj, "message");
|
||||
_connection =
|
||||
GetWeakConnectionByName(obs_data_get_string(obj, "connection"));
|
||||
@@ -80,40 +110,54 @@ bool MacroActionWebsocket::Load(obs_data_t *obj)
|
||||
|
||||
std::string MacroActionWebsocket::GetShortDesc() const
|
||||
{
|
||||
if (_type == Type::REQUEST) {
|
||||
if (_type == MessageType::REQUEST) {
|
||||
return GetWeakConnectionName(_connection);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static inline void populateActionSelection(QComboBox *list)
|
||||
static inline void populateAPISelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : actionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
for (const auto &[_, name] : apiTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
static inline void populateMessageTypeSelection(QComboBox *list)
|
||||
{
|
||||
for (const auto &[_, name] : messageTypes) {
|
||||
list->addItem(obs_module_text(name.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
MacroActionWebsocketEdit::MacroActionWebsocketEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroActionWebsocket> entryData)
|
||||
: QWidget(parent),
|
||||
_actions(new QComboBox(this)),
|
||||
_apiType(new QComboBox(this)),
|
||||
_messageType(new QComboBox(this)),
|
||||
_message(new VariableTextEdit(this)),
|
||||
_connection(new ConnectionSelection(this)),
|
||||
_editLayout(new QHBoxLayout())
|
||||
_editLayout(new QHBoxLayout()),
|
||||
_settingsConflict(new QLabel())
|
||||
{
|
||||
populateActionSelection(_actions);
|
||||
populateAPISelection(_apiType);
|
||||
populateMessageTypeSelection(_messageType);
|
||||
_settingsConflict->setWordWrap(true);
|
||||
|
||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ActionChanged(int)));
|
||||
QWidget::connect(_apiType, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(APITypeChanged(int)));
|
||||
QWidget::connect(_messageType, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(MessageTypeChanged(int)));
|
||||
QWidget::connect(_message, SIGNAL(textChanged()), this,
|
||||
SLOT(MessageChanged()));
|
||||
QWidget::connect(_connection, SIGNAL(SelectionChanged(const QString &)),
|
||||
this,
|
||||
SLOT(ConnectionSelectionChanged(const QString &)));
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(_editLayout);
|
||||
mainLayout->addWidget(_message);
|
||||
mainLayout->addWidget(_settingsConflict);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
@@ -121,34 +165,111 @@ MacroActionWebsocketEdit::MacroActionWebsocketEdit(
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroActionWebsocketEdit::CheckForSettingsConflict()
|
||||
{
|
||||
auto connection = _entryData->_connection.lock();
|
||||
if (!connection) {
|
||||
_settingsConflict->hide();
|
||||
return;
|
||||
}
|
||||
|
||||
if (_entryData->_api == MacroActionWebsocket::API::GENERIC_WEBSOCKET &&
|
||||
connection->IsUsingOBSProtocol()) {
|
||||
_settingsConflict->show();
|
||||
_settingsConflict->setText(obs_module_text(
|
||||
"AdvSceneSwitcher.action.websocket.settingsConflictGeneric"));
|
||||
} else if (_entryData->_api !=
|
||||
MacroActionWebsocket::API::GENERIC_WEBSOCKET &&
|
||||
!connection->IsUsingOBSProtocol()) {
|
||||
_settingsConflict->show();
|
||||
_settingsConflict->setText(obs_module_text(
|
||||
"AdvSceneSwitcher.action.websocket.settingsConflictOBS"));
|
||||
} else {
|
||||
_settingsConflict->hide();
|
||||
}
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionWebsocketEdit::SetupWidgetVisibility()
|
||||
{
|
||||
_messageType->setVisible(_entryData->_api ==
|
||||
MacroActionWebsocket::API::SCENE_SWITCHER);
|
||||
switch (_entryData->_api) {
|
||||
case MacroActionWebsocket::API::SCENE_SWITCHER:
|
||||
if (_entryData->_type ==
|
||||
MacroActionWebsocket::MessageType::REQUEST) {
|
||||
SetupRequestEdit();
|
||||
} else {
|
||||
SetupEventEdit();
|
||||
}
|
||||
break;
|
||||
case MacroActionWebsocket::API::OBS_WEBSOCKET:
|
||||
case MacroActionWebsocket::API::GENERIC_WEBSOCKET:
|
||||
SetupGenericEdit();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
CheckForSettingsConflict();
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroActionWebsocketEdit::SetupRequestEdit()
|
||||
{
|
||||
_editLayout->removeWidget(_actions);
|
||||
_editLayout->removeWidget(_connection);
|
||||
ClearLayout(_editLayout);
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{type}}", _actions},
|
||||
{"{{connection}}", _connection},
|
||||
};
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.action.websocket.entry.request"),
|
||||
_editLayout, widgetPlaceholders);
|
||||
ClearWidgets();
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.websocket.entry.sceneSwitcher.request"),
|
||||
_editLayout,
|
||||
{{"{{api}}", _apiType},
|
||||
{"{{type}}", _messageType},
|
||||
{"{{connection}}", _connection}});
|
||||
_connection->show();
|
||||
}
|
||||
|
||||
void MacroActionWebsocketEdit::SetupEventEdit()
|
||||
{
|
||||
_editLayout->removeWidget(_actions);
|
||||
ClearWidgets();
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
"AdvSceneSwitcher.action.websocket.entry.sceneSwitcher.event"),
|
||||
_editLayout,
|
||||
{{"{{api}}", _apiType},
|
||||
{"{{type}}", _messageType},
|
||||
{"{{connection}}", _connection}});
|
||||
|
||||
// Add widget to layout but hide it
|
||||
_editLayout->addWidget(_connection);
|
||||
_connection->hide();
|
||||
}
|
||||
|
||||
void MacroActionWebsocketEdit::SetupGenericEdit()
|
||||
{
|
||||
ClearWidgets();
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.action.websocket.entry.generic"),
|
||||
_editLayout,
|
||||
{{"{{api}}", _apiType},
|
||||
{"{{type}}", _messageType},
|
||||
{"{{connection}}", _connection}});
|
||||
_connection->show();
|
||||
|
||||
// Add widget to layout but hide it
|
||||
_editLayout->addWidget(_messageType);
|
||||
_messageType->hide();
|
||||
}
|
||||
|
||||
void MacroActionWebsocketEdit::ClearWidgets()
|
||||
{
|
||||
_editLayout->removeWidget(_apiType);
|
||||
_editLayout->removeWidget(_messageType);
|
||||
_editLayout->removeWidget(_connection);
|
||||
ClearLayout(_editLayout);
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{type}}", _actions},
|
||||
{"{{connection}}", _connection},
|
||||
};
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.action.websocket.entry.event"),
|
||||
_editLayout, widgetPlaceholders);
|
||||
_connection->hide();
|
||||
}
|
||||
|
||||
void MacroActionWebsocketEdit::UpdateEntryData()
|
||||
@@ -157,33 +278,37 @@ void MacroActionWebsocketEdit::UpdateEntryData()
|
||||
return;
|
||||
}
|
||||
|
||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||
_apiType->setCurrentIndex(static_cast<int>(_entryData->_api));
|
||||
_messageType->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||
_message->setPlainText(_entryData->_message);
|
||||
_connection->SetConnection(_entryData->_connection);
|
||||
|
||||
if (_entryData->_type == MacroActionWebsocket::Type::REQUEST) {
|
||||
SetupRequestEdit();
|
||||
} else {
|
||||
SetupEventEdit();
|
||||
}
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
SetupWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroActionWebsocketEdit::ActionChanged(int index)
|
||||
void MacroActionWebsocketEdit::APITypeChanged(int index)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_type = static_cast<MacroActionWebsocket::Type>(index);
|
||||
if (_entryData->_type == MacroActionWebsocket::Type::REQUEST) {
|
||||
SetupRequestEdit();
|
||||
} else {
|
||||
SetupEventEdit();
|
||||
_entryData->_api = static_cast<MacroActionWebsocket::API>(index);
|
||||
SetupWidgetVisibility();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroActionWebsocketEdit::MessageTypeChanged(int index)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_type =
|
||||
static_cast<MacroActionWebsocket::MessageType>(index);
|
||||
SetupWidgetVisibility();
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
@@ -210,6 +335,7 @@ void MacroActionWebsocketEdit::ConnectionSelectionChanged(
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_connection = GetWeakConnectionByQString(connection);
|
||||
CheckForSettingsConflict();
|
||||
emit(HeaderInfoChanged(connection));
|
||||
}
|
||||
|
||||
|
||||
@@ -24,17 +24,24 @@ public:
|
||||
return std::make_shared<MacroActionWebsocket>(m);
|
||||
}
|
||||
|
||||
enum class Type {
|
||||
enum class API {
|
||||
SCENE_SWITCHER,
|
||||
OBS_WEBSOCKET,
|
||||
GENERIC_WEBSOCKET,
|
||||
};
|
||||
|
||||
enum class MessageType {
|
||||
REQUEST,
|
||||
EVENT,
|
||||
};
|
||||
|
||||
Type _type = Type::REQUEST;
|
||||
API _api = API::SCENE_SWITCHER;
|
||||
MessageType _type = MessageType::REQUEST;
|
||||
StringVariable _message = obs_module_text("AdvSceneSwitcher.enterText");
|
||||
std::weak_ptr<Connection> _connection;
|
||||
|
||||
private:
|
||||
void SendRequest();
|
||||
void SendRequest(const std::string &msg);
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
@@ -57,7 +64,8 @@ public:
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ActionChanged(int);
|
||||
void APITypeChanged(int);
|
||||
void MessageTypeChanged(int);
|
||||
void MessageChanged();
|
||||
void ConnectionSelectionChanged(const QString &);
|
||||
signals:
|
||||
@@ -67,13 +75,20 @@ protected:
|
||||
std::shared_ptr<MacroActionWebsocket> _entryData;
|
||||
|
||||
private:
|
||||
void CheckForSettingsConflict();
|
||||
void SetupWidgetVisibility();
|
||||
void SetupRequestEdit();
|
||||
void SetupEventEdit();
|
||||
void SetupGenericEdit();
|
||||
void ClearWidgets();
|
||||
|
||||
QComboBox *_actions;
|
||||
QComboBox *_apiType;
|
||||
QComboBox *_messageType;
|
||||
VariableTextEdit *_message;
|
||||
ConnectionSelection *_connection;
|
||||
QHBoxLayout *_editLayout;
|
||||
QLabel *_settingsConflict;
|
||||
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -11,12 +11,15 @@ bool MacroAction::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroSegment::Save(obj);
|
||||
obs_data_set_string(obj, "id", GetId().c_str());
|
||||
obs_data_set_bool(obj, "enabled", _enabled);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroAction::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroSegment::Load(obj);
|
||||
obs_data_set_default_bool(obj, "enabled", true);
|
||||
_enabled = obs_data_get_bool(obj, "enabled");
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -25,6 +28,16 @@ void MacroAction::LogAction() const
|
||||
vblog(LOG_INFO, "performed action %s", GetId().c_str());
|
||||
}
|
||||
|
||||
void MacroAction::SetEnabled(bool value)
|
||||
{
|
||||
_enabled = value;
|
||||
}
|
||||
|
||||
bool MacroAction::Enabled() const
|
||||
{
|
||||
return _enabled;
|
||||
}
|
||||
|
||||
MacroRefAction::MacroRefAction(Macro *m, bool supportsVariableValue)
|
||||
: MacroAction(m, supportsVariableValue)
|
||||
{
|
||||
|
||||
@@ -12,6 +12,11 @@ public:
|
||||
virtual bool Save(obs_data_t *obj) const = 0;
|
||||
virtual bool Load(obs_data_t *obj) = 0;
|
||||
virtual void LogAction() const;
|
||||
void SetEnabled(bool);
|
||||
bool Enabled() const;
|
||||
|
||||
private:
|
||||
bool _enabled = true;
|
||||
};
|
||||
|
||||
class MacroRefAction : virtual public MacroAction {
|
||||
|
||||
@@ -12,7 +12,7 @@ bool MacroConditionAudio::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionAudio::Create, MacroConditionAudioEdit::Create,
|
||||
"AdvSceneSwitcher.condition.audio"});
|
||||
|
||||
static std::map<MacroConditionAudio::Type, std::string> checkTypes = {
|
||||
const static std::map<MacroConditionAudio::Type, std::string> checkTypes = {
|
||||
{MacroConditionAudio::Type::OUTPUT_VOLUME,
|
||||
"AdvSceneSwitcher.condition.audio.type.output"},
|
||||
{MacroConditionAudio::Type::CONFIGURED_VOLUME,
|
||||
@@ -25,7 +25,7 @@ static std::map<MacroConditionAudio::Type, std::string> checkTypes = {
|
||||
"AdvSceneSwitcher.condition.audio.type.balance"},
|
||||
};
|
||||
|
||||
static std::map<MacroConditionAudio::OutputCondition, std::string>
|
||||
const static std::map<MacroConditionAudio::OutputCondition, std::string>
|
||||
audioOutputConditionTypes = {
|
||||
{MacroConditionAudio::OutputCondition::ABOVE,
|
||||
"AdvSceneSwitcher.condition.audio.state.above"},
|
||||
@@ -33,7 +33,7 @@ static std::map<MacroConditionAudio::OutputCondition, std::string>
|
||||
"AdvSceneSwitcher.condition.audio.state.below"},
|
||||
};
|
||||
|
||||
static std::map<MacroConditionAudio::VolumeCondition, std::string>
|
||||
const static std::map<MacroConditionAudio::VolumeCondition, std::string>
|
||||
audioVolumeConditionTypes = {
|
||||
{MacroConditionAudio::VolumeCondition::ABOVE,
|
||||
"AdvSceneSwitcher.condition.audio.state.above"},
|
||||
|
||||
@@ -15,7 +15,7 @@ bool MacroConditionCursor::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionCursor::Create, MacroConditionCursorEdit::Create,
|
||||
"AdvSceneSwitcher.condition.cursor"});
|
||||
|
||||
static std::map<MacroConditionCursor::Condition, std::string>
|
||||
const static std::map<MacroConditionCursor::Condition, std::string>
|
||||
cursorConditionTypes = {
|
||||
{MacroConditionCursor::Condition::REGION,
|
||||
"AdvSceneSwitcher.condition.cursor.type.region"},
|
||||
@@ -27,7 +27,7 @@ static std::map<MacroConditionCursor::Condition, std::string>
|
||||
#endif
|
||||
};
|
||||
|
||||
static std::map<MacroConditionCursor::Button, std::string> buttonTypes = {
|
||||
const static std::map<MacroConditionCursor::Button, std::string> buttonTypes = {
|
||||
{MacroConditionCursor::Button::LEFT,
|
||||
"AdvSceneSwitcher.condition.cursor.button.left"},
|
||||
{MacroConditionCursor::Button::MIDDLE,
|
||||
|
||||
@@ -14,8 +14,8 @@ bool MacroConditionDate::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionDate::Create, MacroConditionDateEdit::Create,
|
||||
"AdvSceneSwitcher.condition.date", false});
|
||||
|
||||
static std::map<MacroConditionDate::Condition, std::string> dateConditionTypes =
|
||||
{
|
||||
const static std::map<MacroConditionDate::Condition, std::string>
|
||||
dateConditionTypes = {
|
||||
{MacroConditionDate::Condition::AT,
|
||||
"AdvSceneSwitcher.condition.date.state.at"},
|
||||
{MacroConditionDate::Condition::AFTER,
|
||||
@@ -28,8 +28,8 @@ static std::map<MacroConditionDate::Condition, std::string> dateConditionTypes =
|
||||
"AdvSceneSwitcher.condition.date.state.pattern"},
|
||||
};
|
||||
|
||||
static std::map<MacroConditionDate::Condition, std::string> weekConditionTypes =
|
||||
{
|
||||
const static std::map<MacroConditionDate::Condition, std::string>
|
||||
weekConditionTypes = {
|
||||
{MacroConditionDate::Condition::AT,
|
||||
"AdvSceneSwitcher.condition.date.state.at"},
|
||||
{MacroConditionDate::Condition::AFTER,
|
||||
@@ -38,7 +38,7 @@ static std::map<MacroConditionDate::Condition, std::string> weekConditionTypes =
|
||||
"AdvSceneSwitcher.condition.date.state.before"},
|
||||
};
|
||||
|
||||
static std::map<MacroConditionDate::Day, std::string> dayOfWeekNames = {
|
||||
const static std::map<MacroConditionDate::Day, std::string> dayOfWeekNames = {
|
||||
{MacroConditionDate::Day::ANY,
|
||||
"AdvSceneSwitcher.condition.date.anyDay"},
|
||||
{MacroConditionDate::Day::MONDAY,
|
||||
|
||||
@@ -12,11 +12,12 @@ bool MacroConditionDisplay::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionDisplay::Create, MacroConditionDisplayEdit::Create,
|
||||
"AdvSceneSwitcher.condition.display"});
|
||||
|
||||
static std::map<MacroConditionDisplay::Condition, std::string> conditionTypes = {
|
||||
{MacroConditionDisplay::Condition::DISPLAY_NAME,
|
||||
"AdvSceneSwitcher.condition.display.type.displayName"},
|
||||
{MacroConditionDisplay::Condition::DISPLAY_COUNT,
|
||||
"AdvSceneSwitcher.condition.display.type.displayCount"},
|
||||
const static std::map<MacroConditionDisplay::Condition, std::string>
|
||||
conditionTypes = {
|
||||
{MacroConditionDisplay::Condition::DISPLAY_NAME,
|
||||
"AdvSceneSwitcher.condition.display.type.displayName"},
|
||||
{MacroConditionDisplay::Condition::DISPLAY_COUNT,
|
||||
"AdvSceneSwitcher.condition.display.type.displayCount"},
|
||||
};
|
||||
|
||||
static bool matchDisplayNames(const std::string &name, const RegexConfig ®ex)
|
||||
|
||||
@@ -182,7 +182,7 @@ MacroConditionEdit::MacroConditionEdit(
|
||||
: MacroSegmentEdit(switcher->macroProperties._highlightConditions,
|
||||
parent),
|
||||
_logicSelection(new QComboBox()),
|
||||
_conditionSelection(new QComboBox()),
|
||||
_conditionSelection(new FilterComboBox()),
|
||||
_dur(new DurationModifierEdit()),
|
||||
_entryData(entryData),
|
||||
_isRoot(root)
|
||||
@@ -295,13 +295,16 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
||||
return;
|
||||
}
|
||||
|
||||
auto idx = _entryData->get()->GetIndex();
|
||||
auto macro = _entryData->get()->GetMacro();
|
||||
std::string id = MacroConditionFactory::GetIdByName(text);
|
||||
if (id.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto temp = DurationModifier();
|
||||
_dur->SetValue(temp);
|
||||
HeaderInfoChanged("");
|
||||
auto idx = _entryData->get()->GetIndex();
|
||||
auto macro = _entryData->get()->GetMacro();
|
||||
{
|
||||
auto lock = LockContext();
|
||||
auto logic = (*_entryData)->GetLogicType();
|
||||
@@ -382,7 +385,7 @@ void AdvSceneSwitcher::AddMacroCondition(int idx)
|
||||
}
|
||||
(*cond)->SetLogicType(logic);
|
||||
macro->UpdateConditionIndices();
|
||||
conditionsList->Insert(
|
||||
ui->conditionsList->Insert(
|
||||
idx,
|
||||
new MacroConditionEdit(this, ¯o->Conditions()[idx],
|
||||
id, idx == 0));
|
||||
@@ -407,7 +410,7 @@ void AdvSceneSwitcher::on_conditionAdd_clicked()
|
||||
if (currentConditionIdx != -1) {
|
||||
MacroConditionSelectionChanged(currentConditionIdx + 1);
|
||||
}
|
||||
conditionsList->SetHelpMsgVisible(false);
|
||||
ui->conditionsList->SetHelpMsgVisible(false);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::RemoveMacroCondition(int idx)
|
||||
@@ -423,14 +426,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);
|
||||
@@ -454,24 +457,45 @@ void AdvSceneSwitcher::on_conditionRemove_clicked()
|
||||
MacroConditionSelectionChanged(-1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_conditionUp_clicked()
|
||||
void AdvSceneSwitcher::on_conditionTop_clicked()
|
||||
{
|
||||
if (currentConditionIdx == -1) {
|
||||
return;
|
||||
}
|
||||
MacroConditionReorder(0, currentConditionIdx);
|
||||
MacroConditionSelectionChanged(0);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_conditionUp_clicked()
|
||||
{
|
||||
if (currentConditionIdx == -1 || currentConditionIdx == 0) {
|
||||
return;
|
||||
}
|
||||
MoveMacroConditionUp(currentConditionIdx);
|
||||
MacroConditionSelectionChanged(currentConditionIdx - 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_conditionDown_clicked()
|
||||
{
|
||||
if (currentConditionIdx == -1) {
|
||||
if (currentConditionIdx == -1 ||
|
||||
currentConditionIdx ==
|
||||
ui->conditionsList->ContentLayout()->count() - 1) {
|
||||
return;
|
||||
}
|
||||
MoveMacroConditionDown(currentConditionIdx);
|
||||
MacroConditionSelectionChanged(currentConditionIdx + 1);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::on_conditionBottom_clicked()
|
||||
{
|
||||
if (currentConditionIdx == -1) {
|
||||
return;
|
||||
}
|
||||
const int newIdx = ui->conditionsList->ContentLayout()->count() - 1;
|
||||
MacroConditionReorder(newIdx, currentConditionIdx);
|
||||
MacroConditionSelectionChanged(newIdx);
|
||||
}
|
||||
|
||||
void AdvSceneSwitcher::SwapConditions(Macro *m, int pos1, int pos2)
|
||||
{
|
||||
if (pos1 == pos2) {
|
||||
@@ -497,11 +521,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);
|
||||
@@ -540,22 +564,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)
|
||||
@@ -565,8 +574,8 @@ void AdvSceneSwitcher::MacroConditionReorder(int to, int from)
|
||||
return;
|
||||
}
|
||||
|
||||
if (from < 0 || from > (int)macro->Conditions().size() || to < 0 ||
|
||||
to > (int)macro->Conditions().size()) {
|
||||
if (to == from || from < 0 || from > (int)macro->Conditions().size() ||
|
||||
to < 0 || to > (int)macro->Conditions().size()) {
|
||||
return;
|
||||
}
|
||||
{
|
||||
@@ -575,30 +584,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);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
#include "macro-condition.hpp"
|
||||
#include "filter-combo-box.hpp"
|
||||
|
||||
#include <memory>
|
||||
|
||||
@@ -77,7 +78,7 @@ private:
|
||||
std::shared_ptr<MacroSegment> Data();
|
||||
|
||||
QComboBox *_logicSelection;
|
||||
QComboBox *_conditionSelection;
|
||||
FilterComboBox *_conditionSelection;
|
||||
DurationModifierEdit *_dur;
|
||||
|
||||
std::shared_ptr<MacroCondition> *_entryData;
|
||||
|
||||
@@ -12,14 +12,16 @@ bool MacroConditionFilter::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionFilter::Create, MacroConditionFilterEdit::Create,
|
||||
"AdvSceneSwitcher.condition.filter"});
|
||||
|
||||
static std::map<MacroConditionFilter::Condition, std::string>
|
||||
const static std::map<MacroConditionFilter::Condition, std::string>
|
||||
filterConditionTypes = {
|
||||
{MacroConditionFilter::Condition::ENABLED,
|
||||
"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()
|
||||
@@ -38,13 +40,20 @@ bool MacroConditionFilter::CheckCondition()
|
||||
case Condition::DISABLED:
|
||||
ret = !obs_source_enabled(filterSource);
|
||||
break;
|
||||
case Condition::SETTINGS:
|
||||
case Condition::SETTINGS_MATCH:
|
||||
ret = CompareSourceSettings(filterWeakSource, _settings,
|
||||
_regex);
|
||||
if (IsReferencedInVars()) {
|
||||
SetVariableValue(GetSourceSettings(filterWeakSource));
|
||||
}
|
||||
break;
|
||||
case Condition::SETTINGS_CHANGED: {
|
||||
std::string settings = GetSourceSettings(_source.GetSource());
|
||||
ret = !_currentSettings.empty() && settings != _currentSettings;
|
||||
_currentSettings = settings;
|
||||
SetVariableValue(settings);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -95,8 +104,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,8 +203,9 @@ 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()
|
||||
@@ -259,8 +269,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,8 @@ public:
|
||||
RegexConfig _regex;
|
||||
|
||||
private:
|
||||
std::string _currentSettings;
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ const std::string MacroConditionHotkey::id = "hotkey";
|
||||
bool MacroConditionHotkey::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionHotkey::id,
|
||||
{MacroConditionHotkey::Create, MacroConditionHotkeyEdit::Create,
|
||||
"AdvSceneSwitcher.condition.hotkey", false});
|
||||
"AdvSceneSwitcher.condition.hotkey"});
|
||||
|
||||
static uint32_t count = 1;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "macro-condition-macro.hpp"
|
||||
#include "macro.hpp"
|
||||
#include "macro-action-edit.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
@@ -11,16 +12,21 @@ bool MacroConditionMacro::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionMacro::Create, MacroConditionMacroEdit::Create,
|
||||
"AdvSceneSwitcher.condition.macro"});
|
||||
|
||||
static std::map<MacroConditionMacro::Type, std::string> macroConditionTypes = {
|
||||
{MacroConditionMacro::Type::COUNT,
|
||||
"AdvSceneSwitcher.condition.macro.type.count"},
|
||||
{MacroConditionMacro::Type::STATE,
|
||||
"AdvSceneSwitcher.condition.macro.type.state"},
|
||||
{MacroConditionMacro::Type::MULTI_STATE,
|
||||
"AdvSceneSwitcher.condition.macro.type.multiState"},
|
||||
const static std::map<MacroConditionMacro::Type, std::string>
|
||||
macroConditionTypes = {
|
||||
{MacroConditionMacro::Type::COUNT,
|
||||
"AdvSceneSwitcher.condition.macro.type.count"},
|
||||
{MacroConditionMacro::Type::STATE,
|
||||
"AdvSceneSwitcher.condition.macro.type.state"},
|
||||
{MacroConditionMacro::Type::MULTI_STATE,
|
||||
"AdvSceneSwitcher.condition.macro.type.multiState"},
|
||||
{MacroConditionMacro::Type::ACTION_DISABLED,
|
||||
"AdvSceneSwitcher.condition.macro.type.actionDisabled"},
|
||||
{MacroConditionMacro::Type::ACTION_ENABLED,
|
||||
"AdvSceneSwitcher.condition.macro.type.actionEnabled"},
|
||||
};
|
||||
|
||||
static std::map<MacroConditionMacro::CounterCondition, std::string>
|
||||
const static std::map<MacroConditionMacro::CounterCondition, std::string>
|
||||
counterConditionTypes = {
|
||||
{MacroConditionMacro::CounterCondition::BELOW,
|
||||
"AdvSceneSwitcher.condition.macro.count.type.below"},
|
||||
@@ -30,7 +36,7 @@ static std::map<MacroConditionMacro::CounterCondition, std::string>
|
||||
"AdvSceneSwitcher.condition.macro.count.type.equal"},
|
||||
};
|
||||
|
||||
static std::map<MacroConditionMacro::MultiStateCondition, std::string>
|
||||
const static std::map<MacroConditionMacro::MultiStateCondition, std::string>
|
||||
multiStateConditionTypes = {
|
||||
{MacroConditionMacro::MultiStateCondition::BELOW,
|
||||
"AdvSceneSwitcher.condition.macro.state.type.below"},
|
||||
@@ -83,6 +89,24 @@ bool MacroConditionMacro::CheckMultiStateCondition()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionMacro::CheckActionStateCondition()
|
||||
{
|
||||
auto macro = _macro.GetMacro();
|
||||
if (!macro) {
|
||||
return false;
|
||||
}
|
||||
if (!IsValidMacroSegmentIndex(macro.get(), _actionIndex - 1, false)) {
|
||||
return false;
|
||||
}
|
||||
if (_type == Type::ACTION_DISABLED) {
|
||||
return !macro->Actions().at(_actionIndex - 1)->Enabled();
|
||||
} else if (_type == Type::ACTION_ENABLED) {
|
||||
return macro->Actions().at(_actionIndex - 1)->Enabled();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionMacro::CheckCountCondition()
|
||||
{
|
||||
auto macro = _macro.GetMacro();
|
||||
@@ -113,6 +137,9 @@ bool MacroConditionMacro::CheckCondition()
|
||||
return CheckMultiStateCondition();
|
||||
case Type::COUNT:
|
||||
return CheckCountCondition();
|
||||
case Type::ACTION_DISABLED:
|
||||
case Type::ACTION_ENABLED:
|
||||
return CheckActionStateCondition();
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -131,6 +158,7 @@ bool MacroConditionMacro::Save(obs_data_t *obj) const
|
||||
_multiSateCount.Save(obj, "multiStateCount");
|
||||
obs_data_set_int(obj, "multiStateCondition",
|
||||
static_cast<int>(_multiSateCondition));
|
||||
_actionIndex.Save(obj, "actionIndex");
|
||||
obs_data_set_int(obj, "version", 1);
|
||||
return true;
|
||||
}
|
||||
@@ -143,6 +171,7 @@ bool MacroConditionMacro::Load(obs_data_t *obj)
|
||||
_type = static_cast<Type>(obs_data_get_int(obj, "type"));
|
||||
_counterCondition = static_cast<CounterCondition>(
|
||||
obs_data_get_int(obj, "condition"));
|
||||
_actionIndex.Load(obj, "actionIndex");
|
||||
// TODO: Remove this fallback in future version
|
||||
if (!obs_data_has_user_value(obj, "multiStateCondition")) {
|
||||
_multiSateCondition = MultiStateCondition::ABOVE;
|
||||
@@ -210,7 +239,9 @@ MacroConditionMacroEdit::MacroConditionMacroEdit(
|
||||
_settingsLine2(new QHBoxLayout()),
|
||||
_macroList(new MacroList(this, false, false)),
|
||||
_multiStateConditions(new QComboBox()),
|
||||
_multiStateCount(new VariableSpinBox())
|
||||
_multiStateCount(new VariableSpinBox()),
|
||||
_actionIndex(new MacroSegmentSelection(
|
||||
this, MacroSegmentSelection::Type::ACTION))
|
||||
{
|
||||
_count->setMaximum(10000000);
|
||||
populateTypeSelection(_types);
|
||||
@@ -245,6 +276,9 @@ MacroConditionMacroEdit::MacroConditionMacroEdit(
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||
this,
|
||||
SLOT(MultiStateCountChanged(const NumberVariable<int> &)));
|
||||
QWidget::connect(_actionIndex,
|
||||
SIGNAL(SelectionChanged(const IntVariable &)), this,
|
||||
SLOT(ActionIndexChanged(const IntVariable &)));
|
||||
|
||||
auto typesLayout = new QHBoxLayout();
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
@@ -254,6 +288,14 @@ MacroConditionMacroEdit::MacroConditionMacroEdit(
|
||||
"AdvSceneSwitcher.condition.macro.type.selection"),
|
||||
typesLayout, widgetPlaceholders);
|
||||
|
||||
_settingsLine1->addWidget(_macros);
|
||||
_settingsLine1->addWidget(_counterConditions);
|
||||
_settingsLine1->addWidget(_count);
|
||||
_settingsLine2->addWidget(_currentCount);
|
||||
_settingsLine2->addWidget(_resetCount);
|
||||
_settingsLine1->addWidget(_multiStateConditions);
|
||||
_settingsLine1->addWidget(_multiStateCount);
|
||||
|
||||
auto mainLayout = new QVBoxLayout(this);
|
||||
mainLayout->addLayout(typesLayout);
|
||||
mainLayout->addLayout(_settingsLine1);
|
||||
@@ -286,10 +328,34 @@ void MacroConditionMacroEdit::ClearLayouts()
|
||||
_settingsLine2->removeWidget(_resetCount);
|
||||
_settingsLine1->removeWidget(_multiStateConditions);
|
||||
_settingsLine1->removeWidget(_multiStateCount);
|
||||
_settingsLine1->removeWidget(_actionIndex);
|
||||
ClearLayout(_settingsLine1);
|
||||
ClearLayout(_settingsLine2);
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::SetupWidgets()
|
||||
{
|
||||
switch (_entryData->_type) {
|
||||
case MacroConditionMacro::Type::COUNT:
|
||||
SetupCountWidgets();
|
||||
break;
|
||||
case MacroConditionMacro::Type::STATE:
|
||||
SetupStateWidgets();
|
||||
break;
|
||||
case MacroConditionMacro::Type::MULTI_STATE:
|
||||
SetupMultiStateWidgets();
|
||||
break;
|
||||
case MacroConditionMacro::Type::ACTION_DISABLED:
|
||||
SetupActionStateWidgets(false);
|
||||
break;
|
||||
case MacroConditionMacro::Type::ACTION_ENABLED:
|
||||
SetupActionStateWidgets(true);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::SetupStateWidgets()
|
||||
{
|
||||
SetWidgetVisibility();
|
||||
@@ -340,43 +406,51 @@ void MacroConditionMacroEdit::SetupCountWidgets()
|
||||
_settingsLine2, widgetPlaceholders);
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::SetupActionStateWidgets(bool enable)
|
||||
{
|
||||
SetWidgetVisibility();
|
||||
ClearLayouts();
|
||||
|
||||
PlaceWidgets(
|
||||
obs_module_text(
|
||||
enable ? "AdvSceneSwitcher.condition.macro.actionState.enabled.entry"
|
||||
: "AdvSceneSwitcher.condition.macro.actionState.disabled.entry"),
|
||||
_settingsLine1,
|
||||
{{"{{macros}}", _macros}, {"{{actionIndex}}", _actionIndex}});
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::SetWidgetVisibility()
|
||||
{
|
||||
switch (_entryData->_type) {
|
||||
case MacroConditionMacro::Type::COUNT:
|
||||
_macros->show();
|
||||
_counterConditions->show();
|
||||
_count->show();
|
||||
_currentCount->show();
|
||||
_resetCount->show();
|
||||
_macroList->hide();
|
||||
_multiStateConditions->hide();
|
||||
_multiStateCount->hide();
|
||||
break;
|
||||
case MacroConditionMacro::Type::STATE:
|
||||
_macros->show();
|
||||
_counterConditions->hide();
|
||||
_count->hide();
|
||||
_currentCount->hide();
|
||||
_resetCount->hide();
|
||||
_macroList->hide();
|
||||
_multiStateConditions->hide();
|
||||
_multiStateCount->hide();
|
||||
break;
|
||||
case MacroConditionMacro::Type::MULTI_STATE:
|
||||
_macros->hide();
|
||||
_counterConditions->hide();
|
||||
_count->hide();
|
||||
_currentCount->hide();
|
||||
_macros->setVisible(
|
||||
_entryData->_type == MacroConditionMacro::Type::COUNT ||
|
||||
_entryData->_type == MacroConditionMacro::Type::STATE ||
|
||||
_entryData->_type ==
|
||||
MacroConditionMacro::Type::ACTION_DISABLED ||
|
||||
_entryData->_type == MacroConditionMacro::Type::ACTION_ENABLED);
|
||||
_counterConditions->setVisible(_entryData->_type ==
|
||||
MacroConditionMacro::Type::COUNT);
|
||||
_count->setVisible(_entryData->_type ==
|
||||
MacroConditionMacro::Type::COUNT);
|
||||
_currentCount->setVisible(_entryData->_type ==
|
||||
MacroConditionMacro::Type::COUNT);
|
||||
_resetCount->setVisible(_entryData->_type ==
|
||||
MacroConditionMacro::Type::COUNT);
|
||||
_macroList->setVisible(_entryData->_type ==
|
||||
MacroConditionMacro::Type::MULTI_STATE);
|
||||
_multiStateConditions->setVisible(
|
||||
_entryData->_type == MacroConditionMacro::Type::MULTI_STATE);
|
||||
_multiStateCount->setVisible(_entryData->_type ==
|
||||
MacroConditionMacro::Type::MULTI_STATE);
|
||||
_actionIndex->setVisible(
|
||||
_entryData->_type ==
|
||||
MacroConditionMacro::Type::ACTION_DISABLED ||
|
||||
_entryData->_type == MacroConditionMacro::Type::ACTION_ENABLED);
|
||||
if (_entryData->_type == MacroConditionMacro::Type::MULTI_STATE ||
|
||||
_entryData->_type == MacroConditionMacro::Type::ACTION_DISABLED ||
|
||||
_entryData->_type == MacroConditionMacro::Type::ACTION_ENABLED) {
|
||||
_pausedWarning->hide();
|
||||
_resetCount->hide();
|
||||
_macroList->show();
|
||||
_multiStateConditions->show();
|
||||
_multiStateCount->show();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
@@ -387,20 +461,7 @@ void MacroConditionMacroEdit::UpdateEntryData()
|
||||
return;
|
||||
}
|
||||
|
||||
switch (_entryData->_type) {
|
||||
case MacroConditionMacro::Type::COUNT:
|
||||
SetupCountWidgets();
|
||||
break;
|
||||
case MacroConditionMacro::Type::STATE:
|
||||
SetupStateWidgets();
|
||||
break;
|
||||
case MacroConditionMacro::Type::MULTI_STATE:
|
||||
SetupMultiStateWidgets();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
SetupWidgets();
|
||||
_macros->SetCurrentMacro(_entryData->_macro);
|
||||
_types->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||
_counterConditions->setCurrentIndex(
|
||||
@@ -410,6 +471,9 @@ void MacroConditionMacroEdit::UpdateEntryData()
|
||||
_multiStateConditions->setCurrentIndex(
|
||||
static_cast<int>(_entryData->_multiSateCondition));
|
||||
_multiStateCount->SetValue(_entryData->_multiSateCount);
|
||||
_actionIndex->SetValue(_entryData->_actionIndex);
|
||||
_actionIndex->SetMacro(_entryData->_macro.GetMacro());
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::MacroChanged(const QString &text)
|
||||
@@ -420,6 +484,7 @@ void MacroConditionMacroEdit::MacroChanged(const QString &text)
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_macro = text;
|
||||
_actionIndex->SetMacro(_entryData->_macro.GetMacro());
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
@@ -460,6 +525,7 @@ void MacroConditionMacroEdit::MacroRemove(const QString &)
|
||||
}
|
||||
}
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::TypeChanged(int type)
|
||||
@@ -470,20 +536,7 @@ void MacroConditionMacroEdit::TypeChanged(int type)
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_type = static_cast<MacroConditionMacro::Type>(type);
|
||||
|
||||
switch (_entryData->_type) {
|
||||
case MacroConditionMacro::Type::COUNT:
|
||||
SetupCountWidgets();
|
||||
break;
|
||||
case MacroConditionMacro::Type::STATE:
|
||||
SetupStateWidgets();
|
||||
break;
|
||||
case MacroConditionMacro::Type::MULTI_STATE:
|
||||
SetupMultiStateWidgets();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
SetupWidgets();
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::ResetClicked()
|
||||
@@ -521,6 +574,7 @@ void MacroConditionMacroEdit::UpdatePaused()
|
||||
_entryData->_type != MacroConditionMacro::Type::MULTI_STATE &&
|
||||
macro && macro->Paused());
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::MultiStateConditionChanged(int cond)
|
||||
@@ -555,6 +609,7 @@ void MacroConditionMacroEdit::Add(const std::string &name)
|
||||
MacroRef macro(name);
|
||||
_entryData->_macros.push_back(macro);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::Remove(int idx)
|
||||
@@ -566,6 +621,7 @@ void MacroConditionMacroEdit::Remove(int idx)
|
||||
auto lock = LockContext();
|
||||
_entryData->_macros.erase(std::next(_entryData->_macros.begin(), idx));
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::Replace(int idx, const std::string &name)
|
||||
@@ -578,6 +634,17 @@ void MacroConditionMacroEdit::Replace(int idx, const std::string &name)
|
||||
auto lock = LockContext();
|
||||
_entryData->_macros[idx] = macro;
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionMacroEdit::ActionIndexChanged(const IntVariable &value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_actionIndex = value;
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#include "macro-condition-edit.hpp"
|
||||
#include "macro-selection.hpp"
|
||||
#include "macro-list.hpp"
|
||||
#include "variable-spinbox.hpp"
|
||||
#include "macro-segment-selection.hpp"
|
||||
|
||||
#include <QComboBox>
|
||||
#include <QSpinBox>
|
||||
@@ -37,6 +37,8 @@ public:
|
||||
COUNT,
|
||||
STATE,
|
||||
MULTI_STATE,
|
||||
ACTION_DISABLED,
|
||||
ACTION_ENABLED,
|
||||
};
|
||||
Type _type = Type::STATE;
|
||||
|
||||
@@ -55,11 +57,13 @@ public:
|
||||
};
|
||||
MultiStateCondition _multiSateCondition = MultiStateCondition::ABOVE;
|
||||
NumberVariable<int> _multiSateCount = 0;
|
||||
IntVariable _actionIndex = 1;
|
||||
|
||||
private:
|
||||
bool CheckCountCondition();
|
||||
bool CheckStateCondition();
|
||||
bool CheckMultiStateCondition();
|
||||
bool CheckActionStateCondition();
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
@@ -95,6 +99,7 @@ private slots:
|
||||
void Add(const std::string &);
|
||||
void Remove(int);
|
||||
void Replace(int, const std::string &);
|
||||
void ActionIndexChanged(const IntVariable &value);
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
@@ -111,15 +116,18 @@ protected:
|
||||
MacroList *_macroList;
|
||||
QComboBox *_multiStateConditions;
|
||||
VariableSpinBox *_multiStateCount;
|
||||
MacroSegmentSelection *_actionIndex;
|
||||
QTimer _countTimer;
|
||||
QTimer _pausedTimer;
|
||||
std::shared_ptr<MacroConditionMacro> _entryData;
|
||||
|
||||
private:
|
||||
void ClearLayouts();
|
||||
void SetupWidgets();
|
||||
void SetupStateWidgets();
|
||||
void SetupMultiStateWidgets();
|
||||
void SetupCountWidgets();
|
||||
void SetupActionStateWidgets(bool enable);
|
||||
void SetWidgetVisibility();
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
@@ -10,7 +10,7 @@ bool MacroConditionStats::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionStats::Create, MacroConditionStatsEdit::Create,
|
||||
"AdvSceneSwitcher.condition.stats"});
|
||||
|
||||
static std::map<MacroConditionStats::Type, std::string> statsTypes = {
|
||||
const static std::map<MacroConditionStats::Type, std::string> statsTypes = {
|
||||
{MacroConditionStats::Type::FPS,
|
||||
"AdvSceneSwitcher.condition.stats.type.fps"},
|
||||
{MacroConditionStats::Type::CPU_USAGE,
|
||||
@@ -39,7 +39,7 @@ static std::map<MacroConditionStats::Type, std::string> statsTypes = {
|
||||
"AdvSceneSwitcher.condition.stats.type.megabytesSent.recording"},
|
||||
};
|
||||
|
||||
static std::map<MacroConditionStats::Condition, std::string>
|
||||
const static std::map<MacroConditionStats::Condition, std::string>
|
||||
statsConditionTypes = {
|
||||
{MacroConditionStats::Condition::ABOVE,
|
||||
"AdvSceneSwitcher.condition.stats.condition.above"},
|
||||
|
||||
@@ -14,7 +14,7 @@ bool MacroConditionPluginState::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionPluginStateEdit::Create,
|
||||
"AdvSceneSwitcher.condition.pluginState"});
|
||||
|
||||
static std::map<MacroConditionPluginState::Condition, std::string>
|
||||
const static std::map<MacroConditionPluginState::Condition, std::string>
|
||||
pluginStateConditionTypes = {
|
||||
{MacroConditionPluginState::Condition::PLUGIN_START,
|
||||
"AdvSceneSwitcher.condition.pluginState.state.start"},
|
||||
@@ -112,24 +112,28 @@ static inline void populateConditionSelection(QComboBox *list)
|
||||
|
||||
MacroConditionPluginStateEdit::MacroConditionPluginStateEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionPluginState> entryData)
|
||||
: QWidget(parent)
|
||||
: QWidget(parent),
|
||||
_condition(new QComboBox()),
|
||||
_shutdownLimitation(new QLabel(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.pluginState.state.shutdown.limitation")))
|
||||
{
|
||||
_condition = new QComboBox();
|
||||
|
||||
_shutdownLimitation->setWordWrap(true);
|
||||
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ConditionChanged(int)));
|
||||
populateConditionSelection(_condition);
|
||||
|
||||
QHBoxLayout *switchLayout = new QHBoxLayout;
|
||||
auto entryLayout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{condition}}", _condition},
|
||||
};
|
||||
PlaceWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.pluginState.entry"),
|
||||
switchLayout, widgetPlaceholders);
|
||||
entryLayout, widgetPlaceholders);
|
||||
entryLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(switchLayout);
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(entryLayout);
|
||||
mainLayout->addWidget(_shutdownLimitation);
|
||||
setLayout(mainLayout);
|
||||
|
||||
_entryData = entryData;
|
||||
@@ -155,6 +159,7 @@ void MacroConditionPluginStateEdit::ConditionChanged(int idx)
|
||||
MacroConditionPluginState::Condition::OBS_SHUTDOWN) {
|
||||
switcher->shutdownConditionCount++;
|
||||
}
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionPluginStateEdit::UpdateEntryData()
|
||||
@@ -165,6 +170,16 @@ void MacroConditionPluginStateEdit::UpdateEntryData()
|
||||
|
||||
_condition->setCurrentIndex(
|
||||
_condition->findData(static_cast<int>(_entryData->_condition)));
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionPluginStateEdit::SetWidgetVisibility()
|
||||
{
|
||||
_shutdownLimitation->setVisible(
|
||||
_entryData->_condition ==
|
||||
MacroConditionPluginState::Condition::OBS_SHUTDOWN);
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -58,7 +58,10 @@ private slots:
|
||||
void ConditionChanged(int idx);
|
||||
|
||||
protected:
|
||||
void SetWidgetVisibility();
|
||||
|
||||
QComboBox *_condition;
|
||||
QLabel *_shutdownLimitation;
|
||||
std::shared_ptr<MacroConditionPluginState> _entryData;
|
||||
|
||||
private:
|
||||
|
||||
@@ -10,7 +10,7 @@ bool MacroConditionRecord::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionRecord::Create, MacroConditionRecordEdit::Create,
|
||||
"AdvSceneSwitcher.condition.record"});
|
||||
|
||||
static std::map<RecordState, std::string> recordStates = {
|
||||
const static std::map<RecordState, std::string> recordStates = {
|
||||
{RecordState::STOP, "AdvSceneSwitcher.condition.record.state.stop"},
|
||||
{RecordState::PAUSE, "AdvSceneSwitcher.condition.record.state.pause"},
|
||||
{RecordState::START, "AdvSceneSwitcher.condition.record.state.start"},
|
||||
|
||||
@@ -11,7 +11,7 @@ bool MacroConditionReplayBuffer::_registered = MacroConditionFactory::Register(
|
||||
MacroConditionReplayBufferEdit::Create,
|
||||
"AdvSceneSwitcher.condition.replay"});
|
||||
|
||||
static std::map<ReplayBufferState, std::string> ReplayBufferStates = {
|
||||
const static std::map<ReplayBufferState, std::string> ReplayBufferStates = {
|
||||
{ReplayBufferState::STOP,
|
||||
"AdvSceneSwitcher.condition.replay.state.stopped"},
|
||||
{ReplayBufferState::START,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
#include "process-config.hpp"
|
||||
#include "duration-control.hpp"
|
||||
|
||||
#include <thread>
|
||||
#include <QCheckBox>
|
||||
#include <QSpinBox>
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ bool MacroConditionSceneOrder::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionSceneOrder::Create, MacroConditionSceneOrderEdit::Create,
|
||||
"AdvSceneSwitcher.condition.sceneOrder"});
|
||||
|
||||
static std::map<MacroConditionSceneOrder::Condition, std::string>
|
||||
const static std::map<MacroConditionSceneOrder::Condition, std::string>
|
||||
sceneOrderConditionTypes = {
|
||||
{MacroConditionSceneOrder::Condition::ABOVE,
|
||||
"AdvSceneSwitcher.condition.sceneOrder.type.above"},
|
||||
@@ -29,16 +29,16 @@ struct PosInfo2 {
|
||||
static bool getSceneItemPositionHelper(obs_scene_t *, obs_sceneitem_t *item,
|
||||
void *ptr)
|
||||
{
|
||||
PosInfo2 *posInfo = reinterpret_cast<PosInfo2 *>(ptr);
|
||||
auto posInfo = reinterpret_cast<PosInfo2 *>(ptr);
|
||||
if (obs_sceneitem_is_group(item)) {
|
||||
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
||||
obs_scene_enum_items(scene, getSceneItemPositionHelper, ptr);
|
||||
}
|
||||
if (posInfo->item == item) {
|
||||
posInfo->pos = posInfo->curPos;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (obs_sceneitem_is_group(item)) {
|
||||
obs_scene_t *scene = obs_sceneitem_group_get_scene(item);
|
||||
obs_scene_enum_items(scene, getSceneItemPositionHelper, ptr);
|
||||
}
|
||||
posInfo->curPos += 1;
|
||||
return true;
|
||||
}
|
||||
@@ -50,11 +50,11 @@ static PosInfo2 getSceneItemPos(obs_scene_item *item, obs_scene *scene)
|
||||
return pos;
|
||||
}
|
||||
|
||||
std::vector<int> getSceneItemPositions(std::vector<obs_scene_item *> &items,
|
||||
obs_scene *scene)
|
||||
static std::vector<int> getSceneItemPositions(std::vector<OBSSceneItem> &items,
|
||||
obs_scene *scene)
|
||||
{
|
||||
std::vector<int> positions;
|
||||
for (auto item : items) {
|
||||
for (const auto &item : items) {
|
||||
auto pos = getSceneItemPos(item, scene);
|
||||
if (pos.pos != -1) {
|
||||
positions.emplace_back(pos.pos);
|
||||
@@ -106,13 +106,6 @@ bool MacroConditionSceneOrder::CheckCondition()
|
||||
auto positions1 = getSceneItemPositions(items1, scene);
|
||||
auto positions2 = getSceneItemPositions(items2, scene);
|
||||
|
||||
for (auto i : items1) {
|
||||
obs_sceneitem_release(i);
|
||||
}
|
||||
for (auto i : items2) {
|
||||
obs_sceneitem_release(i);
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
|
||||
switch (_condition) {
|
||||
@@ -124,8 +117,9 @@ bool MacroConditionSceneOrder::CheckCondition()
|
||||
break;
|
||||
case Condition::POSITION:
|
||||
for (int p : positions1) {
|
||||
if (p == _position)
|
||||
if (p == _position) {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
@@ -195,7 +189,7 @@ std::string MacroConditionSceneOrder::GetShortDesc() const
|
||||
|
||||
static inline void populateConditionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : sceneOrderConditionTypes) {
|
||||
for (const auto &entry : sceneOrderConditionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
@@ -282,6 +276,8 @@ void MacroConditionSceneOrderEdit::SourceChanged(const SceneItemSelection &item)
|
||||
_entryData->_source = item;
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionSceneOrderEdit::Source2Changed(const SceneItemSelection &item)
|
||||
@@ -294,6 +290,8 @@ void MacroConditionSceneOrderEdit::Source2Changed(const SceneItemSelection &item
|
||||
_entryData->_source2 = item;
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionSceneOrderEdit::ConditionChanged(int index)
|
||||
|
||||
@@ -18,12 +18,11 @@ bool MacroConditionSceneTransform::CheckCondition()
|
||||
auto items = _source.GetSceneItems(_scene);
|
||||
|
||||
std::string json;
|
||||
for (auto &item : items) {
|
||||
for (const auto &item : items) {
|
||||
json = GetSceneItemTransform(item);
|
||||
if (MatchJson(json, _settings, _regex)) {
|
||||
ret = true;
|
||||
}
|
||||
obs_sceneitem_release(item);
|
||||
}
|
||||
SetVariableValue(json);
|
||||
return ret;
|
||||
@@ -165,6 +164,8 @@ void MacroConditionSceneTransformEdit::SourceChanged(
|
||||
_entryData->_source = item;
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionSceneTransformEdit::GetSettingsClicked()
|
||||
@@ -184,10 +185,6 @@ void MacroConditionSceneTransformEdit::GetSettingsClicked()
|
||||
settings = EscapeForRegex(settings);
|
||||
}
|
||||
_settings->setPlainText(settings);
|
||||
|
||||
for (auto item : items) {
|
||||
obs_sceneitem_release(item);
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionSceneTransformEdit::SettingsChanged()
|
||||
|
||||
@@ -14,7 +14,7 @@ bool MacroConditionSceneVisibility::_registered =
|
||||
MacroConditionSceneVisibilityEdit::Create,
|
||||
"AdvSceneSwitcher.condition.sceneVisibility"});
|
||||
|
||||
static std::map<MacroConditionSceneVisibility::Condition, std::string>
|
||||
const static std::map<MacroConditionSceneVisibility::Condition, std::string>
|
||||
conditionTypes = {
|
||||
{MacroConditionSceneVisibility::Condition::SHOWN,
|
||||
"AdvSceneSwitcher.condition.sceneVisibility.type.shown"},
|
||||
@@ -24,32 +24,30 @@ static std::map<MacroConditionSceneVisibility::Condition, std::string>
|
||||
"AdvSceneSwitcher.condition.sceneVisibility.type.changed"},
|
||||
};
|
||||
|
||||
static bool areAllSceneItemsShown(const std::vector<obs_scene_item *> &items)
|
||||
static bool areAllSceneItemsShown(const std::vector<OBSSceneItem> &items)
|
||||
{
|
||||
bool ret = true;
|
||||
for (auto item : items) {
|
||||
for (const auto &item : items) {
|
||||
if (!obs_sceneitem_visible(item)) {
|
||||
ret = false;
|
||||
}
|
||||
obs_sceneitem_release(item);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool areAllSceneItemsHidden(const std::vector<obs_scene_item *> &items)
|
||||
static bool areAllSceneItemsHidden(const std::vector<OBSSceneItem> &items)
|
||||
{
|
||||
bool ret = true;
|
||||
for (auto item : items) {
|
||||
for (const auto &item : items) {
|
||||
if (obs_sceneitem_visible(item)) {
|
||||
ret = false;
|
||||
}
|
||||
obs_sceneitem_release(item);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool
|
||||
didVisibilityOfAnySceneItemsChange(const std::vector<obs_scene_item *> &items,
|
||||
didVisibilityOfAnySceneItemsChange(const std::vector<OBSSceneItem> &items,
|
||||
std::vector<bool> &previousVisibility)
|
||||
{
|
||||
std::vector<bool> currentVisibility;
|
||||
@@ -64,10 +62,6 @@ didVisibilityOfAnySceneItemsChange(const std::vector<obs_scene_item *> &items,
|
||||
ret = previousVisibility != currentVisibility;
|
||||
}
|
||||
previousVisibility = currentVisibility;
|
||||
|
||||
for (const auto &item : items) {
|
||||
obs_sceneitem_release(item);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -86,10 +80,10 @@ bool MacroConditionSceneVisibility::CheckCondition()
|
||||
case Condition::CHANGED:
|
||||
return didVisibilityOfAnySceneItemsChange(items,
|
||||
_previousVisibilty);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -129,7 +123,7 @@ std::string MacroConditionSceneVisibility::GetShortDesc() const
|
||||
|
||||
static inline void populateConditionSelection(QComboBox *list)
|
||||
{
|
||||
for (auto entry : conditionTypes) {
|
||||
for (const auto &entry : conditionTypes) {
|
||||
list->addItem(obs_module_text(entry.second.c_str()));
|
||||
}
|
||||
}
|
||||
@@ -183,6 +177,8 @@ void MacroConditionSceneVisibilityEdit::SourceChanged(
|
||||
_entryData->_source = item;
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionSceneVisibilityEdit::SceneChanged(const SceneSelection &s)
|
||||
|
||||
@@ -11,11 +11,13 @@ bool MacroConditionScene::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionScene::Create, MacroConditionSceneEdit::Create,
|
||||
"AdvSceneSwitcher.condition.scene"});
|
||||
|
||||
static std::map<MacroConditionScene::Type, std::string> sceneTypes = {
|
||||
const static std::map<MacroConditionScene::Type, std::string> sceneTypes = {
|
||||
{MacroConditionScene::Type::CURRENT,
|
||||
"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 @@ 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,
|
||||
@@ -79,6 +83,14 @@ bool MacroConditionScene::CheckCondition()
|
||||
SetVariableValue(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));
|
||||
return scene == _scene.GetScene(false);
|
||||
}
|
||||
case Type::CHANGED:
|
||||
SetVariableValue(GetWeakSourceName(switcher->currentScene));
|
||||
return sceneChanged;
|
||||
@@ -95,6 +107,14 @@ bool MacroConditionScene::CheckCondition()
|
||||
SetVariableValue(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));
|
||||
return sceneNameMatchesRegex(scene.Get(), _pattern);
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -108,6 +128,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 +145,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;
|
||||
}
|
||||
|
||||
@@ -137,8 +198,9 @@ std::string MacroConditionScene::GetShortDesc() const
|
||||
|
||||
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 +261,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->_type = static_cast<MacroConditionScene::Type>(
|
||||
_sceneType->itemData(index).toInt());
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
@@ -234,7 +297,8 @@ void MacroConditionSceneEdit::SetWidgetVisibility()
|
||||
{
|
||||
_scenes->setVisible(
|
||||
_entryData->_type == MacroConditionScene::Type::CURRENT ||
|
||||
_entryData->_type == MacroConditionScene::Type::PREVIOUS);
|
||||
_entryData->_type == MacroConditionScene::Type::PREVIOUS ||
|
||||
_entryData->_type == MacroConditionScene::Type::PREVIEW);
|
||||
_useTransitionTargetScene->setVisible(
|
||||
_entryData->_type == MacroConditionScene::Type::CURRENT ||
|
||||
_entryData->_type == MacroConditionScene::Type::PREVIOUS ||
|
||||
@@ -246,7 +310,9 @@ void MacroConditionSceneEdit::SetWidgetVisibility()
|
||||
_entryData->_type ==
|
||||
MacroConditionScene::Type::CURRENT_PATTERN ||
|
||||
_entryData->_type ==
|
||||
MacroConditionScene::Type::PREVIOUS_PATTERN);
|
||||
MacroConditionScene::Type::PREVIOUS_PATTERN ||
|
||||
_entryData->_type ==
|
||||
MacroConditionScene::Type::PREVIEW_PATTERN);
|
||||
|
||||
if (_entryData->_type == MacroConditionScene::Type::PREVIOUS ||
|
||||
_entryData->_type == MacroConditionScene::Type::PREVIOUS_PATTERN) {
|
||||
@@ -259,6 +325,7 @@ void MacroConditionSceneEdit::SetWidgetVisibility()
|
||||
"AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour"));
|
||||
}
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionSceneEdit::UpdateEntryData()
|
||||
@@ -268,7 +335,8 @@ void MacroConditionSceneEdit::UpdateEntryData()
|
||||
}
|
||||
|
||||
_scenes->SetScene(_entryData->_scene);
|
||||
_sceneType->setCurrentIndex(static_cast<int>(_entryData->_type));
|
||||
_sceneType->setCurrentIndex(
|
||||
_sceneType->findData(static_cast<int>(_entryData->_type)));
|
||||
_pattern->setText(QString::fromStdString(_entryData->_pattern));
|
||||
_useTransitionTargetScene->setChecked(
|
||||
_entryData->_useTransitionTargetScene);
|
||||
|
||||
@@ -23,12 +23,14 @@ 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,
|
||||
};
|
||||
|
||||
SceneSelection _scene;
|
||||
|
||||
315
src/macro-core/macro-condition-slideshow.cpp
Normal file
315
src/macro-core/macro-condition-slideshow.cpp
Normal file
@@ -0,0 +1,315 @@
|
||||
#include "macro-condition-slideshow.hpp"
|
||||
#include "macro.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
const std::string MacroConditionSlideshow::id = "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 = {
|
||||
{MacroConditionSlideshow::Condition::SLIDE_CHANGED,
|
||||
"AdvSceneSwitcher.condition.slideshow.condition.slideChanged"},
|
||||
{MacroConditionSlideshow::Condition::SLIDE_INDEX,
|
||||
"AdvSceneSwitcher.condition.slideshow.condition.slideIndex"},
|
||||
{MacroConditionSlideshow::Condition::SLIDE_PATH,
|
||||
"AdvSceneSwitcher.condition.slideshow.condition.slidePath"},
|
||||
};
|
||||
|
||||
MacroConditionSlideshow::MacroConditionSlideshow(Macro *m)
|
||||
: MacroCondition(m, true)
|
||||
{
|
||||
}
|
||||
|
||||
MacroConditionSlideshow::~MacroConditionSlideshow()
|
||||
{
|
||||
RemoveSignalHandler();
|
||||
}
|
||||
|
||||
bool MacroConditionSlideshow::CheckCondition()
|
||||
{
|
||||
auto source = _source.GetSource();
|
||||
if (_currentSignalSource != source) {
|
||||
Reset();
|
||||
RemoveSignalHandler();
|
||||
AddSignalHandler(source);
|
||||
}
|
||||
|
||||
if (!source) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (_condition) {
|
||||
case MacroConditionSlideshow::Condition::SLIDE_CHANGED:
|
||||
if (!_slideChanged) {
|
||||
SetVariableValue("false");
|
||||
return false;
|
||||
}
|
||||
_slideChanged = false;
|
||||
SetVariableValue("true");
|
||||
return true;
|
||||
case MacroConditionSlideshow::Condition::SLIDE_INDEX:
|
||||
if (_currentIndex == -1) {
|
||||
SetVariableValue("-1");
|
||||
return false;
|
||||
}
|
||||
SetVariableValue(std::to_string(_currentIndex + 1));
|
||||
return _currentIndex == _index - 1;
|
||||
case MacroConditionSlideshow::Condition::SLIDE_PATH:
|
||||
if (_currentPath[0] == '\0') {
|
||||
SetVariableValue("");
|
||||
return false;
|
||||
}
|
||||
SetVariableValue(_currentPath);
|
||||
return std::string(_path) == std::string(_currentPath);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MacroConditionSlideshow::Save(obs_data_t *obj) const
|
||||
{
|
||||
MacroCondition::Save(obj);
|
||||
obs_data_set_int(obj, "condition", static_cast<int>(_condition));
|
||||
_source.Save(obj);
|
||||
_index.Save(obj, "index");
|
||||
_path.Save(obj, "path");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MacroConditionSlideshow::Load(obs_data_t *obj)
|
||||
{
|
||||
MacroCondition::Load(obj);
|
||||
_condition = static_cast<Condition>(obs_data_get_int(obj, "condition"));
|
||||
_source.Load(obj);
|
||||
_index.Load(obj, "index");
|
||||
_path.Load(obj, "path");
|
||||
|
||||
auto s = _source.GetSource();
|
||||
AddSignalHandler(s);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string MacroConditionSlideshow::GetShortDesc() const
|
||||
{
|
||||
return _source.ToString();
|
||||
}
|
||||
|
||||
void MacroConditionSlideshow::SetSource(const SourceSelection &source)
|
||||
{
|
||||
Reset();
|
||||
_source = source;
|
||||
RemoveSignalHandler();
|
||||
auto s = _source.GetSource();
|
||||
AddSignalHandler(s);
|
||||
}
|
||||
|
||||
const SourceSelection &MacroConditionSlideshow::GetSource() const
|
||||
{
|
||||
return _source;
|
||||
}
|
||||
|
||||
void MacroConditionSlideshow::SlideChanged(void *c, calldata_t *data)
|
||||
{
|
||||
auto condition = static_cast<MacroConditionSlideshow *>(c);
|
||||
const auto macro = condition->GetMacro();
|
||||
if (macro && macro->Paused()) {
|
||||
return;
|
||||
}
|
||||
|
||||
long long newIndex = 0;
|
||||
if (!calldata_get_int(data, "index", &newIndex)) {
|
||||
condition->_currentIndex = -1;
|
||||
}
|
||||
|
||||
// Function will be called every time the slide_time timeout is reached
|
||||
// regardless of if there was actually a change in slide index.
|
||||
//
|
||||
// Thus we need to manually check if the slide index really changed.
|
||||
if (newIndex != condition->_currentIndex) {
|
||||
condition->_slideChanged = true;
|
||||
}
|
||||
condition->_currentIndex = newIndex;
|
||||
|
||||
if (!calldata_get_string(data, "path", &condition->_currentPath)) {
|
||||
condition->_currentPath = "";
|
||||
}
|
||||
}
|
||||
|
||||
void MacroConditionSlideshow::RemoveSignalHandler()
|
||||
{
|
||||
obs_source_t *source = obs_weak_source_get_source(_currentSignalSource);
|
||||
if (!source) {
|
||||
return;
|
||||
}
|
||||
signal_handler_t *sh = obs_source_get_signal_handler(source);
|
||||
signal_handler_disconnect(sh, "slide_changed", SlideChanged, this);
|
||||
obs_source_release(source);
|
||||
}
|
||||
|
||||
void MacroConditionSlideshow::AddSignalHandler(const OBSWeakSource &s)
|
||||
{
|
||||
_currentSignalSource = s;
|
||||
if (!s) {
|
||||
return;
|
||||
}
|
||||
|
||||
obs_source_t *source = obs_weak_source_get_source(s);
|
||||
signal_handler_t *sh = obs_source_get_signal_handler(source);
|
||||
signal_handler_connect(sh, "slide_changed", SlideChanged, this);
|
||||
obs_source_release(source);
|
||||
}
|
||||
|
||||
void MacroConditionSlideshow::Reset()
|
||||
{
|
||||
_slideChanged = false;
|
||||
_currentIndex = -1;
|
||||
_currentPath = "";
|
||||
}
|
||||
|
||||
static void populateConditionSelection(QComboBox *list)
|
||||
{
|
||||
for (const auto &[_, name] : conditions) {
|
||||
list->addItem(obs_module_text(name.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
static QStringList getSlideshowNames()
|
||||
{
|
||||
auto sourceEnum = [](void *param, obs_source_t *source) -> bool /* -- */
|
||||
{
|
||||
QStringList *list = reinterpret_cast<QStringList *>(param);
|
||||
std::string sourceId = obs_source_get_id(source);
|
||||
if (sourceId.compare("slideshow") == 0) {
|
||||
*list << obs_source_get_name(source);
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
QStringList list;
|
||||
obs_enum_sources(sourceEnum, &list);
|
||||
return list;
|
||||
}
|
||||
|
||||
MacroConditionSlideshowEdit::MacroConditionSlideshowEdit(
|
||||
QWidget *parent, std::shared_ptr<MacroConditionSlideshow> entryData)
|
||||
: QWidget(parent),
|
||||
_conditions(new QComboBox(this)),
|
||||
_index(new VariableSpinBox(this)),
|
||||
_path(new VariableLineEdit(this)),
|
||||
_sources(new SourceSelectionWidget(this, QStringList(), true))
|
||||
{
|
||||
setToolTip(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.slideshow.updateIntervalTooltip"));
|
||||
_index->setMinimum(1);
|
||||
populateConditionSelection(_conditions);
|
||||
|
||||
auto sources = getSlideshowNames();
|
||||
sources.sort();
|
||||
_sources->SetSourceNameList(sources);
|
||||
|
||||
QWidget::connect(_conditions, SIGNAL(currentIndexChanged(int)), this,
|
||||
SLOT(ConditionChanged(int)));
|
||||
QWidget::connect(_sources,
|
||||
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||
SLOT(SourceChanged(const SourceSelection &)));
|
||||
QWidget::connect(
|
||||
_index,
|
||||
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||
this, SLOT(IndexChanged(const NumberVariable<int> &)));
|
||||
QWidget::connect(_path, SIGNAL(editingFinished()), this,
|
||||
SLOT(PathChanged()));
|
||||
|
||||
auto layout = new QHBoxLayout;
|
||||
PlaceWidgets(
|
||||
obs_module_text("AdvSceneSwitcher.condition.slideshow.entry"),
|
||||
layout,
|
||||
{{"{{conditions}}", _conditions},
|
||||
{"{{sources}}", _sources},
|
||||
{"{{index}}", _index},
|
||||
{"{{path}}", _path}});
|
||||
setLayout(layout);
|
||||
|
||||
_entryData = entryData;
|
||||
UpdateEntryData();
|
||||
_loading = false;
|
||||
}
|
||||
|
||||
void MacroConditionSlideshowEdit::ConditionChanged(int index)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_condition =
|
||||
static_cast<MacroConditionSlideshow::Condition>(index);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionSlideshowEdit::SourceChanged(const SourceSelection &source)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->SetSource(source);
|
||||
emit HeaderInfoChanged(
|
||||
QString::fromStdString(_entryData->GetShortDesc()));
|
||||
}
|
||||
|
||||
void MacroConditionSlideshowEdit::IndexChanged(const NumberVariable<int> &value)
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_index = value;
|
||||
}
|
||||
|
||||
void MacroConditionSlideshowEdit::PathChanged()
|
||||
{
|
||||
if (_loading || !_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_path = _path->text().toStdString();
|
||||
}
|
||||
|
||||
void MacroConditionSlideshowEdit::UpdateEntryData()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||
_sources->SetSource(_entryData->GetSource());
|
||||
_index->SetValue(_entryData->_index);
|
||||
_path->setText(_entryData->_path);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionSlideshowEdit::SetWidgetVisibility()
|
||||
{
|
||||
if (!_entryData) {
|
||||
return;
|
||||
}
|
||||
|
||||
_index->setVisible(_entryData->_condition ==
|
||||
MacroConditionSlideshow::Condition::SLIDE_INDEX);
|
||||
_path->setVisible(_entryData->_condition ==
|
||||
MacroConditionSlideshow::Condition::SLIDE_PATH);
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
88
src/macro-core/macro-condition-slideshow.hpp
Normal file
88
src/macro-core/macro-condition-slideshow.hpp
Normal file
@@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
#include "macro-condition-edit.hpp"
|
||||
#include "source-selection.hpp"
|
||||
#include "variable-spinbox.hpp"
|
||||
#include "variable-line-edit.hpp"
|
||||
|
||||
namespace advss {
|
||||
|
||||
class MacroConditionSlideshow : public MacroCondition {
|
||||
public:
|
||||
MacroConditionSlideshow(Macro *m);
|
||||
~MacroConditionSlideshow();
|
||||
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<MacroConditionSlideshow>(m);
|
||||
}
|
||||
|
||||
void SetSource(const SourceSelection &source);
|
||||
const SourceSelection &GetSource() const;
|
||||
|
||||
enum class Condition {
|
||||
SLIDE_CHANGED,
|
||||
SLIDE_INDEX,
|
||||
SLIDE_PATH,
|
||||
};
|
||||
Condition _condition = Condition::SLIDE_CHANGED;
|
||||
IntVariable _index;
|
||||
StringVariable _path;
|
||||
|
||||
private:
|
||||
static void SlideChanged(void *condition, calldata_t *);
|
||||
void RemoveSignalHandler();
|
||||
void AddSignalHandler(const OBSWeakSource &);
|
||||
void Reset();
|
||||
|
||||
SourceSelection _source;
|
||||
OBSWeakSource _currentSignalSource;
|
||||
bool _slideChanged = false;
|
||||
long long _currentIndex = -1;
|
||||
const char *_currentPath = "";
|
||||
|
||||
static bool _registered;
|
||||
static const std::string id;
|
||||
};
|
||||
|
||||
class MacroConditionSlideshowEdit : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
MacroConditionSlideshowEdit(
|
||||
QWidget *parent,
|
||||
std::shared_ptr<MacroConditionSlideshow> cond = nullptr);
|
||||
void UpdateEntryData();
|
||||
static QWidget *Create(QWidget *parent,
|
||||
std::shared_ptr<MacroCondition> cond)
|
||||
{
|
||||
return new MacroConditionSlideshowEdit(
|
||||
parent,
|
||||
std::dynamic_pointer_cast<MacroConditionSlideshow>(
|
||||
cond));
|
||||
}
|
||||
|
||||
private slots:
|
||||
void ConditionChanged(int index);
|
||||
void SourceChanged(const SourceSelection &);
|
||||
void IndexChanged(const NumberVariable<int> &);
|
||||
void PathChanged();
|
||||
signals:
|
||||
void HeaderInfoChanged(const QString &);
|
||||
|
||||
private:
|
||||
void SetWidgetVisibility();
|
||||
|
||||
QComboBox *_conditions;
|
||||
VariableSpinBox *_index;
|
||||
VariableLineEdit *_path;
|
||||
SourceSelectionWidget *_sources;
|
||||
|
||||
std::shared_ptr<MacroConditionSlideshow> _entryData;
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
} // namespace advss
|
||||
@@ -10,13 +10,16 @@ bool MacroConditionSource::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionSource::Create, MacroConditionSourceEdit::Create,
|
||||
"AdvSceneSwitcher.condition.source"});
|
||||
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,7 +116,9 @@ MacroConditionSourceEdit::MacroConditionSourceEdit(
|
||||
populateConditionSelection(_conditions);
|
||||
auto sources = GetSourceNames();
|
||||
sources.sort();
|
||||
_sources->SetSourceNameList(sources);
|
||||
auto scenes = GetSceneNames();
|
||||
scenes.sort();
|
||||
_sources->SetSourceNameList(sources + scenes);
|
||||
|
||||
QWidget::connect(_sources,
|
||||
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||
@@ -121,24 +132,27 @@ MacroConditionSourceEdit::MacroConditionSourceEdit(
|
||||
QWidget::connect(_regex, SIGNAL(RegexConfigChanged(RegexConfig)), this,
|
||||
SLOT(RegexChanged(RegexConfig)));
|
||||
|
||||
QVBoxLayout *mainLayout = new QVBoxLayout;
|
||||
QHBoxLayout *line1Layout = new QHBoxLayout;
|
||||
QHBoxLayout *line2Layout = new QHBoxLayout;
|
||||
QHBoxLayout *line3Layout = new QHBoxLayout;
|
||||
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||
{"{{sources}}", _sources}, {"{{conditions}}", _conditions},
|
||||
{"{{settings}}", _settings}, {"{{getSettings}}", _getSettings},
|
||||
{"{{regex}}", _regex},
|
||||
};
|
||||
auto line1Layout = new QHBoxLayout;
|
||||
line1Layout->setContentsMargins(0, 0, 0, 0);
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.source.entry.line1"),
|
||||
line1Layout, widgetPlaceholders);
|
||||
auto line2Layout = new QHBoxLayout;
|
||||
line2Layout->setContentsMargins(0, 0, 0, 0);
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.source.entry.line2"),
|
||||
line2Layout, widgetPlaceholders, false);
|
||||
auto line3Layout = new QHBoxLayout;
|
||||
line3Layout->setContentsMargins(0, 0, 0, 0);
|
||||
PlaceWidgets(obs_module_text(
|
||||
"AdvSceneSwitcher.condition.source.entry.line3"),
|
||||
line3Layout, widgetPlaceholders);
|
||||
auto mainLayout = new QVBoxLayout;
|
||||
mainLayout->addLayout(line1Layout);
|
||||
mainLayout->addLayout(line2Layout);
|
||||
mainLayout->addLayout(line3Layout);
|
||||
@@ -168,9 +182,9 @@ void MacroConditionSourceEdit::ConditionChanged(int index)
|
||||
}
|
||||
|
||||
auto lock = LockContext();
|
||||
_entryData->_condition = static_cast<SourceCondition>(index);
|
||||
SetSettingsSelectionVisible(_entryData->_condition ==
|
||||
SourceCondition::SETTINGS);
|
||||
_entryData->_condition =
|
||||
static_cast<MacroConditionSource::Condition>(index);
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
void MacroConditionSourceEdit::GetSettingsClicked()
|
||||
@@ -213,12 +227,27 @@ void MacroConditionSourceEdit::RegexChanged(RegexConfig conf)
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionSourceEdit::SetSettingsSelectionVisible(bool visible)
|
||||
void MacroConditionSourceEdit::SetWidgetVisibility()
|
||||
{
|
||||
_settings->setVisible(visible);
|
||||
_getSettings->setVisible(visible);
|
||||
_regex->setVisible(visible);
|
||||
_settings->setVisible(_entryData->_condition ==
|
||||
MacroConditionSource::Condition::SETTINGS_MATCH);
|
||||
_getSettings->setVisible(
|
||||
_entryData->_condition ==
|
||||
MacroConditionSource::Condition::SETTINGS_MATCH);
|
||||
_regex->setVisible(_entryData->_condition ==
|
||||
MacroConditionSource::Condition::SETTINGS_MATCH);
|
||||
|
||||
setToolTip(
|
||||
(_entryData->_condition ==
|
||||
MacroConditionSource::Condition::ACTIVE ||
|
||||
_entryData->_condition ==
|
||||
MacroConditionSource::Condition::SHOWING)
|
||||
? obs_module_text(
|
||||
"AdvSceneSwitcher.condition.source.sceneVisibilityHint")
|
||||
: "");
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
void MacroConditionSourceEdit::UpdateEntryData()
|
||||
@@ -231,11 +260,7 @@ void MacroConditionSourceEdit::UpdateEntryData()
|
||||
_conditions->setCurrentIndex(static_cast<int>(_entryData->_condition));
|
||||
_settings->setPlainText(_entryData->_settings);
|
||||
_regex->SetRegexConfig(_entryData->_regex);
|
||||
SetSettingsSelectionVisible(_entryData->_condition ==
|
||||
SourceCondition::SETTINGS);
|
||||
|
||||
adjustSize();
|
||||
updateGeometry();
|
||||
SetWidgetVisibility();
|
||||
}
|
||||
|
||||
} // namespace advss
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
@@ -74,7 +77,7 @@ protected:
|
||||
std::shared_ptr<MacroConditionSource> _entryData;
|
||||
|
||||
private:
|
||||
void SetSettingsSelectionVisible(bool visible);
|
||||
void SetWidgetVisibility();
|
||||
bool _loading = true;
|
||||
};
|
||||
|
||||
|
||||
@@ -11,17 +11,18 @@ bool MacroConditionStream::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionStream::Create, MacroConditionStreamEdit::Create,
|
||||
"AdvSceneSwitcher.condition.stream"});
|
||||
|
||||
static std::map<MacroConditionStream::Condition, std::string> streamStates = {
|
||||
{MacroConditionStream::Condition::STOP,
|
||||
"AdvSceneSwitcher.condition.stream.state.stop"},
|
||||
{MacroConditionStream::Condition::START,
|
||||
"AdvSceneSwitcher.condition.stream.state.start"},
|
||||
{MacroConditionStream::Condition::STARTING,
|
||||
"AdvSceneSwitcher.condition.stream.state.starting"},
|
||||
{MacroConditionStream::Condition::STOPPING,
|
||||
"AdvSceneSwitcher.condition.stream.state.stopping"},
|
||||
{MacroConditionStream::Condition::KEYFRAME_INTERVAL,
|
||||
"AdvSceneSwitcher.condition.stream.state.keyFrameInterval"},
|
||||
const static std::map<MacroConditionStream::Condition, std::string>
|
||||
streamStates = {
|
||||
{MacroConditionStream::Condition::STOP,
|
||||
"AdvSceneSwitcher.condition.stream.state.stop"},
|
||||
{MacroConditionStream::Condition::START,
|
||||
"AdvSceneSwitcher.condition.stream.state.start"},
|
||||
{MacroConditionStream::Condition::STARTING,
|
||||
"AdvSceneSwitcher.condition.stream.state.starting"},
|
||||
{MacroConditionStream::Condition::STOPPING,
|
||||
"AdvSceneSwitcher.condition.stream.state.stopping"},
|
||||
{MacroConditionStream::Condition::KEYFRAME_INTERVAL,
|
||||
"AdvSceneSwitcher.condition.stream.state.keyFrameInterval"},
|
||||
};
|
||||
|
||||
int MacroConditionStream::GetKeyFrameInterval()
|
||||
|
||||
@@ -10,13 +10,14 @@ bool MacroConditionStudioMode::_registered = MacroConditionFactory::Register(
|
||||
{MacroConditionStudioMode::Create, MacroConditionStudioModeEdit::Create,
|
||||
"AdvSceneSwitcher.condition.studioMode"});
|
||||
|
||||
static std::map<StudioModeCondition, std::string> studioModeConditionTypes = {
|
||||
{StudioModeCondition::STUDIO_MODE_ACTIVE,
|
||||
"AdvSceneSwitcher.condition.studioMode.state.active"},
|
||||
{StudioModeCondition::STUDIO_MODE_NOT_ACTIVE,
|
||||
"AdvSceneSwitcher.condition.studioMode.state.notActive"},
|
||||
{StudioModeCondition::PREVIEW_SCENE,
|
||||
"AdvSceneSwitcher.condition.studioMode.state.previewScene"},
|
||||
const static std::map<StudioModeCondition, std::string>
|
||||
studioModeConditionTypes = {
|
||||
{StudioModeCondition::STUDIO_MODE_ACTIVE,
|
||||
"AdvSceneSwitcher.condition.studioMode.state.active"},
|
||||
{StudioModeCondition::STUDIO_MODE_NOT_ACTIVE,
|
||||
"AdvSceneSwitcher.condition.studioMode.state.notActive"},
|
||||
{StudioModeCondition::PREVIEW_SCENE,
|
||||
"AdvSceneSwitcher.condition.studioMode.state.previewScene"},
|
||||
};
|
||||
|
||||
bool MacroConditionStudioMode::CheckCondition()
|
||||
@@ -154,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
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user