Compare commits

...

68 Commits

Author SHA1 Message Date
WarmUpTill
e683fd82f4 Draft source interaction action 2024-07-09 21:23:38 +02:00
WarmUpTill
17c72b772d Display plugin load failure warning only once 2024-07-09 19:10:51 +02:00
WarmUpTill
3ff9a1f270 Add USB condition type
It allows users to check if a given USB device is currently connected
2024-07-08 20:54:26 +02:00
WarmUpTill
7d120d8b6a Fix MacOS version of install_advss_plugin_dependency_file 2024-07-08 20:54:26 +02:00
WarmUpTill
53cfe4b030 Add libusb dependency 2024-07-08 20:54:26 +02:00
WarmUpTill
4dcd748a1f Switch to github repo of openssl 2024-07-08 20:54:26 +02:00
WarmUpTill
223ce0d0a0 Fix potential crash in StatusControl 2024-07-03 13:02:34 +02:00
WarmUpTill
5bd3341681 Add option to clear message buffer on match 2024-07-03 13:02:34 +02:00
WarmUpTill
bb527d6910 Improve error logging of commercial start via Twitch action 2024-07-03 12:55:49 +02:00
WarmUpTill
dfedbcf31a Add option to set maximum replay buffer time 2024-06-26 19:19:41 +02:00
WarmUpTill
1bbfd16b3f Add option to check disk space available
Based on the OBS stats dock implementation, which queries the drive to
which outputs would write to
2024-06-22 15:40:47 +02:00
WarmUpTill
7f5737d03f Use default cursor icon on macro segment control hover
Previously the cursor icon would be set to Qt::SplitVCursor as those
widgets were moved into the splitter handle layout
2024-06-20 21:41:28 +02:00
WarmUpTill
7702541d81 Cleanup
* Increase update frequency of AutoUpdateTooltipLabel
* Prevent crash in TempVariableRef::PostLoad()
* Ensure that correct widget is passed for MacroSelection connections
2024-06-20 21:41:28 +02:00
WarmUpTill
3bc15e585c Switch QPushButton to QToolButton
This will be more consistent with the widget styles used throughout OBS
and solves a few layout issues
2024-06-20 21:41:28 +02:00
WarmUpTill
d77101b6aa Restore fullscreen projector display selection
Instead of discarding the monitor selection now only no longer perform
the action while the monitor setup is changed.
2024-06-18 21:24:28 +02:00
WarmUpTill
c1e23f9c7a Improve slide show condition
* Add temp var support
* Add regex support for path check
* Improve layout stretch handling
2024-06-16 18:42:06 +02:00
WarmUpTill
70415cd8f4 Add support for "slideshow_v2" 2024-06-16 18:42:06 +02:00
WarmUpTill
f50cd76493 Fix i386 build issue 2024-06-16 11:04:05 +02:00
炭酸コーラ
e4af698881 Add Japanese translation 2024-06-15 10:11:45 +02:00
WarmUpTill
33120a359c Fix Twitch "goal type" temp var tooltips being cut off early 2024-06-15 10:11:45 +02:00
WarmUpTill
091a364097 Print line numbers in check-locale.py in case of error 2024-06-15 10:11:45 +02:00
WarmUpTill
e3ff6f34fc Update OpenCV to 4.10.0
This adds support for the MSVC toolset 19.40.x
2024-06-11 19:01:01 +02:00
WarmUpTill
ed75a221fe Fix crashes in combination with older MSVC redistributable versions
Since the switch of Windows 2022 GitHub actions runner image to version
20240603.1.1 the Visual Studio version was bumped to 17.10.34928.147.
This results in MSVC version 19.40.33811.0 being used at build time.
Combining this with e.g. the MSVC redistributable version 14.34.31938.0
results in segfaults when calling std::mutex::lock.

See also:
https://developercommunity.visualstudio.com/t/Invalid-code-generation-in-release-1940/10678572
2024-06-09 00:39:54 +02:00
WarmUpTill
7b48cb2b8d Fix locale error 2024-06-09 00:39:51 +02:00
WarmUpTill
9d4c8ab475 Fix stylesheet of StatusControl not being set to stopped state 2024-06-07 23:05:08 +02:00
WarmUpTill
3d61ea7d25 Add option to reevaluate condition state in "Macro" action 2024-06-07 21:44:21 +02:00
WarmUpTill
99c8a46296 Add option to ignore pause during condition check 2024-06-07 21:44:21 +02:00
WarmUpTill
7e1d20031c Add HelpIcon
A QLabel consisting of a question mark icon and tooltip
2024-06-07 21:44:21 +02:00
WarmUpTill
0e4b000fb1 Set default action of tpye "Macro" to "Run" 2024-06-07 21:44:21 +02:00
WarmUpTill
fc2451ae08 Rename MacroProperties to MacroSettings 2024-06-07 21:44:21 +02:00
WarmUpTill
be44577967 Add option to set input variable values to Macro action 2024-06-07 21:44:21 +02:00
WarmUpTill
3480ff238e Add macro input variable support 2024-06-07 21:44:21 +02:00
WarmUpTill
ee68427036 Add HighligthMacroSettingsButton() 2024-06-07 21:44:21 +02:00
WarmUpTill
37c32dd1ed Move StringList from base to lib 2024-06-07 21:44:21 +02:00
WarmUpTill
c05a92d417 Refactor widget highlighting 2024-06-07 21:44:21 +02:00
WarmUpTill
d72a0c0d38 Add VariableSelectionDialog 2024-06-07 21:44:21 +02:00
WarmUpTill
235b31fccc Add GUARD_LOADING_AND_LOCK
Helper macro to reduce repetition
2024-06-07 21:44:21 +02:00
WarmUpTill
286f781f4d Add ListEditor helper widget 2024-06-07 21:44:21 +02:00
WarmUpTill
b7516cac5b Fix crash when adding resources to resources tab
A crash could occur if the plugin window was closed and reopened and a
new resource was added to either the Variable, Action queue, Websocket,
or Twitch tab.

No context object was provided to the signal handlers.
The signal provider is intentionally not deleted when the UI is closed.
Because of this, the signal connections were never cleared when the
underlying tab widget was destroyed.
So, in the case of closing and reopening the settings window, the old
connection with the outdated widget pointers would be called again.
2024-06-05 01:05:31 +02:00
WarmUpTill
45967a090f Add tempvar support to filter condition 2024-06-05 01:05:31 +02:00
WarmUpTill
687fb4623e Add tempvar support to source condition 2024-06-05 01:05:31 +02:00
WarmUpTill
4157ae4ed2 Add option to check source height and width 2024-06-05 01:05:31 +02:00
WarmUpTill
5e1469b0d8 Don't restore last opened tab if that tab is no longer visible 2024-06-05 01:05:31 +02:00
WarmUpTill
b3bde6c59f Fix imported variables / actions not being added to respective tabs 2024-06-05 01:05:31 +02:00
WarmUpTill
032f5e2fe9 Improve visibility of plugin stop warning flash in status dock 2024-06-05 01:05:31 +02:00
WarmUpTill
91c053dfd8 Re-add tooltips for the "last used" cells on the variable tab 2024-06-05 01:05:31 +02:00
Przemek Pawlas
1f1ef4ca03 Add variable values swap action 2024-05-25 19:04:09 +02:00
WarmUpTill
7cc44b4470 Fix folder watch condition filter handling 2024-05-19 03:46:53 +02:00
WarmUpTill
54356d9410 Add tooltip to macro property selection in variable action 2024-05-19 01:44:10 +02:00
WarmUpTill
defbdf8b7a Add folder condition
It allows you to watch for chagnes in a given folder
2024-05-19 01:44:10 +02:00
WarmUpTill
a01af6cfc3 Adapt code to be compatible with older MSVC redistributable versions 2024-05-18 23:31:04 +02:00
WarmUpTill
4d9c7f1054 Fix typo 2024-05-18 23:31:04 +02:00
WarmUpTill
ced36e2b5b Add nodiscard to sync-helpers 2024-05-18 23:31:04 +02:00
WarmUpTill
d2749f29b0 Add note about limitations of the window focus action 2024-05-14 20:23:36 +02:00
WarmUpTill
b78c8bc1de Assume minimum volume when no volume update was received within 250ms
Without this timeout the peak volume update, which was received last,
would be used permanently until the next update arrives.
This might only take place when the source produces audio output again.
2024-05-14 19:12:49 +02:00
WarmUpTill
cc4a3560d8 Fix "Window" actions not being applied to OBS windows 2024-05-12 01:29:06 +02:00
WarmUpTill
3ab2ea9e66 Only update Twitch tab content when switching to it
This should reduce the potential lag introduced when querying the token
status using the Twitch API
2024-05-12 01:28:51 +02:00
WarmUpTill
69b82ee2a3 Fix audio condition incorrectly reporting very low volume levels
OBS might very rarely not update _peak quickly enough when very low
intervals are configured on the General tab.
In that case _peak might be set to negative infinity still, which will
result in unexpected behavior, so we use the previously valid peak value
instead.
2024-05-10 15:11:20 +02:00
WarmUpTill
f14e6bf252 Fix crash when access to midi devices is denied 2024-05-10 15:11:20 +02:00
WarmUpTill
e51ae79b4c Improve window action
* The focus action no longer restores maximized windows
* The focus, maximize, minimize, and close actions will be performed on
  all handles matching the given window title
2024-05-10 15:11:20 +02:00
WarmUpTill
8f55856fd5 Fix macro segment highlighting not being in sync
Each macro segment had its own internal timer to handle highlighting.
This handing was now moved centrally to the macro tab.
2024-05-10 15:11:20 +02:00
WarmUpTill
a360d53419 Enable right-click to select macro segments
This will be used to enable copy-paste via the context menu available
when right-clicking a macro segment
2024-05-10 15:11:20 +02:00
WarmUpTill
d28164d02f Fix initial replay buffer save not triggering condition 2024-05-10 15:11:20 +02:00
WarmUpTill
f723212394 Add copy-paste support for individual macro segments 2024-05-10 15:11:20 +02:00
WarmUpTill
a0cb08d18f Fix potential crash when creating actions 2024-05-10 15:11:20 +02:00
WarmUpTill
d18044b764 Add handling for fading of else-controls 2024-05-10 15:11:20 +02:00
WarmUpTill
406b5d61f5 Add option to conditionally run action of other macros 2024-05-10 15:11:20 +02:00
WarmUpTill
9a4eef4a83 Adjust busy loop sleep to 10ms
This is now in line with the new minimum interval value
2024-05-10 15:11:20 +02:00
145 changed files with 7848 additions and 1683 deletions

View File

@@ -9,4 +9,5 @@ package 'libxtst-dev'
package 'libxss-dev' package 'libxss-dev'
package 'libopencv-dev' package 'libopencv-dev'
package 'libtesseract-dev' package 'libtesseract-dev'
package 'libprocps-dev' package 'libprocps-dev'
package 'libusb-1.0-0-dev'

View File

@@ -3,3 +3,4 @@ brew "coreutils"
brew "cmake" brew "cmake"
brew "jq" brew "jq"
brew "xcbeautify" brew "xcbeautify"
brew "automake"

View File

@@ -1,3 +1,4 @@
package 'cmake', path: 'Cmake\bin', bin: 'cmake' package 'cmake', path: 'Cmake\bin', bin: 'cmake'
package 'innosetup', path: 'Inno Setup 6', bin: 'iscc' package 'innosetup', path: 'Inno Setup 6', bin: 'iscc'
package 'OpenSSL', path: 'OpenSSL', bin: 'openssl' package 'OpenSSL', path: 'OpenSSL', bin: 'openssl'
package 'Microsoft.VisualStudio.Locator', path: 'vswhere', bin: 'vswhere'

View File

@@ -380,7 +380,7 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
pushd ${advss_dep_path} pushd ${advss_dep_path}
log_info "Prepare openssl ..." log_info "Prepare openssl ..."
rm -rf openssl rm -rf openssl
git clone git://git.openssl.org/openssl.git --branch openssl-3.1.2 --depth 1 git clone https://github.com/openssl/openssl.git --branch openssl-3.1.2 --depth 1
mv openssl openssl_x86 mv openssl openssl_x86
cp -r openssl_x86 openssl_arm cp -r openssl_x86 openssl_arm
@@ -405,6 +405,55 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
log_info "Clean up openssl dir..." log_info "Clean up openssl dir..."
mv openssl_x86 openssl mv openssl_x86 openssl
rm -rf openssl_arm rm -rf openssl_arm
popd
pushd ${project_root}/deps/libusb
log_info "Prepare libusb ..."
log_info "Building libusb x86 (deps) ..."
export MACOSX_DEPLOYMENT_TARGET=10.9
mkdir ${project_root}/deps/libusb/out_x86
./autogen.sh
./configure --host=x86_64-apple-darwin --prefix=${advss_dep_path}
make && make install
log_info "Building libusb x86 ..."
make clean
rm -r ${project_root}/deps/libusb/out_x86
mkdir ${project_root}/deps/libusb/out_x86
./configure --host=aarch64-apple-darwin --prefix=${project_root}/deps/libusb/out_x86
make && make install
log_info "Building libusb arm ..."
make clean
export SDKROOT=$(xcrun --sdk macosx --show-sdk-path)
export CC=$(xcrun --sdk macosx --find clang)
export CXX=$(xcrun --sdk macosx --find clang++)
export CFLAGS="-arch arm64 -isysroot $SDKROOT"
export CXXFLAGS="-arch arm64 -isysroot $SDKROOT"
export LDFLAGS="-arch arm64 -isysroot $SDKROOT"
export MACOSX_DEPLOYMENT_TARGET=10.15
mkdir ${project_root}/deps/libusb/out_arm
./configure --host=aarch64-apple-darwin --prefix=${project_root}/deps/libusb/out_arm
make && make install
log_info "Combine arm and x86 libusb binaries ..."
lipo -create ${project_root}/deps/libusb/out_x86/lib/libusb-1.0.0.dylib \
${project_root}/deps/libusb/out_arm/lib/libusb-1.0.0.dylib \
-output ${advss_dep_path}/lib/temp-libusb-1.0.0.dylib
mv ${advss_dep_path}/lib/temp-libusb-1.0.0.dylib ${advss_dep_path}/lib/libusb-1.0.0.dylib
install_name_tool -id @rpath/libusb-1.0.0.dylib ${advss_dep_path}/lib/libusb-1.0.0.dylib
log_info "Clean up libusb ..."
unset SDKROOT
unset CC
unset CXX
unset CFLAGS
unset CXXFLAGS
unset LDFLAGS
unset MACOSX_DEPLOYMENT_TARGET
popd
;; ;;
linux) linux)
# Nothing to do for now # Nothing to do for now

View File

@@ -199,6 +199,26 @@ function Build {
Log-Information "Install tesseract..." Log-Information "Install tesseract..."
Invoke-External cmake --install "${TesseractBuildPath}" --prefix "${ADVSSDepPath}" @TesseractCmakeArgs Invoke-External cmake --install "${TesseractBuildPath}" --prefix "${ADVSSDepPath}" @TesseractCmakeArgs
Push-Location -Stack BuildLibusbTemp
Ensure-Location $ProjectRoot
$LibusbPath = "${ProjectRoot}/deps/libusb"
Log-Information "Building libusb..."
$msbuildExe = vswhere -latest -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe | select-object -first 1
if ($msbuildExe) {
Invoke-External $msbuildExe "${LibusbPath}/msvc/libusb.sln" /property:Configuration=Release /property:Platform=x64
$libusbBuildResultDirectory = "${LibusbPath}/build/v143/x64/Release"
if (-not (Test-Path -Path $libusbBuildResultDirectory)) {
$libusbBuildResultDirectory = "${LibusbPath}/x64/Release/dll"
}
Copy-Item -Path "${libusbBuildResultDirectory}/*" -Destination ${ADVSSDepPath} -Recurse -Force
} else {
Log-Information "Failed to locate msbuild.exe - skipping libusb build"
}
} }
Build Build

3
.gitmodules vendored
View File

@@ -25,3 +25,6 @@
[submodule "deps/json"] [submodule "deps/json"]
path = deps/json path = deps/json
url = https://github.com/nlohmann/json.git url = https://github.com/nlohmann/json.git
[submodule "deps/libusb"]
path = deps/libusb
url = https://github.com/libusb/libusb.git

View File

