mirror of
https://github.com/WarmUpTill/SceneSwitcher.git
synced 2026-09-07 09:05:57 -05:00
Compare commits
53 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
17d9b73b9a | ||
|
|
d6185a6099 | ||
|
|
41c06b9edb | ||
|
|
d8807077da | ||
|
|
34e125f82d | ||
|
|
d670b6d07e | ||
|
|
7b0f985f18 | ||
|
|
212be923f6 | ||
|
|
88fcb57e9f | ||
|
|
9b609c118f | ||
|
|
37c398d37a | ||
|
|
a51b7f6b13 | ||
|
|
808fd84b83 | ||
|
|
57bcea15f5 | ||
|
|
4e51b56b9b | ||
|
|
ef5cf41d34 | ||
|
|
911e79ea6a | ||
|
|
d586177de0 | ||
|
|
202c36646c | ||
|
|
ab5102f5ca | ||
|
|
e612fb99f6 | ||
|
|
691e77a69a | ||
|
|
930118c61f | ||
|
|
1e05f2f2ce | ||
|
|
ae25b4d023 | ||
|
|
af055a12a1 | ||
|
|
7de28eedd3 | ||
|
|
8dfe81f522 | ||
|
|
a1d8ae291d | ||
|
|
eb6989527d | ||
|
|
2986a5dd96 | ||
|
|
816ee9b244 | ||
|
|
51b53bf948 | ||
|
|
2c5121ee94 | ||
|
|
6a58684854 | ||
|
|
0b622fdbed | ||
|
|
3bce8e075f | ||
|
|
f598d84ea1 | ||
|
|
d7a244e80e | ||
|
|
408002e96a | ||
|
|
50da3d3210 | ||
|
|
9e13067769 | ||
|
|
821e768e76 | ||
|
|
4d2179448b | ||
|
|
40d9002470 | ||
|
|
7f1e310ca6 | ||
|
|
66d02f4683 | ||
|
|
0aae1b9978 | ||
|
|
db50822b05 | ||
|
|
63a545b293 | ||
|
|
bc0497d2c9 | ||
|
|
37226a3a4c | ||
|
|
9f15fbe47c |
@@ -6,15 +6,6 @@
|
|||||||
"autosort": true
|
"autosort": true
|
||||||
},
|
},
|
||||||
"additional_commands": {
|
"additional_commands": {
|
||||||
"find_qt": {
|
|
||||||
"flags": [],
|
|
||||||
"kwargs": {
|
|
||||||
"COMPONENTS": "+",
|
|
||||||
"COMPONENTS_WIN": "+",
|
|
||||||
"COMPONENTS_MACOS": "+",
|
|
||||||
"COMPONENTS_LINUX": "+"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"set_target_properties_obs": {
|
"set_target_properties_obs": {
|
||||||
"pargs": 1,
|
"pargs": 1,
|
||||||
"flags": [],
|
"flags": [],
|
||||||
|
|||||||
1
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
1
.github/ISSUE_TEMPLATE/bug_report.yaml
vendored
@@ -20,6 +20,7 @@ body:
|
|||||||
- macOS 13
|
- macOS 13
|
||||||
- macOS 12
|
- macOS 12
|
||||||
- macOS 11
|
- macOS 11
|
||||||
|
- Ubuntu 24.04
|
||||||
- Ubuntu 23.10
|
- Ubuntu 23.10
|
||||||
- Ubuntu 22.04
|
- Ubuntu 22.04
|
||||||
- Other
|
- Other
|
||||||
|
|||||||
2
.github/scripts/.Aptfile
vendored
2
.github/scripts/.Aptfile
vendored
@@ -9,5 +9,5 @@ package 'libxtst-dev'
|
|||||||
package 'libxss-dev'
|
package 'libxss-dev'
|
||||||
package 'libopencv-dev'
|
package 'libopencv-dev'
|
||||||
package 'libtesseract-dev'
|
package 'libtesseract-dev'
|
||||||
package 'libprocps-dev'
|
package 'libproc2-dev'
|
||||||
package 'libusb-1.0-0-dev'
|
package 'libusb-1.0-0-dev'
|
||||||
7
.github/scripts/.build-deps.zsh
vendored
7
.github/scripts/.build-deps.zsh
vendored
@@ -480,12 +480,7 @@ Usage: %B${functrace[1]%:*}%b <option> [<options>]
|
|||||||
popd
|
popd
|
||||||
;;
|
;;
|
||||||
linux)
|
linux)
|
||||||
# Hacky workaround to support libproc2 with Ubuntu 22 build environment
|
# Nothing to do for now
|
||||||
local lsb_version=$(lsb_release -r | cut -f 2 || true)
|
|
||||||
if [[ "${lsb_version}" == '22.04' ]] {
|
|
||||||
sudo apt install ${project_root}/build-aux/CI/linux/ubuntu22/libproc2-0_4.0.2-3_amd64.deb
|
|
||||||
sudo apt install ${project_root}/build-aux/CI/linux/ubuntu22/libproc2-dev_4.0.2-3_amd64.deb
|
|
||||||
}
|
|
||||||
;;
|
;;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
0
.github/test
vendored
0
.github/test
vendored
2
.github/workflows/build-debian.yml
vendored
2
.github/workflows/build-debian.yml
vendored
@@ -43,7 +43,7 @@ jobs:
|
|||||||
# devscripts and libobs-dev are needed but they were already installed
|
# devscripts and libobs-dev are needed but they were already installed
|
||||||
# from check_libobs_revision and install_frontend_header sections.
|
# from check_libobs_revision and install_frontend_header sections.
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt install cmake debhelper libcurl4-openssl-dev libxss-dev libxtst-dev qtbase5-dev libopencv-dev libprocps-dev
|
sudo apt install build-essential cmake debhelper libcurl4-openssl-dev libxss-dev libxtst-dev qt6-base-dev libopencv-dev libproc2-dev
|
||||||
- name: build
|
- name: build
|
||||||
run: |
|
run: |
|
||||||
debuild --no-lintian --no-sign
|
debuild --no-lintian --no-sign
|
||||||
|
|||||||
8
.github/workflows/build-project.yaml
vendored
8
.github/workflows/build-project.yaml
vendored
@@ -10,7 +10,7 @@ env:
|
|||||||
jobs:
|
jobs:
|
||||||
check-event:
|
check-event:
|
||||||
name: Check GitHub Event Data 🔎
|
name: Check GitHub Event Data 🔎
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-latest
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -177,7 +177,7 @@ jobs:
|
|||||||
|
|
||||||
ubuntu-build:
|
ubuntu-build:
|
||||||
name: Build for Ubuntu 🐧
|
name: Build for Ubuntu 🐧
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-latest
|
||||||
needs: check-event
|
needs: check-event
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
@@ -241,14 +241,14 @@ jobs:
|
|||||||
- name: Upload Artifacts 📡
|
- name: Upload Artifacts 📡
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ steps.setup.outputs.pluginName }}-${{ steps.setup.outputs.pluginVersion }}-ubuntu-22.04-x86_64-${{ needs.check-event.outputs.commitHash }}
|
name: ${{ steps.setup.outputs.pluginName }}-${{ steps.setup.outputs.pluginVersion }}-ubuntu-24.04-x86_64-${{ needs.check-event.outputs.commitHash }}
|
||||||
path: ${{ github.workspace }}/release/${{ steps.setup.outputs.pluginName }}-*-x86_64*.*
|
path: ${{ github.workspace }}/release/${{ steps.setup.outputs.pluginName }}-*-x86_64*.*
|
||||||
|
|
||||||
- name: Upload debug symbol artifacts 🪲
|
- name: Upload debug symbol artifacts 🪲
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
if: ${{ fromJSON(needs.check-event.outputs.package) }}
|
if: ${{ fromJSON(needs.check-event.outputs.package) }}
|
||||||
with:
|
with:
|
||||||
name: ${{ steps.setup.outputs.pluginName }}-${{ steps.setup.outputs.pluginVersion }}-ubuntu-22.04-x86_64-${{ needs.check-event.outputs.commitHash }}-dbgsym
|
name: ${{ steps.setup.outputs.pluginName }}-${{ steps.setup.outputs.pluginVersion }}-ubuntu-24.04-x86_64-${{ needs.check-event.outputs.commitHash }}-dbgsym
|
||||||
path: ${{ github.workspace }}/release/${{ steps.setup.outputs.pluginName }}-*-x86_64*-dbgsym.ddeb
|
path: ${{ github.workspace }}/release/${{ steps.setup.outputs.pluginName }}-*-x86_64*-dbgsym.ddeb
|
||||||
|
|
||||||
windows-build:
|
windows-build:
|
||||||
|
|||||||
4
.github/workflows/check-format.yaml
vendored
4
.github/workflows/check-format.yaml
vendored
@@ -3,7 +3,7 @@ on:
|
|||||||
workflow_call:
|
workflow_call:
|
||||||
jobs:
|
jobs:
|
||||||
clang-format:
|
clang-format:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@@ -15,7 +15,7 @@ jobs:
|
|||||||
failCondition: error
|
failCondition: error
|
||||||
|
|
||||||
cmake-format:
|
cmake-format:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
|
|||||||
4
.github/workflows/push.yaml
vendored
4
.github/workflows/push.yaml
vendored
@@ -31,7 +31,7 @@ jobs:
|
|||||||
create-release:
|
create-release:
|
||||||
name: Create Release 🛫
|
name: Create Release 🛫
|
||||||
if: github.ref_type == 'tag'
|
if: github.ref_type == 'tag'
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-latest
|
||||||
needs: build-project
|
needs: build-project
|
||||||
defaults:
|
defaults:
|
||||||
run:
|
run:
|
||||||
@@ -77,7 +77,7 @@ jobs:
|
|||||||
variants=(
|
variants=(
|
||||||
'windows-x64;zip|exe'
|
'windows-x64;zip|exe'
|
||||||
'macos-universal;tar.xz|pkg'
|
'macos-universal;tar.xz|pkg'
|
||||||
'ubuntu-22.04-x86_64;tar.xz|deb|ddeb'
|
'ubuntu-24.04-x86_64;tar.xz|deb|ddeb'
|
||||||
'sources;tar.xz'
|
'sources;tar.xz'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,12 @@ if(BUILD_OUT_OF_TREE)
|
|||||||
include(helpers)
|
include(helpers)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
# OBS 31 no longer defines find_qt so check if we need to include it for in-tree
|
||||||
|
# builds
|
||||||
|
if(NOT COMMAND find_qt)
|
||||||
|
include("${CMAKE_CURRENT_SOURCE_DIR}/cmake/common/helpers_common.cmake")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(LIB_NAME "${PROJECT_NAME}-lib")
|
set(LIB_NAME "${PROJECT_NAME}-lib")
|
||||||
add_library(${PROJECT_NAME} MODULE)
|
add_library(${PROJECT_NAME} MODULE)
|
||||||
add_library(${LIB_NAME} SHARED)
|
add_library(${LIB_NAME} SHARED)
|
||||||
@@ -289,9 +295,9 @@ include(cmake/common/advss_helpers.cmake)
|
|||||||
setup_obs_lib_dependency(${LIB_NAME})
|
setup_obs_lib_dependency(${LIB_NAME})
|
||||||
setup_obs_lib_dependency(${PROJECT_NAME})
|
setup_obs_lib_dependency(${PROJECT_NAME})
|
||||||
|
|
||||||
find_qt(COMPONENTS Widgets Core)
|
find_package(Qt6 REQUIRED COMPONENTS Widgets Core)
|
||||||
target_link_libraries(${PROJECT_NAME} PRIVATE Qt::Core Qt::Widgets)
|
target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Widgets)
|
||||||
target_link_libraries(${LIB_NAME} PRIVATE Qt::Core Qt::Widgets)
|
target_link_libraries(${LIB_NAME} PRIVATE Qt6::Core Qt6::Widgets)
|
||||||
target_compile_options(
|
target_compile_options(
|
||||||
${PROJECT_NAME}
|
${PROJECT_NAME}
|
||||||
PRIVATE
|
PRIVATE
|
||||||
@@ -407,7 +413,12 @@ else()
|
|||||||
set(PROCESS_CONDITION_SUPPORTED 1)
|
set(PROCESS_CONDITION_SUPPORTED 1)
|
||||||
endif()
|
endif()
|
||||||
if(PROCPS2_INCLUDE_DIR)
|
if(PROCPS2_INCLUDE_DIR)
|
||||||
message(STATUS "${PROJECT_NAME} using libproc2")
|
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)
|
||||||
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)
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ Build-Depends: cmake,
|
|||||||
libcurl4-openssl-dev,
|
libcurl4-openssl-dev,
|
||||||
libobs-dev,
|
libobs-dev,
|
||||||
libxtst-dev,
|
libxtst-dev,
|
||||||
qtbase5-dev,
|
qt6-base-dev,
|
||||||
libxss-dev,
|
libxss-dev,
|
||||||
libopencv-dev
|
libopencv-dev
|
||||||
Standards-Version: 4.6.0
|
Standards-Version: 4.6.0
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||||
|
|
||||||
export QT_SELECT = qt5
|
export QT_SELECT = qt6
|
||||||
|
|
||||||
%:
|
%:
|
||||||
dh $@
|
dh $@
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
@@ -283,8 +283,8 @@ endfunction()
|
|||||||
|
|
||||||
function(setup_advss_plugin target)
|
function(setup_advss_plugin target)
|
||||||
setup_obs_lib_dependency(${target})
|
setup_obs_lib_dependency(${target})
|
||||||
find_qt(COMPONENTS Widgets Core)
|
find_package(Qt6 REQUIRED COMPONENTS Widgets Core)
|
||||||
target_link_libraries(${target} PRIVATE Qt::Core Qt::Widgets)
|
target_link_libraries(${target} PRIVATE Qt6::Core Qt6::Widgets)
|
||||||
|
|
||||||
set_target_properties(
|
set_target_properties(
|
||||||
${target}
|
${target}
|
||||||
|
|||||||
@@ -17,85 +17,6 @@ if(NOT QT_VERSION)
|
|||||||
set_property(CACHE QT_VERSION PROPERTY STRINGS AUTO 5 6)
|
set_property(CACHE QT_VERSION PROPERTY STRINGS AUTO 5 6)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# find_qt: Macro to find best possible Qt version for use with the project:
|
|
||||||
macro(find_qt)
|
|
||||||
set(multiValueArgs COMPONENTS COMPONENTS_WIN COMPONENTS_MAC COMPONENTS_LINUX)
|
|
||||||
cmake_parse_arguments(find_qt "" "${oneValueArgs}" "${multiValueArgs}"
|
|
||||||
${ARGN})
|
|
||||||
|
|
||||||
# Do not use versionless targets in the first step to avoid Qt::Core being
|
|
||||||
# clobbered by later opportunistic find_package runs
|
|
||||||
set(QT_NO_CREATE_VERSIONLESS_TARGETS TRUE)
|
|
||||||
|
|
||||||
message(DEBUG "Start Qt version discovery...")
|
|
||||||
# Loop until _QT_VERSION is set or FATAL_ERROR aborts script execution early
|
|
||||||
while(NOT _QT_VERSION)
|
|
||||||
message(DEBUG "QT_VERSION set to ${QT_VERSION}")
|
|
||||||
if(QT_VERSION STREQUAL AUTO AND NOT qt_test_version)
|
|
||||||
set(qt_test_version 6)
|
|
||||||
elseif(NOT QT_VERSION STREQUAL AUTO)
|
|
||||||
set(qt_test_version ${QT_VERSION})
|
|
||||||
endif()
|
|
||||||
message(DEBUG "Attempting to find Qt${qt_test_version}")
|
|
||||||
|
|
||||||
find_package(
|
|
||||||
Qt${qt_test_version}
|
|
||||||
COMPONENTS Core
|
|
||||||
QUIET)
|
|
||||||
|
|
||||||
if(TARGET Qt${qt_test_version}::Core)
|
|
||||||
set(_QT_VERSION
|
|
||||||
${qt_test_version}
|
|
||||||
CACHE INTERNAL "")
|
|
||||||
message(STATUS "Qt version found: ${_QT_VERSION}")
|
|
||||||
unset(qt_test_version)
|
|
||||||
break()
|
|
||||||
elseif(QT_VERSION STREQUAL AUTO)
|
|
||||||
if(qt_test_version EQUAL 6)
|
|
||||||
message(WARNING "Qt6 was not found, falling back to Qt5")
|
|
||||||
set(qt_test_version 5)
|
|
||||||
continue()
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
message(FATAL_ERROR "Neither Qt6 nor Qt5 found.")
|
|
||||||
endwhile()
|
|
||||||
|
|
||||||
# Enable versionless targets for the remaining Qt components
|
|
||||||
set(QT_NO_CREATE_VERSIONLESS_TARGETS FALSE)
|
|
||||||
|
|
||||||
set(qt_components ${find_qt_COMPONENTS})
|
|
||||||
if(OS_WINDOWS)
|
|
||||||
list(APPEND qt_components ${find_qt_COMPONENTS_WIN})
|
|
||||||
elseif(OS_MACOS)
|
|
||||||
list(APPEND qt_components ${find_qt_COMPONENTS_MAC})
|
|
||||||
else()
|
|
||||||
list(APPEND qt_components ${find_qt_COMPONENTS_LINUX})
|
|
||||||
endif()
|
|
||||||
message(DEBUG "Trying to find Qt components ${qt_components}...")
|
|
||||||
|
|
||||||
find_package(Qt${_QT_VERSION} REQUIRED ${qt_components})
|
|
||||||
|
|
||||||
list(APPEND qt_components Core)
|
|
||||||
|
|
||||||
if("Gui" IN_LIST find_qt_COMPONENTS_LINUX)
|
|
||||||
list(APPEND qt_components "GuiPrivate")
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Check for versionless targets of each requested component and create if
|
|
||||||
# necessary
|
|
||||||
foreach(component IN LISTS qt_components)
|
|
||||||
message(DEBUG "Checking for target Qt::${component}")
|
|
||||||
if(NOT TARGET Qt::${component} AND TARGET Qt${_QT_VERSION}::${component})
|
|
||||||
add_library(Qt::${component} INTERFACE IMPORTED)
|
|
||||||
set_target_properties(
|
|
||||||
Qt::${component} PROPERTIES INTERFACE_LINK_LIBRARIES
|
|
||||||
Qt${_QT_VERSION}::${component})
|
|
||||||
endif()
|
|
||||||
set_property(TARGET Qt::${component} PROPERTY INTERFACE_COMPILE_FEATURES "")
|
|
||||||
endforeach()
|
|
||||||
|
|
||||||
endmacro()
|
|
||||||
|
|
||||||
# check_uuid: Helper function to check for valid UUID
|
# check_uuid: Helper function to check for valid UUID
|
||||||
function(check_uuid uuid_string return_value)
|
function(check_uuid uuid_string return_value)
|
||||||
set(valid_uuid TRUE)
|
set(valid_uuid TRUE)
|
||||||
|
|||||||
@@ -769,6 +769,11 @@ AdvSceneSwitcher.condition.streamDeck.checkData="Check data field"
|
|||||||
AdvSceneSwitcher.condition.streamDeck.startListen="Start listening"
|
AdvSceneSwitcher.condition.streamDeck.startListen="Start listening"
|
||||||
AdvSceneSwitcher.condition.streamDeck.stopListen="Stop listening"
|
AdvSceneSwitcher.condition.streamDeck.stopListen="Stop listening"
|
||||||
AdvSceneSwitcher.condition.streamDeck.pluginDownload="<html><head/><body><p>The Stream Deck plugin can be found <a href=\"https://github.com/WarmUpTill/advanced-scene-switcher-streamdeck-plugin/releases\"><span style=\" text-decoration: underline; color:#268bd2;\">here on GitHub</span></a>.</p></body></html>"
|
AdvSceneSwitcher.condition.streamDeck.pluginDownload="<html><head/><body><p>The Stream Deck plugin can be found <a href=\"https://github.com/WarmUpTill/advanced-scene-switcher-streamdeck-plugin/releases\"><span style=\" text-decoration: underline; color:#268bd2;\">here on GitHub</span></a>.</p></body></html>"
|
||||||
|
AdvSceneSwitcher.condition.gameCapture="Game capture"
|
||||||
|
AdvSceneSwitcher.condition.gameCapture.entry="{{sources}}hooked a game."
|
||||||
|
|
||||||
|
AdvSceneSwitcher.condition.screenshot="Screenshot"
|
||||||
|
AdvSceneSwitcher.condition.screenshot.entry="A screenshot was taken"
|
||||||
|
|
||||||
# Macro Actions
|
# Macro Actions
|
||||||
AdvSceneSwitcher.action.unknown="Unknown action"
|
AdvSceneSwitcher.action.unknown="Unknown action"
|
||||||
@@ -1054,13 +1059,13 @@ AdvSceneSwitcher.action.http.type.post="POST"
|
|||||||
AdvSceneSwitcher.action.http.entry.line1="Send{{method}}to{{url}}"
|
AdvSceneSwitcher.action.http.entry.line1="Send{{method}}to{{url}}"
|
||||||
AdvSceneSwitcher.action.http.entry.line2="Timeout:{{timeout}}seconds"
|
AdvSceneSwitcher.action.http.entry.line2="Timeout:{{timeout}}seconds"
|
||||||
AdvSceneSwitcher.action.variable="Variable"
|
AdvSceneSwitcher.action.variable="Variable"
|
||||||
AdvSceneSwitcher.action.variable.type.set="Set to fixed value"
|
AdvSceneSwitcher.action.variable.type.set="Set to value"
|
||||||
AdvSceneSwitcher.action.variable.type.append="Append"
|
AdvSceneSwitcher.action.variable.type.append="Append"
|
||||||
AdvSceneSwitcher.action.variable.type.appendVar="Append variable"
|
AdvSceneSwitcher.action.variable.type.appendVar="Append variable"
|
||||||
AdvSceneSwitcher.action.variable.type.increment="Increment"
|
AdvSceneSwitcher.action.variable.type.increment="Increment"
|
||||||
AdvSceneSwitcher.action.variable.type.decrement="Decrement"
|
AdvSceneSwitcher.action.variable.type.decrement="Decrement"
|
||||||
AdvSceneSwitcher.action.variable.type.setActionValue="Set to action value"
|
AdvSceneSwitcher.action.variable.type.setActionValue="Set to action value (legacy)"
|
||||||
AdvSceneSwitcher.action.variable.type.setConditionValue="Set to condition value"
|
AdvSceneSwitcher.action.variable.type.setConditionValue="Set to condition value (legacy)"
|
||||||
AdvSceneSwitcher.action.variable.type.roundToInt="Round to nearest integer"
|
AdvSceneSwitcher.action.variable.type.roundToInt="Round to nearest integer"
|
||||||
AdvSceneSwitcher.action.variable.type.subString="Set to substring of current value"
|
AdvSceneSwitcher.action.variable.type.subString="Set to substring of current value"
|
||||||
AdvSceneSwitcher.action.variable.type.findAndReplace="Find and replace in current value"
|
AdvSceneSwitcher.action.variable.type.findAndReplace="Find and replace in current value"
|
||||||
@@ -1078,6 +1083,7 @@ AdvSceneSwitcher.action.variable.type.truncateValue="Truncate current value"
|
|||||||
AdvSceneSwitcher.action.variable.type.swapValues="Swap variable values"
|
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.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"
|
||||||
@@ -1092,6 +1098,7 @@ AdvSceneSwitcher.action.variable.findAndReplace.replace="Text to replace with"
|
|||||||
AdvSceneSwitcher.action.variable.findAndReplace.replace.tooltip="Using \1, \2, etc. to represent first, second, etc. capture groups is supported."
|
AdvSceneSwitcher.action.variable.findAndReplace.replace.tooltip="Using \1, \2, etc. to represent first, second, etc. capture groups is supported."
|
||||||
AdvSceneSwitcher.action.variable.subString.begin="Beginning"
|
AdvSceneSwitcher.action.variable.subString.begin="Beginning"
|
||||||
AdvSceneSwitcher.action.variable.subString.all="All"
|
AdvSceneSwitcher.action.variable.subString.all="All"
|
||||||
|
AdvSceneSwitcher.action.variable.generateInteger="Only generate integers"
|
||||||
AdvSceneSwitcher.action.variable.invalidSelection="Invalid selection!"
|
AdvSceneSwitcher.action.variable.invalidSelection="Invalid selection!"
|
||||||
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Getting variable values from %1 actions is not supported!"
|
AdvSceneSwitcher.action.variable.actionNoVariableSupport="Getting variable values from %1 actions is not supported!"
|
||||||
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Getting variable values from %1 conditions is not supported!"
|
AdvSceneSwitcher.action.variable.conditionNoVariableSupport="Getting variable values from %1 conditions is not supported!"
|
||||||
@@ -1104,6 +1111,7 @@ AdvSceneSwitcher.action.variable.entry.substringRegex="Assign value of{{regexMat
|
|||||||
AdvSceneSwitcher.action.variable.entry.findAndReplace="{{findStr}}{{findRegex}}{{replaceStr}}"
|
AdvSceneSwitcher.action.variable.entry.findAndReplace="{{findStr}}{{findRegex}}{{replaceStr}}"
|
||||||
AdvSceneSwitcher.action.variable.entry.userInput.customPrompt="{{useCustomPrompt}}Use custom prompt{{inputPrompt}}"
|
AdvSceneSwitcher.action.variable.entry.userInput.customPrompt="{{useCustomPrompt}}Use custom prompt{{inputPrompt}}"
|
||||||
AdvSceneSwitcher.action.variable.entry.userInput.placeholder="{{useInputPlaceholder}}Fill with placeholder{{inputPlaceholder}}"
|
AdvSceneSwitcher.action.variable.entry.userInput.placeholder="{{useInputPlaceholder}}Fill with placeholder{{inputPlaceholder}}"
|
||||||
|
AdvSceneSwitcher.action.variable.entry.randomNumber="Generate random number in range from{{randomNumberStart}}to{{randomNumberEnd}}"
|
||||||
AdvSceneSwitcher.action.projector="Projector"
|
AdvSceneSwitcher.action.projector="Projector"
|
||||||
AdvSceneSwitcher.action.projector.type.source="Source"
|
AdvSceneSwitcher.action.projector.type.source="Source"
|
||||||
AdvSceneSwitcher.action.projector.type.scene="Scene"
|
AdvSceneSwitcher.action.projector.type.scene="Scene"
|
||||||
@@ -1134,10 +1142,15 @@ 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.sendChatMessage="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.reward.getInfo="Get channel points reward information"
|
||||||
|
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.entry.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}}{{pointsReward}}"
|
||||||
AdvSceneSwitcher.action.twitch.entry.chat="Using account{{account}}{{actions}}on{{channel}}{{streamTitle}}{{category}}{{markerDescription}}{{clipHasDelay}}{{duration}}{{announcementColor}}"
|
AdvSceneSwitcher.action.twitch.entry.chat="Using account{{account}}{{actions}}on{{channel}}"
|
||||||
|
AdvSceneSwitcher.action.twitch.entry.user.getInfo="Using account{{account}}{{actions}}for{{userInfoQueryType}}{{userLogin}}{{userId}}"
|
||||||
|
AdvSceneSwitcher.action.twitch.entry.reward.getInfo="Using account{{account}}{{actions}}for channel{{channel}}{{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"
|
||||||
@@ -1147,6 +1160,8 @@ AdvSceneSwitcher.action.twitch.announcement.blue="Blue"
|
|||||||
AdvSceneSwitcher.action.twitch.announcement.green="Green"
|
AdvSceneSwitcher.action.twitch.announcement.green="Green"
|
||||||
AdvSceneSwitcher.action.twitch.announcement.orange="Orange"
|
AdvSceneSwitcher.action.twitch.announcement.orange="Orange"
|
||||||
AdvSceneSwitcher.action.twitch.announcement.purple="Purple"
|
AdvSceneSwitcher.action.twitch.announcement.purple="Purple"
|
||||||
|
AdvSceneSwitcher.action.twitch.user.getInfo.queryType.id="User Id"
|
||||||
|
AdvSceneSwitcher.action.twitch.user.getInfo.queryType.login="User login"
|
||||||
AdvSceneSwitcher.action.clipboard="Clipboard"
|
AdvSceneSwitcher.action.clipboard="Clipboard"
|
||||||
AdvSceneSwitcher.action.clipboard.type.copy.text="Copy text"
|
AdvSceneSwitcher.action.clipboard.type.copy.text="Copy text"
|
||||||
AdvSceneSwitcher.action.clipboard.type.copy.image="Copy image"
|
AdvSceneSwitcher.action.clipboard.type.copy.image="Copy image"
|
||||||
@@ -1211,7 +1226,7 @@ AdvSceneSwitcher.validation.text.maxLength="Only %1 characters are allowed in th
|
|||||||
AdvSceneSwitcher.variable.select="--select variable--"
|
AdvSceneSwitcher.variable.select="--select variable--"
|
||||||
AdvSceneSwitcher.variable.add="Add new variable"
|
AdvSceneSwitcher.variable.add="Add new variable"
|
||||||
AdvSceneSwitcher.variable.configure="Configure variable settings"
|
AdvSceneSwitcher.variable.configure="Configure variable settings"
|
||||||
AdvSceneSwitcher.variable.invalid="Invalid varialbe selection"
|
AdvSceneSwitcher.variable.invalid="Invalid variable selection"
|
||||||
AdvSceneSwitcher.variable.name="Name:"
|
AdvSceneSwitcher.variable.name="Name:"
|
||||||
AdvSceneSwitcher.variable.value="Current value:"
|
AdvSceneSwitcher.variable.value="Current value:"
|
||||||
AdvSceneSwitcher.variable.save="Save / load behavior"
|
AdvSceneSwitcher.variable.save="Save / load behavior"
|
||||||
@@ -1590,12 +1605,21 @@ AdvSceneSwitcher.tempVar.twitch.started_at.shoutoutReceived="Shoutout time"
|
|||||||
AdvSceneSwitcher.tempVar.twitch.started_at.shoutoutReceived.description="The UTC timestamp (in RFC3339 format) of when the moderator sent the Shoutout."
|
AdvSceneSwitcher.tempVar.twitch.started_at.shoutoutReceived.description="The UTC timestamp (in RFC3339 format) of when the moderator sent the Shoutout."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.id.reward="Reward ID"
|
AdvSceneSwitcher.tempVar.twitch.id.reward="Reward ID"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.id.redemption="Redemption ID"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_id.reward="User ID redeeming the reward"
|
AdvSceneSwitcher.tempVar.twitch.user_id.reward="User ID redeeming the reward"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_login.reward="User login redeeming the reward"
|
AdvSceneSwitcher.tempVar.twitch.user_login.reward="User login redeeming the reward"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_name.reward="User name redeeming the reward"
|
AdvSceneSwitcher.tempVar.twitch.user_name.reward="User name redeeming the reward"
|
||||||
AdvSceneSwitcher.tempVar.twitch.user_input.reward="User input for reward"
|
AdvSceneSwitcher.tempVar.twitch.user_input.reward="User input for reward"
|
||||||
AdvSceneSwitcher.tempVar.twitch.reward.reward="Reward Information"
|
AdvSceneSwitcher.tempVar.twitch.reward.reward="Reward Information (JSON)"
|
||||||
AdvSceneSwitcher.tempVar.twitch.reward.reward.description="Basic information about the reward that was redeemed, at the time it was redeemed."
|
AdvSceneSwitcher.tempVar.twitch.reward.reward.description="Basic information about the reward that was redeemed in JSON form, at the time it was redeemed."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reward.id.reward="Reward ID"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reward.id.reward.description="The ID that uniquely identifies the reward."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reward.title.reward="Reward title"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reward.title.reward.description="The reward’s title."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reward.prompt.reward="Reward prompt"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reward.prompt.reward.description="The prompt displayed to the viewer if user input is required."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reward.cost.reward="Reward cost"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.reward.cost.reward.description="The reward’s cost, in Channel Points."
|
||||||
AdvSceneSwitcher.tempVar.twitch.status.reward="Reward status"
|
AdvSceneSwitcher.tempVar.twitch.status.reward="Reward status"
|
||||||
AdvSceneSwitcher.tempVar.twitch.status.reward.description="Defaults to unfulfilled. Possible values are unknown, unfulfilled, fulfilled, and canceled."
|
AdvSceneSwitcher.tempVar.twitch.status.reward.description="Defaults to unfulfilled. Possible values are unknown, unfulfilled, fulfilled, and canceled."
|
||||||
AdvSceneSwitcher.tempVar.twitch.redeemed_at.reward="Redemption time"
|
AdvSceneSwitcher.tempVar.twitch.redeemed_at.reward="Redemption time"
|
||||||
@@ -1610,22 +1634,37 @@ AdvSceneSwitcher.tempVar.twitch.title.reward="Reward title"
|
|||||||
AdvSceneSwitcher.tempVar.twitch.cost.reward="Reward cost"
|
AdvSceneSwitcher.tempVar.twitch.cost.reward="Reward cost"
|
||||||
AdvSceneSwitcher.tempVar.twitch.prompt.reward="Reward description"
|
AdvSceneSwitcher.tempVar.twitch.prompt.reward="Reward description"
|
||||||
AdvSceneSwitcher.tempVar.twitch.is_user_input_required.reward="Reward requires user input"
|
AdvSceneSwitcher.tempVar.twitch.is_user_input_required.reward="Reward requires user input"
|
||||||
AdvSceneSwitcher.tempVar.twitch.should_redemptions_skip_request_queue.reward="Redemptions skip request queue"
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.should_redemptions_skip_request_queue.reward.description="Should redemptions be set to fulfilled status immediately when redeemed and skip the request queue instead of the normal unfulfilled status."
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.max_per_stream.reward="Reward maximum per stream"
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.max_per_user_per_stream.reward="Reward maximum per user per stream"
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.background_color.reward="Reward background color"
|
AdvSceneSwitcher.tempVar.twitch.background_color.reward="Reward background color"
|
||||||
AdvSceneSwitcher.tempVar.twitch.image.reward="Reward image"
|
AdvSceneSwitcher.tempVar.twitch.image.reward="Reward image (JSON)"
|
||||||
AdvSceneSwitcher.tempVar.twitch.image.reward.description="Set of custom images of 1x, 2x and 4x sizes for the reward. Can be null if no images have been uploaded."
|
AdvSceneSwitcher.tempVar.twitch.image.reward.description="Set of custom images of 1x, 2x and 4x sizes for the reward. Can be null if no images have been uploaded."
|
||||||
AdvSceneSwitcher.tempVar.twitch.default_image.reward="Reward default image"
|
AdvSceneSwitcher.tempVar.twitch.image.url_4x.reward="Reward image URL"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.image.url_4x.reward.description="The URL to the custom image for the reward. This field is null if the broadcaster didn’t upload images."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.default_image.reward="Reward default image (JSON)"
|
||||||
AdvSceneSwitcher.tempVar.twitch.default_image.reward.description="Set of default images of 1x, 2x and 4x sizes for the reward."
|
AdvSceneSwitcher.tempVar.twitch.default_image.reward.description="Set of default images of 1x, 2x and 4x sizes for the reward."
|
||||||
AdvSceneSwitcher.tempVar.twitch.global_cooldown.reward="Reward cooldown"
|
AdvSceneSwitcher.tempVar.twitch.default_image.url_4x.reward="Reward default image URL"
|
||||||
AdvSceneSwitcher.tempVar.twitch.global_cooldown.reward.description="Whether a cooldown is enabled and what the cooldown is in seconds."
|
AdvSceneSwitcher.tempVar.twitch.default_image.url_4x.reward.description="The URL to the default image for the reward."
|
||||||
AdvSceneSwitcher.tempVar.twitch.cooldown_expires_at.reward="Reward cooldown expiration"
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.cooldown_expires_at.reward.description="Timestamp of the cooldown expiration. null if the reward isn’t on cooldown."
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.redemptions_redeemed_current_stream.reward="Redemption count"
|
AdvSceneSwitcher.tempVar.twitch.redemptions_redeemed_current_stream.reward="Redemption count"
|
||||||
AdvSceneSwitcher.tempVar.twitch.redemptions_redeemed_current_stream.reward.description="The number of redemptions redeemed during the current live stream. Counts against the max_per_stream limit. null if the broadcasters stream isn’t live or max_per_stream isn’t enabled."
|
AdvSceneSwitcher.tempVar.twitch.redemptions_redeemed_current_stream.reward.description="The number of redemptions redeemed during the current live stream. Counts against the max_per_stream limit. null if the broadcasters stream isn’t live or max_per_stream isn’t enabled."
|
||||||
AdvSceneSwitcher.tempVar.twitch.redemptions_redeemed_current_stream.reward.description="The number of redemptions redeemed during the current live stream. Counts against the max_per_stream limit. null if the broadcasters stream isn’t live or max_per_stream isn’t enabled."
|
AdvSceneSwitcher.tempVar.twitch.should_redemptions_skip_request_queue.reward="Redemptions skip request queue"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.should_redemptions_skip_request_queue.reward.description="Should redemptions be set to fulfilled status immediately when redeemed and skip the request queue instead of the normal unfulfilled status."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.max_per_stream.reward="Maximum redemptions per stream (JSON)"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.max_per_stream.is_enabled.reward="Maximum redemptions per stream enabled"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.max_per_stream.is_enabled.reward.description="A Boolean value that determines whether the reward applies a limit on the number of redemptions allowed per live stream. Is true if the reward applies a limit."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.max_per_stream.max_per_stream.reward="Maximum redemptions per stream"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.max_per_stream.max_per_stream.reward.description="The maximum number of redemptions allowed per live stream."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.max_per_user_per_stream.reward="Reward maximum per user per stream (JSON)"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.max_per_user_per_stream.is_enabled.reward="Maximum redemptions per user per stream enabled"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.max_per_user_per_stream.is_enabled.reward.description="A Boolean value that determines whether the reward applies a limit on the number of redemptions allowed per user per live stream. Is true if the reward applies a limit."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.max_per_user_per_stream.max_per_user_per_stream.reward="Maximum redemptions per user per stream"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.max_per_user_per_stream.max_per_user_per_stream.reward.description="The settings used to determine whether to apply a maximum to the number of redemptions allowed per user per live stream."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.global_cooldown.reward="Global cooldown (JSON)"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.global_cooldown.reward.description="Whether a cooldown is enabled and what the cooldown is in seconds."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.global_cooldown.is_enabled.reward="Global cooldown enabled"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.global_cooldown.is_enabled.reward.description="A Boolean value that determines whether to apply a cooldown period. Is true if a cooldown period is enabled."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.global_cooldown.global_cooldown_seconds.reward="Global cooldown"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.global_cooldown.global_cooldown_seconds.reward.description="The cooldown period, in seconds."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.cooldown_expires_at.reward="Reward cooldown expiration"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.cooldown_expires_at.reward.description="Timestamp of the cooldown expiration. null if the reward isn’t on cooldown."
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.twitch.charity_name="Charity name"
|
AdvSceneSwitcher.tempVar.twitch.charity_name="Charity name"
|
||||||
AdvSceneSwitcher.tempVar.twitch.charity_description="Charity description"
|
AdvSceneSwitcher.tempVar.twitch.charity_description="Charity description"
|
||||||
@@ -1794,6 +1833,24 @@ AdvSceneSwitcher.tempVar.twitch.to_broadcaster_user_name.raid.description="The b
|
|||||||
AdvSceneSwitcher.tempVar.twitch.viewers.raid="Raid participants"
|
AdvSceneSwitcher.tempVar.twitch.viewers.raid="Raid participants"
|
||||||
AdvSceneSwitcher.tempVar.twitch.viewers.raid.description="The number of viewers in the raid."
|
AdvSceneSwitcher.tempVar.twitch.viewers.raid.description="The number of viewers in the raid."
|
||||||
|
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.id.user.getInfo="User ID"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.id.user.getInfo.description="The user ID of the queried account."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.login.user.getInfo="User login"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.login.user.getInfo.description="The user login of the queried account."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.display_name.user.getInfo="User name"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.display_name.user.getInfo.description="The display name of the queried account."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.type.user.getInfo="User type"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.type.user.getInfo.description="The type of user. Possible values are:\n admin — Twitch administrator\n global_mod\n staff — Twitch staff\n \"\" — Normal user"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.broadcaster_type.user.getInfo="Broadcaster type"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.broadcaster_type.user.getInfo.description="The type of broadcaster. Possible values are:\n affiliate — An affiliate broadcaster\n partner — A partner broadcaster\n \"\" — A normal broadcaster"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.description.user.getInfo="Description"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.description.user.getInfo.description="The user's description of their channel."
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.profile_image_url.user.getInfo="Profile image URL"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.offline_image_url.user.getInfo="Offline image URL"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.created_at.user.getInfo="Account creation date"
|
||||||
|
AdvSceneSwitcher.tempVar.twitch.created_at.user.getInfo.description="The UTC date and time that the user's account was created. The timestamp is in RFC3339 format."
|
||||||
|
|
||||||
|
|
||||||
AdvSceneSwitcher.tempVar.audio.output_volume="Output volume"
|
AdvSceneSwitcher.tempVar.audio.output_volume="Output volume"
|
||||||
AdvSceneSwitcher.tempVar.audio.output_volume.description="The volume the audio source is outputting."
|
AdvSceneSwitcher.tempVar.audio.output_volume.description="The volume the audio source is outputting."
|
||||||
AdvSceneSwitcher.tempVar.audio.configured_volume="Configured volume"
|
AdvSceneSwitcher.tempVar.audio.configured_volume="Configured volume"
|
||||||
@@ -1971,6 +2028,16 @@ AdvSceneSwitcher.tempVar.queue.size="Size"
|
|||||||
AdvSceneSwitcher.tempVar.queue.running="Is running"
|
AdvSceneSwitcher.tempVar.queue.running="Is running"
|
||||||
AdvSceneSwitcher.tempVar.queue.running.description="Returns \"true\" if the queue is started and \"false\" if it is stopped."
|
AdvSceneSwitcher.tempVar.queue.running.description="Returns \"true\" if the queue is started and \"false\" if it is stopped."
|
||||||
|
|
||||||
|
AdvSceneSwitcher.tempVar.screenshot.lastScreenshotPath="Last screenshot path"
|
||||||
|
AdvSceneSwitcher.tempVar.screenshot.lastScreenshotPath.description="The filesystem path to the last screenshot taken."
|
||||||
|
|
||||||
|
AdvSceneSwitcher.tempVar.gameCapture.title="Title"
|
||||||
|
AdvSceneSwitcher.tempVar.gameCapture.title.description="Window title of the application captured by the source."
|
||||||
|
AdvSceneSwitcher.tempVar.gameCapture.class="Class"
|
||||||
|
AdvSceneSwitcher.tempVar.gameCapture.class.description="Window class of the application captured by the source."
|
||||||
|
AdvSceneSwitcher.tempVar.gameCapture.executable="Executable"
|
||||||
|
AdvSceneSwitcher.tempVar.gameCapture.executable.description="Executable name of the application captured by the source."
|
||||||
|
|
||||||
AdvSceneSwitcher.selectScene="--select scene--"
|
AdvSceneSwitcher.selectScene="--select scene--"
|
||||||
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
AdvSceneSwitcher.selectPreviousScene="Previous Scene"
|
||||||
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
AdvSceneSwitcher.selectCurrentScene="Current Scene"
|
||||||
|
|||||||
@@ -1089,10 +1089,10 @@ AdvSceneSwitcher.action.twitch.type.clip.create="ストリームクリップの
|
|||||||
AdvSceneSwitcher.action.twitch.type.chat.announcement.send="チャット通知の送信"
|
AdvSceneSwitcher.action.twitch.type.chat.announcement.send="チャット通知の送信"
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.emoteOnly.enable="チャットのエモート専用モードを有効にする"
|
AdvSceneSwitcher.action.twitch.type.chat.emoteOnly.enable="チャットのエモート専用モードを有効にする"
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.emoteOnly.disable="チャットのエモート専用モードを無効にする"
|
AdvSceneSwitcher.action.twitch.type.chat.emoteOnly.disable="チャットのエモート専用モードを無効にする"
|
||||||
AdvSceneSwitcher.action.twitch.type.sendChatMessage="チャットメッセージを送る"
|
AdvSceneSwitcher.action.twitch.type.chat.sendMessage="チャットメッセージを送る"
|
||||||
AdvSceneSwitcher.action.twitch.categorySelectionDisabled="Twitchアカウントを選択しないとカテゴリを選択できません!"
|
AdvSceneSwitcher.action.twitch.categorySelectionDisabled="Twitchアカウントを選択しないとカテゴリを選択できません!"
|
||||||
; AdvSceneSwitcher.action.twitch.entry.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.entry.chat="{{channel}}{{streamTitle}}{{category}}{{markerDescription}}{{clipHasDelay}}{{duration}}{{announcementColor}} でアカウント{{account}}{{actions}}を使用しています"
|
AdvSceneSwitcher.action.twitch.entry.chat="{{channel}}でアカウント{{account}}{{actions}}を使用しています"
|
||||||
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="クリップをキャプチャする前にわずかな遅延を追加します"
|
||||||
|
|||||||
@@ -1070,10 +1070,10 @@ AdvSceneSwitcher.action.twitch.type.clip.create="Criar clipe da transmissão"
|
|||||||
AdvSceneSwitcher.action.twitch.type.chat.announcement.send="Enviar anúncio de chat"
|
AdvSceneSwitcher.action.twitch.type.chat.announcement.send="Enviar anúncio de chat"
|
||||||
AdvSceneSwitcher.action.twitch.type.chat.emoteOnly.enable="Habilitar modo apenas emotes no chat"
|
AdvSceneSwitcher.action.twitch.type.chat.emoteOnly.enable="Habilitar modo apenas emotes no chat"
|
||||||
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.sendChatMessage="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.entry.default="Em{{account}}{{actions}}{{streamTitle}}{{category}}{{markerDescription}}{{clipHasDelay}}{{duration}}{{announcementColor}}{{channel}}"
|
AdvSceneSwitcher.action.twitch.entry.default="Em{{account}}{{actions}}{{streamTitle}}{{category}}{{markerDescription}}{{clipHasDelay}}{{duration}}{{announcementColor}}{{channel}}{{pointsReward}}"
|
||||||
AdvSceneSwitcher.action.twitch.entry.chat="Usando conta{{account}}{{actions}}em{{channel}}{{streamTitle}}{{category}}{{markerDescription}}{{clipHasDelay}}{{duration}}{{announcementColor}}"
|
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"
|
||||||
|
|||||||
13156
deps/exprtk/exprtk.hpp
vendored
13156
deps/exprtk/exprtk.hpp
vendored
File diff suppressed because it is too large
Load Diff
@@ -735,7 +735,7 @@ void OpenSettingsWindow()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AdvSceneSwitcher::HighligthMacroSettingsButton(bool enable)
|
void AdvSceneSwitcher::HighlightMacroSettingsButton(bool enable)
|
||||||
{
|
{
|
||||||
static QObject *highlight = nullptr;
|
static QObject *highlight = nullptr;
|
||||||
if ((highlight && enable) || (!highlight && !enable)) {
|
if ((highlight && enable) || (!highlight && !enable)) {
|
||||||
@@ -755,13 +755,13 @@ void AdvSceneSwitcher::HighligthMacroSettingsButton(bool enable)
|
|||||||
highlight = HighlightWidget(ui->macroSettings, Qt::green);
|
highlight = HighlightWidget(ui->macroSettings, Qt::green);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HighligthMacroSettingsButton(bool enable)
|
void HighlightMacroSettingsButton(bool enable)
|
||||||
{
|
{
|
||||||
auto window = GetSettingsWindow();
|
auto window = GetSettingsWindow();
|
||||||
if (!window) {
|
if (!window) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
static_cast<AdvSceneSwitcher *>(window)->HighligthMacroSettingsButton(
|
static_cast<AdvSceneSwitcher *>(window)->HighlightMacroSettingsButton(
|
||||||
enable);
|
enable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ public:
|
|||||||
void SetConditionData(Macro &m);
|
void SetConditionData(Macro &m);
|
||||||
void SwapActions(Macro *m, int pos1, int pos2);
|
void SwapActions(Macro *m, int pos1, int pos2);
|
||||||
void SwapConditions(Macro *m, int pos1, int pos2);
|
void SwapConditions(Macro *m, int pos1, int pos2);
|
||||||
void HighligthMacroSettingsButton(bool enable = true);
|
void HighlightMacroSettingsButton(bool enable = true);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void on_macroAdd_clicked();
|
void on_macroAdd_clicked();
|
||||||
@@ -386,6 +386,6 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
void OpenSettingsWindow();
|
void OpenSettingsWindow();
|
||||||
void HighligthMacroSettingsButton(bool enable);
|
void HighlightMacroSettingsButton(bool enable);
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -344,6 +344,10 @@ void AdvSceneSwitcher::on_importSettings_clicked()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We have to make sure to that no macro is currently being edited while
|
||||||
|
// the new settings are loaded
|
||||||
|
ui->macros->clearSelection();
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(switcher->m);
|
std::lock_guard<std::mutex> lock(switcher->m);
|
||||||
switcher->LoadSettings(obj);
|
switcher->LoadSettings(obj);
|
||||||
switcher->lastImportPath = path.toStdString();
|
switcher->lastImportPath = path.toStdString();
|
||||||
|
|||||||
@@ -122,11 +122,7 @@ void SwitcherData::writeToStatusFile(const QString &msg)
|
|||||||
QFile file(QString::fromStdString(fileIO.writePath));
|
QFile file(QString::fromStdString(fileIO.writePath));
|
||||||
if (file.open(QIODevice::ReadWrite)) {
|
if (file.open(QIODevice::ReadWrite)) {
|
||||||
QTextStream stream(&file);
|
QTextStream stream(&file);
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
stream << msg << "\n";
|
|
||||||
#else
|
|
||||||
stream << msg << Qt::endl;
|
stream << msg << Qt::endl;
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -384,7 +384,11 @@ static void getProcessListProcps2(QStringList &processes)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
while ((stack = procps_pids_get_(info, PIDS_FETCH_TASKS_ONLY))) {
|
while ((stack = procps_pids_get_(info, PIDS_FETCH_TASKS_ONLY))) {
|
||||||
|
#ifdef PROCPS2_USE_INFO
|
||||||
auto cmd = PIDS_VAL(0, str, stack, info);
|
auto cmd = PIDS_VAL(0, str, stack, info);
|
||||||
|
#else
|
||||||
|
auto cmd = PIDS_VAL(0, str, stack);
|
||||||
|
#endif
|
||||||
QString procName(cmd);
|
QString procName(cmd);
|
||||||
if (!procName.isEmpty() && !processes.contains(procName)) {
|
if (!procName.isEmpty() && !processes.contains(procName)) {
|
||||||
processes << procName;
|
processes << procName;
|
||||||
|
|||||||
@@ -309,11 +309,11 @@ MacroActionMacroEdit::MacroActionMacroEdit(
|
|||||||
_loading = false;
|
_loading = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HighligthMacroSettingsButton(bool enable);
|
void HighlightMacroSettingsButton(bool enable);
|
||||||
|
|
||||||
MacroActionMacroEdit::~MacroActionMacroEdit()
|
MacroActionMacroEdit::~MacroActionMacroEdit()
|
||||||
{
|
{
|
||||||
HighligthMacroSettingsButton(false);
|
HighlightMacroSettingsButton(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionMacroEdit::UpdateEntryData()
|
void MacroActionMacroEdit::UpdateEntryData()
|
||||||
@@ -480,7 +480,7 @@ void MacroActionMacroEdit::SetWidgetVisibility()
|
|||||||
_inputs->setVisible(_entryData->_action ==
|
_inputs->setVisible(_entryData->_action ==
|
||||||
MacroActionMacro::Action::RUN &&
|
MacroActionMacro::Action::RUN &&
|
||||||
_entryData->_runOptions.setInputs);
|
_entryData->_runOptions.setInputs);
|
||||||
HighligthMacroSettingsButton(_entryData->_action ==
|
HighlightMacroSettingsButton(_entryData->_action ==
|
||||||
MacroActionMacro::Action::RUN &&
|
MacroActionMacro::Action::RUN &&
|
||||||
_entryData->_runOptions.setInputs &&
|
_entryData->_runOptions.setInputs &&
|
||||||
!_inputs->HasInputsToSet());
|
!_inputs->HasInputsToSet());
|
||||||
|
|||||||
@@ -6,14 +6,17 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
MacroActionScript::MacroActionScript(Macro *m, const std::string &id,
|
MacroActionScript::MacroActionScript(
|
||||||
const OBSData &defaultSettings,
|
Macro *m, const std::string &id, const OBSData &defaultSettings,
|
||||||
const std::string &propertiesSignalName,
|
const std::string &propertiesSignalName,
|
||||||
const std::string &triggerSignal,
|
const std::string &triggerSignalName,
|
||||||
const std::string &completionSignal)
|
const std::string &completionSignalName,
|
||||||
|
const std::string &newInstanceSignalName,
|
||||||
|
const std::string &deletedInstanceSignalName)
|
||||||
: MacroAction(m),
|
: MacroAction(m),
|
||||||
MacroSegmentScript(defaultSettings, propertiesSignalName,
|
MacroSegmentScript(defaultSettings, propertiesSignalName,
|
||||||
triggerSignal, completionSignal),
|
triggerSignalName, completionSignalName,
|
||||||
|
newInstanceSignalName, deletedInstanceSignalName),
|
||||||
_id(id)
|
_id(id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -89,4 +92,29 @@ void MacroActionScript::WaitForCompletion() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionScript::RegisterTempVarHelper(const std::string &variableId,
|
||||||
|
const std::string &name,
|
||||||
|
const std::string &helpText)
|
||||||
|
{
|
||||||
|
AddTempvar(variableId, name, helpText);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionScript::DeregisterAllTempVarsHelper()
|
||||||
|
{
|
||||||
|
MacroSegment::SetupTempVars();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionScript::SetTempVarValueHelper(const std::string &variableId,
|
||||||
|
const std::string &value)
|
||||||
|
{
|
||||||
|
MacroAction::SetTempVarValue(variableId, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionScript::SetupTempVars()
|
||||||
|
{
|
||||||
|
// This just exists so MacroSegment::SetupTempVars() is not called.
|
||||||
|
// We want the ScriptHandler to handle the registration and clearing of
|
||||||
|
// the temp vars.
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -10,8 +10,10 @@ public:
|
|||||||
MacroActionScript(Macro *m, const std::string &id,
|
MacroActionScript(Macro *m, const std::string &id,
|
||||||
const OBSData &defaultSettings,
|
const OBSData &defaultSettings,
|
||||||
const std::string &propertiesSignalName,
|
const std::string &propertiesSignalName,
|
||||||
const std::string &triggerSignal,
|
const std::string &triggerSignalName,
|
||||||
const std::string &signalComplete);
|
const std::string &completionSignalName,
|
||||||
|
const std::string &newInstanceSignalName,
|
||||||
|
const std::string &deletedInstanceSignalName);
|
||||||
MacroActionScript(const advss::MacroActionScript &);
|
MacroActionScript(const advss::MacroActionScript &);
|
||||||
bool PerformAction();
|
bool PerformAction();
|
||||||
void LogAction() const;
|
void LogAction() const;
|
||||||
@@ -22,6 +24,13 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void WaitForCompletion() const;
|
void WaitForCompletion() const;
|
||||||
|
void RegisterTempVarHelper(const std::string &variableId,
|
||||||
|
const std::string &name,
|
||||||
|
const std::string &helpText);
|
||||||
|
void DeregisterAllTempVarsHelper();
|
||||||
|
void SetTempVarValueHelper(const std::string &variableId,
|
||||||
|
const std::string &value);
|
||||||
|
void SetupTempVars();
|
||||||
|
|
||||||
std::string _id = "";
|
std::string _id = "";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
#include "source-helpers.hpp"
|
#include "source-helpers.hpp"
|
||||||
#include "utility.hpp"
|
#include "utility.hpp"
|
||||||
|
|
||||||
|
#include <random>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
const std::string MacroActionVariable::id = "variable";
|
const std::string MacroActionVariable::id = "variable";
|
||||||
@@ -17,66 +19,6 @@ bool MacroActionVariable::_registered = MacroActionFactory::Register(
|
|||||||
{MacroActionVariable::Create, MacroActionVariableEdit::Create,
|
{MacroActionVariable::Create, MacroActionVariableEdit::Create,
|
||||||
"AdvSceneSwitcher.action.variable"});
|
"AdvSceneSwitcher.action.variable"});
|
||||||
|
|
||||||
const static std::map<MacroActionVariable::Type, std::string> actionTypes = {
|
|
||||||
{MacroActionVariable::Type::SET_FIXED_VALUE,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.set"},
|
|
||||||
{MacroActionVariable::Type::APPEND,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.append"},
|
|
||||||
{MacroActionVariable::Type::APPEND_VAR,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.appendVar"},
|
|
||||||
{MacroActionVariable::Type::INCREMENT,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.increment"},
|
|
||||||
{MacroActionVariable::Type::DECREMENT,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.decrement"},
|
|
||||||
{MacroActionVariable::Type::SET_CONDITION_VALUE,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.setConditionValue"},
|
|
||||||
{MacroActionVariable::Type::SET_ACTION_VALUE,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.setActionValue"},
|
|
||||||
{MacroActionVariable::Type::ROUND_TO_INT,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.roundToInt"},
|
|
||||||
{MacroActionVariable::Type::SUBSTRING,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.subString"},
|
|
||||||
{MacroActionVariable::Type::FIND_AND_REPLACE,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.findAndReplace"},
|
|
||||||
{MacroActionVariable::Type::MATH_EXPRESSION,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.mathExpression"},
|
|
||||||
{MacroActionVariable::Type::USER_INPUT,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.askForValue"},
|
|
||||||
{MacroActionVariable::Type::ENV_VARIABLE,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.environmentVariable"},
|
|
||||||
{MacroActionVariable::Type::SCENE_ITEM_COUNT,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.sceneItemCount"},
|
|
||||||
{MacroActionVariable::Type::STRING_LENGTH,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.stringLength"},
|
|
||||||
{MacroActionVariable::Type::EXTRACT_JSON,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.extractJson"},
|
|
||||||
{MacroActionVariable::Type::SET_TO_TEMPVAR,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.setToTempvar"},
|
|
||||||
{MacroActionVariable::Type::SCENE_ITEM_NAME,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.sceneItemName"},
|
|
||||||
{MacroActionVariable::Type::PAD,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.padValue"},
|
|
||||||
{MacroActionVariable::Type::TRUNCATE,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.truncateValue"},
|
|
||||||
{MacroActionVariable::Type::SWAP_VALUES,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.swapValues"},
|
|
||||||
{MacroActionVariable::Type::TRIM,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.trim"},
|
|
||||||
{MacroActionVariable::Type::CHANGE_CASE,
|
|
||||||
"AdvSceneSwitcher.action.variable.type.changeCase"},
|
|
||||||
};
|
|
||||||
|
|
||||||
const static std::map<MacroActionVariable::CaseType, std::string> caseTypes = {
|
|
||||||
{MacroActionVariable::CaseType::LOWER_CASE,
|
|
||||||
"AdvSceneSwitcher.action.variable.case.type.lowerCase"},
|
|
||||||
{MacroActionVariable::CaseType::UPPER_CASE,
|
|
||||||
"AdvSceneSwitcher.action.variable.case.type.upperCase"},
|
|
||||||
{MacroActionVariable::CaseType::CAPITALIZED,
|
|
||||||
"AdvSceneSwitcher.action.variable.case.type.capitalized"},
|
|
||||||
{MacroActionVariable::CaseType::START_CASE,
|
|
||||||
"AdvSceneSwitcher.action.variable.case.type.startCase"},
|
|
||||||
};
|
|
||||||
|
|
||||||
static void apppend(Variable &var, const std::string &value)
|
static void apppend(Variable &var, const std::string &value)
|
||||||
{
|
{
|
||||||
auto currentValue = var.Value();
|
auto currentValue = var.Value();
|
||||||
@@ -253,6 +195,27 @@ void MacroActionVariable::SetToSceneItemName(Variable *var)
|
|||||||
var->SetValue(data.name);
|
var->SetValue(data.name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionVariable::GenerateRandomNumber(Variable *var)
|
||||||
|
{
|
||||||
|
static std::random_device rd;
|
||||||
|
static std::mt19937 gen(rd());
|
||||||
|
|
||||||
|
double start = _randomNumberStart;
|
||||||
|
double end = _randomNumberEnd;
|
||||||
|
|
||||||
|
if (start > end) {
|
||||||
|
std::swap(start, end);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_generateInteger) {
|
||||||
|
std::uniform_int_distribution<int> dis(start, end);
|
||||||
|
var->SetValue(dis(gen));
|
||||||
|
} else {
|
||||||
|
std::uniform_real_distribution<double> dis(start, end);
|
||||||
|
var->SetValue(dis(gen));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct AskForInputParams {
|
struct AskForInputParams {
|
||||||
AskForInputParams(const QString &prompt_, const QString &placeholder_)
|
AskForInputParams(const QString &prompt_, const QString &placeholder_)
|
||||||
: prompt(prompt_),
|
: prompt(prompt_),
|
||||||
@@ -313,14 +276,14 @@ bool MacroActionVariable::PerformAction()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (_type) {
|
switch (_action) {
|
||||||
case Type::SET_FIXED_VALUE:
|
case Action::SET_VALUE:
|
||||||
var->SetValue(_strValue);
|
var->SetValue(_strValue);
|
||||||
break;
|
break;
|
||||||
case Type::APPEND:
|
case Action::APPEND:
|
||||||
apppend(*var, _strValue);
|
apppend(*var, _strValue);
|
||||||
break;
|
break;
|
||||||
case Type::APPEND_VAR: {
|
case Action::APPEND_VAR: {
|
||||||
auto var2 = _variable2.lock();
|
auto var2 = _variable2.lock();
|
||||||
if (!var2) {
|
if (!var2) {
|
||||||
return true;
|
return true;
|
||||||
@@ -328,14 +291,14 @@ bool MacroActionVariable::PerformAction()
|
|||||||
apppend(*var, var2->Value());
|
apppend(*var, var2->Value());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Type::INCREMENT:
|
case Action::INCREMENT:
|
||||||
modifyNumValue(*var, _numValue.GetValue(), true);
|
modifyNumValue(*var, _numValue.GetValue(), true);
|
||||||
break;
|
break;
|
||||||
case Type::DECREMENT:
|
case Action::DECREMENT:
|
||||||
modifyNumValue(*var, _numValue.GetValue(), false);
|
modifyNumValue(*var, _numValue.GetValue(), false);
|
||||||
break;
|
break;
|
||||||
case Type::SET_CONDITION_VALUE:
|
case Action::SET_CONDITION_VALUE:
|
||||||
case Type::SET_ACTION_VALUE: {
|
case Action::SET_ACTION_VALUE: {
|
||||||
auto m = GetMacro();
|
auto m = GetMacro();
|
||||||
if (!m) {
|
if (!m) {
|
||||||
return true;
|
return true;
|
||||||
@@ -350,7 +313,7 @@ bool MacroActionVariable::PerformAction()
|
|||||||
var->SetValue(segment->GetVariableValue());
|
var->SetValue(segment->GetVariableValue());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case Type::ROUND_TO_INT: {
|
case Action::ROUND_TO_INT: {
|
||||||
auto curValue = var->DoubleValue();
|
auto curValue = var->DoubleValue();
|
||||||
if (!curValue.has_value()) {
|
if (!curValue.has_value()) {
|
||||||
return true;
|
return true;
|
||||||
@@ -358,7 +321,7 @@ bool MacroActionVariable::PerformAction()
|
|||||||
var->SetValue(std::to_string(int(std::round(*curValue))));
|
var->SetValue(std::to_string(int(std::round(*curValue))));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Type::SUBSTRING: {
|
case Action::SUBSTRING: {
|
||||||
if (_subStringRegex.Enabled()) {
|
if (_subStringRegex.Enabled()) {
|
||||||
HandleRegexSubString(var.get());
|
HandleRegexSubString(var.get());
|
||||||
return true;
|
return true;
|
||||||
@@ -366,15 +329,15 @@ bool MacroActionVariable::PerformAction()
|
|||||||
HandleIndexSubString(var.get());
|
HandleIndexSubString(var.get());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Type::FIND_AND_REPLACE: {
|
case Action::FIND_AND_REPLACE: {
|
||||||
HandleFindAndReplace(var.get());
|
HandleFindAndReplace(var.get());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Type::MATH_EXPRESSION: {
|
case Action::MATH_EXPRESSION: {
|
||||||
HandleMathExpression(var.get());
|
HandleMathExpression(var.get());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Type::USER_INPUT: {
|
case Action::USER_INPUT: {
|
||||||
auto params = std::make_shared<AskForInputParams>(
|
auto params = std::make_shared<AskForInputParams>(
|
||||||
_useCustomPrompt
|
_useCustomPrompt
|
||||||
? QString::fromStdString(_inputPrompt)
|
? QString::fromStdString(_inputPrompt)
|
||||||
@@ -399,22 +362,22 @@ bool MacroActionVariable::PerformAction()
|
|||||||
var->SetValue(*params->result);
|
var->SetValue(*params->result);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Type::ENV_VARIABLE: {
|
case Action::ENV_VARIABLE: {
|
||||||
auto value = std::getenv(_envVariableName.c_str());
|
auto value = std::getenv(_envVariableName.c_str());
|
||||||
if (value) {
|
if (value) {
|
||||||
var->SetValue(value);
|
var->SetValue(value);
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Type::SCENE_ITEM_COUNT: {
|
case Action::SCENE_ITEM_COUNT: {
|
||||||
var->SetValue(GetSceneItemCount(_scene.GetScene(false)));
|
var->SetValue(GetSceneItemCount(_scene.GetScene(false)));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Type::STRING_LENGTH: {
|
case Action::STRING_LENGTH: {
|
||||||
var->SetValue(std::string(_strValue).length());
|
var->SetValue(std::string(_strValue).length());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Type::EXTRACT_JSON: {
|
case Action::EXTRACT_JSON: {
|
||||||
auto value = GetJsonField(var->Value(), _strValue);
|
auto value = GetJsonField(var->Value(), _strValue);
|
||||||
if (!value.has_value()) {
|
if (!value.has_value()) {
|
||||||
return true;
|
return true;
|
||||||
@@ -422,7 +385,7 @@ bool MacroActionVariable::PerformAction()
|
|||||||
var->SetValue(*value);
|
var->SetValue(*value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Type::SET_TO_TEMPVAR: {
|
case Action::SET_TO_TEMPVAR: {
|
||||||
auto tempVar = _tempVar.GetTempVariable(GetMacro());
|
auto tempVar = _tempVar.GetTempVariable(GetMacro());
|
||||||
if (!tempVar) {
|
if (!tempVar) {
|
||||||
return true;
|
return true;
|
||||||
@@ -434,18 +397,18 @@ bool MacroActionVariable::PerformAction()
|
|||||||
var->SetValue(*value);
|
var->SetValue(*value);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Type::SCENE_ITEM_NAME:
|
case Action::SCENE_ITEM_NAME:
|
||||||
SetToSceneItemName(var.get());
|
SetToSceneItemName(var.get());
|
||||||
return true;
|
return true;
|
||||||
case Type::PAD:
|
case Action::PAD:
|
||||||
var->SetValue(pad(var->Value(), _direction, _stringLength,
|
var->SetValue(pad(var->Value(), _direction, _stringLength,
|
||||||
_paddingChar));
|
_paddingChar));
|
||||||
return true;
|
return true;
|
||||||
case Type::TRUNCATE:
|
case Action::TRUNCATE:
|
||||||
var->SetValue(
|
var->SetValue(
|
||||||
truncate(var->Value(), _direction, _stringLength));
|
truncate(var->Value(), _direction, _stringLength));
|
||||||
return true;
|
return true;
|
||||||
case Type::SWAP_VALUES: {
|
case Action::SWAP_VALUES: {
|
||||||
auto var2 = _variable2.lock();
|
auto var2 = _variable2.lock();
|
||||||
if (!var2) {
|
if (!var2) {
|
||||||
return true;
|
return true;
|
||||||
@@ -456,15 +419,18 @@ bool MacroActionVariable::PerformAction()
|
|||||||
var2->SetValue(tempValue);
|
var2->SetValue(tempValue);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Type::TRIM: {
|
case Action::TRIM: {
|
||||||
var->SetValue(QString::fromStdString(var->Value())
|
var->SetValue(QString::fromStdString(var->Value())
|
||||||
.trimmed()
|
.trimmed()
|
||||||
.toStdString());
|
.toStdString());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case Type::CHANGE_CASE:
|
case Action::CHANGE_CASE:
|
||||||
HandleCaseChange(var.get());
|
HandleCaseChange(var.get());
|
||||||
return true;
|
return true;
|
||||||
|
case Action::RANDOM_NUMBER:
|
||||||
|
GenerateRandomNumber(var.get());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -479,7 +445,7 @@ bool MacroActionVariable::Save(obs_data_t *obj) const
|
|||||||
GetWeakVariableName(_variable2).c_str());
|
GetWeakVariableName(_variable2).c_str());
|
||||||
_strValue.Save(obj, "strValue");
|
_strValue.Save(obj, "strValue");
|
||||||
_numValue.Save(obj, "numValue");
|
_numValue.Save(obj, "numValue");
|
||||||
obs_data_set_int(obj, "condition", static_cast<int>(_type));
|
obs_data_set_int(obj, "condition", static_cast<int>(_action));
|
||||||
obs_data_set_int(obj, "segmentIdx", GetSegmentIndexValue());
|
obs_data_set_int(obj, "segmentIdx", GetSegmentIndexValue());
|
||||||
_subStringStart.Save(obj, "subStringStart");
|
_subStringStart.Save(obj, "subStringStart");
|
||||||
_subStringSize.Save(obj, "subStringSize");
|
_subStringSize.Save(obj, "subStringSize");
|
||||||
@@ -502,6 +468,9 @@ bool MacroActionVariable::Save(obs_data_t *obj) const
|
|||||||
_stringLength.Save(obj, "stringLength");
|
_stringLength.Save(obj, "stringLength");
|
||||||
obs_data_set_int(obj, "paddingChar", _paddingChar);
|
obs_data_set_int(obj, "paddingChar", _paddingChar);
|
||||||
obs_data_set_int(obj, "caseType", static_cast<int>(_caseType));
|
obs_data_set_int(obj, "caseType", static_cast<int>(_caseType));
|
||||||
|
_randomNumberStart.Save(obj, "randomNumberStart");
|
||||||
|
_randomNumberEnd.Save(obj, "randomNumberEnd");
|
||||||
|
obs_data_set_bool(obj, "generateInteger", _generateInteger);
|
||||||
|
|
||||||
obs_data_set_int(obj, "version", 1);
|
obs_data_set_int(obj, "version", 1);
|
||||||
|
|
||||||
@@ -516,7 +485,7 @@ bool MacroActionVariable::Load(obs_data_t *obj)
|
|||||||
_variable2 = GetWeakVariableByName(
|
_variable2 = GetWeakVariableByName(
|
||||||
obs_data_get_string(obj, "variable2Name"));
|
obs_data_get_string(obj, "variable2Name"));
|
||||||
_strValue.Load(obj, "strValue");
|
_strValue.Load(obj, "strValue");
|
||||||
_type = static_cast<Type>(obs_data_get_int(obj, "condition"));
|
_action = static_cast<Action>(obs_data_get_int(obj, "condition"));
|
||||||
_segmentIdxLoadValue = obs_data_get_int(obj, "segmentIdx");
|
_segmentIdxLoadValue = obs_data_get_int(obj, "segmentIdx");
|
||||||
_subStringRegex.Load(obj);
|
_subStringRegex.Load(obj);
|
||||||
_regexPattern = obs_data_get_string(obj, "regexPattern");
|
_regexPattern = obs_data_get_string(obj, "regexPattern");
|
||||||
@@ -555,6 +524,10 @@ bool MacroActionVariable::Load(obs_data_t *obj)
|
|||||||
_regexMatchIdx.Load(obj, "regexMatchIdx");
|
_regexMatchIdx.Load(obj, "regexMatchIdx");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_randomNumberStart.Load(obj, "randomNumberStart");
|
||||||
|
_randomNumberEnd.Load(obj, "randomNumberEnd");
|
||||||
|
_generateInteger = obs_data_get_bool(obj, "generateInteger");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -595,11 +568,11 @@ void MacroActionVariable::SetSegmentIndexValue(int value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<MacroSegment> segment;
|
std::shared_ptr<MacroSegment> segment;
|
||||||
if (_type == Type::SET_CONDITION_VALUE) {
|
if (_action == Action::SET_CONDITION_VALUE) {
|
||||||
if (value < (int)m->Conditions().size()) {
|
if (value < (int)m->Conditions().size()) {
|
||||||
segment = m->Conditions().at(value);
|
segment = m->Conditions().at(value);
|
||||||
}
|
}
|
||||||
} else if (_type == Type::SET_ACTION_VALUE) {
|
} else if (_action == Action::SET_ACTION_VALUE) {
|
||||||
if (value < (int)m->Actions().size()) {
|
if (value < (int)m->Actions().size()) {
|
||||||
segment = m->Actions().at(value);
|
segment = m->Actions().at(value);
|
||||||
}
|
}
|
||||||
@@ -623,14 +596,14 @@ int MacroActionVariable::GetSegmentIndexValue() const
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_type == Type::SET_CONDITION_VALUE) {
|
if (_action == Action::SET_CONDITION_VALUE) {
|
||||||
auto it = std::find(m->Conditions().begin(),
|
auto it = std::find(m->Conditions().begin(),
|
||||||
m->Conditions().end(), segment);
|
m->Conditions().end(), segment);
|
||||||
if (it != m->Conditions().end()) {
|
if (it != m->Conditions().end()) {
|
||||||
return std::distance(m->Conditions().begin(), it);
|
return std::distance(m->Conditions().begin(), it);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
} else if (_type == Type::SET_ACTION_VALUE) {
|
} else if (_action == Action::SET_ACTION_VALUE) {
|
||||||
auto it = std::find(m->Actions().begin(), m->Actions().end(),
|
auto it = std::find(m->Actions().begin(), m->Actions().end(),
|
||||||
segment);
|
segment);
|
||||||
if (it != m->Actions().end()) {
|
if (it != m->Actions().end()) {
|
||||||
@@ -665,16 +638,99 @@ void MacroActionVariable::DecrementCurrentSegmentVariableRef()
|
|||||||
DecrementVariableRef(segment.get());
|
DecrementVariableRef(segment.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void populateTypeSelection(QComboBox *list)
|
static inline void populateActionSelection(QComboBox *list)
|
||||||
{
|
{
|
||||||
for (const auto &[action, name] : actionTypes) {
|
static const std::vector<std::pair<
|
||||||
list->addItem(obs_module_text(name.c_str()),
|
std::variant<MacroActionVariable::Action, bool>, std::string>>
|
||||||
static_cast<int>(action));
|
actions = {
|
||||||
|
{MacroActionVariable::Action::SET_VALUE,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.set"},
|
||||||
|
{MacroActionVariable::Action::APPEND,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.append"},
|
||||||
|
{MacroActionVariable::Action::PAD,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.padValue"},
|
||||||
|
{MacroActionVariable::Action::TRUNCATE,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.truncateValue"},
|
||||||
|
{MacroActionVariable::Action::SUBSTRING,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.subString"},
|
||||||
|
{MacroActionVariable::Action::FIND_AND_REPLACE,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.findAndReplace"},
|
||||||
|
{MacroActionVariable::Action::EXTRACT_JSON,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.extractJson"},
|
||||||
|
{MacroActionVariable::Action::STRING_LENGTH,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.stringLength"},
|
||||||
|
{MacroActionVariable::Action::TRIM,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.trim"},
|
||||||
|
{MacroActionVariable::Action::CHANGE_CASE,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.changeCase"},
|
||||||
|
{true, ""}, // Separator
|
||||||
|
|
||||||
|
{MacroActionVariable::Action::SET_TO_TEMPVAR,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.setToTempvar"},
|
||||||
|
{MacroActionVariable::Action::SET_CONDITION_VALUE,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.setConditionValue"},
|
||||||
|
{MacroActionVariable::Action::SET_ACTION_VALUE,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.setActionValue"},
|
||||||
|
{true, ""}, // Separator
|
||||||
|
|
||||||
|
{MacroActionVariable::Action::MATH_EXPRESSION,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.mathExpression"},
|
||||||
|
{MacroActionVariable::Action::INCREMENT,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.increment"},
|
||||||
|
{MacroActionVariable::Action::DECREMENT,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.decrement"},
|
||||||
|
{MacroActionVariable::Action::ROUND_TO_INT,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.roundToInt"},
|
||||||
|
{MacroActionVariable::Action::RANDOM_NUMBER,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.randomNumber"},
|
||||||
|
{true, ""}, // Separator
|
||||||
|
|
||||||
|
{MacroActionVariable::Action::USER_INPUT,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.askForValue"},
|
||||||
|
{MacroActionVariable::Action::ENV_VARIABLE,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.environmentVariable"},
|
||||||
|
{true, ""}, // Separator
|
||||||
|
|
||||||
|
{MacroActionVariable::Action::SCENE_ITEM_NAME,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.sceneItemName"},
|
||||||
|
{MacroActionVariable::Action::SCENE_ITEM_COUNT,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.sceneItemCount"},
|
||||||
|
{true, ""}, // Separator
|
||||||
|
|
||||||
|
{MacroActionVariable::Action::SWAP_VALUES,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.swapValues"},
|
||||||
|
{MacroActionVariable::Action::APPEND_VAR,
|
||||||
|
"AdvSceneSwitcher.action.variable.type.appendVar"},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
for (const auto &[action, name] : actions) {
|
||||||
|
if (std::holds_alternative<bool>(action)) {
|
||||||
|
list->insertSeparator(actions.size());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
list->addItem(
|
||||||
|
obs_module_text(name.c_str()),
|
||||||
|
static_cast<int>(
|
||||||
|
std::get<MacroActionVariable::Action>(action)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void populateCaseTypeSelection(QComboBox *list)
|
static inline void populateCaseTypeSelection(QComboBox *list)
|
||||||
{
|
{
|
||||||
|
const static std::map<MacroActionVariable::CaseType, std::string>
|
||||||
|
caseTypes = {
|
||||||
|
{MacroActionVariable::CaseType::LOWER_CASE,
|
||||||
|
"AdvSceneSwitcher.action.variable.case.type.lowerCase"},
|
||||||
|
{MacroActionVariable::CaseType::UPPER_CASE,
|
||||||
|
"AdvSceneSwitcher.action.variable.case.type.upperCase"},
|
||||||
|
{MacroActionVariable::CaseType::CAPITALIZED,
|
||||||
|
"AdvSceneSwitcher.action.variable.case.type.capitalized"},
|
||||||
|
{MacroActionVariable::CaseType::START_CASE,
|
||||||
|
"AdvSceneSwitcher.action.variable.case.type.startCase"},
|
||||||
|
};
|
||||||
|
|
||||||
for (const auto &[type, name] : caseTypes) {
|
for (const auto &[type, name] : caseTypes) {
|
||||||
list->addItem(obs_module_text(name.c_str()),
|
list->addItem(obs_module_text(name.c_str()),
|
||||||
static_cast<int>(type));
|
static_cast<int>(type));
|
||||||
@@ -734,6 +790,13 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
_stringLength(new VariableSpinBox(this)),
|
_stringLength(new VariableSpinBox(this)),
|
||||||
_paddingCharSelection(new SingleCharSelection()),
|
_paddingCharSelection(new SingleCharSelection()),
|
||||||
_caseType(new FilterComboBox(this)),
|
_caseType(new FilterComboBox(this)),
|
||||||
|
_randomNumberStart(new VariableDoubleSpinBox(this)),
|
||||||
|
_randomNumberEnd(new VariableDoubleSpinBox(this)),
|
||||||
|
_generateInteger(new QCheckBox(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.variable.generateInteger"),
|
||||||
|
this)),
|
||||||
|
_randomLayout(new QVBoxLayout()),
|
||||||
_entryLayout(new QHBoxLayout())
|
_entryLayout(new QHBoxLayout())
|
||||||
{
|
{
|
||||||
_numValue->setMinimum(-9999999999);
|
_numValue->setMinimum(-9999999999);
|
||||||
@@ -756,9 +819,13 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
QSizePolicy::Preferred);
|
QSizePolicy::Preferred);
|
||||||
_sceneItemIndex->setMinimum(1);
|
_sceneItemIndex->setMinimum(1);
|
||||||
_stringLength->setMaximum(999);
|
_stringLength->setMaximum(999);
|
||||||
populateTypeSelection(_actions);
|
populateActionSelection(_actions);
|
||||||
populateDirectionSelection(_direction);
|
populateDirectionSelection(_direction);
|
||||||
populateCaseTypeSelection(_caseType);
|
populateCaseTypeSelection(_caseType);
|
||||||
|
_randomNumberStart->setMinimum(-9999999999);
|
||||||
|
_randomNumberStart->setMaximum(9999999999);
|
||||||
|
_randomNumberEnd->setMinimum(-9999999999);
|
||||||
|
_randomNumberEnd->setMaximum(9999999999);
|
||||||
|
|
||||||
QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)),
|
QWidget::connect(_variables, SIGNAL(SelectionChanged(const QString &)),
|
||||||
this, SLOT(VariableChanged(const QString &)));
|
this, SLOT(VariableChanged(const QString &)));
|
||||||
@@ -833,6 +900,18 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
SLOT(CharSelectionChanged(const QString &)));
|
SLOT(CharSelectionChanged(const QString &)));
|
||||||
QWidget::connect(_caseType, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_caseType, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(CaseTypeChanged(int)));
|
SLOT(CaseTypeChanged(int)));
|
||||||
|
QWidget::connect(
|
||||||
|
_randomNumberStart,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<double> &)),
|
||||||
|
this,
|
||||||
|
SLOT(RandomNumberStartChanged(const NumberVariable<double> &)));
|
||||||
|
QWidget::connect(
|
||||||
|
_randomNumberEnd,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<double> &)),
|
||||||
|
this,
|
||||||
|
SLOT(RandomNumberEndChanged(const NumberVariable<double> &)));
|
||||||
|
QWidget::connect(_generateInteger, SIGNAL(stateChanged(int)), this,
|
||||||
|
SLOT(GenerateIntegerChanged(int)));
|
||||||
|
|
||||||
const std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
const std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{variables}}", _variables},
|
{"{{variables}}", _variables},
|
||||||
@@ -861,6 +940,9 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
{"{{stringLength}}", _stringLength},
|
{"{{stringLength}}", _stringLength},
|
||||||
{"{{paddingCharSelection}}", _paddingCharSelection},
|
{"{{paddingCharSelection}}", _paddingCharSelection},
|
||||||
{"{{caseType}}", _caseType},
|
{"{{caseType}}", _caseType},
|
||||||
|
{"{{randomNumberStart}}", _randomNumberStart},
|
||||||
|
{"{{randomNumberEnd}}", _randomNumberEnd},
|
||||||
|
{"{{generateInteger}}", _generateInteger},
|
||||||
};
|
};
|
||||||
PlaceWidgets(
|
PlaceWidgets(
|
||||||
obs_module_text("AdvSceneSwitcher.action.variable.entry.other"),
|
obs_module_text("AdvSceneSwitcher.action.variable.entry.other"),
|
||||||
@@ -890,6 +972,14 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
"AdvSceneSwitcher.action.variable.entry.userInput.placeholder"),
|
"AdvSceneSwitcher.action.variable.entry.userInput.placeholder"),
|
||||||
_placeholderLayout, widgetPlaceholders);
|
_placeholderLayout, widgetPlaceholders);
|
||||||
|
|
||||||
|
auto randomLayout = new QHBoxLayout();
|
||||||
|
PlaceWidgets(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.variable.entry.randomNumber"),
|
||||||
|
randomLayout, widgetPlaceholders);
|
||||||
|
_randomLayout->addLayout(randomLayout);
|
||||||
|
_randomLayout->addWidget(_generateInteger);
|
||||||
|
|
||||||
auto regexConfigLayout = new QHBoxLayout;
|
auto regexConfigLayout = new QHBoxLayout;
|
||||||
regexConfigLayout->addWidget(_substringRegex);
|
regexConfigLayout->addWidget(_substringRegex);
|
||||||
regexConfigLayout->addStretch();
|
regexConfigLayout->addStretch();
|
||||||
@@ -908,6 +998,7 @@ MacroActionVariableEdit::MacroActionVariableEdit(
|
|||||||
layout->addWidget(_mathExpressionResult);
|
layout->addWidget(_mathExpressionResult);
|
||||||
layout->addLayout(_promptLayout);
|
layout->addLayout(_promptLayout);
|
||||||
layout->addLayout(_placeholderLayout);
|
layout->addLayout(_placeholderLayout);
|
||||||
|
layout->addLayout(_randomLayout);
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
|
|
||||||
_entryData = entryData;
|
_entryData = entryData;
|
||||||
@@ -929,14 +1020,14 @@ void MacroActionVariableEdit::UpdateEntryData()
|
|||||||
_variables->SetVariable(_entryData->_variable);
|
_variables->SetVariable(_entryData->_variable);
|
||||||
_variables2->SetVariable(_entryData->_variable2);
|
_variables2->SetVariable(_entryData->_variable2);
|
||||||
_actions->setCurrentIndex(
|
_actions->setCurrentIndex(
|
||||||
_actions->findData(static_cast<int>(_entryData->_type)));
|
_actions->findData(static_cast<int>(_entryData->_action)));
|
||||||
_strValue->setPlainText(_entryData->_strValue);
|
_strValue->setPlainText(_entryData->_strValue);
|
||||||
_numValue->SetValue(_entryData->_numValue);
|
_numValue->SetValue(_entryData->_numValue);
|
||||||
_segmentIdx->SetValue(_entryData->GetSegmentIndexValue() + 1);
|
_segmentIdx->SetValue(_entryData->GetSegmentIndexValue() + 1);
|
||||||
_segmentIdx->SetMacro(_entryData->GetMacro());
|
_segmentIdx->SetMacro(_entryData->GetMacro());
|
||||||
_segmentIdx->SetType(
|
_segmentIdx->SetType(
|
||||||
_entryData->_type ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Type::SET_CONDITION_VALUE
|
MacroActionVariable::Action::SET_CONDITION_VALUE
|
||||||
? MacroSegmentSelection::Type::CONDITION
|
? MacroSegmentSelection::Type::CONDITION
|
||||||
: MacroSegmentSelection::Type::ACTION);
|
: MacroSegmentSelection::Type::ACTION);
|
||||||
_subStringStart->SetValue(_entryData->_subStringStart);
|
_subStringStart->SetValue(_entryData->_subStringStart);
|
||||||
@@ -963,6 +1054,9 @@ void MacroActionVariableEdit::UpdateEntryData()
|
|||||||
QChar::fromLatin1(_entryData->_paddingChar));
|
QChar::fromLatin1(_entryData->_paddingChar));
|
||||||
_caseType->setCurrentIndex(
|
_caseType->setCurrentIndex(
|
||||||
_caseType->findData(static_cast<int>(_entryData->_caseType)));
|
_caseType->findData(static_cast<int>(_entryData->_caseType)));
|
||||||
|
_randomNumberStart->SetValue(_entryData->_randomNumberStart);
|
||||||
|
_randomNumberEnd->SetValue(_entryData->_randomNumberEnd);
|
||||||
|
_generateInteger->setChecked(_entryData->_generateInteger);
|
||||||
|
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
@@ -996,13 +1090,14 @@ void MacroActionVariableEdit::ActionChanged(int idx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
_entryData->_type = static_cast<MacroActionVariable::Type>(
|
_entryData->_action = static_cast<MacroActionVariable::Action>(
|
||||||
_actions->itemData(idx).toInt());
|
_actions->itemData(idx).toInt());
|
||||||
|
|
||||||
if (_entryData->_type == MacroActionVariable::Type::SET_ACTION_VALUE) {
|
if (_entryData->_action ==
|
||||||
|
MacroActionVariable::Action::SET_ACTION_VALUE) {
|
||||||
_segmentIdx->SetType(MacroSegmentSelection::Type::ACTION);
|
_segmentIdx->SetType(MacroSegmentSelection::Type::ACTION);
|
||||||
} else if (_entryData->_type ==
|
} else if (_entryData->_action ==
|
||||||
MacroActionVariable::Type::SET_CONDITION_VALUE) {
|
MacroActionVariable::Action::SET_CONDITION_VALUE) {
|
||||||
_segmentIdx->SetType(MacroSegmentSelection::Type::CONDITION);
|
_segmentIdx->SetType(MacroSegmentSelection::Type::CONDITION);
|
||||||
}
|
}
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
@@ -1054,10 +1149,10 @@ void MacroActionVariableEdit::SetSegmentValueError(const QString &text)
|
|||||||
void MacroActionVariableEdit::UpdateSegmentVariableValue()
|
void MacroActionVariableEdit::UpdateSegmentVariableValue()
|
||||||
{
|
{
|
||||||
if (!_entryData ||
|
if (!_entryData ||
|
||||||
!(_entryData->_type ==
|
!(_entryData->_action ==
|
||||||
MacroActionVariable::Type::SET_CONDITION_VALUE ||
|
MacroActionVariable::Action::SET_CONDITION_VALUE ||
|
||||||
_entryData->_type ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Type::SET_ACTION_VALUE)) {
|
MacroActionVariable::Action::SET_ACTION_VALUE)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1076,13 +1171,14 @@ void MacroActionVariableEdit::UpdateSegmentVariableValue()
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<MacroSegment> segment;
|
std::shared_ptr<MacroSegment> segment;
|
||||||
if (_entryData->_type == MacroActionVariable::Type::SET_ACTION_VALUE) {
|
if (_entryData->_action ==
|
||||||
|
MacroActionVariable::Action::SET_ACTION_VALUE) {
|
||||||
const auto &actions = m->Actions();
|
const auto &actions = m->Actions();
|
||||||
if (index < (int)actions.size()) {
|
if (index < (int)actions.size()) {
|
||||||
segment = actions.at(index);
|
segment = actions.at(index);
|
||||||
}
|
}
|
||||||
} else if (_entryData->_type ==
|
} else if (_entryData->_action ==
|
||||||
MacroActionVariable::Type::SET_CONDITION_VALUE) {
|
MacroActionVariable::Action::SET_CONDITION_VALUE) {
|
||||||
const auto &conditions = m->Conditions();
|
const auto &conditions = m->Conditions();
|
||||||
if (index < (int)conditions.size()) {
|
if (index < (int)conditions.size()) {
|
||||||
segment = conditions.at(index);
|
segment = conditions.at(index);
|
||||||
@@ -1099,14 +1195,14 @@ void MacroActionVariableEdit::UpdateSegmentVariableValue()
|
|||||||
std::string type;
|
std::string type;
|
||||||
QString fmt;
|
QString fmt;
|
||||||
|
|
||||||
if (_entryData->_type ==
|
if (_entryData->_action ==
|
||||||
MacroActionVariable::Type::SET_ACTION_VALUE) {
|
MacroActionVariable::Action::SET_ACTION_VALUE) {
|
||||||
type = MacroActionFactory::GetActionName(
|
type = MacroActionFactory::GetActionName(
|
||||||
segment->GetId());
|
segment->GetId());
|
||||||
fmt = QString(obs_module_text(
|
fmt = QString(obs_module_text(
|
||||||
"AdvSceneSwitcher.action.variable.actionNoVariableSupport"));
|
"AdvSceneSwitcher.action.variable.actionNoVariableSupport"));
|
||||||
} else if (_entryData->_type ==
|
} else if (_entryData->_action ==
|
||||||
MacroActionVariable::Type::SET_CONDITION_VALUE) {
|
MacroActionVariable::Action::SET_CONDITION_VALUE) {
|
||||||
type = MacroConditionFactory::GetConditionName(
|
type = MacroConditionFactory::GetConditionName(
|
||||||
segment->GetId());
|
segment->GetId());
|
||||||
fmt = QString(obs_module_text(
|
fmt = QString(obs_module_text(
|
||||||
@@ -1385,6 +1481,26 @@ void MacroActionVariableEdit::CaseTypeChanged(int index)
|
|||||||
_caseType->itemData(index).toInt());
|
_caseType->itemData(index).toInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionVariableEdit::RandomNumberStartChanged(
|
||||||
|
const NumberVariable<double> &value)
|
||||||
|
{
|
||||||
|
GUARD_LOADING_AND_LOCK();
|
||||||
|
_entryData->_randomNumberStart = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionVariableEdit::RandomNumberEndChanged(
|
||||||
|
const NumberVariable<double> &value)
|
||||||
|
{
|
||||||
|
GUARD_LOADING_AND_LOCK();
|
||||||
|
_entryData->_randomNumberEnd = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionVariableEdit::GenerateIntegerChanged(int value)
|
||||||
|
{
|
||||||
|
GUARD_LOADING_AND_LOCK();
|
||||||
|
_entryData->_generateInteger = value;
|
||||||
|
}
|
||||||
|
|
||||||
void MacroActionVariableEdit::SetWidgetVisibility()
|
void MacroActionVariableEdit::SetWidgetVisibility()
|
||||||
{
|
{
|
||||||
if (!_entryData) {
|
if (!_entryData) {
|
||||||
@@ -1411,10 +1527,11 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
|||||||
};
|
};
|
||||||
|
|
||||||
const char *layoutString = "";
|
const char *layoutString = "";
|
||||||
if (_entryData->_type == MacroActionVariable::Type::PAD) {
|
if (_entryData->_action == MacroActionVariable::Action::PAD) {
|
||||||
layoutString = obs_module_text(
|
layoutString = obs_module_text(
|
||||||
"AdvSceneSwitcher.action.variable.entry.pad");
|
"AdvSceneSwitcher.action.variable.entry.pad");
|
||||||
} else if (_entryData->_type == MacroActionVariable::Type::TRUNCATE) {
|
} else if (_entryData->_action ==
|
||||||
|
MacroActionVariable::Action::TRUNCATE) {
|
||||||
layoutString = obs_module_text(
|
layoutString = obs_module_text(
|
||||||
"AdvSceneSwitcher.action.variable.entry.truncate");
|
"AdvSceneSwitcher.action.variable.entry.truncate");
|
||||||
} else {
|
} else {
|
||||||
@@ -1429,64 +1546,70 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
|||||||
ClearLayout(_entryLayout);
|
ClearLayout(_entryLayout);
|
||||||
PlaceWidgets(layoutString, _entryLayout, widgetPlaceholders);
|
PlaceWidgets(layoutString, _entryLayout, widgetPlaceholders);
|
||||||
|
|
||||||
if (_entryData->_type == MacroActionVariable::Type::SET_FIXED_VALUE ||
|
if (_entryData->_action == MacroActionVariable::Action::SET_VALUE ||
|
||||||
_entryData->_type == MacroActionVariable::Type::APPEND ||
|
_entryData->_action == MacroActionVariable::Action::APPEND ||
|
||||||
_entryData->_type == MacroActionVariable::Type::MATH_EXPRESSION ||
|
_entryData->_action ==
|
||||||
_entryData->_type == MacroActionVariable::Type::ENV_VARIABLE ||
|
MacroActionVariable::Action::MATH_EXPRESSION ||
|
||||||
_entryData->_type == MacroActionVariable::Type::STRING_LENGTH ||
|
_entryData->_action == MacroActionVariable::Action::ENV_VARIABLE ||
|
||||||
_entryData->_type == MacroActionVariable::Type::EXTRACT_JSON) {
|
_entryData->_action == MacroActionVariable::Action::STRING_LENGTH ||
|
||||||
|
_entryData->_action == MacroActionVariable::Action::EXTRACT_JSON) {
|
||||||
RemoveStretchIfPresent(_entryLayout);
|
RemoveStretchIfPresent(_entryLayout);
|
||||||
} else {
|
} else {
|
||||||
AddStretchIfNecessary(_entryLayout);
|
AddStretchIfNecessary(_entryLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
_variables2->setVisible(
|
_variables2->setVisible(
|
||||||
_entryData->_type == MacroActionVariable::Type::APPEND_VAR ||
|
_entryData->_action ==
|
||||||
_entryData->_type == MacroActionVariable::Type::SWAP_VALUES);
|
MacroActionVariable::Action::APPEND_VAR ||
|
||||||
|
_entryData->_action ==
|
||||||
|
MacroActionVariable::Action::SWAP_VALUES);
|
||||||
_strValue->setVisible(
|
_strValue->setVisible(
|
||||||
_entryData->_type ==
|
_entryData->_action == MacroActionVariable::Action::SET_VALUE ||
|
||||||
MacroActionVariable::Type::SET_FIXED_VALUE ||
|
_entryData->_action == MacroActionVariable::Action::APPEND ||
|
||||||
_entryData->_type == MacroActionVariable::Type::APPEND ||
|
_entryData->_action ==
|
||||||
_entryData->_type == MacroActionVariable::Type::STRING_LENGTH ||
|
MacroActionVariable::Action::STRING_LENGTH ||
|
||||||
_entryData->_type == MacroActionVariable::Type::EXTRACT_JSON);
|
_entryData->_action ==
|
||||||
|
MacroActionVariable::Action::EXTRACT_JSON);
|
||||||
_numValue->setVisible(
|
_numValue->setVisible(
|
||||||
_entryData->_type == MacroActionVariable::Type::INCREMENT ||
|
_entryData->_action == MacroActionVariable::Action::INCREMENT ||
|
||||||
_entryData->_type == MacroActionVariable::Type::DECREMENT);
|
_entryData->_action == MacroActionVariable::Action::DECREMENT);
|
||||||
_segmentValueStatus->setVisible(
|
_segmentValueStatus->setVisible(
|
||||||
_entryData->_type ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Type::SET_ACTION_VALUE ||
|
MacroActionVariable::Action::SET_ACTION_VALUE ||
|
||||||
_entryData->_type ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Type::SET_CONDITION_VALUE);
|
MacroActionVariable::Action::SET_CONDITION_VALUE);
|
||||||
_segmentValue->setVisible(
|
_segmentValue->setVisible(
|
||||||
_entryData->_type ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Type::SET_ACTION_VALUE ||
|
MacroActionVariable::Action::SET_ACTION_VALUE ||
|
||||||
_entryData->_type ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Type::SET_CONDITION_VALUE);
|
MacroActionVariable::Action::SET_CONDITION_VALUE);
|
||||||
_segmentIdx->setVisible(
|
_segmentIdx->setVisible(
|
||||||
_entryData->_type ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Type::SET_ACTION_VALUE ||
|
MacroActionVariable::Action::SET_ACTION_VALUE ||
|
||||||
_entryData->_type ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Type::SET_CONDITION_VALUE);
|
MacroActionVariable::Action::SET_CONDITION_VALUE);
|
||||||
SetLayoutVisible(_substringLayout,
|
SetLayoutVisible(_substringLayout,
|
||||||
_entryData->_type ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Type::SUBSTRING);
|
MacroActionVariable::Action::SUBSTRING);
|
||||||
if (_entryData->_type == MacroActionVariable::Type::SUBSTRING) {
|
if (_entryData->_action == MacroActionVariable::Action::SUBSTRING) {
|
||||||
bool showRegex = _entryData->_subStringRegex.Enabled();
|
bool showRegex = _entryData->_subStringRegex.Enabled();
|
||||||
SetLayoutVisible(_subStringIndexEntryLayout, !showRegex);
|
SetLayoutVisible(_subStringIndexEntryLayout, !showRegex);
|
||||||
SetLayoutVisible(_subStringRegexEntryLayout, showRegex);
|
SetLayoutVisible(_subStringRegexEntryLayout, showRegex);
|
||||||
_regexPattern->setVisible(showRegex);
|
_regexPattern->setVisible(showRegex);
|
||||||
}
|
}
|
||||||
SetLayoutVisible(_findReplaceLayout,
|
SetLayoutVisible(_findReplaceLayout,
|
||||||
_entryData->_type ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Type::FIND_AND_REPLACE);
|
MacroActionVariable::Action::FIND_AND_REPLACE);
|
||||||
_mathExpression->setVisible(_entryData->_type ==
|
_mathExpression->setVisible(
|
||||||
MacroActionVariable::Type::MATH_EXPRESSION);
|
_entryData->_action ==
|
||||||
|
MacroActionVariable::Action::MATH_EXPRESSION);
|
||||||
_mathExpressionResult->hide();
|
_mathExpressionResult->hide();
|
||||||
SetLayoutVisible(_promptLayout,
|
SetLayoutVisible(_promptLayout,
|
||||||
_entryData->_type ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Type::USER_INPUT);
|
MacroActionVariable::Action::USER_INPUT);
|
||||||
_inputPrompt->setVisible(
|
_inputPrompt->setVisible(
|
||||||
_entryData->_type == MacroActionVariable::Type::USER_INPUT &&
|
_entryData->_action ==
|
||||||
|
MacroActionVariable::Action::USER_INPUT &&
|
||||||
_entryData->_useCustomPrompt);
|
_entryData->_useCustomPrompt);
|
||||||
if (_entryData->_useCustomPrompt) {
|
if (_entryData->_useCustomPrompt) {
|
||||||
RemoveStretchIfPresent(_promptLayout);
|
RemoveStretchIfPresent(_promptLayout);
|
||||||
@@ -1495,13 +1618,16 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
|||||||
}
|
}
|
||||||
SetLayoutVisible(
|
SetLayoutVisible(
|
||||||
_placeholderLayout,
|
_placeholderLayout,
|
||||||
_entryData->_type == MacroActionVariable::Type::USER_INPUT &&
|
_entryData->_action ==
|
||||||
|
MacroActionVariable::Action::USER_INPUT &&
|
||||||
_entryData->_useCustomPrompt);
|
_entryData->_useCustomPrompt);
|
||||||
_useInputPlaceholder->setVisible(
|
_useInputPlaceholder->setVisible(
|
||||||
_entryData->_type == MacroActionVariable::Type::USER_INPUT &&
|
_entryData->_action ==
|
||||||
|
MacroActionVariable::Action::USER_INPUT &&
|
||||||
_entryData->_useCustomPrompt);
|
_entryData->_useCustomPrompt);
|
||||||
_inputPlaceholder->setVisible(
|
_inputPlaceholder->setVisible(
|
||||||
_entryData->_type == MacroActionVariable::Type::USER_INPUT &&
|
_entryData->_action ==
|
||||||
|
MacroActionVariable::Action::USER_INPUT &&
|
||||||
_entryData->_useCustomPrompt &&
|
_entryData->_useCustomPrompt &&
|
||||||
_entryData->_useInputPlaceholder);
|
_entryData->_useInputPlaceholder);
|
||||||
if (_entryData->_useInputPlaceholder) {
|
if (_entryData->_useInputPlaceholder) {
|
||||||
@@ -1509,31 +1635,35 @@ void MacroActionVariableEdit::SetWidgetVisibility()
|
|||||||
} else {
|
} else {
|
||||||
AddStretchIfNecessary(_placeholderLayout);
|
AddStretchIfNecessary(_placeholderLayout);
|
||||||
}
|
}
|
||||||
_envVariable->setVisible(_entryData->_type ==
|
_envVariable->setVisible(_entryData->_action ==
|
||||||
MacroActionVariable::Type::ENV_VARIABLE);
|
MacroActionVariable::Action::ENV_VARIABLE);
|
||||||
_scenes->setVisible(
|
_scenes->setVisible(
|
||||||
_entryData->_type ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Type::SCENE_ITEM_COUNT ||
|
MacroActionVariable::Action::SCENE_ITEM_COUNT ||
|
||||||
_entryData->_type ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Type::SCENE_ITEM_NAME);
|
MacroActionVariable::Action::SCENE_ITEM_NAME);
|
||||||
_tempVars->setVisible(_entryData->_type ==
|
_tempVars->setVisible(_entryData->_action ==
|
||||||
MacroActionVariable::Type::SET_TO_TEMPVAR);
|
MacroActionVariable::Action::SET_TO_TEMPVAR);
|
||||||
_tempVarsHelp->setVisible(
|
_tempVarsHelp->setVisible(
|
||||||
_entryData->_type ==
|
_entryData->_action ==
|
||||||
MacroActionVariable::Type::SET_TO_TEMPVAR &&
|
MacroActionVariable::Action::SET_TO_TEMPVAR &&
|
||||||
!_entryData->_tempVar.HasValidID());
|
!_entryData->_tempVar.HasValidID());
|
||||||
_sceneItemIndex->setVisible(_entryData->_type ==
|
_sceneItemIndex->setVisible(
|
||||||
MacroActionVariable::Type::SCENE_ITEM_NAME);
|
_entryData->_action ==
|
||||||
|
MacroActionVariable::Action::SCENE_ITEM_NAME);
|
||||||
_direction->setVisible(
|
_direction->setVisible(
|
||||||
_entryData->_type == MacroActionVariable::Type::PAD ||
|
_entryData->_action == MacroActionVariable::Action::PAD ||
|
||||||
_entryData->_type == MacroActionVariable::Type::TRUNCATE);
|
_entryData->_action == MacroActionVariable::Action::TRUNCATE);
|
||||||
_stringLength->setVisible(
|
_stringLength->setVisible(
|
||||||
_entryData->_type == MacroActionVariable::Type::PAD ||
|
_entryData->_action == MacroActionVariable::Action::PAD ||
|
||||||
_entryData->_type == MacroActionVariable::Type::TRUNCATE);
|
_entryData->_action == MacroActionVariable::Action::TRUNCATE);
|
||||||
_paddingCharSelection->setVisible(_entryData->_type ==
|
_paddingCharSelection->setVisible(_entryData->_action ==
|
||||||
MacroActionVariable::Type::PAD);
|
MacroActionVariable::Action::PAD);
|
||||||
_caseType->setVisible(_entryData->_type ==
|
_caseType->setVisible(_entryData->_action ==
|
||||||
MacroActionVariable::Type::CHANGE_CASE);
|
MacroActionVariable::Action::CHANGE_CASE);
|
||||||
|
SetLayoutVisible(_randomLayout,
|
||||||
|
_entryData->_action ==
|
||||||
|
MacroActionVariable::Action::RANDOM_NUMBER);
|
||||||
|
|
||||||
adjustSize();
|
adjustSize();
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ public:
|
|||||||
int GetSegmentIndexValue() const;
|
int GetSegmentIndexValue() const;
|
||||||
void ResolveVariablesToFixedValues();
|
void ResolveVariablesToFixedValues();
|
||||||
|
|
||||||
enum class Type {
|
enum class Action {
|
||||||
SET_FIXED_VALUE,
|
SET_VALUE,
|
||||||
APPEND,
|
APPEND,
|
||||||
APPEND_VAR,
|
APPEND_VAR,
|
||||||
INCREMENT,
|
INCREMENT,
|
||||||
@@ -52,9 +52,10 @@ public:
|
|||||||
SWAP_VALUES,
|
SWAP_VALUES,
|
||||||
TRIM,
|
TRIM,
|
||||||
CHANGE_CASE,
|
CHANGE_CASE,
|
||||||
|
RANDOM_NUMBER,
|
||||||
};
|
};
|
||||||
|
|
||||||
Type _type = Type::SET_FIXED_VALUE;
|
Action _action = Action::SET_VALUE;
|
||||||
std::weak_ptr<Variable> _variable;
|
std::weak_ptr<Variable> _variable;
|
||||||
std::weak_ptr<Variable> _variable2;
|
std::weak_ptr<Variable> _variable2;
|
||||||
StringVariable _strValue = "";
|
StringVariable _strValue = "";
|
||||||
@@ -99,6 +100,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
CaseType _caseType = CaseType::LOWER_CASE;
|
CaseType _caseType = CaseType::LOWER_CASE;
|
||||||
|
DoubleVariable _randomNumberStart = 0;
|
||||||
|
DoubleVariable _randomNumberEnd = 100;
|
||||||
|
bool _generateInteger = true;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DecrementCurrentSegmentVariableRef();
|
void DecrementCurrentSegmentVariableRef();
|
||||||
@@ -108,6 +112,7 @@ private:
|
|||||||
void HandleMathExpression(Variable *);
|
void HandleMathExpression(Variable *);
|
||||||
void HandleCaseChange(Variable *);
|
void HandleCaseChange(Variable *);
|
||||||
void SetToSceneItemName(Variable *);
|
void SetToSceneItemName(Variable *);
|
||||||
|
void GenerateRandomNumber(Variable *);
|
||||||
|
|
||||||
std::weak_ptr<MacroSegment> _macroSegment;
|
std::weak_ptr<MacroSegment> _macroSegment;
|
||||||
int _segmentIdxLoadValue = -1;
|
int _segmentIdxLoadValue = -1;
|
||||||
@@ -161,6 +166,9 @@ private slots:
|
|||||||
void StringLengthChanged(const NumberVariable<int> &);
|
void StringLengthChanged(const NumberVariable<int> &);
|
||||||
void CharSelectionChanged(const QString &);
|
void CharSelectionChanged(const QString &);
|
||||||
void CaseTypeChanged(int index);
|
void CaseTypeChanged(int index);
|
||||||
|
void RandomNumberStartChanged(const NumberVariable<double> &);
|
||||||
|
void RandomNumberEndChanged(const NumberVariable<double> &);
|
||||||
|
void GenerateIntegerChanged(int);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
@@ -206,6 +214,10 @@ private:
|
|||||||
VariableSpinBox *_stringLength;
|
VariableSpinBox *_stringLength;
|
||||||
SingleCharSelection *_paddingCharSelection;
|
SingleCharSelection *_paddingCharSelection;
|
||||||
FilterComboBox *_caseType;
|
FilterComboBox *_caseType;
|
||||||
|
VariableDoubleSpinBox *_randomNumberStart;
|
||||||
|
VariableDoubleSpinBox *_randomNumberEnd;
|
||||||
|
QCheckBox *_generateInteger;
|
||||||
|
QVBoxLayout *_randomLayout;
|
||||||
QHBoxLayout *_entryLayout;
|
QHBoxLayout *_entryLayout;
|
||||||
|
|
||||||
std::shared_ptr<MacroActionVariable> _entryData;
|
std::shared_ptr<MacroActionVariable> _entryData;
|
||||||
|
|||||||
@@ -8,10 +8,14 @@ namespace advss {
|
|||||||
MacroConditionScript::MacroConditionScript(
|
MacroConditionScript::MacroConditionScript(
|
||||||
Macro *m, const std::string &id, const OBSData &defaultSettings,
|
Macro *m, const std::string &id, const OBSData &defaultSettings,
|
||||||
const std::string &propertiesSignalName,
|
const std::string &propertiesSignalName,
|
||||||
const std::string &triggerSignal, const std::string &completionSignal)
|
const std::string &triggerSignalName,
|
||||||
|
const std::string &completionSignalName,
|
||||||
|
const std::string &newInstanceSignalName,
|
||||||
|
const std::string &deletedInstanceSignalName)
|
||||||
: MacroCondition(m),
|
: MacroCondition(m),
|
||||||
MacroSegmentScript(defaultSettings, propertiesSignalName,
|
MacroSegmentScript(defaultSettings, propertiesSignalName,
|
||||||
triggerSignal, completionSignal),
|
triggerSignalName, completionSignalName,
|
||||||
|
newInstanceSignalName, deletedInstanceSignalName),
|
||||||
_id(id)
|
_id(id)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -76,4 +80,29 @@ void MacroConditionScript::WaitForCompletion() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroConditionScript::RegisterTempVarHelper(const std::string &variableId,
|
||||||
|
const std::string &name,
|
||||||
|
const std::string &helpText)
|
||||||
|
{
|
||||||
|
AddTempvar(variableId, name, helpText);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionScript::DeregisterAllTempVarsHelper()
|
||||||
|
{
|
||||||
|
MacroSegment::SetupTempVars();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionScript::SetTempVarValueHelper(const std::string &variableId,
|
||||||
|
const std::string &value)
|
||||||
|
{
|
||||||
|
MacroCondition::SetTempVarValue(variableId, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionScript::SetupTempVars()
|
||||||
|
{
|
||||||
|
// This just exists so MacroSegment::SetupTempVars() is not called.
|
||||||
|
// We want the ScriptHandler to handle the registration and clearing of
|
||||||
|
// the temp vars.
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -10,8 +10,10 @@ public:
|
|||||||
MacroConditionScript(Macro *m, const std::string &id,
|
MacroConditionScript(Macro *m, const std::string &id,
|
||||||
const OBSData &defaultSettings,
|
const OBSData &defaultSettings,
|
||||||
const std::string &propertiesSignalName,
|
const std::string &propertiesSignalName,
|
||||||
const std::string &triggerSignal,
|
const std::string &triggerSignalName,
|
||||||
const std::string &signalComplete);
|
const std::string &completionSignalName,
|
||||||
|
const std::string &newInstanceSignalName,
|
||||||
|
const std::string &deletedInstanceSignalName);
|
||||||
MacroConditionScript(const advss::MacroConditionScript &);
|
MacroConditionScript(const advss::MacroConditionScript &);
|
||||||
bool CheckCondition();
|
bool CheckCondition();
|
||||||
bool Save(obs_data_t *obj) const;
|
bool Save(obs_data_t *obj) const;
|
||||||
@@ -20,6 +22,13 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void WaitForCompletion() const;
|
void WaitForCompletion() const;
|
||||||
|
void RegisterTempVarHelper(const std::string &variableId,
|
||||||
|
const std::string &name,
|
||||||
|
const std::string &helpText);
|
||||||
|
void DeregisterAllTempVarsHelper();
|
||||||
|
void SetTempVarValueHelper(const std::string &variableId,
|
||||||
|
const std::string &value);
|
||||||
|
void SetupTempVars();
|
||||||
|
|
||||||
std::string _id = "";
|
std::string _id = "";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -109,6 +109,14 @@ bool MacroWasPausedSince(
|
|||||||
return macro ? macro->WasPausedSince(time) : false;
|
return macro ? macro->WasPausedSince(time) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MacroWasCheckedSinceLastStart(Macro *macro)
|
||||||
|
{
|
||||||
|
if (!macro) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return macro->LastConditionCheckTime().time_since_epoch().count() != 0;
|
||||||
|
}
|
||||||
|
|
||||||
void AddMacroHelperThread(Macro *macro, std::thread &&newThread)
|
void AddMacroHelperThread(Macro *macro, std::thread &&newThread)
|
||||||
{
|
{
|
||||||
if (!macro) {
|
if (!macro) {
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ EXPORT bool MacroIsPaused(Macro *);
|
|||||||
EXPORT bool
|
EXPORT bool
|
||||||
MacroWasPausedSince(Macro *,
|
MacroWasPausedSince(Macro *,
|
||||||
const std::chrono::high_resolution_clock::time_point &);
|
const std::chrono::high_resolution_clock::time_point &);
|
||||||
|
EXPORT bool MacroWasCheckedSinceLastStart(Macro *);
|
||||||
|
|
||||||
EXPORT void AddMacroHelperThread(Macro *, std::thread &&);
|
EXPORT void AddMacroHelperThread(Macro *, std::thread &&);
|
||||||
|
|
||||||
|
|||||||
@@ -181,15 +181,7 @@ void MacroInputEdit::SetInputVariablesAndValues(
|
|||||||
_variables = inputs;
|
_variables = inputs;
|
||||||
_values = values;
|
_values = values;
|
||||||
if ((size_t)_values.size() < _variables._inputVariables.size()) {
|
if ((size_t)_values.size() < _variables._inputVariables.size()) {
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
for (int i = 0;
|
|
||||||
_variables._inputVariables.size() - (size_t)_values.size();
|
|
||||||
i++) {
|
|
||||||
_values.push_back({});
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
_values.resize(_variables._inputVariables.size());
|
_values.resize(_variables._inputVariables.size());
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
SetupWidgets();
|
SetupWidgets();
|
||||||
}
|
}
|
||||||
@@ -199,7 +191,7 @@ bool MacroInputEdit::HasInputsToSet() const
|
|||||||
return !_variables._inputVariables.empty();
|
return !_variables._inputVariables.empty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void HighligthMacroSettingsButton(bool enable);
|
void HighlightMacroSettingsButton(bool enable);
|
||||||
|
|
||||||
void MacroInputEdit::SetupWidgets()
|
void MacroInputEdit::SetupWidgets()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -29,6 +29,10 @@ static constexpr std::string_view defaultSettingsParam = "default_settings";
|
|||||||
static constexpr std::string_view propertiesSignalParam =
|
static constexpr std::string_view propertiesSignalParam =
|
||||||
"properties_signal_name";
|
"properties_signal_name";
|
||||||
static constexpr std::string_view triggerSignalParam = "trigger_signal_name";
|
static constexpr std::string_view triggerSignalParam = "trigger_signal_name";
|
||||||
|
static constexpr std::string_view newInstanceSignalNameParam =
|
||||||
|
"new_instance_signal_name";
|
||||||
|
static constexpr std::string_view deletedInstanceSignalNameParam =
|
||||||
|
"deleted_instance_signal_name";
|
||||||
|
|
||||||
static std::string getRegisterScriptSegmentDeclString(const char *funcName)
|
static std::string getRegisterScriptSegmentDeclString(const char *funcName)
|
||||||
{
|
{
|
||||||
@@ -72,16 +76,37 @@ static const std::string deregisterScriptConditionDeclString =
|
|||||||
/* Script variables */
|
/* Script variables */
|
||||||
|
|
||||||
static constexpr std::string_view valueParam = "value";
|
static constexpr std::string_view valueParam = "value";
|
||||||
|
static constexpr std::string_view tempVarIdParam = "temp_var_id";
|
||||||
|
static constexpr std::string_view tempVarNameParam = "temp_var_name";
|
||||||
|
static constexpr std::string_view tempVarHelpParam = "temp_var_help";
|
||||||
static constexpr std::string_view getVariableValueFuncName =
|
static constexpr std::string_view getVariableValueFuncName =
|
||||||
"advss_get_variable_value";
|
"advss_get_variable_value";
|
||||||
static constexpr std::string_view setVariableValueFuncName =
|
static constexpr std::string_view setVariableValueFuncName =
|
||||||
"advss_set_variable_value";
|
"advss_set_variable_value";
|
||||||
|
static constexpr std::string_view registerTempVarFuncName =
|
||||||
|
"advss_register_temp_var";
|
||||||
|
static constexpr std::string_view deregisterAllTempVarsFuncName =
|
||||||
|
"advss_deregister_temp_vars";
|
||||||
|
static constexpr std::string_view setTempVarValueFuncName =
|
||||||
|
"advss_set_temp_var_value";
|
||||||
static const std::string getVariableValueDeclString =
|
static const std::string getVariableValueDeclString =
|
||||||
std::string("bool ") + getVariableValueFuncName.data() + "(in string " +
|
std::string("bool ") + getVariableValueFuncName.data() + "(in string " +
|
||||||
nameParam.data() + ", out string " + valueParam.data() + ")";
|
nameParam.data() + ", out string " + valueParam.data() + ")";
|
||||||
static const std::string setVariableValueDeclString =
|
static const std::string setVariableValueDeclString =
|
||||||
std::string("bool ") + setVariableValueFuncName.data() + "(in string " +
|
std::string("bool ") + setVariableValueFuncName.data() + "(in string " +
|
||||||
nameParam.data() + ", in string " + valueParam.data() + ")";
|
nameParam.data() + ", in string " + valueParam.data() + ")";
|
||||||
|
static const std::string registerTempVarDeclString =
|
||||||
|
std::string("bool ") + registerTempVarFuncName.data() + "(in string " +
|
||||||
|
tempVarIdParam.data() + ", in string " + tempVarNameParam.data() +
|
||||||
|
", in string " + tempVarHelpParam.data() + ", in int " +
|
||||||
|
GetInstanceIdParamName().data() + ")";
|
||||||
|
static const std::string deregisterAllTempVarsDeclString =
|
||||||
|
std::string("bool ") + deregisterAllTempVarsFuncName.data() +
|
||||||
|
"(in int " + GetInstanceIdParamName().data() + ")";
|
||||||
|
static const std::string setTempVarValueDeclString =
|
||||||
|
std::string("bool ") + setTempVarValueFuncName.data() + "(in string " +
|
||||||
|
tempVarIdParam.data() + ", in string " + valueParam.data() +
|
||||||
|
", in int " + GetInstanceIdParamName().data() + ")";
|
||||||
|
|
||||||
static bool setup();
|
static bool setup();
|
||||||
static bool setupDone = setup();
|
static bool setupDone = setup();
|
||||||
@@ -103,13 +128,23 @@ static bool setup()
|
|||||||
&ScriptHandler::GetVariableValue, nullptr);
|
&ScriptHandler::GetVariableValue, nullptr);
|
||||||
proc_handler_add(ph, setVariableValueDeclString.c_str(),
|
proc_handler_add(ph, setVariableValueDeclString.c_str(),
|
||||||
&ScriptHandler::SetVariableValue, nullptr);
|
&ScriptHandler::SetVariableValue, nullptr);
|
||||||
|
proc_handler_add(ph, registerTempVarDeclString.c_str(),
|
||||||
|
&ScriptHandler::RegisterTempVar, nullptr);
|
||||||
|
proc_handler_add(ph, deregisterAllTempVarsDeclString.c_str(),
|
||||||
|
&ScriptHandler::DeregisterAllTempVars, nullptr);
|
||||||
|
proc_handler_add(ph, setTempVarValueDeclString.c_str(),
|
||||||
|
&ScriptHandler::SetTempVarValue, nullptr);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void replaceWhitespace(std::string &string)
|
static void replaceProblematicChars(std::string &string)
|
||||||
{
|
{
|
||||||
std::transform(string.begin(), string.end(), string.begin(), [](char c) {
|
std::transform(string.begin(), string.end(), string.begin(), [](char c) {
|
||||||
return std::isspace(static_cast<unsigned char>(c)) ? '_' : c;
|
if (std::isspace(static_cast<unsigned char>(c)) || c == '(' ||
|
||||||
|
c == ')' || c == '[' || c == ']' || c == '{' || c == '}') {
|
||||||
|
return '_';
|
||||||
|
}
|
||||||
|
return c;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,7 +157,7 @@ static std::string getTriggerSignal(const std::string &name,
|
|||||||
const bool isAction)
|
const bool isAction)
|
||||||
{
|
{
|
||||||
std::string signal = name;
|
std::string signal = name;
|
||||||
replaceWhitespace(signal);
|
replaceProblematicChars(signal);
|
||||||
signal += "_run";
|
signal += "_run";
|
||||||
signal += isAction ? "_action" : "_condition";
|
signal += isAction ? "_action" : "_condition";
|
||||||
return signal;
|
return signal;
|
||||||
@@ -140,12 +175,32 @@ static std::string getPropertiesSignal(const std::string &name,
|
|||||||
const bool isAction)
|
const bool isAction)
|
||||||
{
|
{
|
||||||
std::string signal = name;
|
std::string signal = name;
|
||||||
replaceWhitespace(signal);
|
replaceProblematicChars(signal);
|
||||||
signal += isAction ? "_action" : "_condition";
|
signal += isAction ? "_action" : "_condition";
|
||||||
signal += "_get_properties";
|
signal += "_get_properties";
|
||||||
return signal;
|
return signal;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::string getNewInstanceSignal(const std::string &name,
|
||||||
|
const bool isAction)
|
||||||
|
{
|
||||||
|
std::string signal = name;
|
||||||
|
replaceProblematicChars(signal);
|
||||||
|
signal += isAction ? "_action" : "_condition";
|
||||||
|
signal += "_new_instance";
|
||||||
|
return signal;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string getDeletedInstanceSignal(const std::string &name,
|
||||||
|
const bool isAction)
|
||||||
|
{
|
||||||
|
std::string signal = name;
|
||||||
|
replaceProblematicChars(signal);
|
||||||
|
signal += isAction ? "_action" : "_condition";
|
||||||
|
signal += "_deleted_instance";
|
||||||
|
return signal;
|
||||||
|
}
|
||||||
|
|
||||||
void ScriptHandler::RegisterScriptAction(void *, calldata_t *data)
|
void ScriptHandler::RegisterScriptAction(void *, calldata_t *data)
|
||||||
{
|
{
|
||||||
const char *actionName;
|
const char *actionName;
|
||||||
@@ -177,14 +232,19 @@ void ScriptHandler::RegisterScriptAction(void *, calldata_t *data)
|
|||||||
auto triggerSignalName = getTriggerSignal(actionName, true);
|
auto triggerSignalName = getTriggerSignal(actionName, true);
|
||||||
auto completionSignalName = getCompletionSignal(actionName, true);
|
auto completionSignalName = getCompletionSignal(actionName, true);
|
||||||
auto propertiesSignalName = getPropertiesSignal(actionName, true);
|
auto propertiesSignalName = getPropertiesSignal(actionName, true);
|
||||||
|
auto newInstanceSignalName = getNewInstanceSignal(actionName, true);
|
||||||
|
auto deletedInstanceSignalName =
|
||||||
|
getDeletedInstanceSignal(actionName, true);
|
||||||
|
|
||||||
const auto createScriptAction =
|
const auto createScriptAction =
|
||||||
[id, defaultSettings, propertiesSignalName, triggerSignalName,
|
[id, defaultSettings, propertiesSignalName, triggerSignalName,
|
||||||
completionSignalName](
|
completionSignalName, newInstanceSignalName,
|
||||||
|
deletedInstanceSignalName](
|
||||||
Macro *m) -> std::shared_ptr<MacroAction> {
|
Macro *m) -> std::shared_ptr<MacroAction> {
|
||||||
return std::make_shared<MacroActionScript>(
|
return std::make_shared<MacroActionScript>(
|
||||||
m, id, defaultSettings, propertiesSignalName,
|
m, id, defaultSettings, propertiesSignalName,
|
||||||
triggerSignalName, completionSignalName);
|
triggerSignalName, completionSignalName,
|
||||||
|
newInstanceSignalName, deletedInstanceSignalName);
|
||||||
};
|
};
|
||||||
if (!MacroActionFactory::Register(id, {createScriptAction,
|
if (!MacroActionFactory::Register(id, {createScriptAction,
|
||||||
MacroSegmentScriptEdit::Create,
|
MacroSegmentScriptEdit::Create,
|
||||||
@@ -202,9 +262,15 @@ void ScriptHandler::RegisterScriptAction(void *, calldata_t *data)
|
|||||||
triggerSignalName.c_str());
|
triggerSignalName.c_str());
|
||||||
calldata_set_string(data, propertiesSignalParam.data(),
|
calldata_set_string(data, propertiesSignalParam.data(),
|
||||||
propertiesSignalName.c_str());
|
propertiesSignalName.c_str());
|
||||||
|
calldata_set_string(data, newInstanceSignalNameParam.data(),
|
||||||
|
newInstanceSignalName.c_str());
|
||||||
|
calldata_set_string(data, deletedInstanceSignalNameParam.data(),
|
||||||
|
deletedInstanceSignalName.c_str());
|
||||||
_actions.emplace(id, ScriptSegmentType(id, propertiesSignalName,
|
_actions.emplace(id, ScriptSegmentType(id, propertiesSignalName,
|
||||||
triggerSignalName,
|
triggerSignalName,
|
||||||
completionSignalName));
|
completionSignalName,
|
||||||
|
newInstanceSignalName,
|
||||||
|
deletedInstanceSignalName));
|
||||||
|
|
||||||
RETURN_SUCCESS();
|
RETURN_SUCCESS();
|
||||||
}
|
}
|
||||||
@@ -279,14 +345,19 @@ void ScriptHandler::RegisterScriptCondition(void *, calldata_t *data)
|
|||||||
auto triggerSignalName = getTriggerSignal(conditionName, false);
|
auto triggerSignalName = getTriggerSignal(conditionName, false);
|
||||||
auto completionSignalName = getCompletionSignal(conditionName, false);
|
auto completionSignalName = getCompletionSignal(conditionName, false);
|
||||||
auto propertiesSignalName = getPropertiesSignal(conditionName, false);
|
auto propertiesSignalName = getPropertiesSignal(conditionName, false);
|
||||||
|
auto newInstanceSignalName = getNewInstanceSignal(conditionName, false);
|
||||||
|
auto deletedInstanceSignalName =
|
||||||
|
getDeletedInstanceSignal(conditionName, false);
|
||||||
|
|
||||||
const auto createScriptCondition =
|
const auto createScriptCondition =
|
||||||
[id, defaultSettings, propertiesSignalName, triggerSignalName,
|
[id, defaultSettings, propertiesSignalName, triggerSignalName,
|
||||||
completionSignalName](
|
completionSignalName, newInstanceSignalName,
|
||||||
|
deletedInstanceSignalName](
|
||||||
Macro *m) -> std::shared_ptr<MacroCondition> {
|
Macro *m) -> std::shared_ptr<MacroCondition> {
|
||||||
return std::make_shared<MacroConditionScript>(
|
return std::make_shared<MacroConditionScript>(
|
||||||
m, id, defaultSettings, propertiesSignalName,
|
m, id, defaultSettings, propertiesSignalName,
|
||||||
triggerSignalName, completionSignalName);
|
triggerSignalName, completionSignalName,
|
||||||
|
newInstanceSignalName, deletedInstanceSignalName);
|
||||||
};
|
};
|
||||||
if (!MacroConditionFactory::Register(
|
if (!MacroConditionFactory::Register(
|
||||||
id, {createScriptCondition, MacroSegmentScriptEdit::Create,
|
id, {createScriptCondition, MacroSegmentScriptEdit::Create,
|
||||||
@@ -304,9 +375,15 @@ void ScriptHandler::RegisterScriptCondition(void *, calldata_t *data)
|
|||||||
triggerSignalName.c_str());
|
triggerSignalName.c_str());
|
||||||
calldata_set_string(data, propertiesSignalParam.data(),
|
calldata_set_string(data, propertiesSignalParam.data(),
|
||||||
propertiesSignalName.c_str());
|
propertiesSignalName.c_str());
|
||||||
|
calldata_set_string(data, newInstanceSignalNameParam.data(),
|
||||||
|
newInstanceSignalName.c_str());
|
||||||
|
calldata_set_string(data, deletedInstanceSignalNameParam.data(),
|
||||||
|
deletedInstanceSignalName.c_str());
|
||||||
_conditions.emplace(id, ScriptSegmentType(id, propertiesSignalName,
|
_conditions.emplace(id, ScriptSegmentType(id, propertiesSignalName,
|
||||||
triggerSignalName,
|
triggerSignalName,
|
||||||
completionSignalName));
|
completionSignalName,
|
||||||
|
newInstanceSignalName,
|
||||||
|
deletedInstanceSignalName));
|
||||||
|
|
||||||
RETURN_SUCCESS();
|
RETURN_SUCCESS();
|
||||||
}
|
}
|
||||||
@@ -399,6 +476,92 @@ void ScriptHandler::SetVariableValue(void *, calldata_t *data)
|
|||||||
RETURN_SUCCESS();
|
RETURN_SUCCESS();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScriptHandler::RegisterTempVar(void *, calldata_t *data)
|
||||||
|
{
|
||||||
|
const char *variableId;
|
||||||
|
if (!calldata_get_string(data, tempVarIdParam.data(), &variableId) ||
|
||||||
|
strlen(variableId) == 0) {
|
||||||
|
blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!",
|
||||||
|
registerTempVarFuncName.data(), tempVarIdParam.data());
|
||||||
|
RETURN_FAILURE();
|
||||||
|
}
|
||||||
|
const char *name;
|
||||||
|
if (!calldata_get_string(data, tempVarNameParam.data(), &name) ||
|
||||||
|
strlen(name) == 0) {
|
||||||
|
blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!",
|
||||||
|
registerTempVarFuncName.data(), tempVarNameParam.data());
|
||||||
|
RETURN_FAILURE();
|
||||||
|
}
|
||||||
|
const char *helpText;
|
||||||
|
if (!calldata_get_string(data, tempVarHelpParam.data(), &helpText)) {
|
||||||
|
blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!",
|
||||||
|
registerTempVarFuncName.data(), tempVarHelpParam.data());
|
||||||
|
RETURN_FAILURE();
|
||||||
|
}
|
||||||
|
long long instanceId;
|
||||||
|
if (!calldata_get_int(data, GetInstanceIdParamName().data(),
|
||||||
|
&instanceId)) {
|
||||||
|
blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!",
|
||||||
|
registerTempVarFuncName.data(),
|
||||||
|
GetInstanceIdParamName().data());
|
||||||
|
RETURN_FAILURE();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
|
MacroSegmentScript::RegisterTempVar(variableId, name, helpText,
|
||||||
|
instanceId);
|
||||||
|
RETURN_SUCCESS();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptHandler::DeregisterAllTempVars(void *, calldata_t *data)
|
||||||
|
{
|
||||||
|
long long instanceId;
|
||||||
|
if (!calldata_get_int(data, GetInstanceIdParamName().data(),
|
||||||
|
&instanceId)) {
|
||||||
|
blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!",
|
||||||
|
deregisterAllTempVarsFuncName.data(),
|
||||||
|
GetInstanceIdParamName().data());
|
||||||
|
RETURN_FAILURE();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
|
MacroSegmentScript::DeregisterAllTempVars(instanceId);
|
||||||
|
RETURN_SUCCESS();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScriptHandler::SetTempVarValue(void *, calldata_t *data)
|
||||||
|
{
|
||||||
|
const char *variableId;
|
||||||
|
if (!calldata_get_string(data, tempVarIdParam.data(), &variableId) ||
|
||||||
|
strlen(variableId) == 0) {
|
||||||
|
blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!",
|
||||||
|
setTempVarValueFuncName.data(), tempVarIdParam.data());
|
||||||
|
RETURN_FAILURE();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *variableValue;
|
||||||
|
if (!calldata_get_string(data, valueParam.data(), &variableValue) ||
|
||||||
|
strlen(variableValue) == 0) {
|
||||||
|
blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!",
|
||||||
|
setTempVarValueFuncName.data(), valueParam.data());
|
||||||
|
RETURN_FAILURE();
|
||||||
|
}
|
||||||
|
|
||||||
|
long long instanceId;
|
||||||
|
if (!calldata_get_int(data, GetInstanceIdParamName().data(),
|
||||||
|
&instanceId)) {
|
||||||
|
blog(LOG_WARNING, "[%s] failed! \"%s\" parameter missing!",
|
||||||
|
setTempVarValueFuncName.data(),
|
||||||
|
GetInstanceIdParamName().data());
|
||||||
|
RETURN_FAILURE();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
|
MacroSegmentScript::SetTempVarValue(variableId, variableValue,
|
||||||
|
instanceId);
|
||||||
|
RETURN_SUCCESS();
|
||||||
|
}
|
||||||
|
|
||||||
bool ScriptHandler::ActionIdIsValid(const std::string &id)
|
bool ScriptHandler::ActionIdIsValid(const std::string &id)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(_mutex);
|
std::lock_guard<std::mutex> lock(_mutex);
|
||||||
@@ -424,24 +587,39 @@ static std::string signalNameToPropertiesSignalDecl(const std::string &name)
|
|||||||
static std::string signalNameToCompletionSignalDecl(const std::string &name)
|
static std::string signalNameToCompletionSignalDecl(const std::string &name)
|
||||||
{
|
{
|
||||||
return std::string("bool ") + name + "(in int " +
|
return std::string("bool ") + name + "(in int " +
|
||||||
GeCompletionIdParamName().data() + ")";
|
GetCompletionIdParamName().data() + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
ScriptSegmentType::ScriptSegmentType(const std::string &id,
|
static std::string signalNameToInstanceSignalDecl(const std::string &name)
|
||||||
const std::string &propertiesSignal,
|
{
|
||||||
const std::string &triggerSignal,
|
return std::string("void ") + name + "(out int " +
|
||||||
const std::string &completionSignal)
|
GetInstanceIdParamName().data() + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
ScriptSegmentType::ScriptSegmentType(
|
||||||
|
const std::string &id, const std::string &propertiesSignalName,
|
||||||
|
const std::string &triggerSignalName,
|
||||||
|
const std::string &completionSignalName,
|
||||||
|
const std::string &newInstanceSignalName,
|
||||||
|
const std::string &deletedInstanceSignalName)
|
||||||
: _id(id)
|
: _id(id)
|
||||||
{
|
{
|
||||||
|
auto sh = obs_get_signal_handler();
|
||||||
|
|
||||||
signal_handler_add(
|
signal_handler_add(
|
||||||
obs_get_signal_handler(),
|
sh,
|
||||||
signalNameToPropertiesSignalDecl(propertiesSignal).c_str());
|
signalNameToPropertiesSignalDecl(propertiesSignalName).c_str());
|
||||||
signal_handler_add(
|
signal_handler_add(
|
||||||
obs_get_signal_handler(),
|
sh, signalNameToTriggerSignalDecl(triggerSignalName).c_str());
|
||||||
signalNameToTriggerSignalDecl(triggerSignal).c_str());
|
|
||||||
signal_handler_add(
|
signal_handler_add(
|
||||||
obs_get_signal_handler(),
|
sh,
|
||||||
signalNameToCompletionSignalDecl(completionSignal).c_str());
|
signalNameToCompletionSignalDecl(completionSignalName).c_str());
|
||||||
|
signal_handler_add(
|
||||||
|
sh,
|
||||||
|
signalNameToInstanceSignalDecl(newInstanceSignalName).c_str());
|
||||||
|
signal_handler_add(
|
||||||
|
sh, signalNameToInstanceSignalDecl(deletedInstanceSignalName)
|
||||||
|
.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -10,9 +10,11 @@ class ScriptSegmentType {
|
|||||||
public:
|
public:
|
||||||
ScriptSegmentType() = delete;
|
ScriptSegmentType() = delete;
|
||||||
ScriptSegmentType(const std::string &id,
|
ScriptSegmentType(const std::string &id,
|
||||||
const std::string &propertiesSignal,
|
const std::string &propertiesSignalName,
|
||||||
const std::string &triggerSignal,
|
const std::string &triggerSignalName,
|
||||||
const std::string &completionSignal);
|
const std::string &completionSignalName,
|
||||||
|
const std::string &newInstanceSignalName,
|
||||||
|
const std::string &deletedInstanceSignalName);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string _id;
|
std::string _id;
|
||||||
@@ -26,6 +28,9 @@ public:
|
|||||||
static void RegisterScriptCondition(void *ctx, calldata_t *data);
|
static void RegisterScriptCondition(void *ctx, calldata_t *data);
|
||||||
static void DeregisterScriptCondition(void *ctx, calldata_t *data);
|
static void DeregisterScriptCondition(void *ctx, calldata_t *data);
|
||||||
static void GetVariableValue(void *ctx, calldata_t *data);
|
static void GetVariableValue(void *ctx, calldata_t *data);
|
||||||
|
static void RegisterTempVar(void *ctx, calldata_t *data);
|
||||||
|
static void DeregisterAllTempVars(void *ctx, calldata_t *data);
|
||||||
|
static void SetTempVarValue(void *ctx, calldata_t *data);
|
||||||
static void SetVariableValue(void *ctx, calldata_t *data);
|
static void SetVariableValue(void *ctx, calldata_t *data);
|
||||||
static bool ActionIdIsValid(const std::string &id);
|
static bool ActionIdIsValid(const std::string &id);
|
||||||
static bool ConditionIdIsValid(const std::string &id);
|
static bool ConditionIdIsValid(const std::string &id);
|
||||||
@@ -46,14 +51,19 @@ static constexpr std::string_view GetActionCompletionSignalParamName()
|
|||||||
return "completion_signal_name";
|
return "completion_signal_name";
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr std::string_view GeCompletionIdParamName()
|
static constexpr std::string_view GetCompletionIdParamName()
|
||||||
{
|
{
|
||||||
return "completion_id";
|
return "completion_id";
|
||||||
}
|
}
|
||||||
|
|
||||||
static constexpr std::string_view GeResultSignalParamName()
|
static constexpr std::string_view GetResultSignalParamName()
|
||||||
{
|
{
|
||||||
return "result";
|
return "result";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static constexpr std::string_view GetInstanceIdParamName()
|
||||||
|
{
|
||||||
|
return "instance_id";
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -178,11 +178,7 @@ void MacroSegmentList::mousePressEvent(QMouseEvent *event)
|
|||||||
{
|
{
|
||||||
if (event->button() == Qt::LeftButton ||
|
if (event->button() == Qt::LeftButton ||
|
||||||
event->button() == Qt::RightButton) {
|
event->button() == Qt::RightButton) {
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
_dragPosition = GetDragIndex(event->globalPos());
|
|
||||||
#else
|
|
||||||
_dragPosition = GetDragIndex(event->globalPosition().toPoint());
|
_dragPosition = GetDragIndex(event->globalPosition().toPoint());
|
||||||
#endif
|
|
||||||
emit SelectionChanged(_dragPosition);
|
emit SelectionChanged(_dragPosition);
|
||||||
} else {
|
} else {
|
||||||
_dragPosition = -1;
|
_dragPosition = -1;
|
||||||
@@ -300,11 +296,7 @@ void MacroSegmentList::dragMoveEvent(QDragMoveEvent *event)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
_dragCursorPos = (mapToGlobal(event->pos()));
|
|
||||||
#else
|
|
||||||
_dragCursorPos = (mapToGlobal(event->position().toPoint()));
|
_dragCursorPos = (mapToGlobal(event->position().toPoint()));
|
||||||
#endif
|
|
||||||
CheckDropLine(_dragCursorPos);
|
CheckDropLine(_dragCursorPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -450,16 +442,6 @@ void MacroSegmentList::dropEvent(QDropEvent *event)
|
|||||||
{
|
{
|
||||||
HideLastDropLine();
|
HideLastDropLine();
|
||||||
auto widget = qobject_cast<QWidget *>(event->source());
|
auto widget = qobject_cast<QWidget *>(event->source());
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
if (widget && !widget->geometry().contains(event->pos()) &&
|
|
||||||
widgetIsInLayout(widget, _contentLayout)) {
|
|
||||||
int dropPosition = GetDropIndex(mapToGlobal(event->pos()));
|
|
||||||
if (dropPosition == -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
emit Reorder(dropPosition, _dragPosition);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
if (widget &&
|
if (widget &&
|
||||||
!widget->geometry().contains(event->position().toPoint()) &&
|
!widget->geometry().contains(event->position().toPoint()) &&
|
||||||
widgetIsInLayout(widget, _contentLayout)) {
|
widgetIsInLayout(widget, _contentLayout)) {
|
||||||
@@ -470,7 +452,6 @@ void MacroSegmentList::dropEvent(QDropEvent *event)
|
|||||||
}
|
}
|
||||||
emit Reorder(dropPosition, _dragPosition);
|
emit Reorder(dropPosition, _dragPosition);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
_dragPosition = -1;
|
_dragPosition = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,33 +11,106 @@
|
|||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
static std::atomic_int completionIdCounter = 0;
|
static std::atomic_int completionIdCounter = 0;
|
||||||
|
static std::atomic_int instanceIdCounter = 0;
|
||||||
|
static std::mutex instanceMtx;
|
||||||
|
static std::vector<MacroSegmentScript *> instances{};
|
||||||
|
|
||||||
MacroSegmentScript::MacroSegmentScript(obs_data_t *defaultSettings,
|
MacroSegmentScript::MacroSegmentScript(
|
||||||
const std::string &propertiesSignalName,
|
obs_data_t *defaultSettings, const std::string &propertiesSignalName,
|
||||||
const std::string &triggerSignal,
|
const std::string &triggerSignalName,
|
||||||
const std::string &completionSignal)
|
const std::string &completionSignalName,
|
||||||
|
const std::string &newInstanceSignalName,
|
||||||
|
const std::string &deletedInstanceSignalName)
|
||||||
: _settings(obs_data_get_defaults(defaultSettings)),
|
: _settings(obs_data_get_defaults(defaultSettings)),
|
||||||
_propertiesSignal(propertiesSignalName),
|
_propertiesSignal(propertiesSignalName),
|
||||||
_triggerSignal(triggerSignal),
|
_triggerSignal(triggerSignalName),
|
||||||
_completionSignal(completionSignal)
|
_completionSignal(completionSignalName),
|
||||||
|
_newInstanceSignal(newInstanceSignalName),
|
||||||
|
_deletedInstanceSignal(deletedInstanceSignalName),
|
||||||
|
_instanceId(++instanceIdCounter)
|
||||||
{
|
{
|
||||||
signal_handler_connect(obs_get_signal_handler(),
|
signal_handler_connect(obs_get_signal_handler(),
|
||||||
completionSignal.c_str(),
|
completionSignalName.c_str(),
|
||||||
&MacroSegmentScript::CompletionSignalReceived,
|
&MacroSegmentScript::CompletionSignalReceived,
|
||||||
this);
|
this);
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(instanceMtx);
|
||||||
|
instances.emplace_back(this);
|
||||||
|
|
||||||
|
SignalNewInstance();
|
||||||
}
|
}
|
||||||
|
|
||||||
MacroSegmentScript::MacroSegmentScript(const MacroSegmentScript &other)
|
MacroSegmentScript::MacroSegmentScript(const MacroSegmentScript &other)
|
||||||
: _settings(obs_data_create()),
|
: _settings(obs_data_create()),
|
||||||
_propertiesSignal(other._propertiesSignal),
|
_propertiesSignal(other._propertiesSignal),
|
||||||
_triggerSignal(other._triggerSignal),
|
_triggerSignal(other._triggerSignal),
|
||||||
_completionSignal(other._completionSignal)
|
_completionSignal(other._completionSignal),
|
||||||
|
_newInstanceSignal(other._newInstanceSignal),
|
||||||
|
_deletedInstanceSignal(other._deletedInstanceSignal),
|
||||||
|
_instanceId(++instanceIdCounter)
|
||||||
{
|
{
|
||||||
signal_handler_connect(obs_get_signal_handler(),
|
signal_handler_connect(obs_get_signal_handler(),
|
||||||
_completionSignal.c_str(),
|
_completionSignal.c_str(),
|
||||||
&MacroSegmentScript::CompletionSignalReceived,
|
&MacroSegmentScript::CompletionSignalReceived,
|
||||||
this);
|
this);
|
||||||
obs_data_apply(_settings.Get(), other._settings.Get());
|
obs_data_apply(_settings.Get(), other._settings.Get());
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(instanceMtx);
|
||||||
|
instances.emplace_back(this);
|
||||||
|
|
||||||
|
SignalNewInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroSegmentScript::~MacroSegmentScript()
|
||||||
|
{
|
||||||
|
auto data = calldata_create();
|
||||||
|
calldata_set_int(data, GetInstanceIdParamName().data(), _instanceId);
|
||||||
|
signal_handler_signal(obs_get_signal_handler(),
|
||||||
|
_deletedInstanceSignal.c_str(), data);
|
||||||
|
calldata_destroy(data);
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(instanceMtx);
|
||||||
|
instances.erase(std::remove(instances.begin(), instances.end(), this),
|
||||||
|
instances.end());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroSegmentScript::RegisterTempVar(const std::string &variableId,
|
||||||
|
const std::string &name,
|
||||||
|
const std::string &helpText,
|
||||||
|
int instanceId)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(instanceMtx);
|
||||||
|
for (auto instance : instances) {
|
||||||
|
if (instance->_instanceId != instanceId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
instance->RegisterTempVarHelper(variableId, name, helpText);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroSegmentScript::DeregisterAllTempVars(int instanceId)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(instanceMtx);
|
||||||
|
for (auto instance : instances) {
|
||||||
|
if (instance->_instanceId != instanceId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
instance->DeregisterAllTempVarsHelper();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroSegmentScript::SetTempVarValue(const std::string &variableId,
|
||||||
|
const std::string &value,
|
||||||
|
int instanceId)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(instanceMtx);
|
||||||
|
for (auto instance : instances) {
|
||||||
|
if (instance->_instanceId != instanceId) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
instance->SetTempVarValueHelper(variableId, value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroSegmentScript::Save(obs_data_t *obj) const
|
bool MacroSegmentScript::Save(obs_data_t *obj) const
|
||||||
@@ -85,8 +158,10 @@ bool MacroSegmentScript::SendTriggerSignal()
|
|||||||
auto data = calldata_create();
|
auto data = calldata_create();
|
||||||
calldata_set_string(data, GetActionCompletionSignalParamName().data(),
|
calldata_set_string(data, GetActionCompletionSignalParamName().data(),
|
||||||
_completionSignal.c_str());
|
_completionSignal.c_str());
|
||||||
calldata_set_int(data, GeCompletionIdParamName().data(), _completionId);
|
calldata_set_int(data, GetCompletionIdParamName().data(),
|
||||||
|
_completionId);
|
||||||
calldata_set_string(data, "settings", obs_data_get_json(GetSettings()));
|
calldata_set_string(data, "settings", obs_data_get_json(GetSettings()));
|
||||||
|
calldata_set_int(data, GetInstanceIdParamName().data(), _instanceId);
|
||||||
signal_handler_signal(obs_get_signal_handler(), _triggerSignal.c_str(),
|
signal_handler_signal(obs_get_signal_handler(), _triggerSignal.c_str(),
|
||||||
data);
|
data);
|
||||||
calldata_destroy(data);
|
calldata_destroy(data);
|
||||||
@@ -101,18 +176,18 @@ void MacroSegmentScript::CompletionSignalReceived(void *param, calldata_t *data)
|
|||||||
{
|
{
|
||||||
auto segment = static_cast<MacroSegmentScript *>(param);
|
auto segment = static_cast<MacroSegmentScript *>(param);
|
||||||
long long int id;
|
long long int id;
|
||||||
if (!calldata_get_int(data, GeCompletionIdParamName().data(), &id)) {
|
if (!calldata_get_int(data, GetCompletionIdParamName().data(), &id)) {
|
||||||
blog(LOG_WARNING,
|
blog(LOG_WARNING,
|
||||||
"received completion signal without \"%s\" parameter",
|
"received completion signal without \"%s\" parameter",
|
||||||
GeCompletionIdParamName().data());
|
GetCompletionIdParamName().data());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
bool result;
|
bool result;
|
||||||
if (!calldata_get_bool(data, GeResultSignalParamName().data(),
|
if (!calldata_get_bool(data, GetResultSignalParamName().data(),
|
||||||
&result)) {
|
&result)) {
|
||||||
blog(LOG_WARNING,
|
blog(LOG_WARNING,
|
||||||
"received completion signal without \"%s\" parameter",
|
"received completion signal without \"%s\" parameter",
|
||||||
GeResultSignalParamName().data());
|
GetResultSignalParamName().data());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (id != segment->_completionId) {
|
if (id != segment->_completionId) {
|
||||||
@@ -122,6 +197,19 @@ void MacroSegmentScript::CompletionSignalReceived(void *param, calldata_t *data)
|
|||||||
segment->_triggerResult = result;
|
segment->_triggerResult = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroSegmentScript::SignalNewInstance() const
|
||||||
|
{
|
||||||
|
std::thread signalNewInstanceThread([this]() {
|
||||||
|
auto data = calldata_create();
|
||||||
|
calldata_set_int(data, GetInstanceIdParamName().data(),
|
||||||
|
_instanceId);
|
||||||
|
signal_handler_signal(obs_get_signal_handler(),
|
||||||
|
_newInstanceSignal.c_str(), data);
|
||||||
|
calldata_destroy(data);
|
||||||
|
});
|
||||||
|
signalNewInstanceThread.detach();
|
||||||
|
}
|
||||||
|
|
||||||
obs_properties_t *MacroSegmentScriptEdit::GetProperties(void *obj)
|
obs_properties_t *MacroSegmentScriptEdit::GetProperties(void *obj)
|
||||||
{
|
{
|
||||||
auto segmentEdit = reinterpret_cast<MacroSegmentScriptEdit *>(obj);
|
auto segmentEdit = reinterpret_cast<MacroSegmentScriptEdit *>(obj);
|
||||||
|
|||||||
@@ -15,9 +15,20 @@ class MacroSegmentScript {
|
|||||||
public:
|
public:
|
||||||
MacroSegmentScript(obs_data_t *defaultSettings,
|
MacroSegmentScript(obs_data_t *defaultSettings,
|
||||||
const std::string &propertiesSignalName,
|
const std::string &propertiesSignalName,
|
||||||
const std::string &triggerSignal,
|
const std::string &triggerSignalName,
|
||||||
const std::string &completionSignal);
|
const std::string &completionSignalName,
|
||||||
|
const std::string &newInstanceSignalName,
|
||||||
|
const std::string &deletedInstanceSignalName);
|
||||||
MacroSegmentScript(const advss::MacroSegmentScript &);
|
MacroSegmentScript(const advss::MacroSegmentScript &);
|
||||||
|
virtual ~MacroSegmentScript();
|
||||||
|
|
||||||
|
static void RegisterTempVar(const std::string &variableId,
|
||||||
|
const std::string &name,
|
||||||
|
const std::string &helpText,
|
||||||
|
int instanceId);
|
||||||
|
static void DeregisterAllTempVars(int instanceId);
|
||||||
|
static void SetTempVarValue(const std::string &variableId,
|
||||||
|
const std::string &value, int instanceId);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool Save(obs_data_t *obj) const;
|
bool Save(obs_data_t *obj) const;
|
||||||
@@ -31,15 +42,27 @@ protected:
|
|||||||
double GetTimeoutSeconds() const { return _timeout.Seconds(); };
|
double GetTimeoutSeconds() const { return _timeout.Seconds(); };
|
||||||
bool TriggerIsCompleted() const { return _triggerIsComplete; }
|
bool TriggerIsCompleted() const { return _triggerIsComplete; }
|
||||||
|
|
||||||
|
virtual void RegisterTempVarHelper(const std::string &variableId,
|
||||||
|
const std::string &name,
|
||||||
|
const std::string &helpText) = 0;
|
||||||
|
virtual void DeregisterAllTempVarsHelper() = 0;
|
||||||
|
virtual void SetTempVarValueHelper(const std::string &variableId,
|
||||||
|
const std::string &value) = 0;
|
||||||
|
|
||||||
|
const int64_t _instanceId;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void WaitForCompletion() const = 0;
|
virtual void WaitForCompletion() const = 0;
|
||||||
static void CompletionSignalReceived(void *param, calldata_t *data);
|
static void CompletionSignalReceived(void *param, calldata_t *data);
|
||||||
|
void SignalNewInstance() const;
|
||||||
|
|
||||||
OBSDataAutoRelease _settings;
|
OBSDataAutoRelease _settings;
|
||||||
std::string _propertiesSignal = "";
|
std::string _propertiesSignal = "";
|
||||||
|
|
||||||
std::string _triggerSignal = "";
|
std::string _triggerSignal = "";
|
||||||
std::string _completionSignal = "";
|
std::string _completionSignal = "";
|
||||||
|
std::string _newInstanceSignal = "";
|
||||||
|
std::string _deletedInstanceSignal = "";
|
||||||
std::atomic_bool _triggerIsComplete = {false};
|
std::atomic_bool _triggerIsComplete = {false};
|
||||||
bool _triggerResult = false;
|
bool _triggerResult = false;
|
||||||
int64_t _completionId = 0;
|
int64_t _completionId = 0;
|
||||||
|
|||||||
@@ -294,13 +294,8 @@ bool MacroSegmentEdit::eventFilter(QObject *obj, QEvent *ev)
|
|||||||
QMouseEvent *newEvent = new QMouseEvent(
|
QMouseEvent *newEvent = new QMouseEvent(
|
||||||
mouseEvent->type(),
|
mouseEvent->type(),
|
||||||
_headerInfo->mapTo(this, mouseEvent->pos()),
|
_headerInfo->mapTo(this, mouseEvent->pos()),
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
mouseEvent->globalPosition(), mouseEvent->button(),
|
||||||
mouseEvent->globalPos(),
|
mouseEvent->buttons(), mouseEvent->modifiers());
|
||||||
#else
|
|
||||||
mouseEvent->globalPosition(),
|
|
||||||
#endif
|
|
||||||
mouseEvent->button(), mouseEvent->buttons(),
|
|
||||||
mouseEvent->modifiers());
|
|
||||||
QApplication::sendEvent(parentWidget(), newEvent);
|
QApplication::sendEvent(parentWidget(), newEvent);
|
||||||
}
|
}
|
||||||
return QWidget::eventFilter(obj, ev);
|
return QWidget::eventFilter(obj, ev);
|
||||||
|
|||||||
@@ -178,6 +178,7 @@ void MacroTreeItem::Update(bool force)
|
|||||||
QSizePolicy::Maximum);
|
QSizePolicy::Maximum);
|
||||||
_expand->setMaximumSize(10, 16);
|
_expand->setMaximumSize(10, 16);
|
||||||
_expand->setMinimumSize(10, 0);
|
_expand->setMinimumSize(10, 0);
|
||||||
|
_expand->setProperty("class", "checkbox-icon indicator-expand");
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
_expand->setAttribute(Qt::WA_LayoutUsesWidgetRect);
|
_expand->setAttribute(Qt::WA_LayoutUsesWidgetRect);
|
||||||
#endif
|
#endif
|
||||||
@@ -888,14 +889,7 @@ void MacroTree::dropEvent(QDropEvent *event)
|
|||||||
QModelIndexList indices = selectedIndexes();
|
QModelIndexList indices = selectedIndexes();
|
||||||
|
|
||||||
DropIndicatorPosition indicator = dropIndicatorPosition();
|
DropIndicatorPosition indicator = dropIndicatorPosition();
|
||||||
int row = indexAt(
|
int row = indexAt(event->position().toPoint()).row();
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
event->position().toPoint()
|
|
||||||
#else
|
|
||||||
event->pos()
|
|
||||||
#endif
|
|
||||||
)
|
|
||||||
.row();
|
|
||||||
bool emptyDrop = row == -1;
|
bool emptyDrop = row == -1;
|
||||||
|
|
||||||
if (emptyDrop) {
|
if (emptyDrop) {
|
||||||
|
|||||||
@@ -244,8 +244,13 @@ bool Macro::CheckConditions(bool ignorePause)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_stop = false;
|
||||||
_matched = false;
|
_matched = false;
|
||||||
for (auto &condition : _conditions) {
|
for (auto &condition : _conditions) {
|
||||||
|
if (!condition) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (_paused && !ignorePause) {
|
if (_paused && !ignorePause) {
|
||||||
vblog(LOG_INFO, "Macro %s is paused", _name.c_str());
|
vblog(LOG_INFO, "Macro %s is paused", _name.c_str());
|
||||||
return false;
|
return false;
|
||||||
@@ -383,6 +388,9 @@ bool Macro::RunActionsHelper(
|
|||||||
|
|
||||||
bool actionsExecutedSuccessfully = true;
|
bool actionsExecutedSuccessfully = true;
|
||||||
for (auto &action : actions) {
|
for (auto &action : actions) {
|
||||||
|
if (!action) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
if (action->Enabled()) {
|
if (action->Enabled()) {
|
||||||
action->LogAction();
|
action->LogAction();
|
||||||
actionsExecutedSuccessfully =
|
actionsExecutedSuccessfully =
|
||||||
|
|||||||
@@ -40,8 +40,8 @@ ActionQueueTable *ActionQueueTable::Create()
|
|||||||
void ActionQueueTable::Add()
|
void ActionQueueTable::Add()
|
||||||
{
|
{
|
||||||
auto newQueue = std::make_shared<ActionQueue>();
|
auto newQueue = std::make_shared<ActionQueue>();
|
||||||
auto accepted =
|
auto accepted = ActionQueueSettingsDialog::AskForSettings(
|
||||||
ActionQueueSettingsDialog::AskForSettings(this, *newQueue);
|
GetSettingsWindow(), *newQueue);
|
||||||
if (!accepted) {
|
if (!accepted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ static void openSettingsDialog()
|
|||||||
|
|
||||||
auto oldName = queue->Name();
|
auto oldName = queue->Name();
|
||||||
bool accepted = ActionQueueSettingsDialog::AskForSettings(
|
bool accepted = ActionQueueSettingsDialog::AskForSettings(
|
||||||
tabWidget->Table(), *queue.get());
|
GetSettingsWindow(), *queue.get());
|
||||||
if (accepted && oldName != queue->Name()) {
|
if (accepted && oldName != queue->Name()) {
|
||||||
ActionQueueSignalManager::Instance()->Rename(
|
ActionQueueSignalManager::Instance()->Rename(
|
||||||
QString::fromStdString(oldName),
|
QString::fromStdString(oldName),
|
||||||
|
|||||||
@@ -113,6 +113,7 @@ void ActionQueue::Add(const std::shared_ptr<MacroAction> &action)
|
|||||||
action->Save(data);
|
action->Save(data);
|
||||||
copy->Load(data);
|
copy->Load(data);
|
||||||
copy->PostLoad();
|
copy->PostLoad();
|
||||||
|
RunPostLoadSteps();
|
||||||
copy->ResolveVariablesToFixedValues();
|
copy->ResolveVariablesToFixedValues();
|
||||||
_actions.emplace_back(copy);
|
_actions.emplace_back(copy);
|
||||||
} else {
|
} else {
|
||||||
@@ -179,7 +180,7 @@ ActionQueueSettingsDialog::ActionQueueSettingsDialog(QWidget *parent,
|
|||||||
"AdvSceneSwitcher.actionQueues.select",
|
"AdvSceneSwitcher.actionQueues.select",
|
||||||
"AdvSceneSwitcher.actionQueues.add",
|
"AdvSceneSwitcher.actionQueues.add",
|
||||||
"AdvSceneSwitcher.actionQueues.nameNotAvailable",
|
"AdvSceneSwitcher.actionQueues.nameNotAvailable",
|
||||||
parent),
|
true, parent),
|
||||||
_queueRunStatus(new QLabel()),
|
_queueRunStatus(new QLabel()),
|
||||||
_startStopToggle(new QPushButton()),
|
_startStopToggle(new QPushButton()),
|
||||||
_queueSize(new QLabel()),
|
_queueSize(new QLabel()),
|
||||||
|
|||||||
@@ -14,11 +14,7 @@ AutoUpdateTooltipLabel::AutoUpdateTooltipLabel(
|
|||||||
&AutoUpdateTooltipLabel::UpdateTooltip);
|
&AutoUpdateTooltipLabel::UpdateTooltip);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
void AutoUpdateTooltipLabel::enterEvent(QEnterEvent *event)
|
void AutoUpdateTooltipLabel::enterEvent(QEnterEvent *event)
|
||||||
#else
|
|
||||||
void AutoUpdateTooltipLabel::enterEvent(QEvent *event)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
_timer->start(_updateIntervalMs);
|
_timer->start(_updateIntervalMs);
|
||||||
QLabel::enterEvent(event);
|
QLabel::enterEvent(event);
|
||||||
|
|||||||
@@ -17,11 +17,7 @@ public:
|
|||||||
int updateIntervalMs = 300);
|
int updateIntervalMs = 300);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
void enterEvent(QEnterEvent *event) override;
|
void enterEvent(QEnterEvent *event) override;
|
||||||
#else
|
|
||||||
void enterEvent(QEvent *event) override;
|
|
||||||
#endif
|
|
||||||
void leaveEvent(QEvent *event) override;
|
void leaveEvent(QEvent *event) override;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ void Duration::Load(obs_data_t *obj, const char *name)
|
|||||||
// TODO: remove this fallback
|
// TODO: remove this fallback
|
||||||
if (!data || !obs_data_has_user_value(data, "version") ||
|
if (!data || !obs_data_has_user_value(data, "version") ||
|
||||||
obs_data_get_int(data, "version") != 1) {
|
obs_data_get_int(data, "version") != 1) {
|
||||||
|
_value = 0.;
|
||||||
bool usingDefaultArgs = strcmp("duration", name) == 0;
|
bool usingDefaultArgs = strcmp("duration", name) == 0;
|
||||||
if (usingDefaultArgs) {
|
if (usingDefaultArgs) {
|
||||||
_value = obs_data_get_double(obj, "seconds");
|
_value = obs_data_get_double(obj, "seconds");
|
||||||
|
|||||||
@@ -59,7 +59,10 @@ ItemSelection::ItemSelection(std::deque<std::shared_ptr<Item>> &items,
|
|||||||
_conflictStr(conflict)
|
_conflictStr(conflict)
|
||||||
{
|
{
|
||||||
_modify->setMaximumWidth(22);
|
_modify->setMaximumWidth(22);
|
||||||
SetButtonIcon(_modify, ":/settings/images/settings/general.svg");
|
SetButtonIcon(_modify,
|
||||||
|
GetThemeTypeName() == "Light"
|
||||||
|
? ":/settings/images/settings/general.svg"
|
||||||
|
: "theme:Dark/settings/general.svg");
|
||||||
_modify->setFlat(true);
|
_modify->setFlat(true);
|
||||||
if (!configureTooltip.empty()) {
|
if (!configureTooltip.empty()) {
|
||||||
_modify->setToolTip(obs_module_text(configureTooltip.data()));
|
_modify->setToolTip(obs_module_text(configureTooltip.data()));
|
||||||
@@ -265,6 +268,7 @@ ItemSettingsDialog::ItemSettingsDialog(const Item &settings,
|
|||||||
std::string_view select,
|
std::string_view select,
|
||||||
std::string_view add,
|
std::string_view add,
|
||||||
std::string_view nameConflict,
|
std::string_view nameConflict,
|
||||||
|
bool showNameEmptyWarning,
|
||||||
QWidget *parent)
|
QWidget *parent)
|
||||||
: QDialog(parent),
|
: QDialog(parent),
|
||||||
_name(new QLineEdit()),
|
_name(new QLineEdit()),
|
||||||
@@ -274,7 +278,8 @@ ItemSettingsDialog::ItemSettingsDialog(const Item &settings,
|
|||||||
_items(items),
|
_items(items),
|
||||||
_selectStr(select),
|
_selectStr(select),
|
||||||
_addStr(add),
|
_addStr(add),
|
||||||
_conflictStr(nameConflict)
|
_conflictStr(nameConflict),
|
||||||
|
_showNameEmptyWarning(showNameEmptyWarning)
|
||||||
{
|
{
|
||||||
setModal(true);
|
setModal(true);
|
||||||
setWindowModality(Qt::WindowModality::WindowModal);
|
setWindowModality(Qt::WindowModality::WindowModal);
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ public:
|
|||||||
std::string_view addString = "AdvSceneSwitcher.item.add",
|
std::string_view addString = "AdvSceneSwitcher.item.add",
|
||||||
std::string_view conflictString =
|
std::string_view conflictString =
|
||||||
"AdvSceneSwitcher.item.nameNotAvailable",
|
"AdvSceneSwitcher.item.nameNotAvailable",
|
||||||
QWidget *parent = 0);
|
bool showEmptyNameWarning = true, QWidget *parent = 0);
|
||||||
virtual ~ItemSettingsDialog() = default;
|
virtual ~ItemSettingsDialog() = default;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
|
|||||||
@@ -92,7 +92,10 @@ RegexConfigWidget::RegexConfigWidget(QWidget *parent, bool showEnable)
|
|||||||
_openSettings(new QToolButton()),
|
_openSettings(new QToolButton()),
|
||||||
_enable(new QPushButton())
|
_enable(new QPushButton())
|
||||||
{
|
{
|
||||||
SetButtonIcon(_openSettings, ":/settings/images/settings/general.svg");
|
SetButtonIcon(_openSettings,
|
||||||
|
GetThemeTypeName() == "Light"
|
||||||
|
? ":/settings/images/settings/general.svg"
|
||||||
|
: "theme:Dark/settings/general.svg");
|
||||||
_openSettings->setToolTip(
|
_openSettings->setToolTip(
|
||||||
obs_module_text("AdvSceneSwitcher.regex.configure"));
|
obs_module_text("AdvSceneSwitcher.regex.configure"));
|
||||||
|
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ void ResizingPlainTextEdit::AddHeightForScrollBar(bool addHeight)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_hScrollBarAddedHeight = verticalScrollBar()->height();
|
_hScrollBarAddedHeight = horizontalScrollBar()->height();
|
||||||
setFixedHeight(height() + _hScrollBarAddedHeight);
|
setFixedHeight(height() + _hScrollBarAddedHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ private:
|
|||||||
T _value = {};
|
T _value = {};
|
||||||
std::weak_ptr<Variable> _variable;
|
std::weak_ptr<Variable> _variable;
|
||||||
|
|
||||||
friend class GenericVaraiableSpinbox;
|
friend class GenericVariableSpinbox;
|
||||||
friend class VariableSpinBox;
|
friend class VariableSpinBox;
|
||||||
friend class VariableDoubleSpinBox;
|
friend class VariableDoubleSpinBox;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
GenericVaraiableSpinbox::GenericVaraiableSpinbox(QWidget *parent,
|
GenericVariableSpinbox::GenericVariableSpinbox(QWidget *parent,
|
||||||
bool wholeNumber)
|
bool wholeNumber)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
_fixedValueInt(new QSpinBox()),
|
_fixedValueInt(new QSpinBox()),
|
||||||
_fixedValueDouble(new QDoubleSpinBox()),
|
_fixedValueDouble(new QDoubleSpinBox()),
|
||||||
@@ -16,7 +16,9 @@ GenericVaraiableSpinbox::GenericVaraiableSpinbox(QWidget *parent,
|
|||||||
{
|
{
|
||||||
_toggleType->setCheckable(true);
|
_toggleType->setCheckable(true);
|
||||||
_toggleType->setMaximumWidth(11);
|
_toggleType->setMaximumWidth(11);
|
||||||
SetButtonIcon(_toggleType, ":/res/images/dots-vert.svg");
|
SetButtonIcon(_toggleType, GetThemeTypeName() == "Light"
|
||||||
|
? ":/res/images/dots-vert.svg"
|
||||||
|
: "theme:Dark/dots-vert.svg");
|
||||||
|
|
||||||
QWidget::connect(_fixedValueInt, SIGNAL(valueChanged(int)), this,
|
QWidget::connect(_fixedValueInt, SIGNAL(valueChanged(int)), this,
|
||||||
SLOT(SetFixedValue(int)));
|
SLOT(SetFixedValue(int)));
|
||||||
@@ -48,7 +50,7 @@ GenericVaraiableSpinbox::GenericVaraiableSpinbox(QWidget *parent,
|
|||||||
SetVisibility();
|
SetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::SetValue(const NumberVariable<int> &number)
|
void GenericVariableSpinbox::SetValue(const NumberVariable<int> &number)
|
||||||
{
|
{
|
||||||
_numberInt = number;
|
_numberInt = number;
|
||||||
const QSignalBlocker b1(_toggleType);
|
const QSignalBlocker b1(_toggleType);
|
||||||
@@ -59,7 +61,7 @@ void GenericVaraiableSpinbox::SetValue(const NumberVariable<int> &number)
|
|||||||
SetVisibility();
|
SetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::SetValue(const NumberVariable<double> &number)
|
void GenericVariableSpinbox::SetValue(const NumberVariable<double> &number)
|
||||||
{
|
{
|
||||||
_numberDouble = number;
|
_numberDouble = number;
|
||||||
const QSignalBlocker b1(_toggleType);
|
const QSignalBlocker b1(_toggleType);
|
||||||
@@ -70,44 +72,44 @@ void GenericVaraiableSpinbox::SetValue(const NumberVariable<double> &number)
|
|||||||
SetVisibility();
|
SetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::DisableVariableSelection()
|
void GenericVariableSpinbox::DisableVariableSelection()
|
||||||
{
|
{
|
||||||
_hideTypeToggle = true;
|
_hideTypeToggle = true;
|
||||||
_toggleType->hide();
|
_toggleType->hide();
|
||||||
ToggleTypeClicked(false);
|
ToggleTypeClicked(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::setMinimum(double value)
|
void GenericVariableSpinbox::setMinimum(double value)
|
||||||
{
|
{
|
||||||
_fixedValueInt->setMinimum(value);
|
_fixedValueInt->setMinimum(value);
|
||||||
_fixedValueDouble->setMinimum(value);
|
_fixedValueDouble->setMinimum(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::setMaximum(double value)
|
void GenericVariableSpinbox::setMaximum(double value)
|
||||||
{
|
{
|
||||||
_fixedValueInt->setMaximum(value);
|
_fixedValueInt->setMaximum(value);
|
||||||
_fixedValueDouble->setMaximum(value);
|
_fixedValueDouble->setMaximum(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::setPrefix(const QString &prefix)
|
void GenericVariableSpinbox::setPrefix(const QString &prefix)
|
||||||
{
|
{
|
||||||
_fixedValueInt->setPrefix(prefix);
|
_fixedValueInt->setPrefix(prefix);
|
||||||
_fixedValueDouble->setPrefix(prefix);
|
_fixedValueDouble->setPrefix(prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::setSuffix(const QString &suffix)
|
void GenericVariableSpinbox::setSuffix(const QString &suffix)
|
||||||
{
|
{
|
||||||
_fixedValueInt->setSuffix(suffix);
|
_fixedValueInt->setSuffix(suffix);
|
||||||
_fixedValueDouble->setSuffix(suffix);
|
_fixedValueDouble->setSuffix(suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::setSpecialValueText(const QString &text)
|
void GenericVariableSpinbox::setSpecialValueText(const QString &text)
|
||||||
{
|
{
|
||||||
_fixedValueInt->setSpecialValueText(text);
|
_fixedValueInt->setSpecialValueText(text);
|
||||||
_fixedValueDouble->setSpecialValueText(text);
|
_fixedValueDouble->setSpecialValueText(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::SetFixedValue(int value)
|
void GenericVariableSpinbox::SetFixedValue(int value)
|
||||||
{
|
{
|
||||||
_numberInt._value = value;
|
_numberInt._value = value;
|
||||||
const QSignalBlocker b(_fixedValueInt);
|
const QSignalBlocker b(_fixedValueInt);
|
||||||
@@ -115,7 +117,7 @@ void GenericVaraiableSpinbox::SetFixedValue(int value)
|
|||||||
EmitSignals();
|
EmitSignals();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::SetFixedValue(double value)
|
void GenericVariableSpinbox::SetFixedValue(double value)
|
||||||
{
|
{
|
||||||
_numberDouble._value = value;
|
_numberDouble._value = value;
|
||||||
const QSignalBlocker b(_fixedValueDouble);
|
const QSignalBlocker b(_fixedValueDouble);
|
||||||
@@ -123,14 +125,14 @@ void GenericVaraiableSpinbox::SetFixedValue(double value)
|
|||||||
EmitSignals();
|
EmitSignals();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::VariableChanged(const QString &name)
|
void GenericVariableSpinbox::VariableChanged(const QString &name)
|
||||||
{
|
{
|
||||||
_numberInt._variable = GetWeakVariableByQString(name);
|
_numberInt._variable = GetWeakVariableByQString(name);
|
||||||
_numberDouble._variable = GetWeakVariableByQString(name);
|
_numberDouble._variable = GetWeakVariableByQString(name);
|
||||||
EmitSignals();
|
EmitSignals();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::ToggleTypeClicked(bool useVariable)
|
void GenericVariableSpinbox::ToggleTypeClicked(bool useVariable)
|
||||||
{
|
{
|
||||||
_numberInt._type = useVariable ? NumberVariable<int>::Type::VARIABLE
|
_numberInt._type = useVariable ? NumberVariable<int>::Type::VARIABLE
|
||||||
: NumberVariable<int>::Type::FIXED_VALUE;
|
: NumberVariable<int>::Type::FIXED_VALUE;
|
||||||
@@ -142,7 +144,7 @@ void GenericVaraiableSpinbox::ToggleTypeClicked(bool useVariable)
|
|||||||
EmitSignals();
|
EmitSignals();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::EmitSignals()
|
void GenericVariableSpinbox::EmitSignals()
|
||||||
{
|
{
|
||||||
if (_wholeNumber) {
|
if (_wholeNumber) {
|
||||||
emit FixedValueChanged(_numberInt);
|
emit FixedValueChanged(_numberInt);
|
||||||
@@ -153,7 +155,7 @@ void GenericVaraiableSpinbox::EmitSignals()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::SetVisibility()
|
void GenericVariableSpinbox::SetVisibility()
|
||||||
{
|
{
|
||||||
if (_wholeNumber) {
|
if (_wholeNumber) {
|
||||||
_fixedValueDouble->hide();
|
_fixedValueDouble->hide();
|
||||||
@@ -164,7 +166,7 @@ void GenericVaraiableSpinbox::SetVisibility()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::SetVisibilityInt()
|
void GenericVariableSpinbox::SetVisibilityInt()
|
||||||
{
|
{
|
||||||
if (_numberInt.IsFixedType()) {
|
if (_numberInt.IsFixedType()) {
|
||||||
_fixedValueInt->show();
|
_fixedValueInt->show();
|
||||||
@@ -180,7 +182,7 @@ void GenericVaraiableSpinbox::SetVisibilityInt()
|
|||||||
updateGeometry();
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenericVaraiableSpinbox::SetVisibilityDouble()
|
void GenericVariableSpinbox::SetVisibilityDouble()
|
||||||
{
|
{
|
||||||
if (_numberDouble.IsFixedType()) {
|
if (_numberDouble.IsFixedType()) {
|
||||||
_fixedValueDouble->show();
|
_fixedValueDouble->show();
|
||||||
@@ -197,12 +199,12 @@ void GenericVaraiableSpinbox::SetVisibilityDouble()
|
|||||||
}
|
}
|
||||||
|
|
||||||
VariableSpinBox::VariableSpinBox(QWidget *parent)
|
VariableSpinBox::VariableSpinBox(QWidget *parent)
|
||||||
: GenericVaraiableSpinbox(parent, true)
|
: GenericVariableSpinbox(parent, true)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
VariableDoubleSpinBox::VariableDoubleSpinBox(QWidget *parent)
|
VariableDoubleSpinBox::VariableDoubleSpinBox(QWidget *parent)
|
||||||
: GenericVaraiableSpinbox(parent, false)
|
: GenericVariableSpinbox(parent, false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,10 +9,10 @@
|
|||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
class ADVSS_EXPORT GenericVaraiableSpinbox : public QWidget {
|
class ADVSS_EXPORT GenericVariableSpinbox : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
GenericVaraiableSpinbox(QWidget *parent, bool wholeNumber);
|
GenericVariableSpinbox(QWidget *parent, bool wholeNumber);
|
||||||
void SetValue(const NumberVariable<int> &);
|
void SetValue(const NumberVariable<int> &);
|
||||||
void SetValue(const NumberVariable<double> &);
|
void SetValue(const NumberVariable<double> &);
|
||||||
void DisableVariableSelection();
|
void DisableVariableSelection();
|
||||||
@@ -59,7 +59,7 @@ private:
|
|||||||
bool _hideTypeToggle = false;
|
bool _hideTypeToggle = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
class ADVSS_EXPORT VariableSpinBox : public GenericVaraiableSpinbox {
|
class ADVSS_EXPORT VariableSpinBox : public GenericVariableSpinbox {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@@ -68,7 +68,7 @@ public:
|
|||||||
QSpinBox *SpinBox() { return _fixedValueInt; }
|
QSpinBox *SpinBox() { return _fixedValueInt; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class ADVSS_EXPORT VariableDoubleSpinBox : public GenericVaraiableSpinbox {
|
class ADVSS_EXPORT VariableDoubleSpinBox : public GenericVariableSpinbox {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|||||||
@@ -43,8 +43,8 @@ VariableTable *VariableTable::Create()
|
|||||||
void VariableTable::Add()
|
void VariableTable::Add()
|
||||||
{
|
{
|
||||||
auto newVariable = std::make_shared<Variable>();
|
auto newVariable = std::make_shared<Variable>();
|
||||||
auto accepted =
|
auto accepted = VariableSettingsDialog::AskForSettings(
|
||||||
VariableSettingsDialog::AskForSettings(this, *newVariable);
|
GetSettingsWindow(), *newVariable);
|
||||||
if (!accepted) {
|
if (!accepted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -184,7 +184,7 @@ static void openSettingsDialog()
|
|||||||
|
|
||||||
auto oldName = variable->Name();
|
auto oldName = variable->Name();
|
||||||
bool accepted = VariableSettingsDialog::AskForSettings(
|
bool accepted = VariableSettingsDialog::AskForSettings(
|
||||||
tabWidget->Table(), *variable.get());
|
GetSettingsWindow(), *variable.get());
|
||||||
if (accepted && oldName != variable->Name()) {
|
if (accepted && oldName != variable->Name()) {
|
||||||
VariableSignalManager::Instance()->Rename(
|
VariableSignalManager::Instance()->Rename(
|
||||||
QString::fromStdString(oldName),
|
QString::fromStdString(oldName),
|
||||||
|
|||||||
@@ -137,7 +137,8 @@ VariableSettingsDialog::VariableSettingsDialog(QWidget *parent,
|
|||||||
: ItemSettingsDialog(settings, variables,
|
: ItemSettingsDialog(settings, variables,
|
||||||
"AdvSceneSwitcher.variable.select",
|
"AdvSceneSwitcher.variable.select",
|
||||||
"AdvSceneSwitcher.variable.add",
|
"AdvSceneSwitcher.variable.add",
|
||||||
"AdvSceneSwitcher.item.nameNotAvailable", parent),
|
"AdvSceneSwitcher.item.nameNotAvailable", true,
|
||||||
|
parent),
|
||||||
_value(new ResizingPlainTextEdit(this)),
|
_value(new ResizingPlainTextEdit(this)),
|
||||||
_defaultValue(new ResizingPlainTextEdit(this)),
|
_defaultValue(new ResizingPlainTextEdit(this)),
|
||||||
_save(new QComboBox())
|
_save(new QComboBox())
|
||||||
|
|||||||
@@ -89,6 +89,8 @@ target_sources(
|
|||||||
macro-condition-filter.hpp
|
macro-condition-filter.hpp
|
||||||
macro-condition-folder.cpp
|
macro-condition-folder.cpp
|
||||||
macro-condition-folder.hpp
|
macro-condition-folder.hpp
|
||||||
|
macro-condition-game-capture.cpp
|
||||||
|
macro-condition-game-capture.hpp
|
||||||
macro-condition-hotkey.cpp
|
macro-condition-hotkey.cpp
|
||||||
macro-condition-hotkey.hpp
|
macro-condition-hotkey.hpp
|
||||||
macro-condition-idle.cpp
|
macro-condition-idle.cpp
|
||||||
@@ -117,6 +119,8 @@ target_sources(
|
|||||||
macro-condition-scene-visibility.hpp
|
macro-condition-scene-visibility.hpp
|
||||||
macro-condition-scene.cpp
|
macro-condition-scene.cpp
|
||||||
macro-condition-scene.hpp
|
macro-condition-scene.hpp
|
||||||
|
macro-condition-screenshot.cpp
|
||||||
|
macro-condition-screenshot.hpp
|
||||||
macro-condition-slideshow.cpp
|
macro-condition-slideshow.cpp
|
||||||
macro-condition-slideshow.hpp
|
macro-condition-slideshow.hpp
|
||||||
macro-condition-source.cpp
|
macro-condition-source.cpp
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
|||||||
_settingsString(new VariableTextEdit(this)),
|
_settingsString(new VariableTextEdit(this)),
|
||||||
_refreshSettingSelection(new QPushButton(
|
_refreshSettingSelection(new QPushButton(
|
||||||
obs_module_text("AdvSceneSwitcher.action.filter.refresh"))),
|
obs_module_text("AdvSceneSwitcher.action.filter.refresh"))),
|
||||||
_settingsButtons(new QComboBox())
|
_settingsButtons(new SourceSettingsButtonSelection(this))
|
||||||
{
|
{
|
||||||
_filters->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
_filters->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||||
|
|
||||||
@@ -253,8 +253,10 @@ MacroActionFilterEdit::MacroActionFilterEdit(
|
|||||||
SLOT(SelectionChanged(const SourceSetting &)));
|
SLOT(SelectionChanged(const SourceSetting &)));
|
||||||
QWidget::connect(_refreshSettingSelection, SIGNAL(clicked()), this,
|
QWidget::connect(_refreshSettingSelection, SIGNAL(clicked()), this,
|
||||||
SLOT(RefreshVariableSourceSelectionValue()));
|
SLOT(RefreshVariableSourceSelectionValue()));
|
||||||
QWidget::connect(_settingsButtons, SIGNAL(currentIndexChanged(int)),
|
QWidget::connect(_settingsButtons,
|
||||||
this, SLOT(ButtonChanged(int)));
|
SIGNAL(SelectionChanged(const SourceSettingButton &)),
|
||||||
|
this,
|
||||||
|
SLOT(ButtonChanged(const SourceSettingButton &)));
|
||||||
|
|
||||||
const std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
const std::unordered_map<std::string, QWidget *> widgetPlaceholders = {
|
||||||
{"{{sources}}", _sources},
|
{"{{sources}}", _sources},
|
||||||
@@ -305,25 +307,18 @@ void MacroActionFilterEdit::UpdateEntryData()
|
|||||||
const auto filters =
|
const auto filters =
|
||||||
_entryData->_filter.GetFilters(_entryData->_source);
|
_entryData->_filter.GetFilters(_entryData->_source);
|
||||||
OBSWeakSource firstFilter = filters.empty() ? nullptr : filters.at(0);
|
OBSWeakSource firstFilter = filters.empty() ? nullptr : filters.at(0);
|
||||||
_filterSettings->SetSource(firstFilter);
|
_filterSettings->SetSelection(firstFilter, _entryData->_setting);
|
||||||
_filterSettings->SetSetting(_entryData->_setting);
|
|
||||||
_settingsInputMethods->setCurrentIndex(_settingsInputMethods->findData(
|
_settingsInputMethods->setCurrentIndex(_settingsInputMethods->findData(
|
||||||
static_cast<int>(_entryData->_settingsInputMethod)));
|
static_cast<int>(_entryData->_settingsInputMethod)));
|
||||||
_tempVars->SetVariable(_entryData->_tempVar);
|
_tempVars->SetVariable(_entryData->_tempVar);
|
||||||
_manualSettingValue->setPlainText(_entryData->_manualSettingValue);
|
_manualSettingValue->setPlainText(_entryData->_manualSettingValue);
|
||||||
PopulateSourceButtonSelection(_settingsButtons, firstFilter);
|
_settingsButtons->SetSelection(firstFilter, _entryData->_button);
|
||||||
_settingsButtons->setCurrentText(
|
|
||||||
QString::fromStdString(_entryData->_button.ToString()));
|
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionFilterEdit::SourceChanged(const SourceSelection &source)
|
void MacroActionFilterEdit::SourceChanged(const SourceSelection &source)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_source = source;
|
_entryData->_source = source;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,11 +332,13 @@ void MacroActionFilterEdit::FilterChanged(const FilterSelection &filter)
|
|||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
_entryData->_filter = filter;
|
_entryData->_filter = filter;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto filters =
|
const auto filters =
|
||||||
_entryData->_filter.GetFilters(_entryData->_source);
|
_entryData->_filter.GetFilters(_entryData->_source);
|
||||||
OBSWeakSource firstFilter = filters.empty() ? nullptr : filters.at(0);
|
OBSWeakSource firstFilter = filters.empty() ? nullptr : filters.at(0);
|
||||||
_filterSettings->SetSource(firstFilter);
|
_filterSettings->SetSource(firstFilter);
|
||||||
PopulateSourceButtonSelection(_settingsButtons, firstFilter);
|
_settingsButtons->SetSource(firstFilter);
|
||||||
|
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
@@ -349,11 +346,7 @@ void MacroActionFilterEdit::FilterChanged(const FilterSelection &filter)
|
|||||||
|
|
||||||
void MacroActionFilterEdit::ActionChanged(int value)
|
void MacroActionFilterEdit::ActionChanged(int value)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_action = static_cast<MacroActionFilter::Action>(value);
|
_entryData->_action = static_cast<MacroActionFilter::Action>(value);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
@@ -391,11 +384,7 @@ void MacroActionFilterEdit::GetSettingsClicked()
|
|||||||
|
|
||||||
void MacroActionFilterEdit::SettingsStringChanged()
|
void MacroActionFilterEdit::SettingsStringChanged()
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_settingsString =
|
_entryData->_settingsString =
|
||||||
_settingsString->toPlainText().toStdString();
|
_settingsString->toPlainText().toStdString();
|
||||||
|
|
||||||
@@ -405,11 +394,7 @@ void MacroActionFilterEdit::SettingsStringChanged()
|
|||||||
|
|
||||||
void MacroActionFilterEdit::SettingsInputMethodChanged(int idx)
|
void MacroActionFilterEdit::SettingsInputMethodChanged(int idx)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_settingsInputMethod =
|
_entryData->_settingsInputMethod =
|
||||||
static_cast<MacroActionFilter::SettingsInputMethod>(
|
static_cast<MacroActionFilter::SettingsInputMethod>(
|
||||||
_settingsInputMethods->itemData(idx).toInt());
|
_settingsInputMethods->itemData(idx).toInt());
|
||||||
@@ -418,31 +403,19 @@ void MacroActionFilterEdit::SettingsInputMethodChanged(int idx)
|
|||||||
|
|
||||||
void MacroActionFilterEdit::SelectionChanged(const TempVariableRef &var)
|
void MacroActionFilterEdit::SelectionChanged(const TempVariableRef &var)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_tempVar = var;
|
_entryData->_tempVar = var;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionFilterEdit::SelectionChanged(const SourceSetting &setting)
|
void MacroActionFilterEdit::SelectionChanged(const SourceSetting &setting)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_setting = setting;
|
_entryData->_setting = setting;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionFilterEdit::ManualSettingsValueChanged()
|
void MacroActionFilterEdit::ManualSettingsValueChanged()
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_manualSettingValue =
|
_entryData->_manualSettingValue =
|
||||||
_manualSettingValue->toPlainText().toStdString();
|
_manualSettingValue->toPlainText().toStdString();
|
||||||
|
|
||||||
@@ -457,15 +430,10 @@ void MacroActionFilterEdit::RefreshVariableSourceSelectionValue()
|
|||||||
_filterSettings->SetSource(filters.empty() ? nullptr : filters.at(0));
|
_filterSettings->SetSource(filters.empty() ? nullptr : filters.at(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionFilterEdit::ButtonChanged(int idx)
|
void MacroActionFilterEdit::ButtonChanged(const SourceSettingButton &button)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
_entryData->_button = button;
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_button = qvariant_cast<SourceSettingButton>(
|
|
||||||
_settingsButtons->itemData(idx));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionFilterEdit::SetWidgetVisibility()
|
void MacroActionFilterEdit::SetWidgetVisibility()
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ private slots:
|
|||||||
void SelectionChanged(const SourceSetting &);
|
void SelectionChanged(const SourceSetting &);
|
||||||
void ManualSettingsValueChanged();
|
void ManualSettingsValueChanged();
|
||||||
void RefreshVariableSourceSelectionValue();
|
void RefreshVariableSourceSelectionValue();
|
||||||
void ButtonChanged(int idx);
|
void ButtonChanged(const SourceSettingButton &);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
@@ -100,7 +100,7 @@ private:
|
|||||||
SourceSettingSelection *_filterSettings;
|
SourceSettingSelection *_filterSettings;
|
||||||
VariableTextEdit *_settingsString;
|
VariableTextEdit *_settingsString;
|
||||||
QPushButton *_refreshSettingSelection;
|
QPushButton *_refreshSettingSelection;
|
||||||
QComboBox *_settingsButtons;
|
SourceSettingsButtonSelection *_settingsButtons;
|
||||||
|
|
||||||
std::shared_ptr<MacroActionFilter> _entryData;
|
std::shared_ptr<MacroActionFilter> _entryData;
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
|
|||||||
@@ -263,28 +263,12 @@ static inline void populateActionSelection(QComboBox *list)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void populateDeinterlaceModeSelection(QComboBox *list)
|
template<class T>
|
||||||
|
static inline void populateModeSelection(QComboBox *list,
|
||||||
|
const std::map<T, std::string> &modes)
|
||||||
{
|
{
|
||||||
list->clear();
|
list->clear();
|
||||||
for (const auto &[value, name] : deinterlaceModes) {
|
for (const auto &[value, name] : modes) {
|
||||||
list->addItem(obs_module_text(name.c_str()),
|
|
||||||
static_cast<int>(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void populateDeinterlaceFieldOrderSelection(QComboBox *list)
|
|
||||||
{
|
|
||||||
list->clear();
|
|
||||||
for (const auto &[value, name] : deinterlaceFieldOrders) {
|
|
||||||
list->addItem(obs_module_text(name.c_str()),
|
|
||||||
static_cast<int>(value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void populateSettingsInputMethods(QComboBox *list)
|
|
||||||
{
|
|
||||||
list->clear();
|
|
||||||
for (const auto &[value, name] : inputMethods) {
|
|
||||||
list->addItem(obs_module_text(name.c_str()),
|
list->addItem(obs_module_text(name.c_str()),
|
||||||
static_cast<int>(value));
|
static_cast<int>(value));
|
||||||
}
|
}
|
||||||
@@ -295,7 +279,7 @@ MacroActionSourceEdit::MacroActionSourceEdit(
|
|||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
_sources(new SourceSelectionWidget(this, QStringList(), true)),
|
||||||
_actions(new QComboBox()),
|
_actions(new QComboBox()),
|
||||||
_settingsButtons(new QComboBox()),
|
_settingsButtons(new SourceSettingsButtonSelection(this)),
|
||||||
_settingsLayout(new QHBoxLayout()),
|
_settingsLayout(new QHBoxLayout()),
|
||||||
_settingsInputMethods(new QComboBox(this)),
|
_settingsInputMethods(new QComboBox(this)),
|
||||||
_manualSettingValue(new VariableTextEdit(this, 5, 1, 1)),
|
_manualSettingValue(new VariableTextEdit(this, 5, 1, 1)),
|
||||||
@@ -315,16 +299,18 @@ MacroActionSourceEdit::MacroActionSourceEdit(
|
|||||||
auto sources = GetSourceNames();
|
auto sources = GetSourceNames();
|
||||||
sources.sort();
|
sources.sort();
|
||||||
_sources->SetSourceNameList(sources);
|
_sources->SetSourceNameList(sources);
|
||||||
populateDeinterlaceModeSelection(_deinterlaceMode);
|
populateModeSelection(_deinterlaceMode, deinterlaceModes);
|
||||||
populateDeinterlaceFieldOrderSelection(_deinterlaceOrder);
|
populateModeSelection(_deinterlaceOrder, deinterlaceFieldOrders);
|
||||||
populateSettingsInputMethods(_settingsInputMethods);
|
populateModeSelection(_settingsInputMethods, inputMethods);
|
||||||
_refreshSettingSelection->setToolTip(obs_module_text(
|
_refreshSettingSelection->setToolTip(obs_module_text(
|
||||||
"AdvSceneSwitcher.action.source.refresh.tooltip"));
|
"AdvSceneSwitcher.action.source.refresh.tooltip"));
|
||||||
|
|
||||||
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
QWidget::connect(_actions, SIGNAL(currentIndexChanged(int)), this,
|
||||||
SLOT(ActionChanged(int)));
|
SLOT(ActionChanged(int)));
|
||||||
QWidget::connect(_settingsButtons, SIGNAL(currentIndexChanged(int)),
|
QWidget::connect(_settingsButtons,
|
||||||
this, SLOT(ButtonChanged(int)));
|
SIGNAL(SelectionChanged(const SourceSettingButton &)),
|
||||||
|
this,
|
||||||
|
SLOT(ButtonChanged(const SourceSettingButton &)));
|
||||||
QWidget::connect(_sources,
|
QWidget::connect(_sources,
|
||||||
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||||
SLOT(SourceChanged(const SourceSelection &)));
|
SLOT(SourceChanged(const SourceSelection &)));
|
||||||
@@ -394,14 +380,11 @@ void MacroActionSourceEdit::UpdateEntryData()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PopulateSourceButtonSelection(_settingsButtons,
|
const auto weakSource = _entryData->_source.GetSource();
|
||||||
_entryData->_source.GetSource());
|
_settingsButtons->SetSelection(weakSource, _entryData->_button);
|
||||||
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
_actions->setCurrentIndex(static_cast<int>(_entryData->_action));
|
||||||
_sources->SetSource(_entryData->_source);
|
_sources->SetSource(_entryData->_source);
|
||||||
_sourceSettings->SetSource(_entryData->_source.GetSource());
|
_sourceSettings->SetSelection(weakSource, _entryData->_setting);
|
||||||
_sourceSettings->SetSetting(_entryData->_setting);
|
|
||||||
_settingsButtons->setCurrentText(
|
|
||||||
QString::fromStdString(_entryData->_button.ToString()));
|
|
||||||
_settingsString->setPlainText(_entryData->_settingsString);
|
_settingsString->setPlainText(_entryData->_settingsString);
|
||||||
_deinterlaceMode->setCurrentIndex(_deinterlaceMode->findData(
|
_deinterlaceMode->setCurrentIndex(_deinterlaceMode->findData(
|
||||||
static_cast<int>(_entryData->_deinterlaceMode)));
|
static_cast<int>(_entryData->_deinterlaceMode)));
|
||||||
@@ -425,9 +408,10 @@ void MacroActionSourceEdit::SourceChanged(const SourceSelection &source)
|
|||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
_entryData->_source = source;
|
_entryData->_source = source;
|
||||||
}
|
}
|
||||||
PopulateSourceButtonSelection(_settingsButtons,
|
|
||||||
_entryData->_source.GetSource());
|
const auto weakSource = _entryData->_source.GetSource();
|
||||||
_sourceSettings->SetSource(_entryData->_source.GetSource());
|
_sourceSettings->SetSource(weakSource);
|
||||||
|
_settingsButtons->SetSource(weakSource);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
emit HeaderInfoChanged(
|
emit HeaderInfoChanged(
|
||||||
QString::fromStdString(_entryData->GetShortDesc()));
|
QString::fromStdString(_entryData->GetShortDesc()));
|
||||||
@@ -435,24 +419,15 @@ void MacroActionSourceEdit::SourceChanged(const SourceSelection &source)
|
|||||||
|
|
||||||
void MacroActionSourceEdit::ActionChanged(int value)
|
void MacroActionSourceEdit::ActionChanged(int value)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_action = static_cast<MacroActionSource::Action>(value);
|
_entryData->_action = static_cast<MacroActionSource::Action>(value);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionSourceEdit::ButtonChanged(int idx)
|
void MacroActionSourceEdit::ButtonChanged(const SourceSettingButton &button)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
_entryData->_button = button;
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_button = qvariant_cast<SourceSettingButton>(
|
|
||||||
_settingsButtons->itemData(idx));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionSourceEdit::GetSettingsClicked()
|
void MacroActionSourceEdit::GetSettingsClicked()
|
||||||
@@ -479,11 +454,7 @@ void MacroActionSourceEdit::GetSettingsClicked()
|
|||||||
|
|
||||||
void MacroActionSourceEdit::SettingsStringChanged()
|
void MacroActionSourceEdit::SettingsStringChanged()
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_settingsString =
|
_entryData->_settingsString =
|
||||||
_settingsString->toPlainText().toStdString();
|
_settingsString->toPlainText().toStdString();
|
||||||
|
|
||||||
@@ -493,22 +464,14 @@ void MacroActionSourceEdit::SettingsStringChanged()
|
|||||||
|
|
||||||
void MacroActionSourceEdit::DeinterlaceModeChanged(int idx)
|
void MacroActionSourceEdit::DeinterlaceModeChanged(int idx)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_deinterlaceMode = static_cast<obs_deinterlace_mode>(
|
_entryData->_deinterlaceMode = static_cast<obs_deinterlace_mode>(
|
||||||
_deinterlaceMode->itemData(idx).toInt());
|
_deinterlaceMode->itemData(idx).toInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionSourceEdit::DeinterlaceOrderChanged(int idx)
|
void MacroActionSourceEdit::DeinterlaceOrderChanged(int idx)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_deinterlaceOrder =
|
_entryData->_deinterlaceOrder =
|
||||||
static_cast<obs_deinterlace_field_order>(
|
static_cast<obs_deinterlace_field_order>(
|
||||||
_deinterlaceOrder->itemData(idx).toInt());
|
_deinterlaceOrder->itemData(idx).toInt());
|
||||||
@@ -516,21 +479,13 @@ void MacroActionSourceEdit::DeinterlaceOrderChanged(int idx)
|
|||||||
|
|
||||||
void MacroActionSourceEdit::SelectionChanged(const TempVariableRef &var)
|
void MacroActionSourceEdit::SelectionChanged(const TempVariableRef &var)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_tempVar = var;
|
_entryData->_tempVar = var;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionSourceEdit::SettingsInputMethodChanged(int idx)
|
void MacroActionSourceEdit::SettingsInputMethodChanged(int idx)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_settingsInputMethod =
|
_entryData->_settingsInputMethod =
|
||||||
static_cast<MacroActionSource::SettingsInputMethod>(
|
static_cast<MacroActionSource::SettingsInputMethod>(
|
||||||
_settingsInputMethods->itemData(idx).toInt());
|
_settingsInputMethods->itemData(idx).toInt());
|
||||||
@@ -539,21 +494,13 @@ void MacroActionSourceEdit::SettingsInputMethodChanged(int idx)
|
|||||||
|
|
||||||
void MacroActionSourceEdit::SelectionChanged(const SourceSetting &setting)
|
void MacroActionSourceEdit::SelectionChanged(const SourceSetting &setting)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_setting = setting;
|
_entryData->_setting = setting;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionSourceEdit::ManualSettingsValueChanged()
|
void MacroActionSourceEdit::ManualSettingsValueChanged()
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_manualSettingValue =
|
_entryData->_manualSettingValue =
|
||||||
_manualSettingValue->toPlainText().toStdString();
|
_manualSettingValue->toPlainText().toStdString();
|
||||||
|
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ public:
|
|||||||
private slots:
|
private slots:
|
||||||
void SourceChanged(const SourceSelection &);
|
void SourceChanged(const SourceSelection &);
|
||||||
void ActionChanged(int value);
|
void ActionChanged(int value);
|
||||||
void ButtonChanged(int idx);
|
void ButtonChanged(const SourceSettingButton &);
|
||||||
void GetSettingsClicked();
|
void GetSettingsClicked();
|
||||||
void SettingsStringChanged();
|
void SettingsStringChanged();
|
||||||
void DeinterlaceModeChanged(int);
|
void DeinterlaceModeChanged(int);
|
||||||
@@ -99,7 +99,7 @@ private:
|
|||||||
|
|
||||||
SourceSelectionWidget *_sources;
|
SourceSelectionWidget *_sources;
|
||||||
QComboBox *_actions;
|
QComboBox *_actions;
|
||||||
QComboBox *_settingsButtons;
|
SourceSettingsButtonSelection *_settingsButtons;
|
||||||
QHBoxLayout *_settingsLayout;
|
QHBoxLayout *_settingsLayout;
|
||||||
QComboBox *_settingsInputMethods;
|
QComboBox *_settingsInputMethods;
|
||||||
VariableTextEdit *_manualSettingValue;
|
VariableTextEdit *_manualSettingValue;
|
||||||
|
|||||||
@@ -257,7 +257,9 @@ void MacroActionStreamEdit::StringValueChanged()
|
|||||||
|
|
||||||
void MacroActionStreamEdit::ShowPassword()
|
void MacroActionStreamEdit::ShowPassword()
|
||||||
{
|
{
|
||||||
SetButtonIcon(_showPassword, ":res/images/visible.svg");
|
SetButtonIcon(_showPassword, GetThemeTypeName() == "Light"
|
||||||
|
? ":res/images/visible.svg"
|
||||||
|
: "theme:Dark/visible.svg");
|
||||||
_stringValue->setEchoMode(QLineEdit::Normal);
|
_stringValue->setEchoMode(QLineEdit::Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -123,27 +123,23 @@ MacroActionSystrayEdit::MacroActionSystrayEdit(
|
|||||||
|
|
||||||
void MacroActionSystrayEdit::TitleChanged()
|
void MacroActionSystrayEdit::TitleChanged()
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_title = _title->text().toStdString();
|
_entryData->_title = _title->text().toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionSystrayEdit::IconPathChanged(const QString &text)
|
void MacroActionSystrayEdit::IconPathChanged(const QString &text)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_iconPath = text.toStdString();
|
_entryData->_iconPath = text.toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionSystrayEdit::CheckIfTrayIsDisabled()
|
void MacroActionSystrayEdit::CheckIfTrayIsDisabled()
|
||||||
{
|
{
|
||||||
|
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(31, 0, 0)
|
||||||
|
auto config = obs_frontend_get_user_config();
|
||||||
|
#else
|
||||||
auto config = obs_frontend_get_global_config();
|
auto config = obs_frontend_get_global_config();
|
||||||
|
#endif
|
||||||
if (!config) {
|
if (!config) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,15 +176,21 @@ bool MacroConditionDate::CheckRegularDate(int64_t msSinceLastCheck)
|
|||||||
|
|
||||||
bool MacroConditionDate::CheckCondition()
|
bool MacroConditionDate::CheckCondition()
|
||||||
{
|
{
|
||||||
auto m = GetMacro();
|
auto macro = GetMacro();
|
||||||
if (!m) {
|
if (!macro) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
const auto timePassed = std::chrono::high_resolution_clock::now() -
|
|
||||||
LastMacroConditionCheckTime(m);
|
const auto now = std::chrono::high_resolution_clock::now();
|
||||||
|
const auto lastCheck = LastMacroConditionCheckTime(macro);
|
||||||
|
|
||||||
|
const auto timePassed = now - lastCheck;
|
||||||
|
|
||||||
const auto msSinceLastCheck =
|
const auto msSinceLastCheck =
|
||||||
std::chrono::duration_cast<std::chrono::milliseconds>(
|
MacroWasCheckedSinceLastStart(macro)
|
||||||
timePassed);
|
? std::chrono::duration_cast<std::chrono::milliseconds>(
|
||||||
|
timePassed)
|
||||||
|
: std::chrono::milliseconds(0);
|
||||||
|
|
||||||
if (_dayOfWeekCheck) {
|
if (_dayOfWeekCheck) {
|
||||||
return CheckDayOfWeek(msSinceLastCheck.count());
|
return CheckDayOfWeek(msSinceLastCheck.count());
|
||||||
|
|||||||
@@ -420,8 +420,9 @@ void MacroConditionFilterEdit::UpdateEntryData()
|
|||||||
_regex->SetRegexConfig(_entryData->_regex);
|
_regex->SetRegexConfig(_entryData->_regex);
|
||||||
const auto filters =
|
const auto filters =
|
||||||
_entryData->_filter.GetFilters(_entryData->_source);
|
_entryData->_filter.GetFilters(_entryData->_source);
|
||||||
_settingSelection->SetSource(filters.empty() ? nullptr : filters.at(0));
|
_settingSelection->SetSelection(filters.empty() ? nullptr
|
||||||
_settingSelection->SetSetting(_entryData->_setting);
|
: filters.at(0),
|
||||||
|
_entryData->_setting);
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
|
|
||||||
adjustSize();
|
adjustSize();
|
||||||
|
|||||||
197
plugins/base/macro-condition-game-capture.cpp
Normal file
197
plugins/base/macro-condition-game-capture.cpp
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
#include "macro-condition-game-capture.hpp"
|
||||||
|
#include "layout-helpers.hpp"
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
const std::string MacroConditionGameCapture::id = "game_capture";
|
||||||
|
|
||||||
|
#ifdef _WIN32
|
||||||
|
bool MacroConditionGameCapture::_registered = MacroConditionFactory::Register(
|
||||||
|
MacroConditionGameCapture::id,
|
||||||
|
{MacroConditionGameCapture::Create,
|
||||||
|
MacroConditionGameCaptureEdit::Create,
|
||||||
|
"AdvSceneSwitcher.condition.gameCapture"});
|
||||||
|
#else
|
||||||
|
bool MacroConditionGameCapture::_registered =
|
||||||
|
false; // For now the 'game_capture' source only exists on Windows
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool MacroConditionGameCapture::CheckCondition()
|
||||||
|
{
|
||||||
|
auto source = OBSGetStrongRef(_source.GetSource());
|
||||||
|
if (source != _lastSource) {
|
||||||
|
SetupSignalHandler(source);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(_mtx);
|
||||||
|
if (_hooked) {
|
||||||
|
SetTempVarValue("title", _title);
|
||||||
|
SetTempVarValue("class", _class);
|
||||||
|
SetTempVarValue("executable", _executable);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _hooked;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionGameCapture::Save(obs_data_t *obj) const
|
||||||
|
{
|
||||||
|
MacroCondition::Save(obj);
|
||||||
|
_source.Save(obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionGameCapture::Load(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroCondition::Load(obj);
|
||||||
|
_source.Load(obj);
|
||||||
|
SetupSignalHandler(OBSGetStrongRef(_source.GetSource()));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionGameCapture::GetCalldataInfo(calldata_t *cd)
|
||||||
|
{
|
||||||
|
const char *title = "";
|
||||||
|
if (!calldata_get_string(cd, "title", &title)) {
|
||||||
|
blog(LOG_WARNING, "%s failed to get title", __func__);
|
||||||
|
}
|
||||||
|
_title = title;
|
||||||
|
const char *className = "";
|
||||||
|
if (!calldata_get_string(cd, "class", &className)) {
|
||||||
|
blog(LOG_WARNING, "%s failed to get class", __func__);
|
||||||
|
}
|
||||||
|
_class = className;
|
||||||
|
const char *executable = "";
|
||||||
|
if (!calldata_get_string(cd, "executable", &executable)) {
|
||||||
|
blog(LOG_WARNING, "%s failed to get executable", __func__);
|
||||||
|
}
|
||||||
|
_executable = executable;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionGameCapture::HookedSignalReceived(void *data, calldata_t *cd)
|
||||||
|
{
|
||||||
|
auto condition = static_cast<MacroConditionGameCapture *>(data);
|
||||||
|
std::lock_guard<std::mutex> lock(condition->_mtx);
|
||||||
|
condition->GetCalldataInfo(cd);
|
||||||
|
condition->_hooked = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionGameCapture::UnhookedSignalReceived(void *data, calldata_t *)
|
||||||
|
{
|
||||||
|
auto condition = static_cast<MacroConditionGameCapture *>(data);
|
||||||
|
std::lock_guard<std::mutex> lock(condition->_mtx);
|
||||||
|
condition->_hooked = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionGameCapture::SetupTempVars()
|
||||||
|
{
|
||||||
|
MacroCondition::SetupTempVars();
|
||||||
|
AddTempvar(
|
||||||
|
"title",
|
||||||
|
obs_module_text("AdvSceneSwitcher.tempVar.gameCapture.title"),
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.tempVar.gameCapture.title.description"));
|
||||||
|
AddTempvar(
|
||||||
|
"class",
|
||||||
|
obs_module_text("AdvSceneSwitcher.tempVar.gameCapture.class"),
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.tempVar.gameCapture.class.description"));
|
||||||
|
AddTempvar(
|
||||||
|
"executable",
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.tempVar.gameCapture.executable"),
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.tempVar.gameCapture.executable.description"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionGameCapture::SetupSignalHandler(obs_source_t *source)
|
||||||
|
{
|
||||||
|
signal_handler_t *sh = obs_source_get_signal_handler(source);
|
||||||
|
_hookSignal = OBSSignal(sh, "hooked", HookedSignalReceived, this);
|
||||||
|
_unhookSignal = OBSSignal(sh, "unhooked", UnhookedSignalReceived, this);
|
||||||
|
_lastSource = source;
|
||||||
|
|
||||||
|
SetupInitialState(source);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionGameCapture::SetupInitialState(obs_source_t *source)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(_mtx);
|
||||||
|
|
||||||
|
_hooked = false;
|
||||||
|
if (!source) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
calldata_t cd;
|
||||||
|
calldata_init(&cd);
|
||||||
|
auto ph = obs_source_get_proc_handler(source);
|
||||||
|
if (!proc_handler_call(ph, "get_hooked", &cd)) {
|
||||||
|
blog(LOG_WARNING,
|
||||||
|
"%s failed to call proc_handler for 'get_hooked'",
|
||||||
|
__func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!calldata_get_bool(&cd, "hooked", &_hooked)) {
|
||||||
|
blog(LOG_WARNING, "%s failed to get hooked state", __func__);
|
||||||
|
}
|
||||||
|
GetCalldataInfo(&cd);
|
||||||
|
|
||||||
|
calldata_free(&cd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static QStringList getGameCaptureSourceNames()
|
||||||
|
{
|
||||||
|
auto sourceEnum = [](void *param, obs_source_t *source) -> bool /* -- */
|
||||||
|
{
|
||||||
|
QStringList *list = reinterpret_cast<QStringList *>(param);
|
||||||
|
|
||||||
|
if (strcmp(obs_source_get_unversioned_id(source),
|
||||||
|
"game_capture") == 0) {
|
||||||
|
*list << obs_source_get_name(source);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
QStringList list;
|
||||||
|
obs_enum_sources(sourceEnum, &list);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroConditionGameCaptureEdit::MacroConditionGameCaptureEdit(
|
||||||
|
QWidget *parent, std::shared_ptr<MacroConditionGameCapture> entryData)
|
||||||
|
: QWidget(parent),
|
||||||
|
_sources(new SourceSelectionWidget(this, QStringList(), true))
|
||||||
|
{
|
||||||
|
auto sources = getGameCaptureSourceNames();
|
||||||
|
sources.sort();
|
||||||
|
_sources->SetSourceNameList(sources);
|
||||||
|
|
||||||
|
QWidget::connect(_sources,
|
||||||
|
SIGNAL(SourceChanged(const SourceSelection &)), this,
|
||||||
|
SLOT(SourceChanged(const SourceSelection &)));
|
||||||
|
|
||||||
|
auto layout = new QHBoxLayout;
|
||||||
|
PlaceWidgets(
|
||||||
|
obs_module_text("AdvSceneSwitcher.condition.gameCapture.entry"),
|
||||||
|
layout, {{"{{sources}}", _sources}});
|
||||||
|
setLayout(layout);
|
||||||
|
|
||||||
|
_entryData = entryData;
|
||||||
|
UpdateEntryData();
|
||||||
|
_loading = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionGameCaptureEdit::SourceChanged(const SourceSelection &source)
|
||||||
|
{
|
||||||
|
GUARD_LOADING_AND_LOCK();
|
||||||
|
_entryData->_source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionGameCaptureEdit::UpdateEntryData()
|
||||||
|
{
|
||||||
|
_sources->SetSource(_entryData->_source);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
74
plugins/base/macro-condition-game-capture.hpp
Normal file
74
plugins/base/macro-condition-game-capture.hpp
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro-condition-edit.hpp"
|
||||||
|
#include "source-selection.hpp"
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QComboBox>
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
class MacroConditionGameCapture : public MacroCondition {
|
||||||
|
public:
|
||||||
|
MacroConditionGameCapture(Macro *m) : MacroCondition(m) {}
|
||||||
|
bool CheckCondition();
|
||||||
|
bool Save(obs_data_t *obj) const;
|
||||||
|
bool Load(obs_data_t *obj);
|
||||||
|
std::string GetId() const { return id; };
|
||||||
|
static std::shared_ptr<MacroCondition> Create(Macro *m)
|
||||||
|
{
|
||||||
|
return std::make_shared<MacroConditionGameCapture>(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
SourceSelection _source;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static void HookedSignalReceived(void *data, calldata_t *);
|
||||||
|
static void UnhookedSignalReceived(void *data, calldata_t *);
|
||||||
|
|
||||||
|
void SetupTempVars();
|
||||||
|
void SetupSignalHandler(obs_source_t *source);
|
||||||
|
void SetupInitialState(obs_source_t *source);
|
||||||
|
void GetCalldataInfo(calldata_t *cd);
|
||||||
|
|
||||||
|
obs_source_t *_lastSource = nullptr;
|
||||||
|
OBSSignal _hookSignal;
|
||||||
|
OBSSignal _unhookSignal;
|
||||||
|
|
||||||
|
bool _hooked = false;
|
||||||
|
std::string _title = "";
|
||||||
|
std::string _class = "";
|
||||||
|
std::string _executable = "";
|
||||||
|
std::mutex _mtx;
|
||||||
|
|
||||||
|
static bool _registered;
|
||||||
|
static const std::string id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroConditionGameCaptureEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroConditionGameCaptureEdit(
|
||||||
|
QWidget *parent,
|
||||||
|
std::shared_ptr<MacroConditionGameCapture> cond = nullptr);
|
||||||
|
void UpdateEntryData();
|
||||||
|
static QWidget *Create(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroCondition> cond)
|
||||||
|
{
|
||||||
|
return new MacroConditionGameCaptureEdit(
|
||||||
|
parent,
|
||||||
|
std::dynamic_pointer_cast<MacroConditionGameCapture>(
|
||||||
|
cond));
|
||||||
|
}
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void SourceChanged(const SourceSelection &);
|
||||||
|
|
||||||
|
private:
|
||||||
|
SourceSelectionWidget *_sources;
|
||||||
|
std::shared_ptr<MacroConditionGameCapture> _entryData;
|
||||||
|
|
||||||
|
bool _loading = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
@@ -548,14 +548,14 @@ void MacroConditionMedia::MediaNext(void *data, calldata_t *)
|
|||||||
|
|
||||||
void MacroConditionMedia::SetSourceType(SourceType t)
|
void MacroConditionMedia::SetSourceType(SourceType t)
|
||||||
{
|
{
|
||||||
SetupTempVars();
|
|
||||||
_sourceType = t;
|
_sourceType = t;
|
||||||
|
SetupTempVars();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionMedia::SetCheckType(CheckType t)
|
void MacroConditionMedia::SetCheckType(CheckType t)
|
||||||
{
|
{
|
||||||
SetupTempVars();
|
|
||||||
_checkType = t;
|
_checkType = t;
|
||||||
|
SetupTempVars();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void populateSateSelection(QComboBox *list, bool addLegacyEntries)
|
static void populateSateSelection(QComboBox *list, bool addLegacyEntries)
|
||||||
|
|||||||
94
plugins/base/macro-condition-screenshot.cpp
Normal file
94
plugins/base/macro-condition-screenshot.cpp
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
#include "macro-condition-screenshot.hpp"
|
||||||
|
#include "layout-helpers.hpp"
|
||||||
|
|
||||||
|
#include <obs-frontend-api.h>
|
||||||
|
#include <thread>
|
||||||
|
|
||||||
|
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(29, 0, 0)
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
const std::string MacroConditionScreenshot::id = "screenshot";
|
||||||
|
|
||||||
|
bool MacroConditionScreenshot::_registered = MacroConditionFactory::Register(
|
||||||
|
MacroConditionScreenshot::id,
|
||||||
|
{MacroConditionScreenshot::Create, MacroConditionScreenshotEdit::Create,
|
||||||
|
"AdvSceneSwitcher.condition.screenshot"});
|
||||||
|
|
||||||
|
static std::chrono::high_resolution_clock::time_point screenshotTakenTime{};
|
||||||
|
static bool setupScreenshotTakenEventHandler();
|
||||||
|
static bool setupDone = setupScreenshotTakenEventHandler();
|
||||||
|
|
||||||
|
static bool setupScreenshotTakenEventHandler()
|
||||||
|
{
|
||||||
|
static auto handleScreenshotEvent = [](enum obs_frontend_event event,
|
||||||
|
void *) {
|
||||||
|
switch (event) {
|
||||||
|
case OBS_FRONTEND_EVENT_SCREENSHOT_TAKEN:
|
||||||
|
screenshotTakenTime =
|
||||||
|
std::chrono::high_resolution_clock::now();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
obs_frontend_add_event_callback(handleScreenshotEvent, nullptr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionScreenshot::CheckCondition()
|
||||||
|
{
|
||||||
|
if (!_screenshotTimeInitialized) {
|
||||||
|
_screenshotTime = screenshotTakenTime;
|
||||||
|
_screenshotTimeInitialized = true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lastScreenshotPath = obs_frontend_get_last_screenshot();
|
||||||
|
SetTempVarValue("lastScreenshotPath", lastScreenshotPath);
|
||||||
|
bfree(lastScreenshotPath);
|
||||||
|
|
||||||
|
bool newSaveOccurred = _screenshotTime != screenshotTakenTime;
|
||||||
|
_screenshotTime = screenshotTakenTime;
|
||||||
|
return newSaveOccurred;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionScreenshot::Save(obs_data_t *obj) const
|
||||||
|
{
|
||||||
|
MacroCondition::Save(obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionScreenshot::Load(obs_data_t *obj)
|
||||||
|
{
|
||||||
|
MacroCondition::Load(obj);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroConditionScreenshot::SetupTempVars()
|
||||||
|
{
|
||||||
|
MacroCondition::SetupTempVars();
|
||||||
|
AddTempvar(
|
||||||
|
"lastScreenshotPath",
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.tempVar.screenshot.lastScreenshotPath"),
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.tempVar.screenshot.lastScreenshotPath.description"));
|
||||||
|
}
|
||||||
|
|
||||||
|
MacroConditionScreenshotEdit::MacroConditionScreenshotEdit(
|
||||||
|
QWidget *parent, std::shared_ptr<MacroConditionScreenshot> entryData)
|
||||||
|
: QWidget(parent)
|
||||||
|
{
|
||||||
|
auto layout = new QHBoxLayout;
|
||||||
|
PlaceWidgets(
|
||||||
|
obs_module_text("AdvSceneSwitcher.condition.screenshot.entry"),
|
||||||
|
layout, {});
|
||||||
|
setLayout(layout);
|
||||||
|
|
||||||
|
_entryData = entryData;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|
||||||
|
#endif
|
||||||
55
plugins/base/macro-condition-screenshot.hpp
Normal file
55
plugins/base/macro-condition-screenshot.hpp
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
#pragma once
|
||||||
|
#include "macro-condition-edit.hpp"
|
||||||
|
|
||||||
|
#include <obs-config.h>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QComboBox>
|
||||||
|
|
||||||
|
#if LIBOBS_API_VER >= MAKE_SEMANTIC_VERSION(29, 0, 0)
|
||||||
|
|
||||||
|
namespace advss {
|
||||||
|
|
||||||
|
class MacroConditionScreenshot : public MacroCondition {
|
||||||
|
public:
|
||||||
|
MacroConditionScreenshot(Macro *m) : MacroCondition(m) {}
|
||||||
|
bool CheckCondition();
|
||||||
|
bool Save(obs_data_t *obj) const;
|
||||||
|
bool Load(obs_data_t *obj);
|
||||||
|
std::string GetId() const { return id; };
|
||||||
|
static std::shared_ptr<MacroCondition> Create(Macro *m)
|
||||||
|
{
|
||||||
|
return std::make_shared<MacroConditionScreenshot>(m);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SetupTempVars();
|
||||||
|
|
||||||
|
bool _screenshotTimeInitialized = false;
|
||||||
|
std::chrono::high_resolution_clock::time_point _screenshotTime = {};
|
||||||
|
static bool _registered;
|
||||||
|
static const std::string id;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MacroConditionScreenshotEdit : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
MacroConditionScreenshotEdit(
|
||||||
|
QWidget *parent,
|
||||||
|
std::shared_ptr<MacroConditionScreenshot> cond = nullptr);
|
||||||
|
static QWidget *Create(QWidget *parent,
|
||||||
|
std::shared_ptr<MacroCondition> cond)
|
||||||
|
{
|
||||||
|
return new MacroConditionScreenshotEdit(
|
||||||
|
parent,
|
||||||
|
std::dynamic_pointer_cast<MacroConditionScreenshot>(
|
||||||
|
cond));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<MacroConditionScreenshot> _entryData;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace advss
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -483,8 +483,8 @@ void MacroConditionSourceEdit::UpdateEntryData()
|
|||||||
static_cast<int>(_entryData->GetCondition()));
|
static_cast<int>(_entryData->GetCondition()));
|
||||||
_settings->setPlainText(_entryData->_settings);
|
_settings->setPlainText(_entryData->_settings);
|
||||||
_regex->SetRegexConfig(_entryData->_regex);
|
_regex->SetRegexConfig(_entryData->_regex);
|
||||||
_settingSelection->SetSource(_entryData->_source.GetSource());
|
_settingSelection->SetSelection(_entryData->_source.GetSource(),
|
||||||
_settingSelection->SetSetting(_entryData->_setting);
|
_entryData->_setting);
|
||||||
_size->SetValue(_entryData->_size);
|
_size->SetValue(_entryData->_size);
|
||||||
_sizeCompareMethods->setCurrentIndex(
|
_sizeCompareMethods->setCurrentIndex(
|
||||||
static_cast<int>(_entryData->_comparision));
|
static_cast<int>(_entryData->_comparision));
|
||||||
|
|||||||
@@ -111,27 +111,42 @@ bool MacroConditionTransition::CheckCondition()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionTransition::ConnectToTransitionSignals()
|
void advss::MacroConditionTransition::AddTransitionSignals(
|
||||||
|
obs_source_t *transition)
|
||||||
{
|
{
|
||||||
const bool useFrontendTransitionSelection =
|
signal_handler_t *sh = obs_source_get_signal_handler(transition);
|
||||||
_transition.GetType() !=
|
|
||||||
TransitionSelection::Type::TRANSITION ||
|
|
||||||
(_condition == Condition::TRANSITION_SOURCE ||
|
|
||||||
_condition == Condition::TRANSITION_TARGET);
|
|
||||||
|
|
||||||
_signals.clear();
|
|
||||||
OBSSourceAutoRelease source =
|
|
||||||
useFrontendTransitionSelection
|
|
||||||
? obs_frontend_get_current_transition()
|
|
||||||
: obs_weak_source_get_source(
|
|
||||||
_transition.GetTransition());
|
|
||||||
signal_handler_t *sh = obs_source_get_signal_handler(source);
|
|
||||||
_signals.emplace_back(sh, "transition_start", TransitionStarted, this);
|
_signals.emplace_back(sh, "transition_start", TransitionStarted, this);
|
||||||
_signals.emplace_back(sh, "transition_stop", TransitionEnded, this);
|
_signals.emplace_back(sh, "transition_stop", TransitionEnded, this);
|
||||||
_signals.emplace_back(sh, "transition_video_stop", TransitionVideoEnded,
|
_signals.emplace_back(sh, "transition_video_stop", TransitionVideoEnded,
|
||||||
this);
|
this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroConditionTransition::ConnectToTransitionSignals()
|
||||||
|
{
|
||||||
|
_signals.clear();
|
||||||
|
|
||||||
|
const bool watchSingleTransitionType =
|
||||||
|
_transition.GetType() ==
|
||||||
|
TransitionSelection::Type::TRANSITION &&
|
||||||
|
!(_condition == Condition::TRANSITION_SOURCE ||
|
||||||
|
_condition == Condition::TRANSITION_TARGET);
|
||||||
|
|
||||||
|
if (watchSingleTransitionType) {
|
||||||
|
OBSSourceAutoRelease transition =
|
||||||
|
OBSGetStrongRef(_transition.GetTransition());
|
||||||
|
AddTransitionSignals(transition);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
obs_frontend_source_list transitions = {};
|
||||||
|
obs_frontend_get_transitions(&transitions);
|
||||||
|
for (size_t i = 0; i < transitions.sources.num; i++) {
|
||||||
|
obs_source_t *transition = transitions.sources.array[i];
|
||||||
|
AddTransitionSignals(transition);
|
||||||
|
}
|
||||||
|
obs_frontend_source_list_free(&transitions);
|
||||||
|
}
|
||||||
|
|
||||||
void MacroConditionTransition::TransitionStarted(void *data, calldata_t *cd)
|
void MacroConditionTransition::TransitionStarted(void *data, calldata_t *cd)
|
||||||
{
|
{
|
||||||
auto *condition = static_cast<MacroConditionTransition *>(data);
|
auto *condition = static_cast<MacroConditionTransition *>(data);
|
||||||
|
|||||||
@@ -42,6 +42,7 @@ private:
|
|||||||
static void TransitionEnded(void *data, calldata_t *);
|
static void TransitionEnded(void *data, calldata_t *);
|
||||||
static void TransitionVideoEnded(void *data, calldata_t *);
|
static void TransitionVideoEnded(void *data, calldata_t *);
|
||||||
static void HandleFrontendEvent(enum obs_frontend_event event, void *);
|
static void HandleFrontendEvent(enum obs_frontend_event event, void *);
|
||||||
|
void AddTransitionSignals(obs_source_t *);
|
||||||
|
|
||||||
std::vector<OBSSignal> _signals;
|
std::vector<OBSSignal> _signals;
|
||||||
|
|
||||||
|
|||||||
@@ -332,7 +332,8 @@ WSConnectionSettingsDialog::WSConnectionSettingsDialog(
|
|||||||
: ItemSettingsDialog(settings, connections,
|
: ItemSettingsDialog(settings, connections,
|
||||||
"AdvSceneSwitcher.connection.select",
|
"AdvSceneSwitcher.connection.select",
|
||||||
"AdvSceneSwitcher.connection.add",
|
"AdvSceneSwitcher.connection.add",
|
||||||
"AdvSceneSwitcher.item.nameNotAvailable", parent),
|
"AdvSceneSwitcher.item.nameNotAvailable", true,
|
||||||
|
parent),
|
||||||
_useCustomURI(new QCheckBox()),
|
_useCustomURI(new QCheckBox()),
|
||||||
_customUri(new QLineEdit()),
|
_customUri(new QLineEdit()),
|
||||||
_address(new QLineEdit()),
|
_address(new QLineEdit()),
|
||||||
@@ -502,7 +503,9 @@ void WSConnectionSettingsDialog::SetStatus()
|
|||||||
|
|
||||||
void WSConnectionSettingsDialog::ShowPassword()
|
void WSConnectionSettingsDialog::ShowPassword()
|
||||||
{
|
{
|
||||||
SetButtonIcon(_showPassword, ":res/images/visible.svg");
|
SetButtonIcon(_showPassword, GetThemeTypeName() == "Light"
|
||||||
|
? ":res/images/visible.svg"
|
||||||
|
: "theme:Dark/visible.svg");
|
||||||
_password->setEchoMode(QLineEdit::Normal);
|
_password->setEchoMode(QLineEdit::Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -698,7 +698,10 @@ SceneItemSelectionWidget::SceneItemSelectionWidget(QWidget *parent,
|
|||||||
_nameConflictIndex->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
_nameConflictIndex->setSizeAdjustPolicy(QComboBox::AdjustToContents);
|
||||||
|
|
||||||
_changeType->setMaximumWidth(22);
|
_changeType->setMaximumWidth(22);
|
||||||
SetButtonIcon(_changeType, ":/settings/images/settings/general.svg");
|
SetButtonIcon(_changeType,
|
||||||
|
GetThemeTypeName() == "Light"
|
||||||
|
? ":/settings/images/settings/general.svg"
|
||||||
|
: "theme:Dark/settings/general.svg");
|
||||||
_changeType->setFlat(true);
|
_changeType->setFlat(true);
|
||||||
_changeType->setToolTip(obs_module_text(
|
_changeType->setToolTip(obs_module_text(
|
||||||
"AdvSceneSwitcher.sceneItemSelection.configure"));
|
"AdvSceneSwitcher.sceneItemSelection.configure"));
|
||||||
|
|||||||
@@ -29,20 +29,37 @@ std::string SourceSettingButton::ToString() const
|
|||||||
return "[" + id + "] " + description;
|
return "[" + id + "] " + description;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<SourceSettingButton> GetSourceButtons(OBSWeakSource source)
|
static void getSourceButtonsHelper(obs_properties_t *sourceProperties,
|
||||||
|
std::vector<SourceSettingButton> &buttons)
|
||||||
{
|
{
|
||||||
OBSSourceAutoRelease s = obs_weak_source_get_source(source);
|
|
||||||
std::vector<SourceSettingButton> buttons;
|
|
||||||
obs_properties_t *sourceProperties = obs_source_properties(s);
|
|
||||||
auto it = obs_properties_first(sourceProperties);
|
auto it = obs_properties_first(sourceProperties);
|
||||||
do {
|
do {
|
||||||
if (!it || obs_property_get_type(it) != OBS_PROPERTY_BUTTON) {
|
if (!it) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto type = obs_property_get_type(it);
|
||||||
|
if (type == OBS_PROPERTY_GROUP) {
|
||||||
|
auto group = obs_property_group_content(it);
|
||||||
|
getSourceButtonsHelper(group, buttons);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (obs_property_get_type(it) != OBS_PROPERTY_BUTTON) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
SourceSettingButton button = {obs_property_name(it),
|
SourceSettingButton button = {obs_property_name(it),
|
||||||
obs_property_description(it)};
|
obs_property_description(it)};
|
||||||
buttons.emplace_back(button);
|
buttons.emplace_back(button);
|
||||||
} while (obs_property_next(&it));
|
} while (obs_property_next(&it));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<SourceSettingButton> GetSourceButtons(OBSWeakSource source)
|
||||||
|
{
|
||||||
|
OBSSourceAutoRelease s = obs_weak_source_get_source(source);
|
||||||
|
std::vector<SourceSettingButton> buttons;
|
||||||
|
auto sourceProperties = obs_source_properties(s);
|
||||||
|
getSourceButtonsHelper(sourceProperties, buttons);
|
||||||
obs_properties_destroy(sourceProperties);
|
obs_properties_destroy(sourceProperties);
|
||||||
return buttons;
|
return buttons;
|
||||||
}
|
}
|
||||||
@@ -59,19 +76,46 @@ void PressSourceButton(const SourceSettingButton &button, obs_source_t *source)
|
|||||||
obs_properties_destroy(sourceProperties);
|
obs_properties_destroy(sourceProperties);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PopulateSourceButtonSelection(QComboBox *list, OBSWeakSource source)
|
SourceSettingsButtonSelection::SourceSettingsButtonSelection(QWidget *parent)
|
||||||
|
: FilterComboBox(parent)
|
||||||
{
|
{
|
||||||
list->clear();
|
connect(this, &FilterComboBox::currentIndexChanged, [this](int idx) {
|
||||||
|
emit SelectionChanged(
|
||||||
|
qvariant_cast<SourceSettingButton>(itemData(idx)));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceSettingsButtonSelection::SetSource(const OBSWeakSource &source,
|
||||||
|
bool restorePreviousSelection)
|
||||||
|
{
|
||||||
|
const auto previousSelection = currentText();
|
||||||
|
PopulateSelection(source);
|
||||||
|
if (restorePreviousSelection) {
|
||||||
|
setCurrentIndex(findText(previousSelection));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceSettingsButtonSelection::SetSelection(
|
||||||
|
const OBSWeakSource &source, const SourceSettingButton &button)
|
||||||
|
{
|
||||||
|
SetSource(source, false);
|
||||||
|
setCurrentText(QString::fromStdString(button.ToString()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SourceSettingsButtonSelection::PopulateSelection(
|
||||||
|
const OBSWeakSource &source)
|
||||||
|
{
|
||||||
|
const QSignalBlocker b(this);
|
||||||
|
clear();
|
||||||
auto buttons = GetSourceButtons(source);
|
auto buttons = GetSourceButtons(source);
|
||||||
if (buttons.empty()) {
|
if (buttons.empty()) {
|
||||||
list->addItem(
|
addItem(obs_module_text("AdvSceneSwitcher.noSettingsButtons"));
|
||||||
obs_module_text("AdvSceneSwitcher.noSettingsButtons"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const auto &button : buttons) {
|
for (const auto &button : buttons) {
|
||||||
QVariant value;
|
QVariant value;
|
||||||
value.setValue(button);
|
value.setValue(button);
|
||||||
list->addItem(QString::fromStdString(button.ToString()), value);
|
addItem(QString::fromStdString(button.ToString()), value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
#include "filter-combo-box.hpp"
|
||||||
|
|
||||||
#include <obs.hpp>
|
#include <obs.hpp>
|
||||||
#include <QComboBox>
|
|
||||||
#include <qmetatype.h>
|
#include <qmetatype.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
|
class SourceSelection;
|
||||||
|
class FilterSelection;
|
||||||
|
|
||||||
struct SourceSettingButton {
|
struct SourceSettingButton {
|
||||||
bool Save(obs_data_t *obj) const;
|
bool Save(obs_data_t *obj) const;
|
||||||
bool Load(obs_data_t *obj);
|
bool Load(obs_data_t *obj);
|
||||||
@@ -18,7 +22,23 @@ struct SourceSettingButton {
|
|||||||
|
|
||||||
std::vector<SourceSettingButton> GetSourceButtons(OBSWeakSource source);
|
std::vector<SourceSettingButton> GetSourceButtons(OBSWeakSource source);
|
||||||
void PressSourceButton(const SourceSettingButton &button, obs_source_t *source);
|
void PressSourceButton(const SourceSettingButton &button, obs_source_t *source);
|
||||||
void PopulateSourceButtonSelection(QComboBox *list, OBSWeakSource source);
|
|
||||||
|
class SourceSettingsButtonSelection : public FilterComboBox {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
SourceSettingsButtonSelection(QWidget *parent = nullptr);
|
||||||
|
void SetSource(const OBSWeakSource &source,
|
||||||
|
bool restorePreviousSelection = true);
|
||||||
|
void SetSelection(const OBSWeakSource &source,
|
||||||
|
const SourceSettingButton &button);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void SelectionChanged(const SourceSettingButton &);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void PopulateSelection(const OBSWeakSource &source);
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|
||||||
|
|||||||
@@ -249,14 +249,21 @@ SourceSettingSelection::SourceSettingSelection(QWidget *parent)
|
|||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SourceSettingSelection::SetSource(const OBSWeakSource &source)
|
void SourceSettingSelection::SetSource(const OBSWeakSource &source,
|
||||||
|
bool restorePreviousSelection)
|
||||||
{
|
{
|
||||||
_settings->clear();
|
const auto previousSelection = _settings->currentData();
|
||||||
Populate(source);
|
Populate(source);
|
||||||
|
if (restorePreviousSelection) {
|
||||||
|
_settings->setCurrentIndex(
|
||||||
|
_settings->findData(previousSelection));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SourceSettingSelection::SetSetting(const SourceSetting &setting)
|
void SourceSettingSelection::SetSelection(const OBSWeakSource &source,
|
||||||
|
const SourceSetting &setting)
|
||||||
{
|
{
|
||||||
|
SetSource(source, false);
|
||||||
QVariant variant;
|
QVariant variant;
|
||||||
variant.setValue(setting);
|
variant.setValue(setting);
|
||||||
_settings->setCurrentIndex(_settings->findData(variant));
|
_settings->setCurrentIndex(_settings->findData(variant));
|
||||||
@@ -281,6 +288,7 @@ void SourceSettingSelection::SelectionIdxChanged(int idx)
|
|||||||
|
|
||||||
void SourceSettingSelection::Populate(const OBSWeakSource &source)
|
void SourceSettingSelection::Populate(const OBSWeakSource &source)
|
||||||
{
|
{
|
||||||
|
_settings->clear();
|
||||||
OBSSourceAutoRelease s = obs_weak_source_get_source(source);
|
OBSSourceAutoRelease s = obs_weak_source_get_source(source);
|
||||||
auto settings = GetSoruceSettings(s);
|
auto settings = GetSoruceSettings(s);
|
||||||
for (const auto &setting : settings) {
|
for (const auto &setting : settings) {
|
||||||
|
|||||||
@@ -40,8 +40,9 @@ class SourceSettingSelection : public QWidget {
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
SourceSettingSelection(QWidget *parent = nullptr);
|
SourceSettingSelection(QWidget *parent = nullptr);
|
||||||
void SetSource(const OBSWeakSource &);
|
void SetSource(const OBSWeakSource &,
|
||||||
void SetSetting(const SourceSetting &);
|
bool restorePreviousSelection = true);
|
||||||
|
void SetSelection(const OBSWeakSource &source, const SourceSetting &);
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void SelectionIdxChanged(int);
|
void SelectionIdxChanged(int);
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ void WSConnectionsTable::Add()
|
|||||||
{
|
{
|
||||||
auto newConnection = std::make_shared<WSConnection>();
|
auto newConnection = std::make_shared<WSConnection>();
|
||||||
auto accepted = WSConnectionSettingsDialog::AskForSettings(
|
auto accepted = WSConnectionSettingsDialog::AskForSettings(
|
||||||
this, *newConnection);
|
GetSettingsWindow(), *newConnection);
|
||||||
if (!accepted) {
|
if (!accepted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -143,7 +143,7 @@ static void openSettingsDialog()
|
|||||||
|
|
||||||
auto oldName = connection->Name();
|
auto oldName = connection->Name();
|
||||||
bool accepted = WSConnectionSettingsDialog::AskForSettings(
|
bool accepted = WSConnectionSettingsDialog::AskForSettings(
|
||||||
tabWidget->Table(), *connection.get());
|
GetSettingsWindow(), *connection.get());
|
||||||
if (accepted && oldName != connection->Name()) {
|
if (accepted && oldName != connection->Name()) {
|
||||||
ConnectionSelectionSignalManager::Instance()->Rename(
|
ConnectionSelectionSignalManager::Instance()->Rename(
|
||||||
QString::fromStdString(oldName),
|
QString::fromStdString(oldName),
|
||||||
|
|||||||
@@ -139,7 +139,7 @@ void TwitchCategorySelection::SelectionChanged(int index)
|
|||||||
{
|
{
|
||||||
TwitchCategory category{itemData(index).toInt(),
|
TwitchCategory category{itemData(index).toInt(),
|
||||||
currentText().toStdString()};
|
currentText().toStdString()};
|
||||||
emit CategoreyChanged(category);
|
emit CategoryChanged(category);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<QString, int> CategoryGrabber::_categoryMap = {};
|
std::map<QString, int> CategoryGrabber::_categoryMap = {};
|
||||||
@@ -193,7 +193,7 @@ void CategoryGrabber::Search(const std::string &)
|
|||||||
httplib::Params params = {{"first", "100"},
|
httplib::Params params = {{"first", "100"},
|
||||||
{"after", cursor},
|
{"after", cursor},
|
||||||
{"query", _searchString}};
|
{"query", _searchString}};
|
||||||
auto response = SendGetRequest(*_token, uri, path, params);
|
auto response = SendGetRequest(*_token, uri, path, params, true);
|
||||||
|
|
||||||
while (response.status == 200 && !_stop) {
|
while (response.status == 200 && !_stop) {
|
||||||
cursor = ParseReply(response.data);
|
cursor = ParseReply(response.data);
|
||||||
@@ -203,7 +203,7 @@ void CategoryGrabber::Search(const std::string &)
|
|||||||
params = {{"first", "100"},
|
params = {{"first", "100"},
|
||||||
{"after", cursor},
|
{"after", cursor},
|
||||||
{"query", _searchString}};
|
{"query", _searchString}};
|
||||||
response = SendGetRequest(*_token, uri, path, params);
|
response = SendGetRequest(*_token, uri, path, params, true);
|
||||||
emit CategoryCountUpdated(_categoryMap.size() - startCount);
|
emit CategoryCountUpdated(_categoryMap.size() - startCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -217,7 +217,7 @@ void CategoryGrabber::GetAll()
|
|||||||
static std::string cursor;
|
static std::string cursor;
|
||||||
|
|
||||||
httplib::Params params = {{"first", "100"}, {"after", cursor}};
|
httplib::Params params = {{"first", "100"}, {"after", cursor}};
|
||||||
auto response = SendGetRequest(*_token, uri, path, params);
|
auto response = SendGetRequest(*_token, uri, path, params, true);
|
||||||
|
|
||||||
while (response.status == 200 && !_stop) {
|
while (response.status == 200 && !_stop) {
|
||||||
cursor = ParseReply(response.data);
|
cursor = ParseReply(response.data);
|
||||||
@@ -225,7 +225,7 @@ void CategoryGrabber::GetAll()
|
|||||||
break; // End of category list
|
break; // End of category list
|
||||||
}
|
}
|
||||||
params = {{"first", "100"}, {"after", cursor}};
|
params = {{"first", "100"}, {"after", cursor}};
|
||||||
response = SendGetRequest(*_token, uri, path, params);
|
response = SendGetRequest(*_token, uri, path, params, true);
|
||||||
emit CategoryCountUpdated(_categoryMap.size());
|
emit CategoryCountUpdated(_categoryMap.size());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -364,8 +364,8 @@ TwitchCategoryWidget::TwitchCategoryWidget(QWidget *parent)
|
|||||||
_manualSearch(new TwitchCategorySearchButton(this))
|
_manualSearch(new TwitchCategorySearchButton(this))
|
||||||
{
|
{
|
||||||
QWidget::connect(_selection,
|
QWidget::connect(_selection,
|
||||||
SIGNAL(CategoreyChanged(const TwitchCategory &)), this,
|
SIGNAL(CategoryChanged(const TwitchCategory &)), this,
|
||||||
SIGNAL(CategoreyChanged(const TwitchCategory &)));
|
SIGNAL(CategoryChanged(const TwitchCategory &)));
|
||||||
|
|
||||||
auto layout = new QHBoxLayout();
|
auto layout = new QHBoxLayout();
|
||||||
layout->setContentsMargins(0, 0, 0, 0);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ private slots:
|
|||||||
void UpdateCategoryList();
|
void UpdateCategoryList();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void CategoreyChanged(const TwitchCategory &);
|
void CategoryChanged(const TwitchCategory &);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void showPopup() override;
|
void showPopup() override;
|
||||||
@@ -125,7 +125,7 @@ public:
|
|||||||
void SetToken(const std::weak_ptr<TwitchToken> &);
|
void SetToken(const std::weak_ptr<TwitchToken> &);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void CategoreyChanged(const TwitchCategory &);
|
void CategoryChanged(const TwitchCategory &);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
TwitchCategorySelection *_selection;
|
TwitchCategorySelection *_selection;
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
#include "channel-selection.hpp"
|
#include "channel-selection.hpp"
|
||||||
|
#include "log-helper.hpp"
|
||||||
#include "twitch-helpers.hpp"
|
#include "twitch-helpers.hpp"
|
||||||
#include "token.hpp"
|
#include "token.hpp"
|
||||||
|
|
||||||
@@ -36,7 +37,7 @@ std::string TwitchChannel::GetUserID(const TwitchToken &token) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto res = SendGetRequest(token, "https://api.twitch.tv",
|
auto res = SendGetRequest(token, "https://api.twitch.tv",
|
||||||
"/helix/users", {{"login", _name}});
|
"/helix/users", {{"login", _name}}, true);
|
||||||
|
|
||||||
if (res.status == 400) {
|
if (res.status == 400) {
|
||||||
userIDCache[_name] = "invalid";
|
userIDCache[_name] = "invalid";
|
||||||
|
|||||||
@@ -196,12 +196,12 @@ std::string EventSub::AddEventSubscribtion(std::shared_ptr<TwitchToken> token,
|
|||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(eventSub->_subscriptionMtx);
|
std::unique_lock<std::mutex> lock(eventSub->_subscriptionMtx);
|
||||||
if (!eventSub->_connected) {
|
if (!eventSub->_connected) {
|
||||||
std::thread t([eventSub]() { eventSub->Connect(); });
|
|
||||||
t.detach();
|
|
||||||
vblog(LOG_INFO, "Twitch EventSub connect started for %s",
|
vblog(LOG_INFO, "Twitch EventSub connect started for %s",
|
||||||
token->GetName().c_str());
|
token->GetName().c_str());
|
||||||
|
lock.unlock();
|
||||||
|
eventSub->Connect();
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
|
|
||||||
#include <log-helper.hpp>
|
#include <log-helper.hpp>
|
||||||
#include <layout-helpers.hpp>
|
#include <layout-helpers.hpp>
|
||||||
|
#include <ui-helpers.hpp>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
@@ -21,6 +22,18 @@ void MacroActionTwitch::ResolveVariablesToFixedValues()
|
|||||||
_announcementMessage.ResolveVariables();
|
_announcementMessage.ResolveVariables();
|
||||||
_channel.ResolveVariables();
|
_channel.ResolveVariables();
|
||||||
_chatMessage.ResolveVariables();
|
_chatMessage.ResolveVariables();
|
||||||
|
_userLogin.ResolveVariables();
|
||||||
|
_userId.ResolveVariables();
|
||||||
|
_useVariableForRewardSelection = false;
|
||||||
|
auto token = _token.lock();
|
||||||
|
if (token) {
|
||||||
|
ResolveVariableSelectionToRewardId(token);
|
||||||
|
_pointsReward.title = _lastResolvedRewardTitle;
|
||||||
|
_pointsReward.id = _lastResolvedRewardId;
|
||||||
|
} else {
|
||||||
|
_pointsReward.id = "";
|
||||||
|
_pointsReward.id = "";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<MacroAction> MacroActionTwitch::Create(Macro *m)
|
std::shared_ptr<MacroAction> MacroActionTwitch::Create(Macro *m)
|
||||||
@@ -58,7 +71,11 @@ const static std::map<MacroActionTwitch::Action, std::string> actionTypes = {
|
|||||||
{MacroActionTwitch::Action::CHAT_EMOTE_ONLY_DISABLE,
|
{MacroActionTwitch::Action::CHAT_EMOTE_ONLY_DISABLE,
|
||||||
"AdvSceneSwitcher.action.twitch.type.chat.emoteOnly.disable"},
|
"AdvSceneSwitcher.action.twitch.type.chat.emoteOnly.disable"},
|
||||||
{MacroActionTwitch::Action::SEND_CHAT_MESSAGE,
|
{MacroActionTwitch::Action::SEND_CHAT_MESSAGE,
|
||||||
"AdvSceneSwitcher.action.twitch.type.sendChatMessage"},
|
"AdvSceneSwitcher.action.twitch.type.chat.sendMessage"},
|
||||||
|
{MacroActionTwitch::Action::USER_GET_INFO,
|
||||||
|
"AdvSceneSwitcher.action.twitch.type.user.getInfo"},
|
||||||
|
{MacroActionTwitch::Action::POINTS_REWARD_GET_INFO,
|
||||||
|
"AdvSceneSwitcher.action.twitch.type.reward.getInfo"},
|
||||||
};
|
};
|
||||||
|
|
||||||
const static std::map<MacroActionTwitch::AnnouncementColor, std::string>
|
const static std::map<MacroActionTwitch::AnnouncementColor, std::string>
|
||||||
@@ -264,6 +281,228 @@ void MacroActionTwitch::SendChatMessage(
|
|||||||
_chatConnection->SendChatMessage(_chatMessage);
|
_chatConnection->SendChatMessage(_chatMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionTwitch::GetUserInfo(const std::shared_ptr<TwitchToken> &token)
|
||||||
|
{
|
||||||
|
httplib::Params params;
|
||||||
|
switch (_userInfoQueryType) {
|
||||||
|
case UserInfoQueryType::ID:
|
||||||
|
params.insert({"id", std::to_string(_userId)});
|
||||||
|
break;
|
||||||
|
case UserInfoQueryType::LOGIN:
|
||||||
|
params.insert({"login", _userLogin});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
auto result = SendGetRequest(*token, "https://api.twitch.tv",
|
||||||
|
"/helix/users", params, true);
|
||||||
|
|
||||||
|
if (result.status != 200) {
|
||||||
|
blog(LOG_INFO, "Failed get user info! (%d)\n", result.status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSDataArrayAutoRelease array = obs_data_get_array(result.data, "data");
|
||||||
|
size_t count = obs_data_array_count(array);
|
||||||
|
if (count == 0) {
|
||||||
|
blog(LOG_WARNING, "%s did not return any data!", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSDataAutoRelease data = obs_data_array_item(array, 0);
|
||||||
|
SetJsonTempVars(data, [this](const char *id, const char *value) {
|
||||||
|
SetTempVarValue(id, value);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroActionTwitch::ResolveVariableSelectionToRewardId(
|
||||||
|
const std::shared_ptr<TwitchToken> &token)
|
||||||
|
{
|
||||||
|
if (!token) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto variable = _rewardVariable.lock();
|
||||||
|
if (!variable) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto rewardTitle = variable->Value();
|
||||||
|
if (rewardTitle.empty()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_lastResolvedRewardTitle == rewardTitle) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto rewards = GetPointsRewardsForChannel(token, _channel);
|
||||||
|
if (!rewards) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &reward : *rewards) {
|
||||||
|
if (reward.title == rewardTitle) {
|
||||||
|
_lastResolvedRewardId = reward.id;
|
||||||
|
_lastResolvedRewardTitle = reward.title;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionTwitch::GetRewardInfo(const std::shared_ptr<TwitchToken> &token)
|
||||||
|
{
|
||||||
|
if (_useVariableForRewardSelection &&
|
||||||
|
!ResolveVariableSelectionToRewardId(token)) {
|
||||||
|
if (VerboseLoggingEnabled()) {
|
||||||
|
auto variable = _rewardVariable.lock();
|
||||||
|
if (!variable) {
|
||||||
|
blog(LOG_WARNING,
|
||||||
|
"failed to resolve variable reward name to reward id (invalid selection)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
blog(LOG_WARNING,
|
||||||
|
"failed to resolve variable reward name '%s' to reward id",
|
||||||
|
variable->Value().c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
httplib::Params params = {
|
||||||
|
{"broadcaster_id", token->GetUserID()},
|
||||||
|
{"id", _useVariableForRewardSelection ? _lastResolvedRewardId
|
||||||
|
: _pointsReward.id},
|
||||||
|
};
|
||||||
|
auto result = SendGetRequest(*token, "https://api.twitch.tv",
|
||||||
|
"/helix/channel_points/custom_rewards",
|
||||||
|
params, true);
|
||||||
|
|
||||||
|
if (result.status != 200) {
|
||||||
|
blog(LOG_INFO, "Failed get reward info! (%d)\n", result.status);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSDataArrayAutoRelease array = obs_data_get_array(result.data, "data");
|
||||||
|
size_t count = obs_data_array_count(array);
|
||||||
|
if (count == 0) {
|
||||||
|
blog(LOG_WARNING, "%s did not return any data!", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OBSDataAutoRelease data = obs_data_array_item(array, 0);
|
||||||
|
|
||||||
|
SetJsonTempVars(data, [this](const char *id, const char *value) {
|
||||||
|
SetTempVarValue(id, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
OBSDataAutoRelease image = obs_data_get_obj(data, "image");
|
||||||
|
SetTempVarValue("image.url_4x", obs_data_get_string(image, "url_4x"));
|
||||||
|
|
||||||
|
OBSDataAutoRelease default_image =
|
||||||
|
obs_data_get_obj(data, "default_image");
|
||||||
|
SetTempVarValue("default_image.url_4x",
|
||||||
|
obs_data_get_string(default_image, "url_4x"));
|
||||||
|
|
||||||
|
OBSDataAutoRelease max_per_stream_setting =
|
||||||
|
obs_data_get_obj(data, "max_per_stream_setting");
|
||||||
|
SetTempVarValue("max_per_stream.is_enabled",
|
||||||
|
obs_data_get_bool(max_per_stream_setting,
|
||||||
|
"is_enabled"));
|
||||||
|
SetTempVarValue("max_per_stream.max_per_stream",
|
||||||
|
std::to_string(obs_data_get_int(max_per_stream_setting,
|
||||||
|
"max_per_stream")));
|
||||||
|
|
||||||
|
OBSDataAutoRelease max_per_user_per_stream_setting =
|
||||||
|
obs_data_get_obj(data, "max_per_user_per_stream_setting");
|
||||||
|
SetTempVarValue("max_per_user_per_stream.is_enabled",
|
||||||
|
obs_data_get_bool(max_per_user_per_stream_setting,
|
||||||
|
"is_enabled"));
|
||||||
|
SetTempVarValue(
|
||||||
|
"max_per_user_per_stream.max_per_user_per_stream",
|
||||||
|
std::to_string(obs_data_get_int(max_per_user_per_stream_setting,
|
||||||
|
"max_per_user_per_stream")));
|
||||||
|
|
||||||
|
OBSDataAutoRelease global_cooldown_setting =
|
||||||
|
obs_data_get_obj(data, "global_cooldown_setting");
|
||||||
|
SetTempVarValue("global_cooldown.is_enabled",
|
||||||
|
obs_data_get_bool(global_cooldown_setting,
|
||||||
|
"is_enabled"));
|
||||||
|
SetTempVarValue(
|
||||||
|
"max_per_user_per_stream.global_cooldown_seconds",
|
||||||
|
std::to_string(obs_data_get_int(max_per_user_per_stream_setting,
|
||||||
|
"global_cooldown_seconds")));
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string tryTranslate(const std::string &testString)
|
||||||
|
{
|
||||||
|
auto translated = obs_module_text(testString.c_str());
|
||||||
|
if (testString != translated) {
|
||||||
|
return translated;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionTwitch::SetupTempVars()
|
||||||
|
{
|
||||||
|
MacroAction::SetupTempVars();
|
||||||
|
|
||||||
|
auto setupTempVarHelper = [&](const std::string &id,
|
||||||
|
const std::string &extra = "") {
|
||||||
|
std::string name = tryTranslate(
|
||||||
|
"AdvSceneSwitcher.tempVar.twitch." + id + extra);
|
||||||
|
std::string description =
|
||||||
|
tryTranslate("AdvSceneSwitcher.tempVar.twitch." + id +
|
||||||
|
extra + ".description");
|
||||||
|
AddTempvar(id, name.empty() ? id : name, description);
|
||||||
|
};
|
||||||
|
|
||||||
|
switch (_action) {
|
||||||
|
case Action::POINTS_REWARD_GET_INFO:
|
||||||
|
setupTempVarHelper("title", ".reward");
|
||||||
|
setupTempVarHelper("prompt", ".reward");
|
||||||
|
setupTempVarHelper("cost", ".reward");
|
||||||
|
setupTempVarHelper("background_color", ".reward");
|
||||||
|
setupTempVarHelper("is_enabled", ".reward");
|
||||||
|
setupTempVarHelper("is_user_input_required", ".reward");
|
||||||
|
setupTempVarHelper("is_paused", ".reward");
|
||||||
|
setupTempVarHelper("is_in_stock", ".reward");
|
||||||
|
setupTempVarHelper("should_redemptions_skip_request_queue",
|
||||||
|
".reward");
|
||||||
|
setupTempVarHelper("redemptions_redeemed_current_stream",
|
||||||
|
".reward");
|
||||||
|
setupTempVarHelper("cooldown_expires_at", ".reward");
|
||||||
|
setupTempVarHelper("max_per_stream.is_enabled", ".reward");
|
||||||
|
setupTempVarHelper("max_per_stream.max_per_stream", ".reward");
|
||||||
|
setupTempVarHelper("max_per_user_per_stream.is_enabled",
|
||||||
|
".reward");
|
||||||
|
setupTempVarHelper(
|
||||||
|
"max_per_user_per_stream.max_per_user_per_stream",
|
||||||
|
".reward");
|
||||||
|
setupTempVarHelper("global_cooldown.is_enabled", ".reward");
|
||||||
|
setupTempVarHelper("global_cooldown.global_cooldown_seconds",
|
||||||
|
".reward");
|
||||||
|
setupTempVarHelper("image.url_4x", ".reward");
|
||||||
|
setupTempVarHelper("default_image.url_4x", ".reward");
|
||||||
|
break;
|
||||||
|
case Action::USER_GET_INFO:
|
||||||
|
setupTempVarHelper("id", ".user.getInfo");
|
||||||
|
setupTempVarHelper("login", ".user.getInfo");
|
||||||
|
setupTempVarHelper("display_name", ".user.getInfo");
|
||||||
|
setupTempVarHelper("type", ".user.getInfo");
|
||||||
|
setupTempVarHelper("broadcaster_type", ".user.getInfo");
|
||||||
|
setupTempVarHelper("description", ".user.getInfo");
|
||||||
|
setupTempVarHelper("profile_image_url", ".user.getInfo");
|
||||||
|
setupTempVarHelper("offline_image_url", ".user.getInfo");
|
||||||
|
setupTempVarHelper("created_at", ".user.getInfo");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool MacroActionTwitch::PerformAction()
|
bool MacroActionTwitch::PerformAction()
|
||||||
{
|
{
|
||||||
auto token = _token.lock();
|
auto token = _token.lock();
|
||||||
@@ -298,9 +537,16 @@ bool MacroActionTwitch::PerformAction()
|
|||||||
break;
|
break;
|
||||||
case Action::CHAT_EMOTE_ONLY_DISABLE:
|
case Action::CHAT_EMOTE_ONLY_DISABLE:
|
||||||
SetChatEmoteOnlyMode(token, false);
|
SetChatEmoteOnlyMode(token, false);
|
||||||
|
break;
|
||||||
case MacroActionTwitch::Action::SEND_CHAT_MESSAGE:
|
case MacroActionTwitch::Action::SEND_CHAT_MESSAGE:
|
||||||
SendChatMessage(token);
|
SendChatMessage(token);
|
||||||
break;
|
break;
|
||||||
|
case MacroActionTwitch::Action::USER_GET_INFO:
|
||||||
|
GetUserInfo(token);
|
||||||
|
break;
|
||||||
|
case MacroActionTwitch::Action::POINTS_REWARD_GET_INFO:
|
||||||
|
GetRewardInfo(token);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -338,6 +584,15 @@ bool MacroActionTwitch::Save(obs_data_t *obj) const
|
|||||||
static_cast<int>(_announcementColor));
|
static_cast<int>(_announcementColor));
|
||||||
_channel.Save(obj);
|
_channel.Save(obj);
|
||||||
_chatMessage.Save(obj, "chatMessage");
|
_chatMessage.Save(obj, "chatMessage");
|
||||||
|
obs_data_set_int(obj, "userInfoQueryType",
|
||||||
|
static_cast<int>(_userInfoQueryType));
|
||||||
|
_userLogin.Save(obj, "userLogin");
|
||||||
|
_userId.Save(obj, "userId");
|
||||||
|
_pointsReward.Save(obj);
|
||||||
|
obs_data_set_string(obj, "rewardVariable",
|
||||||
|
GetWeakVariableName(_rewardVariable).c_str());
|
||||||
|
obs_data_set_bool(obj, "useVariableForRewardSelection",
|
||||||
|
_useVariableForRewardSelection);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -357,6 +612,16 @@ bool MacroActionTwitch::Load(obs_data_t *obj)
|
|||||||
obs_data_get_int(obj, "announcementColor"));
|
obs_data_get_int(obj, "announcementColor"));
|
||||||
_channel.Load(obj);
|
_channel.Load(obj);
|
||||||
_chatMessage.Load(obj, "chatMessage");
|
_chatMessage.Load(obj, "chatMessage");
|
||||||
|
_userInfoQueryType = static_cast<UserInfoQueryType>(
|
||||||
|
obs_data_get_int(obj, "userInfoQueryType"));
|
||||||
|
_userLogin.Load(obj, "userLogin");
|
||||||
|
_userId.Load(obj, "userId");
|
||||||
|
_pointsReward.Load(obj);
|
||||||
|
_rewardVariable = GetWeakVariableByName(
|
||||||
|
obs_data_get_string(obj, "rewardVariable"));
|
||||||
|
_useVariableForRewardSelection =
|
||||||
|
obs_data_get_bool(obj, "useVariableForRewardSelection");
|
||||||
|
|
||||||
SetAction(static_cast<Action>(obs_data_get_int(obj, "action")));
|
SetAction(static_cast<Action>(obs_data_get_int(obj, "action")));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -366,117 +631,139 @@ void MacroActionTwitch::SetAction(Action action)
|
|||||||
{
|
{
|
||||||
_action = action;
|
_action = action;
|
||||||
ResetChatConnection();
|
ResetChatConnection();
|
||||||
|
SetupTempVars();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroActionTwitch::ActionIsSupportedByToken()
|
bool MacroActionTwitch::ActionIsSupportedByToken()
|
||||||
{
|
{
|
||||||
static const std::unordered_map<Action, TokenOption> requiredOption = {
|
static const std::unordered_map<Action, std::vector<TokenOption>>
|
||||||
{Action::CHANNEL_INFO_TITLE_SET, {"channel:manage:broadcast"}},
|
requiredOption = {
|
||||||
{Action::CHANNEL_INFO_CATEGORY_SET,
|
{Action::CHANNEL_INFO_TITLE_SET,
|
||||||
{"channel:manage:broadcast"}},
|
{{"channel:manage:broadcast"}}},
|
||||||
{Action::CHANNEL_INFO_LANGUAGE_SET,
|
{Action::CHANNEL_INFO_CATEGORY_SET,
|
||||||
{"channel:manage:broadcast"}},
|
{{"channel:manage:broadcast"}}},
|
||||||
{Action::CHANNEL_INFO_DELAY_SET, {"channel:manage:broadcast"}},
|
{Action::CHANNEL_INFO_LANGUAGE_SET,
|
||||||
{Action::CHANNEL_INFO_BRANDED_CONTENT_ENABLE,
|
{{"channel:manage:broadcast"}}},
|
||||||
{"channel:manage:broadcast"}},
|
{Action::CHANNEL_INFO_DELAY_SET,
|
||||||
{Action::CHANNEL_INFO_BRANDED_CONTENT_DISABLE,
|
{{"channel:manage:broadcast"}}},
|
||||||
{"channel:manage:broadcast"}},
|
{Action::CHANNEL_INFO_BRANDED_CONTENT_ENABLE,
|
||||||
{Action::RAID_START, {"channel:manage:raids"}},
|
{{"channel:manage:broadcast"}}},
|
||||||
{Action::RAID_END, {"channel:manage:raids"}},
|
{Action::CHANNEL_INFO_BRANDED_CONTENT_DISABLE,
|
||||||
{Action::SHOUTOUT_SEND, {"moderator:manage:shoutouts"}},
|
{{"channel:manage:broadcast"}}},
|
||||||
{Action::POLL_END, {"channel:manage:polls"}},
|
{Action::RAID_START, {{"channel:manage:raids"}}},
|
||||||
{Action::PREDICTION_END, {"channel:manage:predictions"}},
|
{Action::RAID_END, {{"channel:manage:raids"}}},
|
||||||
{Action::SHIELD_MODE_START, {"moderator:manage:shield_mode"}},
|
{Action::SHOUTOUT_SEND,
|
||||||
{Action::SHIELD_MODE_END, {"moderator:manage:shield_mode"}},
|
{{"moderator:manage:shoutouts"}}},
|
||||||
{Action::POINTS_REWARD_ENABLE, {"channel:manage:redemptions"}},
|
{Action::POLL_END, {{"channel:manage:polls"}}},
|
||||||
{Action::POINTS_REWARD_DISABLE, {"channel:manage:redemptions"}},
|
{Action::PREDICTION_END,
|
||||||
{Action::POINTS_REWARD_PAUSE, {"channel:manage:redemptions"}},
|
{{"channel:manage:predictions"}}},
|
||||||
{Action::POINTS_REWARD_UNPAUSE, {"channel:manage:redemptions"}},
|
{Action::SHIELD_MODE_START,
|
||||||
{Action::POINTS_REWARD_TITLE_SET,
|
{{"moderator:manage:shield_mode"}}},
|
||||||
{"channel:manage:redemptions"}},
|
{Action::SHIELD_MODE_END,
|
||||||
{Action::POINTS_REWARD_PROMPT_SET,
|
{{"moderator:manage:shield_mode"}}},
|
||||||
{"channel:manage:redemptions"}},
|
{Action::POINTS_REWARD_ENABLE,
|
||||||
{Action::POINTS_REWARD_COST_SET,
|
{{"channel:manage:redemptions"}}},
|
||||||
{"channel:manage:redemptions"}},
|
{Action::POINTS_REWARD_DISABLE,
|
||||||
{Action::POINTS_REWARD_USER_INPUT_REQUIRE,
|
{{"channel:manage:redemptions"}}},
|
||||||
{"channel:manage:redemptions"}},
|
{Action::POINTS_REWARD_PAUSE,
|
||||||
{Action::POINTS_REWARD_USER_INPUT_UNREQUIRE,
|
{{"channel:manage:redemptions"}}},
|
||||||
{"channel:manage:redemptions"}},
|
{Action::POINTS_REWARD_UNPAUSE,
|
||||||
{Action::POINTS_REWARD_COOLDOWN_ENABLE,
|
{{"channel:manage:redemptions"}}},
|
||||||
{"channel:manage:redemptions"}},
|
{Action::POINTS_REWARD_TITLE_SET,
|
||||||
{Action::POINTS_REWARD_COOLDOWN_DISABLE,
|
{{"channel:manage:redemptions"}}},
|
||||||
{"channel:manage:redemptions"}},
|
{Action::POINTS_REWARD_PROMPT_SET,
|
||||||
{Action::POINTS_REWARD_QUEUE_SKIP_ENABLE,
|
{{"channel:manage:redemptions"}}},
|
||||||
{"channel:manage:redemptions"}},
|
{Action::POINTS_REWARD_COST_SET,
|
||||||
{Action::POINTS_REWARD_QUEUE_SKIP_DISABLE,
|
{{"channel:manage:redemptions"}}},
|
||||||
{"channel:manage:redemptions"}},
|
{Action::POINTS_REWARD_USER_INPUT_REQUIRE,
|
||||||
{Action::POINTS_REWARD_MAX_PER_STREAM_ENABLE,
|
{{"channel:manage:redemptions"}}},
|
||||||
{"channel:manage:redemptions"}},
|
{Action::POINTS_REWARD_USER_INPUT_UNREQUIRE,
|
||||||
{Action::POINTS_REWARD_MAX_PER_STREAM_DISABLE,
|
{{"channel:manage:redemptions"}}},
|
||||||
{"channel:manage:redemptions"}},
|
{Action::POINTS_REWARD_COOLDOWN_ENABLE,
|
||||||
{Action::POINTS_REWARD_MAX_PER_USER_ENABLE,
|
{{"channel:manage:redemptions"}}},
|
||||||
{"channel:manage:redemptions"}},
|
{Action::POINTS_REWARD_COOLDOWN_DISABLE,
|
||||||
{Action::POINTS_REWARD_MAX_PER_USER_DISABLE,
|
{{"channel:manage:redemptions"}}},
|
||||||
{"channel:manage:redemptions"}},
|
{Action::POINTS_REWARD_QUEUE_SKIP_ENABLE,
|
||||||
{Action::POINTS_REWARD_DELETE, {"channel:manage:redemptions"}},
|
{{"channel:manage:redemptions"}}},
|
||||||
{Action::POINTS_REWARD_REDEMPTION_CANCEL,
|
{Action::POINTS_REWARD_QUEUE_SKIP_DISABLE,
|
||||||
{"channel:manage:redemptions"}},
|
{{"channel:manage:redemptions"}}},
|
||||||
{Action::POINTS_REWARD_REDEMPTION_FULFILL,
|
{Action::POINTS_REWARD_MAX_PER_STREAM_ENABLE,
|
||||||
{"channel:manage:redemptions"}},
|
{{"channel:manage:redemptions"}}},
|
||||||
{Action::USER_BAN, {"moderator:manage:banned_users"}},
|
{Action::POINTS_REWARD_MAX_PER_STREAM_DISABLE,
|
||||||
{Action::USER_UNBAN, {"moderator:manage:banned_users"}},
|
{{"channel:manage:redemptions"}}},
|
||||||
{Action::USER_BLOCK, {"user:manage:blocked_users"}},
|
{Action::POINTS_REWARD_MAX_PER_USER_ENABLE,
|
||||||
{Action::USER_UNBLOCK, {"user:manage:blocked_users"}},
|
{{"channel:manage:redemptions"}}},
|
||||||
{Action::USER_MODERATOR_ADD, {"channel:manage:moderators"}},
|
{Action::POINTS_REWARD_MAX_PER_USER_DISABLE,
|
||||||
{Action::USER_MODERATOR_DELETE, {"channel:manage:moderators"}},
|
{{"channel:manage:redemptions"}}},
|
||||||
{Action::USER_VIP_ADD, {"channel:manage:vips"}},
|
{Action::POINTS_REWARD_DELETE,
|
||||||
{Action::USER_VIP_DELETE, {"channel:manage:vips"}},
|
{{"channel:manage:redemptions"}}},
|
||||||
{Action::COMMERCIAL_START, {"channel:edit:commercial"}},
|
{Action::POINTS_REWARD_REDEMPTION_CANCEL,
|
||||||
{Action::COMMERCIAL_SNOOZE, {"channel:manage:ads"}},
|
{{"channel:manage:redemptions"}}},
|
||||||
{Action::MARKER_CREATE, {"channel:manage:broadcast"}},
|
{Action::POINTS_REWARD_REDEMPTION_FULFILL,
|
||||||
{Action::CLIP_CREATE, {"clips:edit"}},
|
{{"channel:manage:redemptions"}}},
|
||||||
{Action::CHAT_ANNOUNCEMENT_SEND,
|
{Action::USER_BAN, {{"moderator:manage:banned_users"}}},
|
||||||
{"moderator:manage:announcements"}},
|
{Action::USER_UNBAN,
|
||||||
{Action::CHAT_EMOTE_ONLY_ENABLE,
|
{{"moderator:manage:banned_users"}}},
|
||||||
{"moderator:manage:chat_settings"}},
|
{Action::USER_BLOCK, {{"user:manage:blocked_users"}}},
|
||||||
{Action::CHAT_EMOTE_ONLY_DISABLE,
|
{Action::USER_UNBLOCK, {{"user:manage:blocked_users"}}},
|
||||||
{"moderator:manage:chat_settings"}},
|
{Action::USER_MODERATOR_ADD,
|
||||||
{Action::CHAT_FOLLOWER_ONLY_ENABLE,
|
{{"channel:manage:moderators"}}},
|
||||||
{"moderator:manage:chat_settings"}},
|
{Action::USER_MODERATOR_DELETE,
|
||||||
{Action::CHAT_FOLLOWER_ONLY_DISABLE,
|
{{"channel:manage:moderators"}}},
|
||||||
{"moderator:manage:chat_settings"}},
|
{Action::USER_VIP_ADD, {{"channel:manage:vips"}}},
|
||||||
{Action::CHAT_SUBSCRIBER_ONLY_ENABLE,
|
{Action::USER_VIP_DELETE, {{"channel:manage:vips"}}},
|
||||||
{"moderator:manage:chat_settings"}},
|
{Action::COMMERCIAL_START,
|
||||||
{Action::CHAT_SUBSCRIBER_ONLY_DISABLE,
|
{{"channel:edit:commercial"}}},
|
||||||
{"moderator:manage:chat_settings"}},
|
{Action::COMMERCIAL_SNOOZE, {{"channel:manage:ads"}}},
|
||||||
{Action::CHAT_SLOW_MODE_ENABLE,
|
{Action::MARKER_CREATE, {{"channel:manage:broadcast"}}},
|
||||||
{"moderator:manage:chat_settings"}},
|
{Action::CLIP_CREATE, {{"clips:edit"}}},
|
||||||
{Action::CHAT_SLOW_MODE_DISABLE,
|
{Action::CHAT_ANNOUNCEMENT_SEND,
|
||||||
{"moderator:manage:chat_settings"}},
|
{{"moderator:manage:announcements"}}},
|
||||||
{Action::CHAT_NON_MODERATOR_DELAY_ENABLE,
|
{Action::CHAT_EMOTE_ONLY_ENABLE,
|
||||||
{"moderator:manage:chat_settings"}},
|
{{"moderator:manage:chat_settings"}}},
|
||||||
{Action::CHAT_NON_MODERATOR_DELAY_DISABLE,
|
{Action::CHAT_EMOTE_ONLY_DISABLE,
|
||||||
{"moderator:manage:chat_settings"}},
|
{{"moderator:manage:chat_settings"}}},
|
||||||
{Action::CHAT_UNIQUE_MODE_ENABLE,
|
{Action::CHAT_FOLLOWER_ONLY_ENABLE,
|
||||||
{"moderator:manage:chat_settings"}},
|
{{"moderator:manage:chat_settings"}}},
|
||||||
{Action::CHAT_UNIQUE_MODE_DISABLE,
|
{Action::CHAT_FOLLOWER_ONLY_DISABLE,
|
||||||
{"moderator:manage:chat_settings"}},
|
{{"moderator:manage:chat_settings"}}},
|
||||||
{Action::WHISPER_SEND, {"user:manage:whispers"}},
|
{Action::CHAT_SUBSCRIBER_ONLY_ENABLE,
|
||||||
{Action::SEND_CHAT_MESSAGE, {"chat:edit"}},
|
{{"moderator:manage:chat_settings"}}},
|
||||||
};
|
{Action::CHAT_SUBSCRIBER_ONLY_DISABLE,
|
||||||
|
{{"moderator:manage:chat_settings"}}},
|
||||||
|
{Action::CHAT_SLOW_MODE_ENABLE,
|
||||||
|
{{"moderator:manage:chat_settings"}}},
|
||||||
|
{Action::CHAT_SLOW_MODE_DISABLE,
|
||||||
|
{{"moderator:manage:chat_settings"}}},
|
||||||
|
{Action::CHAT_NON_MODERATOR_DELAY_ENABLE,
|
||||||
|
{{"moderator:manage:chat_settings"}}},
|
||||||
|
{Action::CHAT_NON_MODERATOR_DELAY_DISABLE,
|
||||||
|
{{"moderator:manage:chat_settings"}}},
|
||||||
|
{Action::CHAT_UNIQUE_MODE_ENABLE,
|
||||||
|
{{"moderator:manage:chat_settings"}}},
|
||||||
|
{Action::CHAT_UNIQUE_MODE_DISABLE,
|
||||||
|
{{"moderator:manage:chat_settings"}}},
|
||||||
|
{Action::WHISPER_SEND, {{"user:manage:whispers"}}},
|
||||||
|
{Action::SEND_CHAT_MESSAGE, {{"chat:edit"}}},
|
||||||
|
{Action::USER_GET_INFO, {}},
|
||||||
|
{Action::POINTS_REWARD_GET_INFO,
|
||||||
|
{{"channel:read:redemptions"},
|
||||||
|
{"channel:manage:redemptions"}}}};
|
||||||
|
|
||||||
auto token = _token.lock();
|
auto token = _token.lock();
|
||||||
if (!token) {
|
if (!token) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto option = requiredOption.find(_action);
|
auto it = requiredOption.find(_action);
|
||||||
assert(option != requiredOption.end());
|
assert(it != requiredOption.end());
|
||||||
if (option == requiredOption.end()) {
|
if (it == requiredOption.end()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return token->OptionIsEnabled(option->second);
|
const auto &[_, options] = *it;
|
||||||
|
|
||||||
|
return token->AnyOptionIsEnabled(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionTwitch::ResetChatConnection()
|
void MacroActionTwitch::ResetChatConnection()
|
||||||
@@ -507,6 +794,18 @@ static inline void populateAnnouncementColorSelection(QComboBox *list)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void populateUserQueryInfoTypeSelection(QComboBox *list)
|
||||||
|
{
|
||||||
|
list->addItem(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.twitch.user.getInfo.queryType.id"),
|
||||||
|
static_cast<int>(MacroActionTwitch::UserInfoQueryType::ID));
|
||||||
|
list->addItem(
|
||||||
|
obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.twitch.user.getInfo.queryType.login"),
|
||||||
|
static_cast<int>(MacroActionTwitch::UserInfoQueryType::LOGIN));
|
||||||
|
}
|
||||||
|
|
||||||
MacroActionTwitchEdit::MacroActionTwitchEdit(
|
MacroActionTwitchEdit::MacroActionTwitchEdit(
|
||||||
QWidget *parent, std::shared_ptr<MacroActionTwitch> entryData)
|
QWidget *parent, std::shared_ptr<MacroActionTwitch> entryData)
|
||||||
: QWidget(parent),
|
: QWidget(parent),
|
||||||
@@ -523,7 +822,13 @@ MacroActionTwitchEdit::MacroActionTwitchEdit(
|
|||||||
_announcementMessage(new VariableTextEdit(this)),
|
_announcementMessage(new VariableTextEdit(this)),
|
||||||
_announcementColor(new QComboBox(this)),
|
_announcementColor(new QComboBox(this)),
|
||||||
_channel(new TwitchChannelSelection(this)),
|
_channel(new TwitchChannelSelection(this)),
|
||||||
_chatMessage(new VariableTextEdit(this))
|
_chatMessage(new VariableTextEdit(this)),
|
||||||
|
_userInfoQueryType(new QComboBox(this)),
|
||||||
|
_userLogin(new VariableLineEdit(this)),
|
||||||
|
_userId(new VariableSpinBox(this)),
|
||||||
|
_pointsReward(new TwitchPointsRewardWidget(this)),
|
||||||
|
_rewardVariable(new VariableSelection(this)),
|
||||||
|
_toggleRewardSelection(new QPushButton())
|
||||||
{
|
{
|
||||||
SetWidgetProperties();
|
SetWidgetProperties();
|
||||||
SetWidgetSignalConnections();
|
SetWidgetSignalConnections();
|
||||||
@@ -566,14 +871,11 @@ void MacroActionTwitchEdit::ActionChanged(int idx)
|
|||||||
|
|
||||||
void MacroActionTwitchEdit::TwitchTokenChanged(const QString &token)
|
void MacroActionTwitchEdit::TwitchTokenChanged(const QString &token)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_token = GetWeakTwitchTokenByQString(token);
|
_entryData->_token = GetWeakTwitchTokenByQString(token);
|
||||||
_category->SetToken(_entryData->_token);
|
_category->SetToken(_entryData->_token);
|
||||||
_channel->SetToken(_entryData->_token);
|
_channel->SetToken(_entryData->_token);
|
||||||
|
_pointsReward->SetToken(_entryData->_token);
|
||||||
_entryData->ResetChatConnection();
|
_entryData->ResetChatConnection();
|
||||||
|
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
@@ -618,62 +920,38 @@ void MacroActionTwitchEdit::CheckToken()
|
|||||||
|
|
||||||
void MacroActionTwitchEdit::StreamTitleChanged()
|
void MacroActionTwitchEdit::StreamTitleChanged()
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_streamTitle = _streamTitle->text().toStdString();
|
_entryData->_streamTitle = _streamTitle->text().toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionTwitchEdit::CategoreyChanged(const TwitchCategory &category)
|
void MacroActionTwitchEdit::CategoryChanged(const TwitchCategory &category)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_category = category;
|
_entryData->_category = category;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionTwitchEdit::MarkerDescriptionChanged()
|
void MacroActionTwitchEdit::MarkerDescriptionChanged()
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_markerDescription =
|
_entryData->_markerDescription =
|
||||||
_markerDescription->text().toStdString();
|
_markerDescription->text().toStdString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionTwitchEdit::ClipHasDelayChanged(int state)
|
void MacroActionTwitchEdit::ClipHasDelayChanged(int state)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_clipHasDelay = state;
|
_entryData->_clipHasDelay = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionTwitchEdit::DurationChanged(const Duration &duration)
|
void MacroActionTwitchEdit::DurationChanged(const Duration &duration)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_duration = duration;
|
_entryData->_duration = duration;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionTwitchEdit::AnnouncementMessageChanged()
|
void MacroActionTwitchEdit::AnnouncementMessageChanged()
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_announcementMessage =
|
_entryData->_announcementMessage =
|
||||||
_announcementMessage->toPlainText().toStdString();
|
_announcementMessage->toPlainText().toStdString();
|
||||||
|
|
||||||
@@ -683,11 +961,7 @@ void MacroActionTwitchEdit::AnnouncementMessageChanged()
|
|||||||
|
|
||||||
void MacroActionTwitchEdit::AnnouncementColorChanged(int index)
|
void MacroActionTwitchEdit::AnnouncementColorChanged(int index)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_announcementColor =
|
_entryData->_announcementColor =
|
||||||
static_cast<MacroActionTwitch::AnnouncementColor>(index);
|
static_cast<MacroActionTwitch::AnnouncementColor>(index);
|
||||||
}
|
}
|
||||||
@@ -708,6 +982,18 @@ void MacroActionTwitchEdit::SetWidgetProperties()
|
|||||||
|
|
||||||
populateActionSelection(_actions);
|
populateActionSelection(_actions);
|
||||||
populateAnnouncementColorSelection(_announcementColor);
|
populateAnnouncementColorSelection(_announcementColor);
|
||||||
|
populateUserQueryInfoTypeSelection(_userInfoQueryType);
|
||||||
|
|
||||||
|
_userId->setMaximum(999999999);
|
||||||
|
|
||||||
|
_toggleRewardSelection->setCheckable(true);
|
||||||
|
_toggleRewardSelection->setMaximumWidth(11);
|
||||||
|
SetButtonIcon(_toggleRewardSelection,
|
||||||
|
GetThemeTypeName() == "Light"
|
||||||
|
? ":/res/images/dots-vert.svg"
|
||||||
|
: "theme:Dark/dots-vert.svg");
|
||||||
|
_toggleRewardSelection->setToolTip(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.twitch.reward.toggleControl"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionTwitchEdit::SetWidgetSignalConnections()
|
void MacroActionTwitchEdit::SetWidgetSignalConnections()
|
||||||
@@ -721,8 +1007,8 @@ void MacroActionTwitchEdit::SetWidgetSignalConnections()
|
|||||||
QWidget::connect(_streamTitle, SIGNAL(editingFinished()), this,
|
QWidget::connect(_streamTitle, SIGNAL(editingFinished()), this,
|
||||||
SLOT(StreamTitleChanged()));
|
SLOT(StreamTitleChanged()));
|
||||||
QWidget::connect(_category,
|
QWidget::connect(_category,
|
||||||
SIGNAL(CategoreyChanged(const TwitchCategory &)), this,
|
SIGNAL(CategoryChanged(const TwitchCategory &)), this,
|
||||||
SLOT(CategoreyChanged(const TwitchCategory &)));
|
SLOT(CategoryChanged(const TwitchCategory &)));
|
||||||
QWidget::connect(_markerDescription, SIGNAL(editingFinished()), this,
|
QWidget::connect(_markerDescription, SIGNAL(editingFinished()), this,
|
||||||
SLOT(MarkerDescriptionChanged()));
|
SLOT(MarkerDescriptionChanged()));
|
||||||
QObject::connect(_clipHasDelay, SIGNAL(stateChanged(int)), this,
|
QObject::connect(_clipHasDelay, SIGNAL(stateChanged(int)), this,
|
||||||
@@ -738,6 +1024,23 @@ void MacroActionTwitchEdit::SetWidgetSignalConnections()
|
|||||||
SLOT(ChannelChanged(const TwitchChannel &)));
|
SLOT(ChannelChanged(const TwitchChannel &)));
|
||||||
QWidget::connect(_chatMessage, SIGNAL(textChanged()), this,
|
QWidget::connect(_chatMessage, SIGNAL(textChanged()), this,
|
||||||
SLOT(ChatMessageChanged()));
|
SLOT(ChatMessageChanged()));
|
||||||
|
QWidget::connect(_userInfoQueryType, SIGNAL(currentIndexChanged(int)),
|
||||||
|
this, SLOT(UserInfoQueryTypeChanged(int)));
|
||||||
|
QWidget::connect(_userLogin, SIGNAL(editingFinished()), this,
|
||||||
|
SLOT(UserLoginChanged()));
|
||||||
|
QWidget::connect(
|
||||||
|
_userId,
|
||||||
|
SIGNAL(NumberVariableChanged(const NumberVariable<int> &)),
|
||||||
|
this, SLOT(UserIdChanged(const NumberVariable<int> &)));
|
||||||
|
QWidget::connect(
|
||||||
|
_pointsReward,
|
||||||
|
SIGNAL(PointsRewardChanged(const TwitchPointsReward &)), this,
|
||||||
|
SLOT(PointsRewardChanged(const TwitchPointsReward &)));
|
||||||
|
QWidget::connect(_rewardVariable,
|
||||||
|
SIGNAL(SelectionChanged(const QString &)), this,
|
||||||
|
SLOT(RewardVariableChanged(const QString &)));
|
||||||
|
QWidget::connect(_toggleRewardSelection, SIGNAL(toggled(bool)), this,
|
||||||
|
SLOT(ToggleRewardSelection(bool)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionTwitchEdit::SetWidgetVisibility()
|
void MacroActionTwitchEdit::SetWidgetVisibility()
|
||||||
@@ -754,7 +1057,9 @@ void MacroActionTwitchEdit::SetWidgetVisibility()
|
|||||||
_entryData->GetAction() ==
|
_entryData->GetAction() ==
|
||||||
MacroActionTwitch::Action::RAID_END ||
|
MacroActionTwitch::Action::RAID_END ||
|
||||||
_entryData->GetAction() ==
|
_entryData->GetAction() ==
|
||||||
MacroActionTwitch::Action::SEND_CHAT_MESSAGE);
|
MacroActionTwitch::Action::SEND_CHAT_MESSAGE ||
|
||||||
|
_entryData->GetAction() ==
|
||||||
|
MacroActionTwitch::Action::POINTS_REWARD_GET_INFO);
|
||||||
_duration->setVisible(_entryData->GetAction() ==
|
_duration->setVisible(_entryData->GetAction() ==
|
||||||
MacroActionTwitch::Action::COMMERCIAL_START);
|
MacroActionTwitch::Action::COMMERCIAL_START);
|
||||||
_markerDescription->setVisible(
|
_markerDescription->setVisible(
|
||||||
@@ -770,6 +1075,29 @@ void MacroActionTwitchEdit::SetWidgetVisibility()
|
|||||||
MacroActionTwitch::Action::CHAT_ANNOUNCEMENT_SEND);
|
MacroActionTwitch::Action::CHAT_ANNOUNCEMENT_SEND);
|
||||||
_chatMessage->setVisible(_entryData->GetAction() ==
|
_chatMessage->setVisible(_entryData->GetAction() ==
|
||||||
MacroActionTwitch::Action::SEND_CHAT_MESSAGE);
|
MacroActionTwitch::Action::SEND_CHAT_MESSAGE);
|
||||||
|
_userInfoQueryType->setVisible(
|
||||||
|
_entryData->GetAction() ==
|
||||||
|
MacroActionTwitch::Action::USER_GET_INFO);
|
||||||
|
_userLogin->setVisible(
|
||||||
|
_entryData->GetAction() ==
|
||||||
|
MacroActionTwitch::Action::USER_GET_INFO &&
|
||||||
|
_entryData->_userInfoQueryType ==
|
||||||
|
MacroActionTwitch::UserInfoQueryType::LOGIN);
|
||||||
|
_userId->setVisible(_entryData->GetAction() ==
|
||||||
|
MacroActionTwitch::Action::USER_GET_INFO &&
|
||||||
|
_entryData->_userInfoQueryType ==
|
||||||
|
MacroActionTwitch::UserInfoQueryType::ID);
|
||||||
|
_pointsReward->setVisible(
|
||||||
|
_entryData->GetAction() ==
|
||||||
|
MacroActionTwitch::Action::POINTS_REWARD_GET_INFO &&
|
||||||
|
!_entryData->_useVariableForRewardSelection);
|
||||||
|
_rewardVariable->setVisible(
|
||||||
|
_entryData->GetAction() ==
|
||||||
|
MacroActionTwitch::Action::POINTS_REWARD_GET_INFO &&
|
||||||
|
_entryData->_useVariableForRewardSelection);
|
||||||
|
_toggleRewardSelection->setVisible(
|
||||||
|
_entryData->GetAction() ==
|
||||||
|
MacroActionTwitch::Action::POINTS_REWARD_GET_INFO);
|
||||||
|
|
||||||
if (_entryData->GetAction() ==
|
if (_entryData->GetAction() ==
|
||||||
MacroActionTwitch::Action::CHANNEL_INFO_TITLE_SET ||
|
MacroActionTwitch::Action::CHANNEL_INFO_TITLE_SET ||
|
||||||
@@ -788,46 +1116,104 @@ void MacroActionTwitchEdit::SetWidgetVisibility()
|
|||||||
|
|
||||||
void MacroActionTwitchEdit::ChannelChanged(const TwitchChannel &channel)
|
void MacroActionTwitchEdit::ChannelChanged(const TwitchChannel &channel)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_channel = channel;
|
_entryData->_channel = channel;
|
||||||
|
_pointsReward->SetChannel(channel);
|
||||||
_entryData->ResetChatConnection();
|
_entryData->ResetChatConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroActionTwitchEdit::ChatMessageChanged()
|
void MacroActionTwitchEdit::ChatMessageChanged()
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
GUARD_LOADING_AND_LOCK();
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto lock = LockContext();
|
|
||||||
_entryData->_chatMessage = _chatMessage->toPlainText().toStdString();
|
_entryData->_chatMessage = _chatMessage->toPlainText().toStdString();
|
||||||
|
|
||||||
adjustSize();
|
adjustSize();
|
||||||
updateGeometry();
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MacroActionTwitchEdit::UserInfoQueryTypeChanged(int idx)
|
||||||
|
{
|
||||||
|
GUARD_LOADING_AND_LOCK();
|
||||||
|
_entryData->_userInfoQueryType =
|
||||||
|
static_cast<MacroActionTwitch::UserInfoQueryType>(
|
||||||
|
_userInfoQueryType->itemData(idx).toInt());
|
||||||
|
SetWidgetVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionTwitchEdit::UserLoginChanged()
|
||||||
|
{
|
||||||
|
GUARD_LOADING_AND_LOCK();
|
||||||
|
_entryData->_userLogin = _userLogin->text().toStdString();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionTwitchEdit::RewardVariableChanged(const QString &text)
|
||||||
|
{
|
||||||
|
GUARD_LOADING_AND_LOCK()
|
||||||
|
_entryData->_rewardVariable = GetWeakVariableByQString(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionTwitchEdit::ToggleRewardSelection(bool)
|
||||||
|
{
|
||||||
|
GUARD_LOADING_AND_LOCK();
|
||||||
|
_entryData->_useVariableForRewardSelection =
|
||||||
|
!_entryData->_useVariableForRewardSelection;
|
||||||
|
SetWidgetVisibility();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionTwitchEdit::UserIdChanged(const NumberVariable<int> &value)
|
||||||
|
{
|
||||||
|
GUARD_LOADING_AND_LOCK();
|
||||||
|
_entryData->_userId = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MacroActionTwitchEdit::PointsRewardChanged(const TwitchPointsReward &reward)
|
||||||
|
{
|
||||||
|
GUARD_LOADING_AND_LOCK();
|
||||||
|
_entryData->_pointsReward = reward;
|
||||||
|
}
|
||||||
|
|
||||||
void MacroActionTwitchEdit::SetWidgetLayout()
|
void MacroActionTwitchEdit::SetWidgetLayout()
|
||||||
{
|
{
|
||||||
const std::vector<QWidget *> widgets{
|
const std::vector<QWidget *> widgets{_tokens,
|
||||||
_tokens, _actions, _streamTitle,
|
_actions,
|
||||||
_category, _markerDescription, _clipHasDelay,
|
_streamTitle,
|
||||||
_duration, _announcementColor, _channel};
|
_category,
|
||||||
|
_markerDescription,
|
||||||
|
_clipHasDelay,
|
||||||
|
_duration,
|
||||||
|
_announcementColor,
|
||||||
|
_channel,
|
||||||
|
_userInfoQueryType,
|
||||||
|
_userLogin,
|
||||||
|
_userId,
|
||||||
|
_pointsReward,
|
||||||
|
_rewardVariable,
|
||||||
|
_toggleRewardSelection};
|
||||||
for (auto widget : widgets) {
|
for (auto widget : widgets) {
|
||||||
_layout->removeWidget(widget);
|
_layout->removeWidget(widget);
|
||||||
}
|
}
|
||||||
ClearLayout(_layout);
|
ClearLayout(_layout);
|
||||||
|
|
||||||
auto layoutText =
|
const char *layoutText;
|
||||||
_entryData->GetAction() ==
|
switch (_entryData->GetAction()) {
|
||||||
MacroActionTwitch::Action::SEND_CHAT_MESSAGE
|
case MacroActionTwitch::Action::SEND_CHAT_MESSAGE:
|
||||||
? obs_module_text(
|
layoutText = obs_module_text(
|
||||||
"AdvSceneSwitcher.action.twitch.entry.chat")
|
"AdvSceneSwitcher.action.twitch.entry.chat");
|
||||||
: obs_module_text(
|
break;
|
||||||
"AdvSceneSwitcher.action.twitch.entry.default");
|
case MacroActionTwitch::Action::USER_GET_INFO:
|
||||||
|
layoutText = obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.twitch.entry.user.getInfo");
|
||||||
|
break;
|
||||||
|
case MacroActionTwitch::Action::POINTS_REWARD_GET_INFO:
|
||||||
|
layoutText = obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.twitch.entry.reward.getInfo");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
layoutText = obs_module_text(
|
||||||
|
"AdvSceneSwitcher.action.twitch.entry.default");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
PlaceWidgets(layoutText, _layout,
|
PlaceWidgets(layoutText, _layout,
|
||||||
{{"{{account}}", _tokens},
|
{{"{{account}}", _tokens},
|
||||||
{"{{actions}}", _actions},
|
{"{{actions}}", _actions},
|
||||||
@@ -837,7 +1223,14 @@ void MacroActionTwitchEdit::SetWidgetLayout()
|
|||||||
{"{{clipHasDelay}}", _clipHasDelay},
|
{"{{clipHasDelay}}", _clipHasDelay},
|
||||||
{"{{duration}}", _duration},
|
{"{{duration}}", _duration},
|
||||||
{"{{announcementColor}}", _announcementColor},
|
{"{{announcementColor}}", _announcementColor},
|
||||||
{"{{channel}}", _channel}});
|
{"{{channel}}", _channel},
|
||||||
|
{"{{userInfoQueryType}}", _userInfoQueryType},
|
||||||
|
{"{{userLogin}}", _userLogin},
|
||||||
|
{"{{userId}}", _userId},
|
||||||
|
{"{{pointsReward}}", _pointsReward},
|
||||||
|
{"{{rewardVariable}}", _rewardVariable},
|
||||||
|
{"{{toggleRewardSelection}}", _toggleRewardSelection}});
|
||||||
|
|
||||||
_layout->setContentsMargins(0, 0, 0, 0);
|
_layout->setContentsMargins(0, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -862,6 +1255,14 @@ void MacroActionTwitchEdit::UpdateEntryData()
|
|||||||
_channel->SetToken(_entryData->_token);
|
_channel->SetToken(_entryData->_token);
|
||||||
_channel->SetChannel(_entryData->_channel);
|
_channel->SetChannel(_entryData->_channel);
|
||||||
_chatMessage->setPlainText(_entryData->_chatMessage);
|
_chatMessage->setPlainText(_entryData->_chatMessage);
|
||||||
|
_userInfoQueryType->setCurrentIndex(_userInfoQueryType->findData(
|
||||||
|
static_cast<int>(_entryData->_userInfoQueryType)));
|
||||||
|
_userLogin->setText(_entryData->_userLogin);
|
||||||
|
_userId->SetValue(_entryData->_userId);
|
||||||
|
_pointsReward->SetToken(_entryData->_token);
|
||||||
|
_pointsReward->SetChannel(_entryData->_channel);
|
||||||
|
_pointsReward->SetPointsReward(_entryData->_pointsReward);
|
||||||
|
_rewardVariable->SetVariable(_entryData->_rewardVariable);
|
||||||
|
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ public:
|
|||||||
// Reward add
|
// Reward add
|
||||||
POINTS_REWARD_ADD = 600, // TODO
|
POINTS_REWARD_ADD = 600, // TODO
|
||||||
|
|
||||||
|
// Get reward information
|
||||||
|
POINTS_REWARD_GET_INFO = 650,
|
||||||
|
|
||||||
// Reward update
|
// Reward update
|
||||||
POINTS_REWARD_ENABLE = 710,
|
POINTS_REWARD_ENABLE = 710,
|
||||||
POINTS_REWARD_DISABLE = 711,
|
POINTS_REWARD_DISABLE = 711,
|
||||||
@@ -134,6 +137,9 @@ public:
|
|||||||
CHANNEL_SCHEDULE_SEGMENT_DELETE = 3500, // TODO
|
CHANNEL_SCHEDULE_SEGMENT_DELETE = 3500, // TODO
|
||||||
|
|
||||||
SEND_CHAT_MESSAGE = 5000,
|
SEND_CHAT_MESSAGE = 5000,
|
||||||
|
|
||||||
|
// Get user info
|
||||||
|
USER_GET_INFO = 6000
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class AnnouncementColor {
|
enum class AnnouncementColor {
|
||||||
@@ -146,6 +152,8 @@ public:
|
|||||||
|
|
||||||
enum class RedemptionStatus { CANCELED, FULFILLED };
|
enum class RedemptionStatus { CANCELED, FULFILLED };
|
||||||
|
|
||||||
|
enum class UserInfoQueryType { ID, LOGIN };
|
||||||
|
|
||||||
bool PerformAction();
|
bool PerformAction();
|
||||||
void LogAction() const;
|
void LogAction() const;
|
||||||
bool Save(obs_data_t *obj) const;
|
bool Save(obs_data_t *obj) const;
|
||||||
@@ -169,6 +177,12 @@ public:
|
|||||||
AnnouncementColor _announcementColor = AnnouncementColor::PRIMARY;
|
AnnouncementColor _announcementColor = AnnouncementColor::PRIMARY;
|
||||||
TwitchChannel _channel;
|
TwitchChannel _channel;
|
||||||
StringVariable _chatMessage;
|
StringVariable _chatMessage;
|
||||||
|
UserInfoQueryType _userInfoQueryType = UserInfoQueryType::LOGIN;
|
||||||
|
StringVariable _userLogin = "user login";
|
||||||
|
IntVariable _userId = 0;
|
||||||
|
TwitchPointsReward _pointsReward;
|
||||||
|
std::weak_ptr<Variable> _rewardVariable;
|
||||||
|
bool _useVariableForRewardSelection = false;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetStreamTitle(const std::shared_ptr<TwitchToken> &) const;
|
void SetStreamTitle(const std::shared_ptr<TwitchToken> &) const;
|
||||||
@@ -181,10 +195,20 @@ private:
|
|||||||
bool enable) const;
|
bool enable) const;
|
||||||
void StartRaid(const std::shared_ptr<TwitchToken> &);
|
void StartRaid(const std::shared_ptr<TwitchToken> &);
|
||||||
void SendChatMessage(const std::shared_ptr<TwitchToken> &);
|
void SendChatMessage(const std::shared_ptr<TwitchToken> &);
|
||||||
|
void GetUserInfo(const std::shared_ptr<TwitchToken> &);
|
||||||
|
void GetRewardInfo(const std::shared_ptr<TwitchToken> &);
|
||||||
|
|
||||||
|
bool ResolveVariableSelectionToRewardId(
|
||||||
|
const std::shared_ptr<TwitchToken> &);
|
||||||
|
|
||||||
|
void SetupTempVars();
|
||||||
|
|
||||||
Action _action = Action::CHANNEL_INFO_TITLE_SET;
|
Action _action = Action::CHANNEL_INFO_TITLE_SET;
|
||||||
std::shared_ptr<TwitchChatConnection> _chatConnection;
|
std::shared_ptr<TwitchChatConnection> _chatConnection;
|
||||||
|
|
||||||
|
std::string _lastResolvedRewardTitle;
|
||||||
|
std::string _lastResolvedRewardId;
|
||||||
|
|
||||||
static bool _registered;
|
static bool _registered;
|
||||||
static const std::string id;
|
static const std::string id;
|
||||||
};
|
};
|
||||||
@@ -210,7 +234,7 @@ private slots:
|
|||||||
void TwitchTokenChanged(const QString &);
|
void TwitchTokenChanged(const QString &);
|
||||||
void CheckToken();
|
void CheckToken();
|
||||||
void StreamTitleChanged();
|
void StreamTitleChanged();
|
||||||
void CategoreyChanged(const TwitchCategory &);
|
void CategoryChanged(const TwitchCategory &);
|
||||||
void MarkerDescriptionChanged();
|
void MarkerDescriptionChanged();
|
||||||
void ClipHasDelayChanged(int state);
|
void ClipHasDelayChanged(int state);
|
||||||
void DurationChanged(const Duration &);
|
void DurationChanged(const Duration &);
|
||||||
@@ -218,6 +242,12 @@ private slots:
|
|||||||
void AnnouncementColorChanged(int index);
|
void AnnouncementColorChanged(int index);
|
||||||
void ChannelChanged(const TwitchChannel &);
|
void ChannelChanged(const TwitchChannel &);
|
||||||
void ChatMessageChanged();
|
void ChatMessageChanged();
|
||||||
|
void UserInfoQueryTypeChanged(int);
|
||||||
|
void UserLoginChanged();
|
||||||
|
void UserIdChanged(const NumberVariable<int> &);
|
||||||
|
void PointsRewardChanged(const TwitchPointsReward &);
|
||||||
|
void RewardVariableChanged(const QString &);
|
||||||
|
void ToggleRewardSelection(bool);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
@@ -246,6 +276,12 @@ private:
|
|||||||
QComboBox *_announcementColor;
|
QComboBox *_announcementColor;
|
||||||
TwitchChannelSelection *_channel;
|
TwitchChannelSelection *_channel;
|
||||||
VariableTextEdit *_chatMessage;
|
VariableTextEdit *_chatMessage;
|
||||||
|
QComboBox *_userInfoQueryType;
|
||||||
|
VariableLineEdit *_userLogin;
|
||||||
|
VariableSpinBox *_userId;
|
||||||
|
TwitchPointsRewardWidget *_pointsReward;
|
||||||
|
VariableSelection *_rewardVariable;
|
||||||
|
QPushButton *_toggleRewardSelection;
|
||||||
|
|
||||||
bool _loading = true;
|
bool _loading = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -257,65 +257,15 @@ void MacroConditionTwitch::ResetChatConnection()
|
|||||||
_chatConnection.reset();
|
_chatConnection.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
setTempVarsHelper(const std::string &jsonStr,
|
|
||||||
std::function<void(const char *, const char *)> setVar)
|
|
||||||
{
|
|
||||||
try {
|
|
||||||
auto json = nlohmann::json::parse(jsonStr);
|
|
||||||
for (auto it = json.begin(); it != json.end(); ++it) {
|
|
||||||
if (it->is_string()) {
|
|
||||||
setVar(it.key().c_str(),
|
|
||||||
it->get<std::string>().c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
setVar(it.key().c_str(), it->dump().c_str());
|
|
||||||
}
|
|
||||||
} catch (const nlohmann::json::exception &e) {
|
|
||||||
vblog(LOG_INFO, "%s", jsonStr.c_str());
|
|
||||||
vblog(LOG_INFO, "%s", e.what());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
setTempVarsHelper(obs_data_t *data,
|
|
||||||
std::function<void(const char *, const char *)> setVar)
|
|
||||||
{
|
|
||||||
auto jsonStr = obs_data_get_json(data);
|
|
||||||
if (!jsonStr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTempVarsHelper(jsonStr, setVar);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MacroConditionTwitch::CheckChannelGenericEvents()
|
bool MacroConditionTwitch::CheckChannelGenericEvents()
|
||||||
{
|
{
|
||||||
if (!_eventBuffer) {
|
return HandleMatchingSubscriptionEvents([this](const Event &event) {
|
||||||
return false;
|
SetVariableValue(event.ToString());
|
||||||
}
|
SetJsonTempVars(event.data,
|
||||||
|
[this](const char *id, const char *value) {
|
||||||
while (!_eventBuffer->Empty()) {
|
SetTempVarValue(id, value);
|
||||||
auto event = _eventBuffer->ConsumeMessage();
|
});
|
||||||
if (!event) {
|
});
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (_subscriptionID != event->id) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
SetVariableValue(event->ToString());
|
|
||||||
setTempVarsHelper(event->data,
|
|
||||||
[this](const char *id, const char *value) {
|
|
||||||
SetTempVarValue(id, value);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (_clearBufferOnMatch) {
|
|
||||||
_eventBuffer->Clear();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MacroConditionTwitch::CheckChannelLiveEvents()
|
bool MacroConditionTwitch::CheckChannelLiveEvents()
|
||||||
@@ -345,10 +295,105 @@ bool MacroConditionTwitch::CheckChannelLiveEvents()
|
|||||||
}
|
}
|
||||||
|
|
||||||
SetVariableValue(event->ToString());
|
SetVariableValue(event->ToString());
|
||||||
setTempVarsHelper(event->data,
|
SetJsonTempVars(event->data,
|
||||||
[this](const char *id, const char *value) {
|
[this](const char *id, const char *value) {
|
||||||
SetTempVarValue(id, value);
|
SetTempVarValue(id, value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (_clearBufferOnMatch) {
|
||||||
|
_eventBuffer->Clear();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionTwitch::CheckChannelRewardChangeEvents()
|
||||||
|
{
|
||||||
|
return HandleMatchingSubscriptionEvents([this](const Event &event) {
|
||||||
|
SetVariableValue(event.ToString());
|
||||||
|
SetJsonTempVars(event.data,
|
||||||
|
[this](const char *id, const char *value) {
|
||||||
|
SetTempVarValue(id, value);
|
||||||
|
});
|
||||||
|
|
||||||
|
OBSDataAutoRelease image =
|
||||||
|
obs_data_get_obj(event.data, "image");
|
||||||
|
SetTempVarValue("image.url_4x",
|
||||||
|
obs_data_get_string(image, "url_4x"));
|
||||||
|
|
||||||
|
OBSDataAutoRelease default_image =
|
||||||
|
obs_data_get_obj(event.data, "default_image");
|
||||||
|
SetTempVarValue("default_image.url_4x",
|
||||||
|
obs_data_get_string(default_image, "url_4x"));
|
||||||
|
|
||||||
|
OBSDataAutoRelease max_per_stream =
|
||||||
|
obs_data_get_obj(event.data, "max_per_stream");
|
||||||
|
SetTempVarValue("max_per_stream.is_enabled",
|
||||||
|
obs_data_get_bool(max_per_stream,
|
||||||
|
"is_enabled"));
|
||||||
|
SetTempVarValue("max_per_stream.max_per_stream",
|
||||||
|
std::to_string(obs_data_get_int(max_per_stream,
|
||||||
|
"value")));
|
||||||
|
|
||||||
|
OBSDataAutoRelease max_per_user_per_stream =
|
||||||
|
obs_data_get_obj(event.data, "max_per_user_per_stream");
|
||||||
|
SetTempVarValue("max_per_user_per_stream.is_enabled",
|
||||||
|
obs_data_get_bool(max_per_user_per_stream,
|
||||||
|
"is_enabled"));
|
||||||
|
SetTempVarValue(
|
||||||
|
"max_per_user_per_stream.max_per_user_per_stream",
|
||||||
|
std::to_string(obs_data_get_int(max_per_user_per_stream,
|
||||||
|
"value")));
|
||||||
|
|
||||||
|
OBSDataAutoRelease global_cooldown =
|
||||||
|
obs_data_get_obj(event.data, "global_cooldown");
|
||||||
|
SetTempVarValue("global_cooldown.is_enabled",
|
||||||
|
obs_data_get_bool(global_cooldown,
|
||||||
|
"is_enabled"));
|
||||||
|
SetTempVarValue(
|
||||||
|
"max_per_user_per_stream.global_cooldown_seconds",
|
||||||
|
std::to_string(obs_data_get_int(max_per_user_per_stream,
|
||||||
|
"seconds")));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionTwitch::CheckChannelRewardRedemptionEvents()
|
||||||
|
{
|
||||||
|
return HandleMatchingSubscriptionEvents([this](const Event &event) {
|
||||||
|
SetVariableValue(event.ToString());
|
||||||
|
SetJsonTempVars(event.data,
|
||||||
|
[this](const char *id, const char *value) {
|
||||||
|
SetTempVarValue(id, value);
|
||||||
|
});
|
||||||
|
OBSDataAutoRelease rewardInfo =
|
||||||
|
obs_data_get_obj(event.data, "reward");
|
||||||
|
SetJsonTempVars(rewardInfo, [this](const char *nestedId,
|
||||||
|
const char *value) {
|
||||||
|
const std::string id =
|
||||||
|
"reward." + std::string(nestedId);
|
||||||
|
SetTempVarValue(id, value);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MacroConditionTwitch::HandleMatchingSubscriptionEvents(
|
||||||
|
const std::function<void(const Event &)> &matchCb)
|
||||||
|
{
|
||||||
|
if (!_eventBuffer) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!_eventBuffer->Empty()) {
|
||||||
|
auto event = _eventBuffer->ConsumeMessage();
|
||||||
|
if (!event) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (_subscriptionID != event->id) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
matchCb(*event);
|
||||||
|
|
||||||
if (_clearBufferOnMatch) {
|
if (_clearBufferOnMatch) {
|
||||||
_eventBuffer->Clear();
|
_eventBuffer->Clear();
|
||||||
@@ -618,16 +663,18 @@ bool MacroConditionTwitch::CheckCondition()
|
|||||||
case Condition::CHARITY_CAMPAIGN_END_EVENT:
|
case Condition::CHARITY_CAMPAIGN_END_EVENT:
|
||||||
case Condition::SHIELD_MODE_START_EVENT:
|
case Condition::SHIELD_MODE_START_EVENT:
|
||||||
case Condition::SHIELD_MODE_END_EVENT:
|
case Condition::SHIELD_MODE_END_EVENT:
|
||||||
case Condition::POINTS_REWARD_ADDITION_EVENT:
|
|
||||||
case Condition::POINTS_REWARD_UPDATE_EVENT:
|
|
||||||
case Condition::POINTS_REWARD_DELETION_EVENT:
|
|
||||||
case Condition::POINTS_REWARD_REDEMPTION_EVENT:
|
|
||||||
case Condition::POINTS_REWARD_REDEMPTION_UPDATE_EVENT:
|
|
||||||
case Condition::USER_BAN_EVENT:
|
case Condition::USER_BAN_EVENT:
|
||||||
case Condition::USER_UNBAN_EVENT:
|
case Condition::USER_UNBAN_EVENT:
|
||||||
case Condition::USER_MODERATOR_ADDITION_EVENT:
|
case Condition::USER_MODERATOR_ADDITION_EVENT:
|
||||||
case Condition::USER_MODERATOR_DELETION_EVENT:
|
case Condition::USER_MODERATOR_DELETION_EVENT:
|
||||||
return CheckChannelGenericEvents();
|
return CheckChannelGenericEvents();
|
||||||
|
case Condition::POINTS_REWARD_ADDITION_EVENT:
|
||||||
|
case Condition::POINTS_REWARD_UPDATE_EVENT:
|
||||||
|
case Condition::POINTS_REWARD_DELETION_EVENT:
|
||||||
|
return CheckChannelRewardChangeEvents();
|
||||||
|
case Condition::POINTS_REWARD_REDEMPTION_EVENT:
|
||||||
|
case Condition::POINTS_REWARD_REDEMPTION_UPDATE_EVENT:
|
||||||
|
return CheckChannelRewardRedemptionEvents();
|
||||||
case Condition::STREAM_ONLINE_LIVE_EVENT:
|
case Condition::STREAM_ONLINE_LIVE_EVENT:
|
||||||
case Condition::STREAM_ONLINE_PLAYLIST_EVENT:
|
case Condition::STREAM_ONLINE_PLAYLIST_EVENT:
|
||||||
case Condition::STREAM_ONLINE_WATCHPARTY_EVENT:
|
case Condition::STREAM_ONLINE_WATCHPARTY_EVENT:
|
||||||
@@ -1206,25 +1253,41 @@ void MacroConditionTwitch::SetupTempVars()
|
|||||||
setupTempVarHelper("is_user_input_required", ".reward");
|
setupTempVarHelper("is_user_input_required", ".reward");
|
||||||
setupTempVarHelper("should_redemptions_skip_request_queue",
|
setupTempVarHelper("should_redemptions_skip_request_queue",
|
||||||
".reward");
|
".reward");
|
||||||
setupTempVarHelper("max_per_stream", ".reward");
|
|
||||||
setupTempVarHelper("max_per_user_per_stream", ".reward");
|
|
||||||
setupTempVarHelper("background_color", ".reward");
|
setupTempVarHelper("background_color", ".reward");
|
||||||
setupTempVarHelper("image", ".reward");
|
setupTempVarHelper("image", ".reward");
|
||||||
|
setupTempVarHelper("image.url_4x", ".reward");
|
||||||
setupTempVarHelper("default_image", ".reward");
|
setupTempVarHelper("default_image", ".reward");
|
||||||
setupTempVarHelper("global_cooldown", ".reward");
|
setupTempVarHelper("default_image.url_4x", ".reward");
|
||||||
setupTempVarHelper("cooldown_expires_at", ".reward");
|
setupTempVarHelper("cooldown_expires_at", ".reward");
|
||||||
setupTempVarHelper("redemptions_redeemed_current_stream",
|
setupTempVarHelper("redemptions_redeemed_current_stream",
|
||||||
".reward");
|
".reward");
|
||||||
|
setupTempVarHelper("max_per_stream", ".reward");
|
||||||
|
setupTempVarHelper("max_per_stream.is_enabled", ".reward");
|
||||||
|
setupTempVarHelper("max_per_stream.max_per_stream", ".reward");
|
||||||
|
setupTempVarHelper("max_per_user_per_stream", ".reward");
|
||||||
|
setupTempVarHelper("max_per_user_per_stream.is_enabled",
|
||||||
|
".reward");
|
||||||
|
setupTempVarHelper(
|
||||||
|
"max_per_user_per_stream.max_per_user_per_stream",
|
||||||
|
".reward");
|
||||||
|
setupTempVarHelper("global_cooldown", ".reward");
|
||||||
|
setupTempVarHelper("global_cooldown.is_enabled", ".reward");
|
||||||
|
setupTempVarHelper("global_cooldown.global_cooldown_seconds",
|
||||||
|
".reward");
|
||||||
break;
|
break;
|
||||||
case Condition::POINTS_REWARD_REDEMPTION_EVENT:
|
case Condition::POINTS_REWARD_REDEMPTION_EVENT:
|
||||||
case Condition::POINTS_REWARD_REDEMPTION_UPDATE_EVENT:
|
case Condition::POINTS_REWARD_REDEMPTION_UPDATE_EVENT:
|
||||||
setupTempVarHelper("id", ".reward");
|
setupTempVarHelper("id", ".redemption");
|
||||||
setupTempVarHelper("user_id", ".reward");
|
setupTempVarHelper("user_id", ".reward");
|
||||||
setupTempVarHelper("user_login", ".reward");
|
setupTempVarHelper("user_login", ".reward");
|
||||||
setupTempVarHelper("user_name", ".reward");
|
setupTempVarHelper("user_name", ".reward");
|
||||||
setupTempVarHelper("user_input", ".reward");
|
setupTempVarHelper("user_input", ".reward");
|
||||||
setupTempVarHelper("status", ".reward");
|
setupTempVarHelper("status", ".reward");
|
||||||
setupTempVarHelper("reward", ".reward");
|
setupTempVarHelper("reward", ".reward");
|
||||||
|
setupTempVarHelper("reward.id", ".reward");
|
||||||
|
setupTempVarHelper("reward.title", ".reward");
|
||||||
|
setupTempVarHelper("reward.prompt", ".reward");
|
||||||
|
setupTempVarHelper("reward.cost", ".reward");
|
||||||
setupTempVarHelper("redeemed_at", ".reward");
|
setupTempVarHelper("redeemed_at", ".reward");
|
||||||
break;
|
break;
|
||||||
case Condition::USER_BAN_EVENT:
|
case Condition::USER_BAN_EVENT:
|
||||||
@@ -1425,10 +1488,8 @@ MacroConditionTwitchEdit::MacroConditionTwitchEdit(
|
|||||||
this,
|
this,
|
||||||
SLOT(ChatMessagePatternChanged(const ChatMessagePattern &)));
|
SLOT(ChatMessagePatternChanged(const ChatMessagePattern &)));
|
||||||
QWidget::connect(_category,
|
QWidget::connect(_category,
|
||||||
SIGNAL(CategoreyChanged(const TwitchCategory &)), this,
|
SIGNAL(CategoryChanged(const TwitchCategory &)), this,
|
||||||
SLOT(CategoreyChanged(const TwitchCategory &)));
|
SLOT(CategoryChanged(const TwitchCategory &)));
|
||||||
QWidget::connect(this, SIGNAL(TempVarsChanged()), window(),
|
|
||||||
SIGNAL(SegmentTempVarsChanged()));
|
|
||||||
QWidget::connect(_clearBufferOnMatch, SIGNAL(stateChanged(int)), this,
|
QWidget::connect(_clearBufferOnMatch, SIGNAL(stateChanged(int)), this,
|
||||||
SLOT(ClearBufferOnMatchChanged(int)));
|
SLOT(ClearBufferOnMatchChanged(int)));
|
||||||
|
|
||||||
@@ -1480,7 +1541,6 @@ void MacroConditionTwitchEdit::ConditionChanged(int idx)
|
|||||||
_entryData->SetCondition(static_cast<MacroConditionTwitch::Condition>(
|
_entryData->SetCondition(static_cast<MacroConditionTwitch::Condition>(
|
||||||
_conditions->itemData(idx).toInt()));
|
_conditions->itemData(idx).toInt()));
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
emit TempVarsChanged();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionTwitchEdit::TwitchTokenChanged(const QString &token)
|
void MacroConditionTwitchEdit::TwitchTokenChanged(const QString &token)
|
||||||
@@ -1572,7 +1632,7 @@ void MacroConditionTwitchEdit::RegexTitleChanged(const RegexConfig &conf)
|
|||||||
updateGeometry();
|
updateGeometry();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionTwitchEdit::CategoreyChanged(const TwitchCategory &category)
|
void MacroConditionTwitchEdit::CategoryChanged(const TwitchCategory &category)
|
||||||
{
|
{
|
||||||
GUARD_LOADING_AND_LOCK();
|
GUARD_LOADING_AND_LOCK();
|
||||||
_entryData->_category = category;
|
_entryData->_category = category;
|
||||||
|
|||||||
@@ -111,7 +111,11 @@ public:
|
|||||||
private:
|
private:
|
||||||
bool CheckChannelGenericEvents();
|
bool CheckChannelGenericEvents();
|
||||||
bool CheckChannelLiveEvents();
|
bool CheckChannelLiveEvents();
|
||||||
|
bool CheckChannelRewardChangeEvents();
|
||||||
|
bool CheckChannelRewardRedemptionEvents();
|
||||||
bool CheckChatMessages(TwitchToken &token);
|
bool CheckChatMessages(TwitchToken &token);
|
||||||
|
bool HandleMatchingSubscriptionEvents(
|
||||||
|
const std::function<void(const Event &)> &matchCb);
|
||||||
bool CheckChatUserJoinOrLeave(TwitchToken &token);
|
bool CheckChatUserJoinOrLeave(TwitchToken &token);
|
||||||
|
|
||||||
void RegisterEventSubscription();
|
void RegisterEventSubscription();
|
||||||
@@ -171,12 +175,11 @@ private slots:
|
|||||||
void StreamTitleChanged();
|
void StreamTitleChanged();
|
||||||
void RegexTitleChanged(const RegexConfig &);
|
void RegexTitleChanged(const RegexConfig &);
|
||||||
void ChatMessagePatternChanged(const ChatMessagePattern &);
|
void ChatMessagePatternChanged(const ChatMessagePattern &);
|
||||||
void CategoreyChanged(const TwitchCategory &);
|
void CategoryChanged(const TwitchCategory &);
|
||||||
void ClearBufferOnMatchChanged(int);
|
void ClearBufferOnMatchChanged(int);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void HeaderInfoChanged(const QString &);
|
void HeaderInfoChanged(const QString &);
|
||||||
void TempVarsChanged();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void SetWidgetVisibility();
|
void SetWidgetVisibility();
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ void TwitchPointsRewardSelection::PopulateSelection()
|
|||||||
const QSignalBlocker b(this);
|
const QSignalBlocker b(this);
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
auto pointsRewards = GetPointsRewards(token, *_channel);
|
auto pointsRewards = GetPointsRewardsForChannel(token, *_channel);
|
||||||
if (!pointsRewards) {
|
if (!pointsRewards) {
|
||||||
DisplayErrorMessage(obs_module_text(
|
DisplayErrorMessage(obs_module_text(
|
||||||
"AdvSceneSwitcher.twitch.selection.points.reward.tooltip.error"));
|
"AdvSceneSwitcher.twitch.selection.points.reward.tooltip.error"));
|
||||||
@@ -127,47 +127,6 @@ void TwitchPointsRewardSelection::HideErrorMessage()
|
|||||||
setToolTip("");
|
setToolTip("");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::vector<TwitchPointsReward>>
|
|
||||||
TwitchPointsRewardSelection::GetPointsRewards(
|
|
||||||
const std::shared_ptr<TwitchToken> &token, const TwitchChannel &channel)
|
|
||||||
{
|
|
||||||
httplib::Params params = {
|
|
||||||
{"broadcaster_id", channel.GetUserID(*token)}};
|
|
||||||
|
|
||||||
auto response = SendGetRequest(*token, "https://api.twitch.tv",
|
|
||||||
"/helix/channel_points/custom_rewards",
|
|
||||||
params);
|
|
||||||
|
|
||||||
if (response.status != 200) {
|
|
||||||
blog(LOG_WARNING,
|
|
||||||
"Failed to fetch points rewards for user %s and channel %s! (%d)",
|
|
||||||
token->GetName().c_str(), channel.GetName().c_str(),
|
|
||||||
response.status);
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
return ParseResponse(response.data);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<TwitchPointsReward>
|
|
||||||
TwitchPointsRewardSelection::ParseResponse(obs_data_t *response)
|
|
||||||
{
|
|
||||||
std::vector<TwitchPointsReward> pointRewards;
|
|
||||||
OBSDataArrayAutoRelease jsonArray =
|
|
||||||
obs_data_get_array(response, "data");
|
|
||||||
size_t count = obs_data_array_count(jsonArray);
|
|
||||||
|
|
||||||
for (size_t i = 0; i < count; ++i) {
|
|
||||||
OBSDataAutoRelease jsonObj = obs_data_array_item(jsonArray, i);
|
|
||||||
std::string id = obs_data_get_string(jsonObj, "id");
|
|
||||||
std::string title = obs_data_get_string(jsonObj, "title");
|
|
||||||
pointRewards.push_back({id, title});
|
|
||||||
}
|
|
||||||
|
|
||||||
return pointRewards;
|
|
||||||
}
|
|
||||||
|
|
||||||
void TwitchPointsRewardSelection::SelectionChanged(int index)
|
void TwitchPointsRewardSelection::SelectionChanged(int index)
|
||||||
{
|
{
|
||||||
TwitchPointsReward pointsReward{
|
TwitchPointsReward pointsReward{
|
||||||
@@ -182,7 +141,9 @@ TwitchPointsRewardWidget::TwitchPointsRewardWidget(QWidget *parent)
|
|||||||
_refreshButton(new QPushButton(this))
|
_refreshButton(new QPushButton(this))
|
||||||
{
|
{
|
||||||
_refreshButton->setMaximumWidth(22);
|
_refreshButton->setMaximumWidth(22);
|
||||||
SetButtonIcon(_refreshButton, ":res/images/refresh.svg");
|
SetButtonIcon(_refreshButton, GetThemeTypeName() == "Light"
|
||||||
|
? ":res/images/refresh.svg"
|
||||||
|
: "theme:Dark/refresh.svg");
|
||||||
_refreshButton->setToolTip(obs_module_text(
|
_refreshButton->setToolTip(obs_module_text(
|
||||||
"AdvSceneSwitcher.twitch.selection.points.reward.refresh"));
|
"AdvSceneSwitcher.twitch.selection.points.reward.refresh"));
|
||||||
|
|
||||||
@@ -216,4 +177,44 @@ void TwitchPointsRewardWidget::SetToken(const std::weak_ptr<TwitchToken> &token)
|
|||||||
_selection->SetToken(token);
|
_selection->SetToken(token);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static std::vector<TwitchPointsReward> parseApiResponse(obs_data_t *response)
|
||||||
|
{
|
||||||
|
std::vector<TwitchPointsReward> pointRewards;
|
||||||
|
OBSDataArrayAutoRelease jsonArray =
|
||||||
|
obs_data_get_array(response, "data");
|
||||||
|
size_t count = obs_data_array_count(jsonArray);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; ++i) {
|
||||||
|
OBSDataAutoRelease jsonObj = obs_data_array_item(jsonArray, i);
|
||||||
|
std::string id = obs_data_get_string(jsonObj, "id");
|
||||||
|
std::string title = obs_data_get_string(jsonObj, "title");
|
||||||
|
pointRewards.push_back({id, title});
|
||||||
|
}
|
||||||
|
|
||||||
|
return pointRewards;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::vector<TwitchPointsReward>>
|
||||||
|
GetPointsRewardsForChannel(const std::shared_ptr<TwitchToken> &token,
|
||||||
|
const TwitchChannel &channel)
|
||||||
|
{
|
||||||
|
httplib::Params params = {
|
||||||
|
{"broadcaster_id", channel.GetUserID(*token)}};
|
||||||
|
|
||||||
|
auto response = SendGetRequest(*token, "https://api.twitch.tv",
|
||||||
|
"/helix/channel_points/custom_rewards",
|
||||||
|
params, true);
|
||||||
|
|
||||||
|
if (response.status != 200) {
|
||||||
|
blog(LOG_WARNING,
|
||||||
|
"Failed to fetch points rewards for user %s and channel %s! (%d)",
|
||||||
|
token->GetName().c_str(), channel.GetName().c_str(),
|
||||||
|
response.status);
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return parseApiResponse(response.data);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -35,10 +35,6 @@ protected:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void AddPredefinedItems();
|
void AddPredefinedItems();
|
||||||
std::optional<std::vector<TwitchPointsReward>>
|
|
||||||
GetPointsRewards(const std::shared_ptr<TwitchToken> &token,
|
|
||||||
const TwitchChannel &channel);
|
|
||||||
std::vector<TwitchPointsReward> ParseResponse(obs_data_t *response);
|
|
||||||
|
|
||||||
bool _allowAny;
|
bool _allowAny;
|
||||||
const std::vector<TokenOption> _supportedTokenOptions = {
|
const std::vector<TokenOption> _supportedTokenOptions = {
|
||||||
@@ -71,4 +67,8 @@ protected:
|
|||||||
QPushButton *_refreshButton;
|
QPushButton *_refreshButton;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::optional<std::vector<TwitchPointsReward>>
|
||||||
|
GetPointsRewardsForChannel(const std::shared_ptr<TwitchToken> &token,
|
||||||
|
const TwitchChannel &channel);
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -439,7 +439,7 @@ TwitchTokenSettingsDialog::TwitchTokenSettingsDialog(
|
|||||||
"AdvSceneSwitcher.twitchToken.select",
|
"AdvSceneSwitcher.twitchToken.select",
|
||||||
"AdvSceneSwitcher.twitchToken.add",
|
"AdvSceneSwitcher.twitchToken.add",
|
||||||
"AdvSceneSwitcher.twitchToken.nameNotAvailable",
|
"AdvSceneSwitcher.twitchToken.nameNotAvailable",
|
||||||
parent),
|
false, parent),
|
||||||
_requestToken(new QPushButton(
|
_requestToken(new QPushButton(
|
||||||
obs_module_text("AdvSceneSwitcher.twitchToken.request"))),
|
obs_module_text("AdvSceneSwitcher.twitchToken.request"))),
|
||||||
_showToken(new QPushButton()),
|
_showToken(new QPushButton()),
|
||||||
@@ -456,7 +456,6 @@ TwitchTokenSettingsDialog::TwitchTokenSettingsDialog(
|
|||||||
_currentTokenValue->setText(QString::fromStdString(settings._token));
|
_currentTokenValue->setText(QString::fromStdString(settings._token));
|
||||||
|
|
||||||
_name->setReadOnly(true);
|
_name->setReadOnly(true);
|
||||||
_showNameEmptyWarning = false;
|
|
||||||
|
|
||||||
QWidget::connect(_requestToken, SIGNAL(clicked()), this,
|
QWidget::connect(_requestToken, SIGNAL(clicked()), this,
|
||||||
SLOT(RequestToken()));
|
SLOT(RequestToken()));
|
||||||
@@ -561,7 +560,9 @@ void TwitchTokenSettingsDialog::CheckIfTokenValid()
|
|||||||
|
|
||||||
void TwitchTokenSettingsDialog::ShowToken()
|
void TwitchTokenSettingsDialog::ShowToken()
|
||||||
{
|
{
|
||||||
SetButtonIcon(_showToken, ":res/images/visible.svg");
|
SetButtonIcon(_showToken, GetThemeTypeName() == "Light"
|
||||||
|
? ":res/images/visible.svg"
|
||||||
|
: "theme:Dark/visible.svg");
|
||||||
_currentTokenValue->setEchoMode(QLineEdit::Normal);
|
_currentTokenValue->setEchoMode(QLineEdit::Normal);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -682,22 +683,33 @@ void TwitchTokenSettingsDialog::RequestToken()
|
|||||||
void TwitchTokenSettingsDialog::GotToken(const std::optional<QString> &value)
|
void TwitchTokenSettingsDialog::GotToken(const std::optional<QString> &value)
|
||||||
{
|
{
|
||||||
_currentTokenValue->setText(value.value_or(""));
|
_currentTokenValue->setText(value.value_or(""));
|
||||||
if (value.has_value()) {
|
if (!value) {
|
||||||
_tokenStatus->setText(obs_module_text(
|
|
||||||
"AdvSceneSwitcher.twitchToken.request.success"));
|
|
||||||
_currentToken.SetToken(value.value().toStdString());
|
|
||||||
auto name = QString::fromStdString(_currentToken._name);
|
|
||||||
_name->setText(name);
|
|
||||||
_name->textEdited(name);
|
|
||||||
QMetaObject::invokeMethod(this, "NameChanged",
|
|
||||||
Q_ARG(const QString &, name));
|
|
||||||
SetTokenInfoVisible(true);
|
|
||||||
} else {
|
|
||||||
_tokenStatus->setText(obs_module_text(
|
_tokenStatus->setText(obs_module_text(
|
||||||
"AdvSceneSwitcher.twitchToken.request.fail"));
|
"AdvSceneSwitcher.twitchToken.request.fail"));
|
||||||
_name->setText("");
|
_name->setText("");
|
||||||
SetTokenInfoVisible(false);
|
SetTokenInfoVisible(false);
|
||||||
|
_requestToken->setEnabled(true);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_currentToken.SetToken(value.value().toStdString());
|
||||||
|
auto name = QString::fromStdString(_currentToken._name);
|
||||||
|
if (name.isEmpty()) {
|
||||||
|
_tokenStatus->setText(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.twitchToken.request.fail"));
|
||||||
|
_name->setText("");
|
||||||
|
SetTokenInfoVisible(false);
|
||||||
|
_requestToken->setEnabled(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_tokenStatus->setText(obs_module_text(
|
||||||
|
"AdvSceneSwitcher.twitchToken.request.success"));
|
||||||
|
_name->setText(name);
|
||||||
|
_name->textEdited(name);
|
||||||
|
QMetaObject::invokeMethod(this, "NameChanged",
|
||||||
|
Q_ARG(const QString &, name));
|
||||||
|
SetTokenInfoVisible(true);
|
||||||
_requestToken->setEnabled(true);
|
_requestToken->setEnabled(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
#include "twitch-helpers.hpp"
|
#include "twitch-helpers.hpp"
|
||||||
|
#include "plugin-state-helpers.hpp"
|
||||||
#include "token.hpp"
|
#include "token.hpp"
|
||||||
|
|
||||||
#include <log-helper.hpp>
|
#include <log-helper.hpp>
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
namespace advss {
|
namespace advss {
|
||||||
|
|
||||||
static constexpr std::string_view clientID = "ds5tt4ogliifsqc04mz3d3etnck3e5";
|
static constexpr std::string_view clientID = "ds5tt4ogliifsqc04mz3d3etnck3e5";
|
||||||
static const int cacheTimeoutSeconds = 10;
|
static const int cacheTimeoutSeconds = 10;
|
||||||
|
static std::atomic_bool apiIsThrottling = {false};
|
||||||
|
|
||||||
const char *GetClientID()
|
const char *GetClientID()
|
||||||
{
|
{
|
||||||
@@ -64,6 +68,12 @@ static bool cacheIsValid(const std::map<Args, CacheEntry> &cache,
|
|||||||
return it != cache.end() && !cacheIsTooOld(it->second);
|
return it != cache.end() && !cacheIsTooOld(it->second);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cleanupCache(std::map<Args, CacheEntry> &cache, std::mutex &mtx)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mtx);
|
||||||
|
cache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
static httplib::Headers getTokenRequestHeaders(const std::string &token)
|
static httplib::Headers getTokenRequestHeaders(const std::string &token)
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
@@ -78,6 +88,37 @@ static std::string getRequestBody(const OBSData &data)
|
|||||||
return json ? json : "";
|
return json ? json : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handleThrottling(const httplib::Result &response)
|
||||||
|
{
|
||||||
|
const auto &headers = response.value().headers;
|
||||||
|
const auto rateLimitResetTimeStr = headers.find("Ratelimit-Reset");
|
||||||
|
if (rateLimitResetTimeStr == headers.end()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::time_t rateLimitResetTime =
|
||||||
|
std::stoll(rateLimitResetTimeStr->second);
|
||||||
|
auto resetTimePoint =
|
||||||
|
std::chrono::system_clock::from_time_t(rateLimitResetTime);
|
||||||
|
auto sleepDuration = resetTimePoint - std::chrono::system_clock::now();
|
||||||
|
if (sleepDuration.count() < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
blog(LOG_WARNING, "Twitch API access is throttled for %lld seconds!",
|
||||||
|
static_cast<long long int>(
|
||||||
|
std::chrono::duration_cast<std::chrono::seconds>(
|
||||||
|
sleepDuration)
|
||||||
|
.count()));
|
||||||
|
apiIsThrottling = true;
|
||||||
|
|
||||||
|
auto resetThread = std::thread([sleepDuration]() {
|
||||||
|
std::this_thread::sleep_for(sleepDuration);
|
||||||
|
apiIsThrottling = false;
|
||||||
|
});
|
||||||
|
resetThread.detach();
|
||||||
|
}
|
||||||
|
|
||||||
static RequestResult processResult(const httplib::Result &response,
|
static RequestResult processResult(const httplib::Result &response,
|
||||||
const char *funcName)
|
const char *funcName)
|
||||||
{
|
{
|
||||||
@@ -89,6 +130,10 @@ static RequestResult processResult(const httplib::Result &response,
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (response->status == 429) {
|
||||||
|
handleThrottling(response);
|
||||||
|
}
|
||||||
|
|
||||||
RequestResult result;
|
RequestResult result;
|
||||||
result.status = response->status;
|
result.status = response->status;
|
||||||
|
|
||||||
@@ -103,10 +148,15 @@ static RequestResult processResult(const httplib::Result &response,
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestResult SendGetRequest(const TwitchToken &token, const std::string &uri,
|
static RequestResult sendGetRequest(const TwitchToken &token,
|
||||||
const std::string &path,
|
const std::string &uri,
|
||||||
const httplib::Params ¶ms)
|
const std::string &path,
|
||||||
|
const httplib::Params ¶ms)
|
||||||
{
|
{
|
||||||
|
if (apiIsThrottling) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
httplib::Client cli(uri);
|
httplib::Client cli(uri);
|
||||||
auto tokenStr = token.GetToken();
|
auto tokenStr = token.GetToken();
|
||||||
|
|
||||||
@@ -127,9 +177,17 @@ RequestResult SendGetRequest(const TwitchToken &token, const std::string &uri,
|
|||||||
const std::string &path,
|
const std::string &path,
|
||||||
const httplib::Params ¶ms, bool useCache)
|
const httplib::Params ¶ms, bool useCache)
|
||||||
{
|
{
|
||||||
|
if (apiIsThrottling) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
static std::map<Args, CacheEntry> cache;
|
static std::map<Args, CacheEntry> cache;
|
||||||
static std::mutex mtx;
|
static std::mutex mtx;
|
||||||
std::lock_guard<std::mutex> lock(mtx);
|
[[maybe_unused]] static bool _ = []() {
|
||||||
|
AddPluginCleanupStep([]() { cleanupCache(cache, mtx); });
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
|
||||||
auto tokenStr = token.GetToken();
|
auto tokenStr = token.GetToken();
|
||||||
|
|
||||||
if (!tokenStr) {
|
if (!tokenStr) {
|
||||||
@@ -139,22 +197,32 @@ RequestResult SendGetRequest(const TwitchToken &token, const std::string &uri,
|
|||||||
auto headers = getTokenRequestHeaders(*tokenStr);
|
auto headers = getTokenRequestHeaders(*tokenStr);
|
||||||
Args args(uri, path, "", params, headers);
|
Args args(uri, path, "", params, headers);
|
||||||
|
|
||||||
if (useCache && cacheIsValid(cache, args)) {
|
if (!useCache) {
|
||||||
|
return sendGetRequest(token, uri, path, params);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(mtx);
|
||||||
|
if (cacheIsValid(cache, args)) {
|
||||||
auto it = cache.find(args);
|
auto it = cache.find(args);
|
||||||
return it->second.result;
|
return it->second.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = SendGetRequest(token, uri, path, params);
|
auto result = sendGetRequest(token, uri, path, params);
|
||||||
cache[args] = {result};
|
cache[args] = {result};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
|
static RequestResult sendPostRequest(const TwitchToken &token,
|
||||||
const std::string &path,
|
const std::string &uri,
|
||||||
const httplib::Params ¶ms,
|
const std::string &path,
|
||||||
const OBSData &data)
|
const httplib::Params ¶ms,
|
||||||
|
const OBSData &data)
|
||||||
{
|
{
|
||||||
|
if (apiIsThrottling) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
httplib::Client cli(uri);
|
httplib::Client cli(uri);
|
||||||
auto tokenStr = token.GetToken();
|
auto tokenStr = token.GetToken();
|
||||||
|
|
||||||
@@ -179,9 +247,17 @@ RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
|
|||||||
const httplib::Params ¶ms,
|
const httplib::Params ¶ms,
|
||||||
const OBSData &data, bool useCache)
|
const OBSData &data, bool useCache)
|
||||||
{
|
{
|
||||||
|
if (apiIsThrottling) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
static std::map<Args, CacheEntry> cache;
|
static std::map<Args, CacheEntry> cache;
|
||||||
static std::mutex mtx;
|
static std::mutex mtx;
|
||||||
std::lock_guard<std::mutex> lock(mtx);
|
[[maybe_unused]] static bool _ = []() {
|
||||||
|
AddPluginCleanupStep([]() { cleanupCache(cache, mtx); });
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
|
||||||
auto tokenStr = token.GetToken();
|
auto tokenStr = token.GetToken();
|
||||||
|
|
||||||
if (!tokenStr) {
|
if (!tokenStr) {
|
||||||
@@ -192,21 +268,32 @@ RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
|
|||||||
auto body = getRequestBody(data);
|
auto body = getRequestBody(data);
|
||||||
Args args(uri, path, body, params, headers);
|
Args args(uri, path, body, params, headers);
|
||||||
|
|
||||||
if (useCache && cacheIsValid(cache, args)) {
|
if (!useCache) {
|
||||||
|
return sendPostRequest(token, uri, path, params, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(mtx);
|
||||||
|
if (cacheIsValid(cache, args)) {
|
||||||
auto it = cache.find(args);
|
auto it = cache.find(args);
|
||||||
return it->second.result;
|
return it->second.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = SendPostRequest(token, uri, path, params, data);
|
auto result = sendPostRequest(token, uri, path, params, data);
|
||||||
cache[args] = {result};
|
cache[args] = {result};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
|
static RequestResult sendPutRequest(const TwitchToken &token,
|
||||||
const std::string &path,
|
const std::string &uri,
|
||||||
const httplib::Params ¶ms, const OBSData &data)
|
const std::string &path,
|
||||||
|
const httplib::Params ¶ms,
|
||||||
|
const OBSData &data)
|
||||||
{
|
{
|
||||||
|
if (apiIsThrottling) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
httplib::Client cli(uri);
|
httplib::Client cli(uri);
|
||||||
auto tokenStr = token.GetToken();
|
auto tokenStr = token.GetToken();
|
||||||
|
|
||||||
@@ -231,9 +318,17 @@ RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
|
|||||||
const httplib::Params ¶ms, const OBSData &data,
|
const httplib::Params ¶ms, const OBSData &data,
|
||||||
bool useCache)
|
bool useCache)
|
||||||
{
|
{
|
||||||
|
if (apiIsThrottling) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
static std::map<Args, CacheEntry> cache;
|
static std::map<Args, CacheEntry> cache;
|
||||||
static std::mutex mtx;
|
static std::mutex mtx;
|
||||||
std::lock_guard<std::mutex> lock(mtx);
|
[[maybe_unused]] static bool _ = []() {
|
||||||
|
AddPluginCleanupStep([]() { cleanupCache(cache, mtx); });
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
|
||||||
auto tokenStr = token.GetToken();
|
auto tokenStr = token.GetToken();
|
||||||
|
|
||||||
if (!tokenStr) {
|
if (!tokenStr) {
|
||||||
@@ -244,22 +339,32 @@ RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
|
|||||||
auto body = getRequestBody(data);
|
auto body = getRequestBody(data);
|
||||||
Args args(uri, path, body, params, headers);
|
Args args(uri, path, body, params, headers);
|
||||||
|
|
||||||
if (useCache && cacheIsValid(cache, args)) {
|
if (!useCache) {
|
||||||
|
return sendPutRequest(token, uri, path, params, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(mtx);
|
||||||
|
if (cacheIsValid(cache, args)) {
|
||||||
auto it = cache.find(args);
|
auto it = cache.find(args);
|
||||||
return it->second.result;
|
return it->second.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = SendPutRequest(token, uri, path, params, data);
|
auto result = sendPutRequest(token, uri, path, params, data);
|
||||||
cache[args] = {result};
|
cache[args] = {result};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
|
static RequestResult sendPatchRequest(const TwitchToken &token,
|
||||||
const std::string &path,
|
const std::string &uri,
|
||||||
const httplib::Params ¶ms,
|
const std::string &path,
|
||||||
const OBSData &data)
|
const httplib::Params ¶ms,
|
||||||
|
const OBSData &data)
|
||||||
{
|
{
|
||||||
|
if (apiIsThrottling) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
httplib::Client cli(uri);
|
httplib::Client cli(uri);
|
||||||
auto tokenStr = token.GetToken();
|
auto tokenStr = token.GetToken();
|
||||||
|
|
||||||
@@ -284,9 +389,17 @@ RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
|
|||||||
const httplib::Params ¶ms,
|
const httplib::Params ¶ms,
|
||||||
const OBSData &data, bool useCache)
|
const OBSData &data, bool useCache)
|
||||||
{
|
{
|
||||||
|
if (apiIsThrottling) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
static std::map<Args, CacheEntry> cache;
|
static std::map<Args, CacheEntry> cache;
|
||||||
static std::mutex mtx;
|
static std::mutex mtx;
|
||||||
std::lock_guard<std::mutex> lock(mtx);
|
[[maybe_unused]] static bool _ = []() {
|
||||||
|
AddPluginCleanupStep([]() { cleanupCache(cache, mtx); });
|
||||||
|
return true;
|
||||||
|
}();
|
||||||
|
|
||||||
auto tokenStr = token.GetToken();
|
auto tokenStr = token.GetToken();
|
||||||
|
|
||||||
if (!tokenStr) {
|
if (!tokenStr) {
|
||||||
@@ -297,21 +410,31 @@ RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
|
|||||||
auto body = getRequestBody(data);
|
auto body = getRequestBody(data);
|
||||||
Args args(uri, path, body, params, headers);
|
Args args(uri, path, body, params, headers);
|
||||||
|
|
||||||
if (useCache && cacheIsValid(cache, args)) {
|
if (!useCache) {
|
||||||
|
return sendPatchRequest(token, uri, path, params, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::lock_guard<std::mutex> lock(mtx);
|
||||||
|
if (cacheIsValid(cache, args)) {
|
||||||
auto it = cache.find(args);
|
auto it = cache.find(args);
|
||||||
return it->second.result;
|
return it->second.result;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto result = SendPatchRequest(token, uri, path, params, data);
|
auto result = sendPatchRequest(token, uri, path, params, data);
|
||||||
cache[args] = {result};
|
cache[args] = {result};
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestResult SendDeleteRequest(const TwitchToken &token,
|
static RequestResult sendDeleteRequest(const TwitchToken &token,
|
||||||
const std::string &uri, const std::string &path,
|
const std::string &uri,
|
||||||
const httplib::Params ¶ms)
|
const std::string &path,
|
||||||
|
const httplib::Params ¶ms)
|
||||||
{
|
{
|
||||||
|
if (apiIsThrottling) {
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
httplib::Client cli(uri);
|
httplib::Client cli(uri);
|
||||||
auto tokenStr = token.GetToken();
|
auto tokenStr = token.GetToken();
|
||||||
|
|
||||||
@@ -330,4 +453,34 @@ RequestResult SendDeleteRequest(const TwitchToken &token,
|
|||||||
return processResult(response, __func__);
|
return processResult(response, __func__);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetJsonTempVars(const std::string &jsonStr,
|
||||||
|
std::function<void(const char *, const char *)> setVarFunc)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
auto json = nlohmann::json::parse(jsonStr);
|
||||||
|
for (auto it = json.begin(); it != json.end(); ++it) {
|
||||||
|
if (it->is_string()) {
|
||||||
|
setVarFunc(it.key().c_str(),
|
||||||
|
it->get<std::string>().c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
setVarFunc(it.key().c_str(), it->dump().c_str());
|
||||||
|
}
|
||||||
|
} catch (const nlohmann::json::exception &e) {
|
||||||
|
vblog(LOG_INFO, "%s", jsonStr.c_str());
|
||||||
|
vblog(LOG_INFO, "%s", e.what());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetJsonTempVars(obs_data_t *data,
|
||||||
|
std::function<void(const char *, const char *)> setVarFunc)
|
||||||
|
{
|
||||||
|
auto jsonStr = obs_data_get_json(data);
|
||||||
|
if (!jsonStr) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetJsonTempVars(jsonStr, setVarFunc);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -15,42 +15,33 @@ struct RequestResult {
|
|||||||
|
|
||||||
const char *GetClientID();
|
const char *GetClientID();
|
||||||
|
|
||||||
// These functions do *not* use or create RequestResult cache entries
|
// These functions can cache the RequestResult for 10s
|
||||||
|
|
||||||
RequestResult SendGetRequest(const TwitchToken &token, const std::string &uri,
|
RequestResult SendGetRequest(const TwitchToken &token, const std::string &uri,
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
const httplib::Params ¶ms = {});
|
const httplib::Params ¶ms = {},
|
||||||
|
bool useCache = false);
|
||||||
RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
|
RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
const httplib::Params ¶ms = {},
|
const httplib::Params ¶ms = {},
|
||||||
const OBSData &data = nullptr);
|
const OBSData &data = nullptr,
|
||||||
|
bool useCache = false);
|
||||||
RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
|
RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
const httplib::Params ¶ms = {},
|
const httplib::Params ¶ms = {},
|
||||||
const OBSData &data = nullptr);
|
const OBSData &data = nullptr,
|
||||||
|
bool useCache = false);
|
||||||
RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
|
RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
|
||||||
const std::string &path,
|
const std::string &path,
|
||||||
const httplib::Params ¶ms = {},
|
const httplib::Params ¶ms = {},
|
||||||
const OBSData &data = nullptr);
|
const OBSData &data = nullptr,
|
||||||
RequestResult SendDeleteRequest(const TwitchToken &token,
|
bool useCache = false);
|
||||||
const std::string &uri, const std::string &path,
|
|
||||||
const httplib::Params ¶ms = {});
|
|
||||||
|
|
||||||
// These functions will cache the RequestResult for 10s
|
// Helper functions to set temp var values
|
||||||
// Note that the cache will be reported as a "memory leak" on OBS shutdown
|
|
||||||
RequestResult SendGetRequest(const TwitchToken &token, const std::string &uri,
|
void SetJsonTempVars(const std::string &jsonStr,
|
||||||
const std::string &path,
|
std::function<void(const char *, const char *)> setVarFunc);
|
||||||
const httplib::Params ¶ms, bool useCache);
|
void SetJsonTempVars(obs_data_t *data,
|
||||||
RequestResult SendPostRequest(const TwitchToken &token, const std::string &uri,
|
std::function<void(const char *, const char *)> setVarFunc);
|
||||||
const std::string &path,
|
|
||||||
const httplib::Params ¶ms,
|
|
||||||
const OBSData &data, bool useCache);
|
|
||||||
RequestResult SendPutRequest(const TwitchToken &token, const std::string &uri,
|
|
||||||
const std::string &path,
|
|
||||||
const httplib::Params ¶ms, const OBSData &data,
|
|
||||||
bool useCache);
|
|
||||||
RequestResult SendPatchRequest(const TwitchToken &token, const std::string &uri,
|
|
||||||
const std::string &path,
|
|
||||||
const httplib::Params ¶ms,
|
|
||||||
const OBSData &data, bool useCache);
|
|
||||||
|
|
||||||
} // namespace advss
|
} // namespace advss
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ TwitchConnectionsTable *TwitchConnectionsTable::Create()
|
|||||||
void TwitchConnectionsTable::Add()
|
void TwitchConnectionsTable::Add()
|
||||||
{
|
{
|
||||||
auto newToken = std::make_shared<TwitchToken>();
|
auto newToken = std::make_shared<TwitchToken>();
|
||||||
auto accepted =
|
auto accepted = TwitchTokenSettingsDialog::AskForSettings(
|
||||||
TwitchTokenSettingsDialog::AskForSettings(this, *newToken);
|
GetSettingsWindow(), *newToken);
|
||||||
if (!accepted) {
|
if (!accepted) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ static void openSettingsDialog()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TwitchTokenSettingsDialog::AskForSettings(tabWidget->Table(),
|
TwitchTokenSettingsDialog::AskForSettings(GetSettingsWindow(),
|
||||||
*token.get());
|
*token.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -47,8 +47,8 @@ target_sources(
|
|||||||
macro-condition-video.hpp
|
macro-condition-video.hpp
|
||||||
opencv-helpers.cpp
|
opencv-helpers.cpp
|
||||||
opencv-helpers.hpp
|
opencv-helpers.hpp
|
||||||
paramerter-wrappers.cpp
|
parameter-wrappers.cpp
|
||||||
paramerter-wrappers.hpp
|
parameter-wrappers.hpp
|
||||||
preview-dialog.cpp
|
preview-dialog.cpp
|
||||||
preview-dialog.hpp
|
preview-dialog.hpp
|
||||||
screenshot-dialog.cpp
|
screenshot-dialog.cpp
|
||||||
|
|||||||
@@ -482,8 +482,9 @@ static inline void populateVideoInputSelection(QComboBox *list)
|
|||||||
|
|
||||||
static inline void populateConditionSelection(QComboBox *list)
|
static inline void populateConditionSelection(QComboBox *list)
|
||||||
{
|
{
|
||||||
for (auto entry : conditionTypes) {
|
for (auto &[value, name] : conditionTypes) {
|
||||||
list->addItem(obs_module_text(entry.second.c_str()));
|
list->addItem(obs_module_text(name.c_str()),
|
||||||
|
static_cast<int>(value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1189,8 +1190,6 @@ MacroConditionVideoEdit::MacroConditionVideoEdit(
|
|||||||
SIGNAL(VideoSelectionChanged(const VideoInput &)),
|
SIGNAL(VideoSelectionChanged(const VideoInput &)),
|
||||||
&_previewDialog,
|
&_previewDialog,
|
||||||
SLOT(VideoSelectionChanged(const VideoInput &)));
|
SLOT(VideoSelectionChanged(const VideoInput &)));
|
||||||
QWidget::connect(_condition, SIGNAL(currentIndexChanged(int)),
|
|
||||||
&_previewDialog, SLOT(ConditionChanged(int)));
|
|
||||||
QWidget::connect(_area, SIGNAL(Resized()), this, SLOT(Resize()));
|
QWidget::connect(_area, SIGNAL(Resized()), this, SLOT(Resize()));
|
||||||
QWidget::connect(entryData.get(),
|
QWidget::connect(entryData.get(),
|
||||||
&MacroConditionVideo::InputFileChanged, this,
|
&MacroConditionVideo::InputFileChanged, this,
|
||||||
@@ -1320,14 +1319,15 @@ void MacroConditionVideoEdit::HandleVideoInputUpdate()
|
|||||||
emit VideoSelectionChanged(_entryData->_video);
|
emit VideoSelectionChanged(_entryData->_video);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MacroConditionVideoEdit::ConditionChanged(int cond)
|
void MacroConditionVideoEdit::ConditionChanged(int idx)
|
||||||
{
|
{
|
||||||
if (_loading || !_entryData) {
|
if (_loading || !_entryData) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto lock = LockContext();
|
auto lock = LockContext();
|
||||||
_entryData->SetCondition(static_cast<VideoCondition>(cond));
|
_entryData->SetCondition(
|
||||||
|
static_cast<VideoCondition>(_condition->itemData(idx).toInt()));
|
||||||
_entryData->ResetLastMatch();
|
_entryData->ResetLastMatch();
|
||||||
SetWidgetVisibility();
|
SetWidgetVisibility();
|
||||||
|
|
||||||
@@ -1384,23 +1384,12 @@ void MacroConditionVideoEdit::ImageBrowseButtonClicked()
|
|||||||
"AdvSceneSwitcher.condition.video.askFileAction"),
|
"AdvSceneSwitcher.condition.video.askFileAction"),
|
||||||
QMessageBox::Yes | QMessageBox::No |
|
QMessageBox::Yes | QMessageBox::No |
|
||||||
QMessageBox::Cancel);
|
QMessageBox::Cancel);
|
||||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
|
||||||
msgBox.setButtonText(
|
|
||||||
QMessageBox::Yes,
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.condition.video.askFileAction.file"));
|
|
||||||
msgBox.setButtonText(
|
|
||||||
QMessageBox::No,
|
|
||||||
obs_module_text(
|
|
||||||
"AdvSceneSwitcher.condition.video.askFileAction.screenshot"));
|
|
||||||
#else
|
|
||||||
auto yes = msgBox.button(QMessageBox::StandardButton::Yes);
|
auto yes = msgBox.button(QMessageBox::StandardButton::Yes);
|
||||||
yes->setText(obs_module_text(
|
yes->setText(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.video.askFileAction.file"));
|
"AdvSceneSwitcher.condition.video.askFileAction.file"));
|
||||||
auto no = msgBox.button(QMessageBox::StandardButton::No);
|
auto no = msgBox.button(QMessageBox::StandardButton::No);
|
||||||
no->setText(obs_module_text(
|
no->setText(obs_module_text(
|
||||||
"AdvSceneSwitcher.condition.video.askFileAction.screenshot"));
|
"AdvSceneSwitcher.condition.video.askFileAction.screenshot"));
|
||||||
#endif
|
|
||||||
msgBox.setWindowFlags(Qt::Window | Qt::WindowTitleHint |
|
msgBox.setWindowFlags(Qt::Window | Qt::WindowTitleHint |
|
||||||
Qt::CustomizeWindowHint);
|
Qt::CustomizeWindowHint);
|
||||||
const auto result = msgBox.exec();
|
const auto result = msgBox.exec();
|
||||||
@@ -1433,8 +1422,8 @@ void MacroConditionVideoEdit::ImageBrowseButtonClicked()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto screenshot =
|
auto screenshot = ScreenshotDialog::AskForScreenshot(
|
||||||
ScreenshotDialog::AskForScreenshot(_entryData->_video);
|
_entryData->_video, _entryData->_areaParameters);
|
||||||
if (!screenshot) {
|
if (!screenshot) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -1603,8 +1592,8 @@ void MacroConditionVideoEdit::UpdateEntryData()
|
|||||||
static_cast<int>(_entryData->_video.type));
|
static_cast<int>(_entryData->_video.type));
|
||||||
_scenes->SetScene(_entryData->_video.scene);
|
_scenes->SetScene(_entryData->_video.scene);
|
||||||
_sources->SetSource(_entryData->_video.source);
|
_sources->SetSource(_entryData->_video.source);
|
||||||
_condition->setCurrentIndex(
|
_condition->setCurrentIndex(_condition->findData(
|
||||||
static_cast<int>(_entryData->GetCondition()));
|
static_cast<int>(_entryData->GetCondition())));
|
||||||
_reduceLatency->setChecked(_entryData->_blockUntilScreenshotDone);
|
_reduceLatency->setChecked(_entryData->_blockUntilScreenshotDone);
|
||||||
_imagePath->SetPath(QString::fromStdString(_entryData->_file));
|
_imagePath->SetPath(QString::fromStdString(_entryData->_file));
|
||||||
_usePatternForChangedCheck->setChecked(
|
_usePatternForChangedCheck->setChecked(
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "opencv-helpers.hpp"
|
#include "opencv-helpers.hpp"
|
||||||
#include "area-selection.hpp"
|
#include "area-selection.hpp"
|
||||||
#include "paramerter-wrappers.hpp"
|
#include "parameter-wrappers.hpp"
|
||||||
#include "preview-dialog.hpp"
|
#include "preview-dialog.hpp"
|
||||||
|
|
||||||
#include <macro-condition-edit.hpp>
|
#include <macro-condition-edit.hpp>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "paramerter-wrappers.hpp"
|
#include "parameter-wrappers.hpp"
|
||||||
|
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
#include <source-helpers.hpp>
|
#include <source-helpers.hpp>
|
||||||
@@ -251,7 +251,8 @@ OCRParameters::OCRParameters(const OCRParameters &other)
|
|||||||
regex(other.regex),
|
regex(other.regex),
|
||||||
color(other.color),
|
color(other.color),
|
||||||
colorThreshold(other.colorThreshold),
|
colorThreshold(other.colorThreshold),
|
||||||
pageSegMode(other.pageSegMode)
|
pageSegMode(other.pageSegMode),
|
||||||
|
languageCode(other.languageCode)
|
||||||
{
|
{
|
||||||
if (!initDone) {
|
if (!initDone) {
|
||||||
Setup();
|
Setup();
|
||||||
@@ -268,6 +269,7 @@ OCRParameters &OCRParameters::operator=(const OCRParameters &other)
|
|||||||
color = other.color;
|
color = other.color;
|
||||||
colorThreshold = other.colorThreshold;
|
colorThreshold = other.colorThreshold;
|
||||||
pageSegMode = other.pageSegMode;
|
pageSegMode = other.pageSegMode;
|
||||||
|
languageCode = other.languageCode;
|
||||||
if (!initDone) {
|
if (!initDone) {
|
||||||
Setup();
|
Setup();
|
||||||
}
|
}
|
||||||
@@ -310,6 +312,7 @@ bool OCRParameters::Load(obs_data_t *obj)
|
|||||||
if (initDone) {
|
if (initDone) {
|
||||||
ocr->SetPageSegMode(pageSegMode);
|
ocr->SetPageSegMode(pageSegMode);
|
||||||
}
|
}
|
||||||
|
Setup();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,6 +332,7 @@ bool OCRParameters::SetLanguageCode(const std::string &value)
|
|||||||
if (!fileInfo.exists(dataPath)) {
|
if (!fileInfo.exists(dataPath)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
languageCode = value;
|
||||||
Setup();
|
Setup();
|
||||||
ocr->SetPageSegMode(pageSegMode);
|
ocr->SetPageSegMode(pageSegMode);
|
||||||
return true;
|
return true;
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user