mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-08-30 05:06:14 -05:00
Compare commits
2 Commits
test
...
record-pat
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a69e774c2 | ||
|
|
2389f37ed6 |
4
.github/scripts/.build.zsh
vendored
4
.github/scripts/.build.zsh
vendored
@@ -255,10 +255,6 @@ ${_usage_host:-}"
|
|||||||
|
|
||||||
cmake_args+=(
|
cmake_args+=(
|
||||||
-DCMAKE_PREFIX_PATH="${advss_deps_path}"
|
-DCMAKE_PREFIX_PATH="${advss_deps_path}"
|
||||||
-DOPENSSL_ROOT_DIR="${advss_deps_path}"
|
|
||||||
-DOPENSSL_INCLUDE_DIR="${advss_deps_path}/include"
|
|
||||||
-DOPENSSL_CRYPTO_LIBRARY="${advss_deps_path}/lib/libcrypto.a"
|
|
||||||
-DOPENSSL_SSL_LIBRARY="${advss_deps_path}/lib/libssl.a"
|
|
||||||
--preset ${_preset}
|
--preset ${_preset}
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
3
.github/scripts/utils.zsh/check_macos
vendored
3
.github/scripts/utils.zsh/check_macos
vendored
@@ -18,4 +18,7 @@ if (( ! ${+commands[brew]} )) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
brew bundle --file ${SCRIPT_HOME}/.Brewfile
|
brew bundle --file ${SCRIPT_HOME}/.Brewfile
|
||||||
|
# Workaround to make sure locally built openssl is picked up by cmake
|
||||||
|
brew uninstall --ignore-dependencies openssl@3 || true
|
||||||
|
rehash || true
|
||||||
log_group
|
log_group
|
||||||
|
|||||||
2
.github/workflows/build-project.yaml
vendored
2
.github/workflows/build-project.yaml
vendored
@@ -6,7 +6,7 @@ on:
|
|||||||
description: "Project name detected by parsing build spec file"
|
description: "Project name detected by parsing build spec file"
|
||||||
value: ${{ jobs.check-event.outputs.pluginName }}
|
value: ${{ jobs.check-event.outputs.pluginName }}
|
||||||
env:
|
env:
|
||||||
DEP_DIR: .deps/advss-build-dependencies-4
|
DEP_DIR: .deps/advss-build-dependencies-3
|
||||||
jobs:
|
jobs:
|
||||||
check-event:
|
check-event:
|
||||||
name: Check GitHub Event Data 🔎
|
name: Check GitHub Event Data 🔎
|
||||||
|
|||||||
@@ -6,18 +6,18 @@ You have the option to ...
|
|||||||
|
|
||||||
Both methods require [CMake](https://cmake.org/download/).
|
Both methods require [CMake](https://cmake.org/download/).
|
||||||
|
|
||||||
The plugin can be compiled for OBS 31 and above, although using the latest version of OBS is recommended to support all features.
|
The plugin can be compiled for OBS 27 and above, although using the latest version of OBS is recommended to support all features.
|
||||||
|
|
||||||
## Compiling in tree (recommended for development)
|
## Compiling in tree (recommended for development)
|
||||||
This section assumes that you have a working [OBS Studio development environment](https://obsproject.com/wiki/Building-OBS-Studio).
|
This section assumes that you have a working [OBS Studio development environment](https://obsproject.com/wiki/Building-OBS-Studio).
|
||||||
|
|
||||||
Add the "SceneSwitcher" source directory to your obs-studio source directory under obs-studio/plugins:
|
Add the "SceneSwitcher" source directory to your obs-studio source directory under obs-studio/UI/frontend-plugins/:
|
||||||
```
|
```
|
||||||
cd obs-studio/plugins
|
cd obs-studio/UI/frontend-plugins/
|
||||||
git clone --recursive https://github.com/WarmUpTill/SceneSwitcher.git
|
git clone --recursive https://github.com/WarmUpTill/SceneSwitcher.git
|
||||||
```
|
```
|
||||||
|
|
||||||
Then modify the obs-studio/plugins/CMakeLists.txt and add an entry for the scene switcher:
|
Then modify the obs-studio/UI/frontend-plugins/CMakeLists.txt Example and add an entry for the scene switcher:
|
||||||
```
|
```
|
||||||
add_subdirectory(SceneSwitcher)
|
add_subdirectory(SceneSwitcher)
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -166,7 +166,6 @@ target_sources(
|
|||||||
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
|
||||||
lib/macro/macro-websocket-trigger.cpp
|
|
||||||
lib/macro/macro.cpp
|
lib/macro/macro.cpp
|
||||||
lib/macro/macro.hpp)
|
lib/macro/macro.hpp)
|
||||||
|
|
||||||
@@ -185,8 +184,6 @@ target_sources(
|
|||||||
lib/utils/canvas-helpers.hpp
|
lib/utils/canvas-helpers.hpp
|
||||||
lib/utils/condition-logic.cpp
|
lib/utils/condition-logic.cpp
|
||||||
lib/utils/condition-logic.hpp
|
lib/utils/condition-logic.hpp
|
||||||
lib/utils/crash-handler.cpp
|
|
||||||
lib/utils/crash-handler.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.cpp
|
||||||
@@ -204,8 +201,6 @@ 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/first-run-wizard.cpp
|
|
||||||
lib/utils/first-run-wizard.hpp
|
|
||||||
lib/utils/help-icon.hpp
|
lib/utils/help-icon.hpp
|
||||||
lib/utils/help-icon.cpp
|
lib/utils/help-icon.cpp
|
||||||
lib/utils/item-selection-helpers.cpp
|
lib/utils/item-selection-helpers.cpp
|
||||||
@@ -456,29 +451,14 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
if(PROCPS2_INCLUDE_DIR)
|
if(PROCPS2_INCLUDE_DIR)
|
||||||
find_package(PkgConfig REQUIRED)
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(libproc2 IMPORTED_TARGET libproc2<4.0.5 QUIET)
|
||||||
|
if(libproc2_FOUND)
|
||||||
|
target_compile_definitions(${LIB_NAME} PRIVATE PROCPS2_USE_INFO)
|
||||||
|
endif()
|
||||||
pkg_check_modules(libproc2 REQUIRED IMPORTED_TARGET libproc2)
|
pkg_check_modules(libproc2 REQUIRED IMPORTED_TARGET libproc2)
|
||||||
set(PROC_INCLUDE_DIR "${PROCPS2_INCLUDE_DIR}")
|
set(PROC_INCLUDE_DIR "${PROCPS2_INCLUDE_DIR}")
|
||||||
target_compile_definitions(${LIB_NAME} PRIVATE PROCPS2_AVAILABLE)
|
target_compile_definitions(${LIB_NAME} PRIVATE PROCPS2_AVAILABLE)
|
||||||
set(PROCESS_CONDITION_SUPPORTED 1)
|
set(PROCESS_CONDITION_SUPPORTED 1)
|
||||||
|
|
||||||
# Check if PIDS_VAL takes 4 arguments (old API, pre-4.0.5) or 3 (new API)
|
|
||||||
include(CheckCSourceCompiles)
|
|
||||||
set(CMAKE_REQUIRED_INCLUDES "${PROCPS2_INCLUDE_DIR}")
|
|
||||||
set(CMAKE_REQUIRED_LIBRARIES proc2)
|
|
||||||
check_c_source_compiles(
|
|
||||||
"
|
|
||||||
#include <libproc2/pids.h>
|
|
||||||
int main(void) {
|
|
||||||
struct pids_stack *s = 0;
|
|
||||||
struct pids_info *i = 0;
|
|
||||||
(void)PIDS_VAL(0, str, s, i);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
"
|
|
||||||
PROCPS2_PIDS_VAL_TAKES_INFO)
|
|
||||||
if(PROCPS2_PIDS_VAL_TAKES_INFO)
|
|
||||||
target_compile_definitions(${LIB_NAME} PRIVATE PROCPS2_USE_INFO)
|
|
||||||
endif()
|
|
||||||
endif()
|
endif()
|
||||||
if(NOT DEFINED PROCESS_CONDITION_SUPPORTED)
|
if(NOT DEFINED PROCESS_CONDITION_SUPPORTED)
|
||||||
message(
|
message(
|
||||||
@@ -504,11 +484,7 @@ endif()
|
|||||||
# --- End of section ---
|
# --- End of section ---
|
||||||
|
|
||||||
add_subdirectory(plugins)
|
add_subdirectory(plugins)
|
||||||
|
add_subdirectory(tests)
|
||||||
option(ADVSS_ENABLE_TESTS "Build advanced-scene-switcher unit tests" OFF)
|
|
||||||
if(ADVSS_ENABLE_TESTS)
|
|
||||||
add_subdirectory(tests)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# --- Install ---
|
# --- Install ---
|
||||||
|
|
||||||
|
|||||||
@@ -41,8 +41,7 @@
|
|||||||
"description": "Build for macOS 11.0+ (Universal binary) for CI",
|
"description": "Build for macOS 11.0+ (Universal binary) for CI",
|
||||||
"generator": "Xcode",
|
"generator": "Xcode",
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_COMPILE_WARNING_AS_ERROR": true,
|
"CMAKE_COMPILE_WARNING_AS_ERROR": true
|
||||||
"ADVSS_ENABLE_TESTS": true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -70,8 +69,7 @@
|
|||||||
"displayName": "Windows x64 CI build",
|
"displayName": "Windows x64 CI build",
|
||||||
"description": "Build for Windows x64 on CI",
|
"description": "Build for Windows x64 on CI",
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_COMPILE_WARNING_AS_ERROR": true,
|
"CMAKE_COMPILE_WARNING_AS_ERROR": true
|
||||||
"ADVSS_ENABLE_TESTS": true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -99,8 +97,7 @@
|
|||||||
"description": "Build for Linux x86_64 on CI",
|
"description": "Build for Linux x86_64 on CI",
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
|
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
|
||||||
"CMAKE_COMPILE_WARNING_AS_ERROR": true,
|
"CMAKE_COMPILE_WARNING_AS_ERROR": true
|
||||||
"ADVSS_ENABLE_TESTS": true
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -128,8 +125,7 @@
|
|||||||
"description": "Build for Linux aarch64 on CI",
|
"description": "Build for Linux aarch64 on CI",
|
||||||
"cacheVariables": {
|
"cacheVariables": {
|
||||||
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
|
"CMAKE_BUILD_TYPE": "RelWithDebInfo",
|
||||||
"CMAKE_COMPILE_WARNING_AS_ERROR": true,
|
"CMAKE_COMPILE_WARNING_AS_ERROR": true
|
||||||
"ADVSS_ENABLE_TESTS": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -14,6 +14,11 @@ On Linux the plugin is available via the **Flatpak** package manager for users w
|
|||||||
flatpak install com.obsproject.Studio.Plugin.SceneSwitcher
|
flatpak install com.obsproject.Studio.Plugin.SceneSwitcher
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The **Snap** package manager offers an OBS Studio installation which is bundled with the plugin:
|
||||||
|
```
|
||||||
|
sudo snap install obs-studio
|
||||||
|
```
|
||||||
|
|
||||||
More information can be found [here](https://github.com/WarmUpTill/SceneSwitcher/wiki/Installation).
|
More information can be found [here](https://github.com/WarmUpTill/SceneSwitcher/wiki/Installation).
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ function(_git_find_closest_git_dir _start_dir _git_dir_var)
|
|||||||
while(NOT EXISTS "${git_dir}")
|
while(NOT EXISTS "${git_dir}")
|
||||||
# .git dir not found, search parent directories
|
# .git dir not found, search parent directories
|
||||||
set(git_previous_parent "${cur_dir}")
|
set(git_previous_parent "${cur_dir}")
|
||||||
get_filename_component(cur_dir "${cur_dir}" DIRECTORY)
|
get_filename_component(cur_dir ${cur_dir} DIRECTORY)
|
||||||
if(cur_dir STREQUAL git_previous_parent)
|
if(cur_dir STREQUAL git_previous_parent)
|
||||||
# We have reached the root directory, we are not in git
|
# We have reached the root directory, we are not in git
|
||||||
set(${_git_dir_var}
|
set(${_git_dir_var}
|
||||||
|
|||||||
@@ -76,6 +76,7 @@ AdvSceneSwitcher.macroTab.name="Name:"
|
|||||||
AdvSceneSwitcher.macroTab.run="Makro ausführen"
|
AdvSceneSwitcher.macroTab.run="Makro ausführen"
|
||||||
AdvSceneSwitcher.macroTab.runFail="Ausführen von \"%1\" fehlgeschlagen!\nEntweder ist eine der Aktionen fehlgeschlagen oder das Makro wird bereits ausgeführt.\nSoll die aktuelle Ausführung gestoppt werden?"
|
AdvSceneSwitcher.macroTab.runFail="Ausführen von \"%1\" fehlgeschlagen!\nEntweder ist eine der Aktionen fehlgeschlagen oder das Makro wird bereits ausgeführt.\nSoll die aktuelle Ausführung gestoppt werden?"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="Parallel zu anderen Makros ausführen"
|
AdvSceneSwitcher.macroTab.runInParallel="Parallel zu anderen Makros ausführen"
|
||||||
|
AdvSceneSwitcher.macroTab.onChange="Nur bei Änderung ausführen"
|
||||||
AdvSceneSwitcher.macroTab.defaultname="Makro %1"
|
AdvSceneSwitcher.macroTab.defaultname="Makro %1"
|
||||||
AdvSceneSwitcher.macroTab.defaultGroupName="Gruppe %1"
|
AdvSceneSwitcher.macroTab.defaultGroupName="Gruppe %1"
|
||||||
AdvSceneSwitcher.macroTab.removeGroupPopup.text="Sicher, dass \"%1\" und alle zugehörigen Elemente gelöscht werden?"
|
AdvSceneSwitcher.macroTab.removeGroupPopup.text="Sicher, dass \"%1\" und alle zugehörigen Elemente gelöscht werden?"
|
||||||
@@ -145,7 +146,11 @@ AdvSceneSwitcher.condition.file="Datei"
|
|||||||
AdvSceneSwitcher.condition.file.type.match="entspricht"
|
AdvSceneSwitcher.condition.file.type.match="entspricht"
|
||||||
AdvSceneSwitcher.condition.file.type.contentChange="Inhalt geändert"
|
AdvSceneSwitcher.condition.file.type.contentChange="Inhalt geändert"
|
||||||
AdvSceneSwitcher.condition.file.type.dateChange="Änderungsdatum geändert"
|
AdvSceneSwitcher.condition.file.type.dateChange="Änderungsdatum geändert"
|
||||||
AdvSceneSwitcher.condition.file.layout="{{filePath}}{{conditions}}{{regex}}"
|
AdvSceneSwitcher.condition.file.remote="Entfernte Datei"
|
||||||
|
AdvSceneSwitcher.condition.file.local="Lokale Datei"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||||
AdvSceneSwitcher.condition.media="Medien"
|
AdvSceneSwitcher.condition.media="Medien"
|
||||||
AdvSceneSwitcher.condition.media.source="Quelle"
|
AdvSceneSwitcher.condition.media.source="Quelle"
|
||||||
AdvSceneSwitcher.condition.media.anyOnScene="Beliebige Medienquelle in"
|
AdvSceneSwitcher.condition.media.anyOnScene="Beliebige Medienquelle in"
|
||||||
@@ -211,8 +216,8 @@ AdvSceneSwitcher.condition.record.state.start="Aufnahme läuft"
|
|||||||
AdvSceneSwitcher.condition.record.state.pause="Aufnahme pausiert"
|
AdvSceneSwitcher.condition.record.state.pause="Aufnahme pausiert"
|
||||||
AdvSceneSwitcher.condition.record.state.stop="Aufnahme gestoppt"
|
AdvSceneSwitcher.condition.record.state.stop="Aufnahme gestoppt"
|
||||||
AdvSceneSwitcher.condition.process="Prozess"
|
AdvSceneSwitcher.condition.process="Prozess"
|
||||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}läuft{{focused}}und ist fokusiert"
|
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}läuft{{focused}}und ist fokusiert"
|
||||||
AdvSceneSwitcher.condition.process.layout.focus="Aktueller Vordergrundprozess: {{focusProcess}}"
|
AdvSceneSwitcher.condition.process.entry.focus="Aktueller Vordergrundprozess: {{focusProcess}}"
|
||||||
AdvSceneSwitcher.condition.idle="Leerlauf"
|
AdvSceneSwitcher.condition.idle="Leerlauf"
|
||||||
AdvSceneSwitcher.condition.idle.entry="Keine Tastatur- oder Mauseingaben für {{duration}}"
|
AdvSceneSwitcher.condition.idle.entry="Keine Tastatur- oder Mauseingaben für {{duration}}"
|
||||||
AdvSceneSwitcher.condition.pluginState="Plugin-Status"
|
AdvSceneSwitcher.condition.pluginState="Plugin-Status"
|
||||||
@@ -286,14 +291,14 @@ AdvSceneSwitcher.condition.replay.state.started="Replay Buffer gestartet"
|
|||||||
AdvSceneSwitcher.condition.replay.state.saved="Replay Buffer gespeichert"
|
AdvSceneSwitcher.condition.replay.state.saved="Replay Buffer gespeichert"
|
||||||
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
||||||
AdvSceneSwitcher.condition.date="Datum"
|
AdvSceneSwitcher.condition.date="Datum"
|
||||||
AdvSceneSwitcher.day.any="Beliebiger Tag"
|
AdvSceneSwitcher.condition.date.anyDay="Beliebiger Tag"
|
||||||
AdvSceneSwitcher.day.monday="Montag"
|
AdvSceneSwitcher.condition.date.monday="Montag"
|
||||||
AdvSceneSwitcher.day.tuesday="Dienstag"
|
AdvSceneSwitcher.condition.date.tuesday="Dienstag"
|
||||||
AdvSceneSwitcher.day.wednesday="Mittwoch"
|
AdvSceneSwitcher.condition.date.wednesday="Mittwoch"
|
||||||
AdvSceneSwitcher.day.thursday="Donnerstag"
|
AdvSceneSwitcher.condition.date.thursday="Donnerstag"
|
||||||
AdvSceneSwitcher.day.friday="Freitag"
|
AdvSceneSwitcher.condition.date.friday="Freitag"
|
||||||
AdvSceneSwitcher.day.saturday="Samstag"
|
AdvSceneSwitcher.condition.date.saturday="Samstag"
|
||||||
AdvSceneSwitcher.day.sunday="Sonntag"
|
AdvSceneSwitcher.condition.date.sunday="Sonntag"
|
||||||
AdvSceneSwitcher.condition.date.state.at="Am"
|
AdvSceneSwitcher.condition.date.state.at="Am"
|
||||||
AdvSceneSwitcher.condition.date.state.after="Nach"
|
AdvSceneSwitcher.condition.date.state.after="Nach"
|
||||||
AdvSceneSwitcher.condition.date.state.before="Vor"
|
AdvSceneSwitcher.condition.date.state.before="Vor"
|
||||||
@@ -304,13 +309,12 @@ AdvSceneSwitcher.condition.date.ignoreDate="Wenn diese Option nicht aktiviert is
|
|||||||
AdvSceneSwitcher.condition.date.ignoreTime="Wenn diese Option nicht aktiviert ist, wird die Zeitkomponente ignoriert"
|
AdvSceneSwitcher.condition.date.ignoreTime="Wenn diese Option nicht aktiviert ist, wird die Zeitkomponente ignoriert"
|
||||||
AdvSceneSwitcher.condition.date.showAdvancedSettings="Erweiterte Einstellungen anzeigen"
|
AdvSceneSwitcher.condition.date.showAdvancedSettings="Erweiterte Einstellungen anzeigen"
|
||||||
AdvSceneSwitcher.condition.date.showSimpleSettings="Einfache Einstellungen anzeigen"
|
AdvSceneSwitcher.condition.date.showSimpleSettings="Einfache Einstellungen anzeigen"
|
||||||
AdvSceneSwitcher.condition.date.layout.simple.day="Am{{dayOfWeek}}"
|
AdvSceneSwitcher.condition.date.entry.simple="Am {{dayOfWeek}} {{weekCondition}} {{ignoreWeekTime}}{{weekTime}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.simple.time="{{ignoreWeekTime}}{{weekCondition}}{{weekTime}}"
|
AdvSceneSwitcher.condition.date.entry.advanced="{{condition}} {{ignoreDate}}{{date}} {{ignoreTime}}{{time}} {{separator}} {{date2}} {{time2}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.advanced="{{condition}} {{ignoreDate}}{{date}} {{ignoreTime}}{{time}} {{separator}} {{date2}} {{time2}}"
|
AdvSceneSwitcher.condition.date.entry.repeat="{{repeat}} Wiederholen alle {{duration}} bei Datumsübereinstimmung"
|
||||||
AdvSceneSwitcher.condition.date.layout.repeat="{{repeat}} Wiederholen alle {{duration}} bei Datumsübereinstimmung"
|
AdvSceneSwitcher.condition.date.entry.pattern="Aktuelles Datum \"{{currentDate}}\" entspricht dem Muster {{pattern}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.pattern="Aktuelles Datum \"{{currentDate}}\" entspricht dem Muster {{pattern}}"
|
AdvSceneSwitcher.condition.date.entry.nextMatchDate="Nächster Treffer bei: %1"
|
||||||
AdvSceneSwitcher.condition.date.layout.nextMatchDate="Nächster Treffer bei: %1"
|
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} Bei Wiederholung ausgewähltes Datum auf Wiederholungsdatum aktualisieren"
|
||||||
AdvSceneSwitcher.condition.date.layout.updateOnRepeat="{{updateOnRepeat}} Bei Wiederholung ausgewähltes Datum auf Wiederholungsdatum aktualisieren"
|
|
||||||
AdvSceneSwitcher.condition.sceneTransform="Szenenelement transformieren"
|
AdvSceneSwitcher.condition.sceneTransform="Szenenelement transformieren"
|
||||||
AdvSceneSwitcher.condition.sceneTransform.getTransform="Transformation erhalten"
|
AdvSceneSwitcher.condition.sceneTransform.getTransform="Transformation erhalten"
|
||||||
AdvSceneSwitcher.condition.sceneTransform.condition.match="entspricht Transformation"
|
AdvSceneSwitcher.condition.sceneTransform.condition.match="entspricht Transformation"
|
||||||
@@ -408,6 +412,7 @@ AdvSceneSwitcher.action.recording.type.unpause="Aufnahme nicht mehr pausieren"
|
|||||||
AdvSceneSwitcher.action.recording.type.split="Aufnahme-Datei teilen"
|
AdvSceneSwitcher.action.recording.type.split="Aufnahme-Datei teilen"
|
||||||
AdvSceneSwitcher.action.recording.pause.hint="Bitte beachten, dass je nach Aufnahmeeinstellung die Aufnahme möglicherweise nicht unterbrochen werden kann"
|
AdvSceneSwitcher.action.recording.pause.hint="Bitte beachten, dass je nach Aufnahmeeinstellung die Aufnahme möglicherweise nicht unterbrochen werden kann"
|
||||||
AdvSceneSwitcher.action.recording.split.hint="Vergewissern, dass die automatische Dateiaufteilung in den OBS-Einstellungen aktiviert ist!"
|
AdvSceneSwitcher.action.recording.split.hint="Vergewissern, dass die automatische Dateiaufteilung in den OBS-Einstellungen aktiviert ist!"
|
||||||
|
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||||
AdvSceneSwitcher.action.replay="Replay Buffer"
|
AdvSceneSwitcher.action.replay="Replay Buffer"
|
||||||
AdvSceneSwitcher.action.replay.saveWarn="Warnung: Ein zu häufiges Speichern kann dazu führen, dass der Replay Buffer nicht gespeichert wird!"
|
AdvSceneSwitcher.action.replay.saveWarn="Warnung: Ein zu häufiges Speichern kann dazu führen, dass der Replay Buffer nicht gespeichert wird!"
|
||||||
AdvSceneSwitcher.action.replay.type.stop="Replay Buffer stoppen"
|
AdvSceneSwitcher.action.replay.type.stop="Replay Buffer stoppen"
|
||||||
@@ -416,6 +421,7 @@ AdvSceneSwitcher.action.replay.type.save="Replay Buffer speichern"
|
|||||||
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"
|
||||||
|
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}"
|
||||||
AdvSceneSwitcher.action.run="Ausführen"
|
AdvSceneSwitcher.action.run="Ausführen"
|
||||||
AdvSceneSwitcher.action.sceneVisibility="Sichtbarkeit von Szenenelementen"
|
AdvSceneSwitcher.action.sceneVisibility="Sichtbarkeit von Szenenelementen"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.show="Anzeigen"
|
AdvSceneSwitcher.action.sceneVisibility.type.show="Anzeigen"
|
||||||
@@ -423,7 +429,7 @@ AdvSceneSwitcher.action.sceneVisibility.type.hide="Verstecken"
|
|||||||
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Umschalten"
|
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Umschalten"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Quelle"
|
AdvSceneSwitcher.action.sceneVisibility.type.source="Quelle"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Beliebig"
|
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Beliebig"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.layout="Auf{{scenes}}{{actions}}{{sources}}"
|
AdvSceneSwitcher.action.sceneVisibility.entry="Auf{{scenes}}{{actions}}{{sources}}"
|
||||||
AdvSceneSwitcher.action.filter="Filter"
|
AdvSceneSwitcher.action.filter="Filter"
|
||||||
AdvSceneSwitcher.action.filter.type.enable="Aktivieren"
|
AdvSceneSwitcher.action.filter.type.enable="Aktivieren"
|
||||||
AdvSceneSwitcher.action.filter.type.disable="Deaktivieren"
|
AdvSceneSwitcher.action.filter.type.disable="Deaktivieren"
|
||||||
@@ -451,7 +457,7 @@ AdvSceneSwitcher.action.macro="Makro"
|
|||||||
AdvSceneSwitcher.action.macro.type.pause="Pausieren"
|
AdvSceneSwitcher.action.macro.type.pause="Pausieren"
|
||||||
AdvSceneSwitcher.action.macro.type.unpause="Nicht mehr pausieren"
|
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.runActions="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.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"
|
||||||
@@ -499,9 +505,9 @@ AdvSceneSwitcher.action.transition.type.scene="Szenenübergang"
|
|||||||
AdvSceneSwitcher.action.transition.type.sceneOverride="Szenenübergang überschreiben"
|
AdvSceneSwitcher.action.transition.type.sceneOverride="Szenenübergang überschreiben"
|
||||||
AdvSceneSwitcher.action.transition.type.sourceShow="Übergang der Quelle anzeigen"
|
AdvSceneSwitcher.action.transition.type.sourceShow="Übergang der Quelle anzeigen"
|
||||||
AdvSceneSwitcher.action.transition.type.sourceHide="Übergang der Quelle verstecken"
|
AdvSceneSwitcher.action.transition.type.sourceHide="Übergang der Quelle verstecken"
|
||||||
AdvSceneSwitcher.action.transition.layout.type="Anpassen {{type}}{{scenes}}{{sources}}"
|
AdvSceneSwitcher.action.transition.entry.line1="Anpassen {{type}}{{scenes}}{{sources}}"
|
||||||
AdvSceneSwitcher.action.transition.layout.transition="{{setTransition}}Übergangstyp festlegen auf {{transitions}}"
|
AdvSceneSwitcher.action.transition.entry.line2="{{setTransition}}Übergangstyp festlegen auf {{transitions}}"
|
||||||
AdvSceneSwitcher.action.transition.layout.duration="{{setDuration}}Übergangsdauer festlegen auf {{duration}}Sekunden"
|
AdvSceneSwitcher.action.transition.entry.line3="{{setDuration}}Übergangsdauer festlegen auf {{duration}}Sekunden"
|
||||||
AdvSceneSwitcher.action.timer="Timer"
|
AdvSceneSwitcher.action.timer="Timer"
|
||||||
AdvSceneSwitcher.action.timer.type.pause="Pausieren"
|
AdvSceneSwitcher.action.timer.type.pause="Pausieren"
|
||||||
AdvSceneSwitcher.action.timer.type.continue="Fortsetzen"
|
AdvSceneSwitcher.action.timer.type.continue="Fortsetzen"
|
||||||
@@ -828,6 +834,8 @@ AdvSceneSwitcher.status.inactive="Inaktiv"
|
|||||||
AdvSceneSwitcher.running="Plugin läuft"
|
AdvSceneSwitcher.running="Plugin läuft"
|
||||||
AdvSceneSwitcher.stopped="Plugin gestoppt"
|
AdvSceneSwitcher.stopped="Plugin gestoppt"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Dies scheint das erste Mal zu sein, dass der Erweiterte Szenenwechsler gestartet wurde.<br>Bitte schaue ins <a href=\"https://github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> für eine Liste von Anleitungen und Beispielen.<br>Nicht zögern und Fragen im <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">Thread</span></a> des Plugins im OBS-Forum stellen!!</p></body></html>"
|
||||||
|
|
||||||
AdvSceneSwitcher.deprecatedTabWarning="Die Entwicklung für dieses Tab wurde gestoppt!\nBitte stattdessen zur Verwendung des Makros-Tab übergehen.\nDieser Hinweis kann im Allgemein-Tab deaktiviert werden."
|
AdvSceneSwitcher.deprecatedTabWarning="Die Entwicklung für dieses Tab wurde gestoppt!\nBitte stattdessen zur Verwendung des Makros-Tab übergehen.\nDieser Hinweis kann im Allgemein-Tab deaktiviert werden."
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="Millisekunden"
|
AdvSceneSwitcher.unit.milliseconds="Millisekunden"
|
||||||
|
|||||||
@@ -40,13 +40,10 @@ AdvSceneSwitcher.generalTab.generalBehavior.showTrayNotifications="Show system t
|
|||||||
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="Disable UI hints"
|
AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints="Disable UI hints"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.comboBoxFilterDisable="Disable filtering by typing in drop down menus"
|
AdvSceneSwitcher.generalTab.generalBehavior.comboBoxFilterDisable="Disable filtering by typing in drop down menus"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailure="Display warning if plugins cannot be loaded"
|
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailure="Display warning if plugins cannot be loaded"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.suppressCrashRecoveryDialog="Do not ask to keep the plugin stopped after an unclean shutdown"
|
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailureMessage="<html><body>Loading of the following plugin libraries was unsuccessful, which could result in some Advanced Scene Switcher functions not being available:%1Check the OBS logs for details.<br>This message can be disabled on the General tab.</body></html>"
|
AdvSceneSwitcher.generalTab.generalBehavior.warnPluginLoadFailureMessage="<html><body>Loading of the following plugin libraries was unsuccessful, which could result in some Advanced Scene Switcher functions not being available:%1Check the OBS logs for details.<br>This message can be disabled on the General tab.</body></html>"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.warnCorruptedInstallMessage="The plugin installation seems to be corrupted and might crash!\nPlease make sure the plugin was installed correctly!"
|
AdvSceneSwitcher.generalTab.generalBehavior.warnCorruptedInstallMessage="The plugin installation seems to be corrupted and might crash!\nPlease make sure the plugin was installed correctly!"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="Hide tabs which can be represented via macros"
|
AdvSceneSwitcher.generalTab.generalBehavior.hideLegacyTabs="Hide tabs which can be represented via macros"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.alwaysShowMacroSearch="Always show macro search"
|
AdvSceneSwitcher.generalTab.generalBehavior.alwaysShowMacroSearch="Always show macro search"
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.alwaysShowFeatureTabs="Always show all feature tabs"
|
|
||||||
AdvSceneSwitcher.generalTab.generalBehavior.alwaysShowFeatureTabs.tooltip="Show tabs that are normally hidden until first used in a macro (e.g. Action Queues, Variables, Twitch, Websockets)."
|
|
||||||
AdvSceneSwitcher.generalTab.matchBehavior="Match behavior"
|
AdvSceneSwitcher.generalTab.matchBehavior="Match behavior"
|
||||||
AdvSceneSwitcher.generalTab.priority="Priority"
|
AdvSceneSwitcher.generalTab.priority="Priority"
|
||||||
AdvSceneSwitcher.generalTab.priority.description="Switching methods priority (Highest priority is at the top)"
|
AdvSceneSwitcher.generalTab.priority.description="Switching methods priority (Highest priority is at the top)"
|
||||||
@@ -161,8 +158,6 @@ AdvSceneSwitcher.macroTab.title="Macro"
|
|||||||
AdvSceneSwitcher.macroTab.macros="Macros"
|
AdvSceneSwitcher.macroTab.macros="Macros"
|
||||||
AdvSceneSwitcher.macroTab.priorityWarning="Note: It is recommended to configure macros to be the highest priority functionality.\nThis setting can be changed on the General tab."
|
AdvSceneSwitcher.macroTab.priorityWarning="Note: It is recommended to configure macros to be the highest priority functionality.\nThis setting can be changed on the General tab."
|
||||||
AdvSceneSwitcher.macroTab.help="Macros allow you to execute a string of actions depending on multiple conditions.\n\nClick on the highlighted plus symbol to add a new Macro."
|
AdvSceneSwitcher.macroTab.help="Macros allow you to execute a string of actions depending on multiple conditions.\n\nClick on the highlighted plus symbol to add a new Macro."
|
||||||
AdvSceneSwitcher.macroTab.macroLastExecutedTooltip="Was last executed %1 seconds ago."
|
|
||||||
AdvSceneSwitcher.macroTab.macroNotYetExecutedTooltip="Was not yet executed."
|
|
||||||
AdvSceneSwitcher.macroTab.editConditionHelp="This section allows you to define macro conditions.\n\nSelect an existing or add a new macro on the left.\nThen click the plus button below to add a new condition."
|
AdvSceneSwitcher.macroTab.editConditionHelp="This section allows you to define macro conditions.\n\nSelect an existing or add a new macro on the left.\nThen click the plus button below to add a new condition."
|
||||||
AdvSceneSwitcher.macroTab.editActionHelp="This section allows you to define macro actions.\nThe actions in this section will be performed when the conditions are met.\n\nSelect an existing or add a new macro on the left.\nThen click the plus button below to add a new action."
|
AdvSceneSwitcher.macroTab.editActionHelp="This section allows you to define macro actions.\nThe actions in this section will be performed when the conditions are met.\n\nSelect an existing or add a new macro on the left.\nThen click the plus button below to add a new action."
|
||||||
AdvSceneSwitcher.macroTab.editElseActionHelp="This section allows you to define macro actions.\nThe actions in this section will be performed when the conditions are *not* met.\n\nSelect an existing or add a new macro on the left.\nThen click the plus button below to add a new action."
|
AdvSceneSwitcher.macroTab.editElseActionHelp="This section allows you to define macro actions.\nThe actions in this section will be performed when the conditions are *not* met.\n\nSelect an existing or add a new macro on the left.\nThen click the plus button below to add a new action."
|
||||||
@@ -178,12 +173,7 @@ AdvSceneSwitcher.macroTab.run.tooltip="Run all macro actions regardless of condi
|
|||||||
AdvSceneSwitcher.macroTab.runElse="Run macro (else)"
|
AdvSceneSwitcher.macroTab.runElse="Run macro (else)"
|
||||||
AdvSceneSwitcher.macroTab.runFail="Running \"%1\" failed!\nEither one of the actions failed or the macro is running already.\nDo you want to stop it?"
|
AdvSceneSwitcher.macroTab.runFail="Running \"%1\" failed!\nEither one of the actions failed or the macro is running already.\nDo you want to stop it?"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="Run macro in parallel to other macros"
|
AdvSceneSwitcher.macroTab.runInParallel="Run macro in parallel to other macros"
|
||||||
AdvSceneSwitcher.macroTab.actionTriggerMode.label="Perform actions:"
|
AdvSceneSwitcher.macroTab.onChange="Perform actions only on condition change"
|
||||||
AdvSceneSwitcher.macroTab.actionTriggerMode.tooltip="Controls when the actions of this macro are performed.\n\n\"Always\" - actions are performed every time the conditions are met.\n\"Macro result changed\" - actions are only performed when the macro transitions between matching and not matching.\n\"Any condition changed\" - actions are only performed when any individual condition changes its result.\n\"Any condition triggered\" - actions are only performed when any individual condition changes from false to true."
|
|
||||||
AdvSceneSwitcher.macroTab.actionTriggerMode.always="always"
|
|
||||||
AdvSceneSwitcher.macroTab.actionTriggerMode.onOverallChange="only when result changes"
|
|
||||||
AdvSceneSwitcher.macroTab.actionTriggerMode.onAnyConditionChange="only when any condition changes"
|
|
||||||
AdvSceneSwitcher.macroTab.actionTriggerMode.onAnyConditionTriggered="only when any condition becomes true"
|
|
||||||
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
||||||
AdvSceneSwitcher.macroTab.defaultGroupName="Group %1"
|
AdvSceneSwitcher.macroTab.defaultGroupName="Group %1"
|
||||||
AdvSceneSwitcher.macroTab.macroNameExists="The name \"%1\" is already used by a macro."
|
AdvSceneSwitcher.macroTab.macroNameExists="The name \"%1\" is already used by a macro."
|
||||||
@@ -369,7 +359,11 @@ AdvSceneSwitcher.condition.file.type.dateChange="modification date changed"
|
|||||||
AdvSceneSwitcher.condition.file.type.exists="exists"
|
AdvSceneSwitcher.condition.file.type.exists="exists"
|
||||||
AdvSceneSwitcher.condition.file.type.isFile="is a file"
|
AdvSceneSwitcher.condition.file.type.isFile="is a file"
|
||||||
AdvSceneSwitcher.condition.file.type.isFolder="is a folder"
|
AdvSceneSwitcher.condition.file.type.isFolder="is a folder"
|
||||||
AdvSceneSwitcher.condition.file.layout="{{filePath}}{{conditions}}{{regex}}"
|
AdvSceneSwitcher.condition.file.remote="Remote file"
|
||||||
|
AdvSceneSwitcher.condition.file.local="Local file"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||||
AdvSceneSwitcher.condition.media="Media"
|
AdvSceneSwitcher.condition.media="Media"
|
||||||
AdvSceneSwitcher.condition.media.checkType.state="State matches"
|
AdvSceneSwitcher.condition.media.checkType.state="State matches"
|
||||||
AdvSceneSwitcher.condition.media.checkType.time="Time restriction matches"
|
AdvSceneSwitcher.condition.media.checkType.time="Time restriction matches"
|
||||||
@@ -484,9 +478,8 @@ AdvSceneSwitcher.condition.record.state.stop="Recording stopped"
|
|||||||
AdvSceneSwitcher.condition.record.state.duration="Recording duration is longer than"
|
AdvSceneSwitcher.condition.record.state.duration="Recording duration is longer than"
|
||||||
AdvSceneSwitcher.condition.record.entry="{{condition}}{{duration}}"
|
AdvSceneSwitcher.condition.record.entry="{{condition}}{{duration}}"
|
||||||
AdvSceneSwitcher.condition.process="Process"
|
AdvSceneSwitcher.condition.process="Process"
|
||||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}is running{{focused}}and is focused"
|
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}is running{{focused}}and is focused"
|
||||||
AdvSceneSwitcher.condition.process.layout.focus="Current foreground process:{{focusProcess}}"
|
AdvSceneSwitcher.condition.process.entry.focus="Current foreground process:{{focusProcess}}"
|
||||||
AdvSceneSwitcher.condition.process.layout.path="{{checkPath}}Match binary path:{{path}}{{pathRegex}}"
|
|
||||||
AdvSceneSwitcher.condition.idle="Idle"
|
AdvSceneSwitcher.condition.idle="Idle"
|
||||||
AdvSceneSwitcher.condition.idle.entry="No keyboard or mouse inputs for{{duration}}"
|
AdvSceneSwitcher.condition.idle.entry="No keyboard or mouse inputs for{{duration}}"
|
||||||
AdvSceneSwitcher.condition.pluginState="Plugin state"
|
AdvSceneSwitcher.condition.pluginState="Plugin state"
|
||||||
@@ -592,6 +585,14 @@ AdvSceneSwitcher.condition.replay.state.started="Replay buffer started"
|
|||||||
AdvSceneSwitcher.condition.replay.state.saved="Replay buffer saved"
|
AdvSceneSwitcher.condition.replay.state.saved="Replay buffer saved"
|
||||||
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
||||||
AdvSceneSwitcher.condition.date="Date"
|
AdvSceneSwitcher.condition.date="Date"
|
||||||
|
AdvSceneSwitcher.condition.date.anyDay="Any day"
|
||||||
|
AdvSceneSwitcher.condition.date.monday="Monday"
|
||||||
|
AdvSceneSwitcher.condition.date.tuesday="Tuesday"
|
||||||
|
AdvSceneSwitcher.condition.date.wednesday="Wednesday"
|
||||||
|
AdvSceneSwitcher.condition.date.thursday="Thursday"
|
||||||
|
AdvSceneSwitcher.condition.date.friday="Friday"
|
||||||
|
AdvSceneSwitcher.condition.date.saturday="Saturday"
|
||||||
|
AdvSceneSwitcher.condition.date.sunday="Sunday"
|
||||||
AdvSceneSwitcher.condition.date.state.at="At"
|
AdvSceneSwitcher.condition.date.state.at="At"
|
||||||
AdvSceneSwitcher.condition.date.state.after="After"
|
AdvSceneSwitcher.condition.date.state.after="After"
|
||||||
AdvSceneSwitcher.condition.date.state.before="Before"
|
AdvSceneSwitcher.condition.date.state.before="Before"
|
||||||
@@ -602,13 +603,12 @@ AdvSceneSwitcher.condition.date.ignoreDate="If unchecked the date component will
|
|||||||
AdvSceneSwitcher.condition.date.ignoreTime="If unchecked the time component will be ignored"
|
AdvSceneSwitcher.condition.date.ignoreTime="If unchecked the time component will be ignored"
|
||||||
AdvSceneSwitcher.condition.date.showAdvancedSettings="Show advanced settings"
|
AdvSceneSwitcher.condition.date.showAdvancedSettings="Show advanced settings"
|
||||||
AdvSceneSwitcher.condition.date.showSimpleSettings="Show simple settings"
|
AdvSceneSwitcher.condition.date.showSimpleSettings="Show simple settings"
|
||||||
AdvSceneSwitcher.condition.date.layout.simple.day="On{{dayOfWeek}}"
|
AdvSceneSwitcher.condition.date.entry.simple="On{{dayOfWeek}}{{weekCondition}}{{ignoreWeekTime}}{{weekTime}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.simple.time="{{ignoreWeekTime}}{{weekCondition}}{{weekTime}}"
|
AdvSceneSwitcher.condition.date.entry.advanced="{{condition}}{{ignoreDate}}{{date}}{{ignoreTime}}{{time}}{{separator}}{{date2}}{{time2}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.advanced="{{condition}}{{ignoreDate}}{{date}}{{ignoreTime}}{{time}}{{separator}}{{date2}}{{time2}}"
|
AdvSceneSwitcher.condition.date.entry.repeat="{{repeat}}Repeat every{{duration}}on date match"
|
||||||
AdvSceneSwitcher.condition.date.layout.repeat="{{repeat}}Repeat every{{duration}}on date match"
|
AdvSceneSwitcher.condition.date.entry.pattern="Current date \"{{currentDate}}\" matches pattern{{pattern}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.pattern="Current date \"{{currentDate}}\" matches pattern{{pattern}}"
|
AdvSceneSwitcher.condition.date.entry.nextMatchDate="Next match at: %1"
|
||||||
AdvSceneSwitcher.condition.date.layout.nextMatchDate="Next match at: %1"
|
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}}On repeat update selected date to repeat date"
|
||||||
AdvSceneSwitcher.condition.date.layout.updateOnRepeat="{{updateOnRepeat}}On repeat update selected date to repeat date"
|
|
||||||
AdvSceneSwitcher.condition.sceneTransform="Scene item transform"
|
AdvSceneSwitcher.condition.sceneTransform="Scene item transform"
|
||||||
AdvSceneSwitcher.condition.sceneTransform.getTransform="Get transform"
|
AdvSceneSwitcher.condition.sceneTransform.getTransform="Get transform"
|
||||||
AdvSceneSwitcher.condition.sceneTransform.getCurrentValue="Get current value"
|
AdvSceneSwitcher.condition.sceneTransform.getCurrentValue="Get current value"
|
||||||
@@ -674,34 +674,6 @@ AdvSceneSwitcher.condition.websocket.type.event="Scene Switcher Event"
|
|||||||
AdvSceneSwitcher.condition.websocket.useRegex="Use regular expressions"
|
AdvSceneSwitcher.condition.websocket.useRegex="Use regular expressions"
|
||||||
AdvSceneSwitcher.condition.websocket.entry.request="{{type}}was received:"
|
AdvSceneSwitcher.condition.websocket.entry.request="{{type}}was received:"
|
||||||
AdvSceneSwitcher.condition.websocket.entry.event="{{type}}was received from{{connection}}:"
|
AdvSceneSwitcher.condition.websocket.entry.event="{{type}}was received from{{connection}}:"
|
||||||
AdvSceneSwitcher.condition.http="HTTP"
|
|
||||||
AdvSceneSwitcher.condition.http.layout="Receive{{method}}request on{{server}}"
|
|
||||||
AdvSceneSwitcher.condition.http.layout.path="Path:{{path}}{{regex}}"
|
|
||||||
AdvSceneSwitcher.condition.http.layout.body="Body:{{body}}{{regex}}"
|
|
||||||
AdvSceneSwitcher.condition.http.method.any="any"
|
|
||||||
AdvSceneSwitcher.condition.http.method.get="GET"
|
|
||||||
AdvSceneSwitcher.condition.http.method.post="POST"
|
|
||||||
AdvSceneSwitcher.condition.http.method.put="PUT"
|
|
||||||
AdvSceneSwitcher.condition.http.method.patch="PATCH"
|
|
||||||
AdvSceneSwitcher.condition.http.method.delete="DELETE"
|
|
||||||
AdvSceneSwitcher.httpServer.select="Select HTTP server"
|
|
||||||
AdvSceneSwitcher.httpServer.add="Add HTTP server"
|
|
||||||
AdvSceneSwitcher.httpServer.configure="Configure HTTP server"
|
|
||||||
AdvSceneSwitcher.httpServer.invalid="Invalid HTTP server"
|
|
||||||
AdvSceneSwitcher.httpServer.name="Name:"
|
|
||||||
AdvSceneSwitcher.httpServer.port="Port:"
|
|
||||||
AdvSceneSwitcher.httpServer.startOnLoad="Start on load"
|
|
||||||
AdvSceneSwitcher.httpServer.status.listening="Listening"
|
|
||||||
AdvSceneSwitcher.httpServer.status.stopped="Stopped"
|
|
||||||
AdvSceneSwitcher.httpServerTab.title="HTTP Servers"
|
|
||||||
AdvSceneSwitcher.httpServerTab.help="No HTTP servers configured.\nAdd one to receive incoming HTTP requests in conditions."
|
|
||||||
AdvSceneSwitcher.httpServerTab.addButton.tooltip="Add HTTP server"
|
|
||||||
AdvSceneSwitcher.httpServerTab.removeButton.tooltip="Remove HTTP server"
|
|
||||||
AdvSceneSwitcher.httpServerTab.name.header="Name"
|
|
||||||
AdvSceneSwitcher.httpServerTab.port.header="Port"
|
|
||||||
AdvSceneSwitcher.httpServerTab.status.header="Status"
|
|
||||||
AdvSceneSwitcher.httpServerTab.removeSingle.text="Are you sure you want to remove \"%1\"?"
|
|
||||||
AdvSceneSwitcher.httpServerTab.removeMultiple.text="Are you sure you want to remove %1 HTTP servers?"
|
|
||||||
AdvSceneSwitcher.condition.temporaryVariable="Macro property"
|
AdvSceneSwitcher.condition.temporaryVariable="Macro property"
|
||||||
AdvSceneSwitcher.condition.variable="Variable"
|
AdvSceneSwitcher.condition.variable="Variable"
|
||||||
AdvSceneSwitcher.condition.variable.type.compare="equals"
|
AdvSceneSwitcher.condition.variable.type.compare="equals"
|
||||||
@@ -905,15 +877,6 @@ AdvSceneSwitcher.action.audio.fade.rate="{{fade}}Fade{{fadeTypes}}{{rate}}per se
|
|||||||
AdvSceneSwitcher.action.audio.fade.wait="Wait for fade to complete."
|
AdvSceneSwitcher.action.audio.fade.wait="Wait for fade to complete."
|
||||||
AdvSceneSwitcher.action.audio.fade.abort="Abort already active fade."
|
AdvSceneSwitcher.action.audio.fade.abort="Abort already active fade."
|
||||||
AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{volumeDB}}{{percentDBToggle}}{{syncOffset}}{{monitorTypes}}{{track}}"
|
AdvSceneSwitcher.action.audio.entry="{{actions}}{{audioSources}}{{volume}}{{volumeDB}}{{percentDBToggle}}{{syncOffset}}{{monitorTypes}}{{track}}"
|
||||||
AdvSceneSwitcher.action.playAudio="Play Audio File"
|
|
||||||
AdvSceneSwitcher.action.playAudio.file.browse="Browse for audio file"
|
|
||||||
AdvSceneSwitcher.action.playAudio.layout.volume="Volume{{volumeDB}}"
|
|
||||||
AdvSceneSwitcher.action.playAudio.layout.monitor="Monitoring{{monitorTypes}}"
|
|
||||||
AdvSceneSwitcher.action.playAudio.wait="Wait for playback to complete"
|
|
||||||
AdvSceneSwitcher.action.playAudio.monitorUnavailable="Audio monitoring not available"
|
|
||||||
AdvSceneSwitcher.action.playAudio.tracks="Tracks"
|
|
||||||
AdvSceneSwitcher.action.playAudio.layout.startOffset="{{useStartOffset}}Start at{{startOffset}}"
|
|
||||||
AdvSceneSwitcher.action.playAudio.layout.playbackDuration="{{useDuration}}Play for{{playbackDuration}}(0 = until end)"
|
|
||||||
AdvSceneSwitcher.action.recording="Recording"
|
AdvSceneSwitcher.action.recording="Recording"
|
||||||
AdvSceneSwitcher.action.recording.type.stop="Stop recording"
|
AdvSceneSwitcher.action.recording.type.stop="Stop recording"
|
||||||
AdvSceneSwitcher.action.recording.type.start="Start recording"
|
AdvSceneSwitcher.action.recording.type.start="Start recording"
|
||||||
@@ -922,10 +885,9 @@ AdvSceneSwitcher.action.recording.type.unpause="Unpause recording"
|
|||||||
AdvSceneSwitcher.action.recording.type.split="Split recording file"
|
AdvSceneSwitcher.action.recording.type.split="Split recording file"
|
||||||
AdvSceneSwitcher.action.recording.type.changeOutputFolder="Change output folder"
|
AdvSceneSwitcher.action.recording.type.changeOutputFolder="Change output folder"
|
||||||
AdvSceneSwitcher.action.recording.type.changeOutputFileFormat="Change filename formatting"
|
AdvSceneSwitcher.action.recording.type.changeOutputFileFormat="Change filename formatting"
|
||||||
AdvSceneSwitcher.action.recording.type.addChapter="Add chapter"
|
|
||||||
AdvSceneSwitcher.action.recording.pause.hint="Note that depending on your recording settings you might not be able to pause recording"
|
AdvSceneSwitcher.action.recording.pause.hint="Note that depending on your recording settings you might not be able to pause recording"
|
||||||
AdvSceneSwitcher.action.recording.split.hint="Make sure to enable automatic file splitting in the OBS settings first!"
|
AdvSceneSwitcher.action.recording.split.hint="Make sure to enable automatic file splitting in the OBS settings first!"
|
||||||
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{chapterName}}{{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.durationWarn="Warning: Changing the maximum replay time will only apply the next time the replay buffer is started!"
|
||||||
@@ -942,8 +904,7 @@ AdvSceneSwitcher.action.streaming.type.server="Set server URL"
|
|||||||
AdvSceneSwitcher.action.streaming.type.streamKey="Set stream key"
|
AdvSceneSwitcher.action.streaming.type.streamKey="Set stream key"
|
||||||
AdvSceneSwitcher.action.streaming.type.username="Set username"
|
AdvSceneSwitcher.action.streaming.type.username="Set username"
|
||||||
AdvSceneSwitcher.action.streaming.type.password="Set password"
|
AdvSceneSwitcher.action.streaming.type.password="Set password"
|
||||||
AdvSceneSwitcher.action.streaming.getCurrentValue="Get current value"
|
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}"
|
||||||
AdvSceneSwitcher.action.streaming.layout="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}{{getCurrentValue}}"
|
|
||||||
AdvSceneSwitcher.action.run="Run"
|
AdvSceneSwitcher.action.run="Run"
|
||||||
AdvSceneSwitcher.action.run.wait.entry="{{wait}}Wait for process exit or at most {{timeout}}{{waitHelp}}"
|
AdvSceneSwitcher.action.run.wait.entry="{{wait}}Wait for process exit or at most {{timeout}}{{waitHelp}}"
|
||||||
AdvSceneSwitcher.action.run.wait.help.tooltip="Note that macro properties won't work if you leave this unticked, as the process spawns detached from the rest of logic and there's no control over it."
|
AdvSceneSwitcher.action.run.wait.help.tooltip="Note that macro properties won't work if you leave this unticked, as the process spawns detached from the rest of logic and there's no control over it."
|
||||||
@@ -953,9 +914,7 @@ AdvSceneSwitcher.action.sceneVisibility.type.hide="Hide"
|
|||||||
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Toggle"
|
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Toggle"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Source"
|
AdvSceneSwitcher.action.sceneVisibility.type.source="Source"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Any"
|
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Any"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.layout="On{{scenes}}{{actions}}{{sources}}"
|
AdvSceneSwitcher.action.sceneVisibility.entry="On{{scenes}}{{actions}}{{sources}}"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.layout.transition="{{updateTransition}}Set transition to{{transitions}}"
|
|
||||||
AdvSceneSwitcher.action.sceneVisibility.layout.duration="{{updateDuration}}Set transition duration to{{duration}}seconds"
|
|
||||||
AdvSceneSwitcher.action.filter="Filter"
|
AdvSceneSwitcher.action.filter="Filter"
|
||||||
AdvSceneSwitcher.action.filter.type.enable="Enable"
|
AdvSceneSwitcher.action.filter.type.enable="Enable"
|
||||||
AdvSceneSwitcher.action.filter.type.disable="Disable"
|
AdvSceneSwitcher.action.filter.type.disable="Disable"
|
||||||
@@ -986,8 +945,6 @@ AdvSceneSwitcher.action.source.type.openPropertiesDialog="Open properties dialog
|
|||||||
AdvSceneSwitcher.action.source.type.closeInteractionDialog="Close interaction dialog"
|
AdvSceneSwitcher.action.source.type.closeInteractionDialog="Close interaction dialog"
|
||||||
AdvSceneSwitcher.action.source.type.closeFilterDialog="Close filter dialog"
|
AdvSceneSwitcher.action.source.type.closeFilterDialog="Close filter dialog"
|
||||||
AdvSceneSwitcher.action.source.type.closePropertiesDialog="Close properties dialog"
|
AdvSceneSwitcher.action.source.type.closePropertiesDialog="Close properties dialog"
|
||||||
AdvSceneSwitcher.action.source.type.getSetting="Get setting value"
|
|
||||||
AdvSceneSwitcher.action.source.type.getSettings="Get settings JSON"
|
|
||||||
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\""
|
||||||
@@ -1010,49 +967,6 @@ AdvSceneSwitcher.action.source.inputMethod.json="Set setting JSON string"
|
|||||||
AdvSceneSwitcher.action.source.refresh="Refresh"
|
AdvSceneSwitcher.action.source.refresh="Refresh"
|
||||||
AdvSceneSwitcher.action.source.refresh.tooltip="Repopulate the source settings selection with the settings of the source which's name matches the variable value."
|
AdvSceneSwitcher.action.source.refresh.tooltip="Repopulate the source settings selection with the settings of the source which's name matches the variable value."
|
||||||
AdvSceneSwitcher.action.source.dialog.accept="Accept changes"
|
AdvSceneSwitcher.action.source.dialog.accept="Accept changes"
|
||||||
AdvSceneSwitcher.action.sourceInteraction="Source Interaction"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.source="Source"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.noSelection="Select a step to edit it"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.record="Record interaction ..."
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.listEntry.mouseMove="Mouse move (%1, %2)"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.listEntry.mouseUp="up"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.listEntry.mouseDown="down"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.listEntry.mouseClick="Mouse %1 %2 (%3, %4)"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.listEntry.mouseClickCount=" x%1"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.listEntry.mouseWheel="Mouse wheel (%1, %2) dx=%3 dy=%4"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.listEntry.keyUp="up"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.listEntry.keyDown="down"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.listEntry.keyPress="Key %1"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.listEntry.keyPressWithText="Key %1 '%2'"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.listEntry.typeText="Type \"%1\""
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.listEntry.wait="Wait %1 ms"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.type="Type"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.mouseMove="Mouse move"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.mouseClick="Mouse click"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.mouseWheel="Mouse wheel"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.keyPress="Key press"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.typeText="Type text"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.wait="Wait"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.x="X"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.y="Y"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.button="Button"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.mouseUp="Mouse up"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.clickCount="Click count"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.wheelDx="Delta X"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.wheelDy="Delta Y"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.vkey="Virtual key"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.keyUp="Key up"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.text="Text"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.step.edit.waitMs="Duration (ms)"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.button.left="Left"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.button.middle="Middle"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.button.right="Right"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.record.title="Record Source Interactions"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.record.start="Start recording"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.record.stop="Stop recording"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.record.accept="Accept"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.record.placeholder="Start recording and interact with the source to capture steps"
|
|
||||||
AdvSceneSwitcher.action.sourceInteraction.record.invalidSource="No valid source is selected.\nPlease select a source that supports interaction before recording."
|
|
||||||
AdvSceneSwitcher.action.media="Media"
|
AdvSceneSwitcher.action.media="Media"
|
||||||
AdvSceneSwitcher.action.media.type.play="Play"
|
AdvSceneSwitcher.action.media.type.play="Play"
|
||||||
AdvSceneSwitcher.action.media.type.pause="Pause"
|
AdvSceneSwitcher.action.media.type.pause="Pause"
|
||||||
@@ -1072,7 +986,7 @@ AdvSceneSwitcher.action.macro.type.pause="Pause"
|
|||||||
AdvSceneSwitcher.action.macro.type.unpause="Unpause"
|
AdvSceneSwitcher.action.macro.type.unpause="Unpause"
|
||||||
AdvSceneSwitcher.action.macro.type.togglePause="Toggle pause"
|
AdvSceneSwitcher.action.macro.type.togglePause="Toggle pause"
|
||||||
AdvSceneSwitcher.action.macro.type.resetCounter="Reset counter"
|
AdvSceneSwitcher.action.macro.type.resetCounter="Reset counter"
|
||||||
AdvSceneSwitcher.action.macro.type.runActions="Run macro 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.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.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.conditions.false="Only if conditions evaluate to false"
|
||||||
@@ -1087,10 +1001,6 @@ 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.type.getInfo="Get macro info"
|
|
||||||
AdvSceneSwitcher.action.macro.type.runMacro="Run macro"
|
|
||||||
AdvSceneSwitcher.action.macro.type.runMacro.noConditionsWarning="Warning: The selected macro has no conditions!"
|
|
||||||
AdvSceneSwitcher.action.macro.type.runMacro.help="Unlike \"Run macro actions\", this option will immediately re-evaluate the conditions of the selected macro and then run either its actions or else-actions depending on the result."
|
|
||||||
AdvSceneSwitcher.action.macro.type.nestedMacro="Nested macro"
|
AdvSceneSwitcher.action.macro.type.nestedMacro="Nested macro"
|
||||||
AdvSceneSwitcher.action.macro.actionSelectionType.index="at index"
|
AdvSceneSwitcher.action.macro.actionSelectionType.index="at index"
|
||||||
AdvSceneSwitcher.action.macro.actionSelectionType.label="with label"
|
AdvSceneSwitcher.action.macro.actionSelectionType.label="with label"
|
||||||
@@ -1101,7 +1011,6 @@ AdvSceneSwitcher.action.macro.type.nestedMacro.elseActionHelp="This section allo
|
|||||||
AdvSceneSwitcher.action.macro.layout.run="{{actions}}{{actionSections}}of{{macros}}"
|
AdvSceneSwitcher.action.macro.layout.run="{{actions}}{{actionSections}}of{{macros}}"
|
||||||
AdvSceneSwitcher.action.macro.layout.run.condition="{{conditionBehaviors}}of{{conditionMacros}}"
|
AdvSceneSwitcher.action.macro.layout.run.condition="{{conditionBehaviors}}of{{conditionMacros}}"
|
||||||
AdvSceneSwitcher.action.macro.layout.actionState="{{actions}}{{actionSelectionType}}{{actionIndex}}{{label}}{{regex}}{{actionTypes}}in{{actionSections}}section of{{macros}}"
|
AdvSceneSwitcher.action.macro.layout.actionState="{{actions}}{{actionSelectionType}}{{actionIndex}}{{label}}{{regex}}{{actionTypes}}in{{actionSections}}section of{{macros}}"
|
||||||
AdvSceneSwitcher.action.macro.layout.runMacro="{{actions}}{{runMacroHelp}}{{macros}}"
|
|
||||||
AdvSceneSwitcher.action.macro.layout.other="{{actions}}{{macros}}"
|
AdvSceneSwitcher.action.macro.layout.other="{{actions}}{{macros}}"
|
||||||
AdvSceneSwitcher.action.pluginState="Plugin state"
|
AdvSceneSwitcher.action.pluginState="Plugin state"
|
||||||
AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher plugin"
|
AdvSceneSwitcher.action.pluginState.type.stop="Stop the Advanced Scene Switcher plugin"
|
||||||
@@ -1174,16 +1083,13 @@ AdvSceneSwitcher.action.studioMode.type.enable="Enable studio mode"
|
|||||||
AdvSceneSwitcher.action.studioMode.type.disable="Disable studio mode"
|
AdvSceneSwitcher.action.studioMode.type.disable="Disable studio mode"
|
||||||
AdvSceneSwitcher.action.studioMode.entry="{{actions}}{{scenes}}"
|
AdvSceneSwitcher.action.studioMode.entry="{{actions}}{{scenes}}"
|
||||||
AdvSceneSwitcher.action.transition="Transition"
|
AdvSceneSwitcher.action.transition="Transition"
|
||||||
AdvSceneSwitcher.action.transition.type.scene="Modify scene transition"
|
AdvSceneSwitcher.action.transition.type.scene="scene transition"
|
||||||
AdvSceneSwitcher.action.transition.type.sceneOverride="Modify scene transition override"
|
AdvSceneSwitcher.action.transition.type.sceneOverride="scene transition override"
|
||||||
AdvSceneSwitcher.action.transition.type.sourceShow="Modify source show transition"
|
AdvSceneSwitcher.action.transition.type.sourceShow="source show transition"
|
||||||
AdvSceneSwitcher.action.transition.type.sourceHide="Modify source hide transition"
|
AdvSceneSwitcher.action.transition.type.sourceHide="source hide transition"
|
||||||
AdvSceneSwitcher.action.transition.type.tbar="Modify T-Bar position"
|
AdvSceneSwitcher.action.transition.entry.line1="Modify{{type}}{{scenes}}{{sources}}"
|
||||||
AdvSceneSwitcher.action.transition.type.releaseTbar="Release T-Bar"
|
AdvSceneSwitcher.action.transition.entry.line2="{{setTransition}}Set transition type to{{transitions}}"
|
||||||
AdvSceneSwitcher.action.transition.layout.type="{{type}}{{scenes}}{{sources}}"
|
AdvSceneSwitcher.action.transition.entry.line3="{{setDuration}}Set transition duration to{{duration}}seconds"
|
||||||
AdvSceneSwitcher.action.transition.layout.transition="{{setTransition}}Set transition type to{{transitions}}"
|
|
||||||
AdvSceneSwitcher.action.transition.layout.duration="{{setDuration}}Set transition duration to{{duration}}seconds"
|
|
||||||
AdvSceneSwitcher.action.transition.layout.tbar="Set T-Bar position to{{tbarPosition}}"
|
|
||||||
AdvSceneSwitcher.action.timer="Timer"
|
AdvSceneSwitcher.action.timer="Timer"
|
||||||
AdvSceneSwitcher.action.timer.type.pause="Pause"
|
AdvSceneSwitcher.action.timer.type.pause="Pause"
|
||||||
AdvSceneSwitcher.action.timer.type.continue="Continue"
|
AdvSceneSwitcher.action.timer.type.continue="Continue"
|
||||||
@@ -1284,8 +1190,6 @@ AdvSceneSwitcher.action.variable.type.swapValues="Swap variable values"
|
|||||||
AdvSceneSwitcher.action.variable.type.trim="Trim whitespace"
|
AdvSceneSwitcher.action.variable.type.trim="Trim whitespace"
|
||||||
AdvSceneSwitcher.action.variable.type.changeCase="Change case"
|
AdvSceneSwitcher.action.variable.type.changeCase="Change case"
|
||||||
AdvSceneSwitcher.action.variable.type.randomNumber="Generate random number"
|
AdvSceneSwitcher.action.variable.type.randomNumber="Generate random number"
|
||||||
AdvSceneSwitcher.action.variable.type.randomListValue="Select random value"
|
|
||||||
AdvSceneSwitcher.action.variable.type.allowRepeat="Allow repeat values"
|
|
||||||
AdvSceneSwitcher.action.variable.case.type.lowerCase="lowercase"
|
AdvSceneSwitcher.action.variable.case.type.lowerCase="lowercase"
|
||||||
AdvSceneSwitcher.action.variable.case.type.upperCase="UPPERCASE"
|
AdvSceneSwitcher.action.variable.case.type.upperCase="UPPERCASE"
|
||||||
AdvSceneSwitcher.action.variable.case.type.capitalized="Capitalized"
|
AdvSceneSwitcher.action.variable.case.type.capitalized="Capitalized"
|
||||||
@@ -1308,8 +1212,8 @@ AdvSceneSwitcher.action.variable.currentSegmentValue="Current value:"
|
|||||||
AdvSceneSwitcher.action.variable.layout.other="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}{{tempVarsHelp}}{{sceneItemIndex}}{{direction}}{{stringLength}}{{paddingCharSelection}}{{caseType}}{{jsonQuery}}{{jsonQueryHelp}}{{jsonIndex}}"
|
AdvSceneSwitcher.action.variable.layout.other="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}{{tempVarsHelp}}{{sceneItemIndex}}{{direction}}{{stringLength}}{{paddingCharSelection}}{{caseType}}{{jsonQuery}}{{jsonQueryHelp}}{{jsonIndex}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.pad="{{actions}}of{{variables}}to length{{stringLength}}by adding{{paddingCharSelection}}to the{{direction}}"
|
AdvSceneSwitcher.action.variable.layout.pad="{{actions}}of{{variables}}to length{{stringLength}}by adding{{paddingCharSelection}}to the{{direction}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.truncate="{{actions}}of{{variables}}to length{{stringLength}}by removing characters from the{{direction}}"
|
AdvSceneSwitcher.action.variable.layout.truncate="{{actions}}of{{variables}}to length{{stringLength}}by removing characters from the{{direction}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.substringIndex="Substring start:{{subStringStart}}Substring size:{{subStringSize}}{{subStringRegex}}"
|
AdvSceneSwitcher.action.variable.layout.substringIndex="Substring start:{{subStringStart}}Substring size:{{subStringSize}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.substringRegex="Assign value of{{regexMatchIdx}}match using regular expression:{{subStringRegex}}"
|
AdvSceneSwitcher.action.variable.layout.substringRegex="Assign value of{{regexMatchIdx}}match using regular expression:"
|
||||||
AdvSceneSwitcher.action.variable.layout.findAndReplace="{{findStr}}{{findRegex}}{{replaceStr}}"
|
AdvSceneSwitcher.action.variable.layout.findAndReplace="{{findStr}}{{findRegex}}{{replaceStr}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.userInput.customPrompt="{{useCustomPrompt}}Use custom prompt{{inputPrompt}}"
|
AdvSceneSwitcher.action.variable.layout.userInput.customPrompt="{{useCustomPrompt}}Use custom prompt{{inputPrompt}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.userInput.placeholder="{{useInputPlaceholder}}Fill with placeholder{{inputPlaceholder}}"
|
AdvSceneSwitcher.action.variable.layout.userInput.placeholder="{{useInputPlaceholder}}Fill with placeholder{{inputPlaceholder}}"
|
||||||
@@ -1343,52 +1247,21 @@ AdvSceneSwitcher.action.twitch.type.channel.info.category.set="Set stream catego
|
|||||||
AdvSceneSwitcher.action.twitch.type.channel.info.tags.set="Set stream tags"
|
AdvSceneSwitcher.action.twitch.type.channel.info.tags.set="Set stream tags"
|
||||||
AdvSceneSwitcher.action.twitch.type.channel.info.language.set="Set stream language"
|
AdvSceneSwitcher.action.twitch.type.channel.info.language.set="Set stream language"
|
||||||
AdvSceneSwitcher.action.twitch.type.raid.start="Start raid"
|
AdvSceneSwitcher.action.twitch.type.raid.start="Start raid"
|
||||||
AdvSceneSwitcher.action.twitch.type.raid.end="Cancel raid"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.shoutout.send="Send shoutout"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.shieldMode.start="Enable shield mode"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.shieldMode.end="Disable shield mode"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.commercial.start="Start commercial"
|
AdvSceneSwitcher.action.twitch.type.commercial.start="Start commercial"
|
||||||
AdvSceneSwitcher.action.twitch.type.commercial.snooze="Snooze next ad"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.marker.create="Create stream marker"
|
AdvSceneSwitcher.action.twitch.type.marker.create="Create stream marker"
|
||||||
AdvSceneSwitcher.action.twitch.type.clip.create="Create stream clip"
|
AdvSceneSwitcher.action.twitch.type.clip.create="Create stream clip"
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.announcement.send="Send chat announcement"
|
AdvSceneSwitcher.action.twitch.type.chat.announcement.send="Send chat announcement"
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.emoteOnly.enable="Enable chat's emote-only mode"
|
AdvSceneSwitcher.action.twitch.type.chat.emoteOnly.enable="Enable chat's emote-only mode"
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.emoteOnly.disable="Disable chat's emote-only mode"
|
AdvSceneSwitcher.action.twitch.type.chat.emoteOnly.disable="Disable chat's emote-only mode"
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.followerOnly.enable="Enable chat's follower-only mode"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.followerOnly.disable="Disable chat's follower-only mode"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.subscriberOnly.enable="Enable chat's subscriber-only mode"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.subscriberOnly.disable="Disable chat's subscriber-only mode"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.slowMode.enable="Enable chat's slow mode"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.slowMode.disable="Disable chat's slow mode"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.nonModeratorDelay.enable="Enable chat's non-moderator message delay"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.nonModeratorDelay.disable="Disable chat's non-moderator message delay"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.uniqueMode.enable="Enable chat's unique message mode"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.uniqueMode.disable="Disable chat's unique message mode"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.sendMessage="Send chat message"
|
AdvSceneSwitcher.action.twitch.type.chat.sendMessage="Send chat message"
|
||||||
AdvSceneSwitcher.action.twitch.type.user.getInfo="Get user information"
|
AdvSceneSwitcher.action.twitch.type.user.getInfo="Get user information"
|
||||||
AdvSceneSwitcher.action.twitch.type.user.ban="Ban user"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.user.unban="Unban user"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.user.block="Block user"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.user.unblock="Unblock user"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.user.moderator.add="Add user as moderator"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.user.moderator.delete="Remove user as moderator"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.user.vip.add="Add user as VIP"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.user.vip.delete="Remove user as VIP"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.reward.getInfo="Get channel points reward information"
|
AdvSceneSwitcher.action.twitch.type.reward.getInfo="Get channel points reward information"
|
||||||
AdvSceneSwitcher.action.twitch.type.channel.getInfo="Get channel information"
|
|
||||||
AdvSceneSwitcher.action.twitch.reward.toggleControl="Toggle reward name / variable selection control"
|
AdvSceneSwitcher.action.twitch.reward.toggleControl="Toggle reward name / variable selection control"
|
||||||
AdvSceneSwitcher.action.twitch.categorySelectionDisabled="Cannot select category without selecting a Twitch account first!"
|
AdvSceneSwitcher.action.twitch.categorySelectionDisabled="Cannot select category without selecting a Twitch account first!"
|
||||||
AdvSceneSwitcher.action.twitch.layout.default="On{{account}}{{actions}}{{streamTitle}}{{category}}{{markerDescription}}{{clipHasDelay}}{{duration}}{{announcementColor}}{{nonModDelayDuration}}{{channel}}{{pointsReward}}"
|
AdvSceneSwitcher.action.twitch.entry.default="On{{account}}{{actions}}{{streamTitle}}{{category}}{{markerDescription}}{{clipHasDelay}}{{duration}}{{announcementColor}}{{channel}}{{pointsReward}}"
|
||||||
AdvSceneSwitcher.action.twitch.layout.chat="Using account{{account}}{{actions}}on{{channel}}"
|
AdvSceneSwitcher.action.twitch.entry.chat="Using account{{account}}{{actions}}on{{channel}}"
|
||||||
AdvSceneSwitcher.action.twitch.layout.channel.getInfo="Using account{{account}}{{actions}}of{{channel}}"
|
AdvSceneSwitcher.action.twitch.entry.user.getInfo="Using account{{account}}{{actions}}for{{userInfoQueryType}}{{userLogin}}{{userId}}"
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.getInfo.row1="Using account{{account}}{{actions}}"
|
AdvSceneSwitcher.action.twitch.entry.reward.getInfo="Using account{{account}}{{actions}}for channel{{channel}}{{pointsReward}}{{rewardVariable}}{{toggleRewardSelection}}"
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.getInfo.row2="for{{userInfoQueryType}}{{userLogin}}{{userId}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.moderation.row1="Using account{{account}}{{actions}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.moderation.row2="on channel{{channel}}for{{userInfoQueryType}}{{userLogin}}{{userId}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.ban.row1="Using account{{account}}{{actions}}timeout{{duration}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.ban.row2="on channel{{channel}}for{{userInfoQueryType}}{{userLogin}}{{userId}}reason{{banReason}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.reward.getInfo.row1="Using account{{account}}{{actions}}for channel{{channel}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.reward.getInfo.row2="{{pointsReward}}{{rewardVariable}}{{toggleRewardSelection}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.title.title="Enter title"
|
AdvSceneSwitcher.action.twitch.title.title="Enter title"
|
||||||
AdvSceneSwitcher.action.twitch.marker.description="Describe marker"
|
AdvSceneSwitcher.action.twitch.marker.description="Describe marker"
|
||||||
AdvSceneSwitcher.action.twitch.clip.hasDelay="Add a slight delay before capturing the clip"
|
AdvSceneSwitcher.action.twitch.clip.hasDelay="Add a slight delay before capturing the clip"
|
||||||
@@ -1409,8 +1282,6 @@ AdvSceneSwitcher.action.twitch.tags.duplicate.info="This tag is already in the l
|
|||||||
AdvSceneSwitcher.action.twitch.tags.limit="Tag Limit Reached"
|
AdvSceneSwitcher.action.twitch.tags.limit="Tag Limit Reached"
|
||||||
AdvSceneSwitcher.action.twitch.tags.limit.info="You can only have up to %1 tags."
|
AdvSceneSwitcher.action.twitch.tags.limit.info="You can only have up to %1 tags."
|
||||||
AdvSceneSwitcher.action.twitch.type.channel.info.contentClassification.set="Set content classification labels"
|
AdvSceneSwitcher.action.twitch.type.channel.info.contentClassification.set="Set content classification labels"
|
||||||
AdvSceneSwitcher.action.twitch.type.channel.info.brandedContent.enable="Enable branded content"
|
|
||||||
AdvSceneSwitcher.action.twitch.type.channel.info.brandedContent.disable="Disable branded content"
|
|
||||||
AdvSceneSwitcher.action.twitch.contentClassification.debatedSocialIssuesAndPolitics="Discussions or debates about politics or sensitive social issues such as elections, civic integrity, military conflict, and civil rights."
|
AdvSceneSwitcher.action.twitch.contentClassification.debatedSocialIssuesAndPolitics="Discussions or debates about politics or sensitive social issues such as elections, civic integrity, military conflict, and civil rights."
|
||||||
AdvSceneSwitcher.action.twitch.contentClassification.drugsIntoxication="Excessive tobacco glorification or promotion, any marijuana consumption/use, legal drug and alcohol induced intoxication, discussions of illegal drugs."
|
AdvSceneSwitcher.action.twitch.contentClassification.drugsIntoxication="Excessive tobacco glorification or promotion, any marijuana consumption/use, legal drug and alcohol induced intoxication, discussions of illegal drugs."
|
||||||
AdvSceneSwitcher.action.twitch.contentClassification.sexualThemes="Content that focuses on sexualized activities, sexual topics, or experiences."
|
AdvSceneSwitcher.action.twitch.contentClassification.sexualThemes="Content that focuses on sexualized activities, sexual topics, or experiences."
|
||||||
@@ -1515,9 +1386,6 @@ AdvSceneSwitcher.hotkey.macro.segment.remove="Remove selected macro segment"
|
|||||||
AdvSceneSwitcher.askBackup="Detected a new version of the Advanced Scene Switcher.\nShould a backup of the old settings be created?"
|
AdvSceneSwitcher.askBackup="Detected a new version of the Advanced Scene Switcher.\nShould a backup of the old settings be created?"
|
||||||
AdvSceneSwitcher.askForMacro="Select macro{{macroSelection}}"
|
AdvSceneSwitcher.askForMacro="Select macro{{macroSelection}}"
|
||||||
|
|
||||||
AdvSceneSwitcher.crashDetected="OBS did not shut down cleanly (for example, due to a crash or freeze).\n\nThe Advanced Scene Switcher plugin would normally start automatically.\nWould you like to keep it stopped for now?"
|
|
||||||
AdvSceneSwitcher.crashDetected.suppressCheckbox="Do not show this dialog again"
|
|
||||||
|
|
||||||
AdvSceneSwitcher.close="Close"
|
AdvSceneSwitcher.close="Close"
|
||||||
AdvSceneSwitcher.browse="Browse"
|
AdvSceneSwitcher.browse="Browse"
|
||||||
|
|
||||||
@@ -1786,7 +1654,6 @@ AdvSceneSwitcher.script.language.lua="LUA"
|
|||||||
AdvSceneSwitcher.script.language.select="--select language--"
|
AdvSceneSwitcher.script.language.select="--select language--"
|
||||||
AdvSceneSwitcher.script.language.layout="Script language:{{language}}"
|
AdvSceneSwitcher.script.language.layout="Script language:{{language}}"
|
||||||
AdvSceneSwitcher.script.file.open="Open"
|
AdvSceneSwitcher.script.file.open="Open"
|
||||||
AdvSceneSwitcher.script.file.select="Select Script File"
|
|
||||||
AdvSceneSwitcher.script.file.open.failed="Could not open script file!"
|
AdvSceneSwitcher.script.file.open.failed="Could not open script file!"
|
||||||
AdvSceneSwitcher.script.file.warning.notFound="Warning: The given file path was not found!"
|
AdvSceneSwitcher.script.file.warning.notFound="Warning: The given file path was not found!"
|
||||||
AdvSceneSwitcher.script.file.warning.openFail="Warning: Could not open the script file!"
|
AdvSceneSwitcher.script.file.warning.openFail="Warning: Could not open the script file!"
|
||||||
@@ -1795,10 +1662,6 @@ AdvSceneSwitcher.script.file.layout="Script file:{{path}}{{open}}"
|
|||||||
|
|
||||||
AdvSceneSwitcher.tempVar.select="--select value--"
|
AdvSceneSwitcher.tempVar.select="--select value--"
|
||||||
AdvSceneSwitcher.tempVar.selectionInfo.lastValues="Last values:"
|
AdvSceneSwitcher.tempVar.selectionInfo.lastValues="Last values:"
|
||||||
AdvSceneSwitcher.tempVar.outputMappings="Save outputs to variables:"
|
|
||||||
AdvSceneSwitcher.tempVar.outputMappings.add="+ Add output mapping"
|
|
||||||
AdvSceneSwitcher.tempVar.outputMappings.toggle="Assign outputs to variables"
|
|
||||||
AdvSceneSwitcher.tempVar.outputMappings.remove="Remove output mapping"
|
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_id="Twitch broadcaster user ID"
|
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_id="Twitch broadcaster user ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_id.description="The numerical Twitch user ID of the broadcaster."
|
AdvSceneSwitcher.tempVar.twitch.broadcaster_user_id.description="The numerical Twitch user ID of the broadcaster."
|
||||||
@@ -2282,8 +2145,6 @@ AdvSceneSwitcher.tempVar.window.window="Window title"
|
|||||||
AdvSceneSwitcher.tempVar.window.window.description="The window title of the matching window."
|
AdvSceneSwitcher.tempVar.window.window.description="The window title of the matching window."
|
||||||
AdvSceneSwitcher.tempVar.window.windowClass="Window class"
|
AdvSceneSwitcher.tempVar.window.windowClass="Window class"
|
||||||
AdvSceneSwitcher.tempVar.window.windowClass.description="The window class of the matching window."
|
AdvSceneSwitcher.tempVar.window.windowClass.description="The window class of the matching window."
|
||||||
AdvSceneSwitcher.tempVar.window.windowText="Window text"
|
|
||||||
AdvSceneSwitcher.tempVar.window.windowText.description="Text contained within the window (won't work on all window types)."
|
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.timer.seconds="Seconds"
|
AdvSceneSwitcher.tempVar.timer.seconds="Seconds"
|
||||||
AdvSceneSwitcher.tempVar.timer.minutes="Minutes"
|
AdvSceneSwitcher.tempVar.timer.minutes="Minutes"
|
||||||
@@ -2308,21 +2169,8 @@ AdvSceneSwitcher.tempVar.macro.runCount="Run count"
|
|||||||
AdvSceneSwitcher.tempVar.macro.runCount.description="The number of times a macro was executed."
|
AdvSceneSwitcher.tempVar.macro.runCount.description="The number of times a macro was executed."
|
||||||
AdvSceneSwitcher.tempVar.macro.matchedCount="Matched count"
|
AdvSceneSwitcher.tempVar.macro.matchedCount="Matched count"
|
||||||
AdvSceneSwitcher.tempVar.macro.matchedCount.description="The number of macros of which the condition state was true."
|
AdvSceneSwitcher.tempVar.macro.matchedCount.description="The number of macros of which the condition state was true."
|
||||||
AdvSceneSwitcher.tempVar.macro.info.conditionCount="Condition count"
|
|
||||||
AdvSceneSwitcher.tempVar.macro.info.conditionCount.description="The number of conditions in the macro."
|
|
||||||
AdvSceneSwitcher.tempVar.macro.info.actionCount="Action count"
|
|
||||||
AdvSceneSwitcher.tempVar.macro.info.actionCount.description="The number of actions in the macro."
|
|
||||||
AdvSceneSwitcher.tempVar.macro.info.elseActionCount="Else-action count"
|
|
||||||
AdvSceneSwitcher.tempVar.macro.info.elseActionCount.description="The number of else-actions in the macro."
|
|
||||||
AdvSceneSwitcher.tempVar.macro.info.paused="Paused"
|
|
||||||
AdvSceneSwitcher.tempVar.macro.info.paused.description="Whether the macro is currently paused. Value is \"true\" or \"false\"."
|
|
||||||
AdvSceneSwitcher.tempVar.macro.info.runCount="Run count"
|
|
||||||
AdvSceneSwitcher.tempVar.macro.info.runCount.description="The number of times the macro has been executed."
|
|
||||||
AdvSceneSwitcher.tempVar.macro.info.secondsSinceLastRun="Seconds since last run"
|
|
||||||
AdvSceneSwitcher.tempVar.macro.info.secondsSinceLastRun.description="The number of seconds elapsed since the macro was last executed. Value is -1 if the macro has never been executed."
|
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.process.name="Process name"
|
AdvSceneSwitcher.tempVar.process.name="Process name"
|
||||||
AdvSceneSwitcher.tempVar.process.path="Process path"
|
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.run.process.id="Process ID"
|
AdvSceneSwitcher.tempVar.run.process.id="Process ID"
|
||||||
AdvSceneSwitcher.tempVar.run.process.id.description="PID of the process assigned by the system."
|
AdvSceneSwitcher.tempVar.run.process.id.description="PID of the process assigned by the system."
|
||||||
@@ -2341,8 +2189,6 @@ AdvSceneSwitcher.tempVar.recording.durationSeconds.description="Recording durati
|
|||||||
AdvSceneSwitcher.tempVar.recording.lastSavePath="Last save path"
|
AdvSceneSwitcher.tempVar.recording.lastSavePath="Last save path"
|
||||||
AdvSceneSwitcher.tempVar.recording.lastSavePath.description="The file path of the last saved recording."
|
AdvSceneSwitcher.tempVar.recording.lastSavePath.description="The file path of the last saved recording."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.video.similarity="Similarity Rating"
|
|
||||||
AdvSceneSwitcher.tempVar.video.similarity.description="Values range from 0 to 1, where 0 means dissimilar and 1 means highly similar."
|
|
||||||
AdvSceneSwitcher.tempVar.video.patternCount="Pattern count"
|
AdvSceneSwitcher.tempVar.video.patternCount="Pattern count"
|
||||||
AdvSceneSwitcher.tempVar.video.patternCount.description="The number of times the given pattern has been found in a given video input frame."
|
AdvSceneSwitcher.tempVar.video.patternCount.description="The number of times the given pattern has been found in a given video input frame."
|
||||||
AdvSceneSwitcher.tempVar.video.objectCount="Object count"
|
AdvSceneSwitcher.tempVar.video.objectCount="Object count"
|
||||||
@@ -2353,8 +2199,6 @@ AdvSceneSwitcher.tempVar.video.text="OCR text"
|
|||||||
AdvSceneSwitcher.tempVar.video.text.description="The text detected in a given video input frame."
|
AdvSceneSwitcher.tempVar.video.text.description="The text detected in a given video input frame."
|
||||||
AdvSceneSwitcher.tempVar.video.color="Average color"
|
AdvSceneSwitcher.tempVar.video.color="Average color"
|
||||||
AdvSceneSwitcher.tempVar.video.color.description="The average RGB color in a given video input frame in HexArgb format."
|
AdvSceneSwitcher.tempVar.video.color.description="The average RGB color in a given video input frame in HexArgb format."
|
||||||
AdvSceneSwitcher.tempVar.video.dominantColor="Dominant color"
|
|
||||||
AdvSceneSwitcher.tempVar.video.dominantColor.description="The most dominant RGB color in a given video input frame in HexArgb format.\nDetermined using k-means clustering, which groups similar colors and returns the center of the largest group.\nDue to the nature of the algorithm the result may vary slightly between evaluations."
|
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.websocket.message="Received websocket message"
|
AdvSceneSwitcher.tempVar.websocket.message="Received websocket message"
|
||||||
AdvSceneSwitcher.tempVar.websocket.message.description="The received websocket message, which matched the given pattern"
|
AdvSceneSwitcher.tempVar.websocket.message.description="The received websocket message, which matched the given pattern"
|
||||||
@@ -2484,14 +2328,9 @@ AdvSceneSwitcher.tempVar.gameCapture.executable="Executable"
|
|||||||
AdvSceneSwitcher.tempVar.gameCapture.executable.description="Executable name of the application captured by the source."
|
AdvSceneSwitcher.tempVar.gameCapture.executable.description="Executable name of the application captured by the source."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.http.status="Status code"
|
AdvSceneSwitcher.tempVar.http.status="Status code"
|
||||||
|
AdvSceneSwitcher.tempVar.http.body="Message body"
|
||||||
AdvSceneSwitcher.tempVar.http.error="Error"
|
AdvSceneSwitcher.tempVar.http.error="Error"
|
||||||
AdvSceneSwitcher.tempVar.http.error.description="Empty when no error occurred.\nOther possible values:\n\n * Could not establish connection\n * Failed to bind IP address\n * Failed to read connection\n * Failed to write connection\n * Maximum redirect count exceeded\n * Connection handling canceled\n * SSL connection failed\n * SSL certificate loading failed\n * SSL server verification failed\n * Unsupported HTTP multipart boundary characters\n * Compression failed\n * Connection timed out\n * Proxy connection failed\n * Unknown"
|
AdvSceneSwitcher.tempVar.http.error.description="Empty when no error occurred.\nOther possible values:\n\n * Could not establish connection\n * Failed to bind IP address\n * Failed to read connection\n * Failed to write connection\n * Maximum redirect count exceeded\n * Connection handling canceled\n * SSL connection failed\n * SSL certificate loading failed\n * SSL server verification failed\n * Unsupported HTTP multipart boundary characters\n * Compression failed\n * Connection timed out\n * Proxy connection failed\n * Unknown"
|
||||||
AdvSceneSwitcher.tempVar.http.method="Method"
|
|
||||||
AdvSceneSwitcher.tempVar.http.method.description="Received HTTP request method"
|
|
||||||
AdvSceneSwitcher.tempVar.http.path="Request path"
|
|
||||||
AdvSceneSwitcher.tempVar.http.path.description="Received HTTP request path"
|
|
||||||
AdvSceneSwitcher.tempVar.http.body="Message body"
|
|
||||||
AdvSceneSwitcher.tempVar.http.body.description="Received HTTP request body"
|
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.mqtt.message="Message"
|
AdvSceneSwitcher.tempVar.mqtt.message="Message"
|
||||||
|
|
||||||
@@ -2501,14 +2340,6 @@ AdvSceneSwitcher.tempVar.cursor.y="Cursor position (Y)"
|
|||||||
AdvSceneSwitcher.tempVar.replay.lastSavePath="Last save path"
|
AdvSceneSwitcher.tempVar.replay.lastSavePath="Last save path"
|
||||||
AdvSceneSwitcher.tempVar.replay.lastSavePath.description="The file path of the last replay buffer saved."
|
AdvSceneSwitcher.tempVar.replay.lastSavePath.description="The file path of the last replay buffer saved."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.sequence.macro="Macro"
|
|
||||||
AdvSceneSwitcher.tempVar.sequence.macro.description="The name of the macro executed by the \"Sequence\" action.\nIf no macro was executed the returned value is the empty string."
|
|
||||||
AdvSceneSwitcher.tempVar.sequence.nextMacro="Next Macro"
|
|
||||||
AdvSceneSwitcher.tempVar.sequence.nextMacro.description="The name of the macro which will be executed next after the index was set.\nIf no macro will be executed the returned value is the empty string."
|
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.random.macro="Macro"
|
|
||||||
AdvSceneSwitcher.tempVar.random.macro.description="The name of the macro executed by the \"Random\" action.\nIf no macro was executed the returned value is the empty string."
|
|
||||||
|
|
||||||
AdvSceneSwitcher.selectScene="--select scene--"
|
AdvSceneSwitcher.selectScene="--select scene--"
|
||||||
AdvSceneSwitcher.selectCanvas="--select canvas--"
|
AdvSceneSwitcher.selectCanvas="--select canvas--"
|
||||||
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
||||||
@@ -2598,6 +2429,8 @@ AdvSceneSwitcher.status.inactive="Inactive"
|
|||||||
AdvSceneSwitcher.running="Plugin running"
|
AdvSceneSwitcher.running="Plugin running"
|
||||||
AdvSceneSwitcher.stopped="Plugin stopped"
|
AdvSceneSwitcher.stopped="Plugin stopped"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>This seems to be the first time the Advanced Scene Switcher was started.<br>Please have a look at the <a href=\"https://github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> for a list of guides and examples.<br>Do not hesitate to ask questions in the plugin's <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">thread</span></a> on the OBS forums!</p></body></html>"
|
||||||
|
|
||||||
AdvSceneSwitcher.deprecatedTabWarning="Development for this tab stopped!\nPlease consider transitioning to using Macros instead.\nThis hint can be disabled on the General tab."
|
AdvSceneSwitcher.deprecatedTabWarning="Development for this tab stopped!\nPlease consider transitioning to using Macros instead.\nThis hint can be disabled on the General tab."
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="milliseconds"
|
AdvSceneSwitcher.unit.milliseconds="milliseconds"
|
||||||
@@ -2627,47 +2460,6 @@ AdvSceneSwitcher.clearBufferOnMatch="Clear message buffer when matching message
|
|||||||
AdvSceneSwitcher.script.settings="Settings"
|
AdvSceneSwitcher.script.settings="Settings"
|
||||||
AdvSceneSwitcher.script.timeout="Script timeout:{{timeout}}"
|
AdvSceneSwitcher.script.timeout="Script timeout:{{timeout}}"
|
||||||
|
|
||||||
AdvSceneSwitcher.day.monday="Monday"
|
|
||||||
AdvSceneSwitcher.day.tuesday="Tuesday"
|
|
||||||
AdvSceneSwitcher.day.wednesday="Wednesday"
|
|
||||||
AdvSceneSwitcher.day.thursday="Thursday"
|
|
||||||
AdvSceneSwitcher.day.friday="Friday"
|
|
||||||
AdvSceneSwitcher.day.saturday="Saturday"
|
|
||||||
AdvSceneSwitcher.day.sunday="Sunday"
|
|
||||||
AdvSceneSwitcher.day.none="No day"
|
|
||||||
AdvSceneSwitcher.day.any="Any day"
|
|
||||||
|
|
||||||
# First run wizard
|
|
||||||
FirstRunWizard.windowTitle="Advanced Scene Switcher - Setup Wizard"
|
|
||||||
|
|
||||||
FirstRunWizard.welcome.title="Welcome to Advanced Scene Switcher"
|
|
||||||
FirstRunWizard.welcome.subtitle="Let's create your first automation in a few easy steps."
|
|
||||||
FirstRunWizard.welcome.body="<p>Advanced Scene Switcher lets you build <b>Macros</b> - rules of the form:</p><blockquote><i>When [condition] -> perform [action]</i></blockquote><p>This wizard creates a macro that <b>switches to a chosen OBS scene whenever a specific window comes into focus</b>.</p><p>You can skip at any time. Re-open this wizard later from the <b>General</b> tab inside the Advanced Scene Switcher dialog.</p>"
|
|
||||||
|
|
||||||
FirstRunWizard.scene.title="Choose a Target Scene"
|
|
||||||
FirstRunWizard.scene.subtitle="Which OBS scene should become active when your chosen window comes into focus?"
|
|
||||||
FirstRunWizard.scene.label="Switch to scene:"
|
|
||||||
|
|
||||||
FirstRunWizard.window.title="Choose a Trigger Window"
|
|
||||||
FirstRunWizard.window.subtitle="Enter the title of the window that should trigger the scene switch. Partial matches are fine - \"Firefox\" will match any Firefox window."
|
|
||||||
FirstRunWizard.window.label="Window title contains:"
|
|
||||||
FirstRunWizard.window.placeholder="e.g. \"Firefox\", \"Visual Studio Code\""
|
|
||||||
FirstRunWizard.window.autoDetect="Auto-detect focused window"
|
|
||||||
FirstRunWizard.window.autoDetectTooltip="Click, then switch to the target window. The title will be captured automatically after 3 seconds."
|
|
||||||
FirstRunWizard.window.autoDetectCountdown="Detecting in %1 s - focus your window now..."
|
|
||||||
FirstRunWizard.window.hint="<small>Tip: a short partial title is more robust than the full title, which often changes when you switch tabs.</small>"
|
|
||||||
|
|
||||||
FirstRunWizard.review.title="Review Your Macro"
|
|
||||||
FirstRunWizard.review.subtitle="Click Back to make changes, or Finish to create the macro."
|
|
||||||
FirstRunWizard.review.summary="<b>Macro name:</b> Window -> %1<br><br><b>Condition:</b> Focused window title contains <i>\"%2\"</i> (case-insensitive)<br><br><b>Action:</b> Switch to scene <i>\"%1\"</i>"
|
|
||||||
FirstRunWizard.review.errorTitle="Macro Creation Failed"
|
|
||||||
FirstRunWizard.review.errorBody="The macro could not be created automatically.\n\nYou can create it manually on the Macros tab:\n Condition: Window -> contains \"%1\"\n Action: Switch scene -> \"%2\""
|
|
||||||
|
|
||||||
FirstRunWizard.done.title="You're all set!"
|
|
||||||
FirstRunWizard.done.subtitle="Your first macro has been created and is now active."
|
|
||||||
FirstRunWizard.done.body="<p>You can view and edit it on the <b>Macros</b> tab of the Advanced Scene Switcher dialog.</p><p>To learn more:</p><ul><li><a href=\"https://github.com/WarmUpTill/SceneSwitcher/wiki\">Plugin wiki</a></li><li><a href=\"https://obsproject.com/forum/resources/automatic-scene-switching.395/\">OBS forum thread</a></li></ul>"
|
|
||||||
|
|
||||||
FirstRunWizard.openButton="Open Setup Wizard..."
|
|
||||||
# This secion is copied from the OBS locale files
|
# This secion is copied from the OBS locale files
|
||||||
|
|
||||||
# OBS commonly shared locale
|
# OBS commonly shared locale
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ AdvSceneSwitcher.macroTab.add="Agregar nueva macro"
|
|||||||
AdvSceneSwitcher.macroTab.name="Nombre:"
|
AdvSceneSwitcher.macroTab.name="Nombre:"
|
||||||
AdvSceneSwitcher.macroTab.run="Ejecutar macro"
|
AdvSceneSwitcher.macroTab.run="Ejecutar macro"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="Ejecutar macro en paralelo a otras macros"
|
AdvSceneSwitcher.macroTab.runInParallel="Ejecutar macro en paralelo a otras macros"
|
||||||
|
AdvSceneSwitcher.macroTab.onChange="Realizar acciones solo en el cambio de condición"
|
||||||
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
||||||
AdvSceneSwitcher.macroTab.copy="Crear copia"
|
AdvSceneSwitcher.macroTab.copy="Crear copia"
|
||||||
AdvSceneSwitcher.macroTab.expandAll="Expandir todo"
|
AdvSceneSwitcher.macroTab.expandAll="Expandir todo"
|
||||||
@@ -117,7 +118,9 @@ AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Durante la tra
|
|||||||
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="Durante la transición, verifique la escena de origen de la transición"
|
AdvSceneSwitcher.condition.scene.previousSceneTransitionBehaviour="Durante la transición, verifique la escena de origen de la transición"
|
||||||
AdvSceneSwitcher.condition.window="Ventana"
|
AdvSceneSwitcher.condition.window="Ventana"
|
||||||
AdvSceneSwitcher.condition.file="Archivo"
|
AdvSceneSwitcher.condition.file="Archivo"
|
||||||
AdvSceneSwitcher.condition.file.layout="Contenido de{{filePath}}{{conditions}}{{regex}}"
|
AdvSceneSwitcher.condition.file.entry.line1="Contenido de{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||||
AdvSceneSwitcher.condition.media="Medios"
|
AdvSceneSwitcher.condition.media="Medios"
|
||||||
AdvSceneSwitcher.condition.media.anyOnScene="Cualquier fuente multimedia activada"
|
AdvSceneSwitcher.condition.media.anyOnScene="Cualquier fuente multimedia activada"
|
||||||
AdvSceneSwitcher.condition.media.allOnScene="Todas las fuentes de medios activadas"
|
AdvSceneSwitcher.condition.media.allOnScene="Todas las fuentes de medios activadas"
|
||||||
@@ -173,7 +176,7 @@ AdvSceneSwitcher.condition.record.state.start="Grabación en ejecución"
|
|||||||
AdvSceneSwitcher.condition.record.state.pause="Grabación en pausa"
|
AdvSceneSwitcher.condition.record.state.pause="Grabación en pausa"
|
||||||
AdvSceneSwitcher.condition.record.state.stop="Grabación detenida"
|
AdvSceneSwitcher.condition.record.state.stop="Grabación detenida"
|
||||||
AdvSceneSwitcher.condition.process="Proceso"
|
AdvSceneSwitcher.condition.process="Proceso"
|
||||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}se está ejecutando{{focused}}y está enfocado"
|
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}se está ejecutando{{focused}}y está enfocado"
|
||||||
AdvSceneSwitcher.condition.idle="Inactivo"
|
AdvSceneSwitcher.condition.idle="Inactivo"
|
||||||
AdvSceneSwitcher.condition.idle.entry="No hay entradas de teclado o ratón durante {{duration}}"
|
AdvSceneSwitcher.condition.idle.entry="No hay entradas de teclado o ratón durante {{duration}}"
|
||||||
AdvSceneSwitcher.condition.pluginState="Estado del complemento"
|
AdvSceneSwitcher.condition.pluginState="Estado del complemento"
|
||||||
@@ -238,14 +241,14 @@ AdvSceneSwitcher.condition.replay.state.started="Búfer de reproducción iniciad
|
|||||||
AdvSceneSwitcher.condition.replay.state.saved="Búfer de reproducción guardado"
|
AdvSceneSwitcher.condition.replay.state.saved="Búfer de reproducción guardado"
|
||||||
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
||||||
AdvSceneSwitcher.condition.date="Fecha"
|
AdvSceneSwitcher.condition.date="Fecha"
|
||||||
AdvSceneSwitcher.day.any="Cualquier día"
|
AdvSceneSwitcher.condition.date.anyDay="Cualquier día"
|
||||||
AdvSceneSwitcher.day.monday="Lunes"
|
AdvSceneSwitcher.condition.date.monday="Lunes"
|
||||||
AdvSceneSwitcher.day.tuesday="Martes"
|
AdvSceneSwitcher.condition.date.tuesday="Martes"
|
||||||
AdvSceneSwitcher.day.wednesday="Miércoles"
|
AdvSceneSwitcher.condition.date.wednesday="Miércoles"
|
||||||
AdvSceneSwitcher.day.thursday="Jueves"
|
AdvSceneSwitcher.condition.date.thursday="Jueves"
|
||||||
AdvSceneSwitcher.day.friday="Viernes"
|
AdvSceneSwitcher.condition.date.friday="Viernes"
|
||||||
AdvSceneSwitcher.day.saturday="Sábado"
|
AdvSceneSwitcher.condition.date.saturday="Sábado"
|
||||||
AdvSceneSwitcher.day.sunday="Domingo"
|
AdvSceneSwitcher.condition.date.sunday="Domingo"
|
||||||
AdvSceneSwitcher.condition.date.state.at="A las"
|
AdvSceneSwitcher.condition.date.state.at="A las"
|
||||||
AdvSceneSwitcher.condition.date.state.after="Después"
|
AdvSceneSwitcher.condition.date.state.after="Después"
|
||||||
AdvSceneSwitcher.condition.date.state.before="Antes"
|
AdvSceneSwitcher.condition.date.state.before="Antes"
|
||||||
@@ -255,12 +258,11 @@ AdvSceneSwitcher.condition.date.ignoreDate="Si no se marca, se ignorará el comp
|
|||||||
AdvSceneSwitcher.condition.date.ignoreTime="Si no se marca, se ignorará el componente de tiempo"
|
AdvSceneSwitcher.condition.date.ignoreTime="Si no se marca, se ignorará el componente de tiempo"
|
||||||
AdvSceneSwitcher.condition.date.showAdvancedSettings="Mostrar configuración avanzada"
|
AdvSceneSwitcher.condition.date.showAdvancedSettings="Mostrar configuración avanzada"
|
||||||
AdvSceneSwitcher.condition.date.showSimpleSettings="Mostrar configuración simple"
|
AdvSceneSwitcher.condition.date.showSimpleSettings="Mostrar configuración simple"
|
||||||
AdvSceneSwitcher.condition.date.layout.simple.day="El{{dayOfWeek}}"
|
AdvSceneSwitcher.condition.date.entry.simple="El {{dayOfWeek}} {{weekCondition}} {{ignoreWeekTime}}{{weekTime}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.simple.time="{{ignoreWeekTime}}{{weekCondition}}{{weekTime}}"
|
AdvSceneSwitcher.condition.date.entry.advanced="{{condition}} {{ignoreDate}}{{date}} {{ignoreTime}}{{time}} {{separator}} {{date2}} {{time2}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.advanced="{{condition}} {{ignoreDate}}{{date}} {{ignoreTime}}{{time}} {{separator}} {{date2}} {{time2}}"
|
AdvSceneSwitcher.condition.date.entry.repeat="{{repeat}} Repetir cada {{duration}} en la coincidencia de fechas"
|
||||||
AdvSceneSwitcher.condition.date.layout.repeat="{{repeat}} Repetir cada {{duration}} en la coincidencia de fechas"
|
AdvSceneSwitcher.condition.date.entry.nextMatchDate="Próxima coincidencia en: %1"
|
||||||
AdvSceneSwitcher.condition.date.layout.nextMatchDate="Próxima coincidencia en: %1"
|
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} Al repetir actualizar la fecha seleccionada para repetir la fecha"
|
||||||
AdvSceneSwitcher.condition.date.layout.updateOnRepeat="{{updateOnRepeat}} Al repetir actualizar la fecha seleccionada para repetir la fecha"
|
|
||||||
AdvSceneSwitcher.condition.sceneTransform="Transformar elemento de escena"
|
AdvSceneSwitcher.condition.sceneTransform="Transformar elemento de escena"
|
||||||
AdvSceneSwitcher.condition.sceneTransform.getTransform="Obtener transformación"
|
AdvSceneSwitcher.condition.sceneTransform.getTransform="Obtener transformación"
|
||||||
AdvSceneSwitcher.condition.sceneTransform.condition.match="coincide con la transformación"
|
AdvSceneSwitcher.condition.sceneTransform.condition.match="coincide con la transformación"
|
||||||
@@ -332,6 +334,7 @@ AdvSceneSwitcher.action.recording.type.start="Iniciar grabación"
|
|||||||
AdvSceneSwitcher.action.recording.type.pause="Pausar grabación"
|
AdvSceneSwitcher.action.recording.type.pause="Pausar grabación"
|
||||||
AdvSceneSwitcher.action.recording.type.unpause="Reanudar grabación"
|
AdvSceneSwitcher.action.recording.type.unpause="Reanudar grabación"
|
||||||
AdvSceneSwitcher.action.recording.pause.hint="Tenga en cuenta que, dependiendo de la configuración de grabación, es posible que no pueda pausar la grabación"
|
AdvSceneSwitcher.action.recording.pause.hint="Tenga en cuenta que, dependiendo de la configuración de grabación, es posible que no pueda pausar la grabación"
|
||||||
|
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||||
AdvSceneSwitcher.action.replay="Búfer de reproducción"
|
AdvSceneSwitcher.action.replay="Búfer de reproducción"
|
||||||
AdvSceneSwitcher.action.replay.saveWarn="Advertencia: ¡Guardar con demasiada frecuencia puede hacer que el búfer de reproducción no se guarde realmente!"
|
AdvSceneSwitcher.action.replay.saveWarn="Advertencia: ¡Guardar con demasiada frecuencia puede hacer que el búfer de reproducción no se guarde realmente!"
|
||||||
AdvSceneSwitcher.action.replay.type.stop="Detener el búfer de reproducción"
|
AdvSceneSwitcher.action.replay.type.stop="Detener el búfer de reproducción"
|
||||||
@@ -340,13 +343,14 @@ AdvSceneSwitcher.action.replay.type.save="Guardar búfer de reproducción"
|
|||||||
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"
|
||||||
|
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}"
|
||||||
AdvSceneSwitcher.action.run="Ejecutar"
|
AdvSceneSwitcher.action.run="Ejecutar"
|
||||||
AdvSceneSwitcher.action.sceneVisibility="Visibilidad del elemento de escena"
|
AdvSceneSwitcher.action.sceneVisibility="Visibilidad del elemento de escena"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.show="Mostrar"
|
AdvSceneSwitcher.action.sceneVisibility.type.show="Mostrar"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.hide="Ocultar"
|
AdvSceneSwitcher.action.sceneVisibility.type.hide="Ocultar"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Fuente"
|
AdvSceneSwitcher.action.sceneVisibility.type.source="Fuente"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Cualquiera"
|
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Cualquiera"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.layout="En{{scenes}}{{actions}}{{sources}}"
|
AdvSceneSwitcher.action.sceneVisibility.entry="En{{scenes}}{{actions}}{{sources}}"
|
||||||
AdvSceneSwitcher.action.filter="Filtro"
|
AdvSceneSwitcher.action.filter="Filtro"
|
||||||
AdvSceneSwitcher.action.filter.type.enable="Habilitar"
|
AdvSceneSwitcher.action.filter.type.enable="Habilitar"
|
||||||
AdvSceneSwitcher.action.filter.type.disable="Deshabilitar"
|
AdvSceneSwitcher.action.filter.type.disable="Deshabilitar"
|
||||||
@@ -371,7 +375,7 @@ AdvSceneSwitcher.action.macro="Macro"
|
|||||||
AdvSceneSwitcher.action.macro.type.pause="Pausa"
|
AdvSceneSwitcher.action.macro.type.pause="Pausa"
|
||||||
AdvSceneSwitcher.action.macro.type.unpause="Reanudar"
|
AdvSceneSwitcher.action.macro.type.unpause="Reanudar"
|
||||||
AdvSceneSwitcher.action.macro.type.resetCounter="Reiniciar contador"
|
AdvSceneSwitcher.action.macro.type.resetCounter="Reiniciar contador"
|
||||||
AdvSceneSwitcher.action.macro.type.runActions="Ejecutar"
|
AdvSceneSwitcher.action.macro.type.run="Ejecutar"
|
||||||
AdvSceneSwitcher.action.macro.type.stop="Detener"
|
AdvSceneSwitcher.action.macro.type.stop="Detener"
|
||||||
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"
|
||||||
@@ -419,9 +423,9 @@ AdvSceneSwitcher.action.transition.type.scene="transición de escena"
|
|||||||
AdvSceneSwitcher.action.transition.type.sceneOverride="anulación de transición de escena"
|
AdvSceneSwitcher.action.transition.type.sceneOverride="anulación de transición de escena"
|
||||||
AdvSceneSwitcher.action.transition.type.sourceShow="transición del programa de origen"
|
AdvSceneSwitcher.action.transition.type.sourceShow="transición del programa de origen"
|
||||||
AdvSceneSwitcher.action.transition.type.sourceHide="fuente ocultar transición"
|
AdvSceneSwitcher.action.transition.type.sourceHide="fuente ocultar transición"
|
||||||
AdvSceneSwitcher.action.transition.layout.type="Modificar {{type}}{{scenes}}{{sources}}"
|
AdvSceneSwitcher.action.transition.entry.line1="Modificar {{type}}{{scenes}}{{sources}}"
|
||||||
AdvSceneSwitcher.action.transition.layout.transition="{{setTransition}}Establecer el tipo de transición en {{transitions}}"
|
AdvSceneSwitcher.action.transition.entry.line2="{{setTransition}}Establecer el tipo de transición en {{transitions}}"
|
||||||
AdvSceneSwitcher.action.transition.layout.duration="{{setDuration}}Establecer la duración de la transición en {{duration}}segundos"
|
AdvSceneSwitcher.action.transition.entry.line3="{{setDuration}}Establecer la duración de la transición en {{duration}}segundos"
|
||||||
AdvSceneSwitcher.action.timer="Temporizador"
|
AdvSceneSwitcher.action.timer="Temporizador"
|
||||||
AdvSceneSwitcher.action.timer.type.pause="Pausa"
|
AdvSceneSwitcher.action.timer.type.pause="Pausa"
|
||||||
AdvSceneSwitcher.action.timer.type.continue="Continuar"
|
AdvSceneSwitcher.action.timer.type.continue="Continuar"
|
||||||
@@ -676,6 +680,8 @@ AdvSceneSwitcher.status.inactive="Inactivo"
|
|||||||
AdvSceneSwitcher.running="Iniciar complemento"
|
AdvSceneSwitcher.running="Iniciar complemento"
|
||||||
AdvSceneSwitcher.stopped="Complemento de detención"
|
AdvSceneSwitcher.stopped="Complemento de detención"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Esta parece ser la primera vez que se inicia el conmutador de escena avanzado.<br>Por favor, eche un vistazo a <a href=\"https:/ /github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> para obtener una lista de guías y ejemplos.<br>No dude en hacer preguntas en el complemento <a href=\"https://obsproject.com /forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">hilo</span></a> en los foros de OBS!</p></body></html>"
|
||||||
|
|
||||||
AdvSceneSwitcher.deprecatedTabWarning="¡Se detuvo el desarrollo de esta pestaña!\nConsidere cambiar a macros en su lugar.\nEsta sugerencia se puede desactivar en la pestaña General".
|
AdvSceneSwitcher.deprecatedTabWarning="¡Se detuvo el desarrollo de esta pestaña!\nConsidere cambiar a macros en su lugar.\nEsta sugerencia se puede desactivar en la pestaña General".
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="milisegundos"
|
AdvSceneSwitcher.unit.milliseconds="milisegundos"
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ AdvSceneSwitcher.macroTab.add="Ajouter une nouvelle macro"
|
|||||||
AdvSceneSwitcher.macroTab.name="Nom :"
|
AdvSceneSwitcher.macroTab.name="Nom :"
|
||||||
AdvSceneSwitcher.macroTab.run="Exécuter la macro"
|
AdvSceneSwitcher.macroTab.run="Exécuter la macro"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="Exécuter la macro en parallèle avec d'autres macros"
|
AdvSceneSwitcher.macroTab.runInParallel="Exécuter la macro en parallèle avec d'autres macros"
|
||||||
|
AdvSceneSwitcher.macroTab.onChange="Exécuter des actions uniquement en cas de changement de condition"
|
||||||
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
||||||
AdvSceneSwitcher.macroTab.defaultGroupName="Groupe %1"
|
AdvSceneSwitcher.macroTab.defaultGroupName="Groupe %1"
|
||||||
AdvSceneSwitcher.macroTab.removeSingleMacroPopup.text="Êtes-vous sûr de vouloir supprimer \"%1\" ?"
|
AdvSceneSwitcher.macroTab.removeSingleMacroPopup.text="Êtes-vous sûr de vouloir supprimer \"%1\" ?"
|
||||||
@@ -187,6 +188,8 @@ AdvSceneSwitcher.condition.file="Fichier"
|
|||||||
AdvSceneSwitcher.condition.file.type.match="correspond à"
|
AdvSceneSwitcher.condition.file.type.match="correspond à"
|
||||||
AdvSceneSwitcher.condition.file.type.contentChange="a changé de contenu"
|
AdvSceneSwitcher.condition.file.type.contentChange="a changé de contenu"
|
||||||
AdvSceneSwitcher.condition.file.type.dateChange="a changé de date de modification"
|
AdvSceneSwitcher.condition.file.type.dateChange="a changé de date de modification"
|
||||||
|
AdvSceneSwitcher.condition.file.remote="Fichier distant"
|
||||||
|
AdvSceneSwitcher.condition.file.local="Fichier local"
|
||||||
AdvSceneSwitcher.condition.media="Média"
|
AdvSceneSwitcher.condition.media="Média"
|
||||||
AdvSceneSwitcher.condition.media.source="Source"
|
AdvSceneSwitcher.condition.media.source="Source"
|
||||||
AdvSceneSwitcher.condition.media.anyOnScene="Toute source média sur la scène"
|
AdvSceneSwitcher.condition.media.anyOnScene="Toute source média sur la scène"
|
||||||
@@ -279,8 +282,8 @@ AdvSceneSwitcher.condition.record.state.start="Enregistrement en cours"
|
|||||||
AdvSceneSwitcher.condition.record.state.pause="Enregistrement en pause"
|
AdvSceneSwitcher.condition.record.state.pause="Enregistrement en pause"
|
||||||
AdvSceneSwitcher.condition.record.state.stop="Arrêt de l'enregistrement"
|
AdvSceneSwitcher.condition.record.state.stop="Arrêt de l'enregistrement"
|
||||||
AdvSceneSwitcher.condition.process="Processus"
|
AdvSceneSwitcher.condition.process="Processus"
|
||||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}en cours d'exécution{{focused}}et est au premier plan"
|
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}en cours d'exécution{{focused}}et est au premier plan"
|
||||||
AdvSceneSwitcher.condition.process.layout.focus="Processus au premier plan actuel :{{focusProcess}}"
|
AdvSceneSwitcher.condition.process.entry.focus="Processus au premier plan actuel :{{focusProcess}}"
|
||||||
AdvSceneSwitcher.condition.idle="Inactif"
|
AdvSceneSwitcher.condition.idle="Inactif"
|
||||||
AdvSceneSwitcher.condition.idle.entry="Aucune entrée de clavier ou de souris pendant{{duration}}"
|
AdvSceneSwitcher.condition.idle.entry="Aucune entrée de clavier ou de souris pendant{{duration}}"
|
||||||
AdvSceneSwitcher.condition.pluginState="État du plugin"
|
AdvSceneSwitcher.condition.pluginState="État du plugin"
|
||||||
@@ -353,14 +356,14 @@ AdvSceneSwitcher.condition.replay.state.stopped="Tampon de répétition arrêté
|
|||||||
AdvSceneSwitcher.condition.replay.state.started="Tampon de répétition démarré"
|
AdvSceneSwitcher.condition.replay.state.started="Tampon de répétition démarré"
|
||||||
AdvSceneSwitcher.condition.replay.state.saved="Tampon de répétition enregistré"
|
AdvSceneSwitcher.condition.replay.state.saved="Tampon de répétition enregistré"
|
||||||
AdvSceneSwitcher.condition.date="Date"
|
AdvSceneSwitcher.condition.date="Date"
|
||||||
AdvSceneSwitcher.day.any="N'importe quel jour"
|
AdvSceneSwitcher.condition.date.anyDay="N'importe quel jour"
|
||||||
AdvSceneSwitcher.day.monday="Lundi"
|
AdvSceneSwitcher.condition.date.monday="Lundi"
|
||||||
AdvSceneSwitcher.day.tuesday="Mardi"
|
AdvSceneSwitcher.condition.date.tuesday="Mardi"
|
||||||
AdvSceneSwitcher.day.wednesday="Mercredi"
|
AdvSceneSwitcher.condition.date.wednesday="Mercredi"
|
||||||
AdvSceneSwitcher.day.thursday="Jeudi"
|
AdvSceneSwitcher.condition.date.thursday="Jeudi"
|
||||||
AdvSceneSwitcher.day.friday="Vendredi"
|
AdvSceneSwitcher.condition.date.friday="Vendredi"
|
||||||
AdvSceneSwitcher.day.saturday="Samedi"
|
AdvSceneSwitcher.condition.date.saturday="Samedi"
|
||||||
AdvSceneSwitcher.day.sunday="Dimanche"
|
AdvSceneSwitcher.condition.date.sunday="Dimanche"
|
||||||
AdvSceneSwitcher.condition.date.state.at="À"
|
AdvSceneSwitcher.condition.date.state.at="À"
|
||||||
AdvSceneSwitcher.condition.date.state.after="Après"
|
AdvSceneSwitcher.condition.date.state.after="Après"
|
||||||
AdvSceneSwitcher.condition.date.state.before="Avant"
|
AdvSceneSwitcher.condition.date.state.before="Avant"
|
||||||
@@ -371,12 +374,11 @@ AdvSceneSwitcher.condition.date.ignoreDate="Si non cochée, la composante date s
|
|||||||
AdvSceneSwitcher.condition.date.ignoreTime="Si non cochée, la composante heure sera ignorée"
|
AdvSceneSwitcher.condition.date.ignoreTime="Si non cochée, la composante heure sera ignorée"
|
||||||
AdvSceneSwitcher.condition.date.showAdvancedSettings="Afficher les paramètres avancés"
|
AdvSceneSwitcher.condition.date.showAdvancedSettings="Afficher les paramètres avancés"
|
||||||
AdvSceneSwitcher.condition.date.showSimpleSettings="Afficher les paramètres simples"
|
AdvSceneSwitcher.condition.date.showSimpleSettings="Afficher les paramètres simples"
|
||||||
AdvSceneSwitcher.condition.date.layout.simple.day="Le{{dayOfWeek}}"
|
AdvSceneSwitcher.condition.date.entry.simple="Le{{dayOfWeek}}{{weekCondition}}{{ignoreWeekTime}}{{weekTime}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.simple.time="{{ignoreWeekTime}}{{weekCondition}}{{weekTime}}"
|
AdvSceneSwitcher.condition.date.entry.repeat="{{repeat}}Répéter toutes les{{duration}}lorsque la date correspond"
|
||||||
AdvSceneSwitcher.condition.date.layout.repeat="{{repeat}}Répéter toutes les{{duration}}lorsque la date correspond"
|
AdvSceneSwitcher.condition.date.entry.pattern="La date actuelle \"{{currentDate}}\" correspond au motif{{pattern}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.pattern="La date actuelle \"{{currentDate}}\" correspond au motif{{pattern}}"
|
AdvSceneSwitcher.condition.date.entry.nextMatchDate="Prochaine correspondance à : %1"
|
||||||
AdvSceneSwitcher.condition.date.layout.nextMatchDate="Prochaine correspondance à : %1"
|
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}}À la répétition, mettre à jour la date sélectionnée pour la date de répétition"
|
||||||
AdvSceneSwitcher.condition.date.layout.updateOnRepeat="{{updateOnRepeat}}À la répétition, mettre à jour la date sélectionnée pour la date de répétition"
|
|
||||||
AdvSceneSwitcher.condition.sceneTransform="Transformation de l'élément de la scène"
|
AdvSceneSwitcher.condition.sceneTransform="Transformation de l'élément de la scène"
|
||||||
AdvSceneSwitcher.condition.sceneTransform.getTransform="Obtenir la transformation"
|
AdvSceneSwitcher.condition.sceneTransform.getTransform="Obtenir la transformation"
|
||||||
AdvSceneSwitcher.condition.sceneTransform.condition.match="correspond à la transformation"
|
AdvSceneSwitcher.condition.sceneTransform.condition.match="correspond à la transformation"
|
||||||
@@ -508,7 +510,7 @@ AdvSceneSwitcher.action.sceneVisibility.type.hide="Masquer"
|
|||||||
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Basculer"
|
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Basculer"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Source"
|
AdvSceneSwitcher.action.sceneVisibility.type.source="Source"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="N'importe"
|
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="N'importe"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.layout="Sur{{scenes}}{{actions}}{{sources}}"
|
AdvSceneSwitcher.action.sceneVisibility.entry="Sur{{scenes}}{{actions}}{{sources}}"
|
||||||
AdvSceneSwitcher.action.filter="Filtre"
|
AdvSceneSwitcher.action.filter="Filtre"
|
||||||
AdvSceneSwitcher.action.filter.type.enable="Activer"
|
AdvSceneSwitcher.action.filter.type.enable="Activer"
|
||||||
AdvSceneSwitcher.action.filter.type.disable="Désactiver"
|
AdvSceneSwitcher.action.filter.type.disable="Désactiver"
|
||||||
@@ -551,7 +553,7 @@ AdvSceneSwitcher.action.macro="Macro"
|
|||||||
AdvSceneSwitcher.action.macro.type.pause="Pause"
|
AdvSceneSwitcher.action.macro.type.pause="Pause"
|
||||||
AdvSceneSwitcher.action.macro.type.unpause="Reprendre"
|
AdvSceneSwitcher.action.macro.type.unpause="Reprendre"
|
||||||
AdvSceneSwitcher.action.macro.type.resetCounter="Réinitialiser le compteur"
|
AdvSceneSwitcher.action.macro.type.resetCounter="Réinitialiser le compteur"
|
||||||
AdvSceneSwitcher.action.macro.type.runActions="Exécuter les actions"
|
AdvSceneSwitcher.action.macro.type.run="Exécuter les actions"
|
||||||
AdvSceneSwitcher.action.macro.type.stop="Arrêter les actions"
|
AdvSceneSwitcher.action.macro.type.stop="Arrêter les actions"
|
||||||
AdvSceneSwitcher.action.macro.type.disableAction="Désactiver l'action"
|
AdvSceneSwitcher.action.macro.type.disableAction="Désactiver l'action"
|
||||||
AdvSceneSwitcher.action.macro.type.enableAction="Activer l'action"
|
AdvSceneSwitcher.action.macro.type.enableAction="Activer l'action"
|
||||||
@@ -620,9 +622,9 @@ AdvSceneSwitcher.action.transition.type.scene="Transition de scène"
|
|||||||
AdvSceneSwitcher.action.transition.type.sceneOverride="Remplacement de la transition de scène"
|
AdvSceneSwitcher.action.transition.type.sceneOverride="Remplacement de la transition de scène"
|
||||||
AdvSceneSwitcher.action.transition.type.sourceShow="Transition d'affichage de la source"
|
AdvSceneSwitcher.action.transition.type.sourceShow="Transition d'affichage de la source"
|
||||||
AdvSceneSwitcher.action.transition.type.sourceHide="Transition de masquage de la source"
|
AdvSceneSwitcher.action.transition.type.sourceHide="Transition de masquage de la source"
|
||||||
AdvSceneSwitcher.action.transition.layout.type="Modifier{{type}}{{scenes}}{{sources}}"
|
AdvSceneSwitcher.action.transition.entry.line1="Modifier{{type}}{{scenes}}{{sources}}"
|
||||||
AdvSceneSwitcher.action.transition.layout.transition="{{setTransition}}Définir le type de transition sur{{transitions}}"
|
AdvSceneSwitcher.action.transition.entry.line2="{{setTransition}}Définir le type de transition sur{{transitions}}"
|
||||||
AdvSceneSwitcher.action.transition.layout.duration="{{setDuration}}Définir la durée de la transition à{{duration}}secondes"
|
AdvSceneSwitcher.action.transition.entry.line3="{{setDuration}}Définir la durée de la transition à{{duration}}secondes"
|
||||||
AdvSceneSwitcher.action.timer="Minuterie"
|
AdvSceneSwitcher.action.timer="Minuterie"
|
||||||
AdvSceneSwitcher.action.timer.type.pause="Mettre en pause"
|
AdvSceneSwitcher.action.timer.type.pause="Mettre en pause"
|
||||||
AdvSceneSwitcher.action.timer.type.continue="Continuer"
|
AdvSceneSwitcher.action.timer.type.continue="Continuer"
|
||||||
@@ -699,8 +701,8 @@ AdvSceneSwitcher.action.variable.invalidSelection="Sélection invalide !"
|
|||||||
AdvSceneSwitcher.action.variable.actionNoVariableSupport="La récupération de valeurs de variables à partir d'actions %1 n'est pas prise en charge !"
|
AdvSceneSwitcher.action.variable.actionNoVariableSupport="La récupération de valeurs de variables à partir d'actions %1 n'est pas prise en charge !"
|
||||||
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="La récupération de valeurs de variables à partir de conditions %1 n'est pas prise en charge !"
|
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="La récupération de valeurs de variables à partir de conditions %1 n'est pas prise en charge !"
|
||||||
AdvSceneSwitcher.action.variable.currentSegmentValue="Valeur actuelle :"
|
AdvSceneSwitcher.action.variable.currentSegmentValue="Valeur actuelle :"
|
||||||
AdvSceneSwitcher.action.variable.layout.substringIndex="Début de la sous-chaîne :{{subStringStart}}Taille de la sous-chaîne :{{subStringSize}}{{subStringRegex}}"
|
AdvSceneSwitcher.action.variable.layout.substringIndex="Début de la sous-chaîne :{{subStringStart}}Taille de la sous-chaîne :{{subStringSize}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.substringRegex="Attribuer la valeur du match{{regexMatchIdx}}en utilisant une expression régulière:{{subStringRegex}}"
|
AdvSceneSwitcher.action.variable.layout.substringRegex="Attribuer la valeur du match{{regexMatchIdx}}en utilisant une expression régulière :"
|
||||||
AdvSceneSwitcher.action.variable.layout.userInput.customPrompt="{{useCustomPrompt}}Utiliser un message personnalisé{{inputPrompt}}"
|
AdvSceneSwitcher.action.variable.layout.userInput.customPrompt="{{useCustomPrompt}}Utiliser un message personnalisé{{inputPrompt}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.userInput.placeholder="{{useInputPlaceholder}}Remplir avec un indicateur de position{{inputPlaceholder}}"
|
AdvSceneSwitcher.action.variable.layout.userInput.placeholder="{{useInputPlaceholder}}Remplir avec un indicateur de position{{inputPlaceholder}}"
|
||||||
AdvSceneSwitcher.action.projector="Projecteur"
|
AdvSceneSwitcher.action.projector="Projecteur"
|
||||||
@@ -1120,6 +1122,8 @@ AdvSceneSwitcher.status.inactive="Inactif"
|
|||||||
AdvSceneSwitcher.running="Plugin en cours d'exécution"
|
AdvSceneSwitcher.running="Plugin en cours d'exécution"
|
||||||
AdvSceneSwitcher.stopped="Plugin arrêté"
|
AdvSceneSwitcher.stopped="Plugin arrêté"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Il semble que ce soit la première fois que l'Advanced Scene Switcher est démarré.<br>Veuillez consulter le <a href=\"https://github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> pour obtenir une liste de guides et d'exemples.<br>N'hésitez pas à poser des questions dans le <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">fil de discussion</span></a> du plugin sur les forums OBS !</p></body></html>"
|
||||||
|
|
||||||
AdvSceneSwitcher.deprecatedTabWarning="Le développement de cet onglet est terminé !\nVeuillez envisager de passer à l'utilisation des Macros à la place.\nCette astuce peut être désactivée dans l'onglet Général."
|
AdvSceneSwitcher.deprecatedTabWarning="Le développement de cet onglet est terminé !\nVeuillez envisager de passer à l'utilisation des Macros à la place.\nCette astuce peut être désactivée dans l'onglet Général."
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="millisecondes"
|
AdvSceneSwitcher.unit.milliseconds="millisecondes"
|
||||||
|
|||||||
@@ -164,6 +164,7 @@ AdvSceneSwitcher.macroTab.run.tooltip="条件に関係なくすべてのマク
|
|||||||
AdvSceneSwitcher.macroTab.runElse="マクロ実行(else)"
|
AdvSceneSwitcher.macroTab.runElse="マクロ実行(else)"
|
||||||
AdvSceneSwitcher.macroTab.runFail="\"%1\" の実行に失敗しました!\nいずれかのアクションが失敗したか、マクロがすでに実行されています。\n停止しますか?"
|
AdvSceneSwitcher.macroTab.runFail="\"%1\" の実行に失敗しました!\nいずれかのアクションが失敗したか、マクロがすでに実行されています。\n停止しますか?"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="他のマクロと並行してマクロを実行する"
|
AdvSceneSwitcher.macroTab.runInParallel="他のマクロと並行してマクロを実行する"
|
||||||
|
AdvSceneSwitcher.macroTab.onChange="条件変更時のみアクションを実行"
|
||||||
AdvSceneSwitcher.macroTab.defaultname="マクロ %1"
|
AdvSceneSwitcher.macroTab.defaultname="マクロ %1"
|
||||||
AdvSceneSwitcher.macroTab.defaultGroupName="グループ %1"
|
AdvSceneSwitcher.macroTab.defaultGroupName="グループ %1"
|
||||||
AdvSceneSwitcher.macroTab.macroNameExists="名前 \"%1\" は既にマクロで使用されています。"
|
AdvSceneSwitcher.macroTab.macroNameExists="名前 \"%1\" は既にマクロで使用されています。"
|
||||||
@@ -331,6 +332,14 @@ AdvSceneSwitcher.condition.window.entry.text="{{checkText}}ウィンドウにテ
|
|||||||
AdvSceneSwitcher.condition.window.entry.text.note="このオプションは、ウィンドウに表示されているすべてのテキストに対して機能するとは限りません。\nその場合は、代わりにビデオ条件 OCR チェックの使用を検討してください。"
|
AdvSceneSwitcher.condition.window.entry.text.note="このオプションは、ウィンドウに表示されているすべてのテキストに対して機能するとは限りません。\nその場合は、代わりにビデオ条件 OCR チェックの使用を検討してください。"
|
||||||
AdvSceneSwitcher.condition.window.entry.currentFocus="現在のフォーカスウィンドウ:{{focusWindow}}"
|
AdvSceneSwitcher.condition.window.entry.currentFocus="現在のフォーカスウィンドウ:{{focusWindow}}"
|
||||||
AdvSceneSwitcher.condition.file="ファイル"
|
AdvSceneSwitcher.condition.file="ファイル"
|
||||||
|
; AdvSceneSwitcher.condition.file.type.match="matches"
|
||||||
|
AdvSceneSwitcher.condition.file.type.contentChange="内容変更しました"
|
||||||
|
AdvSceneSwitcher.condition.file.type.dateChange="更新日変更"
|
||||||
|
AdvSceneSwitcher.condition.file.remote="リモートファイル"
|
||||||
|
AdvSceneSwitcher.condition.file.local="ローカルファイル"
|
||||||
|
; AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||||
|
; AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
|
; AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||||
; AdvSceneSwitcher.condition.media="Media"
|
; AdvSceneSwitcher.condition.media="Media"
|
||||||
AdvSceneSwitcher.condition.media.checkType.state="状態が一致"
|
AdvSceneSwitcher.condition.media.checkType.state="状態が一致"
|
||||||
AdvSceneSwitcher.condition.media.checkType.time="時間が一致"
|
AdvSceneSwitcher.condition.media.checkType.time="時間が一致"
|
||||||
@@ -445,8 +454,8 @@ AdvSceneSwitcher.condition.stream.service.tooltip="現在のサービス名: %1"
|
|||||||
AdvSceneSwitcher.condition.record.state.duration="録音時間が長くなっています。"
|
AdvSceneSwitcher.condition.record.state.duration="録音時間が長くなっています。"
|
||||||
; AdvSceneSwitcher.condition.record.entry="{{condition}}{{duration}}"
|
; AdvSceneSwitcher.condition.record.entry="{{condition}}{{duration}}"
|
||||||
AdvSceneSwitcher.condition.process="プロセス"
|
AdvSceneSwitcher.condition.process="プロセス"
|
||||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}が実行中{{focused}}に集中しています"
|
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}が実行中{{focused}}に集中しています"
|
||||||
AdvSceneSwitcher.condition.process.layout.focus="現在のフォアグラウンドプロセス:{{focusProcess}}"
|
AdvSceneSwitcher.condition.process.entry.focus="現在のフォアグラウンドプロセス:{{focusProcess}}"
|
||||||
AdvSceneSwitcher.condition.idle="アイドル"
|
AdvSceneSwitcher.condition.idle="アイドル"
|
||||||
AdvSceneSwitcher.condition.idle.entry="{{duration}}の間、キーボードまたはマウスの入力がありません"
|
AdvSceneSwitcher.condition.idle.entry="{{duration}}の間、キーボードまたはマウスの入力がありません"
|
||||||
AdvSceneSwitcher.condition.pluginState="プラグインの状態"
|
AdvSceneSwitcher.condition.pluginState="プラグインの状態"
|
||||||
@@ -546,14 +555,14 @@ AdvSceneSwitcher.condition.replay.state.started="リプレイバッファを開
|
|||||||
AdvSceneSwitcher.condition.replay.state.saved="リプレイバッファを保存"
|
AdvSceneSwitcher.condition.replay.state.saved="リプレイバッファを保存"
|
||||||
; AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
; AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
||||||
AdvSceneSwitcher.condition.date="日付条件"
|
AdvSceneSwitcher.condition.date="日付条件"
|
||||||
AdvSceneSwitcher.day.any="いつでも"
|
AdvSceneSwitcher.condition.date.anyDay="いつでも"
|
||||||
AdvSceneSwitcher.day.monday="月曜日"
|
AdvSceneSwitcher.condition.date.monday="月曜日"
|
||||||
AdvSceneSwitcher.day.tuesday="火曜日"
|
AdvSceneSwitcher.condition.date.tuesday="火曜日"
|
||||||
AdvSceneSwitcher.day.wednesday="水曜日"
|
AdvSceneSwitcher.condition.date.wednesday="水曜日"
|
||||||
AdvSceneSwitcher.day.thursday="木曜日"
|
AdvSceneSwitcher.condition.date.thursday="木曜日"
|
||||||
AdvSceneSwitcher.day.friday="金曜日"
|
AdvSceneSwitcher.condition.date.friday="金曜日"
|
||||||
AdvSceneSwitcher.day.saturday="土曜日"
|
AdvSceneSwitcher.condition.date.saturday="土曜日"
|
||||||
AdvSceneSwitcher.day.sunday="日曜日"
|
AdvSceneSwitcher.condition.date.sunday="日曜日"
|
||||||
; AdvSceneSwitcher.condition.date.state.at="At"
|
; AdvSceneSwitcher.condition.date.state.at="At"
|
||||||
AdvSceneSwitcher.condition.date.state.after="アフター"
|
AdvSceneSwitcher.condition.date.state.after="アフター"
|
||||||
AdvSceneSwitcher.condition.date.state.before="前"
|
AdvSceneSwitcher.condition.date.state.before="前"
|
||||||
@@ -564,9 +573,12 @@ AdvSceneSwitcher.condition.date.ignoreDate="チェックを外すと日付部分
|
|||||||
AdvSceneSwitcher.condition.date.ignoreTime="チェックを外すと時間要素は無視されます"
|
AdvSceneSwitcher.condition.date.ignoreTime="チェックを外すと時間要素は無視されます"
|
||||||
AdvSceneSwitcher.condition.date.showAdvancedSettings="詳細設定を表示"
|
AdvSceneSwitcher.condition.date.showAdvancedSettings="詳細設定を表示"
|
||||||
AdvSceneSwitcher.condition.date.showSimpleSettings="簡単設定を表示"
|
AdvSceneSwitcher.condition.date.showSimpleSettings="簡単設定を表示"
|
||||||
AdvSceneSwitcher.condition.date.layout.repeat="{{repeat}}日付の一致ごとに{{duration}}繰り返します"
|
; AdvSceneSwitcher.condition.date.entry.simple="On{{dayOfWeek}}{{weekCondition}}{{ignoreWeekTime}}{{weekTime}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.pattern="現在の日付「{{currentDate}}」はパターン{{pattern}}と一致します"
|
; AdvSceneSwitcher.condition.date.entry.advanced="{{condition}}{{ignoreDate}}{{date}}{{ignoreTime}}{{time}}{{separator}}{{date2}}{{time2}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.updateOnRepeat="{{updateOnRepeat}}繰り返しの場合、選択した日付を繰り返しの日付に更新します"
|
AdvSceneSwitcher.condition.date.entry.repeat="{{repeat}}日付の一致ごとに{{duration}}繰り返します"
|
||||||
|
AdvSceneSwitcher.condition.date.entry.pattern="現在の日付「{{currentDate}}」はパターン{{pattern}}と一致します"
|
||||||
|
; AdvSceneSwitcher.condition.date.entry.nextMatchDate="Next match at: %1"
|
||||||
|
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}}繰り返しの場合、選択した日付を繰り返しの日付に更新します"
|
||||||
; AdvSceneSwitcher.condition.sceneTransform="Scene item transform"
|
; AdvSceneSwitcher.condition.sceneTransform="Scene item transform"
|
||||||
; AdvSceneSwitcher.condition.sceneTransform.getTransform="Get transform"
|
; AdvSceneSwitcher.condition.sceneTransform.getTransform="Get transform"
|
||||||
AdvSceneSwitcher.condition.sceneTransform.getCurrentValue="現在の値を取得"
|
AdvSceneSwitcher.condition.sceneTransform.getCurrentValue="現在の値を取得"
|
||||||
@@ -858,6 +870,7 @@ AdvSceneSwitcher.action.sceneVisibility.type.hide="非表示"
|
|||||||
AdvSceneSwitcher.action.sceneVisibility.type.toggle="切り替え"
|
AdvSceneSwitcher.action.sceneVisibility.type.toggle="切り替え"
|
||||||
; AdvSceneSwitcher.action.sceneVisibility.type.source="Source"
|
; AdvSceneSwitcher.action.sceneVisibility.type.source="Source"
|
||||||
; AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Any"
|
; AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Any"
|
||||||
|
; AdvSceneSwitcher.action.sceneVisibility.entry="On{{scenes}}{{actions}}{{sources}}"
|
||||||
AdvSceneSwitcher.action.filter="フィルタ"
|
AdvSceneSwitcher.action.filter="フィルタ"
|
||||||
AdvSceneSwitcher.action.filter.type.enable="有効にする"
|
AdvSceneSwitcher.action.filter.type.enable="有効にする"
|
||||||
AdvSceneSwitcher.action.filter.type.disable="無効化"
|
AdvSceneSwitcher.action.filter.type.disable="無効化"
|
||||||
@@ -923,7 +936,7 @@ AdvSceneSwitcher.action.macro.type.pause="一時停止"
|
|||||||
AdvSceneSwitcher.action.macro.type.unpause="一時停止解除"
|
AdvSceneSwitcher.action.macro.type.unpause="一時停止解除"
|
||||||
AdvSceneSwitcher.action.macro.type.togglePause="一時停止を切り替え"
|
AdvSceneSwitcher.action.macro.type.togglePause="一時停止を切り替え"
|
||||||
AdvSceneSwitcher.action.macro.type.resetCounter="カウンターリセット"
|
AdvSceneSwitcher.action.macro.type.resetCounter="カウンターリセット"
|
||||||
AdvSceneSwitcher.action.macro.type.runActions="マクロを実行"
|
AdvSceneSwitcher.action.macro.type.run="マクロを実行"
|
||||||
AdvSceneSwitcher.action.macro.type.run.conditions.ignore="条件の状態を考慮しない"
|
AdvSceneSwitcher.action.macro.type.run.conditions.ignore="条件の状態を考慮しない"
|
||||||
AdvSceneSwitcher.action.macro.type.run.conditions.true="条件が true と評価された場合のみ"
|
AdvSceneSwitcher.action.macro.type.run.conditions.true="条件が true と評価された場合のみ"
|
||||||
AdvSceneSwitcher.action.macro.type.run.conditions.false="条件が false と評価された場合のみ"
|
AdvSceneSwitcher.action.macro.type.run.conditions.false="条件が false と評価された場合のみ"
|
||||||
@@ -1012,9 +1025,9 @@ AdvSceneSwitcher.action.transition="トランジション"
|
|||||||
; AdvSceneSwitcher.action.transition.type.sceneOverride="シーントランジションオーバーライド"
|
; AdvSceneSwitcher.action.transition.type.sceneOverride="シーントランジションオーバーライド"
|
||||||
; AdvSceneSwitcher.action.transition.type.sourceShow="ソース表示トランジション"
|
; AdvSceneSwitcher.action.transition.type.sourceShow="ソース表示トランジション"
|
||||||
; AdvSceneSwitcher.action.transition.type.sourceHide="ソース非表示トランジション"
|
; AdvSceneSwitcher.action.transition.type.sourceHide="ソース非表示トランジション"
|
||||||
; AdvSceneSwitcher.action.transition.layout.type="{{type}}{{scenes}}{{sources}} の変更"
|
; AdvSceneSwitcher.action.transition.entry.line1="{{type}}{{scenes}}{{sources}} の変更"
|
||||||
AdvSceneSwitcher.action.transition.layout.transition="{{setTransition}}トランジションタイプを{{transitions}}に設定します"
|
AdvSceneSwitcher.action.transition.entry.line2="{{setTransition}}トランジションタイプを{{transitions}}に設定します"
|
||||||
AdvSceneSwitcher.action.transition.layout.duration="{{setDuration}}移行時間を {{duration}} 秒に設定します"
|
AdvSceneSwitcher.action.transition.entry.line3="{{setDuration}}移行時間を {{duration}} 秒に設定します"
|
||||||
AdvSceneSwitcher.action.timer="タイマー"
|
AdvSceneSwitcher.action.timer="タイマー"
|
||||||
AdvSceneSwitcher.action.timer.type.pause="一時停止"
|
AdvSceneSwitcher.action.timer.type.pause="一時停止"
|
||||||
AdvSceneSwitcher.action.timer.type.continue="続行"
|
AdvSceneSwitcher.action.timer.type.continue="続行"
|
||||||
@@ -1136,8 +1149,8 @@ AdvSceneSwitcher.action.variable.currentSegmentValue="現在値:"
|
|||||||
; AdvSceneSwitcher.action.variable.layout.other="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}{{tempVarsHelp}}{{sceneItemIndex}}{{direction}}{{stringLength}}{{paddingCharSelection}}"
|
; AdvSceneSwitcher.action.variable.layout.other="{{actions}}{{variables}}{{variables2}}{{strValue}}{{numValue}}{{segmentIndex}}{{mathExpression}}{{envVariableName}}{{scenes}}{{tempVars}}{{tempVarsHelp}}{{sceneItemIndex}}{{direction}}{{stringLength}}{{paddingCharSelection}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.pad="{{actions}}の{{variables}}の長さを{{stringLength}}にするには、{{paddingCharSelection}}を{{direction}}に追加します。"
|
AdvSceneSwitcher.action.variable.layout.pad="{{actions}}の{{variables}}の長さを{{stringLength}}にするには、{{paddingCharSelection}}を{{direction}}に追加します。"
|
||||||
AdvSceneSwitcher.action.variable.layout.truncate="{{actions}}の{{variables}}の長さを{{stringLength}}にするには、{{direction}}から文字を削除します。"
|
AdvSceneSwitcher.action.variable.layout.truncate="{{actions}}の{{variables}}の長さを{{stringLength}}にするには、{{direction}}から文字を削除します。"
|
||||||
AdvSceneSwitcher.action.variable.layout.substringIndex="部分文字列の開始:{{subStringStart}}部分文字列のサイズ:{{subStringSize}}{{subStringRegex}}"
|
AdvSceneSwitcher.action.variable.layout.substringIndex="部分文字列の開始:{{subStringStart}}部分文字列のサイズ:{{subStringSize}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.substringRegex="正規表現を使用して{{regexMatchIdx}}一致の値を割り当てます:{{subStringRegex}}"
|
AdvSceneSwitcher.action.variable.layout.substringRegex="正規表現を使用して{{regexMatchIdx}}一致の値を割り当てます:"
|
||||||
; AdvSceneSwitcher.action.variable.layout.findAndReplace="{{findStr}}{{findRegex}}{{replaceStr}}"
|
; AdvSceneSwitcher.action.variable.layout.findAndReplace="{{findStr}}{{findRegex}}{{replaceStr}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.userInput.customPrompt="{{useCustomPrompt}}カスタム プロンプトを使用する{{inputPrompt}}"
|
AdvSceneSwitcher.action.variable.layout.userInput.customPrompt="{{useCustomPrompt}}カスタム プロンプトを使用する{{inputPrompt}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.userInput.placeholder="{{useInputPlaceholder}}プレースホルダーを入力{{inputPlaceholder}}"
|
AdvSceneSwitcher.action.variable.layout.userInput.placeholder="{{useInputPlaceholder}}プレースホルダーを入力{{inputPlaceholder}}"
|
||||||
@@ -1180,17 +1193,10 @@ AdvSceneSwitcher.action.twitch.type.user.getInfo="ユーザー情報を取得"
|
|||||||
AdvSceneSwitcher.action.twitch.type.reward.getInfo="チャンネルポイントリワード情報を取得"
|
AdvSceneSwitcher.action.twitch.type.reward.getInfo="チャンネルポイントリワード情報を取得"
|
||||||
AdvSceneSwitcher.action.twitch.reward.toggleControl="リワード名/変数選択コントロールの切り替え"
|
AdvSceneSwitcher.action.twitch.reward.toggleControl="リワード名/変数選択コントロールの切り替え"
|
||||||
AdvSceneSwitcher.action.twitch.categorySelectionDisabled="Twitchアカウントを選択しないとカテゴリを選択できません!"
|
AdvSceneSwitcher.action.twitch.categorySelectionDisabled="Twitchアカウントを選択しないとカテゴリを選択できません!"
|
||||||
; AdvSceneSwitcher.action.twitch.layout.default="On{{account}}{{actions}}{{streamTitle}}{{category}}{{markerDescription}}{{clipHasDelay}}{{duration}}{{announcementColor}}{{channel}}"
|
; AdvSceneSwitcher.action.twitch.entry.default="On{{account}}{{actions}}{{streamTitle}}{{category}}{{markerDescription}}{{clipHasDelay}}{{duration}}{{announcementColor}}{{channel}}"
|
||||||
AdvSceneSwitcher.action.twitch.layout.chat="{{channel}}でアカウント{{account}}{{actions}}を使用しています"
|
AdvSceneSwitcher.action.twitch.entry.chat="{{channel}}でアカウント{{account}}{{actions}}を使用しています"
|
||||||
AdvSceneSwitcher.action.twitch.layout.channel.getInfo="チャンネル{{channel}}でアカウント{{account}}{{actions}}を使用"
|
AdvSceneSwitcher.action.twitch.entry.user.getInfo="{{userInfoQueryType}}{{userLogin}}{{userId}}でアカウント{{account}}{{actions}}を使用"
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.getInfo.row1="アカウント{{account}}{{actions}}を使用"
|
AdvSceneSwitcher.action.twitch.entry.reward.getInfo="チャンネル{{channel}}{{pointsReward}}{{rewardVariable}}{{toggleRewardSelection}}でアカウント{{account}}{{actions}}を使用"
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.getInfo.row2="{{userInfoQueryType}}{{userLogin}}{{userId}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.moderation.row1="アカウント{{account}}{{actions}}を使用"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.moderation.row2="チャンネル{{channel}}{{userInfoQueryType}}{{userLogin}}{{userId}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.ban.row1="アカウント{{account}}{{actions}}を使用 タイムアウト{{duration}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.ban.row2="チャンネル{{channel}}{{userInfoQueryType}}{{userLogin}}{{userId}} 理由{{banReason}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.reward.getInfo.row1="チャンネル{{channel}}でアカウント{{account}}{{actions}}を使用"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.reward.getInfo.row2="{{pointsReward}}{{rewardVariable}}{{toggleRewardSelection}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.title.title="タイトルを入力"
|
AdvSceneSwitcher.action.twitch.title.title="タイトルを入力"
|
||||||
AdvSceneSwitcher.action.twitch.marker.description="マーカーの説明"
|
AdvSceneSwitcher.action.twitch.marker.description="マーカーの説明"
|
||||||
AdvSceneSwitcher.action.twitch.clip.hasDelay="クリップをキャプチャする前にわずかな遅延を追加します"
|
AdvSceneSwitcher.action.twitch.clip.hasDelay="クリップをキャプチャする前にわずかな遅延を追加します"
|
||||||
@@ -2250,6 +2256,8 @@ AdvSceneSwitcher.status.inactive="停止中"
|
|||||||
AdvSceneSwitcher.running="プラグイン実行中"
|
AdvSceneSwitcher.running="プラグイン実行中"
|
||||||
AdvSceneSwitcher.stopped="プラグイン停止しました"
|
AdvSceneSwitcher.stopped="プラグイン停止しました"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>高機能シーンスイッチャーが初めて起動したようです。<br>ガイドと使用例については <a href=\"https://github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> をご覧ください。<br>質問は <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">OBSフォーラムのプラグインのスレッド</span></a> で遠慮なくどうぞ!</p></body></html>"
|
||||||
|
|
||||||
AdvSceneSwitcher.deprecatedTabWarning="このタブの開発は停止しました!\n代わりにマクロの使用に移行することを検討してください。\nこのヒントは [全般] タブで無効にすることができます。"
|
AdvSceneSwitcher.deprecatedTabWarning="このタブの開発は停止しました!\n代わりにマクロの使用に移行することを検討してください。\nこのヒントは [全般] タブで無効にすることができます。"
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="ミリ秒"
|
AdvSceneSwitcher.unit.milliseconds="ミリ秒"
|
||||||
|
|||||||
@@ -147,6 +147,7 @@ AdvSceneSwitcher.macroTab.run.tooltip="Execute todas as ações da macro indepen
|
|||||||
AdvSceneSwitcher.macroTab.runElse="Executar macro (alternativa)"
|
AdvSceneSwitcher.macroTab.runElse="Executar macro (alternativa)"
|
||||||
AdvSceneSwitcher.macroTab.runFail="Falha ao executar \"%1\"!\nUma das ações falhou ou a macro já está em execução.\nDeseja interrompê-la?"
|
AdvSceneSwitcher.macroTab.runFail="Falha ao executar \"%1\"!\nUma das ações falhou ou a macro já está em execução.\nDeseja interrompê-la?"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="Executar macro em paralelo com outras macros"
|
AdvSceneSwitcher.macroTab.runInParallel="Executar macro em paralelo com outras macros"
|
||||||
|
AdvSceneSwitcher.macroTab.onChange="Executar ações apenas quando houver mudança na condição"
|
||||||
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
AdvSceneSwitcher.macroTab.defaultname="Macro %1"
|
||||||
AdvSceneSwitcher.macroTab.defaultGroupName="Grupo %1"
|
AdvSceneSwitcher.macroTab.defaultGroupName="Grupo %1"
|
||||||
AdvSceneSwitcher.macroTab.macroNameExists="O nome \"%1\" já está em uso por uma macro."
|
AdvSceneSwitcher.macroTab.macroNameExists="O nome \"%1\" já está em uso por uma macro."
|
||||||
@@ -295,6 +296,11 @@ AdvSceneSwitcher.condition.file="Arquivo"
|
|||||||
AdvSceneSwitcher.condition.file.type.match="corresponde"
|
AdvSceneSwitcher.condition.file.type.match="corresponde"
|
||||||
AdvSceneSwitcher.condition.file.type.contentChange="conteúdo mudou"
|
AdvSceneSwitcher.condition.file.type.contentChange="conteúdo mudou"
|
||||||
AdvSceneSwitcher.condition.file.type.dateChange="data de modificação mudou"
|
AdvSceneSwitcher.condition.file.type.dateChange="data de modificação mudou"
|
||||||
|
AdvSceneSwitcher.condition.file.remote="Arquivo remoto"
|
||||||
|
AdvSceneSwitcher.condition.file.local="Arquivo local"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||||
AdvSceneSwitcher.condition.media="Mídia"
|
AdvSceneSwitcher.condition.media="Mídia"
|
||||||
AdvSceneSwitcher.condition.media.checkType.state="Estado corresponde"
|
AdvSceneSwitcher.condition.media.checkType.state="Estado corresponde"
|
||||||
AdvSceneSwitcher.condition.media.checkType.time="Restrição de tempo corresponde"
|
AdvSceneSwitcher.condition.media.checkType.time="Restrição de tempo corresponde"
|
||||||
@@ -395,8 +401,8 @@ AdvSceneSwitcher.condition.record.state.stop="Gravação parada"
|
|||||||
AdvSceneSwitcher.condition.record.state.duration="Duração da gravação é maior que"
|
AdvSceneSwitcher.condition.record.state.duration="Duração da gravação é maior que"
|
||||||
AdvSceneSwitcher.condition.record.entry="{{condition}}{{duration}}"
|
AdvSceneSwitcher.condition.record.entry="{{condition}}{{duration}}"
|
||||||
AdvSceneSwitcher.condition.process="Processo"
|
AdvSceneSwitcher.condition.process="Processo"
|
||||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}está em execução{{focused}}e está em foco"
|
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}está em execução{{focused}}e está em foco"
|
||||||
AdvSceneSwitcher.condition.process.layout.focus="Processo atual em primeiro plano:{{focusProcess}}"
|
AdvSceneSwitcher.condition.process.entry.focus="Processo atual em primeiro plano:{{focusProcess}}"
|
||||||
AdvSceneSwitcher.condition.idle="Inativo"
|
AdvSceneSwitcher.condition.idle="Inativo"
|
||||||
AdvSceneSwitcher.condition.idle.entry="Sem entradas de teclado ou mouse por {{duration}}"
|
AdvSceneSwitcher.condition.idle.entry="Sem entradas de teclado ou mouse por {{duration}}"
|
||||||
AdvSceneSwitcher.condition.pluginState="Estado do plugin"
|
AdvSceneSwitcher.condition.pluginState="Estado do plugin"
|
||||||
@@ -496,14 +502,14 @@ AdvSceneSwitcher.condition.replay.state.started="Buffer de replay iniciado"
|
|||||||
AdvSceneSwitcher.condition.replay.state.saved="Buffer de replay salvo"
|
AdvSceneSwitcher.condition.replay.state.saved="Buffer de replay salvo"
|
||||||
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
||||||
AdvSceneSwitcher.condition.date="Data"
|
AdvSceneSwitcher.condition.date="Data"
|
||||||
AdvSceneSwitcher.day.any="Qualquer dia"
|
AdvSceneSwitcher.condition.date.anyDay="Qualquer dia"
|
||||||
AdvSceneSwitcher.day.monday="Segunda-feira"
|
AdvSceneSwitcher.condition.date.monday="Segunda-feira"
|
||||||
AdvSceneSwitcher.day.tuesday="Terça-feira"
|
AdvSceneSwitcher.condition.date.tuesday="Terça-feira"
|
||||||
AdvSceneSwitcher.day.wednesday="Quarta-feira"
|
AdvSceneSwitcher.condition.date.wednesday="Quarta-feira"
|
||||||
AdvSceneSwitcher.day.thursday="Quinta-feira"
|
AdvSceneSwitcher.condition.date.thursday="Quinta-feira"
|
||||||
AdvSceneSwitcher.day.friday="Sexta-feira"
|
AdvSceneSwitcher.condition.date.friday="Sexta-feira"
|
||||||
AdvSceneSwitcher.day.saturday="Sábado"
|
AdvSceneSwitcher.condition.date.saturday="Sábado"
|
||||||
AdvSceneSwitcher.day.sunday="Domingo"
|
AdvSceneSwitcher.condition.date.sunday="Domingo"
|
||||||
AdvSceneSwitcher.condition.date.state.at="Às"
|
AdvSceneSwitcher.condition.date.state.at="Às"
|
||||||
AdvSceneSwitcher.condition.date.state.after="Após"
|
AdvSceneSwitcher.condition.date.state.after="Após"
|
||||||
AdvSceneSwitcher.condition.date.state.before="Antes"
|
AdvSceneSwitcher.condition.date.state.before="Antes"
|
||||||
@@ -514,13 +520,12 @@ AdvSceneSwitcher.condition.date.ignoreDate="Se desmarcado, o componente de data
|
|||||||
AdvSceneSwitcher.condition.date.ignoreTime="Se desmarcado, o componente de tempo será ignorado"
|
AdvSceneSwitcher.condition.date.ignoreTime="Se desmarcado, o componente de tempo será ignorado"
|
||||||
AdvSceneSwitcher.condition.date.showAdvancedSettings="Mostrar configurações avançadas"
|
AdvSceneSwitcher.condition.date.showAdvancedSettings="Mostrar configurações avançadas"
|
||||||
AdvSceneSwitcher.condition.date.showSimpleSettings="Mostrar configurações simples"
|
AdvSceneSwitcher.condition.date.showSimpleSettings="Mostrar configurações simples"
|
||||||
AdvSceneSwitcher.condition.date.layout.simple.day="Em{{dayOfWeek}}"
|
AdvSceneSwitcher.condition.date.entry.simple="Em{{dayOfWeek}}{{weekCondition}}{{ignoreWeekTime}}{{weekTime}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.simple.time="{{ignoreWeekTime}}{{weekCondition}}{{weekTime}}"
|
AdvSceneSwitcher.condition.date.entry.advanced="{{condition}}{{ignoreDate}}{{date}}{{ignoreTime}}{{time}}{{separator}}{{date2}}{{time2}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.advanced="{{condition}}{{ignoreDate}}{{date}}{{ignoreTime}}{{time}}{{separator}}{{date2}}{{time2}}"
|
AdvSceneSwitcher.condition.date.entry.repeat="{{repeat}}Repetir a cada{{duration}}em correspondência de data"
|
||||||
AdvSceneSwitcher.condition.date.layout.repeat="{{repeat}}Repetir a cada{{duration}}em correspondência de data"
|
AdvSceneSwitcher.condition.date.entry.pattern="Data atual \"{{currentDate}}\" corresponde ao padrão{{pattern}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.pattern="Data atual \"{{currentDate}}\" corresponde ao padrão{{pattern}}"
|
AdvSceneSwitcher.condition.date.entry.nextMatchDate="Próxima correspondência em: %1"
|
||||||
AdvSceneSwitcher.condition.date.layout.nextMatchDate="Próxima correspondência em: %1"
|
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}}Ao repetir, atualize a data selecionada para a data de repetição"
|
||||||
AdvSceneSwitcher.condition.date.layout.updateOnRepeat="{{updateOnRepeat}}Ao repetir, atualize a data selecionada para a data de repetição"
|
|
||||||
AdvSceneSwitcher.condition.sceneTransform="Transformação do item de cena"
|
AdvSceneSwitcher.condition.sceneTransform="Transformação do item de cena"
|
||||||
AdvSceneSwitcher.condition.sceneTransform.getTransform="Obter transformação"
|
AdvSceneSwitcher.condition.sceneTransform.getTransform="Obter transformação"
|
||||||
AdvSceneSwitcher.condition.sceneTransform.getCurrentValue="Obter valor atual"
|
AdvSceneSwitcher.condition.sceneTransform.getCurrentValue="Obter valor atual"
|
||||||
@@ -749,6 +754,7 @@ AdvSceneSwitcher.action.recording.type.changeOutputFolder="Alterar pasta de saí
|
|||||||
AdvSceneSwitcher.action.recording.type.changeOutputFileFormat="Alterar formatação do nome do arquivo"
|
AdvSceneSwitcher.action.recording.type.changeOutputFileFormat="Alterar formatação do nome do arquivo"
|
||||||
AdvSceneSwitcher.action.recording.pause.hint="Observe que dependendo das suas configurações de gravação, você pode não conseguir pausar a gravação"
|
AdvSceneSwitcher.action.recording.pause.hint="Observe que dependendo das suas configurações de gravação, você pode não conseguir pausar a gravação"
|
||||||
AdvSceneSwitcher.action.recording.split.hint="Certifique-se de habilitar a divisão automática de arquivos nas configurações do OBS primeiro!"
|
AdvSceneSwitcher.action.recording.split.hint="Certifique-se de habilitar a divisão automática de arquivos nas configurações do OBS primeiro!"
|
||||||
|
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||||
AdvSceneSwitcher.action.replay="Buffer de replay"
|
AdvSceneSwitcher.action.replay="Buffer de replay"
|
||||||
AdvSceneSwitcher.action.replay.saveWarn="Aviso: Salvar com muita frequência pode resultar em o buffer de replay não ser realmente salvo!"
|
AdvSceneSwitcher.action.replay.saveWarn="Aviso: Salvar com muita frequência pode resultar em o buffer de replay não ser realmente salvo!"
|
||||||
AdvSceneSwitcher.action.replay.durationWarn="Aviso: Alterar o tempo máximo de replay só se aplicará na próxima vez que o buffer de replay for iniciado!"
|
AdvSceneSwitcher.action.replay.durationWarn="Aviso: Alterar o tempo máximo de replay só se aplicará na próxima vez que o buffer de replay for iniciado!"
|
||||||
@@ -765,6 +771,7 @@ AdvSceneSwitcher.action.streaming.type.server="Definir URL do servidor"
|
|||||||
AdvSceneSwitcher.action.streaming.type.streamKey="Definir chave de transmissão"
|
AdvSceneSwitcher.action.streaming.type.streamKey="Definir chave de transmissão"
|
||||||
AdvSceneSwitcher.action.streaming.type.username="Definir nome de usuário"
|
AdvSceneSwitcher.action.streaming.type.username="Definir nome de usuário"
|
||||||
AdvSceneSwitcher.action.streaming.type.password="Definir senha"
|
AdvSceneSwitcher.action.streaming.type.password="Definir senha"
|
||||||
|
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}"
|
||||||
AdvSceneSwitcher.action.run="Executar"
|
AdvSceneSwitcher.action.run="Executar"
|
||||||
AdvSceneSwitcher.action.run.wait.entry="{{wait}}Aguardar a saída do processo ou no máximo {{timeout}}{{waitHelp}}"
|
AdvSceneSwitcher.action.run.wait.entry="{{wait}}Aguardar a saída do processo ou no máximo {{timeout}}{{waitHelp}}"
|
||||||
AdvSceneSwitcher.action.run.wait.help.tooltip="Observe que as propriedades da macro não funcionarão se você deixar isso desmarcado, pois o processo é iniciado de forma independente do restante da lógica e não há controle sobre ele."
|
AdvSceneSwitcher.action.run.wait.help.tooltip="Observe que as propriedades da macro não funcionarão se você deixar isso desmarcado, pois o processo é iniciado de forma independente do restante da lógica e não há controle sobre ele."
|
||||||
@@ -774,7 +781,7 @@ AdvSceneSwitcher.action.sceneVisibility.type.hide="Ocultar"
|
|||||||
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Alternar"
|
AdvSceneSwitcher.action.sceneVisibility.type.toggle="Alternar"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Fonte"
|
AdvSceneSwitcher.action.sceneVisibility.type.source="Fonte"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Qualquer"
|
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Qualquer"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.layout="Em{{scenes}}{{actions}}{{sources}}"
|
AdvSceneSwitcher.action.sceneVisibility.entry="Em{{scenes}}{{actions}}{{sources}}"
|
||||||
AdvSceneSwitcher.action.filter="Filtro"
|
AdvSceneSwitcher.action.filter="Filtro"
|
||||||
AdvSceneSwitcher.action.filter.type.enable="Habilitar"
|
AdvSceneSwitcher.action.filter.type.enable="Habilitar"
|
||||||
AdvSceneSwitcher.action.filter.type.disable="Desabilitar"
|
AdvSceneSwitcher.action.filter.type.disable="Desabilitar"
|
||||||
@@ -839,7 +846,7 @@ AdvSceneSwitcher.action.macro="Macro"
|
|||||||
AdvSceneSwitcher.action.macro.type.pause="Pausar"
|
AdvSceneSwitcher.action.macro.type.pause="Pausar"
|
||||||
AdvSceneSwitcher.action.macro.type.unpause="Retomar"
|
AdvSceneSwitcher.action.macro.type.unpause="Retomar"
|
||||||
AdvSceneSwitcher.action.macro.type.resetCounter="Reiniciar contador"
|
AdvSceneSwitcher.action.macro.type.resetCounter="Reiniciar contador"
|
||||||
AdvSceneSwitcher.action.macro.type.runActions="Executar macro"
|
AdvSceneSwitcher.action.macro.type.run="Executar macro"
|
||||||
AdvSceneSwitcher.action.macro.type.run.conditions.ignore="Não considerar o estado da condição"
|
AdvSceneSwitcher.action.macro.type.run.conditions.ignore="Não considerar o estado da condição"
|
||||||
AdvSceneSwitcher.action.macro.type.run.conditions.true="Apenas se as condições forem verdadeiras"
|
AdvSceneSwitcher.action.macro.type.run.conditions.true="Apenas se as condições forem verdadeiras"
|
||||||
AdvSceneSwitcher.action.macro.type.run.conditions.false="Apenas se as condições forem falsas"
|
AdvSceneSwitcher.action.macro.type.run.conditions.false="Apenas se as condições forem falsas"
|
||||||
@@ -926,9 +933,9 @@ AdvSceneSwitcher.action.transition.type.scene="transição de cena"
|
|||||||
AdvSceneSwitcher.action.transition.type.sceneOverride="substituição de transição de cena"
|
AdvSceneSwitcher.action.transition.type.sceneOverride="substituição de transição de cena"
|
||||||
AdvSceneSwitcher.action.transition.type.sourceShow="transição de exibição de fonte"
|
AdvSceneSwitcher.action.transition.type.sourceShow="transição de exibição de fonte"
|
||||||
AdvSceneSwitcher.action.transition.type.sourceHide="transição de ocultação de fonte"
|
AdvSceneSwitcher.action.transition.type.sourceHide="transição de ocultação de fonte"
|
||||||
AdvSceneSwitcher.action.transition.layout.type="Modificar{{type}}{{scenes}}{{sources}}"
|
AdvSceneSwitcher.action.transition.entry.line1="Modificar{{type}}{{scenes}}{{sources}}"
|
||||||
AdvSceneSwitcher.action.transition.layout.transition="{{setTransition}}Definir tipo de transição para{{transitions}}"
|
AdvSceneSwitcher.action.transition.entry.line2="{{setTransition}}Definir tipo de transição para{{transitions}}"
|
||||||
AdvSceneSwitcher.action.transition.layout.duration="{{setDuration}}Definir duração da transição para{{duration}}segundos"
|
AdvSceneSwitcher.action.transition.entry.line3="{{setDuration}}Definir duração da transição para{{duration}}segundos"
|
||||||
AdvSceneSwitcher.action.timer="Temporizador"
|
AdvSceneSwitcher.action.timer="Temporizador"
|
||||||
AdvSceneSwitcher.action.timer.type.pause="Pausar"
|
AdvSceneSwitcher.action.timer.type.pause="Pausar"
|
||||||
AdvSceneSwitcher.action.timer.type.continue="Continuar"
|
AdvSceneSwitcher.action.timer.type.continue="Continuar"
|
||||||
@@ -1023,8 +1030,8 @@ AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Obter valores de va
|
|||||||
AdvSceneSwitcher.action.variable.currentSegmentValue="Valor atual:"
|
AdvSceneSwitcher.action.variable.currentSegmentValue="Valor atual:"
|
||||||
AdvSceneSwitcher.action.variable.layout.pad="{{actions}}de{{variables}}para comprimento{{stringLength}}adicionando{{paddingCharSelection}}ao{{direction}}"
|
AdvSceneSwitcher.action.variable.layout.pad="{{actions}}de{{variables}}para comprimento{{stringLength}}adicionando{{paddingCharSelection}}ao{{direction}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.truncate="{{actions}}de{{variables}}para comprimento{{stringLength}}removendo caracteres da{{direction}}"
|
AdvSceneSwitcher.action.variable.layout.truncate="{{actions}}de{{variables}}para comprimento{{stringLength}}removendo caracteres da{{direction}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.substringIndex="Início da substring:{{subStringStart}}Tamanho da substring:{{subStringSize}}{{subStringRegex}}"
|
AdvSceneSwitcher.action.variable.layout.substringIndex="Início da substring:{{subStringStart}}Tamanho da substring:{{subStringSize}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.substringRegex="Atribuir valor do{{regexMatchIdx}}correspondência usando expressão regular:{{subStringRegex}}"
|
AdvSceneSwitcher.action.variable.layout.substringRegex="Atribuir valor do{{regexMatchIdx}}correspondência usando expressão regular:"
|
||||||
AdvSceneSwitcher.action.variable.layout.findAndReplace="{{findStr}}{{findRegex}}{{replaceStr}}"
|
AdvSceneSwitcher.action.variable.layout.findAndReplace="{{findStr}}{{findRegex}}{{replaceStr}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.userInput.customPrompt="{{useCustomPrompt}}Usar prompt personalizado{{inputPrompt}}"
|
AdvSceneSwitcher.action.variable.layout.userInput.customPrompt="{{useCustomPrompt}}Usar prompt personalizado{{inputPrompt}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.userInput.placeholder="{{useInputPlaceholder}}Preencher com placeholder{{inputPlaceholder}}"
|
AdvSceneSwitcher.action.variable.layout.userInput.placeholder="{{useInputPlaceholder}}Preencher com placeholder{{inputPlaceholder}}"
|
||||||
@@ -1058,8 +1065,8 @@ AdvSceneSwitcher.action.twitch.type.chat.emoteOnly.enable="Habilitar modo apenas
|
|||||||
AdvSceneSwitcher.action.twitch.type.chat.emoteOnly.disable="Desabilitar modo apenas emotes no chat"
|
AdvSceneSwitcher.action.twitch.type.chat.emoteOnly.disable="Desabilitar modo apenas emotes no chat"
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.sendMessage="Enviar mensagem de chat"
|
AdvSceneSwitcher.action.twitch.type.chat.sendMessage="Enviar mensagem de chat"
|
||||||
AdvSceneSwitcher.action.twitch.categorySelectionDisabled="Não é possível selecionar categoria sem selecionar uma conta Twitch primeiro!"
|
AdvSceneSwitcher.action.twitch.categorySelectionDisabled="Não é possível selecionar categoria sem selecionar uma conta Twitch primeiro!"
|
||||||
AdvSceneSwitcher.action.twitch.layout.default="Em{{account}}{{actions}}{{streamTitle}}{{category}}{{markerDescription}}{{clipHasDelay}}{{duration}}{{announcementColor}}{{channel}}{{pointsReward}}{{nonModDelayDuration}}"
|
AdvSceneSwitcher.action.twitch.entry.default="Em{{account}}{{actions}}{{streamTitle}}{{category}}{{markerDescription}}{{clipHasDelay}}{{duration}}{{announcementColor}}{{channel}}{{pointsReward}}"
|
||||||
AdvSceneSwitcher.action.twitch.layout.chat="Usando conta{{account}}{{actions}}em{{channel}}"
|
AdvSceneSwitcher.action.twitch.entry.chat="Usando conta{{account}}{{actions}}em{{channel}}"
|
||||||
AdvSceneSwitcher.action.twitch.title.title="Digite o título"
|
AdvSceneSwitcher.action.twitch.title.title="Digite o título"
|
||||||
AdvSceneSwitcher.action.twitch.marker.description="Descreva o marcador"
|
AdvSceneSwitcher.action.twitch.marker.description="Descreva o marcador"
|
||||||
AdvSceneSwitcher.action.twitch.clip.hasDelay="Adicionar um leve atraso antes de capturar o clipe"
|
AdvSceneSwitcher.action.twitch.clip.hasDelay="Adicionar um leve atraso antes de capturar o clipe"
|
||||||
@@ -1864,6 +1871,8 @@ AdvSceneSwitcher.status.inactive="Inativo"
|
|||||||
AdvSceneSwitcher.running="Plugin em execução"
|
AdvSceneSwitcher.running="Plugin em execução"
|
||||||
AdvSceneSwitcher.stopped="Plugin parado"
|
AdvSceneSwitcher.stopped="Plugin parado"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Parece que esta é a primeira vez que o Advanced Scene Switcher está sendo iniciado.<br>Por favor, consulte o <a href=\"https://github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> para uma lista de guias e exemplos.<br>Não hesite em fazer perguntas no <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">tópico</span></a> do plugin nos fóruns do OBS!</p></body></html>"
|
||||||
|
|
||||||
AdvSceneSwitcher.deprecatedTabWarning="Desenvolvimento para esta aba interrompido!\nPor favor, considere a transição para o uso de Macros em vez disso.\nEsta dica pode ser desativada na aba Geral."
|
AdvSceneSwitcher.deprecatedTabWarning="Desenvolvimento para esta aba interrompido!\nPor favor, considere a transição para o uso de Macros em vez disso.\nEsta dica pode ser desativada na aba Geral."
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="milissegundos"
|
AdvSceneSwitcher.unit.milliseconds="milissegundos"
|
||||||
|
|||||||
@@ -85,6 +85,8 @@ AdvSceneSwitcher.condition.scene.type.current="Текущий"
|
|||||||
AdvSceneSwitcher.condition.scene.type.previous="Предыдущий"
|
AdvSceneSwitcher.condition.scene.type.previous="Предыдущий"
|
||||||
AdvSceneSwitcher.condition.window="Окно"
|
AdvSceneSwitcher.condition.window="Окно"
|
||||||
AdvSceneSwitcher.condition.file="Файл"
|
AdvSceneSwitcher.condition.file="Файл"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||||
AdvSceneSwitcher.condition.media="Медиа"
|
AdvSceneSwitcher.condition.media="Медиа"
|
||||||
AdvSceneSwitcher.condition.video="Видео"
|
AdvSceneSwitcher.condition.video="Видео"
|
||||||
AdvSceneSwitcher.condition.video.condition.match="точно соответствует"
|
AdvSceneSwitcher.condition.video.condition.match="точно соответствует"
|
||||||
@@ -103,7 +105,7 @@ AdvSceneSwitcher.condition.record.state.start="Запись запущена"
|
|||||||
AdvSceneSwitcher.condition.record.state.pause="Запись приостановлена"
|
AdvSceneSwitcher.condition.record.state.pause="Запись приостановлена"
|
||||||
AdvSceneSwitcher.condition.record.state.stop="Запись остановлена"
|
AdvSceneSwitcher.condition.record.state.stop="Запись остановлена"
|
||||||
AdvSceneSwitcher.condition.process="Процесс"
|
AdvSceneSwitcher.condition.process="Процесс"
|
||||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}запущен{{focused}}и сфокусирован"
|
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}запущен{{focused}}и сфокусирован"
|
||||||
AdvSceneSwitcher.condition.idle="Простой"
|
AdvSceneSwitcher.condition.idle="Простой"
|
||||||
AdvSceneSwitcher.condition.idle.entry="Не было ни клавиатуры, ни мыши в течении{{duration}}"
|
AdvSceneSwitcher.condition.idle.entry="Не было ни клавиатуры, ни мыши в течении{{duration}}"
|
||||||
AdvSceneSwitcher.condition.pluginState="Состояние плагина"
|
AdvSceneSwitcher.condition.pluginState="Состояние плагина"
|
||||||
@@ -128,6 +130,7 @@ AdvSceneSwitcher.action.recording.type.start="Начать запись"
|
|||||||
AdvSceneSwitcher.action.recording.type.pause="Пауза записи"
|
AdvSceneSwitcher.action.recording.type.pause="Пауза записи"
|
||||||
AdvSceneSwitcher.action.recording.type.unpause="Снять запись с паузы"
|
AdvSceneSwitcher.action.recording.type.unpause="Снять запись с паузы"
|
||||||
AdvSceneSwitcher.action.recording.pause.hint="Обратите внимание, что в зависимости от настроек записи вы можете не иметь возможности приостановить запись"
|
AdvSceneSwitcher.action.recording.pause.hint="Обратите внимание, что в зависимости от настроек записи вы можете не иметь возможности приостановить запись"
|
||||||
|
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||||
AdvSceneSwitcher.action.replay="Буфер воспроизведения"
|
AdvSceneSwitcher.action.replay="Буфер воспроизведения"
|
||||||
AdvSceneSwitcher.action.replay.type.stop="Остановить буфер воспроизведения"
|
AdvSceneSwitcher.action.replay.type.stop="Остановить буфер воспроизведения"
|
||||||
AdvSceneSwitcher.action.replay.type.start="Начать воспроизведение буфера"
|
AdvSceneSwitcher.action.replay.type.start="Начать воспроизведение буфера"
|
||||||
@@ -135,6 +138,7 @@ AdvSceneSwitcher.action.replay.type.save="Сохранить буфер восп
|
|||||||
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="Начать потоковое вещание"
|
||||||
|
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}"
|
||||||
AdvSceneSwitcher.action.run="Запустить"
|
AdvSceneSwitcher.action.run="Запустить"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ AdvSceneSwitcher.macroTab.add="Yeni Makro ekle"
|
|||||||
AdvSceneSwitcher.macroTab.name="İsim:"
|
AdvSceneSwitcher.macroTab.name="İsim:"
|
||||||
AdvSceneSwitcher.macroTab.run="Makro Çalıştırma"
|
AdvSceneSwitcher.macroTab.run="Makro Çalıştırma"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="Makroyu diğer makrolara paralel olarak çalıştırın"
|
AdvSceneSwitcher.macroTab.runInParallel="Makroyu diğer makrolara paralel olarak çalıştırın"
|
||||||
|
AdvSceneSwitcher.macroTab.onChange="Eylemleri yalnızca koşul değişikliğinde gerçekleştirin"
|
||||||
AdvSceneSwitcher.macroTab.defaultname="Makro %1"
|
AdvSceneSwitcher.macroTab.defaultname="Makro %1"
|
||||||
AdvSceneSwitcher.macroTab.copy="Kopya oluştur"
|
AdvSceneSwitcher.macroTab.copy="Kopya oluştur"
|
||||||
AdvSceneSwitcher.macroTab.expandAll="Hepsini Genişlet"
|
AdvSceneSwitcher.macroTab.expandAll="Hepsini Genişlet"
|
||||||
@@ -107,7 +108,9 @@ AdvSceneSwitcher.condition.scene.type.notChanged="Sahne değişmedi"
|
|||||||
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Geçiş hedefi sahnesi için geçiş kontrolü sırasında"
|
AdvSceneSwitcher.condition.scene.currentSceneTransitionBehaviour="Geçiş hedefi sahnesi için geçiş kontrolü sırasında"
|
||||||
AdvSceneSwitcher.condition.window="Pencere"
|
AdvSceneSwitcher.condition.window="Pencere"
|
||||||
AdvSceneSwitcher.condition.file="Dosya"
|
AdvSceneSwitcher.condition.file="Dosya"
|
||||||
AdvSceneSwitcher.condition.file.layout="İçerik{{filePath}}{{conditions}}{{regex}}"
|
AdvSceneSwitcher.condition.file.entry.line1="İçerik{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||||
AdvSceneSwitcher.condition.media="Medya"
|
AdvSceneSwitcher.condition.media="Medya"
|
||||||
AdvSceneSwitcher.condition.media.anyOnScene="Herhangi bir medya kaynağı"
|
AdvSceneSwitcher.condition.media.anyOnScene="Herhangi bir medya kaynağı"
|
||||||
AdvSceneSwitcher.condition.media.allOnScene="Tüm medya kaynakları "
|
AdvSceneSwitcher.condition.media.allOnScene="Tüm medya kaynakları "
|
||||||
@@ -150,7 +153,7 @@ AdvSceneSwitcher.condition.record.state.start="Kayıt Çalışıyor"
|
|||||||
AdvSceneSwitcher.condition.record.state.pause="Kayıt durakladı"
|
AdvSceneSwitcher.condition.record.state.pause="Kayıt durakladı"
|
||||||
AdvSceneSwitcher.condition.record.state.stop="Kayıt durdu"
|
AdvSceneSwitcher.condition.record.state.stop="Kayıt durdu"
|
||||||
AdvSceneSwitcher.condition.process="İşlem"
|
AdvSceneSwitcher.condition.process="İşlem"
|
||||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}çalışıyor{{focused}}ve odaklandı"
|
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}çalışıyor{{focused}}ve odaklandı"
|
||||||
AdvSceneSwitcher.condition.idle="Boşta"
|
AdvSceneSwitcher.condition.idle="Boşta"
|
||||||
AdvSceneSwitcher.condition.idle.entry="...için klavye veya fare girişi yok {{duration}}"
|
AdvSceneSwitcher.condition.idle.entry="...için klavye veya fare girişi yok {{duration}}"
|
||||||
AdvSceneSwitcher.condition.pluginState="Eklenti durumu"
|
AdvSceneSwitcher.condition.pluginState="Eklenti durumu"
|
||||||
@@ -263,6 +266,7 @@ AdvSceneSwitcher.action.recording.type.start="Kayıt Başlat"
|
|||||||
AdvSceneSwitcher.action.recording.type.pause="Kayıt Duraklat"
|
AdvSceneSwitcher.action.recording.type.pause="Kayıt Duraklat"
|
||||||
AdvSceneSwitcher.action.recording.type.unpause="Kayıt Duraklatma"
|
AdvSceneSwitcher.action.recording.type.unpause="Kayıt Duraklatma"
|
||||||
AdvSceneSwitcher.action.recording.pause.hint="Kayıt ayarlarınıza bağlı olarak kaydı duraklatamayabileceğinizi unutmayın."
|
AdvSceneSwitcher.action.recording.pause.hint="Kayıt ayarlarınıza bağlı olarak kaydı duraklatamayabileceğinizi unutmayın."
|
||||||
|
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||||
AdvSceneSwitcher.action.replay="Tekrar arabelleği"
|
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"
|
||||||
@@ -270,13 +274,14 @@ AdvSceneSwitcher.action.replay.type.save="Tekrar arabelleğini kaydet"
|
|||||||
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"
|
||||||
|
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}"
|
||||||
AdvSceneSwitcher.action.run="Çalıştır"
|
AdvSceneSwitcher.action.run="Çalıştır"
|
||||||
AdvSceneSwitcher.action.sceneVisibility="Sahne öğesi görünürlüğü"
|
AdvSceneSwitcher.action.sceneVisibility="Sahne öğesi görünürlüğü"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.show="Göster"
|
AdvSceneSwitcher.action.sceneVisibility.type.show="Göster"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.hide="Gizle"
|
AdvSceneSwitcher.action.sceneVisibility.type.hide="Gizle"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.source="Kayıt"
|
AdvSceneSwitcher.action.sceneVisibility.type.source="Kayıt"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Herhangi"
|
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="Herhangi"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.layout="Açık{{scenes}}{{actions}}{{sources}}"
|
AdvSceneSwitcher.action.sceneVisibility.entry="Açık{{scenes}}{{actions}}{{sources}}"
|
||||||
AdvSceneSwitcher.action.filter="Filtrele"
|
AdvSceneSwitcher.action.filter="Filtrele"
|
||||||
AdvSceneSwitcher.action.filter.type.enable="Etkin"
|
AdvSceneSwitcher.action.filter.type.enable="Etkin"
|
||||||
AdvSceneSwitcher.action.filter.type.disable="Etkisiz"
|
AdvSceneSwitcher.action.filter.type.disable="Etkisiz"
|
||||||
@@ -300,7 +305,7 @@ AdvSceneSwitcher.action.macro="Makro"
|
|||||||
AdvSceneSwitcher.action.macro.type.pause="Duraklat"
|
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.runActions="Çalıştır"
|
AdvSceneSwitcher.action.macro.type.run="Çalıştır"
|
||||||
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:"
|
||||||
@@ -337,8 +342,8 @@ AdvSceneSwitcher.action.file.type.write="Yaz"
|
|||||||
AdvSceneSwitcher.action.file.type.append="Ekle"
|
AdvSceneSwitcher.action.file.type.append="Ekle"
|
||||||
AdvSceneSwitcher.action.file.entry="{{actions}} {{filePath}}:"
|
AdvSceneSwitcher.action.file.entry="{{actions}} {{filePath}}:"
|
||||||
AdvSceneSwitcher.action.transition="Geçiş"
|
AdvSceneSwitcher.action.transition="Geçiş"
|
||||||
AdvSceneSwitcher.action.transition.layout.transition="{{setTransition}}Geçiş türünü ayarla {{transitions}}"
|
AdvSceneSwitcher.action.transition.entry.line2="{{setTransition}}Geçiş türünü ayarla {{transitions}}"
|
||||||
AdvSceneSwitcher.action.transition.layout.duration="{{setDuration}}Geçiş süresini şuna ayarla: {{duration}}saniyeler"
|
AdvSceneSwitcher.action.transition.entry.line3="{{setDuration}}Geçiş süresini şuna ayarla: {{duration}}saniyeler"
|
||||||
AdvSceneSwitcher.action.timer="Zamanlayıcı"
|
AdvSceneSwitcher.action.timer="Zamanlayıcı"
|
||||||
AdvSceneSwitcher.action.timer.type.pause="Duraklat"
|
AdvSceneSwitcher.action.timer.type.pause="Duraklat"
|
||||||
AdvSceneSwitcher.action.timer.type.continue="Devam et"
|
AdvSceneSwitcher.action.timer.type.continue="Devam et"
|
||||||
@@ -582,6 +587,8 @@ AdvSceneSwitcher.status.inactive="İnaktif"
|
|||||||
AdvSceneSwitcher.running="Eklenti çalışıyor"
|
AdvSceneSwitcher.running="Eklenti çalışıyor"
|
||||||
AdvSceneSwitcher.stopped="Eklenti durdu"
|
AdvSceneSwitcher.stopped="Eklenti durdu"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>Gelişmiş Sahne Değiştirici ilk kez başlatılıyor gibi görünüyor.<br>Lütfen <a href=\"https://github.com/ adresine bir göz atın. WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> için kılavuzlar ve örnekler listesi.<br>Yapmayın. eklentinin <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:# sayfasında soru sormaktan çekinmeyin OBS forumlarında 268bd2;\">konu</span></a>!</p></body></html>"
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="millisaniye"
|
AdvSceneSwitcher.unit.milliseconds="millisaniye"
|
||||||
AdvSceneSwitcher.unit.seconds="saniye"
|
AdvSceneSwitcher.unit.seconds="saniye"
|
||||||
AdvSceneSwitcher.unit.minutes="dakika"
|
AdvSceneSwitcher.unit.minutes="dakika"
|
||||||
|
|||||||
@@ -151,6 +151,7 @@ AdvSceneSwitcher.macroTab.run.tooltip="无论条件如何,都运行所有宏
|
|||||||
AdvSceneSwitcher.macroTab.runElse="运行宏(不满足条件)"
|
AdvSceneSwitcher.macroTab.runElse="运行宏(不满足条件)"
|
||||||
AdvSceneSwitcher.macroTab.runFail="运行 \"%1\" 失败!\n要么其中一个操作失败,要么宏已在运行中.\n你想停止它吗?"
|
AdvSceneSwitcher.macroTab.runFail="运行 \"%1\" 失败!\n要么其中一个操作失败,要么宏已在运行中.\n你想停止它吗?"
|
||||||
AdvSceneSwitcher.macroTab.runInParallel="与其他宏并行运行宏"
|
AdvSceneSwitcher.macroTab.runInParallel="与其他宏并行运行宏"
|
||||||
|
AdvSceneSwitcher.macroTab.onChange="仅在条件结果发生变化时执行操作(条件结果不变时只执行一次操作)"
|
||||||
AdvSceneSwitcher.macroTab.defaultname="宏 %1"
|
AdvSceneSwitcher.macroTab.defaultname="宏 %1"
|
||||||
AdvSceneSwitcher.macroTab.defaultGroupName="分组 %1"
|
AdvSceneSwitcher.macroTab.defaultGroupName="分组 %1"
|
||||||
AdvSceneSwitcher.macroTab.macroNameExists="名称 \"%1\" 已被宏使用."
|
AdvSceneSwitcher.macroTab.macroNameExists="名称 \"%1\" 已被宏使用."
|
||||||
@@ -318,7 +319,11 @@ AdvSceneSwitcher.condition.file="文件"
|
|||||||
AdvSceneSwitcher.condition.file.type.match="内容匹配"
|
AdvSceneSwitcher.condition.file.type.match="内容匹配"
|
||||||
AdvSceneSwitcher.condition.file.type.contentChange="内容发生改变"
|
AdvSceneSwitcher.condition.file.type.contentChange="内容发生改变"
|
||||||
AdvSceneSwitcher.condition.file.type.dateChange="修改日期发生改变"
|
AdvSceneSwitcher.condition.file.type.dateChange="修改日期发生改变"
|
||||||
AdvSceneSwitcher.condition.file.layout="{{filePath}}{{conditions}}{{regex}}"
|
AdvSceneSwitcher.condition.file.remote="网络文件"
|
||||||
|
AdvSceneSwitcher.condition.file.local="本地文件"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line1="{{fileType}}{{filePath}}{{conditions}}{{useRegex}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line2="{{matchText}}"
|
||||||
|
AdvSceneSwitcher.condition.file.entry.line3="{{checkModificationDate}}{{checkFileContent}}"
|
||||||
AdvSceneSwitcher.condition.media="媒体"
|
AdvSceneSwitcher.condition.media="媒体"
|
||||||
AdvSceneSwitcher.condition.media.checkType.state="状态匹配"
|
AdvSceneSwitcher.condition.media.checkType.state="状态匹配"
|
||||||
AdvSceneSwitcher.condition.media.checkType.time="时间限制匹配"
|
AdvSceneSwitcher.condition.media.checkType.time="时间限制匹配"
|
||||||
@@ -424,8 +429,8 @@ AdvSceneSwitcher.condition.record.state.stop="录制停止"
|
|||||||
AdvSceneSwitcher.condition.record.state.duration="录制时间长于"
|
AdvSceneSwitcher.condition.record.state.duration="录制时间长于"
|
||||||
AdvSceneSwitcher.condition.record.entry="{{condition}}{{duration}}"
|
AdvSceneSwitcher.condition.record.entry="{{condition}}{{duration}}"
|
||||||
AdvSceneSwitcher.condition.process="进程"
|
AdvSceneSwitcher.condition.process="进程"
|
||||||
AdvSceneSwitcher.condition.process.layout="{{processes}}{{regex}}为正在运行中{{focused}}且为焦点"
|
AdvSceneSwitcher.condition.process.entry="{{processes}}{{regex}}为正在运行中{{focused}}且为焦点"
|
||||||
AdvSceneSwitcher.condition.process.layout.focus="当前焦点进程: {{focusProcess}}"
|
AdvSceneSwitcher.condition.process.entry.focus="当前焦点进程: {{focusProcess}}"
|
||||||
AdvSceneSwitcher.condition.idle="闲置检测"
|
AdvSceneSwitcher.condition.idle="闲置检测"
|
||||||
AdvSceneSwitcher.condition.idle.entry="{{duration}}内没有键盘或鼠标输入"
|
AdvSceneSwitcher.condition.idle.entry="{{duration}}内没有键盘或鼠标输入"
|
||||||
AdvSceneSwitcher.condition.pluginState="插件状态"
|
AdvSceneSwitcher.condition.pluginState="插件状态"
|
||||||
@@ -525,14 +530,14 @@ AdvSceneSwitcher.condition.replay.state.started="回放缓存已启动"
|
|||||||
AdvSceneSwitcher.condition.replay.state.saved="已保存回放缓存"
|
AdvSceneSwitcher.condition.replay.state.saved="已保存回放缓存"
|
||||||
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
AdvSceneSwitcher.condition.replay.entry="{{state}}"
|
||||||
AdvSceneSwitcher.condition.date="日期"
|
AdvSceneSwitcher.condition.date="日期"
|
||||||
AdvSceneSwitcher.day.any="每一天"
|
AdvSceneSwitcher.condition.date.anyDay="每一天"
|
||||||
AdvSceneSwitcher.day.monday="周一"
|
AdvSceneSwitcher.condition.date.monday="周一"
|
||||||
AdvSceneSwitcher.day.tuesday="周二"
|
AdvSceneSwitcher.condition.date.tuesday="周二"
|
||||||
AdvSceneSwitcher.day.wednesday="周三"
|
AdvSceneSwitcher.condition.date.wednesday="周三"
|
||||||
AdvSceneSwitcher.day.thursday="周四"
|
AdvSceneSwitcher.condition.date.thursday="周四"
|
||||||
AdvSceneSwitcher.day.friday="周五"
|
AdvSceneSwitcher.condition.date.friday="周五"
|
||||||
AdvSceneSwitcher.day.saturday="周六"
|
AdvSceneSwitcher.condition.date.saturday="周六"
|
||||||
AdvSceneSwitcher.day.sunday="周日"
|
AdvSceneSwitcher.condition.date.sunday="周日"
|
||||||
AdvSceneSwitcher.condition.date.state.at="现在"
|
AdvSceneSwitcher.condition.date.state.at="现在"
|
||||||
AdvSceneSwitcher.condition.date.state.after="之后"
|
AdvSceneSwitcher.condition.date.state.after="之后"
|
||||||
AdvSceneSwitcher.condition.date.state.before="之前"
|
AdvSceneSwitcher.condition.date.state.before="之前"
|
||||||
@@ -543,13 +548,12 @@ AdvSceneSwitcher.condition.date.ignoreDate="如果未选中,日期组件将被
|
|||||||
AdvSceneSwitcher.condition.date.ignoreTime="如果未选中,时间组件将被忽略"
|
AdvSceneSwitcher.condition.date.ignoreTime="如果未选中,时间组件将被忽略"
|
||||||
AdvSceneSwitcher.condition.date.showAdvancedSettings="显示高级设置"
|
AdvSceneSwitcher.condition.date.showAdvancedSettings="显示高级设置"
|
||||||
AdvSceneSwitcher.condition.date.showSimpleSettings="显示简单设置"
|
AdvSceneSwitcher.condition.date.showSimpleSettings="显示简单设置"
|
||||||
AdvSceneSwitcher.condition.date.layout.simple.day="{{dayOfWeek}}"
|
AdvSceneSwitcher.condition.date.entry.simple="{{dayOfWeek}}{{weekCondition}}{{ignoreWeekTime}}{{weekTime}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.simple.time="{{ignoreWeekTime}}{{weekCondition}}{{weekTime}}"
|
AdvSceneSwitcher.condition.date.entry.advanced="{{condition}}{{ignoreDate}}{{date}}{{ignoreTime}}{{time}}{{separator}}{{date2}}{{time2}}"
|
||||||
AdvSceneSwitcher.condition.date.layout.advanced="{{condition}}{{ignoreDate}}{{date}}{{ignoreTime}}{{time}}{{separator}}{{date2}}{{time2}}"
|
AdvSceneSwitcher.condition.date.entry.repeat="{{repeat}} 每 {{duration}} 重复一次时间/日期匹配"
|
||||||
AdvSceneSwitcher.condition.date.layout.repeat="{{repeat}} 每 {{duration}} 重复一次时间/日期匹配"
|
AdvSceneSwitcher.condition.date.entry.pattern="当前日期 \"{{currentDate}}\" 与 {{pattern}} 模式匹配 , 例子:2025 03 18 24 00 00 = .... .. .. .. .. .. ,难崩,我测试了一段时间才明白"
|
||||||
AdvSceneSwitcher.condition.date.layout.pattern="当前日期 \"{{currentDate}}\" 与 {{pattern}} 模式匹配 , 例子:2025 03 18 24 00 00 = .... .. .. .. .. .. ,难崩,我测试了一段时间才明白"
|
AdvSceneSwitcher.condition.date.entry.nextMatchDate="下一次匹配 在: %1"
|
||||||
AdvSceneSwitcher.condition.date.layout.nextMatchDate="下一次匹配 在: %1"
|
AdvSceneSwitcher.condition.date.entry.updateOnRepeat="{{updateOnRepeat}} 在重复时将选定日期更新为重复日期"
|
||||||
AdvSceneSwitcher.condition.date.layout.updateOnRepeat="{{updateOnRepeat}} 在重复时将选定日期更新为重复日期"
|
|
||||||
AdvSceneSwitcher.condition.sceneTransform="场景项目变换"
|
AdvSceneSwitcher.condition.sceneTransform="场景项目变换"
|
||||||
AdvSceneSwitcher.condition.sceneTransform.getTransform="获取变换"
|
AdvSceneSwitcher.condition.sceneTransform.getTransform="获取变换"
|
||||||
AdvSceneSwitcher.condition.sceneTransform.getCurrentValue="获取当前值"
|
AdvSceneSwitcher.condition.sceneTransform.getCurrentValue="获取当前值"
|
||||||
@@ -809,6 +813,7 @@ AdvSceneSwitcher.action.recording.type.changeOutputFolder="更改输出文件夹
|
|||||||
AdvSceneSwitcher.action.recording.type.changeOutputFileFormat="改变文件名的格式"
|
AdvSceneSwitcher.action.recording.type.changeOutputFileFormat="改变文件名的格式"
|
||||||
AdvSceneSwitcher.action.recording.pause.hint="请注意,根据您的录制设置,您可能无法暂停录制"
|
AdvSceneSwitcher.action.recording.pause.hint="请注意,根据您的录制设置,您可能无法暂停录制"
|
||||||
AdvSceneSwitcher.action.recording.split.hint="注意,请先确保在OBS设置中启用自动分割文件!"
|
AdvSceneSwitcher.action.recording.split.hint="注意,请先确保在OBS设置中启用自动分割文件!"
|
||||||
|
AdvSceneSwitcher.action.recording.entry="{{actions}}{{recordFolder}}{{recordFileFormat}}{{pauseHint}}{{splitHint}}"
|
||||||
AdvSceneSwitcher.action.replay="回放缓存"
|
AdvSceneSwitcher.action.replay="回放缓存"
|
||||||
AdvSceneSwitcher.action.replay.saveWarn="警告:保存过于频繁可能会导致回放缓存实际上未保存!"
|
AdvSceneSwitcher.action.replay.saveWarn="警告:保存过于频繁可能会导致回放缓存实际上未保存!"
|
||||||
AdvSceneSwitcher.action.replay.durationWarn="警告:更改回放缓存时长上限,仅适用于下次回放缓存开启时!"
|
AdvSceneSwitcher.action.replay.durationWarn="警告:更改回放缓存时长上限,仅适用于下次回放缓存开启时!"
|
||||||
@@ -825,6 +830,7 @@ AdvSceneSwitcher.action.streaming.type.server="设置服务器"
|
|||||||
AdvSceneSwitcher.action.streaming.type.streamKey="设置推流码"
|
AdvSceneSwitcher.action.streaming.type.streamKey="设置推流码"
|
||||||
AdvSceneSwitcher.action.streaming.type.username="设置用户名"
|
AdvSceneSwitcher.action.streaming.type.username="设置用户名"
|
||||||
AdvSceneSwitcher.action.streaming.type.password="设置密码"
|
AdvSceneSwitcher.action.streaming.type.password="设置密码"
|
||||||
|
AdvSceneSwitcher.action.streaming.entry="{{actions}}{{keyFrameInterval}}{{stringValue}}{{showPassword}}"
|
||||||
AdvSceneSwitcher.action.run="运行"
|
AdvSceneSwitcher.action.run="运行"
|
||||||
AdvSceneSwitcher.action.run.wait.entry="{{wait}}进程退出或最多等待{{timeout}}{{waitHelp}}"
|
AdvSceneSwitcher.action.run.wait.entry="{{wait}}进程退出或最多等待{{timeout}}{{waitHelp}}"
|
||||||
AdvSceneSwitcher.action.run.wait.help.tooltip="请注意,如果不勾选此选项,宏属性将不起作用,因为进程的启动会脱离逻辑的其他部分,因此无法对其进行控制."
|
AdvSceneSwitcher.action.run.wait.help.tooltip="请注意,如果不勾选此选项,宏属性将不起作用,因为进程的启动会脱离逻辑的其他部分,因此无法对其进行控制."
|
||||||
@@ -834,7 +840,7 @@ AdvSceneSwitcher.action.sceneVisibility.type.hide="隐藏"
|
|||||||
AdvSceneSwitcher.action.sceneVisibility.type.toggle="切换可见性"
|
AdvSceneSwitcher.action.sceneVisibility.type.toggle="切换可见性"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.source="源"
|
AdvSceneSwitcher.action.sceneVisibility.type.source="源"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="任何"
|
AdvSceneSwitcher.action.sceneVisibility.type.sourceGroup="任何"
|
||||||
AdvSceneSwitcher.action.sceneVisibility.layout="{{scenes}}{{actions}}{{sources}}"
|
AdvSceneSwitcher.action.sceneVisibility.entry="{{scenes}}{{actions}}{{sources}}"
|
||||||
AdvSceneSwitcher.action.filter="滤镜"
|
AdvSceneSwitcher.action.filter="滤镜"
|
||||||
AdvSceneSwitcher.action.filter.type.enable="开启"
|
AdvSceneSwitcher.action.filter.type.enable="开启"
|
||||||
AdvSceneSwitcher.action.filter.type.disable="关闭"
|
AdvSceneSwitcher.action.filter.type.disable="关闭"
|
||||||
@@ -899,7 +905,7 @@ AdvSceneSwitcher.action.macro="宏"
|
|||||||
AdvSceneSwitcher.action.macro.type.pause="停用"
|
AdvSceneSwitcher.action.macro.type.pause="停用"
|
||||||
AdvSceneSwitcher.action.macro.type.unpause="启用"
|
AdvSceneSwitcher.action.macro.type.unpause="启用"
|
||||||
AdvSceneSwitcher.action.macro.type.resetCounter="重置计数器"
|
AdvSceneSwitcher.action.macro.type.resetCounter="重置计数器"
|
||||||
AdvSceneSwitcher.action.macro.type.runActions="运行宏"
|
AdvSceneSwitcher.action.macro.type.run="运行宏"
|
||||||
AdvSceneSwitcher.action.macro.type.run.conditions.ignore="忽略条件结果"
|
AdvSceneSwitcher.action.macro.type.run.conditions.ignore="忽略条件结果"
|
||||||
AdvSceneSwitcher.action.macro.type.run.conditions.true="仅当条件结果为真时"
|
AdvSceneSwitcher.action.macro.type.run.conditions.true="仅当条件结果为真时"
|
||||||
AdvSceneSwitcher.action.macro.type.run.conditions.false="仅当条件结果为假时"
|
AdvSceneSwitcher.action.macro.type.run.conditions.false="仅当条件结果为假时"
|
||||||
@@ -988,9 +994,9 @@ AdvSceneSwitcher.action.transition.type.scene="场景转场动画"
|
|||||||
AdvSceneSwitcher.action.transition.type.sceneOverride="覆盖场景转场动画"
|
AdvSceneSwitcher.action.transition.type.sceneOverride="覆盖场景转场动画"
|
||||||
AdvSceneSwitcher.action.transition.type.sourceShow="显示源转场动画"
|
AdvSceneSwitcher.action.transition.type.sourceShow="显示源转场动画"
|
||||||
AdvSceneSwitcher.action.transition.type.sourceHide="隐藏源转场动画"
|
AdvSceneSwitcher.action.transition.type.sourceHide="隐藏源转场动画"
|
||||||
AdvSceneSwitcher.action.transition.layout.type="更改 {{type}}{{scenes}}{{sources}}"
|
AdvSceneSwitcher.action.transition.entry.line1="更改 {{type}}{{scenes}}{{sources}}"
|
||||||
AdvSceneSwitcher.action.transition.layout.transition="{{setTransition}}将转场动画类型设置为 {{transitions}}"
|
AdvSceneSwitcher.action.transition.entry.line2="{{setTransition}}将转场动画类型设置为 {{transitions}}"
|
||||||
AdvSceneSwitcher.action.transition.layout.duration="{{setDuration}}将转场动画时长设置为 {{duration}}秒"
|
AdvSceneSwitcher.action.transition.entry.line3="{{setDuration}}将转场动画时长设置为 {{duration}}秒"
|
||||||
AdvSceneSwitcher.action.timer="计时器"
|
AdvSceneSwitcher.action.timer="计时器"
|
||||||
AdvSceneSwitcher.action.timer.type.pause="暂停"
|
AdvSceneSwitcher.action.timer.type.pause="暂停"
|
||||||
AdvSceneSwitcher.action.timer.type.continue="继续"
|
AdvSceneSwitcher.action.timer.type.continue="继续"
|
||||||
@@ -1094,8 +1100,8 @@ AdvSceneSwitcher.action.variable.conditionNoVariableSupport="不支持从 %1 条
|
|||||||
AdvSceneSwitcher.action.variable.currentSegmentValue="当前值:"
|
AdvSceneSwitcher.action.variable.currentSegmentValue="当前值:"
|
||||||
AdvSceneSwitcher.action.variable.layout.pad="{{actions}}于{{variables}}的{{direction}}起,内容为{{paddingCharSelection}}将其变量值长度增加至{{stringLength}}."
|
AdvSceneSwitcher.action.variable.layout.pad="{{actions}}于{{variables}}的{{direction}}起,内容为{{paddingCharSelection}}将其变量值长度增加至{{stringLength}}."
|
||||||
AdvSceneSwitcher.action.variable.layout.truncate="{{actions}}于{{variables}}的{{direction}}起,将变量长度缩减至{{stringLength}}"
|
AdvSceneSwitcher.action.variable.layout.truncate="{{actions}}于{{variables}}的{{direction}}起,将变量长度缩减至{{stringLength}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.substringIndex="截取字符串开始位置:{{subStringStart}} 截取字符串长度:{{subStringSize}}{{subStringRegex}}"
|
AdvSceneSwitcher.action.variable.layout.substringIndex="截取字符串开始位置:{{subStringStart}} 截取字符串长度:{{subStringSize}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.substringRegex="使用正则表达式为 {{regexMatchIdx}} 匹配的值:{{subStringRegex}}"
|
AdvSceneSwitcher.action.variable.layout.substringRegex="使用正则表达式为 {{regexMatchIdx}} 匹配的值:"
|
||||||
AdvSceneSwitcher.action.variable.layout.findAndReplace="{{findStr}}{{findRegex}}{{replaceStr}}"
|
AdvSceneSwitcher.action.variable.layout.findAndReplace="{{findStr}}{{findRegex}}{{replaceStr}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.userInput.customPrompt="{{useCustomPrompt}}使用自定义提示{{inputPrompt}}"
|
AdvSceneSwitcher.action.variable.layout.userInput.customPrompt="{{useCustomPrompt}}使用自定义提示{{inputPrompt}}"
|
||||||
AdvSceneSwitcher.action.variable.layout.userInput.placeholder="{{useInputPlaceholder}}用占位符填充{{inputPlaceholder}}"
|
AdvSceneSwitcher.action.variable.layout.userInput.placeholder="{{useInputPlaceholder}}用占位符填充{{inputPlaceholder}}"
|
||||||
@@ -1133,17 +1139,10 @@ AdvSceneSwitcher.action.twitch.type.user.getInfo="获取用户信息"
|
|||||||
AdvSceneSwitcher.action.twitch.type.reward.getInfo="获取频道积分奖励信息"
|
AdvSceneSwitcher.action.twitch.type.reward.getInfo="获取频道积分奖励信息"
|
||||||
AdvSceneSwitcher.action.twitch.reward.toggleControl="切换奖励名称/变量选择控制"
|
AdvSceneSwitcher.action.twitch.reward.toggleControl="切换奖励名称/变量选择控制"
|
||||||
AdvSceneSwitcher.action.twitch.categorySelectionDisabled="在未选择 Twitch 帐户的情况下无法选择类别!"
|
AdvSceneSwitcher.action.twitch.categorySelectionDisabled="在未选择 Twitch 帐户的情况下无法选择类别!"
|
||||||
AdvSceneSwitcher.action.twitch.layout.default="{{account}}{{actions}}{{streamTitle}}{{category}}{{markerDescription}}{{clipHasDelay}}{{duration}}{{announcementColor}}{{channel}}{{pointsReward}}{{nonModDelayDuration}}"
|
AdvSceneSwitcher.action.twitch.entry.default="{{account}}{{actions}}{{streamTitle}}{{category}}{{markerDescription}}{{clipHasDelay}}{{duration}}{{announcementColor}}{{channel}}{{pointsReward}}"
|
||||||
AdvSceneSwitcher.action.twitch.layout.chat="使用账户{{account}}{{actions}}{{channel}}"
|
AdvSceneSwitcher.action.twitch.entry.chat="使用账户{{account}}{{actions}}{{channel}}"
|
||||||
AdvSceneSwitcher.action.twitch.layout.channel.getInfo="使用账户{{account}}{{actions}}频道{{channel}}"
|
AdvSceneSwitcher.action.twitch.entry.user.getInfo="使用账户{{account}}{{actions}}{{userInfoQueryType}}{{userLogin}}{{userId}}"
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.getInfo.row1="使用账户{{account}}{{actions}}"
|
AdvSceneSwitcher.action.twitch.entry.reward.getInfo="使用账户{{account}}{{actions}} 频道{{channel}}{{pointsReward}}{{rewardVariable}}{{toggleRewardSelection}}"
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.getInfo.row2="{{userInfoQueryType}}{{userLogin}}{{userId}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.moderation.row1="使用账户{{account}}{{actions}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.moderation.row2="频道{{channel}}{{userInfoQueryType}}{{userLogin}}{{userId}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.ban.row1="使用账户{{account}}{{actions}}超时{{duration}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.user.ban.row2="频道{{channel}}{{userInfoQueryType}}{{userLogin}}{{userId}}原因{{banReason}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.reward.getInfo.row1="使用账户{{account}}{{actions}} 频道{{channel}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.layout.reward.getInfo.row2="{{pointsReward}}{{rewardVariable}}{{toggleRewardSelection}}"
|
|
||||||
AdvSceneSwitcher.action.twitch.title.title="输入标题"
|
AdvSceneSwitcher.action.twitch.title.title="输入标题"
|
||||||
AdvSceneSwitcher.action.twitch.marker.description="标记描述"
|
AdvSceneSwitcher.action.twitch.marker.description="标记描述"
|
||||||
AdvSceneSwitcher.action.twitch.clip.hasDelay="在捕捉视频片段前稍加延迟"
|
AdvSceneSwitcher.action.twitch.clip.hasDelay="在捕捉视频片段前稍加延迟"
|
||||||
@@ -2116,6 +2115,8 @@ AdvSceneSwitcher.status.inactive="已停止"
|
|||||||
AdvSceneSwitcher.running="插件正在运行"
|
AdvSceneSwitcher.running="插件正在运行"
|
||||||
AdvSceneSwitcher.stopped="插件已停止"
|
AdvSceneSwitcher.stopped="插件已停止"
|
||||||
|
|
||||||
|
AdvSceneSwitcher.firstBootMessage="<html><head/><body><p>这似乎是您第一次启动高级场景切换器.<br>请看一下 <a href=\"https://github.com/WarmUpTill/SceneSwitcher/wiki\"><span style=\" text-decoration: underline; color:#268bd2;\">Wiki</span></a> 查看指南和示例列表.<br>如果有问题,在在OBS论坛插件帖子内提问 <a href=\"https://obsproject.com/forum/threads/advanced-scene-switcher.48264\"><span style=\" text-decoration: underline; color:#268bd2;\">thread</span></a></p></body></html>"
|
||||||
|
|
||||||
AdvSceneSwitcher.deprecatedTabWarning="此选项卡的开发已停止!请考虑转换为使用宏来代替。\n可以在“常规”选项卡上禁用此提示."
|
AdvSceneSwitcher.deprecatedTabWarning="此选项卡的开发已停止!请考虑转换为使用宏来代替。\n可以在“常规”选项卡上禁用此提示."
|
||||||
|
|
||||||
AdvSceneSwitcher.unit.milliseconds="毫秒"
|
AdvSceneSwitcher.unit.milliseconds="毫秒"
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
||||||
<svg fill="#fefefe" xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="800px" height="800px" viewBox="0 0 52 52" enable-background="new 0 0 52 52" xml:space="preserve">
|
|
||||||
<path d="M42.6,17.8c2.4,0,7.2-2,7.2-8.4c0-6.4-4.6-6.8-6.1-6.8c-2.8,0-5.6,2-8.1,6.3c-2.5,4.4-5.3,9.1-5.3,9.1
|
|
||||||
l-0.1,0c-0.6-3.1-1.1-5.6-1.3-6.7c-0.5-2.7-3.6-8.4-9.9-8.4c-6.4,0-12.2,3.7-12.2,3.7l0,0C5.8,7.3,5.1,8.5,5.1,9.9
|
|
||||||
c0,2.1,1.7,3.9,3.9,3.9c0.6,0,1.2-0.2,1.7-0.4l0,0c0,0,4.8-2.7,5.9,0c0.3,0.8,0.6,1.7,0.9,2.7c1.2,4.2,2.4,9.1,3.3,13.5l-4.2,6
|
|
||||||
c0,0-4.7-1.7-7.1-1.7s-7.2,2-7.2,8.4s4.6,6.8,6.1,6.8c2.8,0,5.6-2,8.1-6.3c2.5-4.4,5.3-9.1,5.3-9.1c0.8,4,1.5,7.1,1.9,8.5
|
|
||||||
c1.6,4.5,5.3,7.2,10.1,7.2c0,0,5,0,10.9-3.3c1.4-0.6,2.4-2,2.4-3.6c0-2.1-1.7-3.9-3.9-3.9c-0.6,0-1.2,0.2-1.7,0.4l0,0
|
|
||||||
c0,0-4.2,2.4-5.6,0.5c-1-2-1.9-4.6-2.6-7.8c-0.6-2.8-1.3-6.2-2-9.5l4.3-6.2C35.5,16.1,40.2,17.8,42.6,17.8z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 973 B |
@@ -1,10 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
|
||||||
<svg fill="#202020" xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="800px" height="800px" viewBox="0 0 52 52" enable-background="new 0 0 52 52" xml:space="preserve">
|
|
||||||
<path d="M42.6,17.8c2.4,0,7.2-2,7.2-8.4c0-6.4-4.6-6.8-6.1-6.8c-2.8,0-5.6,2-8.1,6.3c-2.5,4.4-5.3,9.1-5.3,9.1
|
|
||||||
l-0.1,0c-0.6-3.1-1.1-5.6-1.3-6.7c-0.5-2.7-3.6-8.4-9.9-8.4c-6.4,0-12.2,3.7-12.2,3.7l0,0C5.8,7.3,5.1,8.5,5.1,9.9
|
|
||||||
c0,2.1,1.7,3.9,3.9,3.9c0.6,0,1.2-0.2,1.7-0.4l0,0c0,0,4.8-2.7,5.9,0c0.3,0.8,0.6,1.7,0.9,2.7c1.2,4.2,2.4,9.1,3.3,13.5l-4.2,6
|
|
||||||
c0,0-4.7-1.7-7.1-1.7s-7.2,2-7.2,8.4s4.6,6.8,6.1,6.8c2.8,0,5.6-2,8.1-6.3c2.5-4.4,5.3-9.1,5.3-9.1c0.8,4,1.5,7.1,1.9,8.5
|
|
||||||
c1.6,4.5,5.3,7.2,10.1,7.2c0,0,5,0,10.9-3.3c1.4-0.6,2.4-2,2.4-3.6c0-2.1-1.7-3.9-3.9-3.9c-0.6,0-1.2,0.2-1.7,0.4l0,0
|
|
||||||
c0,0-4.2,2.4-5.6,0.5c-1-2-1.9-4.6-2.6-7.8c-0.6-2.8-1.3-6.2-2-9.5l4.3-6.2C35.5,16.1,40.2,17.8,42.6,17.8z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 973 B |
@@ -68,7 +68,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>962</width>
|
<width>962</width>
|
||||||
<height>1190</height>
|
<height>1132</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_19">
|
<layout class="QVBoxLayout" name="verticalLayout_19">
|
||||||
@@ -251,13 +251,6 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="suppressCrashRecoveryDialog">
|
|
||||||
<property name="text">
|
|
||||||
<string>AdvSceneSwitcher.generalTab.generalBehavior.suppressCrashRecoveryDialog</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -275,19 +268,9 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="alwaysShowMacroSearch">
|
<widget class="QCheckBox" name="uiHintsDisable">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>AdvSceneSwitcher.generalTab.generalBehavior.alwaysShowMacroSearch</string>
|
<string>AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints</string>
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QCheckBox" name="alwaysShowFeatureTabs">
|
|
||||||
<property name="toolTip">
|
|
||||||
<string>AdvSceneSwitcher.generalTab.generalBehavior.alwaysShowFeatureTabs.tooltip</string>
|
|
||||||
</property>
|
|
||||||
<property name="text">
|
|
||||||
<string>AdvSceneSwitcher.generalTab.generalBehavior.alwaysShowFeatureTabs</string>
|
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -299,9 +282,9 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QCheckBox" name="uiHintsDisable">
|
<widget class="QCheckBox" name="alwaysShowMacroSearch">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>AdvSceneSwitcher.generalTab.generalBehavior.disableUIHints</string>
|
<string>AdvSceneSwitcher.generalTab.generalBehavior.alwaysShowMacroSearch</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -572,13 +555,6 @@
|
|||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="openSetupWizard">
|
|
||||||
<property name="text">
|
|
||||||
<string>FirstRunWizard.openButton</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</widget>
|
</widget>
|
||||||
@@ -604,7 +580,7 @@
|
|||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QGroupBox" name="macroListBox">
|
<widget class="QGroupBox" name="groupBox_5">
|
||||||
<property name="title">
|
<property name="title">
|
||||||
<string>AdvSceneSwitcher.macroTab.macros</string>
|
<string>AdvSceneSwitcher.macroTab.macros</string>
|
||||||
</property>
|
</property>
|
||||||
@@ -800,19 +776,25 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="label_18">
|
<widget class="QCheckBox" name="runMacroOnChange">
|
||||||
<property name="text">
|
<property name="toolTip">
|
||||||
<string>AdvSceneSwitcher.macroTab.actionTriggerMode.label</string>
|
<string>AdvSceneSwitcher.macroTab.onChange</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="text">
|
||||||
<bool>true</bool>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QComboBox" name="actionTriggerMode">
|
<widget class="QLabel" name="label_18">
|
||||||
<property name="toolTip">
|
<property name="toolTip">
|
||||||
<string>AdvSceneSwitcher.macroTab.actionTriggerMode.tooltip</string>
|
<string>AdvSceneSwitcher.macroTab.onChange</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>AdvSceneSwitcher.macroTab.onChange</string>
|
||||||
|
</property>
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -4126,7 +4108,7 @@
|
|||||||
<tabstop>macroName</tabstop>
|
<tabstop>macroName</tabstop>
|
||||||
<tabstop>runMacro</tabstop>
|
<tabstop>runMacro</tabstop>
|
||||||
<tabstop>runMacroInParallel</tabstop>
|
<tabstop>runMacroInParallel</tabstop>
|
||||||
<tabstop>actionTriggerMode</tabstop>
|
<tabstop>runMacroOnChange</tabstop>
|
||||||
<tabstop>macroSettings</tabstop>
|
<tabstop>macroSettings</tabstop>
|
||||||
<tabstop>macroEdit</tabstop>
|
<tabstop>macroEdit</tabstop>
|
||||||
<tabstop>sceneGroups</tabstop>
|
<tabstop>sceneGroups</tabstop>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "backup.hpp"
|
#include "backup.hpp"
|
||||||
#include "crash-handler.hpp"
|
|
||||||
#include "log-helper.hpp"
|
#include "log-helper.hpp"
|
||||||
#include "macro-helpers.hpp"
|
#include "macro-helpers.hpp"
|
||||||
#include "obs-module-helper.hpp"
|
#include "obs-module-helper.hpp"
|
||||||
@@ -192,21 +191,25 @@ static void SaveSceneSwitcher(obs_data_t *save_data, bool saving, void *)
|
|||||||
|
|
||||||
switcher->m.lock();
|
switcher->m.lock();
|
||||||
if (switcher->VersionChanged(data, g_GIT_SHA1)) {
|
if (switcher->VersionChanged(data, g_GIT_SHA1)) {
|
||||||
AskForBackup(data);
|
auto json = obs_data_get_json(data);
|
||||||
|
static QString jsonQString = json ? json : "";
|
||||||
|
std::thread t([]() {
|
||||||
|
obs_queue_task(
|
||||||
|
OBS_TASK_UI,
|
||||||
|
[](void *) {
|
||||||
|
AskForBackup(jsonQString);
|
||||||
|
},
|
||||||
|
nullptr, false);
|
||||||
|
});
|
||||||
|
t.detach();
|
||||||
}
|
}
|
||||||
|
|
||||||
switcher->LoadSettings(data);
|
switcher->LoadSettings(data);
|
||||||
switcher->m.unlock();
|
switcher->m.unlock();
|
||||||
|
|
||||||
if (switcher->stop) {
|
if (!switcher->stop) {
|
||||||
return;
|
switcher->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShouldSkipPluginStartOnUncleanShutdown()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switcher->Start();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -322,7 +325,8 @@ void SwitcherData::SetPreconditions()
|
|||||||
{
|
{
|
||||||
// Window title
|
// Window title
|
||||||
lastTitle = currentTitle;
|
lastTitle = currentTitle;
|
||||||
auto title = GetCurrentWindowTitle();
|
std::string title;
|
||||||
|
GetCurrentWindowTitle(title);
|
||||||
for (auto &window : ignoreWindowsSwitches) {
|
for (auto &window : ignoreWindowsSwitches) {
|
||||||
bool equals = (title == window);
|
bool equals = (title == window);
|
||||||
bool matches = false;
|
bool matches = false;
|
||||||
@@ -342,7 +346,7 @@ void SwitcherData::SetPreconditions()
|
|||||||
currentTitle = title;
|
currentTitle = title;
|
||||||
|
|
||||||
// Process name
|
// Process name
|
||||||
currentForegroundProcess = GetForegroundProcessName();
|
GetForegroundProcessName(currentForegroundProcess);
|
||||||
|
|
||||||
// Macro
|
// Macro
|
||||||
InvalidateMacroTempVarValues();
|
InvalidateMacroTempVarValues();
|
||||||
|
|||||||
@@ -66,12 +66,10 @@ public slots:
|
|||||||
void on_uiHintsDisable_stateChanged(int state);
|
void on_uiHintsDisable_stateChanged(int state);
|
||||||
void on_disableComboBoxFilter_stateChanged(int state);
|
void on_disableComboBoxFilter_stateChanged(int state);
|
||||||
void on_warnPluginLoadFailure_stateChanged(int state);
|
void on_warnPluginLoadFailure_stateChanged(int state);
|
||||||
void on_suppressCrashRecoveryDialog_stateChanged(int state);
|
|
||||||
void on_hideLegacyTabs_stateChanged(int state);
|
void on_hideLegacyTabs_stateChanged(int state);
|
||||||
void on_priorityUp_clicked();
|
void on_priorityUp_clicked();
|
||||||
void on_priorityDown_clicked();
|
void on_priorityDown_clicked();
|
||||||
void on_threadPriority_currentTextChanged(const QString &text);
|
void on_threadPriority_currentTextChanged(const QString &text);
|
||||||
void on_openSetupWizard_clicked();
|
|
||||||
|
|
||||||
/* --- End of legacy tab section --- */
|
/* --- End of legacy tab section --- */
|
||||||
|
|
||||||
@@ -109,7 +107,7 @@ public slots:
|
|||||||
void on_macroDown_clicked() const;
|
void on_macroDown_clicked() const;
|
||||||
void on_macroName_editingFinished();
|
void on_macroName_editingFinished();
|
||||||
void on_runMacroInParallel_stateChanged(int value) const;
|
void on_runMacroInParallel_stateChanged(int value) const;
|
||||||
void on_actionTriggerMode_currentIndexChanged(int index) const;
|
void on_runMacroOnChange_stateChanged(int value) const;
|
||||||
void MacroSelectionChanged();
|
void MacroSelectionChanged();
|
||||||
void ShowMacroContextMenu(const QPoint &);
|
void ShowMacroContextMenu(const QPoint &);
|
||||||
void CopyMacro();
|
void CopyMacro();
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
#include "advanced-scene-switcher.hpp"
|
#include "advanced-scene-switcher.hpp"
|
||||||
#include "crash-handler.hpp"
|
|
||||||
#include "file-selection.hpp"
|
#include "file-selection.hpp"
|
||||||
#include "filter-combo-box.hpp"
|
#include "filter-combo-box.hpp"
|
||||||
#include "first-run-wizard.hpp"
|
|
||||||
#include "layout-helpers.hpp"
|
#include "layout-helpers.hpp"
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include "macro-search.hpp"
|
#include "macro-search.hpp"
|
||||||
#include "macro-settings.hpp"
|
#include "macro-settings.hpp"
|
||||||
#include "path-helpers.hpp"
|
#include "path-helpers.hpp"
|
||||||
|
#include "selection-helpers.hpp"
|
||||||
#include "source-helpers.hpp"
|
#include "source-helpers.hpp"
|
||||||
#include "splitter-helpers.hpp"
|
#include "splitter-helpers.hpp"
|
||||||
#include "status-control.hpp"
|
#include "status-control.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "switcher-data.hpp"
|
||||||
#include "tab-helpers.hpp"
|
#include "tab-helpers.hpp"
|
||||||
#include "ui-helpers.hpp"
|
#include "ui-helpers.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
#include "variable.hpp"
|
#include "variable.hpp"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
|
|
||||||
@@ -195,15 +195,6 @@ void AdvSceneSwitcher::on_warnPluginLoadFailure_stateChanged(int state)
|
|||||||
switcher->warnPluginLoadFailure = state;
|
switcher->warnPluginLoadFailure = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_suppressCrashRecoveryDialog_stateChanged(int state)
|
|
||||||
{
|
|
||||||
if (loading) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
SetSuppressCrashDialog(state);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isLegacyTab(const QString &name)
|
static bool isLegacyTab(const QString &name)
|
||||||
{
|
{
|
||||||
return name == obs_module_text(
|
return name == obs_module_text(
|
||||||
@@ -370,46 +361,14 @@ void AdvSceneSwitcher::RestoreWindowGeo()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void renameMacroIfNecessary(const std::shared_ptr<Macro> ¯o)
|
|
||||||
{
|
|
||||||
if (!GetMacroByName(macro->Name().c_str())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto name = macro->Name();
|
|
||||||
int i = 2;
|
|
||||||
while (GetMacroByName((name + " " + std::to_string(i)).c_str())) {
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro->SetName(name + " " + std::to_string(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::CheckFirstTimeSetup()
|
void AdvSceneSwitcher::CheckFirstTimeSetup()
|
||||||
{
|
{
|
||||||
if (!IsFirstRun() || !GetTopLevelMacros().empty()) {
|
if (switcher->firstBoot && !switcher->disableHints) {
|
||||||
return;
|
switcher->firstBoot = false;
|
||||||
|
DisplayMessage(
|
||||||
|
obs_module_text("AdvSceneSwitcher.firstBootMessage"));
|
||||||
|
switcher->Start();
|
||||||
}
|
}
|
||||||
|
|
||||||
auto macro = FirstRunWizard::ShowWizard(this);
|
|
||||||
if (macro) {
|
|
||||||
renameMacroIfNecessary(macro);
|
|
||||||
QTimer::singleShot(0, this,
|
|
||||||
[this, macro]() { ui->macros->Add(macro); });
|
|
||||||
}
|
|
||||||
switcher->Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_openSetupWizard_clicked()
|
|
||||||
{
|
|
||||||
auto macro = FirstRunWizard::ShowWizard(this);
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
renameMacroIfNecessary(macro);
|
|
||||||
ui->macros->Add(macro);
|
|
||||||
ui->tabWidget->setCurrentWidget(ui->macroTab);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_tabWidget_currentChanged(int)
|
void AdvSceneSwitcher::on_tabWidget_currentChanged(int)
|
||||||
@@ -956,7 +915,6 @@ void AdvSceneSwitcher::SetupGeneralTab()
|
|||||||
FilterComboBox::SetFilterBehaviourEnabled(
|
FilterComboBox::SetFilterBehaviourEnabled(
|
||||||
!switcher->disableFilterComboboxFilter);
|
!switcher->disableFilterComboboxFilter);
|
||||||
ui->warnPluginLoadFailure->setChecked(switcher->warnPluginLoadFailure);
|
ui->warnPluginLoadFailure->setChecked(switcher->warnPluginLoadFailure);
|
||||||
ui->suppressCrashRecoveryDialog->setChecked(GetSuppressCrashDialog());
|
|
||||||
ui->hideLegacyTabs->setChecked(switcher->hideLegacyTabs);
|
ui->hideLegacyTabs->setChecked(switcher->hideLegacyTabs);
|
||||||
|
|
||||||
populatePriorityFunctionList(ui->priorityList);
|
populatePriorityFunctionList(ui->priorityList);
|
||||||
@@ -1071,8 +1029,6 @@ void AdvSceneSwitcher::SetupGeneralTab()
|
|||||||
setTabOrder(ui->importSettings, ui->cooldownTime);
|
setTabOrder(ui->importSettings, ui->cooldownTime);
|
||||||
setTabOrder(ui->cooldownTime, ui->noMatchDontSwitch);
|
setTabOrder(ui->cooldownTime, ui->noMatchDontSwitch);
|
||||||
|
|
||||||
SetupShowAllTabsCheckBox(ui->alwaysShowFeatureTabs, ui->tabWidget);
|
|
||||||
|
|
||||||
MinimizeSizeOfColumn(ui->statusLayout, 0);
|
MinimizeSizeOfColumn(ui->statusLayout, 0);
|
||||||
setWindowTitle(windowTitle() + " - " + g_GIT_TAG);
|
setWindowTitle(windowTitle() + " - " + g_GIT_TAG);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,11 +92,12 @@ bool SwitcherData::checkExeSwitch(OBSWeakSource &scene,
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string title = switcher->currentTitle;
|
std::string title = switcher->currentTitle;
|
||||||
|
QStringList runningProcesses;
|
||||||
bool ignored = false;
|
bool ignored = false;
|
||||||
bool match = false;
|
bool match = false;
|
||||||
|
|
||||||
// Check for match
|
// Check for match
|
||||||
const auto runningProcesses = GetProcessList();
|
GetProcessList(runningProcesses);
|
||||||
for (ExecutableSwitch &s : executableSwitches) {
|
for (ExecutableSwitch &s : executableSwitches) {
|
||||||
if (!s.initialized()) {
|
if (!s.initialized()) {
|
||||||
continue;
|
continue;
|
||||||
|
|||||||
@@ -230,7 +230,8 @@ bool SwitcherData::checkWindowTitleSwitch(OBSWeakSource &scene,
|
|||||||
|
|
||||||
std::string currentWindowTitle = switcher->currentTitle;
|
std::string currentWindowTitle = switcher->currentTitle;
|
||||||
bool match = false;
|
bool match = false;
|
||||||
const auto windowList = GetWindowList();
|
std::vector<std::string> windowList;
|
||||||
|
GetWindowList(windowList);
|
||||||
|
|
||||||
for (WindowSwitch &s : windowSwitches) {
|
for (WindowSwitch &s : windowSwitches) {
|
||||||
if (!s.initialized()) {
|
if (!s.initialized()) {
|
||||||
|
|||||||
@@ -32,9 +32,6 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <climits>
|
|
||||||
#include <dirent.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include "kwin-helpers.h"
|
#include "kwin-helpers.h"
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -236,9 +233,9 @@ std::string getWindowName(Window window)
|
|||||||
return windowTitle;
|
return windowTitle;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GetWindowList()
|
void GetWindowList(std::vector<std::string> &windows)
|
||||||
{
|
{
|
||||||
std::vector<std::string> windows;
|
windows.resize(0);
|
||||||
for (auto window : getTopLevelWindows()) {
|
for (auto window : getTopLevelWindows()) {
|
||||||
auto name = getWindowName(window);
|
auto name = getWindowName(window);
|
||||||
if (name.empty()) {
|
if (name.empty()) {
|
||||||
@@ -246,7 +243,18 @@ std::vector<std::string> GetWindowList()
|
|||||||
}
|
}
|
||||||
windows.emplace_back(name);
|
windows.emplace_back(name);
|
||||||
}
|
}
|
||||||
return windows;
|
}
|
||||||
|
|
||||||
|
void GetWindowList(QStringList &windows)
|
||||||
|
{
|
||||||
|
windows.clear();
|
||||||
|
for (auto window : getTopLevelWindows()) {
|
||||||
|
auto name = getWindowName(window);
|
||||||
|
if (name.empty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
windows << QString::fromStdString(name);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int getActiveWindow(Window *&window)
|
int getActiveWindow(Window *&window)
|
||||||
@@ -270,24 +278,29 @@ int getActiveWindow(Window *&window)
|
|||||||
&bytes, (uint8_t **)&window);
|
&bytes, (uint8_t **)&window);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetCurrentWindowTitle()
|
void GetCurrentWindowTitle(std::string &title)
|
||||||
{
|
{
|
||||||
if (KWin) {
|
if (KWin) {
|
||||||
return FocusNotifier::getActiveWindowTitle();
|
title = FocusNotifier::getActiveWindowTitle();
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Window *data = 0;
|
Window *data = 0;
|
||||||
if (getActiveWindow(data) != Success || !data) {
|
if (getActiveWindow(data) != Success || !data) {
|
||||||
return {};
|
return;
|
||||||
}
|
}
|
||||||
if (!data[0]) {
|
if (!data[0]) {
|
||||||
XFree(data);
|
XFree(data);
|
||||||
return {};
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto name = getWindowName(data[0]);
|
auto name = getWindowName(data[0]);
|
||||||
XFree(data);
|
XFree(data);
|
||||||
return name;
|
|
||||||
|
if (name.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
title = name;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool windowStatesAreSet(const std::string &windowTitle,
|
bool windowStatesAreSet(const std::string &windowTitle,
|
||||||
@@ -396,17 +409,16 @@ static void getProcessListProcps2(QStringList &processes)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList GetProcessList()
|
void GetProcessList(QStringList &processes)
|
||||||
{
|
{
|
||||||
QStringList processes;
|
processes.clear();
|
||||||
if (libprocpsSupported) {
|
if (libprocpsSupported) {
|
||||||
getProcessListProcps(processes);
|
getProcessListProcps(processes);
|
||||||
return processes;
|
return;
|
||||||
}
|
}
|
||||||
if (libprocps2Supported) {
|
if (libprocps2Supported) {
|
||||||
getProcessListProcps2(processes);
|
getProcessListProcps2(processes);
|
||||||
}
|
}
|
||||||
return processes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
long getForegroundProcessPid()
|
long getForegroundProcessPid()
|
||||||
@@ -457,83 +469,24 @@ std::string getProcNameFromPid(long pid)
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetForegroundProcessName()
|
void GetForegroundProcessName(QString &proc)
|
||||||
{
|
{
|
||||||
|
std::string temp;
|
||||||
|
GetForegroundProcessName(temp);
|
||||||
|
proc = QString::fromStdString(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetForegroundProcessName(std::string &proc)
|
||||||
|
{
|
||||||
|
proc.resize(0);
|
||||||
auto pid = getForegroundProcessPid();
|
auto pid = getForegroundProcessPid();
|
||||||
return getProcNameFromPid(pid);
|
proc = getProcNameFromPid(pid);
|
||||||
}
|
|
||||||
|
|
||||||
static std::string getProcessPathFromPid(long pid)
|
|
||||||
{
|
|
||||||
std::string linkPath = "/proc/" + std::to_string(pid) + "/exe";
|
|
||||||
char buf[PATH_MAX];
|
|
||||||
ssize_t len = readlink(linkPath.c_str(), buf, sizeof(buf) - 1);
|
|
||||||
if (len <= 0) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
buf[len] = '\0';
|
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string GetForegroundProcessPath()
|
|
||||||
{
|
|
||||||
auto pid = getForegroundProcessPid();
|
|
||||||
if (pid <= 0) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
return getProcessPathFromPid(pid);
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList GetProcessPathsFromName(const QString &name)
|
|
||||||
{
|
|
||||||
QStringList paths;
|
|
||||||
const std::string nameStr = name.toStdString();
|
|
||||||
DIR *procDir = opendir("/proc");
|
|
||||||
if (!procDir) {
|
|
||||||
return paths;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct dirent *entry;
|
|
||||||
while ((entry = readdir(procDir)) != nullptr) {
|
|
||||||
bool isPid = (entry->d_name[0] != '\0');
|
|
||||||
for (const char *c = entry->d_name; *c; c++) {
|
|
||||||
if (!isdigit(*c)) {
|
|
||||||
isPid = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!isPid) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string pid = entry->d_name;
|
|
||||||
std::string commPath = "/proc/" + pid + "/comm";
|
|
||||||
std::ifstream commFile(commPath);
|
|
||||||
if (!commFile) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
std::string comm;
|
|
||||||
std::getline(commFile, comm);
|
|
||||||
if (comm != nameStr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string path = getProcessPathFromPid(std::stol(pid));
|
|
||||||
if (path.empty()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
QString qPath = QString::fromStdString(path);
|
|
||||||
if (!paths.contains(qPath)) {
|
|
||||||
paths.append(qPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
closedir(procDir);
|
|
||||||
return paths;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsInFocus(const QString &executable)
|
bool IsInFocus(const QString &executable)
|
||||||
{
|
{
|
||||||
const auto current = GetForegroundProcessName();
|
std::string current;
|
||||||
|
GetForegroundProcessName(current);
|
||||||
|
|
||||||
// True if executable switch equals current window
|
// True if executable switch equals current window
|
||||||
bool equals = (executable.toStdString() == current);
|
bool equals = (executable.toStdString() == current);
|
||||||
|
|||||||
@@ -49,12 +49,10 @@ MacroActionEdit::MacroActionEdit(QWidget *parent,
|
|||||||
_section->AddHeaderWidget(_enable);
|
_section->AddHeaderWidget(_enable);
|
||||||
_section->AddHeaderWidget(_actionSelection);
|
_section->AddHeaderWidget(_actionSelection);
|
||||||
_section->AddHeaderWidget(_headerInfo);
|
_section->AddHeaderWidget(_headerInfo);
|
||||||
_section->AddHeaderWidget(_varMappingToggle);
|
|
||||||
|
|
||||||
auto actionLayout = new QVBoxLayout;
|
auto actionLayout = new QVBoxLayout;
|
||||||
actionLayout->setContentsMargins({7, 7, 7, 7});
|
actionLayout->setContentsMargins({7, 7, 7, 7});
|
||||||
actionLayout->addWidget(_section);
|
actionLayout->addWidget(_section);
|
||||||
actionLayout->addWidget(_outputMappings);
|
|
||||||
_contentLayout->addLayout(actionLayout);
|
_contentLayout->addLayout(actionLayout);
|
||||||
|
|
||||||
auto mainLayout = new QHBoxLayout;
|
auto mainLayout = new QHBoxLayout;
|
||||||
@@ -63,6 +61,7 @@ MacroActionEdit::MacroActionEdit(QWidget *parent,
|
|||||||
mainLayout->addWidget(_frame);
|
mainLayout->addWidget(_frame);
|
||||||
setLayout(mainLayout);
|
setLayout(mainLayout);
|
||||||
|
|
||||||
|
_entryData = entryData;
|
||||||
SetupWidgets(true);
|
SetupWidgets(true);
|
||||||
|
|
||||||
actionStateTimer->start(300);
|
actionStateTimer->start(300);
|
||||||
@@ -91,10 +90,7 @@ void MacroActionEdit::SetupWidgets(bool basicSetup)
|
|||||||
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
|
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
|
||||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||||
QWidget::connect(widget, SIGNAL(ShowVariableMappings(bool)), this,
|
|
||||||
SLOT(ShowVariableMappings(bool)));
|
|
||||||
_section->SetContent(widget, (*_entryData)->GetCollapsed());
|
_section->SetContent(widget, (*_entryData)->GetCollapsed());
|
||||||
SetupVarMappings((*_entryData).get());
|
|
||||||
SetFocusPolicyOfWidgets();
|
SetFocusPolicyOfWidgets();
|
||||||
|
|
||||||
_allWidgetsAreSetup = true;
|
_allWidgetsAreSetup = true;
|
||||||
@@ -125,10 +121,7 @@ void MacroActionEdit::ActionSelectionChanged(const QString &text)
|
|||||||
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
|
auto widget = MacroActionFactory::CreateWidget(id, this, *_entryData);
|
||||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||||
QWidget::connect(widget, SIGNAL(ShowVariableMappings(bool)), this,
|
|
||||||
SLOT(ShowVariableMappings(bool)));
|
|
||||||
_section->SetContent(widget);
|
_section->SetContent(widget);
|
||||||
SetupVarMappings((*_entryData).get());
|
|
||||||
SetFocusPolicyOfWidgets();
|
SetFocusPolicyOfWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,8 +4,6 @@
|
|||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include "macro-action-factory.hpp"
|
#include "macro-action-factory.hpp"
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
const std::string MacroActionMacro::id = "macro";
|
const std::string MacroActionMacro::id = "macro";
|
||||||
@@ -95,85 +93,33 @@ bool MacroActionMacro::PerformAction()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto performActionForMacro = [this](Macro *macro) {
|
switch (_action) {
|
||||||
switch (_action) {
|
case Action::PAUSE:
|
||||||
case Action::PAUSE:
|
macro->SetPaused();
|
||||||
macro->SetPaused();
|
break;
|
||||||
break;
|
case Action::UNPAUSE:
|
||||||
case Action::UNPAUSE:
|
macro->SetPaused(false);
|
||||||
macro->SetPaused(false);
|
break;
|
||||||
break;
|
case Action::TOGGLE_PAUSE:
|
||||||
case Action::TOGGLE_PAUSE:
|
macro->SetPaused(!macro->Paused());
|
||||||
macro->SetPaused(!macro->Paused());
|
break;
|
||||||
break;
|
case Action::RESET_COUNTER:
|
||||||
case Action::RESET_COUNTER:
|
macro->ResetRunCount();
|
||||||
macro->ResetRunCount();
|
break;
|
||||||
break;
|
case Action::RUN_ACTIONS:
|
||||||
case Action::RUN_ACTIONS:
|
RunActions(macro.get());
|
||||||
RunActions(macro);
|
break;
|
||||||
break;
|
case Action::STOP:
|
||||||
case Action::STOP:
|
macro->Stop();
|
||||||
macro->Stop();
|
break;
|
||||||
break;
|
case Action::DISABLE_ACTION:
|
||||||
case Action::DISABLE_ACTION:
|
case Action::ENABLE_ACTION:
|
||||||
case Action::ENABLE_ACTION:
|
case Action::TOGGLE_ACTION:
|
||||||
case Action::TOGGLE_ACTION:
|
AdjustActionState(macro.get());
|
||||||
AdjustActionState(macro);
|
break;
|
||||||
break;
|
default:
|
||||||
case Action::RUN_MACRO: {
|
break;
|
||||||
if (_runOptions.skipWhenPaused && macro->Paused()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const bool conditionsMatched =
|
|
||||||
macro->CheckConditions(true);
|
|
||||||
macro->PerformActions(conditionsMatched, false, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case Action::GET_INFO: {
|
|
||||||
SetTempVarValue(
|
|
||||||
"conditionCount",
|
|
||||||
std::to_string(macro->Conditions().size()));
|
|
||||||
SetTempVarValue(
|
|
||||||
"actionCount",
|
|
||||||
std::to_string(macro->Actions().size()));
|
|
||||||
SetTempVarValue(
|
|
||||||
"elseActionCount",
|
|
||||||
std::to_string(macro->ElseActions().size()));
|
|
||||||
SetTempVarValue("paused",
|
|
||||||
macro->Paused() ? "true" : "false");
|
|
||||||
SetTempVarValue("runCount",
|
|
||||||
std::to_string(macro->RunCount()));
|
|
||||||
const auto lastRun = macro->GetLastExecutionTime();
|
|
||||||
const bool hasRun =
|
|
||||||
lastRun.time_since_epoch().count() != 0;
|
|
||||||
const auto secondsSinceLastRun =
|
|
||||||
hasRun ? std::chrono::duration_cast<
|
|
||||||
std::chrono::seconds>(
|
|
||||||
std::chrono::
|
|
||||||
high_resolution_clock::
|
|
||||||
now() -
|
|
||||||
lastRun)
|
|
||||||
.count()
|
|
||||||
: -1;
|
|
||||||
SetTempVarValue("secondsSinceLastRun",
|
|
||||||
std::to_string(secondsSinceLastRun));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!IsGroupMacro(macro.get())) {
|
|
||||||
performActionForMacro(macro.get());
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
auto macros = GetGroupMacroEntries(macro.get());
|
|
||||||
for (const auto ¯o : macros) {
|
|
||||||
performActionForMacro(macro.get());
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -216,12 +162,6 @@ void MacroActionMacro::LogAction() const
|
|||||||
case Action::NESTED_MACRO:
|
case Action::NESTED_MACRO:
|
||||||
ablog(LOG_INFO, "run nested macro");
|
ablog(LOG_INFO, "run nested macro");
|
||||||
break;
|
break;
|
||||||
case Action::GET_INFO:
|
|
||||||
ablog(LOG_INFO, "get info for \"%s\"", macro->Name().c_str());
|
|
||||||
break;
|
|
||||||
case Action::RUN_MACRO:
|
|
||||||
ablog(LOG_INFO, "run macro \"%s\"", macro->Name().c_str());
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -249,8 +189,8 @@ bool MacroActionMacro::Save(obs_data_t *obj) const
|
|||||||
bool MacroActionMacro::Load(obs_data_t *obj)
|
bool MacroActionMacro::Load(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
MacroAction::Load(obj);
|
MacroAction::Load(obj);
|
||||||
SetAction(static_cast<MacroActionMacro::Action>(
|
_action = static_cast<MacroActionMacro::Action>(
|
||||||
obs_data_get_int(obj, "action")));
|
obs_data_get_int(obj, "action"));
|
||||||
_macro.Load(obj);
|
_macro.Load(obj);
|
||||||
_actionSelectionType = static_cast<SelectionType>(
|
_actionSelectionType = static_cast<SelectionType>(
|
||||||
obs_data_get_int(obj, "actionSelectionType"));
|
obs_data_get_int(obj, "actionSelectionType"));
|
||||||
@@ -350,56 +290,6 @@ void MacroActionMacro::RunActions(Macro *actionMacro) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionMacro::SetAction(Action action)
|
|
||||||
{
|
|
||||||
_action = action;
|
|
||||||
SetupTempVars();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroActionMacro::SetupTempVars()
|
|
||||||
{
|
|
||||||
MacroAction::SetupTempVars();
|
|
||||||
|
|
||||||
if (_action != Action::GET_INFO) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
AddTempvar(
|
|
||||||
"conditionCount",
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.tempVar.macro.info.conditionCount"),
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.tempVar.macro.info.conditionCount.description"));
|
|
||||||
AddTempvar(
|
|
||||||
"actionCount",
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.tempVar.macro.info.actionCount"),
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.tempVar.macro.info.actionCount.description"));
|
|
||||||
AddTempvar(
|
|
||||||
"elseActionCount",
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.tempVar.macro.info.elseActionCount"),
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.tempVar.macro.info.elseActionCount.description"));
|
|
||||||
AddTempvar(
|
|
||||||
"paused",
|
|
||||||
obs_module_text("AdvSceneSwitcher.tempVar.macro.info.paused"),
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.tempVar.macro.info.paused.description"));
|
|
||||||
AddTempvar(
|
|
||||||
"runCount",
|
|
||||||
obs_module_text("AdvSceneSwitcher.tempVar.macro.info.runCount"),
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.tempVar.macro.info.runCount.description"));
|
|
||||||
AddTempvar(
|
|
||||||
"secondsSinceLastRun",
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.tempVar.macro.info.secondsSinceLastRun"),
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.tempVar.macro.info.secondsSinceLastRun.description"));
|
|
||||||
}
|
|
||||||
|
|
||||||
static void populateActionSelection(QComboBox *list)
|
static void populateActionSelection(QComboBox *list)
|
||||||
{
|
{
|
||||||
static const std::vector<std::pair<MacroActionMacro::Action, std::string>>
|
static const std::vector<std::pair<MacroActionMacro::Action, std::string>>
|
||||||
@@ -415,9 +305,7 @@ static void populateActionSelection(QComboBox *list)
|
|||||||
{MacroActionMacro::Action::NESTED_MACRO,
|
{MacroActionMacro::Action::NESTED_MACRO,
|
||||||
"AdvSceneSwitcher.action.macro.type.nestedMacro"},
|
"AdvSceneSwitcher.action.macro.type.nestedMacro"},
|
||||||
{MacroActionMacro::Action::RUN_ACTIONS,
|
{MacroActionMacro::Action::RUN_ACTIONS,
|
||||||
"AdvSceneSwitcher.action.macro.type.runActions"},
|
"AdvSceneSwitcher.action.macro.type.run"},
|
||||||
{MacroActionMacro::Action::RUN_MACRO,
|
|
||||||
"AdvSceneSwitcher.action.macro.type.runMacro"},
|
|
||||||
{MacroActionMacro::Action::STOP,
|
{MacroActionMacro::Action::STOP,
|
||||||
"AdvSceneSwitcher.action.macro.type.stop"},
|
"AdvSceneSwitcher.action.macro.type.stop"},
|
||||||
{MacroActionMacro::Action::DISABLE_ACTION,
|
{MacroActionMacro::Action::DISABLE_ACTION,
|
||||||
@@ -426,8 +314,6 @@ static void populateActionSelection(QComboBox *list)
|
|||||||
"AdvSceneSwitcher.action.macro.type.enableAction"},
|
"AdvSceneSwitcher.action.macro.type.enableAction"},
|
||||||
{MacroActionMacro::Action::TOGGLE_ACTION,
|
{MacroActionMacro::Action::TOGGLE_ACTION,
|
||||||
"AdvSceneSwitcher.action.macro.type.toggleAction"},
|
"AdvSceneSwitcher.action.macro.type.toggleAction"},
|
||||||
{MacroActionMacro::Action::GET_INFO,
|
|
||||||
"AdvSceneSwitcher.action.macro.type.getInfo"},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &[value, name] : actions) {
|
for (const auto &[value, name] : actions) {
|
||||||
@@ -497,10 +383,6 @@ MacroActionMacroEdit::MacroActionMacroEdit(
|
|||||||
_actionSections(new QComboBox(this)),
|
_actionSections(new QComboBox(this)),
|
||||||
_skipWhenPaused(new QCheckBox(obs_module_text(
|
_skipWhenPaused(new QCheckBox(obs_module_text(
|
||||||
"AdvSceneSwitcher.action.macro.type.run.skipWhenPaused"))),
|
"AdvSceneSwitcher.action.macro.type.run.skipWhenPaused"))),
|
||||||
_noConditionsWarning(new QLabel(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.action.macro.type.runMacro.noConditionsWarning"))),
|
|
||||||
_runMacroHelp(new HelpIcon(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.action.macro.type.runMacro.help"))),
|
|
||||||
_setInputs(new QCheckBox(obs_module_text(
|
_setInputs(new QCheckBox(obs_module_text(
|
||||||
"AdvSceneSwitcher.action.macro.type.run.setInputs"))),
|
"AdvSceneSwitcher.action.macro.type.run.setInputs"))),
|
||||||
_inputs(new MacroInputEdit()),
|
_inputs(new MacroInputEdit()),
|
||||||
@@ -522,7 +404,6 @@ MacroActionMacroEdit::MacroActionMacroEdit(
|
|||||||
populateActionTypes(_actionTypes);
|
populateActionTypes(_actionTypes);
|
||||||
|
|
||||||
_conditionMacros->HideSelectedMacro();
|
_conditionMacros->HideSelectedMacro();
|
||||||
_conditionMacros->HideGroups();
|
|
||||||
|
|
||||||
QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)),
|
QWidget::connect(_macros, SIGNAL(currentTextChanged(const QString &)),
|
||||||
this, SLOT(MacroChanged(const QString &)));
|
this, SLOT(MacroChanged(const QString &)));
|
||||||
@@ -574,7 +455,6 @@ MacroActionMacroEdit::MacroActionMacroEdit(
|
|||||||
layout->addLayout(_setInputsLayout);
|
layout->addLayout(_setInputsLayout);
|
||||||
layout->addWidget(_inputs);
|
layout->addWidget(_inputs);
|
||||||
layout->addWidget(_skipWhenPaused);
|
layout->addWidget(_skipWhenPaused);
|
||||||
layout->addWidget(_noConditionsWarning);
|
|
||||||
layout->addWidget(_nestedMacro);
|
layout->addWidget(_nestedMacro);
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
_entryData = entryData;
|
_entryData = entryData;
|
||||||
@@ -602,7 +482,7 @@ void MacroActionMacroEdit::UpdateEntryData()
|
|||||||
}
|
}
|
||||||
|
|
||||||
_actions->setCurrentIndex(
|
_actions->setCurrentIndex(
|
||||||
_actions->findData(static_cast<int>(_entryData->GetAction())));
|
_actions->findData(static_cast<int>(_entryData->_action)));
|
||||||
_actionSelectionType->setCurrentIndex(_actionSelectionType->findData(
|
_actionSelectionType->setCurrentIndex(_actionSelectionType->findData(
|
||||||
static_cast<int>(_entryData->_actionSelectionType)));
|
static_cast<int>(_entryData->_actionSelectionType)));
|
||||||
_actionIndex->SetValue(_entryData->_actionIndex);
|
_actionIndex->SetValue(_entryData->_actionIndex);
|
||||||
@@ -651,8 +531,8 @@ void MacroActionMacroEdit::MacroChanged(const QString &text)
|
|||||||
void MacroActionMacroEdit::ActionChanged(int idx)
|
void MacroActionMacroEdit::ActionChanged(int idx)
|
||||||
{
|
{
|
||||||
GUARD_LOADING_AND_LOCK();
|
GUARD_LOADING_AND_LOCK();
|
||||||
_entryData->SetAction(static_cast<MacroActionMacro::Action>(
|
_entryData->_action = static_cast<MacroActionMacro::Action>(
|
||||||
_actions->itemData(idx).toInt()));
|
_actions->itemData(idx).toInt());
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -744,7 +624,6 @@ void MacroActionMacroEdit::InputsChanged(const StringList &inputs)
|
|||||||
void MacroActionMacroEdit::SetWidgetVisibility()
|
void MacroActionMacroEdit::SetWidgetVisibility()
|
||||||
{
|
{
|
||||||
_entryLayout->removeWidget(_actions);
|
_entryLayout->removeWidget(_actions);
|
||||||
_entryLayout->removeWidget(_runMacroHelp);
|
|
||||||
_entryLayout->removeWidget(_actionIndex);
|
_entryLayout->removeWidget(_actionIndex);
|
||||||
_entryLayout->removeWidget(_macros);
|
_entryLayout->removeWidget(_macros);
|
||||||
_entryLayout->removeWidget(_actionSections);
|
_entryLayout->removeWidget(_actionSections);
|
||||||
@@ -760,7 +639,6 @@ void MacroActionMacroEdit::SetWidgetVisibility()
|
|||||||
|
|
||||||
const std::unordered_map<std::string, QWidget *> placeholders = {
|
const std::unordered_map<std::string, QWidget *> placeholders = {
|
||||||
{"{{actions}}", _actions},
|
{"{{actions}}", _actions},
|
||||||
{"{{runMacroHelp}}", _runMacroHelp},
|
|
||||||
{"{{actionIndex}}", _actionIndex},
|
{"{{actionIndex}}", _actionIndex},
|
||||||
{"{{macros}}", _macros},
|
{"{{macros}}", _macros},
|
||||||
{"{{actionSections}}", _actionSections},
|
{"{{actionSections}}", _actionSections},
|
||||||
@@ -773,7 +651,7 @@ void MacroActionMacroEdit::SetWidgetVisibility()
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const auto action = _entryData->GetAction();
|
const auto action = _entryData->_action;
|
||||||
const char *layoutText = "";
|
const char *layoutText = "";
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case MacroActionMacro::Action::PAUSE:
|
case MacroActionMacro::Action::PAUSE:
|
||||||
@@ -782,12 +660,8 @@ void MacroActionMacroEdit::SetWidgetVisibility()
|
|||||||
case MacroActionMacro::Action::RESET_COUNTER:
|
case MacroActionMacro::Action::RESET_COUNTER:
|
||||||
case MacroActionMacro::Action::STOP:
|
case MacroActionMacro::Action::STOP:
|
||||||
case MacroActionMacro::Action::NESTED_MACRO:
|
case MacroActionMacro::Action::NESTED_MACRO:
|
||||||
case MacroActionMacro::Action::GET_INFO:
|
|
||||||
layoutText = "AdvSceneSwitcher.action.macro.layout.other";
|
layoutText = "AdvSceneSwitcher.action.macro.layout.other";
|
||||||
break;
|
break;
|
||||||
case MacroActionMacro::Action::RUN_MACRO:
|
|
||||||
layoutText = "AdvSceneSwitcher.action.macro.layout.runMacro";
|
|
||||||
break;
|
|
||||||
case MacroActionMacro::Action::RUN_ACTIONS:
|
case MacroActionMacro::Action::RUN_ACTIONS:
|
||||||
layoutText = "AdvSceneSwitcher.action.macro.layout.run";
|
layoutText = "AdvSceneSwitcher.action.macro.layout.run";
|
||||||
break;
|
break;
|
||||||
@@ -814,8 +688,7 @@ void MacroActionMacroEdit::SetWidgetVisibility()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (action == MacroActionMacro::Action::RUN_ACTIONS ||
|
if (action == MacroActionMacro::Action::RUN_ACTIONS ||
|
||||||
action == MacroActionMacro::Action::STOP ||
|
action == MacroActionMacro::Action::STOP) {
|
||||||
action == MacroActionMacro::Action::RUN_MACRO) {
|
|
||||||
_macros->HideSelectedMacro();
|
_macros->HideSelectedMacro();
|
||||||
} else {
|
} else {
|
||||||
_macros->ShowAllMacros();
|
_macros->ShowAllMacros();
|
||||||
@@ -860,17 +733,8 @@ void MacroActionMacroEdit::SetWidgetVisibility()
|
|||||||
_actionSections->setVisible(
|
_actionSections->setVisible(
|
||||||
action == MacroActionMacro::Action::RUN_ACTIONS ||
|
action == MacroActionMacro::Action::RUN_ACTIONS ||
|
||||||
isModifyingActionState);
|
isModifyingActionState);
|
||||||
_skipWhenPaused->setVisible(
|
_skipWhenPaused->setVisible(action ==
|
||||||
action == MacroActionMacro::Action::RUN_ACTIONS ||
|
MacroActionMacro::Action::RUN_ACTIONS);
|
||||||
action == MacroActionMacro::Action::RUN_MACRO);
|
|
||||||
|
|
||||||
if (action == MacroActionMacro::Action::RUN_MACRO) {
|
|
||||||
auto macro = _entryData->_macro.GetMacro();
|
|
||||||
_noConditionsWarning->setVisible(!macro ||
|
|
||||||
macro->Conditions().empty());
|
|
||||||
} else {
|
|
||||||
_noConditionsWarning->setVisible(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
_nestedMacro->setVisible(action ==
|
_nestedMacro->setVisible(action ==
|
||||||
MacroActionMacro::Action::NESTED_MACRO);
|
MacroActionMacro::Action::NESTED_MACRO);
|
||||||
|
|||||||
@@ -11,7 +11,6 @@
|
|||||||
|
|
||||||
#include <QCheckBox>
|
#include <QCheckBox>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QLabel>
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -57,15 +56,11 @@ public:
|
|||||||
TOGGLE_ACTION,
|
TOGGLE_ACTION,
|
||||||
TOGGLE_PAUSE,
|
TOGGLE_PAUSE,
|
||||||
NESTED_MACRO,
|
NESTED_MACRO,
|
||||||
GET_INFO,
|
|
||||||
RUN_MACRO,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void SetAction(Action);
|
|
||||||
Action GetAction() const { return _action; }
|
|
||||||
|
|
||||||
enum class SelectionType { INDEX, LABEL, ID };
|
enum class SelectionType { INDEX, LABEL, ID };
|
||||||
|
|
||||||
|
Action _action = Action::NESTED_MACRO;
|
||||||
SelectionType _actionSelectionType = SelectionType::INDEX;
|
SelectionType _actionSelectionType = SelectionType::INDEX;
|
||||||
bool _useElseSection = false;
|
bool _useElseSection = false;
|
||||||
IntVariable _actionIndex = 1;
|
IntVariable _actionIndex = 1;
|
||||||
@@ -77,12 +72,9 @@ public:
|
|||||||
int _customWidgetHeight = 0;
|
int _customWidgetHeight = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetupTempVars();
|
|
||||||
void RunActions(Macro *actionMacro) const;
|
void RunActions(Macro *actionMacro) const;
|
||||||
void AdjustActionState(Macro *) const;
|
void AdjustActionState(Macro *) const;
|
||||||
|
|
||||||
Action _action = Action::NESTED_MACRO;
|
|
||||||
|
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
static const std::string id;
|
static const std::string id;
|
||||||
};
|
};
|
||||||
@@ -133,8 +125,6 @@ private:
|
|||||||
QCheckBox *_reevaluateConditionState;
|
QCheckBox *_reevaluateConditionState;
|
||||||
QComboBox *_actionSections;
|
QComboBox *_actionSections;
|
||||||
QCheckBox *_skipWhenPaused;
|
QCheckBox *_skipWhenPaused;
|
||||||
QLabel *_noConditionsWarning;
|
|
||||||
HelpIcon *_runMacroHelp;
|
|
||||||
QCheckBox *_setInputs;
|
QCheckBox *_setInputs;
|
||||||
MacroInputEdit *_inputs;
|
MacroInputEdit *_inputs;
|
||||||
QHBoxLayout *_entryLayout;
|
QHBoxLayout *_entryLayout;
|
||||||
|
|||||||
@@ -17,15 +17,6 @@ namespace advss {
|
|||||||
|
|
||||||
const std::string MacroActionVariable::id = "variable";
|
const std::string MacroActionVariable::id = "variable";
|
||||||
|
|
||||||
std::vector<TempVariableRef> MacroActionVariable::GetTempVarRefs() const
|
|
||||||
{
|
|
||||||
auto refs = MacroSegment::GetTempVarRefs();
|
|
||||||
if (_tempVar.HasValidID()) {
|
|
||||||
refs.push_back(_tempVar);
|
|
||||||
}
|
|
||||||
return refs;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroActionVariable::_registered = MacroActionFactory::Register(
|
bool MacroActionVariable::_registered = MacroActionFactory::Register(
|
||||||
MacroActionVariable::id,
|
MacroActionVariable::id,
|
||||||
{MacroActionVariable::Create, MacroActionVariableEdit::Create,
|
{MacroActionVariable::Create, MacroActionVariableEdit::Create,
|
||||||
@@ -228,43 +219,6 @@ void MacroActionVariable::GenerateRandomNumber(Variable *var)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionVariable::PickRandomValue(Variable *var)
|
|
||||||
{
|
|
||||||
static std::random_device rd;
|
|
||||||
static std::mt19937 gen(rd());
|
|
||||||
static const uint8_t maxIter = 255;
|
|
||||||
|
|
||||||
if (_randomValues.isEmpty()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_randomValues.size() == 1) {
|
|
||||||
const auto &value = _randomValues.at(0);
|
|
||||||
var->SetValue(value);
|
|
||||||
_lastRandomValue = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::uniform_int_distribution<int> dis(0, _randomValues.size() - 1);
|
|
||||||
StringVariable value = _randomValues.at(dis(gen));
|
|
||||||
|
|
||||||
uint8_t iter = 0;
|
|
||||||
for (; !_allowRepeatValues && iter < maxIter &&
|
|
||||||
_lastRandomValue.has_value() &&
|
|
||||||
std::string(value) == _lastRandomValue.value();
|
|
||||||
iter++) {
|
|
||||||
value = _randomValues.at(dis(gen));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (iter == maxIter) {
|
|
||||||
blog(LOG_INFO,
|
|
||||||
"giving up picking non-repeat random value after %d tries",
|
|
||||||
maxIter);
|
|
||||||
}
|
|
||||||
|
|
||||||
var->SetValue(value);
|
|
||||||
_lastRandomValue = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct AskForInputParams {
|
struct AskForInputParams {
|
||||||
AskForInputParams(const QString &prompt_, const QString &placeholder_)
|
AskForInputParams(const QString &prompt_, const QString &placeholder_)
|
||||||
: prompt(prompt_),
|
: prompt(prompt_),
|
||||||
@@ -504,9 +458,6 @@ bool MacroActionVariable::PerformAction()
|
|||||||
case Action::RANDOM_NUMBER:
|
case Action::RANDOM_NUMBER:
|
||||||
GenerateRandomNumber(var.get());
|
GenerateRandomNumber(var.get());
|
||||||
return true;
|
return true;
|
||||||
case Action::RANDOM_LIST_VALUE:
|
|
||||||
PickRandomValue(var.get());
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -547,8 +498,6 @@ bool MacroActionVariable::Save(obs_data_t *obj) const
|
|||||||
_randomNumberStart.Save(obj, "randomNumberStart");
|
_randomNumberStart.Save(obj, "randomNumberStart");
|
||||||
_randomNumberEnd.Save(obj, "randomNumberEnd");
|
_randomNumberEnd.Save(obj, "randomNumberEnd");
|
||||||
obs_data_set_bool(obj, "generateInteger", _generateInteger);
|
obs_data_set_bool(obj, "generateInteger", _generateInteger);
|
||||||
_randomValues.Save(obj, "randomValues", "value");
|
|
||||||
obs_data_set_bool(obj, "allowRepeatValues", _allowRepeatValues);
|
|
||||||
_jsonQuery.Save(obj, "jsonQuery");
|
_jsonQuery.Save(obj, "jsonQuery");
|
||||||
_jsonIndex.Save(obj, "jsonIndex");
|
_jsonIndex.Save(obj, "jsonIndex");
|
||||||
|
|
||||||
@@ -607,8 +556,6 @@ bool MacroActionVariable::Load(obs_data_t *obj)
|
|||||||
_randomNumberStart.Load(obj, "randomNumberStart");
|
_randomNumberStart.Load(obj, "randomNumberStart");
|
||||||
_randomNumberEnd.Load(obj, "randomNumberEnd");
|
_randomNumberEnd.Load(obj, "randomNumberEnd");
|
||||||
_generateInteger = obs_data_get_bool(obj, "generateInteger");
|
_generateInteger = obs_data_get_bool(obj, "generateInteger");
|
||||||
_randomValues.Load(obj, "randomValues", "value");
|
|
||||||
_allowRepeatValues = obs_data_get_bool(obj, "allowRepeatValues");
|
|
||||||
_jsonQuery.Load(obj, "jsonQuery");
|
_jsonQuery.Load(obj, "jsonQuery");
|
||||||
_jsonIndex.Load(obj, "jsonIndex");
|
_jsonIndex.Load(obj, "jsonIndex");
|
||||||
|
|
||||||
@@ -777,8 +724,6 @@ static inline void populateActionSelection(QComboBox *list)
|
|||||||
"AdvSceneSwitcher.action.variable.type.roundToInt"},
|
"AdvSceneSwitcher.action.variable.type.roundToInt"},
|
||||||
{MacroActionVariable::Action::RANDOM_NUMBER,
|
{MacroActionVariable::Action::RANDOM_NUMBER,
|
||||||
"AdvSceneSwitcher.action.variable.type.randomNumber"},
|
"AdvSceneSwitcher.action.variable.type.randomNumber"},
|
||||||
{MacroActionVariable::Action::RANDOM_LIST_VALUE,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.randomListValue"},
|
|
||||||
{true, ""}, // Separator
|
{true, ""}, // Separator
|
||||||
|
|
||||||
{MacroActionVariable::Action::USER_INPUT,
|
{MacroActionVariable::Action::USER_INPUT,
|
||||||
@@ -856,10 +801,11 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
_segmentValueStatus(new QLabel()),
|
_segmentValueStatus(new QLabel()),
|
||||||
_segmentValue(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
_segmentValue(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
||||||
_substringLayout(new QVBoxLayout()),
|
_substringLayout(new QVBoxLayout()),
|
||||||
_subStringControlsLayout(new QHBoxLayout()),
|
_subStringIndexEntryLayout(new QHBoxLayout()),
|
||||||
|
_subStringRegexEntryLayout(new QHBoxLayout()),
|
||||||
_subStringStart(new VariableSpinBox(this)),
|
_subStringStart(new VariableSpinBox(this)),
|
||||||
_subStringSize(new VariableSpinBox(this)),
|
_subStringSize(new VariableSpinBox(this)),
|
||||||
_subStringRegex(new RegexConfigWidget(parent)),
|
_substringRegex(new RegexConfigWidget(parent)),
|
||||||
_regexPattern(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
_regexPattern(new ResizingPlainTextEdit(this, 10, 1, 1)),
|
||||||
_regexMatchIdx(new VariableSpinBox(this)),
|
_regexMatchIdx(new VariableSpinBox(this)),
|
||||||
_findReplaceLayout(new QHBoxLayout()),
|
_findReplaceLayout(new QHBoxLayout()),
|
||||||
@@ -891,13 +837,7 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
obs_module_text(
|
obs_module_text(
|
||||||
"AdvSceneSwitcher.action.variable.generateInteger"),
|
"AdvSceneSwitcher.action.variable.generateInteger"),
|
||||||
this)),
|
this)),
|
||||||
_randomNumberLayout(new QVBoxLayout()),
|
_randomLayout(new QVBoxLayout()),
|
||||||
_randomValues(new StringListEdit(this)),
|
|
||||||
_allowRepeatValues(new QCheckBox(
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.action.variable.type.allowRepeat"),
|
|
||||||
this)),
|
|
||||||
_randomValueLayout(new QVBoxLayout()),
|
|
||||||
_jsonQuery(new VariableLineEdit(this)),
|
_jsonQuery(new VariableLineEdit(this)),
|
||||||
_jsonQueryHelp(new HelpIcon(
|
_jsonQueryHelp(new HelpIcon(
|
||||||
obs_module_text(
|
obs_module_text(
|
||||||
@@ -933,7 +873,6 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
_randomNumberStart->setMaximum(9999999999);
|
_randomNumberStart->setMaximum(9999999999);
|
||||||
_randomNumberEnd->setMinimum(-9999999999);
|
_randomNumberEnd->setMinimum(-9999999999);
|
||||||
_randomNumberEnd->setMaximum(9999999999);
|
_randomNumberEnd->setMaximum(9999999999);
|
||||||
_randomValues->SetMaxStringSize(99999999);
|
|
||||||
_jsonIndex->setMaximum(999);
|
_jsonIndex->setMaximum(999);
|
||||||
|
|
||||||
QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)),
|
QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)),
|
||||||
@@ -962,7 +901,7 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
_subStringSize,
|
_subStringSize,
|
||||||
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
this, SLOT(SubStringSizeChanged(const NumberVariable<int> &)));
|
this, SLOT(SubStringSizeChanged(const NumberVariable<int> &)));
|
||||||
QWidget::connect(_subStringRegex,
|
QWidget::connect(_substringRegex,
|
||||||
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
|
SIGNAL(RegexConfigChanged(const RegexConfig &)), this,
|
||||||
SLOT(SubStringRegexChanged(const RegexConfig &)));
|
SLOT(SubStringRegexChanged(const RegexConfig &)));
|
||||||
QWidget::connect(_regexPattern, SIGNAL(textChanged()), this,
|
QWidget::connect(_regexPattern, SIGNAL(textChanged()), this,
|
||||||
@@ -1022,11 +961,6 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
SLOT(RandomNumberEndChanged(const NumberVariable<double> &)));
|
SLOT(RandomNumberEndChanged(const NumberVariable<double> &)));
|
||||||
QWidget::connect(_generateInteger, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_generateInteger, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(GenerateIntegerChanged(int)));
|
SLOT(GenerateIntegerChanged(int)));
|
||||||
QWidget::connect(_randomValues,
|
|
||||||
SIGNAL(StringListChanged(const StringList &)), this,
|
|
||||||
SLOT(RandomValueListChanged(const StringList &)));
|
|
||||||
QWidget::connect(_allowRepeatValues, SIGNAL(stateChanged(int)), this,
|
|
||||||
SLOT(AllowRepeatValuesChanged(int)));
|
|
||||||
QWidget::connect(_jsonQuery, SIGNAL(editingFinished()), this,
|
QWidget::connect(_jsonQuery, SIGNAL(editingFinished()), this,
|
||||||
SLOT(JsonQueryChanged()));
|
SLOT(JsonQueryChanged()));
|
||||||
QWidget::connect(
|
QWidget::connect(
|
||||||
@@ -1041,6 +975,9 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
{"{{strValue}}", _strValue},
|
{"{{strValue}}", _strValue},
|
||||||
{"{{numValue}}", _numValue},
|
{"{{numValue}}", _numValue},
|
||||||
{"{{segmentIndex}}", _segmentIdx},
|
{"{{segmentIndex}}", _segmentIdx},
|
||||||
|
{"{{subStringStart}}", _subStringStart},
|
||||||
|
{"{{subStringSize}}", _subStringSize},
|
||||||
|
{"{{regexMatchIdx}}", _regexMatchIdx},
|
||||||
{"{{findRegex}}", _findRegex},
|
{"{{findRegex}}", _findRegex},
|
||||||
{"{{findStr}}", _findStr},
|
{"{{findStr}}", _findStr},
|
||||||
{"{{replaceStr}}", _replaceStr},
|
{"{{replaceStr}}", _replaceStr},
|
||||||
@@ -1072,7 +1009,12 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
PlaceWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text(
|
obs_module_text(
|
||||||
"AdvSceneSwitcher.action.variable.layout.substringIndex"),
|
"AdvSceneSwitcher.action.variable.layout.substringIndex"),
|
||||||
_subStringControlsLayout, widgetPlaceholders);
|
_subStringIndexEntryLayout, widgetPlaceholders);
|
||||||
|
|
||||||
|
PlaceWidgets(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.variable.layout.substringRegex"),
|
||||||
|
_subStringRegexEntryLayout, widgetPlaceholders);
|
||||||
|
|
||||||
PlaceWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text(
|
obs_module_text(
|
||||||
@@ -1093,17 +1035,15 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
obs_module_text(
|
obs_module_text(
|
||||||
"AdvSceneSwitcher.action.variable.layout.randomNumber"),
|
"AdvSceneSwitcher.action.variable.layout.randomNumber"),
|
||||||
randomLayout, widgetPlaceholders);
|
randomLayout, widgetPlaceholders);
|
||||||
_randomNumberLayout->addLayout(randomLayout);
|
_randomLayout->addLayout(randomLayout);
|
||||||
_randomNumberLayout->addWidget(_generateInteger);
|
_randomLayout->addWidget(_generateInteger);
|
||||||
|
|
||||||
_randomValueLayout->addWidget(_randomValues);
|
|
||||||
_randomValueLayout->addWidget(_allowRepeatValues);
|
|
||||||
|
|
||||||
auto regexConfigLayout = new QHBoxLayout;
|
auto regexConfigLayout = new QHBoxLayout;
|
||||||
regexConfigLayout->addWidget(_subStringRegex);
|
regexConfigLayout->addWidget(_substringRegex);
|
||||||
regexConfigLayout->addStretch();
|
regexConfigLayout->addStretch();
|
||||||
|
|
||||||
_substringLayout->addLayout(_subStringControlsLayout);
|
_substringLayout->addLayout(_subStringIndexEntryLayout);
|
||||||
|
_substringLayout->addLayout(_subStringRegexEntryLayout);
|
||||||
_substringLayout->addWidget(_regexPattern);
|
_substringLayout->addWidget(_regexPattern);
|
||||||
_substringLayout->addLayout(regexConfigLayout);
|
_substringLayout->addLayout(regexConfigLayout);
|
||||||
|
|
||||||
@@ -1116,8 +1056,7 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
layout->addWidget(_mathExpressionResult);
|
layout->addWidget(_mathExpressionResult);
|
||||||
layout->addLayout(_promptLayout);
|
layout->addLayout(_promptLayout);
|
||||||
layout->addLayout(_placeholderLayout);
|
layout->addLayout(_placeholderLayout);
|
||||||
layout->addLayout(_randomNumberLayout);
|
layout->addLayout(_randomLayout);
|
||||||
layout->addLayout(_randomValueLayout);
|
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
|
|
||||||
_entryData = entryData;
|
_entryData = entryData;
|
||||||
@@ -1151,7 +1090,7 @@ void MacroActionVariableEdit::UpdateEntryData()
|
|||||||
: MacroSegmentSelection::Type::ACTION);
|
: MacroSegmentSelection::Type::ACTION);
|
||||||
_subStringStart->SetValue(_entryData->_subStringStart);
|
_subStringStart->SetValue(_entryData->_subStringStart);
|
||||||
_subStringSize->SetValue(_entryData->_subStringSize);
|
_subStringSize->SetValue(_entryData->_subStringSize);
|
||||||
_subStringRegex->SetRegexConfig(_entryData->_subStringRegex);
|
_substringRegex->SetRegexConfig(_entryData->_subStringRegex);
|
||||||
_findRegex->SetRegexConfig(_entryData->_findRegex);
|
_findRegex->SetRegexConfig(_entryData->_findRegex);
|
||||||
_regexPattern->setPlainText(
|
_regexPattern->setPlainText(
|
||||||
QString::fromStdString(_entryData->_regexPattern));
|
QString::fromStdString(_entryData->_regexPattern));
|
||||||
@@ -1176,8 +1115,6 @@ void MacroActionVariableEdit::UpdateEntryData()
|
|||||||
_randomNumberStart->SetValue(_entryData->_randomNumberStart);
|
_randomNumberStart->SetValue(_entryData->_randomNumberStart);
|
||||||
_randomNumberEnd->SetValue(_entryData->_randomNumberEnd);
|
_randomNumberEnd->SetValue(_entryData->_randomNumberEnd);
|
||||||
_generateInteger->setChecked(_entryData->_generateInteger);
|
_generateInteger->setChecked(_entryData->_generateInteger);
|
||||||
_allowRepeatValues->setChecked(_entryData->_allowRepeatValues);
|
|
||||||
_randomValues->SetStringList(_entryData->_randomValues);
|
|
||||||
_jsonQuery->setText(_entryData->_jsonQuery);
|
_jsonQuery->setText(_entryData->_jsonQuery);
|
||||||
_jsonIndex->SetValue(_entryData->_jsonIndex);
|
_jsonIndex->SetValue(_entryData->_jsonIndex);
|
||||||
|
|
||||||
@@ -1459,7 +1396,6 @@ void MacroActionVariableEdit::SelectionChanged(const TempVariableRef &var)
|
|||||||
{
|
{
|
||||||
GUARD_LOADING_AND_LOCK();
|
GUARD_LOADING_AND_LOCK();
|
||||||
_entryData->_tempVar = var;
|
_entryData->_tempVar = var;
|
||||||
IncrementTempVarInUseGeneration();
|
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1521,18 +1457,6 @@ void MacroActionVariableEdit::GenerateIntegerChanged(int value)
|
|||||||
_entryData->_generateInteger = value;
|
_entryData->_generateInteger = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionVariableEdit::RandomValueListChanged(const StringList &values)
|
|
||||||
{
|
|
||||||
GUARD_LOADING_AND_LOCK();
|
|
||||||
_entryData->_randomValues = values;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroActionVariableEdit::AllowRepeatValuesChanged(int value)
|
|
||||||
{
|
|
||||||
GUARD_LOADING_AND_LOCK();
|
|
||||||
_entryData->_allowRepeatValues = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroActionVariableEdit::JsonQueryChanged()
|
void MacroActionVariableEdit::JsonQueryChanged()
|
||||||
{
|
{
|
||||||
GUARD_LOADING_AND_LOCK();
|
GUARD_LOADING_AND_LOCK();
|
||||||
@@ -1571,20 +1495,8 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
|||||||
{"{{jsonQuery}}", _jsonQuery},
|
{"{{jsonQuery}}", _jsonQuery},
|
||||||
{"{{jsonQueryHelp}}", _jsonQueryHelp},
|
{"{{jsonQueryHelp}}", _jsonQueryHelp},
|
||||||
{"{{jsonIndex}}", _jsonIndex},
|
{"{{jsonIndex}}", _jsonIndex},
|
||||||
{"{{subStringRegex}}", _subStringRegex},
|
|
||||||
{"{{subStringStart}}", _subStringStart},
|
|
||||||
{"{{subStringSize}}", _subStringSize},
|
|
||||||
{"{{regexMatchIdx}}", _regexMatchIdx},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &[_, widget] : widgetPlaceholders) {
|
|
||||||
_entryLayout->removeWidget(widget);
|
|
||||||
_subStringControlsLayout->removeWidget(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
ClearLayout(_entryLayout);
|
|
||||||
ClearLayout(_subStringControlsLayout);
|
|
||||||
|
|
||||||
const char *layoutString = "";
|
const char *layoutString = "";
|
||||||
if (_entryData->_action == MacroActionVariable::Action::PAD) {
|
if (_entryData->_action == MacroActionVariable::Action::PAD) {
|
||||||
layoutString = obs_module_text(
|
layoutString = obs_module_text(
|
||||||
@@ -1598,6 +1510,11 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
|||||||
"AdvSceneSwitcher.action.variable.layout.other");
|
"AdvSceneSwitcher.action.variable.layout.other");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const auto &[_, widget] : widgetPlaceholders) {
|
||||||
|
_entryLayout->removeWidget(widget);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearLayout(_entryLayout);
|
||||||
PlaceWidgets(layoutString, _entryLayout, widgetPlaceholders);
|
PlaceWidgets(layoutString, _entryLayout, widgetPlaceholders);
|
||||||
|
|
||||||
if (_entryData->_action == MacroActionVariable::Action::SET_VALUE ||
|
if (_entryData->_action == MacroActionVariable::Action::SET_VALUE ||
|
||||||
@@ -1644,25 +1561,15 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
|||||||
MacroActionVariable::Action::SET_ACTION_VALUE ||
|
MacroActionVariable::Action::SET_ACTION_VALUE ||
|
||||||
_entryData->_action ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Action::SET_CONDITION_VALUE);
|
MacroActionVariable::Action::SET_CONDITION_VALUE);
|
||||||
|
|
||||||
bool showRegex = _entryData->_subStringRegex.Enabled();
|
|
||||||
layoutString =
|
|
||||||
showRegex
|
|
||||||
? "AdvSceneSwitcher.action.variable.layout.substringRegex"
|
|
||||||
: "AdvSceneSwitcher.action.variable.layout.substringIndex";
|
|
||||||
PlaceWidgets(obs_module_text(layoutString), _subStringControlsLayout,
|
|
||||||
widgetPlaceholders);
|
|
||||||
_subStringStart->setVisible(!showRegex);
|
|
||||||
_subStringSize->setVisible(!showRegex);
|
|
||||||
_regexMatchIdx->setVisible(showRegex);
|
|
||||||
|
|
||||||
SetLayoutVisible(_substringLayout,
|
SetLayoutVisible(_substringLayout,
|
||||||
_entryData->_action ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Action::SUBSTRING);
|
MacroActionVariable::Action::SUBSTRING);
|
||||||
_regexPattern->setVisible(
|
if (_entryData->_action == MacroActionVariable::Action::SUBSTRING) {
|
||||||
showRegex &&
|
bool showRegex = _entryData->_subStringRegex.Enabled();
|
||||||
_entryData->_action == MacroActionVariable::Action::SUBSTRING);
|
SetLayoutVisible(_subStringIndexEntryLayout, !showRegex);
|
||||||
|
SetLayoutVisible(_subStringRegexEntryLayout, showRegex);
|
||||||
|
_regexPattern->setVisible(showRegex);
|
||||||
|
}
|
||||||
SetLayoutVisible(_findReplaceLayout,
|
SetLayoutVisible(_findReplaceLayout,
|
||||||
_entryData->_action ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Action::FIND_AND_REPLACE);
|
MacroActionVariable::Action::FIND_AND_REPLACE);
|
||||||
@@ -1727,13 +1634,9 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
|||||||
MacroActionVariable::Action::PAD);
|
MacroActionVariable::Action::PAD);
|
||||||
_caseType->setVisible(_entryData->_action ==
|
_caseType->setVisible(_entryData->_action ==
|
||||||
MacroActionVariable::Action::CHANGE_CASE);
|
MacroActionVariable::Action::CHANGE_CASE);
|
||||||
SetLayoutVisible(_randomNumberLayout,
|
SetLayoutVisible(_randomLayout,
|
||||||
_entryData->_action ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Action::RANDOM_NUMBER);
|
MacroActionVariable::Action::RANDOM_NUMBER);
|
||||||
SetLayoutVisible(
|
|
||||||
_randomValueLayout,
|
|
||||||
_entryData->_action ==
|
|
||||||
MacroActionVariable::Action::RANDOM_LIST_VALUE);
|
|
||||||
_jsonQuery->setVisible(_entryData->_action ==
|
_jsonQuery->setVisible(_entryData->_action ==
|
||||||
MacroActionVariable::Action::QUERY_JSON);
|
MacroActionVariable::Action::QUERY_JSON);
|
||||||
_jsonQueryHelp->setVisible(_entryData->_action ==
|
_jsonQueryHelp->setVisible(_entryData->_action ==
|
||||||
|
|||||||
@@ -6,7 +6,6 @@
|
|||||||
#include "resizing-text-edit.hpp"
|
#include "resizing-text-edit.hpp"
|
||||||
#include "scene-selection.hpp"
|
#include "scene-selection.hpp"
|
||||||
#include "single-char-selection.hpp"
|
#include "single-char-selection.hpp"
|
||||||
#include "string-list.hpp"
|
|
||||||
#include "variable-line-edit.hpp"
|
#include "variable-line-edit.hpp"
|
||||||
#include "variable-text-edit.hpp"
|
#include "variable-text-edit.hpp"
|
||||||
#include "variable-spinbox.hpp"
|
#include "variable-spinbox.hpp"
|
||||||
@@ -23,7 +22,6 @@ public:
|
|||||||
bool PostLoad();
|
bool PostLoad();
|
||||||
std::string GetShortDesc() const;
|
std::string GetShortDesc() const;
|
||||||
std::string GetId() const { return id; };
|
std::string GetId() const { return id; };
|
||||||
std::vector<TempVariableRef> GetTempVarRefs() const;
|
|
||||||
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 SetSegmentIndexValue(int);
|
void SetSegmentIndexValue(int);
|
||||||
@@ -58,7 +56,6 @@ public:
|
|||||||
QUERY_JSON,
|
QUERY_JSON,
|
||||||
ARRAY_JSON,
|
ARRAY_JSON,
|
||||||
COPY_VAR,
|
COPY_VAR,
|
||||||
RANDOM_LIST_VALUE,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Action _action = Action::SET_VALUE;
|
Action _action = Action::SET_VALUE;
|
||||||
@@ -110,10 +107,6 @@ public:
|
|||||||
DoubleVariable _randomNumberEnd = 100;
|
DoubleVariable _randomNumberEnd = 100;
|
||||||
bool _generateInteger = true;
|
bool _generateInteger = true;
|
||||||
|
|
||||||
StringList _randomValues = {"value1", "value2", "value3"};
|
|
||||||
bool _allowRepeatValues = true;
|
|
||||||
std::optional<std::string> _lastRandomValue;
|
|
||||||
|
|
||||||
StringVariable _jsonQuery = "$.some.nested.value";
|
StringVariable _jsonQuery = "$.some.nested.value";
|
||||||
IntVariable _jsonIndex = 0;
|
IntVariable _jsonIndex = 0;
|
||||||
|
|
||||||
@@ -126,7 +119,6 @@ private:
|
|||||||
void HandleCaseChange(Variable *);
|
void HandleCaseChange(Variable *);
|
||||||
void SetToSceneItemName(Variable *);
|
void SetToSceneItemName(Variable *);
|
||||||
void GenerateRandomNumber(Variable *);
|
void GenerateRandomNumber(Variable *);
|
||||||
void PickRandomValue(Variable *);
|
|
||||||
|
|
||||||
std::weak_ptr<MacroSegment> _macroSegment;
|
std::weak_ptr<MacroSegment> _macroSegment;
|
||||||
int _segmentIdxLoadValue = -1;
|
int _segmentIdxLoadValue = -1;
|
||||||
@@ -183,8 +175,6 @@ private slots:
|
|||||||
void RandomNumberStartChanged(const NumberVariable<double> &);
|
void RandomNumberStartChanged(const NumberVariable<double> &);
|
||||||
void RandomNumberEndChanged(const NumberVariable<double> &);
|
void RandomNumberEndChanged(const NumberVariable<double> &);
|
||||||
void GenerateIntegerChanged(int);
|
void GenerateIntegerChanged(int);
|
||||||
void RandomValueListChanged(const StringList &);
|
|
||||||
void AllowRepeatValuesChanged(int);
|
|
||||||
void JsonQueryChanged();
|
void JsonQueryChanged();
|
||||||
void JsonIndexChanged(const NumberVariable<int> &);
|
void JsonIndexChanged(const NumberVariable<int> &);
|
||||||
|
|
||||||
@@ -204,10 +194,11 @@ private:
|
|||||||
QLabel *_segmentValueStatus;
|
QLabel *_segmentValueStatus;
|
||||||
ResizingPlainTextEdit *_segmentValue;
|
ResizingPlainTextEdit *_segmentValue;
|
||||||
QVBoxLayout *_substringLayout;
|
QVBoxLayout *_substringLayout;
|
||||||
QHBoxLayout *_subStringControlsLayout;
|
QHBoxLayout *_subStringIndexEntryLayout;
|
||||||
|
QHBoxLayout *_subStringRegexEntryLayout;
|
||||||
VariableSpinBox *_subStringStart;
|
VariableSpinBox *_subStringStart;
|
||||||
VariableSpinBox *_subStringSize;
|
VariableSpinBox *_subStringSize;
|
||||||
RegexConfigWidget *_subStringRegex;
|
RegexConfigWidget *_substringRegex;
|
||||||
ResizingPlainTextEdit *_regexPattern;
|
ResizingPlainTextEdit *_regexPattern;
|
||||||
VariableSpinBox *_regexMatchIdx;
|
VariableSpinBox *_regexMatchIdx;
|
||||||
QHBoxLayout *_findReplaceLayout;
|
QHBoxLayout *_findReplaceLayout;
|
||||||
@@ -234,10 +225,7 @@ private:
|
|||||||
VariableDoubleSpinBox *_randomNumberStart;
|
VariableDoubleSpinBox *_randomNumberStart;
|
||||||
VariableDoubleSpinBox *_randomNumberEnd;
|
VariableDoubleSpinBox *_randomNumberEnd;
|
||||||
QCheckBox *_generateInteger;
|
QCheckBox *_generateInteger;
|
||||||
QVBoxLayout *_randomNumberLayout;
|
QVBoxLayout *_randomLayout;
|
||||||
StringListEdit *_randomValues;
|
|
||||||
QCheckBox *_allowRepeatValues;
|
|
||||||
QVBoxLayout *_randomValueLayout;
|
|
||||||
VariableLineEdit *_jsonQuery;
|
VariableLineEdit *_jsonQuery;
|
||||||
QLabel *_jsonQueryHelp;
|
QLabel *_jsonQueryHelp;
|
||||||
VariableSpinBox *_jsonIndex;
|
VariableSpinBox *_jsonIndex;
|
||||||
|
|||||||
@@ -126,12 +126,10 @@ MacroConditionEdit::MacroConditionEdit(
|
|||||||
_section->AddHeaderWidget(_conditionSelection);
|
_section->AddHeaderWidget(_conditionSelection);
|
||||||
_section->AddHeaderWidget(_headerInfo);
|
_section->AddHeaderWidget(_headerInfo);
|
||||||
_section->AddHeaderWidget(_dur);
|
_section->AddHeaderWidget(_dur);
|
||||||
_section->AddHeaderWidget(_varMappingToggle);
|
|
||||||
|
|
||||||
QVBoxLayout *conditionLayout = new QVBoxLayout;
|
QVBoxLayout *conditionLayout = new QVBoxLayout;
|
||||||
conditionLayout->setContentsMargins({7, 7, 7, 7});
|
conditionLayout->setContentsMargins({7, 7, 7, 7});
|
||||||
conditionLayout->addWidget(_section);
|
conditionLayout->addWidget(_section);
|
||||||
conditionLayout->addWidget(_outputMappings);
|
|
||||||
_contentLayout->addLayout(conditionLayout);
|
_contentLayout->addLayout(conditionLayout);
|
||||||
|
|
||||||
QHBoxLayout *mainLayout = new QHBoxLayout;
|
QHBoxLayout *mainLayout = new QHBoxLayout;
|
||||||
@@ -206,10 +204,7 @@ void MacroConditionEdit::SetupWidgets(bool basicSetup)
|
|||||||
MacroConditionFactory::CreateWidget(id, this, *_entryData);
|
MacroConditionFactory::CreateWidget(id, this, *_entryData);
|
||||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||||
QWidget::connect(widget, SIGNAL(ShowVariableMappings(bool)), this,
|
|
||||||
SLOT(ShowVariableMappings(bool)));
|
|
||||||
_section->SetContent(widget, (*_entryData)->GetCollapsed());
|
_section->SetContent(widget, (*_entryData)->GetCollapsed());
|
||||||
SetupVarMappings((*_entryData).get());
|
|
||||||
SetFocusPolicyOfWidgets();
|
SetFocusPolicyOfWidgets();
|
||||||
|
|
||||||
_allWidgetsAreSetup = true;
|
_allWidgetsAreSetup = true;
|
||||||
@@ -250,10 +245,7 @@ void MacroConditionEdit::ConditionSelectionChanged(const QString &text)
|
|||||||
MacroConditionFactory::CreateWidget(id, this, *_entryData);
|
MacroConditionFactory::CreateWidget(id, this, *_entryData);
|
||||||
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
QWidget::connect(widget, SIGNAL(HeaderInfoChanged(const QString &)),
|
||||||
this, SLOT(HeaderInfoChanged(const QString &)));
|
this, SLOT(HeaderInfoChanged(const QString &)));
|
||||||
QWidget::connect(widget, SIGNAL(ShowVariableMappings(bool)), this,
|
|
||||||
SLOT(ShowVariableMappings(bool)));
|
|
||||||
_section->SetContent(widget);
|
_section->SetContent(widget);
|
||||||
SetupVarMappings((*_entryData).get());
|
|
||||||
_dur->setVisible(MacroConditionFactory::UsesDurationModifier(id));
|
_dur->setVisible(MacroConditionFactory::UsesDurationModifier(id));
|
||||||
SetFocusPolicyOfWidgets();
|
SetFocusPolicyOfWidgets();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -315,7 +315,6 @@ MacroConditionMacroEdit::MacroConditionMacroEdit(
|
|||||||
_actionIndex(new MacroSegmentSelection(
|
_actionIndex(new MacroSegmentSelection(
|
||||||
this, MacroSegmentSelection::Type::ACTION))
|
this, MacroSegmentSelection::Type::ACTION))
|
||||||
{
|
{
|
||||||
_macros->HideGroups();
|
|
||||||
_count->setMaximum(10000000);
|
_count->setMaximum(10000000);
|
||||||
populateTypeSelection(_types);
|
populateTypeSelection(_types);
|
||||||
populateCounterConditionSelection(_counterConditions);
|
populateCounterConditionSelection(_counterConditions);
|
||||||
|
|||||||
@@ -6,15 +6,6 @@ namespace advss {
|
|||||||
|
|
||||||
const std::string MacroConditionTempVar::id = "temp_var";
|
const std::string MacroConditionTempVar::id = "temp_var";
|
||||||
|
|
||||||
std::vector<TempVariableRef> MacroConditionTempVar::GetTempVarRefs() const
|
|
||||||
{
|
|
||||||
auto refs = MacroSegment::GetTempVarRefs();
|
|
||||||
if (_tempVar.HasValidID()) {
|
|
||||||
refs.push_back(_tempVar);
|
|
||||||
}
|
|
||||||
return refs;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroConditionTempVar::_registered = MacroConditionFactory::Register(
|
bool MacroConditionTempVar::_registered = MacroConditionFactory::Register(
|
||||||
MacroConditionTempVar::id,
|
MacroConditionTempVar::id,
|
||||||
{MacroConditionTempVar::Create, MacroConditionTempVarEdit::Create,
|
{MacroConditionTempVar::Create, MacroConditionTempVarEdit::Create,
|
||||||
@@ -275,7 +266,6 @@ void MacroConditionTempVarEdit::VariableChanged(const TempVariableRef &var)
|
|||||||
{
|
{
|
||||||
GUARD_LOADING_AND_LOCK();
|
GUARD_LOADING_AND_LOCK();
|
||||||
_entryData->_tempVar = var;
|
_entryData->_tempVar = var;
|
||||||
IncrementTempVarInUseGeneration();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionTempVarEdit::Variable2Changed(const QString &text)
|
void MacroConditionTempVarEdit::Variable2Changed(const QString &text)
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ public:
|
|||||||
bool Load(obs_data_t *obj);
|
bool Load(obs_data_t *obj);
|
||||||
std::string GetShortDesc() const;
|
std::string GetShortDesc() const;
|
||||||
std::string GetId() const { return id; };
|
std::string GetId() const { return id; };
|
||||||
std::vector<TempVariableRef> GetTempVarRefs() const;
|
|
||||||
static std::shared_ptr<MacroCondition> Create(Macro *m)
|
static std::shared_ptr<MacroCondition> Create(Macro *m)
|
||||||
{
|
{
|
||||||
return std::make_shared<MacroConditionTempVar>(m);
|
return std::make_shared<MacroConditionTempVar>(m);
|
||||||
|
|||||||
@@ -7,17 +7,6 @@ MacroCondition::MacroCondition(Macro *m, bool supportsVariableValue)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroCondition::EvaluateCondition()
|
|
||||||
{
|
|
||||||
bool newValue = CheckCondition();
|
|
||||||
_changed = _previousValue.has_value() && (*_previousValue != newValue);
|
|
||||||
const bool negate = _logic.IsNegationType(GetLogicType());
|
|
||||||
_risingEdge = _changed &&
|
|
||||||
((!negate && newValue) || (negate && !newValue));
|
|
||||||
_previousValue = newValue;
|
|
||||||
return newValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroCondition::Save(obs_data_t *obj) const
|
bool MacroCondition::Save(obs_data_t *obj) const
|
||||||
{
|
{
|
||||||
MacroSegment::Save(obj);
|
MacroSegment::Save(obj);
|
||||||
|
|||||||
@@ -4,19 +4,13 @@
|
|||||||
#include "duration-modifier.hpp"
|
#include "duration-modifier.hpp"
|
||||||
#include "macro-ref.hpp"
|
#include "macro-ref.hpp"
|
||||||
|
|
||||||
#include <optional>
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
class EXPORT MacroCondition : public MacroSegment {
|
class EXPORT MacroCondition : public MacroSegment {
|
||||||
public:
|
public:
|
||||||
MacroCondition(Macro *m, bool supportsVariableValue = false);
|
MacroCondition(Macro *m, bool supportsVariableValue = false);
|
||||||
virtual ~MacroCondition() = default;
|
virtual ~MacroCondition() = default;
|
||||||
|
virtual bool CheckCondition() = 0;
|
||||||
bool EvaluateCondition();
|
|
||||||
bool HasChanged() const { return _changed; }
|
|
||||||
bool IsRisingEdge() const { return _risingEdge; }
|
|
||||||
|
|
||||||
virtual bool Save(obs_data_t *obj) const = 0;
|
virtual bool Save(obs_data_t *obj) const = 0;
|
||||||
virtual bool Load(obs_data_t *obj) = 0;
|
virtual bool Load(obs_data_t *obj) = 0;
|
||||||
|
|
||||||
@@ -34,15 +28,9 @@ public:
|
|||||||
|
|
||||||
static std::string_view GetDefaultID();
|
static std::string_view GetDefaultID();
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual bool CheckCondition() = 0;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Logic _logic = Logic(Logic::Type::ROOT_NONE);
|
Logic _logic = Logic(Logic::Type::ROOT_NONE);
|
||||||
DurationModifier _durationModifier;
|
DurationModifier _durationModifier;
|
||||||
std::optional<bool> _previousValue;
|
|
||||||
bool _changed = false;
|
|
||||||
bool _risingEdge = false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class EXPORT MacroRefCondition : virtual public MacroCondition {
|
class EXPORT MacroRefCondition : virtual public MacroCondition {
|
||||||
|
|||||||
@@ -366,7 +366,7 @@ static void runSegmentHighlightChecksHelper(MacroSegmentList *list)
|
|||||||
// highlight its segments if required
|
// highlight its segments if required
|
||||||
auto macroAction = dynamic_cast<MacroActionMacro *>(data.get());
|
auto macroAction = dynamic_cast<MacroActionMacro *>(data.get());
|
||||||
if (macroAction &&
|
if (macroAction &&
|
||||||
macroAction->GetAction() ==
|
macroAction->_action ==
|
||||||
MacroActionMacro::Action::NESTED_MACRO) {
|
MacroActionMacro::Action::NESTED_MACRO) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1086,11 +1086,6 @@ void MacroEdit::AddMacroAction(Macro *macro, int idx, const std::string &id,
|
|||||||
HighlightAction(idx);
|
HighlightAction(idx);
|
||||||
ui->actionsList->SetHelpMsgVisible(false);
|
ui->actionsList->SetHelpMsgVisible(false);
|
||||||
emit(MacroSegmentOrderChanged());
|
emit(MacroSegmentOrderChanged());
|
||||||
|
|
||||||
QTimer::singleShot(0, this, [this]() {
|
|
||||||
ui->actionsList->ensureWidgetVisible(
|
|
||||||
ui->actionsList->WidgetAt(currentActionIdx));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroEdit::AddMacroAction(int idx)
|
void MacroEdit::AddMacroAction(int idx)
|
||||||
@@ -1394,11 +1389,6 @@ void MacroEdit::AddMacroElseAction(Macro *macro, int idx, const std::string &id,
|
|||||||
HighlightElseAction(idx);
|
HighlightElseAction(idx);
|
||||||
ui->elseActionsList->SetHelpMsgVisible(false);
|
ui->elseActionsList->SetHelpMsgVisible(false);
|
||||||
emit(MacroSegmentOrderChanged());
|
emit(MacroSegmentOrderChanged());
|
||||||
|
|
||||||
QTimer::singleShot(0, this, [this]() {
|
|
||||||
ui->elseActionsList->ensureWidgetVisible(
|
|
||||||
ui->elseActionsList->WidgetAt(currentElseActionIdx));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroEdit::AddMacroElseAction(int idx)
|
void MacroEdit::AddMacroElseAction(int idx)
|
||||||
@@ -1601,11 +1591,6 @@ void MacroEdit::AddMacroCondition(Macro *macro, int idx, const std::string &id,
|
|||||||
HighlightCondition(idx);
|
HighlightCondition(idx);
|
||||||
ui->conditionsList->SetHelpMsgVisible(false);
|
ui->conditionsList->SetHelpMsgVisible(false);
|
||||||
emit(MacroSegmentOrderChanged());
|
emit(MacroSegmentOrderChanged());
|
||||||
|
|
||||||
QTimer::singleShot(0, this, [this]() {
|
|
||||||
ui->conditionsList->ensureWidgetVisible(
|
|
||||||
ui->conditionsList->WidgetAt(currentConditionIdx));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroEdit::on_conditionAdd_clicked()
|
void MacroEdit::on_conditionAdd_clicked()
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ namespace advss {
|
|||||||
class Macro;
|
class Macro;
|
||||||
class MacroSegment;
|
class MacroSegment;
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
* Advanced Scene Switcher window
|
||||||
|
*******************************************************************************/
|
||||||
class MacroEdit : public QWidget {
|
class MacroEdit : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
|||||||
@@ -117,32 +117,9 @@ GetMacroConditions(Macro *macro)
|
|||||||
return macro->Conditions();
|
return macro->Conditions();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsGroupMacro(Macro *macro)
|
std::string_view GetSceneSwitchActionId()
|
||||||
{
|
{
|
||||||
return macro && macro->IsGroup();
|
return MacroAction::GetDefaultID();
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Macro>> GetGroupMacroEntries(Macro *macro)
|
|
||||||
{
|
|
||||||
if (!macro || !macro->IsGroup()) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<Macro>> entries;
|
|
||||||
entries.reserve(macro->GroupSize());
|
|
||||||
|
|
||||||
const auto ¯os = GetTopLevelMacros();
|
|
||||||
for (auto it = macros.begin(); it < macros.end(); it++) {
|
|
||||||
if ((*it)->Name() != macro->Name()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (uint32_t i = 1; i <= macro->GroupSize(); i++) {
|
|
||||||
entries.emplace_back(*std::next(it, i));
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return entries;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::condition_variable &GetMacroWaitCV()
|
std::condition_variable &GetMacroWaitCV()
|
||||||
@@ -242,11 +219,6 @@ bool RunMacroActions(Macro *macro)
|
|||||||
return macro && macro->PerformActions(true);
|
return macro && macro->PerformActions(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RunMacroElseActions(Macro *macro)
|
|
||||||
{
|
|
||||||
return macro && macro->PerformActions(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ResetMacroConditionTimers(Macro *macro)
|
void ResetMacroConditionTimers(Macro *macro)
|
||||||
{
|
{
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <string_view>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
|
||||||
struct obs_data;
|
struct obs_data;
|
||||||
@@ -19,8 +20,6 @@ class Macro;
|
|||||||
class MacroAction;
|
class MacroAction;
|
||||||
class MacroCondition;
|
class MacroCondition;
|
||||||
|
|
||||||
static const int macro_func = 10;
|
|
||||||
|
|
||||||
EXPORT std::deque<std::shared_ptr<Macro>> &GetTopLevelMacros();
|
EXPORT std::deque<std::shared_ptr<Macro>> &GetTopLevelMacros();
|
||||||
std::deque<std::shared_ptr<Macro>> &GetTemporaryMacros();
|
std::deque<std::shared_ptr<Macro>> &GetTemporaryMacros();
|
||||||
EXPORT std::deque<std::shared_ptr<Macro>> GetAllMacros();
|
EXPORT std::deque<std::shared_ptr<Macro>> GetAllMacros();
|
||||||
@@ -36,8 +35,9 @@ GetMacroElseActions(Macro *);
|
|||||||
EXPORT std::optional<std::deque<std::shared_ptr<MacroCondition>>>
|
EXPORT std::optional<std::deque<std::shared_ptr<MacroCondition>>>
|
||||||
GetMacroConditions(Macro *);
|
GetMacroConditions(Macro *);
|
||||||
|
|
||||||
EXPORT bool IsGroupMacro(Macro *);
|
std::string_view GetSceneSwitchActionId();
|
||||||
EXPORT std::vector<std::shared_ptr<Macro>> GetGroupMacroEntries(Macro *);
|
|
||||||
|
constexpr auto macro_func = 10;
|
||||||
|
|
||||||
EXPORT std::condition_variable &GetMacroWaitCV();
|
EXPORT std::condition_variable &GetMacroWaitCV();
|
||||||
EXPORT std::condition_variable &GetMacroTransitionCV();
|
EXPORT std::condition_variable &GetMacroTransitionCV();
|
||||||
@@ -68,7 +68,6 @@ EXPORT void AddMacroHelperThread(Macro *, std::thread &&);
|
|||||||
EXPORT bool CheckMacros();
|
EXPORT bool CheckMacros();
|
||||||
|
|
||||||
EXPORT bool RunMacroActions(Macro *);
|
EXPORT bool RunMacroActions(Macro *);
|
||||||
bool RunMacroElseActions(Macro *);
|
|
||||||
EXPORT bool RunMacros();
|
EXPORT bool RunMacros();
|
||||||
void StopAllMacros();
|
void StopAllMacros();
|
||||||
|
|
||||||
|
|||||||
@@ -244,9 +244,22 @@ bool MacroMatchesSearchFilter(Macro *macro)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (macro->IsGroup()) {
|
if (macro->IsGroup()) {
|
||||||
const auto groupEntries = GetGroupMacroEntries(macro);
|
std::vector<std::shared_ptr<Macro>> subItems;
|
||||||
for (const auto &entry : groupEntries) {
|
subItems.reserve(macro->GroupSize());
|
||||||
if (MacroMatchesSearchFilter(entry.get())) {
|
|
||||||
|
const auto ¯os = GetTopLevelMacros();
|
||||||
|
for (auto it = macros.begin(); it < macros.end(); it++) {
|
||||||
|
if ((*it)->Name() != macro->Name()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (uint32_t i = 1; i <= macro->GroupSize(); i++) {
|
||||||
|
subItems.emplace_back(*std::next(it, i));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &item : subItems) {
|
||||||
|
if (MacroMatchesSearchFilter(item.get())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
#include "macro-segment.hpp"
|
#include "macro-segment.hpp"
|
||||||
#include "macro.hpp"
|
#include "macro.hpp"
|
||||||
#include "mouse-wheel-guard.hpp"
|
#include "mouse-wheel-guard.hpp"
|
||||||
#include "path-helpers.hpp"
|
|
||||||
#include "section.hpp"
|
#include "section.hpp"
|
||||||
#include "ui-helpers.hpp"
|
#include "ui-helpers.hpp"
|
||||||
#include "variable.hpp"
|
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
@@ -15,84 +13,20 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
std::vector<TempVariableRef> MacroSegment::GetTempVarRefs() const
|
|
||||||
{
|
|
||||||
std::vector<TempVariableRef> refs;
|
|
||||||
for (const auto &mapping : _varMappings) {
|
|
||||||
if (mapping.tempVar.HasValidID()) {
|
|
||||||
refs.push_back(mapping.tempVar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return refs;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroSegment::ApplyVarMappings()
|
|
||||||
{
|
|
||||||
auto macro = GetMacro();
|
|
||||||
for (const auto &mapping : _varMappings) {
|
|
||||||
auto var = mapping.variable.lock();
|
|
||||||
if (!var) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const auto tempVar = mapping.tempVar.GetTempVariable(macro);
|
|
||||||
if (!tempVar) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const auto value = tempVar->Value();
|
|
||||||
if (!value) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
var->SetValue(*value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::vector<VarMapping> &MacroSegment::GetVarMappings() const
|
|
||||||
{
|
|
||||||
return _varMappings;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroSegment::SetVarMappings(const std::vector<VarMapping> &mappings)
|
|
||||||
{
|
|
||||||
_varMappings = mappings;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<TempVariable> MacroSegment::GetOwnTempVars() const
|
|
||||||
{
|
|
||||||
return _tempVariables;
|
|
||||||
}
|
|
||||||
|
|
||||||
MacroSegment::MacroSegment(Macro *m, bool supportsVariableValue)
|
MacroSegment::MacroSegment(Macro *m, bool supportsVariableValue)
|
||||||
: _macro(m),
|
: _macro(m),
|
||||||
_supportsVariableValue(supportsVariableValue)
|
_supportsVariableValue(supportsVariableValue)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSegment::SetVarMappingExpanded(bool expanded)
|
|
||||||
{
|
|
||||||
_varMappingExpanded = expanded;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroSegment::Save(obs_data_t *obj) const
|
bool MacroSegment::Save(obs_data_t *obj) const
|
||||||
{
|
{
|
||||||
OBSDataAutoRelease data = obs_data_create();
|
OBSDataAutoRelease data = obs_data_create();
|
||||||
obs_data_set_bool(data, "collapsed", _collapsed);
|
obs_data_set_bool(data, "collapsed", _collapsed);
|
||||||
obs_data_set_bool(data, "varMappingExpanded", _varMappingExpanded);
|
|
||||||
obs_data_set_bool(data, "useCustomLabel", _useCustomLabel);
|
obs_data_set_bool(data, "useCustomLabel", _useCustomLabel);
|
||||||
obs_data_set_string(data, "customLabel", _customLabel.c_str());
|
obs_data_set_string(data, "customLabel", _customLabel.c_str());
|
||||||
obs_data_set_bool(data, "enabled", _enabled);
|
obs_data_set_bool(data, "enabled", _enabled);
|
||||||
obs_data_set_int(data, "version", 1);
|
obs_data_set_int(data, "version", 1);
|
||||||
|
|
||||||
OBSDataArrayAutoRelease mappingsArray = obs_data_array_create();
|
|
||||||
for (const auto &mapping : _varMappings) {
|
|
||||||
OBSDataAutoRelease item = obs_data_create();
|
|
||||||
mapping.tempVar.Save(item, GetMacro(), "tempVar");
|
|
||||||
obs_data_set_string(
|
|
||||||
item, "variable",
|
|
||||||
GetWeakVariableName(mapping.variable).c_str());
|
|
||||||
obs_data_array_push_back(mappingsArray, item);
|
|
||||||
}
|
|
||||||
obs_data_set_array(data, "varMappings", mappingsArray);
|
|
||||||
|
|
||||||
obs_data_set_obj(obj, "segmentSettings", data);
|
obs_data_set_obj(obj, "segmentSettings", data);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -101,7 +35,6 @@ bool MacroSegment::Load(obs_data_t *obj)
|
|||||||
{
|
{
|
||||||
OBSDataAutoRelease data = obs_data_get_obj(obj, "segmentSettings");
|
OBSDataAutoRelease data = obs_data_get_obj(obj, "segmentSettings");
|
||||||
_collapsed = obs_data_get_bool(data, "collapsed");
|
_collapsed = obs_data_get_bool(data, "collapsed");
|
||||||
_varMappingExpanded = obs_data_get_bool(data, "varMappingExpanded");
|
|
||||||
_useCustomLabel = obs_data_get_bool(data, "useCustomLabel");
|
_useCustomLabel = obs_data_get_bool(data, "useCustomLabel");
|
||||||
_customLabel = obs_data_get_string(data, "customLabel");
|
_customLabel = obs_data_get_string(data, "customLabel");
|
||||||
obs_data_set_default_bool(data, "enabled", true);
|
obs_data_set_default_bool(data, "enabled", true);
|
||||||
@@ -112,20 +45,6 @@ bool MacroSegment::Load(obs_data_t *obj)
|
|||||||
_enabled = obs_data_get_bool(obj, "enabled");
|
_enabled = obs_data_get_bool(obj, "enabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
_varMappings.clear();
|
|
||||||
OBSDataArrayAutoRelease mappingsArray =
|
|
||||||
obs_data_get_array(data, "varMappings");
|
|
||||||
const size_t count = obs_data_array_count(mappingsArray);
|
|
||||||
_varMappings.reserve(count);
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
OBSDataAutoRelease item = obs_data_array_item(mappingsArray, i);
|
|
||||||
VarMapping mapping;
|
|
||||||
mapping.variable = GetWeakVariableByName(
|
|
||||||
obs_data_get_string(item, "variable"));
|
|
||||||
_varMappings.push_back(std::move(mapping));
|
|
||||||
_varMappings.back().tempVar.Load(item, GetMacro(), "tempVar");
|
|
||||||
}
|
|
||||||
|
|
||||||
ClearAvailableTempvars();
|
ClearAvailableTempvars();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -233,16 +152,6 @@ void MacroSegment::AddTempvar(const std::string &id, const std::string &name,
|
|||||||
NotifyUIAboutTempVarChange(this);
|
NotifyUIAboutTempVarChange(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroSegment::IsTempVarInUse(const std::string &id) const
|
|
||||||
{
|
|
||||||
for (const auto &var : _tempVariables) {
|
|
||||||
if (var.ID() == id) {
|
|
||||||
return var.IsInUse();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroSegment::SetTempVarValue(const std::string &id,
|
void MacroSegment::SetTempVarValue(const std::string &id,
|
||||||
const std::string &value)
|
const std::string &value)
|
||||||
{
|
{
|
||||||
@@ -302,38 +211,11 @@ MacroSegmentEdit::MacroSegmentEdit(QWidget *parent)
|
|||||||
_headerInfo(new QLabel()),
|
_headerInfo(new QLabel()),
|
||||||
_frame(new QWidget),
|
_frame(new QWidget),
|
||||||
_contentLayout(new QVBoxLayout),
|
_contentLayout(new QVBoxLayout),
|
||||||
_outputMappings(new TempVarOutputMappingsWidget(this)),
|
|
||||||
_varMappingToggle(new QPushButton(this)),
|
|
||||||
_noBorderframe(new QFrame),
|
_noBorderframe(new QFrame),
|
||||||
_borderFrame(new QFrame),
|
_borderFrame(new QFrame),
|
||||||
_dropLineAbove(new QFrame),
|
_dropLineAbove(new QFrame),
|
||||||
_dropLineBelow(new QFrame)
|
_dropLineBelow(new QFrame)
|
||||||
{
|
{
|
||||||
const auto iconPath = QString::fromStdString(GetDataFilePath(
|
|
||||||
"res/images/" + GetThemeTypeName() + "Variable.svg"));
|
|
||||||
_varMappingToggle->setIcon(QIcon(iconPath));
|
|
||||||
_varMappingToggle->setMaximumWidth(22);
|
|
||||||
_varMappingToggle->setFlat(true);
|
|
||||||
_varMappingToggle->setCheckable(true);
|
|
||||||
_varMappingToggle->setVisible(false);
|
|
||||||
_varMappingToggle->setToolTip(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.tempVar.outputMappings.toggle"));
|
|
||||||
|
|
||||||
QWidget::connect(_varMappingToggle, &QPushButton::toggled,
|
|
||||||
_outputMappings,
|
|
||||||
&TempVarOutputMappingsWidget::SetPanelExpanded);
|
|
||||||
QWidget::connect(_varMappingToggle, &QPushButton::toggled, this,
|
|
||||||
[this](bool checked) {
|
|
||||||
if (Data()) {
|
|
||||||
Data()->SetVarMappingExpanded(checked);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
QWidget::connect(_outputMappings,
|
|
||||||
&TempVarOutputMappingsWidget::ExpandableChanged,
|
|
||||||
_varMappingToggle, &QPushButton::setVisible);
|
|
||||||
QWidget::connect(_section, &Section::Collapsed, _outputMappings,
|
|
||||||
&TempVarOutputMappingsWidget::SetSectionCollapsed);
|
|
||||||
|
|
||||||
_dropLineAbove->setLineWidth(3);
|
_dropLineAbove->setLineWidth(3);
|
||||||
_dropLineAbove->setFixedHeight(11);
|
_dropLineAbove->setFixedHeight(11);
|
||||||
_dropLineBelow->setLineWidth(3);
|
_dropLineBelow->setLineWidth(3);
|
||||||
@@ -395,21 +277,6 @@ MacroSegmentEdit::MacroSegmentEdit(QWidget *parent)
|
|||||||
_headerInfo->installEventFilter(this);
|
_headerInfo->installEventFilter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSegmentEdit::SetupVarMappings(MacroSegment *segment)
|
|
||||||
{
|
|
||||||
_outputMappings->SetSegment(segment);
|
|
||||||
_varMappingToggle->setChecked(segment &&
|
|
||||||
segment->GetVarMappingExpanded());
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroSegmentEdit::ShowVariableMappings(bool show)
|
|
||||||
{
|
|
||||||
_varMappingToggle->setChecked(show);
|
|
||||||
if (Data()) {
|
|
||||||
Data()->SetVarMappingExpanded(show);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroSegmentEdit::eventFilter(QObject *obj, QEvent *ev)
|
bool MacroSegmentEdit::eventFilter(QObject *obj, QEvent *ev)
|
||||||
{
|
{
|
||||||
if (obj == _headerInfo && ev->type() == QEvent::MouseMove) {
|
if (obj == _headerInfo && ev->type() == QEvent::MouseMove) {
|
||||||
|
|||||||
@@ -9,23 +9,15 @@
|
|||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
#include <QFrame>
|
#include <QFrame>
|
||||||
#include <QPushButton>
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
#include <obs-data.h>
|
#include <obs-data.h>
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
class QLabel;
|
class QLabel;
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
class Macro;
|
class Macro;
|
||||||
class Variable;
|
|
||||||
|
|
||||||
struct VarMapping {
|
|
||||||
TempVariableRef tempVar;
|
|
||||||
std::weak_ptr<Variable> variable;
|
|
||||||
};
|
|
||||||
|
|
||||||
class EXPORT MacroSegment : public Lockable {
|
class EXPORT MacroSegment : public Lockable {
|
||||||
public:
|
public:
|
||||||
@@ -36,15 +28,12 @@ public:
|
|||||||
int GetIndex() const { return _idx; }
|
int GetIndex() const { return _idx; }
|
||||||
void SetCollapsed(bool collapsed) { _collapsed = collapsed; }
|
void SetCollapsed(bool collapsed) { _collapsed = collapsed; }
|
||||||
bool GetCollapsed() const { return _collapsed; }
|
bool GetCollapsed() const { return _collapsed; }
|
||||||
void SetVarMappingExpanded(bool expanded);
|
|
||||||
bool GetVarMappingExpanded() const { return _varMappingExpanded; }
|
|
||||||
void SetUseCustomLabel(bool enable) { _useCustomLabel = enable; }
|
void SetUseCustomLabel(bool enable) { _useCustomLabel = enable; }
|
||||||
bool GetUseCustomLabel() const { return _useCustomLabel; }
|
bool GetUseCustomLabel() const { return _useCustomLabel; }
|
||||||
void SetCustomLabel(const std::string &label) { _customLabel = label; }
|
void SetCustomLabel(const std::string &label) { _customLabel = label; }
|
||||||
std::string GetCustomLabel() const { return _customLabel; }
|
std::string GetCustomLabel() const { return _customLabel; }
|
||||||
virtual bool Save(obs_data_t *obj) const = 0;
|
virtual bool Save(obs_data_t *obj) const = 0;
|
||||||
virtual bool Load(obs_data_t *obj) = 0;
|
virtual bool Load(obs_data_t *obj) = 0;
|
||||||
virtual std::vector<TempVariableRef> GetTempVarRefs() const;
|
|
||||||
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;
|
||||||
@@ -53,10 +42,6 @@ public:
|
|||||||
void SetEnabled(bool);
|
void SetEnabled(bool);
|
||||||
bool Enabled() const;
|
bool Enabled() const;
|
||||||
virtual std::string GetVariableValue() const;
|
virtual std::string GetVariableValue() const;
|
||||||
void ApplyVarMappings();
|
|
||||||
const std::vector<VarMapping> &GetVarMappings() const;
|
|
||||||
void SetVarMappings(const std::vector<VarMapping> &mappings);
|
|
||||||
std::vector<TempVariable> GetOwnTempVars() const;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
friend bool SupportsVariableValue(MacroSegment *);
|
friend bool SupportsVariableValue(MacroSegment *);
|
||||||
@@ -69,7 +54,6 @@ protected:
|
|||||||
void AddTempvar(const std::string &id, const std::string &name,
|
void AddTempvar(const std::string &id, const std::string &name,
|
||||||
const std::string &description = "");
|
const std::string &description = "");
|
||||||
|
|
||||||
bool IsTempVarInUse(const std::string &id) const;
|
|
||||||
void SetTempVarValue(const std::string &id, const std::string &value);
|
void SetTempVarValue(const std::string &id, const std::string &value);
|
||||||
|
|
||||||
template<typename T, typename = std::enable_if_t<
|
template<typename T, typename = std::enable_if_t<
|
||||||
@@ -80,14 +64,6 @@ protected:
|
|||||||
: std::string("false"));
|
: std::string("false"));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename F, typename = std::enable_if_t<std::is_invocable_v<F>>>
|
|
||||||
void SetTempVarValue(const std::string &id, F &&valueProvider)
|
|
||||||
{
|
|
||||||
if (IsTempVarInUse(id)) {
|
|
||||||
SetTempVarValue(id, valueProvider());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void ClearAvailableTempvars();
|
void ClearAvailableTempvars();
|
||||||
std::optional<const TempVariable>
|
std::optional<const TempVariable>
|
||||||
@@ -101,7 +77,6 @@ private:
|
|||||||
// UI helper
|
// UI helper
|
||||||
bool _highlight = false;
|
bool _highlight = false;
|
||||||
bool _collapsed = false;
|
bool _collapsed = false;
|
||||||
bool _varMappingExpanded = false;
|
|
||||||
bool _enabled = true;
|
bool _enabled = true;
|
||||||
|
|
||||||
// Custom header labels
|
// Custom header labels
|
||||||
@@ -114,7 +89,6 @@ private:
|
|||||||
int _variableRefs = 0;
|
int _variableRefs = 0;
|
||||||
std::string _variableValue;
|
std::string _variableValue;
|
||||||
std::vector<TempVariable> _tempVariables;
|
std::vector<TempVariable> _tempVariables;
|
||||||
std::vector<VarMapping> _varMappings;
|
|
||||||
|
|
||||||
friend class Macro;
|
friend class Macro;
|
||||||
};
|
};
|
||||||
@@ -134,11 +108,8 @@ public:
|
|||||||
virtual std::shared_ptr<MacroSegment> Data() const = 0;
|
virtual std::shared_ptr<MacroSegment> Data() const = 0;
|
||||||
virtual void SetupWidgets(bool basicSetup = false) = 0;
|
virtual void SetupWidgets(bool basicSetup = false) = 0;
|
||||||
|
|
||||||
void SetupVarMappings(MacroSegment *segment);
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
void ShowVariableMappings(bool show);
|
|
||||||
|
|
||||||
protected slots:
|
protected slots:
|
||||||
void Collapsed(bool) const;
|
void Collapsed(bool) const;
|
||||||
@@ -153,8 +124,6 @@ protected:
|
|||||||
QLabel *_headerInfo;
|
QLabel *_headerInfo;
|
||||||
QWidget *_frame;
|
QWidget *_frame;
|
||||||
QVBoxLayout *_contentLayout;
|
QVBoxLayout *_contentLayout;
|
||||||
TempVarOutputMappingsWidget *_outputMappings;
|
|
||||||
QPushButton *_varMappingToggle;
|
|
||||||
bool _allWidgetsAreSetup = false;
|
bool _allWidgetsAreSetup = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -15,6 +15,9 @@ MacroSelection::MacroSelection(QWidget *parent)
|
|||||||
obs_module_text("AdvSceneSwitcher.selectMacro"))
|
obs_module_text("AdvSceneSwitcher.selectMacro"))
|
||||||
{
|
{
|
||||||
for (const auto &m : GetTopLevelMacros()) {
|
for (const auto &m : GetTopLevelMacros()) {
|
||||||
|
if (m->IsGroup()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
addItem(QString::fromStdString(m->Name()));
|
addItem(QString::fromStdString(m->Name()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +54,6 @@ void MacroSelection::HideSelectedMacro()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef UNIT_TEST
|
|
||||||
const auto m = ssWindow->ui->macros->GetCurrentMacro();
|
const auto m = ssWindow->ui->macros->GetCurrentMacro();
|
||||||
if (!m) {
|
if (!m) {
|
||||||
return;
|
return;
|
||||||
@@ -62,23 +64,6 @@ void MacroSelection::HideSelectedMacro()
|
|||||||
}
|
}
|
||||||
|
|
||||||
qobject_cast<QListView *>(view())->setRowHidden(idx, true);
|
qobject_cast<QListView *>(view())->setRowHidden(idx, true);
|
||||||
#endif // !UNIT_TEST
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroSelection::HideGroups()
|
|
||||||
{
|
|
||||||
for (const auto ¯o : GetTopLevelMacros()) {
|
|
||||||
if (!macro->IsGroup()) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int idx = findText(QString::fromStdString(macro->Name()));
|
|
||||||
if (idx == -1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
qobject_cast<QListView *>(view())->setRowHidden(idx, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroSelection::ShowAllMacros()
|
void MacroSelection::ShowAllMacros()
|
||||||
|
|||||||
@@ -15,7 +15,6 @@ public:
|
|||||||
MacroSelection(QWidget *parent);
|
MacroSelection(QWidget *parent);
|
||||||
void SetCurrentMacro(const MacroRef &);
|
void SetCurrentMacro(const MacroRef &);
|
||||||
void HideSelectedMacro(); // Macro currently being edited
|
void HideSelectedMacro(); // Macro currently being edited
|
||||||
void HideGroups();
|
|
||||||
void ShowAllMacros();
|
void ShowAllMacros();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ namespace advss {
|
|||||||
|
|
||||||
static QObject *addPulse = nullptr;
|
static QObject *addPulse = nullptr;
|
||||||
static QTimer onChangeHighlightTimer;
|
static QTimer onChangeHighlightTimer;
|
||||||
static std::chrono::high_resolution_clock::time_point
|
|
||||||
lastOnChangeHighlightCheckTime{};
|
|
||||||
|
|
||||||
static void disableAddButtonHighlight()
|
static void disableAddButtonHighlight()
|
||||||
{
|
{
|
||||||
@@ -149,7 +147,20 @@ void AdvSceneSwitcher::on_macroAdd_clicked()
|
|||||||
static void addGroupSubitems(std::vector<std::shared_ptr<Macro>> ¯os,
|
static void addGroupSubitems(std::vector<std::shared_ptr<Macro>> ¯os,
|
||||||
const std::shared_ptr<Macro> &group)
|
const std::shared_ptr<Macro> &group)
|
||||||
{
|
{
|
||||||
auto subitems = GetGroupMacroEntries(group.get());
|
std::vector<std::shared_ptr<Macro>> subitems;
|
||||||
|
subitems.reserve(group->GroupSize());
|
||||||
|
|
||||||
|
// Find all subitems
|
||||||
|
auto allMacros = GetTopLevelMacros();
|
||||||
|
for (auto it = allMacros.begin(); it < allMacros.end(); it++) {
|
||||||
|
if ((*it)->Name() != group->Name()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (uint32_t i = 1; i <= group->GroupSize(); i++) {
|
||||||
|
subitems.emplace_back(*std::next(it, i));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove subitems which were already selected to avoid duplicates
|
// Remove subitems which were already selected to avoid duplicates
|
||||||
for (const auto &subitem : subitems) {
|
for (const auto &subitem : subitems) {
|
||||||
@@ -474,17 +485,14 @@ void AdvSceneSwitcher::on_runMacroInParallel_stateChanged(int value) const
|
|||||||
macro->SetRunInParallel(value);
|
macro->SetRunInParallel(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_actionTriggerMode_currentIndexChanged(int index) const
|
void AdvSceneSwitcher::on_runMacroOnChange_stateChanged(int value) const
|
||||||
{
|
{
|
||||||
auto macro = GetSelectedMacro();
|
auto macro = GetSelectedMacro();
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
const auto mode = static_cast<Macro::ActionTriggerMode>(
|
macro->SetMatchOnChange(value);
|
||||||
ui->actionTriggerMode->itemData(index).toInt());
|
|
||||||
macro->SetActionTriggerMode(mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::SetMacroEditAreaDisabled(bool disable) const
|
void AdvSceneSwitcher::SetMacroEditAreaDisabled(bool disable) const
|
||||||
@@ -492,7 +500,7 @@ void AdvSceneSwitcher::SetMacroEditAreaDisabled(bool disable) const
|
|||||||
ui->macroName->setDisabled(disable);
|
ui->macroName->setDisabled(disable);
|
||||||
ui->runMacro->setDisabled(disable);
|
ui->runMacro->setDisabled(disable);
|
||||||
ui->runMacroInParallel->setDisabled(disable);
|
ui->runMacroInParallel->setDisabled(disable);
|
||||||
ui->actionTriggerMode->setDisabled(disable);
|
ui->runMacroOnChange->setDisabled(disable);
|
||||||
ui->macroEdit->SetControlsDisabled(disable);
|
ui->macroEdit->SetControlsDisabled(disable);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -522,12 +530,10 @@ void AdvSceneSwitcher::MacroSelectionChanged()
|
|||||||
{
|
{
|
||||||
const QSignalBlocker b1(ui->macroName);
|
const QSignalBlocker b1(ui->macroName);
|
||||||
const QSignalBlocker b2(ui->runMacroInParallel);
|
const QSignalBlocker b2(ui->runMacroInParallel);
|
||||||
const QSignalBlocker b3(ui->actionTriggerMode);
|
const QSignalBlocker b3(ui->runMacroOnChange);
|
||||||
ui->macroName->setText(macro->Name().c_str());
|
ui->macroName->setText(macro->Name().c_str());
|
||||||
ui->runMacroInParallel->setChecked(macro->RunInParallel());
|
ui->runMacroInParallel->setChecked(macro->RunInParallel());
|
||||||
ui->actionTriggerMode->setCurrentIndex(
|
ui->runMacroOnChange->setChecked(macro->MatchOnChange());
|
||||||
ui->actionTriggerMode->findData(static_cast<int>(
|
|
||||||
macro->GetActionTriggerMode())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
macro->ResetUIHelpers();
|
macro->ResetUIHelpers();
|
||||||
@@ -557,14 +563,10 @@ void AdvSceneSwitcher::HighlightOnChange() const
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (macro->ActionTriggerModePreventedActionsSince(
|
if (macro->OnChangePreventedActionsRecently()) {
|
||||||
lastOnChangeHighlightCheckTime)) {
|
HighlightWidget(ui->runMacroOnChange, Qt::yellow,
|
||||||
HighlightWidget(ui->actionTriggerMode, Qt::yellow,
|
|
||||||
Qt::transparent, true);
|
Qt::transparent, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
lastOnChangeHighlightCheckTime =
|
|
||||||
std::chrono::high_resolution_clock::now();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::on_macroSettings_clicked()
|
void AdvSceneSwitcher::on_macroSettings_clicked()
|
||||||
@@ -663,56 +665,28 @@ void AdvSceneSwitcher::SetupMacroTab()
|
|||||||
ui->macroPriorityWarning->setVisible(
|
ui->macroPriorityWarning->setVisible(
|
||||||
switcher->functionNamesByPriority[0] != macro_func);
|
switcher->functionNamesByPriority[0] != macro_func);
|
||||||
|
|
||||||
lastOnChangeHighlightCheckTime =
|
|
||||||
std::chrono::high_resolution_clock::now();
|
|
||||||
onChangeHighlightTimer.setInterval(1500);
|
onChangeHighlightTimer.setInterval(1500);
|
||||||
connect(&onChangeHighlightTimer, SIGNAL(timeout()), this,
|
connect(&onChangeHighlightTimer, SIGNAL(timeout()), this,
|
||||||
SLOT(HighlightOnChange()));
|
SLOT(HighlightOnChange()));
|
||||||
onChangeHighlightTimer.start();
|
onChangeHighlightTimer.start();
|
||||||
|
|
||||||
|
// Reserve more space for macro edit area than for the macro list
|
||||||
|
ui->macroListMacroEditSplitter->setStretchFactor(0, 1);
|
||||||
|
ui->macroListMacroEditSplitter->setStretchFactor(1, 4);
|
||||||
|
|
||||||
|
if (switcher->saveWindowGeo) {
|
||||||
|
if (shouldRestoreSplitter(
|
||||||
|
switcher->macroListMacroEditSplitterPosition)) {
|
||||||
|
ui->macroListMacroEditSplitter->setSizes(
|
||||||
|
switcher->macroListMacroEditSplitterPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
SetupMacroSearchWidgets(ui->macroSearchLayout, ui->macroSearchText,
|
SetupMacroSearchWidgets(ui->macroSearchLayout, ui->macroSearchText,
|
||||||
ui->macroSearchClear, ui->macroSearchType,
|
ui->macroSearchClear, ui->macroSearchType,
|
||||||
ui->macroSearchRegex,
|
ui->macroSearchRegex,
|
||||||
ui->macroSearchShowSettings,
|
ui->macroSearchShowSettings,
|
||||||
[this]() { ui->macros->RefreshFilter(); });
|
[this]() { ui->macros->RefreshFilter(); });
|
||||||
|
|
||||||
static const std::vector<
|
|
||||||
std::pair<Macro::ActionTriggerMode, const char *>>
|
|
||||||
actionTriggerModes = {
|
|
||||||
{Macro::ActionTriggerMode::ALWAYS,
|
|
||||||
"AdvSceneSwitcher.macroTab.actionTriggerMode.always"},
|
|
||||||
{Macro::ActionTriggerMode::MACRO_RESULT_CHANGED,
|
|
||||||
"AdvSceneSwitcher.macroTab.actionTriggerMode.onOverallChange"},
|
|
||||||
{Macro::ActionTriggerMode::ANY_CONDITION_CHANGED,
|
|
||||||
"AdvSceneSwitcher.macroTab.actionTriggerMode.onAnyConditionChange"},
|
|
||||||
{Macro::ActionTriggerMode::ANY_CONDITION_TRIGGERED,
|
|
||||||
"AdvSceneSwitcher.macroTab.actionTriggerMode.onAnyConditionTriggered"},
|
|
||||||
};
|
|
||||||
|
|
||||||
for (const auto &[mode, name] : actionTriggerModes) {
|
|
||||||
ui->actionTriggerMode->addItem(obs_module_text(name),
|
|
||||||
static_cast<int>(mode));
|
|
||||||
}
|
|
||||||
|
|
||||||
ui->macroListBox->setSizePolicy(QSizePolicy::Ignored,
|
|
||||||
QSizePolicy::Preferred);
|
|
||||||
ui->macroListBox->setMinimumWidth(0);
|
|
||||||
ui->macroEditGroup->setSizePolicy(QSizePolicy::Ignored,
|
|
||||||
QSizePolicy::Preferred);
|
|
||||||
ui->macroEditGroup->setMinimumWidth(0);
|
|
||||||
|
|
||||||
if (shouldRestoreSplitter(
|
|
||||||
switcher->macroListMacroEditSplitterPosition)) {
|
|
||||||
ui->macroListMacroEditSplitter->setSizes(
|
|
||||||
switcher->macroListMacroEditSplitterPosition);
|
|
||||||
} else {
|
|
||||||
QTimer::singleShot(0, this, [this]() {
|
|
||||||
const auto totalWidth =
|
|
||||||
ui->macroListMacroEditSplitter->width();
|
|
||||||
ui->macroListMacroEditSplitter->setSizes(
|
|
||||||
{totalWidth / 5, totalWidth * 4 / 5});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::ShowMacroContextMenu(const QPoint &pos)
|
void AdvSceneSwitcher::ShowMacroContextMenu(const QPoint &pos)
|
||||||
|
|||||||
@@ -5,17 +5,18 @@
|
|||||||
#include "path-helpers.hpp"
|
#include "path-helpers.hpp"
|
||||||
#include "sync-helpers.hpp"
|
#include "sync-helpers.hpp"
|
||||||
#include "ui-helpers.hpp"
|
#include "ui-helpers.hpp"
|
||||||
|
#include "utility.hpp"
|
||||||
|
|
||||||
#include <obs.h>
|
#include <obs.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLineEdit>
|
#include <QLineEdit>
|
||||||
#include <QSpacerItem>
|
#include <QSpacerItem>
|
||||||
|
#include <QPushButton>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QStylePainter>
|
#include <QStylePainter>
|
||||||
#include <QToolTip>
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(std::shared_ptr<advss::Macro>);
|
Q_DECLARE_METATYPE(std::shared_ptr<advss::Macro>);
|
||||||
|
|
||||||
@@ -61,11 +62,12 @@ MacroTreeItem::MacroTreeItem(MacroTree *tree, std::shared_ptr<Macro> macroItem,
|
|||||||
|
|
||||||
_boxLayout = new QHBoxLayout();
|
_boxLayout = new QHBoxLayout();
|
||||||
_boxLayout->setContentsMargins(0, 0, 0, 0);
|
_boxLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
_boxLayout->addWidget(_running);
|
||||||
if (isGroup) {
|
if (isGroup) {
|
||||||
_boxLayout->addWidget(_iconLabel);
|
_boxLayout->addWidget(_iconLabel);
|
||||||
_boxLayout->addSpacing(2);
|
_boxLayout->addSpacing(2);
|
||||||
|
_running->hide();
|
||||||
}
|
}
|
||||||
_boxLayout->addWidget(_running);
|
|
||||||
_boxLayout->addWidget(_label);
|
_boxLayout->addWidget(_label);
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
/* Hack: Fixes a bug where scrollbars would be above the lock icon */
|
/* Hack: Fixes a bug where scrollbars would be above the lock icon */
|
||||||
@@ -75,138 +77,29 @@ MacroTreeItem::MacroTreeItem(MacroTree *tree, std::shared_ptr<Macro> macroItem,
|
|||||||
Update(true);
|
Update(true);
|
||||||
setLayout(_boxLayout);
|
setLayout(_boxLayout);
|
||||||
|
|
||||||
connect(_running, SIGNAL(clicked(bool)), this,
|
auto setRunning = [this](bool val) {
|
||||||
SLOT(RunningClicked(bool)));
|
_macro->SetPaused(!val);
|
||||||
|
};
|
||||||
|
connect(_running, &QAbstractButton::clicked, setRunning);
|
||||||
connect(MacroSignalManager::Instance(), SIGNAL(HighlightChanged(bool)),
|
connect(MacroSignalManager::Instance(), SIGNAL(HighlightChanged(bool)),
|
||||||
this, SLOT(EnableHighlight(bool)));
|
this, SLOT(EnableHighlight(bool)));
|
||||||
connect(MacroSignalManager::Instance(),
|
connect(MacroSignalManager::Instance(),
|
||||||
SIGNAL(Rename(const QString &, const QString &)), this,
|
SIGNAL(Rename(const QString &, const QString &)), this,
|
||||||
SLOT(MacroRenamed(const QString &, const QString &)));
|
SLOT(MacroRenamed(const QString &, const QString &)));
|
||||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(HighlightIfExecuted()));
|
connect(&_timer, SIGNAL(timeout()), this, SLOT(HighlightIfExecuted()));
|
||||||
connect(&_timer, SIGNAL(timeout()), this, SLOT(UpdateRunning()));
|
connect(&_timer, SIGNAL(timeout()), this, SLOT(UpdatePaused()));
|
||||||
|
|
||||||
UpdateRunning();
|
|
||||||
_timer.start(1500);
|
_timer.start(1500);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroTreeItem::event(QEvent *event)
|
|
||||||
{
|
|
||||||
if (event->type() != QEvent::ToolTip) {
|
|
||||||
return QFrame::event(event);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_macro->IsGroup()) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString text;
|
|
||||||
if (!_macro->WasExecutedSince({})) {
|
|
||||||
text = obs_module_text(
|
|
||||||
"AdvSceneSwitcher.macroTab.macroNotYetExecutedTooltip");
|
|
||||||
} else {
|
|
||||||
const QString formatStr = obs_module_text(
|
|
||||||
"AdvSceneSwitcher.macroTab.macroLastExecutedTooltip");
|
|
||||||
const auto secondsSinceLastRun =
|
|
||||||
std::chrono::duration_cast<std::chrono::seconds>(
|
|
||||||
std::chrono::high_resolution_clock::now() -
|
|
||||||
_macro->GetLastExecutionTime());
|
|
||||||
text = formatStr.arg(secondsSinceLastRun.count());
|
|
||||||
}
|
|
||||||
|
|
||||||
auto helpEvent = static_cast<QHelpEvent *>(event);
|
|
||||||
QToolTip::showText(helpEvent->globalPos(), text, this);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroTreeItem::EnableHighlight(bool enable)
|
void MacroTreeItem::EnableHighlight(bool enable)
|
||||||
{
|
{
|
||||||
_highlight = enable;
|
_highlight = enable;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroTreeItem::RunningClicked(bool running)
|
void MacroTreeItem::UpdatePaused()
|
||||||
{
|
|
||||||
const auto updateWidget = [this](Macro *macro) {
|
|
||||||
if (!macro) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto ¯os = GetTopLevelMacros();
|
|
||||||
|
|
||||||
bool found = false;
|
|
||||||
int idx = 0;
|
|
||||||
for (const auto &m : macros) {
|
|
||||||
if (m.get() == macro) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
idx++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!found) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto widget = _tree->GetItemWidget(idx);
|
|
||||||
if (widget) {
|
|
||||||
widget->UpdateRunning();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!_macro->IsGroup()) {
|
|
||||||
_macro->SetPaused(!running);
|
|
||||||
if (!_macro->IsSubitem()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto group = _macro->Parent();
|
|
||||||
updateWidget(group.get());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto macros = GetGroupMacroEntries(_macro.get());
|
|
||||||
for (const auto ¯o : macros) {
|
|
||||||
macro->SetPaused(!running);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update backend values before updating UI to prevent flickering in
|
|
||||||
// running state of the group
|
|
||||||
for (const auto ¯o : macros) {
|
|
||||||
updateWidget(macro.get());
|
|
||||||
}
|
|
||||||
UpdateRunning();
|
|
||||||
}
|
|
||||||
|
|
||||||
void MacroTreeItem::UpdateRunning()
|
|
||||||
{
|
{
|
||||||
const QSignalBlocker blocker(_running);
|
const QSignalBlocker blocker(_running);
|
||||||
|
_running->setChecked(!_macro->Paused());
|
||||||
if (!_macro->IsGroup()) {
|
|
||||||
_running->setChecked(!_macro->Paused());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto macros = GetGroupMacroEntries(_macro.get());
|
|
||||||
bool allRunning = true;
|
|
||||||
bool allPaused = true;
|
|
||||||
for (const auto ¯o : macros) {
|
|
||||||
if (macro->Paused()) {
|
|
||||||
allRunning = false;
|
|
||||||
} else {
|
|
||||||
allPaused = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allRunning) {
|
|
||||||
_running->setCheckState(Qt::Checked);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (allPaused) {
|
|
||||||
_running->setCheckState(Qt::Unchecked);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_running->setCheckState(Qt::PartiallyChecked);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroTreeItem::HighlightIfExecuted()
|
void MacroTreeItem::HighlightIfExecuted()
|
||||||
@@ -215,20 +108,10 @@ void MacroTreeItem::HighlightIfExecuted()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool wasHighlighted = false;
|
|
||||||
if (_lastHighlightCheckTime.time_since_epoch().count() != 0 &&
|
if (_lastHighlightCheckTime.time_since_epoch().count() != 0 &&
|
||||||
_macro->WasExecutedSince(_lastHighlightCheckTime)) {
|
_macro->WasExecutedSince(_lastHighlightCheckTime)) {
|
||||||
HighlightWidget(this, Qt::green, QColor(0, 0, 0, 0), true);
|
HighlightWidget(this, Qt::green, QColor(0, 0, 0, 0), true);
|
||||||
wasHighlighted = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!wasHighlighted &&
|
|
||||||
_lastHighlightCheckTime.time_since_epoch().count() != 0 &&
|
|
||||||
_macro->ActionTriggerModePreventedActionsSince(
|
|
||||||
_lastHighlightCheckTime)) {
|
|
||||||
HighlightWidget(this, Qt::yellow, QColor(0, 0, 0, 0), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
_lastHighlightCheckTime = std::chrono::high_resolution_clock::now();
|
_lastHighlightCheckTime = std::chrono::high_resolution_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -305,7 +188,7 @@ void MacroTreeItem::Update(bool force)
|
|||||||
_expand->blockSignals(true);
|
_expand->blockSignals(true);
|
||||||
_expand->setChecked(_macro->IsCollapsed());
|
_expand->setChecked(_macro->IsCollapsed());
|
||||||
_expand->blockSignals(false);
|
_expand->blockSignals(false);
|
||||||
connect(_expand, &QCheckBox::toggled, this,
|
connect(_expand, &QPushButton::toggled, this,
|
||||||
&MacroTreeItem::ExpandClicked);
|
&MacroTreeItem::ExpandClicked);
|
||||||
} else {
|
} else {
|
||||||
_spacer = new QSpacerItem(3, 1);
|
_spacer = new QSpacerItem(3, 1);
|
||||||
@@ -331,6 +214,7 @@ void MacroTreeModel::Reset(std::deque<std::shared_ptr<Macro>> &newItems)
|
|||||||
_macros = newItems;
|
_macros = newItems;
|
||||||
endResetModel();
|
endResetModel();
|
||||||
|
|
||||||
|
UpdateGroupState(false);
|
||||||
_mt->ResetWidgets();
|
_mt->ResetWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -575,6 +459,9 @@ void MacroTreeModel::Remove(std::shared_ptr<Macro> item)
|
|||||||
|
|
||||||
_mt->selectionModel()->clear();
|
_mt->selectionModel()->clear();
|
||||||
|
|
||||||
|
if (isGroup) {
|
||||||
|
UpdateGroupState(true);
|
||||||
|
}
|
||||||
assert(IsInValidState());
|
assert(IsInValidState());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -663,6 +550,7 @@ MacroTreeModel::MacroTreeModel(MacroTree *st_,
|
|||||||
_mt(st_),
|
_mt(st_),
|
||||||
_macros(macros)
|
_macros(macros)
|
||||||
{
|
{
|
||||||
|
UpdateGroupState(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
int MacroTreeModel::rowCount(const QModelIndex &parent) const
|
int MacroTreeModel::rowCount(const QModelIndex &parent) const
|
||||||
@@ -816,6 +704,7 @@ void MacroTreeModel::GroupSelectedItems(QModelIndexList &indices)
|
|||||||
offset++;
|
offset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_hasGroups = true;
|
||||||
_mt->selectionModel()->clear();
|
_mt->selectionModel()->clear();
|
||||||
|
|
||||||
Reset(_macros);
|
Reset(_macros);
|
||||||
@@ -873,6 +762,24 @@ void MacroTreeModel::CollapseGroup(std::shared_ptr<Macro> item)
|
|||||||
assert(IsInValidState());
|
assert(IsInValidState());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroTreeModel::UpdateGroupState(bool update)
|
||||||
|
{
|
||||||
|
bool nowHasGroups = false;
|
||||||
|
for (auto &item : _macros) {
|
||||||
|
if (item->IsGroup()) {
|
||||||
|
nowHasGroups = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nowHasGroups != _hasGroups) {
|
||||||
|
_hasGroups = nowHasGroups;
|
||||||
|
if (update) {
|
||||||
|
_mt->UpdateWidgets(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MacroTree::Reset(std::deque<std::shared_ptr<Macro>> ¯os,
|
void MacroTree::Reset(std::deque<std::shared_ptr<Macro>> ¯os,
|
||||||
bool highlight)
|
bool highlight)
|
||||||
{
|
{
|
||||||
@@ -935,6 +842,7 @@ MacroTree::MacroTree(QWidget *parent_) : QListView(parent_)
|
|||||||
void MacroTree::ResetWidgets()
|
void MacroTree::ResetWidgets()
|
||||||
{
|
{
|
||||||
MacroTreeModel *mtm = GetModel();
|
MacroTreeModel *mtm = GetModel();
|
||||||
|
mtm->UpdateGroupState(false);
|
||||||
int modelIdx = 0;
|
int modelIdx = 0;
|
||||||
for (int i = 0; i < (int)mtm->_macros.size(); i++) {
|
for (int i = 0; i < (int)mtm->_macros.size(); i++) {
|
||||||
QModelIndex index = mtm->createIndex(modelIdx, 0, nullptr);
|
QModelIndex index = mtm->createIndex(modelIdx, 0, nullptr);
|
||||||
|
|||||||
@@ -34,14 +34,10 @@ public:
|
|||||||
explicit MacroTreeItem(MacroTree *tree, std::shared_ptr<Macro> macro,
|
explicit MacroTreeItem(MacroTree *tree, std::shared_ptr<Macro> macro,
|
||||||
bool highlight);
|
bool highlight);
|
||||||
|
|
||||||
protected:
|
|
||||||
bool event(QEvent *) override;
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void ExpandClicked(bool checked);
|
void ExpandClicked(bool checked);
|
||||||
void EnableHighlight(bool enable);
|
void EnableHighlight(bool enable);
|
||||||
void RunningClicked(bool);
|
void UpdatePaused();
|
||||||
void UpdateRunning();
|
|
||||||
void HighlightIfExecuted();
|
void HighlightIfExecuted();
|
||||||
void MacroRenamed(const QString &, const QString &);
|
void MacroRenamed(const QString &, const QString &);
|
||||||
|
|
||||||
@@ -110,6 +106,7 @@ private:
|
|||||||
void UngroupSelectedGroups(QModelIndexList &indices);
|
void UngroupSelectedGroups(QModelIndexList &indices);
|
||||||
void ExpandGroup(std::shared_ptr<Macro> item);
|
void ExpandGroup(std::shared_ptr<Macro> item);
|
||||||
void CollapseGroup(std::shared_ptr<Macro> item);
|
void CollapseGroup(std::shared_ptr<Macro> item);
|
||||||
|
void UpdateGroupState(bool update);
|
||||||
int GetItemMacroIndex(const std::shared_ptr<Macro> &item) const;
|
int GetItemMacroIndex(const std::shared_ptr<Macro> &item) const;
|
||||||
int GetItemModelIndex(const std::shared_ptr<Macro> &item) const;
|
int GetItemModelIndex(const std::shared_ptr<Macro> &item) const;
|
||||||
bool IsLastItem(std::shared_ptr<Macro> item) const;
|
bool IsLastItem(std::shared_ptr<Macro> item) const;
|
||||||
@@ -117,6 +114,7 @@ private:
|
|||||||
|
|
||||||
MacroTree *_mt;
|
MacroTree *_mt;
|
||||||
std::deque<std::shared_ptr<Macro>> &_macros;
|
std::deque<std::shared_ptr<Macro>> &_macros;
|
||||||
|
bool _hasGroups = false;
|
||||||
|
|
||||||
friend class MacroTree;
|
friend class MacroTree;
|
||||||
friend class MacroTreeItem;
|
friend class MacroTreeItem;
|
||||||
|
|||||||
@@ -1,111 +0,0 @@
|
|||||||
#include "websocket-api.hpp"
|
|
||||||
#include "log-helper.hpp"
|
|
||||||
#include "plugin-state-helpers.hpp"
|
|
||||||
#include "variable.hpp"
|
|
||||||
#include "macro-helpers.hpp"
|
|
||||||
|
|
||||||
#include <obs.hpp>
|
|
||||||
|
|
||||||
namespace advss {
|
|
||||||
|
|
||||||
static bool setup();
|
|
||||||
static bool setupDone = setup();
|
|
||||||
static void receiveRunMacroMessage(obs_data_t *data, obs_data_t *);
|
|
||||||
static void receiveSetVariablesMessage(obs_data_t *data, obs_data_t *);
|
|
||||||
|
|
||||||
static const char *runMacroMessage = "AdvancedSceneSwitcherRunMacro";
|
|
||||||
static const char *setVariablesMessage = "AdvancedSceneSwitcherSetVariables";
|
|
||||||
|
|
||||||
static bool setup()
|
|
||||||
{
|
|
||||||
AddPluginInitStep([]() {
|
|
||||||
RegisterWebsocketRequest(runMacroMessage,
|
|
||||||
receiveRunMacroMessage);
|
|
||||||
RegisterWebsocketRequest(setVariablesMessage,
|
|
||||||
receiveSetVariablesMessage);
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setVariables(obs_data_t *data)
|
|
||||||
{
|
|
||||||
OBSDataArrayAutoRelease variables =
|
|
||||||
obs_data_get_array(data, "variables");
|
|
||||||
size_t count = obs_data_array_count(variables);
|
|
||||||
for (size_t i = 0; i < count; i++) {
|
|
||||||
OBSDataAutoRelease item = obs_data_array_item(variables, i);
|
|
||||||
if (!obs_data_has_user_value(item, "name")) {
|
|
||||||
blog(LOG_INFO,
|
|
||||||
"ignoring invalid variable entry in \"%s\" websocket message (missing \"name\")",
|
|
||||||
runMacroMessage);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!obs_data_has_user_value(item, "value")) {
|
|
||||||
blog(LOG_INFO,
|
|
||||||
"ignoring invalid variable entry in \"%s\" websocket message (missing \"value\")",
|
|
||||||
runMacroMessage);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto varName = obs_data_get_string(item, "name");
|
|
||||||
auto value = obs_data_get_string(item, "value");
|
|
||||||
|
|
||||||
auto weakVar = GetWeakVariableByName(varName);
|
|
||||||
auto var = weakVar.lock();
|
|
||||||
if (!var) {
|
|
||||||
blog(LOG_INFO,
|
|
||||||
"ignoring invalid variable name \"%s\" in \"%s\" websocket message",
|
|
||||||
varName, runMacroMessage);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var->SetValue(value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void receiveRunMacroMessage(obs_data_t *data, obs_data_t *)
|
|
||||||
{
|
|
||||||
if (!obs_data_has_user_value(data, "name")) {
|
|
||||||
blog(LOG_INFO,
|
|
||||||
"ignoring invalid \"%s\" websocket message (missing \"name\")",
|
|
||||||
runMacroMessage);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto name = obs_data_get_string(data, "name");
|
|
||||||
const auto weakMacro =
|
|
||||||
GetWeakMacroByName(obs_data_get_string(data, "name"));
|
|
||||||
const auto macro = weakMacro.lock();
|
|
||||||
if (!macro) {
|
|
||||||
blog(LOG_INFO,
|
|
||||||
"ignoring invalid \"%s\" websocket message (macro \"%s\") not found",
|
|
||||||
runMacroMessage, name);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (obs_data_has_user_value(data, "variables")) {
|
|
||||||
setVariables(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool runElse = obs_data_get_bool(data, "runElseActions");
|
|
||||||
if (runElse) {
|
|
||||||
RunMacroElseActions(macro.get());
|
|
||||||
} else {
|
|
||||||
RunMacroActions(macro.get());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void receiveSetVariablesMessage(obs_data_t *data, obs_data_t *)
|
|
||||||
{
|
|
||||||
if (!obs_data_has_user_value(data, "variables")) {
|
|
||||||
blog(LOG_INFO,
|
|
||||||
"ignoring invalid \"%s\" websocket message (missing \"variables\")",
|
|
||||||
setVariablesMessage);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setVariables(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace advss
|
|
||||||
@@ -111,9 +111,8 @@ static bool checkCondition(const std::shared_ptr<MacroCondition> &condition)
|
|||||||
const auto startTime = std::chrono::high_resolution_clock::now();
|
const auto startTime = std::chrono::high_resolution_clock::now();
|
||||||
bool conditionMatched = false;
|
bool conditionMatched = false;
|
||||||
condition->WithLock([&condition, &conditionMatched]() {
|
condition->WithLock([&condition, &conditionMatched]() {
|
||||||
conditionMatched = condition->EvaluateCondition();
|
conditionMatched = condition->CheckCondition();
|
||||||
});
|
});
|
||||||
condition->ApplyVarMappings();
|
|
||||||
const auto endTime = std::chrono::high_resolution_clock::now();
|
const auto endTime = std::chrono::high_resolution_clock::now();
|
||||||
const auto timeSpent = endTime - startTime;
|
const auto timeSpent = endTime - startTime;
|
||||||
|
|
||||||
@@ -242,37 +241,9 @@ bool Macro::CheckConditions(bool ignorePause)
|
|||||||
|
|
||||||
vblog(LOG_INFO, "Macro %s returned %d", _name.c_str(), _matched);
|
vblog(LOG_INFO, "Macro %s returned %d", _name.c_str(), _matched);
|
||||||
|
|
||||||
_actionModeMatch = false;
|
_conditionSateChanged = _lastMatched != _matched;
|
||||||
switch (_actionTriggerMode) {
|
if (!_conditionSateChanged && _performActionsOnChange) {
|
||||||
case Macro::ActionTriggerMode::ALWAYS:
|
_onPreventedActionExecution = true;
|
||||||
_actionModeMatch = true;
|
|
||||||
break;
|
|
||||||
case Macro::ActionTriggerMode::MACRO_RESULT_CHANGED:
|
|
||||||
_actionModeMatch = _lastMatched != _matched;
|
|
||||||
break;
|
|
||||||
case Macro::ActionTriggerMode::ANY_CONDITION_CHANGED:
|
|
||||||
for (const auto &condition : _conditions) {
|
|
||||||
if (condition->HasChanged()) {
|
|
||||||
_actionModeMatch = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case Macro::ActionTriggerMode::ANY_CONDITION_TRIGGERED:
|
|
||||||
for (const auto &condition : _conditions) {
|
|
||||||
if (condition->IsRisingEdge()) {
|
|
||||||
_actionModeMatch = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const bool hasActionsToExecute = _matched ? (_actions.size() > 0)
|
|
||||||
: (_elseActions.size() > 0);
|
|
||||||
if (!_actionModeMatch && hasActionsToExecute) {
|
|
||||||
_lastActionRunModePreventTime =
|
|
||||||
std::chrono::high_resolution_clock::now();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastMatched = _matched;
|
_lastMatched = _matched;
|
||||||
@@ -331,16 +302,6 @@ bool Macro::WasExecutedSince(const TimePoint &time) const
|
|||||||
return _lastExecutionTime > time;
|
return _lastExecutionTime > time;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Macro::ActionTriggerModePreventedActionsSince(const TimePoint &time) const
|
|
||||||
{
|
|
||||||
return _lastActionRunModePreventTime > time;
|
|
||||||
}
|
|
||||||
|
|
||||||
Macro::TimePoint Macro::GetLastExecutionTime() const
|
|
||||||
{
|
|
||||||
return _lastExecutionTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Macro::ConditionsShouldBeChecked() const
|
bool Macro::ConditionsShouldBeChecked() const
|
||||||
{
|
{
|
||||||
if (!_useCustomConditionCheckInterval) {
|
if (!_useCustomConditionCheckInterval) {
|
||||||
@@ -367,9 +328,10 @@ bool Macro::ShouldRunActions() const
|
|||||||
|
|
||||||
const bool hasActionsToExecute =
|
const bool hasActionsToExecute =
|
||||||
!_paused && (_matched || _elseActions.size() > 0) &&
|
!_paused && (_matched || _elseActions.size() > 0) &&
|
||||||
_actionModeMatch;
|
(!_performActionsOnChange || _conditionSateChanged);
|
||||||
|
|
||||||
if (VerboseLoggingEnabled() && !_actionModeMatch) {
|
if (VerboseLoggingEnabled() && _performActionsOnChange &&
|
||||||
|
!_conditionSateChanged) {
|
||||||
if (_matched && _actions.size() > 0) {
|
if (_matched && _actions.size() > 0) {
|
||||||
blog(LOG_INFO, "skip actions for Macro %s (on change)",
|
blog(LOG_INFO, "skip actions for Macro %s (on change)",
|
||||||
_name.c_str());
|
_name.c_str());
|
||||||
@@ -400,24 +362,10 @@ void Macro::ResetTimers()
|
|||||||
_lastExecutionTime = {};
|
_lastExecutionTime = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void Macro::SetActionTriggerMode(ActionTriggerMode mode)
|
|
||||||
{
|
|
||||||
_actionTriggerMode = mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
Macro::ActionTriggerMode Macro::GetActionTriggerMode() const
|
|
||||||
{
|
|
||||||
return _actionTriggerMode;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Macro::RunActionsHelper(
|
bool Macro::RunActionsHelper(
|
||||||
const std::deque<std::shared_ptr<MacroAction>> &actionsToRun,
|
const std::deque<std::shared_ptr<MacroAction>> &actionsToRun,
|
||||||
bool ignorePause)
|
bool ignorePause)
|
||||||
{
|
{
|
||||||
if (_paused && !ignorePause) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create copy of action list as elements might be removed, inserted, or
|
// Create copy of action list as elements might be removed, inserted, or
|
||||||
// reordered while actions are currently being executed.
|
// reordered while actions are currently being executed.
|
||||||
auto actions = actionsToRun;
|
auto actions = actionsToRun;
|
||||||
@@ -433,7 +381,6 @@ bool Macro::RunActionsHelper(
|
|||||||
action->WithLock([&action, &actionResult]() {
|
action->WithLock([&action, &actionResult]() {
|
||||||
actionResult = action->PerformAction();
|
actionResult = action->PerformAction();
|
||||||
});
|
});
|
||||||
action->ApplyVarMappings();
|
|
||||||
actionsExecutedSuccessfully =
|
actionsExecutedSuccessfully =
|
||||||
actionsExecutedSuccessfully && actionResult;
|
actionsExecutedSuccessfully && actionResult;
|
||||||
} else {
|
} else {
|
||||||
@@ -468,6 +415,11 @@ bool Macro::WasPausedSince(const TimePoint &time) const
|
|||||||
return _lastUnpauseTime > time;
|
return _lastUnpauseTime > time;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Macro::SetMatchOnChange(bool onChange)
|
||||||
|
{
|
||||||
|
_performActionsOnChange = onChange;
|
||||||
|
}
|
||||||
|
|
||||||
void Macro::SetStopActionsIfNotDone(bool stopActionsIfNotDone)
|
void Macro::SetStopActionsIfNotDone(bool stopActionsIfNotDone)
|
||||||
{
|
{
|
||||||
_stopActionsIfNotDone = stopActionsIfNotDone;
|
_stopActionsIfNotDone = stopActionsIfNotDone;
|
||||||
@@ -788,8 +740,7 @@ bool Macro::Save(obs_data_t *obj, bool saveForCopy) const
|
|||||||
obs_data_set_bool(obj, "pause", _paused);
|
obs_data_set_bool(obj, "pause", _paused);
|
||||||
obs_data_set_bool(obj, "parallel", _runInParallel);
|
obs_data_set_bool(obj, "parallel", _runInParallel);
|
||||||
obs_data_set_bool(obj, "checkConditionsInParallel", _checkInParallel);
|
obs_data_set_bool(obj, "checkConditionsInParallel", _checkInParallel);
|
||||||
obs_data_set_int(obj, "actionTriggerMode",
|
obs_data_set_bool(obj, "onChange", _performActionsOnChange);
|
||||||
static_cast<int>(_actionTriggerMode));
|
|
||||||
obs_data_set_bool(obj, "skipExecOnStart", _skipExecOnStart);
|
obs_data_set_bool(obj, "skipExecOnStart", _skipExecOnStart);
|
||||||
obs_data_set_bool(obj, "stopActionsIfNotDone", _stopActionsIfNotDone);
|
obs_data_set_bool(obj, "stopActionsIfNotDone", _stopActionsIfNotDone);
|
||||||
obs_data_set_bool(obj, "useShortCircuitEvaluation",
|
obs_data_set_bool(obj, "useShortCircuitEvaluation",
|
||||||
@@ -875,15 +826,7 @@ bool Macro::Load(obs_data_t *obj)
|
|||||||
}
|
}
|
||||||
_runInParallel = obs_data_get_bool(obj, "parallel");
|
_runInParallel = obs_data_get_bool(obj, "parallel");
|
||||||
_checkInParallel = obs_data_get_bool(obj, "checkConditionsInParallel");
|
_checkInParallel = obs_data_get_bool(obj, "checkConditionsInParallel");
|
||||||
if (obs_data_has_user_value(obj, "onChange")) {
|
_performActionsOnChange = obs_data_get_bool(obj, "onChange");
|
||||||
const bool onChange = obs_data_get_bool(obj, "onChange");
|
|
||||||
_actionTriggerMode =
|
|
||||||
onChange ? ActionTriggerMode::MACRO_RESULT_CHANGED
|
|
||||||
: ActionTriggerMode::ALWAYS;
|
|
||||||
} else {
|
|
||||||
_actionTriggerMode = static_cast<ActionTriggerMode>(
|
|
||||||
obs_data_get_int(obj, "actionTriggerMode"));
|
|
||||||
}
|
|
||||||
_skipExecOnStart = obs_data_get_bool(obj, "skipExecOnStart");
|
_skipExecOnStart = obs_data_get_bool(obj, "skipExecOnStart");
|
||||||
_stopActionsIfNotDone = obs_data_get_bool(obj, "stopActionsIfNotDone");
|
_stopActionsIfNotDone = obs_data_get_bool(obj, "stopActionsIfNotDone");
|
||||||
_useShortCircuitEvaluation =
|
_useShortCircuitEvaluation =
|
||||||
@@ -1005,12 +948,12 @@ bool Macro::PostLoad()
|
|||||||
bool Macro::SwitchesScene() const
|
bool Macro::SwitchesScene() const
|
||||||
{
|
{
|
||||||
for (const auto &a : _actions) {
|
for (const auto &a : _actions) {
|
||||||
if (a->GetId() == MacroAction::GetDefaultID()) {
|
if (a->GetId() == GetSceneSwitchActionId()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (const auto &a : _elseActions) {
|
for (const auto &a : _elseActions) {
|
||||||
if (a->GetId() == MacroAction::GetDefaultID()) {
|
if (a->GetId() == GetSceneSwitchActionId()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1043,8 +986,18 @@ bool Macro::HasValidSplitterPositions() const
|
|||||||
!_elseActionSplitterPosition.empty();
|
!_elseActionSplitterPosition.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Macro::OnChangePreventedActionsRecently()
|
||||||
|
{
|
||||||
|
if (_onPreventedActionExecution) {
|
||||||
|
_onPreventedActionExecution = false;
|
||||||
|
return _matched ? _actions.size() > 0 : _elseActions.size() > 0;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void Macro::ResetUIHelpers()
|
void Macro::ResetUIHelpers()
|
||||||
{
|
{
|
||||||
|
_onPreventedActionExecution = false;
|
||||||
for (auto c : _conditions) {
|
for (auto c : _conditions) {
|
||||||
c->GetHighlightAndReset();
|
c->GetHighlightAndReset();
|
||||||
}
|
}
|
||||||
@@ -1143,11 +1096,9 @@ void Macro::ClearHotkeys() const
|
|||||||
void setHotkeyDescriptionHelper(const char *formatModuleText,
|
void setHotkeyDescriptionHelper(const char *formatModuleText,
|
||||||
const std::string name, const obs_hotkey_id id)
|
const std::string name, const obs_hotkey_id id)
|
||||||
{
|
{
|
||||||
#ifndef UNIT_TEST
|
|
||||||
QString format{obs_module_text(formatModuleText)};
|
QString format{obs_module_text(formatModuleText)};
|
||||||
QString hotkeyDesc = format.arg(QString::fromStdString(name));
|
QString hotkeyDesc = format.arg(QString::fromStdString(name));
|
||||||
obs_hotkey_set_description(id, hotkeyDesc.toStdString().c_str());
|
obs_hotkey_set_description(id, hotkeyDesc.toStdString().c_str());
|
||||||
#endif // !UNIT_TEST
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Macro::SetHotkeysDesc() const
|
void Macro::SetHotkeysDesc() const
|
||||||
|
|||||||
@@ -26,16 +26,6 @@ class Macro {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
enum class PauseStateSaveBehavior { PERSIST, PAUSE, UNPAUSE };
|
enum class PauseStateSaveBehavior { PERSIST, PAUSE, UNPAUSE };
|
||||||
enum class ActionTriggerMode {
|
|
||||||
// Trigger always
|
|
||||||
ALWAYS,
|
|
||||||
// Trigger when macro match result flips
|
|
||||||
MACRO_RESULT_CHANGED,
|
|
||||||
// Trigger when any individual condition changes
|
|
||||||
ANY_CONDITION_CHANGED,
|
|
||||||
// Trigger when any individual condition evaluates to true
|
|
||||||
ANY_CONDITION_TRIGGERED,
|
|
||||||
};
|
|
||||||
|
|
||||||
Macro(const std::string &name = "");
|
Macro(const std::string &name = "");
|
||||||
Macro(const std::string &name, const GlobalMacroSettings &settings);
|
Macro(const std::string &name, const GlobalMacroSettings &settings);
|
||||||
@@ -64,8 +54,8 @@ public:
|
|||||||
bool GetStop() const { return _stop; }
|
bool GetStop() const { return _stop; }
|
||||||
void ResetTimers();
|
void ResetTimers();
|
||||||
|
|
||||||
void SetActionTriggerMode(ActionTriggerMode);
|
void SetMatchOnChange(bool onChange);
|
||||||
ActionTriggerMode GetActionTriggerMode() const;
|
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; }
|
||||||
@@ -147,8 +137,7 @@ public:
|
|||||||
const QList<int> &GetElseActionSplitterPosition() const;
|
const QList<int> &GetElseActionSplitterPosition() const;
|
||||||
bool HasValidSplitterPositions() const;
|
bool HasValidSplitterPositions() const;
|
||||||
bool WasExecutedSince(const TimePoint &) const;
|
bool WasExecutedSince(const TimePoint &) const;
|
||||||
bool ActionTriggerModePreventedActionsSince(const TimePoint &) const;
|
bool OnChangePreventedActionsRecently();
|
||||||
TimePoint GetLastExecutionTime() const;
|
|
||||||
void ResetUIHelpers();
|
void ResetUIHelpers();
|
||||||
|
|
||||||
// Hotkeys
|
// Hotkeys
|
||||||
@@ -179,7 +168,6 @@ private:
|
|||||||
TimePoint _lastCheckTime{};
|
TimePoint _lastCheckTime{};
|
||||||
TimePoint _lastUnpauseTime{};
|
TimePoint _lastUnpauseTime{};
|
||||||
TimePoint _lastExecutionTime{};
|
TimePoint _lastExecutionTime{};
|
||||||
TimePoint _lastActionRunModePreventTime{};
|
|
||||||
std::vector<std::thread> _helperThreads;
|
std::vector<std::thread> _helperThreads;
|
||||||
|
|
||||||
std::deque<std::shared_ptr<MacroCondition>> _conditions;
|
std::deque<std::shared_ptr<MacroCondition>> _conditions;
|
||||||
@@ -194,13 +182,14 @@ private:
|
|||||||
bool _useShortCircuitEvaluation = false;
|
bool _useShortCircuitEvaluation = false;
|
||||||
bool _useCustomConditionCheckInterval = false;
|
bool _useCustomConditionCheckInterval = false;
|
||||||
Duration _customConditionCheckInterval = 0.3;
|
Duration _customConditionCheckInterval = 0.3;
|
||||||
bool _actionModeMatch = false;
|
bool _conditionSateChanged = false;
|
||||||
|
|
||||||
bool _runInParallel = false;
|
bool _runInParallel = false;
|
||||||
bool _checkInParallel = false;
|
bool _checkInParallel = false;
|
||||||
bool _matched = false;
|
bool _matched = false;
|
||||||
std::future<void> _conditionCheckFuture;
|
std::future<void> _conditionCheckFuture;
|
||||||
bool _lastMatched = false;
|
bool _lastMatched = false;
|
||||||
|
bool _performActionsOnChange = true;
|
||||||
bool _skipExecOnStart = false;
|
bool _skipExecOnStart = false;
|
||||||
bool _stopActionsIfNotDone = false;
|
bool _stopActionsIfNotDone = false;
|
||||||
bool _paused = false;
|
bool _paused = false;
|
||||||
@@ -210,14 +199,14 @@ 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;
|
||||||
|
|
||||||
ActionTriggerMode _actionTriggerMode =
|
|
||||||
ActionTriggerMode::MACRO_RESULT_CHANGED;
|
|
||||||
|
|
||||||
PauseStateSaveBehavior _pauseSaveBehavior =
|
PauseStateSaveBehavior _pauseSaveBehavior =
|
||||||
PauseStateSaveBehavior::PERSIST;
|
PauseStateSaveBehavior::PERSIST;
|
||||||
|
|
||||||
MacroInputVariables _inputVariables;
|
MacroInputVariables _inputVariables;
|
||||||
|
|
||||||
|
// UI helpers
|
||||||
|
bool _onPreventedActionExecution = false;
|
||||||
|
|
||||||
QList<int> _actionConditionSplitterPosition;
|
QList<int> _actionConditionSplitterPosition;
|
||||||
QList<int> _elseActionSplitterPosition;
|
QList<int> _elseActionSplitterPosition;
|
||||||
|
|
||||||
|
|||||||
@@ -14,9 +14,10 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
std::vector<std::string> GetWindowList()
|
void GetWindowList(std::vector<std::string> &windows)
|
||||||
{
|
{
|
||||||
std::vector<std::string> windows;
|
windows.resize(0);
|
||||||
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
CFArrayRef cfApps = CGWindowListCopyWindowInfo(
|
CFArrayRef cfApps = CGWindowListCopyWindowInfo(
|
||||||
kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
|
kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
|
||||||
@@ -48,12 +49,21 @@ std::vector<std::string> GetWindowList()
|
|||||||
apps = nil;
|
apps = nil;
|
||||||
CFRelease(cfApps);
|
CFRelease(cfApps);
|
||||||
}
|
}
|
||||||
return windows;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetCurrentWindowTitle()
|
void GetWindowList(QStringList &windows)
|
||||||
{
|
{
|
||||||
std::string title;
|
windows.clear();
|
||||||
|
std::vector<std::string> temp;
|
||||||
|
GetWindowList(temp);
|
||||||
|
for (auto &w : temp) {
|
||||||
|
windows << QString::fromStdString(w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetCurrentWindowTitle(std::string &title)
|
||||||
|
{
|
||||||
|
title.resize(0);
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
CFArrayRef cfApps = CGWindowListCopyWindowInfo(
|
CFArrayRef cfApps = CGWindowListCopyWindowInfo(
|
||||||
kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
|
kCGWindowListOptionOnScreenOnly, kCGNullWindowID);
|
||||||
@@ -97,7 +107,6 @@ std::string GetCurrentWindowTitle()
|
|||||||
apps = nil;
|
apps = nil;
|
||||||
CFRelease(cfApps);
|
CFRelease(cfApps);
|
||||||
}
|
}
|
||||||
return title;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isWindowOriginOnScreen(NSDictionary *app, NSScreen *screen,
|
bool isWindowOriginOnScreen(NSDictionary *app, NSScreen *screen,
|
||||||
@@ -264,9 +273,9 @@ int SecondsSinceLastInput()
|
|||||||
return (int)time;
|
return (int)time;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList GetProcessList()
|
void GetProcessList(QStringList &list)
|
||||||
{
|
{
|
||||||
QStringList list;
|
list.clear();
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
|
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
|
||||||
NSArray *array = [ws runningApplications];
|
NSArray *array = [ws runningApplications];
|
||||||
@@ -282,11 +291,11 @@ QStringList GetProcessList()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetForegroundProcessName()
|
void GetForegroundProcessName(std::string &proc)
|
||||||
{
|
{
|
||||||
|
proc.resize(0);
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
|
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
|
||||||
NSArray *array = [ws runningApplications];
|
NSArray *array = [ws runningApplications];
|
||||||
@@ -299,73 +308,23 @@ std::string GetForegroundProcessName()
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const char *str = name.UTF8String;
|
const char *str = name.UTF8String;
|
||||||
if (str) {
|
proc = std::string(str);
|
||||||
return str;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetForegroundProcessPath()
|
void GetForegroundProcessName(QString &proc)
|
||||||
{
|
{
|
||||||
@autoreleasepool {
|
std::string temp;
|
||||||
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
|
GetForegroundProcessName(temp);
|
||||||
for (NSRunningApplication *app in [ws runningApplications]) {
|
proc = QString::fromStdString(temp);
|
||||||
if (!app.isActive) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
NSURL *url = app.executableURL;
|
|
||||||
if (!url) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
const char *str = url.path.UTF8String;
|
|
||||||
if (str) {
|
|
||||||
return str;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList GetProcessPathsFromName(const QString &name)
|
|
||||||
{
|
|
||||||
QStringList paths;
|
|
||||||
@autoreleasepool {
|
|
||||||
NSWorkspace *ws = [NSWorkspace sharedWorkspace];
|
|
||||||
for (NSRunningApplication *app in [ws runningApplications]) {
|
|
||||||
NSString *appName = app.localizedName;
|
|
||||||
if (!appName) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const char *nameStr = appName.UTF8String;
|
|
||||||
if (!nameStr ||
|
|
||||||
name != QString::fromUtf8(nameStr)) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
NSURL *url = app.executableURL;
|
|
||||||
if (!url) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
const char *pathStr = url.path.UTF8String;
|
|
||||||
if (!pathStr) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
QString path = QString::fromUtf8(pathStr);
|
|
||||||
if (!paths.contains(path)) {
|
|
||||||
paths.append(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return paths;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsInFocus(const QString &executable)
|
bool IsInFocus(const QString &executable)
|
||||||
{
|
{
|
||||||
const auto current = GetForegroundProcessName();
|
std::string current;
|
||||||
|
GetForegroundProcessName(current);
|
||||||
|
|
||||||
// True if executable switch equals current window
|
// True if executable switch equals current window
|
||||||
bool equals = (executable.toStdString() == current);
|
bool equals = (executable.toStdString() == current);
|
||||||
|
|||||||
@@ -11,16 +11,15 @@ namespace advss {
|
|||||||
|
|
||||||
enum class HotkeyType;
|
enum class HotkeyType;
|
||||||
|
|
||||||
EXPORT std::vector<std::string> GetWindowList();
|
EXPORT void GetWindowList(std::vector<std::string> &windows);
|
||||||
EXPORT std::string GetCurrentWindowTitle();
|
EXPORT void GetWindowList(QStringList &windows);
|
||||||
|
EXPORT void GetCurrentWindowTitle(std::string &title);
|
||||||
EXPORT bool IsFullscreen(const std::string &title);
|
EXPORT bool IsFullscreen(const std::string &title);
|
||||||
EXPORT bool IsMaximized(const std::string &title);
|
EXPORT bool IsMaximized(const std::string &title);
|
||||||
EXPORT std::optional<std::string> GetTextInWindow(const std::string &window);
|
EXPORT std::optional<std::string> GetTextInWindow(const std::string &window);
|
||||||
EXPORT int SecondsSinceLastInput();
|
EXPORT int SecondsSinceLastInput();
|
||||||
EXPORT QStringList GetProcessList();
|
EXPORT void GetProcessList(QStringList &processes);
|
||||||
EXPORT std::string GetForegroundProcessName();
|
EXPORT void GetForegroundProcessName(std::string &name);
|
||||||
EXPORT std::string GetForegroundProcessPath();
|
|
||||||
EXPORT QStringList GetProcessPathsFromName(const QString &name);
|
|
||||||
EXPORT bool IsInFocus(const QString &executable);
|
EXPORT bool IsInFocus(const QString &executable);
|
||||||
void PlatformInit();
|
void PlatformInit();
|
||||||
void PlatformCleanup();
|
void PlatformCleanup();
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ bool SwitcherData::VersionChanged(obs_data_t *obj, std::string currentVersion)
|
|||||||
if (!obs_data_has_user_value(obj, "version")) {
|
if (!obs_data_has_user_value(obj, "version")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
switcher->firstBoot = false;
|
||||||
std::string previousVersion = obs_data_get_string(obj, "version");
|
std::string previousVersion = obs_data_get_string(obj, "version");
|
||||||
return previousVersion != currentVersion;
|
return previousVersion != currentVersion;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -94,6 +94,7 @@ public:
|
|||||||
bool stop = false;
|
bool stop = false;
|
||||||
std::condition_variable cv;
|
std::condition_variable cv;
|
||||||
|
|
||||||
|
bool firstBoot = true;
|
||||||
bool transitionActive = false;
|
bool transitionActive = false;
|
||||||
bool sceneCollectionStop = false;
|
bool sceneCollectionStop = false;
|
||||||
bool obsIsShuttingDown = false;
|
bool obsIsShuttingDown = false;
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
#include "auto-update-tooltip-label.hpp"
|
#include "auto-update-tooltip-label.hpp"
|
||||||
|
|
||||||
#include <QToolTip>
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
AutoUpdateHelpIcon::AutoUpdateHelpIcon(
|
AutoUpdateHelpIcon::AutoUpdateHelpIcon(
|
||||||
@@ -18,7 +16,6 @@ AutoUpdateHelpIcon::AutoUpdateHelpIcon(
|
|||||||
|
|
||||||
void AutoUpdateHelpIcon::enterEvent(QEnterEvent *event)
|
void AutoUpdateHelpIcon::enterEvent(QEnterEvent *event)
|
||||||
{
|
{
|
||||||
UpdateTooltip();
|
|
||||||
_timer->start(_updateIntervalMs);
|
_timer->start(_updateIntervalMs);
|
||||||
QLabel::enterEvent(event);
|
QLabel::enterEvent(event);
|
||||||
}
|
}
|
||||||
@@ -31,12 +28,7 @@ void AutoUpdateHelpIcon::leaveEvent(QEvent *event)
|
|||||||
|
|
||||||
void AutoUpdateHelpIcon::UpdateTooltip()
|
void AutoUpdateHelpIcon::UpdateTooltip()
|
||||||
{
|
{
|
||||||
if (!underMouse()) {
|
setToolTip(_callback());
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QString text = _callback();
|
|
||||||
QToolTip::showText(QCursor::pos(), text, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -8,18 +8,13 @@
|
|||||||
|
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
#include <obs-module.h>
|
#include <obs-module.h>
|
||||||
#include <util/config-file.h>
|
|
||||||
|
|
||||||
#include <QFileDialog>
|
#include <QFileDialog>
|
||||||
#include <QMainWindow>
|
|
||||||
#include <QTextStream>
|
#include <QTextStream>
|
||||||
#include <QTimer>
|
#include <util/config-file.h>
|
||||||
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
static void showBackupDialogs(const QString &json)
|
void AskForBackup(const QString &json)
|
||||||
{
|
{
|
||||||
const bool backupWasConfirmed = DisplayMessage(
|
const bool backupWasConfirmed = DisplayMessage(
|
||||||
obs_module_text("AdvSceneSwitcher.askBackup"), true, false);
|
obs_module_text("AdvSceneSwitcher.askBackup"), true, false);
|
||||||
@@ -47,27 +42,6 @@ static void showBackupDialogs(const QString &json)
|
|||||||
out << json;
|
out << json;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AskForBackup(obs_data_t *settings)
|
|
||||||
{
|
|
||||||
// This function is called while the plugin settings are being loaded.
|
|
||||||
// Blocking at this stage can cause issues such as OBS failing to start
|
|
||||||
// or crashing.
|
|
||||||
// Therefore, we ask the user whether they want to back up the settings
|
|
||||||
// asynchronously.
|
|
||||||
|
|
||||||
auto json = obs_data_get_json(settings);
|
|
||||||
static QString jsonQString = json ? json : "";
|
|
||||||
|
|
||||||
static const auto askForBackupWrapper = [](void *) {
|
|
||||||
showBackupDialogs(jsonQString);
|
|
||||||
};
|
|
||||||
|
|
||||||
AddFinishedLoadingStep([]() {
|
|
||||||
obs_queue_task(OBS_TASK_UI, askForBackupWrapper, nullptr,
|
|
||||||
false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void BackupSettingsOfCurrentVersion()
|
void BackupSettingsOfCurrentVersion()
|
||||||
{
|
{
|
||||||
auto sceneCollectionName = obs_frontend_get_current_scene_collection();
|
auto sceneCollectionName = obs_frontend_get_current_scene_collection();
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <obs-data.h>
|
#include <QString>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
void AskForBackup(obs_data_t *settings);
|
void AskForBackup(const QString &json);
|
||||||
void BackupSettingsOfCurrentVersion();
|
void BackupSettingsOfCurrentVersion();
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,195 +0,0 @@
|
|||||||
#include "crash-handler.hpp"
|
|
||||||
#include "log-helper.hpp"
|
|
||||||
#include "obs-module-helper.hpp"
|
|
||||||
#include "plugin-state-helpers.hpp"
|
|
||||||
|
|
||||||
#include <obs-frontend-api.h>
|
|
||||||
#include <obs-module.h>
|
|
||||||
|
|
||||||
#include <QCheckBox>
|
|
||||||
#include <QDialog>
|
|
||||||
#include <QDialogButtonBox>
|
|
||||||
#include <QDir>
|
|
||||||
#include <QFile>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QMainWindow>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
namespace advss {
|
|
||||||
|
|
||||||
static constexpr std::string_view sentinel = ".running";
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
static constexpr bool handleUncleanShutdown = false;
|
|
||||||
#else
|
|
||||||
static constexpr bool handleUncleanShutdown = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool wasCleanShutdown = false;
|
|
||||||
static bool suppressCrashDialog = false;
|
|
||||||
|
|
||||||
bool GetSuppressCrashDialog()
|
|
||||||
{
|
|
||||||
return suppressCrashDialog;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SetSuppressCrashDialog(bool suppress)
|
|
||||||
{
|
|
||||||
suppressCrashDialog = suppress;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setup();
|
|
||||||
static bool setupDone = []() {
|
|
||||||
AddPluginInitStep(setup);
|
|
||||||
AddSaveStep([](obs_data_t *obj) {
|
|
||||||
obs_data_set_bool(obj, "suppressCrashDialog",
|
|
||||||
suppressCrashDialog);
|
|
||||||
});
|
|
||||||
AddLoadStep([](obs_data_t *obj) {
|
|
||||||
suppressCrashDialog =
|
|
||||||
obs_data_get_bool(obj, "suppressCrashDialog");
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}();
|
|
||||||
|
|
||||||
static void handleShutdown(enum obs_frontend_event event, void *)
|
|
||||||
{
|
|
||||||
if (event != OBS_FRONTEND_EVENT_EXIT) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *sentinelFile = obs_module_config_path(sentinel.data());
|
|
||||||
if (!sentinelFile) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QFile file(sentinelFile);
|
|
||||||
if (!file.exists()) {
|
|
||||||
bfree(sentinelFile);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!file.remove()) {
|
|
||||||
blog(LOG_WARNING, "failed to remove sentinel file");
|
|
||||||
}
|
|
||||||
|
|
||||||
bfree(sentinelFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void setup()
|
|
||||||
{
|
|
||||||
char *sentinelFile = obs_module_config_path(sentinel.data());
|
|
||||||
if (!sentinelFile) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString dirPath = QFileInfo(sentinelFile).absolutePath();
|
|
||||||
QDir dir(dirPath);
|
|
||||||
if (!dir.exists()) {
|
|
||||||
if (!dir.mkpath(dirPath)) {
|
|
||||||
blog(LOG_WARNING,
|
|
||||||
"failed to create directory for sentinel file");
|
|
||||||
bfree(sentinelFile);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QFile file(sentinelFile);
|
|
||||||
|
|
||||||
wasCleanShutdown = file.exists();
|
|
||||||
|
|
||||||
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
||||||
blog(LOG_WARNING, "failed to create sentinel file");
|
|
||||||
bfree(sentinelFile);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
file.write("running");
|
|
||||||
file.close();
|
|
||||||
bfree(sentinelFile);
|
|
||||||
|
|
||||||
obs_frontend_add_event_callback(handleShutdown, nullptr);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool wasUncleanShutdown()
|
|
||||||
{
|
|
||||||
static bool alreadyHandled = false;
|
|
||||||
|
|
||||||
if (!handleUncleanShutdown || !wasCleanShutdown || alreadyHandled) {
|
|
||||||
alreadyHandled = true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
alreadyHandled = true;
|
|
||||||
blog(LOG_WARNING, "unclean shutdown detected");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void askForStartupSkip()
|
|
||||||
{
|
|
||||||
auto mainWindow =
|
|
||||||
static_cast<QMainWindow *>(obs_frontend_get_main_window());
|
|
||||||
auto dialog = new QDialog(mainWindow);
|
|
||||||
dialog->setWindowTitle(obs_module_text("AdvSceneSwitcher.windowTitle"));
|
|
||||||
dialog->setWindowFlags(dialog->windowFlags() &
|
|
||||||
~Qt::WindowContextHelpButtonHint);
|
|
||||||
|
|
||||||
auto layout = new QVBoxLayout(dialog);
|
|
||||||
auto label = new QLabel(
|
|
||||||
obs_module_text("AdvSceneSwitcher.crashDetected"), dialog);
|
|
||||||
label->setWordWrap(true);
|
|
||||||
layout->addWidget(label);
|
|
||||||
|
|
||||||
auto checkbox = new QCheckBox(
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.crashDetected.suppressCheckbox"),
|
|
||||||
dialog);
|
|
||||||
layout->addWidget(checkbox);
|
|
||||||
|
|
||||||
auto buttonbox = new QDialogButtonBox(
|
|
||||||
QDialogButtonBox::Yes | QDialogButtonBox::No, dialog);
|
|
||||||
QObject::connect(buttonbox, &QDialogButtonBox::accepted, dialog,
|
|
||||||
&QDialog::accept);
|
|
||||||
QObject::connect(buttonbox, &QDialogButtonBox::rejected, dialog,
|
|
||||||
&QDialog::reject);
|
|
||||||
layout->addWidget(buttonbox);
|
|
||||||
|
|
||||||
dialog->setLayout(layout);
|
|
||||||
|
|
||||||
bool skipStart = dialog->exec() == QDialog::Accepted;
|
|
||||||
suppressCrashDialog = checkbox->isChecked();
|
|
||||||
dialog->deleteLater();
|
|
||||||
|
|
||||||
if (!skipStart) {
|
|
||||||
StartPlugin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ShouldSkipPluginStartOnUncleanShutdown()
|
|
||||||
{
|
|
||||||
if (!wasUncleanShutdown()) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (suppressCrashDialog) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This function is called while the plugin settings are being loaded.
|
|
||||||
// Blocking at this stage can cause issues such as OBS failing to start
|
|
||||||
// or crashing.
|
|
||||||
// Therefore, we ask the user whether they want to start the plugin
|
|
||||||
// asynchronously.
|
|
||||||
static const auto showDialogWrapper = [](void *) {
|
|
||||||
askForStartupSkip();
|
|
||||||
};
|
|
||||||
|
|
||||||
AddFinishedLoadingStep([]() {
|
|
||||||
obs_queue_task(OBS_TASK_UI, showDialogWrapper, nullptr, false);
|
|
||||||
});
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace advss
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
namespace advss {
|
|
||||||
|
|
||||||
bool ShouldSkipPluginStartOnUncleanShutdown();
|
|
||||||
|
|
||||||
bool GetSuppressCrashDialog();
|
|
||||||
void SetSuppressCrashDialog(bool suppress);
|
|
||||||
|
|
||||||
} // namespace advss
|
|
||||||
@@ -1,5 +1,12 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef UNIT_TEST
|
||||||
|
|
||||||
|
#define EXPORT
|
||||||
|
#define ADVSS_EXPORT
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#define EXPORT __declspec(dllexport)
|
#define EXPORT __declspec(dllexport)
|
||||||
#else
|
#else
|
||||||
@@ -12,3 +19,5 @@
|
|||||||
#else
|
#else
|
||||||
#define ADVSS_EXPORT Q_DECL_IMPORT
|
#define ADVSS_EXPORT Q_DECL_IMPORT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif // UNIT_TEST
|
||||||
|
|||||||
@@ -7,11 +7,9 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
FileSelection::FileSelection(FileSelection::Type type, QWidget *parent,
|
FileSelection::FileSelection(FileSelection::Type type, QWidget *parent)
|
||||||
const QString &browseTitle)
|
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
_type(type),
|
_type(type),
|
||||||
_browseTitle(browseTitle),
|
|
||||||
_filePath(new VariableLineEdit(this)),
|
_filePath(new VariableLineEdit(this)),
|
||||||
_browseButton(
|
_browseButton(
|
||||||
new QPushButton(obs_module_text("AdvSceneSwitcher.browse")))
|
new QPushButton(obs_module_text("AdvSceneSwitcher.browse")))
|
||||||
@@ -57,14 +55,11 @@ void FileSelection::BrowseButtonClicked()
|
|||||||
QString defaultPath = ValidPathOrDesktop(_filePath->text());
|
QString defaultPath = ValidPathOrDesktop(_filePath->text());
|
||||||
QString path;
|
QString path;
|
||||||
if (_type == FileSelection::Type::WRITE) {
|
if (_type == FileSelection::Type::WRITE) {
|
||||||
path = QFileDialog::getSaveFileName(this, _browseTitle,
|
path = QFileDialog::getSaveFileName(this, "", defaultPath);
|
||||||
defaultPath);
|
|
||||||
} else if (_type == FileSelection::Type::READ) {
|
} else if (_type == FileSelection::Type::READ) {
|
||||||
path = QFileDialog::getOpenFileName(this, _browseTitle,
|
path = QFileDialog::getOpenFileName(this, "", defaultPath);
|
||||||
defaultPath);
|
|
||||||
} else {
|
} else {
|
||||||
path = QFileDialog::getExistingDirectory(this, _browseTitle,
|
path = QFileDialog::getExistingDirectory(this, "", defaultPath);
|
||||||
defaultPath);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (path.isEmpty()) {
|
if (path.isEmpty()) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public:
|
|||||||
|
|
||||||
EXPORT
|
EXPORT
|
||||||
FileSelection(FileSelection::Type type = FileSelection::Type::READ,
|
FileSelection(FileSelection::Type type = FileSelection::Type::READ,
|
||||||
QWidget *parent = 0, const QString &browseTitle = "");
|
QWidget *parent = 0);
|
||||||
EXPORT void SetPath(const StringVariable &);
|
EXPORT void SetPath(const StringVariable &);
|
||||||
EXPORT void SetPath(const QString &);
|
EXPORT void SetPath(const QString &);
|
||||||
EXPORT QString GetPath() const;
|
EXPORT QString GetPath() const;
|
||||||
@@ -34,7 +34,6 @@ signals:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
Type _type;
|
Type _type;
|
||||||
QString _browseTitle;
|
|
||||||
VariableLineEdit *_filePath;
|
VariableLineEdit *_filePath;
|
||||||
QPushButton *_browseButton;
|
QPushButton *_browseButton;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,463 +0,0 @@
|
|||||||
#include "first-run-wizard.hpp"
|
|
||||||
|
|
||||||
#include "log-helper.hpp"
|
|
||||||
#include "macro.hpp"
|
|
||||||
#include "macro-action-factory.hpp"
|
|
||||||
#include "macro-condition-factory.hpp"
|
|
||||||
#include "macro-settings.hpp"
|
|
||||||
#include "platform-funcs.hpp"
|
|
||||||
#include "selection-helpers.hpp"
|
|
||||||
|
|
||||||
#include <obs-frontend-api.h>
|
|
||||||
#include <obs-data.h>
|
|
||||||
#include <util/config-file.h>
|
|
||||||
|
|
||||||
#include <QFrame>
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QMessageBox>
|
|
||||||
#include <QRegularExpression>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
namespace advss {
|
|
||||||
|
|
||||||
static constexpr char kConditionIdWindow[] = "window";
|
|
||||||
static constexpr char kActionIdSceneSwitch[] = "scene_switch";
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// OBS global config helpers
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
static constexpr char kConfigSection[] = "AdvancedSceneSwitcher";
|
|
||||||
static constexpr char kFirstRunKey[] = "firstRun";
|
|
||||||
|
|
||||||
bool IsFirstRun()
|
|
||||||
{
|
|
||||||
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(31, 0, 0)
|
|
||||||
config_t *cfg = obs_frontend_get_user_config();
|
|
||||||
#else
|
|
||||||
config_t *cfg = obs_frontend_get_global_config();
|
|
||||||
#endif
|
|
||||||
if (!config_has_user_value(cfg, kConfigSection, kFirstRunKey)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return config_get_bool(cfg, kConfigSection, kFirstRunKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void WriteFirstRun(bool value)
|
|
||||||
{
|
|
||||||
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(31, 0, 0)
|
|
||||||
config_t *cfg = obs_frontend_get_user_config();
|
|
||||||
#else
|
|
||||||
config_t *cfg = obs_frontend_get_global_config();
|
|
||||||
#endif
|
|
||||||
config_set_bool(cfg, kConfigSection, kFirstRunKey, value);
|
|
||||||
config_save_safe(cfg, "tmp", nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString DetectFocusedWindow()
|
|
||||||
{
|
|
||||||
return QString::fromStdString(GetCurrentWindowTitle());
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===========================================================================
|
|
||||||
// WelcomePage
|
|
||||||
// ===========================================================================
|
|
||||||
|
|
||||||
WelcomePage::WelcomePage(QWidget *parent) : QWizardPage(parent)
|
|
||||||
{
|
|
||||||
setTitle(obs_module_text("FirstRunWizard.welcome.title"));
|
|
||||||
setSubTitle(obs_module_text("FirstRunWizard.welcome.subtitle"));
|
|
||||||
|
|
||||||
auto body = new QLabel(obs_module_text("FirstRunWizard.welcome.body"),
|
|
||||||
this);
|
|
||||||
body->setWordWrap(true);
|
|
||||||
body->setTextFormat(Qt::RichText);
|
|
||||||
|
|
||||||
auto layout = new QVBoxLayout(this);
|
|
||||||
layout->addWidget(body);
|
|
||||||
layout->addStretch();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===========================================================================
|
|
||||||
// SceneSelectionPage
|
|
||||||
// ===========================================================================
|
|
||||||
|
|
||||||
SceneSelectionPage::SceneSelectionPage(QWidget *parent) : QWizardPage(parent)
|
|
||||||
{
|
|
||||||
setTitle(obs_module_text("FirstRunWizard.scene.title"));
|
|
||||||
setSubTitle(obs_module_text("FirstRunWizard.scene.subtitle"));
|
|
||||||
|
|
||||||
auto label =
|
|
||||||
new QLabel(obs_module_text("FirstRunWizard.scene.label"), this);
|
|
||||||
_sceneCombo = new QComboBox(this);
|
|
||||||
_sceneCombo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
|
||||||
|
|
||||||
// registerField with * suffix means the field is mandatory for Next
|
|
||||||
registerField("targetScene*", _sceneCombo, "currentText",
|
|
||||||
SIGNAL(currentTextChanged(QString)));
|
|
||||||
|
|
||||||
connect(_sceneCombo, &QComboBox::currentTextChanged, this,
|
|
||||||
&QWizardPage::completeChanged);
|
|
||||||
|
|
||||||
auto row = new QHBoxLayout;
|
|
||||||
row->addWidget(label);
|
|
||||||
row->addWidget(_sceneCombo, 1);
|
|
||||||
|
|
||||||
auto layout = new QVBoxLayout(this);
|
|
||||||
layout->addLayout(row);
|
|
||||||
layout->addStretch();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SceneSelectionPage::initializePage()
|
|
||||||
{
|
|
||||||
_sceneCombo->clear();
|
|
||||||
for (const QString &name : GetSceneNames())
|
|
||||||
_sceneCombo->addItem(name);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool SceneSelectionPage::isComplete() const
|
|
||||||
{
|
|
||||||
return _sceneCombo->count() > 0 &&
|
|
||||||
!_sceneCombo->currentText().isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===========================================================================
|
|
||||||
// WindowConditionPage
|
|
||||||
// ===========================================================================
|
|
||||||
|
|
||||||
WindowConditionPage::WindowConditionPage(QWidget *parent)
|
|
||||||
: QWizardPage(parent),
|
|
||||||
_detectTimer(new QTimer(this))
|
|
||||||
{
|
|
||||||
setTitle(obs_module_text("FirstRunWizard.window.title"));
|
|
||||||
setSubTitle(obs_module_text("FirstRunWizard.window.subtitle"));
|
|
||||||
|
|
||||||
auto label = new QLabel(obs_module_text("FirstRunWizard.window.label"),
|
|
||||||
this);
|
|
||||||
_windowEdit = new QLineEdit(this);
|
|
||||||
_windowEdit->setPlaceholderText(
|
|
||||||
obs_module_text("FirstRunWizard.window.placeholder"));
|
|
||||||
|
|
||||||
_autoDetect = new QPushButton(
|
|
||||||
obs_module_text("FirstRunWizard.window.autoDetect"), this);
|
|
||||||
_autoDetect->setToolTip(
|
|
||||||
obs_module_text("FirstRunWizard.window.autoDetectTooltip"));
|
|
||||||
|
|
||||||
registerField("windowTitle*", _windowEdit);
|
|
||||||
|
|
||||||
connect(_windowEdit, &QLineEdit::textChanged, this,
|
|
||||||
&QWizardPage::completeChanged);
|
|
||||||
connect(_autoDetect, &QPushButton::clicked, this,
|
|
||||||
&WindowConditionPage::onAutoDetectClicked);
|
|
||||||
connect(_detectTimer, &QTimer::timeout, this,
|
|
||||||
&WindowConditionPage::onCountdownTick);
|
|
||||||
|
|
||||||
auto row = new QHBoxLayout;
|
|
||||||
row->addWidget(label);
|
|
||||||
row->addWidget(_windowEdit, 1);
|
|
||||||
|
|
||||||
auto hint =
|
|
||||||
new QLabel(obs_module_text("FirstRunWizard.window.hint"), this);
|
|
||||||
hint->setTextFormat(Qt::RichText);
|
|
||||||
hint->setWordWrap(true);
|
|
||||||
|
|
||||||
auto layout = new QVBoxLayout(this);
|
|
||||||
layout->addLayout(row);
|
|
||||||
layout->addWidget(_autoDetect, 0, Qt::AlignLeft);
|
|
||||||
layout->addWidget(hint);
|
|
||||||
layout->addStretch();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowConditionPage::initializePage()
|
|
||||||
{
|
|
||||||
if (_windowEdit->text().isEmpty()) {
|
|
||||||
QString detected = DetectFocusedWindow();
|
|
||||||
if (!detected.isEmpty()) {
|
|
||||||
_windowEdit->setText(detected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WindowConditionPage::isComplete() const
|
|
||||||
{
|
|
||||||
return !_windowEdit->text().trimmed().isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowConditionPage::onAutoDetectClicked()
|
|
||||||
{
|
|
||||||
_countdown = 3;
|
|
||||||
_autoDetect->setEnabled(false);
|
|
||||||
_autoDetect->setText(
|
|
||||||
QString(obs_module_text(
|
|
||||||
"FirstRunWizard.window.autoDetectCountdown"))
|
|
||||||
.arg(_countdown));
|
|
||||||
_detectTimer->start(1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
void WindowConditionPage::onCountdownTick()
|
|
||||||
{
|
|
||||||
--_countdown;
|
|
||||||
if (_countdown > 0) {
|
|
||||||
_autoDetect->setText(
|
|
||||||
QString(obs_module_text(
|
|
||||||
"FirstRunWizard.window.autoDetectCountdown"))
|
|
||||||
.arg(_countdown));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_detectTimer->stop();
|
|
||||||
QString title = DetectFocusedWindow();
|
|
||||||
if (!title.isEmpty()) {
|
|
||||||
_windowEdit->setText(title);
|
|
||||||
}
|
|
||||||
|
|
||||||
_autoDetect->setEnabled(true);
|
|
||||||
_autoDetect->setText(
|
|
||||||
obs_module_text("FirstRunWizard.window.autoDetect"));
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===========================================================================
|
|
||||||
// ReviewPage
|
|
||||||
// ===========================================================================
|
|
||||||
|
|
||||||
ReviewPage::ReviewPage(QWidget *parent, std::shared_ptr<Macro> ¯o)
|
|
||||||
: QWizardPage(parent),
|
|
||||||
_macro(macro)
|
|
||||||
{
|
|
||||||
setTitle(obs_module_text("FirstRunWizard.review.title"));
|
|
||||||
setSubTitle(obs_module_text("FirstRunWizard.review.subtitle"));
|
|
||||||
|
|
||||||
_summary = new QLabel(this);
|
|
||||||
_summary->setWordWrap(true);
|
|
||||||
_summary->setTextFormat(Qt::RichText);
|
|
||||||
_summary->setFrameShape(QFrame::StyledPanel);
|
|
||||||
_summary->setContentsMargins(12, 12, 12, 12);
|
|
||||||
|
|
||||||
auto layout = new QVBoxLayout(this);
|
|
||||||
layout->addWidget(_summary);
|
|
||||||
layout->addStretch();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReviewPage::initializePage()
|
|
||||||
{
|
|
||||||
const QString scene = field("targetScene").toString();
|
|
||||||
const QString window = field("windowTitle").toString();
|
|
||||||
|
|
||||||
_summary->setText(
|
|
||||||
QString(obs_module_text("FirstRunWizard.review.summary"))
|
|
||||||
.arg(scene.toHtmlEscaped(), window.toHtmlEscaped()));
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString escapeForRegex(const QString &input)
|
|
||||||
{
|
|
||||||
return QRegularExpression::escape(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ReviewPage::validatePage()
|
|
||||||
{
|
|
||||||
const QString scene = field("targetScene").toString();
|
|
||||||
const QString window = escapeForRegex(field("windowTitle").toString());
|
|
||||||
const std::string name = ("Window -> " + scene).toStdString();
|
|
||||||
|
|
||||||
// Build condition data blob
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
// Condition blob — mirrors MacroConditionWindow::Save() output:
|
|
||||||
//
|
|
||||||
// {
|
|
||||||
// "segmentSettings": { "enabled": true, "version": 1 },
|
|
||||||
// "id": "window",
|
|
||||||
// "checkTitle": true,
|
|
||||||
// "window": "<user input>",
|
|
||||||
// "windowRegexConfig": {
|
|
||||||
// "enable": true, // use regex-style partial matching
|
|
||||||
// "partial": true, // match anywhere in the title
|
|
||||||
// "options": 3 // case-insensitive (QRegularExpression flags)
|
|
||||||
// },
|
|
||||||
// "focus": true, // only trigger when window is focused
|
|
||||||
// "version": 1
|
|
||||||
// }
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
OBSDataAutoRelease condSegment = obs_data_create();
|
|
||||||
obs_data_set_bool(condSegment, "enabled", true);
|
|
||||||
obs_data_set_int(condSegment, "version", 1);
|
|
||||||
|
|
||||||
OBSDataAutoRelease condRegex = obs_data_create();
|
|
||||||
obs_data_set_bool(condRegex, "enable", true);
|
|
||||||
obs_data_set_bool(condRegex, "partial", true);
|
|
||||||
obs_data_set_int(condRegex, "options", 3); // CaseInsensitiveOption
|
|
||||||
|
|
||||||
OBSDataAutoRelease condData = obs_data_create();
|
|
||||||
obs_data_set_obj(condData, "segmentSettings", condSegment);
|
|
||||||
obs_data_set_string(condData, "id", "window");
|
|
||||||
obs_data_set_bool(condData, "checkTitle", true);
|
|
||||||
obs_data_set_string(condData, "window", window.toUtf8().constData());
|
|
||||||
obs_data_set_obj(condData, "windowRegexConfig", condRegex);
|
|
||||||
obs_data_set_bool(condData, "focus", true);
|
|
||||||
obs_data_set_int(condData, "version", 1);
|
|
||||||
|
|
||||||
// Build action data blob
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
// Action blob — mirrors MacroActionSwitchScene::Save() output:
|
|
||||||
//
|
|
||||||
// {
|
|
||||||
// "segmentSettings": { "enabled": true, "version": 1 },
|
|
||||||
// "id": "scene_switch",
|
|
||||||
// "action": 0, // 0 = switch scene
|
|
||||||
// "sceneSelection": {
|
|
||||||
// "type": 0, // 0 = scene by name
|
|
||||||
// "name": "<scene>",
|
|
||||||
// "canvasSelection": "Main"
|
|
||||||
// },
|
|
||||||
// "transitionType": 1, // 1 = use scene's default transition
|
|
||||||
// "blockUntilTransitionDone": false,
|
|
||||||
// "sceneType": 0
|
|
||||||
// }
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
OBSDataAutoRelease actionSegment = obs_data_create();
|
|
||||||
obs_data_set_bool(actionSegment, "enabled", true);
|
|
||||||
obs_data_set_int(actionSegment, "version", 1);
|
|
||||||
|
|
||||||
OBSDataAutoRelease sceneSelection = obs_data_create();
|
|
||||||
obs_data_set_int(sceneSelection, "type", 0);
|
|
||||||
obs_data_set_string(sceneSelection, "name", scene.toUtf8().constData());
|
|
||||||
obs_data_set_string(sceneSelection, "canvasSelection", "Main");
|
|
||||||
|
|
||||||
OBSDataAutoRelease actionData = obs_data_create();
|
|
||||||
obs_data_set_obj(actionData, "segmentSettings", actionSegment);
|
|
||||||
obs_data_set_string(actionData, "id", "scene_switch");
|
|
||||||
obs_data_set_int(actionData, "action", 0);
|
|
||||||
obs_data_set_obj(actionData, "sceneSelection", sceneSelection);
|
|
||||||
obs_data_set_int(actionData, "transitionType", 1);
|
|
||||||
obs_data_set_bool(actionData, "blockUntilTransitionDone", false);
|
|
||||||
obs_data_set_int(actionData, "sceneType", 0);
|
|
||||||
|
|
||||||
if (!FirstRunWizard::CreateMacro(_macro, name, kConditionIdWindow,
|
|
||||||
condData, kActionIdSceneSwitch,
|
|
||||||
actionData)) {
|
|
||||||
QMessageBox::warning(
|
|
||||||
this,
|
|
||||||
obs_module_text("FirstRunWizard.review.errorTitle"),
|
|
||||||
QString(obs_module_text(
|
|
||||||
"FirstRunWizard.review.errorBody"))
|
|
||||||
.arg(window, scene));
|
|
||||||
_macro.reset();
|
|
||||||
// Still advance so the user is not stuck.
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===========================================================================
|
|
||||||
// DonePage
|
|
||||||
// ===========================================================================
|
|
||||||
|
|
||||||
DonePage::DonePage(QWidget *parent) : QWizardPage(parent)
|
|
||||||
{
|
|
||||||
setTitle(obs_module_text("FirstRunWizard.done.title"));
|
|
||||||
setSubTitle(obs_module_text("FirstRunWizard.done.subtitle"));
|
|
||||||
|
|
||||||
auto body =
|
|
||||||
new QLabel(obs_module_text("FirstRunWizard.done.body"), this);
|
|
||||||
body->setWordWrap(true);
|
|
||||||
body->setTextFormat(Qt::RichText);
|
|
||||||
body->setOpenExternalLinks(true);
|
|
||||||
|
|
||||||
auto layout = new QVBoxLayout(this);
|
|
||||||
layout->addWidget(body);
|
|
||||||
layout->addStretch();
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===========================================================================
|
|
||||||
// FirstRunWizard
|
|
||||||
// ===========================================================================
|
|
||||||
|
|
||||||
FirstRunWizard::FirstRunWizard(QWidget *parent) : QWizard(parent)
|
|
||||||
{
|
|
||||||
setWindowTitle(obs_module_text("FirstRunWizard.windowTitle"));
|
|
||||||
setWizardStyle(QWizard::ModernStyle);
|
|
||||||
setMinimumSize(540, 420);
|
|
||||||
|
|
||||||
setPage(PAGE_WELCOME, new WelcomePage(this));
|
|
||||||
setPage(PAGE_SCENE, new SceneSelectionPage(this));
|
|
||||||
setPage(PAGE_WINDOW, new WindowConditionPage(this));
|
|
||||||
setPage(PAGE_REVIEW, new ReviewPage(this, _macro));
|
|
||||||
setPage(PAGE_DONE, new DonePage(this));
|
|
||||||
|
|
||||||
setStartId(PAGE_WELCOME);
|
|
||||||
setOption(QWizard::NoBackButtonOnLastPage, true);
|
|
||||||
setOption(QWizard::NoCancelButtonOnLastPage, true);
|
|
||||||
|
|
||||||
// Mark done on both Accept (Finish) and Reject (Cancel / close)
|
|
||||||
connect(this, &QWizard::accepted, this,
|
|
||||||
&FirstRunWizard::markFirstRunComplete);
|
|
||||||
connect(this, &QWizard::rejected, this,
|
|
||||||
&FirstRunWizard::markFirstRunComplete);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FirstRunWizard::markFirstRunComplete()
|
|
||||||
{
|
|
||||||
WriteFirstRun(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
std::shared_ptr<Macro> FirstRunWizard::ShowWizard(QWidget *parent)
|
|
||||||
{
|
|
||||||
auto wizard = new FirstRunWizard(parent);
|
|
||||||
wizard->exec();
|
|
||||||
wizard->deleteLater();
|
|
||||||
return wizard->_macro;
|
|
||||||
}
|
|
||||||
|
|
||||||
// static
|
|
||||||
bool FirstRunWizard::CreateMacro(std::shared_ptr<Macro> ¯o,
|
|
||||||
const std::string ¯oName,
|
|
||||||
const std::string &conditionId,
|
|
||||||
obs_data_t *conditionData,
|
|
||||||
const std::string &actionId,
|
|
||||||
obs_data_t *actionData)
|
|
||||||
{
|
|
||||||
// 1. Create and register the Macro
|
|
||||||
macro = std::make_shared<Macro>(macroName, GetGlobalMacroSettings());
|
|
||||||
if (!macro) {
|
|
||||||
blog(LOG_WARNING, "FirstRunWizard: Macro allocation failed");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Instantiate condition via factory, then hydrate via Load()
|
|
||||||
auto condition =
|
|
||||||
MacroConditionFactory::Create(conditionId, macro.get());
|
|
||||||
if (!condition) {
|
|
||||||
blog(LOG_WARNING,
|
|
||||||
"FirstRunWizard: condition factory returned null "
|
|
||||||
"for id '%s' — is the base plugin loaded?",
|
|
||||||
conditionId.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!condition->Load(conditionData)) {
|
|
||||||
blog(LOG_WARNING,
|
|
||||||
"FirstRunWizard: condition Load() failed for id '%s'",
|
|
||||||
conditionId.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
macro->Conditions().emplace_back(condition);
|
|
||||||
|
|
||||||
// 3. Instantiate action via factory, then hydrate via Load()
|
|
||||||
auto action = MacroActionFactory::Create(actionId, macro.get());
|
|
||||||
if (!action) {
|
|
||||||
blog(LOG_WARNING,
|
|
||||||
"FirstRunWizard: action factory returned null "
|
|
||||||
"for id '%s' — is the base plugin loaded?",
|
|
||||||
actionId.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (!action->Load(actionData)) {
|
|
||||||
blog(LOG_WARNING,
|
|
||||||
"FirstRunWizard: action Load() failed for id '%s'",
|
|
||||||
actionId.c_str());
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
macro->Actions().emplace_back(action);
|
|
||||||
|
|
||||||
blog(LOG_INFO, "FirstRunWizard: created macro '%s'", macroName.c_str());
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace advss
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <obs-data.h>
|
|
||||||
|
|
||||||
#include <QComboBox>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QLineEdit>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QTimer>
|
|
||||||
#include <QWizard>
|
|
||||||
#include <QWizardPage>
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace advss {
|
|
||||||
|
|
||||||
class Macro;
|
|
||||||
|
|
||||||
bool IsFirstRun();
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// Page IDs
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
enum WizardPageId {
|
|
||||||
PAGE_WELCOME = 0,
|
|
||||||
PAGE_SCENE,
|
|
||||||
PAGE_WINDOW,
|
|
||||||
PAGE_REVIEW,
|
|
||||||
PAGE_DONE,
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// WelcomePage
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
class WelcomePage : public QWizardPage {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit WelcomePage(QWidget *parent = nullptr);
|
|
||||||
int nextId() const override { return PAGE_SCENE; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// SceneSelectionPage
|
|
||||||
// Registers wizard field "targetScene" (QString).
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
class SceneSelectionPage : public QWizardPage {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit SceneSelectionPage(QWidget *parent = nullptr);
|
|
||||||
void initializePage() override;
|
|
||||||
bool isComplete() const override;
|
|
||||||
int nextId() const override { return PAGE_WINDOW; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
QComboBox *_sceneCombo;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// WindowConditionPage
|
|
||||||
// Registers wizard field "windowTitle" (QString).
|
|
||||||
// Auto-detect button samples the focused window after a countdown.
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
class WindowConditionPage : public QWizardPage {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit WindowConditionPage(QWidget *parent = nullptr);
|
|
||||||
void initializePage() override;
|
|
||||||
bool isComplete() const override;
|
|
||||||
int nextId() const override { return PAGE_REVIEW; }
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void onAutoDetectClicked();
|
|
||||||
void onCountdownTick();
|
|
||||||
|
|
||||||
private:
|
|
||||||
QLineEdit *_windowEdit;
|
|
||||||
QPushButton *_autoDetect;
|
|
||||||
QTimer *_detectTimer;
|
|
||||||
int _countdown = 3;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// ReviewPage
|
|
||||||
// Displays a summary and calls FirstRunWizard::CreateMacro() on Finish.
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
class ReviewPage : public QWizardPage {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit ReviewPage(QWidget *parent, std::shared_ptr<Macro> ¯o);
|
|
||||||
void initializePage() override;
|
|
||||||
bool validatePage() override;
|
|
||||||
int nextId() const override { return PAGE_DONE; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
QLabel *_summary;
|
|
||||||
std::shared_ptr<Macro> &_macro;
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// DonePage
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
class DonePage : public QWizardPage {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit DonePage(QWidget *parent = nullptr);
|
|
||||||
int nextId() const override { return -1; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
// FirstRunWizard
|
|
||||||
// ---------------------------------------------------------------------------
|
|
||||||
class FirstRunWizard : public QWizard {
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
explicit FirstRunWizard(QWidget *parent = nullptr);
|
|
||||||
static std::shared_ptr<Macro> ShowWizard(QWidget *parent);
|
|
||||||
static bool
|
|
||||||
CreateMacro(std::shared_ptr<Macro> ¯o, const std::string ¯oName,
|
|
||||||
const std::string &conditionId, obs_data_t *conditionData,
|
|
||||||
const std::string &actionId, obs_data_t *actionData);
|
|
||||||
|
|
||||||
private:
|
|
||||||
void markFirstRunComplete();
|
|
||||||
|
|
||||||
std::shared_ptr<Macro> _macro;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace advss
|
|
||||||
@@ -4,11 +4,9 @@
|
|||||||
#include "ui-helpers.hpp"
|
#include "ui-helpers.hpp"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QLayout>
|
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QTimer>
|
#include <QLayout>
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(advss::Item *);
|
Q_DECLARE_METATYPE(advss::Item *);
|
||||||
|
|
||||||
@@ -332,13 +330,6 @@ void ItemSettingsDialog::NameChanged(const QString &text)
|
|||||||
SetNameWarning("");
|
SetNameWarning("");
|
||||||
}
|
}
|
||||||
|
|
||||||
void ItemSettingsDialog::showEvent(QShowEvent *)
|
|
||||||
{
|
|
||||||
if (_showNameEmptyWarning && _name->text().isEmpty()) {
|
|
||||||
_name->setFocus(Qt::OtherFocusReason);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ItemSettingsDialog::SetNameWarning(const QString warn)
|
void ItemSettingsDialog::SetNameWarning(const QString warn)
|
||||||
{
|
{
|
||||||
if (warn.isEmpty()) {
|
if (warn.isEmpty()) {
|
||||||
|
|||||||
@@ -52,7 +52,6 @@ private slots:
|
|||||||
void NameChanged(const QString &);
|
void NameChanged(const QString &);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void showEvent(QShowEvent *) override;
|
|
||||||
void SetNameWarning(const QString);
|
void SetNameWarning(const QString);
|
||||||
|
|
||||||
QLineEdit *_name;
|
QLineEdit *_name;
|
||||||
|
|||||||
@@ -32,17 +32,6 @@ ListControls::ListControls(QWidget *parent, bool reorder) : QToolBar(parent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListControls::AddWidget(QWidget *widget)
|
|
||||||
{
|
|
||||||
addSeparator();
|
|
||||||
addWidget(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListControls::AddSeparator()
|
|
||||||
{
|
|
||||||
addSeparator();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListControls::AddActionHelper(const char *theme, const char *className,
|
void ListControls::AddActionHelper(const char *theme, const char *className,
|
||||||
const char *tooltip,
|
const char *tooltip,
|
||||||
const std::function<void()> &signal)
|
const std::function<void()> &signal)
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ class ADVSS_EXPORT ListControls final : public QToolBar {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
ListControls(QWidget *parent = nullptr, bool reorder = true);
|
ListControls(QWidget *parent = nullptr, bool reorder = true);
|
||||||
void AddWidget(QWidget *widget);
|
|
||||||
void AddSeparator();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void Add();
|
void Add();
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
#include "list-editor.hpp"
|
#include "list-editor.hpp"
|
||||||
#include "ui-helpers.hpp"
|
#include "ui-helpers.hpp"
|
||||||
|
|
||||||
#include <QEvent>
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
ListEditor::ListEditor(QWidget *parent, bool reorder)
|
ListEditor::ListEditor(QWidget *parent, bool reorder)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
_list(new QListWidget()),
|
_list(new QListWidget()),
|
||||||
_controls(new ListControls(this, reorder)),
|
_controls(new ListControls(this, reorder)),
|
||||||
_mainLayout(new QVBoxLayout()),
|
_mainLayout(new QVBoxLayout())
|
||||||
_placeholder(new QLabel(_list->viewport()))
|
|
||||||
{
|
{
|
||||||
QWidget::connect(_controls, SIGNAL(Add()), this, SLOT(Add()));
|
QWidget::connect(_controls, SIGNAL(Add()), this, SLOT(Add()));
|
||||||
QWidget::connect(_controls, SIGNAL(Remove()), this, SLOT(Remove()));
|
QWidget::connect(_controls, SIGNAL(Remove()), this, SLOT(Remove()));
|
||||||
@@ -18,19 +15,6 @@ ListEditor::ListEditor(QWidget *parent, bool reorder)
|
|||||||
QWidget::connect(_controls, SIGNAL(Down()), this, SLOT(Down()));
|
QWidget::connect(_controls, SIGNAL(Down()), this, SLOT(Down()));
|
||||||
QWidget::connect(_list, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
|
QWidget::connect(_list, SIGNAL(itemDoubleClicked(QListWidgetItem *)),
|
||||||
this, SLOT(Clicked(QListWidgetItem *)));
|
this, SLOT(Clicked(QListWidgetItem *)));
|
||||||
QWidget::connect(_list->model(),
|
|
||||||
SIGNAL(rowsInserted(QModelIndex, int, int)), this,
|
|
||||||
SLOT(UpdatePlaceholder()));
|
|
||||||
QWidget::connect(_list->model(),
|
|
||||||
SIGNAL(rowsRemoved(QModelIndex, int, int)), this,
|
|
||||||
SLOT(UpdatePlaceholder()));
|
|
||||||
QWidget::connect(_list->model(), SIGNAL(modelReset()), this,
|
|
||||||
SLOT(UpdatePlaceholder()));
|
|
||||||
|
|
||||||
_placeholder->setAlignment(Qt::AlignCenter);
|
|
||||||
_placeholder->setWordWrap(true);
|
|
||||||
_placeholder->hide();
|
|
||||||
_list->viewport()->installEventFilter(this);
|
|
||||||
|
|
||||||
_mainLayout->setContentsMargins(0, 0, 0, 0);
|
_mainLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
_mainLayout->addWidget(_list);
|
_mainLayout->addWidget(_list);
|
||||||
@@ -38,40 +22,6 @@ ListEditor::ListEditor(QWidget *parent, bool reorder)
|
|||||||
setLayout(_mainLayout);
|
setLayout(_mainLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ListEditor::SetPlaceholderText(const QString &text)
|
|
||||||
{
|
|
||||||
_placeholder->setText(text);
|
|
||||||
UpdatePlaceholder();
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListEditor::SetMinListHeight(int value)
|
|
||||||
{
|
|
||||||
_minHeight = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListEditor::SetMaxListHeight(int value)
|
|
||||||
{
|
|
||||||
_maxHeight = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListEditor::UpdatePlaceholder()
|
|
||||||
{
|
|
||||||
bool visible = !_placeholder->text().isEmpty() && _list->count() == 0;
|
|
||||||
_placeholder->setVisible(visible);
|
|
||||||
if (visible) {
|
|
||||||
_placeholder->setGeometry(_list->viewport()->rect());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ListEditor::eventFilter(QObject *obj, QEvent *event)
|
|
||||||
{
|
|
||||||
if (obj == _list->viewport() && event->type() == QEvent::Resize &&
|
|
||||||
_placeholder->isVisible()) {
|
|
||||||
_placeholder->setGeometry(_list->viewport()->rect());
|
|
||||||
}
|
|
||||||
return QWidget::eventFilter(obj, event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ListEditor::showEvent(QShowEvent *e)
|
void ListEditor::showEvent(QShowEvent *e)
|
||||||
{
|
{
|
||||||
QWidget::showEvent(e);
|
QWidget::showEvent(e);
|
||||||
@@ -114,24 +64,6 @@ int ListEditor::GetIndexOfSignal() const
|
|||||||
void ListEditor::UpdateListSize()
|
void ListEditor::UpdateListSize()
|
||||||
{
|
{
|
||||||
SetHeightToContentHeight(_list);
|
SetHeightToContentHeight(_list);
|
||||||
|
|
||||||
if (_list->count() == 0 && !_placeholder->text().isEmpty()) {
|
|
||||||
auto height = _list->fontMetrics().height() * 3;
|
|
||||||
_list->setMinimumHeight(height);
|
|
||||||
_list->setMaximumHeight(height);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_minHeight >= 0 && _list->minimumHeight() != _minHeight) {
|
|
||||||
_list->setMinimumHeight(_minHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_maxHeight >= 0 && _list->maximumHeight() != _maxHeight) {
|
|
||||||
if (_list->minimumHeight() > _maxHeight) {
|
|
||||||
_list->setMinimumHeight(_maxHeight);
|
|
||||||
}
|
|
||||||
_list->setMaximumHeight(_maxHeight);
|
|
||||||
}
|
|
||||||
|
|
||||||
adjustSize();
|
adjustSize();
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#include "export-symbol-helper.hpp"
|
#include "export-symbol-helper.hpp"
|
||||||
#include "list-controls.hpp"
|
#include "list-controls.hpp"
|
||||||
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
|
|
||||||
@@ -14,13 +13,9 @@ class ADVSS_EXPORT ListEditor : public QWidget {
|
|||||||
public:
|
public:
|
||||||
ListEditor(QWidget *parent = nullptr, bool reorder = true);
|
ListEditor(QWidget *parent = nullptr, bool reorder = true);
|
||||||
int count() const { return _list->count(); };
|
int count() const { return _list->count(); };
|
||||||
void SetPlaceholderText(const QString &text);
|
|
||||||
void SetMinListHeight(int);
|
|
||||||
void SetMaxListHeight(int);
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void showEvent(QShowEvent *);
|
void showEvent(QShowEvent *);
|
||||||
bool eventFilter(QObject *, QEvent *);
|
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
virtual void Add() = 0;
|
virtual void Add() = 0;
|
||||||
@@ -28,7 +23,6 @@ private slots:
|
|||||||
virtual void Up(){};
|
virtual void Up(){};
|
||||||
virtual void Down(){};
|
virtual void Down(){};
|
||||||
virtual void Clicked(QListWidgetItem *) {}
|
virtual void Clicked(QListWidgetItem *) {}
|
||||||
void UpdatePlaceholder();
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void UpdateListSize();
|
void UpdateListSize();
|
||||||
@@ -37,11 +31,6 @@ protected:
|
|||||||
QListWidget *_list;
|
QListWidget *_list;
|
||||||
ListControls *_controls;
|
ListControls *_controls;
|
||||||
QVBoxLayout *_mainLayout;
|
QVBoxLayout *_mainLayout;
|
||||||
|
|
||||||
private:
|
|
||||||
QLabel *_placeholder;
|
|
||||||
int _minHeight = -1;
|
|
||||||
int _maxHeight = -1;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#ifndef UNIT_TEST
|
||||||
#include <util/base.h>
|
#include <util/base.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -7,7 +9,6 @@ namespace advss {
|
|||||||
#define blog(level, msg, ...)
|
#define blog(level, msg, ...)
|
||||||
#define vblog(level, msg, ...)
|
#define vblog(level, msg, ...)
|
||||||
#define ablog(level, msg, ...)
|
#define ablog(level, msg, ...)
|
||||||
#define mblog(level, msg, ...)
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// Print log with "[adv-ss] " prefix
|
// Print log with "[adv-ss] " prefix
|
||||||
|
|||||||
@@ -9,15 +9,19 @@ namespace advss {
|
|||||||
|
|
||||||
std::variant<double, std::string> EvalMathExpression(const std::string &expr)
|
std::variant<double, std::string> EvalMathExpression(const std::string &expr)
|
||||||
{
|
{
|
||||||
|
static bool setupDone = false;
|
||||||
|
static exprtk::symbol_table<double> symbolTable;
|
||||||
|
static std::random_device rd;
|
||||||
|
static std::mt19937 gen(rd());
|
||||||
|
static std::uniform_real_distribution<double> dis(0.0, 1.0);
|
||||||
static auto randomFunc = []() {
|
static auto randomFunc = []() {
|
||||||
thread_local std::mt19937 gen(std::random_device{}());
|
|
||||||
thread_local std::uniform_real_distribution<double> dis(0.0,
|
|
||||||
1.0);
|
|
||||||
return dis(gen);
|
return dis(gen);
|
||||||
};
|
};
|
||||||
|
|
||||||
exprtk::symbol_table<double> symbolTable;
|
if (!setupDone) {
|
||||||
symbolTable.add_function("random", randomFunc);
|
symbolTable.add_function("random", randomFunc);
|
||||||
|
setupDone = true;
|
||||||
|
}
|
||||||
|
|
||||||
exprtk::expression<double> expression;
|
exprtk::expression<double> expression;
|
||||||
expression.register_symbol_table(symbolTable);
|
expression.register_symbol_table(symbolTable);
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
#include "non-modal-dialog.hpp"
|
#include "non-modal-dialog.hpp"
|
||||||
#include "obs-module-helper.hpp"
|
#include "obs-module-helper.hpp"
|
||||||
|
|
||||||
|
#include <atomic>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
#include <QDialogButtonBox>
|
#include <QDialogButtonBox>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QLayout>
|
#include <QLayout>
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
|
|||||||
@@ -3,42 +3,12 @@
|
|||||||
#include "macro-signals.hpp"
|
#include "macro-signals.hpp"
|
||||||
#include "switcher-data.hpp"
|
#include "switcher-data.hpp"
|
||||||
|
|
||||||
#include "obs-frontend-api.h"
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
static std::mutex initMutex;
|
static std::mutex initMutex;
|
||||||
static std::mutex postLoadMutex;
|
static std::mutex postLoadMutex;
|
||||||
static std::mutex finishLoadMutex;
|
|
||||||
static std::mutex mutex;
|
static std::mutex mutex;
|
||||||
|
|
||||||
static bool setup();
|
|
||||||
static bool setupDonw = setup();
|
|
||||||
bool loadingFinished = false;
|
|
||||||
|
|
||||||
static std::vector<std::function<void()>> &getFinishLoadSteps();
|
|
||||||
|
|
||||||
static bool setup()
|
|
||||||
{
|
|
||||||
static auto handleEvent = [](enum obs_frontend_event event, void *) {
|
|
||||||
switch (event) {
|
|
||||||
case OBS_FRONTEND_EVENT_FINISHED_LOADING: {
|
|
||||||
std::lock_guard<std::mutex> lock(finishLoadMutex);
|
|
||||||
for (const auto &step : getFinishLoadSteps()) {
|
|
||||||
step();
|
|
||||||
}
|
|
||||||
getFinishLoadSteps().clear();
|
|
||||||
loadingFinished = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
obs_frontend_add_event_callback(handleEvent, nullptr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::vector<std::function<void()>> &getPluginInitSteps()
|
static std::vector<std::function<void()>> &getPluginInitSteps()
|
||||||
{
|
{
|
||||||
static std::vector<std::function<void()>> steps;
|
static std::vector<std::function<void()>> steps;
|
||||||
@@ -93,12 +63,6 @@ static std::vector<std::function<void()>> &getPostLoadSteps()
|
|||||||
return steps;
|
return steps;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::vector<std::function<void()>> &getFinishLoadSteps()
|
|
||||||
{
|
|
||||||
static std::vector<std::function<void()>> steps;
|
|
||||||
return steps;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SavePluginSettings(obs_data_t *obj)
|
void SavePluginSettings(obs_data_t *obj)
|
||||||
{
|
{
|
||||||
GetSwitcher()->SaveSettings(obj);
|
GetSwitcher()->SaveSettings(obj);
|
||||||
@@ -172,7 +136,7 @@ void AddPluginInitStep(std::function<void()> step)
|
|||||||
|
|
||||||
void AddPluginPostLoadStep(std::function<void()> step)
|
void AddPluginPostLoadStep(std::function<void()> step)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
std::lock_guard<std::mutex> lock(initMutex);
|
||||||
getPluginPostLoadSteps().emplace_back(step);
|
getPluginPostLoadSteps().emplace_back(step);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -214,16 +178,6 @@ void RunIntervalResetSteps()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddFinishedLoadingStep(std::function<void()> step)
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(finishLoadMutex);
|
|
||||||
if (loadingFinished) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
getFinishLoadSteps().emplace_back(step);
|
|
||||||
}
|
|
||||||
|
|
||||||
void AddStartStep(std::function<void()> step)
|
void AddStartStep(std::function<void()> step)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(mutex);
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
|||||||
@@ -34,9 +34,6 @@ void RunStartSteps();
|
|||||||
void RunStopSteps();
|
void RunStopSteps();
|
||||||
void RunIntervalResetSteps();
|
void RunIntervalResetSteps();
|
||||||
|
|
||||||
// Steps are executed after OBS_FRONTEND_EVENT_FINISHED_LOADING is fired
|
|
||||||
EXPORT void AddFinishedLoadingStep(std::function<void()>);
|
|
||||||
|
|
||||||
enum class NoMatchBehavior { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 };
|
enum class NoMatchBehavior { NO_SWITCH = 0, SWITCH = 1, RANDOM_SWITCH = 2 };
|
||||||
EXPORT void SetPluginNoMatchBehavior(NoMatchBehavior);
|
EXPORT void SetPluginNoMatchBehavior(NoMatchBehavior);
|
||||||
EXPORT NoMatchBehavior GetPluginNoMatchBehavior();
|
EXPORT NoMatchBehavior GetPluginNoMatchBehavior();
|
||||||
|
|||||||
@@ -65,16 +65,13 @@ ResourceTable::ResourceTable(QWidget *parent, const QString &help,
|
|||||||
[openSettings]() { openSettings(); });
|
[openSettings]() { openSettings(); });
|
||||||
|
|
||||||
auto settingsShortcut = new QShortcut(QKeySequence("F2"), this);
|
auto settingsShortcut = new QShortcut(QKeySequence("F2"), this);
|
||||||
settingsShortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
|
||||||
QWidget::connect(settingsShortcut, &QShortcut::activated, this,
|
QWidget::connect(settingsShortcut, &QShortcut::activated, this,
|
||||||
openSettings);
|
openSettings);
|
||||||
auto removeShortcut = new QShortcut(QKeySequence("Del"), this);
|
auto removeShortcut = new QShortcut(QKeySequence("Del"), this);
|
||||||
removeShortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
|
||||||
QWidget::connect(removeShortcut, &QShortcut::activated, this,
|
QWidget::connect(removeShortcut, &QShortcut::activated, this,
|
||||||
[this]() { Remove(); });
|
[this]() { Remove(); });
|
||||||
|
|
||||||
auto newShortcut = new QShortcut(QKeySequence("Ctrl+N"), this);
|
auto newShortcut = new QShortcut(QKeySequence("Ctrl+N"), this);
|
||||||
newShortcut->setContext(Qt::WidgetWithChildrenShortcut);
|
|
||||||
QWidget::connect(newShortcut, &QShortcut::activated, this,
|
QWidget::connect(newShortcut, &QShortcut::activated, this,
|
||||||
[this]() { Add(); });
|
[this]() { Add(); });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -173,9 +173,10 @@ void PopulateTransitionSelection(QComboBox *sel, bool addCurrent, bool addAny,
|
|||||||
void PopulateWindowSelection(QComboBox *sel, bool addSelect)
|
void PopulateWindowSelection(QComboBox *sel, bool addSelect)
|
||||||
{
|
{
|
||||||
|
|
||||||
const auto windows = GetWindowList();
|
std::vector<std::string> windows;
|
||||||
|
GetWindowList(windows);
|
||||||
|
|
||||||
for (const std::string &window : windows) {
|
for (std::string &window : windows) {
|
||||||
sel->addItem(window.c_str());
|
sel->addItem(window.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -256,7 +257,8 @@ void PopulateMediaSelection(QComboBox *sel, bool addSelect)
|
|||||||
|
|
||||||
void PopulateProcessSelection(QComboBox *sel, bool addSelect)
|
void PopulateProcessSelection(QComboBox *sel, bool addSelect)
|
||||||
{
|
{
|
||||||
auto processes = GetProcessList();
|
QStringList processes;
|
||||||
|
GetProcessList(processes);
|
||||||
processes.sort();
|
processes.sort();
|
||||||
for (QString &process : processes) {
|
for (QString &process : processes) {
|
||||||
sel->addItem(process);
|
sel->addItem(process);
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "source-helpers.hpp"
|
#include "source-helpers.hpp"
|
||||||
#include "canvas-helpers.hpp"
|
|
||||||
|
|
||||||
#include <obs-frontend-api.h>
|
#include <obs-frontend-api.h>
|
||||||
|
|
||||||
@@ -29,43 +28,15 @@ std::string GetWeakSourceName(obs_weak_source_t *weak_source)
|
|||||||
|
|
||||||
OBSWeakSource GetWeakSourceByName(const char *name)
|
OBSWeakSource GetWeakSourceByName(const char *name)
|
||||||
{
|
{
|
||||||
OBSSourceAutoRelease source = obs_get_source_by_name(name);
|
OBSWeakSource weak;
|
||||||
|
obs_source_t *source = obs_get_source_by_name(name);
|
||||||
if (source) {
|
if (source) {
|
||||||
return OBSGetWeakRef(source);
|
weak = obs_source_get_weak_source(source);
|
||||||
|
obs_weak_source_release(weak);
|
||||||
|
obs_source_release(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if LIBOBS_API_VER > MAKE_SEMANTIC_VERSION(31, 1, 0)
|
return weak;
|
||||||
struct SearchData {
|
|
||||||
const char *name;
|
|
||||||
OBSWeakSource &scene;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const auto enumCanvasScenes = [](void *dataPtr,
|
|
||||||
obs_source_t *source) -> bool {
|
|
||||||
auto data = static_cast<SearchData *>(dataPtr);
|
|
||||||
if (strcmp(data->name, obs_source_get_name(source)) == 0) {
|
|
||||||
data->scene = OBSGetWeakRef(source);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
static const auto enumCanvases = [](void *dataPtr,
|
|
||||||
obs_canvas_t *canvas) -> bool {
|
|
||||||
obs_canvas_enum_scenes(canvas, enumCanvasScenes, dataPtr);
|
|
||||||
|
|
||||||
auto data = static_cast<SearchData *>(dataPtr);
|
|
||||||
return data->scene == nullptr;
|
|
||||||
};
|
|
||||||
|
|
||||||
OBSWeakSource weakScene;
|
|
||||||
SearchData searchData{name, weakScene};
|
|
||||||
obs_enum_canvases(enumCanvases, &searchData);
|
|
||||||
return weakScene;
|
|
||||||
#else
|
|
||||||
return nullptr;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
OBSWeakSource GetWeakSourceByQString(const QString &name)
|
OBSWeakSource GetWeakSourceByQString(const QString &name)
|
||||||
|
|||||||
@@ -37,8 +37,8 @@ void CenterSplitterPosition(QSplitter *splitter)
|
|||||||
|
|
||||||
void SetSplitterPositionByFraction(QSplitter *splitter, double fraction)
|
void SetSplitterPositionByFraction(QSplitter *splitter, double fraction)
|
||||||
{
|
{
|
||||||
int value1 = (int)((double)QWIDGETSIZE_MAX * fraction);
|
int value1 = (double)QWIDGETSIZE_MAX * fraction;
|
||||||
int value2 = (int)((double)QWIDGETSIZE_MAX * (1.0 - fraction));
|
int value2 = (double)QWIDGETSIZE_MAX * (1.0 - fraction);
|
||||||
splitter->setSizes(QList<int>() << value1 << value2);
|
splitter->setSizes(QList<int>() << value1 << value2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,9 +58,6 @@ StringListEdit::StringListEdit(
|
|||||||
_filterCallback(filter),
|
_filterCallback(filter),
|
||||||
_preprocessCallback(preprocess)
|
_preprocessCallback(preprocess)
|
||||||
{
|
{
|
||||||
if (_addString.isEmpty()) {
|
|
||||||
_addString = obs_module_text("AdvSceneSwitcher.windowTitle");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void StringListEdit::SetStringList(const StringList &list)
|
void StringListEdit::SetStringList(const StringList &list)
|
||||||
|
|||||||
@@ -10,8 +10,6 @@ namespace advss {
|
|||||||
|
|
||||||
class StringList : public QList<StringVariable> {
|
class StringList : public QList<StringVariable> {
|
||||||
public:
|
public:
|
||||||
using QList<StringVariable>::QList;
|
|
||||||
|
|
||||||
EXPORT 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;
|
||||||
EXPORT bool Load(obs_data_t *obj, const char *name,
|
EXPORT bool Load(obs_data_t *obj, const char *name,
|
||||||
|
|||||||
@@ -2,22 +2,8 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
#ifdef UNIT_TEST
|
|
||||||
std::mutex *GetSwitcherMutex()
|
|
||||||
{
|
|
||||||
static std::mutex m;
|
|
||||||
return &m;
|
|
||||||
}
|
|
||||||
std::unique_lock<std::mutex> *GetSwitcherLoopLock()
|
|
||||||
{
|
|
||||||
static std::mutex m;
|
|
||||||
static std::unique_lock<std::mutex> lock(m);
|
|
||||||
return &lock;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
std::mutex *GetSwitcherMutex();
|
std::mutex *GetSwitcherMutex();
|
||||||
std::unique_lock<std::mutex> *GetSwitcherLoopLock();
|
std::unique_lock<std::mutex> *GetSwitcherLoopLock();
|
||||||
#endif
|
|
||||||
|
|
||||||
std::mutex *GetMutex()
|
std::mutex *GetMutex()
|
||||||
{
|
{
|
||||||
@@ -66,15 +52,4 @@ void Lockable::WithLock(const std::function<void()> &func)
|
|||||||
func();
|
func();
|
||||||
}
|
}
|
||||||
|
|
||||||
SuspendLock::SuspendLock(Lockable &lockable)
|
|
||||||
: _mtx(static_cast<std::mutex &>(lockable._mtx))
|
|
||||||
{
|
|
||||||
_mtx.unlock();
|
|
||||||
}
|
|
||||||
|
|
||||||
SuspendLock::~SuspendLock()
|
|
||||||
{
|
|
||||||
_mtx.lock();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "export-symbol-helper.hpp"
|
#include "export-symbol-helper.hpp"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
|
#include <memory>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -51,24 +52,6 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
PerInstanceMutex _mtx;
|
PerInstanceMutex _mtx;
|
||||||
|
|
||||||
friend class SuspendLock;
|
|
||||||
};
|
|
||||||
|
|
||||||
// RAII guard that temporarily releases a Lockable's per-segment lock.
|
|
||||||
// Use this inside PerformAction() / CheckCondition() to unblock the UI
|
|
||||||
// during long-running operations while still running on the original segment.
|
|
||||||
// The caller MUST be holding the lock (i.e. be inside WithLock) when
|
|
||||||
// constructing this object; the lock is re-acquired on destruction.
|
|
||||||
class EXPORT SuspendLock {
|
|
||||||
public:
|
|
||||||
SuspendLock(Lockable &lockable);
|
|
||||||
~SuspendLock();
|
|
||||||
SuspendLock(const SuspendLock &) = delete;
|
|
||||||
SuspendLock &operator=(const SuspendLock &) = delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::mutex &_mtx;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#include "tab-helpers.hpp"
|
#include "tab-helpers.hpp"
|
||||||
#include "log-helper.hpp"
|
#include "log-helper.hpp"
|
||||||
#include "obs-module-helper.hpp"
|
#include "obs-module-helper.hpp"
|
||||||
#include "plugin-state-helpers.hpp"
|
|
||||||
|
|
||||||
#include <obs.hpp>
|
#include <obs.hpp>
|
||||||
#include <QTabBar>
|
#include <QTabBar>
|
||||||
@@ -34,21 +33,6 @@ struct TabCallbacks {
|
|||||||
static std::unordered_map<const char *, TabCallbacks> createTabCallbacks;
|
static std::unordered_map<const char *, TabCallbacks> createTabCallbacks;
|
||||||
|
|
||||||
static int lastOpenedTab = -1;
|
static int lastOpenedTab = -1;
|
||||||
static bool alwaysShowTabs = false;
|
|
||||||
|
|
||||||
[[maybe_unused]] static bool _ = []() {
|
|
||||||
AddPluginInitStep([]() {
|
|
||||||
AddSaveStep([](obs_data_t *data) {
|
|
||||||
obs_data_set_bool(data, "alwaysShowTabs",
|
|
||||||
alwaysShowTabs);
|
|
||||||
});
|
|
||||||
AddLoadStep([](obs_data_t *data) {
|
|
||||||
alwaysShowTabs =
|
|
||||||
obs_data_get_bool(data, "alwaysShowTabs");
|
|
||||||
});
|
|
||||||
});
|
|
||||||
return true;
|
|
||||||
}();
|
|
||||||
|
|
||||||
void SetTabVisibleByName(QTabWidget *tabWidget, bool visible,
|
void SetTabVisibleByName(QTabWidget *tabWidget, bool visible,
|
||||||
const QString &name)
|
const QString &name)
|
||||||
@@ -213,41 +197,7 @@ void SetupOtherTabs(QTabWidget *tabWidget)
|
|||||||
.c_str());
|
.c_str());
|
||||||
tabWidget->insertTab(0, widget, tabText);
|
tabWidget->insertTab(0, widget, tabText);
|
||||||
callbacks.setupTab(tabWidget);
|
callbacks.setupTab(tabWidget);
|
||||||
|
|
||||||
if (alwaysShowTabs) {
|
|
||||||
tabWidget->setTabVisible(0, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetupShowAllTabsCheckBox(QCheckBox *checkBox, QTabWidget *tabWidget)
|
|
||||||
{
|
|
||||||
const auto stateChanged = [tabWidget](int state) {
|
|
||||||
const bool newState = (state != 0);
|
|
||||||
if (newState == alwaysShowTabs) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
alwaysShowTabs = newState;
|
|
||||||
|
|
||||||
// Only show currently hidden tabs, but don't hide tabs which
|
|
||||||
// are already visible
|
|
||||||
if (!alwaysShowTabs) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto &[name, _] : createTabCallbacks) {
|
|
||||||
const auto localeKey =
|
|
||||||
std::string("AdvSceneSwitcher.") + name +
|
|
||||||
".title";
|
|
||||||
auto tabText = obs_module_text(localeKey.c_str());
|
|
||||||
SetTabVisibleByName(tabWidget, true, tabText);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
checkBox->setChecked(alwaysShowTabs);
|
|
||||||
QWidget::connect(checkBox, &QCheckBox::stateChanged, checkBox,
|
|
||||||
stateChanged);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -2,8 +2,6 @@
|
|||||||
#include "export-symbol-helper.hpp"
|
#include "export-symbol-helper.hpp"
|
||||||
|
|
||||||
#include <obs-data.h>
|
#include <obs-data.h>
|
||||||
|
|
||||||
#include <QCheckBox>
|
|
||||||
#include <QTabWidget>
|
#include <QTabWidget>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
@@ -21,6 +19,5 @@ void SetupOtherTabs(QTabWidget *tabWidget);
|
|||||||
void SaveTabOrder(obs_data_t *obj);
|
void SaveTabOrder(obs_data_t *obj);
|
||||||
void LoadTabOrder(obs_data_t *obj);
|
void LoadTabOrder(obs_data_t *obj);
|
||||||
bool MacroTabIsInFocus();
|
bool MacroTabIsInFocus();
|
||||||
void SetupShowAllTabsCheckBox(QCheckBox *checkBox, QTabWidget *tabWidget);
|
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -5,26 +5,14 @@
|
|||||||
#include "macro-edit.hpp"
|
#include "macro-edit.hpp"
|
||||||
#include "macro-segment.hpp"
|
#include "macro-segment.hpp"
|
||||||
#include "plugin-state-helpers.hpp"
|
#include "plugin-state-helpers.hpp"
|
||||||
#include "sync-helpers.hpp"
|
|
||||||
#include "ui-helpers.hpp"
|
#include "ui-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
#include "variable.hpp"
|
|
||||||
|
|
||||||
#include <QAbstractItemView>
|
|
||||||
#include <QHBoxLayout>
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QPropertyAnimation>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QToolButton>
|
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
#include <QVBoxLayout>
|
#include <QAbstractItemView>
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(advss::TempVariableRef);
|
Q_DECLARE_METATYPE(advss::TempVariableRef);
|
||||||
|
|
||||||
static std::atomic<uint64_t> tempVarInUseGeneration{0};
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
TempVariable::TempVariable(const std::string &id, const std::string &name,
|
TempVariable::TempVariable(const std::string &id, const std::string &name,
|
||||||
@@ -132,60 +120,6 @@ TempVariableRef TempVariable::GetRef() const
|
|||||||
return ref;
|
return ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool refsContain(const std::vector<TempVariableRef> &refs,
|
|
||||||
const TempVariableRef &ref)
|
|
||||||
{
|
|
||||||
for (const auto &r : refs) {
|
|
||||||
if (r == ref) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static bool segmentsReferTo(const T &segments, const TempVariableRef &ref)
|
|
||||||
{
|
|
||||||
for (const auto &segment : segments) {
|
|
||||||
if (refsContain(segment->GetTempVarRefs(), ref)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TempVariable::IsInUse() const
|
|
||||||
{
|
|
||||||
const auto currentGen =
|
|
||||||
tempVarInUseGeneration.load(std::memory_order_relaxed);
|
|
||||||
if (_isInUseCacheGeneration == currentGen) {
|
|
||||||
return _isInUseCache;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool inUse = false;
|
|
||||||
const auto ref = GetRef();
|
|
||||||
|
|
||||||
if (ref.HasValidID()) {
|
|
||||||
for (const auto ¯o : GetAllMacros()) {
|
|
||||||
if (segmentsReferTo(macro->Conditions(), ref) ||
|
|
||||||
segmentsReferTo(macro->Actions(), ref) ||
|
|
||||||
segmentsReferTo(macro->ElseActions(), ref)) {
|
|
||||||
inUse = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_isInUseCache = inUse;
|
|
||||||
_isInUseCacheGeneration = currentGen;
|
|
||||||
return inUse;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IncrementTempVarInUseGeneration()
|
|
||||||
{
|
|
||||||
tempVarInUseGeneration.fetch_add(1, std::memory_order_relaxed);
|
|
||||||
}
|
|
||||||
|
|
||||||
TempVariableRef::SegmentType TempVariableRef::GetType() const
|
TempVariableRef::SegmentType TempVariableRef::GetType() const
|
||||||
{
|
{
|
||||||
auto segment = _segment.lock();
|
auto segment = _segment.lock();
|
||||||
@@ -731,302 +665,13 @@ TempVarSignalManager *TempVarSignalManager::Instance()
|
|||||||
|
|
||||||
void NotifyUIAboutTempVarChange(MacroSegment *segment)
|
void NotifyUIAboutTempVarChange(MacroSegment *segment)
|
||||||
{
|
{
|
||||||
IncrementTempVarInUseGeneration();
|
obs_queue_task(
|
||||||
QueueUITask(
|
OBS_TASK_UI,
|
||||||
[](void *segment) {
|
[](void *segment) {
|
||||||
TempVarSignalManager::Instance()->SegmentTempVarsChanged(
|
TempVarSignalManager::Instance()->SegmentTempVarsChanged(
|
||||||
(MacroSegment *)segment);
|
(MacroSegment *)segment);
|
||||||
},
|
},
|
||||||
segment);
|
segment, false);
|
||||||
}
|
|
||||||
|
|
||||||
TempVarOutputMappingsWidget::TempVarOutputMappingsWidget(QWidget *parent)
|
|
||||||
: QWidget(parent),
|
|
||||||
_rowsLayout(new QVBoxLayout()),
|
|
||||||
_addButton(new QPushButton(
|
|
||||||
obs_module_text("AdvSceneSwitcher.tempVar.outputMappings.add"),
|
|
||||||
this)),
|
|
||||||
_animation(new QPropertyAnimation(this, "maximumHeight", this))
|
|
||||||
{
|
|
||||||
_rowsLayout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
_rowsLayout->setSpacing(2);
|
|
||||||
auto rowsContainer = new QWidget(this);
|
|
||||||
rowsContainer->setLayout(_rowsLayout);
|
|
||||||
|
|
||||||
auto label = new QLabel(
|
|
||||||
obs_module_text("AdvSceneSwitcher.tempVar.outputMappings"),
|
|
||||||
this);
|
|
||||||
|
|
||||||
auto mainLayout = new QVBoxLayout();
|
|
||||||
mainLayout->addWidget(label);
|
|
||||||
mainLayout->addWidget(rowsContainer);
|
|
||||||
mainLayout->addWidget(_addButton);
|
|
||||||
setLayout(mainLayout);
|
|
||||||
|
|
||||||
_animation->setDuration(300);
|
|
||||||
_animation->setEasingCurve(QEasingCurve::InOutQuad);
|
|
||||||
connect(_animation, &QPropertyAnimation::finished, this,
|
|
||||||
&TempVarOutputMappingsWidget::AnimationFinished);
|
|
||||||
|
|
||||||
hide();
|
|
||||||
|
|
||||||
connect(_addButton, &QPushButton::clicked, this,
|
|
||||||
&TempVarOutputMappingsWidget::Add);
|
|
||||||
connect(TempVarSignalManager::Instance(),
|
|
||||||
SIGNAL(SegmentTempVarsChanged(MacroSegment *)), this,
|
|
||||||
SLOT(SegmentTempVarsChanged(MacroSegment *)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void TempVarOutputMappingsWidget::SetSegment(MacroSegment *segment)
|
|
||||||
{
|
|
||||||
_segment = segment;
|
|
||||||
_panelExpanded = false;
|
|
||||||
Rebuild();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TempVarOutputMappingsWidget::Add()
|
|
||||||
{
|
|
||||||
if (!_segment) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto mappings = _segment->GetVarMappings();
|
|
||||||
mappings.push_back(VarMapping{});
|
|
||||||
{
|
|
||||||
auto lock = LockContext();
|
|
||||||
_segment->SetVarMappings(mappings);
|
|
||||||
}
|
|
||||||
Rebuild();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TempVarOutputMappingsWidget::Remove(int rowIdx)
|
|
||||||
{
|
|
||||||
if (!_segment) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto mappings = _segment->GetVarMappings();
|
|
||||||
if (rowIdx < 0 || rowIdx >= (int)mappings.size()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
mappings.erase(mappings.begin() + rowIdx);
|
|
||||||
{
|
|
||||||
auto lock = LockContext();
|
|
||||||
_segment->SetVarMappings(mappings);
|
|
||||||
}
|
|
||||||
Rebuild();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TempVarOutputMappingsWidget::SegmentTempVarsChanged(MacroSegment *segment)
|
|
||||||
{
|
|
||||||
if (segment != _segment) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Re-populate each temp var combobox in case temp vars were added/removed
|
|
||||||
_loading = true;
|
|
||||||
const auto &mappings = _segment->GetVarMappings();
|
|
||||||
for (int i = 0; i < (int)_rows.size(); i++) {
|
|
||||||
auto combo = _rows[i].tempVarCombo;
|
|
||||||
const QSignalBlocker blocker(combo);
|
|
||||||
combo->clear();
|
|
||||||
PopulateTempVarCombo(combo);
|
|
||||||
if (i < (int)mappings.size() &&
|
|
||||||
mappings[i].tempVar.HasValidID()) {
|
|
||||||
QVariant v;
|
|
||||||
v.setValue(mappings[i].tempVar);
|
|
||||||
combo->setCurrentIndex(combo->findData(v));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_loading = false;
|
|
||||||
UpdateVisibility();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TempVarOutputMappingsWidget::WriteBackMappings()
|
|
||||||
{
|
|
||||||
if (_loading || !_segment) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
std::vector<VarMapping> mappings;
|
|
||||||
for (const auto &row : _rows) {
|
|
||||||
VarMapping m;
|
|
||||||
const int idx = row.tempVarCombo->currentIndex();
|
|
||||||
if (idx >= 0) {
|
|
||||||
m.tempVar = row.tempVarCombo->itemData(idx)
|
|
||||||
.value<TempVariableRef>();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto item = row.varSelection->GetCurrentItem();
|
|
||||||
if (!item) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
m.variable = GetWeakVariableByName(item->Name());
|
|
||||||
mappings.push_back(std::move(m));
|
|
||||||
}
|
|
||||||
auto lock = LockContext();
|
|
||||||
_segment->SetVarMappings(mappings);
|
|
||||||
}
|
|
||||||
|
|
||||||
void TempVarOutputMappingsWidget::Rebuild()
|
|
||||||
{
|
|
||||||
_loading = true;
|
|
||||||
|
|
||||||
// Remove all existing row widgets from layout and delete them
|
|
||||||
for (auto &row : _rows) {
|
|
||||||
_rowsLayout->removeWidget(row.container);
|
|
||||||
delete row.container;
|
|
||||||
}
|
|
||||||
_rows.clear();
|
|
||||||
|
|
||||||
if (!_segment) {
|
|
||||||
_loading = false;
|
|
||||||
UpdateVisibility();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto &mappings = _segment->GetVarMappings();
|
|
||||||
for (int i = 0; i < (int)mappings.size(); i++) {
|
|
||||||
const auto &mapping = mappings[i];
|
|
||||||
|
|
||||||
auto container = new QWidget(this);
|
|
||||||
auto rowLayout = new QHBoxLayout();
|
|
||||||
rowLayout->setContentsMargins(0, 0, 0, 0);
|
|
||||||
|
|
||||||
auto tempVarCombo = new FilterComboBox(
|
|
||||||
container,
|
|
||||||
obs_module_text("AdvSceneSwitcher.tempVar.select"));
|
|
||||||
tempVarCombo->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
|
||||||
tempVarCombo->setMaximumWidth(350);
|
|
||||||
tempVarCombo->setDuplicatesEnabled(true);
|
|
||||||
PopulateTempVarCombo(tempVarCombo);
|
|
||||||
if (mapping.tempVar.HasValidID()) {
|
|
||||||
QVariant v;
|
|
||||||
v.setValue(mapping.tempVar);
|
|
||||||
tempVarCombo->setCurrentIndex(
|
|
||||||
tempVarCombo->findData(v));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto arrowLabel = new QLabel(container);
|
|
||||||
{
|
|
||||||
QIcon icon;
|
|
||||||
const auto path = (GetThemeTypeName() == "Light")
|
|
||||||
? "theme:Light/right.svg"
|
|
||||||
: "theme:Dark/right.svg";
|
|
||||||
icon.addFile(QString::fromUtf8(path), QSize(),
|
|
||||||
QIcon::Normal, QIcon::Off);
|
|
||||||
arrowLabel->setPixmap(icon.pixmap(16, 16));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto varSel = new VariableSelection(container);
|
|
||||||
varSel->SetVariable(mapping.variable);
|
|
||||||
|
|
||||||
auto removeBtn = new QToolButton(container);
|
|
||||||
removeBtn->setProperty("themeID", QVariant(QString::fromUtf8(
|
|
||||||
"removeIconSmall")));
|
|
||||||
removeBtn->setProperty(
|
|
||||||
"class", QVariant(QString::fromUtf8("icon-trash")));
|
|
||||||
removeBtn->setToolTip(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.tempVar.outputMappings.remove"));
|
|
||||||
|
|
||||||
rowLayout->addWidget(tempVarCombo, 1);
|
|
||||||
rowLayout->addWidget(arrowLabel);
|
|
||||||
rowLayout->addWidget(varSel, 1);
|
|
||||||
rowLayout->addWidget(removeBtn);
|
|
||||||
container->setLayout(rowLayout);
|
|
||||||
|
|
||||||
_rowsLayout->addWidget(container);
|
|
||||||
_rows.push_back({container, tempVarCombo, varSel});
|
|
||||||
|
|
||||||
const int capturedIdx = i;
|
|
||||||
connect(removeBtn, &QPushButton::clicked, this,
|
|
||||||
[this, capturedIdx]() { Remove(capturedIdx); });
|
|
||||||
connect(tempVarCombo,
|
|
||||||
QOverload<int>::of(&QComboBox::currentIndexChanged),
|
|
||||||
this, &TempVarOutputMappingsWidget::WriteBackMappings);
|
|
||||||
connect(varSel, &VariableSelection::SelectionChanged, this,
|
|
||||||
[this](const QString &) { WriteBackMappings(); });
|
|
||||||
}
|
|
||||||
|
|
||||||
_loading = false;
|
|
||||||
UpdateVisibility();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool TempVarOutputMappingsWidget::IsExpandable() const
|
|
||||||
{
|
|
||||||
return _segment && !_segment->GetOwnTempVars().empty();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TempVarOutputMappingsWidget::SetPanelExpanded(bool expanded)
|
|
||||||
{
|
|
||||||
_panelExpanded = expanded;
|
|
||||||
UpdateHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TempVarOutputMappingsWidget::SetSectionCollapsed(bool collapsed)
|
|
||||||
{
|
|
||||||
_sectionCollapsed = collapsed;
|
|
||||||
UpdateHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TempVarOutputMappingsWidget::AnimateTo(int targetHeight)
|
|
||||||
{
|
|
||||||
if (_animation->state() == QAbstractAnimation::Running) {
|
|
||||||
_animation->stop();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (targetHeight > 0 && !isVisible()) {
|
|
||||||
setMinimumHeight(0);
|
|
||||||
setMaximumHeight(0);
|
|
||||||
show();
|
|
||||||
}
|
|
||||||
|
|
||||||
const int currentMax = maximumHeight();
|
|
||||||
const int currentHeight = (currentMax >= QWIDGETSIZE_MAX) ? height()
|
|
||||||
: currentMax;
|
|
||||||
|
|
||||||
_animationTargetHeight = targetHeight;
|
|
||||||
_animation->setStartValue(currentHeight);
|
|
||||||
_animation->setEndValue(targetHeight);
|
|
||||||
_animation->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TempVarOutputMappingsWidget::AnimationFinished()
|
|
||||||
{
|
|
||||||
if (_animationTargetHeight > 0) {
|
|
||||||
setMaximumHeight(QWIDGETSIZE_MAX);
|
|
||||||
} else {
|
|
||||||
hide();
|
|
||||||
setMaximumHeight(QWIDGETSIZE_MAX);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TempVarOutputMappingsWidget::UpdateHeight()
|
|
||||||
{
|
|
||||||
const bool shouldShow = _panelExpanded && !_sectionCollapsed &&
|
|
||||||
IsExpandable();
|
|
||||||
if (shouldShow) {
|
|
||||||
AnimateTo(sizeHint().height());
|
|
||||||
} else {
|
|
||||||
AnimateTo(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TempVarOutputMappingsWidget::UpdateVisibility()
|
|
||||||
{
|
|
||||||
const bool expandable = IsExpandable();
|
|
||||||
emit ExpandableChanged(expandable);
|
|
||||||
UpdateHeight();
|
|
||||||
}
|
|
||||||
|
|
||||||
void TempVarOutputMappingsWidget::PopulateTempVarCombo(
|
|
||||||
FilterComboBox *combo) const
|
|
||||||
{
|
|
||||||
if (!_segment) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
for (const auto &var : _segment->GetOwnTempVars()) {
|
|
||||||
QVariant v;
|
|
||||||
v.setValue(var.GetRef());
|
|
||||||
combo->addItem(QString::fromStdString(var.Name()), v);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -5,12 +5,11 @@
|
|||||||
#include <obs-data.h>
|
#include <obs-data.h>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <QEnterEvent>
|
||||||
|
#include <QEvent>
|
||||||
|
#include <QStringList>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class QPropertyAnimation;
|
|
||||||
class QPushButton;
|
|
||||||
class QVBoxLayout;
|
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
class Macro;
|
class Macro;
|
||||||
@@ -18,9 +17,6 @@ class MacroEdit;
|
|||||||
class MacroSegment;
|
class MacroSegment;
|
||||||
class TempVariableRef;
|
class TempVariableRef;
|
||||||
class TempVariableSelection;
|
class TempVariableSelection;
|
||||||
class TempVarOutputMappingsWidget;
|
|
||||||
class VariableSelection;
|
|
||||||
struct VarMapping;
|
|
||||||
|
|
||||||
// TempVariables are variables that are local to a given macro.
|
// TempVariables are variables that are local to a given macro.
|
||||||
// They can be created and used by macro segments.
|
// They can be created and used by macro segments.
|
||||||
@@ -48,7 +44,6 @@ public:
|
|||||||
void SetValue(const std::string &val);
|
void SetValue(const std::string &val);
|
||||||
void InvalidateValue();
|
void InvalidateValue();
|
||||||
TempVariableRef GetRef() const;
|
TempVariableRef GetRef() const;
|
||||||
EXPORT bool IsInUse() const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _id = "";
|
std::string _id = "";
|
||||||
@@ -58,8 +53,6 @@ private:
|
|||||||
mutable std::mutex _lastValuesMutex;
|
mutable std::mutex _lastValuesMutex;
|
||||||
std::vector<std::string> _lastValues;
|
std::vector<std::string> _lastValues;
|
||||||
bool _valueIsValid = false;
|
bool _valueIsValid = false;
|
||||||
mutable bool _isInUseCache = false;
|
|
||||||
mutable uint64_t _isInUseCacheGeneration = UINT64_MAX;
|
|
||||||
|
|
||||||
std::weak_ptr<MacroSegment> _segment;
|
std::weak_ptr<MacroSegment> _segment;
|
||||||
friend TempVariableSelection;
|
friend TempVariableSelection;
|
||||||
@@ -129,50 +122,5 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void NotifyUIAboutTempVarChange(MacroSegment *);
|
void NotifyUIAboutTempVarChange(MacroSegment *);
|
||||||
EXPORT void IncrementTempVarInUseGeneration();
|
|
||||||
|
|
||||||
class ADVSS_EXPORT TempVarOutputMappingsWidget : public QWidget {
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
TempVarOutputMappingsWidget(QWidget *parent);
|
|
||||||
void SetSegment(MacroSegment *segment);
|
|
||||||
void SetPanelExpanded(bool expanded);
|
|
||||||
void SetSectionCollapsed(bool collapsed);
|
|
||||||
bool IsExpandable() const;
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void ExpandableChanged(bool);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void Add();
|
|
||||||
void Remove(int rowIdx);
|
|
||||||
void SegmentTempVarsChanged(MacroSegment *segment);
|
|
||||||
void WriteBackMappings();
|
|
||||||
void AnimationFinished();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void Rebuild();
|
|
||||||
void UpdateVisibility();
|
|
||||||
void UpdateHeight();
|
|
||||||
void AnimateTo(int targetHeight);
|
|
||||||
void PopulateTempVarCombo(FilterComboBox *combo) const;
|
|
||||||
|
|
||||||
struct MappingRow {
|
|
||||||
QWidget *container;
|
|
||||||
FilterComboBox *tempVarCombo;
|
|
||||||
VariableSelection *varSelection;
|
|
||||||
};
|
|
||||||
|
|
||||||
MacroSegment *_segment = nullptr;
|
|
||||||
QVBoxLayout *_rowsLayout;
|
|
||||||
QPushButton *_addButton;
|
|
||||||
std::vector<MappingRow> _rows;
|
|
||||||
bool _loading = false;
|
|
||||||
bool _panelExpanded = false;
|
|
||||||
bool _sectionCollapsed = false;
|
|
||||||
int _animationTargetHeight = 0;
|
|
||||||
QPropertyAnimation *_animation;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -81,13 +81,13 @@ void GenericVariableSpinbox::DisableVariableSelection()
|
|||||||
|
|
||||||
void GenericVariableSpinbox::setMinimum(double value)
|
void GenericVariableSpinbox::setMinimum(double value)
|
||||||
{
|
{
|
||||||
_fixedValueInt->setMinimum((int)value);
|
_fixedValueInt->setMinimum(value);
|
||||||
_fixedValueDouble->setMinimum(value);
|
_fixedValueDouble->setMinimum(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVariableSpinbox::setMaximum(double value)
|
void GenericVariableSpinbox::setMaximum(double value)
|
||||||
{
|
{
|
||||||
_fixedValueInt->setMaximum((int)value);
|
_fixedValueInt->setMaximum(value);
|
||||||
_fixedValueDouble->setMaximum(value);
|
_fixedValueDouble->setMaximum(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,12 +9,11 @@ void StringVariable::Resolve() const
|
|||||||
_resolvedValue = _value;
|
_resolvedValue = _value;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
const auto lastChange = GetLastVariableChangeTime();
|
if (_lastResolve == GetLastVariableChangeTime()) {
|
||||||
if (_lastResolve == lastChange) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
_resolvedValue = SubstitueVariables(_value);
|
_resolvedValue = SubstitueVariables(_value);
|
||||||
_lastResolve = lastChange;
|
_lastResolve = GetLastVariableChangeTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
StringVariable::operator std::string() const
|
StringVariable::operator std::string() const
|
||||||
@@ -82,7 +81,7 @@ std::string SubstitueVariables(std::string str)
|
|||||||
const auto &variable = std::dynamic_pointer_cast<Variable>(v);
|
const auto &variable = std::dynamic_pointer_cast<Variable>(v);
|
||||||
const std::string pattern = "${" + variable->Name() + "}";
|
const std::string pattern = "${" + variable->Name() + "}";
|
||||||
if (ReplaceAll(str, pattern, variable->Value(false))) {
|
if (ReplaceAll(str, pattern, variable->Value(false))) {
|
||||||
variable->MarkAsUsed();
|
variable->UpdateLastUsed();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return str;
|
return str;
|
||||||
|
|||||||
@@ -12,23 +12,16 @@ static std::deque<std::shared_ptr<Item>> variables;
|
|||||||
|
|
||||||
// Keep track of the last time a variable was changed to save some work when
|
// Keep track of the last time a variable was changed to save some work when
|
||||||
// when resolving strings containing variables, etc.
|
// when resolving strings containing variables, etc.
|
||||||
static std::mutex lastVariableChangeMutex;
|
|
||||||
static std::chrono::high_resolution_clock::time_point lastVariableChange{};
|
static std::chrono::high_resolution_clock::time_point lastVariableChange{};
|
||||||
|
|
||||||
static void setLastVariableChangeTime()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(lastVariableChangeMutex);
|
|
||||||
lastVariableChange = std::chrono::high_resolution_clock::now();
|
|
||||||
}
|
|
||||||
|
|
||||||
Variable::Variable() : Item()
|
Variable::Variable() : Item()
|
||||||
{
|
{
|
||||||
setLastVariableChangeTime();
|
lastVariableChange = std::chrono::high_resolution_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable::~Variable()
|
Variable::~Variable()
|
||||||
{
|
{
|
||||||
setLastVariableChangeTime();
|
lastVariableChange = std::chrono::high_resolution_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Variable::Load(obs_data_t *obj)
|
void Variable::Load(obs_data_t *obj)
|
||||||
@@ -44,7 +37,7 @@ void Variable::Load(obs_data_t *obj)
|
|||||||
SetValue(_defaultValue);
|
SetValue(_defaultValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
setLastVariableChangeTime();
|
lastVariableChange = std::chrono::high_resolution_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Variable::Save(obs_data_t *obj) const
|
void Variable::Save(obs_data_t *obj) const
|
||||||
@@ -52,11 +45,8 @@ void Variable::Save(obs_data_t *obj) const
|
|||||||
Item::Save(obj);
|
Item::Save(obj);
|
||||||
obs_data_set_int(obj, "saveAction", static_cast<int>(_saveAction));
|
obs_data_set_int(obj, "saveAction", static_cast<int>(_saveAction));
|
||||||
|
|
||||||
{
|
if (_saveAction == SaveAction::SAVE) {
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
obs_data_set_string(obj, "value", _value.c_str());
|
||||||
if (_saveAction == SaveAction::SAVE) {
|
|
||||||
obs_data_set_string(obj, "value", _value.c_str());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
obs_data_set_string(obj, "defaultValue", _defaultValue.c_str());
|
obs_data_set_string(obj, "defaultValue", _defaultValue.c_str());
|
||||||
@@ -72,18 +62,6 @@ std::string Variable::Value(bool updateLastUsed) const
|
|||||||
return _value;
|
return _value;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Variable::GetPreviousValue() const
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
|
||||||
return _previousValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
int Variable::GetValueChangeCount() const
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
|
||||||
return _valueChangeCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::optional<double> Variable::DoubleValue() const
|
std::optional<double> Variable::DoubleValue() const
|
||||||
{
|
{
|
||||||
return GetDouble(Value());
|
return GetDouble(Value());
|
||||||
@@ -101,11 +79,8 @@ void Variable::SetValue(const std::string &value)
|
|||||||
_value = value;
|
_value = value;
|
||||||
|
|
||||||
UpdateLastUsed();
|
UpdateLastUsed();
|
||||||
if (_previousValue != _value) {
|
UpdateLastChanged();
|
||||||
_lastChanged = std::chrono::high_resolution_clock::now();
|
lastVariableChange = std::chrono::high_resolution_clock::now();
|
||||||
++_valueChangeCount;
|
|
||||||
}
|
|
||||||
setLastVariableChangeTime();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Variable::SetValue(double value)
|
void Variable::SetValue(double value)
|
||||||
@@ -115,7 +90,6 @@ void Variable::SetValue(double value)
|
|||||||
|
|
||||||
std::optional<uint64_t> Variable::GetSecondsSinceLastUse() const
|
std::optional<uint64_t> Variable::GetSecondsSinceLastUse() const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
|
||||||
if (_lastUsed.time_since_epoch().count() == 0) {
|
if (_lastUsed.time_since_epoch().count() == 0) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -127,7 +101,6 @@ std::optional<uint64_t> Variable::GetSecondsSinceLastUse() const
|
|||||||
|
|
||||||
std::optional<uint64_t> Variable::GetSecondsSinceLastChange() const
|
std::optional<uint64_t> Variable::GetSecondsSinceLastChange() const
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
|
||||||
if (_lastChanged.time_since_epoch().count() == 0) {
|
if (_lastChanged.time_since_epoch().count() == 0) {
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -143,10 +116,12 @@ void Variable::UpdateLastUsed() const
|
|||||||
_lastUsed = std::chrono::high_resolution_clock::now();
|
_lastUsed = std::chrono::high_resolution_clock::now();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Variable::MarkAsUsed() const
|
void Variable::UpdateLastChanged()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
if (_previousValue != _value) {
|
||||||
UpdateLastUsed();
|
_lastChanged = std::chrono::high_resolution_clock::now();
|
||||||
|
++_valueChangeCount;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void populateSaveActionSelection(QComboBox *list)
|
static void populateSaveActionSelection(QComboBox *list)
|
||||||
@@ -231,7 +206,7 @@ bool VariableSettingsDialog::AskForSettings(QWidget *parent, Variable &settings)
|
|||||||
dialog._defaultValue->toPlainText().toStdString();
|
dialog._defaultValue->toPlainText().toStdString();
|
||||||
settings._saveAction =
|
settings._saveAction =
|
||||||
static_cast<Variable::SaveAction>(dialog._save->currentIndex());
|
static_cast<Variable::SaveAction>(dialog._save->currentIndex());
|
||||||
setLastVariableChangeTime();
|
lastVariableChange = std::chrono::high_resolution_clock::now();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -486,7 +461,6 @@ void ImportVariables(obs_data_t *data)
|
|||||||
|
|
||||||
std::chrono::high_resolution_clock::time_point GetLastVariableChangeTime()
|
std::chrono::high_resolution_clock::time_point GetLastVariableChangeTime()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(lastVariableChangeMutex);
|
|
||||||
return lastVariableChange;
|
return lastVariableChange;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -34,15 +34,16 @@ public:
|
|||||||
EXPORT std::string Value(bool updateLastUsed = true) const;
|
EXPORT std::string Value(bool updateLastUsed = true) const;
|
||||||
EXPORT std::optional<double> DoubleValue() const;
|
EXPORT std::optional<double> DoubleValue() const;
|
||||||
EXPORT std::optional<int> IntValue() const;
|
EXPORT std::optional<int> IntValue() const;
|
||||||
std::string GetPreviousValue() const;
|
std::string GetPreviousValue() const { return _previousValue; };
|
||||||
std::string GetDefaultValue() const { return _defaultValue; }
|
std::string GetDefaultValue() const { return _defaultValue; }
|
||||||
EXPORT void SetValue(const std::string &value);
|
EXPORT void SetValue(const std::string &value);
|
||||||
void SetValue(double value);
|
void SetValue(double value);
|
||||||
SaveAction GetSaveAction() const { return _saveAction; }
|
SaveAction GetSaveAction() const { return _saveAction; }
|
||||||
int GetValueChangeCount() const;
|
int GetValueChangeCount() const { return _valueChangeCount; }
|
||||||
std::optional<uint64_t> GetSecondsSinceLastUse() const;
|
std::optional<uint64_t> GetSecondsSinceLastUse() const;
|
||||||
std::optional<uint64_t> GetSecondsSinceLastChange() const;
|
std::optional<uint64_t> GetSecondsSinceLastChange() const;
|
||||||
void MarkAsUsed() const;
|
void UpdateLastUsed() const;
|
||||||
|
void UpdateLastChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SaveAction _saveAction = SaveAction::DONT_SAVE;
|
SaveAction _saveAction = SaveAction::DONT_SAVE;
|
||||||
@@ -54,8 +55,6 @@ private:
|
|||||||
mutable std::chrono::high_resolution_clock::time_point _lastChanged;
|
mutable std::chrono::high_resolution_clock::time_point _lastChanged;
|
||||||
mutable std::mutex _mutex;
|
mutable std::mutex _mutex;
|
||||||
|
|
||||||
void UpdateLastUsed() const;
|
|
||||||
|
|
||||||
friend VariableSelection;
|
friend VariableSelection;
|
||||||
friend VariableSettingsDialog;
|
friend VariableSettingsDialog;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -133,9 +133,9 @@ const std::vector<std::string> getOBSWindows()
|
|||||||
return lastDoneHelper->windows;
|
return lastDoneHelper->windows;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> GetWindowList()
|
void GetWindowList(std::vector<std::string> &windows)
|
||||||
{
|
{
|
||||||
std::vector<std::string> windows;
|
windows.resize(0);
|
||||||
EnumWindowsWithMetro(GetTitleCB, reinterpret_cast<LPARAM>(&windows));
|
EnumWindowsWithMetro(GetTitleCB, reinterpret_cast<LPARAM>(&windows));
|
||||||
|
|
||||||
// Also add OBS windows
|
// Also add OBS windows
|
||||||
@@ -147,10 +147,20 @@ std::vector<std::string> GetWindowList()
|
|||||||
|
|
||||||
// Add entry for OBS Studio itself - see GetCurrentWindowTitle()
|
// Add entry for OBS Studio itself - see GetCurrentWindowTitle()
|
||||||
windows.emplace_back("OBS");
|
windows.emplace_back("OBS");
|
||||||
return windows;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetCurrentWindowTitle()
|
void GetWindowList(QStringList &windows)
|
||||||
|
{
|
||||||
|
windows.clear();
|
||||||
|
|
||||||
|
std::vector<std::string> w;
|
||||||
|
GetWindowList(w);
|
||||||
|
for (auto window : w) {
|
||||||
|
windows << QString::fromStdString(window);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GetCurrentWindowTitle(std::string &title)
|
||||||
{
|
{
|
||||||
HWND window = GetForegroundWindow();
|
HWND window = GetForegroundWindow();
|
||||||
DWORD pid;
|
DWORD pid;
|
||||||
@@ -168,15 +178,15 @@ std::string GetCurrentWindowTitle()
|
|||||||
//
|
//
|
||||||
// So instead rely on Qt to get the title of the active window.
|
// So instead rely on Qt to get the title of the active window.
|
||||||
if (GetCurrentProcessId() == pid) {
|
if (GetCurrentProcessId() == pid) {
|
||||||
auto obsWindow = QApplication::activeWindow();
|
auto window = QApplication::activeWindow();
|
||||||
if (obsWindow) {
|
if (window) {
|
||||||
return obsWindow->windowTitle().toStdString();
|
title = window->windowTitle().toStdString();
|
||||||
|
} else {
|
||||||
|
title = "OBS";
|
||||||
}
|
}
|
||||||
return "OBS";
|
return;
|
||||||
}
|
}
|
||||||
std::string title;
|
|
||||||
GetWindowTitle(window, title);
|
GetWindowTitle(window, title);
|
||||||
return title;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HWND getHWNDfromTitle(const std::string &title)
|
static HWND getHWNDfromTitle(const std::string &title)
|
||||||
@@ -251,14 +261,6 @@ std::optional<std::string> GetTextInWindow(const std::string &window)
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD pid = 0;
|
|
||||||
DWORD thid = 0;
|
|
||||||
thid = GetWindowThreadProcessId(hwnd, &pid);
|
|
||||||
// Calling CoCreateInstance() on the OBS windows might cause a deadlock
|
|
||||||
if (GetCurrentProcessId() == pid) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
IUIAutomation *automation = nullptr;
|
IUIAutomation *automation = nullptr;
|
||||||
auto hr = CoCreateInstance(__uuidof(CUIAutomation), nullptr,
|
auto hr = CoCreateInstance(__uuidof(CUIAutomation), nullptr,
|
||||||
CLSCTX_INPROC_SERVER,
|
CLSCTX_INPROC_SERVER,
|
||||||
@@ -340,22 +342,22 @@ bool IsFullscreen(const std::string &title)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList GetProcessList()
|
void GetProcessList(QStringList &processes)
|
||||||
{
|
{
|
||||||
QStringList processes;
|
|
||||||
HANDLE procSnapshot;
|
HANDLE procSnapshot;
|
||||||
PROCESSENTRY32 procEntry;
|
PROCESSENTRY32 procEntry;
|
||||||
|
|
||||||
procSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
procSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||||
if (procSnapshot == INVALID_HANDLE_VALUE) {
|
if (procSnapshot == INVALID_HANDLE_VALUE) {
|
||||||
return processes;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
procEntry.dwSize = sizeof(PROCESSENTRY32);
|
procEntry.dwSize = sizeof(PROCESSENTRY32);
|
||||||
|
|
||||||
if (!Process32First(procSnapshot, &procEntry)) {
|
if (!Process32First(procSnapshot, &procEntry)) {
|
||||||
CloseHandle(procSnapshot);
|
CloseHandle(procSnapshot);
|
||||||
return processes;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
@@ -373,10 +375,9 @@ QStringList GetProcessList()
|
|||||||
} while (Process32Next(procSnapshot, &procEntry));
|
} while (Process32Next(procSnapshot, &procEntry));
|
||||||
|
|
||||||
CloseHandle(procSnapshot);
|
CloseHandle(procSnapshot);
|
||||||
return processes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString getForegroundProcessNameStr()
|
static void GetForegroundProcessName(QString &proc)
|
||||||
{
|
{
|
||||||
// only checks if the current foreground window is from the same executable,
|
// only checks if the current foreground window is from the same executable,
|
||||||
// may return true for any window from a program
|
// may return true for any window from a program
|
||||||
@@ -387,90 +388,31 @@ static QString getForegroundProcessNameStr()
|
|||||||
HANDLE process = OpenProcess(
|
HANDLE process = OpenProcess(
|
||||||
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
|
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
|
||||||
if (process == NULL) {
|
if (process == NULL) {
|
||||||
return {};
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
WCHAR executablePath[600];
|
WCHAR executablePath[600];
|
||||||
GetModuleFileNameEx(process, 0, executablePath, 600);
|
GetModuleFileNameEx(process, 0, executablePath, 600);
|
||||||
CloseHandle(process);
|
CloseHandle(process);
|
||||||
|
|
||||||
return QString::fromWCharArray(executablePath)
|
proc = QString::fromWCharArray(executablePath)
|
||||||
.split(QRegularExpression("(/|\\\\)"))
|
.split(QRegularExpression("(/|\\\\)"))
|
||||||
.back();
|
.back();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetForegroundProcessName()
|
void GetForegroundProcessName(std::string &proc)
|
||||||
{
|
{
|
||||||
return getForegroundProcessNameStr().toStdString();
|
QString temp;
|
||||||
}
|
GetForegroundProcessName(temp);
|
||||||
|
proc = temp.toStdString();
|
||||||
std::string GetForegroundProcessPath()
|
|
||||||
{
|
|
||||||
HWND foregroundWindow = GetForegroundWindow();
|
|
||||||
DWORD processId = 0;
|
|
||||||
GetWindowThreadProcessId(foregroundWindow, &processId);
|
|
||||||
|
|
||||||
HANDLE process = OpenProcess(
|
|
||||||
PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId);
|
|
||||||
if (process == NULL) {
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
WCHAR executablePath[600];
|
|
||||||
GetModuleFileNameEx(process, 0, executablePath, 600);
|
|
||||||
CloseHandle(process);
|
|
||||||
|
|
||||||
return QString::fromWCharArray(executablePath).toStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
QStringList GetProcessPathsFromName(const QString &name)
|
|
||||||
{
|
|
||||||
QStringList paths;
|
|
||||||
HANDLE procSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
|
||||||
if (procSnapshot == INVALID_HANDLE_VALUE) {
|
|
||||||
return paths;
|
|
||||||
}
|
|
||||||
|
|
||||||
PROCESSENTRY32 procEntry;
|
|
||||||
procEntry.dwSize = sizeof(PROCESSENTRY32);
|
|
||||||
|
|
||||||
if (!Process32First(procSnapshot, &procEntry)) {
|
|
||||||
CloseHandle(procSnapshot);
|
|
||||||
return paths;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
QString exeName = QString::fromWCharArray(procEntry.szExeFile);
|
|
||||||
if (exeName != name) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
HANDLE process =
|
|
||||||
OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
|
|
||||||
FALSE, procEntry.th32ProcessID);
|
|
||||||
if (process == NULL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
WCHAR executablePath[600];
|
|
||||||
if (GetModuleFileNameEx(process, 0, executablePath, 600)) {
|
|
||||||
QString path = QString::fromWCharArray(executablePath);
|
|
||||||
if (!paths.contains(path)) {
|
|
||||||
paths.append(path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
CloseHandle(process);
|
|
||||||
} while (Process32Next(procSnapshot, &procEntry));
|
|
||||||
|
|
||||||
CloseHandle(procSnapshot);
|
|
||||||
return paths;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsInFocus(const QString &executable)
|
bool IsInFocus(const QString &executable)
|
||||||
{
|
{
|
||||||
// only checks if the current foreground window is from the same executable,
|
// only checks if the current foreground window is from the same executable,
|
||||||
// may return true for any window from a program
|
// may return true for any window from a program
|
||||||
const auto foregroundProc = getForegroundProcessNameStr();
|
QString foregroundProc;
|
||||||
|
GetForegroundProcessName(foregroundProc);
|
||||||
|
|
||||||
// True if executable switch equals current window
|
// True if executable switch equals current window
|
||||||
bool equals = (executable == foregroundProc);
|
bool equals = (executable == foregroundProc);
|
||||||
|
|||||||
@@ -25,8 +25,6 @@ target_sources(
|
|||||||
macro-action-obs-settings.hpp
|
macro-action-obs-settings.hpp
|
||||||
macro-action-osc.cpp
|
macro-action-osc.cpp
|
||||||
macro-action-osc.hpp
|
macro-action-osc.hpp
|
||||||
macro-action-play-audio.cpp
|
|
||||||
macro-action-play-audio.hpp
|
|
||||||
macro-action-plugin-state.cpp
|
macro-action-plugin-state.cpp
|
||||||
macro-action-plugin-state.hpp
|
macro-action-plugin-state.hpp
|
||||||
macro-action-profile.cpp
|
macro-action-profile.cpp
|
||||||
@@ -59,8 +57,6 @@ target_sources(
|
|||||||
macro-action-sequence.hpp
|
macro-action-sequence.hpp
|
||||||
macro-action-source.cpp
|
macro-action-source.cpp
|
||||||
macro-action-source.hpp
|
macro-action-source.hpp
|
||||||
macro-action-source-interaction.cpp
|
|
||||||
macro-action-source-interaction.hpp
|
|
||||||
macro-action-streaming.cpp
|
macro-action-streaming.cpp
|
||||||
macro-action-streaming.hpp
|
macro-action-streaming.hpp
|
||||||
macro-action-studio-mode.cpp
|
macro-action-studio-mode.cpp
|
||||||
@@ -148,24 +144,12 @@ target_sources(
|
|||||||
|
|
||||||
target_sources(
|
target_sources(
|
||||||
${PROJECT_NAME}
|
${PROJECT_NAME}
|
||||||
PRIVATE utils/source-interaction-recorder.cpp
|
PRIVATE utils/audio-helpers.cpp
|
||||||
utils/source-interaction-recorder.hpp
|
|
||||||
utils/source-interaction-step.cpp
|
|
||||||
utils/source-interaction-step.hpp
|
|
||||||
utils/source-interaction-step-edit.cpp
|
|
||||||
utils/source-interaction-step-edit.hpp
|
|
||||||
utils/source-interaction-step-list.cpp
|
|
||||||
utils/source-interaction-step-list.hpp
|
|
||||||
utils/source-preview-widget.cpp
|
|
||||||
utils/source-preview-widget.hpp
|
|
||||||
utils/audio-helpers.cpp
|
|
||||||
utils/audio-helpers.hpp
|
utils/audio-helpers.hpp
|
||||||
utils/connection-manager.cpp
|
utils/connection-manager.cpp
|
||||||
utils/connection-manager.hpp
|
utils/connection-manager.hpp
|
||||||
utils/cursor-helpers.cpp
|
utils/cursor-helpers.cpp
|
||||||
utils/cursor-helpers.hpp
|
utils/cursor-helpers.hpp
|
||||||
utils/day-of-week-selector.cpp
|
|
||||||
utils/day-of-week-selector.hpp
|
|
||||||
utils/filter-selection.cpp
|
utils/filter-selection.cpp
|
||||||
utils/filter-selection.hpp
|
utils/filter-selection.hpp
|
||||||
utils/hotkey-helpers.cpp
|
utils/hotkey-helpers.cpp
|
||||||
@@ -182,8 +166,6 @@ target_sources(
|
|||||||
utils/scene-item-selection.hpp
|
utils/scene-item-selection.hpp
|
||||||
utils/scene-item-transform-helpers.cpp
|
utils/scene-item-transform-helpers.cpp
|
||||||
utils/scene-item-transform-helpers.hpp
|
utils/scene-item-transform-helpers.hpp
|
||||||
utils/transition-helpers.cpp
|
|
||||||
utils/transition-helpers.hpp
|
|
||||||
utils/source-properties-button.cpp
|
utils/source-properties-button.cpp
|
||||||
utils/source-properties-button.hpp
|
utils/source-properties-button.hpp
|
||||||
utils/source-settings-helpers.cpp
|
utils/source-settings-helpers.cpp
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ void MacroActionFileEdit::UpdateEntryData()
|
|||||||
}
|
}
|
||||||
|
|
||||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||||
_filePath->SetPath(_entryData->_file);
|
_filePath->SetPath(QString::fromStdString(_entryData->_file));
|
||||||
_text->setPlainText(_entryData->_text);
|
_text->setPlainText(_entryData->_text);
|
||||||
|
|
||||||
adjustSize();
|
adjustSize();
|
||||||
|
|||||||
@@ -9,15 +9,6 @@ namespace advss {
|
|||||||
|
|
||||||
const std::string MacroActionFilter::id = "filter";
|
const std::string MacroActionFilter::id = "filter";
|
||||||
|
|
||||||
std::vector<TempVariableRef> MacroActionFilter::GetTempVarRefs() const
|
|
||||||
{
|
|
||||||
auto refs = MacroSegment::GetTempVarRefs();
|
|
||||||
if (_tempVar.HasValidID()) {
|
|
||||||
refs.push_back(_tempVar);
|
|
||||||
}
|
|
||||||
return refs;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroActionFilter::_registered = MacroActionFactory::Register(
|
bool MacroActionFilter::_registered = MacroActionFactory::Register(
|
||||||
MacroActionFilter::id,
|
MacroActionFilter::id,
|
||||||
{MacroActionFilter::Create, MacroActionFilterEdit::Create,
|
{MacroActionFilter::Create, MacroActionFilterEdit::Create,
|
||||||
@@ -437,7 +428,6 @@ void MacroActionFilterEdit::SelectionChanged(const TempVariableRef &var)
|
|||||||
{
|
{
|
||||||
GUARD_LOADING_AND_LOCK();
|
GUARD_LOADING_AND_LOCK();
|
||||||
_entryData->_tempVar = var;
|
_entryData->_tempVar = var;
|
||||||
IncrementTempVarInUseGeneration();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionFilterEdit::SelectionChanged(const SourceSetting &setting)
|
void MacroActionFilterEdit::SelectionChanged(const SourceSetting &setting)
|
||||||
|
|||||||
@@ -41,8 +41,6 @@ public:
|
|||||||
SettingsInputMethod _settingsInputMethod =
|
SettingsInputMethod _settingsInputMethod =
|
||||||
SettingsInputMethod::INDIVIDUAL_MANUAL;
|
SettingsInputMethod::INDIVIDUAL_MANUAL;
|
||||||
|
|
||||||
std::vector<TempVariableRef> GetTempVarRefs() const;
|
|
||||||
|
|
||||||
SourceSelection _source;
|
SourceSelection _source;
|
||||||
FilterSelection _filter;
|
FilterSelection _filter;
|
||||||
Action _action = Action::ENABLE;
|
Action _action = Action::ENABLE;
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ static void waitHelper(std::unique_lock<std::mutex> *lock, Macro *macro,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionMedia::PerformActionHelper(obs_source_t *source)
|
void MacroActionMedia::PerformActionHelper(obs_source_t *source) const
|
||||||
{
|
{
|
||||||
obs_media_state state = obs_source_media_get_state(source);
|
obs_media_state state = obs_source_media_get_state(source);
|
||||||
|
|
||||||
@@ -130,7 +130,6 @@ void MacroActionMedia::PerformActionHelper(obs_source_t *source)
|
|||||||
SeekToPercentage(source);
|
SeekToPercentage(source);
|
||||||
break;
|
break;
|
||||||
case Action::WAIT_FOR_PLAYBACK_STOP: {
|
case Action::WAIT_FOR_PLAYBACK_STOP: {
|
||||||
SuspendLock suspendLock(*this);
|
|
||||||
std::unique_lock<std::mutex> lock(*GetMutex());
|
std::unique_lock<std::mutex> lock(*GetMutex());
|
||||||
waitHelper(&lock, GetMacro(), source);
|
waitHelper(&lock, GetMacro(), source);
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public:
|
|||||||
SceneSelection _scene;
|
SceneSelection _scene;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void PerformActionHelper(obs_source_t *);
|
void PerformActionHelper(obs_source_t *) const;
|
||||||
void SeekToPercentage(obs_source_t *source) const;
|
void SeekToPercentage(obs_source_t *source) const;
|
||||||
|
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user