@@ -120,14 +120,16 @@ target_sources(
lib/macro/macro-export-import-dialog.hpp lib/macro/macro-export-import-dialog.hpp
lib/macro/macro-helpers.cpp lib/macro/macro-helpers.cpp
lib/macro/macro-helpers.hpp lib/macro/macro-helpers.hpp
lib/macro/macro-input.cpp
lib/macro/macro-input.hpp
lib/macro/macro-list.cpp lib/macro/macro-list.cpp
lib/macro/macro-list.hpp lib/macro/macro-list.hpp
lib/macro/macro-properties.cpp
lib/macro/macro-properties.hpp
lib/macro/macro-ref.cpp lib/macro/macro-ref.cpp
lib/macro/macro-ref.hpp lib/macro/macro-ref.hpp
lib/macro/macro-run-button.cpp lib/macro/macro-run-button.cpp
lib/macro/macro-run-button.hpp lib/macro/macro-run-button.hpp
lib/macro/macro-segment-copy-paste.cpp
lib/macro/macro-segment-copy-paste.hpp
lib/macro/macro-segment-list.cpp lib/macro/macro-segment-list.cpp
lib/macro/macro-segment-list.hpp lib/macro/macro-segment-list.hpp
lib/macro/macro-segment-selection.cpp lib/macro/macro-segment-selection.cpp
@@ -136,6 +138,8 @@ target_sources(
lib/macro/macro-segment.hpp lib/macro/macro-segment.hpp
lib/macro/macro-selection.cpp lib/macro/macro-selection.cpp
lib/macro/macro-selection.hpp lib/macro/macro-selection.hpp
lib/macro/macro-settings.cpp
lib/macro/macro-settings.hpp
lib/macro/macro-tab.cpp lib/macro/macro-tab.cpp
lib/macro/macro-tree.cpp lib/macro/macro-tree.cpp
lib/macro/macro-tree.hpp lib/macro/macro-tree.hpp
@@ -153,6 +157,8 @@ target_sources(
lib/utils/backup.hpp lib/utils/backup.hpp
lib/utils/curl-helper.cpp lib/utils/curl-helper.cpp
lib/utils/curl-helper.hpp lib/utils/curl-helper.hpp
lib/utils/cursor-shape-changer.cpp
lib/utils/cursor-shape-changer.hpp
lib/utils/double-slider.cpp lib/utils/double-slider.cpp
lib/utils/double-slider.hpp lib/utils/double-slider.hpp
lib/utils/duration-control.cpp lib/utils/duration-control.cpp
@@ -164,10 +170,16 @@ target_sources(
lib/utils/file-selection.hpp lib/utils/file-selection.hpp
lib/utils/filter-combo-box.cpp lib/utils/filter-combo-box.cpp
lib/utils/filter-combo-box.hpp lib/utils/filter-combo-box.hpp
lib/utils/help-icon.hpp
lib/utils/help-icon.cpp
lib/utils/item-selection-helpers.cpp lib/utils/item-selection-helpers.cpp
lib/utils/item-selection-helpers.hpp lib/utils/item-selection-helpers.hpp
lib/utils/layout-helpers.cpp lib/utils/layout-helpers.cpp
lib/utils/layout-helpers.hpp lib/utils/layout-helpers.hpp
lib/utils/list-controls.cpp
lib/utils/list-controls.hpp
lib/utils/list-editor.cpp
lib/utils/list-editor.hpp
lib/utils/log-helper.cpp lib/utils/log-helper.cpp
lib/utils/log-helper.hpp lib/utils/log-helper.hpp
lib/utils/math-helpers.cpp lib/utils/math-helpers.cpp
@@ -219,6 +231,8 @@ target_sources(
lib/utils/splitter-helpers.hpp lib/utils/splitter-helpers.hpp
lib/utils/status-control.cpp lib/utils/status-control.cpp
lib/utils/status-control.hpp lib/utils/status-control.hpp
lib/utils/string-list.cpp
lib/utils/string-list.hpp
lib/utils/switch-button.cpp lib/utils/switch-button.cpp
lib/utils/switch-button.hpp lib/utils/switch-button.hpp
lib/utils/sync-helpers.cpp lib/utils/sync-helpers.cpp
@@ -335,6 +349,9 @@ if(OS_WINDOWS)
if(MSVC) if(MSVC)
target_compile_options(${LIB_NAME} PUBLIC /MP /d2FH4- /wd4267 /wd4267 target_compile_options(${LIB_NAME} PUBLIC /MP /d2FH4- /wd4267 /wd4267
/bigobj) /bigobj)
# Workaround for MSVC incompatibility in CI environment
add_compile_definitions(${target_name} _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR)
endif() endif()
target_sources(${LIB_NAME} PRIVATE lib/win/advanced-scene-switcher-win.cpp) target_sources(${LIB_NAME} PRIVATE lib/win/advanced-scene-switcher-win.cpp)
add_definitions(-D_WEBSOCKETPP_CPP11_STL_) add_definitions(-D_WEBSOCKETPP_CPP11_STL_)

View File

@@ -12,11 +12,13 @@ class localeEntry:
locale = "" locale = ""
widgetPlaceholders = [] widgetPlaceholders = []
qStringArgs = [] qStringArgs = []
lineNum = -1
def __init__(self, locale, widgetPlaceholders, qStringArgs) -> None: def __init__(self, locale, widgetPlaceholders, qStringArgs, lineNum) -> None:
self.locale = locale self.locale = locale
self.widgetPlaceholders = widgetPlaceholders self.widgetPlaceholders = widgetPlaceholders
self.qStringArgs = qStringArgs self.qStringArgs = qStringArgs
self.lineNum = lineNum
def getNonDefaultLocales(dir): def getNonDefaultLocales(dir):
@@ -32,7 +34,7 @@ def getNonDefaultLocales(dir):
def getAllLocaleEntries(file): def getAllLocaleEntries(file):
localeEntries = [] localeEntries = []
with open(file, "r", encoding="UTF-8") as f: with open(file, "r", encoding="UTF-8") as f:
for line in f.readlines(): for lineNum, line in enumerate(f):
widgetPlaceholders = [] widgetPlaceholders = []
qStringArgs = [] qStringArgs = []
@@ -49,7 +51,9 @@ def getAllLocaleEntries(file):
qStringArgs.append(match.group(0)) qStringArgs.append(match.group(0))
localeEntries.append( localeEntries.append(
localeEntry(line.split("=")[0], widgetPlaceholders, qStringArgs) localeEntry(
line.split("=")[0], widgetPlaceholders, qStringArgs, lineNum + 1
)
) )
return localeEntries return localeEntries
@@ -73,8 +77,8 @@ def checkLocaleEntries(file, expectedLocaleEntries):
if expectedLocaleEntry is None: if expectedLocaleEntry is None:
result = False result = False
print( print(
'ERROR: Locale entry "{}" from "{}" not found in "{}"'.format( 'ERROR: Locale entry "{}" from "{}:{}" not found in "{}"'.format(
localeEntry.locale, file, defaultLocaleFile localeEntry.locale, file, localeEntry.lineNum, defaultLocaleFile
) )
) )
continue continue
@@ -83,8 +87,13 @@ def checkLocaleEntries(file, expectedLocaleEntries):
if placeholder not in expectedLocaleEntry.widgetPlaceholders: if placeholder not in expectedLocaleEntry.widgetPlaceholders:
result = False result = False
print( print(
'ERROR: Locale entry "{}" from "{}" does contain "{}" widget placeholder while "{}" does not'.format( 'ERROR: Locale entry "{}" from "{}:{}" does contain "{}" widget placeholder while "{}:{}" does not'.format(
localeEntry.locale, file, placeholder, defaultLocaleFile localeEntry.locale,
file,
localeEntry.lineNum,
placeholder,
defaultLocaleFile,
expectedLocaleEntry.lineNum,
) )
) )
@@ -92,8 +101,8 @@ def checkLocaleEntries(file, expectedLocaleEntries):
if placeholder not in localeEntry.widgetPlaceholders: if placeholder not in localeEntry.widgetPlaceholders:
result = False result = False
print( print(
'ERROR: Locale entry "{}" from "{}" does not contain "{}" widget placeholder'.format( 'ERROR: Locale entry "{}" from "{}:{}" does not contain "{}" widget placeholder'.format(
localeEntry.locale, file, placeholder localeEntry.locale, file, localeEntry.lineNum, placeholder
) )
) )
@@ -101,8 +110,13 @@ def checkLocaleEntries(file, expectedLocaleEntries):
if arg not in expectedLocaleEntry.qStringArgs: if arg not in expectedLocaleEntry.qStringArgs:
result = False result = False
print( print(
'ERROR: Locale entry "{}" from "{}" does contain "{}" QString arg while "{}" does not'.format( 'ERROR: Locale entry "{}" from "{}:{}" does contain "{}" QString arg while "{}:{}" does not'.format(
localeEntry.locale, file, arg, defaultLocaleFile localeEntry.locale,
file,
localeEntry.lineNum,
arg,
defaultLocaleFile,
expectedLocaleEntry.lineNum,
) )
) )
@@ -110,8 +124,8 @@ def checkLocaleEntries(file, expectedLocaleEntries):
if arg not in localeEntry.qStringArgs: if arg not in localeEntry.qStringArgs:
result = False result = False
print( print(
'ERROR: Locale entry "{}" from "{}" does not contain "{}" QString arg'.format( 'ERROR: Locale entry "{}" from "{}:{}" does not contain "{}" QString arg'.format(
localeEntry.locale, file, arg localeEntry.locale, file, localeEntry.lineNum, arg
) )
) )

View File

@@ -60,10 +60,36 @@ if(OS_MACOS)
${dep}_Development) ${dep}_Development)
endfunction() endfunction()
function(install_advss_plugin_dependency_file ${target} dep) function(install_advss_plugin_dependency_file target dep)
target_sources(advanced-scene-switcher PRIVATE ${dep}) get_filename_component(_FILENAME ${dep} NAME)
set_source_files_properties(${dep} PROPERTIES MACOSX_PACKAGE_LOCATION string(REGEX REPLACE "\\.[^.]*$" "" _FILENAMENOEXT ${_FILENAME})
${ADVSS_BUNDLE_PLUGIN_DIR}) set(_DEP_NAME "${target}-${_FILENAMENOEXT}")
install(
FILES "${dep}"
DESTINATION "${ADVSS_BUNDLE_PLUGIN_DIR}"
COMPONENT ${_DEP_NAME}_Runtime
DESTINATION "${ADVSS_BUNDLE_PLUGIN_DIR}"
COMPONENT ${_DEP_NAME}_Runtime
NAMELINK_COMPONENT ${_DEP_NAME}_Development)
install(
FILES "${dep}"
DESTINATION "${ADVSS_BUNDLE_PLUGIN_DIR}"
COMPONENT obs_${_DEP_NAME}
EXCLUDE_FROM_ALL
DESTINATION "${ADVSS_BUNDLE_PLUGIN_DIR}"
COMPONENT obs_${_DEP_NAME}
EXCLUDE_FROM_ALL)
add_custom_command(
TARGET ${target}
POST_BUILD
COMMAND
"${CMAKE_COMMAND}" --install ${CMAKE_CURRENT_BINARY_DIR} --config
$<CONFIG> --prefix ${CMAKE_INSTALL_PREFIX} --component obs_${_DEP_NAME}
COMMENT "Installing ${_DEP_NAME} to OBS rundir\n"
VERBATIM)
endfunction() endfunction()
# --- End of section --- # --- End of section ---

View File

@@ -427,7 +427,6 @@ AdvSceneSwitcher.action.replay.saveWarn="Warnung: Ein zu häufiges Speichern kan
AdvSceneSwitcher.action.replay.type.stop="Replay Buffer stoppen" AdvSceneSwitcher.action.replay.type.stop="Replay Buffer stoppen"
AdvSceneSwitcher.action.replay.type.start="Replay Buffer starten" AdvSceneSwitcher.action.replay.type.start="Replay Buffer starten"
AdvSceneSwitcher.action.replay.type.save="Replay Buffer speichern" AdvSceneSwitcher.action.replay.type.save="Replay Buffer speichern"
AdvSceneSwitcher.action.replay.entry="{{actions}}"
AdvSceneSwitcher.action.streaming="Stream" AdvSceneSwitcher.action.streaming="Stream"
AdvSceneSwitcher.action.streaming.type.stop="Stream stoppen" AdvSceneSwitcher.action.streaming.type.stop="Stream stoppen"
AdvSceneSwitcher.action.streaming.type.start="Stream starten" AdvSceneSwitcher.action.streaming.type.start="Stream starten"
@@ -469,7 +468,6 @@ AdvSceneSwitcher.action.macro.type.unpause="Nicht mehr pausieren"
AdvSceneSwitcher.action.macro.type.resetCounter="Zähler zurücksetzen" AdvSceneSwitcher.action.macro.type.resetCounter="Zähler zurücksetzen"
AdvSceneSwitcher.action.macro.type.run="Aktionen ausführen" AdvSceneSwitcher.action.macro.type.run="Aktionen ausführen"
AdvSceneSwitcher.action.macro.type.stop="Aktionen stoppen" AdvSceneSwitcher.action.macro.type.stop="Aktionen stoppen"
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}"
AdvSceneSwitcher.action.pluginState="Plugin-Status" AdvSceneSwitcher.action.pluginState="Plugin-Status"
AdvSceneSwitcher.action.pluginState.type.stop="Erweiterten Automatischen Szenenwechsler stoppen" AdvSceneSwitcher.action.pluginState.type.stop="Erweiterten Automatischen Szenenwechsler stoppen"
AdvSceneSwitcher.action.pluginState.type.noMatch="Ändern des Nichtübereinstimmungsverhaltens:" AdvSceneSwitcher.action.pluginState.type.noMatch="Ändern des Nichtübereinstimmungsverhaltens:"

View File

@@ -99,8 +99,8 @@ AdvSceneSwitcher.actionQueueTab.isRunning.header="Is running"
AdvSceneSwitcher.actionQueueTab.runOnStartup.header="Run on startup" AdvSceneSwitcher.actionQueueTab.runOnStartup.header="Run on startup"
AdvSceneSwitcher.actionQueueTab.yes="Yes" AdvSceneSwitcher.actionQueueTab.yes="Yes"
AdvSceneSwitcher.actionQueueTab.no="No" AdvSceneSwitcher.actionQueueTab.no="No"
AdvSceneSwitcher.actionQueueTab.removeSingleConnectionPopup.text="Are you sure you want to remove \"%1\"?" AdvSceneSwitcher.actionQueueTab.removeSingleQueuePopup.text="Are you sure you want to remove \"%1\"?"
AdvSceneSwitcher.actionQueueTab.removeMultipleConnectionsPopup.text="Are you sure you want to remove %1 action queues?" AdvSceneSwitcher.actionQueueTab.removeMultipleQueuesPopup.text="Are you sure you want to remove %1 action queues?"
; Websocket Connections Tab ; Websocket Connections Tab
AdvSceneSwitcher.websocketConnectionTab.title="Websocket Connections" AdvSceneSwitcher.websocketConnectionTab.title="Websocket Connections"
@@ -177,9 +177,15 @@ AdvSceneSwitcher.macroTab.minimize="Minimize"
AdvSceneSwitcher.macroTab.segment.useCustomLabel="Use custom label" AdvSceneSwitcher.macroTab.segment.useCustomLabel="Use custom label"
AdvSceneSwitcher.macroTab.segment.defaultCustomLabel="My label" AdvSceneSwitcher.macroTab.segment.defaultCustomLabel="My label"
AdvSceneSwitcher.macroTab.segment.setCustomLabel="Set label ..." AdvSceneSwitcher.macroTab.segment.setCustomLabel="Set label ..."
AdvSceneSwitcher.macroTab.segment.copy="Copy"
AdvSceneSwitcher.macroTab.segment.paste="Paste"
AdvSceneSwitcher.macroTab.highlightSettings="Visual settings" AdvSceneSwitcher.macroTab.highlightSettings="Visual settings"
AdvSceneSwitcher.macroTab.hotkeySettings="Hotkey settings" AdvSceneSwitcher.macroTab.hotkeySettings="Hotkey settings"
AdvSceneSwitcher.macroTab.generalSettings="General settings" AdvSceneSwitcher.macroTab.generalSettings="General settings"
AdvSceneSwitcher.macroTab.inputSettings="Input settings"
AdvSceneSwitcher.macroTab.inputSettings.description="This section will allow you to specify variables, which will be treated as input parameters for the selected macro.\nWhen executing the macro using the \"Macro\" action type, you will have the option to set the values for those variables."
AdvSceneSwitcher.macroTab.inputSettings.invalid="<Invalid selection>"
AdvSceneSwitcher.macroTab.inputSettings.noInputs="No inputs are defined for the selected macro!\nOpen the settings of the macro to define inputs.\nThe settings button is highlighted above."
AdvSceneSwitcher.macroTab.dockSettings="Dock settings" AdvSceneSwitcher.macroTab.dockSettings="Dock settings"
AdvSceneSwitcher.macroTab.highlightExecutedMacros="Highlight recently executed macros" AdvSceneSwitcher.macroTab.highlightExecutedMacros="Highlight recently executed macros"
AdvSceneSwitcher.macroTab.highlightTrueConditions="Highlight conditions of currently selected macro that evaluated to true recently" AdvSceneSwitcher.macroTab.highlightTrueConditions="Highlight conditions of currently selected macro that evaluated to true recently"
@@ -224,7 +230,7 @@ AdvSceneSwitcher.macroTab.tooltip.elseActionTopButton="Move selected action to t
AdvSceneSwitcher.macroTab.tooltip.elseActionUpButton="Move selected action up in the else section" AdvSceneSwitcher.macroTab.tooltip.elseActionUpButton="Move selected action up in the else section"
AdvSceneSwitcher.macroTab.tooltip.elseActionDownButton="Move selected action down in the else section" AdvSceneSwitcher.macroTab.tooltip.elseActionDownButton="Move selected action down in the else section"
AdvSceneSwitcher.macroTab.tooltip.elseActionBottomButton="Move selected action to the bottom in the else section" AdvSceneSwitcher.macroTab.tooltip.elseActionBottomButton="Move selected action to the bottom in the else section"
AdvSceneSwitcher.macroTab.tooltip.openMacroPropertiesButton="Open macro properties" AdvSceneSwitcher.macroTab.tooltip.openMacroSettingsButton="Open macro settings"
AdvSceneSwitcher.macroDock.pause="Pause" AdvSceneSwitcher.macroDock.pause="Pause"
AdvSceneSwitcher.macroDock.unpause="Unpause" AdvSceneSwitcher.macroDock.unpause="Unpause"
@@ -451,11 +457,16 @@ AdvSceneSwitcher.condition.source.type.settingsMatch="Settings match"
AdvSceneSwitcher.condition.source.type.settingsChanged="Settings changed" AdvSceneSwitcher.condition.source.type.settingsChanged="Settings changed"
AdvSceneSwitcher.condition.source.type.individualSettingMatches="Setting value matches" AdvSceneSwitcher.condition.source.type.individualSettingMatches="Setting value matches"
AdvSceneSwitcher.condition.source.type.individualSettingChanged="Setting value changed" AdvSceneSwitcher.condition.source.type.individualSettingChanged="Setting value changed"
AdvSceneSwitcher.condition.source.type.width="Width"
AdvSceneSwitcher.condition.source.type.height="Height"
AdvSceneSwitcher.condition.source.sizeCompare.less="Smaller than"
AdvSceneSwitcher.condition.source.sizeCompare.equal="Equals"
AdvSceneSwitcher.condition.source.sizeCompare.more="Bigger than"
AdvSceneSwitcher.condition.source.refresh="Refresh" AdvSceneSwitcher.condition.source.refresh="Refresh"
AdvSceneSwitcher.condition.source.refreshTooltip="Repopulate the source settings selection with the settings of the source which's name matches the variable value." AdvSceneSwitcher.condition.source.refreshTooltip="Repopulate the source settings selection with the settings of the source which's name matches the variable value."
AdvSceneSwitcher.condition.source.sceneVisibilityHint="Scene specific visibility can be checked using the \"Scene item visibility\" condition" AdvSceneSwitcher.condition.source.sceneVisibilityHint="Scene specific visibility can be checked using the \"Scene item visibility\" condition"
AdvSceneSwitcher.condition.source.getSettings="Get current settings" AdvSceneSwitcher.condition.source.getSettings="Get current settings"
AdvSceneSwitcher.condition.source.entry.line1="{{sources}}{{conditions}}{{settingSelection}}{{refresh}}" AdvSceneSwitcher.condition.source.entry.line1="{{sources}}{{conditions}}{{settingSelection}}{{refresh}}{{sizeCompareMethods}}{{size}}"
AdvSceneSwitcher.condition.source.entry.line2="{{settings}}" AdvSceneSwitcher.condition.source.entry.line2="{{settings}}"
AdvSceneSwitcher.condition.source.entry.line3="{{regex}}{{getSettings}}" AdvSceneSwitcher.condition.source.entry.line3="{{regex}}{{getSettings}}"
AdvSceneSwitcher.condition.virtualCamera="Virtual camera" AdvSceneSwitcher.condition.virtualCamera="Virtual camera"
@@ -609,7 +620,7 @@ AdvSceneSwitcher.condition.slideshow.condition.slideChanged="Slide changed"
AdvSceneSwitcher.condition.slideshow.condition.slideIndex="Current slide number is" AdvSceneSwitcher.condition.slideshow.condition.slideIndex="Current slide number is"
AdvSceneSwitcher.condition.slideshow.condition.slidePath="Current slide path is" AdvSceneSwitcher.condition.slideshow.condition.slidePath="Current slide path is"
AdvSceneSwitcher.condition.slideshow.updateIntervalTooltip="Information about the slide show status will only be updated based on the configured time between slides" AdvSceneSwitcher.condition.slideshow.updateIntervalTooltip="Information about the slide show status will only be updated based on the configured time between slides"
AdvSceneSwitcher.condition.slideshow.entry="{{sources}}{{conditions}}{{index}}{{path}}" AdvSceneSwitcher.condition.slideshow.entry="{{sources}}{{conditions}}{{index}}{{path}}{{regex}}"
AdvSceneSwitcher.condition.twitch="Twitch" AdvSceneSwitcher.condition.twitch="Twitch"
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online="Stream went online" AdvSceneSwitcher.condition.twitch.type.event.channel.stream.online="Stream went online"
AdvSceneSwitcher.condition.twitch.type.event.channel.stream.offline="Stream went offline" AdvSceneSwitcher.condition.twitch.type.event.channel.stream.offline="Stream went offline"
@@ -681,6 +692,27 @@ AdvSceneSwitcher.condition.clipboard.condition.isImage="Clipboard contains an im
AdvSceneSwitcher.condition.clipboard.condition.isURL="Clipboard contains an URL" AdvSceneSwitcher.condition.clipboard.condition.isURL="Clipboard contains an URL"
AdvSceneSwitcher.condition.clipboard.condition.matches="Clipboard content matches" AdvSceneSwitcher.condition.clipboard.condition.matches="Clipboard content matches"
AdvSceneSwitcher.condition.clipboard.condition.entry="{{conditions}}{{regex}}{{urlInfo}}" AdvSceneSwitcher.condition.clipboard.condition.entry="{{conditions}}{{regex}}{{urlInfo}}"
AdvSceneSwitcher.condition.folder="Folder watch"
AdvSceneSwitcher.condition.folder.tooltip="This condition type will allow you to monitor the contents of a folder.\nNote that the monitoring will *not* recursively scan for changes in sub directories within directories of the selected folder!\nNote that if there are several changes during a short period of time, some of the changes might not emit this signal.\nHowever, the last change in the sequence of changes always will."
AdvSceneSwitcher.condition.folder.condition.any="Any change happened"
AdvSceneSwitcher.condition.folder.condition.fileAdd="A file was added"
AdvSceneSwitcher.condition.folder.condition.fileChange="A file was modified"
AdvSceneSwitcher.condition.folder.condition.fileRemove="A file was removed"
AdvSceneSwitcher.condition.folder.condition.folderAdd="A directory was added"
AdvSceneSwitcher.condition.folder.condition.folderRemove="A directory was removed"
AdvSceneSwitcher.condition.folder.entry="{{conditions}}in{{folder}}{{tooltip}}"
AdvSceneSwitcher.condition.folder.enableFilter="Only evaluate to true, if the changed path matches a patern"
AdvSceneSwitcher.condition.folder.entry.filter="{{filter}}{{regex}}"
AdvSceneSwitcher.condition.usb="USB"
AdvSceneSwitcher.condition.usb.description="A USB device matching the following properties is connected:"
AdvSceneSwitcher.condition.usb.vendorID="Vendor ID:"
AdvSceneSwitcher.condition.usb.productID="Product ID:"
AdvSceneSwitcher.condition.usb.busNumber="Bus Number:"
AdvSceneSwitcher.condition.usb.deviceAddress="Device Address:"
AdvSceneSwitcher.condition.usb.vendorName="Vendor Name:"
AdvSceneSwitcher.condition.usb.productName="Product Name:"
AdvSceneSwitcher.condition.usb.serialNumber="Serial Number:"
AdvSceneSwitcher.condition.noDevicesFoundWarning="No USB devices detected!\nThe plugin might not have the required permissions to check for USB devices."
; Macro Actions ; Macro Actions
AdvSceneSwitcher.action.scene="Switch scene" AdvSceneSwitcher.action.scene="Switch scene"
@@ -726,10 +758,12 @@ AdvSceneSwitcher.action.recording.split.hint="Make sure to enable automatic file
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}" AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
AdvSceneSwitcher.action.replay="Replay buffer" AdvSceneSwitcher.action.replay="Replay buffer"
AdvSceneSwitcher.action.replay.saveWarn="Warning: Saving too frequently might result in the replay buffer not actually being saved!" AdvSceneSwitcher.action.replay.saveWarn="Warning: Saving too frequently might result in the replay buffer not actually being saved!"
AdvSceneSwitcher.action.replay.durationWarn="Warning: Changing the maximum replay time will only apply the next time the replay buffer is started!"
AdvSceneSwitcher.action.replay.type.stop="Stop replay buffer" AdvSceneSwitcher.action.replay.type.stop="Stop replay buffer"
AdvSceneSwitcher.action.replay.type.start="Start replay buffer" AdvSceneSwitcher.action.replay.type.start="Start replay buffer"
AdvSceneSwitcher.action.replay.type.save="Save replay buffer" AdvSceneSwitcher.action.replay.type.save="Save replay buffer"
AdvSceneSwitcher.action.replay.entry="{{actions}}" AdvSceneSwitcher.action.replay.type.duration="Set maximum replay time"
AdvSceneSwitcher.action.replay.entry="{{actions}}{{duration}}"
AdvSceneSwitcher.action.streaming="Streaming" AdvSceneSwitcher.action.streaming="Streaming"
AdvSceneSwitcher.action.streaming.type.stop="Stop streaming" AdvSceneSwitcher.action.streaming.type.stop="Stop streaming"
AdvSceneSwitcher.action.streaming.type.start="Start streaming" AdvSceneSwitcher.action.streaming.type.start="Start streaming"
@@ -775,6 +809,12 @@ AdvSceneSwitcher.action.source.type.deinterlaceOrder="Set deinterlace field orde
AdvSceneSwitcher.action.source.type.openInteractionDialog="Open interaction dialog" AdvSceneSwitcher.action.source.type.openInteractionDialog="Open interaction dialog"
AdvSceneSwitcher.action.source.type.openFilterDialog="Open filter dialog" AdvSceneSwitcher.action.source.type.openFilterDialog="Open filter dialog"
AdvSceneSwitcher.action.source.type.openPropertiesDialog="Open properties dialog" AdvSceneSwitcher.action.source.type.openPropertiesDialog="Open properties dialog"
AdvSceneSwitcher.action.source.type.interact="Interact"
AdvSceneSwitcher.action.source.type.interact.selectType="Interaction type:{{type}}"
AdvSceneSwitcher.action.source.type.interact.mouseClick="Send mouse click"
AdvSceneSwitcher.action.source.type.interact.mouseMove="Send mouse move"
AdvSceneSwitcher.action.source.type.interact.mouseWheel="Send mouse wheel"
AdvSceneSwitcher.action.source.type.interact.keyPress="Send key press"
AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}{{deinterlaceMode}}{{deinterlaceOrder}}{{refresh}}" AdvSceneSwitcher.action.source.entry="{{actions}}{{sources}}{{settingsButtons}}{{deinterlaceMode}}{{deinterlaceOrder}}{{refresh}}"
AdvSceneSwitcher.action.source.entry.settings="{{settings}}{{settingsInputMethod}}{{settingValue}}{{tempVar}}" AdvSceneSwitcher.action.source.entry.settings="{{settings}}{{settingsInputMethod}}{{settingValue}}{{tempVar}}"
AdvSceneSwitcher.action.source.warning="Warning: Enabling and disabling sources globally cannot be controlled by the OBS UI\nYou might be looking for \"Scene item visibility\"" AdvSceneSwitcher.action.source.warning="Warning: Enabling and disabling sources globally cannot be controlled by the OBS UI\nYou might be looking for \"Scene item visibility\""
@@ -812,12 +852,24 @@ AdvSceneSwitcher.action.macro="Macro"
AdvSceneSwitcher.action.macro.type.pause="Pause" AdvSceneSwitcher.action.macro.type.pause="Pause"
AdvSceneSwitcher.action.macro.type.unpause="Unpause" AdvSceneSwitcher.action.macro.type.unpause="Unpause"
AdvSceneSwitcher.action.macro.type.resetCounter="Reset counter" AdvSceneSwitcher.action.macro.type.resetCounter="Reset counter"
AdvSceneSwitcher.action.macro.type.run="Run actions" AdvSceneSwitcher.action.macro.type.run="Run macro"
AdvSceneSwitcher.action.macro.type.run.conditions.ignore="Do not consider condition state"
AdvSceneSwitcher.action.macro.type.run.conditions.true="Only if conditions evaluate to true"
AdvSceneSwitcher.action.macro.type.run.conditions.false="Only if conditions evaluate to false"
AdvSceneSwitcher.action.macro.type.run.updateConditionMatchState="Reevaluate the condition state before executing this action"
AdvSceneSwitcher.action.macro.type.run.updateConditionMatchState.help="The plugin operates in phases:\n * The phase evaluating the macro conditions\n * The phase running macro actions\nMacros executed before this particular action might have side effects on the condition state of macros.\nCheck this option if you want those side effects to be taken into account when evaluating the condition state."
AdvSceneSwitcher.action.macro.type.run.actionType.regular="actions"
AdvSceneSwitcher.action.macro.type.run.actionType.else="else-actions"
AdvSceneSwitcher.action.macro.type.run.skipWhenPaused="Skip execution when macro is paused"
AdvSceneSwitcher.action.macro.type.run.setInputs="Set inputs"
AdvSceneSwitcher.action.macro.type.run.setInputs.description="Input variables can be defined in the macro settings.\nDefining input variables will allow you to modify the values of variables before an action is executed."
AdvSceneSwitcher.action.macro.type.stop="Stop actions" AdvSceneSwitcher.action.macro.type.stop="Stop actions"
AdvSceneSwitcher.action.macro.type.disableAction="Disable action" AdvSceneSwitcher.action.macro.type.disableAction="Disable action"
AdvSceneSwitcher.action.macro.type.enableAction="Enable action" AdvSceneSwitcher.action.macro.type.enableAction="Enable action"
AdvSceneSwitcher.action.macro.type.toggleAction="Toggle action" AdvSceneSwitcher.action.macro.type.toggleAction="Toggle action"
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}" AdvSceneSwitcher.action.macro.entry.run="{{actions}}{{actionTypes}}of{{macros}}"
AdvSceneSwitcher.action.macro.entry.run.condition="{{conditionBehaviors}}of{{conditionMacros}}"
AdvSceneSwitcher.action.macro.entry.other="{{actions}}{{actionIndex}}{{macros}}"
AdvSceneSwitcher.action.pluginState="Plugin state" AdvSceneSwitcher.action.pluginState="Plugin state"
AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher plugin" AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher plugin"
AdvSceneSwitcher.action.pluginState.type.noMatch="Change the no-match behaviour:" AdvSceneSwitcher.action.pluginState.type.noMatch="Change the no-match behaviour:"
@@ -962,9 +1014,11 @@ AdvSceneSwitcher.action.variable.type.sceneItemCount="Set to scene item count of
AdvSceneSwitcher.action.variable.type.stringLength="Set to length of string" AdvSceneSwitcher.action.variable.type.stringLength="Set to length of string"
AdvSceneSwitcher.action.variable.type.extractJson="Extract json field with name" AdvSceneSwitcher.action.variable.type.extractJson="Extract json field with name"
AdvSceneSwitcher.action.variable.type.setToTempvar="Set to macro property" AdvSceneSwitcher.action.variable.type.setToTempvar="Set to macro property"
AdvSceneSwitcher.action.variable.type.setToTempvar.help="This action type will allow you to extract values out of segments of the current macro and assign those values to the selected variable.\nFor example, you can get the current scene name from a scene condition and assign this name to a variable."
AdvSceneSwitcher.action.variable.type.sceneItemName="Set to scene item name at index" AdvSceneSwitcher.action.variable.type.sceneItemName="Set to scene item name at index"
AdvSceneSwitcher.action.variable.type.padValue="Pad current value" AdvSceneSwitcher.action.variable.type.padValue="Pad current value"
AdvSceneSwitcher.action.variable.type.truncateValue="Truncate current value" AdvSceneSwitcher.action.variable.type.truncateValue="Truncate current value"
AdvSceneSwitcher.action.variable.type.swapValues="Swap variable values"
AdvSceneSwitcher.action.variable.truncateOrPadDirection.left="Left" AdvSceneSwitcher.action.variable.truncateOrPadDirection.left="Left"
AdvSceneSwitcher.action.variable.truncateOrPadDirection.right="Right" AdvSceneSwitcher.action.variable.truncateOrPadDirection.right="Right"
AdvSceneSwitcher.action.variable.askForValuePromptDefault="Assign value to variable \"%1\":" AdvSceneSwitcher.action.variable.askForValuePromptDefault="Assign value to variable \"%1\":"
@@ -978,7 +1032,7 @@ AdvSceneSwitcher.action.variable.invalidSelection="Invalid selection!"
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Getting variable values from %1 actions is not supported!" AdvSceneSwitcher.action.variable.actionNoVariableSupport="Getting variable values from %1 actions is not supported!"
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Getting variable values from %1 conditions is not supported!" AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Getting variable values from %1 conditions is not supported!"
AdvSceneSwitcher.action.variable.currentSegmentValue="Current value:" AdvSceneSwitcher.action.variable.currentSegmentValue="Current value:"
AdvSceneSwitcher.action.variable.entry.other="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}{{sceneItemIndex}}{{direction}}{{stringLength}}{{paddingCharSelection}}" AdvSceneSwitcher.action.variable.entry.other="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}{{tempVarsHelp}}{{sceneItemIndex}}{{direction}}{{stringLength}}{{paddingCharSelection}}"
AdvSceneSwitcher.action.variable.entry.pad="{{actions}}of{{variables}}to length{{stringLength}}by adding{{paddingCharSelection}}to the{{direction}}" AdvSceneSwitcher.action.variable.entry.pad="{{actions}}of{{variables}}to length{{stringLength}}by adding{{paddingCharSelection}}to the{{direction}}"
AdvSceneSwitcher.action.variable.entry.truncate="{{actions}}of{{variables}}to length{{stringLength}}by removing characters from the{{direction}}" AdvSceneSwitcher.action.variable.entry.truncate="{{actions}}of{{variables}}to length{{stringLength}}by removing characters from the{{direction}}"
AdvSceneSwitcher.action.variable.entry.substringIndex="Substring start:{{subStringStart}}Substring size:{{subStringSize}}" AdvSceneSwitcher.action.variable.entry.substringIndex="Substring start:{{subStringStart}}Substring size:{{subStringSize}}"
@@ -1044,6 +1098,8 @@ AdvSceneSwitcher.action.queue.entry.add="{{actions}}actions of macro{{macros}}to
AdvSceneSwitcher.action.queue.entry.other="{{actions}}queue{{queues}}" AdvSceneSwitcher.action.queue.entry.other="{{actions}}queue{{queues}}"
AdvSceneSwitcher.action.window="Window" AdvSceneSwitcher.action.window="Window"
AdvSceneSwitcher.action.window.type.setFocusWindow="Focus window" AdvSceneSwitcher.action.window.type.setFocusWindow="Focus window"
AdvSceneSwitcher.action.window.type.setFocusWindow.limitation="The focus action can only be performed under certain circumstances"
AdvSceneSwitcher.action.window.type.setFocusWindow.limitation.details="At least one of the following conditions must be true:\n OBS is the foreground process.\n There is currently no foreground window, and thus no foreground process.\n OBS received the last input event."
AdvSceneSwitcher.action.window.type.maximizeWindow="Maximize window" AdvSceneSwitcher.action.window.type.maximizeWindow="Maximize window"
AdvSceneSwitcher.action.window.type.minimizeWindow="Minimize window" AdvSceneSwitcher.action.window.type.minimizeWindow="Minimize window"
AdvSceneSwitcher.action.window.type.closeWindow="Close window" AdvSceneSwitcher.action.window.type.closeWindow="Close window"
@@ -1079,6 +1135,11 @@ AdvSceneSwitcher.item.emptyName="Empty name not allowed!"
AdvSceneSwitcher.item.nameNotAvailable="Name not available!" AdvSceneSwitcher.item.nameNotAvailable="Name not available!"
AdvSceneSwitcher.item.nameReserved="Name reserved!" AdvSceneSwitcher.item.nameReserved="Name reserved!"
AdvSceneSwitcher.listControls.add="Add"
AdvSceneSwitcher.listControls.remove="Remove"
AdvSceneSwitcher.listControls.up="Up"
AdvSceneSwitcher.listControls.down="Down"
AdvSceneSwitcher.macroSegmentSelection.invalid="Invalid selection!" AdvSceneSwitcher.macroSegmentSelection.invalid="Invalid selection!"
AdvSceneSwitcher.validation.text.maxLength="Only %1 characters are allowed in this field!" AdvSceneSwitcher.validation.text.maxLength="Only %1 characters are allowed in this field!"
@@ -1093,6 +1154,7 @@ AdvSceneSwitcher.variable.save="Save / load behavior"
AdvSceneSwitcher.variable.save.dontSave="Don't save variable value" AdvSceneSwitcher.variable.save.dontSave="Don't save variable value"
AdvSceneSwitcher.variable.save.save="Save variable value" AdvSceneSwitcher.variable.save.save="Save variable value"
AdvSceneSwitcher.variable.save.default="Set to value" AdvSceneSwitcher.variable.save.default="Set to value"
AdvSceneSwitcher.variable.selectionDialog="Select variable:"
AdvSceneSwitcher.tooltip.availableVariables="Variables are supported, use ${VarName} to retrieve the value of VarName" AdvSceneSwitcher.tooltip.availableVariables="Variables are supported, use ${VarName} to retrieve the value of VarName"
@@ -1401,24 +1463,13 @@ AdvSceneSwitcher.tempVar.twitch.status.prediction.description="The status of the
AdvSceneSwitcher.tempVar.twitch.id.goal="Goal ID" AdvSceneSwitcher.tempVar.twitch.id.goal="Goal ID"
AdvSceneSwitcher.tempVar.twitch.type.goal="Goal type" AdvSceneSwitcher.tempVar.twitch.type.goal="Goal type"
AdvSceneSwitcher.tempVar.twitch.type.goal.description="The type of goal. Possible values are:\n AdvSceneSwitcher.tempVar.twitch.type.goal.description="The type of goal. Possible values are:\n follow — The goal is to increase followers.\n subscription — The goal is to increase subscriptions. This type shows the net increase or decrease in tier points associated with the subscriptions.\n subscription_count — The goal is to increase subscriptions. This type shows the net increase or decrease in the number of subscriptions.\n new_subscription — The goal is to increase subscriptions. This type shows only the net increase in tier points associated with the subscriptions (it does not account for users that unsubscribed since the goal started).\n new_subscription_count — The goal is to increase subscriptions. This type shows only the net increase in the number of subscriptions (it does not account for users that unsubscribed since the goal started)."
follow — The goal is to increase followers.\n
subscription — The goal is to increase subscriptions. This type shows the net increase or decrease in tier points associated with the subscriptions.\n
subscription_count — The goal is to increase subscriptions. This type shows the net increase or decrease in the number of subscriptions.\n
new_subscription — The goal is to increase subscriptions. This type shows only the net increase in tier points associated with the subscriptions (it does not account for users that unsubscribed since the goal started).\n
new_subscription_count — The goal is to increase subscriptions. This type shows only the net increase in the number of subscriptions (it does not account for users that unsubscribed since the goal started)."
AdvSceneSwitcher.tempVar.twitch.description.goal="Goal description" AdvSceneSwitcher.tempVar.twitch.description.goal="Goal description"
AdvSceneSwitcher.tempVar.twitch.description.goal.description="A description of the goal, if specified. The description may contain a maximum of 40 characters." AdvSceneSwitcher.tempVar.twitch.description.goal.description="A description of the goal, if specified. The description may contain a maximum of 40 characters."
AdvSceneSwitcher.tempVar.twitch.is_achieved.goal="Goal is achieved" AdvSceneSwitcher.tempVar.twitch.is_achieved.goal="Goal is achieved"
AdvSceneSwitcher.tempVar.twitch.is_achieved.goal.description="A Boolean value that indicates whether the broadcaster achieved their goal. Is true if the goal was achieved; otherwise, false." AdvSceneSwitcher.tempVar.twitch.is_achieved.goal.description="A Boolean value that indicates whether the broadcaster achieved their goal. Is true if the goal was achieved; otherwise, false."
AdvSceneSwitcher.tempVar.twitch.current_amount.goal="Goal current amount" AdvSceneSwitcher.tempVar.twitch.current_amount.goal="Goal current amount"
AdvSceneSwitcher.tempVar.twitch.current_amount.goal.description="The goal's current value.\n AdvSceneSwitcher.tempVar.twitch.current_amount.goal.description="The goal's current value.\nThe goal's type determines how this value is increased or decreased.\n If type is follow, this field is set to the broadcaster's current number of followers. This number increases with new followers and decreases when users unfollow the broadcaster.\n If type is subscription, this field is increased and decreased by the points value associated with the subscription tier. For example, if a tier-two subscription is worth 2 points, this field is increased or decreased by 2, not 1.\n If type is subscription_count, this field is increased by 1 for each new subscription and decreased by 1 for each user that unsubscribes.\n If type is new_subscription, this field is increased by the points value associated with the subscription tier. For example, if a tier-two subscription is worth 2 points, this field is increased by 2, not 1.\n If type is new_subscription_count, this field is increased by 1 for each new subscription."
The goal's type determines how this value is increased or decreased.\n
If type is follow, this field is set to the broadcaster's current number of followers. This number increases with new followers and decreases when users unfollow the broadcaster.\n
If type is subscription, this field is increased and decreased by the points value associated with the subscription tier. For example, if a tier-two subscription is worth 2 points, this field is increased or decreased by 2, not 1.\n
If type is subscription_count, this field is increased by 1 for each new subscription and decreased by 1 for each user that unsubscribes.\n
If type is new_subscription, this field is increased by the points value associated with the subscription tier. For example, if a tier-two subscription is worth 2 points, this field is increased by 2, not 1.\n
If type is new_subscription_count, this field is increased by 1 for each new subscription."
AdvSceneSwitcher.tempVar.twitch.target_amount.goal="Goal target amount" AdvSceneSwitcher.tempVar.twitch.target_amount.goal="Goal target amount"
AdvSceneSwitcher.tempVar.twitch.target_amount.goal.description="The goal's target value. For example, if the broadcaster has 200 followers before creating the goal, and their goal is to double that number, this field is set to 400." AdvSceneSwitcher.tempVar.twitch.target_amount.goal.description="The goal's target value. For example, if the broadcaster has 200 followers before creating the goal, and their goal is to double that number, this field is set to 400."
AdvSceneSwitcher.tempVar.twitch.started_at.goal="Goal start time" AdvSceneSwitcher.tempVar.twitch.started_at.goal="Goal start time"
@@ -1722,6 +1773,35 @@ AdvSceneSwitcher.tempVar.clipboard.text.description="The text contained in the c
AdvSceneSwitcher.tempVar.file.content="File content" AdvSceneSwitcher.tempVar.file.content="File content"
AdvSceneSwitcher.tempVar.file.date="File modification date" AdvSceneSwitcher.tempVar.file.date="File modification date"
AdvSceneSwitcher.tempVar.folder.newFiles="New files"
AdvSceneSwitcher.tempVar.folder.changedFiles="Changed files"
AdvSceneSwitcher.tempVar.folder.removedFiles="Removed files"
AdvSceneSwitcher.tempVar.folder.newDirs="New directories"
AdvSceneSwitcher.tempVar.folder.removedDirs="Removed directories"
AdvSceneSwitcher.tempVar.source.width="Source width"
AdvSceneSwitcher.tempVar.source.height="Source height"
AdvSceneSwitcher.tempVar.source.setting="Setting value"
AdvSceneSwitcher.tempVar.source.settings="Settings string"
AdvSceneSwitcher.tempVar.filter.setting="Setting value"
AdvSceneSwitcher.tempVar.filter.settings="Settings string"
AdvSceneSwitcher.tempVar.slideShow.index="Slide index"
AdvSceneSwitcher.tempVar.slideShow.index.description="The index of the slide currently being displayed.\nIf the index cannot be determined, -1 is returned."
AdvSceneSwitcher.tempVar.slideShow.path="Slide path"
AdvSceneSwitcher.tempVar.slideShow.path.description="The filesystem path of the slide currently being displayed."
AdvSceneSwitcher.tempVar.slideShow.fileName="Slide file name"
AdvSceneSwitcher.tempVar.slideShow.fileName.description="The name of file of the slide currently being displayed."
AdvSceneSwitcher.tempVar.usb.vendorID="Vendor ID"
AdvSceneSwitcher.tempVar.usb.productID="Product ID"
AdvSceneSwitcher.tempVar.usb.busNumber="Bus Number"
AdvSceneSwitcher.tempVar.usb.deviceAddress="Device Address"
AdvSceneSwitcher.tempVar.usb.vendorName="Vendor Name"
AdvSceneSwitcher.tempVar.usb.productName="Product Name"
AdvSceneSwitcher.tempVar.usb.serialNumber="Serial Number"
AdvSceneSwitcher.selectScene="--select scene--" AdvSceneSwitcher.selectScene="--select scene--"
AdvSceneSwitcher.selectPreviousScene="Previous Scene" AdvSceneSwitcher.selectPreviousScene="Previous Scene"
AdvSceneSwitcher.selectCurrentScene="Current Scene" AdvSceneSwitcher.selectCurrentScene="Current Scene"
@@ -1813,6 +1893,27 @@ AdvSceneSwitcher.audio.monitor.both="Monitor and Output"
AdvSceneSwitcher.noSettingsButtons="No buttons found!" AdvSceneSwitcher.noSettingsButtons="No buttons found!"
AdvSceneSwitcher.clearBufferOnMatch="Clear message buffer when matching message was found"
AdvSceneSwitcher.key="Key:"
AdvSceneSwitcher.key.up="Key up:"
AdvSceneSwitcher.modifierKey="Modifier keys:"
AdvSceneSwitcher.modifierKey.shift="Shift"
AdvSceneSwitcher.modifierKey.ctrl="Ctrl"
AdvSceneSwitcher.modifierKey.alt="Alt"
AdvSceneSwitcher.modifierKey.meta="Meta"
AdvSceneSwitcher.mouse.button="Mouse button:"
AdvSceneSwitcher.mouse.button.left="Left"
AdvSceneSwitcher.mouse.button.middle="Middle"
AdvSceneSwitcher.mouse.button.right="Right"
AdvSceneSwitcher.mouse.position="Mouse position:"
AdvSceneSwitcher.mouse.up="Mouse up event:"
AdvSceneSwitcher.mouse.count="Mouse click count:"
AdvSceneSwitcher.mouse.leave="Mouse leave event:"
AdvSceneSwitcher.mouse.scrollAmount="Mouse scroll amount:"
; Legacy tabs below - please don't waste your time adding translations for these :) ; Legacy tabs below - please don't waste your time adding translations for these :)
; Transition Tab ; Transition Tab
AdvSceneSwitcher.transitionTab.title="Transition" AdvSceneSwitcher.transitionTab.title="Transition"

View File

@@ -348,7 +348,6 @@ AdvSceneSwitcher.action.replay.saveWarn="Advertencia: ¡Guardar con demasiada fr
AdvSceneSwitcher.action.replay.type.stop="Detener el búfer de reproducción" AdvSceneSwitcher.action.replay.type.stop="Detener el búfer de reproducción"
AdvSceneSwitcher.action.replay.type.start="Iniciar búfer de reproducción" AdvSceneSwitcher.action.replay.type.start="Iniciar búfer de reproducción"
AdvSceneSwitcher.action.replay.type.save="Guardar búfer de reproducción" AdvSceneSwitcher.action.replay.type.save="Guardar búfer de reproducción"
AdvSceneSwitcher.action.replay.entry="{{actions}}"
AdvSceneSwitcher.action.streaming="Transmisión" AdvSceneSwitcher.action.streaming="Transmisión"
AdvSceneSwitcher.action.streaming.type.stop="Detener transmisión" AdvSceneSwitcher.action.streaming.type.stop="Detener transmisión"
AdvSceneSwitcher.action.streaming.type.start="Iniciar transmisión" AdvSceneSwitcher.action.streaming.type.start="Iniciar transmisión"
@@ -386,7 +385,6 @@ AdvSceneSwitcher.action.macro.type.unpause="Reanudar"
AdvSceneSwitcher.action.macro.type.resetCounter="Reiniciar contador" AdvSceneSwitcher.action.macro.type.resetCounter="Reiniciar contador"
AdvSceneSwitcher.action.macro.type.run="Ejecutar" AdvSceneSwitcher.action.macro.type.run="Ejecutar"
AdvSceneSwitcher.action.macro.type.stop="Detener" AdvSceneSwitcher.action.macro.type.stop="Detener"
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}"
AdvSceneSwitcher.action.pluginState="Estado del complemento" AdvSceneSwitcher.action.pluginState="Estado del complemento"
AdvSceneSwitcher.action.pluginState.type.stop="Detener el complemento Advanced Scene Switcher" AdvSceneSwitcher.action.pluginState.type.stop="Detener el complemento Advanced Scene Switcher"
AdvSceneSwitcher.action.pluginState.type.noMatch="Cambiar el comportamiento de no coincidencia:" AdvSceneSwitcher.action.pluginState.type.noMatch="Cambiar el comportamiento de no coincidencia:"

2090
data/locale/ja-JP.ini Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -137,7 +137,6 @@ AdvSceneSwitcher.action.replay="Буфер воспроизведения"
AdvSceneSwitcher.action.replay.type.stop="Остановить буфер воспроизведения" AdvSceneSwitcher.action.replay.type.stop="Остановить буфер воспроизведения"
AdvSceneSwitcher.action.replay.type.start="Начать воспроизведение буфера" AdvSceneSwitcher.action.replay.type.start="Начать воспроизведение буфера"
AdvSceneSwitcher.action.replay.type.save="Сохранить буфер воспроизведения" AdvSceneSwitcher.action.replay.type.save="Сохранить буфер воспроизведения"
AdvSceneSwitcher.action.replay.entry="{{actions}}"
AdvSceneSwitcher.action.streaming="Потоковое вещание" AdvSceneSwitcher.action.streaming="Потоковое вещание"
AdvSceneSwitcher.action.streaming.type.stop="Остановить потоковое вещание" AdvSceneSwitcher.action.streaming.type.stop="Остановить потоковое вещание"
AdvSceneSwitcher.action.streaming.type.start="Начать потоковое вещание" AdvSceneSwitcher.action.streaming.type.start="Начать потоковое вещание"

View File

@@ -279,7 +279,6 @@ AdvSceneSwitcher.action.replay="Tekrar arabelleği"
AdvSceneSwitcher.action.replay.type.stop="Tekrar arabelleğini durdur" AdvSceneSwitcher.action.replay.type.stop="Tekrar arabelleğini durdur"
AdvSceneSwitcher.action.replay.type.start="Tekrar arabelleğini başlat" AdvSceneSwitcher.action.replay.type.start="Tekrar arabelleğini başlat"
AdvSceneSwitcher.action.replay.type.save="Tekrar arabelleğini kaydet" AdvSceneSwitcher.action.replay.type.save="Tekrar arabelleğini kaydet"
AdvSceneSwitcher.action.replay.entry="{{actions}}"
AdvSceneSwitcher.action.streaming="Yayın" AdvSceneSwitcher.action.streaming="Yayın"
AdvSceneSwitcher.action.streaming.type.stop="Yayın durdur" AdvSceneSwitcher.action.streaming.type.stop="Yayın durdur"
AdvSceneSwitcher.action.streaming.type.start="Yayın başlat" AdvSceneSwitcher.action.streaming.type.start="Yayın başlat"
@@ -315,7 +314,6 @@ AdvSceneSwitcher.action.macro.type.pause="Duraklat"
AdvSceneSwitcher.action.macro.type.unpause="Duraklatma" AdvSceneSwitcher.action.macro.type.unpause="Duraklatma"
AdvSceneSwitcher.action.macro.type.resetCounter="Sayacı sıfırla" AdvSceneSwitcher.action.macro.type.resetCounter="Sayacı sıfırla"
AdvSceneSwitcher.action.macro.type.run="Çalıştır" AdvSceneSwitcher.action.macro.type.run="Çalıştır"
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}"
AdvSceneSwitcher.action.pluginState="Eklenti durumu" AdvSceneSwitcher.action.pluginState="Eklenti durumu"
AdvSceneSwitcher.action.pluginState.type.stop="Advanced Scene Switcher eklentisini durdurun" AdvSceneSwitcher.action.pluginState.type.stop="Advanced Scene Switcher eklentisini durdurun"
AdvSceneSwitcher.action.pluginState.type.noMatch="Eşleşmeme davranışını değiştirin:" AdvSceneSwitcher.action.pluginState.type.noMatch="Eşleşmeme davranışını değiştirin:"

View File

@@ -481,7 +481,6 @@ AdvSceneSwitcher.action.replay.saveWarn="警告:保存过于频繁可能会导
AdvSceneSwitcher.action.replay.type.stop="停止回放缓存" AdvSceneSwitcher.action.replay.type.stop="停止回放缓存"
AdvSceneSwitcher.action.replay.type.start="启动回放缓存" AdvSceneSwitcher.action.replay.type.start="启动回放缓存"
AdvSceneSwitcher.action.replay.type.save="保存回放缓存" AdvSceneSwitcher.action.replay.type.save="保存回放缓存"
AdvSceneSwitcher.action.replay.entry="{{actions}}"
AdvSceneSwitcher.action.streaming="推流" AdvSceneSwitcher.action.streaming="推流"
AdvSceneSwitcher.action.streaming.type.stop="停止推流" AdvSceneSwitcher.action.streaming.type.stop="停止推流"
AdvSceneSwitcher.action.streaming.type.start="开始推流" AdvSceneSwitcher.action.streaming.type.start="开始推流"
@@ -524,7 +523,6 @@ AdvSceneSwitcher.action.macro.type.unpause="取消暂停"
AdvSceneSwitcher.action.macro.type.resetCounter="复位计数器" AdvSceneSwitcher.action.macro.type.resetCounter="复位计数器"
AdvSceneSwitcher.action.macro.type.run="运行操作" AdvSceneSwitcher.action.macro.type.run="运行操作"
AdvSceneSwitcher.action.macro.type.stop="停止操作" AdvSceneSwitcher.action.macro.type.stop="停止操作"
AdvSceneSwitcher.action.macro.entry="{{actions}}{{actionIndex}}{{macros}}"
AdvSceneSwitcher.action.pluginState="插件状态" AdvSceneSwitcher.action.pluginState="插件状态"
AdvSceneSwitcher.action.pluginState.type.stop="停止高级场景切换插件" AdvSceneSwitcher.action.pluginState.type.stop="停止高级场景切换插件"
AdvSceneSwitcher.action.pluginState.type.noMatch="没有匹配项时:" AdvSceneSwitcher.action.pluginState.type.noMatch="没有匹配项时:"

1
deps/libusb vendored Submodule

Submodule deps/libusb added at d52e355daa

2
deps/opencv vendored

View File

@@ -68,7 +68,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>962</width> <width>962</width>
<height>1033</height> <height>1040</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_19"> <layout class="QVBoxLayout" name="verticalLayout_19">
@@ -572,40 +572,22 @@
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_32"> <layout class="QHBoxLayout" name="horizontalLayout_32">
<item> <item>
<widget class="QPushButton" name="priorityUp"> <widget class="QToolButton" name="priorityUp">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="icon"> <property name="icon">
<iconset> <iconset>
<normaloff>../../../forms/images/up.png</normaloff>../../../forms/images/up.png</iconset> <normaloff>../../../forms/images/up.png</normaloff>../../../forms/images/up.png</iconset>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">upArrowIconSmall</string> <string notr="true">upArrowIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="priorityDown"> <widget class="QToolButton" name="priorityDown">
<property name="maximumSize">
<size>
<width>22</width>
<height>22</height>
</size>
</property>
<property name="icon"> <property name="icon">
<iconset> <iconset>
<normaloff>../../../forms/images/down.png</normaloff>../../../forms/images/down.png</iconset> <normaloff>../../../forms/images/down.png</normaloff>../../../forms/images/down.png</iconset>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">downArrowIconSmall</string> <string notr="true">downArrowIconSmall</string>
</property> </property>
@@ -739,135 +721,47 @@
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_61"> <layout class="QHBoxLayout" name="macroControlLayout">
<item> <item>
<widget class="QPushButton" name="macroAdd"> <widget class="QToolButton" name="macroAdd">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.macroAddButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.macroAddButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">addIconSmall</string> <string notr="true">addIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="macroRemove"> <widget class="QToolButton" name="macroRemove">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.macroRemoveButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.macroRemoveButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">removeIconSmall</string> <string notr="true">removeIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer_130"> <widget class="QToolButton" name="macroUp">
<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_46">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_131">
<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="macroUp">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.macroUpButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.macroUpButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">upArrowIconSmall</string> <string notr="true">upArrowIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="macroDown"> <widget class="QToolButton" name="macroDown">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.macroDownButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.macroDownButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">downArrowIconSmall</string> <string notr="true">downArrowIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item>
<spacer name="horizontalSpacer_65">
<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> </layout>
</item> </item>
</layout> </layout>
@@ -960,22 +854,13 @@
</spacer> </spacer>
</item> </item>
<item> <item>
<widget class="QPushButton" name="macroProperties"> <widget class="QToolButton" name="macroSettings">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.openMacroPropertiesButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.openMacroSettingsButton</string>
</property> </property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">propertiesIconSmall</string> <string notr="true">propertiesIconSmall</string>
</property> </property>
@@ -1013,173 +898,67 @@
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_12"> <layout class="QHBoxLayout" name="conditionControlsLayout">
<property name="leftMargin"> <property name="leftMargin">
<number>9</number> <number>9</number>
</property> </property>
<item> <item>
<widget class="QPushButton" name="conditionAdd"> <widget class="QToolButton" name="conditionAdd">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.conditionAddButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.conditionAddButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">addIconSmall</string> <string notr="true">addIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="conditionRemove"> <widget class="QToolButton" name="conditionRemove">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.conditionRemoveButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.conditionRemoveButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">removeIconSmall</string> <string notr="true">removeIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer_135"> <widget class="QToolButton" name="conditionTop">
<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_48">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_134">
<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="conditionTop">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.conditionTopButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.conditionTopButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="conditionUp"> <widget class="QToolButton" name="conditionUp">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.conditionUpButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.conditionUpButton</string>
</property> </property>
<property name="text"> <property name="text">
<string/> <string/>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">upArrowIconSmall</string> <string notr="true">upArrowIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="conditionDown"> <widget class="QToolButton" name="conditionDown">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.conditionDownButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.conditionDownButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">downArrowIconSmall</string> <string notr="true">downArrowIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="conditionBottom"> <widget class="QToolButton" name="conditionBottom">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.conditionBottomButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.conditionBottomButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item>
<spacer name="horizontalSpacer_15">
<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> </layout>
</item> </item>
</layout> </layout>
@@ -1213,155 +992,62 @@
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_21"> <layout class="QHBoxLayout" name="actionControlsLayout">
<property name="leftMargin"> <property name="leftMargin">
<number>9</number> <number>9</number>
</property> </property>
<item> <item>
<widget class="QPushButton" name="actionAdd"> <widget class="QToolButton" name="actionAdd">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.actionAddButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.actionAddButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">addIconSmall</string> <string notr="true">addIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="actionRemove"> <widget class="QToolButton" name="actionRemove">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.actionRemoveButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.actionRemoveButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">removeIconSmall</string> <string notr="true">removeIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer_133"> <widget class="QToolButton" name="actionTop">
<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="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.actionTopButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.actionTopButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="actionUp"> <widget class="QToolButton" name="actionUp">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.actionUpButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.actionUpButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">upArrowIconSmall</string> <string notr="true">upArrowIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="actionDown"> <widget class="QToolButton" name="actionDown">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.actionDownButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.actionDownButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">downArrowIconSmall</string> <string notr="true">downArrowIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="actionBottom"> <widget class="QToolButton" name="actionBottom">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.actionBottomButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.actionBottomButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@@ -1378,22 +1064,13 @@
</spacer> </spacer>
</item> </item>
<item> <item>
<widget class="QPushButton" name="toggleElseActions"> <widget class="QToolButton" name="toggleElseActions">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.toggleShowElseSection</string> <string>AdvSceneSwitcher.macroTab.tooltip.toggleShowElseSection</string>
</property> </property>
<property name="checkable"> <property name="checkable">
<bool>true</bool> <bool>true</bool>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
</layout> </layout>
@@ -1425,170 +1102,64 @@
</widget> </widget>
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout_33"> <layout class="QHBoxLayout" name="elseActionControlsLayout">
<property name="leftMargin"> <property name="leftMargin">
<number>9</number> <number>9</number>
</property> </property>
<item> <item>
<widget class="QPushButton" name="elseActionAdd"> <widget class="QToolButton" name="elseActionAdd">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.elseActionAddButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.elseActionAddButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">addIconSmall</string> <string notr="true">addIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="elseActionRemove"> <widget class="QToolButton" name="elseActionRemove">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.elseActionRemoveButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.elseActionRemoveButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">removeIconSmall</string> <string notr="true">removeIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<spacer name="horizontalSpacer_138"> <widget class="QToolButton" name="elseActionTop">
<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="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.elseActionTopButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.elseActionTopButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="elseActionUp"> <widget class="QToolButton" name="elseActionUp">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.elseActionUpButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.elseActionUpButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">upArrowIconSmall</string> <string notr="true">upArrowIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="elseActionDown"> <widget class="QToolButton" name="elseActionDown">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.elseActionDownButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.elseActionDownButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
<property name="themeID" stdset="0"> <property name="themeID" stdset="0">
<string notr="true">downArrowIconSmall</string> <string notr="true">downArrowIconSmall</string>
</property> </property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="elseActionBottom"> <widget class="QToolButton" name="elseActionBottom">
<property name="maximumSize">
<size>
<width>22</width>
<height>16777215</height>
</size>
</property>
<property name="toolTip"> <property name="toolTip">
<string>AdvSceneSwitcher.macroTab.tooltip.elseActionBottomButton</string> <string>AdvSceneSwitcher.macroTab.tooltip.elseActionBottomButton</string>
</property> </property>
<property name="flat">
<bool>true</bool>
</property>
</widget> </widget>
</item> </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> </layout>
</item> </item>
</layout> </layout>
@@ -5033,7 +4604,7 @@
<tabstop>runMacro</tabstop> <tabstop>runMacro</tabstop>
<tabstop>runMacroInParallel</tabstop> <tabstop>runMacroInParallel</tabstop>
<tabstop>runMacroOnChange</tabstop> <tabstop>runMacroOnChange</tabstop>
<tabstop>macroProperties</tabstop> <tabstop>macroSettings</tabstop>
<tabstop>conditionsList</tabstop> <tabstop>conditionsList</tabstop>
<tabstop>conditionAdd</tabstop> <tabstop>conditionAdd</tabstop>
<tabstop>conditionRemove</tabstop> <tabstop>conditionRemove</tabstop>

View File

@@ -70,6 +70,9 @@ static void DisplayMissingDependencyWarning()
QString warning(obs_module_text( QString warning(obs_module_text(
"AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailureMessage")); "AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailureMessage"));
DisplayMessage(warning.arg(failedLibsString)); DisplayMessage(warning.arg(failedLibsString));
// Only display the warning once per plugin load
switcher->loadFailureLibs.clear();
} }
static void DisplayMissingDataDirWarning() static void DisplayMissingDataDirWarning()
@@ -240,7 +243,7 @@ void SwitcherData::Thread()
if (duration.count() < 1) { if (duration.count() < 1) {
blog(LOG_INFO, blog(LOG_INFO,
"detected busy loop - refusing to sleep less than 1ms"); "detected busy loop - refusing to sleep less than 1ms");
duration = std::chrono::milliseconds(50); duration = std::chrono::milliseconds(10);
} }
} }
@@ -750,6 +753,36 @@ QWidget *GetSettingsWindow()
return SettingsWindowIsOpened() ? AdvSceneSwitcher::window : nullptr; return SettingsWindowIsOpened() ? AdvSceneSwitcher::window : nullptr;
} }
void AdvSceneSwitcher::HighligthMacroSettingsButton(bool enable)
{
static QObject *highlight = nullptr;
if ((highlight && enable) || (!highlight && !enable)) {
return;
}
if (highlight && !enable) {
highlight->deleteLater();
highlight = nullptr;
return;
}
if (!HighlightUIElementsEnabled()) {
return;
}
highlight = HighlightWidget(ui->macroSettings, Qt::green);
}
void HighligthMacroSettingsButton(bool enable)
{
auto window = GetSettingsWindow();
if (!window) {
return;
}
static_cast<AdvSceneSwitcher *>(window)->HighligthMacroSettingsButton(
enable);
}
void SetupActionQueues(); void SetupActionQueues();
extern "C" EXPORT void InitSceneSwitcher(obs_module_t *module, extern "C" EXPORT void InitSceneSwitcher(obs_module_t *module,

View File

@@ -12,6 +12,7 @@ class MacroActionEdit;
class MacroConditionEdit; class MacroConditionEdit;
class Duration; class Duration;
class SequenceWidget; class SequenceWidget;
enum class LogicType;
struct SceneGroup; struct SceneGroup;
/******************************************************************************* /*******************************************************************************
@@ -95,6 +96,7 @@ public:
void SetConditionData(Macro &m); void SetConditionData(Macro &m);
void SwapActions(Macro *m, int pos1, int pos2); void SwapActions(Macro *m, int pos1, int pos2);
void SwapConditions(Macro *m, int pos1, int pos2); void SwapConditions(Macro *m, int pos1, int pos2);
void HighligthMacroSettingsButton(bool enable = true);
public slots: public slots:
void on_macroAdd_clicked(); void on_macroAdd_clicked();
@@ -152,12 +154,16 @@ public slots:
void SetElseActionsStateToVisible(); void SetElseActionsStateToVisible();
void MacroActionSelectionChanged(int idx); void MacroActionSelectionChanged(int idx);
void MacroActionReorder(int to, int target); void MacroActionReorder(int to, int target);
void AddMacroAction(Macro *macro, int idx, const std::string &id,
obs_data_t *data);
void AddMacroAction(int idx); void AddMacroAction(int idx);
void RemoveMacroAction(int idx); void RemoveMacroAction(int idx);
void MoveMacroActionUp(int idx); void MoveMacroActionUp(int idx);
void MoveMacroActionDown(int idx); void MoveMacroActionDown(int idx);
void MacroElseActionSelectionChanged(int idx); void MacroElseActionSelectionChanged(int idx);
void MacroElseActionReorder(int to, int target); void MacroElseActionReorder(int to, int target);
void AddMacroElseAction(Macro *macro, int idx, const std::string &id,
obs_data_t *data);
void AddMacroElseAction(int idx); void AddMacroElseAction(int idx);
void RemoveMacroElseAction(int idx); void RemoveMacroElseAction(int idx);
void SwapElseActions(Macro *m, int pos1, int pos2); void SwapElseActions(Macro *m, int pos1, int pos2);
@@ -166,16 +172,16 @@ public slots:
void MacroConditionSelectionChanged(int idx); void MacroConditionSelectionChanged(int idx);
void MacroConditionReorder(int to, int target); void MacroConditionReorder(int to, int target);
void AddMacroCondition(int idx); void AddMacroCondition(int idx);
void AddMacroCondition(Macro *macro, int idx, const std::string &id,
obs_data_t *data, LogicType logic);
void RemoveMacroCondition(int idx); void RemoveMacroCondition(int idx);
void MoveMacroConditionUp(int idx); void MoveMacroConditionUp(int idx);
void MoveMacroConditionDown(int idx); void MoveMacroConditionDown(int idx);
void FadeOutActionControls();
void FadeOutConditionControls();
void ResetOpacityActionControls();
void ResetOpacityConditionControls();
void HighlightControls(); void HighlightControls();
void HighlightOnChange(); void HighlightOnChange();
void on_macroProperties_clicked(); void on_macroSettings_clicked();
void CopyMacroSegment();
void PasteMacroSegment();
signals: signals:
void MacroAdded(const QString &name); void MacroAdded(const QString &name);
@@ -184,9 +190,6 @@ signals:
void MacroSegmentOrderChanged(); void MacroSegmentOrderChanged();
void SegmentTempVarsChanged(); void SegmentTempVarsChanged();
void HighlightMacrosChanged(bool value); void HighlightMacrosChanged(bool value);
void HighlightActionsChanged(bool value);
void HighlightElseActionsChanged(bool value);
void HighlightConditionsChanged(bool value);
void ConnectionAdded(const QString &); void ConnectionAdded(const QString &);
void ConnectionRenamed(const QString &oldName, const QString &newName); void ConnectionRenamed(const QString &oldName, const QString &newName);
@@ -408,5 +411,6 @@ public slots:
void OpenSettingsWindow(); void OpenSettingsWindow();
QWidget *GetSettingsWindow(); QWidget *GetSettingsWindow();
void HighligthMacroSettingsButton(bool enable);
} // namespace advss } // namespace advss

View File

@@ -431,7 +431,7 @@ void SwitcherData::LoadSettings(obs_data_t *obj)
} }
LoadMacros(obj); LoadMacros(obj);
LoadGlobalMacroProperties(obj); LoadGlobalMacroSettings(obj);
loadWindowTitleSwitches(obj); loadWindowTitleSwitches(obj);
loadScreenRegionSwitches(obj); loadScreenRegionSwitches(obj);
loadPauseSwitches(obj); loadPauseSwitches(obj);
@@ -466,7 +466,7 @@ void SwitcherData::SaveSettings(obs_data_t *obj)
saveSceneGroups(obj); saveSceneGroups(obj);
SaveMacros(obj); SaveMacros(obj);
SaveGlobalMacroProperties(obj); SaveGlobalMacroSettings(obj);
SaveVariables(obj); SaveVariables(obj);
saveWindowTitleSwitches(obj); saveWindowTitleSwitches(obj);
saveScreenRegionSwitches(obj); saveScreenRegionSwitches(obj);

View File

@@ -12,7 +12,7 @@
namespace advss { namespace advss {
static QMetaObject::Connection addPulse; static QObject *addPulse = nullptr;
SceneGroupEditWidget *typeEdit = nullptr; SceneGroupEditWidget *typeEdit = nullptr;
std::deque<SceneGroup> &GetSceneGroups() std::deque<SceneGroup> &GetSceneGroups()
@@ -170,7 +170,8 @@ void AdvSceneSwitcher::on_sceneGroupAdd_clicked()
item->setData(Qt::UserRole, text); item->setData(Qt::UserRole, text);
ui->sceneGroups->setCurrentItem(item); ui->sceneGroups->setCurrentItem(item);
ui->sceneGroupAdd->disconnect(addPulse); addPulse->deleteLater();
addPulse = nullptr;
ui->sceneGroupHelp->setVisible(false); ui->sceneGroupHelp->setVisible(false);
emit SceneGroupAdded(QString::fromStdString(name)); emit SceneGroupAdded(QString::fromStdString(name));
@@ -512,8 +513,8 @@ void AdvSceneSwitcher::SetupSceneGroupTab()
if (switcher->sceneGroups.size() == 0) { if (switcher->sceneGroups.size() == 0) {
if (!switcher->disableHints) { if (!switcher->disableHints) {
addPulse = PulseWidget(ui->sceneGroupAdd, addPulse = HighlightWidget(ui->sceneGroupAdd,
QColor(Qt::green)); QColor(Qt::green));
} }
ui->sceneGroupHelp->setVisible(true); ui->sceneGroupHelp->setVisible(true);
} else { } else {

View File

@@ -12,7 +12,7 @@
namespace advss { namespace advss {
bool SceneTrigger::pause = false; bool SceneTrigger::pause = false;
static QMetaObject::Connection addPulse; static QObject *addPulse = nullptr;
void AdvSceneSwitcher::on_triggerAdd_clicked() void AdvSceneSwitcher::on_triggerAdd_clicked()
{ {
@@ -22,7 +22,7 @@ void AdvSceneSwitcher::on_triggerAdd_clicked()
listAddClicked(ui->sceneTriggers, listAddClicked(ui->sceneTriggers,
new SceneTriggerWidget(this, new SceneTriggerWidget(this,
&switcher->sceneTriggers.back()), &switcher->sceneTriggers.back()),
ui->triggerAdd, &addPulse); ui->triggerAdd, addPulse);
ui->triggerHelp->setVisible(false); ui->triggerHelp->setVisible(false);
} }
@@ -370,8 +370,8 @@ void AdvSceneSwitcher::SetupTriggerTab()
if (switcher->sceneTriggers.size() == 0) { if (switcher->sceneTriggers.size() == 0) {
if (!switcher->disableHints) { if (!switcher->disableHints) {
addPulse = addPulse = HighlightWidget(ui->triggerAdd,
PulseWidget(ui->triggerAdd, QColor(Qt::green)); QColor(Qt::green));
} }
ui->triggerHelp->setVisible(true); ui->triggerHelp->setVisible(true);
} else { } else {

View File

@@ -12,7 +12,7 @@
namespace advss { namespace advss {
bool AudioSwitch::pause = false; bool AudioSwitch::pause = false;
static QMetaObject::Connection addPulse; static QObject *addPulse = nullptr;
void AdvSceneSwitcher::on_audioAdd_clicked() void AdvSceneSwitcher::on_audioAdd_clicked()
{ {
@@ -22,7 +22,7 @@ void AdvSceneSwitcher::on_audioAdd_clicked()
AudioSwitchWidget *sw = AudioSwitchWidget *sw =
new AudioSwitchWidget(this, &switcher->audioSwitches.back()); new AudioSwitchWidget(this, &switcher->audioSwitches.back());
listAddClicked(ui->audioSwitches, sw, ui->audioAdd, &addPulse); listAddClicked(ui->audioSwitches, sw, ui->audioAdd, addPulse);
ui->audioHelp->setVisible(false); ui->audioHelp->setVisible(false);
} }
@@ -232,7 +232,8 @@ void AdvSceneSwitcher::SetupAudioTab()
if (switcher->audioSwitches.size() == 0) { if (switcher->audioSwitches.size() == 0) {
if (!switcher->disableHints) { if (!switcher->disableHints) {
addPulse = PulseWidget(ui->audioAdd, QColor(Qt::green)); addPulse = HighlightWidget(ui->audioAdd,
QColor(Qt::green));
} }
ui->audioHelp->setVisible(true); ui->audioHelp->setVisible(true);
} else { } else {

View File

@@ -9,7 +9,7 @@
namespace advss { namespace advss {
bool ExecutableSwitch::pause = false; bool ExecutableSwitch::pause = false;
static QMetaObject::Connection addPulse; static QObject *addPulse = nullptr;
void AdvSceneSwitcher::on_executableAdd_clicked() void AdvSceneSwitcher::on_executableAdd_clicked()
{ {
@@ -19,7 +19,7 @@ void AdvSceneSwitcher::on_executableAdd_clicked()
listAddClicked(ui->executables, listAddClicked(ui->executables,
new ExecutableSwitchWidget( new ExecutableSwitchWidget(
this, &switcher->executableSwitches.back()), this, &switcher->executableSwitches.back()),
ui->executableAdd, &addPulse); ui->executableAdd, addPulse);
ui->exeHelp->setVisible(false); ui->exeHelp->setVisible(false);
} }
@@ -177,8 +177,8 @@ void AdvSceneSwitcher::SetupExecutableTab()
if (switcher->executableSwitches.size() == 0) { if (switcher->executableSwitches.size() == 0) {
if (!switcher->disableHints) { if (!switcher->disableHints) {
addPulse = PulseWidget(ui->executableAdd, addPulse = HighlightWidget(ui->executableAdd,
QColor(Qt::green)); QColor(Qt::green));
} }
ui->exeHelp->setVisible(true); ui->exeHelp->setVisible(true);
} else { } else {

View File

@@ -18,7 +18,7 @@
namespace advss { namespace advss {
bool FileSwitch::pause = false; bool FileSwitch::pause = false;
static QMetaObject::Connection addPulse; static QObject *addPulse = nullptr;
static std::hash<std::string> strHash; static std::hash<std::string> strHash;
void AdvSceneSwitcher::on_browseButton_clicked() void AdvSceneSwitcher::on_browseButton_clicked()
@@ -291,7 +291,7 @@ void AdvSceneSwitcher::on_fileAdd_clicked()
listAddClicked(ui->fileSwitches, listAddClicked(ui->fileSwitches,
new FileSwitchWidget(this, new FileSwitchWidget(this,
&switcher->fileSwitches.back()), &switcher->fileSwitches.back()),
ui->fileAdd, &addPulse); ui->fileAdd, addPulse);
ui->fileHelp->setVisible(false); ui->fileHelp->setVisible(false);
} }
@@ -441,7 +441,8 @@ void AdvSceneSwitcher::SetupFileTab()
if (switcher->fileSwitches.size() == 0) { if (switcher->fileSwitches.size() == 0) {
if (!switcher->disableHints) { if (!switcher->disableHints) {
addPulse = PulseWidget(ui->fileAdd, QColor(Qt::green)); addPulse =
HighlightWidget(ui->fileAdd, QColor(Qt::green));
} }
ui->fileHelp->setVisible(true); ui->fileHelp->setVisible(true);
} else { } else {

View File

@@ -9,7 +9,7 @@
namespace advss { namespace advss {
bool MediaSwitch::pause = false; bool MediaSwitch::pause = false;
static QMetaObject::Connection addPulse; static QObject *addPulse = nullptr;
constexpr auto media_played_to_end_idx = 8; constexpr auto media_played_to_end_idx = 8;
constexpr auto media_any_idx = 9; constexpr auto media_any_idx = 9;
@@ -22,7 +22,7 @@ void AdvSceneSwitcher::on_mediaAdd_clicked()
listAddClicked(ui->mediaSwitches, listAddClicked(ui->mediaSwitches,
new MediaSwitchWidget(this, new MediaSwitchWidget(this,
&switcher->mediaSwitches.back()), &switcher->mediaSwitches.back()),
ui->mediaAdd, &addPulse); ui->mediaAdd, addPulse);
ui->mediaHelp->setVisible(false); ui->mediaHelp->setVisible(false);
} }
@@ -252,7 +252,8 @@ void AdvSceneSwitcher::SetupMediaTab()
if (switcher->mediaSwitches.size() == 0) { if (switcher->mediaSwitches.size() == 0) {
if (!switcher->disableHints) { if (!switcher->disableHints) {
addPulse = PulseWidget(ui->mediaAdd, QColor(Qt::green)); addPulse = HighlightWidget(ui->mediaAdd,
QColor(Qt::green));
} }
ui->mediaHelp->setVisible(true); ui->mediaHelp->setVisible(true);
} else { } else {

View File

@@ -10,7 +10,7 @@
namespace advss { namespace advss {
static QMetaObject::Connection addPulse; static QObject *addPulse = nullptr;
void AdvSceneSwitcher::on_pauseAdd_clicked() void AdvSceneSwitcher::on_pauseAdd_clicked()
{ {
@@ -20,7 +20,7 @@ void AdvSceneSwitcher::on_pauseAdd_clicked()
listAddClicked(ui->pauseEntries, listAddClicked(ui->pauseEntries,
new PauseEntryWidget(this, new PauseEntryWidget(this,
&switcher->pauseEntries.back()), &switcher->pauseEntries.back()),
ui->pauseAdd, &addPulse); ui->pauseAdd, addPulse);
ui->pauseHelp->setVisible(false); ui->pauseHelp->setVisible(false);
} }
@@ -264,7 +264,8 @@ void AdvSceneSwitcher::SetupPauseTab()
if (switcher->pauseEntries.size() == 0) { if (switcher->pauseEntries.size() == 0) {
if (!switcher->disableHints) { if (!switcher->disableHints) {
addPulse = PulseWidget(ui->pauseAdd, QColor(Qt::green)); addPulse = HighlightWidget(ui->pauseAdd,
QColor(Qt::green));
} }
ui->pauseHelp->setVisible(true); ui->pauseHelp->setVisible(true);
} else { } else {

View File

@@ -9,7 +9,7 @@
namespace advss { namespace advss {
bool RandomSwitch::pause = false; bool RandomSwitch::pause = false;
static QMetaObject::Connection addPulse; static QObject *addPulse = nullptr;
void AdvSceneSwitcher::on_randomAdd_clicked() void AdvSceneSwitcher::on_randomAdd_clicked()
{ {
@@ -19,7 +19,7 @@ void AdvSceneSwitcher::on_randomAdd_clicked()
listAddClicked(ui->randomSwitches, listAddClicked(ui->randomSwitches,
new RandomSwitchWidget(this, new RandomSwitchWidget(this,
&switcher->randomSwitches.back()), &switcher->randomSwitches.back()),
ui->randomAdd, &addPulse); ui->randomAdd, addPulse);
ui->randomHelp->setVisible(false); ui->randomHelp->setVisible(false);
} }
@@ -131,8 +131,8 @@ void AdvSceneSwitcher::SetupRandomTab()
if (switcher->randomSwitches.size() == 0) { if (switcher->randomSwitches.size() == 0) {
if (!switcher->disableHints) { if (!switcher->disableHints) {
addPulse = addPulse = HighlightWidget(ui->randomAdd,
PulseWidget(ui->randomAdd, QColor(Qt::green)); QColor(Qt::green));
} }
ui->randomHelp->setVisible(true); ui->randomHelp->setVisible(true);
} else { } else {
@@ -147,8 +147,8 @@ void AdvSceneSwitcher::SetupRandomTab()
}"); }");
if (switcher->switchIfNotMatching != NoMatchBehavior::RANDOM_SWITCH) { if (switcher->switchIfNotMatching != NoMatchBehavior::RANDOM_SWITCH) {
if (!switcher->disableHints) { if (!switcher->disableHints) {
PulseWidget(ui->randomDisabledWarning, QColor(Qt::red), HighlightWidget(ui->randomDisabledWarning,
QColor(0, 0, 0, 0)); QColor(Qt::red), QColor(0, 0, 0, 0));
} }
} else { } else {
ui->randomDisabledWarning->setVisible(false); ui->randomDisabledWarning->setVisible(false);

View File

@@ -11,7 +11,7 @@
namespace advss { namespace advss {
bool ScreenRegionSwitch::pause = false; bool ScreenRegionSwitch::pause = false;
static QMetaObject::Connection addPulse; static QObject *addPulse = nullptr;
void AdvSceneSwitcher::ClearFrames(QListWidget *list) void AdvSceneSwitcher::ClearFrames(QListWidget *list)
{ {
@@ -79,7 +79,7 @@ void AdvSceneSwitcher::on_screenRegionAdd_clicked()
listAddClicked(ui->screenRegionSwitches, listAddClicked(ui->screenRegionSwitches,
new ScreenRegionWidget( new ScreenRegionWidget(
this, &switcher->screenRegionSwitches.back()), this, &switcher->screenRegionSwitches.back()),
ui->screenRegionAdd, &addPulse); ui->screenRegionAdd, addPulse);
ui->regionHelp->setVisible(false); ui->regionHelp->setVisible(false);
} }
@@ -248,8 +248,8 @@ void AdvSceneSwitcher::SetupRegionTab()
if (switcher->screenRegionSwitches.size() == 0) { if (switcher->screenRegionSwitches.size() == 0) {
if (!switcher->disableHints) { if (!switcher->disableHints) {
addPulse = PulseWidget(ui->screenRegionAdd, addPulse = HighlightWidget(ui->screenRegionAdd,
QColor(Qt::green)); QColor(Qt::green));
} }
ui->regionHelp->setVisible(true); ui->regionHelp->setVisible(true);
} else { } else {

View File

@@ -16,7 +16,7 @@ namespace advss {
constexpr auto max_extend_text_size = 150; constexpr auto max_extend_text_size = 150;
bool SceneSequenceSwitch::pause = false; bool SceneSequenceSwitch::pause = false;
static QMetaObject::Connection addPulse; static QObject *addPulse = nullptr;
void AdvSceneSwitcher::on_sceneSequenceAdd_clicked() void AdvSceneSwitcher::on_sceneSequenceAdd_clicked()
{ {
@@ -26,7 +26,7 @@ void AdvSceneSwitcher::on_sceneSequenceAdd_clicked()
listAddClicked(ui->sceneSequenceSwitches, listAddClicked(ui->sceneSequenceSwitches,
new SequenceWidget( new SequenceWidget(
this, &switcher->sceneSequenceSwitches.back()), this, &switcher->sceneSequenceSwitches.back()),
ui->sceneSequenceAdd, &addPulse); ui->sceneSequenceAdd, addPulse);
ui->sequenceHelp->setVisible(false); ui->sequenceHelp->setVisible(false);
} }
@@ -299,8 +299,8 @@ void AdvSceneSwitcher::SetupSequenceTab()
if (switcher->sceneSequenceSwitches.size() == 0) { if (switcher->sceneSequenceSwitches.size() == 0) {
if (!switcher->disableHints) { if (!switcher->disableHints) {
addPulse = PulseWidget(ui->sceneSequenceAdd, addPulse = HighlightWidget(ui->sceneSequenceAdd,
QColor(Qt::green)); QColor(Qt::green));
} }
ui->sequenceHelp->setVisible(true); ui->sequenceHelp->setVisible(true);
} else { } else {

View File

@@ -7,7 +7,7 @@
namespace advss { namespace advss {
bool TimeSwitch::pause = false; bool TimeSwitch::pause = false;
static QMetaObject::Connection addPulse; static QObject *addPulse = nullptr;
void AdvSceneSwitcher::on_timeAdd_clicked() void AdvSceneSwitcher::on_timeAdd_clicked()
{ {
@@ -17,7 +17,7 @@ void AdvSceneSwitcher::on_timeAdd_clicked()
listAddClicked(ui->timeSwitches, listAddClicked(ui->timeSwitches,
new TimeSwitchWidget(this, new TimeSwitchWidget(this,
&switcher->timeSwitches.back()), &switcher->timeSwitches.back()),
ui->timeAdd, &addPulse); ui->timeAdd, addPulse);
ui->timeHelp->setVisible(false); ui->timeHelp->setVisible(false);
} }
@@ -197,7 +197,8 @@ void AdvSceneSwitcher::SetupTimeTab()
if (switcher->timeSwitches.size() == 0) { if (switcher->timeSwitches.size() == 0) {
if (!switcher->disableHints) { if (!switcher->disableHints) {
addPulse = PulseWidget(ui->timeAdd, QColor(Qt::green)); addPulse =
HighlightWidget(ui->timeAdd, QColor(Qt::green));
} }
ui->timeHelp->setVisible(true); ui->timeHelp->setVisible(true);
} else { } else {

View File

@@ -14,7 +14,7 @@
namespace advss { namespace advss {
bool VideoSwitch::pause = false; bool VideoSwitch::pause = false;
static QMetaObject::Connection addPulse; static QObject *addPulse = nullptr;
void AdvSceneSwitcher::on_videoAdd_clicked() void AdvSceneSwitcher::on_videoAdd_clicked()
{ {
@@ -24,7 +24,7 @@ void AdvSceneSwitcher::on_videoAdd_clicked()
VideoSwitchWidget *sw = VideoSwitchWidget *sw =
new VideoSwitchWidget(this, &switcher->videoSwitches.back()); new VideoSwitchWidget(this, &switcher->videoSwitches.back());
listAddClicked(ui->videoSwitches, sw, ui->videoAdd, &addPulse); listAddClicked(ui->videoSwitches, sw, ui->videoAdd, addPulse);
ui->videoHelp->setVisible(false); ui->videoHelp->setVisible(false);
} }
@@ -202,7 +202,8 @@ void AdvSceneSwitcher::SetupVideoTab()
if (switcher->videoSwitches.size() == 0) { if (switcher->videoSwitches.size() == 0) {
if (!switcher->disableHints) { if (!switcher->disableHints) {
addPulse = PulseWidget(ui->videoAdd, QColor(Qt::green)); addPulse = HighlightWidget(ui->videoAdd,
QColor(Qt::green));
} }
ui->videoHelp->setVisible(true); ui->videoHelp->setVisible(true);
} else { } else {

View File

@@ -11,7 +11,7 @@
namespace advss { namespace advss {
bool WindowSwitch::pause = false; bool WindowSwitch::pause = false;
static QMetaObject::Connection addPulse; static QObject *addPulse = nullptr;
void AdvSceneSwitcher::on_windowAdd_clicked() void AdvSceneSwitcher::on_windowAdd_clicked()
{ {
@@ -21,7 +21,7 @@ void AdvSceneSwitcher::on_windowAdd_clicked()
listAddClicked(ui->windowSwitches, listAddClicked(ui->windowSwitches,
new WindowSwitchWidget(this, new WindowSwitchWidget(this,
&switcher->windowSwitches.back()), &switcher->windowSwitches.back()),
ui->windowAdd, &addPulse); ui->windowAdd, addPulse);
ui->windowHelp->setVisible(false); ui->windowHelp->setVisible(false);
} }
@@ -335,8 +335,8 @@ void AdvSceneSwitcher::SetupTitleTab()
if (switcher->windowSwitches.size() == 0) { if (switcher->windowSwitches.size() == 0) {
if (!switcher->disableHints) { if (!switcher->disableHints) {
addPulse = addPulse = HighlightWidget(ui->windowAdd,
PulseWidget(ui->windowAdd, QColor(Qt::green)); QColor(Qt::green));
} }
ui->windowHelp->setVisible(true); ui->windowHelp->setVisible(true);
} else { } else {

View File

@@ -1,7 +1,7 @@
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
#include "advanced-scene-switcher.hpp" #include "advanced-scene-switcher.hpp"
#include "macro-helpers.hpp" #include "macro-helpers.hpp"
#include "macro-properties.hpp" #include "macro-settings.hpp"
#include "macro.hpp" #include "macro.hpp"
#include "plugin-state-helpers.hpp" #include "plugin-state-helpers.hpp"
#include "section.hpp" #include "section.hpp"
@@ -29,8 +29,7 @@ static inline void populateActionSelection(QComboBox *list)
MacroActionEdit::MacroActionEdit(QWidget *parent, MacroActionEdit::MacroActionEdit(QWidget *parent,
std::shared_ptr<MacroAction> *entryData, std::shared_ptr<MacroAction> *entryData,
const std::string &id) const std::string &id)
: MacroSegmentEdit(GetGlobalMacroProperties()._highlightActions, : MacroSegmentEdit(parent),
parent),
_actionSelection(new FilterComboBox()), _actionSelection(new FilterComboBox()),
_enable(new SwitchButton()), _enable(new SwitchButton()),
_entryData(entryData) _entryData(entryData)
@@ -40,8 +39,6 @@ MacroActionEdit::MacroActionEdit(QWidget *parent,
SLOT(ActionSelectionChanged(const QString &))); SLOT(ActionSelectionChanged(const QString &)));
QWidget::connect(_enable, SIGNAL(checked(bool)), this, QWidget::connect(_enable, SIGNAL(checked(bool)), this,
SLOT(ActionEnableChanged(bool))); SLOT(ActionEnableChanged(bool)));
QWidget::connect(window(), SIGNAL(HighlightActionsChanged(bool)), this,
SLOT(EnableHighlight(bool)));
QWidget::connect(&_actionStateTimer, SIGNAL(timeout()), this, QWidget::connect(&_actionStateTimer, SIGNAL(timeout()), this,
SLOT(UpdateActionState())); SLOT(UpdateActionState()));
@@ -161,33 +158,20 @@ std::shared_ptr<MacroSegment> MacroActionEdit::Data() const
return *_entryData; return *_entryData;
} }
void AdvSceneSwitcher::AddMacroAction(int idx) void AdvSceneSwitcher::AddMacroAction(Macro *macro, int idx,
const std::string &id, obs_data_t *data)
{ {
auto macro = GetSelectedMacro();
if (!macro) {
return;
}
if (idx < 0 || idx > (int)macro->Actions().size()) { if (idx < 0 || idx > (int)macro->Actions().size()) {
assert(false);
return; return;
} }
std::string id;
if (idx - 1 >= 0) {
id = macro->Actions().at(idx - 1)->GetId();
} else {
id = MacroAction::GetDefaultID();
}
{ {
auto lock = LockContext(); auto lock = LockContext();
macro->Actions().emplace( macro->Actions().emplace(macro->Actions().begin() + idx,
macro->Actions().begin() + idx, MacroActionFactory::Create(id, macro));
MacroActionFactory::Create(id, macro.get())); if (data) {
if (idx - 1 >= 0) {
auto data = obs_data_create();
macro->Actions().at(idx - 1)->Save(data);
macro->Actions().at(idx)->Load(data); macro->Actions().at(idx)->Load(data);
obs_data_release(data);
} }
macro->Actions().at(idx)->PostLoad(); macro->Actions().at(idx)->PostLoad();
RunPostLoadSteps(); RunPostLoadSteps();
@@ -198,9 +182,37 @@ void AdvSceneSwitcher::AddMacroAction(int idx)
SetActionData(*macro); SetActionData(*macro);
} }
HighlightAction(idx); HighlightAction(idx);
ui->actionsList->SetHelpMsgVisible(false);
emit(MacroSegmentOrderChanged()); emit(MacroSegmentOrderChanged());
} }
void AdvSceneSwitcher::AddMacroAction(int idx)
{
auto macro = GetSelectedMacro();
if (!macro) {
return;
}
if (idx < 0 || idx > (int)macro->Actions().size()) {
assert(false);
return;
}
std::string id;
if (idx - 1 >= 0) {
id = macro->Actions().at(idx - 1)->GetId();
} else {
id = MacroAction::GetDefaultID();
}
OBSDataAutoRelease data;
if (idx - 1 >= 0) {
data = obs_data_create();
macro->Actions().at(idx - 1)->Save(data);
}
AddMacroAction(macro.get(), idx, id, data);
}
void AdvSceneSwitcher::on_actionAdd_clicked() void AdvSceneSwitcher::on_actionAdd_clicked()
{ {
auto macro = GetSelectedMacro(); auto macro = GetSelectedMacro();
@@ -216,7 +228,6 @@ void AdvSceneSwitcher::on_actionAdd_clicked()
if (currentActionIdx != -1) { if (currentActionIdx != -1) {
MacroActionSelectionChanged(currentActionIdx + 1); MacroActionSelectionChanged(currentActionIdx + 1);
} }
ui->actionsList->SetHelpMsgVisible(false);
} }
void AdvSceneSwitcher::RemoveMacroAction(int idx) void AdvSceneSwitcher::RemoveMacroAction(int idx)
@@ -311,7 +322,6 @@ void AdvSceneSwitcher::on_elseActionAdd_clicked()
if (currentElseActionIdx != -1) { if (currentElseActionIdx != -1) {
MacroElseActionSelectionChanged(currentElseActionIdx + 1); MacroElseActionSelectionChanged(currentElseActionIdx + 1);
} }
ui->elseActionsList->SetHelpMsgVisible(false);
} }
void AdvSceneSwitcher::on_elseActionRemove_clicked() void AdvSceneSwitcher::on_elseActionRemove_clicked()
@@ -450,31 +460,21 @@ void AdvSceneSwitcher::MacroElseActionReorder(int to, int from)
emit(MacroSegmentOrderChanged()); emit(MacroSegmentOrderChanged());
} }
void AdvSceneSwitcher::AddMacroElseAction(int idx) void AdvSceneSwitcher::AddMacroElseAction(Macro *macro, int idx,
const std::string &id,
obs_data_t *data)
{ {
auto macro = GetSelectedMacro();
if (!macro) {
return;
}
if (idx < 0 || idx > (int)macro->ElseActions().size()) { if (idx < 0 || idx > (int)macro->ElseActions().size()) {
assert(false);
return; return;
} }
std::string id;
if (idx - 1 >= 0) {
id = macro->ElseActions().at(idx - 1)->GetId();
} else {
id = MacroAction::GetDefaultID();
}
{ {
auto lock = LockContext(); auto lock = LockContext();
macro->ElseActions().emplace( macro->ElseActions().emplace(macro->ElseActions().begin() + idx,
macro->ElseActions().begin() + idx, MacroActionFactory::Create(id,
MacroActionFactory::Create(id, macro.get())); macro));
if (idx - 1 >= 0) { if (data) {
OBSDataAutoRelease data = obs_data_create();
macro->ElseActions().at(idx - 1)->Save(data);
macro->ElseActions().at(idx)->Load(data); macro->ElseActions().at(idx)->Load(data);
} }
macro->ElseActions().at(idx)->PostLoad(); macro->ElseActions().at(idx)->PostLoad();
@@ -486,9 +486,37 @@ void AdvSceneSwitcher::AddMacroElseAction(int idx)
SetElseActionData(*macro); SetElseActionData(*macro);
} }
HighlightElseAction(idx); HighlightElseAction(idx);
ui->elseActionsList->SetHelpMsgVisible(false);
emit(MacroSegmentOrderChanged()); emit(MacroSegmentOrderChanged());
} }
void AdvSceneSwitcher::AddMacroElseAction(int idx)
{
auto macro = GetSelectedMacro();
if (!macro) {
return;
}
if (idx < 0 || idx > (int)macro->ElseActions().size()) {
assert(false);
return;
}
std::string id;
if (idx - 1 >= 0) {
id = macro->ElseActions().at(idx - 1)->GetId();
} else {
id = MacroAction::GetDefaultID();
}
OBSDataAutoRelease data;
if (idx - 1 >= 0) {
data = obs_data_create();
macro->ElseActions().at(idx - 1)->Save(data);
}
AddMacroElseAction(macro.get(), idx, id, data);
}
void AdvSceneSwitcher::RemoveMacroElseAction(int idx) void AdvSceneSwitcher::RemoveMacroElseAction(int idx)
{ {
auto macro = GetSelectedMacro(); auto macro = GetSelectedMacro();
@@ -507,7 +535,7 @@ void AdvSceneSwitcher::RemoveMacroElseAction(int idx)
SetMacroAbortWait(true); SetMacroAbortWait(true);
GetMacroWaitCV().notify_all(); GetMacroWaitCV().notify_all();
macro->UpdateElseActionIndices(); macro->UpdateElseActionIndices();
SetActionData(*macro); SetElseActionData(*macro);
} }
MacroElseActionSelectionChanged(-1); MacroElseActionSelectionChanged(-1);
lastInteracted = MacroSection::ELSE_ACTIONS; lastInteracted = MacroSection::ELSE_ACTIONS;

View File

@@ -1,4 +1,5 @@
#include "macro-action-macro.hpp" #include "macro-action-macro.hpp"
#include "help-icon.hpp"
#include "layout-helpers.hpp" #include "layout-helpers.hpp"
#include "macro.hpp" #include "macro.hpp"
@@ -48,9 +49,7 @@ bool MacroActionMacro::PerformAction()
macro->ResetRunCount(); macro->ResetRunCount();
break; break;
case Action::RUN: case Action::RUN:
if (!macro->Paused()) { RunActions(macro.get());
macro->PerformActions(true, false, true);
}
break; break;
case Action::STOP: case Action::STOP:
macro->Stop(); macro->Stop();
@@ -127,6 +126,7 @@ bool MacroActionMacro::Save(obs_data_t *obj) const
_macro.Save(obj); _macro.Save(obj);
_actionIndex.Save(obj, "actionIndex"); _actionIndex.Save(obj, "actionIndex");
obs_data_set_int(obj, "action", static_cast<int>(_action)); obs_data_set_int(obj, "action", static_cast<int>(_action));
_runOptions.Save(obj);
return true; return true;
} }
@@ -137,6 +137,15 @@ bool MacroActionMacro::Load(obs_data_t *obj)
_actionIndex.Load(obj, "actionIndex"); _actionIndex.Load(obj, "actionIndex");
_action = static_cast<MacroActionMacro::Action>( _action = static_cast<MacroActionMacro::Action>(
obs_data_get_int(obj, "action")); obs_data_get_int(obj, "action"));
_runOptions.Load(obj);
return true;
}
bool MacroActionMacro::PostLoad()
{
MacroRefAction::PostLoad();
MacroAction::PostLoad();
_runOptions.macro.PostLoad();
return true; return true;
} }
@@ -160,11 +169,68 @@ void MacroActionMacro::ResolveVariablesToFixedValues()
_actionIndex.ResolveVariables(); _actionIndex.ResolveVariables();
} }
static inline void populateActionSelection(QComboBox *list) static void runActionsHelper(Macro *macro, bool runElseActions, bool setInputs,
const StringList &inputs)
{ {
for (auto entry : actionTypes) { if (setInputs) {
list->addItem(obs_module_text(entry.second.c_str())); macro->GetInputVariables().SetValues(inputs);
} }
macro->PerformActions(!runElseActions, false, true);
}
void MacroActionMacro::RunActions(Macro *actionMacro) const
{
if (_runOptions.skipWhenPaused && actionMacro->Paused()) {
return;
}
if (_runOptions.logic == RunOptions::Logic::IGNORE_CONDITIONS) {
runActionsHelper(actionMacro, _runOptions.runElseActions,
_runOptions.setInputs, _runOptions.inputs);
return;
}
auto conditionMacro = _runOptions.macro.GetMacro();
if (!conditionMacro) {
return;
}
if (_runOptions.reevaluateConditionState) {
conditionMacro->CeckMatch(true);
}
if ((_runOptions.logic == RunOptions::Logic::CONDITIONS &&
conditionMacro->Matched()) ||
(_runOptions.logic == RunOptions::Logic::INVERT_CONDITIONS &&
!conditionMacro->Matched())) {
runActionsHelper(actionMacro, _runOptions.runElseActions,
_runOptions.setInputs, _runOptions.inputs);
}
}
static void populateActionSelection(QComboBox *list)
{
for (const auto &[_, name] : actionTypes) {
list->addItem(obs_module_text(name.c_str()));
}
}
static void populateConditionBehaviorSelection(QComboBox *list)
{
list->addItem(obs_module_text(
"AdvSceneSwitcher.action.macro.type.run.conditions.ignore"));
list->addItem(obs_module_text(
"AdvSceneSwitcher.action.macro.type.run.conditions.true"));
list->addItem(obs_module_text(
"AdvSceneSwitcher.action.macro.type.run.conditions.false"));
}
static void populateActionTypeSelection(QComboBox *list)
{
list->addItem(obs_module_text(
"AdvSceneSwitcher.action.macro.type.run.actionType.regular"));
list->addItem(obs_module_text(
"AdvSceneSwitcher.action.macro.type.run.actionType.else"));
} }
MacroActionMacroEdit::MacroActionMacroEdit( MacroActionMacroEdit::MacroActionMacroEdit(
@@ -173,9 +239,28 @@ MacroActionMacroEdit::MacroActionMacroEdit(
_macros(new MacroSelection(parent)), _macros(new MacroSelection(parent)),
_actionIndex(new MacroSegmentSelection( _actionIndex(new MacroSegmentSelection(
this, MacroSegmentSelection::Type::ACTION)), this, MacroSegmentSelection::Type::ACTION)),
_actions(new QComboBox()) _actions(new QComboBox()),
_conditionMacros(new MacroSelection(parent)),
_conditionBehaviors(new QComboBox()),
_reevaluateConditionState(new QCheckBox(
obs_module_text("AdvSceneSwitcher.action.macro.type.run."
"updateConditionMatchState"))),
_actionTypes(new QComboBox()),
_skipWhenPaused(new QCheckBox(obs_module_text(
"AdvSceneSwitcher.action.macro.type.run.skipWhenPaused"))),
_setInputs(new QCheckBox(obs_module_text(
"AdvSceneSwitcher.action.macro.type.run.setInputs"))),
_inputs(new MacroInputEdit()),
_entryLayout(new QHBoxLayout()),
_conditionLayout(new QHBoxLayout()),
_reevaluateConditionStateLayout(new QHBoxLayout()),
_setInputsLayout(new QHBoxLayout())
{ {
populateActionSelection(_actions); populateActionSelection(_actions);
populateConditionBehaviorSelection(_conditionBehaviors);
populateActionTypeSelection(_actionTypes);
_conditionMacros->HideSelectedMacro();
QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)), QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)),
this, SLOT(MacroChanged(const QString &))); this, SLOT(MacroChanged(const QString &)));
@@ -184,20 +269,53 @@ MacroActionMacroEdit::MacroActionMacroEdit(
QWidget::connect(_actionIndex, QWidget::connect(_actionIndex,
SIGNAL(SelectionChanged(const IntVariable &)), this, SIGNAL(SelectionChanged(const IntVariable &)), this,
SLOT(ActionIndexChanged(const IntVariable &))); SLOT(ActionIndexChanged(const IntVariable &)));
QWidget::connect(_conditionMacros,
SIGNAL(currentTextChanged(const QString &)), this,
SLOT(ConditionMacroChanged(const QString &)));
QWidget::connect(_conditionBehaviors, SIGNAL(currentIndexChanged(int)),
this, SLOT(ConditionBehaviorChanged(int)));
QWidget::connect(_actionTypes, SIGNAL(currentIndexChanged(int)), this,
SLOT(ActionTypeChanged(int)));
QWidget::connect(_skipWhenPaused, SIGNAL(stateChanged(int)), this,
SLOT(SkipWhenPausedChanged(int)));
QWidget::connect(_setInputs, SIGNAL(stateChanged(int)), this,
SLOT(SetInputsChanged(int)));
QWidget::connect(_inputs,
SIGNAL(MacroInputValuesChanged(const StringList &)),
this, SLOT(InputsChanged(const StringList &)));
QWidget::connect(_reevaluateConditionState, SIGNAL(stateChanged(int)),
this, SLOT(ReevaluateConditionStateChanged(int)));
auto mainLayout = new QHBoxLayout; _setInputsLayout->addWidget(_setInputs);
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.macro.entry"), _setInputsLayout->addWidget(new HelpIcon(obs_module_text(
mainLayout, "AdvSceneSwitcher.action.macro.type.run.setInputs.description")));
{{"{{actions}}", _actions}, _setInputsLayout->addStretch();
{"{{actionIndex}}", _actionIndex},
{"{{macros}}", _macros}});
setLayout(mainLayout);
_reevaluateConditionStateLayout->addWidget(_reevaluateConditionState);
_reevaluateConditionStateLayout->addWidget(new HelpIcon(obs_module_text(
"AdvSceneSwitcher.action.macro.type.run.updateConditionMatchState.help")));
_reevaluateConditionStateLayout->addStretch();
auto layout = new QVBoxLayout();
layout->addLayout(_entryLayout);
layout->addLayout(_conditionLayout);
layout->addLayout(_reevaluateConditionStateLayout);
layout->addLayout(_setInputsLayout);
layout->addWidget(_inputs);
layout->addWidget(_skipWhenPaused);
setLayout(layout);
_entryData = entryData; _entryData = entryData;
UpdateEntryData(); UpdateEntryData();
_loading = false; _loading = false;
} }
void HighligthMacroSettingsButton(bool enable);
MacroActionMacroEdit::~MacroActionMacroEdit()
{
HighligthMacroSettingsButton(false);
}
void MacroActionMacroEdit::UpdateEntryData() void MacroActionMacroEdit::UpdateEntryData()
{ {
if (!_entryData) { if (!_entryData) {
@@ -207,45 +325,132 @@ void MacroActionMacroEdit::UpdateEntryData()
_actionIndex->SetValue(_entryData->_actionIndex); _actionIndex->SetValue(_entryData->_actionIndex);
_actionIndex->SetMacro(_entryData->_macro.GetMacro()); _actionIndex->SetMacro(_entryData->_macro.GetMacro());
_macros->SetCurrentMacro(_entryData->_macro); _macros->SetCurrentMacro(_entryData->_macro);
_conditionMacros->SetCurrentMacro(_entryData->_runOptions.macro);
_conditionBehaviors->setCurrentIndex(
static_cast<int>(_entryData->_runOptions.logic));
_reevaluateConditionState->setChecked(
_entryData->_runOptions.reevaluateConditionState);
_actionTypes->setCurrentIndex(
_entryData->_runOptions.runElseActions ? 1 : 0);
_skipWhenPaused->setChecked(_entryData->_runOptions.skipWhenPaused);
_setInputs->setChecked(_entryData->_runOptions.setInputs);
SetupMacroInput(_entryData->_macro.GetMacro().get());
SetWidgetVisibility(); SetWidgetVisibility();
} }
void MacroActionMacroEdit::MacroChanged(const QString &text) void MacroActionMacroEdit::MacroChanged(const QString &text)
{ {
if (_loading || !_entryData) { GUARD_LOADING_AND_LOCK();
return;
}
auto lock = LockContext();
_entryData->_macro = text; _entryData->_macro = text;
_actionIndex->SetMacro(_entryData->_macro.GetMacro()); const auto &macro = _entryData->_macro.GetMacro();
_actionIndex->SetMacro(macro);
SetupMacroInput(macro.get());
emit HeaderInfoChanged( emit HeaderInfoChanged(
QString::fromStdString(_entryData->GetShortDesc())); QString::fromStdString(_entryData->GetShortDesc()));
SetWidgetVisibility();
} }
void MacroActionMacroEdit::ActionChanged(int value) void MacroActionMacroEdit::ActionChanged(int value)
{ {
if (_loading || !_entryData) { GUARD_LOADING_AND_LOCK();
return;
}
auto lock = LockContext();
_entryData->_action = static_cast<MacroActionMacro::Action>(value); _entryData->_action = static_cast<MacroActionMacro::Action>(value);
SetWidgetVisibility(); SetWidgetVisibility();
} }
void MacroActionMacroEdit::ActionIndexChanged(const IntVariable &value) void MacroActionMacroEdit::ActionIndexChanged(const IntVariable &value)
{ {
if (_loading || !_entryData) { GUARD_LOADING_AND_LOCK();
return;
}
auto lock = LockContext();
_entryData->_actionIndex = value; _entryData->_actionIndex = value;
} }
void MacroActionMacroEdit::ConditionMacroChanged(const QString &text)
{
GUARD_LOADING_AND_LOCK();
_entryData->_runOptions.macro = text;
}
void MacroActionMacroEdit::ConditionBehaviorChanged(int value)
{
GUARD_LOADING_AND_LOCK();
_entryData->_runOptions.logic =
static_cast<MacroActionMacro::RunOptions::Logic>(value);
SetWidgetVisibility();
}
void MacroActionMacroEdit::ReevaluateConditionStateChanged(int value)
{
GUARD_LOADING_AND_LOCK();
_entryData->_runOptions.reevaluateConditionState = value;
SetWidgetVisibility();
}
void MacroActionMacroEdit::ActionTypeChanged(int value)
{
GUARD_LOADING_AND_LOCK();
_entryData->_runOptions.runElseActions = value;
}
void MacroActionMacroEdit::SkipWhenPausedChanged(int value)
{
GUARD_LOADING_AND_LOCK();
_entryData->_runOptions.skipWhenPaused = value;
}
void MacroActionMacroEdit::SetInputsChanged(int value)
{
GUARD_LOADING_AND_LOCK();
_entryData->_runOptions.setInputs = value;
SetWidgetVisibility();
}
void MacroActionMacroEdit::InputsChanged(const StringList &inputs)
{
GUARD_LOADING_AND_LOCK();
_entryData->_runOptions.inputs = inputs;
adjustSize();
updateGeometry();
}
void MacroActionMacroEdit::SetWidgetVisibility() void MacroActionMacroEdit::SetWidgetVisibility()
{ {
_entryLayout->removeWidget(_actions);
_entryLayout->removeWidget(_actionIndex);
_entryLayout->removeWidget(_macros);
_entryLayout->removeWidget(_actionTypes);
_conditionLayout->removeWidget(_conditionBehaviors);
_conditionLayout->removeWidget(_conditionMacros);
ClearLayout(_entryLayout);
ClearLayout(_conditionLayout);
const std::unordered_map<std::string, QWidget *> placeholders = {
{"{{actions}}", _actions},
{"{{actionIndex}}", _actionIndex},
{"{{macros}}", _macros},
{"{{actionTypes}}", _actionTypes},
{"{{conditionBehaviors}}", _conditionBehaviors},
{"{{conditionMacros}}", _conditionMacros},
};
PlaceWidgets(
obs_module_text(
_entryData->_action == MacroActionMacro::Action::RUN
? "AdvSceneSwitcher.action.macro.entry.run"
: "AdvSceneSwitcher.action.macro.entry.other"),
_entryLayout, placeholders);
if (_entryData->_runOptions.logic ==
MacroActionMacro::RunOptions::Logic::IGNORE_CONDITIONS) {
_conditionLayout->addWidget(_conditionBehaviors);
_conditionLayout->addStretch();
} else {
PlaceWidgets(
obs_module_text(
"AdvSceneSwitcher.action.macro.entry.run.condition"),
_conditionLayout, placeholders);
}
if (_entryData->_action == MacroActionMacro::Action::RUN || if (_entryData->_action == MacroActionMacro::Action::RUN ||
_entryData->_action == MacroActionMacro::Action::STOP) { _entryData->_action == MacroActionMacro::Action::STOP) {
_macros->HideSelectedMacro(); _macros->HideSelectedMacro();
@@ -260,6 +465,73 @@ void MacroActionMacroEdit::SetWidgetVisibility()
MacroActionMacro::Action::ENABLE_ACTION || MacroActionMacro::Action::ENABLE_ACTION ||
_entryData->_action == MacroActionMacro::Action::TOGGLE_ACTION; _entryData->_action == MacroActionMacro::Action::TOGGLE_ACTION;
_actionIndex->setVisible(isModifyingActionState); _actionIndex->setVisible(isModifyingActionState);
SetLayoutVisible(_conditionLayout,
_entryData->_action == MacroActionMacro::Action::RUN);
const bool needsAdditionalConditionWidgets =
_entryData->_action == MacroActionMacro::Action::RUN &&
_entryData->_runOptions.logic !=
MacroActionMacro::RunOptions::Logic::IGNORE_CONDITIONS;
_conditionMacros->setVisible(needsAdditionalConditionWidgets);
SetLayoutVisible(_reevaluateConditionStateLayout,
needsAdditionalConditionWidgets);
SetLayoutVisible(_setInputsLayout,
_entryData->_action == MacroActionMacro::Action::RUN);
_inputs->setVisible(_entryData->_action ==
MacroActionMacro::Action::RUN &&
_entryData->_runOptions.setInputs);
HighligthMacroSettingsButton(_entryData->_action ==
MacroActionMacro::Action::RUN &&
_entryData->_runOptions.setInputs &&
!_inputs->HasInputsToSet());
_actionTypes->setVisible(_entryData->_action ==
MacroActionMacro::Action::RUN);
_skipWhenPaused->setVisible(_entryData->_action ==
MacroActionMacro::Action::RUN);
adjustSize();
updateGeometry();
}
void MacroActionMacroEdit::SetupMacroInput(Macro *macro) const
{
if (macro) {
_inputs->SetInputVariablesAndValues(
macro->GetInputVariables(),
_entryData->_runOptions.inputs);
} else {
_inputs->SetInputVariablesAndValues({}, {});
}
}
void MacroActionMacro::RunOptions::Save(obs_data_t *obj) const
{
OBSDataAutoRelease data = obs_data_create();
obs_data_set_int(data, "logic", static_cast<int>(logic));
obs_data_set_bool(data, "reevaluateConditionState",
reevaluateConditionState);
obs_data_set_bool(data, "runElseActions", runElseActions);
obs_data_set_bool(data, "skipWhenPaused", skipWhenPaused);
obs_data_set_bool(data, "setInputs", setInputs);
inputs.Save(data, "inputs");
macro.Save(data);
obs_data_set_obj(obj, "runOptions", data);
}
void MacroActionMacro::RunOptions::Load(obs_data_t *obj)
{
if (!obs_data_has_user_value(obj, "runOptions")) {
return;
}
OBSDataAutoRelease data = obs_data_get_obj(obj, "runOptions");
logic = static_cast<Logic>(obs_data_get_int(data, "logic"));
reevaluateConditionState =
obs_data_get_bool(data, "reevaluateConditionState");
runElseActions = obs_data_get_bool(data, "runElseActions");
skipWhenPaused = obs_data_get_bool(data, "skipWhenPaused");
setInputs = obs_data_get_bool(data, "setInputs");
inputs.Load(data, "inputs");
macro.Load(data);
} }
} // namespace advss } // namespace advss

View File

@@ -1,25 +1,45 @@
#pragma once #pragma once
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
#include "macro-input.hpp"
#include "macro-selection.hpp" #include "macro-selection.hpp"
#include "macro-segment-selection.hpp" #include "macro-segment-selection.hpp"
#include <QCheckBox>
#include <QHBoxLayout> #include <QHBoxLayout>
namespace advss { namespace advss {
class MacroActionMacro : public MacroRefAction { class MacroActionMacro final : public MacroRefAction {
public: public:
MacroActionMacro(Macro *m) : MacroAction(m), MacroRefAction(m) {} MacroActionMacro(Macro *m) : MacroAction(m), MacroRefAction(m) {}
bool PerformAction(); bool PerformAction();
void LogAction() const; void LogAction() const;
bool Save(obs_data_t *obj) const; bool Save(obs_data_t *obj) const;
bool Load(obs_data_t *obj); bool Load(obs_data_t *obj);
bool PostLoad();
std::string GetShortDesc() const; std::string GetShortDesc() const;
std::string GetId() const { return id; }; std::string GetId() const { return id; };
static std::shared_ptr<MacroAction> Create(Macro *m); static std::shared_ptr<MacroAction> Create(Macro *m);
std::shared_ptr<MacroAction> Copy() const; std::shared_ptr<MacroAction> Copy() const;
void ResolveVariablesToFixedValues(); void ResolveVariablesToFixedValues();
struct RunOptions {
void Save(obs_data_t *obj) const;
void Load(obs_data_t *obj);
enum class Logic {
IGNORE_CONDITIONS,
CONDITIONS,
INVERT_CONDITIONS,
};
Logic logic;
bool reevaluateConditionState = false;
bool runElseActions = false;
bool skipWhenPaused = true;
bool setInputs = false;
StringList inputs;
MacroRef macro;
};
enum class Action { enum class Action {
PAUSE, PAUSE,
UNPAUSE, UNPAUSE,
@@ -30,21 +50,25 @@ public:
ENABLE_ACTION, ENABLE_ACTION,
TOGGLE_ACTION, TOGGLE_ACTION,
}; };
Action _action = Action::PAUSE; Action _action = Action::RUN;
IntVariable _actionIndex = 1; IntVariable _actionIndex = 1;
RunOptions _runOptions = {};
private: private:
void RunActions(Macro *actionMacro) const;
static bool _registered; static bool _registered;
static const std::string id; static const std::string id;
}; };
class MacroActionMacroEdit : public QWidget { class MacroActionMacroEdit final : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
MacroActionMacroEdit( MacroActionMacroEdit(
QWidget *parent, QWidget *parent,
std::shared_ptr<MacroActionMacro> entryData = nullptr); std::shared_ptr<MacroActionMacro> entryData = nullptr);
~MacroActionMacroEdit();
void UpdateEntryData(); void UpdateEntryData();
static QWidget *Create(QWidget *parent, static QWidget *Create(QWidget *parent,
std::shared_ptr<MacroAction> action) std::shared_ptr<MacroAction> action)
@@ -58,18 +82,37 @@ private slots:
void MacroChanged(const QString &text); void MacroChanged(const QString &text);
void ActionChanged(int value); void ActionChanged(int value);
void ActionIndexChanged(const IntVariable &value); void ActionIndexChanged(const IntVariable &value);
void ConditionMacroChanged(const QString &text);
void ConditionBehaviorChanged(int value);
void ReevaluateConditionStateChanged(int value);
void ActionTypeChanged(int value);
void SkipWhenPausedChanged(int value);
void SetInputsChanged(int value);
void InputsChanged(const StringList &);
signals: signals:
void HeaderInfoChanged(const QString &); void HeaderInfoChanged(const QString &);
protected: private:
void SetWidgetVisibility();
void SetupMacroInput(Macro *) const;
MacroSelection *_macros; MacroSelection *_macros;
MacroSegmentSelection *_actionIndex; MacroSegmentSelection *_actionIndex;
QComboBox *_actions; QComboBox *_actions;
MacroSelection *_conditionMacros;
QComboBox *_conditionBehaviors;
QCheckBox *_reevaluateConditionState;
QComboBox *_actionTypes;
QCheckBox *_skipWhenPaused;
QCheckBox *_setInputs;
MacroInputEdit *_inputs;
QHBoxLayout *_entryLayout;
QHBoxLayout *_conditionLayout;
QHBoxLayout *_reevaluateConditionStateLayout;
QHBoxLayout *_setInputsLayout;
std::shared_ptr<MacroActionMacro> _entryData; std::shared_ptr<MacroActionMacro> _entryData;
private:
void SetWidgetVisibility();
bool _loading = true; bool _loading = true;
}; };

View File

@@ -58,6 +58,8 @@ const static std::map<MacroActionVariable::Type, std::string> actionTypes = {
"AdvSceneSwitcher.action.variable.type.padValue"}, "AdvSceneSwitcher.action.variable.type.padValue"},
{MacroActionVariable::Type::TRUNCATE, {MacroActionVariable::Type::TRUNCATE,
"AdvSceneSwitcher.action.variable.type.truncateValue"}, "AdvSceneSwitcher.action.variable.type.truncateValue"},
{MacroActionVariable::Type::SWAP_VALUES,
"AdvSceneSwitcher.action.variable.type.swapValues"},
}; };
static void apppend(Variable &var, const std::string &value) static void apppend(Variable &var, const std::string &value)
@@ -392,6 +394,17 @@ bool MacroActionVariable::PerformAction()
var->SetValue( var->SetValue(
truncate(var->Value(), _direction, _stringLength)); truncate(var->Value(), _direction, _stringLength));
return true; return true;
case Type::SWAP_VALUES: {
auto var2 = _variable2.lock();
if (!var2) {
return true;
}
auto tempValue = var->Value();
var->SetValue(var2->Value());
var2->SetValue(tempValue);
return true;
}
} }
return true; return true;
@@ -630,6 +643,8 @@ MacroActionVariableEdit::MacroActionVariableEdit(
_scenes(new SceneSelectionWidget(this, true, false, true, true, _scenes(new SceneSelectionWidget(this, true, false, true, true,
true)), true)),
_tempVars(new TempVariableSelection(this)), _tempVars(new TempVariableSelection(this)),
_tempVarsHelp(new HelpIcon(obs_module_text(
"AdvSceneSwitcher.action.variable.type.setToTempvar.help"))),
_sceneItemIndex(new VariableSpinBox()), _sceneItemIndex(new VariableSpinBox()),
_direction(new QComboBox()), _direction(new QComboBox()),
_stringLength(new VariableSpinBox()), _stringLength(new VariableSpinBox()),
@@ -742,6 +757,7 @@ MacroActionVariableEdit::MacroActionVariableEdit(
{"{{envVariableName}}", _envVariable}, {"{{envVariableName}}", _envVariable},
{"{{scenes}}", _scenes}, {"{{scenes}}", _scenes},
{"{{tempVars}}", _tempVars}, {"{{tempVars}}", _tempVars},
{"{{tempVarsHelp}}", _tempVarsHelp},
{"{{sceneItemIndex}}", _sceneItemIndex}, {"{{sceneItemIndex}}", _sceneItemIndex},
{"{{direction}}", _direction}, {"{{direction}}", _direction},
{"{{stringLength}}", _stringLength}, {"{{stringLength}}", _stringLength},
@@ -1202,6 +1218,7 @@ void MacroActionVariableEdit::SelectionChanged(const TempVariableRef &var)
auto lock = LockContext(); auto lock = LockContext();
_entryData->_tempVar = var; _entryData->_tempVar = var;
SetWidgetVisibility();
} }
void MacroActionVariableEdit::SceneItemIndexChanged( void MacroActionVariableEdit::SceneItemIndexChanged(
@@ -1268,6 +1285,7 @@ void MacroActionVariableEdit::SetWidgetVisibility()
{"{{envVariableName}}", _envVariable}, {"{{envVariableName}}", _envVariable},
{"{{scenes}}", _scenes}, {"{{scenes}}", _scenes},
{"{{tempVars}}", _tempVars}, {"{{tempVars}}", _tempVars},
{"{{tempVarsHelp}}", _tempVarsHelp},
{"{{sceneItemIndex}}", _sceneItemIndex}, {"{{sceneItemIndex}}", _sceneItemIndex},
{"{{direction}}", _direction}, {"{{direction}}", _direction},
{"{{stringLength}}", _stringLength}, {"{{stringLength}}", _stringLength},
@@ -1304,8 +1322,9 @@ void MacroActionVariableEdit::SetWidgetVisibility()
AddStretchIfNecessary(_entryLayout); AddStretchIfNecessary(_entryLayout);
} }
_variables2->setVisible(_entryData->_type == _variables2->setVisible(
MacroActionVariable::Type::APPEND_VAR); _entryData->_type == MacroActionVariable::Type::APPEND_VAR ||
_entryData->_type == MacroActionVariable::Type::SWAP_VALUES);
_strValue->setVisible( _strValue->setVisible(
_entryData->_type == _entryData->_type ==
MacroActionVariable::Type::SET_FIXED_VALUE || MacroActionVariable::Type::SET_FIXED_VALUE ||
@@ -1381,6 +1400,10 @@ void MacroActionVariableEdit::SetWidgetVisibility()
MacroActionVariable::Type::SCENE_ITEM_NAME); MacroActionVariable::Type::SCENE_ITEM_NAME);
_tempVars->setVisible(_entryData->_type == _tempVars->setVisible(_entryData->_type ==
MacroActionVariable::Type::SET_TO_TEMPVAR); MacroActionVariable::Type::SET_TO_TEMPVAR);
_tempVarsHelp->setVisible(
_entryData->_type ==
MacroActionVariable::Type::SET_TO_TEMPVAR &&
!_entryData->_tempVar.HasValidID());
_sceneItemIndex->setVisible(_entryData->_type == _sceneItemIndex->setVisible(_entryData->_type ==
MacroActionVariable::Type::SCENE_ITEM_NAME); MacroActionVariable::Type::SCENE_ITEM_NAME);
_direction->setVisible( _direction->setVisible(

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
#include "help-icon.hpp"
#include "macro-segment-selection.hpp" #include "macro-segment-selection.hpp"
#include "regex-config.hpp" #include "regex-config.hpp"
#include "resizing-text-edit.hpp" #include "resizing-text-edit.hpp"
@@ -48,6 +49,7 @@ public:
SCENE_ITEM_NAME, SCENE_ITEM_NAME,
PAD, PAD,
TRUNCATE, TRUNCATE,
SWAP_VALUES,
}; };
Type _type = Type::SET_FIXED_VALUE; Type _type = Type::SET_FIXED_VALUE;
@@ -185,6 +187,7 @@ private:
VariableLineEdit *_envVariable; VariableLineEdit *_envVariable;
SceneSelectionWidget *_scenes; SceneSelectionWidget *_scenes;
TempVariableSelection *_tempVars; TempVariableSelection *_tempVars;
HelpIcon *_tempVarsHelp;
VariableSpinBox *_sceneItemIndex; VariableSpinBox *_sceneItemIndex;
QComboBox *_direction; QComboBox *_direction;
VariableSpinBox *_stringLength; VariableSpinBox *_stringLength;

View File

@@ -1,6 +1,6 @@
#include "macro-condition-edit.hpp" #include "macro-condition-edit.hpp"
#include "advanced-scene-switcher.hpp" #include "advanced-scene-switcher.hpp"
#include "macro-properties.hpp" #include "macro-settings.hpp"
#include "macro.hpp" #include "macro.hpp"
#include "path-helpers.hpp" #include "path-helpers.hpp"
#include "plugin-state-helpers.hpp" #include "plugin-state-helpers.hpp"
@@ -121,8 +121,7 @@ void DurationModifierEdit::Collapse(bool collapse)
MacroConditionEdit::MacroConditionEdit( MacroConditionEdit::MacroConditionEdit(
QWidget *parent, std::shared_ptr<MacroCondition> *entryData, QWidget *parent, std::shared_ptr<MacroCondition> *entryData,
const std::string &id, bool root) const std::string &id, bool root)
: MacroSegmentEdit(GetGlobalMacroProperties()._highlightConditions, : MacroSegmentEdit(parent),
parent),
_logicSelection(new QComboBox()), _logicSelection(new QComboBox()),
_conditionSelection(new FilterComboBox()), _conditionSelection(new FilterComboBox()),
_dur(new DurationModifierEdit()), _dur(new DurationModifierEdit()),
@@ -139,8 +138,6 @@ MacroConditionEdit::MacroConditionEdit(
QWidget::connect(_dur, SIGNAL(ModifierChanged(DurationModifier::Type)), QWidget::connect(_dur, SIGNAL(ModifierChanged(DurationModifier::Type)),
this, this,
SLOT(DurationModifierChanged(DurationModifier::Type))); SLOT(DurationModifierChanged(DurationModifier::Type)));
QWidget::connect(window(), SIGNAL(HighlightConditionsChanged(bool)),
this, SLOT(EnableHighlight(bool)));
populateLogicSelection(_logicSelection, root); populateLogicSelection(_logicSelection, root);
populateConditionSelection(_conditionSelection); populateConditionSelection(_conditionSelection);
@@ -299,6 +296,7 @@ void AdvSceneSwitcher::AddMacroCondition(int idx)
} }
if (idx < 0 || idx > (int)macro->Conditions().size()) { if (idx < 0 || idx > (int)macro->Conditions().size()) {
assert(false);
return; return;
} }
@@ -315,16 +313,31 @@ void AdvSceneSwitcher::AddMacroCondition(int idx)
id = MacroCondition::GetDefaultID(); id = MacroCondition::GetDefaultID();
logic = LogicType::ROOT_NONE; logic = LogicType::ROOT_NONE;
} }
OBSDataAutoRelease data;
if (idx - 1 >= 0) {
data = obs_data_create();
macro->Conditions().at(idx - 1)->Save(data);
}
AddMacroCondition(macro.get(), idx, id, data.Get(), logic);
}
void AdvSceneSwitcher::AddMacroCondition(Macro *macro, int idx,
const std::string &id,
obs_data_t *data, LogicType logic)
{
if (idx < 0 || idx > (int)macro->Conditions().size()) {
assert(false);
return;
}
{ {
auto lock = LockContext(); auto lock = LockContext();
auto cond = macro->Conditions().emplace( auto cond = macro->Conditions().emplace(
macro->Conditions().begin() + idx, macro->Conditions().begin() + idx,
MacroConditionFactory::Create(id, macro.get())); MacroConditionFactory::Create(id, macro));
if (idx - 1 >= 0) { if (data) {
auto data = obs_data_create();
macro->Conditions().at(idx - 1)->Save(data);
macro->Conditions().at(idx)->Load(data); macro->Conditions().at(idx)->Load(data);
obs_data_release(data);
} }
macro->Conditions().at(idx)->PostLoad(); macro->Conditions().at(idx)->PostLoad();
RunPostLoadSteps(); RunPostLoadSteps();
@@ -337,6 +350,7 @@ void AdvSceneSwitcher::AddMacroCondition(int idx)
SetConditionData(*macro); SetConditionData(*macro);
} }
HighlightCondition(idx); HighlightCondition(idx);
ui->conditionsList->SetHelpMsgVisible(false);
emit(MacroSegmentOrderChanged()); emit(MacroSegmentOrderChanged());
} }
@@ -355,7 +369,6 @@ void AdvSceneSwitcher::on_conditionAdd_clicked()
if (currentConditionIdx != -1) { if (currentConditionIdx != -1) {
MacroConditionSelectionChanged(currentConditionIdx + 1); MacroConditionSelectionChanged(currentConditionIdx + 1);
} }
ui->conditionsList->SetHelpMsgVisible(false);
} }
void AdvSceneSwitcher::RemoveMacroCondition(int idx) void AdvSceneSwitcher::RemoveMacroCondition(int idx)

View File

@@ -167,7 +167,7 @@ void MacroDock::Highlight()
} }
if (_lastHighlightCheckTime.time_since_epoch().count() != 0 && if (_lastHighlightCheckTime.time_since_epoch().count() != 0 &&
macro->WasExecutedSince(_lastHighlightCheckTime)) { macro->WasExecutedSince(_lastHighlightCheckTime)) {
PulseWidget(this, Qt::green, QColor(0, 0, 0, 0), true); HighlightWidget(this, Qt::green, QColor(0, 0, 0, 0), true);
} }
_lastHighlightCheckTime = std::chrono::high_resolution_clock::now(); _lastHighlightCheckTime = std::chrono::high_resolution_clock::now();
} }

241
lib/macro/macro-input.cpp Normal file
View File

@@ -0,0 +1,241 @@
#include "macro-input.hpp"
#include "layout-helpers.hpp"
#include "log-helper.hpp"
#include "obs-module-helper.hpp"
#include "variable-line-edit.hpp"
#include <algorithm>
#include <obs.hpp>
namespace advss {
void MacroInputVariables::Save(obs_data_t *obj) const
{
OBSDataArrayAutoRelease array = obs_data_array_create();
for (auto &var : _inputVariables) {
OBSDataAutoRelease arrayObj = obs_data_create();
auto variable = var.lock();
if (variable) {
obs_data_set_string(arrayObj, "variableName",
variable->Name().c_str());
} else {
obs_data_set_bool(arrayObj, "invalidVariable", true);
}
obs_data_array_push_back(array, arrayObj);
}
obs_data_set_array(obj, "inputVariables", array);
}
void MacroInputVariables::Load(obs_data_t *obj)
{
OBSDataArrayAutoRelease array =
obs_data_get_array(obj, "inputVariables");
const size_t count = obs_data_array_count(array);
for (size_t i = 0; i < count; i++) {
OBSDataAutoRelease arrayObj = obs_data_array_item(array, i);
const bool isInvalid =
obs_data_get_bool(arrayObj, "invalidVariable");
if (isInvalid) {
_inputVariables.emplace_back();
} else {
const auto name =
obs_data_get_string(arrayObj, "variableName");
_inputVariables.emplace_back(
GetWeakVariableByName(name));
}
}
}
void MacroInputVariables::SetValues(const StringList &values)
{
if (_inputVariables.size() != (size_t)values.size()) {
blog(LOG_WARNING,
"%s - sizes do not match (variables: %d, values %d)",
__func__, (int)_inputVariables.size(), (int)values.size());
}
for (size_t index = 0;
index < _inputVariables.size() && index < (size_t)values.size();
index++) {
auto variable = _inputVariables.at(index).lock();
if (!variable) {
continue;
}
variable->SetValue(values.at(index));
}
}
MacroInputSelection::MacroInputSelection(QWidget *parent) : ListEditor(parent)
{
_list->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
}
void MacroInputSelection::SetInputs(const MacroInputVariables &inputs)
{
_currentSelection = inputs;
for (const auto &var : inputs._inputVariables) {
auto variable = var.lock();
const auto name =
variable
? QString::fromStdString(variable->Name())
: obs_module_text(
"AdvSceneSwitcher.macroTab.inputSettings.invalid");
QVariant v = QVariant::fromValue(name);
auto item = new QListWidgetItem(name, _list);
item->setData(Qt::UserRole, name);
}
UpdateListSize();
}
void MacroInputSelection::Add()
{
std::string varName;
bool accepted = VariableSelectionDialog::AskForVariable(this, varName);
if (!accepted || varName.empty()) {
return;
}
_currentSelection._inputVariables.emplace_back(
GetWeakVariableByName(varName));
QVariant v = QVariant::fromValue(QString::fromStdString(varName));
auto item = new QListWidgetItem(QString::fromStdString(varName), _list);
item->setData(Qt::UserRole, QString::fromStdString(varName));
UpdateListSize();
}
void MacroInputSelection::Remove()
{
auto item = _list->currentItem();
int idx = _list->currentRow();
if (!item || idx == -1) {
return;
}
_currentSelection._inputVariables.erase(
std::next(_currentSelection._inputVariables.begin(), idx));
delete item;
UpdateListSize();
}
void MacroInputSelection::Up()
{
int idx = _list->currentRow();
if (idx < 1) {
return;
}
_list->insertItem(idx - 1, _list->takeItem(idx));
_list->setCurrentRow(idx - 1);
std::iter_swap(
std::next(_currentSelection._inputVariables.begin(), idx),
std::next(_currentSelection._inputVariables.begin(), idx - 1));
}
void MacroInputSelection::Down()
{
int idx = _list->currentRow();
if (idx < 0 || idx >= _list->count()) {
return;
}
_list->insertItem(idx + 1, _list->takeItem(idx));
_list->setCurrentRow(idx + 1);
std::iter_swap(
std::next(_currentSelection._inputVariables.begin(), idx + 1),
std::next(_currentSelection._inputVariables.begin(), idx));
}
void MacroInputSelection::Clicked(QListWidgetItem *item)
{
std::string varName;
bool accepted = VariableSelectionDialog::AskForVariable(this, varName);
if (!accepted || varName.empty()) {
return;
}
item->setText(QString::fromStdString(varName));
int idx = _list->currentRow();
_currentSelection._inputVariables.at(idx) =
GetWeakVariableByName(varName);
}
MacroInputEdit::MacroInputEdit(QWidget *parent)
: QWidget(parent),
_layout(new QGridLayout())
{
setLayout(_layout);
}
void MacroInputEdit::SetInputVariablesAndValues(
const MacroInputVariables &inputs, const StringList &values)
{
_variables = inputs;
_values = values;
if ((size_t)_values.size() < _variables._inputVariables.size()) {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
for (int i = 0;
_variables._inputVariables.size() - (size_t)_values.size();
i++) {
_values.push_back({});
}
#else
_values.resize(_variables._inputVariables.size());
#endif
}
SetupWidgets();
}
bool MacroInputEdit::HasInputsToSet() const
{
return !_variables._inputVariables.empty();
}
void HighligthMacroSettingsButton(bool enable);
void MacroInputEdit::SetupWidgets()
{
ClearLayout(_layout);
auto &vars = _variables._inputVariables;
if (vars.empty()) {
_layout->addWidget(new QLabel(obs_module_text(
"AdvSceneSwitcher.macroTab.inputSettings.noInputs")));
adjustSize();
updateGeometry();
return;
}
for (size_t index = 0; index < vars.size(); index++) {
auto variable = vars.at(index).lock();
QLabel *label = new QLabel(
variable
? QString::fromStdString(variable->Name())
: obs_module_text(
"AdvSceneSwitcher.macroTab.inputSettings.invalid"));
_layout->addWidget(label, index, 0);
auto valueEdit = new VariableLineEdit(this);
valueEdit->setEnabled(!!variable);
valueEdit->setText(_values.at(index));
connect(valueEdit, &VariableLineEdit::editingFinished,
[this, valueEdit, index]() {
_values[index] =
valueEdit->text().toStdString();
emit MacroInputValuesChanged(_values);
});
_layout->addWidget(valueEdit, index, 1);
}
adjustSize();
updateGeometry();
}
} // namespace advss

63
lib/macro/macro-input.hpp Normal file
View File

@@ -0,0 +1,63 @@
#pragma once
#include "list-editor.hpp"
#include "string-list.hpp"
#include "variable.hpp"
#include <QGridLayout>
#include <memory>
#include <vector>
namespace advss {
class MacroInputVariables {
public:
void Save(obs_data_t *obj) const;
void Load(obs_data_t *obj);
void SetValues(const StringList &values);
private:
std::vector<std::weak_ptr<Variable>> _inputVariables;
friend class MacroInputSelection;
friend class MacroInputEdit;
};
class MacroInputSelection final : public ListEditor {
Q_OBJECT
public:
MacroInputSelection(QWidget *parent = nullptr);
void SetInputs(const MacroInputVariables &inputs);
MacroInputVariables GetInputs() const { return _currentSelection; }
private slots:
void Add();
void Remove();
void Up();
void Down();
void Clicked(QListWidgetItem *);
private:
MacroInputVariables _currentSelection;
};
class MacroInputEdit final : public QWidget {
Q_OBJECT
public:
MacroInputEdit(QWidget *parent = nullptr);
void SetInputVariablesAndValues(const MacroInputVariables &inputs,
const StringList &values);
bool HasInputsToSet() const;
signals:
void MacroInputValuesChanged(const StringList &);
private:
void SetupWidgets();
MacroInputVariables _variables;
StringList _values;
QGridLayout *_layout;
};
} // namespace advss

View File

@@ -7,68 +7,16 @@
namespace advss { namespace advss {
MacroList::MacroList(QWidget *parent, bool allowDuplicates, bool reorder) MacroList::MacroList(QWidget *parent, bool allowDuplicates, bool reorder)
: QWidget(parent), : ListEditor(parent, reorder),
_list(new QListWidget()), _allowDuplicates(allowDuplicates)
_add(new QPushButton()),
_remove(new QPushButton()),
_up(new QPushButton()),
_down(new QPushButton()),
_controlsLayout(new QHBoxLayout()),
_allowDuplicates(allowDuplicates),
_reorder(reorder)
{ {
_add->setMaximumWidth(22);
_add->setProperty("themeID",
QVariant(QString::fromUtf8("addIconSmall")));
_add->setFlat(true);
_remove->setMaximumWidth(22);
_remove->setProperty("themeID",
QVariant(QString::fromUtf8("removeIconSmall")));
_remove->setFlat(true);
_up->setMaximumWidth(22);
_up->setProperty("themeID",
QVariant(QString::fromUtf8("upArrowIconSmall")));
_up->setFlat(true);
_down->setMaximumWidth(22);
_down->setProperty("themeID",
QVariant(QString::fromUtf8("downArrowIconSmall")));
_down->setFlat(true);
QWidget::connect(_add, SIGNAL(clicked()), this, SLOT(Add()));
QWidget::connect(_remove, SIGNAL(clicked()), this, SLOT(Remove()));
QWidget::connect(_up, SIGNAL(clicked()), this, SLOT(Up()));
QWidget::connect(_down, SIGNAL(clicked()), this, SLOT(Down()));
QWidget::connect(_list, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
this, SLOT(MacroItemClicked(QListWidgetItem *)));
QWidget::connect(window(), QWidget::connect(window(),
SIGNAL(MacroRenamed(const QString &, const QString &)), SIGNAL(MacroRenamed(const QString &, const QString &)),
this, this,
SLOT(MacroRename(const QString &, const QString &))); SLOT(MacroRename(const QString &, const QString &)));
QWidget::connect(window(), SIGNAL(MacroRemoved(const QString &)), this, QWidget::connect(window(), SIGNAL(MacroRemoved(const QString &)), this,
SLOT(MacroRemove(const QString &))); SLOT(MacroRemove(const QString &)));
UpdateListSize();
_controlsLayout->addWidget(_add);
_controlsLayout->addWidget(_remove);
if (reorder) {
QFrame *line = new QFrame();
line->setFrameShape(QFrame::VLine);
line->setFrameShadow(QFrame::Sunken);
_controlsLayout->addWidget(line);
}
_controlsLayout->addWidget(_up);
_controlsLayout->addWidget(_down);
_controlsLayout->addStretch();
auto mainLayout = new QVBoxLayout;
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->addWidget(_list);
mainLayout->addLayout(_controlsLayout);
setLayout(mainLayout);
_up->setVisible(reorder);
_down->setVisible(reorder);
SetMacroListSize();
} }
void MacroList::SetContent(const std::vector<MacroRef> &macros) void MacroList::SetContent(const std::vector<MacroRef> &macros)
@@ -89,12 +37,15 @@ void MacroList::SetContent(const std::vector<MacroRef> &macros)
new QListWidgetItem(listEntryName, _list); new QListWidgetItem(listEntryName, _list);
item->setData(Qt::UserRole, listEntryName); item->setData(Qt::UserRole, listEntryName);
} }
SetMacroListSize(); UpdateListSize();
} }
void MacroList::AddControl(QWidget *widget) QAction *MacroList::AddControl(QWidget *widget, bool addSeperator)
{ {
_controlsLayout->insertWidget(_controlsLayout->count() - 1, widget); if (addSeperator) {
_controls->addSeparator();
}
return _controls->addWidget(widget);
} }
int MacroList::CurrentRow() int MacroList::CurrentRow()
@@ -122,7 +73,7 @@ void MacroList::MacroRemove(const QString &name)
delete _list->item(idx); delete _list->item(idx);
idx = FindEntry(name.toStdString()); idx = FindEntry(name.toStdString());
} }
SetMacroListSize(); UpdateListSize();
} }
void MacroList::Add() void MacroList::Add()
@@ -142,7 +93,7 @@ void MacroList::Add()
auto item = auto item =
new QListWidgetItem(QString::fromStdString(macroName), _list); new QListWidgetItem(QString::fromStdString(macroName), _list);
item->setData(Qt::UserRole, QString::fromStdString(macroName)); item->setData(Qt::UserRole, QString::fromStdString(macroName));
SetMacroListSize(); UpdateListSize();
emit Added(macroName); emit Added(macroName);
} }
@@ -154,7 +105,7 @@ void MacroList::Remove()
return; return;
} }
delete item; delete item;
SetMacroListSize(); UpdateListSize();
emit Removed(idx); emit Removed(idx);
} }
@@ -178,7 +129,7 @@ void MacroList::Down()
} }
} }
void MacroList::MacroItemClicked(QListWidgetItem *item) void MacroList::Clicked(QListWidgetItem *item)
{ {
std::string macroName; std::string macroName;
bool accepted = MacroSelectionDialog::AskForMacro(this, macroName); bool accepted = MacroSelectionDialog::AskForMacro(this, macroName);
@@ -216,10 +167,4 @@ int MacroList::FindEntry(const std::string &macro)
return idx; return idx;
} }
void MacroList::SetMacroListSize()
{
SetHeightToContentHeight(_list);
adjustSize();
}
} // namespace advss } // namespace advss

View File

@@ -1,18 +1,15 @@
#pragma once #pragma once
#include "list-editor.hpp"
#include "macro-ref.hpp" #include "macro-ref.hpp"
#include <QListWidget>
#include <QPushButton>
#include <QHBoxLayout>
namespace advss { namespace advss {
class ADVSS_EXPORT MacroList : public QWidget { class ADVSS_EXPORT MacroList final : public ListEditor {
Q_OBJECT Q_OBJECT
public: public:
MacroList(QWidget *parent, bool allowDuplicates, bool reorder); MacroList(QWidget *parent, bool allowDuplicates, bool reorder);
void SetContent(const std::vector<MacroRef> &); void SetContent(const std::vector<MacroRef> &);
void AddControl(QWidget *); QAction *AddControl(QWidget *, bool addSeperator = true);
int CurrentRow(); int CurrentRow();
private slots: private slots:
@@ -22,7 +19,7 @@ private slots:
void Remove(); void Remove();
void Up(); void Up();
void Down(); void Down();
void MacroItemClicked(QListWidgetItem *); void Clicked(QListWidgetItem *);
signals: signals:
void Added(const std::string &); void Added(const std::string &);
@@ -33,16 +30,8 @@ signals:
private: private:
int FindEntry(const std::string &macro); int FindEntry(const std::string &macro);
void SetMacroListSize();
QListWidget *_list;
QPushButton *_add;
QPushButton *_remove;
QPushButton *_up;
QPushButton *_down;
QHBoxLayout *_controlsLayout;
const bool _allowDuplicates; const bool _allowDuplicates;
const bool _reorder;
}; };
} // namespace advss } // namespace advss

View File

@@ -0,0 +1,104 @@
#include "advanced-scene-switcher.hpp"
#include "macro.hpp"
#include <QShortcut>
namespace advss {
struct MacroSegmentCopyInfo {
enum class Type { NONE, CONDITION, ACTION, ELSE };
Type type = Type::NONE;
std::shared_ptr<MacroSegment> segment;
};
static MacroSegmentCopyInfo copyInfo;
void AdvSceneSwitcher::CopyMacroSegment()
{
copyInfo.segment.reset();
copyInfo.type = MacroSegmentCopyInfo::Type::NONE;
if (currentConditionIdx == -1 && currentActionIdx == -1 &&
currentElseActionIdx == -1) {
return;
}
auto macro = GetSelectedMacro();
if (!macro) {
return;
}
if (currentConditionIdx != -1) {
copyInfo.type = MacroSegmentCopyInfo::Type::CONDITION;
copyInfo.segment = macro->Conditions().at(currentConditionIdx);
} else if (currentActionIdx != -1) {
copyInfo.type = MacroSegmentCopyInfo::Type::ACTION;
copyInfo.segment = macro->Actions().at(currentActionIdx);
} else if (currentElseActionIdx != -1) {
copyInfo.type = MacroSegmentCopyInfo::Type::ELSE;
copyInfo.segment =
macro->ElseActions().at(currentElseActionIdx);
} else {
assert(false);
}
}
void AdvSceneSwitcher::PasteMacroSegment()
{
if (copyInfo.type == MacroSegmentCopyInfo::Type::NONE) {
return;
}
auto macro = GetSelectedMacro();
if (!macro || !copyInfo.segment) {
return;
}
OBSDataAutoRelease data = obs_data_create();
copyInfo.segment->Save(data);
switch (copyInfo.type) {
case MacroSegmentCopyInfo::Type::CONDITION: {
const auto condition = std::static_pointer_cast<MacroCondition>(
copyInfo.segment);
auto logic = condition->GetLogicType();
if (logic > LogicType::ROOT_LAST &&
macro->Conditions().empty()) {
logic = LogicType::ROOT_NONE;
}
if (logic < LogicType::ROOT_LAST &&
!macro->Conditions().empty()) {
logic = LogicType::OR;
}
AddMacroCondition(macro.get(), macro->Conditions().size(),
copyInfo.segment->GetId(), data.Get(), logic);
break;
}
case MacroSegmentCopyInfo::Type::ACTION:
AddMacroAction(macro.get(), macro->Actions().size(),
copyInfo.segment->GetId(), data.Get());
break;
case MacroSegmentCopyInfo::Type::ELSE:
AddMacroElseAction(macro.get(), macro->ElseActions().size(),
copyInfo.segment->GetId(), data.Get());
break;
default:
break;
}
}
bool MacroSegmentIsInClipboard()
{
return copyInfo.type != MacroSegmentCopyInfo::Type::NONE;
}
void SetupSegmentCopyPasteShortcutHandlers(AdvSceneSwitcher *window)
{
auto copyShortcut = new QShortcut(QKeySequence("Ctrl+C"), window);
QWidget::connect(copyShortcut, &QShortcut::activated, window,
&AdvSceneSwitcher::CopyMacroSegment);
auto pasteShortcut = new QShortcut(QKeySequence("Ctrl+V"), window);
QWidget::connect(pasteShortcut, &QShortcut::activated, window,
&AdvSceneSwitcher::PasteMacroSegment);
}
} // namespace advss

View File

@@ -0,0 +1,8 @@
namespace advss {
class AdvSceneSwitcher;
bool MacroSegmentIsInClipboard();
void SetupSegmentCopyPasteShortcutHandlers(AdvSceneSwitcher *window);
} // namespace advss

View File

@@ -130,7 +130,7 @@ void MacroSegmentList::Highlight(int idx, QColor color)
if (!widget) { if (!widget) {
return; return;
} }
PulseWidget(widget, color, QColor(0, 0, 0, 0), true); HighlightWidget(widget, color, QColor(0, 0, 0, 0), true);
} }
void MacroSegmentList::SetCollapsed(bool collapse) void MacroSegmentList::SetCollapsed(bool collapse)
@@ -176,7 +176,8 @@ bool MacroSegmentList::eventFilter(QObject *object, QEvent *event)
void MacroSegmentList::mousePressEvent(QMouseEvent *event) void MacroSegmentList::mousePressEvent(QMouseEvent *event)
{ {
if (event->button() == Qt::LeftButton) { if (event->button() == Qt::LeftButton ||
event->button() == Qt::RightButton) {
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
_dragPosition = GetDragIndex(event->globalPos()); _dragPosition = GetDragIndex(event->globalPos());
#else #else

View File

@@ -175,7 +175,7 @@ void MacroSegmentSelection::MarkSelectedSegment()
index - 1, QColor(Qt::lightGray)); index - 1, QColor(Qt::lightGray));
} }
PulseWidget(this, QColor(Qt::lightGray), QColor(0, 0, 0, 0), true); HighlightWidget(this, QColor(Qt::lightGray), QColor(0, 0, 0, 0), true);
} }
} // namespace advss } // namespace advss

View File

@@ -59,12 +59,12 @@ std::string MacroSegment::GetShortDesc() const
return ""; return "";
} }
void MacroSegment::SetHighlight() void MacroSegment::EnableHighlight()
{ {
_highlight = true; _highlight = true;
} }
bool MacroSegment::Highlight() bool MacroSegment::GetHighlightAndReset()
{ {
if (_highlight) { if (_highlight) {
_highlight = false; _highlight = false;
@@ -194,7 +194,7 @@ void DecrementVariableRef(MacroSegment *segment)
segment->_variableRefs--; segment->_variableRefs--;
} }
MacroSegmentEdit::MacroSegmentEdit(bool highlight, QWidget *parent) MacroSegmentEdit::MacroSegmentEdit(QWidget *parent)
: QWidget(parent), : QWidget(parent),
_section(new Section(300)), _section(new Section(300)),
_headerInfo(new QLabel()), _headerInfo(new QLabel()),
@@ -203,8 +203,7 @@ MacroSegmentEdit::MacroSegmentEdit(bool highlight, QWidget *parent)
_noBorderframe(new QFrame), _noBorderframe(new QFrame),
_borderFrame(new QFrame), _borderFrame(new QFrame),
_dropLineAbove(new QFrame), _dropLineAbove(new QFrame),
_dropLineBelow(new QFrame), _dropLineBelow(new QFrame)
_showHighlight(highlight)
{ {
_dropLineAbove->setLineWidth(3); _dropLineAbove->setLineWidth(3);
_dropLineAbove->setFixedHeight(11); _dropLineAbove->setFixedHeight(11);
@@ -282,10 +281,6 @@ MacroSegmentEdit::MacroSegmentEdit(bool highlight, QWidget *parent)
// Enable dragging while clicking on the header text // Enable dragging while clicking on the header text
_headerInfo->installEventFilter(this); _headerInfo->installEventFilter(this);
_timer.setInterval(1500);
connect(&_timer, SIGNAL(timeout()), this, SLOT(Highlight()));
_timer.start();
} }
bool MacroSegmentEdit::eventFilter(QObject *obj, QEvent *ev) bool MacroSegmentEdit::eventFilter(QObject *obj, QEvent *ev)
@@ -330,22 +325,6 @@ void MacroSegmentEdit::Collapsed(bool collapsed)
} }
} }
void MacroSegmentEdit::Highlight()
{
if (!Data()) {
return;
}
if (_showHighlight && Data()->Highlight()) {
PulseWidget(this, Qt::green, QColor(0, 0, 0, 0), true);
}
}
void MacroSegmentEdit::EnableHighlight(bool value)
{
_showHighlight = value;
}
void MacroSegmentEdit::SetFocusPolicyOfWidgets() void MacroSegmentEdit::SetFocusPolicyOfWidgets()
{ {
QList<QWidget *> widgets = this->findChildren<QWidget *>(); QList<QWidget *> widgets = this->findChildren<QWidget *>();

View File

@@ -37,8 +37,8 @@ public:
virtual bool PostLoad(); virtual bool PostLoad();
virtual std::string GetShortDesc() const; virtual std::string GetShortDesc() const;
virtual std::string GetId() const = 0; virtual std::string GetId() const = 0;
void SetHighlight(); void EnableHighlight();
bool Highlight(); bool GetHighlightAndReset();
virtual std::string GetVariableValue() const; virtual std::string GetVariableValue() const;
protected: protected:
@@ -87,7 +87,7 @@ class MacroSegmentEdit : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
MacroSegmentEdit(bool highlight, QWidget *parent = nullptr); MacroSegmentEdit(QWidget *parent = nullptr);
// Use this function to avoid accidental edits when scrolling through // Use this function to avoid accidental edits when scrolling through
// list of actions and conditions // list of actions and conditions
void SetFocusPolicyOfWidgets(); void SetFocusPolicyOfWidgets();
@@ -100,8 +100,6 @@ public slots:
protected slots: protected slots:
void Collapsed(bool); void Collapsed(bool);
void Highlight();
void EnableHighlight(bool);
signals: signals:
void MacroAdded(const QString &name); void MacroAdded(const QString &name);
void MacroRemoved(const QString &name); void MacroRemoved(const QString &name);
@@ -143,9 +141,6 @@ private:
QFrame *_dropLineAbove; QFrame *_dropLineAbove;
QFrame *_dropLineBelow; QFrame *_dropLineBelow;
bool _showHighlight;
QTimer _timer;
friend class MacroSegmentList; friend class MacroSegmentList;
}; };

View File

@@ -19,11 +19,13 @@ MacroSelection::MacroSelection(QWidget *parent)
addItem(QString::fromStdString(m->Name())); addItem(QString::fromStdString(m->Name()));
} }
QWidget::connect(parent, SIGNAL(MacroAdded(const QString &)), this, QWidget::connect(GetSettingsWindow(),
SIGNAL(MacroAdded(const QString &)), this,
SLOT(MacroAdd(const QString &))); SLOT(MacroAdd(const QString &)));
QWidget::connect(parent, SIGNAL(MacroRemoved(const QString &)), this, QWidget::connect(GetSettingsWindow(),
SIGNAL(MacroRemoved(const QString &)), this,
SLOT(MacroRemove(const QString &))); SLOT(MacroRemove(const QString &)));
QWidget::connect(parent, QWidget::connect(GetSettingsWindow(),
SIGNAL(MacroRenamed(const QString &, const QString &)), SIGNAL(MacroRenamed(const QString &, const QString &)),
this, this,
SLOT(MacroRename(const QString &, const QString &))); SLOT(MacroRename(const QString &, const QString &)));

View File

@@ -1,4 +1,4 @@
#include "macro-properties.hpp" #include "macro-settings.hpp"
#include "layout-helpers.hpp" #include "layout-helpers.hpp"
#include "obs-module-helper.hpp" #include "obs-module-helper.hpp"
#include "macro.hpp" #include "macro.hpp"
@@ -10,9 +10,9 @@
namespace advss { namespace advss {
static MacroProperties macroProperties; static GlobalMacroSettings macroSettings;
void MacroProperties::Save(obs_data_t *obj) const void GlobalMacroSettings::Save(obs_data_t *obj) const
{ {
auto data = obs_data_create(); auto data = obs_data_create();
obs_data_set_bool(data, "highlightExecuted", _highlightExecuted); obs_data_set_bool(data, "highlightExecuted", _highlightExecuted);
@@ -20,13 +20,16 @@ void MacroProperties::Save(obs_data_t *obj) const
obs_data_set_bool(data, "highlightActions", _highlightActions); obs_data_set_bool(data, "highlightActions", _highlightActions);
obs_data_set_bool(data, "newMacroRegisterHotkey", obs_data_set_bool(data, "newMacroRegisterHotkey",
_newMacroRegisterHotkeys); _newMacroRegisterHotkeys);
obs_data_set_obj(obj, "macroProperties", data); obs_data_set_obj(obj, "macroSettings", data);
obs_data_release(data); obs_data_release(data);
} }
void MacroProperties::Load(obs_data_t *obj) void GlobalMacroSettings::Load(obs_data_t *obj)
{ {
auto data = obs_data_get_obj(obj, "macroProperties"); auto data = obs_data_get_obj(
obj, obs_data_has_user_value(obj, "macroProperties")
? "macroProperties"
: "macroSettings");
obs_data_set_default_bool(data, "highlightExecuted", true); obs_data_set_default_bool(data, "highlightExecuted", true);
obs_data_set_default_bool(data, "highlightConditions", true); obs_data_set_default_bool(data, "highlightConditions", true);
obs_data_set_default_bool(data, "highlightActions", true); obs_data_set_default_bool(data, "highlightActions", true);
@@ -38,9 +41,9 @@ void MacroProperties::Load(obs_data_t *obj)
obs_data_release(data); obs_data_release(data);
} }
MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent, MacroSettingsDialog::MacroSettingsDialog(QWidget *parent,
const MacroProperties &prop, const GlobalMacroSettings &settings,
Macro *macro) Macro *macro)
: QDialog(parent), : QDialog(parent),
_executed(new QCheckBox(obs_module_text( _executed(new QCheckBox(obs_module_text(
"AdvSceneSwitcher.macroTab.highlightExecutedMacros"))), "AdvSceneSwitcher.macroTab.highlightExecutedMacros"))),
@@ -56,6 +59,7 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
"AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup"))), "AdvSceneSwitcher.macroTab.currentSkipExecutionOnStartup"))),
_currentStopActionsIfNotDone(new QCheckBox(obs_module_text( _currentStopActionsIfNotDone(new QCheckBox(obs_module_text(
"AdvSceneSwitcher.macroTab.currentStopActionsIfNotDone"))), "AdvSceneSwitcher.macroTab.currentStopActionsIfNotDone"))),
_currentInputs(new MacroInputSelection()),
_currentMacroRegisterDock(new QCheckBox(obs_module_text( _currentMacroRegisterDock(new QCheckBox(obs_module_text(
"AdvSceneSwitcher.macroTab.currentRegisterDock"))), "AdvSceneSwitcher.macroTab.currentRegisterDock"))),
_currentMacroDockAddRunButton(new QCheckBox(obs_module_text( _currentMacroDockAddRunButton(new QCheckBox(obs_module_text(
@@ -101,6 +105,16 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
generalLayout->addWidget(_currentStopActionsIfNotDone); generalLayout->addWidget(_currentStopActionsIfNotDone);
generalOptions->setLayout(generalLayout); generalOptions->setLayout(generalLayout);
auto inputOptions = new QGroupBox(
obs_module_text("AdvSceneSwitcher.macroTab.inputSettings"));
auto description = new QLabel(obs_module_text(
"AdvSceneSwitcher.macroTab.inputSettings.description"));
description->setWordWrap(true);
auto inputLayout = new QVBoxLayout();
inputLayout->addWidget(description);
inputLayout->addWidget(_currentInputs);
inputOptions->setLayout(inputLayout);
int row = 0; int row = 0;
_dockLayout->addWidget(_currentMacroRegisterDock, row, 1, 1, 2); _dockLayout->addWidget(_currentMacroRegisterDock, row, 1, 1, 2);
row++; row++;
@@ -157,13 +171,13 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
connect(buttonbox, &QDialogButtonBox::rejected, this, &QDialog::reject); connect(buttonbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
connect(_currentMacroRegisterDock, &QCheckBox::stateChanged, this, connect(_currentMacroRegisterDock, &QCheckBox::stateChanged, this,
&MacroPropertiesDialog::DockEnableChanged); &MacroSettingsDialog::DockEnableChanged);
connect(_currentMacroDockAddRunButton, &QCheckBox::stateChanged, this, connect(_currentMacroDockAddRunButton, &QCheckBox::stateChanged, this,
&MacroPropertiesDialog::RunButtonEnableChanged); &MacroSettingsDialog::RunButtonEnableChanged);
connect(_currentMacroDockAddPauseButton, &QCheckBox::stateChanged, this, connect(_currentMacroDockAddPauseButton, &QCheckBox::stateChanged, this,
&MacroPropertiesDialog::PauseButtonEnableChanged); &MacroSettingsDialog::PauseButtonEnableChanged);
connect(_currentMacroDockAddStatusLabel, &QCheckBox::stateChanged, this, connect(_currentMacroDockAddStatusLabel, &QCheckBox::stateChanged, this,
&MacroPropertiesDialog::StatusLabelEnableChanged); &MacroSettingsDialog::StatusLabelEnableChanged);
auto scrollArea = new QScrollArea(this); auto scrollArea = new QScrollArea(this);
scrollArea->setWidgetResizable(true); scrollArea->setWidgetResizable(true);
@@ -174,6 +188,7 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
layout->addWidget(highlightOptions); layout->addWidget(highlightOptions);
layout->addWidget(hotkeyOptions); layout->addWidget(hotkeyOptions);
layout->addWidget(generalOptions); layout->addWidget(generalOptions);
layout->addWidget(inputOptions);
layout->addWidget(_dockOptions); layout->addWidget(_dockOptions);
layout->setContentsMargins(0, 0, 0, 0); layout->setContentsMargins(0, 0, 0, 0);
scrollArea->setWidget(contentWidget); scrollArea->setWidget(contentWidget);
@@ -183,14 +198,15 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
dialogLayout->addWidget(buttonbox); dialogLayout->addWidget(buttonbox);
setLayout(dialogLayout); setLayout(dialogLayout);
_executed->setChecked(prop._highlightExecuted); _executed->setChecked(settings._highlightExecuted);
_conditions->setChecked(prop._highlightConditions); _conditions->setChecked(settings._highlightConditions);
_actions->setChecked(prop._highlightActions); _actions->setChecked(settings._highlightActions);
_newMacroRegisterHotkeys->setChecked(prop._newMacroRegisterHotkeys); _newMacroRegisterHotkeys->setChecked(settings._newMacroRegisterHotkeys);
if (!macro || macro->IsGroup()) { if (!macro || macro->IsGroup()) {
hotkeyOptions->hide(); hotkeyOptions->hide();
generalOptions->hide(); generalOptions->hide();
inputOptions->hide();
_dockOptions->hide(); _dockOptions->hide();
return; return;
} }
@@ -198,6 +214,7 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
_currentMacroRegisterHotkeys->setChecked(macro->PauseHotkeysEnabled()); _currentMacroRegisterHotkeys->setChecked(macro->PauseHotkeysEnabled());
_currentSkipOnStartup->setChecked(macro->SkipExecOnStart()); _currentSkipOnStartup->setChecked(macro->SkipExecOnStart());
_currentStopActionsIfNotDone->setChecked(macro->StopActionsIfNotDone()); _currentStopActionsIfNotDone->setChecked(macro->StopActionsIfNotDone());
_currentInputs->SetInputs(macro->GetInputVariables());
const bool dockEnabled = macro->DockEnabled(); const bool dockEnabled = macro->DockEnabled();
_currentMacroRegisterDock->setChecked(dockEnabled); _currentMacroRegisterDock->setChecked(dockEnabled);
_currentMacroDockAddRunButton->setChecked(macro->DockHasRunButton()); _currentMacroDockAddRunButton->setChecked(macro->DockHasRunButton());
@@ -245,7 +262,7 @@ MacroPropertiesDialog::MacroPropertiesDialog(QWidget *parent,
20); 20);
} }
void MacroPropertiesDialog::DockEnableChanged(int enabled) void MacroSettingsDialog::DockEnableChanged(int enabled)
{ {
_currentMacroDockAddRunButton->setVisible(enabled); _currentMacroDockAddRunButton->setVisible(enabled);
_currentMacroDockAddPauseButton->setVisible(enabled); _currentMacroDockAddPauseButton->setVisible(enabled);
@@ -270,37 +287,37 @@ void MacroPropertiesDialog::DockEnableChanged(int enabled)
Resize(); Resize();
} }
void MacroPropertiesDialog::RunButtonEnableChanged(int enabled) void MacroSettingsDialog::RunButtonEnableChanged(int enabled)
{ {
SetGridLayoutRowVisible(_dockLayout, _runButtonTextRow, enabled); SetGridLayoutRowVisible(_dockLayout, _runButtonTextRow, enabled);
Resize(); Resize();
} }
void MacroPropertiesDialog::PauseButtonEnableChanged(int enabled) void MacroSettingsDialog::PauseButtonEnableChanged(int enabled)
{ {
SetGridLayoutRowVisible(_dockLayout, _pauseButtonTextRow, enabled); SetGridLayoutRowVisible(_dockLayout, _pauseButtonTextRow, enabled);
SetGridLayoutRowVisible(_dockLayout, _unpauseButtonTextRow, enabled); SetGridLayoutRowVisible(_dockLayout, _unpauseButtonTextRow, enabled);
Resize(); Resize();
} }
void MacroPropertiesDialog::StatusLabelEnableChanged(int enabled) void MacroSettingsDialog::StatusLabelEnableChanged(int enabled)
{ {
SetGridLayoutRowVisible(_dockLayout, _conditionsTrueTextRow, enabled); SetGridLayoutRowVisible(_dockLayout, _conditionsTrueTextRow, enabled);
SetGridLayoutRowVisible(_dockLayout, _conditionsFalseTextRow, enabled); SetGridLayoutRowVisible(_dockLayout, _conditionsFalseTextRow, enabled);
Resize(); Resize();
} }
void MacroPropertiesDialog::Resize() void MacroSettingsDialog::Resize()
{ {
_dockOptions->adjustSize(); _dockOptions->adjustSize();
_dockOptions->updateGeometry(); _dockOptions->updateGeometry();
} }
bool MacroPropertiesDialog::AskForSettings(QWidget *parent, bool MacroSettingsDialog::AskForSettings(QWidget *parent,
MacroProperties &userInput, GlobalMacroSettings &userInput,
Macro *macro) Macro *macro)
{ {
MacroPropertiesDialog dialog(parent, userInput, macro); MacroSettingsDialog dialog(parent, userInput, macro);
dialog.setWindowTitle(obs_module_text("AdvSceneSwitcher.windowTitle")); dialog.setWindowTitle(obs_module_text("AdvSceneSwitcher.windowTitle"));
if (dialog.exec() != DialogCode::Accepted) { if (dialog.exec() != DialogCode::Accepted) {
return false; return false;
@@ -337,23 +354,23 @@ bool MacroPropertiesDialog::AskForSettings(QWidget *parent,
dialog._conditionsTrueStatusText->text().toStdString()); dialog._conditionsTrueStatusText->text().toStdString());
macro->SetConditionsFalseStatusText( macro->SetConditionsFalseStatusText(
dialog._conditionsFalseStatusText->text().toStdString()); dialog._conditionsFalseStatusText->text().toStdString());
macro->SetInputVariables(dialog._currentInputs->GetInputs());
return true; return true;
} }
MacroProperties &GetGlobalMacroProperties() GlobalMacroSettings &GetGlobalMacroSettings()
{ {
return macroProperties; return macroSettings;
} }
void SaveGlobalMacroProperties(obs_data_t *obj) void SaveGlobalMacroSettings(obs_data_t *obj)
{ {
macroProperties.Save(obj); macroSettings.Save(obj);
} }
void LoadGlobalMacroProperties(obs_data_t *obj) void LoadGlobalMacroSettings(obs_data_t *obj)
{ {
macroProperties.Load(obj); macroSettings.Load(obj);
} }
} // namespace advss } // namespace advss

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "variable-line-edit.hpp" #include "variable-line-edit.hpp"
#include "macro-input.hpp"
#include <QWidget> #include <QWidget>
#include <QDialog> #include <QDialog>
@@ -13,7 +14,7 @@ namespace advss {
class Macro; class Macro;
class MacroProperties { class GlobalMacroSettings {
public: public:
void Save(obs_data_t *obj) const; void Save(obs_data_t *obj) const;
void Load(obs_data_t *obj); void Load(obs_data_t *obj);
@@ -25,13 +26,14 @@ public:
}; };
// Dialog for configuring global and individual macro specific settings // Dialog for configuring global and individual macro specific settings
class MacroPropertiesDialog : public QDialog { class MacroSettingsDialog : public QDialog {
Q_OBJECT Q_OBJECT
public: public:
MacroPropertiesDialog(QWidget *parent, const MacroProperties &, MacroSettingsDialog(QWidget *parent, const GlobalMacroSettings &,
Macro *macro); Macro *macro);
static bool AskForSettings(QWidget *parent, MacroProperties &userInput, static bool AskForSettings(QWidget *parent,
GlobalMacroSettings &userInput,
Macro *macro); Macro *macro);
private slots: private slots:
void DockEnableChanged(int); void DockEnableChanged(int);
@@ -50,6 +52,7 @@ private:
QCheckBox *_currentMacroRegisterHotkeys; QCheckBox *_currentMacroRegisterHotkeys;
QCheckBox *_currentSkipOnStartup; QCheckBox *_currentSkipOnStartup;
QCheckBox *_currentStopActionsIfNotDone; QCheckBox *_currentStopActionsIfNotDone;
MacroInputSelection *_currentInputs;
QCheckBox *_currentMacroRegisterDock; QCheckBox *_currentMacroRegisterDock;
QCheckBox *_currentMacroDockAddRunButton; QCheckBox *_currentMacroDockAddRunButton;
QCheckBox *_currentMacroDockAddPauseButton; QCheckBox *_currentMacroDockAddPauseButton;
@@ -70,8 +73,8 @@ private:
int _conditionsFalseTextRow = -1; int _conditionsFalseTextRow = -1;
}; };
MacroProperties &GetGlobalMacroProperties(); GlobalMacroSettings &GetGlobalMacroSettings();
void SaveGlobalMacroProperties(obs_data_t *obj); void SaveGlobalMacroSettings(obs_data_t *obj);
void LoadGlobalMacroProperties(obs_data_t *obj); void LoadGlobalMacroSettings(obs_data_t *obj);
} // namespace advss } // namespace advss

View File

@@ -1,9 +1,11 @@
#include "advanced-scene-switcher.hpp" #include "advanced-scene-switcher.hpp"
#include "action-queue.hpp" #include "action-queue.hpp"
#include "cursor-shape-changer.hpp"
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
#include "macro-condition-edit.hpp" #include "macro-condition-edit.hpp"
#include "macro-export-import-dialog.hpp" #include "macro-export-import-dialog.hpp"
#include "macro-properties.hpp" #include "macro-settings.hpp"
#include "macro-segment-copy-paste.hpp"
#include "macro-tree.hpp" #include "macro-tree.hpp"
#include "macro.hpp" #include "macro.hpp"
#include "math-helpers.hpp" #include "math-helpers.hpp"
@@ -22,7 +24,7 @@
namespace advss { namespace advss {
static QMetaObject::Connection addPulse; static QObject *addPulse = nullptr;
static QTimer onChangeHighlightTimer; static QTimer onChangeHighlightTimer;
static bool macroNameExists(const std::string &name) static bool macroNameExists(const std::string &name)
@@ -85,7 +87,7 @@ bool AdvSceneSwitcher::AddNewMacro(std::shared_ptr<Macro> &res,
} }
res = std::make_shared<Macro>( res = std::make_shared<Macro>(
name, GetGlobalMacroProperties()._newMacroRegisterHotkeys); name, GetGlobalMacroSettings()._newMacroRegisterHotkeys);
return true; return true;
} }
@@ -98,7 +100,8 @@ void AdvSceneSwitcher::on_macroAdd_clicked()
} }
ui->macros->Add(newMacro); ui->macros->Add(newMacro);
ui->macroAdd->disconnect(addPulse); addPulse->deleteLater();
addPulse = nullptr;
emit MacroAdded(QString::fromStdString(name)); emit MacroAdded(QString::fromStdString(name));
} }
@@ -461,7 +464,7 @@ void AdvSceneSwitcher::ImportMacros()
RunPostLoadSteps(); RunPostLoadSteps();
ui->macros->Reset(GetMacros(), ui->macros->Reset(GetMacros(),
GetGlobalMacroProperties()._highlightExecuted); GetGlobalMacroSettings()._highlightExecuted);
} }
void AdvSceneSwitcher::on_macroName_editingFinished() void AdvSceneSwitcher::on_macroName_editingFinished()
@@ -741,8 +744,8 @@ void AdvSceneSwitcher::MacroSelectionChanged()
void AdvSceneSwitcher::HighlightOnChange() void AdvSceneSwitcher::HighlightOnChange()
{ {
if (!GetGlobalMacroProperties()._highlightActions && if (!GetGlobalMacroSettings()._highlightActions &&
!GetGlobalMacroProperties()._highlightExecuted) { !GetGlobalMacroSettings()._highlightExecuted) {
return; return;
} }
@@ -752,38 +755,38 @@ void AdvSceneSwitcher::HighlightOnChange()
} }
if (macro->OnChangePreventedActionsRecently()) { if (macro->OnChangePreventedActionsRecently()) {
PulseWidget(ui->runMacroOnChange, Qt::yellow, Qt::transparent, HighlightWidget(ui->runMacroOnChange, Qt::yellow,
true); Qt::transparent, true);
} }
} }
void AdvSceneSwitcher::on_macroProperties_clicked() void AdvSceneSwitcher::on_macroSettings_clicked()
{ {
MacroProperties prop = GetGlobalMacroProperties(); GlobalMacroSettings prop = GetGlobalMacroSettings();
bool accepted = MacroPropertiesDialog::AskForSettings( bool accepted = MacroSettingsDialog::AskForSettings(
this, prop, GetSelectedMacro().get()); this, prop, GetSelectedMacro().get());
if (!accepted) { if (!accepted) {
return; return;
} }
GetGlobalMacroProperties() = prop; GetGlobalMacroSettings() = prop;
emit HighlightMacrosChanged(prop._highlightExecuted); emit HighlightMacrosChanged(prop._highlightExecuted);
emit HighlightActionsChanged(prop._highlightActions);
emit HighlightConditionsChanged(prop._highlightConditions);
} }
static void moveControlsToSplitter(QSplitter *splitter, int idx, static void moveControlsToSplitter(QSplitter *splitter, int idx,
QLayoutItem *item) QLayoutItem *item)
{ {
static int splitterHandleWidth = 38; static int splitterHandleWidth = 32;
auto handle = splitter->handle(idx); auto handle = splitter->handle(idx);
auto layout = item->layout(); auto layout = item->layout();
layout->setContentsMargins(7, 7, 7, 7); int leftMargin, rightMargin;
layout->getContentsMargins(&leftMargin, nullptr, &rightMargin, nullptr);
layout->setContentsMargins(leftMargin, 0, rightMargin, 0);
handle->setLayout(layout); handle->setLayout(layout);
splitter->setHandleWidth(splitterHandleWidth); splitter->setHandleWidth(splitterHandleWidth);
splitter->setStyleSheet("QSplitter::handle {background: transparent;}"); splitter->setStyleSheet("QSplitter::handle {background: transparent;}");
} }
bool shouldRestoreSplitter(const QList<int> &pos) static bool shouldRestoreSplitter(const QList<int> &pos)
{ {
if (pos.size() == 0) { if (pos.size() == 0) {
return false; return false;
@@ -797,16 +800,77 @@ bool shouldRestoreSplitter(const QList<int> &pos)
return true; return true;
} }
static void runSegmentHighligtChecksHelper(MacroSegmentList *list)
{
MacroSegmentEdit *widget = nullptr;
for (int i = 0; (widget = list->WidgetAt(i)); i++) {
if (widget->Data() && widget->Data()->GetHighlightAndReset()) {
list->Highlight(i);
}
}
}
static void runSegmentHighligtChecks(AdvSceneSwitcher *ss)
{
if (!ss || !HighlightUIElementsEnabled()) {
return;
}
auto macro = ss->GetSelectedMacro();
if (!macro) {
return;
}
const auto &settings = GetGlobalMacroSettings();
if (settings._highlightConditions) {
runSegmentHighligtChecksHelper(ss->ui->conditionsList);
}
if (settings._highlightActions) {
runSegmentHighligtChecksHelper(ss->ui->actionsList);
runSegmentHighligtChecksHelper(ss->ui->elseActionsList);
}
}
static QToolBar *
setupToolBar(const std::initializer_list<std::initializer_list<QWidget *>>
&widgetGroups)
{
auto toolbar = new QToolBar();
toolbar->setIconSize({16, 16});
QAction *lastSeperator = nullptr;
for (const auto &widgetGroup : widgetGroups) {
for (const auto &widget : widgetGroup) {
toolbar->addWidget(widget);
}
lastSeperator = toolbar->addSeparator();
}
if (lastSeperator) {
toolbar->removeAction(lastSeperator);
}
// Prevent "extension" button from showing up
toolbar->setSizePolicy(QSizePolicy::MinimumExpanding,
QSizePolicy::Preferred);
return toolbar;
}
void AdvSceneSwitcher::SetupMacroTab() void AdvSceneSwitcher::SetupMacroTab()
{ {
ui->macroElseActions->installEventFilter(this); ui->macroElseActions->installEventFilter(this);
ui->macros->installEventFilter(this); ui->macros->installEventFilter(this);
if (GetMacros().size() == 0 && !switcher->disableHints) { if (GetMacros().size() == 0 && !switcher->disableHints) {
addPulse = PulseWidget(ui->macroAdd, QColor(Qt::green)); addPulse = HighlightWidget(ui->macroAdd, QColor(Qt::green));
} }
auto macroControls = setupToolBar({{ui->macroAdd, ui->macroRemove},
{ui->macroUp, ui->macroDown}});
ui->macroControlLayout->addWidget(macroControls);
ui->macros->Reset(GetMacros(), ui->macros->Reset(GetMacros(),
GetGlobalMacroProperties()._highlightExecuted); GetGlobalMacroSettings()._highlightExecuted);
connect(ui->macros, SIGNAL(MacroSelectionAboutToChange()), this, connect(ui->macros, SIGNAL(MacroSelectionAboutToChange()), this,
SLOT(MacroSelectionAboutToChange())); SLOT(MacroSelectionAboutToChange()));
connect(ui->macros, SIGNAL(MacroSelectionChanged()), this, connect(ui->macros, SIGNAL(MacroSelectionChanged()), this,
@@ -856,13 +920,7 @@ void AdvSceneSwitcher::SetupMacroTab()
SLOT(HighlightOnChange())); SLOT(HighlightOnChange()));
onChangeHighlightTimer.start(); onChangeHighlightTimer.start();
// Move condition controls into splitter handle layout // Set action and condition toolbars
moveControlsToSplitter(ui->macroActionConditionSplitter, 1,
ui->macroConditionsLayout->takeAt(1));
moveControlsToSplitter(ui->macroElseActionSplitter, 1,
ui->macroActionsLayout->takeAt(1));
// Set action and condition control icons
const std::string pathPrefix = const std::string pathPrefix =
GetDataFilePath("res/images/" + GetThemeTypeName()); GetDataFilePath("res/images/" + GetThemeTypeName());
SetButtonIcon(ui->actionTop, (pathPrefix + "DoubleUp.svg").c_str()); SetButtonIcon(ui->actionTop, (pathPrefix + "DoubleUp.svg").c_str());
@@ -877,6 +935,44 @@ void AdvSceneSwitcher::SetupMacroTab()
SetButtonIcon(ui->toggleElseActions, SetButtonIcon(ui->toggleElseActions,
(pathPrefix + "NotEqual.svg").c_str()); (pathPrefix + "NotEqual.svg").c_str());
auto conditionToolbar =
setupToolBar({{ui->conditionAdd, ui->conditionRemove},
{ui->conditionTop, ui->conditionUp,
ui->conditionDown, ui->conditionBottom}});
auto actionToolbar = setupToolBar({{ui->actionAdd, ui->actionRemove},
{ui->actionTop, ui->actionUp,
ui->actionDown, ui->actionBottom}});
auto elseActionToolbar =
setupToolBar({{ui->elseActionAdd, ui->elseActionRemove},
{ui->elseActionTop, ui->elseActionUp,
ui->elseActionDown, ui->elseActionBottom}});
ui->conditionControlsLayout->addWidget(conditionToolbar);
ui->actionControlsLayout->insertWidget(0, actionToolbar);
ui->elseActionControlsLayout->addWidget(elseActionToolbar);
// Move condition controls into splitter handle layout
moveControlsToSplitter(ui->macroActionConditionSplitter, 1,
ui->macroConditionsLayout->takeAt(1));
moveControlsToSplitter(ui->macroElseActionSplitter, 1,
ui->macroActionsLayout->takeAt(1));
// Override splitter cursor icon when hovering over controls in splitter
SetCursorOnWidgetHover(ui->conditionAdd, Qt::CursorShape::ArrowCursor);
SetCursorOnWidgetHover(ui->conditionRemove,
Qt::CursorShape::ArrowCursor);
SetCursorOnWidgetHover(ui->conditionTop, Qt::CursorShape::ArrowCursor);
SetCursorOnWidgetHover(ui->conditionUp, Qt::CursorShape::ArrowCursor);
SetCursorOnWidgetHover(ui->conditionDown, Qt::CursorShape::ArrowCursor);
SetCursorOnWidgetHover(ui->conditionBottom,
Qt::CursorShape::ArrowCursor);
SetCursorOnWidgetHover(ui->actionAdd, Qt::CursorShape::ArrowCursor);
SetCursorOnWidgetHover(ui->actionRemove, Qt::CursorShape::ArrowCursor);
SetCursorOnWidgetHover(ui->actionTop, Qt::CursorShape::ArrowCursor);
SetCursorOnWidgetHover(ui->actionUp, Qt::CursorShape::ArrowCursor);
SetCursorOnWidgetHover(ui->actionDown, Qt::CursorShape::ArrowCursor);
SetCursorOnWidgetHover(ui->actionBottom, Qt::CursorShape::ArrowCursor);
// Reserve more space for macro edit area than for the macro list // Reserve more space for macro edit area than for the macro list
ui->macroListMacroEditSplitter->setStretchFactor(0, 1); ui->macroListMacroEditSplitter->setStretchFactor(0, 1);
ui->macroListMacroEditSplitter->setStretchFactor(1, 4); ui->macroListMacroEditSplitter->setStretchFactor(1, 4);
@@ -891,6 +987,14 @@ void AdvSceneSwitcher::SetupMacroTab()
switcher->macroListMacroEditSplitterPosition); switcher->macroListMacroEditSplitterPosition);
} }
} }
SetupSegmentCopyPasteShortcutHandlers(this);
// Macro segment highlight
auto timer = new QTimer(this);
connect(timer, &QTimer::timeout,
[this]() { runSegmentHighligtChecks(this); });
timer->start(1500);
} }
void AdvSceneSwitcher::ShowMacroContextMenu(const QPoint &pos) void AdvSceneSwitcher::ShowMacroContextMenu(const QPoint &pos)
@@ -978,16 +1082,19 @@ static void setupConextMenu(AdvSceneSwitcher *ss, const QPoint &pos,
MacroSegmentList *list) MacroSegmentList *list)
{ {
QMenu menu; QMenu menu;
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.expandAll"),
ss, [ss, expand]() { expand(ss); });
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.collapseAll"),
ss, [ss, collapse]() { collapse(ss); });
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.maximize"),
ss, [ss, maximize]() { maximize(ss); });
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.minimize"),
ss, [ss, minimize]() { minimize(ss); });
auto segmentEdit = list->WidgetAt(pos); auto segmentEdit = list->WidgetAt(pos);
auto copy = menu.addAction(
obs_module_text("AdvSceneSwitcher.macroTab.segment.copy"), ss,
[ss]() { ss->CopyMacroSegment(); });
copy->setEnabled(!!segmentEdit);
auto paste = menu.addAction(
obs_module_text("AdvSceneSwitcher.macroTab.segment.paste"), ss,
[ss]() { ss->PasteMacroSegment(); });
paste->setEnabled(MacroSegmentIsInClipboard());
menu.addSeparator();
if (segmentEdit) { if (segmentEdit) {
auto customLabel = menu.addAction(obs_module_text( auto customLabel = menu.addAction(obs_module_text(
"AdvSceneSwitcher.macroTab.segment.useCustomLabel")); "AdvSceneSwitcher.macroTab.segment.useCustomLabel"));
@@ -999,6 +1106,21 @@ static void setupConextMenu(AdvSceneSwitcher *ss, const QPoint &pos,
std::bind(handleCustomLabelChange, segmentEdit, std::bind(handleCustomLabelChange, segmentEdit,
customLabel)); customLabel));
} }
menu.addSeparator();
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.expandAll"),
ss, [ss, expand]() { expand(ss); });
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.collapseAll"),
ss, [ss, collapse]() { collapse(ss); });
menu.addSeparator();
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.maximize"),
ss, [ss, maximize]() { maximize(ss); });
menu.addAction(obs_module_text("AdvSceneSwitcher.macroTab.minimize"),
ss, [ss, minimize]() { minimize(ss); });
menu.exec(list->mapToGlobal(pos)); menu.exec(list->mapToGlobal(pos));
} }
@@ -1051,7 +1173,8 @@ void AdvSceneSwitcher::CopyMacro()
Macro::PrepareMoveToGroup(macro->Parent(), newMacro); Macro::PrepareMoveToGroup(macro->Parent(), newMacro);
ui->macros->Add(newMacro, macro); ui->macros->Add(newMacro, macro);
ui->macroAdd->disconnect(addPulse); addPulse->deleteLater();
addPulse = nullptr;
emit MacroAdded(QString::fromStdString(name)); emit MacroAdded(QString::fromStdString(name));
} }
@@ -1343,58 +1466,47 @@ static void fade(QWidget *widget, bool fadeOut)
animation->start(QPropertyAnimation::DeleteWhenStopped); animation->start(QPropertyAnimation::DeleteWhenStopped);
} }
void AdvSceneSwitcher::FadeOutActionControls() static void fadeWidgets(const std::vector<QWidget *> &widgets, bool fadeOut)
{ {
fade(ui->actionAdd, true); for (const auto &widget : widgets) {
fade(ui->actionRemove, true); fade(widget, fadeOut);
fade(ui->actionTop, true); }
fade(ui->actionUp, true);
fade(ui->actionDown, true);
fade(ui->actionBottom, true);
}
void AdvSceneSwitcher::FadeOutConditionControls()
{
fade(ui->conditionAdd, true);
fade(ui->conditionRemove, true);
fade(ui->conditionTop, true);
fade(ui->conditionUp, true);
fade(ui->conditionDown, true);
fade(ui->conditionBottom, true);
}
void AdvSceneSwitcher::ResetOpacityActionControls()
{
fade(ui->actionAdd, false);
fade(ui->actionRemove, false);
fade(ui->actionTop, false);
fade(ui->actionUp, false);
fade(ui->actionDown, false);
fade(ui->actionBottom, false);
}
void AdvSceneSwitcher::ResetOpacityConditionControls()
{
fade(ui->conditionAdd, false);
fade(ui->conditionRemove, false);
fade(ui->conditionTop, false);
fade(ui->conditionUp, false);
fade(ui->conditionDown, false);
fade(ui->conditionBottom, false);
} }
void AdvSceneSwitcher::HighlightControls() void AdvSceneSwitcher::HighlightControls()
{ {
if ((currentActionIdx == -1 && currentConditionIdx == -1) || const std::vector<QWidget *> conditionControls{
(currentActionIdx != -1 && currentConditionIdx != -1)) { ui->conditionAdd, ui->conditionRemove, ui->conditionTop,
ResetOpacityActionControls(); ui->conditionUp, ui->conditionDown, ui->conditionBottom,
ResetOpacityConditionControls(); };
const std::vector<QWidget *> actionControls{
ui->actionAdd, ui->actionRemove, ui->actionTop,
ui->actionUp, ui->actionDown, ui->actionBottom,
};
const std::vector<QWidget *> elseActionControls{
ui->elseActionAdd, ui->elseActionRemove, ui->elseActionTop,
ui->elseActionUp, ui->elseActionDown, ui->elseActionBottom,
};
if ((currentActionIdx == -1 && currentConditionIdx == -1 &&
currentElseActionIdx == -1)) {
fadeWidgets(conditionControls, false);
fadeWidgets(actionControls, false);
fadeWidgets(elseActionControls, false);
} else if (currentConditionIdx != -1) {
fadeWidgets(conditionControls, false);
fadeWidgets(actionControls, true);
fadeWidgets(elseActionControls, true);
} else if (currentActionIdx != -1) { } else if (currentActionIdx != -1) {
FadeOutConditionControls(); fadeWidgets(conditionControls, true);
ResetOpacityActionControls(); fadeWidgets(actionControls, false);
fadeWidgets(elseActionControls, true);
} else if (currentElseActionIdx != -1) {
fadeWidgets(conditionControls, true);
fadeWidgets(actionControls, true);
fadeWidgets(elseActionControls, false);
} else { } else {
FadeOutActionControls(); assert(false);
ResetOpacityConditionControls();
} }
} }

View File

@@ -108,7 +108,7 @@ void MacroTreeItem::HighlightIfExecuted()
if (_lastHighlightCheckTime.time_since_epoch().count() != 0 && if (_lastHighlightCheckTime.time_since_epoch().count() != 0 &&
_macro->WasExecutedSince(_lastHighlightCheckTime)) { _macro->WasExecutedSince(_lastHighlightCheckTime)) {
PulseWidget(this, Qt::green, QColor(0, 0, 0, 0), true); HighlightWidget(this, Qt::green, QColor(0, 0, 0, 0), true);
} }
_lastHighlightCheckTime = std::chrono::high_resolution_clock::now(); _lastHighlightCheckTime = std::chrono::high_resolution_clock::now();
} }

View File

@@ -101,7 +101,7 @@ void Macro::PrepareMoveToGroup(std::shared_ptr<Macro> group,
} }
} }
bool Macro::CeckMatch() bool Macro::CeckMatch(bool ignorePause)
{ {
if (_isGroup) { if (_isGroup) {
return false; return false;
@@ -109,7 +109,7 @@ bool Macro::CeckMatch()
_matched = false; _matched = false;
for (auto &c : _conditions) { for (auto &c : _conditions) {
if (_paused) { if (_paused && !ignorePause) {
vblog(LOG_INFO, "Macro %s is paused", _name.c_str()); vblog(LOG_INFO, "Macro %s is paused", _name.c_str());
return false; return false;
} }
@@ -137,37 +137,37 @@ bool Macro::CeckMatch()
case LogicType::AND: case LogicType::AND:
_matched = _matched && cond; _matched = _matched && cond;
if (cond) { if (cond) {
c->SetHighlight(); c->EnableHighlight();
} }
break; break;
case LogicType::OR: case LogicType::OR:
_matched = _matched || cond; _matched = _matched || cond;
if (cond) { if (cond) {
c->SetHighlight(); c->EnableHighlight();
} }
break; break;
case LogicType::AND_NOT: case LogicType::AND_NOT:
_matched = _matched && !cond; _matched = _matched && !cond;
if (!cond) { if (!cond) {
c->SetHighlight(); c->EnableHighlight();
} }
break; break;
case LogicType::OR_NOT: case LogicType::OR_NOT:
_matched = _matched || !cond; _matched = _matched || !cond;
if (!cond) { if (!cond) {
c->SetHighlight(); c->EnableHighlight();
} }
break; break;
case LogicType::ROOT_NONE: case LogicType::ROOT_NONE:
_matched = cond; _matched = cond;
if (cond) { if (cond) {
c->SetHighlight(); c->EnableHighlight();
} }
break; break;
case LogicType::ROOT_NOT: case LogicType::ROOT_NOT:
_matched = !cond; _matched = !cond;
if (!cond) { if (!cond) {
c->SetHighlight(); c->EnableHighlight();
} }
break; break;
default: default:
@@ -185,6 +185,7 @@ bool Macro::CeckMatch()
if (!_conditionSateChanged && _performActionsOnChange) { if (!_conditionSateChanged && _performActionsOnChange) {
_onPreventedActionExecution = true; _onPreventedActionExecution = true;
} }
_lastMatched = _matched; _lastMatched = _matched;
_lastCheckTime = std::chrono::high_resolution_clock::now(); _lastCheckTime = std::chrono::high_resolution_clock::now();
return _matched; return _matched;
@@ -313,7 +314,7 @@ bool Macro::RunActionsHelper(
break; break;
} }
if (action->Enabled()) { if (action->Enabled()) {
action->SetHighlight(); action->EnableHighlight();
} }
} }
_done = true; _done = true;
@@ -348,6 +349,11 @@ void Macro::SetMatchOnChange(bool onChange)
_performActionsOnChange = onChange; _performActionsOnChange = onChange;
} }
void Macro::SetStopActionsIfNotDone(bool stopActionsIfNotDone)
{
_stopActionsIfNotDone = stopActionsIfNotDone;
}
void Macro::SetPaused(bool pause) void Macro::SetPaused(bool pause)
{ {
if (_paused && !pause) { if (_paused && !pause) {
@@ -382,6 +388,16 @@ void Macro::Stop()
} }
} }
MacroInputVariables Macro::GetInputVariables() const
{
return _inputVariables;
}
void Macro::SetInputVariables(const MacroInputVariables &inputVariables)
{
_inputVariables = inputVariables;
}
std::vector<TempVariable> Macro::GetTempVars(MacroSegment *filter) const std::vector<TempVariable> Macro::GetTempVars(MacroSegment *filter) const
{ {
std::vector<TempVariable> res; std::vector<TempVariable> res;
@@ -610,6 +626,8 @@ bool Macro::Save(obs_data_t *obj) const
} }
obs_data_set_array(obj, "elseActions", elseActions); obs_data_set_array(obj, "elseActions", elseActions);
_inputVariables.Save(obj);
return true; return true;
} }
@@ -748,6 +766,8 @@ bool Macro::Load(obs_data_t *obj)
} }
UpdateElseActionIndices(); UpdateElseActionIndices();
_inputVariables.Load(obj);
return true; return true;
} }
@@ -819,10 +839,10 @@ void Macro::ResetUIHelpers()
{ {
_onPreventedActionExecution = false; _onPreventedActionExecution = false;
for (auto c : _conditions) { for (auto c : _conditions) {
c->Highlight(); c->GetHighlightAndReset();
} }
for (auto a : _actions) { for (auto a : _actions) {
a->Highlight(); a->GetHighlightAndReset();
} }
} }

View File

@@ -2,6 +2,7 @@
#include "macro-action.hpp" #include "macro-action.hpp"
#include "macro-condition.hpp" #include "macro-condition.hpp"
#include "macro-helpers.hpp" #include "macro-helpers.hpp"
#include "macro-input.hpp"
#include "macro-ref.hpp" #include "macro-ref.hpp"
#include "variable-string.hpp" #include "variable-string.hpp"
#include "temp-variable.hpp" #include "temp-variable.hpp"
@@ -25,35 +26,44 @@ public:
Macro(const std::string &name = "", const bool addHotkey = false); Macro(const std::string &name = "", const bool addHotkey = false);
virtual ~Macro(); virtual ~Macro();
bool CeckMatch();
bool PerformActions(bool match, bool forceParallel = false,
bool ignorePause = false);
bool Matched() const { return _matched; }
bool ShouldRunActions() const;
int64_t MsSinceLastCheck() const;
std::string Name() const { return _name; } std::string Name() const { return _name; }
void SetName(const std::string &name); void SetName(const std::string &name);
void SetRunInParallel(bool parallel) { _runInParallel = parallel; }
bool RunInParallel() const { return _runInParallel; } bool CeckMatch(bool ignorePause = false);
bool Matched() const { return _matched; }
int64_t MsSinceLastCheck() const;
bool ShouldRunActions() const;
bool PerformActions(bool match, bool forceParallel = false,
bool ignorePause = false);
void SetPaused(bool pause = true); void SetPaused(bool pause = true);
bool Paused() const { return _paused; } bool Paused() const { return _paused; }
bool WasPausedSince( bool WasPausedSince(
const std::chrono::high_resolution_clock::time_point &) const; const std::chrono::high_resolution_clock::time_point &) const;
void Stop();
bool GetStop() const { return _stop; }
void ResetTimers();
void SetMatchOnChange(bool onChange); void SetMatchOnChange(bool onChange);
bool MatchOnChange() const { return _performActionsOnChange; } bool MatchOnChange() const { return _performActionsOnChange; }
void SetSkipExecOnStart(bool skip) { _skipExecOnStart = skip; } void SetSkipExecOnStart(bool skip) { _skipExecOnStart = skip; }
bool SkipExecOnStart() const { return _skipExecOnStart; } bool SkipExecOnStart() const { return _skipExecOnStart; }
void SetStopActionsIfNotDone(bool stopActionsIfNotDone)
{ void SetStopActionsIfNotDone(bool stopActionsIfNotDone);
_stopActionsIfNotDone = stopActionsIfNotDone;
}
bool StopActionsIfNotDone() const { return _stopActionsIfNotDone; } bool StopActionsIfNotDone() const { return _stopActionsIfNotDone; }
int RunCount() const { return _runCount; }; int RunCount() const { return _runCount; };
void ResetRunCount() { _runCount = 0; }; void ResetRunCount() { _runCount = 0; };
void ResetTimers();
void AddHelperThread(std::thread &&); void AddHelperThread(std::thread &&);
bool GetStop() const { return _stop; } void SetRunInParallel(bool parallel) { _runInParallel = parallel; }
void Stop(); bool RunInParallel() const { return _runInParallel; }
// Input variables
MacroInputVariables GetInputVariables() const;
void SetInputVariables(const MacroInputVariables &);
// Temporary variable helpers // Temporary variable helpers
std::vector<TempVariable> GetTempVars(MacroSegment *filter) const; std::vector<TempVariable> GetTempVars(MacroSegment *filter) const;
@@ -98,19 +108,21 @@ public:
bool SwitchesScene() const; bool SwitchesScene() const;
// UI helpers // UI helpers
const QList<int> &GetActionConditionSplitterPosition() const;
void SetActionConditionSplitterPosition(const QList<int>); void SetActionConditionSplitterPosition(const QList<int>);
const QList<int> &GetElseActionSplitterPosition() const; const QList<int> &GetActionConditionSplitterPosition() const;
void SetElseActionSplitterPosition(const QList<int>); void SetElseActionSplitterPosition(const QList<int>);
const QList<int> &GetElseActionSplitterPosition() const;
bool HasValidSplitterPositions() const; bool HasValidSplitterPositions() const;
bool WasExecutedSince( bool WasExecutedSince(
const std::chrono::high_resolution_clock::time_point &) const; const std::chrono::high_resolution_clock::time_point &) const;
bool OnChangePreventedActionsRecently(); bool OnChangePreventedActionsRecently();
void ResetUIHelpers(); void ResetUIHelpers();
// Hotkeys
void EnablePauseHotkeys(bool); void EnablePauseHotkeys(bool);
bool PauseHotkeysEnabled() const; bool PauseHotkeysEnabled() const;
// Docks
void EnableDock(bool); void EnableDock(bool);
bool DockEnabled() const { return _registerDock; } bool DockEnabled() const { return _registerDock; }
void SetDockHasRunButton(bool value); void SetDockHasRunButton(bool value);
@@ -182,6 +194,8 @@ private:
obs_hotkey_id _unpauseHotkey = OBS_INVALID_HOTKEY_ID; obs_hotkey_id _unpauseHotkey = OBS_INVALID_HOTKEY_ID;
obs_hotkey_id _togglePauseHotkey = OBS_INVALID_HOTKEY_ID; obs_hotkey_id _togglePauseHotkey = OBS_INVALID_HOTKEY_ID;
MacroInputVariables _inputVariables;
// UI helpers // UI helpers
bool _onPreventedActionExecution = false; bool _onPreventedActionExecution = false;

View File

@@ -11,19 +11,16 @@
namespace advss { namespace advss {
static bool registerTab();
static void setupTab(QTabWidget *); static void setupTab(QTabWidget *);
static bool registerTabDone = registerTab();
static ActionQueueTable *tabWidget = nullptr; static ActionQueueTable *tabWidget = nullptr;
static bool registerTab() void RegisterActionQueueTab()
{ {
AddPluginInitStep([]() { AddPluginInitStep([]() {
AddSetupTabCallback("actionQueueTab", ActionQueueTable::Create, AddSetupTabCallback("actionQueueTab", ActionQueueTable::Create,
setupTab); setupTab);
}); });
return true;
} }
static void setTabVisible(QTabWidget *tabWidget, bool visible) static void setTabVisible(QTabWidget *tabWidget, bool visible)
@@ -70,11 +67,11 @@ static QStringList getCellLabels(ActionQueue *queue, bool addName = true)
<< QString::fromStdString(obs_module_text( << QString::fromStdString(obs_module_text(
queue->IsRunning() queue->IsRunning()
? "AdvSceneSwitcher.actionQueueTab.yes" ? "AdvSceneSwitcher.actionQueueTab.yes"
: "AdvSceneSwitcher.actionQueueTab.yes")) : "AdvSceneSwitcher.actionQueueTab.no"))
<< QString::fromStdString(obs_module_text( << QString::fromStdString(obs_module_text(
queue->RunsOnStartup() queue->RunsOnStartup()
? "AdvSceneSwitcher.actionQueueTab.yes" ? "AdvSceneSwitcher.actionQueueTab.yes"
: "AdvSceneSwitcher.actionQueueTab.yes")); : "AdvSceneSwitcher.actionQueueTab.no"));
return result; return result;
} }
@@ -223,14 +220,15 @@ static void setupTab(QTabWidget *tab)
} }
QWidget::connect(ActionQueueSignalManager::Instance(), QWidget::connect(ActionQueueSignalManager::Instance(),
&ActionQueueSignalManager::Rename, &ActionQueueSignalManager::Rename, tab,
[](const QString &oldName, const QString &newName) { [](const QString &oldName, const QString &newName) {
RenameItemTableRow(tabWidget->Table(), oldName, RenameItemTableRow(tabWidget->Table(), oldName,
newName); newName);
}); });
QWidget::connect( QWidget::connect(
ActionQueueSignalManager::Instance(), ActionQueueSignalManager::Instance(),
&ActionQueueSignalManager::Add, [tab](const QString &name) { &ActionQueueSignalManager::Add, tab,
[tab](const QString &name) {
AddItemTableRow( AddItemTableRow(
tabWidget->Table(), tabWidget->Table(),
getCellLabels(GetWeakActionQueueByQString(name) getCellLabels(GetWeakActionQueueByQString(name)
@@ -241,7 +239,7 @@ static void setupTab(QTabWidget *tab)
setTabVisible(tab, true); setTabVisible(tab, true);
}); });
QWidget::connect(ActionQueueSignalManager::Instance(), QWidget::connect(ActionQueueSignalManager::Instance(),
&ActionQueueSignalManager::Remove, &ActionQueueSignalManager::Remove, tab,
[](const QString &name) { [](const QString &name) {
RemoveItemTableRow(tabWidget->Table(), name); RemoveItemTableRow(tabWidget->Table(), name);
if (tabWidget->Table()->rowCount() == 0) { if (tabWidget->Table()->rowCount() == 0) {

View File

@@ -1,6 +1,7 @@
#include "action-queue.hpp" #include "action-queue.hpp"
#include "obs-module-helper.hpp" #include "obs-module-helper.hpp"
#include "plugin-state-helpers.hpp" #include "plugin-state-helpers.hpp"
#include "ui-helpers.hpp"
namespace advss { namespace advss {
@@ -11,6 +12,8 @@ std::deque<std::shared_ptr<Item>> &GetActionQueues()
return queues; return queues;
} }
void RegisterActionQueueTab();
void SetupActionQueues() void SetupActionQueues()
{ {
static bool done = false; static bool done = false;
@@ -19,6 +22,7 @@ void SetupActionQueues()
} }
AddSaveStep(SaveActionQueues); AddSaveStep(SaveActionQueues);
AddLoadStep(LoadActionQueues); AddLoadStep(LoadActionQueues);
RegisterActionQueueTab();
done = true; done = true;
} }
@@ -376,11 +380,24 @@ static bool queueWithNameExists(const std::string &name)
return !GetWeakActionQueueByName(name).expired(); return !GetWeakActionQueueByName(name).expired();
} }
static void signalImportedQueues(void *varsPtr)
{
auto queues = std::unique_ptr<std::vector<std::shared_ptr<Item>>>(
static_cast<std::vector<std::shared_ptr<Item>> *>(varsPtr));
for (const auto &queue : *queues) {
ActionQueueSignalManager::Instance()->Add(
QString::fromStdString(queue->Name()));
}
}
void ImportQueues(obs_data_t *data) void ImportQueues(obs_data_t *data)
{ {
OBSDataArrayAutoRelease array = OBSDataArrayAutoRelease array =
obs_data_get_array(data, "actionQueues"); obs_data_get_array(data, "actionQueues");
size_t count = obs_data_array_count(array); size_t count = obs_data_array_count(array);
auto importedQueues = new std::vector<std::shared_ptr<Item>>;
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
OBSDataAutoRelease arrayElement = obs_data_array_item(array, i); OBSDataAutoRelease arrayElement = obs_data_array_item(array, i);
auto queue = ActionQueue::Create(); auto queue = ActionQueue::Create();
@@ -389,7 +406,10 @@ void ImportQueues(obs_data_t *data)
continue; continue;
} }
queues.emplace_back(queue); queues.emplace_back(queue);
importedQueues->emplace_back(queue);
} }
QeueUITask(signalImportedQueues, importedQueues);
} }
std::weak_ptr<ActionQueue> GetWeakActionQueueByName(const std::string &name) std::weak_ptr<ActionQueue> GetWeakActionQueueByName(const std::string &name)

View File

@@ -16,7 +16,7 @@
#include "switch-video.hpp" #include "switch-video.hpp"
#include "switch-network.hpp" #include "switch-network.hpp"
#include "macro-properties.hpp" #include "macro-settings.hpp"
#include "duration-control.hpp" #include "duration-control.hpp"
#include "priority-helper.hpp" #include "priority-helper.hpp"
#include "plugin-state-helpers.hpp" #include "plugin-state-helpers.hpp"

View File

@@ -0,0 +1,34 @@
#include "cursor-shape-changer.hpp"
#include <QCursor>
#include <QEvent>
#include <QGuiApplication>
namespace advss {
CursorShapeChanger::CursorShapeChanger(QObject *parent, Qt::CursorShape shape)
: QObject(parent),
_shape(shape)
{
}
bool CursorShapeChanger::eventFilter(QObject *o, QEvent *e)
{
if ((e->type() == QEvent::HoverEnter || e->type() == QEvent::Enter) &&
!_overrideActive) {
_overrideActive = true;
QGuiApplication::setOverrideCursor(QCursor(_shape));
} else if (_overrideActive && e->type() == QEvent::Leave) {
_overrideActive = false;
QGuiApplication::restoreOverrideCursor();
}
return QObject::eventFilter(o, e);
}
void SetCursorOnWidgetHover(QWidget *widget, Qt::CursorShape shape)
{
widget->installEventFilter(new CursorShapeChanger(widget, shape));
}
} // namespace advss

View File

@@ -0,0 +1,20 @@
#pragma once
#include <QWidget>
namespace advss {
class CursorShapeChanger : public QObject {
public:
CursorShapeChanger(QObject *, Qt::CursorShape shape);
protected:
bool eventFilter(QObject *o, QEvent *e) override;
private:
Qt::CursorShape _shape;
std::atomic_bool _overrideActive = {false};
};
void SetCursorOnWidgetHover(QWidget *widget, Qt::CursorShape shape);
} // namespace advss

19
lib/utils/help-icon.cpp Normal file
View File

@@ -0,0 +1,19 @@
#include "help-icon.hpp"
#include "ui-helpers.hpp"
namespace advss {
HelpIcon::HelpIcon(const QString &tooltip, QWidget *parent) : QLabel(parent)
{
auto path = GetThemeTypeName() == "Light"
? ":/res/images/help.svg"
: ":/res/images/help_light.svg";
QIcon icon(path);
QPixmap pixmap = icon.pixmap(QSize(16, 16));
setPixmap(pixmap);
if (!tooltip.isEmpty()) {
setToolTip(tooltip);
}
}
} // namespace advss

15
lib/utils/help-icon.hpp Normal file
View File

@@ -0,0 +1,15 @@
#pragma once
#include "export-symbol-helper.hpp"
#include <QLabel>
namespace advss {
class ADVSS_EXPORT HelpIcon : public QLabel {
Q_OBJECT
public:
HelpIcon(const QString &tooltip = "", QWidget *parent = nullptr);
};
} // namespace advss

View File

@@ -81,6 +81,7 @@ public:
"AdvSceneSwitcher.item.nameNotAvailable", "AdvSceneSwitcher.item.nameNotAvailable",
std::string_view configureTooltip = "", QWidget *parent = 0); std::string_view configureTooltip = "", QWidget *parent = 0);
virtual ~ItemSelection() = default; virtual ~ItemSelection() = default;
Item *GetCurrentItem();
void SetItem(const std::string &); void SetItem(const std::string &);
void ShowRenameContextMenu(bool value); void ShowRenameContextMenu(bool value);
@@ -99,8 +100,6 @@ signals:
void ItemRenamed(const QString &oldName, const QString &name); void ItemRenamed(const QString &oldName, const QString &name);
private: private:
Item *GetCurrentItem();
FilterComboBox *_selection; FilterComboBox *_selection;
QPushButton *_modify; QPushButton *_modify;
CreateItemFunc _create; CreateItemFunc _create;

View File

@@ -0,0 +1,44 @@
#include "list-controls.hpp"
#include "obs-module-helper.hpp"
#include "ui-helpers.hpp"
#include <QLayout>
#include <QToolButton>
namespace advss {
ListControls::ListControls(QWidget *parent, bool reorder) : QToolBar(parent)
{
setObjectName("listControls");
setStyleSheet("#listControls { background-color: transparent; }");
setIconSize({16, 16});
AddActionHelper("addIconSmall", "AdvSceneSwitcher.listControls.add",
[this]() { Add(); });
AddActionHelper("removeIconSmall",
"AdvSceneSwitcher.listControls.remove",
[this]() { Remove(); });
if (reorder) {
addSeparator();
AddActionHelper("upArrowIconSmall",
"AdvSceneSwitcher.listControls.up",
[this]() { Up(); });
AddActionHelper("downArrowIconSmall",
"AdvSceneSwitcher.listControls.down",
[this]() { Down(); });
}
}
void ListControls::AddActionHelper(const char *theme, const char *tooltip,
const std::function<void()> &signal)
{
auto button = new QToolButton(this);
button->setToolTip(obs_module_text(tooltip));
button->setProperty("themeID", QVariant(QString(theme)));
(void)addWidget(button);
button->connect(button, &QToolButton::clicked, this, signal);
}
} // namespace advss

View File

@@ -0,0 +1,25 @@
#pragma once
#include "export-symbol-helper.hpp"
#include <QToolBar>
namespace advss {
class ADVSS_EXPORT ListControls final : public QToolBar {
Q_OBJECT
public:
ListControls(QWidget *parent = nullptr, bool reorder = true);
signals:
void Add();
void Remove();
void Up();
void Down();
private:
void AddActionHelper(const char *theme, const char *tooltip,
const std::function<void()> &signal);
};
} // namespace advss

43
lib/utils/list-editor.cpp Normal file
View File

@@ -0,0 +1,43 @@
#include "list-editor.hpp"
#include "ui-helpers.hpp"
namespace advss {
ListEditor::ListEditor(QWidget *parent, bool reorder)
: QWidget(parent),
_list(new QListWidget()),
_controls(new ListControls(this, reorder)),
_mainLayout(new QVBoxLayout())
{
QWidget::connect(_controls, SIGNAL(Add()), this, SLOT(Add()));
QWidget::connect(_controls, SIGNAL(Remove()), this, SLOT(Remove()));
QWidget::connect(_controls, SIGNAL(Up()), this, SLOT(Up()));
QWidget::connect(_controls, SIGNAL(Down()), this, SLOT(Down()));
QWidget::connect(_list, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
this, SLOT(Clicked(QListWidgetItem *)));
_mainLayout->setContentsMargins(0, 0, 0, 0);
_mainLayout->addWidget(_list);
_mainLayout->addWidget(_controls);
setLayout(_mainLayout);
}
void ListEditor::showEvent(QShowEvent *e)
{
QWidget::showEvent(e);
// This is necessary as the list viewport might not be updated yet while
// the list was hidden.
// Thus, previous calls to UpdateListSize() might not have resized the
// widget correctly, for example due to not regarding the horizontal
// scrollbar yet.
UpdateListSize();
}
void ListEditor::UpdateListSize()
{
SetHeightToContentHeight(_list);
adjustSize();
updateGeometry();
}
} // namespace advss

34
lib/utils/list-editor.hpp Normal file
View File

@@ -0,0 +1,34 @@
#pragma once
#include "export-symbol-helper.hpp"
#include "list-controls.hpp"
#include <QListWidget>
#include <QLayout>
namespace advss {
class ADVSS_EXPORT ListEditor : public QWidget {
Q_OBJECT
public:
ListEditor(QWidget *parent = nullptr, bool reorder = true);
protected:
void showEvent(QShowEvent *);
private slots:
virtual void Add() = 0;
virtual void Remove() = 0;
virtual void Up(){};
virtual void Down(){};
virtual void Clicked(QListWidgetItem *) {}
protected:
void UpdateListSize();
QListWidget *_list;
ListControls *_controls;
QVBoxLayout *_mainLayout;
};
} // namespace advss

View File

@@ -88,12 +88,10 @@ RegexConfig RegexConfig::PartialMatchRegexConfig()
RegexConfigWidget::RegexConfigWidget(QWidget *parent, bool showEnable) RegexConfigWidget::RegexConfigWidget(QWidget *parent, bool showEnable)
: QWidget(parent), : QWidget(parent),
_openSettings(new QPushButton()), _openSettings(new QToolButton()),
_enable(new QPushButton()) _enable(new QPushButton())
{ {
_openSettings->setMaximumWidth(22);
SetButtonIcon(_openSettings, ":/settings/images/settings/general.svg"); SetButtonIcon(_openSettings, ":/settings/images/settings/general.svg");
_openSettings->setFlat(true);
_openSettings->setToolTip( _openSettings->setToolTip(
obs_module_text("AdvSceneSwitcher.regex.configure")); obs_module_text("AdvSceneSwitcher.regex.configure"));

View File

@@ -2,12 +2,13 @@
#include "export-symbol-helper.hpp" #include "export-symbol-helper.hpp"
#include <obs-data.h> #include <obs-data.h>
#include <QWidget>
#include <QCheckBox> #include <QCheckBox>
#include <QPushButton>
#include <QDialog> #include <QDialog>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QPushButton>
#include <QRegularExpression> #include <QRegularExpression>
#include <QToolButton>
#include <QWidget>
namespace advss { namespace advss {
@@ -63,7 +64,7 @@ signals:
private: private:
void SetVisibility(); void SetVisibility();
QPushButton *_openSettings; QToolButton *_openSettings;
QPushButton *_enable; QPushButton *_enable;
RegexConfig _config; RegexConfig _config;
}; };

View File

@@ -15,20 +15,16 @@ ResourceTable::ResourceTable(QTabWidget *parent, const QString &help,
const std::function<void()> &openSettings) const std::function<void()> &openSettings)
: QWidget(parent), : QWidget(parent),
_table(new QTableWidget()), _table(new QTableWidget()),
_add(new QPushButton()), _add(new QToolButton()),
_remove(new QPushButton()), _remove(new QToolButton()),
_help(new QLabel(help)) _help(new QLabel(help))
{ {
_add->setMaximumWidth(22);
_add->setProperty("themeID", _add->setProperty("themeID",
QVariant(QString::fromUtf8("addIconSmall"))); QVariant(QString::fromUtf8("addIconSmall")));
_add->setFlat(true);
_add->setToolTip(addToolTip); _add->setToolTip(addToolTip);
_remove->setMaximumWidth(22);
_remove->setProperty("themeID", _remove->setProperty("themeID",
QVariant(QString::fromUtf8("removeIconSmall"))); QVariant(QString::fromUtf8("removeIconSmall")));
_remove->setFlat(true);
_remove->setToolTip(removeToolTip); _remove->setToolTip(removeToolTip);
_help->setWordWrap(true); _help->setWordWrap(true);
@@ -81,9 +77,13 @@ void ResourceTable::SetHelpVisible(bool visible) const
void ResourceTable::HighlightAddButton(bool enable) void ResourceTable::HighlightAddButton(bool enable)
{ {
_add->disconnect(_highlightConnection); if (_highlightConnection) {
_highlightConnection->deleteLater();
_highlightConnection = nullptr;
}
if (enable && HighlightUIElementsEnabled()) { if (enable && HighlightUIElementsEnabled()) {
_highlightConnection = PulseWidget(_add, QColor(Qt::green)); _highlightConnection = HighlightWidget(_add, QColor(Qt::green));
} }
} }

View File

@@ -2,8 +2,8 @@
#include "export-symbol-helper.hpp" #include "export-symbol-helper.hpp"
#include <QLabel> #include <QLabel>
#include <QPushButton>
#include <QString> #include <QString>
#include <QToolButton>
#include <QTableWidget> #include <QTableWidget>
class QResizeEvent; class QResizeEvent;
@@ -33,11 +33,11 @@ protected:
private: private:
QTableWidget *_table; QTableWidget *_table;
QPushButton *_add; QToolButton *_add;
QPushButton *_remove; QToolButton *_remove;
QLabel *_help; QLabel *_help;
QMetaObject::Connection _highlightConnection; QObject *_highlightConnection = nullptr;
}; };
EXPORT void AddItemTableRow(QTableWidget *table, const QStringList &cells); EXPORT void AddItemTableRow(QTableWidget *table, const QStringList &cells);

View File

@@ -8,6 +8,7 @@
#include <obs-frontend-api.h> #include <obs-frontend-api.h>
#include <QAction> #include <QAction>
#include <QMainWindow> #include <QMainWindow>
#include <QPalette>
#include <QToolBar> #include <QToolBar>
namespace advss { namespace advss {
@@ -15,6 +16,50 @@ namespace advss {
void OpenSettingsWindow(); void OpenSettingsWindow();
StatusDock *dock = nullptr; StatusDock *dock = nullptr;
static QString colorToString(const QColor &color)
{
return QString("rgba(") + QString::number(color.red()) + "," +
QString::number(color.green()) + "," +
QString::number(color.blue()) + "," +
QString::number(color.alpha()) + ")";
}
static QString getDefaultBackgroundColorString()
{
static QString defaultColorString;
static bool cacheReady = false;
if (cacheReady) {
return defaultColorString;
}
QWidget tempWidget;
const auto defaultColor =
tempWidget.palette().brush(QPalette::Window).color();
defaultColorString = colorToString(defaultColor);
cacheReady = true;
return defaultColorString;
}
static QString getDefaultTextColorString()
{
static QString defaultColorString;
static bool cacheReady = false;
if (cacheReady) {
return defaultColorString;
}
QLabel tempWidget;
const auto defaultColor =
tempWidget.palette().brush(QPalette::Text).color();
defaultColorString = colorToString(defaultColor);
cacheReady = true;
return defaultColorString;
}
StatusControl::StatusControl(QWidget *parent, bool noLayout) StatusControl::StatusControl(QWidget *parent, bool noLayout)
: QWidget(parent), : QWidget(parent),
_button(new QPushButton("-", this)), _button(new QPushButton("-", this)),
@@ -28,30 +73,22 @@ StatusControl::StatusControl(QWidget *parent, bool noLayout)
_statusPrefix->setWordWrap(true); _statusPrefix->setWordWrap(true);
_statusPrefix->setSizePolicy(QSizePolicy::Expanding, _statusPrefix->setSizePolicy(QSizePolicy::Expanding,
QSizePolicy::Expanding); QSizePolicy::Expanding);
_status->setStyleSheet("QLabel{ \
border-style: outset; \
border-width: 2px; \
border-radius: 7px; \
border-color: rgb(0,0,0,0) \
}");
_status->setSizePolicy(QSizePolicy::Maximum,
QSizePolicy::MinimumExpanding);
QWidget::connect(_button, SIGNAL(clicked()), this, QWidget::connect(_button, SIGNAL(clicked()), this,
SLOT(ButtonClicked())); SLOT(ButtonClicked()));
if (!noLayout) { if (!noLayout) {
QHBoxLayout *statusLayout = new QHBoxLayout();
statusLayout->addWidget(_statusPrefix);
statusLayout->addStretch();
statusLayout->addWidget(_status);
statusLayout->setStretch(0, 10);
_buttonLayout->setContentsMargins(0, 0, 0, 0); _buttonLayout->setContentsMargins(0, 0, 0, 0);
_buttonLayout->addWidget(_button); _buttonLayout->addWidget(_button);
QVBoxLayout *layout = new QVBoxLayout(); QVBoxLayout *layout = new QVBoxLayout();
layout->addLayout(statusLayout); _statusPrefix->setAlignment(Qt::AlignCenter);
_status->setAlignment(Qt::AlignCenter);
layout->addWidget(_statusPrefix);
layout->addWidget(_status);
layout->addLayout(_buttonLayout); layout->addLayout(_buttonLayout);
setLayout(layout); setLayout(layout);
} else {
_status->setSizePolicy(QSizePolicy::Maximum,
QSizePolicy::MinimumExpanding);
} }
if (PluginIsRunning()) { if (PluginIsRunning()) {
@@ -94,7 +131,10 @@ void StatusControl::SetStarted()
_button->setText( _button->setText(
obs_module_text("AdvSceneSwitcher.generalTab.status.stop")); obs_module_text("AdvSceneSwitcher.generalTab.status.stop"));
_status->setText(obs_module_text("AdvSceneSwitcher.status.active")); _status->setText(obs_module_text("AdvSceneSwitcher.status.active"));
_status->disconnect(_pulse); if (_pulse) {
_pulse->deleteLater();
}
SetStatusStyleSheet(false);
_setToStopped = false; _setToStopped = false;
} }
@@ -103,13 +143,31 @@ void StatusControl::SetStopped()
_button->setText( _button->setText(
obs_module_text("AdvSceneSwitcher.generalTab.status.start")); obs_module_text("AdvSceneSwitcher.generalTab.status.start"));
_status->setText(obs_module_text("AdvSceneSwitcher.status.inactive")); _status->setText(obs_module_text("AdvSceneSwitcher.status.inactive"));
SetStatusStyleSheet(true);
if (HighlightUIElementsEnabled()) { if (HighlightUIElementsEnabled()) {
_pulse = PulseWidget(_status, QColor(Qt::red), _pulse = HighlightWidget(_status, QColor(Qt::red),
QColor(0, 0, 0, 0)); QColor(0, 0, 0, 0));
} }
_setToStopped = true; _setToStopped = true;
} }
void StatusControl::SetStatusStyleSheet(bool stopped) const
{
auto style = QString("QLabel{ "
"background-color: ");
if (stopped) {
style += getDefaultBackgroundColorString() + "; ";
} else {
style += "transparent; ";
}
style += "border-style: outset; "
"border-width: 2px; "
"border-radius: 7px; "
"border-color: " +
getDefaultTextColorString() + "; }";
_status->setStyleSheet(style);
}
StatusDock::StatusDock(QWidget *parent) : OBSDock(parent) StatusDock::StatusDock(QWidget *parent) : OBSDock(parent)
{ {
setWindowTitle(obs_module_text("AdvSceneSwitcher.windowTitle")); setWindowTitle(obs_module_text("AdvSceneSwitcher.windowTitle"));

View File

@@ -26,13 +26,14 @@ private slots:
private: private:
void SetStopped(); void SetStopped();
void SetStarted(); void SetStarted();
void SetStatusStyleSheet(bool stopped) const;
QPushButton *_button; QPushButton *_button;
QHBoxLayout *_buttonLayout; QHBoxLayout *_buttonLayout;
QLabel *_status; QLabel *_status;
QLabel *_statusPrefix; QLabel *_statusPrefix;
QTimer _timer; QTimer _timer;
QMetaObject::Connection _pulse; QObject *_pulse = nullptr;
bool _setToStopped = true; bool _setToStopped = true;
}; };

View File

@@ -49,60 +49,12 @@ void StringList::ResolveVariables()
StringListEdit::StringListEdit(QWidget *parent, const QString &addString, StringListEdit::StringListEdit(QWidget *parent, const QString &addString,
const QString &addStringDescription, const QString &addStringDescription,
int maxStringSize, bool allowEmtpy) int maxStringSize, bool allowEmtpy)
: QWidget(parent), : ListEditor(parent),
_list(new QListWidget()),
_add(new QPushButton()),
_remove(new QPushButton()),
_up(new QPushButton()),
_down(new QPushButton()),
_addString(addString), _addString(addString),
_addStringDescription(addStringDescription), _addStringDescription(addStringDescription),
_maxStringSize(maxStringSize), _maxStringSize(maxStringSize),
_allowEmpty(allowEmtpy) _allowEmpty(allowEmtpy)
{ {
_add->setMaximumWidth(22);
_add->setProperty("themeID",
QVariant(QString::fromUtf8("addIconSmall")));
_add->setFlat(true);
_remove->setMaximumWidth(22);
_remove->setProperty("themeID",
QVariant(QString::fromUtf8("removeIconSmall")));
_remove->setFlat(true);
_up->setMaximumWidth(22);
_up->setProperty("themeID",
QVariant(QString::fromUtf8("upArrowIconSmall")));
_up->setFlat(true);
_down->setMaximumWidth(22);
_down->setProperty("themeID",
QVariant(QString::fromUtf8("downArrowIconSmall")));
_down->setFlat(true);
QWidget::connect(_add, SIGNAL(clicked()), this, SLOT(Add()));
QWidget::connect(_remove, SIGNAL(clicked()), this, SLOT(Remove()));
QWidget::connect(_up, SIGNAL(clicked()), this, SLOT(Up()));
QWidget::connect(_down, SIGNAL(clicked()), this, SLOT(Down()));
QWidget::connect(_list, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
this, SLOT(Clicked(QListWidgetItem *)));
auto controlLayout = new QHBoxLayout;
controlLayout->setContentsMargins(0, 0, 0, 0);
controlLayout->addWidget(_add);
controlLayout->addWidget(_remove);
QFrame *line = new QFrame();
line->setFrameShape(QFrame::VLine);
line->setFrameShadow(QFrame::Sunken);
controlLayout->addWidget(line);
controlLayout->addWidget(_up);
controlLayout->addWidget(_down);
controlLayout->addStretch();
auto mainLayout = new QVBoxLayout;
mainLayout->setContentsMargins(0, 0, 0, 0);
mainLayout->addWidget(_list);
mainLayout->addLayout(controlLayout);
setLayout(mainLayout);
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
} }
void StringListEdit::SetStringList(const StringList &list) void StringListEdit::SetStringList(const StringList &list)
@@ -115,7 +67,7 @@ void StringListEdit::SetStringList(const StringList &list)
_list); _list);
item->setData(Qt::UserRole, string); item->setData(Qt::UserRole, string);
} }
SetListSize(); UpdateListSize();
} }
void StringListEdit::SetMaxStringSize(int size) void StringListEdit::SetMaxStringSize(int size)
@@ -123,17 +75,6 @@ void StringListEdit::SetMaxStringSize(int size)
_maxStringSize = size; _maxStringSize = size;
} }
void StringListEdit::showEvent(QShowEvent *e)
{
QWidget::showEvent(e);
// This is necessary as the list viewport might not be updated yet
// while the list was hidden.
// Thus, previous calls to SetListSize() might not have resized the
// widget correctly, for example due to not regarding the horizontal
// scrollbar yet.
SetListSize();
}
void StringListEdit::Add() void StringListEdit::Add()
{ {
std::string name; std::string name;
@@ -153,7 +94,7 @@ void StringListEdit::Add()
_stringList << string; _stringList << string;
// Delay resizing to make sure the list viewport was already updated // Delay resizing to make sure the list viewport was already updated
QTimer::singleShot(0, this, [this]() { SetListSize(); }); QTimer::singleShot(0, this, [this]() { UpdateListSize(); });
StringListChanged(_stringList); StringListChanged(_stringList);
} }
@@ -173,7 +114,7 @@ void StringListEdit::Remove()
delete item; delete item;
// Delay resizing to make sure the list viewport was already updated // Delay resizing to make sure the list viewport was already updated
QTimer::singleShot(0, this, [this]() { SetListSize(); }); QTimer::singleShot(0, this, [this]() { UpdateListSize(); });
StringListChanged(_stringList); StringListChanged(_stringList);
} }
@@ -222,16 +163,9 @@ void StringListEdit::Clicked(QListWidgetItem *item)
_stringList[idx] = string; _stringList[idx] = string;
// Delay resizing to make sure the list viewport was already updated // Delay resizing to make sure the list viewport was already updated
QTimer::singleShot(0, this, [this]() { SetListSize(); }); QTimer::singleShot(0, this, [this]() { UpdateListSize(); });
StringListChanged(_stringList); StringListChanged(_stringList);
} }
void StringListEdit::SetListSize()
{
SetHeightToContentHeight(_list);
adjustSize();
updateGeometry();
}
} // namespace advss } // namespace advss

View File

@@ -1,27 +1,25 @@
#pragma once #pragma once
#include "variable-string.hpp" #include "export-symbol-helper.hpp"
#include "list-editor.hpp"
#include "obs-module-helper.hpp" #include "obs-module-helper.hpp"
#include "variable-string.hpp"
#include <obs-data.h> #include <obs-data.h>
#include <QPushButton>
#include <QListWidget>
#include <QStringList>
namespace advss { namespace advss {
class StringList : public QList<StringVariable> { class StringList : public QList<StringVariable> {
public: public:
bool Save(obs_data_t *obj, const char *name, EXPORT bool Save(obs_data_t *obj, const char *name,
const char *elementName = "string") const; const char *elementName = "string") const;
bool Load(obs_data_t *obj, const char *name, EXPORT bool Load(obs_data_t *obj, const char *name,
const char *elementName = "string"); const char *elementName = "string");
void ResolveVariables(); EXPORT void ResolveVariables();
friend class StringListEdit; friend class StringListEdit;
}; };
class StringListEdit : public QWidget { class ADVSS_EXPORT StringListEdit final : public ListEditor {
Q_OBJECT Q_OBJECT
public: public:
@@ -31,9 +29,6 @@ public:
void SetStringList(const StringList &); void SetStringList(const StringList &);
void SetMaxStringSize(int); void SetMaxStringSize(int);
protected:
void showEvent(QShowEvent *);
private slots: private slots:
void Add(); void Add();
void Remove(); void Remove();
@@ -44,16 +39,8 @@ signals:
void StringListChanged(const StringList &); void StringListChanged(const StringList &);
private: private:
void SetListSize();
StringList _stringList; StringList _stringList;
QListWidget *_list;
QPushButton *_add;
QPushButton *_remove;
QPushButton *_up;
QPushButton *_down;
QString _addString; QString _addString;
QString _addStringDescription; QString _addStringDescription;
int _maxStringSize = 170; int _maxStringSize = 170;

View File

@@ -5,8 +5,15 @@
namespace advss { namespace advss {
EXPORT std::mutex *GetMutex(); // Helper used in macro segment edit widgets
EXPORT std::lock_guard<std::mutex> LockContext(); #define GUARD_LOADING_AND_LOCK() \
EXPORT std::unique_lock<std::mutex> *GetLoopLock(); if (_loading || !_entryData) { \
return; \
} \
auto lock = LockContext();
[[nodiscard]] EXPORT std::mutex *GetMutex();
[[nodiscard]] EXPORT std::lock_guard<std::mutex> LockContext();
[[nodiscard]] EXPORT std::unique_lock<std::mutex> *GetLoopLock();
} // namespace advss } // namespace advss

View File

@@ -161,7 +161,7 @@ void SetTabOrder(QTabWidget *tabWidget)
void SetCurrentTab(QTabWidget *tabWidget) void SetCurrentTab(QTabWidget *tabWidget)
{ {
if (lastOpenedTab >= 0) { if (lastOpenedTab >= 0 && tabWidget->isTabVisible(lastOpenedTab)) {
tabWidget->setCurrentIndex(lastOpenedTab); tabWidget->setCurrentIndex(lastOpenedTab);
} }
} }

View File

@@ -182,6 +182,10 @@ void TempVariableRef::Load(obs_data_t *obj, Macro *macro, const char *name)
void TempVariableRef::PostLoad(int idx, SegmentType type, Macro *macro) void TempVariableRef::PostLoad(int idx, SegmentType type, Macro *macro)
{ {
if (!macro) {
return;
}
std::deque<std::shared_ptr<MacroSegment>> segments; std::deque<std::shared_ptr<MacroSegment>> segments;
switch (type) { switch (type) {
case SegmentType::NONE: case SegmentType::NONE:
@@ -458,7 +462,7 @@ void AutoUpdateTooltipLabel::enterEvent(QEnterEvent *event)
void AutoUpdateTooltipLabel::enterEvent(QEvent *event) void AutoUpdateTooltipLabel::enterEvent(QEvent *event)
#endif #endif
{ {
_timer->start(1000); _timer->start(300);
QLabel::enterEvent(event); QLabel::enterEvent(event);
} }

View File

@@ -65,6 +65,7 @@ public:
EXPORT void Load(obs_data_t *, Macro *, const char *name = "tempVar"); EXPORT void Load(obs_data_t *, Macro *, const char *name = "tempVar");
EXPORT std::optional<const TempVariable> GetTempVariable(Macro *) const; EXPORT std::optional<const TempVariable> GetTempVariable(Macro *) const;
EXPORT bool operator==(const TempVariableRef &other) const; EXPORT bool operator==(const TempVariableRef &other) const;
bool HasValidID() const { return !_id.empty(); }
private: private:
enum class SegmentType { NONE, CONDITION, ACTION, ELSEACTION }; enum class SegmentType { NONE, CONDITION, ACTION, ELSEACTION };

View File

@@ -13,8 +13,8 @@
namespace advss { namespace advss {
QMetaObject::Connection PulseWidget(QWidget *widget, QColor startColor, QObject *HighlightWidget(QWidget *widget, QColor startColor, QColor endColor,
QColor endColor, bool once) bool once)
{ {
QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect(widget); QGraphicsColorizeEffect *effect = new QGraphicsColorizeEffect(widget);
widget->setGraphicsEffect(effect); widget->setGraphicsEffect(effect);
@@ -24,33 +24,22 @@ QMetaObject::Connection PulseWidget(QWidget *widget, QColor startColor,
animation->setEndValue(endColor); animation->setEndValue(endColor);
animation->setDuration(1000); animation->setDuration(1000);
QMetaObject::Connection con; // Clean up the effect when the animation is deleted
QWidget::connect(animation, &QPropertyAnimation::destroyed, [widget]() {
if (widget) {
widget->setGraphicsEffect(nullptr);
}
});
if (once) { if (once) {
auto widgetPtr = widget;
con = QWidget::connect(
animation, &QPropertyAnimation::finished,
[widgetPtr]() {
if (widgetPtr) {
widgetPtr->setGraphicsEffect(nullptr);
}
});
animation->start(QPropertyAnimation::DeleteWhenStopped); animation->start(QPropertyAnimation::DeleteWhenStopped);
} else { return animation;
auto widgetPtr = widget;
con = QWidget::connect(
animation, &QPropertyAnimation::finished,
[animation, widgetPtr]() {
QTimer *timer = new QTimer(widgetPtr);
QWidget::connect(timer, &QTimer::timeout,
[animation] {
animation->start();
});
timer->setSingleShot(true);
timer->start(1000);
});
animation->start();
} }
return con;
QWidget::connect(animation, &QPropertyAnimation::finished,
[animation]() { animation->start(); });
animation->start();
return animation;
} }
static int getHorizontalScrollBarHeight(QListWidget *list) static int getHorizontalScrollBarHeight(QListWidget *list)
@@ -81,7 +70,7 @@ void SetHeightToContentHeight(QListWidget *list)
list->setMaximumHeight(height); list->setMaximumHeight(height);
} }
void SetButtonIcon(QPushButton *button, const char *path) void SetButtonIcon(QAbstractButton *button, const char *path)
{ {
QIcon icon; QIcon icon;
icon.addFile(QString::fromUtf8(path), QSize(), QIcon::Normal, icon.addFile(QString::fromUtf8(path), QSize(), QIcon::Normal,
@@ -166,4 +155,9 @@ std::string GetThemeTypeName()
#endif #endif
} }
void QeueUITask(void (*task)(void *param), void *param)
{
obs_queue_task(OBS_TASK_UI, task, param, false);
}
} // namespace advss } // namespace advss

View File

@@ -1,23 +1,25 @@
#pragma once #pragma once
#include "export-symbol-helper.hpp" #include "export-symbol-helper.hpp"
#include <QAbstractButton>
#include <QColor> #include <QColor>
#include <QComboBox> #include <QComboBox>
#include <QIcon> #include <QIcon>
#include <QListWidget> #include <QListWidget>
#include <QPushButton>
#include <QString> #include <QString>
#include <QWidget> #include <QWidget>
#include <string> #include <string>
namespace advss { namespace advss {
EXPORT QMetaObject::Connection PulseWidget(QWidget *widget, QColor startColor, // Returns QObject* to QPropertyAnimation object
QColor endColor = QColor(0, 0, 0, 0), // Delete it to stop the animation
bool once = false); EXPORT QObject *HighlightWidget(QWidget *widget, QColor startColor,
QColor endColor = QColor(0, 0, 0, 0),
bool once = false);
EXPORT void SetHeightToContentHeight(QListWidget *list); EXPORT void SetHeightToContentHeight(QListWidget *list);
EXPORT void SetButtonIcon(QPushButton *button, const char *path); EXPORT void SetButtonIcon(QAbstractButton *button, const char *path);
EXPORT int EXPORT int
FindIdxInRagne(QComboBox *list, int start, int stop, const std::string &value, FindIdxInRagne(QComboBox *list, int start, int stop, const std::string &value,
Qt::MatchFlags = Qt::MatchExactly | Qt::MatchCaseSensitive); Qt::MatchFlags = Qt::MatchExactly | Qt::MatchCaseSensitive);
@@ -29,4 +31,6 @@ EXPORT void DisplayTrayMessage(const QString &title, const QString &msg,
EXPORT std::string GetThemeTypeName(); EXPORT std::string GetThemeTypeName();
void QeueUITask(void (*task)(void *param), void *param);
} // namespace advss } // namespace advss

View File

@@ -76,15 +76,15 @@ std::string ToString(double value)
} }
void listAddClicked(QListWidget *list, QWidget *newWidget, void listAddClicked(QListWidget *list, QWidget *newWidget,
QPushButton *addButton, QPushButton *addButton, QObject *addHighlight)
QMetaObject::Connection *addHighlight)
{ {
if (!list || !newWidget) { if (!list || !newWidget) {
return; return;
} }
if (addButton && addHighlight) { if (addHighlight) {
addButton->disconnect(*addHighlight); addHighlight->deleteLater();
addHighlight = nullptr;
} }
QListWidgetItem *item; QListWidgetItem *item;

View File

@@ -24,7 +24,7 @@ std::string ToString(double value);
void listAddClicked(QListWidget *list, QWidget *newWidget, void listAddClicked(QListWidget *list, QWidget *newWidget,
QPushButton *addButton = nullptr, QPushButton *addButton = nullptr,
QMetaObject::Connection *addHighlight = nullptr); QObject *addHighlight = nullptr);
bool listMoveUp(QListWidget *list); bool listMoveUp(QListWidget *list);
bool listMoveDown(QListWidget *list); bool listMoveDown(QListWidget *list);

View File

@@ -154,6 +154,15 @@ static void updateVariableStatus(QTableWidget *table)
UpdateItemTableRow(table, row, UpdateItemTableRow(table, row,
getCellLabels(variable.get(), false)); getCellLabels(variable.get(), false));
// Special tooltip handling for the "last used" cell
const auto lastUsedItem = table->item(row, 4);
if (!lastUsedItem) {
continue;
}
const auto lastUsedTooltip =
formatLastChangedTooltip(variable.get());
lastUsedItem->setToolTip(lastUsedTooltip);
} }
} }
@@ -264,14 +273,14 @@ static void setupTab(QTabWidget *tab)
} }
QWidget::connect(VariableSignalManager::Instance(), QWidget::connect(VariableSignalManager::Instance(),
&VariableSignalManager::Rename, &VariableSignalManager::Rename, tab,
[](const QString &oldName, const QString &newName) { [](const QString &oldName, const QString &newName) {
RenameItemTableRow(tabWidget->Table(), oldName, RenameItemTableRow(tabWidget->Table(), oldName,
newName); newName);
}); });
QWidget::connect( QWidget::connect(
VariableSignalManager::Instance(), &VariableSignalManager::Add, VariableSignalManager::Instance(), &VariableSignalManager::Add,
[tab](const QString &name) { tab, [tab](const QString &name) {
AddItemTableRow( AddItemTableRow(
tabWidget->Table(), tabWidget->Table(),
getCellLabels(GetVariableByQString(name))); getCellLabels(GetVariableByQString(name)));
@@ -280,7 +289,7 @@ static void setupTab(QTabWidget *tab)
setTabVisible(tab, true); setTabVisible(tab, true);
}); });
QWidget::connect(VariableSignalManager::Instance(), QWidget::connect(VariableSignalManager::Instance(),
&VariableSignalManager::Remove, &VariableSignalManager::Remove, tab,
[](const QString &name) { [](const QString &name) {
RemoveItemTableRow(tabWidget->Table(), name); RemoveItemTableRow(tabWidget->Table(), name);
if (tabWidget->Table()->rowCount() == 0) { if (tabWidget->Table()->rowCount() == 0) {

View File

@@ -1,6 +1,7 @@
#include "variable.hpp" #include "variable.hpp"
#include "math-helpers.hpp" #include "math-helpers.hpp"
#include "obs-module-helper.hpp" #include "obs-module-helper.hpp"
#include "ui-helpers.hpp"
#include "utility.hpp" #include "utility.hpp"
#include <QGridLayout> #include <QGridLayout>
@@ -267,6 +268,53 @@ void VariableSelection::SetVariable(const std::weak_ptr<Variable> &variable_)
} }
} }
VariableSelectionDialog::VariableSelectionDialog(QWidget *parent)
: QDialog(parent),
_variableSelection(new VariableSelection(this))
{
setModal(true);
setWindowModality(Qt::WindowModality::ApplicationModal);
setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
setMinimumWidth(350);
setMinimumHeight(70);
auto buttonbox = new QDialogButtonBox(QDialogButtonBox::Ok |
QDialogButtonBox::Cancel);
buttonbox->setCenterButtons(true);
connect(buttonbox, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttonbox, &QDialogButtonBox::rejected, this, &QDialog::reject);
auto selectionLayout = new QHBoxLayout();
selectionLayout->addWidget(new QLabel(
obs_module_text("AdvSceneSwitcher.variable.selectionDialog")));
selectionLayout->addWidget(_variableSelection);
selectionLayout->addStretch();
auto layout = new QVBoxLayout();
layout->addLayout(selectionLayout);
layout->addWidget(buttonbox);
setLayout(layout);
}
QWidget *GetSettingsWindow();
bool VariableSelectionDialog::AskForVariable(QWidget *parent,
std::string &varName)
{
VariableSelectionDialog dialog(GetSettingsWindow());
dialog.setWindowTitle(obs_module_text("AdvSceneSwitcher.windowTitle"));
if (dialog.exec() != DialogCode::Accepted) {
return false;
}
auto item = dialog._variableSelection->GetCurrentItem();
if (!item) {
return false;
}
varName = item->Name();
return true;
}
VariableSignalManager::VariableSignalManager(QObject *parent) : QObject(parent) VariableSignalManager::VariableSignalManager(QObject *parent) : QObject(parent)
{ {
} }
@@ -375,11 +423,23 @@ void LoadVariables(obs_data_t *obj)
obs_data_array_release(variablesArray); obs_data_array_release(variablesArray);
} }
static void signalImportedVariables(void *varsPtr)
{
auto vars = std::unique_ptr<std::vector<std::shared_ptr<Item>>>(
static_cast<std::vector<std::shared_ptr<Item>> *>(varsPtr));
for (const auto &var : *vars) {
VariableSignalManager::Instance()->Add(
QString::fromStdString(var->Name()));
}
}
void ImportVariables(obs_data_t *data) void ImportVariables(obs_data_t *data)
{ {
obs_data_array_t *array = obs_data_get_array(data, "variables"); obs_data_array_t *array = obs_data_get_array(data, "variables");
size_t count = obs_data_array_count(array); size_t count = obs_data_array_count(array);
auto importedVars = new std::vector<std::shared_ptr<Item>>;
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
obs_data_t *arrayElement = obs_data_array_item(array, i); obs_data_t *arrayElement = obs_data_array_item(array, i);
auto var = Variable::Create(); auto var = Variable::Create();
@@ -391,9 +451,12 @@ void ImportVariables(obs_data_t *data)
} }
GetVariables().emplace_back(var); GetVariables().emplace_back(var);
importedVars->emplace_back(var);
} }
obs_data_array_release(array); obs_data_array_release(array);
QeueUITask(signalImportedVariables, importedVars);
} }
std::chrono::high_resolution_clock::time_point GetLastVariableChangeTime() std::chrono::high_resolution_clock::time_point GetLastVariableChangeTime()

View File

@@ -82,6 +82,17 @@ public:
void SetVariable(const std::weak_ptr<Variable> &); void SetVariable(const std::weak_ptr<Variable> &);
}; };
class VariableSelectionDialog : public QDialog {
Q_OBJECT
public:
VariableSelectionDialog(QWidget *parent);
static bool AskForVariable(QWidget *parent, std::string &variableName);
private:
VariableSelection *_variableSelection;
};
class ADVSS_EXPORT VariableSignalManager : public QObject { class ADVSS_EXPORT VariableSignalManager : public QObject {
Q_OBJECT Q_OBJECT
public: public:

View File

@@ -31,4 +31,5 @@ install_advss_plugin_dependency(...)
add_plugin(midi) add_plugin(midi)
add_plugin(openvr) add_plugin(openvr)
add_plugin(twitch) add_plugin(twitch)
add_plugin(usb)
add_plugin(video) add_plugin(video)

View File

@@ -87,6 +87,8 @@ target_sources(
macro-condition-file.hpp macro-condition-file.hpp
macro-condition-filter.cpp macro-condition-filter.cpp
macro-condition-filter.hpp macro-condition-filter.hpp
macro-condition-folder.cpp
macro-condition-folder.hpp
macro-condition-hotkey.cpp macro-condition-hotkey.cpp
macro-condition-hotkey.hpp macro-condition-hotkey.hpp
macro-condition-idle.cpp macro-condition-idle.cpp
@@ -164,10 +166,10 @@ target_sources(
utils/source-properties-button.hpp utils/source-properties-button.hpp
utils/source-settings-helpers.cpp utils/source-settings-helpers.cpp
utils/source-settings-helpers.hpp utils/source-settings-helpers.hpp
utils/source-interact.cpp
utils/source-interact.hpp
utils/source-setting.cpp utils/source-setting.cpp
utils/source-setting.hpp utils/source-setting.hpp
utils/string-list.cpp
utils/string-list.hpp
utils/striped-frame.cpp utils/striped-frame.cpp
utils/striped-frame.hpp utils/striped-frame.hpp
utils/text-helpers.cpp utils/text-helpers.cpp

View File

@@ -60,8 +60,13 @@ bool MacroActionProjector::PerformAction()
} }
if (_fullscreen && _monitor == -1) { if (_fullscreen && _monitor == -1) {
blog(LOG_INFO, "refusing to open fullscreen projector" blog(LOG_INFO, "refusing to open fullscreen projector "
" with invalid display selection"); "with invalid display selection");
return true;
}
if (_fullscreen && MonitorSetupChanged()) {
blog(LOG_INFO, "refusing to open fullscreen projector - "
"monitor setup seems to have changed!");
return true; return true;
} }
@@ -109,13 +114,6 @@ bool MacroActionProjector::Load(obs_data_t *obj)
_fullscreen = obs_data_get_bool(obj, "fullscreen"); _fullscreen = obs_data_get_bool(obj, "fullscreen");
_scene.Load(obj); _scene.Load(obj);
_source.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; return true;
} }
@@ -149,10 +147,13 @@ void MacroActionProjector::SetMonitor(int idx)
int MacroActionProjector::GetMonitor() const int MacroActionProjector::GetMonitor() const
{ {
if (MonitorSetupChanged()) {
return -1;
}
return _monitor; return _monitor;
} }
bool MacroActionProjector::MonitorSetupChanged() bool MacroActionProjector::MonitorSetupChanged() const
{ {
if (_monitorName.empty()) { if (_monitorName.empty()) {
return false; return false;
@@ -248,41 +249,25 @@ void MacroActionProjectorEdit::UpdateEntryData()
void MacroActionProjectorEdit::SceneChanged(const SceneSelection &s) void MacroActionProjectorEdit::SceneChanged(const SceneSelection &s)
{ {
if (_loading || !_entryData) { GUARD_LOADING_AND_LOCK();
return;
}
auto lock = LockContext();
_entryData->_scene = s; _entryData->_scene = s;
} }
void MacroActionProjectorEdit::SourceChanged(const SourceSelection &source) void MacroActionProjectorEdit::SourceChanged(const SourceSelection &source)
{ {
if (_loading || !_entryData) { GUARD_LOADING_AND_LOCK();
return;
}
auto lock = LockContext();
_entryData->_source = source; _entryData->_source = source;
} }
void MacroActionProjectorEdit::MonitorChanged(int value) void MacroActionProjectorEdit::MonitorChanged(int value)
{ {
if (_loading || !_entryData) { GUARD_LOADING_AND_LOCK();
return;
}
auto lock = LockContext();
_entryData->SetMonitor(value); _entryData->SetMonitor(value);
} }
void MacroActionProjectorEdit::WindowTypeChanged(int) void MacroActionProjectorEdit::WindowTypeChanged(int)
{ {
if (_loading || !_entryData) { GUARD_LOADING_AND_LOCK();
return;
}
auto lock = LockContext();
_entryData->_fullscreen = _entryData->_fullscreen =
_windowTypes->currentText() == _windowTypes->currentText() ==
obs_module_text("AdvSceneSwitcher.action.projector.fullscreen"); obs_module_text("AdvSceneSwitcher.action.projector.fullscreen");
@@ -291,11 +276,7 @@ void MacroActionProjectorEdit::WindowTypeChanged(int)
void MacroActionProjectorEdit::TypeChanged(int value) void MacroActionProjectorEdit::TypeChanged(int value)
{ {
if (_loading || !_entryData) { GUARD_LOADING_AND_LOCK();
return;
}
auto lock = LockContext();
_entryData->_type = static_cast<MacroActionProjector::Type>(value); _entryData->_type = static_cast<MacroActionProjector::Type>(value);
SetWidgetVisibility(); SetWidgetVisibility();
} }

View File

@@ -33,7 +33,7 @@ public:
bool _fullscreen = true; bool _fullscreen = true;
private: private:
bool MonitorSetupChanged(); bool MonitorSetupChanged() const;
int _monitor = -1; int _monitor = -1;
// Only used to detect display setup changes // Only used to detect display setup changes
@@ -66,17 +66,17 @@ private slots:
void SourceChanged(const SourceSelection &); void SourceChanged(const SourceSelection &);
void MonitorChanged(int value); void MonitorChanged(int value);
protected: private:
void SetWidgetVisibility();
QComboBox *_windowTypes; QComboBox *_windowTypes;
QComboBox *_types; QComboBox *_types;
SceneSelectionWidget *_scenes; SceneSelectionWidget *_scenes;
SourceSelectionWidget *_sources; SourceSelectionWidget *_sources;
QHBoxLayout *_monitorSelection; QHBoxLayout *_monitorSelection;
QComboBox *_monitors; QComboBox *_monitors;
std::shared_ptr<MacroActionProjector> _entryData;
private: std::shared_ptr<MacroActionProjector> _entryData;
void SetWidgetVisibility();
bool _loading = true; bool _loading = true;
}; };

View File

@@ -2,6 +2,7 @@
#include "layout-helpers.hpp" #include "layout-helpers.hpp"
#include <obs-frontend-api.h> #include <obs-frontend-api.h>
#include <util/config-file.h>
namespace advss { namespace advss {
@@ -12,31 +13,49 @@ bool MacroActionReplayBuffer::_registered = MacroActionFactory::Register(
{MacroActionReplayBuffer::Create, MacroActionReplayBufferEdit::Create, {MacroActionReplayBuffer::Create, MacroActionReplayBufferEdit::Create,
"AdvSceneSwitcher.action.replay"}); "AdvSceneSwitcher.action.replay"});
static const std::map<ReplayBufferAction, std::string> actionTypes = { static const std::map<MacroActionReplayBuffer::Action, std::string>
{ReplayBufferAction::STOP, "AdvSceneSwitcher.action.replay.type.stop"}, actionTypes = {
{ReplayBufferAction::START, {MacroActionReplayBuffer::Action::STOP,
"AdvSceneSwitcher.action.replay.type.start"}, "AdvSceneSwitcher.action.replay.type.stop"},
{ReplayBufferAction::SAVE, "AdvSceneSwitcher.action.replay.type.save"}, {MacroActionReplayBuffer::Action::START,
"AdvSceneSwitcher.action.replay.type.start"},
{MacroActionReplayBuffer::Action::SAVE,
"AdvSceneSwitcher.action.replay.type.save"},
{MacroActionReplayBuffer::Action::DURATION,
"AdvSceneSwitcher.action.replay.type.duration"},
}; };
bool MacroActionReplayBuffer::PerformAction() bool MacroActionReplayBuffer::PerformAction()
{ {
switch (_action) { switch (_action) {
case ReplayBufferAction::STOP: case Action::STOP:
if (obs_frontend_replay_buffer_active()) { if (obs_frontend_replay_buffer_active()) {
obs_frontend_replay_buffer_stop(); obs_frontend_replay_buffer_stop();
} }
break; break;
case ReplayBufferAction::START: case Action::START:
if (!obs_frontend_replay_buffer_active()) { if (!obs_frontend_replay_buffer_active()) {
obs_frontend_replay_buffer_start(); obs_frontend_replay_buffer_start();
} }
break; break;
case ReplayBufferAction::SAVE: case Action::SAVE:
if (obs_frontend_replay_buffer_active()) { if (obs_frontend_replay_buffer_active()) {
obs_frontend_replay_buffer_save(); obs_frontend_replay_buffer_save();
} }
break; break;
case Action::DURATION: {
auto conf = obs_frontend_get_profile_config();
auto value = std::to_string(_duration.Seconds());
config_set_string(conf, "SimpleOutput", "RecRBTime",
value.c_str());
config_set_string(conf, "AdvOut", "RecRBTime", value.c_str());
if (config_save(conf) != CONFIG_SUCCESS) {
blog(LOG_WARNING,
"failed to set replay buffer duration");
}
break;
}
default: default:
break; break;
} }
@@ -58,14 +77,15 @@ bool MacroActionReplayBuffer::Save(obs_data_t *obj) const
{ {
MacroAction::Save(obj); MacroAction::Save(obj);
obs_data_set_int(obj, "action", static_cast<int>(_action)); obs_data_set_int(obj, "action", static_cast<int>(_action));
_duration.Save(obj);
return true; return true;
} }
bool MacroActionReplayBuffer::Load(obs_data_t *obj) bool MacroActionReplayBuffer::Load(obs_data_t *obj)
{ {
MacroAction::Load(obj); MacroAction::Load(obj);
_action = static_cast<ReplayBufferAction>( _action = static_cast<Action>(obs_data_get_int(obj, "action"));
obs_data_get_int(obj, "action")); _duration.Load(obj);
return true; return true;
} }
@@ -90,23 +110,24 @@ MacroActionReplayBufferEdit::MacroActionReplayBufferEdit(
QWidget *parent, std::shared_ptr<MacroActionReplayBuffer> entryData) QWidget *parent, std::shared_ptr<MacroActionReplayBuffer> entryData)
: QWidget(parent), : QWidget(parent),
_actions(new QComboBox()), _actions(new QComboBox()),
_saveWarning(new QLabel( _warning(new QLabel(
obs_module_text("AdvSceneSwitcher.action.replay.saveWarn"))) obs_module_text("AdvSceneSwitcher.action.replay.saveWarn"))),
_duration(new DurationSelection(this, false, 5.))
{ {
populateActionSelection(_actions); populateActionSelection(_actions);
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this, QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
SLOT(ActionChanged(int))); SLOT(ActionChanged(int)));
QWidget::connect(_duration, SIGNAL(DurationChanged(const Duration &)),
this, SLOT(DurationChanged(const Duration &)));
QHBoxLayout *layout = new QHBoxLayout; auto layout = new QHBoxLayout;
std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
{"{{actions}}", _actions},
};
PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.replay.entry"), PlaceWidgets(obs_module_text("AdvSceneSwitcher.action.replay.entry"),
layout, widgetPlaceholders); layout,
{{"{{actions}}", _actions}, {"{{duration}}", _duration}});
QVBoxLayout *mainLayout = new QVBoxLayout; QVBoxLayout *mainLayout = new QVBoxLayout;
mainLayout->addLayout(layout); mainLayout->addLayout(layout);
mainLayout->addWidget(_saveWarning); mainLayout->addWidget(_warning);
setLayout(mainLayout); setLayout(mainLayout);
_entryData = entryData; _entryData = entryData;
@@ -120,21 +141,41 @@ void MacroActionReplayBufferEdit::UpdateEntryData()
return; return;
} }
_actions->setCurrentIndex(static_cast<int>(_entryData->_action)); _actions->setCurrentIndex(static_cast<int>(_entryData->_action));
_saveWarning->setVisible(_entryData->_action == _duration->SetDuration(_entryData->_duration);
ReplayBufferAction::SAVE); SetWidgetVisiblity();
}
void MacroActionReplayBufferEdit::SetWidgetVisiblity()
{
_warning->setVisible(_entryData->_action ==
MacroActionReplayBuffer::Action::SAVE);
_duration->setVisible(_entryData->_action ==
MacroActionReplayBuffer::Action::DURATION);
_warning->setText(obs_module_text(
(_entryData->_action == MacroActionReplayBuffer::Action::SAVE)
? "AdvSceneSwitcher.action.replay.saveWarn"
: "AdvSceneSwitcher.action.replay.durationWarn"));
_warning->setVisible(_entryData->_action ==
MacroActionReplayBuffer::Action::SAVE ||
_entryData->_action ==
MacroActionReplayBuffer::Action::DURATION);
adjustSize();
updateGeometry();
} }
void MacroActionReplayBufferEdit::ActionChanged(int value) void MacroActionReplayBufferEdit::ActionChanged(int value)
{ {
if (_loading || !_entryData) { GUARD_LOADING_AND_LOCK();
return; _entryData->_action =
} static_cast<MacroActionReplayBuffer::Action>(value);
auto lock = LockContext(); SetWidgetVisiblity();
_entryData->_action = static_cast<ReplayBufferAction>(value); }
_saveWarning->setVisible(_entryData->_action ==
ReplayBufferAction::SAVE); void MacroActionReplayBufferEdit::DurationChanged(const Duration &duration)
adjustSize(); {
GUARD_LOADING_AND_LOCK();
_entryData->_duration = duration;
} }
} // namespace advss } // namespace advss

View File

@@ -6,12 +6,6 @@
namespace advss { namespace advss {
enum class ReplayBufferAction {
STOP,
START,
SAVE,
};
class MacroActionReplayBuffer : public MacroAction { class MacroActionReplayBuffer : public MacroAction {
public: public:
MacroActionReplayBuffer(Macro *m) : MacroAction(m) {} MacroActionReplayBuffer(Macro *m) : MacroAction(m) {}
@@ -23,7 +17,14 @@ public:
static std::shared_ptr<MacroAction> Create(Macro *m); static std::shared_ptr<MacroAction> Create(Macro *m);
std::shared_ptr<MacroAction> Copy() const; std::shared_ptr<MacroAction> Copy() const;
ReplayBufferAction _action = ReplayBufferAction::STOP; enum class Action {
STOP,
START,
SAVE,
DURATION,
};
Action _action = Action::STOP;
Duration _duration;
private: private:
static bool _registered; static bool _registered;
@@ -49,13 +50,16 @@ public:
private slots: private slots:
void ActionChanged(int value); void ActionChanged(int value);
void DurationChanged(const Duration &);
protected:
QComboBox *_actions;
QLabel *_saveWarning;
std::shared_ptr<MacroActionReplayBuffer> _entryData;
private: private:
void SetWidgetVisiblity();
QComboBox *_actions;
QLabel *_warning;
DurationSelection *_duration;
std::shared_ptr<MacroActionReplayBuffer> _entryData;
bool _loading = true; bool _loading = true;
}; };

View File

@@ -1,6 +1,5 @@
#include "macro-action-run.hpp" #include "macro-action-run.hpp"
#include "layout-helpers.hpp" #include "layout-helpers.hpp"
#include "ui-helpers.hpp"
#include <QProcess> #include <QProcess>
#include <QDesktopServices> #include <QDesktopServices>
@@ -130,16 +129,10 @@ MacroActionRunEdit::MacroActionRunEdit(
_waitLayout(new QHBoxLayout()), _waitLayout(new QHBoxLayout()),
_wait(new QCheckBox()), _wait(new QCheckBox()),
_timeout(new DurationSelection(this, true, 0.1)), _timeout(new DurationSelection(this, true, 0.1)),
_waitHelp(new QLabel()) _waitHelp(new HelpIcon(obs_module_text(
"AdvSceneSwitcher.action.run.wait.help.tooltip")))
{ {
QString helpIconPath = GetThemeTypeName() == "Light"
? ":/res/images/help.svg"
: ":/res/images/help_light.svg";
QIcon helpIcon(helpIconPath);
_waitHelp->setPixmap(helpIcon.pixmap(QSize(16, 16)));
_waitHelp->hide(); _waitHelp->hide();
_waitHelp->setToolTip(obs_module_text(
"AdvSceneSwitcher.action.run.wait.help.tooltip"));
QWidget::connect(_procConfig, QWidget::connect(_procConfig,
SIGNAL(ConfigChanged(const ProcessConfig &)), this, SIGNAL(ConfigChanged(const ProcessConfig &)), this,

View File

@@ -1,5 +1,6 @@
#pragma once #pragma once
#include "macro-action-edit.hpp" #include "macro-action-edit.hpp"
#include "help-icon.hpp"
#include "process-config.hpp" #include "process-config.hpp"
#include "duration-control.hpp" #include "duration-control.hpp"
@@ -60,7 +61,7 @@ private:
QHBoxLayout *_waitLayout; QHBoxLayout *_waitLayout;
QCheckBox *_wait; QCheckBox *_wait;
DurationSelection *_timeout; DurationSelection *_timeout;
QLabel *_waitHelp; HelpIcon *_waitHelp;
std::shared_ptr<MacroActionRun> _entryData; std::shared_ptr<MacroActionRun> _entryData;
bool _loading = true; bool _loading = true;

View File

@@ -197,11 +197,7 @@ MacroActionSequenceEdit::MacroActionSequenceEdit(
_resetIndex->setMinimum(1); _resetIndex->setMinimum(1);
auto line = new QFrame(); (void)_macroList->AddControl(_continueFrom);
line->setFrameShape(QFrame::VLine);
line->setFrameShadow(QFrame::Sunken);
_macroList->AddControl(line);
_macroList->AddControl(_continueFrom);
QWidget::connect(_macroList, SIGNAL(Added(const std::string &)), this, QWidget::connect(_macroList, SIGNAL(Added(const std::string &)), this,
SLOT(Add(const std::string &))); SLOT(Add(const std::string &)));

View File

@@ -36,6 +36,8 @@ const static std::map<MacroActionSource::Action, std::string> actionTypes = {
"AdvSceneSwitcher.action.source.type.openFilterDialog"}, "AdvSceneSwitcher.action.source.type.openFilterDialog"},
{MacroActionSource::Action::OPEN_PROPERTIES_DIALOG, {MacroActionSource::Action::OPEN_PROPERTIES_DIALOG,
"AdvSceneSwitcher.action.source.type.openPropertiesDialog"}, "AdvSceneSwitcher.action.source.type.openPropertiesDialog"},
{MacroActionSource::Action::INTERACT,
"AdvSceneSwitcher.action.source.type.interact"},
}; };
const static std::map<obs_deinterlace_mode, std::string> deinterlaceModes = { const static std::map<obs_deinterlace_mode, std::string> deinterlaceModes = {
@@ -142,6 +144,9 @@ bool MacroActionSource::PerformAction()
case Action::SETTINGS_BUTTON: case Action::SETTINGS_BUTTON:
PressSourceButton(_button, s); PressSourceButton(_button, s);
break; break;
case Action::INTERACT:
_interaction.SendToSource(s);
break;
case Action::DEINTERLACE_MODE: case Action::DEINTERLACE_MODE:
obs_source_set_deinterlace_mode(s, _deinterlaceMode); obs_source_set_deinterlace_mode(s, _deinterlaceMode);
break; break;
@@ -199,6 +204,7 @@ bool MacroActionSource::Save(obs_data_t *obj) const
static_cast<int>(_deinterlaceMode)); static_cast<int>(_deinterlaceMode));
obs_data_set_int(obj, "deinterlaceOrder", obs_data_set_int(obj, "deinterlaceOrder",
static_cast<int>(_deinterlaceOrder)); static_cast<int>(_deinterlaceOrder));
_interaction.Save(obj);
return true; return true;
} }
@@ -223,6 +229,7 @@ bool MacroActionSource::Load(obs_data_t *obj)
obs_data_get_int(obj, "deinterlaceMode")); obs_data_get_int(obj, "deinterlaceMode"));
_deinterlaceOrder = static_cast<obs_deinterlace_field_order>( _deinterlaceOrder = static_cast<obs_deinterlace_field_order>(
obs_data_get_int(obj, "deinterlaceOrder")); obs_data_get_int(obj, "deinterlaceOrder"));
_interaction.Load(obj);
return true; return true;
} }
@@ -309,7 +316,8 @@ MacroActionSourceEdit::MacroActionSourceEdit(
_warning(new QLabel( _warning(new QLabel(
obs_module_text("AdvSceneSwitcher.action.source.warning"))), obs_module_text("AdvSceneSwitcher.action.source.warning"))),
_refreshSettingSelection(new QPushButton( _refreshSettingSelection(new QPushButton(
obs_module_text("AdvSceneSwitcher.action.source.refresh"))) obs_module_text("AdvSceneSwitcher.action.source.refresh"))),
_interaction(new SourceInteractionWidget())
{ {
populateActionSelection(_actions); populateActionSelection(_actions);
auto sources = GetSourceNames(); auto sources = GetSourceNames();
@@ -349,6 +357,13 @@ MacroActionSourceEdit::MacroActionSourceEdit(
SLOT(SelectionChanged(const SourceSetting &))); SLOT(SelectionChanged(const SourceSetting &)));
QWidget::connect(_refreshSettingSelection, SIGNAL(clicked()), this, QWidget::connect(_refreshSettingSelection, SIGNAL(clicked()), this,
SLOT(RefreshVariableSourceSelectionValue())); SLOT(RefreshVariableSourceSelectionValue()));
QWidget::connect(
_interaction,
SIGNAL(SettingsChanged(SourceInteractionInstance *)), this,
SLOT(InteractionSettingsChanged(SourceInteractionInstance *)));
QWidget::connect(_interaction,
SIGNAL(TypeChanged(SourceInteraction::Type)), this,
SLOT(InteractionTypeChanged(SourceInteraction::Type)));
auto entryLayout = new QHBoxLayout; auto entryLayout = new QHBoxLayout;
entryLayout->setContentsMargins(0, 0, 0, 0); entryLayout->setContentsMargins(0, 0, 0, 0);
@@ -381,6 +396,7 @@ MacroActionSourceEdit::MacroActionSourceEdit(
buttonLayout->addWidget(_getSettings); buttonLayout->addWidget(_getSettings);
buttonLayout->addStretch(); buttonLayout->addStretch();
mainLayout->addLayout(buttonLayout); mainLayout->addLayout(buttonLayout);
mainLayout->addWidget(_interaction);
setLayout(mainLayout); setLayout(mainLayout);
_entryData = entryData; _entryData = entryData;
@@ -411,6 +427,7 @@ void MacroActionSourceEdit::UpdateEntryData()
static_cast<int>(_entryData->_settingsInputMethod))); static_cast<int>(_entryData->_settingsInputMethod)));
_tempVars->SetVariable(_entryData->_tempVar); _tempVars->SetVariable(_entryData->_tempVar);
_manualSettingValue->setPlainText(_entryData->_manualSettingValue); _manualSettingValue->setPlainText(_entryData->_manualSettingValue);
_interaction->SetSourceInteractionSelection(_entryData->_interaction);
SetWidgetVisibility(); SetWidgetVisibility();
} }
@@ -561,6 +578,29 @@ void MacroActionSourceEdit::ManualSettingsValueChanged()
updateGeometry(); updateGeometry();
} }
void MacroActionSourceEdit::InteractionTypeChanged(SourceInteraction::Type value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_interaction.SetType(value);
adjustSize();
updateGeometry();
}
void MacroActionSourceEdit::InteractionSettingsChanged(
SourceInteractionInstance *value)
{
if (_loading || !_entryData) {
return;
}
auto lock = LockContext();
_entryData->_interaction.SetSettings(value);
}
void MacroActionSourceEdit::RefreshVariableSourceSelectionValue() void MacroActionSourceEdit::RefreshVariableSourceSelectionValue()
{ {
_sourceSettings->SetSource(_entryData->_source.GetSource()); _sourceSettings->SetSource(_entryData->_source.GetSource());
@@ -617,6 +657,8 @@ void MacroActionSourceEdit::SetWidgetVisibility()
_entryData->_source.GetType() == _entryData->_source.GetType() ==
SourceSelection::Type::VARIABLE); SourceSelection::Type::VARIABLE);
_interaction->setVisible(_entryData->_action ==
MacroActionSource::Action::INTERACT);
adjustSize(); adjustSize();
updateGeometry(); updateGeometry();
} }

Some files were not shown because too many files have changed in this diff Show More