diff --git a/.gitignore b/.gitignore index 429aa9c1..228c4fbe 100644 --- a/.gitignore +++ b/.gitignore @@ -262,3 +262,4 @@ cython_debug/ /ThirdParty/qml-plausible/ /ThirdParty/ffmpeg/** /ThirdParty/qt-layer-shell/** +/ThirdParty/Godot/Godot_*.* diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index aa18166e..0c7f42da 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,6 +18,7 @@ stages: - check documentation: + dependencies: [] stage: .post script: - curl --request POST --form "token=$CI_JOB_TOKEN" --form ref=master https://gitlab.com/api/v4/projects/15800262/trigger/pipeline diff --git a/.gitlab/ci/base_jobs.yml b/.gitlab/ci/base_jobs.yml index ae441ca1..5b890502 100644 --- a/.gitlab/ci/base_jobs.yml +++ b/.gitlab/ci/base_jobs.yml @@ -4,6 +4,8 @@ - python -m pip install -U pip wheel - python -m pip install -r Tools/requirements.txt - python Tools/setup.py + - git submodule sync --recursive + - git submodule update --init --recursive tags: - windows10 artifacts: @@ -33,11 +35,13 @@ - cd .. - git clone https://invent.kde.org/plasma/layer-shell-qt.git - cd layer-shell-qt - - cmake configure . -DCMAKE_PREFIX_PATH="./../../../aqt/6.5.2/gcc_64" + - cmake configure . -DCMAKE_PREFIX_PATH="./../../../aqt/6.6.1/gcc_64" - make - make install - cd .. - cd .. + - git submodule sync --recursive + - git submodule update --init --recursive image: name: ubuntu:22.04 tags: @@ -53,9 +57,7 @@ - pip3 install -U pip - pip3 install -r Tools/requirements.txt - python3 Tools/setup.py + - git submodule sync --recursive + - git submodule update --init --recursive tags: - osx - artifacts: - expire_in: "2 weeks" - paths: - - build-64-osx-universal-release/bin/ diff --git a/.gitlab/ci/build_jobs.yml b/.gitlab/ci/build_jobs.yml index 5a7821fb..421d11ad 100644 --- a/.gitlab/ci/build_jobs.yml +++ b/.gitlab/ci/build_jobs.yml @@ -10,7 +10,12 @@ standalone_osx: extends: - .base_osx_build script: - - python3 Tools/build.py --type=release --use-aqt --deploy-version --sign_osx + - python3 Tools/build.py --type=release --use-aqt --installer --deploy-version --sign_osx + - mv build-64-osx-universal-release/ScreenPlay-Installer-ScreenPlayComponent.dmg build-64-osx-universal-release/ScreenPlay-Installer.dmg + artifacts: + expire_in: "2 weeks" + paths: + - build-64-osx-universal-release/ScreenPlay-Installer.dmg standalone_linux: stage: build @@ -32,10 +37,14 @@ steam_osx: - .base_osx_build script: - python3 Tools/build.py --type=release -steam --use-aqt --deploy-version --sign_osx + artifacts: + expire_in: "2 weeks" + paths: + - build-64-osx-universal-release/bin/ScreenPlay.app steam_linux: stage: build_steam extends: - .base_linux_build script: - - python3 Tools/build.py --type=release -steam --deploy-version --use-aqt --installer + - python3 Tools/build.py --type=release -steam --use-aqt --deploy-version diff --git a/.gitlab/ci/check_jobs.yml b/.gitlab/ci/check_jobs.yml index f3890288..0cf8d8cc 100644 --- a/.gitlab/ci/check_jobs.yml +++ b/.gitlab/ci/check_jobs.yml @@ -1,18 +1,20 @@ formatting: dependencies: [] stage: check - allow_failure: true image: name: ubuntu:23.10 tags: - gitlab-org-docker - before_script: - - apt-get update -y - - apt-get install python3-pip python-is-python3 clang clang-format -y script: - - python -m pip install -U pip wheel --break-system-packages - - python -m pip install -U cmakelang --break-system-packages + - apt update -y + # For Ubuntu 22.04 and newer we need to create an virutal env + - apt install python3.11 python3.11-venv clang clang-format -y + # Run this command in the ScreenPlay source root folder: + - python3 -m venv env + - source env/bin/activate + - python3 -m pip install -U pip wheel + - python3 -m pip install -U cmakelang - cd Tools - - python check_format_cmake.py --check - - python check_format_cpp.py --check + - python3 check_format_cmake.py --check + - python3 check_format_cpp.py --check #- python check_format_qml.py --check diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..d9f3cdde --- /dev/null +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "ScreenPlayWallpaper/Godot/GDExtention/extern/godot-cpp"] + path = ScreenPlayWallpaper/Godot/GDExtention/extern/godot-cpp + url = https://github.com/godotengine/godot-cpp.git + branch = 4.1 diff --git a/.vscode/extensions.json b/.vscode/extensions.json index d94eeef8..b9fea37c 100644 --- a/.vscode/extensions.json +++ b/.vscode/extensions.json @@ -6,6 +6,9 @@ "ms-vscode.cmake-tools", "seanwu.vscode-qt-for-python", "mhutchie.git-graph", - "vadimcn.vscode-lldb" + "vadimcn.vscode-lldb", + "josetr.cmake-language-support-vscode", + "geequlim.godot-tools", + "stevebushresearch.buildoutputcolorizer" ] } \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json index 74134e24..57905650 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -5,7 +5,7 @@ "version": "0.2.0", "configurations": [ { - "name": "Windows Launch", + "name": "๐ŸชŸ Windows Launch", "type": "cppvsdbg", "request": "launch", "program": "${command:cmake.launchTargetPath}", @@ -17,18 +17,26 @@ "environment": [ { "name": "Path", - "value": "${env:Path};${workspaceFolder}\\..\\aqt\\6.5.2\\msvc2019_64\\bin\\;${workspaceFolder}\\..\\aqt\\6.5.2\\msvc2019_64\\modules\\;${workspaceFolder}\\..\\aqt\\6.5.2\\msvc2019_64\\qml\\;${workspaceFolder}\\..\\vcpkg\\installed\\x64-windows\\debug\\bin;" + "value": "${env:Path};${workspaceFolder}\\..\\aqt\\6.6.1\\msvc2019_64\\bin\\;${workspaceFolder}\\..\\aqt\\6.6.1\\msvc2019_64\\modules\\;${workspaceFolder}\\..\\aqt\\6.6.1\\msvc2019_64\\qml\\;${workspaceFolder}\\..\\vcpkg\\installed\\x64-windows\\debug\\bin;" } ], "visualizerFile": "${workspaceFolder}/.vscode/qt.natvis.xml" }, { - "name": "macOS/linux Launch", + "name": "๐ŸmacOS & ๐Ÿงlinux Launch", "type": "lldb", "request": "launch", "program": "${command:cmake.launchTargetPath}", "args": [], "cwd": "${command:cmake.buildDirectory}/bin", + }, + { + "name": "๐Ÿ Python: Current File", + "type": "python", + "request": "launch", + "program": "${file}", + "console": "integratedTerminal", + "justMyCode": true } ] } \ No newline at end of file diff --git a/.vscode/qt.natvis.xml b/.vscode/qt.natvis.xml index 3dea4083..94c2260d 100644 --- a/.vscode/qt.natvis.xml +++ b/.vscode/qt.natvis.xml @@ -6,14 +6,14 @@ - + {val} val - + @@ -38,32 +38,32 @@ - + {d_ptr.d,na} d_ptr.d - + {{{data1,Xb}-{data2,Xb}-{data3,Xb}-{(data4[0]),nvoXb}{(data4[1]),nvoXb}-{(data4[2]),nvoXb}{(data4[3]),nvoXb}{(data4[4]),nvoXb}{(data4[5]),nvoXb}{(data4[6]),nvoXb}{(data4[7]),nvoXb}}} - + {val} val - + {_q_value} _q_value - + empty @@ -73,8 +73,8 @@ - - + + {{ x = {xp}, y = {yp} }} xp @@ -82,7 +82,7 @@ - + {{ x = {x1}, y = {y1}, width = {x2 - x1 + 1}, height = {y2 - y1 + 1} }} x1 @@ -92,7 +92,7 @@ - + {{ x = {xp}, y = {yp}, width = {w}, height = {h} }} xp @@ -102,8 +102,8 @@ - - + + {{ width = {wd}, height = {ht} }} wd @@ -111,8 +111,8 @@ - - + + {{ start point = {pt1}, end point = {pt2} }} @@ -131,7 +131,7 @@ - + {{ size={d->size} }} d->ref.atomic._q_value @@ -142,7 +142,7 @@ - + {{ size={d->size} }} @@ -160,7 +160,7 @@ - + {{ x = {xp}, y = {yp} }} xp @@ -168,7 +168,7 @@ - + {{ x = {xp}, y = {yp}, z = {zp} }} xp @@ -177,7 +177,7 @@ - + {{ x = {xp}, y = {yp}, z = {zp}, w = {wp} }} xp @@ -187,7 +187,7 @@ - + {{ m11 = {_m11}, m12 = {_m12}, m21 = {_m21}, m22 = {_m22}, ... }} @@ -201,7 +201,7 @@ - + {{ m11 = {m[0][0]}, m12 = {m[1][0]}, m13 = {m[2][0]}, m14 = {m[3][0]}, ... }} @@ -225,7 +225,7 @@ - + {{ horizontal = {static_cast<Policy>(bits.horPolicy)}, vertical = {static_cast<Policy>(bits.verPolicy)}, type = {ControlType(1 << bits.ctype)} }} @@ -256,7 +256,7 @@ - + {ucs,c} ucs,c @@ -265,7 +265,7 @@ - + "{(reinterpret_cast<unsigned short*>(d.ptr)),sub}" (reinterpret_cast<unsigned short*>(d.ptr)),sub @@ -277,7 +277,7 @@ - + {m_string,[m_size]} u"" {m_string->d.ptr+m_position,[m_size]} "" @@ -292,7 +292,7 @@ - + {m_data,[m_size]} m_data,[m_size] @@ -304,7 +304,7 @@ - + "{((reinterpret_cast<char*>(d.ptr))),sb}" ((reinterpret_cast<char*>(d.ptr))),sb @@ -316,7 +316,7 @@ - + @@ -344,11 +344,11 @@ - + {{ julian day = {jd} }} - + @@ -375,7 +375,7 @@ - + ({first}, {second}) first @@ -383,8 +383,8 @@ - - + + {{ size={d.size} }} @@ -394,7 +394,7 @@ - + {{ size={s} }} a @@ -405,8 +405,8 @@ - - + + {{ size={d.d->m._Mypair._Myval2._Myval2._Mysize} }} @@ -423,7 +423,7 @@ {second} - + {value} key @@ -431,7 +431,7 @@ - + {value->value} ({value->value}, {value->next->value}) ({value->value}, {value->next->value}, ...) @@ -444,8 +444,8 @@ - - + + @@ -602,15 +602,15 @@ - + {{ size={q_hash.d->size} }} q_hash - - + + @@ -620,115 +620,115 @@ (null) - QObject* + QObject* - {*(QMap<QString,QVariant>*) sharedDataStar()} - {*(QList<QVariant>*) sharedDataStar()} - {*(QHash<QString,QVariant>*) sharedDataStar()} - QVariantPair - {*(QList<QByteArray>*) sharedDataStar()} - {*(QList<QString>*) sharedDataStar()} + {*(QMap<QString,QVariant>*) sharedDataStar()} + {*(QList<QVariant>*) sharedDataStar()} + {*(QHash<QString,QVariant>*) sharedDataStar()} + QVariantPair + {*(QList<QByteArray>*) sharedDataStar()} + {*(QList<QString>*) sharedDataStar()} - {*(bool*) dataStar()} - {*(int*) dataStar()} - {*(unsigned int*) dataStar()} - {*(long long*) dataStar()} - {*(unsigned long long*) dataStar()} - {*(double*) dataStar()} - {*(void**) dataStar()} - {*(long*) dataStar()} - {*(short*) dataStar()} - {*(char*) dataStar()} - {*(char16_t*) dataStar()} - {*(char32_t*) dataStar()} - {*(unsigned long*) dataStar()} - {*(unsigned short*) dataStar()} - {*(unsigned char*) dataStar()} - {*(float*) dataStar()} - {*(signed char*) dataStar()} + {*(bool*) dataStar()} + {*(int*) dataStar()} + {*(unsigned int*) dataStar()} + {*(long long*) dataStar()} + {*(unsigned long long*) dataStar()} + {*(double*) dataStar()} + {*(void**) dataStar()} + {*(long*) dataStar()} + {*(short*) dataStar()} + {*(char*) dataStar()} + {*(char16_t*) dataStar()} + {*(char32_t*) dataStar()} + {*(unsigned long*) dataStar()} + {*(unsigned short*) dataStar()} + {*(unsigned char*) dataStar()} + {*(float*) dataStar()} + {*(signed char*) dataStar()} - {*(QChar*) sharedDataStar()} - {*(QString*) sharedDataStar()} - {*(QByteArray*) sharedDataStar()} - {*(QDate*) sharedDataStar()} - {*(QTime*) sharedDataStar()} - QDateTime - QUrl - QLocale - {*(QRect*) sharedDataStar()} - {*(QRectF*) sharedDataStar()} - {*(QSize*) sharedDataStar()} - {*(QSizeF*) sharedDataStar()} - {*(QLine*) sharedDataStar()} - {*(QLineF*) sharedDataStar()} - {*(QPoint*) sharedDataStar()} - {*(QPointF*) sharedDataStar()} - EasingCurve - Uuid - RegularExpression - QJsonValue - QJsonObject - QJsonArray - QJsonDocument - QCborValue - QCborArray - QCborMap - ModelIndex - QPersistentModelIndex + {*(QChar*) sharedDataStar()} + {*(QString*) sharedDataStar()} + {*(QByteArray*) sharedDataStar()} + {*(QDate*) sharedDataStar()} + {*(QTime*) sharedDataStar()} + QDateTime + QUrl + QLocale + {*(QRect*) sharedDataStar()} + {*(QRectF*) sharedDataStar()} + {*(QSize*) sharedDataStar()} + {*(QSizeF*) sharedDataStar()} + {*(QLine*) sharedDataStar()} + {*(QLineF*) sharedDataStar()} + {*(QPoint*) sharedDataStar()} + {*(QPointF*) sharedDataStar()} + EasingCurve + Uuid + RegularExpression + QJsonValue + QJsonObject + QJsonArray + QJsonDocument + QCborValue + QCborArray + QCborMap + ModelIndex + QPersistentModelIndex - QFont - QPixmap - QBrush - QColor - QPalette - QIcon - QImage - QPolygon - QRegion - QBitmap - QCursor - QKeySequence - QPen - QTextLength - QTextFormat - QTransform - QMatrix4x4 - QVector2D - QVector3D - QVector4D - QQuaternion - QPolygonF - QColorSpace + QFont + QPixmap + QBrush + QColor + QPalette + QIcon + QImage + QPolygon + QRegion + QBitmap + QCursor + QKeySequence + QPen + QTextLength + QTextFormat + QTransform + QMatrix4x4 + QVector2D + QVector3D + QVector4D + QQuaternion + QPolygonF + QColorSpace - QSizePolicy + QSizePolicy - ##NAMESPACE##::QMetaType::Type ({typeId()}) + QMetaType::Type ({typeId()}) - *(QString*) sharedDataStar() - *(QByteArray*) sharedDataStar() - *(QDate*) sharedDataStar() - *(QTime*) sharedDataStar() - *(QRect*) sharedDataStar() - *(QRectF*) sharedDataStar() - *(QSize*) sharedDataStar() - *(QSizeF*) sharedDataStar() - *(QLine*) sharedDataStar() - *(QLineF*) sharedDataStar() - *(QPoint*) sharedDataStar() - *(QPointF*) sharedDataStar() + *(QString*) sharedDataStar() + *(QByteArray*) sharedDataStar() + *(QDate*) sharedDataStar() + *(QTime*) sharedDataStar() + *(QRect*) sharedDataStar() + *(QRectF*) sharedDataStar() + *(QSize*) sharedDataStar() + *(QSizeF*) sharedDataStar() + *(QLine*) sharedDataStar() + *(QLineF*) sharedDataStar() + *(QPoint*) sharedDataStar() + *(QPointF*) sharedDataStar() - *(QMap<QString,QVariant>*) sharedDataStar() - *(QList<QVariant>*) sharedDataStar() - *(QHash<QString,QVariant>*) sharedDataStar() - *(QList<QByteArray>*) sharedDataStar() - *(QList<QString>*) sharedDataStar() + *(QMap<QString,QVariant>*) sharedDataStar() + *(QList<QVariant>*) sharedDataStar() + *(QHash<QString,QVariant>*) sharedDataStar() + *(QList<QByteArray>*) sharedDataStar() + *(QList<QString>*) sharedDataStar() diff --git a/.vscode/tasks.json b/.vscode/tasks.json index a6b91c44..ab23c178 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -15,61 +15,7 @@ }, { "type": "process", - "label": "Format Cpp files", - "command": "python3", - "windows": { - "command": "python" - }, - "group": { - "kind": "build", - "isDefault": true - }, - "options": { - "cwd": "${workspaceFolder}/Tools" - }, - "args": [ - "check_format_cpp.py" - ] - }, - { - "type": "process", - "label": "Format CMake files", - "command": "python3", - "windows": { - "command": "python" - }, - "group": { - "kind": "build", - "isDefault": true - }, - "options": { - "cwd": "${workspaceFolder}/Tools" - }, - "args": [ - "check_format_cmake.py" - ] - }, - { - "type": "process", - "label": "Format Qml files", - "command": "python3", - "windows": { - "command": "python" - }, - "group": { - "kind": "build", - "isDefault": true - }, - "options": { - "cwd": "${workspaceFolder}/Tools" - }, - "args": [ - "check_format_qml.py" - ] - }, - { - "type": "process", - "label": "Run setup.py", + "label": "๐Ÿ›ซ Run setup.py", "command": "python3", "windows": { "command": "python" @@ -87,7 +33,27 @@ }, { "type": "process", - "label": "Build ScreenPlay release, with deploy and steam enabled", + "label": "โš™๏ธ Build Godot Wallpaper", + "command": "python3", + "windows": { + "command": "python" + }, + "group": { + "kind": "build", + "isDefault": true + }, + "options": { + "cwd": "${workspaceFolder}/Tools" + }, + "args": [ + "build_godot.py", + "--build_path", + "${command:cmake.buildDirectory}/bin" + ] + }, + { + "type": "process", + "label": "โš™๏ธ Build ScreenPlay release, with deploy and steam enabled", "command": "python3", "windows": { "command": "python" @@ -116,7 +82,61 @@ }, { "type": "process", - "label": "Update Qt *.ts translations", + "label": "๐Ÿ“ƒ Format Cpp files", + "command": "python3", + "windows": { + "command": "python" + }, + "group": { + "kind": "build", + "isDefault": true + }, + "options": { + "cwd": "${workspaceFolder}/Tools" + }, + "args": [ + "check_format_cpp.py" + ] + }, + { + "type": "process", + "label": "๐Ÿ“ƒ Format CMake files", + "command": "python3", + "windows": { + "command": "python" + }, + "group": { + "kind": "build", + "isDefault": true + }, + "options": { + "cwd": "${workspaceFolder}/Tools" + }, + "args": [ + "check_format_cmake.py" + ] + }, + { + "type": "process", + "label": "๐Ÿ“ƒ Format Qml files", + "command": "python3", + "windows": { + "command": "python" + }, + "group": { + "kind": "build", + "isDefault": true + }, + "options": { + "cwd": "${workspaceFolder}/Tools" + }, + "args": [ + "check_format_qml.py" + ] + }, + { + "type": "process", + "label": "๐Ÿ—จ๏ธ Update Qt *.ts translations", "command": "python3", "windows": { "command": "python" diff --git a/CMake/CMakeVariables.h.in b/CMake/CMakeVariables.h.in index fa665fc0..930271db 100644 --- a/CMake/CMakeVariables.h.in +++ b/CMake/CMakeVariables.h.in @@ -1,3 +1,14 @@ #pragma once -#define SCREENPLAY_SOURCE_DIR "@SOURCE_DIR@" \ No newline at end of file +#define SCREENPLAY_VERSION "@SCREENPLAY_VERSION@" +#define SCREENPLAY_SOURCE_DIR "@SCREENPLAY_SOURCE_DIR@" +#define SCREENPLAY_GODOT_VERSION "@SCREENPLAY_GODOT_VERSION@" +#define SCREENPLAY_GODOT_VERSION_MAJOR @SCREENPLAY_GODOT_VERSION_MAJOR@ +#define SCREENPLAY_GODOT_VERSION_MINOR @SCREENPLAY_GODOT_VERSION_MINOR@ +#define SCREENPLAY_GODOT_RELEASE_TYPE "@SCREENPLAY_GODOT_RELEASE_TYPE@" +#define SCREENPLAY_BUILD_TYPE "@SCREENPLAY_BUILD_TYPE@" +#define SCREENPLAY_GIT_BRANCH_NAME "@SCREENPLAY_GIT_BRANCH_NAME@" +#define SCREENPLAY_GIT_COMMIT_HASH "@SCREENPLAY_GIT_COMMIT_HASH@" +#define SCREENPLAY_DEPLOY_VERSION @SCREENPLAY_DEPLOY_VERSION@ +#define SCREENPLAY_BUILD_DATE "@SCREENPLAY_BUILD_DATE@" +#define SCREENPLAY_STEAM_VERSION @SCREENPLAY_STEAM_VERSION@ diff --git a/CMake/CopyRecursive.cmake b/CMake/CopyRecursive.cmake index aecf3c76..9368e4d7 100644 --- a/CMake/CopyRecursive.cmake +++ b/CMake/CopyRecursive.cmake @@ -22,7 +22,7 @@ function(copy_recursive SOURCE_PATH DESTINATION_PATH REGEX) file(RELATIVE_PATH RELATIVE_FILE_PATH ${SOURCE_PATH} ${file}) get_filename_component(FOLDER ${RELATIVE_FILE_PATH} DIRECTORY ${SOURCE_PATH}) file(MAKE_DIRECTORY ${DESTINATION_PATH}/${FOLDER} ) - message(STATUS "${file} - ${DESTINATION_PATH}/${RELATIVE_FILE_PATH}") + #message(STATUS "${file} - ${DESTINATION_PATH}/${RELATIVE_FILE_PATH}") configure_file(${file} "${DESTINATION_PATH}/${RELATIVE_FILE_PATH}" COPYONLY) endforeach() diff --git a/CMake/CreateDmgInstaller.cmake b/CMake/CreateDmgInstaller.cmake index 15c87e64..89ce9ff7 100644 --- a/CMake/CreateDmgInstaller.cmake +++ b/CMake/CreateDmgInstaller.cmake @@ -1,22 +1,41 @@ message(STATUS "[DMG INSTALLER ENABLED]: Configuring. This can take some time...") + +set(CPACK_PACKAGE_VENDOR "Elias Steurer Tachiom") +set(CPACK_PACKAGE_NAME "ScreenPlay") +set(CPACK_PACKAGE_CONTACT "Elias Steurer ") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "ScreenPlay is an Open Source Live-Wallpaper app for Windows and OSX. ") +set(CPACK_PACKAGE_DESCRIPTION_FILE "${PROJECT_SOURCE_DIR}/README.md") +set(CPACK_RESOURCE_FILE_LICENSE "${PROJECT_SOURCE_DIR}/LICENSE") +set(CPACK_PACKAGE_VERSION_MAJOR ${PROJECT_VERSION_MAJOR}) +set(CPACK_PACKAGE_VERSION_MINOR ${PROJECT_VERSION_MINOR}) +set(CPACK_PACKAGE_VERSION_PATCH ${PROJECT_VERSION_PATCH}) + set(CPACK_GENERATOR "DragNDrop") -set(CPACK_DMG_FORMAT "UDBZ") -set(CPACK_DMG_VOLUME_NAME "ScreenPlay") +set(MACOSX_BUNDLE_BUNDLE_NAME ${CPACK_PACKAGE_NAME}) +set(MACOSX_BUNDLE_BUNDLE_GUI_IDENTIFIER "app.screenplay.screenplay") +set(CPACK_DMG_VOLUME_NAME ${CPACK_PACKAGE_NAME}) set(CPACK_SYSTEM_NAME "OSX") -set(CPACK_PACKAGE_ICON "${CMAKE_SOURCE_DIR}/ScreenPlay/assets/icons/app.ico") set(CPACK_COMPONENTS_GROUPING IGNORE) -set(CPACK_PACKAGE_NAME "ScreenPlay") +set(CPACK_PACKAGING_INSTALL_PREFIX "/") set(CPACK_PACKAGE_FILE_NAME "ScreenPlay-Installer") -set(CPACK_PACKAGE_VENDOR "Elias Steurer") -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "${PROJECT_DESCRIPTION}") -set(CPACK_PACKAGE_DIRECTORY "${CMAKE_BINARY_DIR}") +set(CPACK_COMPONENTS_ALL "ScreenPlayComponent") +set(CPACK_ARCHIVE_COMPONENT_INSTALL ON) +set(CPACK_COMPONENTS_ALL_IN_ONE_PACKAGE ON) -include(CPack) +set(MACOSX_BUNDLE_BUNDLE_VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}") +set(MACOSX_BUNDLE_ICON_FILE "${CMAKE_SOURCE_DIR}/ScreenPlay/assets/icons/ScreenPlay.icns") +set(CPACK_DMG_DS_STORE_SETUP_SCRIPT "${CMAKE_SOURCE_DIR}/CMake/DS_Store.scpt") +set(CPACK_DMG_BACKGROUND_IMAGE "${CMAKE_SOURCE_DIR}/CMake/dmg_background.png") +set(MACOSX_BUNDLE_INFO_PLIST "${CMAKE_SOURCE_DIR}/CMake/MacOSXBundleInfo.plist.in") + +set_source_files_properties(${CMAKE_SOURCE_DIR}/CMake/exampleApp.icns PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") # Install all files from /bin install( DIRECTORY "${CMAKE_BINARY_DIR}/bin/" - COMPONENT ScreenPlay - DESTINATION "./") \ No newline at end of file + COMPONENT ScreenPlayComponent + DESTINATION "./") + +include(CPack) diff --git a/CMake/DS_Store.scpt b/CMake/DS_Store.scpt new file mode 100644 index 00000000..8f2fed73 --- /dev/null +++ b/CMake/DS_Store.scpt @@ -0,0 +1,41 @@ +on run argv + -- Constants for window dimensions + + set BG_W to 780 + set BG_H to 390 + set TITLE_BAR_H to 22 + + set diskImage to item 1 of argv + + tell application "Finder" + tell disk diskImage + -- Must call open and close to set window options later + open + -- Setup background and icon arrangement + set current view of container window to icon view + set theViewOptions to the icon view options of container window + -- Note: CMake automatically renames the file to background. + set background picture of theViewOptions to file ".background:background.png" + set arrangement of theViewOptions to not arranged + set icon size of theViewOptions to 72 + + -- Attempt to hide sidebar and toolbar + set toolbar visible of container window to false + set statusbar visible of container window to false + set sidebar width of container window to 0 + + -- Get current position of the window + set {currentX, currentY} to position of container window + -- Set the new bounds of the window + set bounds of container window to {currentX, currentY, currentX + BG_W, currentY + BG_H + TITLE_BAR_H} + -- Set icon positions + set position of item "ScreenPlay.app" to {137, 99} + set position of item "Applications" to {287, 99} + + -- Update and apply changes + update without registering applications + delay 5 + close + end tell + end tell +end run diff --git a/CMake/GenerateCMakeVariableHeader.cmake b/CMake/GenerateCMakeVariableHeader.cmake index 7fd241f1..1329b2c2 100644 --- a/CMake/GenerateCMakeVariableHeader.cmake +++ b/CMake/GenerateCMakeVariableHeader.cmake @@ -1,16 +1,42 @@ -#! generate_cmake_variable_header : Generates a header CmakeVariables.h that contains defines for the variables specified in CmakeVariables.h.in! +# ! generate_cmake_variable_header : Generates a header CmakeVariables.h that contains defines for the variables specified in +# CmakeVariables.h.in! # # The generated CmakeVariables.h header can then be used to access e.g. the PROJECT_NAME define in C++ code. # -# Example -# generate_cmake_variable_header(${PROJECT_NAME}) +# Example generate_cmake_variable_header(${PROJECT_NAME}) # function(generate_cmake_variable_header TARGET) - set(SOURCE_DIR ${CMAKE_SOURCE_DIR}) + # โš ๏ธ Also add to CMakeVariables.h.in โš ๏ธ + + set(SCREENPLAY_SOURCE_DIR ${CMAKE_SOURCE_DIR}) + # Like v4.2-beta3 or v5.0.1-stable + set(SCREENPLAY_GODOT_VERSION ${GODOT_VERSION}) + # Only single numbers + set(SCREENPLAY_GODOT_VERSION_MAJOR ${GODOT_VERSION_MAJOR}) + set(SCREENPLAY_GODOT_VERSION_MINOR ${GODOT_VERSION_MINOR}) + # stable, rc1 or beta5 + set(SCREENPLAY_GODOT_RELEASE_TYPE ${GODOT_RELEASE_TYPE}) + set(SCREENPLAY_BUILD_TYPE "${CMAKE_BUILD_TYPE}") + set(SCREENPLAY_BUILD_DATE "${BUILD_DATE}") + set(SCREENPLAY_VERSION "${SCREENPLAY_VERSION}") + set(SCREENPLAY_GIT_BRANCH_NAME "${GIT_BRANCH_NAME}") + set(SCREENPLAY_GIT_COMMIT_HASH "${GIT_COMMIT_HASH}") + + set(SCREENPLAY_DEPLOY_VERSION 0) + if(${SCREENPLAY_DEPLOY}) + set(SCREENPLAY_DEPLOY_VERSION 1) + endif() + + set(SCREENPLAY_STEAM_VERSION 0) + if(${SCREENPLAY_STEAM}) + set(SCREENPLAY_STEAM_VERSION 1) + endif() # Specify the configuration file from which the header file will be generated configure_file(${CMAKE_SOURCE_DIR}/CMake/CMakeVariables.h.in ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/CMakeVariables.h @ONLY) - message(STATUS "GENERATE: ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/CMakeVariables.h and add ${TARGET} to ${CMAKE_CURRENT_BINARY_DIR}") + message( + STATUS "GENERATE: ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}/CMakeVariables.h and add ${TARGET} to ${CMAKE_CURRENT_BINARY_DIR}") + # Add the directory containing the generated header target_include_directories(${TARGET} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) endfunction() diff --git a/CMake/MacOSXBundleInfo.plist.in b/CMake/MacOSXBundleInfo.plist.in new file mode 100644 index 00000000..e5447fc9 --- /dev/null +++ b/CMake/MacOSXBundleInfo.plist.in @@ -0,0 +1,36 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleGetInfoString + ${MACOSX_BUNDLE_INFO_STRING} + CFBundleIconFile + ${MACOSX_BUNDLE_ICON_FILE} + CFBundleIdentifier + ${MACOSX_BUNDLE_GUI_IDENTIFIER} + CFBundleInfoDictionaryVersion + 6.0 + CFBundleLongVersionString + ${MACOSX_BUNDLE_LONG_VERSION_STRING} + CFBundleName + ${MACOSX_BUNDLE_BUNDLE_NAME} + CFBundlePackageType + APPL + CFBundleShortVersionString + ${MACOSX_BUNDLE_SHORT_VERSION_STRING} + CFBundleSignature + ???? + CFBundleVersion + ${MACOSX_BUNDLE_BUNDLE_VERSION} + NSHumanReadableCopyright + ${MACOSX_BUNDLE_COPYRIGHT} + NSHighResolutionCapable + True + NSSupportsAutomaticGraphicsSwitching + + + diff --git a/CMake/dmg_background.png b/CMake/dmg_background.png new file mode 100755 index 00000000..9ff37b72 Binary files /dev/null and b/CMake/dmg_background.png differ diff --git a/CMakeLists.txt b/CMakeLists.txt index 72c74ebe..0a04297b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,11 +2,18 @@ cmake_minimum_required(VERSION 3.22.0) set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH}) include(GetProjectVersion) -get_project_version(PROJECT_VERSION) +get_project_version(SCREENPLAY_VERSION) + +# This must be set before project() +if(APPLE) + set(CMAKE_OSX_ARCHITECTURES + "arm64;x86_64" + CACHE STRING "" FORCE) +endif() project( ScreenPlay - VERSION ${PROJECT_VERSION} + VERSION ${SCREENPLAY_VERSION} DESCRIPTION "Modern, Cross Plattform, Live Wallpaper, Widgets and AppDrawer!" HOMEPAGE_URL "https://screen-play.app/" LANGUAGES CXX) @@ -27,13 +34,6 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_CXX_STANDARD 20) set(THIRD_PARTY_PATH "${CMAKE_CURRENT_SOURCE_DIR}/ThirdParty") set(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake" ${CMAKE_MODULE_PATH}) -list(APPEND CMAKE_MODULE_PATH "${THIRD_PARTY_PATH}/ecm/modules") -list(APPEND CMAKE_MODULE_PATH "${THIRD_PARTY_PATH}/ecm/find-modules") -list(APPEND CMAKE_MODULE_PATH "${THIRD_PARTY_PATH}/ecm/kde-modules") -message(STATUS "[PROJECT] CMAKE_MODULE_PATH = ${CMAKE_MODULE_PATH}") - - -option(OSX_BUNDLE "Enable distribution macOS bundle" OFF) set(CMAKE_OSX_DEPLOYMENT_TARGET "13.0") # This is needed for OSX: Because we bundle ScreenPlay and ScreenPlayWallpaper into .app they both need other QML dependencies like @@ -45,7 +45,6 @@ set(CMAKE_OSX_DEPLOYMENT_TARGET "13.0") set(SCREENPLAY_QML_MODULES_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/qml") if(APPLE) - set(CMAKE_OSX_ARCHITECTURES "x86_64;arm64") set(SCREENPLAY_QML_MODULES_PATH "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ScreenPlay.app/Contents/MacOS/qml") endif() @@ -59,11 +58,37 @@ set(VCPKG_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../vcpkg") set(VCPKG_INSTALLED_PATH "${VCPKG_PATH}/installed/${VCPKG_ARCH}") set(VCPKG_BIN_PATH "${VCPKG_INSTALLED_PATH}/bin") +# Godot Editor +set(GODOT_VERSION_MAJOR "4") +set(GODOT_VERSION_MINOR "2") +set(GODOT_VERSION_PATCH "") +set(GODOT_RELEASE_TYPE "stable") + +# Use an if statement to check if GODOT_VERSION_PATCH is empty or not +if(GODOT_VERSION_PATCH STREQUAL "") + # If patch version is empty, don't include it and the preceding dot + set(GODOT_VERSION "v${GODOT_VERSION_MAJOR}.${GODOT_VERSION_MINOR}-${GODOT_RELEASE_TYPE}") +else() + # If patch version is not empty, include it and the preceding dot + set(GODOT_VERSION "v${GODOT_VERSION_MAJOR}.${GODOT_VERSION_MINOR}.${GODOT_VERSION_PATCH}-${GODOT_RELEASE_TYPE}") +endif() + +if(WIN32) + set(GODOT_EDITOR_NAME "Godot_${GODOT_VERSION}_win64.exe") +elseif(APPLE) + set(GODOT_EDITOR_NAME "Godot.app") +elseif(UNIX) + set(GODOT_EDITOR_NAME "Godot_${GODOT_VERSION}_linux.x86_64") +else() + message(FATAL_ERROR "Unsupported OS") +endif() + option(SCREENPLAY_STEAM "For FOSS distribution so we do not bundle proprietary code." ON) option(SCREENPLAY_DEPLOY "Marks this version as an official deploy version. This version uses different import paths and other settings." OFF) option(SCREENPLAY_TESTS "Enables UI tests." ON) option(SCREENPLAY_INSTALLER "Indicates whether an installer via the Qt Installer Framework is created." OFF) +option(SCREENPLAY_GODOT "Compiles ScreenPlayGodotWallpaper." ON) # Gitlab CI has many ENV variables. We use this one to check if the current build happens inside the CI if(DEFINED ENV{CI_COMMIT_MESSAGE}) @@ -72,13 +97,8 @@ endif() file(MAKE_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) -add_compile_definitions(COMPILE_INFO="Build Date: ${BUILD_DATE}. Git Hash: ${GIT_COMMIT_HASH}. ") -add_compile_definitions(SOURCE_DIR="${CMAKE_CURRENT_SOURCE_DIR}") -if(${SCREENPLAY_DEPLOY}) - add_compile_definitions(DEPLOY_VERSION) -endif() - find_package(Git REQUIRED) + if(WIN32) set(DATE_COMMAND "CMD") set(DATE_ARG "/c date /t") @@ -87,14 +107,12 @@ else() set(DATE_ARG "") endif() - if(UNIX AND NOT APPLE) # Fixes QWebEngine linker errors on Ubuntu 22.04 set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fuse-ld=gold") endif() - execute_process( COMMAND ${DATE_COMMAND} ${DATE_ARG} WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" @@ -113,24 +131,21 @@ execute_process( OUTPUT_VARIABLE GIT_COMMIT_HASH OUTPUT_STRIP_TRAILING_WHITESPACE) -add_compile_definitions(BUILD_TYPE="${CMAKE_BUILD_TYPE}") -add_compile_definitions(BUILD_DATE="${BUILD_DATE}") -add_compile_definitions(GIT_BRANCH_NAME="${GIT_BRANCH_NAME}") -add_compile_definitions(GIT_COMMIT_HASH="${GIT_COMMIT_HASH}") +if(${SCREENPLAY_TESTS}) + enable_testing() +endif() + +if(UNIX AND NOT APPLE) + # Needs to be append, because we include ecm as third party on linux + set(ECM_DIR "${THIRD_PARTY_PATH}/ecm") + list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake") + list(APPEND CMAKE_MODULE_PATH "${ECM_DIR}") + list(APPEND CMAKE_MODULE_PATH "${ECM_DIR}/cmake") +endif() add_subdirectory(ThirdParty) -set(ECM_DIR "${THIRD_PARTY_PATH}/ecm") add_subdirectory(CMake) -if(UNIX AND NOT APPLE) - # Needs to be append, because we include ecm as third party on linux - list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMake") - list(APPEND CMAKE_MODULE_PATH "${ECM_DIR}") - list(APPEND CMAKE_MODULE_PATH "${ECM_DIR}/cmake") -else() - -endif() add_subdirectory(Tools) - add_subdirectory(ScreenPlay) add_subdirectory(ScreenPlaySDK) add_subdirectory(ScreenPlayShader) @@ -139,12 +154,13 @@ add_subdirectory(ScreenPlayWidget) add_subdirectory(ScreenPlayUtil) add_subdirectory(ScreenPlayWeather) -if(${SCREENPLAY_TESTS}) - enable_testing() +if(${SCREENPLAY_GODOT}) + add_subdirectory(ScreenPlayWallpaper/Godot) endif() # Only add target SteamSDKQtEnums add_subdirectory(ScreenPlayWorkshop/SteamSDK) + if(${SCREENPLAY_STEAM}) add_subdirectory(ScreenPlayWorkshop) endif() @@ -161,7 +177,7 @@ if(${SCREENPLAY_INSTALLER}) endif() endif() -message(STATUS "[PROJECT] PROJECT_VERSION = ${PROJECT_VERSION}") +message(STATUS "[PROJECT] CMAKE_MODULE_PATH = ${CMAKE_MODULE_PATH}") message(STATUS "[PROJECT] CMAKE_VERSION = ${CMAKE_VERSION}") message(STATUS "[PROJECT] SCREENPLAY_QML_MODULES_PATH = ${SCREENPLAY_QML_MODULES_PATH}") message(STATUS "[PROJECT] CMAKE_TOOLCHAIN_FILE = ${CMAKE_TOOLCHAIN_FILE}") @@ -169,10 +185,14 @@ message(STATUS "[PROJECT] VCPKG_PATH = ${VCPKG_PATH}") message(STATUS "[PROJECT] CMAKE_MODULE_PATH = ${CMAKE_MODULE_PATH}") message(STATUS "[PROJECT] VCPKG_TARGET_TRIPLET = ${VCPKG_TARGET_TRIPLET}") message(STATUS "[PROJECT] CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}") +message(STATUS "[PROJECT] GODOT_VERSION = ${GODOT_VERSION}") +message(STATUS "[PROJECT] GODOT_EDITOR_NAME = ${GODOT_EDITOR_NAME}") +message(STATUS "[PROJECT] SCREENPLAY_VERSION = ${SCREENPLAY_VERSION}") message(STATUS "[OPTION] SCREENPLAY_DEPLOY = ${SCREENPLAY_DEPLOY}") message(STATUS "[OPTION] SCREENPLAY_INSTALLER = ${SCREENPLAY_INSTALLER}") message(STATUS "[OPTION] SCREENPLAY_STEAM = ${SCREENPLAY_STEAM}") message(STATUS "[OPTION] SCREENPLAY_TESTS = ${SCREENPLAY_TESTS}") +message(STATUS "[OPTION] SCREENPLAY_GODOT = ${SCREENPLAY_GODOT}") message(STATUS "[DEFINE] BUILD_TYPE = ${CMAKE_BUILD_TYPE}") message(STATUS "[DEFINE] GIT_COMMIT_HASH = ${GIT_COMMIT_HASH}") message(STATUS "[CPP DEFINE] DEPLOY_VERSION = ${DEPLOY_VERSION}") diff --git a/CMakePresets.json b/CMakePresets.json index 9c69b60e..f75a1b54 100644 --- a/CMakePresets.json +++ b/CMakePresets.json @@ -1,194 +1,213 @@ { - "version": 5, - "cmakeMinimumRequired": { - "major": 3, - "minor": 23, - "patch": 0 - }, - "configurePresets": [ - { - "name": "default-windows", - "displayName": "ScreenPlay 64bit Windows", - "description": "Windows only!", - "generator": "Ninja", - "hidden": true, - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Windows" - }, - "environment": { - "qt_path": "${sourceDir}/../aqt", - "qt_version": "6.5.2" - }, - "toolset": { - "value": "host=x64", - "strategy": "external" - }, - "architecture": { - "value": "x64", - "strategy": "external" - }, - "cacheVariables": { - "CMAKE_PREFIX_PATH": "$env{qt_path}/$env{qt_version}/msvc2019_64", - "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../vcpkg/scripts/buildsystems/vcpkg.cmake", - "VCPKG_TARGET_TRIPLET": "x64-windows", - "CMAKE_C_COMPILER": "cl.exe", - "CMAKE_CXX_COMPILER": "cl.exe" - } + "version": 5, + "cmakeMinimumRequired": { + "major": 3, + "minor": 23, + "patch": 0 }, - { - "name": "windows-debug-qt-6.5.2", - "inherits": "default-windows", - "displayName": "MSVC SP Qt 6.5.2 Debug", - "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.5.2_MSVC_Debug", - "environment": { - "qt_version": "6.5.2" - }, - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Debug" - } - }, - { - "name": "windows-relwithdebinfo-qt-6.5.2", - "inherits": "default-windows", - "displayName": "MSVC SP Qt 6.5.2 RelWithDebInfo", - "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.5.2_MSVC_RelWithDebInfo", - "environment": { - "qt_version": "6.5.2" - }, - "cacheVariables": { - "CMAKE_BUILD_TYPE": "RelWithDebInfo" - } - }, - { - "name": "windows-release-qt-6.5.2", - "inherits": "default-windows", - "displayName": "MSVC SP Qt 6.5.2 Release", - "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.5.2_MSVC_Release", - "environment": { - "qt_version": "6.5.2" - }, - "cacheVariables": { - "CMAKE_BUILD_TYPE": "Release" - } - }, - { - "name": "linux-generic-debug", - "displayName": "ScreenPlay 64bit Debug Linux", - "description": "Linux only!", - "generator": "Ninja", - "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.5.2_GCC_Debug", - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Linux" - }, - "architecture": { - "value": "x64", - "strategy": "external" - }, - "cacheVariables": { - "CMAKE_CXX_COMPILER": "g++", - "CMAKE_C_COMPILER": "gcc", - "CMAKE_BUILD_TYPE": "Debug", - "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../vcpkg/scripts/buildsystems/vcpkg.cmake", - "VCPKG_TARGET_TRIPLET": "x64-linux", - "SCREENPLAY_STEAM": "OFF", - "SCREENPLAY_TESTS": "OFF" - } - }, - { - "name": "linux-relwithdebinfo", - "displayName": "ScreenPlay 64bit RelWithDebInfo Linux", - "inherits": "linux-generic-debug", - "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.5.2_GCC_RelWithDebInfo", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "RelWithDebInfo" - } - }, - { - "name": "linux-aqt-debug", - "displayName": "ScreenPlay 64bit Debug Linux using aqt", - "description": "Linux only!", - "generator": "Ninja", - "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.5.2_GCC_Debug", - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Linux" - }, - "environment": { - "qt_path": "${sourceDir}/../aqt" - }, - "architecture": { - "value": "x64", - "strategy": "external" - }, - "cacheVariables": { - "CMAKE_CXX_COMPILER": "g++", - "CMAKE_C_COMPILER": "gcc", - "CMAKE_BUILD_TYPE": "Debug", - "CMAKE_PREFIX_PATH": "$env{qt_path}/6.5.2/gcc_64", - "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../vcpkg/scripts/buildsystems/vcpkg.cmake", - "VCPKG_TARGET_TRIPLET": "x64-linux" - } - }, - { - "name": "linux-aqt-relwithdebinfo", - "displayName": "ScreenPlay 64bit RelWithDebInfo Linux using aqt", - "inherits": "linux-ubuntu-debug", - "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.5.2_GCC_RelWithDebInfo", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "RelWithDebInfo" - } - }, - { - "name": "osx-debug", - "displayName": "ScreenPlay 64bit Debug osx", - "description": "Osx only!", - "generator": "Ninja", - "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.5.2_Clang_Debug", - "condition": { - "type": "equals", - "lhs": "${hostSystemName}", - "rhs": "Darwin" - }, - "environment": { - "qt_path": "${sourceDir}/../aqt" - }, - "cacheVariables": { - "VCPKG_OSX_ARCHITECTURES": "arm64;x86_64", - "VCPKG_TARGET_TRIPLET": "64-osx-universal", - "CMAKE_CXX_COMPILER": "clang++", - "CMAKE_C_COMPILER": "clang", - "CMAKE_BUILD_TYPE": "Debug", - "CMAKE_PREFIX_PATH": "$env{qt_path}/6.5.2/macos", - "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../vcpkg/scripts/buildsystems/vcpkg.cmake" - } - }, - { - "name": "osx-relwithdebinfo", - "displayName": "ScreenPlay 64bit RelWithDebInfo osx", - "inherits": "osx-debug", - "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.5.2_Clang_RelWithDebInfo", - "cacheVariables": { - "CMAKE_BUILD_TYPE": "RelWithDebInfo" - } - } - ], - "buildPresets": [ - { - "name": "linux-debug", - "configurePreset": "linux-debug" - }, - { - "name": "default-windows", - "configurePreset": "default-windows" - }, - { - "name": "osx-debug", - "configurePreset": "osx-debug" - } - ] -} + "configurePresets": [ + { + "name": "default-windows", + "displayName": "ScreenPlay 64bit Windows", + "description": "Windows only!", + "generator": "Ninja", + "hidden": true, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + }, + "environment": { + "qt_path": "${sourceDir}/../aqt", + "qt_version": "6.6.1" + }, + "toolset": { + "value": "host=x64", + "strategy": "external" + }, + "architecture": { + "value": "x64", + "strategy": "external" + }, + "cacheVariables": { + "CMAKE_PREFIX_PATH": "$env{qt_path}/$env{qt_version}/msvc2019_64", + "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../vcpkg/scripts/buildsystems/vcpkg.cmake", + "VCPKG_TARGET_TRIPLET": "x64-windows", + "CMAKE_C_COMPILER": "cl.exe", + "CMAKE_CXX_COMPILER": "cl.exe" + } + }, + { + "name": "windows-debug-qt-6.6.1", + "inherits": "default-windows", + "displayName": "MSVC SP Qt 6.6.1 Debug", + "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.6.1_MSVC_Debug", + "environment": { + "qt_version": "6.6.1" + }, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "windows-relwithdebinfo-qt-6.6.1", + "inherits": "default-windows", + "displayName": "MSVC SP Qt 6.6.1 RelWithDebInfo", + "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.6.1_MSVC_RelWithDebInfo", + "environment": { + "qt_version": "6.6.1" + }, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + } + }, + { + "name": "windows-release-qt-6.6.1", + "inherits": "default-windows", + "displayName": "MSVC SP Qt 6.6.1 Release", + "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.6.1_MSVC_Release", + "environment": { + "qt_version": "6.6.1" + }, + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release" + } + }, + { + "name": "windows-release-qt-6.6.1-release-deploy", + "inherits": "windows-release-qt-6.6.1", + "displayName": "MSVC SP Qt 6.6.1 Release Steam Deploy", + "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.6.1_MSVC_Release_Steam_Deploy", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "Release", + "SCREENPLAY_DEPLOY": "ON", + "SCREENPLAY_STEAM": "ON" + } + }, + { + "name": "linux-generic-debug", + "displayName": "ScreenPlay 64bit Debug Linux", + "description": "Linux only!", + "generator": "Ninja", + "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.6.1_GCC_Debug", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Linux" + }, + "architecture": { + "value": "x64", + "strategy": "external" + }, + "cacheVariables": { + "CMAKE_CXX_COMPILER": "g++", + "CMAKE_C_COMPILER": "gcc", + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../vcpkg/scripts/buildsystems/vcpkg.cmake", + "VCPKG_TARGET_TRIPLET": "x64-linux", + "SCREENPLAY_STEAM": "OFF", + "SCREENPLAY_TESTS": "OFF" + } + }, + { + "name": "linux-relwithdebinfo", + "displayName": "ScreenPlay 64bit RelWithDebInfo Linux", + "inherits": "linux-generic-debug", + "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.6.1_GCC_RelWithDebInfo", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + } + }, + { + "name": "linux-aqt-debug", + "displayName": "ScreenPlay 64bit Debug Linux using aqt", + "description": "Linux only!", + "generator": "Ninja", + "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.6.1_GCC_Debug", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Linux" + }, + "environment": { + "qt_path": "${sourceDir}/../aqt" + }, + "architecture": { + "value": "x64", + "strategy": "external" + }, + "cacheVariables": { + "CMAKE_CXX_COMPILER": "g++", + "CMAKE_C_COMPILER": "gcc", + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_PREFIX_PATH": "$env{qt_path}/6.6.1/gcc_64", + "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../vcpkg/scripts/buildsystems/vcpkg.cmake", + "VCPKG_TARGET_TRIPLET": "x64-linux" + } + }, + { + "name": "linux-aqt-relwithdebinfo", + "displayName": "ScreenPlay 64bit RelWithDebInfo Linux using aqt", + "inherits": "linux-ubuntu-debug", + "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.6.1_GCC_RelWithDebInfo", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + } + }, + { + "name": "osx-debug", + "displayName": "ScreenPlay 64bit Debug osx", + "description": "Osx only!", + "generator": "Ninja", + "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.6.1_Clang_Debug", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Darwin" + }, + "environment": { + "qt_path": "${sourceDir}/../aqt" + }, + "cacheVariables": { + "VCPKG_OSX_ARCHITECTURES": "arm64;x86_64", + "VCPKG_TARGET_TRIPLET": "64-osx-universal", + "CMAKE_CXX_COMPILER": "clang++", + "CMAKE_C_COMPILER": "clang", + "CMAKE_BUILD_TYPE": "Debug", + "CMAKE_PREFIX_PATH": "$env{qt_path}/6.6.1/macos", + "CMAKE_TOOLCHAIN_FILE": "${sourceDir}/../vcpkg/scripts/buildsystems/vcpkg.cmake" + } + }, + { + "name": "osx-relwithdebinfo", + "displayName": "ScreenPlay 64bit RelWithDebInfo osx", + "inherits": "osx-debug", + "binaryDir": "${sourceDir}/../build_ScreenPlay_Qt_6.6.1_Clang_RelWithDebInfo", + "cacheVariables": { + "CMAKE_BUILD_TYPE": "RelWithDebInfo" + } + } + ], + "buildPresets": [ + { + "name": "linux-debug", + "configurePreset": "linux-debug" + }, + { + "name": "default-windows", + "configurePreset": "default-windows" + }, + { + "name": "osx-debug", + "configurePreset": "osx-debug" + } + ], + "testPresets": [ + { + "name": "Test", + "description": "", + "displayName": "", + "configurePreset": "windows-release-qt-6.6.1" + } + ] +} \ No newline at end of file diff --git a/Content/wallpaper_godot_fjord/.gitattributes b/Content/wallpaper_godot_fjord/.gitattributes new file mode 100644 index 00000000..8ad74f78 --- /dev/null +++ b/Content/wallpaper_godot_fjord/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/Content/wallpaper_godot_fjord/.gitignore b/Content/wallpaper_godot_fjord/.gitignore new file mode 100644 index 00000000..47091836 --- /dev/null +++ b/Content/wallpaper_godot_fjord/.gitignore @@ -0,0 +1,2 @@ +# Godot 4+ specific ignores +.godot/ diff --git a/Content/wallpaper_godot_fjord/Action.gd b/Content/wallpaper_godot_fjord/Action.gd new file mode 100644 index 00000000..74593f7c --- /dev/null +++ b/Content/wallpaper_godot_fjord/Action.gd @@ -0,0 +1,27 @@ +extends Node + +# Reference to the PathFollow node +@onready var path_follow = $Path3D/PathFollow3D +@onready var label = $Label3D +var debug_path +var screenplaywallpaper +var appID = "" +# Speed of the movement along the path +var speed = 0.8 +var path = "/root/Wallpaper/ScreenPlayGodotWallpaper" + + +func _process(delta): + # Update the offset to move the object along the path + path_follow.progress += speed * delta + + # Loop back to the start if we've reached the end of the path + if path_follow.progress >= 18.81: + path_follow.progress = 0.0 + return + if has_node(path): + if get_node(path): + appID = screenplaywallpaper.get_appID() + else: + appID = "404" + label.text = "Godot Wallpaper\n" + Time.get_time_string_from_system() + "\nAppID: " + appID diff --git a/Content/wallpaper_godot_fjord/Path3D.gd b/Content/wallpaper_godot_fjord/Path3D.gd new file mode 100644 index 00000000..fd4a5377 --- /dev/null +++ b/Content/wallpaper_godot_fjord/Path3D.gd @@ -0,0 +1,17 @@ +extends Path3D + +# Reference to the PathFollow node +@onready var path_follow = $PathFollow3D +@onready var path_follow = + +# Speed of the movement along the path +var speed = 0.8 + + +func _process(delta): + # Update the offset to move the object along the path + path_follow.progress += speed * delta + + # Loop back to the start if we've reached the end of the path + if path_follow.progress >= 18.81: + path_follow.progress = 0.0 diff --git a/Content/wallpaper_godot_fjord/export_presets.cfg b/Content/wallpaper_godot_fjord/export_presets.cfg new file mode 100644 index 00000000..88e962f2 --- /dev/null +++ b/Content/wallpaper_godot_fjord/export_presets.cfg @@ -0,0 +1,61 @@ +[preset.0] + +name="Windows Desktop" +platform="Windows Desktop" +runnable=true +dedicated_server=false +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="" +encryption_include_filters="" +encryption_exclude_filters="" +encrypt_pck=false +encrypt_directory=false + +[preset.0.options] + +custom_template/debug="" +custom_template/release="" +debug/export_console_wrapper=1 +binary_format/embed_pck=false +texture_format/bptc=true +texture_format/s3tc=true +texture_format/etc=false +texture_format/etc2=false +binary_format/architecture="x86_64" +codesign/enable=false +codesign/timestamp=true +codesign/timestamp_server_url="" +codesign/digest_algorithm=1 +codesign/description="" +codesign/custom_options=PackedStringArray() +application/modify_resources=true +application/icon="" +application/console_wrapper_icon="" +application/icon_interpolation=4 +application/file_version="" +application/product_version="" +application/company_name="" +application/product_name="" +application/file_description="" +application/copyright="" +application/trademarks="" +ssh_remote_deploy/enabled=false +ssh_remote_deploy/host="user@host_ip" +ssh_remote_deploy/port="22" +ssh_remote_deploy/extra_args_ssh="" +ssh_remote_deploy/extra_args_scp="" +ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}' +$action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}' +$trigger = New-ScheduledTaskTrigger -Once -At 00:00 +$settings = New-ScheduledTaskSettingsSet +$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings +Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true +Start-ScheduledTask -TaskName godot_remote_debug +while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 } +Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue" +ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue +Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue +Remove-Item -Recurse -Force '{temp_dir}'" diff --git a/Content/wallpaper_godot_fjord/icon.svg b/Content/wallpaper_godot_fjord/icon.svg new file mode 100644 index 00000000..b370ceb7 --- /dev/null +++ b/Content/wallpaper_godot_fjord/icon.svg @@ -0,0 +1 @@ + diff --git a/Content/wallpaper_godot_fjord/icon.svg.import b/Content/wallpaper_godot_fjord/icon.svg.import new file mode 100644 index 00000000..d27a3408 --- /dev/null +++ b/Content/wallpaper_godot_fjord/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://boex5vkldqpl5" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/Content/wallpaper_godot_fjord/preview.png b/Content/wallpaper_godot_fjord/preview.png new file mode 100644 index 00000000..9ad7fde7 Binary files /dev/null and b/Content/wallpaper_godot_fjord/preview.png differ diff --git a/Content/wallpaper_godot_fjord/preview.png.import b/Content/wallpaper_godot_fjord/preview.png.import new file mode 100644 index 00000000..9c874ec1 --- /dev/null +++ b/Content/wallpaper_godot_fjord/preview.png.import @@ -0,0 +1,34 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://b50wk45iaak85" +path="res://.godot/imported/preview.png-b4838d23de224c84c7c9b5588b6708a6.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://preview.png" +dest_files=["res://.godot/imported/preview.png-b4838d23de224c84c7c9b5588b6708a6.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 diff --git a/Content/wallpaper_godot_fjord/project.godot b/Content/wallpaper_godot_fjord/project.godot new file mode 100644 index 00000000..d60e8d8a --- /dev/null +++ b/Content/wallpaper_godot_fjord/project.godot @@ -0,0 +1,20 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="Fjord" +run/main_scene="res://wallpaper.tscn" +config/features=PackedStringArray("4.2", "Mobile") +config/icon="res://icon.svg" + +[rendering] + +renderer/rendering_method="mobile" diff --git a/Content/wallpaper_godot_fjord/project.json b/Content/wallpaper_godot_fjord/project.json new file mode 100644 index 00000000..6d5a7cb3 --- /dev/null +++ b/Content/wallpaper_godot_fjord/project.json @@ -0,0 +1,11 @@ +{ + "description": "Godot", + "file": "main.qml", + "preview": "preview.png", + "tags": [ + "Godot" + ], + "title": "Godot Wallpaper", + "type": "godotWallpaper", + "visibility": "public" +} \ No newline at end of file diff --git a/Content/wallpaper_godot_fjord/wallpaper.tscn b/Content/wallpaper_godot_fjord/wallpaper.tscn new file mode 100644 index 00000000..a9c57760 --- /dev/null +++ b/Content/wallpaper_godot_fjord/wallpaper.tscn @@ -0,0 +1,39 @@ +[gd_scene load_steps=3 format=3 uid="uid://dp883pjlm7gk8"] + +[ext_resource type="Script" path="res://Action.gd" id="1_p251a"] + +[sub_resource type="Curve3D" id="Curve3D_8adw4"] +bake_interval = 2.4 +_data = { +"points": PackedVector3Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -2.82099, -0.143238, -1.14419, 0, 0, 0, 0, 0, 0, -0.837192, 0.205974, -1.5077, 0, 0, 0, 0, 0, 0, 2.26923, 2.38419e-07, -1.10178, 0, 0, 0, 0, 0, 0, 3.0406, -0.00296563, 0.345948, 0, 0, 0, 0, 0, 0, 0.398976, -0.117547, 1.42909, 0, 0, 0, 0, 0, 0, -2.74903, -0.071628, 0.795209, 0, 0, 0, 0, 0, 0, 0, 0, 0), +"tilts": PackedFloat32Array(0, 0, 0, 0, 0, 0, 0, 0) +} +point_count = 8 + +[node name="Node3D" type="Node3D"] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.0123152, 0) +script = ExtResource("1_p251a") + +[node name="Camera3D" type="Camera3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.04825, 4.0185) + +[node name="CSGBox3D" type="CSGBox3D" parent="."] +transform = Transform3D(3.5774, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.223695, 0) +size = Vector3(7.59119, 0.0764128, 5.75358) + +[node name="Path3D" type="Path3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.1394, 0, 0.705414) +curve = SubResource("Curve3D_8adw4") + +[node name="PathFollow3D" type="PathFollow3D" parent="Path3D"] +transform = Transform3D(0.375854, -0.0435545, 0.925652, -3.72525e-09, 0.998895, 0.0470007, -0.926666, -0.0176657, 0.375443, 0, 0, 0) + +[node name="OmniLight3D" type="OmniLight3D" parent="Path3D/PathFollow3D"] +light_color = Color(0.921569, 0.52549, 0.32549, 1) + +[node name="Label3D" type="Label3D" parent="."] +transform = Transform3D(0.997247, 0, 0, 0, 0.997247, 0, 0, 0, 0.997247, 0.030704, 1.238, -1.40679) +shaded = true +text = "GODO WALLPAPER" +font_size = 126 +outline_size = 42 diff --git a/Content/wallpaper_qml/main.qml b/Content/wallpaper_qml/main.qml index 92e21a65..4b8b941d 100644 --- a/Content/wallpaper_qml/main.qml +++ b/Content/wallpaper_qml/main.qml @@ -3,6 +3,7 @@ import QtQuick import QtQuick.Layouts import QtQuick.Controls import QtQuick.Controls.Material +import ScreenPlayWallpaper Rectangle { id: root @@ -23,5 +24,16 @@ Rectangle { Layout.fillWidth: true onClicked: root.counter++ } + TextField { + placeholderText: "Edit me" + } + Button { + text: "Exit" + onClicked: { + Qt.callLater(function () { + Wallpaper.terminate(); + }); + } + } } } diff --git a/Content/wallpaper_qml_particles/main.qml b/Content/wallpaper_qml_particles/main.qml index 9f2b561f..08d76ead 100644 --- a/Content/wallpaper_qml_particles/main.qml +++ b/Content/wallpaper_qml_particles/main.qml @@ -119,7 +119,7 @@ Item { bottom: parent.bottom bottomMargin: -width * .65 } - SequentialAnimation on opacity { + SequentialAnimation on opacity { loops: Animation.Infinite OpacityAnimator { diff --git a/Content/widget_analog_clock/Clock.qml b/Content/widget_analog_clock/Clock.qml index b50a08f2..5ce745a8 100644 --- a/Content/widget_analog_clock/Clock.qml +++ b/Content/widget_analog_clock/Clock.qml @@ -63,7 +63,7 @@ Item { origin.x: 7.5 origin.y: 73 angle: (clock.hours * 30) + (clock.minutes * 0.5) - Behavior on angle { + Behavior on angle { SpringAnimation { spring: 2 damping: 0.2 @@ -82,7 +82,7 @@ Item { origin.x: 6.5 origin.y: 83 angle: clock.minutes * 6 - Behavior on angle { + Behavior on angle { SpringAnimation { spring: 2 damping: 0.2 @@ -101,7 +101,7 @@ Item { origin.x: 2.5 origin.y: 80 angle: clock.seconds * 6 - Behavior on angle { + Behavior on angle { SpringAnimation { spring: 2 damping: 0.2 diff --git a/Content/widget_analog_clock/main.qml b/Content/widget_analog_clock/main.qml index a9bdae7b..2aa9119a 100644 --- a/Content/widget_analog_clock/main.qml +++ b/Content/widget_analog_clock/main.qml @@ -62,7 +62,7 @@ Item { source: "arrow.png" rotation: -90 opacity: clockview.atXBeginning ? 0 : 0.5 - Behavior on opacity { + Behavior on opacity { NumberAnimation { duration: 500 } @@ -76,7 +76,7 @@ Item { source: "arrow.png" rotation: 90 opacity: clockview.atXEnd ? 0 : 0.5 - Behavior on opacity { + Behavior on opacity { NumberAnimation { duration: 500 } diff --git a/Content/widget_hello_world/main.qml b/Content/widget_hello_world/main.qml index 5b263a10..810b292a 100644 --- a/Content/widget_hello_world/main.qml +++ b/Content/widget_hello_world/main.qml @@ -23,7 +23,7 @@ Item { // to the opacity of the rectangle opacity: sizeSlider.value // Animate the opacity change to make it smooth - Behavior on opacity { + Behavior on opacity { NumberAnimation { duration: 100 } diff --git a/Docs/macOSSigning.md b/Docs/macOSSigning.md index bf38b145..6770492d 100644 --- a/Docs/macOSSigning.md +++ b/Docs/macOSSigning.md @@ -119,4 +119,24 @@ Run the follwoing if you get an signing error: Error: HTTP status code: 403. A required agreement is missing or has expired. This request requires an in-effect agreement that has not been signed or has expired. Ensure your team has signed the necessary legal agreements and that they are not expired. ``` -Go to [appstoreconnect.apple.com](https://appstoreconnect.apple.com) and accept the updated 'Apple Developer Program License Agreement'. \ No newline at end of file +Go to [appstoreconnect.apple.com](https://appstoreconnect.apple.com) and accept the updated 'Apple Developer Program License Agreement'. + +## Dmg signing +Ensure you have both a Developer ID Application certificate and a Developer ID Installer certificate in your Keychain. You can check this in the Keychain Access app. +- Developer ID Application Certificate: + - Used for code signing the application itself. This ensures that the app is from a known developer and hasn't been tampered with since it was signed. +- Developer ID Installer Certificate: + - Used specifically for signing installer packages like PKG files or disk images (DMGs). This is separate from the application certificate and is specifically for the installer. +1. Check Your Certificates at https://developer.apple.com/account/resources/certificates/list and create a new one `Mac Installer Distribution +This certificate is used to sign your app's Installer Package for submission to the Mac App Store.` +2. `Upload a Certificate Signing Request`. To manually generate a Certificate, you need a Certificate Signing Request (CSR) file from your Mac. https://developer.apple.com/help/account/create-certificates/create-a-certificate-signing-request + 1. Launch Keychain Access located in /Applications/Utilities. + 1. Choose Keychain Access > Certificate Assistant > Request a Certificate from a Certificate Authority. + 1. In the Certificate Assistant dialog, enter an email address in the User Email Address field. + 1. In the Common Name field, enter a name for the key (for example, Gita Kumar Dev Key). + 1. Leave the CA Email Address field empty. + 1. Choose โ€œSaved to disk,โ€ call it something like `CertificateSigningRequest_Tachiom_Installer_Certificate` then click Continue. +3. Download the new certificate +4. Download your certificate to your Mac, then double click the .cer file to install in Keychain Access. IMPORTANT: Select `Keychan: Login` in the dropdown! Make sure to save a backup copy of your private and public keys somewhere secure. + - The "login" keychain is tied to your user account and unlocks when you log in, making it a convenient location for development-related certificates. The "System" keychain is more restrictive and requires admin permissions for access, while the "Local Items" keychain is specific to iCloud Keychain items. +5. This should now be displayed like `3rd Party Mac Developer Installer: Elias Steurer (V887LHYKRH)` and be valid one year. \ No newline at end of file diff --git a/ScreenPlay/CMakeLists.txt b/ScreenPlay/CMakeLists.txt index d2842184..16c32e9e 100644 --- a/ScreenPlay/CMakeLists.txt +++ b/ScreenPlay/CMakeLists.txt @@ -5,6 +5,9 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOMOC ON) +# ##### USE CMAKE VARIABLES IN CODE ##### +include(GenerateCMakeVariableHeader) + set(SOURCES # cmake-format: sort src/app.cpp @@ -21,7 +24,6 @@ set(SOURCES src/screenplaywidget.cpp src/sdkconnection.cpp src/settings.cpp - src/util.cpp src/wizards.cpp) set(HEADER @@ -42,21 +44,21 @@ set(HEADER inc/public/ScreenPlay/screenplaywidget.h inc/public/ScreenPlay/sdkconnection.h inc/public/ScreenPlay/settings.h - inc/public/ScreenPlay/util.h inc/public/ScreenPlay/wizards.h) set(QML # cmake-format: sort main.qml - qml/Community/Community.qml qml/Community/CommunityNavItem.qml + qml/Community/CommunityView.qml qml/Community/XMLNewsfeed.qml - qml/Create/Create.qml qml/Create/CreateSidebar.qml + qml/Create/CreateView.qml qml/Create/StartInfo.qml qml/Create/StartInfoLinkImage.qml qml/Create/Wizard.qml qml/Create/Wizards/GifWallpaper.qml + qml/Create/Wizards/GodotWallpaper.qml qml/Create/Wizards/HTMLWallpaper.qml qml/Create/Wizards/HTMLWidget.qml qml/Create/Wizards/Importh264/Importh264.qml @@ -73,32 +75,30 @@ set(QML qml/Create/Wizards/QMLWidget.qml qml/Create/Wizards/WebsiteWallpaper.qml qml/Create/Wizards/WizardPage.qml - qml/Create/WizardsFiles/QMLWallpaperMain.qml - qml/Create/WizardsFiles/QMLWidgetMain.qml - qml/Installed/Installed.qml qml/Installed/InstalledNavigation.qml + qml/Installed/InstalledView.qml qml/Installed/InstalledWelcomeScreen.qml qml/Installed/ScreenPlayItem.qml qml/Installed/ScreenPlayItemImage.qml qml/Installed/Sidebar.qml qml/Monitors/DefaultVideoControls.qml - qml/Monitors/Monitors.qml qml/Monitors/MonitorSelection.qml qml/Monitors/MonitorSelectionItem.qml qml/Monitors/MonitorsProjectSettingItem.qml + qml/Monitors/MonitorsView.qml qml/Monitors/SaveNotification.qml qml/Navigation/ExitPopup.qml qml/Navigation/Navigation.qml qml/Settings/SettingBool.qml - qml/Settings/Settings.qml qml/Settings/SettingsButton.qml qml/Settings/SettingsComboBox.qml qml/Settings/SettingsExpander.qml qml/Settings/SettingsHeader.qml qml/Settings/SettingsHorizontalSeperator.qml qml/Settings/SettingsPage.qml + qml/Settings/SettingsView.qml qml/TrayIcon.qml - qml/Workshop/Workshop.qml) + qml/Workshop/WorkshopView.qml) set(TS_FILES # cmake-format: sort @@ -135,6 +135,7 @@ set(RESOURCES assets/icons/icon_build.svg assets/icons/icon_cake.afdesign assets/icons/icon_cake.svg + assets/icons/icon_cancel_presentation.svg assets/icons/icon_close.svg assets/icons/icon_code.svg assets/icons/icon_community.svg @@ -143,6 +144,7 @@ set(RESOURCES assets/icons/icon_document.svg assets/icons/icon_done.svg assets/icons/icon_download.svg + assets/icons/icon_edit.svg assets/icons/icon_emptyWidget.svg assets/icons/icon_folder_open.svg assets/icons/icon_forum.svg @@ -156,6 +158,7 @@ set(RESOURCES assets/icons/icon_movie.svg assets/icons/icon_new_releases.svg assets/icons/icon_open_in_new.svg + assets/icons/icon_open_in_new_black.svg assets/icons/icon_pause.svg assets/icons/icon_people.svg assets/icons/icon_play.svg @@ -172,7 +175,7 @@ set(RESOURCES assets/icons/icon_thumb_down.svg assets/icons/icon_thumb_up.svg assets/icons/icon_upload.svg - assets/icons/icon_video_settings_black_24dp.svg + assets/icons/icon_video_settings.svg assets/icons/icon_volume.svg assets/icons/icon_volume_mute.svg assets/icons/icon_volume_up.svg @@ -198,9 +201,6 @@ set(RESOURCES assets/licenses/Apache2.txt assets/licenses/OFL.txt assets/macos/app.screenplay.plist - assets/particle/backgroundGlow.png - assets/particle/dot.png - assets/shader/movingcolorramp.fsh assets/startinfo/blender.png assets/startinfo/flaticon.png assets/startinfo/forums.png @@ -229,7 +229,6 @@ set(RESOURCES assets/wizards/License_CC_Attribution-ShareAlike_4.0.txt assets/wizards/License_CC_Attribution_4.0.txt assets/wizards/License_GPL_3.0.txt - assets/wizards/QmlProject.qmlproject assets/WorkshopPreview.html legal/DataProtection.txt legal/gpl-3.0.txt @@ -237,9 +236,16 @@ set(RESOURCES legal/OFL.txt legal/OpenSSL.txt profiles.json + qml/Create/WizardsFiles/Godot_v5/export_presets.cfg + qml/Create/WizardsFiles/Godot_v5/project.godot + qml/Create/WizardsFiles/Godot_v5/spinner.gd + qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn qml/Create/WizardsFiles/HTMLWallpaperMain.html qml/Create/WizardsFiles/HTMLWidgetMain.html + qml/Create/WizardsFiles/QmlProject.qmlproject qml/Create/WizardsFiles/QMLWallpaperMain.qml + qml/Create/WizardsFiles/QMLWallpaperMain.qml + qml/Create/WizardsFiles/QMLWidgetMain.qml qml/Create/WizardsFiles/QMLWidgetMain.qml qtquickcontrols2.conf) @@ -268,8 +274,17 @@ find_package( Test) add_library(ScreenPlayApp STATIC) + +target_include_directories( + ScreenPlayApp + PUBLIC inc/public/ + PRIVATE src/) + +# Note making this public is so that *_qmltyperegistrations.cpp can find the needed include target_include_directories(ScreenPlayApp PUBLIC src/ inc/public/ScreenPlay) +# ScreenPlayApp is our qml module needed for compiling of all classes and most importanly for QML_ELEMENT. So our app is mostly a module +# that then link to ScreenPlay executable. qt_add_qml_module( ScreenPlayApp URI @@ -296,7 +311,6 @@ target_link_libraries( ScreenPlayUtilplugin QArchive Plausibleplugin - SteamSDKQtEnums Threads::Threads Qt6::Quick Qt6::Gui @@ -308,7 +322,6 @@ target_link_libraries( Qt6::Xml) if(${SCREENPLAY_STEAM}) - target_compile_definitions(ScreenPlayApp PRIVATE SCREENPLAY_STEAM) target_link_libraries(ScreenPlayApp PUBLIC ScreenPlayWorkshopplugin ScreenPlayWorkshop) endif() @@ -318,26 +331,16 @@ target_link_libraries(${PROJECT_NAME} PRIVATE ScreenPlayApp ScreenPlayAppplugin) if(${SCREENPLAY_TESTS}) add_executable(tst_ScreenPlay tests/tst_main.cpp) target_link_libraries(tst_ScreenPlay PRIVATE ScreenPlayApp ScreenPlayAppplugin Qt6::Test) + generate_cmake_variable_header(tst_ScreenPlay) if(${SCREENPLAY_STEAM}) - target_compile_definitions(tst_ScreenPlay PRIVATE SCREENPLAY_STEAM) target_link_libraries(tst_ScreenPlay PUBLIC ScreenPlayWorkshopplugin ScreenPlayWorkshop) endif() + + if(APPLE) + set_target_properties(tst_ScreenPlay PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/") + endif() endif() -if(APPLE AND NOT OSX_BUNDLE) - set_source_files_properties( - ${TS_FILES} PROPERTIES OUTPUT_LOCATION "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${PROJECT_NAME}.app/Contents/Resources/translations") -else() - set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/translations") -endif() - -qt_add_lrelease(${PROJECT_NAME} TS_FILES ${TS_FILES}) - -target_include_directories( - ScreenPlayApp - PUBLIC inc/public/ - PRIVATE src/) - if(WIN32 OR UNIX AND NOT APPLE) @@ -349,7 +352,7 @@ if(WIN32 endif() if(WIN32) - target_link_libraries(ScreenPlayApp PUBLIC CURL::libcurl sentry::sentry) + target_link_libraries(ScreenPlayApp PUBLIC CURL::libcurl sentry::sentry ScreenPlayWallpaperLib) # Icon target_sources(${PROJECT_NAME} PRIVATE ScreenPlay.rc) @@ -375,30 +378,22 @@ if(WIN32) endif() -if(APPLE AND OSX_BUNDLE) - # Set the installation destination - install(TARGETS "ScreenPlay" DESTINATION /Applications) +if(APPLE) - include(InstallRequiredSystemLibraries) - set(CPACK_GENERATOR "Bundle") - set(CPACK_BINARY_DRAGNDROP ON) - set(CPACK_BUNDLE_NAME "ScreenPlay") - set(CPACK_BUNDLE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/assets/icons/app.ico") - set(CPACK_PACKAGE_ICON "${CMAKE_CURRENT_SOURCE_DIR}/assets/icons/app.ico") - set(CPACK_BUNDLE_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist") - set(CPACK_BUNDLE_APPLE_ENTITLEMENTS "${CMAKE_CURRENT_SOURCE_DIR}/entitlements.plist") - set(CPACK_PACKAGE_FILE_NAME "ScreenPlay-0.15") - include(CPack) + # Set the path to the icon file + set(APP_ICON_MACOSX ${CMAKE_CURRENT_SOURCE_DIR}/assets/icons/ScreenPlay.icns) - # Install all files from /bin - install( - DIRECTORY "${CMAKE_BINARY_DIR}/bin/" - COMPONENT ScreenPlay - DESTINATION "./") + # Tell CMake where to find the icon + set_source_files_properties(${APP_ICON_MACOSX} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources") -endif() + set(RESOURCES_DIR "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ScreenPlay.app/Contents/Resources") + file(MAKE_DIRECTORY ${RESOURCES_DIR}) + + # Specify the name of the icon file for the bundle + set(MACOSX_BUNDLE_ICON_FILE ScreenPlay.icns) # Only the file name + # Fore some reason this only works with maually copy + configure_file(${APP_ICON_MACOSX} "${RESOURCES_DIR}/ScreenPlay.icns" COPYONLY) -if(APPLE AND NOT OSX_BUNDLE) # Creates a ScreenPlay.app set_target_properties( ${PROJECT_NAME} @@ -406,9 +401,9 @@ if(APPLE AND NOT OSX_BUNDLE) MACOSX_BUNDLE TRUE MACOSX_RPATH TRUE MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist - MACOSX_FRAMEWORK_IDENTIFIER screen-play.app + MACOSX_FRAMEWORK_IDENTIFIER app.screenplay XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@loader_path/Libraries" - RESOURCE "${RESOURCE_FILES}" + RESOURCE "${RESOURCE_FILES};${APP_ICON_MACOSX}" # Include the icon in the resources XCODE_ATTRIBUTE_ENABLE_HARDENED_RUNTIME TRUE XCODE_ATTRIBUTE_EXECUTABLE_NAME ${PROJECT_NAME}) @@ -424,29 +419,23 @@ if(APPLE AND NOT OSX_BUNDLE) COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/../ThirdParty/ffmpeg/ffprobe ${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/) - # tst_ScreenPlay needs ffmpeg in the base path - if(${SCREENPLAY_TESTS}) - add_custom_command( - TARGET ${PROJECT_NAME} - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/../ThirdParty/ffmpeg/ffmpeg ${CMAKE_BINARY_DIR}/bin/) - - add_custom_command( - TARGET ${PROJECT_NAME} - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/../ThirdParty/ffmpeg/ffprobe ${CMAKE_BINARY_DIR}/bin/) - endif() - # fonts include(CopyRecursive) - set(FONTS_OUT_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ScreenPlay.app/Contents/Resources/fonts/) + set(FONTS_OUT_DIR "${RESOURCES_DIR}/fonts") file(MAKE_DIRECTORY ${FONTS_OUT_DIR}) copy_recursive(${CMAKE_CURRENT_SOURCE_DIR}/assets/fonts ${FONTS_OUT_DIR} "*.ttf") copy_recursive(${CMAKE_CURRENT_SOURCE_DIR}/assets/fonts ${FONTS_OUT_DIR} "*.otf") + # .qm translations + set(QM_OUT_DIR "${RESOURCES_DIR}/translations") + file(MAKE_DIRECTORY ${QM_OUT_DIR}) + set_source_files_properties(${TS_FILES} PROPERTIES OUTPUT_LOCATION ${QM_OUT_DIR}) + endif() -# ##### USE CMAKE VARIABLES IN CODE ##### -include(GenerateCMakeVariableHeader) -# Note: Must not be ${PROJECT_NAME}, but ScreenPlayApp to work! +# Must be called here, because we need to change the OUTPUT_LOCATION for macos +qt_add_lrelease(${PROJECT_NAME} TS_FILES ${TS_FILES}) + +# Note: We need the variables in the lib and exe! +generate_cmake_variable_header(${PROJECT_NAME}) generate_cmake_variable_header(ScreenPlayApp) diff --git a/ScreenPlay/Info.plist b/ScreenPlay/Info.plist index 59a52224..72449769 100644 --- a/ScreenPlay/Info.plist +++ b/ScreenPlay/Info.plist @@ -7,9 +7,9 @@ CFBundleExecutable ScreenPlay CFBundleIconFile - + ScreenPlay CFBundleIdentifier - app.screen-play + app.screenplay CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/ScreenPlay/assets/icons/Readme.md b/ScreenPlay/assets/icons/Readme.md new file mode 100644 index 00000000..93d6a159 --- /dev/null +++ b/ScreenPlay/assets/icons/Readme.md @@ -0,0 +1,33 @@ +Create icons. Replace `\` with `^` on windows. + +``` +convert app.png -resize 16x16 ScreenPlay.iconset/icon_16x16.png \ +&& convert app.png -resize 32x32 ScreenPlay.iconset/icon_16x16@2x.png \ +&& convert app.png -resize 32x32 ScreenPlay.iconset/icon_32x32.png \ +&& convert app.png -resize 64x64 ScreenPlay.iconset/icon_32x32@2x.png \ +&& convert app.png -resize 128x128 ScreenPlay.iconset/icon_128x128.png \ +&& convert app.png -resize 256x256 ScreenPlay.iconset/icon_128x128@2x.png \ +&& convert app.png -resize 256x256 ScreenPlay.iconset/icon_256x256.png \ +&& convert app.png -resize 512x512 ScreenPlay.iconset/icon_256x256@2x.png \ +&& convert app.png -resize 512x512 ScreenPlay.iconset/icon_512x512.png \ +&& convert app.png -resize 1024x1024 ScreenPlay.iconset/icon_512x512@2x.png + +// Convert to .icns +iconutil -c icns ScreenPlay.iconset +``` +Convert for Windows .ico +``` +magick convert app.png \ +\( -clone 0 -resize 16x16 \) \ +\( -clone 0 -resize 32x32 \) \ +\( -clone 0 -resize 48x48 \) \ +\( -clone 0 -resize 64x64 \) \ +\( -clone 0 -resize 128x128 \) \ +\( -clone 0 -resize 256x256 \) \ +-delete 0 -background transparent app.ico + +``` +Make the 1k logo smaller +``` +convert app.png -resize 512x512 app_icon.png +``` \ No newline at end of file diff --git a/ScreenPlay/assets/icons/ScreenPlay.icns b/ScreenPlay/assets/icons/ScreenPlay.icns new file mode 100644 index 00000000..10d281a0 Binary files /dev/null and b/ScreenPlay/assets/icons/ScreenPlay.icns differ diff --git a/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_128x128.png b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_128x128.png new file mode 100644 index 00000000..c010845c Binary files /dev/null and b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_128x128.png differ diff --git a/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_128x128@2x.png b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_128x128@2x.png new file mode 100644 index 00000000..a03b5a35 Binary files /dev/null and b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_128x128@2x.png differ diff --git a/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_16x16.png b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_16x16.png new file mode 100644 index 00000000..a4162ffb Binary files /dev/null and b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_16x16.png differ diff --git a/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_16x16@2x.png b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_16x16@2x.png new file mode 100644 index 00000000..dbf38a0a Binary files /dev/null and b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_16x16@2x.png differ diff --git a/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_256x256.png b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_256x256.png new file mode 100644 index 00000000..a03b5a35 Binary files /dev/null and b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_256x256.png differ diff --git a/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_256x256@2x.png b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_256x256@2x.png new file mode 100644 index 00000000..d9099122 Binary files /dev/null and b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_256x256@2x.png differ diff --git a/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_32x32.png b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_32x32.png new file mode 100644 index 00000000..dbf38a0a Binary files /dev/null and b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_32x32.png differ diff --git a/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_32x32@2x.png b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_32x32@2x.png new file mode 100644 index 00000000..d354e6ab Binary files /dev/null and b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_32x32@2x.png differ diff --git a/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_512x512.png b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_512x512.png new file mode 100644 index 00000000..d9099122 Binary files /dev/null and b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_512x512.png differ diff --git a/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_512x512@2x.png b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_512x512@2x.png new file mode 100644 index 00000000..35d767fc Binary files /dev/null and b/ScreenPlay/assets/icons/ScreenPlay.iconset/icon_512x512@2x.png differ diff --git a/ScreenPlay/assets/icons/app.ico b/ScreenPlay/assets/icons/app.ico index de00f568..d03bd1eb 100644 Binary files a/ScreenPlay/assets/icons/app.ico and b/ScreenPlay/assets/icons/app.ico differ diff --git a/ScreenPlay/assets/icons/app.png b/ScreenPlay/assets/icons/app.png new file mode 100755 index 00000000..7bb9dd85 Binary files /dev/null and b/ScreenPlay/assets/icons/app.png differ diff --git a/ScreenPlay/assets/icons/app_512x512.png b/ScreenPlay/assets/icons/app_512x512.png new file mode 100644 index 00000000..175ecf81 Binary files /dev/null and b/ScreenPlay/assets/icons/app_512x512.png differ diff --git a/ScreenPlay/assets/icons/app_dark.png b/ScreenPlay/assets/icons/app_dark.png new file mode 100755 index 00000000..40c5952b Binary files /dev/null and b/ScreenPlay/assets/icons/app_dark.png differ diff --git a/ScreenPlay/assets/icons/icon_cancel_presentation.svg b/ScreenPlay/assets/icons/icon_cancel_presentation.svg new file mode 100644 index 00000000..c0da419c --- /dev/null +++ b/ScreenPlay/assets/icons/icon_cancel_presentation.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ScreenPlay/assets/icons/icon_edit.svg b/ScreenPlay/assets/icons/icon_edit.svg new file mode 100644 index 00000000..cb81b113 --- /dev/null +++ b/ScreenPlay/assets/icons/icon_edit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ScreenPlay/assets/icons/icon_open_in_new_black.svg b/ScreenPlay/assets/icons/icon_open_in_new_black.svg new file mode 100644 index 00000000..42895ffd --- /dev/null +++ b/ScreenPlay/assets/icons/icon_open_in_new_black.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/ScreenPlay/assets/icons/icon_steam.svg b/ScreenPlay/assets/icons/icon_steam.svg index c7e45690..7a35f5b3 100644 --- a/ScreenPlay/assets/icons/icon_steam.svg +++ b/ScreenPlay/assets/icons/icon_steam.svg @@ -1 +1,5 @@ - \ No newline at end of file + + + + + diff --git a/ScreenPlay/assets/icons/icon_video_settings_black_24dp.svg b/ScreenPlay/assets/icons/icon_video_settings.svg similarity index 100% rename from ScreenPlay/assets/icons/icon_video_settings_black_24dp.svg rename to ScreenPlay/assets/icons/icon_video_settings.svg diff --git a/ScreenPlay/assets/particle/backgroundGlow.png b/ScreenPlay/assets/particle/backgroundGlow.png deleted file mode 100644 index ba18cc8d..00000000 Binary files a/ScreenPlay/assets/particle/backgroundGlow.png and /dev/null differ diff --git a/ScreenPlay/assets/particle/dot.png b/ScreenPlay/assets/particle/dot.png deleted file mode 100644 index 082a04d1..00000000 Binary files a/ScreenPlay/assets/particle/dot.png and /dev/null differ diff --git a/ScreenPlay/assets/shader/movingcolorramp.fsh b/ScreenPlay/assets/shader/movingcolorramp.fsh deleted file mode 100644 index efe1d207..00000000 --- a/ScreenPlay/assets/shader/movingcolorramp.fsh +++ /dev/null @@ -1,18 +0,0 @@ -uniform float time; -uniform float shaderOpacity; -uniform vec2 resolution; - -void main( void ) { - - - vec2 position = ( gl_FragCoord.xy / resolution.xy ); - - vec3 color1 = vec3(1.0, 0.6, 0.01); - vec3 color2 = vec3(0.97, 0.24, 0.24); - float mixValue = distance(position,vec2(0,1)); - - vec3 color = mix( color1, color2, mixValue); - - gl_FragColor = vec4(color,mixValue) * shaderOpacity; - -} diff --git a/ScreenPlay/assets/tests/video_import.mp4 b/ScreenPlay/assets/tests/video_import.mp4 deleted file mode 100644 index 6a2ac6d2..00000000 Binary files a/ScreenPlay/assets/tests/video_import.mp4 and /dev/null differ diff --git a/ScreenPlay/inc/public/ScreenPlay/app.h b/ScreenPlay/inc/public/ScreenPlay/app.h index 81231b38..fe90e73b 100644 --- a/ScreenPlay/inc/public/ScreenPlay/app.h +++ b/ScreenPlay/inc/public/ScreenPlay/app.h @@ -25,8 +25,8 @@ #include "ScreenPlay/profilelistmodel.h" #include "ScreenPlay/screenplaymanager.h" #include "ScreenPlay/settings.h" -#include "ScreenPlay/util.h" #include "ScreenPlay/wizards.h" +#include "ScreenPlayUtil/util.h" #include @@ -101,10 +101,8 @@ public slots: void setMainWindowEngine(QQmlApplicationEngine* mainWindowEngine); void setWizards(Wizards* wizards); - private: QNetworkAccessManager m_networkAccessManager; - QElapsedTimer m_continuousIntegrationMetricsTimer; std::unique_ptr m_mainWindowEngine; std::unique_ptr m_create; diff --git a/ScreenPlay/inc/public/ScreenPlay/create.h b/ScreenPlay/inc/public/ScreenPlay/create.h index ebadca23..13dae279 100644 --- a/ScreenPlay/inc/public/ScreenPlay/create.h +++ b/ScreenPlay/inc/public/ScreenPlay/create.h @@ -24,6 +24,7 @@ #include +#include "ScreenPlay/createimportstates.h" #include "ScreenPlay/createimportvideo.h" #include "ScreenPlay/globalvariables.h" @@ -32,6 +33,8 @@ namespace ScreenPlay { class Create : public QObject { Q_OBJECT QML_ELEMENT + QML_UNCREATABLE("") + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") Q_PROPERTY(QString workingDir READ workingDir WRITE setWorkingDir NOTIFY workingDirChanged) Q_PROPERTY(float progress READ progress WRITE setProgress NOTIFY progressChanged) @@ -55,7 +58,7 @@ public: QString ffmpegOutput() const { return m_ffmpegOutput; } signals: - void createWallpaperStateChanged(ImportVideoState::ImportVideoState state); + void createWallpaperStateChanged(Import::State state); void progressChanged(float progress); void abortCreateWallpaper(); void workingDirChanged(QString workingDir); @@ -112,7 +115,6 @@ public slots: } private: - void init(); void reset(); private: diff --git a/ScreenPlay/inc/public/ScreenPlay/createimportstates.h b/ScreenPlay/inc/public/ScreenPlay/createimportstates.h index 9d564581..d64d0b5f 100644 --- a/ScreenPlay/inc/public/ScreenPlay/createimportstates.h +++ b/ScreenPlay/inc/public/ScreenPlay/createimportstates.h @@ -3,17 +3,16 @@ #pragma once #include +#include namespace ScreenPlay { -/*! - \namespace ScreenPlay::ImportVideoState - \inmodule ScreenPlay - \brief Global enum for ImportVideoState. -*/ -namespace ImportVideoState { - Q_NAMESPACE - enum class ImportVideoState { +class Import : public QObject { + Q_OBJECT + QML_ELEMENT + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") +public: + enum class State { Idle, Started, AnalyseVideo, @@ -49,6 +48,6 @@ namespace ImportVideoState { Finished, Failed, }; - Q_ENUM_NS(ImportVideoState) -} + Q_ENUM(State) +}; } diff --git a/ScreenPlay/inc/public/ScreenPlay/createimportvideo.h b/ScreenPlay/inc/public/ScreenPlay/createimportvideo.h index 83f1d56b..da255051 100644 --- a/ScreenPlay/inc/public/ScreenPlay/createimportvideo.h +++ b/ScreenPlay/inc/public/ScreenPlay/createimportvideo.h @@ -24,24 +24,27 @@ namespace ScreenPlay { class CreateImportVideo : public QObject { Q_OBJECT + QML_ELEMENT QML_UNCREATABLE("") - + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") Q_PROPERTY(float progress READ progress WRITE setProgress NOTIFY progressChanged) public: explicit CreateImportVideo(const QString& videoPath, const QString& exportPath, const QString& codec, const int quality, std::atomic& interrupt); explicit CreateImportVideo(const QString& videoPath, const QString& exportPath, std::atomic& interrupt); + enum class Executable { + FFMPEG, + FFPROBE + }; + Q_ENUM(Executable) + float progress() const { return m_progress; } - bool m_skipAudio { false }; - // If the video is < 1s in duration we cannot create a 5s preview bool m_smallVideo { false }; - // We do not get many infos with this bool m_isWebm { false }; - float m_progress { 0.0F }; QString m_videoPath; @@ -54,13 +57,8 @@ public: int m_length { 0 }; int m_framerate { 0 }; - enum class Executable { - FFMPEG, - FFPROBE - }; - signals: - void createWallpaperStateChanged(ImportVideoState::ImportVideoState state); + void createWallpaperStateChanged(ScreenPlay::Import::State state); void processOutput(QString text); void finished(); void abortAndCleanup(); @@ -104,4 +102,3 @@ private: std::atomic& m_interrupt; }; } -Q_DECLARE_METATYPE(ScreenPlay::ImportVideoState::ImportVideoState) diff --git a/ScreenPlay/inc/public/ScreenPlay/globalvariables.h b/ScreenPlay/inc/public/ScreenPlay/globalvariables.h index 726283ef..9d317aa2 100644 --- a/ScreenPlay/inc/public/ScreenPlay/globalvariables.h +++ b/ScreenPlay/inc/public/ScreenPlay/globalvariables.h @@ -16,22 +16,24 @@ namespace ScreenPlay { class GlobalVariables : public QObject { Q_OBJECT QML_ELEMENT + QML_UNCREATABLE("") Q_PROPERTY(QVersionNumber version READ version CONSTANT) - Q_PROPERTY(QUrl localStoragePath READ localStoragePath WRITE setLocalStoragePath NOTIFY localStoragePathChanged) - Q_PROPERTY(QUrl localSettingsPath READ localSettingsPath WRITE setLocalSettingsPath NOTIFY localSettingsPathChanged) - Q_PROPERTY(QUrl wallpaperExecutablePath READ wallpaperExecutablePath WRITE setWallpaperExecutablePath NOTIFY wallpaperExecutablePathChanged) - Q_PROPERTY(QUrl widgetExecutablePath READ widgetExecutablePath WRITE setWidgetExecutablePath NOTIFY widgetExecutablePathChanged) + Q_PROPERTY(QUrl localStoragePath READ localStoragePath WRITE setLocalStoragePath NOTIFY localStoragePathChanged FINAL) + Q_PROPERTY(QUrl localSettingsPath READ localSettingsPath WRITE setLocalSettingsPath NOTIFY localSettingsPathChanged FINAL) + Q_PROPERTY(QUrl wallpaperExecutablePath READ wallpaperExecutablePath WRITE setWallpaperExecutablePath NOTIFY wallpaperExecutablePathChanged FINAL) + Q_PROPERTY(QUrl widgetExecutablePath READ widgetExecutablePath WRITE setWidgetExecutablePath NOTIFY widgetExecutablePathChanged FINAL) + Q_PROPERTY(QUrl godotWallpaperExecutablePath READ godotWallpaperExecutablePath WRITE setGodotWallpaperExecutablePath NOTIFY godotWallpaperExecutablePathChanged FINAL) + Q_PROPERTY(QUrl godotEditorExecutablePath READ godotEditorExecutablePath WRITE setGodotEditorExecutablePath NOTIFY godotEditorExecutablePathChanged FINAL) public: explicit GlobalVariables(QObject* parent = nullptr); /*! - \brief We need to check if there was an error in the Wallpaper/Widgets. - For this we ping it every 3s. - */ - static const int contentPingAliveIntervalMS = 3000; - + \property GlobalVariables::m_version + \brief Returns the current app version. Not yet used. + */ + QVersionNumber version() const { return m_version; } /*! \property GlobalVariables::localStoragePath \brief Returns the localStoragePath. @@ -56,51 +58,35 @@ public: \property GlobalVariables::m_version \brief Returns the current app version. Not yet used. */ - QVersionNumber version() const { return m_version; } + QUrl godotWallpaperExecutablePath() const { return m_godotWallpaperExecutablePath; } + /*! + \property GlobalVariables::m_version + \brief Returns the current app version. Not yet used. + */ + QUrl godotEditorExecutablePath() const { return m_godotEditorExecutablePath; } signals: void localStoragePathChanged(QUrl localStoragePath); void localSettingsPathChanged(QUrl localSettingsPath); void wallpaperExecutablePathChanged(QUrl wallpaperExecutablePath); void widgetExecutablePathChanged(QUrl widgetExecutablePath); + void godotWallpaperExecutablePathChanged(QUrl godotWallpaperExecutablePath); + void godotEditorExecutablePathChanged(QUrl godotEditorExecutablePath); public slots: + void setLocalStoragePath(QUrl localStoragePath); + void setLocalSettingsPath(QUrl localSettingsPath); + void setWallpaperExecutablePath(QUrl wallpaperExecutablePath); + void setWidgetExecutablePath(QUrl widgetExecutablePath); + void setGodotWallpaperExecutablePath(QUrl godotWallpaperExecutablePath); + void setGodotEditorExecutablePath(QUrl godotEditorExecutablePath); - void setLocalStoragePath(QUrl localStoragePath) - { - if (m_localStoragePath == localStoragePath) - return; - - m_localStoragePath = localStoragePath; - emit localStoragePathChanged(m_localStoragePath); - } - - void setLocalSettingsPath(QUrl localSettingsPath) - { - if (m_localSettingsPath == localSettingsPath) - return; - - m_localSettingsPath = localSettingsPath; - emit localSettingsPathChanged(m_localSettingsPath); - } - - void setWallpaperExecutablePath(QUrl wallpaperExecutablePath) - { - if (m_wallpaperExecutablePath == wallpaperExecutablePath) - return; - - m_wallpaperExecutablePath = wallpaperExecutablePath; - emit wallpaperExecutablePathChanged(m_wallpaperExecutablePath); - } - - void setWidgetExecutablePath(QUrl widgetExecutablePath) - { - if (m_widgetExecutablePath == widgetExecutablePath) - return; - - m_widgetExecutablePath = widgetExecutablePath; - emit widgetExecutablePathChanged(m_widgetExecutablePath); - } +public: + /*! + \brief We need to check if there was an error in the Wallpaper/Widgets. + For this we ping it every 3s. + */ + static const int contentPingAliveIntervalMS = 3000; private: QUrl m_localStoragePath; @@ -108,5 +94,7 @@ private: QUrl m_wallpaperExecutablePath; QUrl m_widgetExecutablePath; QVersionNumber m_version { 1, 0, 0 }; + QUrl m_godotWallpaperExecutablePath; + QUrl m_godotEditorExecutablePath; }; } diff --git a/ScreenPlay/inc/public/ScreenPlay/installedlistfilter.h b/ScreenPlay/inc/public/ScreenPlay/installedlistfilter.h index c4c77cd1..36c6ce9a 100644 --- a/ScreenPlay/inc/public/ScreenPlay/installedlistfilter.h +++ b/ScreenPlay/inc/public/ScreenPlay/installedlistfilter.h @@ -19,7 +19,7 @@ public: InstalledListFilter(const std::shared_ptr& ilm); public slots: - void sortBySearchType(const ScreenPlay::SearchType::SearchType searchType); + void sortBySearchType(const ScreenPlay::ContentTypes::SearchType searchType); void setSortOrder(const Qt::SortOrder sortOrder); void sortByName(const QString& name); void resetFilter(); @@ -29,7 +29,7 @@ signals: private: const std::shared_ptr m_ilm; - ScreenPlay::SearchType::SearchType m_searchType = ScreenPlay::SearchType::SearchType::All; + ScreenPlay::ContentTypes::SearchType m_searchType = ScreenPlay::ContentTypes::SearchType::All; Qt::SortOrder m_sortOrder = Qt::SortOrder::DescendingOrder; }; } diff --git a/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h b/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h index 32bdd3dc..274cc481 100644 --- a/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h +++ b/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h @@ -25,8 +25,8 @@ #include "ScreenPlay/globalvariables.h" #include "ScreenPlay/profilelistmodel.h" #include "ScreenPlay/settings.h" -#include "ScreenPlay/util.h" #include "ScreenPlayUtil/projectfile.h" +#include "ScreenPlayUtil/util.h" #include @@ -77,7 +77,7 @@ public slots: void append(const QString& projectJsonFilePath); void reset(); void init(); - void deinstallItemAt(const QString& absoluteStoragePath); + bool deinstallItemAt(const QString& absoluteStoragePath); void setCount(int count) { @@ -96,6 +96,7 @@ private: QFileSystemWatcher m_fileSystemWatcher; QVector m_screenPlayFiles; int m_count { 0 }; + QTimer m_reloadLimiter; std::atomic_bool m_isLoading { false }; const std::shared_ptr& m_globalVariables; diff --git a/ScreenPlay/inc/public/ScreenPlay/monitorlistmodel.h b/ScreenPlay/inc/public/ScreenPlay/monitorlistmodel.h index ed80ce6e..976b93b3 100644 --- a/ScreenPlay/inc/public/ScreenPlay/monitorlistmodel.h +++ b/ScreenPlay/inc/public/ScreenPlay/monitorlistmodel.h @@ -41,6 +41,8 @@ struct Monitor { class MonitorListModel : public QAbstractListModel { Q_OBJECT QML_ELEMENT + QML_UNCREATABLE("") + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") public: explicit MonitorListModel(QObject* parent = nullptr); diff --git a/ScreenPlay/inc/public/ScreenPlay/projectsettingslistmodel.h b/ScreenPlay/inc/public/ScreenPlay/projectsettingslistmodel.h index 6799079c..061edcb9 100644 --- a/ScreenPlay/inc/public/ScreenPlay/projectsettingslistmodel.h +++ b/ScreenPlay/inc/public/ScreenPlay/projectsettingslistmodel.h @@ -11,7 +11,7 @@ #include #include -#include "ScreenPlay/util.h" +#include "ScreenPlayUtil/util.h" namespace ScreenPlay { @@ -59,7 +59,7 @@ public: Q_ENUM(ProjectSettingsRole) QJsonObject getActiveSettingsJson(); - void init(const InstalledType::InstalledType& type, const QJsonObject& properties); + void init(const ContentTypes::InstalledType& type, const QJsonObject& properties); void append(const SettingsItem&& item); public slots: diff --git a/ScreenPlay/inc/public/ScreenPlay/screenplaymanager.h b/ScreenPlay/inc/public/ScreenPlay/screenplaymanager.h index 00fbc390..a16550a9 100644 --- a/ScreenPlay/inc/public/ScreenPlay/screenplaymanager.h +++ b/ScreenPlay/inc/public/ScreenPlay/screenplaymanager.h @@ -24,6 +24,7 @@ namespace ScreenPlay { class ScreenPlayManager : public QObject { Q_OBJECT QML_ELEMENT + QML_UNCREATABLE("") Q_PROPERTY(int activeWallpaperCounter READ activeWallpaperCounter WRITE setActiveWallpaperCounter NOTIFY activeWallpaperCounterChanged) Q_PROPERTY(int activeWidgetsCounter READ activeWidgetsCounter WRITE setActiveWidgetsCounter NOTIFY activeWidgetsCounterChanged) @@ -40,7 +41,6 @@ public: int activeWidgetsCounter() const { return m_activeWidgetsCounter; } bool isAnotherScreenPlayInstanceRunning() { return m_isAnotherScreenPlayInstanceRunning; } - signals: void activeWallpaperCounterChanged(int activeWallpaperCounter); void activeWidgetsCounterChanged(int activeWidgetsCounter); @@ -58,8 +58,8 @@ private slots: public slots: // moc needs full enum namespace info see QTBUG-58454 bool createWallpaper( - const ScreenPlay::InstalledType::InstalledType type, - const ScreenPlay::FillMode::FillMode fillMode, + const ScreenPlay::ContentTypes::InstalledType type, + const ScreenPlay::Video::FillMode fillMode, const QString& absoluteStoragePath, const QString& previewImage, const QString& file, @@ -70,7 +70,7 @@ public slots: const bool saveToProfilesConfigFile); bool createWidget( - const ScreenPlay::InstalledType::InstalledType type, + const ScreenPlay::ContentTypes::InstalledType type, const QPoint& position, const QString& absoluteStoragePath, const QString& previewImage, diff --git a/ScreenPlay/inc/public/ScreenPlay/screenplaywallpaper.h b/ScreenPlay/inc/public/ScreenPlay/screenplaywallpaper.h index 65516e0e..37bf7344 100644 --- a/ScreenPlay/inc/public/ScreenPlay/screenplaywallpaper.h +++ b/ScreenPlay/inc/public/ScreenPlay/screenplaywallpaper.h @@ -3,10 +3,13 @@ #pragma once #include +#include +#include #include #include #include - +#include +#include #include #include "ScreenPlay/globalvariables.h" @@ -19,27 +22,21 @@ namespace ScreenPlay { class ScreenPlayWallpaper : public QObject { Q_OBJECT QML_ELEMENT + QML_UNCREATABLE("") Q_PROPERTY(bool isConnected READ isConnected WRITE setIsConnected NOTIFY isConnectedChanged) - Q_PROPERTY(QVector screenNumber READ screenNumber WRITE setScreenNumber NOTIFY screenNumberChanged) - Q_PROPERTY(float volume READ volume WRITE setVolume NOTIFY volumeChanged) Q_PROPERTY(float playbackRate READ playbackRate WRITE setPlaybackRate NOTIFY playbackRateChanged) Q_PROPERTY(bool isLooping READ isLooping WRITE setIsLooping NOTIFY isLoopingChanged) - Q_PROPERTY(QString file READ file WRITE setFile NOTIFY fileChanged) Q_PROPERTY(QString absolutePath READ absolutePath WRITE setAbsolutePath NOTIFY absolutePathChanged) Q_PROPERTY(QString previewImage READ previewImage WRITE setPreviewImage NOTIFY previewImageChanged) Q_PROPERTY(QString appID READ appID WRITE setAppID NOTIFY appIDChanged) - - Q_PROPERTY(FillMode::FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged) - Q_PROPERTY(InstalledType::InstalledType type READ type WRITE setType NOTIFY typeChanged) + Q_PROPERTY(Video::FillMode fillMode READ fillMode WRITE setFillMode NOTIFY fillModeChanged) + Q_PROPERTY(ContentTypes::InstalledType type READ type WRITE setType NOTIFY typeChanged) public: - // Default constructor needed for qml engine - ScreenPlayWallpaper() { } - explicit ScreenPlayWallpaper( const QVector& screenNumber, const std::shared_ptr& globalVariables, @@ -49,8 +46,8 @@ public: const QString& file, const float volume, const float playbackRate, - const FillMode::FillMode fillMode, - const InstalledType::InstalledType type, + const Video::FillMode fillMode, + const ContentTypes::InstalledType type, const QJsonObject& properties, const std::shared_ptr& settings, QObject* parent = nullptr); @@ -62,8 +59,8 @@ public: const QString& previewImage, const QString& file, const float volume, - const FillMode::FillMode fillMode, - const InstalledType::InstalledType type, + const Video::FillMode fillMode, + const ContentTypes::InstalledType type, const bool checkWallpaperVisible); void setSDKConnection(std::unique_ptr connection); @@ -73,9 +70,9 @@ public: QVector screenNumber() const { return m_screenNumber; } QString previewImage() const { return m_previewImage; } QString appID() const { return m_appID; } - InstalledType::InstalledType type() const { return m_type; } + ContentTypes::InstalledType type() const { return m_type; } QString file() const { return m_file; } - FillMode::FillMode fillMode() const { return m_fillMode; } + Video::FillMode fillMode() const { return m_fillMode; } QString absolutePath() const { return m_absolutePath; } float volume() const { return m_volume; } bool isLooping() const { return m_isLooping; } @@ -87,9 +84,9 @@ signals: void screenNumberChanged(QVector screenNumber); void previewImageChanged(QString previewImage); void appIDChanged(QString appID); - void typeChanged(InstalledType::InstalledType type); + void typeChanged(ContentTypes::InstalledType type); void fileChanged(QString file); - void fillModeChanged(FillMode::FillMode fillMode); + void fillModeChanged(Video::FillMode fillMode); void absolutePathChanged(QString absolutePath); void profileJsonObjectChanged(QJsonObject profileJsonObject); void volumeChanged(float volume); @@ -135,7 +132,7 @@ public slots: emit appIDChanged(m_appID); } - void setType(InstalledType::InstalledType type) + void setType(ContentTypes::InstalledType type) { if (m_type == type) return; @@ -153,7 +150,7 @@ public slots: emit fileChanged(m_file); } - void setFillMode(FillMode::FillMode fillMode) + void setFillMode(Video::FillMode fillMode) { if (m_fillMode == fillMode) return; @@ -209,17 +206,21 @@ public slots: emit isConnectedChanged(m_isConnected); } +private: + bool exportGodotProject(); + private: const std::shared_ptr m_globalVariables; std::unique_ptr m_connection; const std::shared_ptr m_settings; ProjectSettingsListModel m_projectSettingsListModel; + QJsonObject m_projectJson; QVector m_screenNumber; QProcess m_process; QString m_previewImage; - InstalledType::InstalledType m_type; - FillMode::FillMode m_fillMode; + ContentTypes::InstalledType m_type; + Video::FillMode m_fillMode; QString m_appID; QString m_absolutePath; QString m_file; diff --git a/ScreenPlay/inc/public/ScreenPlay/screenplaywidget.h b/ScreenPlay/inc/public/ScreenPlay/screenplaywidget.h index fa6e587f..0d0cdcd0 100644 --- a/ScreenPlay/inc/public/ScreenPlay/screenplaywidget.h +++ b/ScreenPlay/inc/public/ScreenPlay/screenplaywidget.h @@ -23,12 +23,13 @@ namespace ScreenPlay { class ScreenPlayWidget : public QObject { Q_OBJECT QML_ELEMENT + QML_UNCREATABLE("") Q_PROPERTY(QString absolutePath READ absolutePath WRITE setAbsolutePath NOTIFY absolutePathChanged) Q_PROPERTY(QString previewImage READ previewImage WRITE setPreviewImage NOTIFY previewImageChanged) Q_PROPERTY(QPoint position READ position WRITE setPosition NOTIFY positionChanged) Q_PROPERTY(QString appID READ appID WRITE setAppID NOTIFY appIDChanged) - Q_PROPERTY(InstalledType::InstalledType type READ type WRITE setType NOTIFY typeChanged) + Q_PROPERTY(ContentTypes::InstalledType type READ type WRITE setType NOTIFY typeChanged) public: explicit ScreenPlayWidget( @@ -37,7 +38,7 @@ public: const QPoint& position, const QString& absolutePath, const QString& previewImage, const QJsonObject& properties, - const InstalledType::InstalledType type); + const ContentTypes::InstalledType type); bool start(); @@ -47,7 +48,7 @@ public: QPoint position() const { return m_position; } QString absolutePath() const { return m_absolutePath; } QString appID() const { return m_appID; } - InstalledType::InstalledType type() const { return m_type; } + ContentTypes::InstalledType type() const { return m_type; } void setSDKConnection(std::unique_ptr connection); @@ -84,7 +85,7 @@ public slots: emit appIDChanged(m_appID); } - void setType(InstalledType::InstalledType type) + void setType(ContentTypes::InstalledType type) { if (m_type == type) return; @@ -106,7 +107,7 @@ signals: void previewImageChanged(QString previewImage); void positionChanged(QPoint position); void appIDChanged(QString appID); - void typeChanged(InstalledType::InstalledType type); + void typeChanged(ContentTypes::InstalledType type); void absolutePathChanged(QString absolutePath); void requestSave(); @@ -122,7 +123,7 @@ private: QString m_previewImage; QString m_appID; QPoint m_position; - InstalledType::InstalledType m_type; + ContentTypes::InstalledType m_type; QString m_absolutePath; QTimer m_pingAliveTimer; QStringList m_appArgumentsList; diff --git a/ScreenPlay/inc/public/ScreenPlay/sdkconnection.h b/ScreenPlay/inc/public/ScreenPlay/sdkconnection.h index 6dbf336c..88bb4787 100644 --- a/ScreenPlay/inc/public/ScreenPlay/sdkconnection.h +++ b/ScreenPlay/inc/public/ScreenPlay/sdkconnection.h @@ -14,7 +14,6 @@ #include #include "ScreenPlay/globalvariables.h" -#include "ScreenPlay/util.h" #include "ScreenPlayUtil/util.h" #include diff --git a/ScreenPlay/inc/public/ScreenPlay/settings.h b/ScreenPlay/inc/public/ScreenPlay/settings.h index 3fc63987..e0888e37 100644 --- a/ScreenPlay/inc/public/ScreenPlay/settings.h +++ b/ScreenPlay/inc/public/ScreenPlay/settings.h @@ -33,7 +33,7 @@ #include #include "ScreenPlay/globalvariables.h" -#include "ScreenPlay/util.h" +#include "ScreenPlayUtil/util.h" #include #include @@ -43,7 +43,9 @@ class ActiveProfile; class Settings : public QObject { Q_OBJECT + QML_ELEMENT QML_UNCREATABLE("") + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") Q_PROPERTY(bool showDefaultContent READ showDefaultContent WRITE setShowDefaultContent NOTIFY showDefaultContentChanged) Q_PROPERTY(bool anonymousTelemetry READ anonymousTelemetry WRITE setAnonymousTelemetry NOTIFY anonymousTelemetryChanged) @@ -54,10 +56,10 @@ class Settings : public QObject { Q_PROPERTY(bool offlineMode READ offlineMode WRITE setOfflineMode NOTIFY offlineModeChanged) Q_PROPERTY(bool steamVersion READ steamVersion WRITE setSteamVersion NOTIFY steamVersionChanged) - Q_PROPERTY(ScreenPlay::FillMode::FillMode videoFillMode READ videoFillMode WRITE setVideoFillMode NOTIFY videoFillModeChanged) - Q_PROPERTY(DesktopEnvironment desktopEnvironment READ desktopEnvironment WRITE setDesktopEnvironment NOTIFY desktopEnvironmentChanged) - Q_PROPERTY(Language language READ language WRITE setLanguage NOTIFY languageChanged) - Q_PROPERTY(Theme theme READ theme WRITE setTheme NOTIFY themeChanged) + Q_PROPERTY(ScreenPlay::Video::FillMode videoFillMode READ videoFillMode WRITE setVideoFillMode NOTIFY videoFillModeChanged) + Q_PROPERTY(ScreenPlay::Settings::DesktopEnvironment desktopEnvironment READ desktopEnvironment WRITE setDesktopEnvironment NOTIFY desktopEnvironmentChanged) + Q_PROPERTY(ScreenPlay::Settings::Language language READ language WRITE setLanguage NOTIFY languageChanged) + Q_PROPERTY(ScreenPlay::Settings::Theme theme READ theme WRITE setTheme NOTIFY themeChanged) Q_PROPERTY(QString decoder READ decoder WRITE setDecoder NOTIFY decoderChanged) Q_PROPERTY(QString buildInfos READ buildInfos WRITE setBuildInfos NOTIFY buildInfosChanged) @@ -83,6 +85,7 @@ public: Unity, XFCE, }; + Q_ENUM(DesktopEnvironment) enum class Language { En_US, @@ -116,12 +119,12 @@ public: bool silentStart() const { return m_silentStart; } bool anonymousTelemetry() const { return m_anonymousTelemetry; } bool checkWallpaperVisible() const { return m_checkWallpaperVisible; } - ScreenPlay::FillMode::FillMode videoFillMode() const { return m_videoFillMode; } - Language language() const { return m_language; } + ScreenPlay::Video::FillMode videoFillMode() const { return m_videoFillMode; } + ScreenPlay::Settings::Language language() const { return m_language; } QString font() const { return m_font; } - Theme theme() const { return m_theme; } + ScreenPlay::Settings::Theme theme() const { return m_theme; } bool steamVersion() const { return m_steamVersion; } - DesktopEnvironment desktopEnvironment() const { return m_desktopEnvironment; } + ScreenPlay::Settings::DesktopEnvironment desktopEnvironment() const { return m_desktopEnvironment; } const QString& buildInfos() const { return m_buildInfos; } bool showDefaultContent() const { return m_showDefaultContent; } @@ -137,12 +140,12 @@ signals: void silentStartChanged(bool silentStart); void anonymousTelemetryChanged(bool anonymousTelemetry); void checkWallpaperVisibleChanged(bool checkWallpaperVisible); - void videoFillModeChanged(ScreenPlay::FillMode::FillMode videoFillMode); + void videoFillModeChanged(ScreenPlay::Video::FillMode videoFillMode); void languageChanged(ScreenPlay::Settings::Language language); void fontChanged(QString font); void themeChanged(ScreenPlay::Settings::Theme theme); void steamVersionChanged(bool steamVersion); - void desktopEnvironmentChanged(DesktopEnvironment desktopEnvironment); + void desktopEnvironmentChanged(ScreenPlay::Settings::DesktopEnvironment desktopEnvironment); void buildInfosChanged(const QString& buildInfos); void showDefaultContentChanged(bool showDefaultContent); @@ -152,306 +155,23 @@ public slots: void setupWidgetAndWindowPaths(); bool retranslateUI(); - void setShowDefaultContent(bool showDefaultContent) - { - if (m_showDefaultContent == showDefaultContent) - return; - m_showDefaultContent = showDefaultContent; - emit showDefaultContentChanged(showDefaultContent); - } - - void setqSetting(const QString& key, const QVariant& value) - { - m_qSettings.setValue(key, value); - m_qSettings.sync(); - } - - void setAutostart(bool autostart) - { - if (desktopEnvironment() == DesktopEnvironment::Windows) { - - QSettings settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat); - if (autostart) { - settings.setValue("ScreenPlay", QDir::toNativeSeparators(QCoreApplication::applicationFilePath()) + " -silent"); - settings.sync(); - } else { - settings.remove("ScreenPlay"); - } - } - if (desktopEnvironment() == DesktopEnvironment::OSX) { - const QString plistFileName = "app.screenplay.plist"; - QFile defaultPListFile(":/qml/ScreenPlayApp/assets/macos/" + plistFileName); - defaultPListFile.open(QIODevice::ReadOnly); - QString settingsPlistContent = defaultPListFile.readAll(); - if (!settingsPlistContent.contains("{{SCREENPLAY_PATH}}")) { - qCritical() << "Unable to load plist settings template from qrc to set autostart!"; - return; - } - - QDir workingDir(QGuiApplication::applicationDirPath()); - workingDir.cdUp(); - workingDir.cdUp(); - workingDir.cdUp(); - const QString screenPlayPath = QUrl::fromUserInput(workingDir.path() + "/ScreenPlay.app/Contents/MacOS/ScreenPlay").toLocalFile(); - settingsPlistContent.replace("{{SCREENPLAY_PATH}}", screenPlayPath); - settingsPlistContent.replace("{{SCREENPLAY_AUTOSTART}}", autostart ? "true" : "false"); - - const QString homePath = QDir::homePath(); - QFile settingsPlist(homePath + "/Library/LaunchAgents/" + plistFileName); - if (settingsPlist.exists()) { - QDomDocument doc; - if (!doc.setContent(&settingsPlist)) { - settingsPlist.close(); - return; - } - settingsPlist.close(); - - QDomElement root = doc.firstChildElement(); - QDomNodeList dictList = root.elementsByTagName("dict"); - if (dictList.size() > 1 && dictList.size() < 1) { - return; - } - - // Check if autostart and corresponding path is set and abort if so. This is needed since osx 13.0 Ventura - // because it displays an annoying message every time we change the file. - bool isCorrectPath = false; - bool isAutostartEnabled = false; - QDomNode dictNode = dictList.at(0); - if (dictNode.isElement()) { - QDomElement dictElement = dictNode.toElement(); - QDomNodeList keyList = dictElement.elementsByTagName("key"); - for (int j = 0; j < keyList.size(); j++) { - QDomNode keyNode = keyList.at(j); - if (keyNode.isElement()) { - QDomElement keyElement = keyNode.toElement(); - if (keyElement.text() == "ProgramArguments") { - QDomNode valueNode = keyNode.nextSibling(); - if (valueNode.isElement()) { - QDomElement valueElement = valueNode.toElement(); - QDomNodeList stringList = valueElement.elementsByTagName("string"); - if (!stringList.isEmpty()) { - QDomNode stringNode = stringList.at(0); - if (stringNode.isElement()) { - QDomElement stringElement = stringNode.toElement(); - const QString path = stringElement.text(); - if (path == screenPlayPath) { - isCorrectPath = true; - } - } - } - } - } - } - } - } - - if (dictNode.isElement()) { - QDomElement dictElement = dictNode.toElement(); - QDomNodeList keyList = dictElement.elementsByTagName("key"); - for (int j = 0; j < keyList.size(); j++) { - QDomNode keyNode = keyList.at(j); - if (keyNode.isElement()) { - QDomElement keyElement = keyNode.toElement(); - if (keyElement.text() == "RunAtLoad") { - QDomNode valueNode = keyNode.nextSibling(); - if (valueNode.isElement()) { - QDomElement valueElement = valueNode.toElement(); - if (valueElement.tagName() == "true") { - isAutostartEnabled = true; - } - } - } - } - } - } - - // Nothing to do. Autostart has the same value and the path is also correct. - if (isAutostartEnabled == autostart && isCorrectPath) - return; - - if (!settingsPlist.remove()) { - qCritical() << "Unable to remove: " << settingsPlist.fileName(); - } - } - - settingsPlist.open(QIODevice::WriteOnly | QIODevice::Truncate); - QTextStream out(&settingsPlist); - out.setEncoding(QStringConverter::Utf8); - out << settingsPlistContent; - settingsPlist.flush(); - settingsPlist.close(); - - qInfo() << "Set autostart enabled: " << autostart; - } - setqSetting("Autostart", autostart); - - m_autostart = autostart; - emit autostartChanged(m_autostart); - } - - void setHighPriorityStart(bool highPriorityStart) - { - if (m_highPriorityStart == highPriorityStart) - return; - - setqSetting("HighPriorityStart", highPriorityStart); - - const QString app = "'" + QGuiApplication::applicationDirPath() + "/WindowsServiceHelper.exe" + "'"; - QStringList args { "-Command", QString("Start-Process %1 -Verb runAs").arg(app), "-ArgumentList" }; - - // Because we must use powershell, we need to add an extra 'var' and , - auto appendAsString = [&](const QString& string, const bool isLast = false) { - QString arg = "'" + string + "'"; - if (!isLast) - arg += ","; - args.append(arg); - }; - - appendAsString("--t"); - appendAsString("create"); - appendAsString("--sn"); - appendAsString("ScreenPlayService"); - appendAsString("--dn"); - appendAsString("ScreenPlayService"); - appendAsString("--a"); - appendAsString(QVariant(highPriorityStart).toString(), true); - - QProcess process; - process.start(QStringLiteral("powershell"), args); - process.waitForFinished(5000); - - m_highPriorityStart = highPriorityStart; - emit highPriorityStartChanged(m_highPriorityStart); - } - - void setLocalStoragePath(QUrl localStoragePath) - { - // Remove: "file:///" - QJsonValue cleanedPath = QJsonValue(localStoragePath.toString()); - - setqSetting("ScreenPlayContentPath", cleanedPath); - - m_globalVariables->setLocalStoragePath(cleanedPath.toString()); - emit resetInstalledListmodel(); - } - - void setDecoder(QString decoder) - { - if (m_decoder == decoder) - return; - - m_decoder = decoder; - - emit decoderChanged(m_decoder); - } - - void setOfflineMode(bool offlineMode) - { - if (m_offlineMode == offlineMode) - return; - - m_offlineMode = offlineMode; - emit offlineModeChanged(m_offlineMode); - } - - void setSilentStart(bool silentStart) - { - if (m_silentStart == silentStart) - return; - - m_silentStart = silentStart; - emit silentStartChanged(m_silentStart); - } - - void setAnonymousTelemetry(bool anonymousTelemetry) - { - if (m_anonymousTelemetry == anonymousTelemetry) - return; - - setqSetting("AnonymousTelemetry", anonymousTelemetry); - - m_anonymousTelemetry = anonymousTelemetry; - emit anonymousTelemetryChanged(m_anonymousTelemetry); - } - - void setCheckWallpaperVisible(bool checkWallpaperVisible) - { - if (m_checkWallpaperVisible == checkWallpaperVisible) - return; - - setqSetting("CheckWallpaperVisible", checkWallpaperVisible); - - m_checkWallpaperVisible = checkWallpaperVisible; - emit checkWallpaperVisibleChanged(m_checkWallpaperVisible); - } - - void setVideoFillMode(ScreenPlay::FillMode::FillMode videoFillMode) - { - if (m_videoFillMode == videoFillMode) - return; - - setqSetting("VideoFillMode", QVariant::fromValue(videoFillMode).toString()); - - m_videoFillMode = videoFillMode; - emit videoFillModeChanged(m_videoFillMode); - } - - void setLanguage(ScreenPlay::Settings::Language language) - { - if (m_language == language) - return; - - setqSetting("Language", QVariant::fromValue(language).toString()); - - m_language = language; - emit languageChanged(m_language); - } - - void setFont(QString font) - { - if (m_font == font) - return; - - m_font = font; - emit fontChanged(m_font); - } - - void setTheme(ScreenPlay::Settings::Theme theme) - { - if (m_theme == theme) - return; - - setqSetting("Theme", QVariant::fromValue(theme).toString()); - - m_theme = theme; - emit themeChanged(m_theme); - } - - void setSteamVersion(bool steamVersion) - { - if (m_steamVersion == steamVersion) - return; - - m_steamVersion = steamVersion; - emit steamVersionChanged(m_steamVersion); - } - - void setDesktopEnvironment(DesktopEnvironment desktopEnvironment) - { - if (m_desktopEnvironment == desktopEnvironment) - return; - - m_desktopEnvironment = desktopEnvironment; - emit desktopEnvironmentChanged(m_desktopEnvironment); - } - - void setBuildInfos(const QString& buildInfos) - { - if (m_buildInfos == buildInfos) - return; - m_buildInfos = buildInfos; - emit buildInfosChanged(m_buildInfos); - } + void setShowDefaultContent(bool showDefaultContent); + void setqSetting(const QString& key, const QVariant& value); + void setAutostart(bool autostart); + void setHighPriorityStart(bool highPriorityStart); + void setLocalStoragePath(QUrl localStoragePath); + void setDecoder(QString decoder); + void setOfflineMode(bool offlineMode); + void setSilentStart(bool silentStart); + void setAnonymousTelemetry(bool anonymousTelemetry); + void setCheckWallpaperVisible(bool checkWallpaperVisible); + void setVideoFillMode(ScreenPlay::Video::FillMode videoFillMode); + void setLanguage(ScreenPlay::Settings::Language language); + void setFont(QString font); + void setTheme(ScreenPlay::Settings::Theme theme); + void setSteamVersion(bool steamVersion); + void setDesktopEnvironment(ScreenPlay::Settings::DesktopEnvironment desktopEnvironment); + void setBuildInfos(const QString& buildInfos); private: void restoreDefault(const QString& appConfigLocation, const QString& settingsFileType); @@ -473,13 +193,13 @@ private: bool m_anonymousTelemetry { true }; bool m_showDefaultContent { false }; - QString m_decoder; - ScreenPlay::FillMode::FillMode m_videoFillMode { ScreenPlay::FillMode::FillMode::Cover }; - Language m_language { Language::En_US }; - Theme m_theme { Theme::System }; + ScreenPlay::Video::FillMode m_videoFillMode { ScreenPlay::Video::FillMode::Cover }; + ScreenPlay::Settings::Language m_language { Language::En_US }; + ScreenPlay::Settings::Theme m_theme { Theme::System }; + ScreenPlay::Settings::DesktopEnvironment m_desktopEnvironment { DesktopEnvironment::Unknown }; QString m_font { "Roboto" }; + QString m_decoder; bool m_steamVersion { false }; - DesktopEnvironment m_desktopEnvironment = DesktopEnvironment::Unknown; QString m_buildInfos; }; } diff --git a/ScreenPlay/inc/public/ScreenPlay/util.h b/ScreenPlay/inc/public/ScreenPlay/util.h deleted file mode 100644 index 40387ed8..00000000 --- a/ScreenPlay/inc/public/ScreenPlay/util.h +++ /dev/null @@ -1,132 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only - -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "ScreenPlay/globalvariables.h" -#include "ScreenPlayUtil/contenttypes.h" -#include "ScreenPlayUtil/util.h" - -#include -#include -#include - -namespace QArchive { -class DiskCompressor; -class DiskExtractor; -} - -namespace ScreenPlay { - -template -T QStringToEnum(const QString& key, const T defaultValue) -{ - auto metaEnum = QMetaEnum::fromType(); - - bool ok = false; - T wantedEnum = static_cast(metaEnum.keyToValue(key.toUtf8(), &ok)); - - if (ok) { - return wantedEnum; - } else { - qWarning() << "Unable to convert QStringToEnum. Key: " << key; - } - - return defaultValue; -} - -class Util : public QObject { - Q_OBJECT - Q_PROPERTY(QString debugMessages READ debugMessages NOTIFY debugMessagesChanged) - -public: - Util(); - ~Util(); - - QString debugMessages() const { return m_debugMessages; } - -signals: - void extractionProgressChanged(QString file, int proc, int total, qint64 br, qint64 bt); - void extractionFinished(); - void compressionProgressChanged(QString file, int proc, int total, qint64 br, qint64 bt); - void compressionFinished(); - - void requestNavigation(QString nav); - void requestNavigationActive(bool isActive); - void requestToggleWallpaperConfiguration(); - void setSidebarItem(QString folderName, ScreenPlay::InstalledType::InstalledType type); - void allLicenseLoaded(QString licensesText); - void allDataProtectionLoaded(QString dataProtectionText); - void debugMessagesChanged(QString debugMessages); - -public slots: - void copyToClipboard(const QString& text) const; - void openFolderInExplorer(const QString& url) const; - QString toLocal(const QString& url) const; - bool exportProject(QString contentPath, QString exportFileName); - bool importProject(QString archivePath, QString extractionPath); - void requestAllLicenses(); - void requestDataProtection(); - bool fileExists(const QString& filePath) const; - - static void logToGui(QtMsgType type, const QMessageLogContext& context, const QString& msg); - static bool writeJsonObjectToFile(const QString& absoluteFilePath, const QJsonObject& object, bool truncate = true); - static bool writeSettings(const QJsonObject& obj, const QString& absolutePath); - static bool writeFile(const QString& text, const QString& absolutePath); - static bool writeFileFromQrc(const QString& qrcPath, const QString& absolutePath); - static bool copyPreviewThumbnail(QJsonObject& obj, const QString& previewThumbnail, const QString& destination); - - void setNavigation(QString nav) - { - emit requestNavigation(nav); - } - - // When we create a wallpaper the main navigation gets disabled - void setNavigationActive(bool isActive) - { - emit requestNavigationActive(isActive); - } - - void setToggleWallpaperConfiguration() - { - emit requestToggleWallpaperConfiguration(); - } - - void appendDebugMessages(QString debugMessages) - { - if (m_debugMessages.size() > 10000) { - m_debugMessages = "###### DEBUG CLEARED ######"; - } - - m_debugMessages += debugMessages; - emit debugMessagesChanged(m_debugMessages); - } - -private: - QString m_debugMessages {}; - QFuture m_requestAllLicensesFuture; - std::unique_ptr m_compressor; - std::unique_ptr m_extractor; -}; - -// Used for redirect content from static logToGui to setDebugMessages -static Util* utilPointer { nullptr }; -} diff --git a/ScreenPlay/inc/public/ScreenPlay/wizards.h b/ScreenPlay/inc/public/ScreenPlay/wizards.h index 10abc659..3ab6f2fb 100644 --- a/ScreenPlay/inc/public/ScreenPlay/wizards.h +++ b/ScreenPlay/inc/public/ScreenPlay/wizards.h @@ -2,6 +2,7 @@ #pragma once +#include #include #include #include @@ -24,7 +25,7 @@ #include "ScreenPlay/createimportvideo.h" #include "ScreenPlay/globalvariables.h" -#include "ScreenPlay/util.h" +#include "ScreenPlayUtil/util.h" #include #include @@ -34,9 +35,11 @@ namespace ScreenPlay { class Wizards : public QObject { Q_OBJECT QML_ELEMENT + QML_UNCREATABLE("CPP ONLY") public: - explicit Wizards(const std::shared_ptr& globalVariables, QObject* parent = nullptr); - Wizards() { } + explicit Wizards( + const std::shared_ptr& globalVariables, + QObject* parent = nullptr); enum class WizardResult { Ok, @@ -82,6 +85,14 @@ public slots: const QString& previewThumbnail, const QVector& tags); + void createGodotWallpaper( + const QString& title, + const QString& licenseName, + const QString& licenseFile, + const QString& createdBy, + const QString& previewThumbnail, + const QVector& tags); + void createGifWallpaper( const QString& title, const QString& licenseName, @@ -103,8 +114,17 @@ signals: private: const std::shared_ptr m_globalVariables; const std::optional createTemporaryFolder() const; + void createPreviewImage(const QString& name, const QString& targetPath); private: QFuture m_wizardFuture; + QVector m_gradientColors = { + QColor("#B71C1C"), + QColor("#1B5E20"), + QColor("#0D47A1"), + QColor("#FFD600"), + QColor("#4A148C") + }; + Util m_util; }; } diff --git a/ScreenPlay/main.cpp b/ScreenPlay/main.cpp index f7ea57ef..335847f9 100644 --- a/ScreenPlay/main.cpp +++ b/ScreenPlay/main.cpp @@ -1,6 +1,8 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only +#include "ScreenPlay/CMakeVariables.h" #include "ScreenPlay/app.h" +#include "ScreenPlayUtil/logginghandler.h" #include #include #include @@ -30,12 +32,14 @@ int main(int argc, char* argv[]) if (app.m_isAnotherScreenPlayInstanceRunning) { return 0; - } else { - app.init(); - const int status = qtGuiApp.exec(); -#if defined(Q_OS_WIN) - sentry_shutdown(); -#endif - return status; } + + auto logging = std::make_unique("ScreenPlay"); + app.init(); + const int status = qtGuiApp.exec(); +#if defined(Q_OS_WIN) + sentry_shutdown(); +#endif + logging.reset(); + return status; } diff --git a/ScreenPlay/main.qml b/ScreenPlay/main.qml index 4ec06b04..59319cc3 100644 --- a/ScreenPlay/main.qml +++ b/ScreenPlay/main.qml @@ -7,7 +7,6 @@ import QtQuick.Controls.Material import QtQuick.Layouts import ScreenPlayApp import ScreenPlay -import Settings import ScreenPlayUtil as Util import Qt5Compat.GraphicalEffects import Plausible 1.0 @@ -22,13 +21,13 @@ ApplicationWindow { function setTheme(theme) { switch (theme) { - case Settings.System: + case Settings.Theme.System: root.Material.theme = Material.System; break; - case Settings.Dark: + case Settings.Theme.Dark: root.Material.theme = Material.Dark; break; - case Settings.Light: + case Settings.Theme.Light: root.Material.theme = Material.Light; break; } @@ -40,14 +39,15 @@ ApplicationWindow { App.installedListModel.reset(); } if (name === "Installed") { - stackView.replace("qrc:/qml/ScreenPlayApp/qml/Installed/Installed.qml", { + stackView.replace("qrc:/qml/ScreenPlayApp/qml/Installed/InstalledView.qml", { "sidebar": sidebar }); return; } - stackView.replace("qrc:/qml/ScreenPlayApp/qml/" + name + "/" + name + ".qml", { + stackView.replace("qrc:/qml/ScreenPlayApp/qml/" + name + "/" + name + "View.qml", { "modalSource": content }); + nav.setNavigation(name); sidebar.state = "inactive"; } @@ -56,7 +56,7 @@ ApplicationWindow { visible: false width: 1400 height: 810 - title: "ScreenPlay Alpha - V" + App.version() + title: "ScreenPlay Alpha - v" + App.version() minimumHeight: 450 minimumWidth: 1050 @@ -72,9 +72,10 @@ ApplicationWindow { // https://bugreports.qt.io/browse/QTBUG-86047 Material.accent: Material.color(Material.Orange) onVisibilityChanged: { - if (root.visibility === 2) - App.installedListModel.reset(); + if (root.visibility !== 2) + return; } + onClosing: close => { close.accepted = false; if (App.screenPlayManager.activeWallpaperCounter === 0 && App.screenPlayManager.activeWidgetsCounter === 0) { @@ -103,14 +104,17 @@ ApplicationWindow { } Component.onCompleted: { + print("Settings.Language.Pl_PL", Settings.Language.Pl_PL); + print(App.settings.theme, Settings.Theme.Light); setTheme(App.settings.theme); - stackView.push("qrc:/qml/ScreenPlayApp/qml/Installed/Installed.qml", { + stackView.push("qrc:/qml/ScreenPlayApp/qml/Installed/InstalledView.qml", { "sidebar": sidebar }); if (!App.settings.silentStart) { App.showDockIcon(true); root.show(); } + App.installedListModel.reset(); } Item { @@ -129,7 +133,7 @@ ApplicationWindow { modalSource: content } - Monitors.Monitors { + Monitors.MonitorsView { id: monitors modalSource: content } diff --git a/ScreenPlay/qml/Community/Community.qml b/ScreenPlay/qml/Community/CommunityView.qml similarity index 100% rename from ScreenPlay/qml/Community/Community.qml rename to ScreenPlay/qml/Community/CommunityView.qml diff --git a/ScreenPlay/qml/Community/XMLNewsfeed.qml b/ScreenPlay/qml/Community/XMLNewsfeed.qml index dcbd43fc..f0e13477 100644 --- a/ScreenPlay/qml/Community/XMLNewsfeed.qml +++ b/ScreenPlay/qml/Community/XMLNewsfeed.qml @@ -105,7 +105,7 @@ Item { source: image opacity: status === Image.Ready ? 1 : 0 - Behavior on opacity { + Behavior on opacity { PropertyAnimation { duration: 250 } diff --git a/ScreenPlay/qml/Create/CreateSidebar.qml b/ScreenPlay/qml/Create/CreateSidebar.qml index bf1ef42b..e9f49057 100644 --- a/ScreenPlay/qml/Create/CreateSidebar.qml +++ b/ScreenPlay/qml/Create/CreateSidebar.qml @@ -6,7 +6,6 @@ import Qt5Compat.GraphicalEffects import QtQuick.Controls.Material.impl import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create import ScreenPlayUtil Rectangle { @@ -42,9 +41,7 @@ Rectangle { function onWizardExited() { root.expanded = true; - stackView.clear(StackView.PushTransition); - stackView.push("qrc:/qml/ScreenPlayApp/qml/Create/StartInfo.qml"); - listView.currentIndex = 0; + App.util.setNavigation("Installed"); App.util.setNavigationActive(true); } @@ -87,6 +84,13 @@ Rectangle { objectName: "" } + ListElement { + headline: qsTr("3D Engine Wallpaper (Godot 4.2)") + source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/GodotWallpaper.qml" + category: "Code Wallpaper" + objectName: "" + } + ListElement { headline: qsTr("QML Wallpaper") source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/QMLWallpaper.qml" diff --git a/ScreenPlay/qml/Create/Create.qml b/ScreenPlay/qml/Create/CreateView.qml similarity index 99% rename from ScreenPlay/qml/Create/Create.qml rename to ScreenPlay/qml/Create/CreateView.qml index 849ce0ca..409d5037 100644 --- a/ScreenPlay/qml/Create/Create.qml +++ b/ScreenPlay/qml/Create/CreateView.qml @@ -6,7 +6,6 @@ import Qt5Compat.GraphicalEffects import QtQuick.Controls.Material.impl import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create import ScreenPlayUtil Item { diff --git a/ScreenPlay/qml/Create/StartInfo.qml b/ScreenPlay/qml/Create/StartInfo.qml index 9de354cf..7267a17b 100644 --- a/ScreenPlay/qml/Create/StartInfo.qml +++ b/ScreenPlay/qml/Create/StartInfo.qml @@ -6,7 +6,6 @@ import Qt5Compat.GraphicalEffects import QtQuick.Controls.Material.impl import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create import ScreenPlayUtil as Util Item { diff --git a/ScreenPlay/qml/Create/StartInfoLinkImage.qml b/ScreenPlay/qml/Create/StartInfoLinkImage.qml index 09f21eda..0bd5bea0 100644 --- a/ScreenPlay/qml/Create/StartInfoLinkImage.qml +++ b/ScreenPlay/qml/Create/StartInfoLinkImage.qml @@ -6,7 +6,6 @@ import Qt5Compat.GraphicalEffects import QtQuick.Controls.Material.impl import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create import ScreenPlayUtil Item { diff --git a/ScreenPlay/qml/Create/Wizard.qml b/ScreenPlay/qml/Create/Wizard.qml index a9c47189..a33d6980 100644 --- a/ScreenPlay/qml/Create/Wizard.qml +++ b/ScreenPlay/qml/Create/Wizard.qml @@ -5,7 +5,6 @@ import QtQuick.Controls.Material import QtQuick.Layouts import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create import ScreenPlayUtil Item { diff --git a/ScreenPlay/qml/Create/Wizards/GodotWallpaper.qml b/ScreenPlay/qml/Create/Wizards/GodotWallpaper.qml new file mode 100644 index 00000000..1e33b48d --- /dev/null +++ b/ScreenPlay/qml/Create/Wizards/GodotWallpaper.qml @@ -0,0 +1,100 @@ +import QtQuick +import Qt5Compat.GraphicalEffects +import QtQuick.Controls +import QtQuick.Controls.Material +import QtQuick.Layouts +import ScreenPlayApp +import ScreenPlay +import ScreenPlayUtil as Util + +WizardPage { + id: root + + sourceComponent: ColumnLayout { + id: rightWrapper + + function create() { + App.wizards.createGodotWallpaper(tfTitle.text, cbLicense.name, cbLicense.licenseFile, tfCreatedBy.text, previewSelector.imageSource, tagSelector.getTags()); + } + + spacing: 10 + + anchors { + top: parent.top + right: parent.right + left: parent.left + } + + Util.Headline { + text: qsTr("Create a Godot Wallpaper") + Layout.fillWidth: true + } + + Util.HeadlineSection { + text: qsTr("General") + } + + RowLayout { + spacing: 20 + + Util.TextField { + id: tfTitle + + Layout.fillWidth: true + placeholderText: qsTr("Wallpaper name") + required: true + onTextChanged: root.ready = text.length >= 1 + } + + Util.TextField { + id: tfCreatedBy + + Layout.fillWidth: true + placeholderText: qsTr("Created By") + } + } + + Util.TextField { + id: tfDescription + + Layout.fillWidth: true + placeholderText: qsTr("Description") + } + + Item { + height: 30 + } + + Util.HeadlineSection { + text: qsTr("License & Tags") + } + + RowLayout { + spacing: 20 + + Util.LicenseSelector { + id: cbLicense + } + + Util.TagSelector { + id: tagSelector + + Layout.fillWidth: true + } + } + + Item { + height: 30 + } + + Util.HeadlineSection { + text: qsTr("Preview Image") + } + + Util.ImageSelector { + id: previewSelector + + Layout.fillWidth: true + } + } +} diff --git a/ScreenPlay/qml/Create/Wizards/HTMLWallpaper.qml b/ScreenPlay/qml/Create/Wizards/HTMLWallpaper.qml index 3788ff89..0a56537a 100644 --- a/ScreenPlay/qml/Create/Wizards/HTMLWallpaper.qml +++ b/ScreenPlay/qml/Create/Wizards/HTMLWallpaper.qml @@ -5,7 +5,6 @@ import QtQuick.Controls.Material import QtQuick.Layouts import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create import ScreenPlayUtil as Util WizardPage { diff --git a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml index 391176c2..c3d6ee8e 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaper.qml @@ -5,7 +5,6 @@ import QtQuick.Controls.Material import QtQuick.Layouts import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create Item { id: root diff --git a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml index 57cfe5cf..c778401c 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperInit.qml @@ -6,7 +6,6 @@ import QtQuick.Layouts import QtQuick.Dialogs import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create import ScreenPlayUtil as Util Item { @@ -59,10 +58,6 @@ Item { } ComboBox { - // ListElement { - // text: "AV1 (NVidia 3000, AMD 6000 or newer). ULTRA SLOW ENCODING!" - // value: Create.AV1 - // } id: comboBoxCodec Layout.preferredWidth: 400 @@ -76,14 +71,13 @@ Item { ListElement { text: "VP8 (Better for older hardware)" - value: Create.VP9 + value: Util.Video.VideoCodec.VP9 } ListElement { text: "VP9 (Better for newer hardware 2018+)" - value: Create.VP8 + value: Util.Video.VideoCodec.VP8 } - // Import works but the QWebEngine cannot display AV1 :( } } } diff --git a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperResult.qml b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperResult.qml index 3dff9f52..3279355c 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperResult.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperResult.qml @@ -5,7 +5,6 @@ import QtQuick.Layouts import Qt5Compat.GraphicalEffects import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create Item { id: wrapperError diff --git a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml index 160ce497..f717836e 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportVideoAndConvert/CreateWallpaperVideoImportConvert.qml @@ -5,8 +5,6 @@ import QtQuick.Controls.Material import QtQuick.Layouts import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create -import ScreenPlay.Enums.ImportVideoState import ScreenPlayUtil as Util Item { diff --git a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebm.qml b/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebm.qml index 71215f30..81ad6c4c 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebm.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebm.qml @@ -5,7 +5,6 @@ import QtQuick.Controls.Material import QtQuick.Layouts import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create Item { id: root diff --git a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml b/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml index 9b275ed9..4732d307 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml @@ -5,8 +5,6 @@ import QtQuick.Controls.Material import QtQuick.Layouts import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create -import ScreenPlay.Enums.ImportVideoState import ScreenPlayUtil as Util Item { @@ -329,7 +327,7 @@ Item { onClicked: { if (conversionFinishedSuccessful) { btnSave.enabled = false; - App.create.saveWallpaper(textFieldName.text, textFieldDescription.text, root.filePath, previewSelector.imageSource, textFieldYoutubeURL.text, Create.VP9, textFieldTags.getTags()); + App.create.saveWallpaper(textFieldName.text, textFieldDescription.text, root.filePath, previewSelector.imageSource, textFieldYoutubeURL.text, Util.Video.VideoCodec.VP9, textFieldTags.getTags()); savePopup.open(); } } diff --git a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmInit.qml b/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmInit.qml index f77c22ad..a5b2477d 100644 --- a/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmInit.qml +++ b/ScreenPlay/qml/Create/Wizards/ImportWebm/ImportWebmInit.qml @@ -6,7 +6,6 @@ import QtQuick.Layouts import QtQuick.Dialogs import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create import ScreenPlayUtil as Util import "../../" diff --git a/ScreenPlay/qml/Create/Wizards/Importh264/Importh264.qml b/ScreenPlay/qml/Create/Wizards/Importh264/Importh264.qml index 6a00209e..970038d4 100644 --- a/ScreenPlay/qml/Create/Wizards/Importh264/Importh264.qml +++ b/ScreenPlay/qml/Create/Wizards/Importh264/Importh264.qml @@ -5,7 +5,6 @@ import QtQuick.Controls.Material import QtQuick.Layouts import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create Item { id: root diff --git a/ScreenPlay/qml/Create/Wizards/Importh264/Importh264Convert.qml b/ScreenPlay/qml/Create/Wizards/Importh264/Importh264Convert.qml index 6e467d85..f93071ac 100644 --- a/ScreenPlay/qml/Create/Wizards/Importh264/Importh264Convert.qml +++ b/ScreenPlay/qml/Create/Wizards/Importh264/Importh264Convert.qml @@ -5,8 +5,6 @@ import QtQuick.Controls.Material import QtQuick.Layouts import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create -import ScreenPlay.Enums.ImportVideoState import ScreenPlayUtil as Util Item { diff --git a/ScreenPlay/qml/Create/Wizards/Importh264/Importh264Init.qml b/ScreenPlay/qml/Create/Wizards/Importh264/Importh264Init.qml index 81fe7d55..c0156117 100644 --- a/ScreenPlay/qml/Create/Wizards/Importh264/Importh264Init.qml +++ b/ScreenPlay/qml/Create/Wizards/Importh264/Importh264Init.qml @@ -6,7 +6,6 @@ import QtQuick.Layouts import QtQuick.Dialogs import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create import ScreenPlayUtil as Util import "../../" @@ -46,7 +45,7 @@ Item { Text { id: txtDescription - text: qsTr("ScreenPlay V0.15 and up can play *.mp4 (also more known as h264). This can improove performance on older systems.") + text: qsTr("ScreenPlay v0.15 and up can play *.mp4 (also more known as h264). This can improove performance on older systems.") color: Material.primaryTextColor Layout.fillWidth: true font.pointSize: 13 diff --git a/ScreenPlay/qml/Create/Wizards/QMLWallpaper.qml b/ScreenPlay/qml/Create/Wizards/QMLWallpaper.qml index afea832c..cabd5789 100644 --- a/ScreenPlay/qml/Create/Wizards/QMLWallpaper.qml +++ b/ScreenPlay/qml/Create/Wizards/QMLWallpaper.qml @@ -5,7 +5,6 @@ import QtQuick.Controls.Material import QtQuick.Layouts import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create import ScreenPlayUtil as Util WizardPage { diff --git a/ScreenPlay/qml/Create/Wizards/WebsiteWallpaper.qml b/ScreenPlay/qml/Create/Wizards/WebsiteWallpaper.qml index 605920aa..a8095838 100644 --- a/ScreenPlay/qml/Create/Wizards/WebsiteWallpaper.qml +++ b/ScreenPlay/qml/Create/Wizards/WebsiteWallpaper.qml @@ -5,21 +5,25 @@ import QtQuick.Controls.Material import QtQuick.Layouts import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create import ScreenPlayUtil as Util WizardPage { id: root - + function isValidURL(string) { + var res = string.match(/(http(s)?:\/\/.)?(www\.)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/g); + return (res !== null); + } sourceComponent: ColumnLayout { - property bool ready: tfTitle.text.length >= 1 && tfUrl.text.length > 1 + id: layout + function validate() { + root.ready = tfTitle.text.length >= 1 && root.isValidURL(tfUrl.text); + } function create() { App.wizards.createWebsiteWallpaper(tfTitle.text, previewSelector.imageSource, tfUrl.text, tagSelector.getTags()); } spacing: 10 - onReadyChanged: root.ready = ready anchors { top: parent.top @@ -41,11 +45,10 @@ WizardPage { Util.TextField { id: tfTitle - Layout.fillWidth: true placeholderText: qsTr("Wallpaper name") required: true - onTextChanged: root.ready = text.length >= 1 + onTextChanged: layout.validate() } Util.TextField { @@ -65,10 +68,10 @@ WizardPage { Util.TextField { id: tfUrl - Layout.fillWidth: true required: true text: "https://" + onTextChanged: layout.validate() } Item { diff --git a/ScreenPlay/qml/Create/Wizards/WizardPage.qml b/ScreenPlay/qml/Create/Wizards/WizardPage.qml index 1530c900..017a7aea 100644 --- a/ScreenPlay/qml/Create/Wizards/WizardPage.qml +++ b/ScreenPlay/qml/Create/Wizards/WizardPage.qml @@ -6,7 +6,6 @@ import QtQuick.Layouts import QtQuick.Window import ScreenPlayApp import ScreenPlay -import ScreenPlay.Create FocusScope { id: root diff --git a/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/export_presets.cfg b/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/export_presets.cfg new file mode 100644 index 00000000..40ff0c71 --- /dev/null +++ b/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/export_presets.cfg @@ -0,0 +1,15 @@ +[preset.0] + +name="Windows Desktop" +platform="Windows Desktop" +runnable=true +dedicated_server=false +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="" +encryption_include_filters="" +encryption_exclude_filters="" +encrypt_pck=false +encrypt_directory=false diff --git a/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/project.godot b/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/project.godot new file mode 100644 index 00000000..ea0f2efb --- /dev/null +++ b/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/project.godot @@ -0,0 +1,15 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="Test" +run/main_scene="res://wallpaper.tscn" +config/features=PackedStringArray("4.2", "Forward Plus") diff --git a/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/spinner.gd b/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/spinner.gd new file mode 100644 index 00000000..2e5cdb3b --- /dev/null +++ b/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/spinner.gd @@ -0,0 +1,6 @@ +extends CSGBox3D + +var rotation_speed = 3.0 + +func _process(delta): + rotate_y(rotation_speed * delta) diff --git a/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn b/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn new file mode 100644 index 00000000..714824ae --- /dev/null +++ b/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn @@ -0,0 +1,19 @@ +[gd_scene load_steps=2 format=3 uid="uid://d105uliklnkd5"] + +[ext_resource type="Script" path="res://spinner.gd" id="1_ggnsn"] + +[node name="Node3D" type="Node3D"] + +[node name="Camera3D" type="Camera3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 5) + +[node name="CSGBox3D" type="CSGBox3D" parent="."] +transform = Transform3D(0.707107, -0.5, -0.5, 0, 0.707107, -0.707107, 0.707107, 0.5, 0.5, 0, 0, 0) +script = ExtResource("1_ggnsn") + +[node name="OmniLight3D" type="OmniLight3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.41283, 1.52646) + +[node name="Label3D" type="Label3D" parent="."] +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.874896, 0.37249) +text = "Godot Wallpaper" diff --git a/ScreenPlay/assets/wizards/QmlProject.qmlproject b/ScreenPlay/qml/Create/WizardsFiles/QmlProject.qmlproject similarity index 100% rename from ScreenPlay/assets/wizards/QmlProject.qmlproject rename to ScreenPlay/qml/Create/WizardsFiles/QmlProject.qmlproject diff --git a/ScreenPlay/qml/Installed/InstalledNavigation.qml b/ScreenPlay/qml/Installed/InstalledNavigation.qml index 92bb5fb6..84a22a8e 100644 --- a/ScreenPlay/qml/Installed/InstalledNavigation.qml +++ b/ScreenPlay/qml/Installed/InstalledNavigation.qml @@ -6,8 +6,6 @@ import Qt5Compat.GraphicalEffects import QtQuick.Controls.Material.impl import ScreenPlayApp import ScreenPlay -import ScreenPlay.Enums.InstalledType -import ScreenPlay.Enums.SearchType import ScreenPlayUtil as Util Item { @@ -64,7 +62,7 @@ Item { icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_installed.svg" onClicked: { setSidebarActive(false); - App.installedListFilter.sortBySearchType(SearchType.All); + App.installedListFilter.sortBySearchType(Util.ContentTypes.SearchType.All); } } @@ -73,7 +71,7 @@ Item { icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_code.svg" onClicked: { setSidebarActive(false); - App.installedListFilter.sortBySearchType(SearchType.Scene); + App.installedListFilter.sortBySearchType(Util.ContentTypes.SearchType.Scene); } } @@ -82,7 +80,7 @@ Item { icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_movie.svg" onClicked: { setSidebarActive(false); - App.installedListFilter.sortBySearchType(SearchType.Wallpaper); + App.installedListFilter.sortBySearchType(Util.ContentTypes.SearchType.Wallpaper); } } @@ -91,7 +89,7 @@ Item { icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_widgets.svg" onClicked: { setSidebarActive(false); - App.installedListFilter.sortBySearchType(SearchType.Widget); + App.installedListFilter.sortBySearchType(Util.ContentTypes.SearchType.Widget); } } } diff --git a/ScreenPlay/qml/Installed/Installed.qml b/ScreenPlay/qml/Installed/InstalledView.qml similarity index 90% rename from ScreenPlay/qml/Installed/Installed.qml rename to ScreenPlay/qml/Installed/InstalledView.qml index c8600802..68b5e037 100644 --- a/ScreenPlay/qml/Installed/Installed.qml +++ b/ScreenPlay/qml/Installed/InstalledView.qml @@ -8,8 +8,6 @@ import QtQuick.Controls.Material.impl import QtCore as QCore import ScreenPlayApp import ScreenPlay -import ScreenPlay.Enums.InstalledType -import ScreenPlay.Enums.SearchType import ScreenPlayUtil as Util Item { @@ -41,7 +39,6 @@ Item { StackView.onActivated: { navWrapper.state = "in"; - App.installedListFilter.sortBySearchType(SearchType.All); checkIsContentInstalled(); } @@ -85,15 +82,11 @@ Item { property bool isDragging: false property bool isScrolling: gridView.verticalVelocity !== 0 - boundsBehavior: Flickable.DragOverBounds - maximumFlickVelocity: 3000 - flickDeceleration: 7500 anchors.fill: parent cellWidth: 340 cellHeight: 200 cacheBuffer: 160 interactive: root.enabled - snapMode: GridView.SnapToRow onDragStarted: isDragging = true onDragEnded: isDragging = false model: App.installedListFilter @@ -177,7 +170,7 @@ Item { font.pointSize: 18 } - PropertyAnimation on opacity { + PropertyAnimation on opacity { id: animFadeIn from: 0 @@ -211,7 +204,7 @@ Item { } } - PropertyAnimation on opacity { + PropertyAnimation on opacity { id: animFadeInTxtFooter from: 0 @@ -240,11 +233,19 @@ Item { contextMenu.publishedFileID = delegate.publishedFileID; contextMenu.absoluteStoragePath = delegate.absoluteStoragePath; contextMenu.fileName = delegate.customTitle; + contextMenu.type = delegate.type; + print(delegate.publishedFileID); + if (contextMenu.godotItem) + contextMenu.godotItem.destroy(); const pos = delegate.mapToItem(root, position.x, position.y); // Disable duplicate opening. The can happen if we // call popup when we are in the closing animtion. if (contextMenu.visible || contextMenu.opened) return; + if (delegate.type === Util.ContentTypes.InstalledType.GodotWallpaper) { + contextMenu.godotItem = editGodotWallpaperComp.createObject(); + contextMenu.insertItem(0, contextMenu.godotItem); + } contextMenu.popup(pos.x, pos.y); } } @@ -253,14 +254,30 @@ Item { snapMode: ScrollBar.SnapOnRelease } } + Component { + id: editGodotWallpaperComp + MenuItem { + text: qsTr("Edit Wallpaper") + objectName: "editWallpaper" + enabled: contextMenu.type === Util.ContentTypes.InstalledType.GodotWallpaper + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_edit.svg" + onClicked: { + App.util.openGodotEditor(contextMenu.absoluteStoragePath, App.globalVariables.godotEditorExecutablePath); + } + } + } Menu { id: contextMenu objectName: "installedItemContextMenu" - + // Must be var to support 64-bit size! property var publishedFileID: 0 + property var type: 0 property url absoluteStoragePath property string fileName + // We need to dynamically add this menu item + // if it is a Godot Wallpaper, see onOpenContextMenu + property var godotItem MenuItem { text: qsTr("Open containing folder") @@ -312,7 +329,9 @@ Item { anchors.centerIn: Overlay.overlay onAccepted: { root.sidebar.clear(); - App.installedListModel.deinstallItemAt(contextMenu.absoluteStoragePath); + if (!App.installedListModel.deinstallItemAt(contextMenu.absoluteStoragePath)) { + console.error("Unable to uninstall item", contextMenu.absoluteStoragePath); + } } } @@ -392,7 +411,8 @@ Item { importProjectErrorDialog.open(); return; } - var file = ""; // Convert url to string + var file = ""; + // Convert url to string file = "" + drop.urls[0]; if (!file.endsWith('.screenplay')) { importProjectErrorDialog.title = qsTr("File type not supported. We only support '.screenplay' files."); diff --git a/ScreenPlay/qml/Installed/ScreenPlayItem.qml b/ScreenPlay/qml/Installed/ScreenPlayItem.qml index f22a4701..85b9fea9 100644 --- a/ScreenPlay/qml/Installed/ScreenPlayItem.qml +++ b/ScreenPlay/qml/Installed/ScreenPlayItem.qml @@ -4,8 +4,7 @@ import QtQuick.Controls import QtQuick.Controls.Material import ScreenPlayApp import ScreenPlay -import ScreenPlay.Enums.InstalledType -import ScreenPlayUtil +import ScreenPlayUtil as Util Item { id: root @@ -13,7 +12,8 @@ Item { property string customTitle property string screenId property url absoluteStoragePath - property int type: InstalledType.Unknown + property int type: ContentTypes.InstalledType.Unknown + // Must be var to make it work wit 64bit ints property var publishedFileID: 0 property int itemIndex property bool isScrolling: false @@ -25,15 +25,15 @@ Item { width: 320 height: 180 onTypeChanged: { - if (JSUtil.isWidget(type)) { + if (App.util.isWidget(type)) { icnType.source = "qrc:/qml/ScreenPlayApp/assets/icons/icon_widgets.svg"; return; } - if (JSUtil.isScene(type)) { + if (App.util.isScene(type)) { icnType.source = "qrc:/qml/ScreenPlayApp/assets/icons/icon_code.svg"; return; } - if (JSUtil.isVideo(type)) { + if (App.util.isVideo(type)) { icnType.source = "qrc:/qml/ScreenPlayApp/assets/icons/icon_movie.svg"; return; } diff --git a/ScreenPlay/qml/Installed/ScreenPlayItemImage.qml b/ScreenPlay/qml/Installed/ScreenPlayItemImage.qml index a60eedc7..213afce4 100644 --- a/ScreenPlay/qml/Installed/ScreenPlayItemImage.qml +++ b/ScreenPlay/qml/Installed/ScreenPlayItemImage.qml @@ -6,7 +6,7 @@ Item { property string absoluteStoragePath property string sourceImage property string sourceImageGIF - property var type: InstalledType.Unknown + property var type: ContentTypes.InstalledType.Unknown function enter() { if (root.sourceImageGIF != "") diff --git a/ScreenPlay/qml/Installed/Sidebar.qml b/ScreenPlay/qml/Installed/Sidebar.qml index 96ce53cc..d13f508c 100644 --- a/ScreenPlay/qml/Installed/Sidebar.qml +++ b/ScreenPlay/qml/Installed/Sidebar.qml @@ -6,16 +6,14 @@ import QtQuick.Controls.Material import QtQuick.Controls.Material.impl import ScreenPlayApp import ScreenPlay -import ScreenPlay.Enums.FillMode -import ScreenPlay.Enums.InstalledType +import ScreenPlayUtil import "../Monitors" -import ScreenPlayUtil as Util Item { id: root property real navHeight - property var type: InstalledType.QMLWallpaper + property var type: ContentTypes.InstalledType.QMLWallpaper property string contentFolderName function indexOfValue(model, value) { @@ -51,11 +49,11 @@ Item { } else { imagePreview.source = previewImageFilePath; } - if (JSUtil.isWidget(root.type) || (monitorSelection.activeMonitors.length > 0)) { - btnSetWallpaper.enabled = true; + if (App.util.isWidget(root.type) || (monitorSelection.activeMonitors.length > 0)) { + btnLaunchContent.enabled = true; return; } - btnSetWallpaper.enabled = false; + btnLaunchContent.enabled = false; } Connections { @@ -68,22 +66,22 @@ Item { } root.contentFolderName = folderName; root.type = type; - if (JSUtil.isWallpaper(root.type)) { - if (type === InstalledType.VideoWallpaper) + if (App.util.isWallpaper(root.type)) { + if (type === ContentTypes.InstalledType.VideoWallpaper) root.state = "activeWallpaper"; else root.state = "activeScene"; - btnSetWallpaper.text = qsTr("Set Wallpaper"); + btnLaunchContent.text = qsTr("Set Wallpaper"); } else { root.state = "activeWidget"; - btnSetWallpaper.text = qsTr("Set Widget"); + btnLaunchContent.text = qsTr("Set Widget"); } } target: App.util } - Util.MouseHoverBlocker { + MouseHoverBlocker { } Rectangle { @@ -275,7 +273,7 @@ Item { } } - Util.Slider { + Slider { id: sliderVolume Layout.fillWidth: true @@ -315,19 +313,19 @@ Item { valueRole: "value" font.family: App.settings.font model: [{ - "value": FillMode.Stretch, + "value": Settings.FillMode.Stretch, "text": qsTr("Stretch") }, { - "value": FillMode.Fill, + "value": Settings.FillMode.Fill, "text": qsTr("Fill") }, { - "value": FillMode.Contain, + "value": Settings.FillMode.Contain, "text": qsTr("Contain") }, { - "value": FillMode.Cover, + "value": Settings.FillMode.Cover, "text": qsTr("Cover") }, { - "value": FillMode.Scale_Down, + "value": Settings.FillMode.Scale_Down, "text": qsTr("Scale-Down") }] Component.onCompleted: { @@ -338,18 +336,19 @@ Item { } Button { - id: btnSetWallpaper - objectName: "btnSetWallpaper" - enabled: JSUtil.isWidget(root.type) ? true : monitorSelection.isSelected + id: btnLaunchContent + objectName: "btnLaunchContent" + enabled: App.util.isWidget(root.type) ? true : monitorSelection.isSelected Material.background: Material.accent Material.foreground: "white" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_plus.svg" icon.color: "white" font.pointSize: 12 onClicked: { - const absoluteStoragePath = App.globalVariables.localStoragePath + "/" + root.contentFolderName; - const previewImage = App.installedListModel.get(root.contentFolderName).m_preview; - if (JSUtil.isWallpaper(root.type)) { + const item = App.installedListModel.get(root.contentFolderName); + const absoluteStoragePath = item.m_absoluteStoragePath; + const previewImage = item.m_preview; + if (App.util.isWallpaper(root.type)) { let activeMonitors = monitorSelection.getActiveMonitors(); // TODO Alert user to choose a monitor if (activeMonitors.length === 0) @@ -357,12 +356,12 @@ Item { // We only have sliderVolume if it is a VideoWallpaper let volume = 0; - if (type === InstalledType.VideoWallpaper) + if (type === ContentTypes.InstalledType.VideoWallpaper) volume = Math.round(sliderVolume.slider.value * 100) / 100; - const screenFile = App.installedListModel.get(root.contentFolderName).m_file; + const screenFile = item.m_file; let success = App.screenPlayManager.createWallpaper(root.type, cbVideoFillMode.currentValue, absoluteStoragePath, previewImage, screenFile, activeMonitors, volume, 1, {}, true); } - if (JSUtil.isWidget(root.type)) + if (App.util.isWidget(root.type)) App.screenPlayManager.createWidget(type, Qt.point(0, 0), absoluteStoragePath, previewImage, {}, true); root.state = "inactive"; monitorSelection.reset(); diff --git a/ScreenPlay/qml/Monitors/DefaultVideoControls.qml b/ScreenPlay/qml/Monitors/DefaultVideoControls.qml index e1f51bfb..863e9f7e 100644 --- a/ScreenPlay/qml/Monitors/DefaultVideoControls.qml +++ b/ScreenPlay/qml/Monitors/DefaultVideoControls.qml @@ -5,7 +5,6 @@ import QtQuick.Controls.Material import QtQuick.Layouts import ScreenPlayApp import ScreenPlay -import ScreenPlay.Enums.FillMode import ScreenPlayUtil as Util ColumnLayout { @@ -81,19 +80,19 @@ ColumnLayout { valueRole: "value" currentIndex: root.indexOfValue(settingsComboBox.model, App.settings.videoFillMode) model: [{ - "value": FillMode.Stretch, + "value": Util.Video.FillMode.Stretch, "text": qsTr("Stretch") }, { - "value": FillMode.Fill, + "value": Util.Video.FillMode.Fill, "text": qsTr("Fill") }, { - "value": FillMode.Contain, + "value": Util.Video.FillMode.Contain, "text": qsTr("Contain") }, { - "value": FillMode.Cover, + "value": Util.Video.FillMode.Cover, "text": qsTr("Cover") }, { - "value": FillMode.Scale_Down, + "value": Util.Video.FillMode.Scale_Down, "text": qsTr("Scale_Down") }] onActivated: { diff --git a/ScreenPlay/qml/Monitors/MonitorSelection.qml b/ScreenPlay/qml/Monitors/MonitorSelection.qml index 2dd0b1ac..57e382a6 100644 --- a/ScreenPlay/qml/Monitors/MonitorSelection.qml +++ b/ScreenPlay/qml/Monitors/MonitorSelection.qml @@ -17,7 +17,7 @@ Rectangle { // We preselect the main monitor property var activeMonitors: [] property alias background: root.color - property alias radius: root.radius + property alias bgRadius: root.radius Component.onCompleted: { resize(); diff --git a/ScreenPlay/qml/Monitors/MonitorSelectionItem.qml b/ScreenPlay/qml/Monitors/MonitorSelectionItem.qml index 99a6f9cf..820699ee 100644 --- a/ScreenPlay/qml/Monitors/MonitorSelectionItem.qml +++ b/ScreenPlay/qml/Monitors/MonitorSelectionItem.qml @@ -3,7 +3,7 @@ import Qt5Compat.GraphicalEffects import QtQuick.Controls.Material import ScreenPlayApp import ScreenPlay -import ScreenPlay.Enums.InstalledType +import ScreenPlayUtil Item { id: root @@ -18,7 +18,7 @@ Item { property string previewImage property string appID - property var installedType: InstalledType.QMLWallpaper + property var installedType: ContentTypes.InstalledType.QMLWallpaper property bool monitorWithoutContentSelectable: true property bool hasContent: appID !== "" property int fontSize: 10 diff --git a/ScreenPlay/qml/Monitors/Monitors.qml b/ScreenPlay/qml/Monitors/MonitorsView.qml similarity index 98% rename from ScreenPlay/qml/Monitors/Monitors.qml rename to ScreenPlay/qml/Monitors/MonitorsView.qml index 50596121..73460367 100644 --- a/ScreenPlay/qml/Monitors/Monitors.qml +++ b/ScreenPlay/qml/Monitors/MonitorsView.qml @@ -6,7 +6,6 @@ import QtQuick.Layouts import QtQuick.Controls.Material.impl import ScreenPlayApp import ScreenPlay -import ScreenPlay.Enums.InstalledType import ScreenPlayUtil as Util Util.Popup { @@ -72,7 +71,7 @@ Util.Popup { MonitorSelection { id: monitorSelection - radius: 3 + bgRadius: 3 height: 200 width: parent.width * 0.9 multipleMonitorsSelectable: false @@ -80,7 +79,7 @@ Util.Popup { availableWidth: width - 20 availableHeight: 150 onRequestProjectSettings: function (index, installedType, appID) { - if (installedType === InstalledType.VideoWallpaper) { + if (installedType === Util.ContentTypes.InstalledType.VideoWallpaper) { videoControlWrapper.state = "visible"; customPropertiesGridView.visible = false; const wallpaper = App.screenPlayManager.getWallpaperByAppID(appID); diff --git a/ScreenPlay/qml/Navigation/Navigation.qml b/ScreenPlay/qml/Navigation/Navigation.qml index 16b5c639..7d80f5f1 100644 --- a/ScreenPlay/qml/Navigation/Navigation.qml +++ b/ScreenPlay/qml/Navigation/Navigation.qml @@ -13,7 +13,7 @@ Rectangle { id: root property string currentNavigationName: "Installed" - property var navArray: [navCreate, navWorkshop, navInstalled, navSettings, navCommunity] + property var navArray: [navCreate, navWorkshop, navInstalled, navCommunity, navSettings] property bool navActive: true property Item modalSource property int iconWidth: 16 @@ -28,13 +28,12 @@ Rectangle { else root.state = "disabled"; } - function setNavigation(name) { - var i = 0; - for (; i < navArray.length; i++) { - if (navArray[i].name === name) { + for (var i = 0; i < navArray.length; i++) { + if (navArray[i].objectName === name) { navArray[i].state = "active"; root.currentNavigationName = name; + tabBar.currentIndex = navArray[i].index; } else { navArray[i].state = "inactive"; } @@ -70,7 +69,7 @@ Rectangle { } TabBar { - id: row + id: tabBar height: 50 currentIndex: 2 @@ -84,55 +83,60 @@ Rectangle { CustomTabButton { id: navCreate + index: 0 icon.height: 22 icon.width: 22 text: qsTr("Create") + objectName: "Create" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_plus.svg" onClicked: { root.onPageChanged("Create"); } - objectName: "createTab" } CustomTabButton { id: navWorkshop + index: 1 enabled: App.settings.steamVersion text: qsTr("Workshop") + objectName: "Workshop" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_steam.svg" onClicked: { root.onPageChanged("Workshop"); } - objectName: "workshopTab" } CustomTabButton { id: navInstalled + index: 2 text: qsTr("Installed") + " " + App.installedListModel.count + objectName: "Installed" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_installed.svg" onClicked: { root.onPageChanged("Installed"); } - objectName: "installedTab" } CustomTabButton { id: navCommunity + index: 3 text: qsTr("Community") + objectName: "Community" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_community.svg" onClicked: { root.onPageChanged("Community"); } - objectName: "communityTab" } CustomTabButton { id: navSettings + index: 4 text: qsTr("Settings") + objectName: "Settings" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_settings.svg" onClicked: { root.onPageChanged("Settings"); } - objectName: "settingsTab" } } @@ -142,6 +146,7 @@ Rectangle { font.pointSize: 12 height: parent.height width: implicitWidth + property int index: 0 background: Item { } font.capitalization: Font.MixedCase @@ -260,7 +265,7 @@ Rectangle { ToolButton { id: miConfig Layout.alignment: Qt.AlignVCenter - icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_video_settings_black_24dp.svg" + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_video_settings.svg" icon.width: root.iconWidth icon.height: root.iconHeight onClicked: App.util.setToggleWallpaperConfiguration() @@ -278,7 +283,7 @@ Rectangle { name: "disabled" PropertyChanges { - target: row + target: tabBar opacity: 0.3 } } @@ -289,7 +294,7 @@ Rectangle { to: "*" PropertyAnimation { - target: row + target: tabBar duration: 300 } } diff --git a/ScreenPlay/qml/Settings/SettingBool.qml b/ScreenPlay/qml/Settings/SettingBool.qml index d2915787..0f64af84 100644 --- a/ScreenPlay/qml/Settings/SettingBool.qml +++ b/ScreenPlay/qml/Settings/SettingBool.qml @@ -78,7 +78,7 @@ Item { id: radioButton checked: settingsBool.isChecked - onCheckedChanged: { + onClicked: { if (radioButton.checkState === Qt.Checked) checkboxChanged(true); else diff --git a/ScreenPlay/qml/Settings/SettingsComboBox.qml b/ScreenPlay/qml/Settings/SettingsComboBox.qml index e25fea12..04147078 100644 --- a/ScreenPlay/qml/Settings/SettingsComboBox.qml +++ b/ScreenPlay/qml/Settings/SettingsComboBox.qml @@ -1,9 +1,8 @@ import QtQuick import QtQuick.Controls import QtQuick.Layouts -import QtQuick.Controls.Material -import ScreenPlayApp import ScreenPlay +import ScreenPlayApp Control { id: settingsComboBox diff --git a/ScreenPlay/qml/Settings/Settings.qml b/ScreenPlay/qml/Settings/SettingsView.qml similarity index 73% rename from ScreenPlay/qml/Settings/Settings.qml rename to ScreenPlay/qml/Settings/SettingsView.qml index 6e540746..756788a5 100644 --- a/ScreenPlay/qml/Settings/Settings.qml +++ b/ScreenPlay/qml/Settings/SettingsView.qml @@ -1,4 +1,5 @@ import QtQuick +import QtCore as QCore import QtQuick.Dialogs import QtQuick.Controls import QtQuick.Controls.Material @@ -6,8 +7,6 @@ import QtQuick.Layouts import Qt5Compat.GraphicalEffects import ScreenPlayApp import ScreenPlay -import ScreenPlay.Enums.FillMode -import Settings import ScreenPlayUtil Item { @@ -15,15 +14,6 @@ Item { property Item modalSource - function indexOfValue(model, value) { - for (var i = 0; i < model.length; i++) { - let ourValue = model[i].value; - if (value === ourValue) - return i; - } - return -1; - } - Flickable { id: flickableWrapper @@ -73,18 +63,18 @@ Item { } } - SettingsHorizontalSeperator { - } + // SettingsHorizontalSeperator { + // } - SettingBool { - headline: qsTr("Show default installed content") - description: qsTr("ScreenPlay will show build in content.") - isChecked: App.settings.showDefaultContent - onCheckboxChanged: function (checked) { - App.settings.setShowDefaultContent(checked); - App.installedListModel.reset(); - } - } + // SettingBool { + // headline: qsTr("Show default installed content") + // description: qsTr("ScreenPlay will show build in content.") + // isChecked: App.settings.showDefaultContent + // onCheckboxChanged: function (checked) { + // App.settings.setShowDefaultContent(checked); + // App.installedListModel.reset(); + // } + // } SettingsHorizontalSeperator { } @@ -152,51 +142,63 @@ Item { headline: qsTr("Language") description: qsTr("Set the ScreenPlay UI Language") - Component.onCompleted: { - settingsLanguage.comboBox.currentIndex = root.indexOfValue(settingsLanguage.comboBox.model, App.settings.language); - } - comboBox { - model: [{ - "value": Settings.En_US, - "text": "English" - }, { - "value": Settings.De_DE, - "text": "German" - }, { - "value": Settings.Pl_PL, - "text": "Polish" - }, { - "value": Settings.It_IT, - "text": "Italian" - }, { - "value": Settings.Zh_CN, - "text": "Chinese - Simplified" - }, { - "value": Settings.Ru_RU, - "text": "Russian" - }, { - "value": Settings.Fr_FR, - "text": "French" - }, { - "value": Settings.Es_ES, - "text": "Spanish" - }, { - "value": Settings.Ko_KR, - "text": "Korean" - }, { - "value": Settings.Vi_VN, - "text": "Vietnamese" - }, { - "value": Settings.Pt_BR, - "text": "Portuguese (Brazil)" - }, { - "value": Settings.Tr_TR, - "text": "Turkish" - }, { - "value": Settings.Nl_NL, - "text": "Dutch" - }] + Component.onCompleted: comboBox.currentIndex = comboBox.indexOfValue(App.settings.language) + model: ListModel { + id: lmLangauge + ListElement { + value: Settings.Language.En_US + text: "English" + } + ListElement { + value: Settings.Language.De_DE + text: "German" + } + ListElement { + value: Settings.Language.Pl_PL + text: "Polish" + } + ListElement { + value: Settings.Language.It_IT + text: "Italian" + } + ListElement { + value: Settings.Language.Zh_CN + text: "Chinese - Simplified" + } + ListElement { + value: Settings.Language.Ru_RU + text: "Russian" + } + ListElement { + value: Settings.Language.Fr_FR + text: "French" + } + ListElement { + value: Settings.Language.Es_ES + text: "Spanish" + } + ListElement { + value: Settings.Language.Ko_KR + text: "Korean" + } + ListElement { + value: Settings.Language.Vi_VN + text: "Vietnamese" + } + ListElement { + value: Settings.Language.Pt_BR + text: "Portuguese (Brazil)" + } + ListElement { + value: Settings.Language.Tr_TR + text: "Turkish" + } + ListElement { + value: Settings.Language.Nl_NL + text: "Dutch" + } + } onActivated: { App.settings.setLanguage(settingsLanguage.comboBox.currentValue); App.settings.retranslateUI(); @@ -212,21 +214,22 @@ Item { headline: qsTr("Theme") description: qsTr("Switch dark/light theme") - Component.onCompleted: { - settingsTheme.comboBox.currentIndex = root.indexOfValue(settingsTheme.comboBox.model, App.settings.theme); - } - comboBox { - model: [{ - "value": Settings.System, - "text": qsTr("System Default") - }, { - "value": Settings.Dark, - "text": qsTr("Dark") - }, { - "value": Settings.Light, - "text": qsTr("Light") - }] + Component.onCompleted: comboBox.currentIndex = comboBox.indexOfValue(App.settings.theme) + model: ListModel { + ListElement { + value: Settings.Theme.System + text: qsTr("System Default") + } + ListElement { + value: Settings.Theme.Dark + text: qsTr("Dark") + } + ListElement { + value: Settings.Theme.Light + text: qsTr("Light") + } + } onActivated: { App.settings.setTheme(settingsTheme.comboBox.currentValue); } @@ -266,28 +269,33 @@ Item { headline: qsTr("Default Wallpaper Fill Mode") description: qsTr("Set this property to define how the video is scaled to fit the target area.") - Component.onCompleted: { - cbVideoFillMode.comboBox.currentIndex = root.indexOfValue(cbVideoFillMode.comboBox.model, App.settings.videoFillMode); - } - comboBox { - onActivated: App.settings.setVideoFillMode(cbVideoFillMode.comboBox.currentValue) - model: [{ - "value": FillMode.Stretch, - "text": qsTr("Stretch") - }, { - "value": FillMode.Fill, - "text": qsTr("Fill") - }, { - "value": FillMode.Contain, - "text": qsTr("Contain") - }, { - "value": FillMode.Cover, - "text": qsTr("Cover") - }, { - "value": FillMode.Scale_Down, - "text": qsTr("Scale-Down") - }] + Component.onCompleted: comboBox.currentIndex = comboBox.indexOfValue(App.settings.videoFillMode) + model: ListModel { + ListElement { + value: Video.FillMode.Stretch + text: qsTr("Stretch") + } + ListElement { + value: Video.FillMode.Fill + text: qsTr("Fill") + } + ListElement { + value: Video.FillMode.Contain + text: qsTr("Contain") + } + ListElement { + value: Video.FillMode.Cover + text: qsTr("Cover") + } + ListElement { + value: Video.FillMode.Scale_Down + text: qsTr("Scale-Down") + } + } + onActivated: { + App.settings.setVideoFillMode(cbVideoFillMode.comboBox.currentValue); + } } } } @@ -402,7 +410,7 @@ Item { Image { id: imgLogoHead - source: "https://assets.gitlab-static.net/uploads/-/system/user/avatar/64172/avatar.png" + source: "https://gitlab.com/uploads/-/system/user/avatar/64172/avatar.png" width: 120 height: 120 visible: false @@ -482,16 +490,11 @@ Item { description: qsTr("If your ScreenPlay missbehaves this is a good way to look for answers. This shows all logs and warning during runtime.") buttonText: qsTr("Show Logs") onButtonPressed: { - expanderDebug.toggle(); + const logsPath = QCore.StandardPaths.writableLocation(QCore.StandardPaths.GenericDataLocation) + "/ScreenPlay/Logs"; + App.util.openFolderInExplorer(logsPath); } } - SettingsExpander { - id: expanderDebug - - text: App.util.debugMessages - } - SettingsHorizontalSeperator { } diff --git a/ScreenPlay/qml/TrayIcon.qml b/ScreenPlay/qml/TrayIcon.qml index 6e946522..43c73e46 100644 --- a/ScreenPlay/qml/TrayIcon.qml +++ b/ScreenPlay/qml/TrayIcon.qml @@ -27,29 +27,99 @@ SystemTrayIcon { } } + function open() { + App.showDockIcon(true); + window.show(); + } + menu: Menu { MenuItem { + id: miOpenScreenPlay text: qsTr("Open ScreenPlay") + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_open_in_new_black.svg" onTriggered: { - App.showDockIcon(true); - window.show(); + root.open(); + } + } + MenuItem { + id: miChangeWallpaperSettings + text: qsTr("Change Wallpaper settings") + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_video_settings.svg" + onTriggered: { + root.open(); + App.util.setNavigation("Installed"); + App.util.setToggleWallpaperConfiguration(); + } + } + MenuItem { + separator: true + } + + MenuItem { + text: qsTr("Browse Workshop") + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_steam.svg" + onTriggered: { + root.open(); + App.util.setNavigation("Workshop"); } } + MenuItem { + id: miCreate + text: qsTr("Create new Wallpaper or Widgets") + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_plus.svg" + onTriggered: { + root.open(); + App.util.setNavigation("Create"); + } + } + MenuItem { + id: miSettings + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_settings.svg" + text: qsTr("Settings") + onTriggered: { + root.open(); + App.util.setNavigation("Settings"); + } + } + + MenuItem { + separator: true + } + MenuItem { + text: qsTr("Forums and Help") + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_supervisor_account.svg" + onTriggered: { + Qt.openUrlExternally("https://forum.screen-play.app/"); + } + } + MenuItem { + text: qsTr("Frequently Asked Questions (FAQ)") + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_help_center.svg" + onTriggered: { + Qt.openUrlExternally("https://kelteseth.gitlab.io/ScreenPlayDocs/Frequently%20Asked%20Questions/"); + } + } + MenuItem { + separator: true + } MenuItem { id: miMuteAll - property bool isMuted: true + property bool isMuted: false text: qsTr("Mute all") + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_volume_mute.svg" onTriggered: { if (miMuteAll.isMuted) { isMuted = false; miMuteAll.text = qsTr("Mute all"); + miMuteAll.icon.source = "qrc:/qml/ScreenPlayApp/assets/icons/icon_volume_mute.svg"; App.screenPlayManager.setAllWallpaperValue("muted", "true"); } else { isMuted = true; miMuteAll.text = qsTr("Unmute all"); + miMuteAll.icon.source = "qrc:/qml/ScreenPlayApp/assets/icons/icon_volume_up.svg"; App.screenPlayManager.setAllWallpaperValue("muted", "false"); } } @@ -61,14 +131,17 @@ SystemTrayIcon { property bool isPlaying: false text: qsTr("Pause all") + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_pause.svg" onTriggered: { if (miStopAll.isPlaying) { isPlaying = false; miStopAll.text = qsTr("Pause all"); + miStopAll.icon.source = "qrc:/qml/ScreenPlayApp/assets/icons/icon_pause.svg"; App.screenPlayManager.setAllWallpaperValue("isPlaying", "true"); } else { isPlaying = true; miStopAll.text = qsTr("Play all"); + miStopAll.icon.source = "qrc:/qml/ScreenPlayApp/assets/icons/icon_play.svg"; App.screenPlayManager.setAllWallpaperValue("isPlaying", "false"); } } @@ -76,6 +149,7 @@ SystemTrayIcon { MenuItem { text: qsTr("Quit ScreenPlay") + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_cancel_presentation.svg" onTriggered: App.exit() } } diff --git a/ScreenPlay/qml/Workshop/Workshop.qml b/ScreenPlay/qml/Workshop/WorkshopView.qml similarity index 97% rename from ScreenPlay/qml/Workshop/Workshop.qml rename to ScreenPlay/qml/Workshop/WorkshopView.qml index 7edb1cc5..21572861 100644 --- a/ScreenPlay/qml/Workshop/Workshop.qml +++ b/ScreenPlay/qml/Workshop/WorkshopView.qml @@ -3,7 +3,6 @@ import QtQuick.Controls import QtQuick.Controls.Material import Qt5Compat.GraphicalEffects import QtQuick.Layouts -import Settings import ScreenPlay import ScreenPlayWorkshop diff --git a/ScreenPlay/src/app.cpp b/ScreenPlay/src/app.cpp index 9bfe8e16..175b52f3 100644 --- a/ScreenPlay/src/app.cpp +++ b/ScreenPlay/src/app.cpp @@ -1,12 +1,13 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "ScreenPlay/app.h" -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) #include "ScreenPlayUtil/macutils.h" #endif +#include "ScreenPlay/CMakeVariables.h" +#include "ScreenPlayUtil/steamenumsgenerated.h" #include "app.h" -#include "steam/steam_qt_enums_generated.h" #include #include #include @@ -16,9 +17,7 @@ namespace ScreenPlay { /*! \module ScreenPlay - \title ScreenPlay - \brief Module for ScreenPlay. */ /*! @@ -31,32 +30,6 @@ namespace ScreenPlay { \class ScreenPlay::App \inmodule ScreenPlay \brief The App class contains all members for ScreenPlay. - - - \raw HTML -
- graph TD - - Main.cpp --> App - App --> QQmlApplicationEngine - App --> GlobalVariables - App --> ScreenPlayManager - ScreenPlayManager --> ScreenPlayWallpaper - ScreenPlayManager --> ScreenPlayWidget - App --> Create - Create--> CreateVideoImport - App --> Util - App --> Settings - App --> InstalledListModel - InstalledListModel --> ProjectFile - App --> InstalledListFilter - App --> MonitorListModel - MonitorListModel --> Monitor - App --> ProfileListModel - ProfileListModel --> Profile - -
- \endraw */ /*! @@ -67,62 +40,12 @@ App::App() : QObject(nullptr) { - m_continuousIntegrationMetricsTimer.start(); - QGuiApplication::setWindowIcon(QIcon(":/qml/ScreenPlayApp/assets/icons/app.ico")); QGuiApplication::setOrganizationName("ScreenPlay"); QGuiApplication::setOrganizationDomain("screen-play.app"); QGuiApplication::setApplicationName("ScreenPlay"); - QGuiApplication::setApplicationVersion(QVersionNumber(0, 15, 0).toString()); + QGuiApplication::setApplicationVersion(QString(SCREENPLAY_VERSION)); QGuiApplication::setQuitOnLastWindowClosed(false); - - QString fontsPath = QGuiApplication::instance()->applicationDirPath() + "/assets/fonts/"; -#if defined(Q_OS_OSX) - fontsPath = QGuiApplication::instance()->applicationDirPath() + "/../Resources/fonts/"; -#endif - const QDir fontsDir(fontsPath); - if (!fontsDir.isEmpty() && fontsDir.exists()) { - QDirIterator it(fontsPath, { "*.ttf", "*.otf" }, QDir::Files); - while (it.hasNext()) { - QFontDatabase::addApplicationFont(it.next()); - } - } else { - qWarning() << "Unable to load font from: " << fontsPath; - } - - // TODO: This is a workaround because I don't know how to - // init this in the ScreenPlayWorkshop plugin. - // Move to workshop plugin. - qmlRegisterUncreatableMetaObject(ScreenPlayWorkshopSteamEnums::staticMetaObject, - "WorkshopEnums", - 1, 0, - "SteamEnums", - "Error: only enums"); - - // Registers the enums from globalvariables. - // Apparently this is the only way for qml to work - // https://www.kdab.com/new-qt-5-8-meta-object-support-namespaces/ - qRegisterMetaType(); - qmlRegisterUncreatableMetaObject(ScreenPlay::FillMode::staticMetaObject, - "ScreenPlay.Enums.FillMode", - 1, 0, - "FillMode", - "Error: only enums"); - - qRegisterMetaType(); - qmlRegisterUncreatableMetaObject(ScreenPlay::InstalledType::staticMetaObject, - "ScreenPlay.Enums.InstalledType", - 1, 0, - "InstalledType", - "Error: only enums"); - - qRegisterMetaType(); - qmlRegisterUncreatableMetaObject(ScreenPlay::SearchType::staticMetaObject, - "ScreenPlay.Enums.SearchType", - 1, 0, - "SearchType", - "Error: only enums"); - // ScreenPlayManager first to check if another ScreenPlay Instace is running m_screenPlayManager = std::make_unique(); m_isAnotherScreenPlayInstanceRunning = m_screenPlayManager->isAnotherScreenPlayInstanceRunning(); @@ -136,13 +59,27 @@ App::App() */ void App::init() { + qInfo() << "Init ScreenPlay"; + + QString fontsPath = QGuiApplication::instance()->applicationDirPath() + "/assets/fonts/"; +#if defined(Q_OS_MACOS) + fontsPath = QGuiApplication::instance()->applicationDirPath() + "/../Resources/fonts/"; +#endif + const QDir fontsDir(fontsPath); + if (!fontsDir.isEmpty() && fontsDir.exists()) { + QDirIterator it(fontsPath, { "*.ttf", "*.otf" }, QDir::Files); + while (it.hasNext()) { + QFontDatabase::addApplicationFont(it.next()); + } + } else { + qWarning() << "Unable to load font from: " << fontsPath; + } using std::make_shared, std::make_unique; - // Util should be created as first so we redirect qDebugs etc. into the log - m_util = make_unique(); m_globalVariables = make_shared(); m_monitorListModel = make_shared(); + m_util = make_unique(); m_profileListModel = make_shared(m_globalVariables); m_settings = make_shared(m_globalVariables); m_installedListModel = make_shared(m_globalVariables, m_settings); @@ -161,7 +98,7 @@ void App::init() const QString appPath = QGuiApplication::applicationDirPath(); sentry_options_set_handler_path(options, QString(appPath + "/crashpad_handler.exe").toStdString().c_str()); sentry_options_set_database_path(options, appPath.toStdString().c_str()); - sentry_options_set_handler_path(options, QString(QGuiApplication::applicationDirPath() + "/crashpad_handler" + ScreenPlayUtil::executableBinEnding()).toStdString().c_str()); + sentry_options_set_handler_path(options, QString(QGuiApplication::applicationDirPath() + "/crashpad_handler" + Util().executableBinEnding()).toStdString().c_str()); sentry_options_set_database_path(options, QGuiApplication::applicationDirPath().toStdString().c_str()); const int sentryInitStatus = sentry_init(options); if (sentryInitStatus != 0) { @@ -221,13 +158,22 @@ void App::exit() { m_screenPlayManager->removeAllWallpapers(); m_screenPlayManager->removeAllWidgets(); - auto* guiAppInst = dynamic_cast(QGuiApplication::instance()); - guiAppInst->quit(); + // Must be called inside a separate event loop otherwise we + // would kill the qml engine while it is calling this function. + // A single shot timer is a handy woraround for this. + QTimer::singleShot(0, this, [this]() { + auto* appInst = QGuiApplication::instance(); + // We must ensure that we kill the qml engine first + // before we destory the rest of the app + m_mainWindowEngine->clearSingletons(); + m_mainWindowEngine.reset(); + appInst->quit(); + }); } void App::showDockIcon(const bool show) { -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) MacUtils::instance()->showDockIcon(show); #endif } diff --git a/ScreenPlay/src/create.cpp b/ScreenPlay/src/create.cpp index 32fd381b..5e867b99 100644 --- a/ScreenPlay/src/create.cpp +++ b/ScreenPlay/src/create.cpp @@ -1,7 +1,6 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "ScreenPlay/create.h" -#include "ScreenPlay/util.h" #include "ScreenPlayUtil/util.h" namespace ScreenPlay { @@ -23,7 +22,6 @@ Create::Create(const std::shared_ptr& globalVariables) : QObject(nullptr) , m_globalVariables(globalVariables) { - init(); } /*! @@ -32,21 +30,6 @@ Create::Create(const std::shared_ptr& globalVariables) Create::Create() : QObject(nullptr) { - init(); -} - -void Create::init() -{ - qRegisterMetaType("Create::VideoCodec"); - qmlRegisterUncreatableType("ScreenPlay.Create", 1, 0, "VideoCodec", "Error only for enums"); - qmlRegisterType("ScreenPlay.Create", 1, 0, "Create"); - - qRegisterMetaType("ImportVideoState::ImportVideoState"); - qmlRegisterUncreatableMetaObject(ScreenPlay::ImportVideoState::staticMetaObject, - "ScreenPlay.Enums.ImportVideoState", - 1, 0, - "ImportVideoState", - "Error: only enums"); } void Create::reset() @@ -63,9 +46,10 @@ void Create::reset() void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, const int quality) { reset(); - videoPath = ScreenPlayUtil::toLocal(videoPath); + ScreenPlay::Util util; + videoPath = util.toLocal(videoPath); - const QDir installedDir = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString()); + const QDir installedDir = util.toLocal(m_globalVariables->localStoragePath().toString()); // Create a temp dir so we can later alter it to the workshop id const QDateTime date = QDateTime::currentDateTime(); @@ -74,7 +58,7 @@ void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, c if (!installedDir.mkdir(folderName)) { qInfo() << "Unable to create folder with name: " << folderName << " at: " << installedDir; - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CreateTmpFolderError); + emit createWallpaperStateChanged(Import::State::CreateTmpFolderError); emit abortCreateWallpaper(); return; } @@ -103,21 +87,21 @@ void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, c Qt::ConnectionType::QueuedConnection); if (!import.createWallpaperInfo() || m_interrupt) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed); + emit createWallpaperStateChanged(Import::State::Failed); emit import.abortAndCleanup(); return; } qInfo() << "createWallpaperImageThumbnailPreview()"; if (!import.createWallpaperImageThumbnailPreview() || m_interrupt) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed); + emit createWallpaperStateChanged(Import::State::Failed); emit import.abortAndCleanup(); return; } qInfo() << "createWallpaperImagePreview()"; if (!import.createWallpaperImagePreview() || m_interrupt) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed); + emit createWallpaperStateChanged(Import::State::Failed); emit import.abortAndCleanup(); return; } @@ -126,7 +110,7 @@ void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, c if (!import.m_isWebm) { qInfo() << "createWallpaperVideoPreview()"; if (!import.createWallpaperVideoPreview() || m_interrupt) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed); + emit createWallpaperStateChanged(Import::State::Failed); emit import.abortAndCleanup(); return; @@ -135,7 +119,7 @@ void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, c qInfo() << "createWallpaperGifPreview()"; if (!import.createWallpaperGifPreview() || m_interrupt) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed); + emit createWallpaperStateChanged(Import::State::Failed); emit import.abortAndCleanup(); return; } @@ -144,7 +128,7 @@ void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, c if (!import.m_skipAudio) { qInfo() << "extractWallpaperAudio()"; if (!import.extractWallpaperAudio() || m_interrupt) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed); + emit createWallpaperStateChanged(Import::State::Failed); emit import.abortAndCleanup(); return; } @@ -152,17 +136,17 @@ void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, c // Skip convert for webm if (import.m_isWebm) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Finished); + emit createWallpaperStateChanged(Import::State::Finished); return; } qInfo() << "createWallpaperVideo()"; if (!import.createWallpaperVideo() || m_interrupt) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed); + emit createWallpaperStateChanged(Import::State::Failed); emit import.abortAndCleanup(); return; } - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Finished); + emit createWallpaperStateChanged(Import::State::Finished); }); QObject::connect(&m_createImportFutureWatcher, &QFutureWatcherBase::finished, this, [this]() { @@ -176,9 +160,10 @@ void Create::createWallpaperStart(QString videoPath, Create::VideoCodec codec, c void Create::importH264(QString videoPath) { reset(); - videoPath = ScreenPlayUtil::toLocal(videoPath); + ScreenPlay::Util util; + videoPath = util.toLocal(videoPath); - const QDir installedDir = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString()); + const QDir installedDir = util.toLocal(m_globalVariables->localStoragePath().toString()); // Create a temp dir so we can later alter it to the workshop id const QDateTime date = QDateTime::currentDateTime(); @@ -187,7 +172,7 @@ void Create::importH264(QString videoPath) if (!installedDir.mkdir(folderName)) { qInfo() << "Unable to create folder with name: " << folderName << " at: " << installedDir; - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CreateTmpFolderError); + emit createWallpaperStateChanged(Import::State::CreateTmpFolderError); emit abortCreateWallpaper(); return; } @@ -203,35 +188,35 @@ void Create::importH264(QString videoPath) Qt::ConnectionType::QueuedConnection); if (!import.createWallpaperInfo() || m_interrupt) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed); + emit createWallpaperStateChanged(Import::State::Failed); emit import.abortAndCleanup(); return; } qInfo() << "createWallpaperImageThumbnailPreview()"; if (!import.createWallpaperImageThumbnailPreview() || m_interrupt) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed); + emit createWallpaperStateChanged(Import::State::Failed); emit import.abortAndCleanup(); return; } qInfo() << "createWallpaperImagePreview()"; if (!import.createWallpaperImagePreview() || m_interrupt) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed); + emit createWallpaperStateChanged(Import::State::Failed); emit import.abortAndCleanup(); return; } // Skip preview convert for webm if (!import.createWallpaperVideoPreview() || m_interrupt) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed); + emit createWallpaperStateChanged(Import::State::Failed); emit import.abortAndCleanup(); return; } qInfo() << "createWallpaperGifPreview()"; if (!import.createWallpaperGifPreview() || m_interrupt) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed); + emit createWallpaperStateChanged(Import::State::Failed); emit import.abortAndCleanup(); return; } @@ -240,13 +225,13 @@ void Create::importH264(QString videoPath) if (!import.m_skipAudio) { qInfo() << "extractWallpaperAudio()"; if (!import.extractWallpaperAudio() || m_interrupt) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Failed); + emit createWallpaperStateChanged(Import::State::Failed); emit import.abortAndCleanup(); return; } } - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::Finished); + emit createWallpaperStateChanged(Import::State::Finished); return; }); @@ -270,10 +255,11 @@ void Create::saveWallpaper( const Create::VideoCodec codec, const QVector tags) { - filePath = ScreenPlayUtil::toLocal(filePath); - previewImagePath = ScreenPlayUtil::toLocal(previewImagePath); + ScreenPlay::Util util; + filePath = util.toLocal(filePath); + previewImagePath = util.toLocal(previewImagePath); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CopyFiles); + emit createWallpaperStateChanged(Import::State::CopyFiles); // Case when the selected users preview image has the same name as // our default "preview.jpg" name. QFile::copy does no override exsisting files @@ -282,7 +268,7 @@ void Create::saveWallpaper( if (userSelectedPreviewImage.fileName() == "preview.jpg") { if (!userSelectedPreviewImage.remove()) { qDebug() << "Could remove" << previewImagePath; - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CopyFilesError); + emit createWallpaperStateChanged(Import::State::CopyFilesError); } } @@ -290,7 +276,7 @@ void Create::saveWallpaper( if (previewImageFile.exists()) { if (!QFile::copy(previewImagePath, m_workingDir + "/" + previewImageFile.fileName())) { qDebug() << "Could not copy" << previewImagePath << " to " << m_workingDir + "/" + previewImageFile.fileName(); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CopyFilesError); + emit createWallpaperStateChanged(Import::State::CopyFilesError); return; } } @@ -299,12 +285,12 @@ void Create::saveWallpaper( if (filePath.endsWith(".webm") || filePath.endsWith(".mp4")) { if (!QFile::copy(filePath, m_workingDir + "/" + filePathFile.fileName())) { qDebug() << "Could not copy" << filePath << " to " << m_workingDir + "/" + filePathFile.fileName(); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CopyFilesError); + emit createWallpaperStateChanged(Import::State::CopyFilesError); return; } } - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CopyFilesFinished); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CreateProjectFile); + emit createWallpaperStateChanged(Import::State::CopyFilesFinished); + emit createWallpaperStateChanged(Import::State::CreateProjectFile); QJsonObject obj; obj.insert("description", description); @@ -317,7 +303,7 @@ void Create::saveWallpaper( obj.insert("preview", previewImageFile.exists() ? previewImageFile.fileName() : "preview.jpg"); obj.insert("previewThumbnail", "previewThumbnail.jpg"); obj.insert("type", "videoWallpaper"); - obj.insert("tags", ScreenPlayUtil::fillArray(tags)); + obj.insert("tags", util.fillArray(tags)); QFile audioFile { m_workingDir + "/audio.mp3" }; if (audioFile.exists() && audioFile.size() > 0) { @@ -325,12 +311,12 @@ void Create::saveWallpaper( obj.insert("audioCodec", "mp3"); } - if (!Util::writeSettings(std::move(obj), m_workingDir + "/project.json")) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CreateProjectFileError); + if (!util.writeSettings(std::move(obj), m_workingDir + "/project.json")) { + emit createWallpaperStateChanged(Import::State::CreateProjectFileError); return; } - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::CreateProjectFileFinished); + emit createWallpaperStateChanged(Import::State::CreateProjectFileFinished); emit finished(); } @@ -351,7 +337,7 @@ void Create::abortAndCleanup() QDir exportPath(m_workingDir); if (exportPath.exists()) { if (!exportPath.removeRecursively()) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AbortCleanupError); + emit createWallpaperStateChanged(Import::State::AbortCleanupError); qWarning() << "Could not delete temp exportPath: " << exportPath; } } else { diff --git a/ScreenPlay/src/createimportvideo.cpp b/ScreenPlay/src/createimportvideo.cpp index b620f3cb..ce350deb 100644 --- a/ScreenPlay/src/createimportvideo.cpp +++ b/ScreenPlay/src/createimportvideo.cpp @@ -17,13 +17,6 @@ namespace ScreenPlay { */ -/*! - \brief This constructor is only needed for calling qRegisterMetaType on CreateImportVideo to register the enums. - \code - qRegisterMetaType("ImportVideoState::ImportVideoState"); - \endcode - */ - /*! \brief Creates a CreateImportVideo object to be used in a different thread. A \a videoPath and a \a exportPath are needed for convertion. @@ -57,13 +50,14 @@ CreateImportVideo::CreateImportVideo(const QString& videoPath, const QString& ex void CreateImportVideo::setupFFMPEG() { + Util util; #ifdef Q_OS_LINUX // Use system ffmpeg m_ffprobeExecutable = "ffprobe"; m_ffmpegExecutable = "ffmpeg"; #else - m_ffprobeExecutable = QGuiApplication::applicationDirPath() + "/ffprobe" + ScreenPlayUtil::executableBinEnding(); - m_ffmpegExecutable = QGuiApplication::applicationDirPath() + "/ffmpeg" + ScreenPlayUtil::executableBinEnding(); + m_ffprobeExecutable = QGuiApplication::applicationDirPath() + "/ffprobe" + util.executableBinEnding(); + m_ffmpegExecutable = QGuiApplication::applicationDirPath() + "/ffmpeg" + util.executableBinEnding(); #endif // We use system ffmpeg on linux #ifndef Q_OS_LINUX @@ -116,16 +110,17 @@ bool CreateImportVideo::createWallpaperInfo() args.append(m_videoPath); - emit processOutput("ffprobe " + ScreenPlayUtil::toString(args)); + Util util; + emit processOutput("ffprobe " + util.toString(args)); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideo); + emit createWallpaperStateChanged(Import::State::AnalyseVideo); const QString ffmpegOut = waitForFinished(args, QProcess::SeparateChannels, Executable::FFPROBE); qInfo() << ffmpegOut; - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideoFinished); + emit createWallpaperStateChanged(Import::State::AnalyseVideoFinished); - auto obj = ScreenPlayUtil::parseQByteArrayToQJsonObject(QByteArray::fromStdString(ffmpegOut.toStdString())); + auto obj = util.parseQByteArrayToQJsonObject(QByteArray::fromStdString(ffmpegOut.toStdString())); if (!obj) { QString error = ffmpegOut; @@ -133,14 +128,14 @@ bool CreateImportVideo::createWallpaperInfo() emit processOutput(ffmpegOut); emit processOutput("Error parsing FFPROBE json output"); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideoError); + emit createWallpaperStateChanged(Import::State::AnalyseVideoError); return false; } if (obj->empty()) { qCritical() << "Error! File could not be parsed."; emit processOutput("Error! File could not be parsed."); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideoError); + emit createWallpaperStateChanged(Import::State::AnalyseVideoError); return false; } @@ -158,7 +153,7 @@ bool CreateImportVideo::createWallpaperInfo() bool CreateImportVideo::analyzeWebmReadFrames(const QJsonObject& obj) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideo); + emit createWallpaperStateChanged(Import::State::AnalyseVideo); // Number of frames is a string for some reason... if (!obj.value("streams").isArray()) { @@ -227,7 +222,7 @@ bool CreateImportVideo::analyzeVideo(const QJsonObject& obj) if (!hasVideoStream) { qDebug() << "Error! File has no video Stream!"; emit processOutput("Error! File has no video Stream!"); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideoHasNoVideoStreamError); + emit createWallpaperStateChanged(Import::State::AnalyseVideoHasNoVideoStreamError); return false; } @@ -243,7 +238,7 @@ bool CreateImportVideo::analyzeVideo(const QJsonObject& obj) emit processOutput("Error parsing number of frames. Is this really a valid video File?"); QJsonDocument tmpVideoStreamDoc(videoStream); emit processOutput(tmpVideoStreamDoc.toJson()); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideoError); + emit createWallpaperStateChanged(Import::State::AnalyseVideoError); return false; } @@ -256,7 +251,7 @@ bool CreateImportVideo::analyzeVideo(const QJsonObject& obj) if (!okParseDuration) { qDebug() << "Error parsing video length. Is this really a valid video File?"; emit processOutput("Error parsing video length. Is this really a valid video File?"); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideoError); + emit createWallpaperStateChanged(Import::State::AnalyseVideoError); return false; } @@ -317,7 +312,7 @@ bool CreateImportVideo::analyzeVideo(const QJsonObject& obj) bool CreateImportVideo::createWallpaperVideoPreview() { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewVideo); + emit createWallpaperStateChanged(Import::State::ConvertingPreviewVideo); QStringList args; args.append("-y"); @@ -336,18 +331,18 @@ bool CreateImportVideo::createWallpaperVideoPreview() // Disable audio args.append("-an"); args.append(m_exportPath + "/preview.webm"); - emit processOutput("ffmpeg " + ScreenPlayUtil::toString(args)); + emit processOutput("ffmpeg " + Util().toString(args)); const QString ffmpegOut = waitForFinished(args); const QFile previewVideo(m_exportPath + "/preview.webm"); if (!previewVideo.exists() || !(previewVideo.size() > 0)) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewVideoError); + emit createWallpaperStateChanged(Import::State::ConvertingPreviewVideoError); return false; } emit processOutput(ffmpegOut); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewVideoFinished); + emit createWallpaperStateChanged(Import::State::ConvertingPreviewVideoFinished); return true; } @@ -369,7 +364,7 @@ bool CreateImportVideo::createWallpaperVideoPreview() bool CreateImportVideo::createWallpaperGifPreview() { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewGif); + emit createWallpaperStateChanged(Import::State::ConvertingPreviewGif); QStringList args; args.append("-y"); @@ -383,20 +378,20 @@ bool CreateImportVideo::createWallpaperGifPreview() args.append("-filter_complex"); args.append("[0:v] fps=12,scale=w=480:h=-1,split [a][b];[a] palettegen=stats_mode=single [p];[b][p] paletteuse=new=1"); args.append(m_exportPath + "/preview.gif"); - emit processOutput("ffmpeg " + ScreenPlayUtil::toString(args)); + emit processOutput("ffmpeg " + Util().toString(args)); const QString ffmpegOut = waitForFinished(args); if (!ffmpegOut.isEmpty()) { const QFile previewGif(m_exportPath + "/preview.gif"); if (!previewGif.exists() || !(previewGif.size() > 0)) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewGifError); + emit createWallpaperStateChanged(Import::State::ConvertingPreviewGifError); return false; } } emit processOutput(ffmpegOut); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewGifFinished); + emit createWallpaperStateChanged(Import::State::ConvertingPreviewGifFinished); return true; } @@ -412,7 +407,7 @@ bool CreateImportVideo::createWallpaperGifPreview() bool CreateImportVideo::createWallpaperImageThumbnailPreview() { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewImageThumbnail); + emit createWallpaperStateChanged(Import::State::ConvertingPreviewImageThumbnail); QStringList args; args.clear(); @@ -442,19 +437,19 @@ bool CreateImportVideo::createWallpaperImageThumbnailPreview() } args.append(m_exportPath + "/previewThumbnail.jpg"); - emit processOutput("ffmpeg " + ScreenPlayUtil::toString(args)); + emit processOutput("ffmpeg " + Util().toString(args)); const QString ffmpegOut = waitForFinished(args); if (!ffmpegOut.isEmpty()) { const QFile previewImg(m_exportPath + "/previewThumbnail.jpg"); if (!previewImg.exists() || !(previewImg.size() > 0)) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewImageThumbnailError); + emit createWallpaperStateChanged(Import::State::ConvertingPreviewImageThumbnailError); return false; } } emit processOutput(ffmpegOut); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewImageThumbnailFinished); + emit createWallpaperStateChanged(Import::State::ConvertingPreviewImageThumbnailFinished); return true; } @@ -465,7 +460,7 @@ bool CreateImportVideo::createWallpaperImageThumbnailPreview() bool CreateImportVideo::createWallpaperImagePreview() { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewImage); + emit createWallpaperStateChanged(Import::State::ConvertingPreviewImage); QStringList args; args.clear(); @@ -487,18 +482,18 @@ bool CreateImportVideo::createWallpaperImagePreview() } args.append(m_exportPath + "/preview.jpg"); - emit processOutput("ffmpeg " + ScreenPlayUtil::toString(args)); + emit processOutput("ffmpeg " + Util().toString(args)); const QString ffmpegOut = waitForFinished(args); if (!ffmpegOut.isEmpty()) { const QFile previewImg(m_exportPath + "/preview.jpg"); if (!previewImg.exists() || !(previewImg.size() > 0)) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewImageError); + emit createWallpaperStateChanged(Import::State::ConvertingPreviewImageError); return false; } } emit processOutput(ffmpegOut); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingPreviewImageFinished); + emit createWallpaperStateChanged(Import::State::ConvertingPreviewImageFinished); return true; } @@ -524,13 +519,13 @@ bool CreateImportVideo::createWallpaperImagePreview() */ bool CreateImportVideo::createWallpaperVideo() { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingVideo); + emit createWallpaperStateChanged(Import::State::ConvertingVideo); connect(m_process.get(), &QProcess::readyReadStandardOutput, this, [&]() { QString tmpOut = m_process->readAllStandardOutput(); qInfo() << tmpOut; if (tmpOut.contains("Conversion failed!")) { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingVideoError); + emit createWallpaperStateChanged(Import::State::ConvertingVideoError); } const auto tmpList = tmpOut.split(QRegularExpression("\\s+"), Qt::SplitBehaviorFlags::SkipEmptyParts); @@ -631,11 +626,11 @@ bool CreateImportVideo::createWallpaperVideo() QFile video(convertedFileAbsolutePath); if (!video.exists() || !(video.size() > 0)) { qDebug() << convertedFileAbsolutePath << ffmpegOutput << video.exists() << video.size(); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingVideoError); + emit createWallpaperStateChanged(Import::State::ConvertingVideoError); return false; } - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingVideoFinished); + emit createWallpaperStateChanged(Import::State::ConvertingVideoFinished); return true; } @@ -658,7 +653,7 @@ bool CreateImportVideo::createWallpaperVideo() bool CreateImportVideo::extractWallpaperAudio() { - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingAudio); + emit createWallpaperStateChanged(Import::State::ConvertingAudio); QStringList args; args.append("-y"); @@ -679,13 +674,13 @@ bool CreateImportVideo::extractWallpaperAudio() if (!previewImg.exists() || !(previewImg.size() > 0)) { qDebug() << args; qDebug() << tmpErrImg; - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingAudioError); + emit createWallpaperStateChanged(Import::State::ConvertingAudioError); return false; } } emit processOutput(tmpErrImg); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::ConvertingAudioFinished); + emit createWallpaperStateChanged(Import::State::ConvertingAudioFinished); return true; } @@ -701,9 +696,9 @@ QString CreateImportVideo::waitForFinished( { m_process = std::make_unique(); - QObject::connect(m_process.get(), &QProcess::errorOccurred, [=](QProcess::ProcessError error) { + QObject::connect(m_process.get(), &QProcess::errorOccurred, [=, this](QProcess::ProcessError error) { qDebug() << "error enum val = " << error << m_process->errorString(); - emit createWallpaperStateChanged(ImportVideoState::ImportVideoState::AnalyseVideoError); + emit createWallpaperStateChanged(Import::State::AnalyseVideoError); m_process->terminate(); if (!m_process->waitForFinished(1000)) { m_process->kill(); @@ -723,7 +718,7 @@ QString CreateImportVideo::waitForFinished( m_process->setProgram(m_ffprobeExecutable); } -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS QProcess changeChmod; changeChmod.setProgram("chmod"); changeChmod.setArguments({ "+x", m_process->program() }); diff --git a/ScreenPlay/src/globalvariables.cpp b/ScreenPlay/src/globalvariables.cpp index 5e3cb75c..1e48aad2 100644 --- a/ScreenPlay/src/globalvariables.cpp +++ b/ScreenPlay/src/globalvariables.cpp @@ -19,6 +19,58 @@ ScreenPlay::GlobalVariables::GlobalVariables(QObject* parent) setLocalSettingsPath(QUrl { QStandardPaths::writableLocation(QStandardPaths::AppLocalDataLocation) }); } +void GlobalVariables::setLocalStoragePath(QUrl localStoragePath) +{ + if (m_localStoragePath == localStoragePath) + return; + + m_localStoragePath = localStoragePath; + emit localStoragePathChanged(m_localStoragePath); +} + +void GlobalVariables::setLocalSettingsPath(QUrl localSettingsPath) +{ + if (m_localSettingsPath == localSettingsPath) + return; + + m_localSettingsPath = localSettingsPath; + emit localSettingsPathChanged(m_localSettingsPath); +} + +void GlobalVariables::setWallpaperExecutablePath(QUrl wallpaperExecutablePath) +{ + if (m_wallpaperExecutablePath == wallpaperExecutablePath) + return; + + m_wallpaperExecutablePath = wallpaperExecutablePath; + emit wallpaperExecutablePathChanged(m_wallpaperExecutablePath); +} + +void GlobalVariables::setWidgetExecutablePath(QUrl widgetExecutablePath) +{ + if (m_widgetExecutablePath == widgetExecutablePath) + return; + + m_widgetExecutablePath = widgetExecutablePath; + emit widgetExecutablePathChanged(m_widgetExecutablePath); +} + +void GlobalVariables::setGodotWallpaperExecutablePath(QUrl godotWallpaperExecutablePath) +{ + if (m_godotWallpaperExecutablePath == godotWallpaperExecutablePath) + return; + m_godotWallpaperExecutablePath = godotWallpaperExecutablePath; + emit godotWallpaperExecutablePathChanged(m_godotWallpaperExecutablePath); +} + +void GlobalVariables::setGodotEditorExecutablePath(QUrl godotEditorExecutablePath) +{ + if (m_godotEditorExecutablePath == godotEditorExecutablePath) + return; + m_godotEditorExecutablePath = godotEditorExecutablePath; + emit godotEditorExecutablePathChanged(m_godotEditorExecutablePath); +} + } #include "moc_globalvariables.cpp" diff --git a/ScreenPlay/src/installedlistfilter.cpp b/ScreenPlay/src/installedlistfilter.cpp index abdb15e2..dce27793 100644 --- a/ScreenPlay/src/installedlistfilter.cpp +++ b/ScreenPlay/src/installedlistfilter.cpp @@ -48,9 +48,9 @@ void InstalledListFilter::sortByName(const QString& name) Wallpaper, Widget, */ -void InstalledListFilter::sortBySearchType(const ScreenPlay::SearchType::SearchType searchType) +void InstalledListFilter::sortBySearchType(const ScreenPlay::ContentTypes::SearchType searchType) { - if (searchType == SearchType::SearchType::All) { + if (searchType == ContentTypes::SearchType::All) { resetFilter(); emit sortChanged(); return; diff --git a/ScreenPlay/src/installedlistmodel.cpp b/ScreenPlay/src/installedlistmodel.cpp index 0be5bc54..9c8e64a7 100644 --- a/ScreenPlay/src/installedlistmodel.cpp +++ b/ScreenPlay/src/installedlistmodel.cpp @@ -35,18 +35,23 @@ InstalledListModel::InstalledListModel( */ void InstalledListModel::init() { - if (!m_fileSystemWatcher.addPath(m_globalVariables->localStoragePath().toLocalFile())) { - qWarning() << "Could not setup file system watcher for changed files with path: " << m_globalVariables->localStoragePath().toLocalFile(); + QString projectsPath = m_globalVariables->localStoragePath().toLocalFile(); + QDirIterator projectFilesIter(projectsPath, { "*.qml", "*.html", "*.css", "*.js", "*.png", "project.json" }, QDir::Files | QDir::NoSymLinks, QDirIterator::Subdirectories); + while (projectFilesIter.hasNext()) { + m_fileSystemWatcher.addPath(projectFilesIter.next()); } + m_reloadLimiter.setInterval(500); + m_reloadLimiter.setSingleShot(true); + QObject::connect(&m_reloadLimiter, &QTimer::timeout, this, [this]() { + reset(); + }); - auto reloadLambda = [this]() { - QTimer::singleShot(500, this, [this]() { - reset(); - }); + auto restartTimer = [this]() { + m_reloadLimiter.start(); }; - QObject::connect(&m_fileSystemWatcher, &QFileSystemWatcher::directoryChanged, this, reloadLambda); - QObject::connect(&m_fileSystemWatcher, &QFileSystemWatcher::fileChanged, this, reloadLambda); + QObject::connect(&m_fileSystemWatcher, &QFileSystemWatcher::directoryChanged, this, restartTimer); + QObject::connect(&m_fileSystemWatcher, &QFileSystemWatcher::fileChanged, this, restartTimer); } /*! @@ -54,28 +59,27 @@ void InstalledListModel::init() installed list. We wait for the qml engine to free all resources before we proceed. This like the preview.gif will be in use when clicking on an item */ -void InstalledListModel::deinstallItemAt(const QString& absoluteStoragePath) +bool InstalledListModel::deinstallItemAt(const QString& absoluteStoragePath) { - QTimer::singleShot(1000, this, [this, absoluteStoragePath]() { - int index = -1; - for (int i = 0; i < m_screenPlayFiles.size(); ++i) { - if (m_screenPlayFiles.at(i).projectJsonFilePath.absoluteFilePath() == absoluteStoragePath) { - index = i; - break; - } + const QString path = Util().toLocal(absoluteStoragePath); + int index = -1; + for (int i = 0; i < m_screenPlayFiles.size(); ++i) { + if (m_screenPlayFiles.at(i).projectJsonFilePath.path() == path) { + index = i; + break; } + } - if (index < 0 || index >= m_screenPlayFiles.count()) { - qWarning() << "Remove folder error, invalid index " << index; - return; - } + if (index < 0 || index >= m_screenPlayFiles.count()) { + qWarning() << "Remove folder error, invalid index " << index; + return false; + } - beginRemoveRows(QModelIndex(), index, index); - m_screenPlayFiles.removeAt(index); - endRemoveRows(); - - const QString path = ScreenPlayUtil::toLocal(absoluteStoragePath); + beginRemoveRows(QModelIndex(), index, index); + m_screenPlayFiles.removeAt(index); + endRemoveRows(); + QTimer::singleShot(1000, this, [this, path]() { QDir dir(path); bool success = true; if (!dir.exists()) { @@ -110,6 +114,7 @@ void InstalledListModel::deinstallItemAt(const QString& absoluteStoragePath) m_fileSystemWatcher.blockSignals(false); }); }); + return true; } /*! @@ -235,11 +240,12 @@ void InstalledListModel::loadInstalledContent() counter += 1; } }; -#ifdef DEPLOY_VERSION - const QString defaultContentPath = QGuiApplication::instance()->applicationDirPath() + "/Content"; -#else - const QString defaultContentPath = QString(SCREENPLAY_SOURCE_DIR) + "/Content"; -#endif + QString defaultContentPath; + if (SCREENPLAY_DEPLOY_VERSION) { + defaultContentPath = QGuiApplication::instance()->applicationDirPath() + "/Content"; + } else { + defaultContentPath = QString(SCREENPLAY_SOURCE_DIR) + "/Content"; + } if (m_settings->showDefaultContent()) { loadFiles(defaultContentPath); } @@ -287,6 +293,10 @@ QVariantMap InstalledListModel::get(const QString& folderName) const */ void InstalledListModel::reset() { + if (m_isLoading) { + qInfo() << "loadInstalledContent is already running. Skip."; + return; + } beginResetModel(); m_screenPlayFiles.clear(); m_screenPlayFiles.squeeze(); diff --git a/ScreenPlay/src/monitorlistmodel.cpp b/ScreenPlay/src/monitorlistmodel.cpp index 3b17e431..904d57ce 100644 --- a/ScreenPlay/src/monitorlistmodel.cpp +++ b/ScreenPlay/src/monitorlistmodel.cpp @@ -1,6 +1,9 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "ScreenPlay/monitorlistmodel.h" +#ifdef Q_OS_WIN +#include "windowsintegration.h" +#endif #include namespace ScreenPlay { @@ -111,16 +114,15 @@ void MonitorListModel::loadMonitors() #ifdef Q_OS_WIN QModelIndex index; - ScreenPlayUtil::WinMonitorStats monitors; + auto monitors = WindowsIntegration().getAllMonitors(); // This offset lets us center the monitor selection view in the center int offsetX = 0; int offsetY = 0; - const int moinitorCount = monitors.iMonitors.size(); - for (int i = 0; i < moinitorCount; i++) { - const int x = monitors.rcMonitors[i].left; - const int y = monitors.rcMonitors[i].top; + for (auto& monitor : monitors) { + const int x = monitor.position.left; + const int y = monitor.position.top; if (x < 0) { offsetX += (x * -1); } @@ -129,11 +131,11 @@ void MonitorListModel::loadMonitors() } } - for (int i = 0; i < moinitorCount; i++) { - const int width = std::abs(monitors.rcMonitors[i].right - monitors.rcMonitors[i].left); - const int height = std::abs(monitors.rcMonitors[i].top - monitors.rcMonitors[i].bottom); - const int x = monitors.rcMonitors[i].left; - const int y = monitors.rcMonitors[i].top; + for (int i = 0; auto& monitor : monitors) { + const int width = std::abs(monitor.position.right - monitor.position.left); + const int height = std::abs(monitor.position.top - monitor.position.bottom); + const int x = monitor.position.left; + const int y = monitor.position.top; QRect geometry( x + offsetX, y + offsetY, @@ -142,6 +144,7 @@ void MonitorListModel::loadMonitors() beginInsertRows(index, m_monitorList.size(), m_monitorList.size()); m_monitorList.append(Monitor { i, geometry }); endInsertRows(); + i++; } #else QModelIndex index; diff --git a/ScreenPlay/src/profilelistmodel.cpp b/ScreenPlay/src/profilelistmodel.cpp index c92c6a1d..95252a25 100644 --- a/ScreenPlay/src/profilelistmodel.cpp +++ b/ScreenPlay/src/profilelistmodel.cpp @@ -22,7 +22,9 @@ namespace ScreenPlay { /*! Constructor */ -ProfileListModel::ProfileListModel(const std::shared_ptr& globalVariables, QObject* parent) +ProfileListModel::ProfileListModel( + const std::shared_ptr& globalVariables, + QObject* parent) : QAbstractListModel(parent) , m_globalVariables { globalVariables } { diff --git a/ScreenPlay/src/projectsettingslistmodel.cpp b/ScreenPlay/src/projectsettingslistmodel.cpp index eb0aa2ce..89351cbb 100644 --- a/ScreenPlay/src/projectsettingslistmodel.cpp +++ b/ScreenPlay/src/projectsettingslistmodel.cpp @@ -41,7 +41,7 @@ namespace ScreenPlay { We need to _flatten_ the json to make it work with a flat list model! See \sa getActiveSettingsJson to make the flat list to a hierarchical json object */ -void ProjectSettingsListModel::init(const InstalledType::InstalledType& type, const QJsonObject& properties) +void ProjectSettingsListModel::init(const ContentTypes::InstalledType& type, const QJsonObject& properties) { for (QJsonObject::const_iterator itParent = properties.begin(); itParent != properties.end(); itParent++) { diff --git a/ScreenPlay/src/screenplaymanager.cpp b/ScreenPlay/src/screenplaymanager.cpp index d267c6b2..8a1af2be 100644 --- a/ScreenPlay/src/screenplaymanager.cpp +++ b/ScreenPlay/src/screenplaymanager.cpp @@ -1,7 +1,7 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "ScreenPlay/screenplaymanager.h" -#include "ScreenPlay/util.h" +#include "ScreenPlayUtil/util.h" #include namespace ScreenPlay { @@ -98,8 +98,8 @@ void ScreenPlayManager::init( if we call the method when using via the settings on startup to skip a unnecessary save. */ bool ScreenPlayManager::createWallpaper( - const InstalledType::InstalledType type, - const FillMode::FillMode fillMode, + const ContentTypes::InstalledType type, + const Video::FillMode fillMode, const QString& absoluteStoragePath, const QString& previewImage, const QString& file, @@ -129,7 +129,7 @@ bool ScreenPlayManager::createWallpaper( }); const QString path = QUrl::fromUserInput(absoluteStoragePath).toLocalFile(); - const QString appID = ScreenPlayUtil::generateRandomString(); + const QString appID = Util().generateRandomString(); // Only support remove wallpaper that spans over 1 monitor if (monitorIndex.length() == 1) { @@ -169,7 +169,9 @@ bool ScreenPlayManager::createWallpaper( QObject::connect(wallpaper.get(), &ScreenPlayWallpaper::requestSave, this, &ScreenPlayManager::requestSaveProfiles); QObject::connect(wallpaper.get(), &ScreenPlayWallpaper::requestClose, this, &ScreenPlayManager::removeWallpaper); QObject::connect(wallpaper.get(), &ScreenPlayWallpaper::error, this, &ScreenPlayManager::displayErrorPopup); - + if (!wallpaper->start()) { + return false; + } m_screenPlayWallpapers.append(wallpaper); m_monitorListModel->setWallpaperMonitor(wallpaper, monitorIndex); increaseActiveWallpaperCounter(); @@ -180,7 +182,7 @@ bool ScreenPlayManager::createWallpaper( \brief Creates a ScreenPlayWidget object via a \a absoluteStoragePath and a \a preview image (relative path). */ bool ScreenPlayManager::createWidget( - const InstalledType::InstalledType type, + const ContentTypes::InstalledType type, const QPoint& position, const QString& absoluteStoragePath, const QString& previewImage, @@ -194,7 +196,7 @@ bool ScreenPlayManager::createWidget( } }); - const QString appID = ScreenPlayUtil::generateRandomString(); + const QString appID = Util().generateRandomString(); const QString path = QUrl::fromUserInput(absoluteStoragePath).toLocalFile(); if (path.isEmpty()) { @@ -256,7 +258,7 @@ bool ScreenPlayManager::removeAllWallpapers() bool ScreenPlayManager::removeAllWidgets() { if (m_screenPlayWidgets.empty()) { - qWarning() << "Trying to remove all Widgets while m_screenPlayWidgets is not empty. Count: " << m_screenPlayWidgets.size(); + qWarning() << "Trying to remove all Widgets while m_screenPlayWidgets is empty. Count: " << m_screenPlayWidgets.size(); return false; } @@ -301,7 +303,7 @@ bool ScreenPlayManager::removeWallpaperAt(int index) */ bool ScreenPlayManager::requestProjectSettingsAtMonitorIndex(const int index) { - for (const std::shared_ptr& uPtrWallpaper : qAsConst(m_screenPlayWallpapers)) { + for (const std::shared_ptr& uPtrWallpaper : std::as_const(m_screenPlayWallpapers)) { if (uPtrWallpaper->screenNumber()[0] == index) { emit projectSettingsListModelResult( @@ -331,10 +333,10 @@ bool ScreenPlayManager::setWallpaperValueAtMonitorIndex(const int index, const Q */ bool ScreenPlayManager::setWallpaperFillModeAtMonitorIndex(const int index, const int fillmode) { - const auto fillModeTyped = static_cast(fillmode); + const auto fillModeTyped = static_cast(fillmode); if (auto appID = m_monitorListModel->getAppIDByMonitorIndex(index)) { - return setWallpaperValue(*appID, "fillmode", QVariant::fromValue(fillModeTyped).toString()); + return setWallpaperValue(*appID, "fillmode", QVariant::fromValue(fillModeTyped).toString()); } qWarning() << "Could net get appID from m_monitorListModel!"; @@ -512,12 +514,12 @@ bool ScreenPlayManager::saveProfiles() m_saveLimiter.stop(); QJsonArray wallpaper {}; - for (const auto& activeWallpaper : qAsConst(m_screenPlayWallpapers)) { + for (const auto& activeWallpaper : std::as_const(m_screenPlayWallpapers)) { wallpaper.append(activeWallpaper->getActiveSettingsJson()); } QJsonArray widgets {}; - for (const auto& activeWidget : qAsConst(m_screenPlayWidgets)) { + for (const auto& activeWidget : std::as_const(m_screenPlayWidgets)) { widgets.append(activeWidget->getActiveSettingsJson()); } @@ -534,7 +536,7 @@ bool ScreenPlayManager::saveProfiles() profile.insert("version", "1.0.0"); profile.insert("profiles", activeProfileList); - if (Util::writeJsonObjectToFile({ m_globalVariables->localSettingsPath().toString() + "/profiles.json" }, profile)) { + if (Util().writeJsonObjectToFile({ m_globalVariables->localSettingsPath().toString() + "/profiles.json" }, profile)) { emit profilesSaved(); return true; } @@ -546,14 +548,15 @@ bool ScreenPlayManager::saveProfiles() */ bool ScreenPlayManager::loadProfiles() { - const auto configObj = ScreenPlayUtil::openJsonFileToObject(m_globalVariables->localSettingsPath().toString() + "/profiles.json"); + Util util; + const auto configObj = util.openJsonFileToObject(m_globalVariables->localSettingsPath().toString() + "/profiles.json"); if (!configObj) { qWarning() << "Could not load active profiles at path: " << m_globalVariables->localSettingsPath().toString() + "/profiles.json"; return false; } - std::optional version = ScreenPlayUtil::getVersionNumberFromString(configObj->value("version").toString()); + std::optional version = util.getVersionNumberFromString(configObj->value("version").toString()); if (version && *version != m_globalVariables->version()) { qWarning() << "Version missmatch fileVersion: " << version->toString() << "m_version: " << m_globalVariables->version().toString(); @@ -625,8 +628,8 @@ bool ScreenPlayManager::loadProfiles() const QString typeString = wallpaperObj.value("type").toString(); const QJsonObject properties = wallpaperObj.value("properties").toObject(); - const auto type = QStringToEnum(typeString, InstalledType::InstalledType::VideoWallpaper); - const auto fillMode = QStringToEnum(fillModeString, FillMode::FillMode::Cover); + const auto type = QStringToEnum(typeString, ContentTypes::InstalledType::VideoWallpaper); + const auto fillMode = QStringToEnum(fillModeString, Video::FillMode::Cover); const bool success = createWallpaper(type, fillMode, absolutePath, previewImage, file, monitors, volume, playbackRate, properties, false); @@ -648,7 +651,7 @@ bool ScreenPlayManager::loadProfiles() const int positionX = widgetObj.value("positionX").toInt(0); const int positionY = widgetObj.value("positionY").toInt(0); const QPoint position { positionX, positionY }; - const auto type = QStringToEnum(typeString, InstalledType::InstalledType::QMLWidget); + const auto type = QStringToEnum(typeString, ContentTypes::InstalledType::QMLWidget); const QJsonObject properties = widgetObj.value("properties").toObject(); const bool success = createWidget(type, position, absolutePath, previewImage, properties, false); @@ -668,7 +671,6 @@ bool ScreenPlayManager::loadProfiles() return true; } - } #include "moc_screenplaymanager.cpp" diff --git a/ScreenPlay/src/screenplaywallpaper.cpp b/ScreenPlay/src/screenplaywallpaper.cpp index 8717a001..83558427 100644 --- a/ScreenPlay/src/screenplaywallpaper.cpp +++ b/ScreenPlay/src/screenplaywallpaper.cpp @@ -16,7 +16,8 @@ namespace ScreenPlay { /*! \brief Constructor for ScreenPlayWallpaper. */ -ScreenPlayWallpaper::ScreenPlayWallpaper(const QVector& screenNumber, +ScreenPlayWallpaper::ScreenPlayWallpaper( + const QVector& screenNumber, const std::shared_ptr& globalVariables, const QString& appID, const QString& absolutePath, @@ -24,8 +25,8 @@ ScreenPlayWallpaper::ScreenPlayWallpaper(const QVector& screenNumber, const QString& file, const float volume, const float playbackRate, - const FillMode::FillMode fillMode, - const InstalledType::InstalledType type, + const Video::FillMode fillMode, + const ContentTypes::InstalledType type, const QJsonObject& properties, const std::shared_ptr& settings, QObject* parent) @@ -42,14 +43,18 @@ ScreenPlayWallpaper::ScreenPlayWallpaper(const QVector& screenNumber, , m_playbackRate { playbackRate } , m_settings { settings } { - + Util util; + std::optional projectOpt = util.openJsonFileToObject(absolutePath + "/project.json"); + if (projectOpt.has_value()) { + m_projectJson = projectOpt.value(); + } QJsonObject projectSettingsListModelProperties; - if (type == InstalledType::InstalledType::VideoWallpaper) { + if (type == ContentTypes::InstalledType::VideoWallpaper) { projectSettingsListModelProperties.insert("volume", m_volume); projectSettingsListModelProperties.insert("playbackRate", m_playbackRate); } else { if (properties.isEmpty()) { - if (auto obj = ScreenPlayUtil::openJsonFileToObject(absolutePath + "/project.json")) { + if (auto obj = util.openJsonFileToObject(absolutePath + "/project.json")) { if (obj->contains("properties")) projectSettingsListModelProperties = obj->value("properties").toObject(); } @@ -66,7 +71,7 @@ ScreenPlayWallpaper::ScreenPlayWallpaper(const QVector& screenNumber, QString tmpScreenNumber; if (m_screenNumber.length() > 1) { - for (const int number : qAsConst(m_screenNumber)) { + for (const int number : std::as_const(m_screenNumber)) { // IMPORTANT: NO TRAILING COMMA! if (number == m_screenNumber.back()) { tmpScreenNumber += QString::number(number); @@ -86,20 +91,41 @@ ScreenPlayWallpaper::ScreenPlayWallpaper(const QVector& screenNumber, QVariant::fromValue(fillMode).toString(), QVariant::fromValue(type).toString(), QString::number(m_settings->checkWallpaperVisible()), - // Fixes issue 84 media key overlay - " --disable-features=HardwareMediaKeyHandling" }; + + // Fixes issue 84 media key overlay in Qt apps + if (m_type != ContentTypes::InstalledType::GodotWallpaper) { + m_appArgumentsList.append(" --disable-features=HardwareMediaKeyHandling"); + } + if (m_type == ContentTypes::InstalledType::GodotWallpaper) { + if (m_projectJson.contains("version")) { + const quint64 version = m_projectJson.value("version").toInt(); + const QString packageFileName = QString("project-v%1.zip").arg(version); + m_appArgumentsList.append(packageFileName); + } + } } bool ScreenPlayWallpaper::start() { + if (m_type == ContentTypes::InstalledType::GodotWallpaper) { + if (!exportGodotProject()) + return false; + } + m_process.setArguments(m_appArgumentsList); - m_process.setProgram(m_globalVariables->wallpaperExecutablePath().toString()); + if (m_type == ContentTypes::InstalledType::GodotWallpaper) { + m_process.setProgram(m_globalVariables->godotWallpaperExecutablePath().toString()); + } else { + m_process.setProgram(m_globalVariables->wallpaperExecutablePath().toString()); + } + // We must start detatched otherwise we would instantly close the process // and would loose the animted fade-out and the background refresh needed // to display the original wallpaper. const bool success = m_process.startDetached(); - qInfo() << "Starting ScreenPlayWallpaper detached: " << (success ? "success" : "failed!"); + qInfo() << "Starting ScreenPlayWallpaper detached: " << (success ? "success" : "failed!") << m_process.program(); + qInfo() << m_appArgumentsList; if (!success) { qInfo() << m_process.program() << m_appArgumentsList; emit error(QString("Could not start Wallpaper: " + m_process.errorString())); @@ -114,13 +140,13 @@ bool ScreenPlayWallpaper::start() QJsonObject ScreenPlayWallpaper::getActiveSettingsJson() { QJsonArray screenNumber; - for (const int i : qAsConst(m_screenNumber)) { + for (const int i : std::as_const(m_screenNumber)) { screenNumber.append(i); } QJsonObject obj; QJsonObject properties; - if (m_type == InstalledType::InstalledType::VideoWallpaper) { + if (m_type == ContentTypes::InstalledType::VideoWallpaper) { obj.insert("fillMode", QVariant::fromValue(m_fillMode).toString()); obj.insert("isLooping", m_isLooping); obj.insert("volume", m_volume); @@ -197,7 +223,7 @@ bool ScreenPlayWallpaper::setWallpaperValue(const QString& key, const QString& v setPlaybackRate(value.toFloat()); } if (key == "fillmode") { - setFillMode(QStringToEnum(value, FillMode::FillMode::Cover)); + setFillMode(QStringToEnum(value, Video::FillMode::Cover)); } const bool success = m_connection->sendMessage(QJsonDocument(obj).toJson(QJsonDocument::Compact)); @@ -220,7 +246,7 @@ void ScreenPlayWallpaper::setSDKConnection(std::unique_ptr connec QObject::connect(m_connection.get(), &SDKConnection::disconnected, this, [this]() { setIsConnected(false); - qInfo() << "disconnecetd;"; + qInfo() << "Wallpaper:" << m_connection->appID() << "disconnected"; }); QTimer::singleShot(1000, this, [this]() { if (playbackRate() != 1.0) { @@ -248,8 +274,8 @@ bool ScreenPlayWallpaper::replace( const QString& previewImage, const QString& file, const float volume, - const FillMode::FillMode fillMode, - const InstalledType::InstalledType type, + const Video::FillMode fillMode, + const ContentTypes::InstalledType type, const bool checkWallpaperVisible) { @@ -281,6 +307,79 @@ bool ScreenPlayWallpaper::replace( return success; } +/*! + \brief . +*/ +bool ScreenPlayWallpaper::exportGodotProject() +{ + if (!m_projectJson.contains("version")) + return false; + + const quint64 version = m_projectJson.value("version").toInt(); + const QString packageFileName = QString("project-v%1.zip").arg(version); + QFileInfo godotPackageFile(m_absolutePath + "/" + packageFileName); + // Skip reexport + if (godotPackageFile.exists()) + return true; + + qInfo() << "No suitable version found for Godot package" << packageFileName << " at" << godotPackageFile.absoluteFilePath() << " exporting a new pck as zip."; + + // Prepare the Godot export command + const QList + godotCmd + = { "--export-pack", "--headless", "Windows Desktop", packageFileName }; + + // Create QProcess instance to run the command + QProcess process; + + // Set the working directory to the given absolute path + process.setWorkingDirectory(m_absolutePath); + process.setProgram(m_globalVariables->godotEditorExecutablePath().toString()); + // Start the Godot export process + process.setArguments(godotCmd); + process.start(); + + // Wait for the process to finish or timeout + const int timeoutMilliseconds = 30000; + if (!process.waitForFinished(timeoutMilliseconds)) { + qCritical() << "Godot export process timed out or failed to start."; + return false; + } + + // Capture the standard output and error + QString stdoutString = process.readAllStandardOutput(); + QString stderrString = process.readAllStandardError(); + + // If you want to print the output to the console: + if (!stdoutString.isEmpty()) + qDebug() << "Output:" << stdoutString; + if (!stderrString.isEmpty()) + qDebug() << "Error:" << stderrString; + + // Check for errors + if (process.exitStatus() != QProcess::NormalExit || process.exitCode() != 0) { + qCritical() << "Failed to export Godot project. Error:" << process.errorString(); + return false; + } + + // Check if the project.zip file was created + QString zipPath = QDir(m_absolutePath).filePath(packageFileName); + if (!QFile::exists(zipPath)) { + qCritical() << "Expected export file (" << packageFileName << ") was not created."; + return false; + } + + // Optional: Verify if the .zip file is valid + // (A complete verification would involve extracting the file and checking its contents, + // but for simplicity, we're just checking its size here) + QFileInfo zipInfo(zipPath); + if (zipInfo.size() <= 0) { + qCritical() << "The exported " << packageFileName << " file seems to be invalid."; + return false; + } + + return true; +} } #include "moc_screenplaywallpaper.cpp" diff --git a/ScreenPlay/src/screenplaywidget.cpp b/ScreenPlay/src/screenplaywidget.cpp index 41e91ff8..95389e60 100644 --- a/ScreenPlay/src/screenplaywidget.cpp +++ b/ScreenPlay/src/screenplaywidget.cpp @@ -21,7 +21,7 @@ ScreenPlayWidget::ScreenPlayWidget( const QString& absolutePath, const QString& previewImage, const QJsonObject& properties, - const InstalledType::InstalledType type) + const ContentTypes::InstalledType type) : QObject { nullptr } , m_globalVariables { globalVariables } , m_previewImage { previewImage } @@ -34,7 +34,7 @@ ScreenPlayWidget::ScreenPlayWidget( QJsonObject projectSettingsListModelProperties; if (properties.isEmpty()) { - if (auto obj = ScreenPlayUtil::openJsonFileToObject(absolutePath + "/project.json")) { + if (auto obj = Util().openJsonFileToObject(absolutePath + "/project.json")) { if (obj->contains("properties")) projectSettingsListModelProperties = obj->value("properties").toObject(); } diff --git a/ScreenPlay/src/sdkconnection.cpp b/ScreenPlay/src/sdkconnection.cpp index 99fa4812..4402f7d1 100644 --- a/ScreenPlay/src/sdkconnection.cpp +++ b/ScreenPlay/src/sdkconnection.cpp @@ -37,56 +37,61 @@ ScreenPlay::SDKConnection::SDKConnection(QLocalSocket* socket, QObject* parent) */ void ScreenPlay::SDKConnection::readyRead() { - - auto msg = QString(m_socket->readAll()); - - if (msg == "ping") { - emit pingAliveReceived(); - return; - } - - // The first message allways contains the appID - if (msg.startsWith("appID=")) { - QStringList args = msg.split(","); - // Only use the first 32 chars for the appID - QString appID = args.at(0); - m_appID = appID.remove("appID="); - - bool typeFound = false; - for (const QString& type : ScreenPlayUtil::getAvailableTypes()) { - if (msg.contains(type, Qt::CaseInsensitive)) { - m_type = type; - typeFound = true; - break; - } - } - - if (!typeFound) { - qCritical() << "Wallpaper type not found. Expected: " << ScreenPlayUtil::getAvailableTypes() << " got: " << msg; - } - - qInfo() << "[2/4] SDKConnection parsed with type: " << m_type << " connected with AppID:" << m_appID; - - emit appConnected(this); - - } else if (msg.startsWith("command=")) { - msg.remove("command="); - if (msg == "requestRaise") { - qInfo() << "Another ScreenPlay instance reuqested this one to raise!"; - emit requestRaise(); - } - } else if (msg.startsWith("{") && msg.endsWith("}")) { - QJsonObject obj; - QJsonParseError err {}; - QJsonDocument doc = QJsonDocument::fromJson(QByteArray { msg.toUtf8() }, &err); - - if (err.error != QJsonParseError::NoError) + // Split all messages by semicolon. This fixes double messages like pingping + // when we get messages to fast + const QString read = QString(m_socket->readAll()); + const QStringList messages = read.split(";"); + for (const QString& msg : messages) { + if (msg == "ping") { + emit pingAliveReceived(); return; + } - emit jsonMessageReceived(doc.object()); + // The first message allways contains the appID + if (msg.startsWith("appID=")) { + QStringList args = msg.split(","); + // Only use the first 32 chars for the appID + QString appID = args.at(0); + m_appID = appID.remove("appID="); - } else { - qInfo() << "### Message from: " << m_appID << ": " << msg; + bool typeFound = false; + Util util; + for (const QString& type : util.getAvailableTypes()) { + if (msg.contains(type, Qt::CaseInsensitive)) { + m_type = type; + typeFound = true; + break; + } + } + + if (!typeFound) { + qCritical() << "Wallpaper type not found. Expected: " << util.getAvailableTypes() << " got: " << msg; + } + + qInfo() << "[2/4] SDKConnection parsed with type: " << m_type << " connected with AppID:" << m_appID; + + emit appConnected(this); + + } else if (msg.startsWith("command=")) { + QString command = msg; + command.remove("command="); + if (msg == "requestRaise") { + qInfo() << "Another ScreenPlay instance reuqested this one to raise!"; + emit requestRaise(); + } + } else if (msg.startsWith("{") && msg.endsWith("}")) { + QJsonObject obj; + QJsonParseError err {}; + QJsonDocument doc = QJsonDocument::fromJson(QByteArray { msg.toUtf8() }, &err); + + if (err.error != QJsonParseError::NoError) + return; + + emit jsonMessageReceived(doc.object()); + + } else { + qInfo() << "### Message from: " << m_appID << ": " << msg; + } } } diff --git a/ScreenPlay/src/settings.cpp b/ScreenPlay/src/settings.cpp index d577bdce..8a1d7d54 100644 --- a/ScreenPlay/src/settings.cpp +++ b/ScreenPlay/src/settings.cpp @@ -2,6 +2,9 @@ #include "ScreenPlay/settings.h" #include "ScreenPlayUtil/util.h" #include +#include + +#include "ScreenPlay/CMakeVariables.h" #ifdef Q_OS_WIN #include @@ -45,17 +48,19 @@ Settings::Settings(const std::shared_ptr& globalVariables, , m_globalVariables { globalVariables } { const QString qtVersion = QString("Qt Version: %1.%2.%3\n").arg(QT_VERSION_MAJOR).arg(QT_VERSION_MINOR).arg(QT_VERSION_PATCH); - const QString buildType = QString("Build type: %1\n").arg(BUILD_TYPE); - const QString buildDate = QString("Build date: %1\n").arg(BUILD_DATE); - const QString commitHash = QString("Git commit hash: %1").arg(GIT_COMMIT_HASH); - setBuildInfos(qtVersion + buildType + buildDate + commitHash); -#ifdef SCREENPLAY_STEAM - setSteamVersion(true); -#endif + const QString buildType = QString("Build type: %1\n").arg(QString(SCREENPLAY_BUILD_TYPE)); + const QString buildDate = QString("Build date: %1\n").arg(QString(SCREENPLAY_BUILD_DATE)); + const QString commitHash = QString("Git commit hash: %1\n").arg(QString(SCREENPLAY_GIT_COMMIT_HASH)); + const QString isDeployVersion = QString("Is deploy version: %1\n").arg((SCREENPLAY_DEPLOY_VERSION ? QString("โœ… Yes") : QString("โŒ No"))); + const QString isSteamVersion = QString("Is steam version: %1").arg((SCREENPLAY_STEAM_VERSION ? QString("โœ… Yes") : QString("โŒ No"))); + setBuildInfos(qtVersion + buildType + buildDate + commitHash + isDeployVersion + isSteamVersion); + + setSteamVersion(SCREENPLAY_STEAM_VERSION); + #ifdef Q_OS_WIN setDesktopEnvironment(DesktopEnvironment::Windows); #endif -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS setDesktopEnvironment(DesktopEnvironment::OSX); #endif #ifdef Q_OS_LINUX @@ -63,35 +68,27 @@ Settings::Settings(const std::shared_ptr& globalVariables, setDesktopEnvironment(DesktopEnvironment::Wayland); #endif - qRegisterMetaType("Settings::Language"); - qRegisterMetaType("Settings::Theme"); - qRegisterMetaType("Settings::DesktopEnvironment"); - - qmlRegisterUncreatableType("Settings", 1, 0, "Settings", "Error only for enums"); - // Lets not set the dev version as startup. -#ifdef DEPLOY_VERSION - if (desktopEnvironment() == DesktopEnvironment::Windows) { - QSettings settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat); - if (!settings.childGroups().contains("ScreenPlay", Qt::CaseSensitive)) { - settings.setValue("ScreenPlay", QDir::toNativeSeparators(QCoreApplication::applicationFilePath()) + " -silent"); - settings.sync(); - if (!m_qSettings.contains("Autostart")) { - m_qSettings.setValue("Autostart", true); - m_qSettings.sync(); + if (SCREENPLAY_DEPLOY_VERSION) + if (desktopEnvironment() == DesktopEnvironment::Windows) { + QSettings settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat); + if (!settings.childGroups().contains("ScreenPlay", Qt::CaseSensitive)) { + settings.setValue("ScreenPlay", QDir::toNativeSeparators(QCoreApplication::applicationFilePath()) + " -silent"); + settings.sync(); + if (!m_qSettings.contains("Autostart")) { + m_qSettings.setValue("Autostart", true); + m_qSettings.sync(); + } } } - } - -#endif setCheckWallpaperVisible(m_qSettings.value("CheckWallpaperVisible", false).toBool()); setHighPriorityStart(m_qSettings.value("ScreenPlayExecutable", false).toBool()); if (m_qSettings.contains("VideoFillMode")) { auto value = m_qSettings.value("VideoFillMode").toString(); - setVideoFillMode(QStringToEnum(value, FillMode::FillMode::Cover)); + setVideoFillMode(QStringToEnum(value, Video::FillMode::Cover)); } else { - setVideoFillMode(FillMode::FillMode::Cover); + setVideoFillMode(Video::FillMode::Cover); } if (m_qSettings.contains("Theme")) { @@ -150,38 +147,47 @@ void Settings::writeJsonFileFromResource(const QString& filename) void Settings::setupWidgetAndWindowPaths() { QDir workingDir(QGuiApplication::applicationDirPath()); + const QString osType = QSysInfo::productType(); + Util util; -#ifdef Q_OS_WIN - m_globalVariables->setWidgetExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWidget" + ScreenPlayUtil::executableBinEnding())); - m_globalVariables->setWallpaperExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWallpaper" + ScreenPlayUtil::executableBinEnding())); -#endif - -#ifdef Q_OS_LINUX - m_globalVariables->setWidgetExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWidget")); - m_globalVariables->setWallpaperExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWallpaper")); -#endif - -#ifdef Q_OS_OSX - - // ScreenPlayTest is not bundled in an .app so the working directory - // the the same as the executable. - if (QFileInfo(QCoreApplication::applicationFilePath()).fileName() != "tst_ScreenPlay") { - workingDir.cdUp(); - workingDir.cdUp(); - workingDir.cdUp(); + QString godotVersion = QString(SCREENPLAY_GODOT_VERSION); + QString godotReleaseType = QString(SCREENPLAY_GODOT_RELEASE_TYPE); + if (osType == "windows") { + m_globalVariables->setWidgetExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWidget" + util.executableBinEnding())); + m_globalVariables->setWallpaperExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWallpaper" + util.executableBinEnding())); + m_globalVariables->setGodotWallpaperExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWallpaperGodot" + util.executableBinEnding())); + const auto godotEditorName = "Godot_" + godotVersion + "_win64.exe"; + m_globalVariables->setGodotEditorExecutablePath(QUrl(workingDir.path() + "/" + godotEditorName)); + if (!QFileInfo::exists(m_globalVariables->godotWallpaperExecutablePath().toString())) { + qInfo() << "godotWallpaperExecutablePath:" << m_globalVariables->godotWallpaperExecutablePath(); + qCritical("Godot Wallpaper not found"); + } + if (!QFileInfo::exists(m_globalVariables->godotEditorExecutablePath().toString())) { + qInfo() << "godotEditorExecutablePath :" << m_globalVariables->godotEditorExecutablePath(); + qCritical("Godot Editor not found"); + } + } else if (osType == "macos") { + m_globalVariables->setWidgetExecutablePath(QUrl::fromUserInput(workingDir.path() + "/ScreenPlayWidget").toLocalFile()); + m_globalVariables->setWallpaperExecutablePath(QUrl::fromUserInput(workingDir.path() + "/ScreenPlayWallpaper").toLocalFile()); + m_globalVariables->setGodotWallpaperExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWallpaperGodot").toLocalFile()); + const auto godotEditorName = "Godot_" + godotVersion + "-stable_osx.universal"; + m_globalVariables->setGodotEditorExecutablePath(QUrl(workingDir.path() + "/" + godotEditorName)); + } else if (osType == "linux" || osType == "ubuntu") { + m_globalVariables->setWidgetExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWidget")); + m_globalVariables->setWallpaperExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWallpaper")); + m_globalVariables->setGodotWallpaperExecutablePath(QUrl(workingDir.path() + "/ScreenPlayWallpaperGodot")); + const auto godotEditorName = "Godot_" + godotVersion + "-stable_x11.64"; + m_globalVariables->setGodotEditorExecutablePath(QUrl(workingDir.path() + "/" + godotEditorName)); + } else { + qFatal("OS not supported."); } - m_globalVariables->setWidgetExecutablePath(QUrl::fromUserInput(workingDir.path() + "/ScreenPlay.app/Contents/MacOS/ScreenPlayWidget").toLocalFile()); - m_globalVariables->setWallpaperExecutablePath(QUrl::fromUserInput(workingDir.path() + "/ScreenPlay.app/Contents/MacOS/ScreenPlayWallpaper").toLocalFile()); - -#endif - if (!QFileInfo::exists(m_globalVariables->widgetExecutablePath().toString())) { - qInfo() << "widgetExecutablePath:" << m_globalVariables->widgetExecutablePath().toString(); + qInfo() << "widgetExecutablePath:" << m_globalVariables->widgetExecutablePath(); qCritical("widget executable not found!"); } if (!QFileInfo::exists(m_globalVariables->wallpaperExecutablePath().toString())) { - qInfo() << "wallpaperExecutablePath:" << m_globalVariables->wallpaperExecutablePath().toString(); + qInfo() << "wallpaperExecutablePath:" << m_globalVariables->wallpaperExecutablePath(); qCritical("wallpaper executable not found!"); } } @@ -270,13 +276,17 @@ void Settings::initSteamInstalledPath() void Settings::setupLanguage() { QString langCode; - if (m_qSettings.value("Language").isNull()) { + + // Note: isNull is true of no "Language" entry _at all_ is set + // isEmpty is true if we have an "Language" entry that is empty + if (m_qSettings.value("Language").isNull() || m_qSettings.value("Language").toString().isEmpty()) { langCode = QLocale::system().name(); // QML enum begin with uppercase: de_DE -> De_DE langCode = langCode.replace(0, 1, langCode.at(0).toUpper()); } else { langCode = m_qSettings.value("Language").toString(); } + QStringList parts = langCode.split('_'); setLanguage(QStringToEnum(langCode, Language::En_US)); retranslateUI(); @@ -313,6 +323,307 @@ bool Settings::retranslateUI() return false; } +void Settings::setShowDefaultContent(bool showDefaultContent) +{ + if (m_showDefaultContent == showDefaultContent) + return; + m_showDefaultContent = showDefaultContent; + emit showDefaultContentChanged(showDefaultContent); +} + +void Settings::setqSetting(const QString& key, const QVariant& value) +{ + m_qSettings.setValue(key, value); + m_qSettings.sync(); +} + +void Settings::setAutostart(bool autostart) +{ + if (desktopEnvironment() == DesktopEnvironment::Windows) { + + QSettings settings("HKEY_CURRENT_USER\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", QSettings::NativeFormat); + if (autostart) { + settings.setValue("ScreenPlay", QDir::toNativeSeparators(QCoreApplication::applicationFilePath()) + " -silent"); + settings.sync(); + } else { + settings.remove("ScreenPlay"); + } + } + if (desktopEnvironment() == DesktopEnvironment::OSX) { + const QString plistFileName = "app.screenplay.plist"; + QFile defaultPListFile(":/qml/ScreenPlayApp/assets/macos/" + plistFileName); + defaultPListFile.open(QIODevice::ReadOnly); + QString settingsPlistContent = defaultPListFile.readAll(); + if (!settingsPlistContent.contains("{{SCREENPLAY_PATH}}")) { + qCritical() << "Unable to load plist settings template from qrc to set autostart!"; + return; + } + + QDir workingDir(QGuiApplication::applicationDirPath()); + workingDir.cdUp(); + workingDir.cdUp(); + workingDir.cdUp(); + const QString screenPlayPath = QUrl::fromUserInput(workingDir.path() + "/ScreenPlay.app/Contents/MacOS/ScreenPlay").toLocalFile(); + settingsPlistContent.replace("{{SCREENPLAY_PATH}}", screenPlayPath); + settingsPlistContent.replace("{{SCREENPLAY_AUTOSTART}}", autostart ? "true" : "false"); + + const QString homePath = QDir::homePath(); + QFile settingsPlist(homePath + "/Library/LaunchAgents/" + plistFileName); + if (settingsPlist.exists()) { + QDomDocument doc; + if (!doc.setContent(&settingsPlist)) { + settingsPlist.close(); + return; + } + settingsPlist.close(); + + QDomElement root = doc.firstChildElement(); + QDomNodeList dictList = root.elementsByTagName("dict"); + if (dictList.size() > 1 && dictList.size() < 1) { + return; + } + + // Check if autostart and corresponding path is set and abort if so. This is needed since osx 13.0 Ventura + // because it displays an annoying message every time we change the file. + bool isCorrectPath = false; + bool isAutostartEnabled = false; + QDomNode dictNode = dictList.at(0); + if (dictNode.isElement()) { + QDomElement dictElement = dictNode.toElement(); + QDomNodeList keyList = dictElement.elementsByTagName("key"); + for (int j = 0; j < keyList.size(); j++) { + QDomNode keyNode = keyList.at(j); + if (keyNode.isElement()) { + QDomElement keyElement = keyNode.toElement(); + if (keyElement.text() == "ProgramArguments") { + QDomNode valueNode = keyNode.nextSibling(); + if (valueNode.isElement()) { + QDomElement valueElement = valueNode.toElement(); + QDomNodeList stringList = valueElement.elementsByTagName("string"); + if (!stringList.isEmpty()) { + QDomNode stringNode = stringList.at(0); + if (stringNode.isElement()) { + QDomElement stringElement = stringNode.toElement(); + const QString path = stringElement.text(); + if (path == screenPlayPath) { + isCorrectPath = true; + } + } + } + } + } + } + } + } + + if (dictNode.isElement()) { + QDomElement dictElement = dictNode.toElement(); + QDomNodeList keyList = dictElement.elementsByTagName("key"); + for (int j = 0; j < keyList.size(); j++) { + QDomNode keyNode = keyList.at(j); + if (keyNode.isElement()) { + QDomElement keyElement = keyNode.toElement(); + if (keyElement.text() == "RunAtLoad") { + QDomNode valueNode = keyNode.nextSibling(); + if (valueNode.isElement()) { + QDomElement valueElement = valueNode.toElement(); + if (valueElement.tagName() == "true") { + isAutostartEnabled = true; + } + } + } + } + } + } + + // Nothing to do. Autostart has the same value and the path is also correct. + if (isAutostartEnabled == autostart && isCorrectPath) + return; + + if (!settingsPlist.remove()) { + qCritical() << "Unable to remove: " << settingsPlist.fileName(); + } + } + + settingsPlist.open(QIODevice::WriteOnly | QIODevice::Truncate); + QTextStream out(&settingsPlist); + out.setEncoding(QStringConverter::Utf8); + out << settingsPlistContent; + settingsPlist.flush(); + settingsPlist.close(); + + qInfo() << "Set autostart enabled: " << autostart; + } + setqSetting("Autostart", autostart); + + m_autostart = autostart; + emit autostartChanged(m_autostart); +} + +void Settings::setHighPriorityStart(bool highPriorityStart) +{ + if (m_highPriorityStart == highPriorityStart) + return; + + setqSetting("HighPriorityStart", highPriorityStart); + + const QString app = "'" + QGuiApplication::applicationDirPath() + "/WindowsServiceHelper.exe" + "'"; + QStringList args { "-Command", QString("Start-Process %1 -Verb runAs").arg(app), "-ArgumentList" }; + + // Because we must use powershell, we need to add an extra 'var' and , + auto appendAsString = [&](const QString& string, const bool isLast = false) { + QString arg = "'" + string + "'"; + if (!isLast) + arg += ","; + args.append(arg); + }; + + appendAsString("--t"); + appendAsString("create"); + appendAsString("--sn"); + appendAsString("ScreenPlayService"); + appendAsString("--dn"); + appendAsString("ScreenPlayService"); + appendAsString("--a"); + appendAsString(QVariant(highPriorityStart).toString(), true); + + QProcess process; + process.start(QStringLiteral("powershell"), args); + process.waitForFinished(5000); + + m_highPriorityStart = highPriorityStart; + emit highPriorityStartChanged(m_highPriorityStart); +} + +void Settings::setLocalStoragePath(QUrl localStoragePath) +{ + // Remove: "file:///" + QJsonValue cleanedPath = QJsonValue(localStoragePath.toString()); + + setqSetting("ScreenPlayContentPath", cleanedPath); + + m_globalVariables->setLocalStoragePath(cleanedPath.toString()); + emit resetInstalledListmodel(); +} + +void Settings::setDecoder(QString decoder) +{ + if (m_decoder == decoder) + return; + + m_decoder = decoder; + + emit decoderChanged(m_decoder); +} + +void Settings::setOfflineMode(bool offlineMode) +{ + if (m_offlineMode == offlineMode) + return; + + m_offlineMode = offlineMode; + emit offlineModeChanged(m_offlineMode); +} + +void Settings::setSilentStart(bool silentStart) +{ + if (m_silentStart == silentStart) + return; + + m_silentStart = silentStart; + emit silentStartChanged(m_silentStart); +} + +void Settings::setAnonymousTelemetry(bool anonymousTelemetry) +{ + if (m_anonymousTelemetry == anonymousTelemetry) + return; + + setqSetting("AnonymousTelemetry", anonymousTelemetry); + + m_anonymousTelemetry = anonymousTelemetry; + emit anonymousTelemetryChanged(m_anonymousTelemetry); +} + +void Settings::setCheckWallpaperVisible(bool checkWallpaperVisible) +{ + if (m_checkWallpaperVisible == checkWallpaperVisible) + return; + + setqSetting("CheckWallpaperVisible", checkWallpaperVisible); + + m_checkWallpaperVisible = checkWallpaperVisible; + emit checkWallpaperVisibleChanged(m_checkWallpaperVisible); +} + +void Settings::setVideoFillMode(ScreenPlay::Video::FillMode videoFillMode) +{ + if (m_videoFillMode == videoFillMode) + return; + + setqSetting("VideoFillMode", QVariant::fromValue(videoFillMode).toString()); + + m_videoFillMode = videoFillMode; + emit videoFillModeChanged(m_videoFillMode); +} + +void Settings::setLanguage(ScreenPlay::Settings::Language language) +{ + if (m_language == language) + return; + + setqSetting("Language", QVariant::fromValue(language).toString()); + + m_language = language; + emit languageChanged(m_language); +} + +void Settings::setFont(QString font) +{ + if (m_font == font) + return; + + m_font = font; + emit fontChanged(m_font); +} + +void Settings::setTheme(ScreenPlay::Settings::Theme theme) +{ + if (m_theme == theme) + return; + + setqSetting("Theme", QVariant::fromValue(theme).toString()); + + m_theme = theme; + emit themeChanged(m_theme); +} + +void Settings::setSteamVersion(bool steamVersion) +{ + if (m_steamVersion == steamVersion) + return; + + m_steamVersion = steamVersion; + emit steamVersionChanged(m_steamVersion); +} + +void Settings::setDesktopEnvironment(DesktopEnvironment desktopEnvironment) +{ + if (m_desktopEnvironment == desktopEnvironment) + return; + + m_desktopEnvironment = desktopEnvironment; + emit desktopEnvironmentChanged(m_desktopEnvironment); +} + +void Settings::setBuildInfos(const QString& buildInfos) +{ + if (m_buildInfos == buildInfos) + return; + m_buildInfos = buildInfos; + emit buildInfosChanged(m_buildInfos); +} + /*! \brief We must translate between qml langauge code and real ones. */ diff --git a/ScreenPlay/src/util.cpp b/ScreenPlay/src/util.cpp deleted file mode 100644 index c1dba609..00000000 --- a/ScreenPlay/src/util.cpp +++ /dev/null @@ -1,443 +0,0 @@ -// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only -#include "ScreenPlay/util.h" - -#include "qarchive_enums.hpp" -#include "qarchivediskcompressor.hpp" -#include "qarchivediskextractor.hpp" - -#include -#include - -#if defined(Q_OS_WIN) -#include -#endif - -namespace ScreenPlay { - -/*! - \class ScreenPlay::Util - \inmodule ScreenPlay - \brief Easy to use global object to use when certain functionality is not available in QML. -*/ - -/*! - \brief Constructor. -*/ -Util::Util() - : QObject(nullptr) -{ - // Fix log access vilation on quit - utilPointer = this; - auto* guiAppInst = dynamic_cast(QGuiApplication::instance()); - QObject::connect(guiAppInst, &QGuiApplication::aboutToQuit, this, []() { utilPointer = nullptr; }); - - m_extractor = std::make_unique(); - m_compressor = std::make_unique(); - - QObject::connect(m_extractor.get(), &QArchive::DiskExtractor::progress, this, &Util::extractionProgressChanged); - QObject::connect(m_extractor.get(), &QArchive::DiskExtractor::finished, this, &Util::extractionFinished); - - QObject::connect(m_compressor.get(), &QArchive::DiskCompressor::progress, this, &Util::compressionProgressChanged); - QObject::connect(m_compressor.get(), &QArchive::DiskCompressor::finished, this, &Util::compressionFinished); - - // In release mode redirect messages to logging otherwhise we break the nice clickable output :( -#ifdef QT_NO_DEBUG - qInstallMessageHandler(Util::logToGui); - qInfo() << "Starting ScreenPlay LOG!"; -#endif - - // This gives us nice clickable output in QtCreator - qSetMessagePattern("%{if-category}%{category}: %{endif}%{message}\n Loc: [%{file}:%{line}]"); -} - -/*! - \brief Needed only for QArchive unique_ptr - https://stackoverflow.com/questions/28386185/cant-use-stdunique-ptrt-with-t-being-a-forward-declaration -*/ -Util::~Util() { } - -/*! - \brief Copies the given string to the clipboard. -*/ -void Util::copyToClipboard(const QString& text) const -{ - auto* clipboard = QGuiApplication::clipboard(); - clipboard->setText(text); -} - -/*! - \brief Writes a given QJsonObject to a file. The path must be absolute. When truncate is set to - true the exsisting json file will be overriten. -*/ -bool Util::writeJsonObjectToFile(const QString& absoluteFilePath, const QJsonObject& object, bool truncate) -{ - QFile configTmp; - configTmp.setFileName(absoluteFilePath); - QIODevice::OpenMode openMode; - if (truncate) { - openMode = QIODevice::ReadWrite | QIODevice::Truncate; - } else { - openMode = QIODevice::ReadWrite | QIODevice::Append; - } - - if (!configTmp.open(openMode)) { - qWarning() << "Could not open out file!" << configTmp.errorString(); - return false; - } - - QTextStream out(&configTmp); - out.setEncoding(QStringConverter::Utf8); - out << QJsonDocument(object).toJson(); - - configTmp.close(); - return true; -} - -/*! - \brief Opens a native folder window on the given path. Windows and Mac only for now! -*/ -void Util::openFolderInExplorer(const QString& url) const -{ - const QString path = QUrl::fromUserInput(url).toLocalFile(); - - // QDesktopServices can hang on Windows - if (QSysInfo::productType() == "windows") { - QProcess explorer; - explorer.setProgram("explorer.exe"); - // When we have space in the path like - // C:\Program Files (x86)\Steam\... - // we cannot set the path as an argument. But we can set the working it - // to the wanted path and open the current path via the dot. - explorer.setWorkingDirectory(QDir::toNativeSeparators(path)); - explorer.setArguments({ "." }); - explorer.startDetached(); - return; - } - - QDesktopServices::openUrl(QUrl::fromLocalFile(path)); -} - -/*! - \brief Removes file///: or file:// from the url/string -*/ -QString Util::toLocal(const QString& url) const -{ - return ScreenPlayUtil::toLocal(url); -} - -/*! - \brief Exports a given project into a .screenplay 7Zip file. -*/ -bool Util::exportProject(QString contentPath, QString exportFileName) -{ - m_compressor->clear(); - contentPath = ScreenPlayUtil::toLocal(contentPath); - exportFileName = ScreenPlayUtil::toLocal(exportFileName); - - QDir dir(contentPath); - bool success = true; - if (!dir.exists()) { - qWarning() << "Directory does not exist!" << dir; - return false; - } - QStringList files; - for (auto& item : dir.entryInfoList(QDir::Files)) { - files.append(item.absoluteFilePath()); - } - QFile exportFile(exportFileName); - if (exportFile.exists()) { - if (!exportFile.remove()) { - qWarning() << "Unable to delte file marked to override!" << dir; - return false; - } - } - m_compressor->setFileName(exportFileName); - m_compressor->setArchiveFormat(QArchive::SevenZipFormat); - m_compressor->addFiles(files); - m_compressor->start(); - return true; -} - -/*! - \brief Imports a given project from a .screenplay zip file. The argument extractionPath - must be copied otherwise it will get reset in qml before extracting. -*/ -bool Util::importProject(QString archivePath, QString extractionPath) -{ - m_extractor->clear(); - archivePath = ScreenPlayUtil::toLocal(archivePath); - extractionPath = ScreenPlayUtil::toLocal(extractionPath); - - QFileInfo fileInfo(archivePath); - if (!fileInfo.fileName().endsWith(".screenplay")) { - qWarning() << "Unsupported file type: " << fileInfo.fileName() << ". We only support '.screenplay' files."; - return false; - } - const QString name = fileInfo.fileName().remove(".screenplay"); - - const auto timestamp = QDateTime::currentDateTime().toString("ddMMyyyyhhmmss-"); - extractionPath = extractionPath + "/" + timestamp + name + "/"; - QDir dir(extractionPath); - - if (dir.exists()) { - qWarning() << "Directory does already exist!" << dir; - return false; - } - - if (!dir.mkdir(extractionPath)) { - qWarning() << "Unable to create directory:" << dir; - return false; - } - - m_extractor->setArchive(archivePath); - m_extractor->setOutputDirectory(extractionPath); - m_extractor->setCalculateProgress(true); - m_extractor->getInfo(); - m_extractor->start(); - return true; -} - -/*! - \brief Loads all content of the legal folder in the qrc into a property string of this class. - allLicenseLoaded is emited when loading is finished. -*/ -void Util::Util::requestAllLicenses() -{ - if (m_requestAllLicensesFuture.isRunning()) - return; - - m_requestAllLicensesFuture = QtConcurrent::run([this]() { - QString tmp; - QFile file; - QTextStream out(&file); - - file.setFileName(":/qml/ScreenPlayApp/legal/Font Awesome Free License.txt"); - file.open(QIODevice::ReadOnly | QIODevice::Text); - tmp += out.readAll(); - file.close(); - - file.setFileName(":/qml/ScreenPlayApp/legal/gpl-3.0.txt"); - file.open(QIODevice::ReadOnly | QIODevice::Text); - tmp += out.readAll(); - file.close(); - - file.setFileName(":/qml/ScreenPlayApp/legal/gpl-3.0.txt"); - file.open(QIODevice::ReadOnly | QIODevice::Text); - tmp += out.readAll(); - file.close(); - - file.setFileName(":/qml/ScreenPlayApp/legal/OFL.txt"); - file.open(QIODevice::ReadOnly | QIODevice::Text); - tmp += out.readAll(); - file.close(); - - file.setFileName(":/qml/ScreenPlayApp/legal/OpenSSL.txt"); - file.open(QIODevice::ReadOnly | QIODevice::Text); - tmp += out.readAll(); - file.close(); - - file.setFileName(":/qml/ScreenPlayApp/legal/Qt LGPLv3.txt"); - file.open(QIODevice::ReadOnly | QIODevice::Text); - tmp += out.readAll(); - file.close(); - - emit this->allLicenseLoaded(tmp); - }); -} - -/*! - \brief Loads all dataprotection of the legal folder in the qrc into a property string of this class. - allDataProtectionLoaded is emited when loading is finished. -*/ -void Util::Util::requestDataProtection() -{ - QString tmp; - QFile file; - QTextStream out(&file); - - file.setFileName(":/qml/ScreenPlayApp/legal/DataProtection.txt"); - file.open(QIODevice::ReadOnly | QIODevice::Text); - tmp += out.readAll(); - file.close(); - - emit this->allDataProtectionLoaded(tmp); -} - -bool Util::fileExists(const QString& filePath) const -{ - const QFileInfo file(toLocal(filePath)); - return file.isFile(); -} - -static const char* -logLevelForMessageType(QtMsgType msgType) -{ - switch (msgType) { - case QtDebugMsg: - return "debug"; - case QtWarningMsg: - return "warning"; - case QtCriticalMsg: - return "error"; - case QtFatalMsg: - return "fatal"; - case QtInfoMsg: - Q_FALLTHROUGH(); - default: - return "info"; - } -} - -/*! - \brief Basic logging to the GUI. No logging is done to a log file for now. This string can be copied - in the settings tab in the UI. -*/ -void Util::logToGui(QtMsgType type, const QMessageLogContext& context, const QString& msg) -{ - qDebug() << msg; - QByteArray localMsg = msg.toLocal8Bit(); - QByteArray file = "File: " + QByteArray(context.file) + ", "; - QByteArray line = "in line " + QByteArray::number(context.line) + ", "; - QByteArray function = "function " + QByteArray(context.function) + ", Message: "; - - QString log = "  " + QDateTime::currentDateTime().toString() + "   " + localMsg + "
"; - - switch (type) { - case QtDebugMsg: - log.prepend(" Debug:"); - break; - case QtInfoMsg: - log.prepend(" Info:"); - break; - case QtWarningMsg: - log.prepend(" Warning:"); - break; - case QtCriticalMsg: - log.prepend(" Critical:"); - break; - case QtFatalMsg: - log.prepend(" Fatal:"); - break; - } - log.append("\n"); - - if (utilPointer != nullptr) - utilPointer->appendDebugMessages(log); - -#if defined(Q_OS_WIN) - sentry_value_t crumb - = sentry_value_new_breadcrumb("default", qUtf8Printable(msg)); - - sentry_value_set_by_key( - crumb, "category", sentry_value_new_string(context.category)); - - sentry_value_set_by_key( - crumb, "level", sentry_value_new_string(logLevelForMessageType(type))); - - sentry_value_t location = sentry_value_new_object(); - sentry_value_set_by_key( - location, "file", sentry_value_new_string(context.file)); - sentry_value_set_by_key( - location, "line", sentry_value_new_int32(context.line)); - sentry_value_set_by_key(crumb, "data", location); - - sentry_add_breadcrumb(crumb); -#endif -} - -/*! - \brief Takes ownership of \a obj and \a name. Tries to save into a text file - with of name. -*/ -bool Util::writeSettings(const QJsonObject& obj, const QString& absolutePath) -{ - QFile file { absolutePath }; - if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - qDebug() << "Could not open" << absolutePath; - return false; - } - - QTextStream out(&file); - out.setEncoding(QStringConverter::Utf8); - QJsonDocument doc(obj); - - out << doc.toJson(); - - file.close(); - return true; -} - -/*! - \brief Tries to save into a text file with absolute path. -*/ -bool Util::writeFile(const QString& text, const QString& absolutePath) -{ - QFile file { absolutePath }; - if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - qDebug() << "Could not open" << absolutePath; - return false; - } - - QTextStream out(&file); - out.setEncoding(QStringConverter::Utf8); - out << text; - - file.close(); - return true; -} - -/*! - \brief Tries to save into a text file with absolute path. -*/ -bool Util::writeFileFromQrc(const QString& qrcPath, const QString& absolutePath) -{ - - QFile file { absolutePath }; - if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - qDebug() << "Could not open" << absolutePath; - return false; - } - - QTextStream out(&file); - out.setEncoding(QStringConverter::Utf8); - - QFile qrc(qrcPath); - qrc.open(QIODevice::ReadOnly); - - QTextStream in(&qrc); - // Read line by line to avoid CLRF/LF issues - while (!in.atEnd()) { - out << in.readLine() << "\n"; - } - - qrc.close(); - file.close(); - return true; -} - -/*! - \brief Takes reference to \a obj. If the copy of the thumbnail is successful, - it adds the corresponding settings entry to the json object reference. -*/ -bool Util::copyPreviewThumbnail(QJsonObject& obj, const QString& previewThumbnail, const QString& destination) -{ - const QUrl previewThumbnailUrl { previewThumbnail }; - const QFileInfo previewImageFile(previewThumbnailUrl.toString()); - const QString destinationFilePath = destination + "/" + previewImageFile.fileName(); - - if (!previewThumbnail.isEmpty()) { - if (!QFile::copy(previewThumbnailUrl.toLocalFile(), destinationFilePath)) { - qDebug() << "Could not copy" << previewThumbnailUrl.toLocalFile() << " to " << destinationFilePath; - return false; - } - } - - obj.insert("previewThumbnail", previewImageFile.fileName()); - obj.insert("preview", previewImageFile.fileName()); - - return true; -} - -} - -#include "moc_util.cpp" diff --git a/ScreenPlay/src/wizards.cpp b/ScreenPlay/src/wizards.cpp index 5fd438b1..6ff59d53 100644 --- a/ScreenPlay/src/wizards.cpp +++ b/ScreenPlay/src/wizards.cpp @@ -1,6 +1,11 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "ScreenPlay/wizards.h" +#include "ScreenPlay/CMakeVariables.h" #include "ScreenPlayUtil/util.h" +#include +#include +#include +#include namespace ScreenPlay { /*! @@ -16,9 +21,6 @@ Wizards::Wizards(const std::shared_ptr& globalVariables, QObjec : QObject(parent) , m_globalVariables(globalVariables) { - qRegisterMetaType("Wizards::WizardResult"); - qmlRegisterUncreatableType("ScreenPlay.Wizards", 1, 0, "WizardResult", "Error only for enums"); - qmlRegisterType("ScreenPlay.Wizards", 1, 0, "Wizards"); } /*! @@ -44,41 +46,39 @@ void Wizards::createQMLWidget(const QString& title, return; } - const QString workingPath = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value()); + const QString workingPath = m_util.toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value()); QJsonObject obj; obj.insert("license", licenseName); obj.insert("title", title); - obj.insert("tags", ScreenPlayUtil::fillArray(tags)); + obj.insert("tags", m_util.fillArray(tags)); obj.insert("createdBy", createdBy); - obj.insert("type", QVariant::fromValue(InstalledType::InstalledType::QMLWidget).toString()); + obj.insert("type", QVariant::fromValue(ContentTypes::InstalledType::QMLWidget).toString()); obj.insert("file", "main.qml"); - if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/assets/wizards/" + licenseFile, workingPath + "/" + licenseFile)) { + if (!m_util.writeFileFromQrc(":/qml/ScreenPlayApp/assets/wizards/" + licenseFile, workingPath + "/" + licenseFile)) { qWarning() << "Could not write " << licenseFile; emit widgetCreationFinished(WizardResult::WriteLicenseFileError); return; } - if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/QMLWidgetMain.qml", workingPath + "/main.qml")) { + if (!m_util.writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/QMLWidgetMain.qml", workingPath + "/main.qml")) { qWarning() << "Could not write main.qml"; emit widgetCreationFinished(WizardResult::WriteProjectFileError); return; } if (!previewThumbnail.isEmpty()) { - QUrl previewThumbnailUrl { previewThumbnail }; - QFileInfo previewImageFile(previewThumbnailUrl.toLocalFile()); - obj.insert("previewThumbnail", previewImageFile.fileName()); - obj.insert("preview", previewImageFile.fileName()); - if (!QFile::copy(previewThumbnailUrl.toLocalFile(), workingPath + "/" + previewImageFile.fileName())) { - qWarning() << "Could not copy" << previewThumbnailUrl.toLocalFile() << " to " << workingPath + "/" + previewImageFile.fileName(); - emit widgetCreationFinished(WizardResult::CopyError); + if (!m_util.copyPreviewThumbnail(obj, previewThumbnail, workingPath)) { + emit widgetCreationFinished(WizardResult::CopyPreviewThumbnailError); return; } + } else { + obj.insert("preview", "preview.png"); + createPreviewImage(title, workingPath); } - if (!Util::writeSettings(obj, workingPath + "/project.json")) { + if (!m_util.writeSettings(obj, workingPath + "/project.json")) { emit widgetCreationFinished(WizardResult::WriteProjectFileError); return; } @@ -110,23 +110,23 @@ void Wizards::createHTMLWidget(const QString& title, return; } - const QString workingPath = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value()); + const QString workingPath = m_util.toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value()); QJsonObject obj; obj.insert("license", licenseName); obj.insert("createdBy", createdBy); obj.insert("title", title); - obj.insert("tags", ScreenPlayUtil::fillArray(tags)); - obj.insert("type", QVariant::fromValue(InstalledType::InstalledType::HTMLWidget).toString()); + obj.insert("tags", m_util.fillArray(tags)); + obj.insert("type", QVariant::fromValue(ContentTypes::InstalledType::HTMLWidget).toString()); obj.insert("file", "index.html"); - if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/assets/wizards/" + licenseFile, workingPath + "/" + licenseFile)) { + if (!m_util.writeFileFromQrc(":/qml/ScreenPlayApp/assets/wizards/" + licenseFile, workingPath + "/" + licenseFile)) { qWarning() << "Could not write " << licenseFile; emit widgetCreationFinished(WizardResult::WriteLicenseFileError); return; } - if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/HTMLWidgetMain.html", workingPath + "/index.html")) { + if (!m_util.writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/HTMLWidgetMain.html", workingPath + "/index.html")) { qWarning() << "Could not write HTMLWidgetMain.html"; emit widgetCreationFinished(WizardResult::WriteProjectFileError); return; @@ -136,16 +136,16 @@ void Wizards::createHTMLWidget(const QString& title, QFileInfo previewImageFile(previewThumbnailUrl.toLocalFile()); if (!previewThumbnail.isEmpty()) { - obj.insert("previewThumbnail", previewImageFile.fileName()); - obj.insert("preview", previewImageFile.fileName()); - if (!QFile::copy(previewThumbnailUrl.toLocalFile(), workingPath + "/" + previewImageFile.fileName())) { - qWarning() << "Could not copy" << previewThumbnailUrl.toLocalFile() << " to " << workingPath + "/" + previewImageFile.fileName(); - emit widgetCreationFinished(WizardResult::CopyError); + if (!m_util.copyPreviewThumbnail(obj, previewThumbnail, workingPath)) { + emit widgetCreationFinished(WizardResult::CopyPreviewThumbnailError); return; } + } else { + obj.insert("preview", "preview.png"); + createPreviewImage(title, workingPath); } - if (!Util::writeSettings(obj, workingPath + "/project.json")) { + if (!m_util.writeSettings(obj, workingPath + "/project.json")) { emit widgetCreationFinished(WizardResult::WriteProjectFileError); return; } @@ -178,41 +178,39 @@ void Wizards::createHTMLWallpaper( return; } - const QString workingPath = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value()); + const QString workingPath = m_util.toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value()); QJsonObject obj; obj.insert("license", licenseName); obj.insert("createdBy", createdBy); obj.insert("title", title); - obj.insert("tags", ScreenPlayUtil::fillArray(tags)); - obj.insert("type", QVariant::fromValue(InstalledType::InstalledType::HTMLWallpaper).toString()); + obj.insert("tags", m_util.fillArray(tags)); + obj.insert("type", QVariant::fromValue(ContentTypes::InstalledType::HTMLWallpaper).toString()); obj.insert("file", "index.html"); - if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/assets/wizards/" + licenseFile, workingPath + "/" + licenseFile)) { + if (!m_util.writeFileFromQrc(":/qml/ScreenPlayApp/assets/wizards/" + licenseFile, workingPath + "/" + licenseFile)) { qWarning() << "Could not write " << licenseFile; emit widgetCreationFinished(WizardResult::WriteLicenseFileError); return; } - if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/HTMLWallpaperMain.html", workingPath + "/index.html")) { + if (!m_util.writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/HTMLWallpaperMain.html", workingPath + "/index.html")) { qWarning() << "Could not write HTMLWallpaperMain.html"; emit widgetCreationFinished(WizardResult::WriteProjectFileError); return; } if (!previewThumbnail.isEmpty()) { - QUrl previewThumbnailUrl { previewThumbnail }; - QFileInfo previewImageFile(previewThumbnailUrl.toLocalFile()); - obj.insert("previewThumbnail", previewImageFile.fileName()); - obj.insert("preview", previewImageFile.fileName()); - if (!QFile::copy(previewThumbnailUrl.toLocalFile(), workingPath + "/" + previewImageFile.fileName())) { - qWarning() << "Could not copy" << previewThumbnailUrl.toLocalFile() << " to " << workingPath + "/" + previewImageFile.fileName(); + if (!m_util.copyPreviewThumbnail(obj, previewThumbnail, workingPath)) { emit widgetCreationFinished(WizardResult::CopyPreviewThumbnailError); return; } + } else { + obj.insert("preview", "preview.png"); + createPreviewImage(title, workingPath); } - if (!Util::writeSettings(obj, workingPath + "/project.json")) { + if (!m_util.writeSettings(obj, workingPath + "/project.json")) { emit widgetCreationFinished(WizardResult::WriteProjectFileError); return; } @@ -245,42 +243,45 @@ void Wizards::createQMLWallpaper( return; } - const QString workingPath = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value()); + const QString workingPath = m_util.toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value()); QJsonObject obj; obj.insert("license", licenseName); obj.insert("title", title); obj.insert("createdBy", createdBy); - obj.insert("tags", ScreenPlayUtil::fillArray(tags)); - obj.insert("type", QVariant::fromValue(InstalledType::InstalledType::QMLWallpaper).toString()); + obj.insert("tags", m_util.fillArray(tags)); + obj.insert("type", QVariant::fromValue(ContentTypes::InstalledType::QMLWallpaper).toString()); obj.insert("file", "main.qml"); if (!previewThumbnail.isEmpty()) { - if (!Util::copyPreviewThumbnail(obj, previewThumbnail, workingPath)) { + if (!m_util.copyPreviewThumbnail(obj, previewThumbnail, workingPath)) { emit widgetCreationFinished(WizardResult::CopyPreviewThumbnailError); return; } + } else { + obj.insert("preview", "preview.png"); + createPreviewImage(title, workingPath); } - if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/assets/wizards/" + licenseFile, workingPath + "/" + licenseFile)) { + if (!m_util.writeFileFromQrc(":/qml/ScreenPlayApp/assets/wizards/" + licenseFile, workingPath + "/" + licenseFile)) { qWarning() << "Could not write " << licenseFile; emit widgetCreationFinished(WizardResult::WriteLicenseFileError); return; } const QString qmlproject = workingPath + "/" + title + ".qmlproject"; - if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/assets/wizards/" + QString("QmlProject.qmlproject"), qmlproject)) { + if (!m_util.writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/" + QString("QmlProject.qmlproject"), qmlproject)) { qWarning() << "Could not write " << qmlproject; emit widgetCreationFinished(WizardResult::WriteLicenseFileError); return; } - if (!Util::writeSettings(obj, workingPath + "/project.json")) { + if (!m_util.writeSettings(obj, workingPath + "/project.json")) { emit widgetCreationFinished(WizardResult::WriteProjectFileError); return; } - if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/QMLWallpaperMain.qml", workingPath + "/main.qml")) { + if (!m_util.writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/QMLWallpaperMain.qml", workingPath + "/main.qml")) { qWarning() << "Could not write main.qml"; return; } @@ -289,6 +290,95 @@ void Wizards::createQMLWallpaper( }); } +/*! + \brief . +*/ +void Wizards::createGodotWallpaper( + const QString& title, + const QString& licenseName, + const QString& licenseFile, + const QString& createdBy, + const QString& previewThumbnail, + const QVector& tags) +{ + if (m_wizardFuture.isRunning()) { + qWarning() << "Another wizard is already running! Abort."; + return; + } + + m_wizardFuture = QtConcurrent::run([=]() { + std::optional folderName = createTemporaryFolder(); + + if (!folderName.has_value()) { + emit widgetCreationFinished(WizardResult::CreateProjectFolderError); + return; + } + + const QString workingPath = m_util.toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value()); + + QJsonObject obj; + obj.insert("license", licenseName); + obj.insert("title", title); + obj.insert("createdBy", createdBy); + // Every version change will trigger an reexport + obj.insert("version", 1); + // Something like v4.2-beta3 or v5.0.1-stable + QString godotVersionMajor = QString::number(SCREENPLAY_GODOT_VERSION_MAJOR); + QString godotVersionMinor = QString::number(SCREENPLAY_GODOT_VERSION_MINOR); + obj.insert("godotVersionMajor", godotVersionMajor); + obj.insert("godotVersionMinor", godotVersionMinor); + obj.insert("tags", m_util.fillArray(tags)); + obj.insert("type", QVariant::fromValue(ContentTypes::InstalledType::GodotWallpaper).toString()); + obj.insert("file", "wallpaper.tscn"); + + if (!previewThumbnail.isEmpty()) { + if (!m_util.copyPreviewThumbnail(obj, previewThumbnail, workingPath)) { + emit widgetCreationFinished(WizardResult::CopyPreviewThumbnailError); + return; + } + } else { + obj.insert("preview", "preview.png"); + createPreviewImage(title, workingPath); + } + + if (!m_util.writeFileFromQrc(":/qml/ScreenPlayApp/assets/wizards/" + licenseFile, workingPath + "/" + licenseFile)) { + qWarning() << "Could not write " << licenseFile; + emit widgetCreationFinished(WizardResult::WriteLicenseFileError); + return; + } + + if (!m_util.writeSettings(obj, workingPath + "/project.json")) { + emit widgetCreationFinished(WizardResult::WriteProjectFileError); + return; + } + + if (!m_util.writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/Godot_v5/project.godot", workingPath + "/project.godot")) { + qWarning() << "Could not write project.godot"; + return; + } + + if (!m_util.writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/Godot_v5/spinner.gd", workingPath + "/spinner.gd")) { + qWarning() << "Could not write spinner.gd"; + return; + } + + if (!m_util.writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn", workingPath + "/wallpaper.tscn")) { + qWarning() << "Could not write wallpaper.tscn"; + return; + } + + // This presets file is needed for the export. Because we do only export + // package files, it does not matter that we hardcode "Windows Desktop" as + // export preset. + if (!m_util.writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/Godot_v5/export_presets.cfg", workingPath + "/export_presets.cfg")) { + qWarning() << "Could not write export_presets.cfg"; + return; + } + + emit widgetCreationFinished(WizardResult::Ok, workingPath); + }); +} + void Wizards::createGifWallpaper( const QString& title, const QString& licenseName, @@ -310,8 +400,8 @@ void Wizards::createGifWallpaper( return; } - const QString workingPath = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value()); - const QString gifFileName = QFileInfo(ScreenPlayUtil::toLocal(file)).fileName(); + const QString workingPath = m_util.toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value()); + const QString gifFileName = QFileInfo(m_util.toLocal(file)).fileName(); QJsonObject obj; obj.insert("license", licenseName); @@ -319,21 +409,21 @@ void Wizards::createGifWallpaper( obj.insert("title", title); obj.insert("file", gifFileName); obj.insert("previewGIF", gifFileName); - obj.insert("tags", ScreenPlayUtil::fillArray(tags)); - obj.insert("type", QVariant::fromValue(InstalledType::InstalledType::GifWallpaper).toString()); + obj.insert("tags", m_util.fillArray(tags)); + obj.insert("type", QVariant::fromValue(ContentTypes::InstalledType::GifWallpaper).toString()); - if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/assets/wizards/" + licenseFile, workingPath + "/" + licenseFile)) { + if (!m_util.writeFileFromQrc(":/qml/ScreenPlayApp/assets/wizards/" + licenseFile, workingPath + "/" + licenseFile)) { qWarning() << "Could not write " << licenseFile; emit widgetCreationFinished(WizardResult::WriteLicenseFileError); return; } - if (!Util::writeSettings(obj, workingPath + "/project.json")) { + if (!m_util.writeSettings(obj, workingPath + "/project.json")) { emit widgetCreationFinished(WizardResult::WriteProjectFileError); return; } - if (!QFile::copy(ScreenPlayUtil::toLocal(file), workingPath + "/" + gifFileName)) { + if (!QFile::copy(m_util.toLocal(file), workingPath + "/" + gifFileName)) { qWarning() << "Could not copy gif " << file << " to: " << workingPath + "/" + gifFileName; emit widgetCreationFinished(WizardResult::CopyFileError); return; @@ -365,22 +455,25 @@ void Wizards::createWebsiteWallpaper( return; } - const QString workingPath = ScreenPlayUtil::toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value()); + const QString workingPath = m_util.toLocal(m_globalVariables->localStoragePath().toString() + "/" + folderName.value()); QJsonObject obj; obj.insert("title", title); - obj.insert("tags", ScreenPlayUtil::fillArray(tags)); - obj.insert("type", QVariant::fromValue(InstalledType::InstalledType::WebsiteWallpaper).toString()); + obj.insert("tags", m_util.fillArray(tags)); + obj.insert("type", QVariant::fromValue(ContentTypes::InstalledType::WebsiteWallpaper).toString()); obj.insert("url", url.toString()); if (!previewThumbnail.isEmpty()) { - if (!Util::copyPreviewThumbnail(obj, previewThumbnail, workingPath)) { + if (!m_util.copyPreviewThumbnail(obj, previewThumbnail, workingPath)) { emit widgetCreationFinished(WizardResult::CopyPreviewThumbnailError); return; } + } else { + obj.insert("preview", "preview.png"); + createPreviewImage(title, workingPath); } - if (!Util::writeSettings(obj, workingPath + "/project.json")) { + if (!m_util.writeSettings(obj, workingPath + "/project.json")) { emit widgetCreationFinished(WizardResult::WriteProjectFileError); return; } @@ -408,6 +501,48 @@ const std::optional Wizards::createTemporaryFolder() const return folderName; } + +/*! + \brief Creates a default preview.png. +*/ +void Wizards::createPreviewImage(const QString& name, const QString& targetPath) +{ + // Step 1: Create QImage and QPainter + QImage image(749, 442, QImage::Format_ARGB32); + QPainter painter(&image); + + // Step 2: Select Random Colors (example colors, replace with Material colors) + // These are just placeholder colors, replace with actual Material colors + int randomIndex1 = QRandomGenerator::global()->bounded(5); + int randomIndex2 = QRandomGenerator::global()->bounded(5); + + // Step 3: Create and Set Gradient + QLinearGradient gradient(QPointF(0, image.height()), QPointF(image.width(), 0)); + gradient.setColorAt(0, m_gradientColors[randomIndex1].darker()); // Dark color + gradient.setColorAt(1, m_gradientColors[randomIndex2].lighter()); // Bright color + + painter.fillRect(image.rect(), gradient); + + // Step 4: Draw Text + // Set the font size depending on the size of the image + painter.setPen(Qt::white); + int fontSize = qMin(image.width(), image.height()) / 10; // Adjust proportion as needed + QFont font = painter.font(); + font.setFamily("Noto Sans Light"); + font.setPointSize(fontSize); + painter.setFont(font); + + // Define a margin and adjust the rect accordingly + int margin = 30; + QRect rect(margin, margin, image.width() - 2 * margin, image.height() - 2 * margin); + + // Draw text within the adjusted rect + QTextOption option(Qt::AlignCenter); + painter.drawText(rect, name, option); + + // Step 5: Save Image + image.save(targetPath + "/preview.png"); +} } #include "moc_wizards.cpp" diff --git a/ScreenPlay/tests/tst_main.cpp b/ScreenPlay/tests/tst_main.cpp index e60d9def..03126b64 100644 --- a/ScreenPlay/tests/tst_main.cpp +++ b/ScreenPlay/tests/tst_main.cpp @@ -3,6 +3,8 @@ #include "ScreenPlay/app.h" #include "ScreenPlay/create.h" +#include "ScreenPlay/CMakeVariables.h" + #include #include #include @@ -100,7 +102,7 @@ void ScreenPlayTest::import_convert_video() auto* createWallpaperInit = m_window->findChild("createWallpaperInit"); QVERIFY(createWallpaperInit); - const QString originalVideoPath = QString(SOURCE_DIR) + "/ScreenPlay/assets/tests/video_import.mp4"; + const QString originalVideoPath = QString(SCREENPLAY_SOURCE_DIR) + "/Content/wallpaper_video_nebula_h264/mantissa.xyz_loop_072.mp4"; qInfo() << originalVideoPath; QVERIFY(QMetaObject::invokeMethod(createWallpaperInit, @@ -112,15 +114,15 @@ void ScreenPlayTest::import_convert_video() QTest::qWait(1000); // Wait for Create::createWallpaperStart { - ImportVideoState::ImportVideoState status = ImportVideoState::ImportVideoState::Idle; - QObject::connect(app.create(), &Create::createWallpaperStateChanged, this, [&status](ImportVideoState::ImportVideoState state) { + Import::State status = Import::State::Idle; + QObject::connect(app.create(), &Create::createWallpaperStateChanged, this, [&status](Import::State state) { status = state; }); while (true) { QSignalSpy videoConvertFinishSpy(app.create(), &Create::createWallpaperStateChanged); - if (status == ImportVideoState::ImportVideoState::Finished || status == ImportVideoState::ImportVideoState::Failed) { - QVERIFY(status == ImportVideoState::ImportVideoState::Finished); + if (status == Import::State::Finished || status == Import::State::Failed) { + QVERIFY(status == Import::State::Finished); QTest::qWait(1000); // Wait for the ui to process the event break; } @@ -135,15 +137,15 @@ void ScreenPlayTest::import_convert_video() // Wait for Create::saveWallpaper { - ImportVideoState::ImportVideoState status = ImportVideoState::ImportVideoState::Idle; - QObject::connect(app.create(), &Create::createWallpaperStateChanged, this, [&status](ImportVideoState::ImportVideoState state) { + Import::State status = Import::State::Idle; + QObject::connect(app.create(), &Create::createWallpaperStateChanged, this, [&status](Import::State state) { status = state; }); while (true) { QSignalSpy videoConvertFinishSpy(app.create(), &Create::createWallpaperStateChanged); - if (status == ImportVideoState::ImportVideoState::CreateProjectFileFinished || status == ImportVideoState::ImportVideoState::CreateProjectFileError || status == ImportVideoState::ImportVideoState::CopyFilesError) { - QVERIFY(status == ImportVideoState::ImportVideoState::CreateProjectFileFinished); + if (status == Import::State::CreateProjectFileFinished || status == Import::State::CreateProjectFileError || status == Import::State::CopyFilesError) { + QVERIFY(status == Import::State::CreateProjectFileFinished); QTest::qWait(1000); // Wait for the ui to process the event break; } diff --git a/ScreenPlay/translations/ScreenPlay_.ts b/ScreenPlay/translations/ScreenPlay_.ts index c92587d9..3fc2a569 100644 --- a/ScreenPlay/translations/ScreenPlay_.ts +++ b/ScreenPlay/translations/ScreenPlay_.ts @@ -622,6 +622,10 @@ ScreenPlay will only quit if no Wallpaper are running. Widgets + + Search for Wallpaper & Widgets + + InstalledWelcomeScreen @@ -815,14 +819,6 @@ ScreenPlay will only quit if no Wallpaper are running. ScreenPlay will start with Windows and will setup your Desktop every time for you. - - High priority Autostart - - - - This options grants ScreenPlay a higher autostart priority than other apps. - - Send anonymous crash reports and statistics @@ -875,22 +871,6 @@ ScreenPlay will only quit if no Wallpaper are running. Light - - Performance - - - - Pause wallpaper video rendering while another app is in the foreground - - - - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - - - - Default Fill Mode - - Set this property to define how the video is scaled to fit the target area. @@ -971,6 +951,30 @@ ScreenPlay will only quit if no Wallpaper are running. Privacy + + Show default installed content + + + + ScreenPlay will show build in content. + + + + Wallpaper and Widgets + + + + Pause wallpaper video rendering while another app is in the foreground. + + + + Limitations: This setting is Windows only, currently only works if you have exactly one monitor connected, and is limited to wallpapers with no audio. Wallpaper restart is required, when changing this setting! + + + + Default Wallpaper Fill Mode + + SettingsExpander @@ -1037,6 +1041,37 @@ ScreenPlay will only quit if no Wallpaper are running. + + TrayIcon + + ScreenPlay - Double click to change you settings. + + + + Open ScreenPlay + + + + Mute all + + + + Unmute all + + + + Pause all + + + + Play all + + + + Quit ScreenPlay + + + WebsiteWallpaper diff --git a/ScreenPlay/translations/ScreenPlay_de_DE.ts b/ScreenPlay/translations/ScreenPlay_de_DE.ts index 92da3d3c..c5dac152 100644 --- a/ScreenPlay/translations/ScreenPlay_de_DE.ts +++ b/ScreenPlay/translations/ScreenPlay_de_DE.ts @@ -624,6 +624,10 @@ ScreenPlay will only quit if no Wallpaper are running. Widgets Widgets + + Search for Wallpaper & Widgets + + InstalledWelcomeScreen @@ -817,14 +821,6 @@ ScreenPlay will only quit if no Wallpaper are running. ScreenPlay will start with Windows and will setup your Desktop every time for you. ScreenPlay startet mit Windows und richtet deinen Desktop jedes Mal fรผr dich ein. - - High priority Autostart - Hohe Prioritรคt fรผr Autostart - - - This options grants ScreenPlay a higher autostart priority than other apps. - Diese Option gewรคhrt ScreenPlay eine hรถhere Autostartprioritรคt als anderen Anwendungen. - Send anonymous crash reports and statistics Sende anonyme Absturzberichte und Statistiken @@ -877,22 +873,6 @@ ScreenPlay will only quit if no Wallpaper are running. Light Hell - - Performance - Leistung - - - Pause wallpaper video rendering while another app is in the foreground - Pausiere Wallpaper Video Rendering wenn eine andere App im Vordergrund ist - - - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - Wir deaktivieren das Video Rendering (Aber nicht die Sounds) fรผr die beste Leistung. Wenn du damit probleme haben solltest kannst dieses Verhalten hier ausschalten. Ein Neustart wird aber von Nรถten sein! - - - Default Fill Mode - Standard-Fรผllmodus - Set this property to define how the video is scaled to fit the target area. Lege diese Eigenschaft fest, um zu definieren, wie das Video skaliert wird, damit es in den Zielbereich passt. @@ -973,6 +953,30 @@ ScreenPlay will only quit if no Wallpaper are running. Privacy Datenschutz + + Show default installed content + + + + ScreenPlay will show build in content. + + + + Wallpaper and Widgets + + + + Pause wallpaper video rendering while another app is in the foreground. + + + + Limitations: This setting is Windows only, currently only works if you have exactly one monitor connected, and is limited to wallpapers with no audio. Wallpaper restart is required, when changing this setting! + + + + Default Wallpaper Fill Mode + + SettingsExpander @@ -1039,6 +1043,37 @@ ScreenPlay will only quit if no Wallpaper are running. Below you can find tools to create wallaper, beyond the tools that ScreenPlay provides for you! + + TrayIcon + + ScreenPlay - Double click to change you settings. + + + + Open ScreenPlay + + + + Mute all + + + + Unmute all + + + + Pause all + + + + Play all + + + + Quit ScreenPlay + + + WebsiteWallpaper diff --git a/ScreenPlay/translations/ScreenPlay_es_ES.ts b/ScreenPlay/translations/ScreenPlay_es_ES.ts index 119b93e7..b23da173 100644 --- a/ScreenPlay/translations/ScreenPlay_es_ES.ts +++ b/ScreenPlay/translations/ScreenPlay_es_ES.ts @@ -625,6 +625,10 @@ ScreenPlay will only quit if no Wallpaper are running. Widgets Widgets + + Search for Wallpaper & Widgets + + InstalledWelcomeScreen @@ -818,14 +822,6 @@ ScreenPlay will only quit if no Wallpaper are running. ScreenPlay will start with Windows and will setup your Desktop every time for you. ScreenPlay will start with Windows and will setup your Desktop every time for you. - - High priority Autostart - High priority Autostart - - - This options grants ScreenPlay a higher autostart priority than other apps. - This options grants ScreenPlay a higher autostart priority than other apps. - Send anonymous crash reports and statistics Send anonymous crash reports and statistics @@ -878,22 +874,6 @@ ScreenPlay will only quit if no Wallpaper are running. Light Light - - Performance - Performance - - - Pause wallpaper video rendering while another app is in the foreground - Pause wallpaper video rendering while another app is in the foreground - - - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - - - Default Fill Mode - Default Fill Mode - Set this property to define how the video is scaled to fit the target area. Set this property to define how the video is scaled to fit the target area. @@ -974,6 +954,30 @@ ScreenPlay will only quit if no Wallpaper are running. Privacy Privacy + + Show default installed content + + + + ScreenPlay will show build in content. + + + + Wallpaper and Widgets + + + + Pause wallpaper video rendering while another app is in the foreground. + + + + Limitations: This setting is Windows only, currently only works if you have exactly one monitor connected, and is limited to wallpapers with no audio. Wallpaper restart is required, when changing this setting! + + + + Default Wallpaper Fill Mode + + SettingsExpander @@ -1040,6 +1044,37 @@ ScreenPlay will only quit if no Wallpaper are running. Below you can find tools to create wallaper, beyond the tools that ScreenPlay provides for you! + + TrayIcon + + ScreenPlay - Double click to change you settings. + + + + Open ScreenPlay + + + + Mute all + + + + Unmute all + + + + Pause all + + + + Play all + + + + Quit ScreenPlay + + + WebsiteWallpaper diff --git a/ScreenPlay/translations/ScreenPlay_fr_FR.ts b/ScreenPlay/translations/ScreenPlay_fr_FR.ts index f23c9ce9..ef49b2d5 100644 --- a/ScreenPlay/translations/ScreenPlay_fr_FR.ts +++ b/ScreenPlay/translations/ScreenPlay_fr_FR.ts @@ -625,6 +625,10 @@ ScreenPlay will only quit if no Wallpaper are running. Widgets Widgets + + Search for Wallpaper & Widgets + + InstalledWelcomeScreen @@ -818,14 +822,6 @@ ScreenPlay will only quit if no Wallpaper are running. ScreenPlay will start with Windows and will setup your Desktop every time for you. ScreenPlay dรฉmarrera avec Windows et configurera votre bureau ร  chaque fois pour vous. - - High priority Autostart - Dรฉmarrage automatique haute prioritรฉ - - - This options grants ScreenPlay a higher autostart priority than other apps. - Cette option accorde ร  ScreenPlay une prioritรฉ de dรฉmarrage automatique plus รฉlevรฉe que les autres applications. - Send anonymous crash reports and statistics Envoyer des rapports d'incidents et des statistiques anonymes @@ -878,22 +874,6 @@ ScreenPlay will only quit if no Wallpaper are running. Light Clair - - Performance - Performance - - - Pause wallpaper video rendering while another app is in the foreground - Mettre en pause le rendu vidรฉo du fond d'รฉcran quand une autre application est en premier plan - - - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - Nous dรฉsactivons le rendu vidรฉo (pas l'audio) pour obtenir les meilleures performances. Si vous rencontrez des problรจmes, vous pouvez dรฉsactiver ce comportement ici. Redรฉmarrage du fond d'รฉcran requis ! - - - Default Fill Mode - Mode de remplissage par dรฉfaut - Set this property to define how the video is scaled to fit the target area. Dรฉfinissez cette propriรฉtรฉ afin de dรฉterminer la faรงon dont la vidรฉo est mise ร  l'รฉchelle pour s'adapter ร  la zone cible. @@ -974,6 +954,30 @@ ScreenPlay will only quit if no Wallpaper are running. Privacy Confidentialitรฉ + + Show default installed content + + + + ScreenPlay will show build in content. + + + + Wallpaper and Widgets + + + + Pause wallpaper video rendering while another app is in the foreground. + + + + Limitations: This setting is Windows only, currently only works if you have exactly one monitor connected, and is limited to wallpapers with no audio. Wallpaper restart is required, when changing this setting! + + + + Default Wallpaper Fill Mode + + SettingsExpander @@ -1040,6 +1044,37 @@ ScreenPlay will only quit if no Wallpaper are running. Vous trouverez ci-dessous des outils pour crรฉer des fonds d'รฉcran, au-delร  des outils que ScreenPlay met ร  votre disposition ! + + TrayIcon + + ScreenPlay - Double click to change you settings. + + + + Open ScreenPlay + + + + Mute all + + + + Unmute all + + + + Pause all + + + + Play all + + + + Quit ScreenPlay + + + WebsiteWallpaper diff --git a/ScreenPlay/translations/ScreenPlay_it_IT.ts b/ScreenPlay/translations/ScreenPlay_it_IT.ts index 3de0eb35..a8668e70 100644 --- a/ScreenPlay/translations/ScreenPlay_it_IT.ts +++ b/ScreenPlay/translations/ScreenPlay_it_IT.ts @@ -625,6 +625,10 @@ ScreenPlay will only quit if no Wallpaper are running. Widgets Widgets + + Search for Wallpaper & Widgets + + InstalledWelcomeScreen @@ -818,14 +822,6 @@ ScreenPlay will only quit if no Wallpaper are running. ScreenPlay will start with Windows and will setup your Desktop every time for you. ScreenPlay si avvierร  con Windows e configurerร  il desktop ogni volta per te. - - High priority Autostart - Avvio automatico ad alta prioritร  - - - This options grants ScreenPlay a higher autostart priority than other apps. - Questa opzione garantisce a ScreenPlay una prioritร  di avvio automatico piรน alta di altre applicazioni. - Send anonymous crash reports and statistics Invia report e statistiche anonime sui crash @@ -878,22 +874,6 @@ ScreenPlay will only quit if no Wallpaper are running. Light Chiaro - - Performance - Prestazioni - - - Pause wallpaper video rendering while another app is in the foreground - Metti in pausa il rendering video dello sfondo mentre un'altra app รจ in primo piano - - - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - Disattiviamo il rendering video (non l'audio!) per migliori prestazioni. Se hai problemi puoi disabilitare questa opzione qui. รˆ necessario riavviare lo sfondo! - - - Default Fill Mode - Modalitร  riempimento predefinita - Set this property to define how the video is scaled to fit the target area. Imposta questa proprietร  per definire come il video viene adattato all'area di destinazione. @@ -974,6 +954,30 @@ ScreenPlay will only quit if no Wallpaper are running. Privacy Privacy + + Show default installed content + + + + ScreenPlay will show build in content. + + + + Wallpaper and Widgets + + + + Pause wallpaper video rendering while another app is in the foreground. + + + + Limitations: This setting is Windows only, currently only works if you have exactly one monitor connected, and is limited to wallpapers with no audio. Wallpaper restart is required, when changing this setting! + + + + Default Wallpaper Fill Mode + + SettingsExpander @@ -1040,6 +1044,37 @@ ScreenPlay will only quit if no Wallpaper are running. Below you can find tools to create wallaper, beyond the tools that ScreenPlay provides for you! + + TrayIcon + + ScreenPlay - Double click to change you settings. + + + + Open ScreenPlay + + + + Mute all + + + + Unmute all + + + + Pause all + + + + Play all + + + + Quit ScreenPlay + + + WebsiteWallpaper diff --git a/ScreenPlay/translations/ScreenPlay_ko_KR.ts b/ScreenPlay/translations/ScreenPlay_ko_KR.ts index 723603ff..5ee20bbd 100644 --- a/ScreenPlay/translations/ScreenPlay_ko_KR.ts +++ b/ScreenPlay/translations/ScreenPlay_ko_KR.ts @@ -625,6 +625,10 @@ ScreenPlay will only quit if no Wallpaper are running. Widgets Widgets + + Search for Wallpaper & Widgets + + InstalledWelcomeScreen @@ -818,14 +822,6 @@ ScreenPlay will only quit if no Wallpaper are running. ScreenPlay will start with Windows and will setup your Desktop every time for you. ScreenPlay will start with Windows and will setup your Desktop every time for you. - - High priority Autostart - High priority Autostart - - - This options grants ScreenPlay a higher autostart priority than other apps. - This options grants ScreenPlay a higher autostart priority than other apps. - Send anonymous crash reports and statistics Send anonymous crash reports and statistics @@ -878,22 +874,6 @@ ScreenPlay will only quit if no Wallpaper are running. Light Light - - Performance - Performance - - - Pause wallpaper video rendering while another app is in the foreground - Pause wallpaper video rendering while another app is in the foreground - - - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - - - Default Fill Mode - Default Fill Mode - Set this property to define how the video is scaled to fit the target area. Set this property to define how the video is scaled to fit the target area. @@ -974,6 +954,30 @@ ScreenPlay will only quit if no Wallpaper are running. Privacy Privacy + + Show default installed content + + + + ScreenPlay will show build in content. + + + + Wallpaper and Widgets + + + + Pause wallpaper video rendering while another app is in the foreground. + + + + Limitations: This setting is Windows only, currently only works if you have exactly one monitor connected, and is limited to wallpapers with no audio. Wallpaper restart is required, when changing this setting! + + + + Default Wallpaper Fill Mode + + SettingsExpander @@ -1040,6 +1044,37 @@ ScreenPlay will only quit if no Wallpaper are running. Below you can find tools to create wallaper, beyond the tools that ScreenPlay provides for you! + + TrayIcon + + ScreenPlay - Double click to change you settings. + + + + Open ScreenPlay + + + + Mute all + + + + Unmute all + + + + Pause all + + + + Play all + + + + Quit ScreenPlay + + + WebsiteWallpaper diff --git a/ScreenPlay/translations/ScreenPlay_nl_NL.ts b/ScreenPlay/translations/ScreenPlay_nl_NL.ts index c1e78717..94801792 100644 --- a/ScreenPlay/translations/ScreenPlay_nl_NL.ts +++ b/ScreenPlay/translations/ScreenPlay_nl_NL.ts @@ -625,6 +625,10 @@ ScreenPlay will only quit if no Wallpaper are running. Widgets Widgets + + Search for Wallpaper & Widgets + + InstalledWelcomeScreen @@ -818,14 +822,6 @@ ScreenPlay will only quit if no Wallpaper are running. ScreenPlay will start with Windows and will setup your Desktop every time for you. ScreenPlay will start with Windows and will setup your Desktop every time for you. - - High priority Autostart - High priority Autostart - - - This options grants ScreenPlay a higher autostart priority than other apps. - This options grants ScreenPlay a higher autostart priority than other apps. - Send anonymous crash reports and statistics Send anonymous crash reports and statistics @@ -878,22 +874,6 @@ ScreenPlay will only quit if no Wallpaper are running. Light Light - - Performance - Performance - - - Pause wallpaper video rendering while another app is in the foreground - Pause wallpaper video rendering while another app is in the foreground - - - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - - - Default Fill Mode - Default Fill Mode - Set this property to define how the video is scaled to fit the target area. Set this property to define how the video is scaled to fit the target area. @@ -974,6 +954,30 @@ ScreenPlay will only quit if no Wallpaper are running. Privacy Privacy + + Show default installed content + + + + ScreenPlay will show build in content. + + + + Wallpaper and Widgets + + + + Pause wallpaper video rendering while another app is in the foreground. + + + + Limitations: This setting is Windows only, currently only works if you have exactly one monitor connected, and is limited to wallpapers with no audio. Wallpaper restart is required, when changing this setting! + + + + Default Wallpaper Fill Mode + + SettingsExpander @@ -1040,6 +1044,37 @@ ScreenPlay will only quit if no Wallpaper are running. Below you can find tools to create wallaper, beyond the tools that ScreenPlay provides for you! + + TrayIcon + + ScreenPlay - Double click to change you settings. + + + + Open ScreenPlay + + + + Mute all + + + + Unmute all + + + + Pause all + + + + Play all + + + + Quit ScreenPlay + + + WebsiteWallpaper diff --git a/ScreenPlay/translations/ScreenPlay_pl_PL.ts b/ScreenPlay/translations/ScreenPlay_pl_PL.ts index a3a0a647..aaa896cf 100644 --- a/ScreenPlay/translations/ScreenPlay_pl_PL.ts +++ b/ScreenPlay/translations/ScreenPlay_pl_PL.ts @@ -625,6 +625,10 @@ ScreenPlay will only quit if no Wallpaper are running. Widgets Widgets + + Search for Wallpaper & Widgets + + InstalledWelcomeScreen @@ -818,14 +822,6 @@ ScreenPlay will only quit if no Wallpaper are running. ScreenPlay will start with Windows and will setup your Desktop every time for you. ScreenPlay zostanie uruchomione przy starcie systemu Windows i ustawi dla Ciebie tapetฤ™ za kaลผdym razem. - - High priority Autostart - Wysoki priorytet autostartu - - - This options grants ScreenPlay a higher autostart priority than other apps. - Ta opcja nadaje ScreenPlay wyลผszy priorytet autostartu w porรณwnaniu do innych aplikacji. - Send anonymous crash reports and statistics Wysyล‚aj anonimowe raporty o awariach oraz statystyki @@ -878,22 +874,6 @@ ScreenPlay will only quit if no Wallpaper are running. Light Jasny - - Performance - Wydajnoล›ฤ‡ - - - Pause wallpaper video rendering while another app is in the foreground - Wstrzymaj renderowanie tapety wideo, gdy inna aplikacja jest na pierwszym planie - - - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - Wyล‚ฤ…czamy renderowanie wideo (dลบwiฤ™k zostaje!) dla najlepszej wydajnoล›ci. W przypadku problemรณw, moลผesz wyล‚ฤ…czyฤ‡ tฤ™ funkcjฤ™ tutaj. Wymaga ponownego uruchomienia tapety! - - - Default Fill Mode - Domyล›lny tryb wypeล‚niania - Set this property to define how the video is scaled to fit the target area. To ustawienie okreล›la, w jaki sposรณb film jest skalowany, aby dopasowaฤ‡ go do obszaru docelowego. @@ -974,6 +954,30 @@ ScreenPlay will only quit if no Wallpaper are running. Privacy Prywatnoล›ฤ‡ + + Show default installed content + + + + ScreenPlay will show build in content. + + + + Wallpaper and Widgets + + + + Pause wallpaper video rendering while another app is in the foreground. + + + + Limitations: This setting is Windows only, currently only works if you have exactly one monitor connected, and is limited to wallpapers with no audio. Wallpaper restart is required, when changing this setting! + + + + Default Wallpaper Fill Mode + + SettingsExpander @@ -1040,6 +1044,37 @@ ScreenPlay will only quit if no Wallpaper are running. Poniลผej znajdziesz dodatkowe narzฤ™dzia do tworzenia tapety poza tymi, ktรณre oferuje dla Ciebie ScreenPlay! + + TrayIcon + + ScreenPlay - Double click to change you settings. + + + + Open ScreenPlay + + + + Mute all + + + + Unmute all + + + + Pause all + + + + Play all + + + + Quit ScreenPlay + + + WebsiteWallpaper diff --git a/ScreenPlay/translations/ScreenPlay_pt_BR.ts b/ScreenPlay/translations/ScreenPlay_pt_BR.ts index 210eecfe..577a8fce 100644 --- a/ScreenPlay/translations/ScreenPlay_pt_BR.ts +++ b/ScreenPlay/translations/ScreenPlay_pt_BR.ts @@ -625,6 +625,10 @@ ScreenPlay will only quit if no Wallpaper are running. Widgets Widgets + + Search for Wallpaper & Widgets + + InstalledWelcomeScreen @@ -818,14 +822,6 @@ ScreenPlay will only quit if no Wallpaper are running. ScreenPlay will start with Windows and will setup your Desktop every time for you. ScreenPlay will start with Windows and will setup your Desktop every time for you. - - High priority Autostart - High priority Autostart - - - This options grants ScreenPlay a higher autostart priority than other apps. - This options grants ScreenPlay a higher autostart priority than other apps. - Send anonymous crash reports and statistics Send anonymous crash reports and statistics @@ -878,22 +874,6 @@ ScreenPlay will only quit if no Wallpaper are running. Light Light - - Performance - Performance - - - Pause wallpaper video rendering while another app is in the foreground - Pause wallpaper video rendering while another app is in the foreground - - - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - - - Default Fill Mode - Default Fill Mode - Set this property to define how the video is scaled to fit the target area. Set this property to define how the video is scaled to fit the target area. @@ -974,6 +954,30 @@ ScreenPlay will only quit if no Wallpaper are running. Privacy Privacy + + Show default installed content + + + + ScreenPlay will show build in content. + + + + Wallpaper and Widgets + + + + Pause wallpaper video rendering while another app is in the foreground. + + + + Limitations: This setting is Windows only, currently only works if you have exactly one monitor connected, and is limited to wallpapers with no audio. Wallpaper restart is required, when changing this setting! + + + + Default Wallpaper Fill Mode + + SettingsExpander @@ -1040,6 +1044,37 @@ ScreenPlay will only quit if no Wallpaper are running. Below you can find tools to create wallaper, beyond the tools that ScreenPlay provides for you! + + TrayIcon + + ScreenPlay - Double click to change you settings. + + + + Open ScreenPlay + + + + Mute all + + + + Unmute all + + + + Pause all + + + + Play all + + + + Quit ScreenPlay + + + WebsiteWallpaper diff --git a/ScreenPlay/translations/ScreenPlay_ru_RU.ts b/ScreenPlay/translations/ScreenPlay_ru_RU.ts index 815643b8..b4515b15 100644 --- a/ScreenPlay/translations/ScreenPlay_ru_RU.ts +++ b/ScreenPlay/translations/ScreenPlay_ru_RU.ts @@ -625,6 +625,10 @@ ScreenPlay will only quit if no Wallpaper are running. Widgets Widgets + + Search for Wallpaper & Widgets + + InstalledWelcomeScreen @@ -818,14 +822,6 @@ ScreenPlay will only quit if no Wallpaper are running. ScreenPlay will start with Windows and will setup your Desktop every time for you. ScreenPlay will start with Windows and will setup your Desktop every time for you. - - High priority Autostart - High priority Autostart - - - This options grants ScreenPlay a higher autostart priority than other apps. - This options grants ScreenPlay a higher autostart priority than other apps. - Send anonymous crash reports and statistics Send anonymous crash reports and statistics @@ -878,22 +874,6 @@ ScreenPlay will only quit if no Wallpaper are running. Light Light - - Performance - Performance - - - Pause wallpaper video rendering while another app is in the foreground - Pause wallpaper video rendering while another app is in the foreground - - - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - - - Default Fill Mode - Default Fill Mode - Set this property to define how the video is scaled to fit the target area. Set this property to define how the video is scaled to fit the target area. @@ -974,6 +954,30 @@ ScreenPlay will only quit if no Wallpaper are running. Privacy Privacy + + Show default installed content + + + + ScreenPlay will show build in content. + + + + Wallpaper and Widgets + + + + Pause wallpaper video rendering while another app is in the foreground. + + + + Limitations: This setting is Windows only, currently only works if you have exactly one monitor connected, and is limited to wallpapers with no audio. Wallpaper restart is required, when changing this setting! + + + + Default Wallpaper Fill Mode + + SettingsExpander @@ -1040,6 +1044,37 @@ ScreenPlay will only quit if no Wallpaper are running. Below you can find tools to create wallaper, beyond the tools that ScreenPlay provides for you! + + TrayIcon + + ScreenPlay - Double click to change you settings. + + + + Open ScreenPlay + + + + Mute all + + + + Unmute all + + + + Pause all + + + + Play all + + + + Quit ScreenPlay + + + WebsiteWallpaper diff --git a/ScreenPlay/translations/ScreenPlay_tr_TR.ts b/ScreenPlay/translations/ScreenPlay_tr_TR.ts index c82601eb..764a5518 100644 --- a/ScreenPlay/translations/ScreenPlay_tr_TR.ts +++ b/ScreenPlay/translations/ScreenPlay_tr_TR.ts @@ -625,6 +625,10 @@ ScreenPlay will only quit if no Wallpaper are running. Widgets Widgets + + Search for Wallpaper & Widgets + + InstalledWelcomeScreen @@ -818,14 +822,6 @@ ScreenPlay will only quit if no Wallpaper are running. ScreenPlay will start with Windows and will setup your Desktop every time for you. ScreenPlay, Windows ile baลŸlayacak ve her seferinde sizin iรงin Masaรผstรผnรผzรผ kuracaktฤฑr. - - High priority Autostart - Yรผksek รถncelikli Otomatik baลŸlatma - - - This options grants ScreenPlay a higher autostart priority than other apps. - Bu seรงenekler, ScreenPlay'e diฤŸer uygulamalardan daha yรผksek bir otomatik baลŸlatma รถnceliฤŸi verir. - Send anonymous crash reports and statistics Send anonymous crash reports and statistics @@ -878,22 +874,6 @@ ScreenPlay will only quit if no Wallpaper are running. Light Aydฤฑnlฤฑk - - Performance - Performans - - - Pause wallpaper video rendering while another app is in the foreground - BaลŸka bir uygulama รถn plandayken duvar kaฤŸฤฑdฤฑ video oluลŸturmayฤฑ duraklatฤฑn - - - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - En iyi performans iรงin video oluลŸturmayฤฑ (sesi deฤŸil!) devre dฤฑลŸฤฑ bฤฑrakฤฑyoruz. Sorun yaลŸฤฑyorsanฤฑz, bu davranฤฑลŸฤฑ buradan devre dฤฑลŸฤฑ bฤฑrakabilirsiniz. Duvar kaฤŸฤฑdฤฑnฤฑn yeniden baลŸlatฤฑlmasฤฑ gerekiyor! - - - Default Fill Mode - Varsayฤฑlan Doldurma Modu - Set this property to define how the video is scaled to fit the target area. Videonun hedef alana sฤฑฤŸacak ลŸekilde nasฤฑl รถlรงeklendirileceฤŸini tanฤฑmlamak iรงin bu รถzelliฤŸi ayarlayฤฑn. @@ -974,6 +954,30 @@ ScreenPlay will only quit if no Wallpaper are running. Privacy Privacy + + Show default installed content + + + + ScreenPlay will show build in content. + + + + Wallpaper and Widgets + + + + Pause wallpaper video rendering while another app is in the foreground. + + + + Limitations: This setting is Windows only, currently only works if you have exactly one monitor connected, and is limited to wallpapers with no audio. Wallpaper restart is required, when changing this setting! + + + + Default Wallpaper Fill Mode + + SettingsExpander @@ -1040,6 +1044,37 @@ ScreenPlay will only quit if no Wallpaper are running. Below you can find tools to create wallaper, beyond the tools that ScreenPlay provides for you! + + TrayIcon + + ScreenPlay - Double click to change you settings. + + + + Open ScreenPlay + + + + Mute all + + + + Unmute all + + + + Pause all + + + + Play all + + + + Quit ScreenPlay + + + WebsiteWallpaper diff --git a/ScreenPlay/translations/ScreenPlay_vi_VN.ts b/ScreenPlay/translations/ScreenPlay_vi_VN.ts index 692d6c67..4ad437cb 100644 --- a/ScreenPlay/translations/ScreenPlay_vi_VN.ts +++ b/ScreenPlay/translations/ScreenPlay_vi_VN.ts @@ -625,6 +625,10 @@ ScreenPlay will only quit if no Wallpaper are running. Widgets Widgets + + Search for Wallpaper & Widgets + + InstalledWelcomeScreen @@ -818,14 +822,6 @@ ScreenPlay will only quit if no Wallpaper are running. ScreenPlay will start with Windows and will setup your Desktop every time for you. ScreenPlay sแบฝ chแบกy cรนng vแป›i Windows vร  sแบฝ thiแบฟt lแบญp mร n hรฌnh nแปn cho bแบกn. - - High priority Autostart - Tแปฑ ฤ‘แป™ng mแปŸ ฦฐu tiรชn hฦกn - - - This options grants ScreenPlay a higher autostart priority than other apps. - Tรนy chแปn nร y cho phรฉp ScreenPlay quyแปn tแปฑ ฤ‘แป™ng chแบกy ฦฐu tiรชn hฦกn nhแปฏng แปฉng dแปฅng khรกc. - Send anonymous crash reports and statistics Gแปญi bรกo cรกo sแปฑ cแป‘ vร  sรณ liแป‡u thแป‘ng kรช แบฉn danh @@ -878,22 +874,6 @@ ScreenPlay will only quit if no Wallpaper are running. Light Sรกng - - Performance - Hiแป‡u suแบฅt - - - Pause wallpaper video rendering while another app is in the foreground - Tแบกm dแปซng แบฃnh nแปn video khi cรณ mแป™t แปฉng dแปฅng khรกc ฤ‘ang mแปŸ phรญa trฦฐแป›c - - - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - Chรบng tรดi tแบฏt hiแปƒn thแป‹ video (khรดng phแบฃi รขm thanh!) ฤแปƒ cรณ hiแป‡u suแบฅt tแป‘t nhแบฅt. Nแบฟu bแบกn gแบทp sแปฑ cแป‘, bแบกn cรณ thแปƒ vรด hiแป‡u hรณa hร nh vi nร y tแบกi ฤ‘รขy. Yรชu cแบงu khแปŸi ฤ‘แป™ng lแบกi hรฌnh nแปn! - - - Default Fill Mode - Cรกch lแบฅp ฤ‘แบงy mแบทc ฤ‘แป‹nh - Set this property to define how the video is scaled to fit the target area. ฤแบทt thuแป™c tรญnh nร y ฤ‘แปƒ xรกc ฤ‘แป‹nh cรกch chia tแปท lแป‡ video ฤ‘แปƒ phรน hแปฃp vแป›i khu vแปฑc mแปฅc tiรชu. @@ -974,6 +954,30 @@ ScreenPlay will only quit if no Wallpaper are running. Privacy Quyแปn riรชng tฦฐ + + Show default installed content + + + + ScreenPlay will show build in content. + + + + Wallpaper and Widgets + + + + Pause wallpaper video rendering while another app is in the foreground. + + + + Limitations: This setting is Windows only, currently only works if you have exactly one monitor connected, and is limited to wallpapers with no audio. Wallpaper restart is required, when changing this setting! + + + + Default Wallpaper Fill Mode + + SettingsExpander @@ -1040,6 +1044,37 @@ ScreenPlay will only quit if no Wallpaper are running. Below you can find tools to create wallaper, beyond the tools that ScreenPlay provides for you! + + TrayIcon + + ScreenPlay - Double click to change you settings. + + + + Open ScreenPlay + + + + Mute all + + + + Unmute all + + + + Pause all + + + + Play all + + + + Quit ScreenPlay + + + WebsiteWallpaper diff --git a/ScreenPlay/translations/ScreenPlay_zh_CN.ts b/ScreenPlay/translations/ScreenPlay_zh_CN.ts index 205a158a..7f71130e 100644 --- a/ScreenPlay/translations/ScreenPlay_zh_CN.ts +++ b/ScreenPlay/translations/ScreenPlay_zh_CN.ts @@ -625,6 +625,10 @@ ScreenPlay will only quit if no Wallpaper are running. Widgets Widgets + + Search for Wallpaper & Widgets + + InstalledWelcomeScreen @@ -818,14 +822,6 @@ ScreenPlay will only quit if no Wallpaper are running. ScreenPlay will start with Windows and will setup your Desktop every time for you. ScreenPlayๅฐ†ๅœจๆ“ไฝœ็ณป็ปŸๅฏๅŠจๆ—ถๅฏๅŠจ๏ผŒๅนถไผš่ฎพ็ฝฎๆ‚จ็š„ๆกŒ้ขใ€‚ - - High priority Autostart - ้ซ˜ไผ˜ๅ…ˆ็บง่‡ชๅฏๅŠจ - - - This options grants ScreenPlay a higher autostart priority than other apps. - ่ฟ™ไธช้€‰้กน่ต‹ไบˆScreenPlayๆฏ”ๅ…ถไป–ๅบ”็”จ็จ‹ๅบๆ›ด้ซ˜็š„่‡ชๅฏๅŠจไผ˜ๅ…ˆ็บงใ€‚ - Send anonymous crash reports and statistics ๅ‘้€ๅŒฟๅๅดฉๆบƒๆŠฅๅ‘Šๅ’Œ็ปŸ่ฎกๆ•ฐๆฎ @@ -878,22 +874,6 @@ ScreenPlay will only quit if no Wallpaper are running. Light ไบฎ - - Performance - ๆ€ง่ƒฝ - - - Pause wallpaper video rendering while another app is in the foreground - ๅฝ“ๅ…ถไป–ๅบ”็”จ็จ‹ๅบๅœจๅ‰ๅฐๆ—ถ๏ผŒๆš‚ๅœๅฃ็บธ่ง†้ข‘ๆธฒๆŸ“ - - - We disable the video rendering (not the audio!) for the best performance. If you have problem you can disable this behaviour here. Wallpaper restart required! - ๆˆ‘ไปฌ็ฆ็”จ่ง†้ข‘ๆธฒๆŸ“๏ผˆไธๆ˜ฏ้Ÿณ้ข‘๏ผ‰ไปฅ่Žทๅพ—ๆœ€ไฝณๆ€ง่ƒฝใ€‚ๅฆ‚ๆžœๆ‚จๆœ‰้—ฎ้ข˜๏ผŒๅฏไปฅๅœจๆญคๅค„็ฆ็”จๆญค่กŒไธบใ€‚ ้œ€่ฆ้‡ๅฏๅฃ็บธ๏ผ - - - Default Fill Mode - ้ป˜่ฎคๅกซๅ……ๆจกๅผ - Set this property to define how the video is scaled to fit the target area. ่ฎพ็ฝฎๆญคๅฑžๆ€งๅฏๅฎšไน‰่ง†้ข‘็š„็ผฉๆ”พๆ–นๅผไปฅ้€‚ๅบ”็›ฎๆ ‡ๅŒบๅŸŸใ€‚ @@ -974,6 +954,30 @@ ScreenPlay will only quit if no Wallpaper are running. Privacy ้š็ง + + Show default installed content + + + + ScreenPlay will show build in content. + + + + Wallpaper and Widgets + + + + Pause wallpaper video rendering while another app is in the foreground. + + + + Limitations: This setting is Windows only, currently only works if you have exactly one monitor connected, and is limited to wallpapers with no audio. Wallpaper restart is required, when changing this setting! + + + + Default Wallpaper Fill Mode + + SettingsExpander @@ -1040,6 +1044,37 @@ ScreenPlay will only quit if no Wallpaper are running. ไธ‹้ขๆ˜ฏไธ€ไบ›้žScreenPlayๆไพ›็š„ๅฃ็บธๅˆ›ๅปบๅทฅๅ…ท + + TrayIcon + + ScreenPlay - Double click to change you settings. + + + + Open ScreenPlay + + + + Mute all + + + + Unmute all + + + + Pause all + + + + Play all + + + + Quit ScreenPlay + + + WebsiteWallpaper diff --git a/ScreenPlaySDK/src/screenplaysdk.cpp b/ScreenPlaySDK/src/screenplaysdk.cpp index 4caec706..1847890e 100644 --- a/ScreenPlaySDK/src/screenplaysdk.cpp +++ b/ScreenPlaySDK/src/screenplaysdk.cpp @@ -63,7 +63,7 @@ void ScreenPlaySDK::connected() return; } - QByteArray welcomeMessage = QString("appID=" + m_appID + "," + m_type).toUtf8(); + QByteArray welcomeMessage = QString("appID=" + m_appID + "," + m_type + ";").toUtf8(); m_socket.write(welcomeMessage); if (!m_socket.waitForBytesWritten()) { disconnected(); @@ -164,7 +164,7 @@ void ScreenPlaySDK::redirectMessage(QByteArray& msg) void ScreenPlaySDK::pingAlive() { - m_socket.write("ping"); + m_socket.write("ping;"); if (!m_socket.waitForBytesWritten(500)) { qInfo() << "Cannot ping to main application. Closing!"; emit sdkDisconnected(); diff --git a/ScreenPlayShader/CMakeLists.txt b/ScreenPlayShader/CMakeLists.txt index d25f2b6d..2356c31c 100644 --- a/ScreenPlayShader/CMakeLists.txt +++ b/ScreenPlayShader/CMakeLists.txt @@ -36,7 +36,7 @@ set(RESOURCES assets/test_image_andras-vas-Bd7gNnWJBkU-unsplash.jpg) qt_add_library(${PROJECT_NAME} STATIC) -target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Quick) +target_link_libraries(${PROJECT_NAME} PUBLIC Qt6::Core Qt6::Quick ScreenPlayUtilplugin) target_include_directories(${PROJECT_NAME} PUBLIC src/) qt_add_qml_module( @@ -71,4 +71,8 @@ qt6_add_shaders( if(${SCREENPLAY_TESTS}) qt_add_executable(tst_ScreenPlayShader src/TestMain.cpp) target_link_libraries(tst_ScreenPlayShader PRIVATE Qt::Quick ${PROJECT_NAME}plugin) + if(APPLE) + set_target_properties(tst_ScreenPlayShader PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/") + endif() endif() diff --git a/ScreenPlayShader/src/TestMain.cpp b/ScreenPlayShader/src/TestMain.cpp index 5762ea00..c8712b06 100644 --- a/ScreenPlayShader/src/TestMain.cpp +++ b/ScreenPlayShader/src/TestMain.cpp @@ -5,6 +5,7 @@ #include Q_IMPORT_QML_PLUGIN(ScreenPlayShaderPlugin) +Q_IMPORT_QML_PLUGIN(ScreenPlayUtilPlugin) int main(int argc, char* argv[]) { diff --git a/ScreenPlayUtil/CMakeLists.txt b/ScreenPlayUtil/CMakeLists.txt index 919e9e45..66992bff 100644 --- a/ScreenPlayUtil/CMakeLists.txt +++ b/ScreenPlayUtil/CMakeLists.txt @@ -5,9 +5,13 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOMOC ON) +find_package(fmt CONFIG REQUIRED) +# Needed on macos +find_package(Threads REQUIRED) +find_package(LibArchive REQUIRED) find_package( Qt6 - COMPONENTS Core Quick + COMPONENTS Core Quick Gui REQUIRED) set(QML @@ -25,7 +29,6 @@ set(QML qml/Headline.qml qml/HeadlineSection.qml qml/ImageSelector.qml - qml/JSUtil.js qml/LicenseSelector.qml qml/ModalBackgroundBlur.qml qml/MouseHoverBlocker.qml @@ -39,24 +42,27 @@ set(QML set(SOURCES # cmake-format: sort - inc/public/ScreenPlayUtil/httpfileserver.cpp + src/archive.cpp src/contenttypes.cpp + src/exitcodes.cpp + src/httpfileserver.cpp + src/logginghandler.cpp src/projectfile.cpp + src/steamenumsgenerated.cpp src/util.cpp) set(HEADER # cmake-format: sort - inc/public/ScreenPlayUtil/AutoPropertyHelpers.h - inc/public/ScreenPlayUtil/ConstRefPropertyHelpers.h + inc/public/ScreenPlayUtil/archive.h inc/public/ScreenPlayUtil/contenttypes.h inc/public/ScreenPlayUtil/exitcodes.h inc/public/ScreenPlayUtil/HelpersCommon.h inc/public/ScreenPlayUtil/httpfileserver.h inc/public/ScreenPlayUtil/ListPropertyHelper.h + inc/public/ScreenPlayUtil/logginghandler.h inc/public/ScreenPlayUtil/projectfile.h inc/public/ScreenPlayUtil/PropertyHelpers.h - inc/public/ScreenPlayUtil/PtrPropertyHelpers.h - inc/public/ScreenPlayUtil/SingletonHelper.h + inc/public/ScreenPlayUtil/steamenumsgenerated.h inc/public/ScreenPlayUtil/util.h) if(APPLE) @@ -96,9 +102,24 @@ target_include_directories( PUBLIC inc/public/ PRIVATE src/) -target_link_libraries(${PROJECT_NAME} PRIVATE Qt6::Core Qt6::Quick) +# Note making this public is so thatscreenplayutil_qmltyperegistrations.cpp can find the #include include +target_include_directories(${PROJECT_NAME} PUBLIC inc/public/ScreenPlayUtil) +target_include_directories(${PROJECT_NAME}plugin PUBLIC inc/public/ScreenPlayUtil) + +target_link_libraries( + ${PROJECT_NAME} + PUBLIC Qt6::Core + Qt6::Quick + Qt6::Gui + fmt::fmt-header-only + LibArchive::LibArchive + QArchive) if(WIN32) # Used for query windows monitor data target_link_libraries(${PROJECT_NAME} PUBLIC shcore.lib) endif() + +# ##### USE CMAKE VARIABLES IN CODE ##### +include(GenerateCMakeVariableHeader) +generate_cmake_variable_header(${PROJECT_NAME}) diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/AutoPropertyHelpers.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/AutoPropertyHelpers.h deleted file mode 100644 index b6cecf09..00000000 --- a/ScreenPlayUtil/inc/public/ScreenPlayUtil/AutoPropertyHelpers.h +++ /dev/null @@ -1,79 +0,0 @@ -#pragma once - -#include - -#include "HelpersCommon.h" - -#define AUTO_GETTER(type, name) \ -public: \ - CheapestType::type_def MAKE_GETTER_NAME(name)() const \ - { \ - return m_##name; \ - } - -#define AUTO_SETTER(type, name) \ -public: \ - void set_##name(CheapestType::type_def name) \ - { \ - if (m_##name != name) { \ - m_##name = name; \ - Q_EMIT name##Changed(); \ - } \ - } - -#define W_AUTO_PROPERTY(type, name) \ -protected: \ - Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) WRITE set_##name NOTIFY name##Changed) \ - \ - MEMBER(type, name) \ - AUTO_GETTER(type, name) \ - AUTO_SETTER(type, name) \ - NOTIFIER(name) \ -private: - -#define R_AUTO_PROPERTY(type, name) \ -protected: \ - Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) NOTIFY name##Changed) \ - \ - MEMBER(type, name) \ - AUTO_GETTER(type, name) \ - AUTO_SETTER(type, name) \ - NOTIFIER(name) \ -private: - -#define C_AUTO_PROPERTY(type, name) \ -protected: \ - Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) CONSTANT) \ - \ - MEMBER(type, name) \ - AUTO_GETTER(type, name) \ -private: - -#define W_AUTO_PROPERTY_DEFAULT(type, name, defaultValue) \ - Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) WRITE set_##name NOTIFY name##Changed) \ - \ - MEMBER_DEFAULT(type, name, defaultValue) \ - AUTO_GETTER(type, name) \ - AUTO_SETTER(type, name) \ - NOTIFIER(name) \ -private: - -// NOTE : test class for all cases - -class _Test_QmlAutoProperty_ : public QObject { - Q_OBJECT - - W_AUTO_PROPERTY(bool, var1) - W_AUTO_PROPERTY(QString, var2) - W_AUTO_PROPERTY(QObject*, var3) - - R_AUTO_PROPERTY(bool, var4) - R_AUTO_PROPERTY(QString, var5) - R_AUTO_PROPERTY(QObject*, var6) - - C_AUTO_PROPERTY(bool, var7) - C_AUTO_PROPERTY(QString, var8) - C_AUTO_PROPERTY(QObject*, var9) - - W_AUTO_PROPERTY_DEFAULT(bool, var10, true) -}; diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/ConstRefPropertyHelpers.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/ConstRefPropertyHelpers.h deleted file mode 100644 index 90b4b398..00000000 --- a/ScreenPlayUtil/inc/public/ScreenPlayUtil/ConstRefPropertyHelpers.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -#include - -#include "HelpersCommon.h" - -#define CONST_SETTER(type, name) \ -public: \ - void set_##name(const type& name) \ - { \ - if (m_##name != name) { \ - m_##name = name; \ - Q_EMIT name##Changed(); \ - } \ - } - -#define CONST_GETTER(type, name) \ -public: \ - const type& MAKE_GETTER_NAME(name)() const \ - { \ - return m_##name; \ - } - -#define W_CREF_PROPERTY(type, name) \ -protected: \ - Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) WRITE set_##name NOTIFY name##Changed) \ -private: \ - MEMBER(type, name) \ - CONST_GETTER(type, name) \ - CONST_SETTER(type, name) \ - NOTIFIER(name) - -#define R_CREF_PROPERTY(type, name) \ -protected: \ - Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) NOTIFY name##Changed) \ - MEMBER(type, name) \ - CONST_GETTER(type, name) \ - CONST_SETTER(type, name) \ - NOTIFIER(name) \ -private: - -#define C_CREF_PROPERTY(type, name) \ -protected: \ - Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) CONSTANT) \ - MEMBER(type, name) \ - CONST_GETTER(type, name) \ -private: - -#define W_CREF_PROPERTY_DEFAULT(type, name, defaultValue) \ -protected: \ - Q_PROPERTY(type name READ MAKE_GETTER_NAME(name) WRITE set_##name NOTIFY name##Changed) \ -private: \ - MEMBER_DEFAULT(type, name, defaultValue) \ - CONST_GETTER(type, name) \ - CONST_SETTER(type, name) \ - NOTIFIER(name) - -class Test : public QObject { - Q_OBJECT - - W_CREF_PROPERTY(QString, var1) - R_CREF_PROPERTY(QString, var2) - C_CREF_PROPERTY(QString, var3) - - W_CREF_PROPERTY_DEFAULT(QString, var4, QStringLiteral("test")) -}; diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/PtrPropertyHelpers.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/PtrPropertyHelpers.h deleted file mode 100644 index 1249adeb..00000000 --- a/ScreenPlayUtil/inc/public/ScreenPlayUtil/PtrPropertyHelpers.h +++ /dev/null @@ -1,132 +0,0 @@ -#pragma once - -#include -#include - -#include "HelpersCommon.h" - -#define PTR_GETTER(type, name) \ -public: \ - type* MAKE_GETTER_NAME(name)() const \ - { \ - return m_##name; \ - } - -#define PTR_SETTER(type, name) \ -public: \ - void set_##name(type* name) \ - { \ - if (m_##name != name) { \ - m_##name = name; \ - Q_EMIT name##Changed(); \ - } \ - } - -#define SMART_PTR_GETTER(type, name) \ -public: \ - type* MAKE_GETTER_NAME(name)() const \ - { \ - return m_##name.get(); \ - } - -#define SMART_PTR_SETTER(type, name) \ -public: \ - void set_##name(type name) \ - { \ - m_##name = std::move(name); \ - Q_EMIT name##Changed(); \ - } - -#define W_PTR_PROPERTY(type, name) \ -protected: \ - Q_PROPERTY(type* name READ MAKE_GETTER_NAME(name) WRITE set_##name NOTIFY name##Changed) \ - \ - MEMBER(type*, name) \ - PTR_GETTER(type, name) \ - PTR_SETTER(type, name) \ - NOTIFIER(name) \ -private: - -#define R_PTR_PROPERTY(type, name) \ -protected: \ - Q_PROPERTY(type* name READ MAKE_GETTER_NAME(name) NOTIFY name##Changed) \ - \ - MEMBER(type*, name) \ - PTR_GETTER(type, name) \ - PTR_SETTER(type, name) \ - NOTIFIER(name) \ -private: - -#define C_PTR_PROPERTY(type, name) \ -protected: \ - Q_PROPERTY(type* name READ MAKE_GETTER_NAME(name) CONSTANT) \ - \ - MEMBER(type*, name) \ - PTR_GETTER(type, name) \ -private: - -#define W_PTR_PROPERTY_DEFAULT(type, name, defaultValue) \ -protected: \ - Q_PROPERTY(type* name READ MAKE_GETTER_NAME(name) WRITE set_##name NOTIFY name##Changed) \ - \ - MEMBER_DEFAULT(type*, name, defaultValue) \ - PTR_GETTER(type, name) \ - PTR_SETTER(type, name) \ - NOTIFIER(name) \ -private: - -#define UNIQUE_PTR_PROPERTY(type, name) \ -protected: \ - Q_PROPERTY(type* name READ name NOTIFY name##Changed) \ - \ - MEMBER(std::unique_ptr, name) \ - SMART_PTR_GETTER(type, name) \ - SMART_PTR_SETTER(std::unique_ptr&, name) \ - NOTIFIER(name) \ -private: - -#define UNIQUE_PTR_PROPERTY_INIT(type, name) \ -protected: \ - Q_PROPERTY(type* name READ name NOTIFY name##Changed) \ - \ - MEMBER_DEFAULT(std::unique_ptr, name, std::make_unique()) \ - SMART_PTR_GETTER(type, name) \ - SMART_PTR_SETTER(std::unique_ptr&, name) \ - NOTIFIER(name) \ -private: - -#define SHARED_PTR_PROPERTY(type, name) \ -protected: \ - Q_PROPERTY(type* name READ name NOTIFY name##Changed) \ - \ - MEMBER(std::shared_ptr, name) \ - SMART_PTR_GETTER(type, name) \ - SMART_PTR_SETTER(std::unique_ptr&, name) \ - NOTIFIER(name) \ -private: - -#define SHARED_PTR_PROPERTY_INIT(type, name) \ -protected: \ - Q_PROPERTY(type* name READ name NOTIFY name##Changed) \ - \ - MEMBER_DEFAULT(std::shared_ptr, name, std::make_shared()) \ - SMART_PTR_GETTER(type, name) \ - SMART_PTR_SETTER(std::shared_ptr, name) \ - NOTIFIER(name) \ -private: - -class _QmlPtrProperty_ : public QObject { - Q_OBJECT - - W_PTR_PROPERTY(int, var1) - R_PTR_PROPERTY(bool, var2) - C_PTR_PROPERTY(QString, test) - - // W_PTR_PROPERTY_DEFAULT(QString, var4, nullptr) - - // UNIQUE_PTR_PROPERTY(QString, test2) - // UNIQUE_PTR_PROPERTY_INIT(QString, test3) - - // SHARED_PTR_PROPERTY(QString, test4) - // SHARED_PTR_PROPERTY_INIT(QString, test5) -}; diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/SingletonHelper.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/SingletonHelper.h deleted file mode 100644 index 1b58691e..00000000 --- a/ScreenPlayUtil/inc/public/ScreenPlayUtil/SingletonHelper.h +++ /dev/null @@ -1,31 +0,0 @@ -#pragma once - -#include -#include -#include -#include - -#define QML_SINGLETON_IMPL(CLASS) \ -public: \ - static CLASS& instance() \ - { \ - static CLASS ret; \ - return ret; \ - } \ - static QObject* qmlSingletonFactory(QQmlEngine* qmlEngine, QJSEngine* jsEngine) \ - { \ - Q_UNUSED(jsEngine) \ - Q_UNUSED(qmlEngine) \ - QObject* ret = &instance(); \ - QQmlEngine::setObjectOwnership(ret, QQmlEngine::CppOwnership); \ - return ret; \ - } \ - static void registerQmlModule(const char* uri, const int majorVersion, const int minorVersion, const char* name) \ - { \ - qmlRegisterSingletonType(uri, majorVersion, minorVersion, name, &CLASS::qmlSingletonFactory); \ - } - -class _test_QmlSingleton_ : public QObject { - Q_OBJECT - QML_SINGLETON_IMPL(_test_QmlSingleton_) -}; diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/archive.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/archive.h new file mode 100644 index 00000000..0b578491 --- /dev/null +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/archive.h @@ -0,0 +1,30 @@ +#pragma once +#include +#include + +#include "qarchive_enums.hpp" +#include "qarchivediskcompressor.hpp" +#include "qarchivediskextractor.hpp" + +namespace ScreenPlay { + +class Archive : public QObject { + Q_OBJECT + QML_ELEMENT +public: + explicit Archive(QObject* parent = nullptr); + + Q_INVOKABLE bool importProject(QString archivePath, QString extractionPath); + Q_INVOKABLE bool exportProject(QString contentPath, QString exportFileName); + +signals: + void extractionProgressChanged(QString file, int proc, int total, qint64 br, qint64 bt); + void extractionFinished(); + void compressionProgressChanged(QString file, int proc, int total, qint64 br, qint64 bt); + void compressionFinished(); + +private: + std::unique_ptr m_compressor; + std::unique_ptr m_extractor; +}; +} diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/contenttypes.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/contenttypes.h index 286108e4..e0f45d44 100644 --- a/ScreenPlayUtil/inc/public/ScreenPlayUtil/contenttypes.h +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/contenttypes.h @@ -2,16 +2,23 @@ #pragma once #include +#include #include -namespace ScreenPlay { -/*! - \namespace ScreenPlay::SearchType - \inmodule ScreenPlayUtil - \brief Global enum for search types. Used in the "Installed" tab. -*/ -namespace SearchType { - Q_NAMESPACE +// We must package everything into a class for +// qml to be able to have typed enums. Making +// qml enums unscoped as default was a mistake. +namespace ScreenPlay { + +class ContentTypes : public QObject { + Q_OBJECT + QML_ELEMENT + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + /*! + \brief Used in the "Installed" tab. + */ +public: + ContentTypes(QObject* parent = nullptr); enum class SearchType { All, Text, @@ -19,41 +26,14 @@ namespace SearchType { Wallpaper, Widget, }; - Q_ENUM_NS(SearchType) - -} -/*! - \namespace ScreenPlay::FillMode - \inmodule ScreenPlayUtil - \brief Global enum for fill mode. This is a c++ representation - of HTML fill modes. We use "_" instead of "-" for scale down, - because c++ forbids "-" in enum names. -*/ -namespace FillMode { - Q_NAMESPACE - - enum class FillMode { - Stretch, - Fill, - Contain, - Cover, - Scale_Down - }; - Q_ENUM_NS(FillMode) - -} -/*! - \namespace ScreenPlay::InstalledType - \inmodule ScreenPlayUtil - \brief When changing the enum, one also needs to change: - GlobalVariables::getAvailableWallpaper - GlobalVariables::getAvailableWidgets - Common/Util.js isWallpaper() and isWidget() - ScreenPlayWallpaper: BaseWindow::parseWallpaperType() -*/ -namespace InstalledType { - Q_NAMESPACE - + Q_ENUM(SearchType) + /*! + \brief When changing the enum, one also needs to change: + GlobalVariables::getAvailableWallpaper + GlobalVariables::getAvailableWidgets + Common/Util.js isWallpaper() and isWidget() + ScreenPlayWallpaper: BaseWindow::parseWallpaperType() + */ enum class InstalledType { Unknown, // Wallpaper @@ -67,21 +47,36 @@ namespace InstalledType { QMLWidget, HTMLWidget, }; - Q_ENUM_NS(InstalledType) + Q_ENUM(InstalledType) +}; -} +class Video : public QObject { + Q_OBJECT + QML_ELEMENT + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") +public: + Video(QObject* parent = nullptr); + /*! + \brief This is a c++ representation + of HTML fill modes. We use "_" instead of "-" for scale down, + because c++ forbids "-" in enum names. + */ + enum class FillMode { + Stretch, + Fill, + Contain, + Cover, + Scale_Down + }; + Q_ENUM(FillMode) -/*! - \namespace ScreenPlay::InstalledType - \inmodule ScreenPlayUtil - \brief When changing the enum, one also needs to change: - GlobalVariables::getAvailableWallpaper - GlobalVariables::getAvailableWidgets - Common/Util.js isWallpaper() and isWidget() - ScreenPlayWallpaper: BaseWindow::parseWallpaperType() -*/ -namespace VideoCodec { - Q_NAMESPACE + /*! + \brief When changing the enum, one also needs to change: + GlobalVariables::getAvailableWallpaper + GlobalVariables::getAvailableWidgets + Common/Util.js isWallpaper() and isWidget() + ScreenPlayWallpaper: BaseWindow::parseWallpaperType() + */ enum class VideoCodec { Unknown, @@ -91,6 +86,6 @@ namespace VideoCodec { H264, H265 }; - Q_ENUM_NS(VideoCodec) -} + Q_ENUM(VideoCodec) +}; } diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/exitcodes.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/exitcodes.h index 9a3e5c76..572ec041 100644 --- a/ScreenPlayUtil/inc/public/ScreenPlayUtil/exitcodes.h +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/exitcodes.h @@ -1,20 +1,28 @@ #pragma once +#include +#include + namespace ScreenPlay { -Q_NAMESPACE - -enum class WallpaperExitCode { - Ok = 0, - Invalid_ArgumentSize, - Invalid_ActiveScreensList, - Invalid_InstalledType, - Invalid_CheckWallpaperVisible, - Invalid_Volume, - Invalid_AppID, - Invalid_Setup_ProjectParsingError, - Invalid_Setup_Error, - Invalid_Start_Windows_HandleError, +class WallpaperExit : public QObject { + Q_OBJECT + QML_ELEMENT + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") +public: + WallpaperExit(QObject* parent = nullptr); + enum class Code { + Ok = 0, + Invalid_ArgumentSize, + Invalid_ActiveScreensList, + Invalid_InstalledType, + Invalid_CheckWallpaperVisible, + Invalid_Volume, + Invalid_AppID, + Invalid_Setup_ProjectParsingError, + Invalid_Setup_Error, + Invalid_Start_Windows_HandleError, + }; + Q_ENUM(Code) }; -Q_ENUM_NS(WallpaperExitCode) -} \ No newline at end of file +} diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/logginghandler.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/logginghandler.h new file mode 100644 index 00000000..403a4d12 --- /dev/null +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/logginghandler.h @@ -0,0 +1,36 @@ +#pragma once +#include +#include +#include +#include + +namespace ScreenPlayUtil { +class LoggingHandler : public QObject { + Q_OBJECT + +public: + explicit LoggingHandler(const QString& logFileName); + ~LoggingHandler() override; + +private: + static void start(); + static void stop(); + static std::mutex& logFileMutex(); + static QFile& logFile(); + static size_t& logFileCounter(); + static QString logLine(QtMsgType type, const QMessageLogContext& context, const QString& message); + static QString toString(QtMsgType type); + static QString extractFileName(const QMessageLogContext& context); + static QString extractFunction(const QMessageLogContext& context); + static void writeToConsole(QtMsgType type, const QMessageLogContext& context, const QString& message); + static void writeToFile(const QString& line); + static void checkLogRotation(); + static void loggingMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message); + +private: + // When increasing the allowed file size, the code that selects the correct log file must be adjusted. + // Otherwise already completed log files of the day will be expanded. + static constexpr qint64 m_maxFileSize = 2000000000; // 2GB + static QString m_logFileName; +}; +} diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/projectfile.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/projectfile.h index 97842218..ee129b9b 100644 --- a/ScreenPlayUtil/inc/public/ScreenPlayUtil/projectfile.h +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/projectfile.h @@ -44,13 +44,13 @@ struct ProjectFile { // Website Wallpaper QUrl url; // Video Wallpaper - ScreenPlay::VideoCodec::VideoCodec videoCodec; + ScreenPlay::Video::VideoCodec videoCodec; QVariant publishedFileID { 0 }; QStringList tags; - InstalledType::InstalledType type = InstalledType::InstalledType::Unknown; - SearchType::SearchType searchType = SearchType::SearchType::All; + ContentTypes::InstalledType type = ContentTypes::InstalledType::Unknown; + ContentTypes::SearchType searchType = ContentTypes::SearchType::All; bool isNew = false; bool containsAudio = false; QDateTime lastModified; diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/steamenumsgenerated.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/steamenumsgenerated.h new file mode 100644 index 00000000..16174cc6 --- /dev/null +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/steamenumsgenerated.h @@ -0,0 +1,2181 @@ +// GENERATED FILE DO NOT EDIT +// TO REGENERATE run ScreenPlayInternal\SteamSDK +// > python.exe updateEnums.py + +#pragma once +#include +#include + +namespace ScreenPlay { + +class Steam : public QObject { + Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("") + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +public: + explicit Steam(); + + enum class ESteamIPType { + K_ESteamIPTypeIPv4 = 0, + K_ESteamIPTypeIPv6 = 1, + }; + Q_ENUM(ESteamIPType) + + enum class EUniverse { + K_EUniverseInvalid = 0, + K_EUniversePublic = 1, + K_EUniverseBeta = 2, + K_EUniverseInternal = 3, + K_EUniverseDev = 4, + K_EUniverseMax = 5, + }; + Q_ENUM(EUniverse) + + enum class EResult { + K_EResultNone = 0, + K_EResultOK = 1, + K_EResultFail = 2, + K_EResultNoConnection = 3, + K_EResultInvalidPassword = 5, + K_EResultLoggedInElsewhere = 6, + K_EResultInvalidProtocolVer = 7, + K_EResultInvalidParam = 8, + K_EResultFileNotFound = 9, + K_EResultBusy = 10, + K_EResultInvalidState = 11, + K_EResultInvalidName = 12, + K_EResultInvalidEmail = 13, + K_EResultDuplicateName = 14, + K_EResultAccessDenied = 15, + K_EResultTimeout = 16, + K_EResultBanned = 17, + K_EResultAccountNotFound = 18, + K_EResultInvalidSteamID = 19, + K_EResultServiceUnavailable = 20, + K_EResultNotLoggedOn = 21, + K_EResultPending = 22, + K_EResultEncryptionFailure = 23, + K_EResultInsufficientPrivilege = 24, + K_EResultLimitExceeded = 25, + K_EResultRevoked = 26, + K_EResultExpired = 27, + K_EResultAlreadyRedeemed = 28, + K_EResultDuplicateRequest = 29, + K_EResultAlreadyOwned = 30, + K_EResultIPNotFound = 31, + K_EResultPersistFailed = 32, + K_EResultLockingFailed = 33, + K_EResultLogonSessionReplaced = 34, + K_EResultConnectFailed = 35, + K_EResultHandshakeFailed = 36, + K_EResultIOFailure = 37, + K_EResultRemoteDisconnect = 38, + K_EResultShoppingCartNotFound = 39, + K_EResultBlocked = 40, + K_EResultIgnored = 41, + K_EResultNoMatch = 42, + K_EResultAccountDisabled = 43, + K_EResultServiceReadOnly = 44, + K_EResultAccountNotFeatured = 45, + K_EResultAdministratorOK = 46, + K_EResultContentVersion = 47, + K_EResultTryAnotherCM = 48, + K_EResultPasswordRequiredToKickSession = 49, + K_EResultAlreadyLoggedInElsewhere = 50, + K_EResultSuspended = 51, + K_EResultCancelled = 52, + K_EResultDataCorruption = 53, + K_EResultDiskFull = 54, + K_EResultRemoteCallFailed = 55, + K_EResultPasswordUnset = 56, + K_EResultExternalAccountUnlinked = 57, + K_EResultPSNTicketInvalid = 58, + K_EResultExternalAccountAlreadyLinked = 59, + K_EResultRemoteFileConflict = 60, + K_EResultIllegalPassword = 61, + K_EResultSameAsPreviousValue = 62, + K_EResultAccountLogonDenied = 63, + K_EResultCannotUseOldPassword = 64, + K_EResultInvalidLoginAuthCode = 65, + K_EResultAccountLogonDeniedNoMail = 66, + K_EResultHardwareNotCapableOfIPT = 67, + K_EResultIPTInitError = 68, + K_EResultParentalControlRestricted = 69, + K_EResultFacebookQueryError = 70, + K_EResultExpiredLoginAuthCode = 71, + K_EResultIPLoginRestrictionFailed = 72, + K_EResultAccountLockedDown = 73, + K_EResultAccountLogonDeniedVerifiedEmailRequired = 74, + K_EResultNoMatchingURL = 75, + K_EResultBadResponse = 76, + K_EResultRequirePasswordReEntry = 77, + K_EResultValueOutOfRange = 78, + K_EResultUnexpectedError = 79, + K_EResultDisabled = 80, + K_EResultInvalidCEGSubmission = 81, + K_EResultRestrictedDevice = 82, + K_EResultRegionLocked = 83, + K_EResultRateLimitExceeded = 84, + K_EResultAccountLoginDeniedNeedTwoFactor = 85, + K_EResultItemDeleted = 86, + K_EResultAccountLoginDeniedThrottle = 87, + K_EResultTwoFactorCodeMismatch = 88, + K_EResultTwoFactorActivationCodeMismatch = 89, + K_EResultAccountAssociatedToMultiplePartners = 90, + K_EResultNotModified = 91, + K_EResultNoMobileDevice = 92, + K_EResultTimeNotSynced = 93, + K_EResultSmsCodeFailed = 94, + K_EResultAccountLimitExceeded = 95, + K_EResultAccountActivityLimitExceeded = 96, + K_EResultPhoneActivityLimitExceeded = 97, + K_EResultRefundToWallet = 98, + K_EResultEmailSendFailure = 99, + K_EResultNotSettled = 100, + K_EResultNeedCaptcha = 101, + K_EResultGSLTDenied = 102, + K_EResultGSOwnerDenied = 103, + K_EResultInvalidItemType = 104, + K_EResultIPBanned = 105, + K_EResultGSLTExpired = 106, + K_EResultInsufficientFunds = 107, + K_EResultTooManyPending = 108, + K_EResultNoSiteLicensesFound = 109, + K_EResultWGNetworkSendExceeded = 110, + K_EResultAccountNotFriends = 111, + K_EResultLimitedUserAccount = 112, + K_EResultCantRemoveItem = 113, + K_EResultAccountDeleted = 114, + K_EResultExistingUserCancelledLicense = 115, + K_EResultCommunityCooldown = 116, + K_EResultNoLauncherSpecified = 117, + K_EResultMustAgreeToSSA = 118, + K_EResultLauncherMigrated = 119, + K_EResultSteamRealmMismatch = 120, + K_EResultInvalidSignature = 121, + K_EResultParseFailure = 122, + K_EResultNoVerifiedPhone = 123, + K_EResultInsufficientBattery = 124, + K_EResultChargerRequired = 125, + K_EResultCachedCredentialInvalid = 126, + K_EResultPhoneNumberIsVOIP = 127, + }; + Q_ENUM(EResult) + + enum class EVoiceResult { + K_EVoiceResultOK = 0, + K_EVoiceResultNotInitialized = 1, + K_EVoiceResultNotRecording = 2, + K_EVoiceResultNoData = 3, + K_EVoiceResultBufferTooSmall = 4, + K_EVoiceResultDataCorrupted = 5, + K_EVoiceResultRestricted = 6, + K_EVoiceResultUnsupportedCodec = 7, + K_EVoiceResultReceiverOutOfDate = 8, + K_EVoiceResultReceiverDidNotAnswer = 9, + }; + Q_ENUM(EVoiceResult) + + enum class EDenyReason { + K_EDenyInvalid = 0, + K_EDenyInvalidVersion = 1, + K_EDenyGeneric = 2, + K_EDenyNotLoggedOn = 3, + K_EDenyNoLicense = 4, + K_EDenyCheater = 5, + K_EDenyLoggedInElseWhere = 6, + K_EDenyUnknownText = 7, + K_EDenyIncompatibleAnticheat = 8, + K_EDenyMemoryCorruption = 9, + K_EDenyIncompatibleSoftware = 10, + K_EDenySteamConnectionLost = 11, + K_EDenySteamConnectionError = 12, + K_EDenySteamResponseTimedOut = 13, + K_EDenySteamValidationStalled = 14, + K_EDenySteamOwnerLeftGuestUser = 15, + }; + Q_ENUM(EDenyReason) + + enum class EBeginAuthSessionResult { + K_EBeginAuthSessionResultOK = 0, + K_EBeginAuthSessionResultInvalidTicket = 1, + K_EBeginAuthSessionResultDuplicateRequest = 2, + K_EBeginAuthSessionResultInvalidVersion = 3, + K_EBeginAuthSessionResultGameMismatch = 4, + K_EBeginAuthSessionResultExpiredTicket = 5, + }; + Q_ENUM(EBeginAuthSessionResult) + + enum class EAuthSessionResponse { + K_EAuthSessionResponseOK = 0, + K_EAuthSessionResponseUserNotConnectedToSteam = 1, + K_EAuthSessionResponseNoLicenseOrExpired = 2, + K_EAuthSessionResponseVACBanned = 3, + K_EAuthSessionResponseLoggedInElseWhere = 4, + K_EAuthSessionResponseVACCheckTimedOut = 5, + K_EAuthSessionResponseAuthTicketCanceled = 6, + K_EAuthSessionResponseAuthTicketInvalidAlreadyUsed = 7, + K_EAuthSessionResponseAuthTicketInvalid = 8, + K_EAuthSessionResponsePublisherIssuedBan = 9, + K_EAuthSessionResponseAuthTicketNetworkIdentityFailure = 10, + }; + Q_ENUM(EAuthSessionResponse) + + enum class EUserHasLicenseForAppResult { + K_EUserHasLicenseResultHasLicense = 0, + K_EUserHasLicenseResultDoesNotHaveLicense = 1, + K_EUserHasLicenseResultNoAuth = 2, + }; + Q_ENUM(EUserHasLicenseForAppResult) + + enum class EAccountType { + K_EAccountTypeInvalid = 0, + K_EAccountTypeIndividual = 1, + K_EAccountTypeMultiseat = 2, + K_EAccountTypeGameServer = 3, + K_EAccountTypeAnonGameServer = 4, + K_EAccountTypePending = 5, + K_EAccountTypeContentServer = 6, + K_EAccountTypeClan = 7, + K_EAccountTypeChat = 8, + K_EAccountTypeConsoleUser = 9, + K_EAccountTypeAnonUser = 10, + K_EAccountTypeMax = 11, + }; + Q_ENUM(EAccountType) + + enum class EChatEntryType { + K_EChatEntryTypeInvalid = 0, + K_EChatEntryTypeChatMsg = 1, + K_EChatEntryTypeTyping = 2, + K_EChatEntryTypeInviteGame = 3, + K_EChatEntryTypeEmote = 4, + K_EChatEntryTypeLeftConversation = 6, + K_EChatEntryTypeEntered = 7, + K_EChatEntryTypeWasKicked = 8, + K_EChatEntryTypeWasBanned = 9, + K_EChatEntryTypeDisconnected = 10, + K_EChatEntryTypeHistoricalChat = 11, + K_EChatEntryTypeLinkBlocked = 14, + }; + Q_ENUM(EChatEntryType) + + enum class EChatRoomEnterResponse { + K_EChatRoomEnterResponseSuccess = 1, + K_EChatRoomEnterResponseDoesntExist = 2, + K_EChatRoomEnterResponseNotAllowed = 3, + K_EChatRoomEnterResponseFull = 4, + K_EChatRoomEnterResponseError = 5, + K_EChatRoomEnterResponseBanned = 6, + K_EChatRoomEnterResponseLimited = 7, + K_EChatRoomEnterResponseClanDisabled = 8, + K_EChatRoomEnterResponseCommunityBan = 9, + K_EChatRoomEnterResponseMemberBlockedYou = 10, + K_EChatRoomEnterResponseYouBlockedMember = 11, + K_EChatRoomEnterResponseRatelimitExceeded = 15, + }; + Q_ENUM(EChatRoomEnterResponse) + + enum class EChatSteamIDInstanceFlags { + K_EChatAccountInstanceMask = 4095, + K_EChatInstanceFlagClan = 524288, + K_EChatInstanceFlagLobby = 262144, + K_EChatInstanceFlagMMSLobby = 131072, + }; + Q_ENUM(EChatSteamIDInstanceFlags) + + enum class ENotificationPosition { + K_EPositionInvalid = -1, + K_EPositionTopLeft = 0, + K_EPositionTopRight = 1, + K_EPositionBottomLeft = 2, + K_EPositionBottomRight = 3, + }; + Q_ENUM(ENotificationPosition) + + enum class EBroadcastUploadResult { + K_EBroadcastUploadResultNone = 0, + K_EBroadcastUploadResultOK = 1, + K_EBroadcastUploadResultInitFailed = 2, + K_EBroadcastUploadResultFrameFailed = 3, + K_EBroadcastUploadResultTimeout = 4, + K_EBroadcastUploadResultBandwidthExceeded = 5, + K_EBroadcastUploadResultLowFPS = 6, + K_EBroadcastUploadResultMissingKeyFrames = 7, + K_EBroadcastUploadResultNoConnection = 8, + K_EBroadcastUploadResultRelayFailed = 9, + K_EBroadcastUploadResultSettingsChanged = 10, + K_EBroadcastUploadResultMissingAudio = 11, + K_EBroadcastUploadResultTooFarBehind = 12, + K_EBroadcastUploadResultTranscodeBehind = 13, + K_EBroadcastUploadResultNotAllowedToPlay = 14, + K_EBroadcastUploadResultBusy = 15, + K_EBroadcastUploadResultBanned = 16, + K_EBroadcastUploadResultAlreadyActive = 17, + K_EBroadcastUploadResultForcedOff = 18, + K_EBroadcastUploadResultAudioBehind = 19, + K_EBroadcastUploadResultShutdown = 20, + K_EBroadcastUploadResultDisconnect = 21, + K_EBroadcastUploadResultVideoInitFailed = 22, + K_EBroadcastUploadResultAudioInitFailed = 23, + }; + Q_ENUM(EBroadcastUploadResult) + + enum class EMarketNotAllowedReasonFlags { + K_EMarketNotAllowedReason_None = 0, + K_EMarketNotAllowedReason_TemporaryFailure = 1, + K_EMarketNotAllowedReason_AccountDisabled = 2, + K_EMarketNotAllowedReason_AccountLockedDown = 4, + K_EMarketNotAllowedReason_AccountLimited = 8, + K_EMarketNotAllowedReason_TradeBanned = 16, + K_EMarketNotAllowedReason_AccountNotTrusted = 32, + K_EMarketNotAllowedReason_SteamGuardNotEnabled = 64, + K_EMarketNotAllowedReason_SteamGuardOnlyRecentlyEnabled = 128, + K_EMarketNotAllowedReason_RecentPasswordReset = 256, + K_EMarketNotAllowedReason_NewPaymentMethod = 512, + K_EMarketNotAllowedReason_InvalidCookie = 1024, + K_EMarketNotAllowedReason_UsingNewDevice = 2048, + K_EMarketNotAllowedReason_RecentSelfRefund = 4096, + K_EMarketNotAllowedReason_NewPaymentMethodCannotBeVerified = 8192, + K_EMarketNotAllowedReason_NoRecentPurchases = 16384, + K_EMarketNotAllowedReason_AcceptedWalletGift = 32768, + }; + Q_ENUM(EMarketNotAllowedReasonFlags) + + enum class EDurationControlProgress { + K_EDurationControlProgress_Full = 0, + K_EDurationControlProgress_Half = 1, + K_EDurationControlProgress_None = 2, + K_EDurationControl_ExitSoon_3h = 3, + K_EDurationControl_ExitSoon_5h = 4, + K_EDurationControl_ExitSoon_Night = 5, + }; + Q_ENUM(EDurationControlProgress) + + enum class EDurationControlNotification { + K_EDurationControlNotification_None = 0, + K_EDurationControlNotification_1Hour = 1, + K_EDurationControlNotification_3Hours = 2, + K_EDurationControlNotification_HalfProgress = 3, + K_EDurationControlNotification_NoProgress = 4, + K_EDurationControlNotification_ExitSoon_3h = 5, + K_EDurationControlNotification_ExitSoon_5h = 6, + K_EDurationControlNotification_ExitSoon_Night = 7, + }; + Q_ENUM(EDurationControlNotification) + + enum class EDurationControlOnlineState { + K_EDurationControlOnlineState_Invalid = 0, + K_EDurationControlOnlineState_Offline = 1, + K_EDurationControlOnlineState_Online = 2, + K_EDurationControlOnlineState_OnlineHighPri = 3, + }; + Q_ENUM(EDurationControlOnlineState) + + enum class EGameSearchErrorCode_t { + K_EGameSearchErrorCode_OK = 1, + K_EGameSearchErrorCode_Failed_Search_Already_In_Progress = 2, + K_EGameSearchErrorCode_Failed_No_Search_In_Progress = 3, + K_EGameSearchErrorCode_Failed_Not_Lobby_Leader = 4, + K_EGameSearchErrorCode_Failed_No_Host_Available = 5, + K_EGameSearchErrorCode_Failed_Search_Params_Invalid = 6, + K_EGameSearchErrorCode_Failed_Offline = 7, + K_EGameSearchErrorCode_Failed_NotAuthorized = 8, + K_EGameSearchErrorCode_Failed_Unknown_Error = 9, + }; + Q_ENUM(EGameSearchErrorCode_t) + + enum class EPlayerResult_t { + K_EPlayerResultFailedToConnect = 1, + K_EPlayerResultAbandoned = 2, + K_EPlayerResultKicked = 3, + K_EPlayerResultIncomplete = 4, + K_EPlayerResultCompleted = 5, + }; + Q_ENUM(EPlayerResult_t) + + enum class ESteamIPv6ConnectivityProtocol { + K_ESteamIPv6ConnectivityProtocol_Invalid = 0, + K_ESteamIPv6ConnectivityProtocol_HTTP = 1, + K_ESteamIPv6ConnectivityProtocol_UDP = 2, + }; + Q_ENUM(ESteamIPv6ConnectivityProtocol) + + enum class ESteamIPv6ConnectivityState { + K_ESteamIPv6ConnectivityState_Unknown = 0, + K_ESteamIPv6ConnectivityState_Good = 1, + K_ESteamIPv6ConnectivityState_Bad = 2, + }; + Q_ENUM(ESteamIPv6ConnectivityState) + + enum class EFriendRelationship { + K_EFriendRelationshipNone = 0, + K_EFriendRelationshipBlocked = 1, + K_EFriendRelationshipRequestRecipient = 2, + K_EFriendRelationshipFriend = 3, + K_EFriendRelationshipRequestInitiator = 4, + K_EFriendRelationshipIgnored = 5, + K_EFriendRelationshipIgnoredFriend = 6, + K_EFriendRelationshipSuggested_DEPRECATED = 7, + K_EFriendRelationshipMax = 8, + }; + Q_ENUM(EFriendRelationship) + + enum class EPersonaState { + K_EPersonaStateOffline = 0, + K_EPersonaStateOnline = 1, + K_EPersonaStateBusy = 2, + K_EPersonaStateAway = 3, + K_EPersonaStateSnooze = 4, + K_EPersonaStateLookingToTrade = 5, + K_EPersonaStateLookingToPlay = 6, + K_EPersonaStateInvisible = 7, + K_EPersonaStateMax = 8, + }; + Q_ENUM(EPersonaState) + + enum class EFriendFlags { + K_EFriendFlagNone = 0, + K_EFriendFlagBlocked = 1, + K_EFriendFlagFriendshipRequested = 2, + K_EFriendFlagImmediate = 4, + K_EFriendFlagClanMember = 8, + K_EFriendFlagOnGameServer = 16, + K_EFriendFlagRequestingFriendship = 128, + K_EFriendFlagRequestingInfo = 256, + K_EFriendFlagIgnored = 512, + K_EFriendFlagIgnoredFriend = 1024, + K_EFriendFlagChatMember = 4096, + K_EFriendFlagAll = 65535, + }; + Q_ENUM(EFriendFlags) + + enum class EUserRestriction { + K_nUserRestrictionNone = 0, + K_nUserRestrictionUnknown = 1, + K_nUserRestrictionAnyChat = 2, + K_nUserRestrictionVoiceChat = 4, + K_nUserRestrictionGroupChat = 8, + K_nUserRestrictionRating = 16, + K_nUserRestrictionGameInvites = 32, + K_nUserRestrictionTrading = 64, + }; + Q_ENUM(EUserRestriction) + + enum class EOverlayToStoreFlag { + K_EOverlayToStoreFlag_None = 0, + K_EOverlayToStoreFlag_AddToCart = 1, + K_EOverlayToStoreFlag_AddToCartAndShow = 2, + }; + Q_ENUM(EOverlayToStoreFlag) + + enum class EActivateGameOverlayToWebPageMode { + K_EActivateGameOverlayToWebPageMode_Default = 0, + K_EActivateGameOverlayToWebPageMode_Modal = 1, + }; + Q_ENUM(EActivateGameOverlayToWebPageMode) + + enum class ECommunityProfileItemType { + K_ECommunityProfileItemType_AnimatedAvatar = 0, + K_ECommunityProfileItemType_AvatarFrame = 1, + K_ECommunityProfileItemType_ProfileModifier = 2, + K_ECommunityProfileItemType_ProfileBackground = 3, + K_ECommunityProfileItemType_MiniProfileBackground = 4, + }; + Q_ENUM(ECommunityProfileItemType) + + enum class ECommunityProfileItemProperty { + K_ECommunityProfileItemProperty_ImageSmall = 0, + K_ECommunityProfileItemProperty_ImageLarge = 1, + K_ECommunityProfileItemProperty_InternalName = 2, + K_ECommunityProfileItemProperty_Title = 3, + K_ECommunityProfileItemProperty_Description = 4, + K_ECommunityProfileItemProperty_AppID = 5, + K_ECommunityProfileItemProperty_TypeID = 6, + K_ECommunityProfileItemProperty_Class = 7, + K_ECommunityProfileItemProperty_MovieWebM = 8, + K_ECommunityProfileItemProperty_MovieMP4 = 9, + K_ECommunityProfileItemProperty_MovieWebMSmall = 10, + K_ECommunityProfileItemProperty_MovieMP4Small = 11, + }; + Q_ENUM(ECommunityProfileItemProperty) + + enum class EPersonaChange { + K_EPersonaChangeName = 1, + K_EPersonaChangeStatus = 2, + K_EPersonaChangeComeOnline = 4, + K_EPersonaChangeGoneOffline = 8, + K_EPersonaChangeGamePlayed = 16, + K_EPersonaChangeGameServer = 32, + K_EPersonaChangeAvatar = 64, + K_EPersonaChangeJoinedSource = 128, + K_EPersonaChangeLeftSource = 256, + K_EPersonaChangeRelationshipChanged = 512, + K_EPersonaChangeNameFirstSet = 1024, + K_EPersonaChangeBroadcast = 2048, + K_EPersonaChangeNickname = 4096, + K_EPersonaChangeSteamLevel = 8192, + K_EPersonaChangeRichPresence = 16384, + }; + Q_ENUM(EPersonaChange) + + enum class ESteamAPICallFailure { + K_ESteamAPICallFailureNone = -1, + K_ESteamAPICallFailureSteamGone = 0, + K_ESteamAPICallFailureNetworkFailure = 1, + K_ESteamAPICallFailureInvalidHandle = 2, + K_ESteamAPICallFailureMismatchedCallback = 3, + }; + Q_ENUM(ESteamAPICallFailure) + + enum class EGamepadTextInputMode { + K_EGamepadTextInputModeNormal = 0, + K_EGamepadTextInputModePassword = 1, + }; + Q_ENUM(EGamepadTextInputMode) + + enum class EGamepadTextInputLineMode { + K_EGamepadTextInputLineModeSingleLine = 0, + K_EGamepadTextInputLineModeMultipleLines = 1, + }; + Q_ENUM(EGamepadTextInputLineMode) + + enum class EFloatingGamepadTextInputMode { + K_EFloatingGamepadTextInputModeModeSingleLine = 0, + K_EFloatingGamepadTextInputModeModeMultipleLines = 1, + K_EFloatingGamepadTextInputModeModeEmail = 2, + K_EFloatingGamepadTextInputModeModeNumeric = 3, + }; + Q_ENUM(EFloatingGamepadTextInputMode) + + enum class ETextFilteringContext { + K_ETextFilteringContextUnknown = 0, + K_ETextFilteringContextGameContent = 1, + K_ETextFilteringContextChat = 2, + K_ETextFilteringContextName = 3, + }; + Q_ENUM(ETextFilteringContext) + + enum class ECheckFileSignature { + K_ECheckFileSignatureInvalidSignature = 0, + K_ECheckFileSignatureValidSignature = 1, + K_ECheckFileSignatureFileNotFound = 2, + K_ECheckFileSignatureNoSignaturesFoundForThisApp = 3, + K_ECheckFileSignatureNoSignaturesFoundForThisFile = 4, + }; + Q_ENUM(ECheckFileSignature) + + enum class EMatchMakingServerResponse { + EServerResponded = 0, + EServerFailedToRespond = 1, + ENoServersListedOnMasterServer = 2, + }; + Q_ENUM(EMatchMakingServerResponse) + + enum class ELobbyType { + K_ELobbyTypePrivate = 0, + K_ELobbyTypeFriendsOnly = 1, + K_ELobbyTypePublic = 2, + K_ELobbyTypeInvisible = 3, + K_ELobbyTypePrivateUnique = 4, + }; + Q_ENUM(ELobbyType) + + enum class ELobbyComparison { + K_ELobbyComparisonEqualToOrLessThan = -2, + K_ELobbyComparisonLessThan = -1, + K_ELobbyComparisonEqual = 0, + K_ELobbyComparisonGreaterThan = 1, + K_ELobbyComparisonEqualToOrGreaterThan = 2, + K_ELobbyComparisonNotEqual = 3, + }; + Q_ENUM(ELobbyComparison) + + enum class ELobbyDistanceFilter { + K_ELobbyDistanceFilterClose = 0, + K_ELobbyDistanceFilterDefault = 1, + K_ELobbyDistanceFilterFar = 2, + K_ELobbyDistanceFilterWorldwide = 3, + }; + Q_ENUM(ELobbyDistanceFilter) + + enum class EChatMemberStateChange { + K_EChatMemberStateChangeEntered = 1, + K_EChatMemberStateChangeLeft = 2, + K_EChatMemberStateChangeDisconnected = 4, + K_EChatMemberStateChangeKicked = 8, + K_EChatMemberStateChangeBanned = 16, + }; + Q_ENUM(EChatMemberStateChange) + + enum class ESteamPartyBeaconLocationType { + K_ESteamPartyBeaconLocationType_Invalid = 0, + K_ESteamPartyBeaconLocationType_ChatGroup = 1, + K_ESteamPartyBeaconLocationType_Max = 2, + }; + Q_ENUM(ESteamPartyBeaconLocationType) + + enum class ESteamPartyBeaconLocationData { + K_ESteamPartyBeaconLocationDataInvalid = 0, + K_ESteamPartyBeaconLocationDataName = 1, + K_ESteamPartyBeaconLocationDataIconURLSmall = 2, + K_ESteamPartyBeaconLocationDataIconURLMedium = 3, + K_ESteamPartyBeaconLocationDataIconURLLarge = 4, + }; + Q_ENUM(ESteamPartyBeaconLocationData) + + enum class ERemoteStoragePlatform { + K_ERemoteStoragePlatformNone = 0, + K_ERemoteStoragePlatformWindows = 1, + K_ERemoteStoragePlatformOSX = 2, + K_ERemoteStoragePlatformPS3 = 4, + K_ERemoteStoragePlatformLinux = 8, + K_ERemoteStoragePlatformSwitch = 16, + K_ERemoteStoragePlatformAndroid = 32, + K_ERemoteStoragePlatformIOS = 64, + K_ERemoteStoragePlatformAll = -1, + }; + Q_ENUM(ERemoteStoragePlatform) + + enum class ERemoteStoragePublishedFileVisibility { + K_ERemoteStoragePublishedFileVisibilityPublic = 0, + K_ERemoteStoragePublishedFileVisibilityFriendsOnly = 1, + K_ERemoteStoragePublishedFileVisibilityPrivate = 2, + K_ERemoteStoragePublishedFileVisibilityUnlisted = 3, + }; + Q_ENUM(ERemoteStoragePublishedFileVisibility) + + enum class EWorkshopFileType { + K_EWorkshopFileTypeFirst = 0, + K_EWorkshopFileTypeCommunity = 0, + K_EWorkshopFileTypeMicrotransaction = 1, + K_EWorkshopFileTypeCollection = 2, + K_EWorkshopFileTypeArt = 3, + K_EWorkshopFileTypeVideo = 4, + K_EWorkshopFileTypeScreenshot = 5, + K_EWorkshopFileTypeGame = 6, + K_EWorkshopFileTypeSoftware = 7, + K_EWorkshopFileTypeConcept = 8, + K_EWorkshopFileTypeWebGuide = 9, + K_EWorkshopFileTypeIntegratedGuide = 10, + K_EWorkshopFileTypeMerch = 11, + K_EWorkshopFileTypeControllerBinding = 12, + K_EWorkshopFileTypeSteamworksAccessInvite = 13, + K_EWorkshopFileTypeSteamVideo = 14, + K_EWorkshopFileTypeGameManagedItem = 15, + K_EWorkshopFileTypeMax = 16, + }; + Q_ENUM(EWorkshopFileType) + + enum class EWorkshopVote { + K_EWorkshopVoteUnvoted = 0, + K_EWorkshopVoteFor = 1, + K_EWorkshopVoteAgainst = 2, + K_EWorkshopVoteLater = 3, + }; + Q_ENUM(EWorkshopVote) + + enum class EWorkshopFileAction { + K_EWorkshopFileActionPlayed = 0, + K_EWorkshopFileActionCompleted = 1, + }; + Q_ENUM(EWorkshopFileAction) + + enum class EWorkshopEnumerationType { + K_EWorkshopEnumerationTypeRankedByVote = 0, + K_EWorkshopEnumerationTypeRecent = 1, + K_EWorkshopEnumerationTypeTrending = 2, + K_EWorkshopEnumerationTypeFavoritesOfFriends = 3, + K_EWorkshopEnumerationTypeVotedByFriends = 4, + K_EWorkshopEnumerationTypeContentByFriends = 5, + K_EWorkshopEnumerationTypeRecentFromFollowedUsers = 6, + }; + Q_ENUM(EWorkshopEnumerationType) + + enum class EWorkshopVideoProvider { + K_EWorkshopVideoProviderNone = 0, + K_EWorkshopVideoProviderYoutube = 1, + }; + Q_ENUM(EWorkshopVideoProvider) + + enum class EUGCReadAction { + K_EUGCRead_ContinueReadingUntilFinished = 0, + K_EUGCRead_ContinueReading = 1, + K_EUGCRead_Close = 2, + }; + Q_ENUM(EUGCReadAction) + + enum class ERemoteStorageLocalFileChange { + K_ERemoteStorageLocalFileChange_Invalid = 0, + K_ERemoteStorageLocalFileChange_FileUpdated = 1, + K_ERemoteStorageLocalFileChange_FileDeleted = 2, + }; + Q_ENUM(ERemoteStorageLocalFileChange) + + enum class ERemoteStorageFilePathType { + K_ERemoteStorageFilePathType_Invalid = 0, + K_ERemoteStorageFilePathType_Absolute = 1, + K_ERemoteStorageFilePathType_APIFilename = 2, + }; + Q_ENUM(ERemoteStorageFilePathType) + + enum class ELeaderboardDataRequest { + K_ELeaderboardDataRequestGlobal = 0, + K_ELeaderboardDataRequestGlobalAroundUser = 1, + K_ELeaderboardDataRequestFriends = 2, + K_ELeaderboardDataRequestUsers = 3, + }; + Q_ENUM(ELeaderboardDataRequest) + + enum class ELeaderboardSortMethod { + K_ELeaderboardSortMethodNone = 0, + K_ELeaderboardSortMethodAscending = 1, + K_ELeaderboardSortMethodDescending = 2, + }; + Q_ENUM(ELeaderboardSortMethod) + + enum class ELeaderboardDisplayType { + K_ELeaderboardDisplayTypeNone = 0, + K_ELeaderboardDisplayTypeNumeric = 1, + K_ELeaderboardDisplayTypeTimeSeconds = 2, + K_ELeaderboardDisplayTypeTimeMilliSeconds = 3, + }; + Q_ENUM(ELeaderboardDisplayType) + + enum class ELeaderboardUploadScoreMethod { + K_ELeaderboardUploadScoreMethodNone = 0, + K_ELeaderboardUploadScoreMethodKeepBest = 1, + K_ELeaderboardUploadScoreMethodForceUpdate = 2, + }; + Q_ENUM(ELeaderboardUploadScoreMethod) + + enum class EP2PSessionError { + K_EP2PSessionErrorNone = 0, + K_EP2PSessionErrorNoRightsToApp = 2, + K_EP2PSessionErrorTimeout = 4, + K_EP2PSessionErrorNotRunningApp_DELETED = 1, + K_EP2PSessionErrorDestinationNotLoggedIn_DELETED = 3, + K_EP2PSessionErrorMax = 5, + }; + Q_ENUM(EP2PSessionError) + + enum class EP2PSend { + K_EP2PSendUnreliable = 0, + K_EP2PSendUnreliableNoDelay = 1, + K_EP2PSendReliable = 2, + K_EP2PSendReliableWithBuffering = 3, + }; + Q_ENUM(EP2PSend) + + enum class ESNetSocketState { + K_ESNetSocketStateInvalid = 0, + K_ESNetSocketStateConnected = 1, + K_ESNetSocketStateInitiated = 10, + K_ESNetSocketStateLocalCandidatesFound = 11, + K_ESNetSocketStateReceivedRemoteCandidates = 12, + K_ESNetSocketStateChallengeHandshake = 15, + K_ESNetSocketStateDisconnecting = 21, + K_ESNetSocketStateLocalDisconnect = 22, + K_ESNetSocketStateTimeoutDuringConnect = 23, + K_ESNetSocketStateRemoteEndDisconnected = 24, + K_ESNetSocketStateConnectionBroken = 25, + }; + Q_ENUM(ESNetSocketState) + + enum class ESNetSocketConnectionType { + K_ESNetSocketConnectionTypeNotConnected = 0, + K_ESNetSocketConnectionTypeUDP = 1, + K_ESNetSocketConnectionTypeUDPRelay = 2, + }; + Q_ENUM(ESNetSocketConnectionType) + + enum class EVRScreenshotType { + K_EVRScreenshotType_None = 0, + K_EVRScreenshotType_Mono = 1, + K_EVRScreenshotType_Stereo = 2, + K_EVRScreenshotType_MonoCubemap = 3, + K_EVRScreenshotType_MonoPanorama = 4, + K_EVRScreenshotType_StereoPanorama = 5, + }; + Q_ENUM(EVRScreenshotType) + + enum class AudioPlayback_Status { + AudioPlayback_Undefined = 0, + AudioPlayback_Playing = 1, + AudioPlayback_Paused = 2, + AudioPlayback_Idle = 3, + }; + Q_ENUM(AudioPlayback_Status) + + enum class EHTTPMethod { + K_EHTTPMethodInvalid = 0, + K_EHTTPMethodGET = 1, + K_EHTTPMethodHEAD = 2, + K_EHTTPMethodPOST = 3, + K_EHTTPMethodPUT = 4, + K_EHTTPMethodDELETE = 5, + K_EHTTPMethodOPTIONS = 6, + K_EHTTPMethodPATCH = 7, + }; + Q_ENUM(EHTTPMethod) + + enum class EHTTPStatusCode { + K_EHTTPStatusCodeInvalid = 0, + K_EHTTPStatusCode100Continue = 100, + K_EHTTPStatusCode101SwitchingProtocols = 101, + K_EHTTPStatusCode200OK = 200, + K_EHTTPStatusCode201Created = 201, + K_EHTTPStatusCode202Accepted = 202, + K_EHTTPStatusCode203NonAuthoritative = 203, + K_EHTTPStatusCode204NoContent = 204, + K_EHTTPStatusCode205ResetContent = 205, + K_EHTTPStatusCode206PartialContent = 206, + K_EHTTPStatusCode300MultipleChoices = 300, + K_EHTTPStatusCode301MovedPermanently = 301, + K_EHTTPStatusCode302Found = 302, + K_EHTTPStatusCode303SeeOther = 303, + K_EHTTPStatusCode304NotModified = 304, + K_EHTTPStatusCode305UseProxy = 305, + K_EHTTPStatusCode307TemporaryRedirect = 307, + K_EHTTPStatusCode308PermanentRedirect = 308, + K_EHTTPStatusCode400BadRequest = 400, + K_EHTTPStatusCode401Unauthorized = 401, + K_EHTTPStatusCode402PaymentRequired = 402, + K_EHTTPStatusCode403Forbidden = 403, + K_EHTTPStatusCode404NotFound = 404, + K_EHTTPStatusCode405MethodNotAllowed = 405, + K_EHTTPStatusCode406NotAcceptable = 406, + K_EHTTPStatusCode407ProxyAuthRequired = 407, + K_EHTTPStatusCode408RequestTimeout = 408, + K_EHTTPStatusCode409Conflict = 409, + K_EHTTPStatusCode410Gone = 410, + K_EHTTPStatusCode411LengthRequired = 411, + K_EHTTPStatusCode412PreconditionFailed = 412, + K_EHTTPStatusCode413RequestEntityTooLarge = 413, + K_EHTTPStatusCode414RequestURITooLong = 414, + K_EHTTPStatusCode415UnsupportedMediaType = 415, + K_EHTTPStatusCode416RequestedRangeNotSatisfiable = 416, + K_EHTTPStatusCode417ExpectationFailed = 417, + K_EHTTPStatusCode4xxUnknown = 418, + K_EHTTPStatusCode429TooManyRequests = 429, + K_EHTTPStatusCode444ConnectionClosed = 444, + K_EHTTPStatusCode500InternalServerError = 500, + K_EHTTPStatusCode501NotImplemented = 501, + K_EHTTPStatusCode502BadGateway = 502, + K_EHTTPStatusCode503ServiceUnavailable = 503, + K_EHTTPStatusCode504GatewayTimeout = 504, + K_EHTTPStatusCode505HTTPVersionNotSupported = 505, + K_EHTTPStatusCode5xxUnknown = 599, + }; + Q_ENUM(EHTTPStatusCode) + + enum class EInputSourceMode { + K_EInputSourceMode_None = 0, + K_EInputSourceMode_Dpad = 1, + K_EInputSourceMode_Buttons = 2, + K_EInputSourceMode_FourButtons = 3, + K_EInputSourceMode_AbsoluteMouse = 4, + K_EInputSourceMode_RelativeMouse = 5, + K_EInputSourceMode_JoystickMove = 6, + K_EInputSourceMode_JoystickMouse = 7, + K_EInputSourceMode_JoystickCamera = 8, + K_EInputSourceMode_ScrollWheel = 9, + K_EInputSourceMode_Trigger = 10, + K_EInputSourceMode_TouchMenu = 11, + K_EInputSourceMode_MouseJoystick = 12, + K_EInputSourceMode_MouseRegion = 13, + K_EInputSourceMode_RadialMenu = 14, + K_EInputSourceMode_SingleButton = 15, + K_EInputSourceMode_Switches = 16, + }; + Q_ENUM(EInputSourceMode) + + enum class EInputActionOrigin { + K_EInputActionOrigin_None = 0, + K_EInputActionOrigin_SteamController_A = 1, + K_EInputActionOrigin_SteamController_B = 2, + K_EInputActionOrigin_SteamController_X = 3, + K_EInputActionOrigin_SteamController_Y = 4, + K_EInputActionOrigin_SteamController_LeftBumper = 5, + K_EInputActionOrigin_SteamController_RightBumper = 6, + K_EInputActionOrigin_SteamController_LeftGrip = 7, + K_EInputActionOrigin_SteamController_RightGrip = 8, + K_EInputActionOrigin_SteamController_Start = 9, + K_EInputActionOrigin_SteamController_Back = 10, + K_EInputActionOrigin_SteamController_LeftPad_Touch = 11, + K_EInputActionOrigin_SteamController_LeftPad_Swipe = 12, + K_EInputActionOrigin_SteamController_LeftPad_Click = 13, + K_EInputActionOrigin_SteamController_LeftPad_DPadNorth = 14, + K_EInputActionOrigin_SteamController_LeftPad_DPadSouth = 15, + K_EInputActionOrigin_SteamController_LeftPad_DPadWest = 16, + K_EInputActionOrigin_SteamController_LeftPad_DPadEast = 17, + K_EInputActionOrigin_SteamController_RightPad_Touch = 18, + K_EInputActionOrigin_SteamController_RightPad_Swipe = 19, + K_EInputActionOrigin_SteamController_RightPad_Click = 20, + K_EInputActionOrigin_SteamController_RightPad_DPadNorth = 21, + K_EInputActionOrigin_SteamController_RightPad_DPadSouth = 22, + K_EInputActionOrigin_SteamController_RightPad_DPadWest = 23, + K_EInputActionOrigin_SteamController_RightPad_DPadEast = 24, + K_EInputActionOrigin_SteamController_LeftTrigger_Pull = 25, + K_EInputActionOrigin_SteamController_LeftTrigger_Click = 26, + K_EInputActionOrigin_SteamController_RightTrigger_Pull = 27, + K_EInputActionOrigin_SteamController_RightTrigger_Click = 28, + K_EInputActionOrigin_SteamController_LeftStick_Move = 29, + K_EInputActionOrigin_SteamController_LeftStick_Click = 30, + K_EInputActionOrigin_SteamController_LeftStick_DPadNorth = 31, + K_EInputActionOrigin_SteamController_LeftStick_DPadSouth = 32, + K_EInputActionOrigin_SteamController_LeftStick_DPadWest = 33, + K_EInputActionOrigin_SteamController_LeftStick_DPadEast = 34, + K_EInputActionOrigin_SteamController_Gyro_Move = 35, + K_EInputActionOrigin_SteamController_Gyro_Pitch = 36, + K_EInputActionOrigin_SteamController_Gyro_Yaw = 37, + K_EInputActionOrigin_SteamController_Gyro_Roll = 38, + K_EInputActionOrigin_SteamController_Reserved0 = 39, + K_EInputActionOrigin_SteamController_Reserved1 = 40, + K_EInputActionOrigin_SteamController_Reserved2 = 41, + K_EInputActionOrigin_SteamController_Reserved3 = 42, + K_EInputActionOrigin_SteamController_Reserved4 = 43, + K_EInputActionOrigin_SteamController_Reserved5 = 44, + K_EInputActionOrigin_SteamController_Reserved6 = 45, + K_EInputActionOrigin_SteamController_Reserved7 = 46, + K_EInputActionOrigin_SteamController_Reserved8 = 47, + K_EInputActionOrigin_SteamController_Reserved9 = 48, + K_EInputActionOrigin_SteamController_Reserved10 = 49, + K_EInputActionOrigin_PS4_X = 50, + K_EInputActionOrigin_PS4_Circle = 51, + K_EInputActionOrigin_PS4_Triangle = 52, + K_EInputActionOrigin_PS4_Square = 53, + K_EInputActionOrigin_PS4_LeftBumper = 54, + K_EInputActionOrigin_PS4_RightBumper = 55, + K_EInputActionOrigin_PS4_Options = 56, + K_EInputActionOrigin_PS4_Share = 57, + K_EInputActionOrigin_PS4_LeftPad_Touch = 58, + K_EInputActionOrigin_PS4_LeftPad_Swipe = 59, + K_EInputActionOrigin_PS4_LeftPad_Click = 60, + K_EInputActionOrigin_PS4_LeftPad_DPadNorth = 61, + K_EInputActionOrigin_PS4_LeftPad_DPadSouth = 62, + K_EInputActionOrigin_PS4_LeftPad_DPadWest = 63, + K_EInputActionOrigin_PS4_LeftPad_DPadEast = 64, + K_EInputActionOrigin_PS4_RightPad_Touch = 65, + K_EInputActionOrigin_PS4_RightPad_Swipe = 66, + K_EInputActionOrigin_PS4_RightPad_Click = 67, + K_EInputActionOrigin_PS4_RightPad_DPadNorth = 68, + K_EInputActionOrigin_PS4_RightPad_DPadSouth = 69, + K_EInputActionOrigin_PS4_RightPad_DPadWest = 70, + K_EInputActionOrigin_PS4_RightPad_DPadEast = 71, + K_EInputActionOrigin_PS4_CenterPad_Touch = 72, + K_EInputActionOrigin_PS4_CenterPad_Swipe = 73, + K_EInputActionOrigin_PS4_CenterPad_Click = 74, + K_EInputActionOrigin_PS4_CenterPad_DPadNorth = 75, + K_EInputActionOrigin_PS4_CenterPad_DPadSouth = 76, + K_EInputActionOrigin_PS4_CenterPad_DPadWest = 77, + K_EInputActionOrigin_PS4_CenterPad_DPadEast = 78, + K_EInputActionOrigin_PS4_LeftTrigger_Pull = 79, + K_EInputActionOrigin_PS4_LeftTrigger_Click = 80, + K_EInputActionOrigin_PS4_RightTrigger_Pull = 81, + K_EInputActionOrigin_PS4_RightTrigger_Click = 82, + K_EInputActionOrigin_PS4_LeftStick_Move = 83, + K_EInputActionOrigin_PS4_LeftStick_Click = 84, + K_EInputActionOrigin_PS4_LeftStick_DPadNorth = 85, + K_EInputActionOrigin_PS4_LeftStick_DPadSouth = 86, + K_EInputActionOrigin_PS4_LeftStick_DPadWest = 87, + K_EInputActionOrigin_PS4_LeftStick_DPadEast = 88, + K_EInputActionOrigin_PS4_RightStick_Move = 89, + K_EInputActionOrigin_PS4_RightStick_Click = 90, + K_EInputActionOrigin_PS4_RightStick_DPadNorth = 91, + K_EInputActionOrigin_PS4_RightStick_DPadSouth = 92, + K_EInputActionOrigin_PS4_RightStick_DPadWest = 93, + K_EInputActionOrigin_PS4_RightStick_DPadEast = 94, + K_EInputActionOrigin_PS4_DPad_North = 95, + K_EInputActionOrigin_PS4_DPad_South = 96, + K_EInputActionOrigin_PS4_DPad_West = 97, + K_EInputActionOrigin_PS4_DPad_East = 98, + K_EInputActionOrigin_PS4_Gyro_Move = 99, + K_EInputActionOrigin_PS4_Gyro_Pitch = 100, + K_EInputActionOrigin_PS4_Gyro_Yaw = 101, + K_EInputActionOrigin_PS4_Gyro_Roll = 102, + K_EInputActionOrigin_PS4_DPad_Move = 103, + K_EInputActionOrigin_PS4_Reserved1 = 104, + K_EInputActionOrigin_PS4_Reserved2 = 105, + K_EInputActionOrigin_PS4_Reserved3 = 106, + K_EInputActionOrigin_PS4_Reserved4 = 107, + K_EInputActionOrigin_PS4_Reserved5 = 108, + K_EInputActionOrigin_PS4_Reserved6 = 109, + K_EInputActionOrigin_PS4_Reserved7 = 110, + K_EInputActionOrigin_PS4_Reserved8 = 111, + K_EInputActionOrigin_PS4_Reserved9 = 112, + K_EInputActionOrigin_PS4_Reserved10 = 113, + K_EInputActionOrigin_XBoxOne_A = 114, + K_EInputActionOrigin_XBoxOne_B = 115, + K_EInputActionOrigin_XBoxOne_X = 116, + K_EInputActionOrigin_XBoxOne_Y = 117, + K_EInputActionOrigin_XBoxOne_LeftBumper = 118, + K_EInputActionOrigin_XBoxOne_RightBumper = 119, + K_EInputActionOrigin_XBoxOne_Menu = 120, + K_EInputActionOrigin_XBoxOne_View = 121, + K_EInputActionOrigin_XBoxOne_LeftTrigger_Pull = 122, + K_EInputActionOrigin_XBoxOne_LeftTrigger_Click = 123, + K_EInputActionOrigin_XBoxOne_RightTrigger_Pull = 124, + K_EInputActionOrigin_XBoxOne_RightTrigger_Click = 125, + K_EInputActionOrigin_XBoxOne_LeftStick_Move = 126, + K_EInputActionOrigin_XBoxOne_LeftStick_Click = 127, + K_EInputActionOrigin_XBoxOne_LeftStick_DPadNorth = 128, + K_EInputActionOrigin_XBoxOne_LeftStick_DPadSouth = 129, + K_EInputActionOrigin_XBoxOne_LeftStick_DPadWest = 130, + K_EInputActionOrigin_XBoxOne_LeftStick_DPadEast = 131, + K_EInputActionOrigin_XBoxOne_RightStick_Move = 132, + K_EInputActionOrigin_XBoxOne_RightStick_Click = 133, + K_EInputActionOrigin_XBoxOne_RightStick_DPadNorth = 134, + K_EInputActionOrigin_XBoxOne_RightStick_DPadSouth = 135, + K_EInputActionOrigin_XBoxOne_RightStick_DPadWest = 136, + K_EInputActionOrigin_XBoxOne_RightStick_DPadEast = 137, + K_EInputActionOrigin_XBoxOne_DPad_North = 138, + K_EInputActionOrigin_XBoxOne_DPad_South = 139, + K_EInputActionOrigin_XBoxOne_DPad_West = 140, + K_EInputActionOrigin_XBoxOne_DPad_East = 141, + K_EInputActionOrigin_XBoxOne_DPad_Move = 142, + K_EInputActionOrigin_XBoxOne_LeftGrip_Lower = 143, + K_EInputActionOrigin_XBoxOne_LeftGrip_Upper = 144, + K_EInputActionOrigin_XBoxOne_RightGrip_Lower = 145, + K_EInputActionOrigin_XBoxOne_RightGrip_Upper = 146, + K_EInputActionOrigin_XBoxOne_Share = 147, + K_EInputActionOrigin_XBoxOne_Reserved6 = 148, + K_EInputActionOrigin_XBoxOne_Reserved7 = 149, + K_EInputActionOrigin_XBoxOne_Reserved8 = 150, + K_EInputActionOrigin_XBoxOne_Reserved9 = 151, + K_EInputActionOrigin_XBoxOne_Reserved10 = 152, + K_EInputActionOrigin_XBox360_A = 153, + K_EInputActionOrigin_XBox360_B = 154, + K_EInputActionOrigin_XBox360_X = 155, + K_EInputActionOrigin_XBox360_Y = 156, + K_EInputActionOrigin_XBox360_LeftBumper = 157, + K_EInputActionOrigin_XBox360_RightBumper = 158, + K_EInputActionOrigin_XBox360_Start = 159, + K_EInputActionOrigin_XBox360_Back = 160, + K_EInputActionOrigin_XBox360_LeftTrigger_Pull = 161, + K_EInputActionOrigin_XBox360_LeftTrigger_Click = 162, + K_EInputActionOrigin_XBox360_RightTrigger_Pull = 163, + K_EInputActionOrigin_XBox360_RightTrigger_Click = 164, + K_EInputActionOrigin_XBox360_LeftStick_Move = 165, + K_EInputActionOrigin_XBox360_LeftStick_Click = 166, + K_EInputActionOrigin_XBox360_LeftStick_DPadNorth = 167, + K_EInputActionOrigin_XBox360_LeftStick_DPadSouth = 168, + K_EInputActionOrigin_XBox360_LeftStick_DPadWest = 169, + K_EInputActionOrigin_XBox360_LeftStick_DPadEast = 170, + K_EInputActionOrigin_XBox360_RightStick_Move = 171, + K_EInputActionOrigin_XBox360_RightStick_Click = 172, + K_EInputActionOrigin_XBox360_RightStick_DPadNorth = 173, + K_EInputActionOrigin_XBox360_RightStick_DPadSouth = 174, + K_EInputActionOrigin_XBox360_RightStick_DPadWest = 175, + K_EInputActionOrigin_XBox360_RightStick_DPadEast = 176, + K_EInputActionOrigin_XBox360_DPad_North = 177, + K_EInputActionOrigin_XBox360_DPad_South = 178, + K_EInputActionOrigin_XBox360_DPad_West = 179, + K_EInputActionOrigin_XBox360_DPad_East = 180, + K_EInputActionOrigin_XBox360_DPad_Move = 181, + K_EInputActionOrigin_XBox360_Reserved1 = 182, + K_EInputActionOrigin_XBox360_Reserved2 = 183, + K_EInputActionOrigin_XBox360_Reserved3 = 184, + K_EInputActionOrigin_XBox360_Reserved4 = 185, + K_EInputActionOrigin_XBox360_Reserved5 = 186, + K_EInputActionOrigin_XBox360_Reserved6 = 187, + K_EInputActionOrigin_XBox360_Reserved7 = 188, + K_EInputActionOrigin_XBox360_Reserved8 = 189, + K_EInputActionOrigin_XBox360_Reserved9 = 190, + K_EInputActionOrigin_XBox360_Reserved10 = 191, + K_EInputActionOrigin_Switch_A = 192, + K_EInputActionOrigin_Switch_B = 193, + K_EInputActionOrigin_Switch_X = 194, + K_EInputActionOrigin_Switch_Y = 195, + K_EInputActionOrigin_Switch_LeftBumper = 196, + K_EInputActionOrigin_Switch_RightBumper = 197, + K_EInputActionOrigin_Switch_Plus = 198, + K_EInputActionOrigin_Switch_Minus = 199, + K_EInputActionOrigin_Switch_Capture = 200, + K_EInputActionOrigin_Switch_LeftTrigger_Pull = 201, + K_EInputActionOrigin_Switch_LeftTrigger_Click = 202, + K_EInputActionOrigin_Switch_RightTrigger_Pull = 203, + K_EInputActionOrigin_Switch_RightTrigger_Click = 204, + K_EInputActionOrigin_Switch_LeftStick_Move = 205, + K_EInputActionOrigin_Switch_LeftStick_Click = 206, + K_EInputActionOrigin_Switch_LeftStick_DPadNorth = 207, + K_EInputActionOrigin_Switch_LeftStick_DPadSouth = 208, + K_EInputActionOrigin_Switch_LeftStick_DPadWest = 209, + K_EInputActionOrigin_Switch_LeftStick_DPadEast = 210, + K_EInputActionOrigin_Switch_RightStick_Move = 211, + K_EInputActionOrigin_Switch_RightStick_Click = 212, + K_EInputActionOrigin_Switch_RightStick_DPadNorth = 213, + K_EInputActionOrigin_Switch_RightStick_DPadSouth = 214, + K_EInputActionOrigin_Switch_RightStick_DPadWest = 215, + K_EInputActionOrigin_Switch_RightStick_DPadEast = 216, + K_EInputActionOrigin_Switch_DPad_North = 217, + K_EInputActionOrigin_Switch_DPad_South = 218, + K_EInputActionOrigin_Switch_DPad_West = 219, + K_EInputActionOrigin_Switch_DPad_East = 220, + K_EInputActionOrigin_Switch_ProGyro_Move = 221, + K_EInputActionOrigin_Switch_ProGyro_Pitch = 222, + K_EInputActionOrigin_Switch_ProGyro_Yaw = 223, + K_EInputActionOrigin_Switch_ProGyro_Roll = 224, + K_EInputActionOrigin_Switch_DPad_Move = 225, + K_EInputActionOrigin_Switch_Reserved1 = 226, + K_EInputActionOrigin_Switch_Reserved2 = 227, + K_EInputActionOrigin_Switch_Reserved3 = 228, + K_EInputActionOrigin_Switch_Reserved4 = 229, + K_EInputActionOrigin_Switch_Reserved5 = 230, + K_EInputActionOrigin_Switch_Reserved6 = 231, + K_EInputActionOrigin_Switch_Reserved7 = 232, + K_EInputActionOrigin_Switch_Reserved8 = 233, + K_EInputActionOrigin_Switch_Reserved9 = 234, + K_EInputActionOrigin_Switch_Reserved10 = 235, + K_EInputActionOrigin_Switch_RightGyro_Move = 236, + K_EInputActionOrigin_Switch_RightGyro_Pitch = 237, + K_EInputActionOrigin_Switch_RightGyro_Yaw = 238, + K_EInputActionOrigin_Switch_RightGyro_Roll = 239, + K_EInputActionOrigin_Switch_LeftGyro_Move = 240, + K_EInputActionOrigin_Switch_LeftGyro_Pitch = 241, + K_EInputActionOrigin_Switch_LeftGyro_Yaw = 242, + K_EInputActionOrigin_Switch_LeftGyro_Roll = 243, + K_EInputActionOrigin_Switch_LeftGrip_Lower = 244, + K_EInputActionOrigin_Switch_LeftGrip_Upper = 245, + K_EInputActionOrigin_Switch_RightGrip_Lower = 246, + K_EInputActionOrigin_Switch_RightGrip_Upper = 247, + K_EInputActionOrigin_Switch_JoyConButton_N = 248, + K_EInputActionOrigin_Switch_JoyConButton_E = 249, + K_EInputActionOrigin_Switch_JoyConButton_S = 250, + K_EInputActionOrigin_Switch_JoyConButton_W = 251, + K_EInputActionOrigin_Switch_Reserved15 = 252, + K_EInputActionOrigin_Switch_Reserved16 = 253, + K_EInputActionOrigin_Switch_Reserved17 = 254, + K_EInputActionOrigin_Switch_Reserved18 = 255, + K_EInputActionOrigin_Switch_Reserved19 = 256, + K_EInputActionOrigin_Switch_Reserved20 = 257, + K_EInputActionOrigin_PS5_X = 258, + K_EInputActionOrigin_PS5_Circle = 259, + K_EInputActionOrigin_PS5_Triangle = 260, + K_EInputActionOrigin_PS5_Square = 261, + K_EInputActionOrigin_PS5_LeftBumper = 262, + K_EInputActionOrigin_PS5_RightBumper = 263, + K_EInputActionOrigin_PS5_Option = 264, + K_EInputActionOrigin_PS5_Create = 265, + K_EInputActionOrigin_PS5_Mute = 266, + K_EInputActionOrigin_PS5_LeftPad_Touch = 267, + K_EInputActionOrigin_PS5_LeftPad_Swipe = 268, + K_EInputActionOrigin_PS5_LeftPad_Click = 269, + K_EInputActionOrigin_PS5_LeftPad_DPadNorth = 270, + K_EInputActionOrigin_PS5_LeftPad_DPadSouth = 271, + K_EInputActionOrigin_PS5_LeftPad_DPadWest = 272, + K_EInputActionOrigin_PS5_LeftPad_DPadEast = 273, + K_EInputActionOrigin_PS5_RightPad_Touch = 274, + K_EInputActionOrigin_PS5_RightPad_Swipe = 275, + K_EInputActionOrigin_PS5_RightPad_Click = 276, + K_EInputActionOrigin_PS5_RightPad_DPadNorth = 277, + K_EInputActionOrigin_PS5_RightPad_DPadSouth = 278, + K_EInputActionOrigin_PS5_RightPad_DPadWest = 279, + K_EInputActionOrigin_PS5_RightPad_DPadEast = 280, + K_EInputActionOrigin_PS5_CenterPad_Touch = 281, + K_EInputActionOrigin_PS5_CenterPad_Swipe = 282, + K_EInputActionOrigin_PS5_CenterPad_Click = 283, + K_EInputActionOrigin_PS5_CenterPad_DPadNorth = 284, + K_EInputActionOrigin_PS5_CenterPad_DPadSouth = 285, + K_EInputActionOrigin_PS5_CenterPad_DPadWest = 286, + K_EInputActionOrigin_PS5_CenterPad_DPadEast = 287, + K_EInputActionOrigin_PS5_LeftTrigger_Pull = 288, + K_EInputActionOrigin_PS5_LeftTrigger_Click = 289, + K_EInputActionOrigin_PS5_RightTrigger_Pull = 290, + K_EInputActionOrigin_PS5_RightTrigger_Click = 291, + K_EInputActionOrigin_PS5_LeftStick_Move = 292, + K_EInputActionOrigin_PS5_LeftStick_Click = 293, + K_EInputActionOrigin_PS5_LeftStick_DPadNorth = 294, + K_EInputActionOrigin_PS5_LeftStick_DPadSouth = 295, + K_EInputActionOrigin_PS5_LeftStick_DPadWest = 296, + K_EInputActionOrigin_PS5_LeftStick_DPadEast = 297, + K_EInputActionOrigin_PS5_RightStick_Move = 298, + K_EInputActionOrigin_PS5_RightStick_Click = 299, + K_EInputActionOrigin_PS5_RightStick_DPadNorth = 300, + K_EInputActionOrigin_PS5_RightStick_DPadSouth = 301, + K_EInputActionOrigin_PS5_RightStick_DPadWest = 302, + K_EInputActionOrigin_PS5_RightStick_DPadEast = 303, + K_EInputActionOrigin_PS5_DPad_North = 304, + K_EInputActionOrigin_PS5_DPad_South = 305, + K_EInputActionOrigin_PS5_DPad_West = 306, + K_EInputActionOrigin_PS5_DPad_East = 307, + K_EInputActionOrigin_PS5_Gyro_Move = 308, + K_EInputActionOrigin_PS5_Gyro_Pitch = 309, + K_EInputActionOrigin_PS5_Gyro_Yaw = 310, + K_EInputActionOrigin_PS5_Gyro_Roll = 311, + K_EInputActionOrigin_PS5_DPad_Move = 312, + K_EInputActionOrigin_PS5_LeftGrip = 313, + K_EInputActionOrigin_PS5_RightGrip = 314, + K_EInputActionOrigin_PS5_LeftFn = 315, + K_EInputActionOrigin_PS5_RightFn = 316, + K_EInputActionOrigin_PS5_Reserved5 = 317, + K_EInputActionOrigin_PS5_Reserved6 = 318, + K_EInputActionOrigin_PS5_Reserved7 = 319, + K_EInputActionOrigin_PS5_Reserved8 = 320, + K_EInputActionOrigin_PS5_Reserved9 = 321, + K_EInputActionOrigin_PS5_Reserved10 = 322, + K_EInputActionOrigin_PS5_Reserved11 = 323, + K_EInputActionOrigin_PS5_Reserved12 = 324, + K_EInputActionOrigin_PS5_Reserved13 = 325, + K_EInputActionOrigin_PS5_Reserved14 = 326, + K_EInputActionOrigin_PS5_Reserved15 = 327, + K_EInputActionOrigin_PS5_Reserved16 = 328, + K_EInputActionOrigin_PS5_Reserved17 = 329, + K_EInputActionOrigin_PS5_Reserved18 = 330, + K_EInputActionOrigin_PS5_Reserved19 = 331, + K_EInputActionOrigin_PS5_Reserved20 = 332, + K_EInputActionOrigin_SteamDeck_A = 333, + K_EInputActionOrigin_SteamDeck_B = 334, + K_EInputActionOrigin_SteamDeck_X = 335, + K_EInputActionOrigin_SteamDeck_Y = 336, + K_EInputActionOrigin_SteamDeck_L1 = 337, + K_EInputActionOrigin_SteamDeck_R1 = 338, + K_EInputActionOrigin_SteamDeck_Menu = 339, + K_EInputActionOrigin_SteamDeck_View = 340, + K_EInputActionOrigin_SteamDeck_LeftPad_Touch = 341, + K_EInputActionOrigin_SteamDeck_LeftPad_Swipe = 342, + K_EInputActionOrigin_SteamDeck_LeftPad_Click = 343, + K_EInputActionOrigin_SteamDeck_LeftPad_DPadNorth = 344, + K_EInputActionOrigin_SteamDeck_LeftPad_DPadSouth = 345, + K_EInputActionOrigin_SteamDeck_LeftPad_DPadWest = 346, + K_EInputActionOrigin_SteamDeck_LeftPad_DPadEast = 347, + K_EInputActionOrigin_SteamDeck_RightPad_Touch = 348, + K_EInputActionOrigin_SteamDeck_RightPad_Swipe = 349, + K_EInputActionOrigin_SteamDeck_RightPad_Click = 350, + K_EInputActionOrigin_SteamDeck_RightPad_DPadNorth = 351, + K_EInputActionOrigin_SteamDeck_RightPad_DPadSouth = 352, + K_EInputActionOrigin_SteamDeck_RightPad_DPadWest = 353, + K_EInputActionOrigin_SteamDeck_RightPad_DPadEast = 354, + K_EInputActionOrigin_SteamDeck_L2_SoftPull = 355, + K_EInputActionOrigin_SteamDeck_L2 = 356, + K_EInputActionOrigin_SteamDeck_R2_SoftPull = 357, + K_EInputActionOrigin_SteamDeck_R2 = 358, + K_EInputActionOrigin_SteamDeck_LeftStick_Move = 359, + K_EInputActionOrigin_SteamDeck_L3 = 360, + K_EInputActionOrigin_SteamDeck_LeftStick_DPadNorth = 361, + K_EInputActionOrigin_SteamDeck_LeftStick_DPadSouth = 362, + K_EInputActionOrigin_SteamDeck_LeftStick_DPadWest = 363, + K_EInputActionOrigin_SteamDeck_LeftStick_DPadEast = 364, + K_EInputActionOrigin_SteamDeck_LeftStick_Touch = 365, + K_EInputActionOrigin_SteamDeck_RightStick_Move = 366, + K_EInputActionOrigin_SteamDeck_R3 = 367, + K_EInputActionOrigin_SteamDeck_RightStick_DPadNorth = 368, + K_EInputActionOrigin_SteamDeck_RightStick_DPadSouth = 369, + K_EInputActionOrigin_SteamDeck_RightStick_DPadWest = 370, + K_EInputActionOrigin_SteamDeck_RightStick_DPadEast = 371, + K_EInputActionOrigin_SteamDeck_RightStick_Touch = 372, + K_EInputActionOrigin_SteamDeck_L4 = 373, + K_EInputActionOrigin_SteamDeck_R4 = 374, + K_EInputActionOrigin_SteamDeck_L5 = 375, + K_EInputActionOrigin_SteamDeck_R5 = 376, + K_EInputActionOrigin_SteamDeck_DPad_Move = 377, + K_EInputActionOrigin_SteamDeck_DPad_North = 378, + K_EInputActionOrigin_SteamDeck_DPad_South = 379, + K_EInputActionOrigin_SteamDeck_DPad_West = 380, + K_EInputActionOrigin_SteamDeck_DPad_East = 381, + K_EInputActionOrigin_SteamDeck_Gyro_Move = 382, + K_EInputActionOrigin_SteamDeck_Gyro_Pitch = 383, + K_EInputActionOrigin_SteamDeck_Gyro_Yaw = 384, + K_EInputActionOrigin_SteamDeck_Gyro_Roll = 385, + K_EInputActionOrigin_SteamDeck_Reserved1 = 386, + K_EInputActionOrigin_SteamDeck_Reserved2 = 387, + K_EInputActionOrigin_SteamDeck_Reserved3 = 388, + K_EInputActionOrigin_SteamDeck_Reserved4 = 389, + K_EInputActionOrigin_SteamDeck_Reserved5 = 390, + K_EInputActionOrigin_SteamDeck_Reserved6 = 391, + K_EInputActionOrigin_SteamDeck_Reserved7 = 392, + K_EInputActionOrigin_SteamDeck_Reserved8 = 393, + K_EInputActionOrigin_SteamDeck_Reserved9 = 394, + K_EInputActionOrigin_SteamDeck_Reserved10 = 395, + K_EInputActionOrigin_SteamDeck_Reserved11 = 396, + K_EInputActionOrigin_SteamDeck_Reserved12 = 397, + K_EInputActionOrigin_SteamDeck_Reserved13 = 398, + K_EInputActionOrigin_SteamDeck_Reserved14 = 399, + K_EInputActionOrigin_SteamDeck_Reserved15 = 400, + K_EInputActionOrigin_SteamDeck_Reserved16 = 401, + K_EInputActionOrigin_SteamDeck_Reserved17 = 402, + K_EInputActionOrigin_SteamDeck_Reserved18 = 403, + K_EInputActionOrigin_SteamDeck_Reserved19 = 404, + K_EInputActionOrigin_SteamDeck_Reserved20 = 405, + K_EInputActionOrigin_Count = 406, + K_EInputActionOrigin_MaximumPossibleValue = 32767, + }; + Q_ENUM(EInputActionOrigin) + + enum class EXboxOrigin { + K_EXboxOrigin_A = 0, + K_EXboxOrigin_B = 1, + K_EXboxOrigin_X = 2, + K_EXboxOrigin_Y = 3, + K_EXboxOrigin_LeftBumper = 4, + K_EXboxOrigin_RightBumper = 5, + K_EXboxOrigin_Menu = 6, + K_EXboxOrigin_View = 7, + K_EXboxOrigin_LeftTrigger_Pull = 8, + K_EXboxOrigin_LeftTrigger_Click = 9, + K_EXboxOrigin_RightTrigger_Pull = 10, + K_EXboxOrigin_RightTrigger_Click = 11, + K_EXboxOrigin_LeftStick_Move = 12, + K_EXboxOrigin_LeftStick_Click = 13, + K_EXboxOrigin_LeftStick_DPadNorth = 14, + K_EXboxOrigin_LeftStick_DPadSouth = 15, + K_EXboxOrigin_LeftStick_DPadWest = 16, + K_EXboxOrigin_LeftStick_DPadEast = 17, + K_EXboxOrigin_RightStick_Move = 18, + K_EXboxOrigin_RightStick_Click = 19, + K_EXboxOrigin_RightStick_DPadNorth = 20, + K_EXboxOrigin_RightStick_DPadSouth = 21, + K_EXboxOrigin_RightStick_DPadWest = 22, + K_EXboxOrigin_RightStick_DPadEast = 23, + K_EXboxOrigin_DPad_North = 24, + K_EXboxOrigin_DPad_South = 25, + K_EXboxOrigin_DPad_West = 26, + K_EXboxOrigin_DPad_East = 27, + K_EXboxOrigin_Count = 28, + }; + Q_ENUM(EXboxOrigin) + + enum class ESteamControllerPad { + K_ESteamControllerPad_Left = 0, + K_ESteamControllerPad_Right = 1, + }; + Q_ENUM(ESteamControllerPad) + + enum class EControllerHapticLocation { + K_EControllerHapticLocation_Left = 1, + K_EControllerHapticLocation_Right = 2, + K_EControllerHapticLocation_Both = 3, + }; + Q_ENUM(EControllerHapticLocation) + + enum class EControllerHapticType { + K_EControllerHapticType_Off = 0, + K_EControllerHapticType_Tick = 1, + K_EControllerHapticType_Click = 2, + }; + Q_ENUM(EControllerHapticType) + + enum class ESteamInputType { + K_ESteamInputType_Unknown = 0, + K_ESteamInputType_SteamController = 1, + K_ESteamInputType_XBox360Controller = 2, + K_ESteamInputType_XBoxOneController = 3, + K_ESteamInputType_GenericGamepad = 4, + K_ESteamInputType_PS4Controller = 5, + K_ESteamInputType_AppleMFiController = 6, + K_ESteamInputType_AndroidController = 7, + K_ESteamInputType_SwitchJoyConPair = 8, + K_ESteamInputType_SwitchJoyConSingle = 9, + K_ESteamInputType_SwitchProController = 10, + K_ESteamInputType_MobileTouch = 11, + K_ESteamInputType_PS3Controller = 12, + K_ESteamInputType_PS5Controller = 13, + K_ESteamInputType_SteamDeckController = 14, + K_ESteamInputType_Count = 15, + K_ESteamInputType_MaximumPossibleValue = 255, + }; + Q_ENUM(ESteamInputType) + + enum class ESteamInputConfigurationEnableType { + K_ESteamInputConfigurationEnableType_None = 0, + K_ESteamInputConfigurationEnableType_Playstation = 1, + K_ESteamInputConfigurationEnableType_Xbox = 2, + K_ESteamInputConfigurationEnableType_Generic = 4, + K_ESteamInputConfigurationEnableType_Switch = 8, + }; + Q_ENUM(ESteamInputConfigurationEnableType) + + enum class ESteamInputLEDFlag { + K_ESteamInputLEDFlag_SetColor = 0, + K_ESteamInputLEDFlag_RestoreUserDefault = 1, + }; + Q_ENUM(ESteamInputLEDFlag) + + enum class ESteamInputGlyphSize { + K_ESteamInputGlyphSize_Small = 0, + K_ESteamInputGlyphSize_Medium = 1, + K_ESteamInputGlyphSize_Large = 2, + K_ESteamInputGlyphSize_Count = 3, + }; + Q_ENUM(ESteamInputGlyphSize) + + enum class ESteamInputGlyphStyle { + ESteamInputGlyphStyle_Knockout = 0, + ESteamInputGlyphStyle_Light = 1, + ESteamInputGlyphStyle_Dark = 2, + ESteamInputGlyphStyle_NeutralColorABXY = 16, + ESteamInputGlyphStyle_SolidABXY = 32, + }; + Q_ENUM(ESteamInputGlyphStyle) + + enum class ESteamInputActionEventType { + ESteamInputActionEventType_DigitalAction = 0, + ESteamInputActionEventType_AnalogAction = 1, + }; + Q_ENUM(ESteamInputActionEventType) + + enum class EControllerActionOrigin { + K_EControllerActionOrigin_None = 0, + K_EControllerActionOrigin_A = 1, + K_EControllerActionOrigin_B = 2, + K_EControllerActionOrigin_X = 3, + K_EControllerActionOrigin_Y = 4, + K_EControllerActionOrigin_LeftBumper = 5, + K_EControllerActionOrigin_RightBumper = 6, + K_EControllerActionOrigin_LeftGrip = 7, + K_EControllerActionOrigin_RightGrip = 8, + K_EControllerActionOrigin_Start = 9, + K_EControllerActionOrigin_Back = 10, + K_EControllerActionOrigin_LeftPad_Touch = 11, + K_EControllerActionOrigin_LeftPad_Swipe = 12, + K_EControllerActionOrigin_LeftPad_Click = 13, + K_EControllerActionOrigin_LeftPad_DPadNorth = 14, + K_EControllerActionOrigin_LeftPad_DPadSouth = 15, + K_EControllerActionOrigin_LeftPad_DPadWest = 16, + K_EControllerActionOrigin_LeftPad_DPadEast = 17, + K_EControllerActionOrigin_RightPad_Touch = 18, + K_EControllerActionOrigin_RightPad_Swipe = 19, + K_EControllerActionOrigin_RightPad_Click = 20, + K_EControllerActionOrigin_RightPad_DPadNorth = 21, + K_EControllerActionOrigin_RightPad_DPadSouth = 22, + K_EControllerActionOrigin_RightPad_DPadWest = 23, + K_EControllerActionOrigin_RightPad_DPadEast = 24, + K_EControllerActionOrigin_LeftTrigger_Pull = 25, + K_EControllerActionOrigin_LeftTrigger_Click = 26, + K_EControllerActionOrigin_RightTrigger_Pull = 27, + K_EControllerActionOrigin_RightTrigger_Click = 28, + K_EControllerActionOrigin_LeftStick_Move = 29, + K_EControllerActionOrigin_LeftStick_Click = 30, + K_EControllerActionOrigin_LeftStick_DPadNorth = 31, + K_EControllerActionOrigin_LeftStick_DPadSouth = 32, + K_EControllerActionOrigin_LeftStick_DPadWest = 33, + K_EControllerActionOrigin_LeftStick_DPadEast = 34, + K_EControllerActionOrigin_Gyro_Move = 35, + K_EControllerActionOrigin_Gyro_Pitch = 36, + K_EControllerActionOrigin_Gyro_Yaw = 37, + K_EControllerActionOrigin_Gyro_Roll = 38, + K_EControllerActionOrigin_PS4_X = 39, + K_EControllerActionOrigin_PS4_Circle = 40, + K_EControllerActionOrigin_PS4_Triangle = 41, + K_EControllerActionOrigin_PS4_Square = 42, + K_EControllerActionOrigin_PS4_LeftBumper = 43, + K_EControllerActionOrigin_PS4_RightBumper = 44, + K_EControllerActionOrigin_PS4_Options = 45, + K_EControllerActionOrigin_PS4_Share = 46, + K_EControllerActionOrigin_PS4_LeftPad_Touch = 47, + K_EControllerActionOrigin_PS4_LeftPad_Swipe = 48, + K_EControllerActionOrigin_PS4_LeftPad_Click = 49, + K_EControllerActionOrigin_PS4_LeftPad_DPadNorth = 50, + K_EControllerActionOrigin_PS4_LeftPad_DPadSouth = 51, + K_EControllerActionOrigin_PS4_LeftPad_DPadWest = 52, + K_EControllerActionOrigin_PS4_LeftPad_DPadEast = 53, + K_EControllerActionOrigin_PS4_RightPad_Touch = 54, + K_EControllerActionOrigin_PS4_RightPad_Swipe = 55, + K_EControllerActionOrigin_PS4_RightPad_Click = 56, + K_EControllerActionOrigin_PS4_RightPad_DPadNorth = 57, + K_EControllerActionOrigin_PS4_RightPad_DPadSouth = 58, + K_EControllerActionOrigin_PS4_RightPad_DPadWest = 59, + K_EControllerActionOrigin_PS4_RightPad_DPadEast = 60, + K_EControllerActionOrigin_PS4_CenterPad_Touch = 61, + K_EControllerActionOrigin_PS4_CenterPad_Swipe = 62, + K_EControllerActionOrigin_PS4_CenterPad_Click = 63, + K_EControllerActionOrigin_PS4_CenterPad_DPadNorth = 64, + K_EControllerActionOrigin_PS4_CenterPad_DPadSouth = 65, + K_EControllerActionOrigin_PS4_CenterPad_DPadWest = 66, + K_EControllerActionOrigin_PS4_CenterPad_DPadEast = 67, + K_EControllerActionOrigin_PS4_LeftTrigger_Pull = 68, + K_EControllerActionOrigin_PS4_LeftTrigger_Click = 69, + K_EControllerActionOrigin_PS4_RightTrigger_Pull = 70, + K_EControllerActionOrigin_PS4_RightTrigger_Click = 71, + K_EControllerActionOrigin_PS4_LeftStick_Move = 72, + K_EControllerActionOrigin_PS4_LeftStick_Click = 73, + K_EControllerActionOrigin_PS4_LeftStick_DPadNorth = 74, + K_EControllerActionOrigin_PS4_LeftStick_DPadSouth = 75, + K_EControllerActionOrigin_PS4_LeftStick_DPadWest = 76, + K_EControllerActionOrigin_PS4_LeftStick_DPadEast = 77, + K_EControllerActionOrigin_PS4_RightStick_Move = 78, + K_EControllerActionOrigin_PS4_RightStick_Click = 79, + K_EControllerActionOrigin_PS4_RightStick_DPadNorth = 80, + K_EControllerActionOrigin_PS4_RightStick_DPadSouth = 81, + K_EControllerActionOrigin_PS4_RightStick_DPadWest = 82, + K_EControllerActionOrigin_PS4_RightStick_DPadEast = 83, + K_EControllerActionOrigin_PS4_DPad_North = 84, + K_EControllerActionOrigin_PS4_DPad_South = 85, + K_EControllerActionOrigin_PS4_DPad_West = 86, + K_EControllerActionOrigin_PS4_DPad_East = 87, + K_EControllerActionOrigin_PS4_Gyro_Move = 88, + K_EControllerActionOrigin_PS4_Gyro_Pitch = 89, + K_EControllerActionOrigin_PS4_Gyro_Yaw = 90, + K_EControllerActionOrigin_PS4_Gyro_Roll = 91, + K_EControllerActionOrigin_XBoxOne_A = 92, + K_EControllerActionOrigin_XBoxOne_B = 93, + K_EControllerActionOrigin_XBoxOne_X = 94, + K_EControllerActionOrigin_XBoxOne_Y = 95, + K_EControllerActionOrigin_XBoxOne_LeftBumper = 96, + K_EControllerActionOrigin_XBoxOne_RightBumper = 97, + K_EControllerActionOrigin_XBoxOne_Menu = 98, + K_EControllerActionOrigin_XBoxOne_View = 99, + K_EControllerActionOrigin_XBoxOne_LeftTrigger_Pull = 100, + K_EControllerActionOrigin_XBoxOne_LeftTrigger_Click = 101, + K_EControllerActionOrigin_XBoxOne_RightTrigger_Pull = 102, + K_EControllerActionOrigin_XBoxOne_RightTrigger_Click = 103, + K_EControllerActionOrigin_XBoxOne_LeftStick_Move = 104, + K_EControllerActionOrigin_XBoxOne_LeftStick_Click = 105, + K_EControllerActionOrigin_XBoxOne_LeftStick_DPadNorth = 106, + K_EControllerActionOrigin_XBoxOne_LeftStick_DPadSouth = 107, + K_EControllerActionOrigin_XBoxOne_LeftStick_DPadWest = 108, + K_EControllerActionOrigin_XBoxOne_LeftStick_DPadEast = 109, + K_EControllerActionOrigin_XBoxOne_RightStick_Move = 110, + K_EControllerActionOrigin_XBoxOne_RightStick_Click = 111, + K_EControllerActionOrigin_XBoxOne_RightStick_DPadNorth = 112, + K_EControllerActionOrigin_XBoxOne_RightStick_DPadSouth = 113, + K_EControllerActionOrigin_XBoxOne_RightStick_DPadWest = 114, + K_EControllerActionOrigin_XBoxOne_RightStick_DPadEast = 115, + K_EControllerActionOrigin_XBoxOne_DPad_North = 116, + K_EControllerActionOrigin_XBoxOne_DPad_South = 117, + K_EControllerActionOrigin_XBoxOne_DPad_West = 118, + K_EControllerActionOrigin_XBoxOne_DPad_East = 119, + K_EControllerActionOrigin_XBox360_A = 120, + K_EControllerActionOrigin_XBox360_B = 121, + K_EControllerActionOrigin_XBox360_X = 122, + K_EControllerActionOrigin_XBox360_Y = 123, + K_EControllerActionOrigin_XBox360_LeftBumper = 124, + K_EControllerActionOrigin_XBox360_RightBumper = 125, + K_EControllerActionOrigin_XBox360_Start = 126, + K_EControllerActionOrigin_XBox360_Back = 127, + K_EControllerActionOrigin_XBox360_LeftTrigger_Pull = 128, + K_EControllerActionOrigin_XBox360_LeftTrigger_Click = 129, + K_EControllerActionOrigin_XBox360_RightTrigger_Pull = 130, + K_EControllerActionOrigin_XBox360_RightTrigger_Click = 131, + K_EControllerActionOrigin_XBox360_LeftStick_Move = 132, + K_EControllerActionOrigin_XBox360_LeftStick_Click = 133, + K_EControllerActionOrigin_XBox360_LeftStick_DPadNorth = 134, + K_EControllerActionOrigin_XBox360_LeftStick_DPadSouth = 135, + K_EControllerActionOrigin_XBox360_LeftStick_DPadWest = 136, + K_EControllerActionOrigin_XBox360_LeftStick_DPadEast = 137, + K_EControllerActionOrigin_XBox360_RightStick_Move = 138, + K_EControllerActionOrigin_XBox360_RightStick_Click = 139, + K_EControllerActionOrigin_XBox360_RightStick_DPadNorth = 140, + K_EControllerActionOrigin_XBox360_RightStick_DPadSouth = 141, + K_EControllerActionOrigin_XBox360_RightStick_DPadWest = 142, + K_EControllerActionOrigin_XBox360_RightStick_DPadEast = 143, + K_EControllerActionOrigin_XBox360_DPad_North = 144, + K_EControllerActionOrigin_XBox360_DPad_South = 145, + K_EControllerActionOrigin_XBox360_DPad_West = 146, + K_EControllerActionOrigin_XBox360_DPad_East = 147, + K_EControllerActionOrigin_SteamV2_A = 148, + K_EControllerActionOrigin_SteamV2_B = 149, + K_EControllerActionOrigin_SteamV2_X = 150, + K_EControllerActionOrigin_SteamV2_Y = 151, + K_EControllerActionOrigin_SteamV2_LeftBumper = 152, + K_EControllerActionOrigin_SteamV2_RightBumper = 153, + K_EControllerActionOrigin_SteamV2_LeftGrip_Lower = 154, + K_EControllerActionOrigin_SteamV2_LeftGrip_Upper = 155, + K_EControllerActionOrigin_SteamV2_RightGrip_Lower = 156, + K_EControllerActionOrigin_SteamV2_RightGrip_Upper = 157, + K_EControllerActionOrigin_SteamV2_LeftBumper_Pressure = 158, + K_EControllerActionOrigin_SteamV2_RightBumper_Pressure = 159, + K_EControllerActionOrigin_SteamV2_LeftGrip_Pressure = 160, + K_EControllerActionOrigin_SteamV2_RightGrip_Pressure = 161, + K_EControllerActionOrigin_SteamV2_LeftGrip_Upper_Pressure = 162, + K_EControllerActionOrigin_SteamV2_RightGrip_Upper_Pressure = 163, + K_EControllerActionOrigin_SteamV2_Start = 164, + K_EControllerActionOrigin_SteamV2_Back = 165, + K_EControllerActionOrigin_SteamV2_LeftPad_Touch = 166, + K_EControllerActionOrigin_SteamV2_LeftPad_Swipe = 167, + K_EControllerActionOrigin_SteamV2_LeftPad_Click = 168, + K_EControllerActionOrigin_SteamV2_LeftPad_Pressure = 169, + K_EControllerActionOrigin_SteamV2_LeftPad_DPadNorth = 170, + K_EControllerActionOrigin_SteamV2_LeftPad_DPadSouth = 171, + K_EControllerActionOrigin_SteamV2_LeftPad_DPadWest = 172, + K_EControllerActionOrigin_SteamV2_LeftPad_DPadEast = 173, + K_EControllerActionOrigin_SteamV2_RightPad_Touch = 174, + K_EControllerActionOrigin_SteamV2_RightPad_Swipe = 175, + K_EControllerActionOrigin_SteamV2_RightPad_Click = 176, + K_EControllerActionOrigin_SteamV2_RightPad_Pressure = 177, + K_EControllerActionOrigin_SteamV2_RightPad_DPadNorth = 178, + K_EControllerActionOrigin_SteamV2_RightPad_DPadSouth = 179, + K_EControllerActionOrigin_SteamV2_RightPad_DPadWest = 180, + K_EControllerActionOrigin_SteamV2_RightPad_DPadEast = 181, + K_EControllerActionOrigin_SteamV2_LeftTrigger_Pull = 182, + K_EControllerActionOrigin_SteamV2_LeftTrigger_Click = 183, + K_EControllerActionOrigin_SteamV2_RightTrigger_Pull = 184, + K_EControllerActionOrigin_SteamV2_RightTrigger_Click = 185, + K_EControllerActionOrigin_SteamV2_LeftStick_Move = 186, + K_EControllerActionOrigin_SteamV2_LeftStick_Click = 187, + K_EControllerActionOrigin_SteamV2_LeftStick_DPadNorth = 188, + K_EControllerActionOrigin_SteamV2_LeftStick_DPadSouth = 189, + K_EControllerActionOrigin_SteamV2_LeftStick_DPadWest = 190, + K_EControllerActionOrigin_SteamV2_LeftStick_DPadEast = 191, + K_EControllerActionOrigin_SteamV2_Gyro_Move = 192, + K_EControllerActionOrigin_SteamV2_Gyro_Pitch = 193, + K_EControllerActionOrigin_SteamV2_Gyro_Yaw = 194, + K_EControllerActionOrigin_SteamV2_Gyro_Roll = 195, + K_EControllerActionOrigin_Switch_A = 196, + K_EControllerActionOrigin_Switch_B = 197, + K_EControllerActionOrigin_Switch_X = 198, + K_EControllerActionOrigin_Switch_Y = 199, + K_EControllerActionOrigin_Switch_LeftBumper = 200, + K_EControllerActionOrigin_Switch_RightBumper = 201, + K_EControllerActionOrigin_Switch_Plus = 202, + K_EControllerActionOrigin_Switch_Minus = 203, + K_EControllerActionOrigin_Switch_Capture = 204, + K_EControllerActionOrigin_Switch_LeftTrigger_Pull = 205, + K_EControllerActionOrigin_Switch_LeftTrigger_Click = 206, + K_EControllerActionOrigin_Switch_RightTrigger_Pull = 207, + K_EControllerActionOrigin_Switch_RightTrigger_Click = 208, + K_EControllerActionOrigin_Switch_LeftStick_Move = 209, + K_EControllerActionOrigin_Switch_LeftStick_Click = 210, + K_EControllerActionOrigin_Switch_LeftStick_DPadNorth = 211, + K_EControllerActionOrigin_Switch_LeftStick_DPadSouth = 212, + K_EControllerActionOrigin_Switch_LeftStick_DPadWest = 213, + K_EControllerActionOrigin_Switch_LeftStick_DPadEast = 214, + K_EControllerActionOrigin_Switch_RightStick_Move = 215, + K_EControllerActionOrigin_Switch_RightStick_Click = 216, + K_EControllerActionOrigin_Switch_RightStick_DPadNorth = 217, + K_EControllerActionOrigin_Switch_RightStick_DPadSouth = 218, + K_EControllerActionOrigin_Switch_RightStick_DPadWest = 219, + K_EControllerActionOrigin_Switch_RightStick_DPadEast = 220, + K_EControllerActionOrigin_Switch_DPad_North = 221, + K_EControllerActionOrigin_Switch_DPad_South = 222, + K_EControllerActionOrigin_Switch_DPad_West = 223, + K_EControllerActionOrigin_Switch_DPad_East = 224, + K_EControllerActionOrigin_Switch_ProGyro_Move = 225, + K_EControllerActionOrigin_Switch_ProGyro_Pitch = 226, + K_EControllerActionOrigin_Switch_ProGyro_Yaw = 227, + K_EControllerActionOrigin_Switch_ProGyro_Roll = 228, + K_EControllerActionOrigin_Switch_RightGyro_Move = 229, + K_EControllerActionOrigin_Switch_RightGyro_Pitch = 230, + K_EControllerActionOrigin_Switch_RightGyro_Yaw = 231, + K_EControllerActionOrigin_Switch_RightGyro_Roll = 232, + K_EControllerActionOrigin_Switch_LeftGyro_Move = 233, + K_EControllerActionOrigin_Switch_LeftGyro_Pitch = 234, + K_EControllerActionOrigin_Switch_LeftGyro_Yaw = 235, + K_EControllerActionOrigin_Switch_LeftGyro_Roll = 236, + K_EControllerActionOrigin_Switch_LeftGrip_Lower = 237, + K_EControllerActionOrigin_Switch_LeftGrip_Upper = 238, + K_EControllerActionOrigin_Switch_RightGrip_Lower = 239, + K_EControllerActionOrigin_Switch_RightGrip_Upper = 240, + K_EControllerActionOrigin_PS4_DPad_Move = 241, + K_EControllerActionOrigin_XBoxOne_DPad_Move = 242, + K_EControllerActionOrigin_XBox360_DPad_Move = 243, + K_EControllerActionOrigin_Switch_DPad_Move = 244, + K_EControllerActionOrigin_PS5_X = 245, + K_EControllerActionOrigin_PS5_Circle = 246, + K_EControllerActionOrigin_PS5_Triangle = 247, + K_EControllerActionOrigin_PS5_Square = 248, + K_EControllerActionOrigin_PS5_LeftBumper = 249, + K_EControllerActionOrigin_PS5_RightBumper = 250, + K_EControllerActionOrigin_PS5_Option = 251, + K_EControllerActionOrigin_PS5_Create = 252, + K_EControllerActionOrigin_PS5_Mute = 253, + K_EControllerActionOrigin_PS5_LeftPad_Touch = 254, + K_EControllerActionOrigin_PS5_LeftPad_Swipe = 255, + K_EControllerActionOrigin_PS5_LeftPad_Click = 256, + K_EControllerActionOrigin_PS5_LeftPad_DPadNorth = 257, + K_EControllerActionOrigin_PS5_LeftPad_DPadSouth = 258, + K_EControllerActionOrigin_PS5_LeftPad_DPadWest = 259, + K_EControllerActionOrigin_PS5_LeftPad_DPadEast = 260, + K_EControllerActionOrigin_PS5_RightPad_Touch = 261, + K_EControllerActionOrigin_PS5_RightPad_Swipe = 262, + K_EControllerActionOrigin_PS5_RightPad_Click = 263, + K_EControllerActionOrigin_PS5_RightPad_DPadNorth = 264, + K_EControllerActionOrigin_PS5_RightPad_DPadSouth = 265, + K_EControllerActionOrigin_PS5_RightPad_DPadWest = 266, + K_EControllerActionOrigin_PS5_RightPad_DPadEast = 267, + K_EControllerActionOrigin_PS5_CenterPad_Touch = 268, + K_EControllerActionOrigin_PS5_CenterPad_Swipe = 269, + K_EControllerActionOrigin_PS5_CenterPad_Click = 270, + K_EControllerActionOrigin_PS5_CenterPad_DPadNorth = 271, + K_EControllerActionOrigin_PS5_CenterPad_DPadSouth = 272, + K_EControllerActionOrigin_PS5_CenterPad_DPadWest = 273, + K_EControllerActionOrigin_PS5_CenterPad_DPadEast = 274, + K_EControllerActionOrigin_PS5_LeftTrigger_Pull = 275, + K_EControllerActionOrigin_PS5_LeftTrigger_Click = 276, + K_EControllerActionOrigin_PS5_RightTrigger_Pull = 277, + K_EControllerActionOrigin_PS5_RightTrigger_Click = 278, + K_EControllerActionOrigin_PS5_LeftStick_Move = 279, + K_EControllerActionOrigin_PS5_LeftStick_Click = 280, + K_EControllerActionOrigin_PS5_LeftStick_DPadNorth = 281, + K_EControllerActionOrigin_PS5_LeftStick_DPadSouth = 282, + K_EControllerActionOrigin_PS5_LeftStick_DPadWest = 283, + K_EControllerActionOrigin_PS5_LeftStick_DPadEast = 284, + K_EControllerActionOrigin_PS5_RightStick_Move = 285, + K_EControllerActionOrigin_PS5_RightStick_Click = 286, + K_EControllerActionOrigin_PS5_RightStick_DPadNorth = 287, + K_EControllerActionOrigin_PS5_RightStick_DPadSouth = 288, + K_EControllerActionOrigin_PS5_RightStick_DPadWest = 289, + K_EControllerActionOrigin_PS5_RightStick_DPadEast = 290, + K_EControllerActionOrigin_PS5_DPad_Move = 291, + K_EControllerActionOrigin_PS5_DPad_North = 292, + K_EControllerActionOrigin_PS5_DPad_South = 293, + K_EControllerActionOrigin_PS5_DPad_West = 294, + K_EControllerActionOrigin_PS5_DPad_East = 295, + K_EControllerActionOrigin_PS5_Gyro_Move = 296, + K_EControllerActionOrigin_PS5_Gyro_Pitch = 297, + K_EControllerActionOrigin_PS5_Gyro_Yaw = 298, + K_EControllerActionOrigin_PS5_Gyro_Roll = 299, + K_EControllerActionOrigin_XBoxOne_LeftGrip_Lower = 300, + K_EControllerActionOrigin_XBoxOne_LeftGrip_Upper = 301, + K_EControllerActionOrigin_XBoxOne_RightGrip_Lower = 302, + K_EControllerActionOrigin_XBoxOne_RightGrip_Upper = 303, + K_EControllerActionOrigin_XBoxOne_Share = 304, + K_EControllerActionOrigin_SteamDeck_A = 305, + K_EControllerActionOrigin_SteamDeck_B = 306, + K_EControllerActionOrigin_SteamDeck_X = 307, + K_EControllerActionOrigin_SteamDeck_Y = 308, + K_EControllerActionOrigin_SteamDeck_L1 = 309, + K_EControllerActionOrigin_SteamDeck_R1 = 310, + K_EControllerActionOrigin_SteamDeck_Menu = 311, + K_EControllerActionOrigin_SteamDeck_View = 312, + K_EControllerActionOrigin_SteamDeck_LeftPad_Touch = 313, + K_EControllerActionOrigin_SteamDeck_LeftPad_Swipe = 314, + K_EControllerActionOrigin_SteamDeck_LeftPad_Click = 315, + K_EControllerActionOrigin_SteamDeck_LeftPad_DPadNorth = 316, + K_EControllerActionOrigin_SteamDeck_LeftPad_DPadSouth = 317, + K_EControllerActionOrigin_SteamDeck_LeftPad_DPadWest = 318, + K_EControllerActionOrigin_SteamDeck_LeftPad_DPadEast = 319, + K_EControllerActionOrigin_SteamDeck_RightPad_Touch = 320, + K_EControllerActionOrigin_SteamDeck_RightPad_Swipe = 321, + K_EControllerActionOrigin_SteamDeck_RightPad_Click = 322, + K_EControllerActionOrigin_SteamDeck_RightPad_DPadNorth = 323, + K_EControllerActionOrigin_SteamDeck_RightPad_DPadSouth = 324, + K_EControllerActionOrigin_SteamDeck_RightPad_DPadWest = 325, + K_EControllerActionOrigin_SteamDeck_RightPad_DPadEast = 326, + K_EControllerActionOrigin_SteamDeck_L2_SoftPull = 327, + K_EControllerActionOrigin_SteamDeck_L2 = 328, + K_EControllerActionOrigin_SteamDeck_R2_SoftPull = 329, + K_EControllerActionOrigin_SteamDeck_R2 = 330, + K_EControllerActionOrigin_SteamDeck_LeftStick_Move = 331, + K_EControllerActionOrigin_SteamDeck_L3 = 332, + K_EControllerActionOrigin_SteamDeck_LeftStick_DPadNorth = 333, + K_EControllerActionOrigin_SteamDeck_LeftStick_DPadSouth = 334, + K_EControllerActionOrigin_SteamDeck_LeftStick_DPadWest = 335, + K_EControllerActionOrigin_SteamDeck_LeftStick_DPadEast = 336, + K_EControllerActionOrigin_SteamDeck_LeftStick_Touch = 337, + K_EControllerActionOrigin_SteamDeck_RightStick_Move = 338, + K_EControllerActionOrigin_SteamDeck_R3 = 339, + K_EControllerActionOrigin_SteamDeck_RightStick_DPadNorth = 340, + K_EControllerActionOrigin_SteamDeck_RightStick_DPadSouth = 341, + K_EControllerActionOrigin_SteamDeck_RightStick_DPadWest = 342, + K_EControllerActionOrigin_SteamDeck_RightStick_DPadEast = 343, + K_EControllerActionOrigin_SteamDeck_RightStick_Touch = 344, + K_EControllerActionOrigin_SteamDeck_L4 = 345, + K_EControllerActionOrigin_SteamDeck_R4 = 346, + K_EControllerActionOrigin_SteamDeck_L5 = 347, + K_EControllerActionOrigin_SteamDeck_R5 = 348, + K_EControllerActionOrigin_SteamDeck_DPad_Move = 349, + K_EControllerActionOrigin_SteamDeck_DPad_North = 350, + K_EControllerActionOrigin_SteamDeck_DPad_South = 351, + K_EControllerActionOrigin_SteamDeck_DPad_West = 352, + K_EControllerActionOrigin_SteamDeck_DPad_East = 353, + K_EControllerActionOrigin_SteamDeck_Gyro_Move = 354, + K_EControllerActionOrigin_SteamDeck_Gyro_Pitch = 355, + K_EControllerActionOrigin_SteamDeck_Gyro_Yaw = 356, + K_EControllerActionOrigin_SteamDeck_Gyro_Roll = 357, + K_EControllerActionOrigin_SteamDeck_Reserved1 = 358, + K_EControllerActionOrigin_SteamDeck_Reserved2 = 359, + K_EControllerActionOrigin_SteamDeck_Reserved3 = 360, + K_EControllerActionOrigin_SteamDeck_Reserved4 = 361, + K_EControllerActionOrigin_SteamDeck_Reserved5 = 362, + K_EControllerActionOrigin_SteamDeck_Reserved6 = 363, + K_EControllerActionOrigin_SteamDeck_Reserved7 = 364, + K_EControllerActionOrigin_SteamDeck_Reserved8 = 365, + K_EControllerActionOrigin_SteamDeck_Reserved9 = 366, + K_EControllerActionOrigin_SteamDeck_Reserved10 = 367, + K_EControllerActionOrigin_SteamDeck_Reserved11 = 368, + K_EControllerActionOrigin_SteamDeck_Reserved12 = 369, + K_EControllerActionOrigin_SteamDeck_Reserved13 = 370, + K_EControllerActionOrigin_SteamDeck_Reserved14 = 371, + K_EControllerActionOrigin_SteamDeck_Reserved15 = 372, + K_EControllerActionOrigin_SteamDeck_Reserved16 = 373, + K_EControllerActionOrigin_SteamDeck_Reserved17 = 374, + K_EControllerActionOrigin_SteamDeck_Reserved18 = 375, + K_EControllerActionOrigin_SteamDeck_Reserved19 = 376, + K_EControllerActionOrigin_SteamDeck_Reserved20 = 377, + K_EControllerActionOrigin_Switch_JoyConButton_N = 378, + K_EControllerActionOrigin_Switch_JoyConButton_E = 379, + K_EControllerActionOrigin_Switch_JoyConButton_S = 380, + K_EControllerActionOrigin_Switch_JoyConButton_W = 381, + K_EControllerActionOrigin_PS5_LeftGrip = 382, + K_EControllerActionOrigin_PS5_RightGrip = 383, + K_EControllerActionOrigin_PS5_LeftFn = 384, + K_EControllerActionOrigin_PS5_RightFn = 385, + K_EControllerActionOrigin_Count = 386, + K_EControllerActionOrigin_MaximumPossibleValue = 32767, + }; + Q_ENUM(EControllerActionOrigin) + + enum class ESteamControllerLEDFlag { + K_ESteamControllerLEDFlag_SetColor = 0, + K_ESteamControllerLEDFlag_RestoreUserDefault = 1, + }; + Q_ENUM(ESteamControllerLEDFlag) + + enum class EUGCMatchingUGCType { + K_EUGCMatchingUGCType_Items = 0, + K_EUGCMatchingUGCType_Items_Mtx = 1, + K_EUGCMatchingUGCType_Items_ReadyToUse = 2, + K_EUGCMatchingUGCType_Collections = 3, + K_EUGCMatchingUGCType_Artwork = 4, + K_EUGCMatchingUGCType_Videos = 5, + K_EUGCMatchingUGCType_Screenshots = 6, + K_EUGCMatchingUGCType_AllGuides = 7, + K_EUGCMatchingUGCType_WebGuides = 8, + K_EUGCMatchingUGCType_IntegratedGuides = 9, + K_EUGCMatchingUGCType_UsableInGame = 10, + K_EUGCMatchingUGCType_ControllerBindings = 11, + K_EUGCMatchingUGCType_GameManagedItems = 12, + K_EUGCMatchingUGCType_All = -1, + }; + Q_ENUM(EUGCMatchingUGCType) + + enum class EUserUGCList { + K_EUserUGCList_Published = 0, + K_EUserUGCList_VotedOn = 1, + K_EUserUGCList_VotedUp = 2, + K_EUserUGCList_VotedDown = 3, + K_EUserUGCList_WillVoteLater = 4, + K_EUserUGCList_Favorited = 5, + K_EUserUGCList_Subscribed = 6, + K_EUserUGCList_UsedOrPlayed = 7, + K_EUserUGCList_Followed = 8, + }; + Q_ENUM(EUserUGCList) + + enum class EUserUGCListSortOrder { + K_EUserUGCListSortOrder_CreationOrderDesc = 0, + K_EUserUGCListSortOrder_CreationOrderAsc = 1, + K_EUserUGCListSortOrder_TitleAsc = 2, + K_EUserUGCListSortOrder_LastUpdatedDesc = 3, + K_EUserUGCListSortOrder_SubscriptionDateDesc = 4, + K_EUserUGCListSortOrder_VoteScoreDesc = 5, + K_EUserUGCListSortOrder_ForModeration = 6, + }; + Q_ENUM(EUserUGCListSortOrder) + + enum class EUGCQuery { + K_EUGCQuery_RankedByVote = 0, + K_EUGCQuery_RankedByPublicationDate = 1, + K_EUGCQuery_AcceptedForGameRankedByAcceptanceDate = 2, + K_EUGCQuery_RankedByTrend = 3, + K_EUGCQuery_FavoritedByFriendsRankedByPublicationDate = 4, + K_EUGCQuery_CreatedByFriendsRankedByPublicationDate = 5, + K_EUGCQuery_RankedByNumTimesReported = 6, + K_EUGCQuery_CreatedByFollowedUsersRankedByPublicationDate = 7, + K_EUGCQuery_NotYetRated = 8, + K_EUGCQuery_RankedByTotalVotesAsc = 9, + K_EUGCQuery_RankedByVotesUp = 10, + K_EUGCQuery_RankedByTextSearch = 11, + K_EUGCQuery_RankedByTotalUniqueSubscriptions = 12, + K_EUGCQuery_RankedByPlaytimeTrend = 13, + K_EUGCQuery_RankedByTotalPlaytime = 14, + K_EUGCQuery_RankedByAveragePlaytimeTrend = 15, + K_EUGCQuery_RankedByLifetimeAveragePlaytime = 16, + K_EUGCQuery_RankedByPlaytimeSessionsTrend = 17, + K_EUGCQuery_RankedByLifetimePlaytimeSessions = 18, + K_EUGCQuery_RankedByLastUpdatedDate = 19, + }; + Q_ENUM(EUGCQuery) + + enum class EItemUpdateStatus { + K_EItemUpdateStatusInvalid = 0, + K_EItemUpdateStatusPreparingConfig = 1, + K_EItemUpdateStatusPreparingContent = 2, + K_EItemUpdateStatusUploadingContent = 3, + K_EItemUpdateStatusUploadingPreviewFile = 4, + K_EItemUpdateStatusCommittingChanges = 5, + }; + Q_ENUM(EItemUpdateStatus) + + enum class EItemState { + K_EItemStateNone = 0, + K_EItemStateSubscribed = 1, + K_EItemStateLegacyItem = 2, + K_EItemStateInstalled = 4, + K_EItemStateNeedsUpdate = 8, + K_EItemStateDownloading = 16, + K_EItemStateDownloadPending = 32, + }; + Q_ENUM(EItemState) + + enum class EItemStatistic { + K_EItemStatistic_NumSubscriptions = 0, + K_EItemStatistic_NumFavorites = 1, + K_EItemStatistic_NumFollowers = 2, + K_EItemStatistic_NumUniqueSubscriptions = 3, + K_EItemStatistic_NumUniqueFavorites = 4, + K_EItemStatistic_NumUniqueFollowers = 5, + K_EItemStatistic_NumUniqueWebsiteViews = 6, + K_EItemStatistic_ReportScore = 7, + K_EItemStatistic_NumSecondsPlayed = 8, + K_EItemStatistic_NumPlaytimeSessions = 9, + K_EItemStatistic_NumComments = 10, + K_EItemStatistic_NumSecondsPlayedDuringTimePeriod = 11, + K_EItemStatistic_NumPlaytimeSessionsDuringTimePeriod = 12, + }; + Q_ENUM(EItemStatistic) + + enum class EItemPreviewType { + K_EItemPreviewType_Image = 0, + K_EItemPreviewType_YouTubeVideo = 1, + K_EItemPreviewType_Sketchfab = 2, + K_EItemPreviewType_EnvironmentMap_HorizontalCross = 3, + K_EItemPreviewType_EnvironmentMap_LatLong = 4, + K_EItemPreviewType_ReservedMax = 255, + }; + Q_ENUM(EItemPreviewType) + + enum class EUGCContentDescriptorID { + K_EUGCContentDescriptor_NudityOrSexualContent = 1, + K_EUGCContentDescriptor_FrequentViolenceOrGore = 2, + K_EUGCContentDescriptor_AdultOnlySexualContent = 3, + K_EUGCContentDescriptor_GratuitousSexualContent = 4, + K_EUGCContentDescriptor_AnyMatureContent = 5, + }; + Q_ENUM(EUGCContentDescriptorID) + + enum class ESteamItemFlags { + K_ESteamItemNoTrade = 1, + K_ESteamItemRemoved = 256, + K_ESteamItemConsumed = 512, + }; + Q_ENUM(ESteamItemFlags) + + enum class EParentalFeature { + K_EFeatureInvalid = 0, + K_EFeatureStore = 1, + K_EFeatureCommunity = 2, + K_EFeatureProfile = 3, + K_EFeatureFriends = 4, + K_EFeatureNews = 5, + K_EFeatureTrading = 6, + K_EFeatureSettings = 7, + K_EFeatureConsole = 8, + K_EFeatureBrowser = 9, + K_EFeatureParentalSetup = 10, + K_EFeatureLibrary = 11, + K_EFeatureTest = 12, + K_EFeatureSiteLicense = 13, + K_EFeatureKioskMode = 14, + K_EFeatureMax = 15, + }; + Q_ENUM(EParentalFeature) + + enum class ESteamDeviceFormFactor { + K_ESteamDeviceFormFactorUnknown = 0, + K_ESteamDeviceFormFactorPhone = 1, + K_ESteamDeviceFormFactorTablet = 2, + K_ESteamDeviceFormFactorComputer = 3, + K_ESteamDeviceFormFactorTV = 4, + }; + Q_ENUM(ESteamDeviceFormFactor) + + enum class ESteamNetworkingAvailability { + K_ESteamNetworkingAvailability_CannotTry = -102, + K_ESteamNetworkingAvailability_Failed = -101, + K_ESteamNetworkingAvailability_Previously = -100, + K_ESteamNetworkingAvailability_Retrying = -10, + K_ESteamNetworkingAvailability_NeverTried = 1, + K_ESteamNetworkingAvailability_Waiting = 2, + K_ESteamNetworkingAvailability_Attempting = 3, + K_ESteamNetworkingAvailability_Current = 100, + K_ESteamNetworkingAvailability_Unknown = 0, + K_ESteamNetworkingAvailability__Force32bit = 2147483647, + }; + Q_ENUM(ESteamNetworkingAvailability) + + enum class ESteamNetworkingIdentityType { + K_ESteamNetworkingIdentityType_Invalid = 0, + K_ESteamNetworkingIdentityType_SteamID = 16, + K_ESteamNetworkingIdentityType_XboxPairwiseID = 17, + K_ESteamNetworkingIdentityType_SonyPSN = 18, + K_ESteamNetworkingIdentityType_GoogleStadia = 19, + K_ESteamNetworkingIdentityType_IPAddress = 1, + K_ESteamNetworkingIdentityType_GenericString = 2, + K_ESteamNetworkingIdentityType_GenericBytes = 3, + K_ESteamNetworkingIdentityType_UnknownType = 4, + K_ESteamNetworkingIdentityType__Force32bit = 2147483647, + }; + Q_ENUM(ESteamNetworkingIdentityType) + + enum class ESteamNetworkingFakeIPType { + K_ESteamNetworkingFakeIPType_Invalid = 0, + K_ESteamNetworkingFakeIPType_NotFake = 1, + K_ESteamNetworkingFakeIPType_GlobalIPv4 = 2, + K_ESteamNetworkingFakeIPType_LocalIPv4 = 3, + K_ESteamNetworkingFakeIPType__Force32Bit = 2147483647, + }; + Q_ENUM(ESteamNetworkingFakeIPType) + + enum class ESteamNetworkingConnectionState { + K_ESteamNetworkingConnectionState_None = 0, + K_ESteamNetworkingConnectionState_Connecting = 1, + K_ESteamNetworkingConnectionState_FindingRoute = 2, + K_ESteamNetworkingConnectionState_Connected = 3, + K_ESteamNetworkingConnectionState_ClosedByPeer = 4, + K_ESteamNetworkingConnectionState_ProblemDetectedLocally = 5, + K_ESteamNetworkingConnectionState_FinWait = -1, + K_ESteamNetworkingConnectionState_Linger = -2, + K_ESteamNetworkingConnectionState_Dead = -3, + K_ESteamNetworkingConnectionState__Force32Bit = 2147483647, + }; + Q_ENUM(ESteamNetworkingConnectionState) + + enum class ESteamNetConnectionEnd { + K_ESteamNetConnectionEnd_Invalid = 0, + K_ESteamNetConnectionEnd_App_Min = 1000, + K_ESteamNetConnectionEnd_App_Generic = 1000, + K_ESteamNetConnectionEnd_App_Max = 1999, + K_ESteamNetConnectionEnd_AppException_Min = 2000, + K_ESteamNetConnectionEnd_AppException_Generic = 2000, + K_ESteamNetConnectionEnd_AppException_Max = 2999, + K_ESteamNetConnectionEnd_Local_Min = 3000, + K_ESteamNetConnectionEnd_Local_OfflineMode = 3001, + K_ESteamNetConnectionEnd_Local_ManyRelayConnectivity = 3002, + K_ESteamNetConnectionEnd_Local_HostedServerPrimaryRelay = 3003, + K_ESteamNetConnectionEnd_Local_NetworkConfig = 3004, + K_ESteamNetConnectionEnd_Local_Rights = 3005, + K_ESteamNetConnectionEnd_Local_P2P_ICE_NoPublicAddresses = 3006, + K_ESteamNetConnectionEnd_Local_Max = 3999, + K_ESteamNetConnectionEnd_Remote_Min = 4000, + K_ESteamNetConnectionEnd_Remote_Timeout = 4001, + K_ESteamNetConnectionEnd_Remote_BadCrypt = 4002, + K_ESteamNetConnectionEnd_Remote_BadCert = 4003, + K_ESteamNetConnectionEnd_Remote_BadProtocolVersion = 4006, + K_ESteamNetConnectionEnd_Remote_P2P_ICE_NoPublicAddresses = 4007, + K_ESteamNetConnectionEnd_Remote_Max = 4999, + K_ESteamNetConnectionEnd_Misc_Min = 5000, + K_ESteamNetConnectionEnd_Misc_Generic = 5001, + K_ESteamNetConnectionEnd_Misc_InternalError = 5002, + K_ESteamNetConnectionEnd_Misc_Timeout = 5003, + K_ESteamNetConnectionEnd_Misc_SteamConnectivity = 5005, + K_ESteamNetConnectionEnd_Misc_NoRelaySessionsToClient = 5006, + K_ESteamNetConnectionEnd_Misc_P2P_Rendezvous = 5008, + K_ESteamNetConnectionEnd_Misc_P2P_NAT_Firewall = 5009, + K_ESteamNetConnectionEnd_Misc_PeerSentNoConnection = 5010, + K_ESteamNetConnectionEnd_Misc_Max = 5999, + K_ESteamNetConnectionEnd__Force32Bit = 2147483647, + }; + Q_ENUM(ESteamNetConnectionEnd) + + enum class ESteamNetworkingConfigScope { + K_ESteamNetworkingConfig_Global = 1, + K_ESteamNetworkingConfig_SocketsInterface = 2, + K_ESteamNetworkingConfig_ListenSocket = 3, + K_ESteamNetworkingConfig_Connection = 4, + K_ESteamNetworkingConfigScope__Force32Bit = 2147483647, + }; + Q_ENUM(ESteamNetworkingConfigScope) + + enum class ESteamNetworkingConfigDataType { + K_ESteamNetworkingConfig_Int32 = 1, + K_ESteamNetworkingConfig_Int64 = 2, + K_ESteamNetworkingConfig_Float = 3, + K_ESteamNetworkingConfig_String = 4, + K_ESteamNetworkingConfig_Ptr = 5, + K_ESteamNetworkingConfigDataType__Force32Bit = 2147483647, + }; + Q_ENUM(ESteamNetworkingConfigDataType) + + enum class ESteamNetworkingConfigValue { + K_ESteamNetworkingConfig_Invalid = 0, + K_ESteamNetworkingConfig_TimeoutInitial = 24, + K_ESteamNetworkingConfig_TimeoutConnected = 25, + K_ESteamNetworkingConfig_SendBufferSize = 9, + K_ESteamNetworkingConfig_ConnectionUserData = 40, + K_ESteamNetworkingConfig_SendRateMin = 10, + K_ESteamNetworkingConfig_SendRateMax = 11, + K_ESteamNetworkingConfig_NagleTime = 12, + K_ESteamNetworkingConfig_IP_AllowWithoutAuth = 23, + K_ESteamNetworkingConfig_MTU_PacketSize = 32, + K_ESteamNetworkingConfig_MTU_DataSize = 33, + K_ESteamNetworkingConfig_Unencrypted = 34, + K_ESteamNetworkingConfig_SymmetricConnect = 37, + K_ESteamNetworkingConfig_LocalVirtualPort = 38, + K_ESteamNetworkingConfig_DualWifi_Enable = 39, + K_ESteamNetworkingConfig_EnableDiagnosticsUI = 46, + K_ESteamNetworkingConfig_FakePacketLoss_Send = 2, + K_ESteamNetworkingConfig_FakePacketLoss_Recv = 3, + K_ESteamNetworkingConfig_FakePacketLag_Send = 4, + K_ESteamNetworkingConfig_FakePacketLag_Recv = 5, + K_ESteamNetworkingConfig_FakePacketReorder_Send = 6, + K_ESteamNetworkingConfig_FakePacketReorder_Recv = 7, + K_ESteamNetworkingConfig_FakePacketReorder_Time = 8, + K_ESteamNetworkingConfig_FakePacketDup_Send = 26, + K_ESteamNetworkingConfig_FakePacketDup_Recv = 27, + K_ESteamNetworkingConfig_FakePacketDup_TimeMax = 28, + K_ESteamNetworkingConfig_PacketTraceMaxBytes = 41, + K_ESteamNetworkingConfig_FakeRateLimit_Send_Rate = 42, + K_ESteamNetworkingConfig_FakeRateLimit_Send_Burst = 43, + K_ESteamNetworkingConfig_FakeRateLimit_Recv_Rate = 44, + K_ESteamNetworkingConfig_FakeRateLimit_Recv_Burst = 45, + K_ESteamNetworkingConfig_Callback_ConnectionStatusChanged = 201, + K_ESteamNetworkingConfig_Callback_AuthStatusChanged = 202, + K_ESteamNetworkingConfig_Callback_RelayNetworkStatusChanged = 203, + K_ESteamNetworkingConfig_Callback_MessagesSessionRequest = 204, + K_ESteamNetworkingConfig_Callback_MessagesSessionFailed = 205, + K_ESteamNetworkingConfig_Callback_CreateConnectionSignaling = 206, + K_ESteamNetworkingConfig_Callback_FakeIPResult = 207, + K_ESteamNetworkingConfig_P2P_STUN_ServerList = 103, + K_ESteamNetworkingConfig_P2P_Transport_ICE_Enable = 104, + K_ESteamNetworkingConfig_P2P_Transport_ICE_Penalty = 105, + K_ESteamNetworkingConfig_P2P_Transport_SDR_Penalty = 106, + K_ESteamNetworkingConfig_P2P_TURN_ServerList = 107, + K_ESteamNetworkingConfig_P2P_TURN_UserList = 108, + K_ESteamNetworkingConfig_P2P_TURN_PassList = 109, + K_ESteamNetworkingConfig_P2P_Transport_ICE_Implementation = 110, + K_ESteamNetworkingConfig_SDRClient_ConsecutitivePingTimeoutsFailInitial = 19, + K_ESteamNetworkingConfig_SDRClient_ConsecutitivePingTimeoutsFail = 20, + K_ESteamNetworkingConfig_SDRClient_MinPingsBeforePingAccurate = 21, + K_ESteamNetworkingConfig_SDRClient_SingleSocket = 22, + K_ESteamNetworkingConfig_SDRClient_ForceRelayCluster = 29, + K_ESteamNetworkingConfig_SDRClient_DebugTicketAddress = 30, + K_ESteamNetworkingConfig_SDRClient_ForceProxyAddr = 31, + K_ESteamNetworkingConfig_SDRClient_FakeClusterPing = 36, + K_ESteamNetworkingConfig_LogLevel_AckRTT = 13, + K_ESteamNetworkingConfig_LogLevel_PacketDecode = 14, + K_ESteamNetworkingConfig_LogLevel_Message = 15, + K_ESteamNetworkingConfig_LogLevel_PacketGaps = 16, + K_ESteamNetworkingConfig_LogLevel_P2PRendezvous = 17, + K_ESteamNetworkingConfig_LogLevel_SDRRelayPings = 18, + K_ESteamNetworkingConfig_DELETED_EnumerateDevVars = 35, + K_ESteamNetworkingConfigValue__Force32Bit = 2147483647, + }; + Q_ENUM(ESteamNetworkingConfigValue) + + enum class ESteamNetworkingGetConfigValueResult { + K_ESteamNetworkingGetConfigValue_BadValue = -1, + K_ESteamNetworkingGetConfigValue_BadScopeObj = -2, + K_ESteamNetworkingGetConfigValue_BufferTooSmall = -3, + K_ESteamNetworkingGetConfigValue_OK = 1, + K_ESteamNetworkingGetConfigValue_OKInherited = 2, + K_ESteamNetworkingGetConfigValueResult__Force32Bit = 2147483647, + }; + Q_ENUM(ESteamNetworkingGetConfigValueResult) + + enum class ESteamNetworkingSocketsDebugOutputType { + K_ESteamNetworkingSocketsDebugOutputType_None = 0, + K_ESteamNetworkingSocketsDebugOutputType_Bug = 1, + K_ESteamNetworkingSocketsDebugOutputType_Error = 2, + K_ESteamNetworkingSocketsDebugOutputType_Important = 3, + K_ESteamNetworkingSocketsDebugOutputType_Warning = 4, + K_ESteamNetworkingSocketsDebugOutputType_Msg = 5, + K_ESteamNetworkingSocketsDebugOutputType_Verbose = 6, + K_ESteamNetworkingSocketsDebugOutputType_Debug = 7, + K_ESteamNetworkingSocketsDebugOutputType_Everything = 8, + K_ESteamNetworkingSocketsDebugOutputType__Force32Bit = 2147483647, + }; + Q_ENUM(ESteamNetworkingSocketsDebugOutputType) + + enum class EServerMode { + EServerModeInvalid = 0, + EServerModeNoAuthentication = 1, + EServerModeAuthentication = 2, + EServerModeAuthenticationAndSecure = 3, + }; + Q_ENUM(EServerMode) +}; +} diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h b/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h index 4961572f..7e3d5db2 100644 --- a/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h +++ b/ScreenPlayUtil/inc/public/ScreenPlayUtil/util.h @@ -2,91 +2,125 @@ #pragma once -#include - -#if defined(Q_OS_WIN) - -// Must be first! -#include -// Do not sort ! -#include "WinUser.h" -#include -#endif - -#include "ScreenPlayUtil/contenttypes.h" +#include +#include +#include +#include +#include #include +#include #include #include #include +#include +#include +#include +#include +#include +#include #include +#include #include -#include +#include +#include #include -namespace ScreenPlayUtil { -#if defined(Q_OS_WIN) -struct WinMonitorStats { +#include "ScreenPlayUtil/contenttypes.h" - WinMonitorStats() - { - EnumDisplayMonitors(NULL, NULL, MonitorEnum, (LPARAM)this); +namespace ScreenPlay { + +template +T QStringToEnum(const QString& key, const T defaultValue) +{ + auto metaEnum = QMetaEnum::fromType(); + + bool ok = false; + T wantedEnum = static_cast(metaEnum.keyToValue(key.toUtf8(), &ok)); + + if (ok) { + return wantedEnum; + } else { + qWarning() << "Unable to convert QStringToEnum. Key: " << key; } - static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, - LPARAM pData) - { - WinMonitorStats* pThis = reinterpret_cast(pData); - auto scaleFactor = DEVICE_SCALE_FACTOR::DEVICE_SCALE_FACTOR_INVALID; - GetScaleFactorForMonitor(hMon, &scaleFactor); - - UINT x = 0; - UINT y = 0; - GetDpiForMonitor(hMon, MONITOR_DPI_TYPE::MDT_RAW_DPI, &x, &y); - pThis->sizes.push_back({ x, y }); - pThis->scaleFactor.push_back(scaleFactor); - pThis->hMonitors.push_back(hMon); - pThis->hdcMonitors.push_back(hdc); - pThis->rcMonitors.push_back(*lprcMonitor); - pThis->iMonitors.push_back(pThis->hdcMonitors.size()); - - // qInfo() << std::abs(lprcMonitor->right - lprcMonitor->left) << std::abs(lprcMonitor->top - lprcMonitor->bottom); - - return TRUE; - } - - std::vector iMonitors; - std::vector hMonitors; - std::vector hdcMonitors; - std::vector rcMonitors; - std::vector scaleFactor; - std::vector> sizes; - int index = 0; -}; -#endif -QJsonArray fillArray(const QVector& items); -ScreenPlay::SearchType::SearchType getSearchTypeFromInstalledType(const ScreenPlay::InstalledType::InstalledType type); -std::optional getInstalledTypeFromString(const QString& type); -std::optional getVideoCodecFromString(const QString& type); -std::optional parseQByteArrayToQJsonObject(const QByteArray& byteArray); -std::optional openJsonFileToObject(const QString& path); -std::optional openJsonFileToString(const QString& path); -std::optional getVersionNumberFromString(const QString& str); -bool writeJsonObjectToFile(const QString& absoluteFilePath, const QJsonObject& object, bool truncate = true); -bool writeSettings(const QJsonObject& obj, const QString& absolutePath); -bool writeFile(const QString& text, const QString& absolutePath); -bool writeFileFromQrc(const QString& qrcPath, const QString& absolutePath); -bool copyPreviewThumbnail(QJsonObject& obj, const QString& previewThumbnail, const QString& destination); -QString toString(const QStringList& list); -QString toLocal(const QString& url); -QString generateRandomString(quint32 length = 32); -QString executableAppEnding(); -QString executableBinEnding(); -QStringList getAvailableWallpaper(); -QStringList getAvailableWidgets(); -QStringList getAvailableTypes(); -QStringList getAvailableFillModes(); -bool isWallpaper(const ScreenPlay::InstalledType::InstalledType type); -bool isWidget(const ScreenPlay::InstalledType::InstalledType type); -std::optional> parseStringToIntegerList(const QString string); -float roundDecimalPlaces(const float number); + return defaultValue; +} + +class Util : public QObject { + Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("") + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +public: + QJsonArray fillArray(const QVector& items); + ScreenPlay::ContentTypes::SearchType getSearchTypeFromInstalledType(const ScreenPlay::ContentTypes::InstalledType type); + std::optional getInstalledTypeFromString(const QString& type); + std::optional getVideoCodecFromString(const QString& type); + std::optional parseQByteArrayToQJsonObject(const QByteArray& byteArray); + std::optional openJsonFileToObject(const QString& path); + std::optional openJsonFileToString(const QString& path); + std::optional getVersionNumberFromString(const QString& str); + bool writeJsonObjectToFile(const QString& absoluteFilePath, const QJsonObject& object, bool truncate = true); + bool writeSettings(const QJsonObject& obj, const QString& absolutePath); + bool writeFile(const QString& text, const QString& absolutePath); + bool writeFileFromQrc(const QString& qrcPath, const QString& absolutePath); + bool copyPreviewThumbnail(QJsonObject& obj, const QString& previewThumbnail, const QString& destination); + QString toString(const QStringList& list) const; + std::optional> parseStringToIntegerList(const QString string) const; + float roundDecimalPlaces(const float number) const; + QString generateRandomString(quint32 length = 32); + QString executableAppEnding(); + QString executableBinEnding(); + QStringList getAvailableWallpaper() const; + QStringList getAvailableWidgets() const; + QStringList getAvailableTypes() const; + QStringList getAvailableFillModes() const; + // QML callable functions + Q_INVOKABLE QString toLocal(const QString& url) const; + + Q_INVOKABLE bool isWallpaper(const ScreenPlay::ContentTypes::InstalledType type) const; + Q_INVOKABLE bool isWidget(const ScreenPlay::ContentTypes::InstalledType type) const; + Q_INVOKABLE bool isScene(const ScreenPlay::ContentTypes::InstalledType type) const; + Q_INVOKABLE bool isVideo(const ScreenPlay::ContentTypes::InstalledType type) const; + + Q_INVOKABLE void copyToClipboard(const QString& text) const; + Q_INVOKABLE void openFolderInExplorer(const QString& url) const; + Q_INVOKABLE bool openGodotEditor(QString contentPath, QString godotEditorExecutablePath) const; + Q_INVOKABLE void requestAllLicenses(); + Q_INVOKABLE void requestDataProtection(); + Q_INVOKABLE bool fileExists(const QString& filePath) const; + + Q_INVOKABLE void setNavigation(QString nav) + { + emit requestNavigation(nav); + } + + // When we create a wallpaper the main navigation gets disabled + Q_INVOKABLE void setNavigationActive(bool isActive) + { + emit requestNavigationActive(isActive); + } + + Q_INVOKABLE void setToggleWallpaperConfiguration() + { + emit requestToggleWallpaperConfiguration(); + } + +signals: + void extractionProgressChanged(QString file, int proc, int total, qint64 br, qint64 bt); + void extractionFinished(); + void compressionProgressChanged(QString file, int proc, int total, qint64 br, qint64 bt); + void compressionFinished(); + + void requestNavigation(QString nav); + void requestNavigationActive(bool isActive); + void requestToggleWallpaperConfiguration(); + void setSidebarItem(QString folderName, ScreenPlay::ContentTypes::InstalledType type); + void allLicenseLoaded(QString licensesText); + void allDataProtectionLoaded(QString dataProtectionText); + +private: + QFuture m_requestAllLicensesFuture; +}; } diff --git a/ScreenPlayUtil/qml/Dialogs/CriticalError.qml b/ScreenPlayUtil/qml/Dialogs/CriticalError.qml index 71680f9e..0c068f7a 100644 --- a/ScreenPlayUtil/qml/Dialogs/CriticalError.qml +++ b/ScreenPlayUtil/qml/Dialogs/CriticalError.qml @@ -15,7 +15,7 @@ Util.Dialog { property string message standardButtons: Dialog.Ok | Dialog.Help onHelpRequested: { - Qt.openUrlExternally("https://forum.screen-play.app/category/7/troubleshooting"); + Qt.openUrlExternally("https://forum.screen-play.app/"); } Connections { @@ -29,8 +29,8 @@ Util.Dialog { } contentItem: Item { - width: 600 - height: 400 + implicitWidth: 600 + implicitHeight: 400 ColumnLayout { anchors.margins: 20 diff --git a/ScreenPlayUtil/qml/JSUtil.js b/ScreenPlayUtil/qml/JSUtil.js index 1d552bb4..7c0d85d3 100644 --- a/ScreenPlayUtil/qml/JSUtil.js +++ b/ScreenPlayUtil/qml/JSUtil.js @@ -1,25 +1,25 @@ function isWallpaper(type) { - return type === InstalledType.VideoWallpaper - || type === InstalledType.HTMLWallpaper - || type === InstalledType.QMLWallpaper - || type === InstalledType.GifWallpaper - || type === InstalledType.WebsiteWallpaper - || type === InstalledType.GodotWallpaper + return type === ContentTypes.InstalledType.VideoWallpaper + || type === ContentTypes.InstalledType.HTMLWallpaper + || type === ContentTypes.InstalledType.QMLWallpaper + || type === ContentTypes.InstalledType.GifWallpaper + || type === ContentTypes.InstalledType.WebsiteWallpaper + || type === ContentTypes.InstalledType.GodotWallpaper } function isWidget(type) { - return type === InstalledType.HTMLWidget || type === InstalledType.QMLWidget + return type === ContentTypes.InstalledType.HTMLWidget || type === ContentTypes.InstalledType.QMLWidget } function isScene(type) { - return type === InstalledType.HTMLWallpaper - || type === InstalledType.QMLWallpaper - || type === InstalledType.WebsiteWallpaper - || type === InstalledType.GodotWallpaper + return type === ContentTypes.InstalledType.HTMLWallpaper + || type === ContentTypes.InstalledType.QMLWallpaper + || type === ContentTypes.InstalledType.WebsiteWallpaper + || type === ContentTypes.InstalledType.GodotWallpaper } function isVideo(type) { - return type === InstalledType.VideoWallpaper - || type === InstalledType.GifWallpaper + return type === ContentTypes.InstalledType.VideoWallpaper + || type === ContentTypes.InstalledType.GifWallpaper } diff --git a/ScreenPlayUtil/src/archive.cpp b/ScreenPlayUtil/src/archive.cpp new file mode 100644 index 00000000..ef7321ad --- /dev/null +++ b/ScreenPlayUtil/src/archive.cpp @@ -0,0 +1,90 @@ +#include "ScreenPlayUtil/archive.h" +#include "ScreenPlayUtil/util.h" +namespace ScreenPlay { + +Archive::Archive(QObject* parent) + : QObject { parent } +{ + + m_extractor = std::make_unique(); + m_compressor = std::make_unique(); + QObject::connect(m_extractor.get(), &QArchive::DiskExtractor::progress, this, &Archive::extractionProgressChanged); + QObject::connect(m_extractor.get(), &QArchive::DiskExtractor::finished, this, &Archive::extractionFinished); + + QObject::connect(m_compressor.get(), &QArchive::DiskCompressor::progress, this, &Archive::compressionProgressChanged); + QObject::connect(m_compressor.get(), &QArchive::DiskCompressor::finished, this, &Archive::compressionFinished); +} + +/*! + \brief Imports a given project from a .screenplay zip file. The argument extractionPath + must be copied otherwise it will get reset in qml before extracting. +*/ +bool Archive::importProject(QString archivePath, QString extractionPath) +{ + m_extractor->clear(); + Util util; + archivePath = util.toLocal(archivePath); + extractionPath = util.toLocal(extractionPath); + + QFileInfo fileInfo(archivePath); + if (!fileInfo.fileName().endsWith(".screenplay")) { + qWarning() << "Unsupported file type: " << fileInfo.fileName() << ". We only support '.screenplay' files."; + return false; + } + const QString name = fileInfo.fileName().remove(".screenplay"); + + const auto timestamp = QDateTime::currentDateTime().toString("ddMMyyyyhhmmss-"); + extractionPath = extractionPath + "/" + timestamp + name + "/"; + QDir dir(extractionPath); + + if (dir.exists()) { + qWarning() << "Directory does already exist!" << dir; + return false; + } + + if (!dir.mkdir(extractionPath)) { + qWarning() << "Unable to create directory:" << dir; + return false; + } + + m_extractor->setArchive(archivePath); + m_extractor->setOutputDirectory(extractionPath); + m_extractor->setCalculateProgress(true); + m_extractor->getInfo(); + m_extractor->start(); + return true; +} +/*! + \brief Exports a given project into a .screenplay 7Zip file. +*/ +bool Archive::exportProject(QString contentPath, QString exportFileName) +{ + m_compressor->clear(); + Util util; + contentPath = util.toLocal(contentPath); + exportFileName = util.toLocal(exportFileName); + + QDir dir(contentPath); + bool success = true; + if (!dir.exists()) { + qWarning() << "Directory does not exist!" << dir; + return false; + } + QStringList files; + for (auto& item : dir.entryInfoList(QDir::Files)) { + files.append(item.absoluteFilePath()); + } + QFile exportFile(exportFileName); + if (exportFile.exists()) { + if (!exportFile.remove()) { + qWarning() << "Unable to delte file marked to override!" << dir; + return false; + } + } + m_compressor->setFileName(exportFileName); + m_compressor->setArchiveFormat(QArchive::SevenZipFormat); + m_compressor->addFiles(files); + m_compressor->start(); + return true; +} +} diff --git a/ScreenPlayUtil/src/contenttypes.cpp b/ScreenPlayUtil/src/contenttypes.cpp index edc9b269..c68b8d90 100644 --- a/ScreenPlayUtil/src/contenttypes.cpp +++ b/ScreenPlayUtil/src/contenttypes.cpp @@ -1,6 +1,14 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "ScreenPlayUtil/contenttypes.h" -namespace ScreenPlayUtil { - +namespace ScreenPlay { +ContentTypes::ContentTypes(QObject* parent) + : QObject(parent) +{ +} + +Video::Video(QObject* parent) + : QObject(parent) +{ +} } diff --git a/ScreenPlayUtil/src/exitcodes.cpp b/ScreenPlayUtil/src/exitcodes.cpp new file mode 100644 index 00000000..ec9c5ff5 --- /dev/null +++ b/ScreenPlayUtil/src/exitcodes.cpp @@ -0,0 +1,9 @@ +// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only +#include "ScreenPlayUtil/exitcodes.h" + +namespace ScreenPlay { +WallpaperExit::WallpaperExit(QObject* parent) + : QObject(parent) +{ +} +} diff --git a/ScreenPlayUtil/inc/public/ScreenPlayUtil/httpfileserver.cpp b/ScreenPlayUtil/src/httpfileserver.cpp similarity index 100% rename from ScreenPlayUtil/inc/public/ScreenPlayUtil/httpfileserver.cpp rename to ScreenPlayUtil/src/httpfileserver.cpp diff --git a/ScreenPlayUtil/src/logginghandler.cpp b/ScreenPlayUtil/src/logginghandler.cpp new file mode 100644 index 00000000..5c61f061 --- /dev/null +++ b/ScreenPlayUtil/src/logginghandler.cpp @@ -0,0 +1,273 @@ +#include "ScreenPlayUtil/logginghandler.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ScreenPlayUtil/CMakeVariables.h" + +#ifdef Q_OS_WINDOWS +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include +#endif + +/*! + \class ScreenPlayUtil::LoggingHandler + \brief The LoggingHandler class writes logs to the console and a log file. +*/ + +namespace ScreenPlayUtil { +QString LoggingHandler::m_logFileName; + +LoggingHandler::LoggingHandler(const QString& logFileName) + : QObject() +{ +#ifdef Q_OS_WINDOWS + // Enable UTF-8 support + SetConsoleOutputCP(CP_UTF8); + // This is a QtCreator workaround and crashes std::fmt + // when running standalone. + if (!SCREENPLAY_DEPLOY_VERSION) { + // QtCreator has issues with fmt prints + // https://bugreports.qt.io/browse/QTCREATORBUG-3994 + setvbuf(stdout, NULL, _IONBF, 0); + qInfo() << "Setting setvbuf(stdout, NULL, _IONBF, 0); This unbuffered output causes crashes in release with threaded fmt!"; + } +#endif + + qSetMessagePattern("[%{time dd.MM.yyyy h:mm:ss.zzz} %{if-debug}Debug%{endif}%{if-info}Info%{endif}%{if-warning}Warning%{endif}%{if-critical}Critical%{endif}%{if-fatal}Fatal%{endif}] %{file}:%{line} - %{message}"); + qInstallMessageHandler(LoggingHandler::loggingMessageHandler); + const auto lock = std::lock_guard(logFileMutex()); + m_logFileName = logFileName; + start(); +} + +LoggingHandler::~LoggingHandler() +{ + const auto lock = std::lock_guard(logFileMutex()); + stop(); +} + +void LoggingHandler::start() +{ + Q_ASSERT(!m_logFileName.isEmpty()); + + QDir directory; + QString cacheDir = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation); + directory = QDir(cacheDir + "/ScreenPlay/Logs"); + if (!directory.exists()) { + if (!directory.mkpath(directory.path())) { + qCritical() << "Unable to create logging path at:" << directory.path(); + return; + } + } + + QString filePath; + for (++logFileCounter(); logFileCounter() < 1000; ++logFileCounter()) { + const auto dateTime = QDateTime::currentDateTime().toString("yy-MM-dd"); + const auto fileName = QString { "%1-%2-%3.log" }.arg(dateTime).arg(m_logFileName).arg(QString::number(logFileCounter())); + filePath = directory.path() + "/" + fileName; + auto file = QFile { filePath }; + if (!file.exists()) + break; + if (file.size() <= m_maxFileSize) + break; + } + + logFile().setFileName(filePath); + const auto isOpen = logFile().open(QIODevice::Append | QIODevice::Text); + if (!isOpen) { + qCritical() << "Unable to open log file" << logFile().fileName(); + return; + } + + const auto now = QLocale().toString(QDateTime::currentDateTime(), QLocale::FormatType::ShortFormat); + const auto message = QString { "[%1] Start logging\n" }.arg(now); + logFile().write(message.toStdString().c_str()); +} + +void LoggingHandler::stop() +{ + const auto now = QLocale().toString(QDateTime::currentDateTime(), QLocale::FormatType::ShortFormat); + const auto message = QString { "[%1] Stop logging\n\n" }.arg(now); + logFile().write(message.toStdString().c_str()); + logFile().close(); +} + +std::mutex& LoggingHandler::logFileMutex() +{ + static std::mutex mutex; + return mutex; +} + +size_t& LoggingHandler::logFileCounter() +{ + static size_t counter = 0; + return counter; +} + +QFile& LoggingHandler::logFile() +{ + static QFile file; + return file; +} + +/*! + \brief Returns a formatted logging line. + + Format: "[]|.|:||\n" + + If possible, this format should not be changed, otherwise the subsequent parsing of the log file will be very difficult. + */ +QString LoggingHandler::logLine(QtMsgType type, const QMessageLogContext& context, const QString& message) +{ + const auto now = QLocale().toString(QDateTime::currentDateTime(), QLocale::FormatType::ShortFormat); + const auto filename = extractFileName(context); + const auto function = extractFunction(context); + auto category = QString(context.category); + if (category == "default") + category = ""; + + return QString("[%1] %2.%3 | %4:%5 | %6 | %7\n").arg(now).arg(category).arg(toString(type)).arg(filename).arg(context.line).arg(function).arg(message); +} + +QString LoggingHandler::toString(QtMsgType type) +{ + switch (type) { + case QtDebugMsg: + return "Debug"; + case QtWarningMsg: + return "Warning"; + case QtCriticalMsg: + return "Critical"; + case QtFatalMsg: + return "Fatal"; + case QtInfoMsg: + return "Info"; + default: + return "?"; + } +} + +QString LoggingHandler::extractFileName(const QMessageLogContext& context) +{ + auto file = QString(context.file); + return file.mid(file.lastIndexOf("\\")).remove("\\"); +} + +/*! + \brief Removes all the unreadable type stuff from the function information in \a context. + */ +QString LoggingHandler::extractFunction(const QMessageLogContext& context) +{ + auto func = QString(context.function); + + auto from = -1; + if (from < 0) { + static const QString search { "__thiscall" }; + from = func.indexOf(search); + if (from >= 0) { + from += search.length(); + } + } + if (from < 0) { + static const QString search { "__cdecl" }; + from = func.indexOf(search); + if (from >= 0) { + from += search.length(); + } + } + if (from < 0) { + from = 0; + } + + auto to = func.indexOf("(", from); + if (to < 0) + return func; + + auto length = to - from; + return func.mid(from, length).trimmed(); +} + +/*! + * \brief LoggingHandler::writeToConsole + * std::flush is used to fix QtCreator not printing output. + */ +void LoggingHandler::writeToConsole(QtMsgType type, const QMessageLogContext& context, const QString& message) +{ + constexpr auto darkMode = true; + auto color = fmt::color::black; + QString typeIndicator; + + switch (type) { + case QtDebugMsg: + color = fmt::color::green; + typeIndicator = "Debug"; + break; + case QtWarningMsg: + color = fmt::color::orange; + typeIndicator = "Warning"; + break; + case QtCriticalMsg: + color = fmt::color::magenta; + typeIndicator = "Critical"; + break; + case QtFatalMsg: + color = fmt::color::red; + typeIndicator = "Fatal"; + break; + default: + color = darkMode ? fmt::color::gray : fmt::color::black; + typeIndicator = "Info"; // Assuming default is info + break; + } + + const auto now = QDateTime::currentDateTime().toString("dd.MM.yyyy h:mm:ss.zzz"); + const auto filename = extractFileName(context); + const auto function = extractFunction(context); + const auto line = context.line; + fmt::print( + "[{}] {} {}:{} - {}\n", + fmt::styled(now.toStdString(), fmt::emphasis::bold), + fmt::styled(typeIndicator.toStdString(), fg(color)), + function.toStdString(), // Replace with context.file when QTCREATORBUG-24353 is fixed + line, + message.toStdString()); +} + +void LoggingHandler::writeToFile(const QString& line) +{ + std::lock_guard lock(logFileMutex()); + if (logFile().isOpen()) { + checkLogRotation(); + logFile().write(line.toStdString().c_str()); + } +} + +/*! + \brief Opens a new log file if the current log file becomes too large. + */ +void LoggingHandler::checkLogRotation() +{ + if (logFile().size() <= m_maxFileSize) + return; + + logFile().write("Maximum file size reached. A new log file is used\n"); + qInfo() << "Rotate Log file"; + stop(); + start(); +} + +void LoggingHandler::loggingMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) +{ + const QString line = LoggingHandler::logLine(type, context, message); + LoggingHandler::writeToConsole(type, context, message); + LoggingHandler::writeToFile(line); +} +} diff --git a/ScreenPlayUtil/src/projectfile.cpp b/ScreenPlayUtil/src/projectfile.cpp index d0e899bd..89d428cc 100644 --- a/ScreenPlayUtil/src/projectfile.cpp +++ b/ScreenPlayUtil/src/projectfile.cpp @@ -7,7 +7,8 @@ bool ProjectFile::init() if (!isValid()) return false; - const auto jsonObjOpt = ScreenPlayUtil::openJsonFileToObject(projectJsonFilePath.absoluteFilePath()); + Util util; + const auto jsonObjOpt = util.openJsonFileToObject(projectJsonFilePath.absoluteFilePath()); QDir folder = projectJsonFilePath.dir(); folderName = folder.dirName(); QFileInfo folderInfo(folder.path()); @@ -22,17 +23,6 @@ bool ProjectFile::init() if (obj.isEmpty()) return false; - // Required: - if (!obj.contains("file")) - return false; - file = obj.value("file").toString(); - - QFileInfo fileInfo(folder.path() + "/" + file); - if (!fileInfo.exists()) { - qCritical() << "Requested file:" << fileInfo.absoluteFilePath() << "does not exist!"; - return false; - } - if (!obj.contains("title")) return false; title = obj.value("title").toString(); @@ -40,13 +30,35 @@ bool ProjectFile::init() if (!obj.contains("type")) return false; - auto typeParsed = ScreenPlayUtil::getInstalledTypeFromString(obj.value("type").toString()); + auto typeParsed = util.getInstalledTypeFromString(obj.value("type").toString()); if (!typeParsed.has_value()) { qWarning() << "Type could not parsed from string: " << obj.value("type").toString(); return false; } type = typeParsed.value(); + // File is required. Website Wallpaper doe not have a file, but a url + if (!obj.contains("file") && type != ScreenPlay::ContentTypes::InstalledType::WebsiteWallpaper) + return false; + + if (type != ScreenPlay::ContentTypes::InstalledType::WebsiteWallpaper) { + file = obj.value("file").toString(); + + if (type == ScreenPlay::ContentTypes::InstalledType::GodotWallpaper) { + QFileInfo fileInfo(folder.path() + "/wallpaper.tscn"); + if (!fileInfo.exists()) { + qCritical() << "Requested file:" << fileInfo.absoluteFilePath() << "does not exist!"; + return false; + } + } else { + QFileInfo fileInfo(folder.path() + "/" + file); + if (!fileInfo.exists()) { + qCritical() << "Requested file:" << fileInfo.absoluteFilePath() << "does not exist!"; + return false; + } + } + } + // Optional: if (!obj.contains("description")) description = obj.value("description").toString(); @@ -78,36 +90,36 @@ bool ProjectFile::init() } } - if (type == InstalledType::InstalledType::GifWallpaper) { + if (type == ContentTypes::InstalledType::GifWallpaper) { preview = previewGIF; } - if (type == ScreenPlay::InstalledType::InstalledType::WebsiteWallpaper) { + if (type == ContentTypes::InstalledType::WebsiteWallpaper) { if (url.isEmpty()) { qWarning() << "No url was specified for a websiteWallpaper!"; return false; } } - searchType = ScreenPlayUtil::getSearchTypeFromInstalledType(type); + searchType = util.getSearchTypeFromInstalledType(type); if (obj.contains("codec")) { - if (auto videoCodecOpt = ScreenPlayUtil::getVideoCodecFromString(obj.value("codec").toString())) { + if (auto videoCodecOpt = util.getVideoCodecFromString(obj.value("codec").toString())) { videoCodec = videoCodecOpt.value(); } else { qWarning("Invalid videoCodec was specified inside the json object!"); } - } else if (type == ScreenPlay::InstalledType::InstalledType::VideoWallpaper) { - qWarning("No videoCodec was specified inside the json object!"); + } else if (type == ScreenPlay::ContentTypes::InstalledType::VideoWallpaper) { + // qWarning("No videoCodec was specified inside the json object!"); if (file.endsWith(".mp4")) { - videoCodec = ScreenPlay::VideoCodec::VideoCodec::H264; - qWarning("Eyeball to h264 because of .mp4"); + videoCodec = ScreenPlay::Video::VideoCodec::H264; + // qWarning("Eyeball to h264 because of .mp4"); } else if (file.endsWith(".webm")) { - videoCodec = ScreenPlay::VideoCodec::VideoCodec::VP8; - qWarning("Eyeball to VP8 because of .webm"); + videoCodec = ScreenPlay::Video::VideoCodec::VP8; + // qWarning("Eyeball to VP8 because of .webm"); } } - if (type == ScreenPlay::InstalledType::InstalledType::VideoWallpaper) { + if (type == ScreenPlay::ContentTypes::InstalledType::VideoWallpaper) { QFileInfo audioFile(folder.absolutePath() + "/audio.mp3"); containsAudio = audioFile.exists(); } diff --git a/ScreenPlayUtil/src/steamenumsgenerated.cpp b/ScreenPlayUtil/src/steamenumsgenerated.cpp new file mode 100644 index 00000000..efbc1149 --- /dev/null +++ b/ScreenPlayUtil/src/steamenumsgenerated.cpp @@ -0,0 +1,7 @@ +#include "ScreenPlayUtil/steamenumsgenerated.h" + +namespace ScreenPlay { +Steam::Steam() +{ +} +} diff --git a/ScreenPlayUtil/src/util.cpp b/ScreenPlayUtil/src/util.cpp index eaf02123..b0cb7c7b 100644 --- a/ScreenPlayUtil/src/util.cpp +++ b/ScreenPlayUtil/src/util.cpp @@ -1,5 +1,7 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "ScreenPlayUtil/util.h" +#include "qguiapplication.h" +#include #include #include #include @@ -10,18 +12,18 @@ \brief Module for ScreenPlayUtil. */ /*! - \namespace ScreenPlayUtil + \namespace ScreenPlay \inmodule ScreenPlayUtil \brief Namespace for ScreenPlayUtil. */ -namespace ScreenPlayUtil { +namespace ScreenPlay { /*! \brief Opens a json file (absolute path) and tries to convert it to a QJsonObject. Returns std::nullopt when not successful. */ -std::optional openJsonFileToObject(const QString& path) +std::optional Util::openJsonFileToObject(const QString& path) { auto jsonString = openJsonFileToString(path); @@ -45,7 +47,7 @@ std::optional openJsonFileToObject(const QString& path) \brief Writes a QJsonObject into a given file. It defaults to truncate the file or you can set it to append to an existing file. */ -bool writeJsonObjectToFile(const QString& absoluteFilePath, const QJsonObject& object, bool truncate) +bool Util::writeJsonObjectToFile(const QString& absoluteFilePath, const QJsonObject& object, bool truncate) { QFile configTmp; configTmp.setFileName(absoluteFilePath); @@ -69,11 +71,78 @@ bool writeJsonObjectToFile(const QString& absoluteFilePath, const QJsonObject& o return true; } +/*! + \brief Takes ownership of \a obj and \a name. Tries to save into a text file + with of name. +*/ +bool Util::writeSettings(const QJsonObject& obj, const QString& absolutePath) +{ + QFile file { absolutePath }; + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + qDebug() << "Could not open" << absolutePath; + return false; + } + + QTextStream out(&file); + out.setEncoding(QStringConverter::Utf8); + QJsonDocument doc(obj); + + out << doc.toJson(); + + file.close(); + return true; +} +/*! + \brief Tries to save into a text file with absolute path. +*/ +bool Util::writeFile(const QString& text, const QString& absolutePath) +{ + QFile file { absolutePath }; + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + qDebug() << "Could not open" << absolutePath; + return false; + } + + QTextStream out(&file); + out.setEncoding(QStringConverter::Utf8); + out << text; + + file.close(); + return true; +} +/*! + \brief Tries to save into a text file with absolute path. +*/ +bool Util::writeFileFromQrc(const QString& qrcPath, const QString& absolutePath) +{ + + QFile file { absolutePath }; + if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { + qDebug() << "Could not open" << absolutePath; + return false; + } + + QTextStream out(&file); + out.setEncoding(QStringConverter::Utf8); + + QFile qrc(qrcPath); + qrc.open(QIODevice::ReadOnly); + + QTextStream in(&qrc); + // Read line by line to avoid CLRF/LF issues + while (!in.atEnd()) { + out << in.readLine() << "\n"; + } + + qrc.close(); + file.close(); + return true; +} /*! \brief Opens a json file (absolute path) and tries to convert it to a QString. Returns std::nullopt when not successful. */ -std::optional openJsonFileToString(const QString& path) +std::optional Util::openJsonFileToString(const QString& path) { QFile file; file.setFileName(path); @@ -96,7 +165,7 @@ std::optional openJsonFileToString(const QString& path) \li 0-9 \endlist */ -QString generateRandomString(quint32 length) +QString Util::generateRandomString(quint32 length) { const QString possibleCharacters { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" @@ -115,7 +184,7 @@ QString generateRandomString(quint32 length) /*! \brief Return .exe on windows otherwise empty string. */ -QString executableBinEnding() +QString Util::executableBinEnding() { #ifdef Q_OS_WIN return ".exe"; @@ -126,12 +195,12 @@ QString executableBinEnding() /*! \brief Return .exe on windows, .app on osx otherwise empty string. */ -QString executableAppEnding() +QString Util::executableAppEnding() { #ifdef Q_OS_WIN return ".exe"; #endif -#ifdef Q_OS_OSX +#ifdef Q_OS_MACOS return ".app"; #endif return ""; @@ -142,7 +211,7 @@ QString executableAppEnding() 1.0.0 - Major.Minor.Patch. A fixed position is used for parsing (at 0,2,4). Return std::nullopt when not successful. */ -std::optional getVersionNumberFromString(const QString& str) +std::optional Util::getVersionNumberFromString(const QString& str) { // Must be: Major.Minor.Patch bool okMajor { false }; @@ -163,7 +232,7 @@ std::optional getVersionNumberFromString(const QString& str) /*! \brief Parses a QByteArray to a QJsonObject. If returns and std::nullopt on failure. */ -std::optional parseQByteArrayToQJsonObject(const QByteArray& byteArray) +std::optional Util::parseQByteArrayToQJsonObject(const QByteArray& byteArray) { QJsonObject obj; QJsonParseError err {}; @@ -180,7 +249,7 @@ std::optional parseQByteArrayToQJsonObject(const QByteArray& byteAr /*! \brief Helper function to append a QStringList into a QString with a space between the items. */ -QString toString(const QStringList& list) +QString Util::toString(const QStringList& list) const { QString out; for (const auto& string : list) { @@ -192,7 +261,7 @@ QString toString(const QStringList& list) /*! \brief Util function that converts a QVector of Strings into a QJsonArray. */ -QJsonArray fillArray(const QVector& items) +QJsonArray Util::fillArray(const QVector& items) { QJsonArray array; for (const QString& item : items) { @@ -204,63 +273,60 @@ QJsonArray fillArray(const QVector& items) /*! \brief Maps the Search type to an installed type. Used for filtering the installed content. */ -ScreenPlay::SearchType::SearchType getSearchTypeFromInstalledType(const ScreenPlay::InstalledType::InstalledType type) +ScreenPlay::ContentTypes::SearchType Util::getSearchTypeFromInstalledType(const ScreenPlay::ContentTypes::InstalledType type) { - using ScreenPlay::InstalledType::InstalledType; - using ScreenPlay::SearchType::SearchType; - + using namespace ScreenPlay; switch (type) { - case InstalledType::GodotWallpaper: - case InstalledType::HTMLWallpaper: - case InstalledType::QMLWallpaper: - case InstalledType::GifWallpaper: - case InstalledType::WebsiteWallpaper: - return SearchType::Scene; - case InstalledType::VideoWallpaper: - return SearchType::Wallpaper; - case InstalledType::HTMLWidget: - case InstalledType::QMLWidget: - return SearchType::Widget; - case InstalledType::Unknown: + case ContentTypes::InstalledType::GodotWallpaper: + case ContentTypes::InstalledType::HTMLWallpaper: + case ContentTypes::InstalledType::QMLWallpaper: + case ContentTypes::InstalledType::GifWallpaper: + case ContentTypes::InstalledType::WebsiteWallpaper: + return ContentTypes::SearchType::Scene; + case ContentTypes::InstalledType::VideoWallpaper: + return ContentTypes::SearchType::Wallpaper; + case ContentTypes::InstalledType::HTMLWidget: + case ContentTypes::InstalledType::QMLWidget: + return ContentTypes::SearchType::Widget; + case ContentTypes::InstalledType::Unknown: default: - return SearchType::All; + return ContentTypes::SearchType::All; } } /*! \brief Maps the installed type from a QString to an enum. Used for parsing the project.json. */ -std::optional getInstalledTypeFromString(const QString& type) +std::optional Util::getInstalledTypeFromString(const QString& type) { - using ScreenPlay::InstalledType::InstalledType; - + using namespace ScreenPlay; if (type.endsWith("Wallpaper", Qt::CaseInsensitive)) { if (type.startsWith("video", Qt::CaseInsensitive)) { - return InstalledType::VideoWallpaper; + return ContentTypes::InstalledType::VideoWallpaper; } if (type.startsWith("qml", Qt::CaseInsensitive)) { - return InstalledType::QMLWallpaper; + return ContentTypes::InstalledType::QMLWallpaper; } if (type.startsWith("html", Qt::CaseInsensitive)) { - return InstalledType::HTMLWallpaper; + return ContentTypes::InstalledType::HTMLWallpaper; } if (type.startsWith("godot", Qt::CaseInsensitive)) { - return InstalledType::GodotWallpaper; + return ContentTypes::InstalledType::GodotWallpaper; } if (type.startsWith("website", Qt::CaseInsensitive)) { - return InstalledType::WebsiteWallpaper; + return ContentTypes::InstalledType::WebsiteWallpaper; } if (type.startsWith("gif", Qt::CaseInsensitive)) { - return InstalledType::GifWallpaper; + return ContentTypes::InstalledType::GifWallpaper; } } if (type.endsWith("Widget", Qt::CaseInsensitive)) { if (type.startsWith("qml", Qt::CaseInsensitive)) { - return InstalledType::QMLWidget; + return ContentTypes::InstalledType::QMLWidget; } if (type.startsWith("html", Qt::CaseInsensitive)) { - return InstalledType::HTMLWidget; + return ContentTypes::InstalledType::HTMLWidget; } } @@ -270,25 +336,25 @@ std::optional getInstalledTypeFromStri /*! \brief Maps the video codec type from a QString to an enum. Used for parsing the project.json. */ -std::optional getVideoCodecFromString(const QString& type) +std::optional Util::getVideoCodecFromString(const QString& type) { if (type.isEmpty()) return std::nullopt; if (type.contains("vp8", Qt::CaseInsensitive)) - return ScreenPlay::VideoCodec::VideoCodec::VP8; + return ScreenPlay::Video::VideoCodec::VP8; if (type.contains("vp9", Qt::CaseInsensitive)) - return ScreenPlay::VideoCodec::VideoCodec::VP9; + return ScreenPlay::Video::VideoCodec::VP9; if (type.contains("av1", Qt::CaseInsensitive)) - return ScreenPlay::VideoCodec::VideoCodec::AV1; + return ScreenPlay::Video::VideoCodec::AV1; if (type.contains("h264", Qt::CaseInsensitive)) - return ScreenPlay::VideoCodec::VideoCodec::H264; + return ScreenPlay::Video::VideoCodec::H264; if (type.contains("h265", Qt::CaseInsensitive)) - return ScreenPlay::VideoCodec::VideoCodec::H264; + return ScreenPlay::Video::VideoCodec::H264; return std::nullopt; } @@ -296,7 +362,7 @@ std::optional getVideoCodecFromString(const /*! \brief Converts the given \a url string to a local file path. */ -QString toLocal(const QString& url) +QString Util::toLocal(const QString& url) const { return QUrl(url).toLocalFile(); } @@ -304,7 +370,7 @@ QString toLocal(const QString& url) /*! \brief Returns a list of available wallpaper types like videoWallpaper. */ -QStringList getAvailableWallpaper() +QStringList Util::getAvailableWallpaper() const { return { "qmlWallpaper", @@ -319,7 +385,7 @@ QStringList getAvailableWallpaper() /*! \brief Returns a list of available widget types like qmlWidget. */ -QStringList getAvailableWidgets() +QStringList Util::getAvailableWidgets() const { return { "qmlWidget", @@ -330,7 +396,7 @@ QStringList getAvailableWidgets() /*! \brief Returns a combined list of available widgets and wallpaper types. */ -QStringList getAvailableTypes() +QStringList Util::getAvailableTypes() const { return { getAvailableWallpaper() + getAvailableWidgets() }; } @@ -338,35 +404,55 @@ QStringList getAvailableTypes() /*! \brief Returns true of the given type is a wallpaper. */ -bool isWallpaper(const ScreenPlay::InstalledType::InstalledType type) +bool Util::isWallpaper(const ScreenPlay::ContentTypes::InstalledType type) const { - using ScreenPlay::InstalledType::InstalledType; - - return (type == InstalledType::VideoWallpaper - || type == InstalledType::QMLWallpaper - || type == InstalledType::HTMLWallpaper - || type == InstalledType::GifWallpaper - || type == InstalledType::WebsiteWallpaper - || type == InstalledType::GodotWallpaper); + using namespace ScreenPlay; + return (type == ContentTypes::InstalledType::VideoWallpaper + || type == ContentTypes::InstalledType::QMLWallpaper + || type == ContentTypes::InstalledType::HTMLWallpaper + || type == ContentTypes::InstalledType::GifWallpaper + || type == ContentTypes::InstalledType::WebsiteWallpaper + || type == ContentTypes::InstalledType::GodotWallpaper); } /*! \brief Returns true of the given type is a widget. */ -bool isWidget(const ScreenPlay::InstalledType::InstalledType type) +bool Util::isWidget(const ScreenPlay::ContentTypes::InstalledType type) const { + using namespace ScreenPlay; - using ScreenPlay::InstalledType::InstalledType; + return (type == ContentTypes::InstalledType::QMLWidget || type == ContentTypes::InstalledType::HTMLWidget); +} +/*! + \brief Returns true of the given type is a isScene. +*/ +bool Util::isScene(const ScreenPlay::ContentTypes::InstalledType type) const +{ + using namespace ScreenPlay; - return (type == InstalledType::QMLWidget || type == InstalledType::HTMLWidget); + return (type == ContentTypes::InstalledType::HTMLWallpaper + || type == ContentTypes::InstalledType::QMLWallpaper + || type == ContentTypes::InstalledType::WebsiteWallpaper + || type == ContentTypes::InstalledType::GodotWallpaper); +} +/*! + \brief Returns true of the given type is a isVideo. +*/ +bool Util::isVideo(const ScreenPlay::ContentTypes::InstalledType type) const +{ + using namespace ScreenPlay; + + return (type == ContentTypes::InstalledType::VideoWallpaper + || type == ContentTypes::InstalledType::GifWallpaper); } /*! \brief HTML video fillModes to be used in the QWebEngine video player. See https://developer.mozilla.org/en-US/docs/Web/CSS/object-fit */ -QStringList getAvailableFillModes() +QStringList Util::getAvailableFillModes() const { return { "stretch", "fill", "contain", "cover", "scale-down" }; } @@ -375,7 +461,7 @@ QStringList getAvailableFillModes() \brief parseIntList parses a list of string separated with a comma "1,2,3". IMPORTANT: No trailing comma! */ -std::optional> parseStringToIntegerList(const QString string) +std::optional> Util::parseStringToIntegerList(const QString string) const { if (string.isEmpty()) return {}; @@ -395,10 +481,145 @@ std::optional> parseStringToIntegerList(const QString string) return list; } -float roundDecimalPlaces(const float number) +float Util::roundDecimalPlaces(const float number) const { float big = number * 100.0; return std::ceil(big * 0.01); } - +/*! + \brief Copies the given string to the clipboard. +*/ +void Util::copyToClipboard(const QString& text) const +{ + auto* clipboard = QGuiApplication::clipboard(); + clipboard->setText(text); +} + +/*! + \brief Opens a native folder window on the given path. Windows and Mac only for now! +*/ +void Util::openFolderInExplorer(const QString& url) const +{ + const QString path = QUrl::fromUserInput(url).toLocalFile(); + + // QDesktopServices can hang on Windows + if (QSysInfo::productType() == "windows") { + QProcess explorer; + explorer.setProgram("explorer.exe"); + // When we have space in the path like + // C:\Program Files (x86)\Steam\... + // we cannot set the path as an argument. But we can set the working it + // to the wanted path and open the current path via the dot. + explorer.setWorkingDirectory(QDir::toNativeSeparators(path)); + explorer.setArguments({ "." }); + explorer.startDetached(); + return; + } + + QDesktopServices::openUrl(QUrl::fromLocalFile(path)); +} + +bool Util::openGodotEditor(QString contentPath, QString godotEditorExecutablePath) const +{ + const QList godotCmd = { "--editor", "--path", toLocal(contentPath) }; + QProcess process; + process.setProgram(godotEditorExecutablePath); + process.setArguments(godotCmd); + return process.startDetached(); +} + +/*! + \brief Loads all content of the legal folder in the qrc into a property string of this class. + allLicenseLoaded is emited when loading is finished. +*/ +void Util::requestAllLicenses() +{ + if (m_requestAllLicensesFuture.isRunning()) + return; + + m_requestAllLicensesFuture = QtConcurrent::run([this]() { + QString tmp; + QFile file; + QTextStream out(&file); + + file.setFileName(":/qml/ScreenPlayApp/legal/Font Awesome Free License.txt"); + file.open(QIODevice::ReadOnly | QIODevice::Text); + tmp += out.readAll(); + file.close(); + + file.setFileName(":/qml/ScreenPlayApp/legal/gpl-3.0.txt"); + file.open(QIODevice::ReadOnly | QIODevice::Text); + tmp += out.readAll(); + file.close(); + + file.setFileName(":/qml/ScreenPlayApp/legal/gpl-3.0.txt"); + file.open(QIODevice::ReadOnly | QIODevice::Text); + tmp += out.readAll(); + file.close(); + + file.setFileName(":/qml/ScreenPlayApp/legal/OFL.txt"); + file.open(QIODevice::ReadOnly | QIODevice::Text); + tmp += out.readAll(); + file.close(); + + file.setFileName(":/qml/ScreenPlayApp/legal/OpenSSL.txt"); + file.open(QIODevice::ReadOnly | QIODevice::Text); + tmp += out.readAll(); + file.close(); + + file.setFileName(":/qml/ScreenPlayApp/legal/Qt LGPLv3.txt"); + file.open(QIODevice::ReadOnly | QIODevice::Text); + tmp += out.readAll(); + file.close(); + + emit this->allLicenseLoaded(tmp); + }); +} + +/*! + \brief Loads all dataprotection of the legal folder in the qrc into a property string of this class. + allDataProtectionLoaded is emited when loading is finished. +*/ +void Util::requestDataProtection() +{ + QString tmp; + QFile file; + QTextStream out(&file); + + file.setFileName(":/qml/ScreenPlayApp/legal/DataProtection.txt"); + file.open(QIODevice::ReadOnly | QIODevice::Text); + tmp += out.readAll(); + file.close(); + + emit this->allDataProtectionLoaded(tmp); +} + +bool Util::fileExists(const QString& filePath) const +{ + const QFileInfo file(toLocal(filePath)); + return file.isFile(); +} + +/*! + \brief Takes reference to \a obj. If the copy of the thumbnail is successful, + it adds the corresponding settings entry to the json object reference. +*/ +bool Util::copyPreviewThumbnail(QJsonObject& obj, const QString& previewThumbnail, const QString& destination) +{ + const QUrl previewThumbnailUrl { previewThumbnail }; + const QFileInfo previewImageFile(previewThumbnailUrl.toString()); + const QString destinationFilePath = destination + "/" + previewImageFile.fileName(); + + if (!previewThumbnail.isEmpty()) { + if (!QFile::copy(previewThumbnailUrl.toLocalFile(), destinationFilePath)) { + qDebug() << "Could not copy" << previewThumbnailUrl.toLocalFile() << " to " << destinationFilePath; + return false; + } + } + + obj.insert("previewThumbnail", previewImageFile.fileName()); + obj.insert("preview", previewImageFile.fileName()); + + return true; +} } diff --git a/ScreenPlayWallpaper/CMakeLists.txt b/ScreenPlayWallpaper/CMakeLists.txt index 30f08dea..cbb5dce4 100644 --- a/ScreenPlayWallpaper/CMakeLists.txt +++ b/ScreenPlayWallpaper/CMakeLists.txt @@ -46,7 +46,19 @@ set(QML qml/Wallpaper.qml qml/WebsiteWallpaper.qml) -set(RESOURCES dot.png qtquickcontrols2.conf index.html) +set(RESOURCES qtquickcontrols2.conf index.html) + +set(LIB_SOURCES) +set(LIB_HEADER) + +if(WIN32) + set(LIB_SOURCES src/windowsintegration.cpp) + set(LIB_HEADER src/windowsintegration.h) + add_library(ScreenPlayWallpaperLib STATIC ${LIB_SOURCES} ${LIB_HEADER}) + target_include_directories(ScreenPlayWallpaperLib PUBLIC src) + # Used for query windows monitor data + target_link_libraries(ScreenPlayWallpaperLib PUBLIC shcore.lib) +endif() add_executable(${PROJECT_NAME} ${SOURCES} ${HEADER}) @@ -69,6 +81,7 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE ScreenPlaySDK ScreenPlayUtil + ScreenPlayUtilplugin ScreenPlayWeatherplugin Qt6::Quick Qt6::Gui @@ -79,31 +92,34 @@ target_link_libraries( Qt6::Multimedia Qt6::WebEngineCore Qt6::WebEngineQuick) + if(WIN32) - target_link_libraries(${PROJECT_NAME} PRIVATE ScreenPlaySysInfoplugin) + target_link_libraries(${PROJECT_NAME} PRIVATE ScreenPlaySysInfoplugin ScreenPlayWallpaperLib) elseif(UNIX AND NOT APPLE) target_link_libraries(${PROJECT_NAME} PRIVATE X11) endif() if(UNIX AND NOT APPLE) - find_package(ECM CONFIG REQUIRED NO_MODULE) + find_package( + ECM + CONFIG + REQUIRED + NO_MODULE) set(LayerShellQt "${CMAKE_CURRENT_SOURCE_DIR}/../ThirdParty/layer-shell-qt/") find_package(LayerShellQt REQUIRED) - target_link_libraries( - ${PROJECT_NAME} - PRIVATE LayerShellQtInterface) + target_link_libraries(${PROJECT_NAME} PRIVATE LayerShellQtInterface) endif() if(APPLE) target_link_libraries(${PROJECT_NAME} PRIVATE "-framework Cocoa") - if(NOT OSX_BUNDLE) - add_custom_command( - TARGET ${PROJECT_NAME} - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/index.html - ${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/) - set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/") - endif() + + add_custom_command( + TARGET ${PROJECT_NAME} + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/index.html + ${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/) + set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/") + endif() if(WIN32) diff --git a/ScreenPlayWallpaper/Godot/CMakeLists.txt b/ScreenPlayWallpaper/Godot/CMakeLists.txt new file mode 100644 index 00000000..05fbbca5 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/CMakeLists.txt @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only + +if(WIN32) + add_subdirectory(GDExtention) +endif() diff --git a/ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt b/ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt new file mode 100644 index 00000000..a201be38 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt @@ -0,0 +1,111 @@ +# SPDX-License-Identifier: Unlicense + +cmake_minimum_required(VERSION 3.22) + +message(STATUS "Using CMake ${CMAKE_VERSION}") + +# Require out-of-source builds +file(TO_CMAKE_PATH "${PROJECT_BINARY_DIR}/CMakeLists.txt" LOC_PATH) + +if(EXISTS "${LOC_PATH}") + message(FATAL_ERROR "You cannot build in the source directory. Please use a build subdirectory.") +endif() + +# Add paths to modules +list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/") + +# Turn on link time optimization for everything +set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELEASE ON) + +# Output compile commands to compile_commands.json (for debugging CMake issues) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) + +# Build universal lib on macOS Note that CMAKE_OSX_ARCHITECTURES must be set before project(). +if(APPLE) + set(CMAKE_OSX_ARCHITECTURES + "x86_64;arm64" + CACHE STRING "") +endif() + +# Main project information +project(ScreenPlayGodotWallpaper LANGUAGES CXX) + +# Create our library +add_library(${PROJECT_NAME} SHARED) +# Runs after compilation Enable executing python scripts +find_package(Python COMPONENTS Interpreter) + +add_custom_command( + TARGET ${PROJECT_NAME} + POST_BUILD + WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/Tools" + COMMAND "${Python_EXECUTABLE}" "build_godot.py" "--build_path" "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + COMMENT "Running post-build step") + +# LIB_ARCH is the architecture being built. It is set to the build system's architecture. For macOS, we build a universal library (both +# arm64 and x86_64). +set(LIB_ARCH ${CMAKE_SYSTEM_PROCESSOR}) + +if(APPLE) + set(LIB_ARCH "universal") +endif() + +# LIB_DIR is where the actual library ends up. This is used in both the build directory and the install directory and needs to be consistent +# with the paths in the gdextension file. e.g. linux.release.x86_64 = "lib/Linux-x86_64/libGDExtensionTemplate.so" +set(LIB_DIR "lib/${CMAKE_SYSTEM_NAME}-${LIB_ARCH}") + +message(STATUS "Building ${PROJECT_NAME} for ${LIB_ARCH} on ${CMAKE_SYSTEM_NAME}") + +# BUILD_OUTPUT_DIR is where we put the resulting library (in the build directory) +set(BUILD_OUTPUT_DIR "${PROJECT_BINARY_DIR}/${PROJECT_NAME}/") +set(OUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../ScreenPlayGodot/${PROJECT_NAME}/) + +# Compile directly into our Godot project +set_target_properties( + ${PROJECT_NAME} + PROPERTIES CXX_VISIBILITY_PRESET hidden + VISIBILITY_INLINES_HIDDEN true + RUNTIME_OUTPUT_DIRECTORY "${OUT_PATH}/${LIB_DIR}" + LIBRARY_OUTPUT_DIRECTORY "${OUT_PATH}/${LIB_DIR}") + +if(NOT DEFINED CMAKE_DEBUG_POSTFIX) + set_target_properties(${PROJECT_NAME} PROPERTIES DEBUG_POSTFIX "-d") +endif() + +# Warnings +include(CompilerWarnings) + +# Create and include version info file from git +include(GitVersionInfo) + +add_subdirectory(src) + +# Install library and extension file in ${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME} +set(INSTALL_DIR "${CMAKE_INSTALL_PREFIX}/${PROJECT_NAME}/") + +add_subdirectory(templates) + +# ccache Turns on ccache if found +include(ccache) + +# Formatting Adds a custom target to format all the code at once +include(ClangFormat) + +# godot-cpp From here: https://github.com/godotengine/godot-cpp +if(NOT EXISTS "${CMAKE_CURRENT_LIST_DIR}/extern/godot-cpp/Makefile") + message( + FATAL_ERROR + "[${PROJECT_NAME}] The godot-cpp submodule was not downloaded. Please update submodules: git submodule update --init --recursive." + ) +endif() + +set(GODOT_CPP_SYSTEM_HEADERS + ON + CACHE BOOL "" FORCE) + +add_subdirectory(extern/godot-cpp) + +set_target_properties(godot-cpp PROPERTIES CXX_VISIBILITY_PRESET hidden # visibility needs to be the same as the main library +) + +target_link_libraries(${PROJECT_NAME} PRIVATE godot-cpp ScreenPlayWallpaperLib) diff --git a/ScreenPlayWallpaper/Godot/GDExtention/CMakePresets.json b/ScreenPlayWallpaper/Godot/GDExtention/CMakePresets.json new file mode 100644 index 00000000..2f925072 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/CMakePresets.json @@ -0,0 +1,87 @@ +{ + "version": 5, + "cmakeMinimumRequired": { + "major": 3, + "minor": 23, + "patch": 0 + }, + "configurePresets": [ + { + "name": "default", + "displayName": "default", + "description": "Default preset that are inherited by all", + "generator": "Ninja", + "hidden": true, + "binaryDir": "${sourceDir}/../build_MyGodotProject" + }, + { + "name": "default-windows", + "displayName": "64bit Windows", + "description": "Windows only!", + "inherits": "default", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Windows" + }, + "toolset": { + "value": "host=x64", + "strategy": "external" + }, + "architecture": { + "value": "x64", + "strategy": "external" + }, + "cacheVariables": { + "CMAKE_C_COMPILER": "cl.exe", + "CMAKE_CXX_COMPILER": "cl.exe" + } + }, + { + "name": "linux-debug", + "displayName": "64bit Debug Linux", + "description": "Linux only!", + "generator": "Ninja", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Linux" + }, + "cacheVariables": { + "CMAKE_CXX_COMPILER": "g++", + "CMAKE_C_COMPILER": "gcc", + "CMAKE_BUILD_TYPE": "Debug" + } + }, + { + "name": "osx-debug", + "displayName": "64bit Debug osx", + "description": "Osx only!", + "generator": "Ninja", + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Darwin" + }, + "cacheVariables": { + "CMAKE_CXX_COMPILER": "clang++", + "CMAKE_C_COMPILER": "clang", + "CMAKE_BUILD_TYPE": "Debug" + } + } + ], + "buildPresets": [ + { + "name": "linux-debug", + "configurePreset": "linux-debug" + }, + { + "name": "default-windows", + "configurePreset": "default-windows" + }, + { + "name": "osx-debug", + "configurePreset": "osx-debug" + } + ] +} diff --git a/ScreenPlayWallpaper/Godot/GDExtention/cmake/ClangFormat.cmake b/ScreenPlayWallpaper/Godot/GDExtention/cmake/ClangFormat.cmake new file mode 100644 index 00000000..a6eb8a0b --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/cmake/ClangFormat.cmake @@ -0,0 +1,32 @@ +# SPDX-License-Identifier: Unlicense + +find_program( CLANG_FORMAT_PROGRAM NAMES clang-format ) + +if ( CLANG_FORMAT_PROGRAM ) + # get version information + execute_process( + COMMAND "${CLANG_FORMAT_PROGRAM}" --version + OUTPUT_VARIABLE CLANG_FORMAT_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + message( STATUS "Using clang-format: ${CLANG_FORMAT_PROGRAM} (${CLANG_FORMAT_VERSION})" ) + + get_target_property( CLANG_FORMAT_SOURCES ${PROJECT_NAME} SOURCES ) + + # Remove some files from the list + list( FILTER CLANG_FORMAT_SOURCES EXCLUDE REGEX ".*/extern/.*" ) + list( FILTER CLANG_FORMAT_SOURCES EXCLUDE REGEX ".*/gen/.*" ) + list( FILTER CLANG_FORMAT_SOURCES EXCLUDE REGEX ".*/*.gdextension.in" ) + list( FILTER CLANG_FORMAT_SOURCES EXCLUDE REGEX ".*/Version.h.in" ) + + add_custom_target( clang-format + COMMAND "${CLANG_FORMAT_PROGRAM}" --style=file -i ${CLANG_FORMAT_SOURCES} + COMMENT "Running clang-format..." + COMMAND_EXPAND_LISTS + VERBATIM + ) + + unset( CLANG_FORMAT_VERSION ) + unset( CLANG_FORMAT_SOURCES ) +endif() diff --git a/ScreenPlayWallpaper/Godot/GDExtention/cmake/CompilerWarnings.cmake b/ScreenPlayWallpaper/Godot/GDExtention/cmake/CompilerWarnings.cmake new file mode 100644 index 00000000..78aab1e7 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/cmake/CompilerWarnings.cmake @@ -0,0 +1,115 @@ +# SPDX-License-Identifier: Unlicense +# by Andy Maloney + +string( TOUPPER ${PROJECT_NAME} PROJECT_NAME_UPPERCASE ) + +if ( NOT MSVC ) + option( ${PROJECT_NAME_UPPERCASE}_WARN_EVERYTHING "Turn on all warnings (not recommended - used for lib development)" OFF ) +endif() + +option( ${PROJECT_NAME_UPPERCASE}_WARNING_AS_ERROR "Treat warnings as errors" OFF ) + +# Add warnings based on compiler +# Set some helper variables for readability +set( compiler_is_clang "$,$>" ) +set( compiler_is_gnu "$" ) +set( compiler_is_msvc "$" ) + +target_compile_options( ${PROJECT_NAME} + PRIVATE + # MSVC only + $<${compiler_is_msvc}: + /W4 + + /w14263 # 'function': member function does not override any base class virtual member function + /w14296 # 'operator': expression is always 'boolean_value' + /w14311 # 'variable': pointer truncation from 'type1' to 'type2' + /w14545 # expression before comma evaluates to a function which is missing an argument list + /w14546 # function call before comma missing argument list + /w14547 # 'operator': operator before comma has no effect; expected operator with side-effect + /w14549 # 'operator': operator before comma has no effect; did you intend 'operator'? + /w14619 # pragma warning: there is no warning number 'number' + /w14640 # thread un-safe static member initialization + /w14905 # wide string literal cast to 'LPSTR' + /w14906 # string literal cast to 'LPWSTR' + + # Disable warnings which bleed through from godot-cpp's macros. + /wd4100 # unreferenced formal parameter + > + + # Clang and GNU + $<$: + -Wall + -Wcast-align + -Wctor-dtor-privacy + -Wextra + -Wformat=2 + -Wnon-virtual-dtor + -Wnull-dereference + -Woverloaded-virtual + -Wpedantic + -Wshadow + -Wunused + -Wwrite-strings + + # Disable warnings which bleed through from godot-cpp's macros. + -Wno-unused-parameter + > + + # Clang only + $<${compiler_is_clang}: + -Wdocumentation + -Wimplicit-fallthrough + > + + # GNU only + $<${compiler_is_gnu}: + -Walloc-zero + -Wduplicated-branches + -Wduplicated-cond + -Wlogical-op + > +) + +# Turn on (almost) all warnings on Clang, Apple Clang, and GNU. +# Useful for internal development, but too noisy for general development. +function( set_warn_everything ) + message( STATUS "[${PROJECT_NAME}] Turning on (almost) all warnings") + + target_compile_options( ${PROJECT_NAME} + PRIVATE + # Clang and GNU + $<$: + -Weverything + -Wno-c++98-compat + -Wno-c++98-compat-pedantic + -Wno-padded + > + ) +endfunction() + +if ( NOT MSVC AND ${PROJECT_NAME_UPPERCASE}_WARN_EVERYTHING ) + set_warn_everything() +endif() + +# Treat warnings as errors +function( set_warning_as_error ) + message( STATUS "[${PROJECT_NAME}] Treating warnings as errors") + + if ( CMAKE_VERSION VERSION_GREATER_EQUAL "3.24" ) + set_target_properties( ${PROJECT_NAME} + PROPERTIES + COMPILE_WARNING_AS_ERROR ON + ) + else() + target_compile_options( ${PROJECT_NAME} + PRIVATE + $<${compiler_is_msvc}:/WX> + $<$:-Werror> + ) + endif() +endfunction() + +if ( ${PROJECT_NAME_UPPERCASE}_WARNING_AS_ERROR ) + set_warning_as_error() +endif() diff --git a/ScreenPlayWallpaper/Godot/GDExtention/cmake/GetGitRevisionDescription.cmake b/ScreenPlayWallpaper/Godot/GDExtention/cmake/GetGitRevisionDescription.cmake new file mode 100644 index 00000000..4fbd90db --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/cmake/GetGitRevisionDescription.cmake @@ -0,0 +1,284 @@ +# - Returns a version string from Git +# +# These functions force a re-configure on each git commit so that you can +# trust the values of the variables in your build system. +# +# get_git_head_revision( [ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR]) +# +# Returns the refspec and sha hash of the current head revision +# +# git_describe( [ ...]) +# +# Returns the results of git describe on the source tree, and adjusting +# the output so that it tests false if an error occurs. +# +# git_describe_working_tree( [ ...]) +# +# Returns the results of git describe on the working tree (--dirty option), +# and adjusting the output so that it tests false if an error occurs. +# +# git_get_exact_tag( [ ...]) +# +# Returns the results of git describe --exact-match on the source tree, +# and adjusting the output so that it tests false if there was no exact +# matching tag. +# +# git_local_changes() +# +# Returns either "CLEAN" or "DIRTY" with respect to uncommitted changes. +# Uses the return code of "git diff-index --quiet HEAD --". +# Does not regard untracked files. +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2020 Ryan Pavlik +# http://academic.cleardefinition.com +# +# Copyright 2009-2013, Iowa State University. +# Copyright 2013-2020, Ryan Pavlik +# Copyright 2013-2020, Contributors +# SPDX-License-Identifier: BSL-1.0 +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) + +if(__get_git_revision_description) + return() +endif() +set(__get_git_revision_description YES) + +# We must run the following at "include" time, not at function call time, +# to find the path to this module rather than the path to a calling list file +get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) + +# Function _git_find_closest_git_dir finds the next closest .git directory +# that is part of any directory in the path defined by _start_dir. +# The result is returned in the parent scope variable whose name is passed +# as variable _git_dir_var. If no .git directory can be found, the +# function returns an empty string via _git_dir_var. +# +# Example: Given a path C:/bla/foo/bar and assuming C:/bla/.git exists and +# neither foo nor bar contain a file/directory .git. This wil return +# C:/bla/.git +# +function(_git_find_closest_git_dir _start_dir _git_dir_var) + set(cur_dir "${_start_dir}") + set(git_dir "${_start_dir}/.git") + while(NOT EXISTS "${git_dir}") + # .git dir not found, search parent directories + set(git_previous_parent "${cur_dir}") + get_filename_component(cur_dir "${cur_dir}" DIRECTORY) + if(cur_dir STREQUAL git_previous_parent) + # We have reached the root directory, we are not in git + set(${_git_dir_var} + "" + PARENT_SCOPE) + return() + endif() + set(git_dir "${cur_dir}/.git") + endwhile() + set(${_git_dir_var} + "${git_dir}" + PARENT_SCOPE) +endfunction() + +function(get_git_head_revision _refspecvar _hashvar) + _git_find_closest_git_dir("${CMAKE_CURRENT_SOURCE_DIR}" GIT_DIR) + + if("${ARGN}" STREQUAL "ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR") + set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR TRUE) + else() + set(ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR FALSE) + endif() + if(NOT "${GIT_DIR}" STREQUAL "") + file(RELATIVE_PATH _relative_to_source_dir "${CMAKE_SOURCE_DIR}" + "${GIT_DIR}") + if("${_relative_to_source_dir}" MATCHES "[.][.]" AND NOT ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR) + # We've gone above the CMake root dir. + set(GIT_DIR "") + endif() + endif() + if("${GIT_DIR}" STREQUAL "") + set(${_refspecvar} + "GITDIR-NOTFOUND" + PARENT_SCOPE) + set(${_hashvar} + "GITDIR-NOTFOUND" + PARENT_SCOPE) + return() + endif() + + # Check if the current source dir is a git submodule or a worktree. + # In both cases .git is a file instead of a directory. + # + if(NOT IS_DIRECTORY ${GIT_DIR}) + # The following git command will return a non empty string that + # points to the super project working tree if the current + # source dir is inside a git submodule. + # Otherwise the command will return an empty string. + # + execute_process( + COMMAND "${GIT_EXECUTABLE}" rev-parse + --show-superproject-working-tree + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + OUTPUT_VARIABLE out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT "${out}" STREQUAL "") + # If out is empty, GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a submodule + file(READ ${GIT_DIR} submodule) + string(REGEX REPLACE "gitdir: (.*)$" "\\1" GIT_DIR_RELATIVE + ${submodule}) + string(STRIP ${GIT_DIR_RELATIVE} GIT_DIR_RELATIVE) + get_filename_component(SUBMODULE_DIR ${GIT_DIR} PATH) + get_filename_component(GIT_DIR ${SUBMODULE_DIR}/${GIT_DIR_RELATIVE} + ABSOLUTE) + set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD") + else() + # GIT_DIR/CMAKE_CURRENT_SOURCE_DIR is in a worktree + file(READ ${GIT_DIR} worktree_ref) + # The .git directory contains a path to the worktree information directory + # inside the parent git repo of the worktree. + # + string(REGEX REPLACE "gitdir: (.*)$" "\\1" git_worktree_dir + ${worktree_ref}) + string(STRIP ${git_worktree_dir} git_worktree_dir) + _git_find_closest_git_dir("${git_worktree_dir}" GIT_DIR) + set(HEAD_SOURCE_FILE "${git_worktree_dir}/HEAD") + endif() + else() + set(HEAD_SOURCE_FILE "${GIT_DIR}/HEAD") + endif() + set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") + if(NOT EXISTS "${GIT_DATA}") + file(MAKE_DIRECTORY "${GIT_DATA}") + endif() + + if(NOT EXISTS "${HEAD_SOURCE_FILE}") + return() + endif() + set(HEAD_FILE "${GIT_DATA}/HEAD") + configure_file("${HEAD_SOURCE_FILE}" "${HEAD_FILE}" COPYONLY) + + configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" + "${GIT_DATA}/grabRef.cmake" @ONLY) + include("${GIT_DATA}/grabRef.cmake") + + set(${_refspecvar} + "${HEAD_REF}" + PARENT_SCOPE) + set(${_hashvar} + "${HEAD_HASH}" + PARENT_SCOPE) +endfunction() + +function(git_describe _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} + "GIT-NOTFOUND" + PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} + "HEAD-HASH-NOTFOUND" + PARENT_SCOPE) + return() + endif() + + # TODO sanitize + #if((${ARGN}" MATCHES "&&") OR + # (ARGN MATCHES "||") OR + # (ARGN MATCHES "\\;")) + # message("Please report the following error to the project!") + # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") + #endif() + + #message(STATUS "Arguments to execute_process: ${ARGN}") + + execute_process( + COMMAND "${GIT_EXECUTABLE}" describe --tags --always ${hash} ${ARGN} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE res + OUTPUT_VARIABLE out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() + + set(${_var} + "${out}" + PARENT_SCOPE) +endfunction() + +function(git_describe_working_tree _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + if(NOT GIT_FOUND) + set(${_var} + "GIT-NOTFOUND" + PARENT_SCOPE) + return() + endif() + + execute_process( + COMMAND "${GIT_EXECUTABLE}" describe --dirty ${ARGN} + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE res + OUTPUT_VARIABLE out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(NOT res EQUAL 0) + set(out "${out}-${res}-NOTFOUND") + endif() + + set(${_var} + "${out}" + PARENT_SCOPE) +endfunction() + +function(git_get_exact_tag _var) + git_describe(out --exact-match ${ARGN}) + set(${_var} + "${out}" + PARENT_SCOPE) +endfunction() + +function(git_local_changes _var) + if(NOT GIT_FOUND) + find_package(Git QUIET) + endif() + get_git_head_revision(refspec hash) + if(NOT GIT_FOUND) + set(${_var} + "GIT-NOTFOUND" + PARENT_SCOPE) + return() + endif() + if(NOT hash) + set(${_var} + "HEAD-HASH-NOTFOUND" + PARENT_SCOPE) + return() + endif() + + execute_process( + COMMAND "${GIT_EXECUTABLE}" diff-index --quiet HEAD -- + WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}" + RESULT_VARIABLE res + OUTPUT_VARIABLE out + ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) + if(res EQUAL 0) + set(${_var} + "CLEAN" + PARENT_SCOPE) + else() + set(${_var} + "DIRTY" + PARENT_SCOPE) + endif() +endfunction() diff --git a/ScreenPlayWallpaper/Godot/GDExtention/cmake/GetGitRevisionDescription.cmake.in b/ScreenPlayWallpaper/Godot/GDExtention/cmake/GetGitRevisionDescription.cmake.in new file mode 100644 index 00000000..116efc4e --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/cmake/GetGitRevisionDescription.cmake.in @@ -0,0 +1,43 @@ +# +# Internal file for GetGitRevisionDescription.cmake +# +# Requires CMake 2.6 or newer (uses the 'function' command) +# +# Original Author: +# 2009-2010 Ryan Pavlik +# http://academic.cleardefinition.com +# Iowa State University HCI Graduate Program/VRAC +# +# Copyright 2009-2012, Iowa State University +# Copyright 2011-2015, Contributors +# Distributed under the Boost Software License, Version 1.0. +# (See accompanying file LICENSE_1_0.txt or copy at +# http://www.boost.org/LICENSE_1_0.txt) +# SPDX-License-Identifier: BSL-1.0 + +set(HEAD_HASH) + +file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) + +string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) +if(HEAD_CONTENTS MATCHES "ref") + # named branch + string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") + if(EXISTS "@GIT_DIR@/${HEAD_REF}") + configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) + else() + configure_file("@GIT_DIR@/packed-refs" "@GIT_DATA@/packed-refs" COPYONLY) + file(READ "@GIT_DATA@/packed-refs" PACKED_REFS) + if(${PACKED_REFS} MATCHES "([0-9a-z]*) ${HEAD_REF}") + set(HEAD_HASH "${CMAKE_MATCH_1}") + endif() + endif() +else() + # detached HEAD + configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) +endif() + +if(NOT HEAD_HASH) + file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) + string(STRIP "${HEAD_HASH}" HEAD_HASH) +endif() diff --git a/ScreenPlayWallpaper/Godot/GDExtention/cmake/GitVersionInfo.cmake b/ScreenPlayWallpaper/Godot/GDExtention/cmake/GitVersionInfo.cmake new file mode 100644 index 00000000..c1285ab5 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/cmake/GitVersionInfo.cmake @@ -0,0 +1,46 @@ +# SPDX-License-Identifier: Unlicense + +find_program( GIT_PROGRAM git ) + +if ( GIT_PROGRAM ) + # get version information + execute_process( + COMMAND "${GIT_PROGRAM}" --version + OUTPUT_VARIABLE GIT_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + message( STATUS "Using git: ${GIT_PROGRAM} (${GIT_VERSION})" ) + + include( GetGitRevisionDescription ) + + get_git_head_revision( GIT_REFSPEC GIT_SHA1 ) + git_describe( GIT_SHORT ) + + string( TOUPPER ${PROJECT_NAME} UPPER_PROJECT_NAME ) + + set( VERSION_INPUT_FILE "src/Version.h.in" ) + set( VERSION_OUTPUT_FILE "${CMAKE_BINARY_DIR}/gen/Version.h" ) + + configure_file( "${VERSION_INPUT_FILE}" "${VERSION_OUTPUT_FILE}" ) + + target_sources( ${PROJECT_NAME} + PRIVATE + "${VERSION_INPUT_FILE}" + "${VERSION_OUTPUT_FILE}" + ) + + get_filename_component( VERSION_OUTPUT_FILE_DIR ${VERSION_OUTPUT_FILE} DIRECTORY ) + + target_include_directories( ${PROJECT_NAME} + PRIVATE + ${VERSION_OUTPUT_FILE_DIR} + ) + + message( STATUS "${PROJECT_NAME} version: ${GIT_SHORT}" ) + + unset( VERSION_INPUT_FILE ) + unset( VERSION_OUTPUT_FILE ) + unset( VERSION_OUTPUT_FILE_DIR ) + unset( GIT_VERSION ) +endif() diff --git a/ScreenPlayWallpaper/Godot/GDExtention/cmake/ccache.cmake b/ScreenPlayWallpaper/Godot/GDExtention/cmake/ccache.cmake new file mode 100644 index 00000000..4bb5661b --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/cmake/ccache.cmake @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: Unlicense + +# See: https://crascit.com/2016/04/09/using-ccache-with-cmake/ +find_program( CCACHE_PROGRAM ccache ) + +if ( CCACHE_PROGRAM ) + # get version information + execute_process( + COMMAND "${CCACHE_PROGRAM}" --version + OUTPUT_VARIABLE CCACHE_VERSION + ) + + string( REGEX MATCH "[^\r\n]*" CCACHE_VERSION ${CCACHE_VERSION} ) + + message( STATUS "Using ccache: ${CCACHE_PROGRAM} (${CCACHE_VERSION})" ) + + # Turn on ccache for all targets + set( CMAKE_CXX_COMPILER_LAUNCHER "${CCACHE_PROGRAM}" ) + set( CMAKE_C_COMPILER_LAUNCHER "${CCACHE_PROGRAM}" ) + + unset( CCACHE_VERSION ) +endif() diff --git a/ScreenPlayWallpaper/Godot/GDExtention/extern/godot-cpp b/ScreenPlayWallpaper/Godot/GDExtention/extern/godot-cpp new file mode 160000 index 00000000..32409472 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/extern/godot-cpp @@ -0,0 +1 @@ +Subproject commit 32409472b785fd6f9062300664fa55b46bfd07e7 diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/CMakeLists.txt b/ScreenPlayWallpaper/Godot/GDExtention/src/CMakeLists.txt new file mode 100644 index 00000000..243dc376 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/CMakeLists.txt @@ -0,0 +1,18 @@ +# SPDX-License-Identifier: Unlicense + +target_sources( + ${PROJECT_NAME} + PRIVATE ScreenPlayGodotWallpaper.h + ScreenPlayGodotWallpaper.cpp + WindowsPipe.h + WindowsPipe.cpp + RegisterExtension.cpp) +find_package(Catch2 CONFIG REQUIRED) +target_include_directories(${PROJECT_NAME} PRIVATE "src") + +# Test app. Start WindowsPipeTestServer.py! +if(${SCREENPLAY_TESTS}) + add_executable(WindowsPipeTest WindowsPipe.cpp WindowsPipe.h WindowsPipeTest.cpp) + target_link_libraries(WindowsPipeTest PRIVATE Catch2::Catch2 Catch2::Catch2WithMain) + target_include_directories(WindowsPipeTest PRIVATE "src") +endif() diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/RegisterExtension.cpp b/ScreenPlayWallpaper/Godot/GDExtention/src/RegisterExtension.cpp new file mode 100644 index 00000000..ac95cde5 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/RegisterExtension.cpp @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only + +#include "gdextension_interface.h" + +#include "godot_cpp/core/class_db.hpp" +#include "godot_cpp/core/defs.hpp" +#include "godot_cpp/godot.hpp" + +#include "ScreenPlayGodotWallpaper.h" + +/// @file +/// Register our classes with Godot. + +namespace { +/// @brief Called by Godot to let us register our classes with Godot. +/// +/// @param p_level the level being initialized by Godot +/// +/// @see GDExtensionInit +void initializeExtension(godot::ModuleInitializationLevel p_level) +{ + if (p_level != godot::MODULE_INITIALIZATION_LEVEL_SCENE) { + return; + } + + godot::ClassDB::register_class(); +} + +/// @brief Called by Godot to let us do any cleanup. +/// +/// @see GDExtensionInit +void uninitializeExtension(godot::ModuleInitializationLevel p_level) +{ + if (p_level != godot::MODULE_INITIALIZATION_LEVEL_SCENE) { + return; + } +} +} + +extern "C" { +/// @brief This is the entry point for the shared library. +/// +/// @note The name of this function must match the "entry_symbol" in +/// templates/template.*.gdextension.in +/// +/// @param p_get_proc_address the interface (need more info) +/// @param p_library the library (need more info) +/// @param r_initialization the intialization (need more info) +/// +/// @returns GDExtensionBool +GDExtensionBool GDE_EXPORT GDExtensionInit( + GDExtensionInterfaceGetProcAddress p_get_proc_address, GDExtensionClassLibraryPtr p_library, + GDExtensionInitialization* r_initialization) +{ + { + godot::GDExtensionBinding::InitObject init_obj(p_get_proc_address, p_library, + r_initialization); + + init_obj.register_initializer(initializeExtension); + init_obj.register_terminator(uninitializeExtension); + init_obj.set_minimum_library_initialization_level( + godot::MODULE_INITIALIZATION_LEVEL_SCENE); + + return init_obj.init(); + } +} +} diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp new file mode 100644 index 00000000..7476a1d6 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp @@ -0,0 +1,307 @@ +// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only +#include "ScreenPlayGodotWallpaper.h" +#include "godot_cpp/classes/display_server.hpp" +#include "godot_cpp/classes/global_constants.hpp" +#include "godot_cpp/classes/label.hpp" +#include "godot_cpp/classes/os.hpp" +#include "godot_cpp/core/class_db.hpp" +#include "godot_cpp/variant/utility_functions.hpp" + +//// ScreenPlayWallpaper +using namespace godot; + +ScreenPlayGodotWallpaper::ScreenPlayGodotWallpaper() +{ +} + +ScreenPlayGodotWallpaper::~ScreenPlayGodotWallpaper() +{ +} + +void ScreenPlayGodotWallpaper::_bind_methods() +{ + UtilityFunctions::print("ScreenPlayGodotWallpaper _bind_methods"); + ClassDB::bind_method(godot::D_METHOD("init"), &ScreenPlayGodotWallpaper::init); + ClassDB::bind_method(godot::D_METHOD("connect_to_named_pipe"), &ScreenPlayGodotWallpaper::connect_to_named_pipe); + ClassDB::bind_method(godot::D_METHOD("send_welcome"), &ScreenPlayGodotWallpaper::send_welcome); + ClassDB::bind_method(godot::D_METHOD("get_screenPlayConnected"), &ScreenPlayGodotWallpaper::get_screenPlayConnected); + ClassDB::bind_method(godot::D_METHOD("get_pipeConnected"), &ScreenPlayGodotWallpaper::get_pipeConnected); + ClassDB::bind_method(godot::D_METHOD("read_from_pipe"), &ScreenPlayGodotWallpaper::read_from_pipe); + ClassDB::bind_method(godot::D_METHOD("send_ping"), &ScreenPlayGodotWallpaper::send_ping); + ClassDB::bind_method(godot::D_METHOD("exit"), &ScreenPlayGodotWallpaper::exit); + + ClassDB::bind_method(godot::D_METHOD("get_activeScreensList"), &ScreenPlayGodotWallpaper::get_activeScreensList); + ClassDB::bind_method(godot::D_METHOD("set_activeScreensList", "screens"), &ScreenPlayGodotWallpaper::set_activeScreensList); + + ClassDB::bind_method(godot::D_METHOD("get_projectPackageFile"), &ScreenPlayGodotWallpaper::get_projectPackageFile); + ClassDB::bind_method(godot::D_METHOD("set_projectPackageFile", "projectPackageFile"), &ScreenPlayGodotWallpaper::set_projectPackageFile); + + ClassDB::bind_method(godot::D_METHOD("get_projectPath"), &ScreenPlayGodotWallpaper::get_projectPath); + ClassDB::bind_method(godot::D_METHOD("set_projectPath", "path"), &ScreenPlayGodotWallpaper::set_projectPath); + + ClassDB::bind_method(godot::D_METHOD("get_appID"), &ScreenPlayGodotWallpaper::get_appID); + ClassDB::bind_method(godot::D_METHOD("set_appID", "id"), &ScreenPlayGodotWallpaper::set_appID); + + ClassDB::bind_method(godot::D_METHOD("get_volume"), &ScreenPlayGodotWallpaper::get_volume); + ClassDB::bind_method(godot::D_METHOD("set_volume", "volume"), &ScreenPlayGodotWallpaper::set_volume); + + ClassDB::bind_method(godot::D_METHOD("get_checkWallpaperVisible"), &ScreenPlayGodotWallpaper::get_checkWallpaperVisible); + ClassDB::bind_method(godot::D_METHOD("set_checkWallpaperVisible", "visible"), &ScreenPlayGodotWallpaper::set_checkWallpaperVisible); +} + +void ScreenPlayGodotWallpaper::hideFromTaskbar(HWND hwnd) +{ + LONG lExStyle = GetWindowLong(hwnd, GWL_EXSTYLE); + lExStyle |= WS_EX_TOOLWINDOW; // Add WS_EX_TOOLWINDOW + lExStyle &= ~WS_EX_APPWINDOW; // Remove WS_EX_APPWINDOW + SetWindowLong(hwnd, GWL_EXSTYLE, lExStyle); +} + +godot::String ScreenPlayGodotWallpaper::get_projectPackageFile() const +{ + return m_projectPackageFile; +} + +void ScreenPlayGodotWallpaper::set_projectPackageFile(const godot::String& projectPackageFile) +{ + m_projectPackageFile = projectPackageFile; +} + +bool ScreenPlayGodotWallpaper::configureWindowGeometry() +{ + if (!m_windowsIntegration.searchWorkerWindowToParentTo()) { + UtilityFunctions::print("No worker window found"); + return false; + } + if (!IsWindow(m_windowsIntegration.windowHandleWorker())) { + UtilityFunctions::print("Could not get a valid window handle worker!"); + return false; + } + // WARNING: Setting Window flags must be called *here*! + SetWindowLongPtr(m_windowsIntegration.windowHandle(), GWL_EXSTYLE, WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT); + SetWindowLongPtr(m_windowsIntegration.windowHandle(), GWL_STYLE, WS_POPUPWINDOW); + + return true; +} + +bool ScreenPlayGodotWallpaper::init(int activeScreen) +{ + auto* displayServer = DisplayServer::get_singleton(); + + int64_t handle_int = displayServer->window_get_native_handle(godot::DisplayServer::HandleType::WINDOW_HANDLE); + HWND hwnd = reinterpret_cast(handle_int); + m_windowsIntegration.setWindowHandle(hwnd); + ShowWindow(m_windowsIntegration.windowHandle(), SW_HIDE); + if (!IsWindow(hwnd)) { + UtilityFunctions::print("ScreenPlayGodotWallpaper::init Could not get a valid window handle !", activeScreen, handle_int); + UtilityFunctions::print("init hwnd: ", (int64_t)hwnd, activeScreen, handle_int); + + std::vector monitors = m_windowsIntegration.getAllMonitors(); + for (const auto& monitor : monitors) { + UtilityFunctions::print(monitor.toString().c_str()); + } + return false; + } + + if (!configureWindowGeometry()) { + return false; + } + hideFromTaskbar(m_windowsIntegration.windowHandle()); + auto updateWindowSize = [&displayServer](const int width, const int height) { + displayServer->window_set_size(godot::Vector2((real_t)width, (real_t)height)); + }; + + WindowsIntegration::MonitorResult monitor = m_windowsIntegration.setupWallpaperForOneScreen(activeScreen, updateWindowSize); + if (monitor.status != WindowsIntegration::MonitorResultStatus::Ok) { + UtilityFunctions::print("setupWallpaperForOneScreen failed status: ", (int)monitor.status); + return false; + } + displayServer->window_set_size(godot::Vector2((real_t)monitor.monitor->size.cx, (real_t)monitor.monitor->size.cy)); + + const std::string windowTitle = "ScreenPlayWallpaperGodot"; + SetWindowText(m_windowsIntegration.windowHandle(), windowTitle.c_str()); + ShowWindow(m_windowsIntegration.windowHandle(), SW_SHOW); + + // m_windowsIntegration.setupWindowMouseHook(); + // Set up the mouse event handler + // m_windowsIntegration.setMouseEventHandler([this](DWORD mouseButton, UINT type, POINT p) { + // Ref mouse_event; + // Ref motion_event; + // switch (type) { + // case WM_LBUTTONDOWN: + // case WM_LBUTTONUP: + // case WM_RBUTTONDOWN: + // case WM_RBUTTONUP: + // mouse_event.instantiate(); + // mouse_event->set_position(Vector2(p.x, p.y)); + // mouse_event->set_global_position(Vector2(p.x, p.y)); // Assuming global == local for this context + // mouse_event->set_button_index( + // type == WM_LBUTTONDOWN || type == WM_LBUTTONUP ? MOUSE_BUTTON_LEFT : MOUSE_BUTTON_RIGHT); + // mouse_event->set_pressed(type == WM_LBUTTONDOWN || type == WM_RBUTTONDOWN); + // break; + // case WM_MOUSEMOVE: + // motion_event.instantiate(); + // motion_event->set_position(Vector2(p.x, p.y)); + // motion_event->set_global_position(Vector2(p.x, p.y)); + // break; + // // Add more cases as needed + // } + + // if (mouse_event.is_valid()) { + // get_tree()->get_root()->get_viewport()->push_input(mouse_event); + // } + // if (motion_event.is_valid()) { + // get_tree()->get_root()->get_viewport()->push_input(motion_event); + // } + // }); 2 + return true; +} + +bool ScreenPlayGodotWallpaper::connect_to_named_pipe() +{ + m_windowsPipe.setPipeName(L"ScreenPlay"); + m_pipeConnected = m_windowsPipe.start(); + return m_pipeConnected; +} + +godot::String ScreenPlayGodotWallpaper::read_from_pipe() +{ + std::string outMsg; + if (!m_windowsPipe.readFromPipe(outMsg)) { + // No new message + return ""; + } + return godot::String(outMsg.c_str()); +} + +bool ScreenPlayGodotWallpaper::writeToPipe(const godot::String& message) +{ + std::string stdMessage = message.utf8().get_data(); + + return m_windowsPipe.writeToPipe(stdMessage); +} + +bool ScreenPlayGodotWallpaper::send_ping() +{ + if (!m_screenPlayConnected || !m_pipeConnected) { + UtilityFunctions::print("ScreenPlay hasn't connected to us yet!"); + return false; + } + const godot::String msg = "ping;"; + if (!writeToPipe(msg)) { + return false; + } + + return true; +} + +bool ScreenPlayGodotWallpaper::send_welcome() +{ + // Ensure you have valid appID and type + if (m_appID.is_empty()) { + UtilityFunctions::print("Unable to connect with empty: appid"); + return false; + } + + // Construct welcome message and write to the named pipe + // See void ScreenPlay::SDKConnection::readyRead() + godot::String msg = godot::String("appID=") + m_appID + ",godotWallpaper;"; + if (!writeToPipe(msg)) { + return false; + } + + m_screenPlayConnected = true; + return true; +} + +void ScreenPlayGodotWallpaper::messageReceived(const std::string& key, const std::string& value) +{ + try { + if (key == "volume") { + m_volume = std::stof(value); + return; + } + if (key == "appID") { + m_appID = godot::String(value.c_str()); + return; + } + + if (key == "projectPath") { + m_projectPath = godot::String(value.c_str()); + return; + } + + // If none of the keys match + // Assuming sceneValueReceived is a signal you've defined + emit_signal("sceneValueReceived", key.c_str(), value.c_str()); + + } catch (const std::invalid_argument& ia) { + // Invalid argument passed to stof/stoi. Handle error as necessary. + std::cerr << "Invalid argument: " << ia.what() << std::endl; + } catch (const std::out_of_range& oor) { + // Converted number is out of range for float/int. Handle error as necessary. + std::cerr << "Out of range: " << oor.what() << std::endl; + } +} +bool ScreenPlayGodotWallpaper::exit() +{ + // Somehow this gets called at editor startup + // so just return if not initialized + + ShowWindow(m_windowsIntegration.windowHandle(), SW_HIDE); + + // Force refresh so that we display the regular + // desktop wallpaper again + ShowWindow(m_windowsIntegration.windowHandleWorker(), SW_SHOW); + ShowWindow(m_windowsIntegration.windowHandleWorker(), SW_HIDE); + return true; +} +void ScreenPlayGodotWallpaper::set_checkWallpaperVisible(bool visible) +{ + m_checkWallpaperVisible = visible; +} +bool ScreenPlayGodotWallpaper::get_screenPlayConnected() const +{ + return m_screenPlayConnected; +} +bool ScreenPlayGodotWallpaper::get_pipeConnected() const +{ + return m_pipeConnected; +} +bool ScreenPlayGodotWallpaper::get_checkWallpaperVisible() const +{ + return m_checkWallpaperVisible; +} + +void ScreenPlayGodotWallpaper::set_volume(float vol) +{ + m_volume = vol; +} +float ScreenPlayGodotWallpaper::get_volume() const +{ + return m_volume; +} +void ScreenPlayGodotWallpaper::set_appID(const godot::String& id) +{ + m_appID = id; +} +godot::String ScreenPlayGodotWallpaper::get_appID() const +{ + return m_appID; +} +void ScreenPlayGodotWallpaper::set_projectPath(const godot::String& path) +{ + m_projectPath = path; +} +godot::String ScreenPlayGodotWallpaper::get_projectPath() const +{ + return m_projectPath; +} +void ScreenPlayGodotWallpaper::set_activeScreensList(const godot::PackedInt64Array& screens) +{ + m_activeScreensList = screens; +} +PackedInt64Array ScreenPlayGodotWallpaper::get_activeScreensList() const +{ + return m_activeScreensList; +} diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.h b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.h new file mode 100644 index 00000000..b8fcb18b --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.h @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only +#pragma once + +#ifndef NOMINMAX +#define NOMINMAX +#endif + +#include "godot_cpp/classes/control.hpp" +#include "godot_cpp/classes/engine.hpp" +#include "godot_cpp/classes/global_constants.hpp" +#include "godot_cpp/classes/input_event_key.hpp" +#include "godot_cpp/classes/input_event_mouse_button.hpp" +#include "godot_cpp/classes/input_event_mouse_motion.hpp" +#include "godot_cpp/classes/node.hpp" +#include "godot_cpp/classes/scene_tree.hpp" +#include "godot_cpp/classes/timer.hpp" +#include "godot_cpp/classes/viewport.hpp" +#include "godot_cpp/classes/window.hpp" +#include "godot_cpp/core/binder_common.hpp" +#include "godot_cpp/variant/string.hpp" +#include "godot_cpp/variant/vector2.hpp" + +#include +#include +#include + +#include "ScreenPlayGodotWallpaper.h" +#include "WindowsPipe.h" +#include "windowsintegration.h" + +class ScreenPlayGodotWallpaper : public godot::Node { + GDCLASS(ScreenPlayGodotWallpaper, Node) + +public: + ScreenPlayGodotWallpaper(); + ~ScreenPlayGodotWallpaper() override; + + bool init(int activeScreen); + bool connect_to_named_pipe(); + bool send_welcome(); + bool writeToPipe(const godot::String& message); + godot::String read_from_pipe(); + void messageReceived(const std::string& key, const std::string& value); + + godot::PackedInt64Array get_activeScreensList() const; + void set_activeScreensList(const godot::PackedInt64Array& screens); + godot::String get_projectPath() const; + void set_projectPath(const godot::String& path); + godot::String get_appID() const; + void set_appID(const godot::String& id); + float get_volume() const; + void set_volume(float vol); + bool get_checkWallpaperVisible() const; + void set_checkWallpaperVisible(bool visible); + bool get_screenPlayConnected() const; + bool get_pipeConnected() const; + bool send_ping(); + bool exit(); + + godot::String get_projectPackageFile() const; + void set_projectPackageFile(const godot::String& projectPackageFile); + +protected: + static void _bind_methods(); + +private: + bool configureWindowGeometry(); + void hideFromTaskbar(HWND hwnd); + +private: + OVERLAPPED overlappedRead = {}; + OVERLAPPED overlappedWrite = {}; + + godot::String m_appID = ""; + godot::String m_projectPath = ""; + godot::String m_projectPackageFile = ""; + WindowsIntegration m_windowsIntegration; + double m_timesinceLastRead = 0.0; + bool m_pipeConnected = false; + bool m_screenPlayConnected = false; + WindowsPipe m_windowsPipe; + + godot::PackedInt64Array m_activeScreensList; + float m_volume = 0.0; + bool m_checkWallpaperVisible = false; +}; diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/Version.h.in b/ScreenPlayWallpaper/Godot/GDExtention/src/Version.h.in new file mode 100644 index 00000000..10a52438 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/Version.h.in @@ -0,0 +1,45 @@ +#pragma once +// This file is generated by cmake. Changes will be overwritten. +// clang-format off + +#include + +// Creates a version number for use in macro comparisons. +// +// Example: +// +// // Check if the version is less than 2.1.0 +// #if ${UPPER_PROJECT_NAME}_VERSION < ${UPPER_PROJECT_NAME}_VERSION_CHECK(2, 1, 0) +// // do stuff +// #endif +// +// Returns an integer which may be used in comparisons +#define ${UPPER_PROJECT_NAME}_VERSION_CHECK( major, minor, patch ) ( ((major)<<16) | ((minor)<<8) | (patch) ) + +#define ${UPPER_PROJECT_NAME}_VERSION_MAJOR ${PROJECT_VERSION_MAJOR} +#define ${UPPER_PROJECT_NAME}_VERSION_MINOR ${PROJECT_VERSION_MINOR} +#define ${UPPER_PROJECT_NAME}_VERSION_PATCH ${PROJECT_VERSION_PATCH} + +// The version number of this extension. Used for #if comparisons. +// This is generated using the version set in the CMake project macro. +#define ${UPPER_PROJECT_NAME}_VERSION ${UPPER_PROJECT_NAME}_VERSION_CHECK( ${PROJECT_VERSION_MAJOR}, ${PROJECT_VERSION_MINOR}, ${PROJECT_VERSION_PATCH} ) + +namespace VersionInfo { + // Project name and version as a string. + // This is generated using the project name from the cmake project macro and the current git commit information. + // + // It uses the form " -<# commits since last tag>-". + // If there are no commits since the last tag, only the tag is shown. + constexpr std::string_view VERSION_STR = "${PROJECT_NAME} ${GIT_SHORT}"; + + // The version information as a string. + // This is generated using the current git commit information. + // + // It uses the form "-<# commits since last tag>-". + // If there are no commits since the last tag, only the tag is shown. + constexpr std::string_view VERSION_SHORT_STR = "${GIT_SHORT}"; + + // The full git SHA1 hash as a string. + // This is generated using the current git commit information. + constexpr std::string_view GIT_SHA1_STR = "${GIT_SHA1}"; +} diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipe.cpp b/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipe.cpp new file mode 100644 index 00000000..4622d554 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipe.cpp @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only +#include "WindowsPipe.h" + +bool WindowsPipe::connectToPipe() +{ + if (m_pipeName.empty()) { + std::cerr << "Pipe name not set." << std::endl; + return false; + } + + std::wstring fullPipeName = L"\\\\.\\pipe\\" + m_pipeName; + + m_hPipe = CreateFileW( + fullPipeName.c_str(), + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_FLAG_OVERLAPPED, + NULL); + + if (m_hPipe == INVALID_HANDLE_VALUE) { + std::cerr << "Failed to connect to pipe. Error code: " << GetLastError() << std::endl; + return false; + } + + return true; +} + +bool WindowsPipe::readFromPipe(std::string& outMessage) +{ + char buffer[128]; + DWORD bytesRead; + + if (!ReadFile(m_hPipe, buffer, sizeof(buffer) - 1, &bytesRead, &m_overlapped)) { + DWORD error = GetLastError(); + if (error == ERROR_IO_PENDING) { + // Check if the overlapped read operation is complete without waiting + if (!GetOverlappedResult(m_hPipe, &m_overlapped, &bytesRead, FALSE)) { + if (GetLastError() == ERROR_IO_INCOMPLETE) { + // The I/O operation is still pending (no data available yet) + return false; + } + std::cerr << "Overlapped ReadFile failed. Error code: " << GetLastError() << std::endl; + return false; + } + } else { + std::cerr << "ReadFile from pipe failed. Error code: " << error << std::endl; + return false; + } + } + + buffer[bytesRead] = '\0'; + outMessage = buffer; + return true; +} + +bool WindowsPipe::writeToPipe(const std::string& message) +{ + DWORD bytesWritten; + + if (!WriteFile(m_hPipe, message.c_str(), static_cast(message.size()), &bytesWritten, &m_overlapped)) { + if (GetLastError() != ERROR_IO_PENDING) { + std::cerr << "WriteFile to pipe failed. Error code: " << GetLastError() << std::endl; + return false; + } + WaitForSingleObject(m_overlapped.hEvent, INFINITE); + if (!GetOverlappedResult(m_hPipe, &m_overlapped, &bytesWritten, FALSE)) { + std::cerr << "Overlapped WriteFile failed. Error code: " << GetLastError() << std::endl; + return false; + } + } + + if (static_cast(bytesWritten) != message.size()) { + std::cerr << "Bytes written mismatch." << std::endl; + return false; + } + + return true; +} diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipe.h b/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipe.h new file mode 100644 index 00000000..894e6cf5 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipe.h @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only +#pragma once + +#include +#include +#include + +class WindowsPipe { +public: + WindowsPipe() + : m_hPipe(INVALID_HANDLE_VALUE) + { + memset(&m_overlapped, 0, sizeof(m_overlapped)); + m_overlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); // Manual reset event + } + + void setPipeName(const std::wstring& pipeName) + { + m_pipeName = pipeName; + } + + bool start() + { + return connectToPipe(); + } + + bool readFromPipe(std::string& outMessage); + bool writeToPipe(const std::string& message); + void close() + { + if (m_hPipe != INVALID_HANDLE_VALUE) { + CloseHandle(m_hPipe); + } + } + ~WindowsPipe() + { + close(); + CloseHandle(m_overlapped.hEvent); + } + +private: + bool connectToPipe(); + +private: + HANDLE m_hPipe; + OVERLAPPED m_overlapped; + std::wstring m_pipeName; +}; diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipeTest.cpp b/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipeTest.cpp new file mode 100644 index 00000000..bc388bfc --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/WindowsPipeTest.cpp @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only + +#include "WindowsPipe.h" + +#define CATCH_CONFIG_MAIN +#include + +TEST_CASE("Test WindowsPipe with Python echo server", "[WindowsPipe]") +{ + WindowsPipe client; + client.setPipeName(L"ScreenPlay"); + REQUIRE(client.start()); + const int count = 100; + + SECTION("Ping server and expect ping back") + { + for (size_t i = 0; i < count; i++) { + std::string message = "ping;"; + REQUIRE(client.writeToPipe(message)); + + std::string response; + REQUIRE(client.readFromPipe(response)); + REQUIRE(response == "pong;"); + std::cout << response << "ok\n"; + } + } +} diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/windowsPipeTestServer.py b/ScreenPlayWallpaper/Godot/GDExtention/src/windowsPipeTestServer.py new file mode 100644 index 00000000..af5bfd19 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/windowsPipeTestServer.py @@ -0,0 +1,56 @@ +# SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only +# python -m pip install pywin32 +import win32pipe +import win32file +import pywintypes +import time + +PIPE_NAME = 'ScreenPlay' + +def create_pipe(): + return win32pipe.CreateNamedPipe( + r'\\.\pipe\{}'.format(PIPE_NAME), + win32pipe.PIPE_ACCESS_DUPLEX, + win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT, + 1, # max instances + 65536, # out buffer size + 65536, # in buffer size + 0, # default timeout + None # security attributes + ) + +def main(): + print("Starting Python Pipe Server...") + pipe_handle = create_pipe() + print("Waiting for a client to connect...") + win32pipe.ConnectNamedPipe(pipe_handle, None) + + while True: + try: + # Reading from the client + result, data = win32file.ReadFile(pipe_handle, 4096) + if result == 0: # 0 means the read operation completed successfully + print("Received:", data.decode()) + + # Sending a response back to the client + response = "pong;" + win32file.WriteFile(pipe_handle, response.encode()) + + except pywintypes.error as e: + if e.args[0] == 109: # ERROR_BROKEN_PIPE + print("Client disconnected.") + # Disconnect and close the current pipe handle + win32pipe.DisconnectNamedPipe(pipe_handle) + win32file.CloseHandle(pipe_handle) + + # Create a new pipe instance for the next client + pipe_handle = create_pipe() + + else: + print("Error occurred:", e) + + + #time.sleep(0.01) + +if __name__ == '__main__': + main() diff --git a/ScreenPlayWallpaper/Godot/GDExtention/templates/CMakeLists.txt b/ScreenPlayWallpaper/Godot/GDExtention/templates/CMakeLists.txt new file mode 100644 index 00000000..167530ea --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/templates/CMakeLists.txt @@ -0,0 +1,36 @@ +# SPDX-License-Identifier: Unlicense + +add_custom_target(templates SOURCES template.debug.gdextension.in template.release.gdextension.in) + +add_dependencies(${PROJECT_NAME} templates) + +# We shouldn't be relying on CMAKE_BUILD_TYPE (see https://github.com/asmaloney/GDExtensionTemplate/issues/25) But until we fix it here and +# in godot-cpp, ensure it's one we expect. +set(ALLOWED_BUILDS "Debug;Release;debug;release") + +if(NOT + "${CMAKE_BUILD_TYPE}" + IN_LIST + ALLOWED_BUILDS) + message(FATAL_ERROR "CMAKE_BUILD_TYPE must be set to Debug or Release") +endif() + +# Get our gdextension input file name based on build type +string(TOLOWER ${CMAKE_BUILD_TYPE} BUILD_TYPE) +set(GD_EXTENSION_FILE_INPUT template.${BUILD_TYPE}.gdextension.in) + +# Workaround to add the "lib" prefix to the library in our template file if using MSYS2. +if(MINGW) + set(LIB_PREFIX "lib") +endif() + +# Generate our project's .gdextension file from the template +set(OUT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../ScreenPlayGodot/${PROJECT_NAME}/) +set(GD_EXTENSION_FILE ${PROJECT_NAME}.gdextension) +# configure_file(${GD_EXTENSION_FILE_INPUT} ${OUT_PATH}/${GD_EXTENSION_FILE}) + +unset(ALLOWED_BUILDS) +unset(BUILD_TYPE) +unset(GD_EXTENSION_FILE) +unset(GD_EXTENSION_FILE_INPUT) +unset(LIB_PREFIX) diff --git a/ScreenPlayWallpaper/Godot/GDExtention/templates/template.debug.gdextension.in b/ScreenPlayWallpaper/Godot/GDExtention/templates/template.debug.gdextension.in new file mode 100644 index 00000000..0765cee8 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/templates/template.debug.gdextension.in @@ -0,0 +1,10 @@ +[configuration] + +entry_symbol = "GDExtensionInit" +compatibility_minimum = 4.1 + +[libraries] + +linux.debug.x86_64 = "lib/Linux-x86_64/lib${PROJECT_NAME}-d.so" +macos.debug = "lib/Darwin-Universal/lib${PROJECT_NAME}-d.dylib" +windows.debug.x86_64 = "lib/Windows-AMD64/${LIB_PREFIX}${PROJECT_NAME}-d.dll" diff --git a/ScreenPlayWallpaper/Godot/GDExtention/templates/template.release.gdextension.in b/ScreenPlayWallpaper/Godot/GDExtention/templates/template.release.gdextension.in new file mode 100644 index 00000000..dd1c9362 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/GDExtention/templates/template.release.gdextension.in @@ -0,0 +1,10 @@ +[configuration] + +entry_symbol = "GDExtensionInit" +compatibility_minimum = 4.1 + +[libraries] + +linux.release.x86_64 = "lib/Linux-x86_64/lib${PROJECT_NAME}.so" +macos.release = "lib/Darwin-universal/lib${PROJECT_NAME}.dylib" +windows.release.x86_64 = "lib/Windows-AMD64/${LIB_PREFIX}${PROJECT_NAME}.dll" diff --git a/ScreenPlayWallpaper/Godot/ScreenPlayGodot/.gitattributes b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/.gitattributes new file mode 100644 index 00000000..8ad74f78 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/.gitattributes @@ -0,0 +1,2 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf diff --git a/ScreenPlayWallpaper/Godot/ScreenPlayGodot/.gitignore b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/.gitignore new file mode 100644 index 00000000..47091836 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/.gitignore @@ -0,0 +1,2 @@ +# Godot 4+ specific ignores +.godot/ diff --git a/ScreenPlayWallpaper/Godot/ScreenPlayGodot/ScreenPlayGodotWallpaper/ScreenPlayGodotWallpaper.gdextension b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/ScreenPlayGodotWallpaper/ScreenPlayGodotWallpaper.gdextension new file mode 100644 index 00000000..5cd17ebe --- /dev/null +++ b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/ScreenPlayGodotWallpaper/ScreenPlayGodotWallpaper.gdextension @@ -0,0 +1,13 @@ +[configuration] + +entry_symbol = "GDExtensionInit" +compatibility_minimum = 4.1 + +[libraries] + +macos.release = "res://ScreenPlayGodotWallpaper/lib/Darwin-universal/libScreenPlayGodotWallpaper.dylib" +macos.debug = "res://ScreenPlayGodotWallpaper/lib/Darwin-Universal/libScreenPlayGodotWallpaper-d.dylib" +linux.release.x86_64 = "res://ScreenPlayGodotWallpaper/lib/Linux-x86_64/libScreenPlayGodotWallpaper.so" +linux.debug.x86_64 = "res://ScreenPlayGodotWallpaper/lib/Linux-x86_64/libScreenPlayGodotWallpaper-d.so" +windows.release.x86_64 = "res://ScreenPlayGodotWallpaper/lib/Windows-AMD64/ScreenPlayGodotWallpaper.dll" +windows.debug.x86_64 = "res://ScreenPlayGodotWallpaper/lib/Windows-AMD64/ScreenPlayGodotWallpaper-d.dll" \ No newline at end of file diff --git a/ScreenPlayWallpaper/Godot/ScreenPlayGodot/export_presets.cfg b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/export_presets.cfg new file mode 100644 index 00000000..88e962f2 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/export_presets.cfg @@ -0,0 +1,61 @@ +[preset.0] + +name="Windows Desktop" +platform="Windows Desktop" +runnable=true +dedicated_server=false +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="" +encryption_include_filters="" +encryption_exclude_filters="" +encrypt_pck=false +encrypt_directory=false + +[preset.0.options] + +custom_template/debug="" +custom_template/release="" +debug/export_console_wrapper=1 +binary_format/embed_pck=false +texture_format/bptc=true +texture_format/s3tc=true +texture_format/etc=false +texture_format/etc2=false +binary_format/architecture="x86_64" +codesign/enable=false +codesign/timestamp=true +codesign/timestamp_server_url="" +codesign/digest_algorithm=1 +codesign/description="" +codesign/custom_options=PackedStringArray() +application/modify_resources=true +application/icon="" +application/console_wrapper_icon="" +application/icon_interpolation=4 +application/file_version="" +application/product_version="" +application/company_name="" +application/product_name="" +application/file_description="" +application/copyright="" +application/trademarks="" +ssh_remote_deploy/enabled=false +ssh_remote_deploy/host="user@host_ip" +ssh_remote_deploy/port="22" +ssh_remote_deploy/extra_args_ssh="" +ssh_remote_deploy/extra_args_scp="" +ssh_remote_deploy/run_script="Expand-Archive -LiteralPath '{temp_dir}\\{archive_name}' -DestinationPath '{temp_dir}' +$action = New-ScheduledTaskAction -Execute '{temp_dir}\\{exe_name}' -Argument '{cmd_args}' +$trigger = New-ScheduledTaskTrigger -Once -At 00:00 +$settings = New-ScheduledTaskSettingsSet +$task = New-ScheduledTask -Action $action -Trigger $trigger -Settings $settings +Register-ScheduledTask godot_remote_debug -InputObject $task -Force:$true +Start-ScheduledTask -TaskName godot_remote_debug +while (Get-ScheduledTask -TaskName godot_remote_debug | ? State -eq running) { Start-Sleep -Milliseconds 100 } +Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue" +ssh_remote_deploy/cleanup_script="Stop-ScheduledTask -TaskName godot_remote_debug -ErrorAction:SilentlyContinue +Unregister-ScheduledTask -TaskName godot_remote_debug -Confirm:$false -ErrorAction:SilentlyContinue +Remove-Item -Recurse -Force '{temp_dir}'" diff --git a/ScreenPlayWallpaper/Godot/ScreenPlayGodot/icon.svg b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/icon.svg new file mode 100644 index 00000000..b370ceb7 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/icon.svg @@ -0,0 +1 @@ + diff --git a/ScreenPlayWallpaper/Godot/ScreenPlayGodot/icon.svg.import b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/icon.svg.import new file mode 100644 index 00000000..fb6aa80d --- /dev/null +++ b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/icon.svg.import @@ -0,0 +1,37 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://by316gekc8lr7" +path="res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex" +metadata={ +"vram_texture": false +} + +[deps] + +source_file="res://icon.svg" +dest_files=["res://.godot/imported/icon.svg-218a8f2b3041327d8a5756f3a245f83b.ctex"] + +[params] + +compress/mode=0 +compress/high_quality=false +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=false +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=false +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=1 +svg/scale=1.0 +editor/scale_with_editor_scale=false +editor/convert_colors_with_editor_theme=false diff --git a/ScreenPlayWallpaper/Godot/ScreenPlayGodot/main.gd b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/main.gd new file mode 100644 index 00000000..71d21a4c --- /dev/null +++ b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/main.gd @@ -0,0 +1,129 @@ +extends Node3D + +@onready var screen_play_wallpaper: ScreenPlayGodotWallpaper = $ScreenPlayGodotWallpaper +@onready var ping_alive_timer: Timer = $PingAliveTimer +@onready var check_messages_timer: Timer = $CheckMessagesTimer +var send_welcome: bool = false + +# Pings main ScreenPlay application that +# this wallpaper is still active +func ping_alive(): + var success = screen_play_wallpaper.send_ping() + if not success: + terminate() + +func terminate(): + var exit = screen_play_wallpaper.exit() + print("exit ", exit) + get_tree().quit() + +# Checks for messages from the main ScreenPlay instance +# for example for propery changes or commands like quit +func check_messages(): + var msg = screen_play_wallpaper.read_from_pipe() + if not msg.is_empty(): + if "quit" in msg: + return terminate() + + +func _ready(): + ping_alive_timer.wait_time = 0.5 + ping_alive_timer.timeout.connect(ping_alive) + + check_messages_timer.wait_time = 0.5 + check_messages_timer.timeout.connect(check_messages) + + if not screen_play_wallpaper: + printerr("ERROR INVALID SCREENPLAY OBJECT") + return + + var path + var args = OS.get_cmdline_args() + if args.size() > 1: + if not parse_args(): + get_tree().quit() + return + #screen_play_wallpaper.set_projectPath("C:\\Code\\cpp\\ScreenPlay\\ScreenPlay\\Content\\wallpaper_godot_fjord") + path = screen_play_wallpaper.get_projectPath() + "/" + screen_play_wallpaper.get_projectPackageFile() + else: + get_tree().quit() + return + print(path) + if not load_scene(path): + print("Failed to load the PCK file.") + # No not call terminate here because we did not + # yet setup via screenplay_manager.init() + get_tree().quit() + return + Engine.set_max_fps(144) + + var ok = screen_play_wallpaper.init(screen_play_wallpaper.get_activeScreensList()[0]) + if not ok: + printerr("Unable to setup screen") + if not screen_play_wallpaper.get_pipeConnected(): + var ok_connect_to_named_pipe = screen_play_wallpaper.connect_to_named_pipe() + +func _process(delta): + + if not send_welcome: + if not screen_play_wallpaper.get_screenPlayConnected(): + send_welcome = screen_play_wallpaper.send_welcome() + if send_welcome: + check_messages_timer.start() + ping_alive_timer.start() + + +func load_scene(path): + var success = ProjectSettings.load_resource_pack(path) + if success: + var scene_resource = load("res://wallpaper.tscn") + if scene_resource: + var scene_instance = scene_resource.instantiate() + if scene_instance: + add_child(scene_instance) + else: + print("Failed to instantiate the wallpaper.tscn scene.") + return false + else: + print("Failed to load the wallpaper.tscn scene.") + return false + else: + print("Failed to load the PCK file.") + return false + return true + +func parse_args(): + var args = OS.get_cmdline_args() + print("Parse args:", args) + var offset = 0 + if args[0] == "res://main.tscn": + offset = 1 + + if args.size() < 8: # Adjust this number based on the expected number of arguments + print("Not enough arguments provided!") + return false + + var activeScreensList = [] + if args[0 + offset].is_valid_int(): + activeScreensList.append(args[0 + offset].to_int()) + else: + var potentialInts = args[0 + offset].split(",") + for val in potentialInts: + if not val.is_valid_int(): + print("Invalid argument: Not an integer:", val) + return false + else: + activeScreensList.append(val.to_int()) + + screen_play_wallpaper.set_projectPath(args[1 + offset]) + screen_play_wallpaper.set_appID(args[2 + offset].replace("appID=", "")) + screen_play_wallpaper.set_volume(float(args[3 + offset])) + #screen_play_wallpaper.set_fillmode(int(args[4 + offset])) + var type = args[5] # This might need further parsing depending on its expected format + screen_play_wallpaper.set_checkWallpaperVisible(args[6 + offset].to_lower() == "true") + screen_play_wallpaper.set_activeScreensList(activeScreensList) + screen_play_wallpaper.set_projectPackageFile(args[7 + offset]) + + # Print or use the parsed values as needed + print("Parsing done:", activeScreensList, screen_play_wallpaper.get_projectPath(), screen_play_wallpaper.get_appID(), screen_play_wallpaper.get_volume(), type, screen_play_wallpaper.get_checkWallpaperVisible()) + return true diff --git a/ScreenPlayWallpaper/Godot/ScreenPlayGodot/main.tscn b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/main.tscn new file mode 100644 index 00000000..6958b3e3 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/main.tscn @@ -0,0 +1,14 @@ +[gd_scene load_steps=2 format=3 uid="uid://bc5caslt2tiuk"] + +[ext_resource type="Script" path="res://main.gd" id="1_ceeuk"] + +[node name="Wallpaper" type="Node3D"] +script = ExtResource("1_ceeuk") + +[node name="ScreenPlayGodotWallpaper" type="ScreenPlayGodotWallpaper" parent="."] + +[node name="PingAliveTimer" type="Timer" parent="."] +wait_time = 0.5 + +[node name="CheckMessagesTimer" type="Timer" parent="."] +wait_time = 0.5 diff --git a/ScreenPlayWallpaper/Godot/ScreenPlayGodot/project.godot b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/project.godot new file mode 100644 index 00000000..d48bcd61 --- /dev/null +++ b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/project.godot @@ -0,0 +1,41 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +[application] + +config/name="ScreenPlay" +run/main_scene="res://main.tscn" +config/features=PackedStringArray("4.2", "Mobile") +run/flush_stdout_on_print=true +boot_splash/bg_color=Color(0.141176, 0.141176, 0.141176, 0) +boot_splash/show_image=false +boot_splash/fullsize=false +config/icon="res://icon.svg" + +[display] + +window/size/viewport_width=1 +window/size/viewport_height=1 +window/size/resizable=false +window/size/borderless=true +window/size/transparent=true +window/energy_saving/keep_screen_on=false + +[editor] + +run/main_run_args="\"1\" \"C:/Code/Cpp/ScreenPlay/ScreenPlay/Content/wallpaper_godot_fjord\" \"appID=test\" \"1\" \"Cover\" \"GodotWallpaper\" \"1\" \"project-v1.zip\"" + +[filesystem] + +import/blender/enabled=false + +[rendering] + +renderer/rendering_method="mobile" diff --git a/ScreenPlayWallpaper/main.cpp b/ScreenPlayWallpaper/main.cpp index 32f9ddf3..1092705a 100644 --- a/ScreenPlayWallpaper/main.cpp +++ b/ScreenPlayWallpaper/main.cpp @@ -9,23 +9,25 @@ #include "ScreenPlayWallpaper/CMakeVariables.h" #include "ScreenPlayUtil/exitcodes.h" +#include "ScreenPlayUtil/logginghandler.h" #include "ScreenPlayUtil/util.h" #if defined(Q_OS_WIN) #include "src/winwindow.h" Q_IMPORT_QML_PLUGIN(ScreenPlaySysInfoPlugin) #elif defined(Q_OS_LINUX) -#include "src/linuxx11window.h" #include "src/linuxwaylandwindow.h" -#elif defined(Q_OS_OSX) +#include "src/linuxx11window.h" +#elif defined(Q_OS_MACOS) #include "src/macwindow.h" #endif Q_IMPORT_QML_PLUGIN(ScreenPlayWeatherPlugin) +Q_IMPORT_QML_PLUGIN(ScreenPlayUtilPlugin) int main(int argc, char* argv[]) { - + using namespace ScreenPlay; // Lets keep using it until: https://bugreports.qt.io/browse/QTBUG-109401 QtWebEngineQuick::initialize(); @@ -36,24 +38,26 @@ int main(int argc, char* argv[]) #endif QGuiApplication app(argc, argv); + std::unique_ptr logging; std::unique_ptr window; const auto platformName = QGuiApplication::platformName(); #if defined(Q_OS_WIN) window = std::make_unique(); #elif defined(Q_OS_LINUX) - if(platformName == "xcb"){ - window = std::make_unique(); - } else if(platformName == "wayland"){ + if (platformName == "xcb") { + window = std::make_unique(); + } else if (platformName == "wayland") { window = std::make_unique(); } -#elif defined(Q_OS_OSX) +#elif defined(Q_OS_MACOS) window = std::make_unique(); #endif // If we start with only one argument (app path) // It means we want to test a single wallpaper const QStringList argumentList = app.arguments(); + QString appID; // For testing purposes when starting the ScreenPlayWallpaper directly. if (argumentList.length() == 1) { @@ -66,7 +70,7 @@ int main(int argc, char* argv[]) "/wallpaper_video_astronaut_vp9", // 4 "/wallpaper_video_nebula_h264" // 5 }; - const int index = 1; + const int index = 5; QString projectPath = exampleContentPath + contentFolder.at(index); window->setActiveScreensList({ 0 }); @@ -74,47 +78,47 @@ int main(int argc, char* argv[]) window->setAppID("test"); window->setVolume(1); window->setFillMode("cover"); - window->setType(ScreenPlay::InstalledType::InstalledType::VideoWallpaper); + window->setType(ScreenPlay::ContentTypes::InstalledType::VideoWallpaper); window->setCheckWallpaperVisible(true); window->setDebugMode(false); } else { // 8 parameter + 1 OS working directory as the first default paramter if (argumentList.length() != 9) { - return static_cast(ScreenPlay::WallpaperExitCode::Invalid_ArgumentSize); + return static_cast(WallpaperExit::Code::Invalid_ArgumentSize); } - - const auto activeScreensList = ScreenPlayUtil::parseStringToIntegerList(argumentList.at(1)); + ScreenPlay::Util util; + const auto activeScreensList = util.parseStringToIntegerList(argumentList.at(1)); if (!activeScreensList.has_value()) { qCritical("Could not activeScreensList"); - return static_cast(ScreenPlay::WallpaperExitCode::Invalid_ActiveScreensList); + return static_cast(WallpaperExit::Code::Invalid_ActiveScreensList); } - auto installedType = ScreenPlay::InstalledType::InstalledType::Unknown; - if (auto typeOpt = ScreenPlayUtil::getInstalledTypeFromString(argumentList.at(6))) { + auto installedType = ScreenPlay::ContentTypes::InstalledType::Unknown; + if (auto typeOpt = util.getInstalledTypeFromString(argumentList.at(6))) { installedType = typeOpt.value(); } else { qCritical() << "Cannot parse Wallpaper type from value" << argumentList.at(6); - return static_cast(ScreenPlay::WallpaperExitCode::Invalid_InstalledType); + return static_cast(WallpaperExit::Code::Invalid_InstalledType); } bool okParseCheckWallpaperVisible = false; const bool checkWallpaperVisible = argumentList.at(7).toInt(&okParseCheckWallpaperVisible); if (!okParseCheckWallpaperVisible) { qCritical("Could not parse checkWallpaperVisible"); - return static_cast(ScreenPlay::WallpaperExitCode::Invalid_CheckWallpaperVisible); + return static_cast(WallpaperExit::Code::Invalid_CheckWallpaperVisible); } bool okParseVolume = 0.0f; const float volume = argumentList.at(4).toFloat(&okParseVolume); if (!okParseVolume) { qCritical("Could not parse Volume"); - return static_cast(ScreenPlay::WallpaperExitCode::Invalid_Volume); + return static_cast(WallpaperExit::Code::Invalid_Volume); } - QString appID = argumentList.at(3); + appID = argumentList.at(3); if (!appID.startsWith("appID=")) { qCritical("Invalid appID"); - return static_cast(ScreenPlay::WallpaperExitCode::Invalid_AppID); + return static_cast(WallpaperExit::Code::Invalid_AppID); } appID = appID.remove("appID="); @@ -129,13 +133,16 @@ int main(int argc, char* argv[]) } const auto setupStatus = window->setup(); - if (setupStatus != ScreenPlay::WallpaperExitCode::Ok) { + if (setupStatus != WallpaperExit::Code::Ok) { return static_cast(setupStatus); } const auto startStatus = window->start(); - if (startStatus != ScreenPlay::WallpaperExitCode::Ok) { + if (startStatus != WallpaperExit::Code::Ok) { return static_cast(startStatus); } emit window->qmlStart(); - return app.exec(); + logging = std::make_unique("ScreenPlayWallpaper_" + appID); + const int status = app.exec(); + logging.reset(); + return status; } diff --git a/ScreenPlayWallpaper/qml/MultimediaWebView.qml b/ScreenPlayWallpaper/qml/MultimediaWebView.qml index 2f37fed5..9e7dd425 100644 --- a/ScreenPlayWallpaper/qml/MultimediaWebView.qml +++ b/ScreenPlayWallpaper/qml/MultimediaWebView.qml @@ -1,6 +1,5 @@ import QtQuick import QtWebEngine -import ScreenPlay.Enums.InstalledType import ScreenPlayWallpaper /*! diff --git a/ScreenPlayWallpaper/qml/Test.qml b/ScreenPlayWallpaper/qml/Test.qml index 76fa0f6d..299dc93e 100644 --- a/ScreenPlayWallpaper/qml/Test.qml +++ b/ScreenPlayWallpaper/qml/Test.qml @@ -104,14 +104,6 @@ Rectangle { } } - ImageParticle { - height: 16 - width: 16 - source: "dot.png" - system: particleSystem - opacity: root.imgOpacity - } - Text { id: txtMousePos @@ -164,6 +156,7 @@ Rectangle { } Row { + id: rowCounter spacing: 20 anchors { @@ -205,18 +198,27 @@ Rectangle { } } - // WebView { - // width: 1000 - // height: 400 - // url: "https://screen-play.app" + Column { - // anchors { - // horizontalCenter: parent.horizontalCenter - // bottom: parent.bottom - // bottomMargin: 50 - // } + anchors { + horizontalCenter: parent.horizontalCenter + top: rowCounter.bottom + topMargin: 20 + } + spacing: 20 + TextField { + placeholderText: "Edit me" + } + Button { + text: "Exit" + onClicked: { + Qt.callLater(function () { + Wallpaper.terminate(); + }); + } + } + } - // } MultimediaView { width: 1000 height: 400 diff --git a/ScreenPlayWallpaper/qml/Wallpaper.qml b/ScreenPlayWallpaper/qml/Wallpaper.qml index 5a6e0163..d025ce75 100644 --- a/ScreenPlayWallpaper/qml/Wallpaper.qml +++ b/ScreenPlayWallpaper/qml/Wallpaper.qml @@ -2,8 +2,7 @@ import QtQml import QtQuick import QtQuick.Controls import ScreenPlayWallpaper -import ScreenPlay.Enums.InstalledType -import ScreenPlay.Enums.VideoCodec +import ScreenPlayUtil Rectangle { id: root @@ -14,14 +13,15 @@ Rectangle { function start() { fadeInImageSetup(); switch (Wallpaper.type) { - case InstalledType.VideoWallpaper: - if (Wallpaper.videoCodec === VideoCodec.Unknown) { + case ContentTypes.InstalledType.VideoWallpaper: + if (Wallpaper.videoCodec === Video.VideoCodec.Unknown) { Wallpaper.terminate(); } // macOS only supports h264 via the native Qt MM if (Qt.platform.os === "osx") { - if ((Wallpaper.videoCodec === VideoCodec.VP8 || Wallpaper.videoCodec === VideoCodec.VP9)) { + print(ContentTypes.InstalledType.VideoWallpaper); + if ((Wallpaper.videoCodec === Video.VideoCodec.VP8 || Wallpaper.videoCodec === Video.VideoCodec.VP9)) { loader.source = "qrc:/qml/ScreenPlayWallpaper/qml/MultimediaWebView.qml"; } else { loader.source = "qrc:/qml/ScreenPlayWallpaper/qml/MultimediaView.qml"; @@ -31,20 +31,20 @@ Rectangle { loader.source = "qrc:/qml/ScreenPlayWallpaper/qml/MultimediaView.qml"; } break; - case InstalledType.HTMLWallpaper: + case ContentTypes.InstalledType.HTMLWallpaper: loader.setSource("qrc:/qml/ScreenPlayWallpaper/qml/WebsiteWallpaper.qml", { "url": Qt.resolvedUrl(Wallpaper.projectSourceFileAbsolute) }); break; - case InstalledType.QMLWallpaper: + case ContentTypes.InstalledType.QMLWallpaper: loader.source = Qt.resolvedUrl(Wallpaper.projectSourceFileAbsolute); break; - case InstalledType.WebsiteWallpaper: + case ContentTypes.InstalledType.WebsiteWallpaper: loader.setSource("qrc:/qml/ScreenPlayWallpaper/qml/WebsiteWallpaper.qml", { "url": Wallpaper.projectSourceFileAbsolute }); break; - case InstalledType.GifWallpaper: + case ContentTypes.InstalledType.GifWallpaper: loader.setSource("qrc:/qml/ScreenPlayWallpaper/qml/GifWallpaper.qml", { "source": Qt.resolvedUrl(Wallpaper.projectSourceFileAbsolute) }); @@ -171,7 +171,7 @@ Rectangle { function onReloadVideo(oldType) { // We need to check if the old type // was also Video not get called twice - if (oldType === InstalledType.VideoWallpaper) + if (oldType === ContentTypes.InstalledType.VideoWallpaper) return; loader.source = "qrc:/qml/ScreenPlayWallpaper/qml/MultimediaView.qml"; } @@ -184,7 +184,7 @@ Rectangle { //asynchronous: true onStatusChanged: { if (loader.status === Loader.Ready) { - if (Wallpaper.type === InstalledType.QMLWallpaper) { + if (Wallpaper.type === ContentTypes.InstalledType.QMLWallpaper) { root.fadeIn(); } } diff --git a/ScreenPlayWallpaper/src/basewindow.cpp b/ScreenPlayWallpaper/src/basewindow.cpp index 67231f16..0560f377 100644 --- a/ScreenPlayWallpaper/src/basewindow.cpp +++ b/ScreenPlayWallpaper/src/basewindow.cpp @@ -18,42 +18,27 @@ \brief . */ +namespace ScreenPlay { BaseWindow::BaseWindow() { QGuiApplication::instance()->installEventFilter(this); - - qRegisterMetaType(); - qmlRegisterUncreatableMetaObject(ScreenPlay::InstalledType::staticMetaObject, - "ScreenPlay.Enums.InstalledType", - 1, 0, - "InstalledType", - "Error: only enums"); - - qmlRegisterUncreatableMetaObject(ScreenPlay::VideoCodec::staticMetaObject, - "ScreenPlay.Enums.VideoCodec", - 1, 0, - "VideoCodec", - "Error: only enums"); - - qmlRegisterType("ScreenPlay.Wallpaper", 1, 0, "Wallpaper"); - setOSVersion(QSysInfo::productVersion()); } -ScreenPlay::WallpaperExitCode BaseWindow::setup() +WallpaperExit::Code BaseWindow::setup() { if (projectPath() == "test") { - setType(ScreenPlay::InstalledType::InstalledType::QMLWallpaper); + setType(ScreenPlay::ContentTypes::InstalledType::QMLWallpaper); setProjectSourceFileAbsolute({ "qrc:/qml/ScreenPlayWallpaper/qml/Test.qml" }); setupLiveReloading(); - return ScreenPlay::WallpaperExitCode::Ok; + return WallpaperExit::Code::Ok; } ScreenPlay::ProjectFile projectFile; projectFile.projectJsonFilePath = QFileInfo(projectPath() + "/project.json"); if (!projectFile.init()) { qWarning() << "Invalid project at " << projectPath(); - return ScreenPlay::WallpaperExitCode::Invalid_Setup_ProjectParsingError; + return WallpaperExit::Code::Invalid_Setup_ProjectParsingError; } setType(projectFile.type); setProjectSourceFile(projectFile.file); @@ -67,7 +52,7 @@ ScreenPlay::WallpaperExitCode BaseWindow::setup() } } - if (m_type == ScreenPlay::InstalledType::InstalledType::WebsiteWallpaper) { + if (m_type == ScreenPlay::ContentTypes::InstalledType::WebsiteWallpaper) { setProjectSourceFileAbsolute(projectFile.url); } else { setProjectSourceFileAbsolute(QUrl::fromLocalFile(projectPath() + "/" + projectSourceFile())); @@ -84,7 +69,7 @@ ScreenPlay::WallpaperExitCode BaseWindow::setup() sdk()->start(); } - return ScreenPlay::WallpaperExitCode::Ok; + return WallpaperExit::Code::Ok; } /*! @@ -161,12 +146,12 @@ void BaseWindow::replaceWallpaper( const QString type, const bool checkWallpaperVisible) { - const ScreenPlay::InstalledType::InstalledType oldType = this->type(); + const ScreenPlay::ContentTypes::InstalledType oldType = this->type(); setCheckWallpaperVisible(checkWallpaperVisible); setVolume(volume); setFillMode(fillMode); - if (auto typeOpt = ScreenPlayUtil::getInstalledTypeFromString(type)) { + if (auto typeOpt = ScreenPlay::Util().getInstalledTypeFromString(type)) { setType(typeOpt.value()); } @@ -176,13 +161,13 @@ void BaseWindow::replaceWallpaper( setProjectSourceFileAbsolute(QUrl::fromUserInput(absolutePath + "/" + file)); } - if (m_type == ScreenPlay::InstalledType::InstalledType::QMLWallpaper || m_type == ScreenPlay::InstalledType::InstalledType::HTMLWallpaper) + if (m_type == ScreenPlay::ContentTypes::InstalledType::QMLWallpaper || m_type == ScreenPlay::ContentTypes::InstalledType::HTMLWallpaper) emit reloadQML(oldType); - if (m_type == ScreenPlay::InstalledType::InstalledType::VideoWallpaper) + if (m_type == ScreenPlay::ContentTypes::InstalledType::VideoWallpaper) emit reloadVideo(oldType); - if (m_type == ScreenPlay::InstalledType::InstalledType::GifWallpaper) + if (m_type == ScreenPlay::ContentTypes::InstalledType::GifWallpaper) emit reloadGIF(oldType); } @@ -244,17 +229,18 @@ void BaseWindow::setupLiveReloading() } } -ScreenPlay::VideoCodec::VideoCodec BaseWindow::videoCodec() const +ScreenPlay::Video::VideoCodec BaseWindow::videoCodec() const { return m_videoCodec; } -void BaseWindow::setVideoCodec(ScreenPlay::VideoCodec::VideoCodec newVideoCodec) +void BaseWindow::setVideoCodec(ScreenPlay::Video::VideoCodec newVideoCodec) { if (m_videoCodec == newVideoCodec) return; m_videoCodec = newVideoCodec; emit videoCodecChanged(newVideoCodec); } +} #include "moc_basewindow.cpp" diff --git a/ScreenPlayWallpaper/src/basewindow.h b/ScreenPlayWallpaper/src/basewindow.h index 97ad3c3f..0db1c384 100644 --- a/ScreenPlayWallpaper/src/basewindow.h +++ b/ScreenPlayWallpaper/src/basewindow.h @@ -19,15 +19,16 @@ #include +namespace ScreenPlay { class BaseWindow : public QObject { Q_OBJECT public: BaseWindow(); - virtual ScreenPlay::WallpaperExitCode setup() final; + virtual WallpaperExit::Code setup() final; - virtual ScreenPlay::WallpaperExitCode start() = 0; + virtual WallpaperExit::Code start() = 0; Q_PROPERTY(int width READ width WRITE setWidth NOTIFY widthChanged) Q_PROPERTY(int height READ height WRITE setHeight NOTIFY heightChanged) @@ -54,8 +55,8 @@ public: Q_PROPERTY(float playbackRate READ playbackRate WRITE setPlaybackRate NOTIFY playbackRateChanged) Q_PROPERTY(float currentTime READ currentTime WRITE setCurrentTime NOTIFY currentTimeChanged) - Q_PROPERTY(ScreenPlay::InstalledType::InstalledType type READ type WRITE setType NOTIFY typeChanged) - Q_PROPERTY(ScreenPlay::VideoCodec::VideoCodec videoCodec READ videoCodec WRITE setVideoCodec NOTIFY videoCodecChanged) + Q_PROPERTY(ScreenPlay::ContentTypes::InstalledType type READ type WRITE setType NOTIFY typeChanged) + Q_PROPERTY(ScreenPlay::Video::VideoCodec videoCodec READ videoCodec WRITE setVideoCodec NOTIFY videoCodecChanged) Q_PROPERTY(QString OSVersion READ OSVersion WRITE setOSVersion NOTIFY OSVersionChanged) Q_PROPERTY(ScreenPlaySDK* sdk READ sdk WRITE setSdk NOTIFY sdkChanged) @@ -64,7 +65,7 @@ public: float volume() const { return m_volume; } bool isPlaying() const { return m_isPlaying; } float playbackRate() const { return m_playbackRate; } - ScreenPlay::InstalledType::InstalledType type() const { return m_type; } + ScreenPlay::ContentTypes::InstalledType type() const { return m_type; } QString appID() const { return m_appID; } QString OSVersion() const { return m_OSVersion; } bool muted() const { return m_muted; } @@ -82,22 +83,22 @@ public: const QString& projectSourceFile() const { return m_projectSourceFile; } const QUrl& projectSourceFileAbsolute() const { return m_projectSourceFileAbsolute; } - ScreenPlay::VideoCodec::VideoCodec videoCodec() const; - void setVideoCodec(ScreenPlay::VideoCodec::VideoCodec newVideoCodec); + ScreenPlay::Video::VideoCodec videoCodec() const; + void setVideoCodec(ScreenPlay::Video::VideoCodec newVideoCodec); signals: void qmlStart(); void qmlExit(); void fadeIn(); - void reloadQML(const ScreenPlay::InstalledType::InstalledType oldType); - void reloadVideo(const ScreenPlay::InstalledType::InstalledType oldType); - void reloadGIF(const ScreenPlay::InstalledType::InstalledType oldType); + void reloadQML(const ScreenPlay::ContentTypes::InstalledType oldType); + void reloadVideo(const ScreenPlay::ContentTypes::InstalledType oldType); + void reloadGIF(const ScreenPlay::ContentTypes::InstalledType oldType); void loopsChanged(bool loops); void volumeChanged(float volume); void isPlayingChanged(bool isPlaying); void playbackRateChanged(float playbackRate); - void typeChanged(ScreenPlay::InstalledType::InstalledType type); + void typeChanged(ScreenPlay::ContentTypes::InstalledType type); void appIDChanged(QString appID); void qmlSceneValueReceived(QString key, QString value); void OSVersionChanged(QString OSVersion); @@ -115,7 +116,7 @@ signals: void projectPathChanged(const QString& rojectPath); void projectSourceFileChanged(const QString& projectSourceFile); void projectSourceFileAbsoluteChanged(const QUrl& rojectSourceFileAbsolute); - void videoCodecChanged(ScreenPlay::VideoCodec::VideoCodec codec); + void videoCodecChanged(ScreenPlay::Video::VideoCodec codec); public slots: void requestFadeIn(); @@ -173,7 +174,7 @@ public slots: m_playbackRate = playbackRate; emit playbackRateChanged(m_playbackRate); } - void setType(ScreenPlay::InstalledType::InstalledType type) + void setType(ScreenPlay::ContentTypes::InstalledType type) { if (m_type == type) return; @@ -231,10 +232,10 @@ public slots: fillMode = fillMode.toLower(); - if (!ScreenPlayUtil::getAvailableFillModes().contains(fillMode)) { + if (!ScreenPlay::Util().getAvailableFillModes().contains(fillMode)) { qWarning() << "Unable to set fillmode, the provided value did not match the available values" << "Provided: " << fillMode - << "Available: " << ScreenPlayUtil::getAvailableFillModes(); + << "Available: " << ScreenPlay::Util().getAvailableFillModes(); return; } @@ -348,12 +349,13 @@ protected: int m_width { 0 }; int m_height { 0 }; - ScreenPlay::InstalledType::InstalledType m_type = ScreenPlay::InstalledType::InstalledType::Unknown; + ScreenPlay::ContentTypes::InstalledType m_type = ScreenPlay::ContentTypes::InstalledType::Unknown; QVector m_activeScreensList; QFileSystemWatcher m_fileSystemWatcher; QTimer m_liveReloadLimiter; QSysInfo m_sysinfo; std::unique_ptr m_sdk; QUrl m_projectSourceFileAbsolute; - ScreenPlay::VideoCodec::VideoCodec m_videoCodec = ScreenPlay::VideoCodec::VideoCodec::Unknown; + ScreenPlay::Video::VideoCodec m_videoCodec = ScreenPlay::Video::VideoCodec::Unknown; }; +} \ No newline at end of file diff --git a/ScreenPlayWallpaper/src/linuxwaylandwindow.cpp b/ScreenPlayWallpaper/src/linuxwaylandwindow.cpp index 5879cdeb..90f82835 100644 --- a/ScreenPlayWallpaper/src/linuxwaylandwindow.cpp +++ b/ScreenPlayWallpaper/src/linuxwaylandwindow.cpp @@ -1,12 +1,13 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "linuxwaylandwindow.h" -#include #include +#include -#include #include +#include -ScreenPlay::WallpaperExitCode LinuxWaylandWindow::start() +namespace ScreenPlay { +WallpaperExit::Code LinuxWaylandWindow::start() { if (!debugMode()) { @@ -22,24 +23,16 @@ ScreenPlay::WallpaperExitCode LinuxWaylandWindow::start() // Get the Wayland display if (QGuiApplication::platformName() == "wayland") { - QPlatformNativeInterface *native = QGuiApplication::platformNativeInterface(); - + QPlatformNativeInterface* native = QGuiApplication::platformNativeInterface(); - auto *layerShell = LayerShellQt::Window::get(&m_window); - layerShell->setLayer(LayerShellQt::Window::LayerBackground); - layerShell->setAnchors(static_cast>( - LayerShellQt::Window::Anchor::AnchorTop | - LayerShellQt::Window::Anchor::AnchorBottom | - LayerShellQt::Window::Anchor::AnchorLeft | - LayerShellQt::Window::Anchor::AnchorRight - )); - - - + auto* layerShell = LayerShellQt::Window::get(&m_window); + layerShell->setLayer(LayerShellQt::Window::LayerBackground); + layerShell->setAnchors(static_cast>( + LayerShellQt::Window::Anchor::AnchorTop | LayerShellQt::Window::Anchor::AnchorBottom | LayerShellQt::Window::Anchor::AnchorLeft | LayerShellQt::Window::Anchor::AnchorRight)); } m_window.show(); - return ScreenPlay::WallpaperExitCode::Ok; + return WallpaperExit::Code::Ok; } void LinuxWaylandWindow::setupWallpaperForOneScreen(int activeScreen) @@ -67,4 +60,5 @@ void LinuxWaylandWindow::destroyThis() void LinuxWaylandWindow::terminate() { QCoreApplication::quit(); +} } \ No newline at end of file diff --git a/ScreenPlayWallpaper/src/linuxwaylandwindow.h b/ScreenPlayWallpaper/src/linuxwaylandwindow.h index 2a949a61..e014c311 100644 --- a/ScreenPlayWallpaper/src/linuxwaylandwindow.h +++ b/ScreenPlayWallpaper/src/linuxwaylandwindow.h @@ -14,11 +14,12 @@ #include "basewindow.h" +namespace ScreenPlay { class LinuxWaylandWindow : public BaseWindow { Q_OBJECT public: - ScreenPlay::WallpaperExitCode start() override; + WallpaperExit::Code start() override; signals: @@ -33,3 +34,4 @@ private: void setupWallpaperForAllScreens(); void setupWallpaperForMultipleScreens(const QVector& activeScreensList); }; +} \ No newline at end of file diff --git a/ScreenPlayWallpaper/src/linuxx11window.cpp b/ScreenPlayWallpaper/src/linuxx11window.cpp index eed0d645..eeb20dc8 100644 --- a/ScreenPlayWallpaper/src/linuxx11window.cpp +++ b/ScreenPlayWallpaper/src/linuxx11window.cpp @@ -24,7 +24,8 @@ #define NAME "xwinwrap" #define ATOM(a) XInternAtom(display, #a, False) -ScreenPlay::WallpaperExitCode LinuxX11Window::start() +namespace ScreenPlay { +WallpaperExit::Code LinuxX11Window::start() { if (!debugMode()) { @@ -111,7 +112,7 @@ ScreenPlay::WallpaperExitCode LinuxX11Window::start() m_window.setResizeMode(QQuickView::ResizeMode::SizeRootObjectToView); m_window.setSource(QUrl("qrc:/qml/ScreenPlayWallpaper/qml/Wallpaper.qml")); m_window.show(); - return ScreenPlay::WallpaperExitCode::Ok; + return WallpaperExit::Code::Ok; } void LinuxX11Window::setupWallpaperForOneScreen(int activeScreen) @@ -139,4 +140,5 @@ void LinuxX11Window::destroyThis() void LinuxX11Window::terminate() { QCoreApplication::quit(); +} } \ No newline at end of file diff --git a/ScreenPlayWallpaper/src/linuxx11window.h b/ScreenPlayWallpaper/src/linuxx11window.h index 26e151dc..0eac4c78 100644 --- a/ScreenPlayWallpaper/src/linuxx11window.h +++ b/ScreenPlayWallpaper/src/linuxx11window.h @@ -13,12 +13,12 @@ #include #include "basewindow.h" - +namespace ScreenPlay { class LinuxX11Window : public BaseWindow { Q_OBJECT public: - ScreenPlay::WallpaperExitCode start() override; + WallpaperExit::Code start() override; signals: @@ -33,3 +33,5 @@ private: void setupWallpaperForAllScreens(); void setupWallpaperForMultipleScreens(const QVector& activeScreensList); }; + +} \ No newline at end of file diff --git a/ScreenPlayWallpaper/src/macwindow.cpp b/ScreenPlayWallpaper/src/macwindow.cpp index a06f5ef6..b4a221aa 100644 --- a/ScreenPlayWallpaper/src/macwindow.cpp +++ b/ScreenPlayWallpaper/src/macwindow.cpp @@ -4,7 +4,8 @@ #include -ScreenPlay::WallpaperExitCode MacWindow::start() +namespace ScreenPlay { +WallpaperExit::Code MacWindow::start() { MacUtils::showDockIcon(false); @@ -31,7 +32,7 @@ ScreenPlay::WallpaperExitCode MacWindow::start() MacIntegration* macIntegration = new MacIntegration(this); macIntegration->SetBackgroundLevel(&m_window); - return ScreenPlay::WallpaperExitCode::Ok; + return WallpaperExit::Code::Ok; } void MacWindow::setVisible(bool show) @@ -53,5 +54,5 @@ void MacWindow::clearComponentCache() { m_window.engine()->clearComponentCache(); } - +} #include "moc_macwindow.cpp" diff --git a/ScreenPlayWallpaper/src/macwindow.h b/ScreenPlayWallpaper/src/macwindow.h index 796fd01a..1af3adac 100644 --- a/ScreenPlayWallpaper/src/macwindow.h +++ b/ScreenPlayWallpaper/src/macwindow.h @@ -15,10 +15,11 @@ #include "basewindow.h" #include "macintegration.h" +namespace ScreenPlay { class MacWindow : public BaseWindow { Q_OBJECT public: - ScreenPlay::WallpaperExitCode start() override; + WallpaperExit::Code start() override; signals: @@ -31,3 +32,4 @@ public slots: private: QQuickView m_window; }; +} \ No newline at end of file diff --git a/ScreenPlayWallpaper/src/windowsintegration.cpp b/ScreenPlayWallpaper/src/windowsintegration.cpp new file mode 100644 index 00000000..def9feef --- /dev/null +++ b/ScreenPlayWallpaper/src/windowsintegration.cpp @@ -0,0 +1,472 @@ +#include "windowsintegration.h" + +/*! + \brief Returns scaling factor as reported by Windows. +*/ +float WindowsIntegration::getScaling(const int monitorIndex) const +{ + // Get all monitors + int monitorCount = GetSystemMetrics(SM_CMONITORS); + + if (monitorIndex < 0 || monitorIndex >= monitorCount) { + // Invalid monitor index + return 1.0f; + } + + DISPLAY_DEVICE displayDevice; + ZeroMemory(&displayDevice, sizeof(displayDevice)); + displayDevice.cb = sizeof(displayDevice); + + // Enumerate through monitors until we find the one we're looking for + for (int i = 0; EnumDisplayDevices(NULL, i, &displayDevice, 0); i++) { + if (i == monitorIndex) { + DEVMODE devMode; + ZeroMemory(&devMode, sizeof(devMode)); + devMode.dmSize = sizeof(devMode); + + // Get settings for selected monitor + if (!EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode)) { + // Unable to get monitor settings + return 1.0f; + } + + // Get DPI for selected monitor + HMONITOR hMonitor = MonitorFromPoint({ devMode.dmPosition.x, devMode.dmPosition.y }, MONITOR_DEFAULTTONEAREST); + UINT dpiX = 0, dpiY = 0; + if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) { + return (float)dpiX / 96.0f; // Standard DPI is 96 + } + } + } + + // If we reach here, it means we couldn't find the monitor with the given index or couldn't get the DPI. + return 1.0f; +} + +bool WindowsIntegration::searchWorkerWindowToParentTo() +{ + HWND progman_hwnd = FindWindowW(L"Progman", L"Program Manager"); + const DWORD WM_SPAWN_WORKER = 0x052C; + SendMessageTimeoutW(progman_hwnd, WM_SPAWN_WORKER, 0xD, 0x1, SMTO_NORMAL, + 10000, nullptr); + + return EnumWindows(SearchForWorkerWindow, reinterpret_cast(&m_windowHandleWorker)); +} +/*! + \brief Searches for the worker window for our window to parent to. +*/ +BOOL SearchForWorkerWindow(HWND hwnd, LPARAM lparam) +{ + // 0xXXXXXXX "" WorkerW + // ... + // 0xXXXXXXX "" SHELLDLL_DefView + // 0xXXXXXXXX "FolderView" SysListView32 + // 0xXXXXXXXX "" WorkerW <---- We want this one + // 0xXXXXXXXX "Program Manager" Progman + if (FindWindowExW(hwnd, nullptr, L"SHELLDLL_DefView", nullptr)) + *reinterpret_cast(lparam) = FindWindowExW(nullptr, hwnd, L"WorkerW", nullptr); + return TRUE; +} + +std::vector WindowsIntegration::getAllMonitors() +{ + std::vector monitors; + + // Use the static MonitorEnumProc callback for EnumDisplayMonitors + EnumDisplayMonitors(NULL, NULL, MonitorEnumProc, reinterpret_cast(&monitors)); + + return monitors; +} + +int WindowsIntegration::GetMonitorIndex(HMONITOR hMonitor) +{ + sEnumInfo info; + info.hMonitor = hMonitor; + + if (EnumDisplayMonitors(NULL, NULL, GetMonitorByHandle, (LPARAM)&info)) + return -1; + + return info.iIndex; +} +/*! + \brief This method is called via a fixed interval to detect if a window completely + covers a monitor. If then sets visualPaused for QML to pause the content. +*/ +bool WindowsIntegration::checkForFullScreenWindow(HWND windowHandle) +{ + + HWND hFoundWnd = nullptr; + EnumWindows(&FindTheDesiredWnd, reinterpret_cast(&hFoundWnd)); + + // True if one window has WS_MAXIMIZE + if (hFoundWnd != nullptr) { + DWORD dwFlags = 0; + HMONITOR monitor = MonitorFromWindow(hFoundWnd, dwFlags); + HMONITOR wallpaper = MonitorFromWindow(windowHandle, dwFlags); + int monitorIndex = GetMonitorIndex(monitor); + int wallpaperIndex = GetMonitorIndex(wallpaper); + // qDebug() << monitorIndex << wallpaperIndex; + + // If the window that has WS_MAXIMIZE is at the same monitor as this wallpaper + return monitorIndex == wallpaperIndex; + + } else { + return false; + } +} +/* + * Adjusting a Window's Position and Size for Different Monitor DPI Scale Factors: + * * Windows allows users to set different DPI (dots per inch) scale factors for each monitor. This DPI scaling can lead to + * discrepancies in the positioning and size of windows, especially if we want to place a window on a monitor with a different + * scale factor than the one it was originally on. + * * In our scenario, we want to move and resize a window (`m_windowHandle`) to fit perfectly within a target monitor. However, + * both the window and the target monitor can have different DPI scale factors, so we need to account for these when calculating + * the window's new position and size. + * * Steps: + * * 1. Retrieve the DPI scale factor for the window: + * - This gives us the current scale factor of the window based on its original monitor. + * * 2. Retrieve the DPI scale factor for the target monitor: + * - This gives us the scale factor of the monitor where we want to place the window. + * * 3. Calculate the window's new position: + * - The new position should be relative to the `WorkerW` window's coordinates. + * - Adjust the position based on the ratio of the window's DPI scale factor to the target monitor's DPI scale factor. + * This ensures that the window is positioned correctly on the monitor regardless of any differences in scale factors. + * * 4. Calculate the window's new size: + * - Adjust the size of the window based on the ratio of the window's DPI scale factor to the target monitor's DPI scale factor. + * This ensures that the window fits perfectly within the monitor, taking into account any differences in scale factors. + * * By following this approach, we can accurately position and resize the window on any monitor, regardless of differences in DPI + * scale factors. + */ + +WindowsIntegration::MonitorResult WindowsIntegration::setupWallpaperForOneScreen(const int activeScreen, std::function updateWindowSize) +{ + if (!IsWindow(m_windowHandle)) { + std::cout << "Could not get a valid window handle !"; + return { std::nullopt, MonitorResultStatus::WindowHandleInvalidError }; + } + + if (!IsWindow(m_windowHandleWorker)) { + std::cout << "Could not get a valid window handle wroker!"; + return { std::nullopt, MonitorResultStatus::WorkerWindowHandleInvalidError }; + } + + std::vector monitors = getAllMonitors(); + for (const auto& monitor : monitors) { + monitor.print(); + if (monitor.index != activeScreen) + continue; + + SetWindowPos(m_windowHandle, HWND_TOP, + monitor.position.left, monitor.position.top, + monitor.size.cx, monitor.size.cy, + SWP_NOZORDER | SWP_NOACTIVATE); + + // Must be called here to fix window positions! + updateWindowSize(monitor.size.cx, monitor.size.cy); + + RECT oldRect; + GetWindowRect(m_windowHandle, &oldRect); + std::cout << "Old Window Position: (" << oldRect.left << ", " << oldRect.top << ")" << std::endl; + + float windowDpiScaleFactor = static_cast(GetDpiForWindow(m_windowHandle)) / 96.0f; + float targetMonitorDpiScaleFactor = monitor.scaleFactor; + std::cout << "Window DPI Scale Factor: " << windowDpiScaleFactor << std::endl; + std::cout << "Target Monitor DPI Scale Factor: " << targetMonitorDpiScaleFactor << std::endl; + + SetParent(m_windowHandle, m_windowHandleWorker); + RECT parentRect; + GetWindowRect(m_windowHandleWorker, &parentRect); + std::cout << "WorkerW Window Position: (" << parentRect.left << ", " << parentRect.top << ")" << std::endl; + + int newX = static_cast((oldRect.left - parentRect.left) * (windowDpiScaleFactor / targetMonitorDpiScaleFactor)); + int newY = static_cast((oldRect.top - parentRect.top) * (windowDpiScaleFactor / targetMonitorDpiScaleFactor)); + std::cout << "Calculated New Position: (" << newX << ", " << newY << ")" << std::endl; + + int newWidth = static_cast(monitor.size.cx * (windowDpiScaleFactor / targetMonitorDpiScaleFactor)); + int newHeight = static_cast(monitor.size.cy * (windowDpiScaleFactor / targetMonitorDpiScaleFactor)); + std::cout << "Calculated New Size: (" << newWidth << "x" << newHeight << ")" << std::endl; + + SetWindowPos(m_windowHandle, NULL, newX, newY, newWidth, newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + return { monitor, MonitorResultStatus::Ok }; + } + return { std::nullopt, MonitorResultStatus::MonitorIterationError }; +} +/** + * Spans the window across multiple monitors. + * * This function takes a vector of monitor indices and adjusts the window's + * size and position to span across the specified monitors. It determines the + * window's new size by finding the bounding rectangle that covers all selected + * monitors. The window's new position is set to the top-left corner of this + * bounding rectangle. + * * Note: This function assumes that all monitors have the same DPI scaling. If + * they don't, the window may not fit perfectly across the monitors. + * * @param activeScreens A vector containing the indices of monitors across + * which the window should span. + * * Usage: + * setupWallpaperForMultipleScreens({0, 1}); // Spans the window across monitors 0 and 1. + * * Internals: + * 1. For each monitor in `activeScreens`, determine its bounding rectangle. + * 2. Compute the window's new width as `rightmost - leftmost` and its new + * height as `bottommost - topmost`. + * 3. Adjust the window's position and size to fit this bounding rectangle. + */ +WindowsIntegration::SpanResult WindowsIntegration::setupWallpaperForMultipleScreens(const std::vector& activeScreens) +{ + std::vector monitors = getAllMonitors(); + + int leftmost = INT_MAX; + int topmost = INT_MAX; + int rightmost = INT_MIN; + int bottommost = INT_MIN; + + for (const auto& monitorIndex : activeScreens) { + if (monitorIndex < monitors.size()) { + const Monitor& monitor = monitors[monitorIndex]; + leftmost = (std::min)(leftmost, static_cast(monitor.position.left)); + topmost = (std::min)(topmost, static_cast(monitor.position.top)); + rightmost = (std::max)(rightmost, static_cast(monitor.position.right)); + bottommost = (std::max)(bottommost, static_cast(monitor.position.bottom)); + } + } + + int newWidth = rightmost - leftmost; + int newHeight = bottommost - topmost; + + RECT oldRect; + GetWindowRect(m_windowHandle, &oldRect); + + float windowDpiScaleFactor = static_cast(GetDpiForWindow(m_windowHandle)) / 96.0f; + + SetParent(m_windowHandle, m_windowHandleWorker); + RECT parentRect; + GetWindowRect(m_windowHandleWorker, &parentRect); + + int newX = static_cast((leftmost - parentRect.left) * windowDpiScaleFactor); + int newY = static_cast((topmost - parentRect.top) * windowDpiScaleFactor); + + SetWindowPos(m_windowHandle, NULL, newX, newY, newWidth, newHeight, SWP_NOZORDER | SWP_NOACTIVATE); + SpanResult result; + result.width = rightmost - leftmost; + result.height = bottommost - topmost; + result.success = true; + + return result; +} +/** + * Sets up the wallpaper to span across all connected screens. + * * This function retrieves information about all connected monitors, including their positions, dimensions, and scale factors. + * It then calculates the combined dimensions needed to span the window across all these monitors, taking into account + * the scale factors. The function also handles reparenting the window to the WorkerW window, ensuring it remains below + * other desktop icons. The calculated position and dimensions are adjusted to account for any potential scaling differences + * between the window and the combined monitor setup. + * * @note This function assumes that the window's DPI scale factor is based on a default of 96 DPI. Adjustments are made + * based on this assumption. + * * @note The function currently multiplies the scale factors of all monitors to get an overall scale factor. This may need + * adjustments based on specific application needs. + * * @return SpanResult A structure containing the combined width and height of the monitors, and a success flag indicating + * whether the operation was successful. + * * @retval SpanResult::width The combined width of all monitors after scaling. + * @retval SpanResult::height The combined height of all monitors after scaling. + * @retval SpanResult::success A boolean flag indicating the success of the operation. Currently, it always returns `true` + * assuming all operations are successful. This can be adjusted based on error checks as needed. + */ +WindowsIntegration::SpanResult WindowsIntegration::setupWallpaperForAllScreens() +{ + std::vector monitors = getAllMonitors(); + + int leftmost = INT_MAX; + int topmost = INT_MAX; + int rightmost = INT_MIN; + int bottommost = INT_MIN; + float overallScaleFactor = 1.0f; // assuming default is no scaling + + // Calculate the combined dimensions of all monitors + for (const auto& monitor : monitors) { + leftmost = (std::min)(leftmost, static_cast(monitor.position.left)); + topmost = (std::min)(topmost, static_cast(monitor.position.top)); + rightmost = (std::max)(rightmost, static_cast(monitor.position.right)); + bottommost = (std::max)(bottommost, static_cast(monitor.position.bottom)); + overallScaleFactor *= monitor.scaleFactor; // Adjust as per your scaling needs + } + + int scaledWidth = static_cast((rightmost - leftmost) * overallScaleFactor); + int scaledHeight = static_cast((bottommost - topmost) * overallScaleFactor); + + // Set the position and size of the window to span all monitors + SetWindowPos(m_windowHandle, HWND_TOP, leftmost, topmost, scaledWidth, scaledHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + // Reparenting and scaling logic + RECT oldRect; + GetWindowRect(m_windowHandle, &oldRect); + float windowDpiScaleFactor = static_cast(GetDpiForWindow(m_windowHandle)) / 96.0f; + SetParent(m_windowHandle, m_windowHandleWorker); + RECT parentRect; + GetWindowRect(m_windowHandleWorker, &parentRect); + int newX = static_cast((oldRect.left - parentRect.left) * (windowDpiScaleFactor / overallScaleFactor)); + int newY = static_cast((oldRect.top - parentRect.top) * (windowDpiScaleFactor / overallScaleFactor)); + + SetWindowPos(m_windowHandle, NULL, newX, newY, scaledWidth, scaledHeight, SWP_NOZORDER | SWP_NOACTIVATE); + + // Return the combined span of all monitors + SpanResult result; + result.width = scaledWidth; + result.height = scaledHeight; + result.success = true; // Assuming the operations are successful; adjust as needed + + return result; +} + +HWND WindowsIntegration::windowHandle() const +{ + return m_windowHandle; +} + +HWND WindowsIntegration::windowHandleWorker() const +{ + return m_windowHandleWorker; +} + +void WindowsIntegration::setWindowHandle(HWND windowHandle) +{ + m_windowHandle = windowHandle; +} + +BOOL GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) +{ + + auto info = (sEnumInfo*)dwData; + if (info->hMonitor == hMonitor) + return FALSE; + ++info->iIndex; + return TRUE; +} + +BOOL FindTheDesiredWnd(HWND hWnd, LPARAM lParam) +{ + DWORD dwStyle = (DWORD)GetWindowLong(hWnd, GWL_STYLE); + if ((dwStyle & WS_MAXIMIZE) != 0) { + *(reinterpret_cast(lParam)) = hWnd; + return false; // stop enumerating + } + return true; // keep enumerating +} + +BOOL MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) +{ + std::vector* pMonitors = reinterpret_cast*>(dwData); + + MONITORINFOEX info; + info.cbSize = sizeof(info); + GetMonitorInfo(hMonitor, &info); + + UINT dpiX, dpiY; + GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY); + + Monitor monitor; + monitor.monitorID = hMonitor; + monitor.index = pMonitors->size(); // Set index based on the current size of the vector + monitor.position = info.rcMonitor; + monitor.size.cx = info.rcMonitor.right - info.rcMonitor.left; + monitor.size.cy = info.rcMonitor.bottom - info.rcMonitor.top; + monitor.scaleFactor = static_cast(dpiX) / 96.0f; + + pMonitors->push_back(monitor); + + return true; +} + +void WindowsIntegration::setMouseEventHandler(MouseEventHandler handler) +{ + m_mouseEventHandler = handler; +} + +LRESULT __stdcall WindowsIntegration::MouseHookCallback(int nCode, WPARAM wParam, LPARAM lParam) +{ + // Initialize mouse event variables + DWORD mouseButton = 0; + UINT type = WM_MOUSEMOVE; + POINT p {}; + + if (nCode >= 0) { + switch (wParam) { + case WM_LBUTTONDOWN: + mouseButton = MK_LBUTTON; + type = WM_LBUTTONDOWN; + break; + case WM_LBUTTONUP: + mouseButton = MK_LBUTTON; + type = WM_LBUTTONUP; + break; + case WM_RBUTTONDOWN: + mouseButton = MK_RBUTTON; + type = WM_RBUTTONDOWN; + break; + default: + type = WM_MOUSEMOVE; + } + } + + if (GetCursorPos(&p)) { + // Check if the callback function is set and call it + if (m_mouseEventHandler) { + m_mouseEventHandler(mouseButton, type, p); + } + + } else { + return CallNextHookEx(m_mouseHook, nCode, wParam, lParam); + } + + return CallNextHookEx(m_mouseHook, nCode, wParam, lParam); +} + +void WindowsIntegration::setupWindowMouseHook() +{ + HINSTANCE hInstance = GetModuleHandle(NULL); + if (!(m_mouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookCallback, hInstance, 0))) { + OutputDebugStringW(L"Failed to install mouse hook!"); + return; + } +} + +void WindowsIntegration::setupWindowKeyboardHook() +{ + HINSTANCE hInstance = GetModuleHandle(NULL); + if (!(m_keyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, KeyboardHookCallback, hInstance, 0))) { + OutputDebugStringW(L"Failed to install keyboard hook!"); + return; + } +} + +void WindowsIntegration::setKeyboardEventHandler(KeyboardEventHandler handler) +{ + m_keyboardEventHandler = std::move(handler); +} + +LRESULT __stdcall WindowsIntegration::KeyboardHookCallback(int nCode, WPARAM wParam, LPARAM lParam) +{ + if (nCode >= 0) { + KBDLLHOOKSTRUCT* kbStruct = (KBDLLHOOKSTRUCT*)lParam; + bool keyDown = wParam == WM_KEYDOWN || wParam == WM_SYSKEYDOWN; + // Check if the callback function is set and call it + if (m_keyboardEventHandler) { + m_keyboardEventHandler(kbStruct->vkCode, keyDown); + } + } + return CallNextHookEx(NULL, nCode, wParam, lParam); +} + +void WindowsIntegration::unhookMouse() +{ + if (m_mouseHook != NULL) { + UnhookWindowsHookEx(m_mouseHook); + m_mouseHook = NULL; + } +} + +void WindowsIntegration::unhookKeyboard() +{ + if (m_keyboardHook != NULL) { + UnhookWindowsHookEx(m_keyboardHook); + m_keyboardHook = NULL; + } +} diff --git a/ScreenPlayWallpaper/src/windowsintegration.h b/ScreenPlayWallpaper/src/windowsintegration.h new file mode 100644 index 00000000..6643bd3d --- /dev/null +++ b/ScreenPlayWallpaper/src/windowsintegration.h @@ -0,0 +1,110 @@ +#pragma once + +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include + +// Do not change windows.h order ! +#include +#include +#include +#include +#include +#include + +// Do not sort ! +#include "WinUser.h" +#include + +struct Monitor { + HMONITOR monitorID; // Handle to the monitor + int index; // Index of the monitor + RECT position; // Monitor's position and size + SIZE size; // Monitor's width and height + float scaleFactor; // Scale factor (DPI scaling as a factor, e.g., 1.5 for 150% scaling) + std::string toString() const + { + return std::format( + "Monitor Info:\n" + "Monitor ID: {}\n" + "Index: {}\n" + "Position: ({}, {}, {}, {})\n" + "Size: ({}x{})\n" + "Scale Factor: {}\n", + (int64_t)monitorID, index, position.left, position.top, + position.right, position.bottom, size.cx, size.cy, scaleFactor); + } + void print() const + { + std::cout << toString() << std::endl; + } +}; + +// Static callback function for EnumDisplayMonitors +BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData); +BOOL CALLBACK GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData); +BOOL CALLBACK FindTheDesiredWnd(HWND hWnd, LPARAM lParam); +BOOL WINAPI SearchForWorkerWindow(HWND hwnd, LPARAM lparam); + +struct Point { + int x = 0; + int y = 0; +}; + +struct sEnumInfo { + int iIndex; + HMONITOR hMonitor; +}; + +using MouseEventHandler = std::function; +static MouseEventHandler m_mouseEventHandler; +static HHOOK m_mouseHook; + +typedef std::function KeyboardEventHandler; +static HHOOK m_keyboardHook; +static KeyboardEventHandler m_keyboardEventHandler; + +class WindowsIntegration { +public: + struct SpanResult { + int width = 0; + int height = 0; + bool success = false; + }; + enum class MonitorResultStatus { + Ok, + WindowHandleInvalidError, + WorkerWindowHandleInvalidError, + MonitorIterationError, + }; + struct MonitorResult { + std::optional monitor; + MonitorResultStatus status = MonitorResultStatus::Ok; + }; + + bool searchWorkerWindowToParentTo(); + float getScaling(const int monitorIndex) const; + std::vector getAllMonitors(); + int GetMonitorIndex(HMONITOR hMonitor); + bool checkForFullScreenWindow(HWND windowHandle); + WindowsIntegration::MonitorResult setupWallpaperForOneScreen(const int activeScreen, std::function updateWindowSize); + SpanResult setupWallpaperForMultipleScreens(const std::vector& activeScreens); + SpanResult setupWallpaperForAllScreens(); + HWND windowHandle() const; + HWND windowHandleWorker() const; + void setWindowHandle(HWND windowHandle); + void setupWindowMouseHook(); + void unhookMouse(); + void setMouseEventHandler(MouseEventHandler handler); + static LRESULT __stdcall MouseHookCallback(int nCode, WPARAM wParam, LPARAM lParam); + + void setupWindowKeyboardHook(); + void unhookKeyboard(); + void setKeyboardEventHandler(KeyboardEventHandler handler); + static LRESULT __stdcall KeyboardHookCallback(int nCode, WPARAM wParam, LPARAM lParam); + +private: + HWND m_windowHandle {}; + HWND m_windowHandleWorker {}; +}; diff --git a/ScreenPlayWallpaper/src/winwindow.cpp b/ScreenPlayWallpaper/src/winwindow.cpp index 62c05d26..0ed0549b 100644 --- a/ScreenPlayWallpaper/src/winwindow.cpp +++ b/ScreenPlayWallpaper/src/winwindow.cpp @@ -1,10 +1,8 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "winwindow.h" -#include "ScreenPlayUtil/projectfile.h" +#include "windowsintegration.h" #include #include -#include -#include #include #include #include @@ -15,106 +13,9 @@ \brief ScreenPlayWindow used for the Windows implementation. */ -/*! - \brief Searches for the worker window for our window to parent to. -*/ -BOOL WINAPI SearchForWorkerWindow(HWND hwnd, LPARAM lparam) -{ - // 0xXXXXXXX "" WorkerW - // ... - // 0xXXXXXXX "" SHELLDLL_DefView - // 0xXXXXXXXX "FolderView" SysListView32 - // 0xXXXXXXXX "" WorkerW <---- We want this one - // 0xXXXXXXXX "Program Manager" Progman - if (FindWindowExW(hwnd, nullptr, L"SHELLDLL_DefView", nullptr)) - *reinterpret_cast(lparam) = FindWindowExW(nullptr, hwnd, L"WorkerW", nullptr); - return TRUE; -} +namespace ScreenPlay { -HHOOK g_mouseHook; -QPoint g_LastMousePosition { 0, 0 }; -QPoint g_globalOffset { 0, 0 }; -QQuickView* g_winGlobalHook = nullptr; - -/*! - \brief Windows mouse callback. This hook then forwards the event to the Qt window. - We must manually call a release event otherwise QML gets stuck. -*/ -LRESULT __stdcall MouseHookCallback(int nCode, WPARAM wParam, LPARAM lParam) -{ - - Qt::MouseButton mouseButton {}; - Qt::MouseButtons mouseButtons {}; - Qt::KeyboardModifier keyboardModifier {}; - QMouseEvent::Type type { QMouseEvent::Type::MouseMove }; - - if (nCode >= 0) { - switch (wParam) { - case WM_LBUTTONDOWN: - mouseButton = Qt::MouseButton::LeftButton; - mouseButtons.setFlag(Qt::LeftButton); - type = QMouseEvent::Type::MouseButtonPress; - break; - case WM_LBUTTONUP: - mouseButton = Qt::MouseButton::LeftButton; - mouseButtons.setFlag(Qt::LeftButton); - type = QMouseEvent::Type::MouseButtonRelease; - break; - case WM_RBUTTONDOWN: - mouseButton = Qt::MouseButton::RightButton; - mouseButtons.setFlag(Qt::RightButton); - type = QMouseEvent::Type::MouseButtonPress; - break; - default: - type = QMouseEvent::Type::MouseMove; - } - } - - POINT p {}; - if (GetCursorPos(&p)) { - g_LastMousePosition.setX(p.x); - g_LastMousePosition.setY(p.y); - } else { - return CallNextHookEx(g_mouseHook, nCode, wParam, lParam); - } - - auto event = QMouseEvent(type, g_LastMousePosition, mouseButton, mouseButtons, keyboardModifier); - - QGuiApplication::sendEvent(g_winGlobalHook, &event); - - if (type == QMouseEvent::Type::MouseButtonPress) { - } - QTimer::singleShot(100, [&]() { - // auto eventPress = QMouseEvent(QMouseEvent::Type::MouseButtonPress, g_LastMousePosition, mouseButton, mouseButtons, {}); - // qInfo() << mouseButton << QGuiApplication::sendEvent(g_winGlobalHook, &eventPress) << g_globalOffset.x() << g_globalOffset.y(); - auto eventRelease = QMouseEvent(QMouseEvent::Type::MouseButtonRelease, g_LastMousePosition, mouseButton, mouseButtons, {}); - QGuiApplication::sendEvent(g_winGlobalHook, &eventRelease); - }); - - return CallNextHookEx(g_mouseHook, nCode, wParam, lParam); -} - -/*! - \brief Setup the SetWindowsHookEx hook to be used to receive mouse events. -*/ -void WinWindow::setupWindowMouseHook() -{ - using ScreenPlay::InstalledType::InstalledType; - - // MUST be called before setting hook for events! - if (type() != InstalledType::VideoWallpaper && type() != InstalledType::GifWallpaper) { - qInfo() << "Enable mousehook"; - g_winGlobalHook = &m_window; - - HINSTANCE hInstance = GetModuleHandle(NULL); - if (!(g_mouseHook = SetWindowsHookEx(WH_MOUSE_LL, MouseHookCallback, hInstance, 0))) { - qInfo() << "Faild to install mouse hook!"; - return; - } - } -} - -ScreenPlay::WallpaperExitCode WinWindow::start() +WallpaperExit::Code WinWindow::start() { connect( &m_window, &QQuickView::statusChanged, this, [this](auto status) { @@ -139,15 +40,16 @@ ScreenPlay::WallpaperExitCode WinWindow::start() } m_windowsDesktopProperties = std::make_unique(); - m_windowHandle = reinterpret_cast(m_window.winId()); - if (!IsWindow(m_windowHandle)) { + m_windowsIntegration.setWindowHandle(reinterpret_cast(m_window.winId())); + if (!IsWindow(m_windowsIntegration.windowHandle())) { qCritical("Could not get a valid window handle!"); - return ScreenPlay::WallpaperExitCode::Invalid_Start_Windows_HandleError; + return WallpaperExit::Code::Invalid_Start_Windows_HandleError; } qRegisterMetaType(); qRegisterMetaType(); qmlRegisterSingletonInstance("ScreenPlayWallpaper", 1, 0, "Wallpaper", this); + m_window.setResizeMode(QQuickView::ResizeMode::SizeRootObjectToView); configureWindowGeometry(); // We do not support autopause for multi monitor wallpaper and @@ -158,11 +60,80 @@ ScreenPlay::WallpaperExitCode WinWindow::start() } } - QTimer::singleShot(1000, this, [&]() { - setupWindowMouseHook(); - }); + qInfo() << "Setup " << width() << height(); + m_window.setSource(QUrl("qrc:/qml/ScreenPlayWallpaper/qml/Wallpaper.qml")); + m_window.show(); - return ScreenPlay::WallpaperExitCode::Ok; + QTimer::singleShot(1000, this, [&]() { + m_windowsIntegration.setupWindowMouseHook(); + // Set up the mouse event handler + m_windowsIntegration.setMouseEventHandler([this](DWORD mouseButton, UINT type, POINT p) { + Qt::MouseButton button = Qt::NoButton; + QEvent::Type eventType = QEvent::None; + + // Determine the Qt mouse event type and button + switch (type) { + case WM_LBUTTONDOWN: + eventType = QEvent::MouseButtonPress; + button = Qt::LeftButton; + break; + case WM_LBUTTONUP: + eventType = QEvent::MouseButtonRelease; + button = Qt::LeftButton; + break; + case WM_RBUTTONDOWN: + eventType = QEvent::MouseButtonPress; + button = Qt::RightButton; + break; + case WM_RBUTTONUP: + eventType = QEvent::MouseButtonRelease; + button = Qt::RightButton; + break; + case WM_MOUSEMOVE: + eventType = QEvent::MouseMove; + button = Qt::NoButton; + break; + // Add more cases as needed + } + + // Convert POINT to global position + QPoint globalPos(p.x, p.y); + + // Convert global position to local position within the target widget + QPoint localPos = m_window.mapFromGlobal(globalPos); + + // Create the QMouseEvent + QMouseEvent* qEvent = new QMouseEvent(eventType, localPos, globalPos, button, button, QGuiApplication::keyboardModifiers()); + + // Handle the mouse event + // For example, logging the mouse button and position + // qDebug() << "Mouse event: Button=" << mouseButton << ", Type=" << type + // << ", Position=(" << p.x << ", " << p.y << ")" << globalPos << localPos << button; + // Post the event to the target widget + QCoreApplication::postEvent(&m_window, qEvent); + }); + + // Inside your main application or somewhere appropriate + m_windowsIntegration.setupWindowKeyboardHook(); + // Set up the keyboard event handler + m_windowsIntegration.setKeyboardEventHandler([this](UINT vkCode, bool keyDown) { + QEvent::Type eventType = keyDown ? QEvent::KeyPress : QEvent::KeyRelease; + + // Map the vkCode to Qt key code if necessary + auto [qtKey, text] = mapVirtualKeyToQtKey(vkCode); // Implement this function based on your needs + + // Create the QKeyEvent + QKeyEvent* qEvent = new QKeyEvent(eventType, qtKey, Qt::NoModifier, text); + + // Handle the keyboard event + // For example, logging the key press + // qDebug() << "Keyboard event: Key=" << vkCode << ", Type=" << (keyDown ? "KeyDown" : "KeyUp") << qEvent; + + // Post the event to the target widget + QCoreApplication::postEvent(&m_window, qEvent); + }); + }); + return WallpaperExit::Code::Ok; } /*! @@ -171,12 +142,12 @@ ScreenPlay::WallpaperExitCode WinWindow::start() void WinWindow::setVisible(bool show) { if (show) { - if (!ShowWindow(m_windowHandle, SW_SHOW)) { + if (!ShowWindow(m_windowsIntegration.windowHandle(), SW_SHOW)) { qDebug() << "Cannot set window handle SW_SHOW"; } } else { - if (!ShowWindow(m_windowHandle, SW_HIDE)) { + if (!ShowWindow(m_windowsIntegration.windowHandle(), SW_HIDE)) { qDebug() << "Cannot set window handle SW_HIDE"; } } @@ -192,54 +163,17 @@ void WinWindow::destroyThis() emit qmlExit(); } -struct sEnumInfo { - int iIndex; - HMONITOR hMonitor; -}; - -BOOL CALLBACK GetMonitorByIndex(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -{ - auto* info = (sEnumInfo*)dwData; - if (--info->iIndex < 0) { - info->hMonitor = hMonitor; - return FALSE; - } - return TRUE; -} - -/*! - \brief This method is called if the user want to have one wallpaper on one window. -*/ void WinWindow::setupWallpaperForOneScreen(int activeScreen) { - - const QRect screenRect = QGuiApplication::screens().at(activeScreen)->geometry(); - const int boderWidth = 2; - const float scaling = getScaling(activeScreen); - const int borderOffset = -1; - - ScreenPlayUtil::WinMonitorStats monitors; - const int width = (std::abs(monitors.rcMonitors[activeScreen].right - monitors.rcMonitors[activeScreen].left) / scaling) + boderWidth; - const int height = (std::abs(monitors.rcMonitors[activeScreen].top - monitors.rcMonitors[activeScreen].bottom) / scaling) + boderWidth; - - const int x = monitors.rcMonitors[activeScreen].left + m_zeroPoint.x() + borderOffset; - const int y = monitors.rcMonitors[activeScreen].top + m_zeroPoint.y() + borderOffset; - qInfo() << QString("Setup window activeScreen: %1 scaling: %2 x: %3 y: %4 width: %5 height: %6").arg(activeScreen).arg(scaling).arg(x).arg(y).arg(width).arg(height); - // Also set it in BaseWindow. This is needed for Windows fade in. - setWidth(width - boderWidth); - setHeight(height - boderWidth); - { - // Must be called twice for some reason when window has scaling... - if (!SetWindowPos(m_windowHandle, nullptr, x, y, width, height, SWP_HIDEWINDOW)) { - qFatal("Could not set window pos"); - } - if (!SetWindowPos(m_windowHandle, nullptr, x, y, width, height, SWP_HIDEWINDOW)) { - qFatal("Could not set window pos"); - } - } - - if (SetParent(m_windowHandle, m_windowHandleWorker) == nullptr) { - qFatal("Could not attach to parent window"); + auto updateWindowSize = [this](const int width, const int height) { + setWidth(width); + setHeight(height); + m_window.setWidth(width); + m_window.setHeight(height); + }; + WindowsIntegration::MonitorResult monitor = m_windowsIntegration.setupWallpaperForOneScreen(activeScreen, updateWindowSize); + if (monitor.status != WindowsIntegration::MonitorResultStatus::Ok) { + qCritical("setupWallpaperForOneScreen failed status: ", (int)monitor.status); } } @@ -248,43 +182,11 @@ void WinWindow::setupWallpaperForOneScreen(int activeScreen) */ void WinWindow::setupWallpaperForAllScreens() { - ScreenPlayUtil::WinMonitorStats monitors; - QRect rect; - for (int i = 0; i < monitors.iMonitors.size(); i++) { - const int width = std::abs(monitors.rcMonitors[i].right - monitors.rcMonitors[i].left); - const int height = std::abs(monitors.rcMonitors[i].top - monitors.rcMonitors[i].bottom); - qInfo() << width << height; - rect.setWidth(rect.width() + width); - rect.setHeight(rect.height() + height); - } - int offsetX = 0; - int offsetY = 0; - for (int i = 0; i < monitors.iMonitors.size(); i++) { - const int x = monitors.rcMonitors[i].left; - const int y = monitors.rcMonitors[i].top; - qInfo() << x << y; - if (x < offsetX) { - offsetX = x; - } - if (y < offsetY) { - offsetY += y; - } - } - if (!SetWindowPos(m_windowHandle, nullptr, offsetX, offsetY, rect.width(), rect.height(), SWP_NOSIZE | SWP_NOMOVE)) { - qFatal("Could not set window pos: "); - } - if (!SetWindowPos(m_windowHandle, nullptr, offsetX, offsetY, rect.width(), rect.height(), SWP_NOSIZE | SWP_NOMOVE)) { - qFatal("Could not set window pos: "); - } - if (SetParent(m_windowHandle, m_windowHandleWorker) == nullptr) { - qFatal("Could not attach to parent window"); - } - qInfo() << rect.width() << rect.height() << offsetX << offsetY; - m_window.setHeight(rect.height()); - m_window.setWidth(rect.width()); - m_window.setY(offsetY); - m_window.setX(offsetX + 1920); - qInfo() << m_window.geometry(); + WindowsIntegration::SpanResult span = m_windowsIntegration.setupWallpaperForAllScreens(); + setWidth(span.width); + setHeight(span.height); + m_window.setWidth(width()); + m_window.setHeight(height()); } /*! @@ -292,99 +194,12 @@ void WinWindow::setupWallpaperForAllScreens() */ void WinWindow::setupWallpaperForMultipleScreens(const QVector& activeScreensList) { - QRect rect; - QScreen* upperLeftScreen { nullptr }; - // Check for the upper left screen first so we get x and y positions - for (const int screen : activeScreensList) { - QScreen* screenTmp = QGuiApplication::screens().at(screen); - if (upperLeftScreen != nullptr) { - if (screenTmp->geometry().x() < upperLeftScreen->geometry().x() || screenTmp->geometry().y() < upperLeftScreen->geometry().y()) { - upperLeftScreen = screenTmp; - } - } else { - upperLeftScreen = screenTmp; - } - rect.setWidth(screenTmp->geometry().width() + rect.width()); - rect.setHeight(screenTmp->geometry().height() + rect.height()); - } - - rect.setX(upperLeftScreen->geometry().x()); - rect.setY(upperLeftScreen->geometry().y()); - - if (!SetWindowPos(m_windowHandle, nullptr, rect.x() + m_zeroPoint.x(), rect.y() + m_zeroPoint.y(), rect.width(), rect.height(), SWP_SHOWWINDOW)) { - qFatal("Could not set window pos: "); - } - if (SetParent(m_windowHandle, m_windowHandleWorker) == nullptr) { - qFatal("Could not attach to parent window"); - } -} - -bool WinWindow::searchWorkerWindowToParentTo() -{ - - HWND progman_hwnd = FindWindowW(L"Progman", L"Program Manager"); - const DWORD WM_SPAWN_WORKER = 0x052C; - SendMessageTimeoutW(progman_hwnd, WM_SPAWN_WORKER, 0xD, 0x1, SMTO_NORMAL, - 10000, nullptr); - - return EnumWindows(SearchForWorkerWindow, reinterpret_cast(&m_windowHandleWorker)); -} - -/*! - \brief Returns scaling factor as reported by Windows. -*/ -float WinWindow::getScaling(const int monitorIndex) const -{ - // Get all monitors - int monitorCount = GetSystemMetrics(SM_CMONITORS); - - if (monitorIndex < 0 || monitorIndex >= monitorCount) { - // Invalid monitor index - return 1.0f; - } - - DISPLAY_DEVICE displayDevice; - ZeroMemory(&displayDevice, sizeof(displayDevice)); - displayDevice.cb = sizeof(displayDevice); - - // Enumerate through monitors until we find the one we're looking for - for (int i = 0; EnumDisplayDevices(NULL, i, &displayDevice, 0); i++) { - if (i == monitorIndex) { - DEVMODE devMode; - ZeroMemory(&devMode, sizeof(devMode)); - devMode.dmSize = sizeof(devMode); - - // Get settings for selected monitor - if (!EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &devMode)) { - // Unable to get monitor settings - return 1.0f; - } - - // Get DPI for selected monitor - HMONITOR hMonitor = MonitorFromPoint({ devMode.dmPosition.x, devMode.dmPosition.y }, MONITOR_DEFAULTTONEAREST); - UINT dpiX = 0, dpiY = 0; - if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) { - return (float)dpiX / 96.0f; // Standard DPI is 96 - } - } - } - - // If we reach here, it means we couldn't find the monitor with the given index or couldn't get the DPI. - return 1.0f; -} - -/*! - \brief Returns true of at least one monitor has active scaling enabled. -*/ -bool WinWindow::hasWindowScaling() const -{ - const auto screens = QGuiApplication::screens(); - for (int i = 0; i < screens.count(); i++) { - if (getScaling(i) != 1) { - return true; - } - } - return false; + std::vector activeScreens(activeScreensList.begin(), activeScreensList.end()); + WindowsIntegration::SpanResult span = m_windowsIntegration.setupWallpaperForMultipleScreens(activeScreens); + setWidth(span.width); + setHeight(span.height); + m_window.setWidth(width()); + m_window.setHeight(height()); } /*! @@ -393,24 +208,17 @@ bool WinWindow::hasWindowScaling() const */ void WinWindow::configureWindowGeometry() { - if (!searchWorkerWindowToParentTo()) { + if (!m_windowsIntegration.searchWorkerWindowToParentTo()) { qFatal("No worker window found"); } - - RECT rect {}; - if (!GetWindowRect(m_windowHandleWorker, &rect)) { - qFatal("Unable to get WindoeRect from worker"); + if (!IsWindow(m_windowsIntegration.windowHandleWorker())) { + qCritical("Could not get a valid window handle wroker!"); + return; } - // Windows coordante system begins at 0x0 at the - // main monitors upper left and not at the most left top monitor. - // This can be easily read from the worker window. - m_zeroPoint = { std::abs(rect.left), std::abs(rect.top) }; - g_globalOffset = m_zeroPoint; - // WARNING: Setting Window flags must be called *here*! - SetWindowLongPtr(m_windowHandle, GWL_EXSTYLE, WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT); - SetWindowLongPtr(m_windowHandle, GWL_STYLE, WS_POPUPWINDOW); + SetWindowLongPtr(m_windowsIntegration.windowHandle(), GWL_EXSTYLE, WS_EX_LEFT | WS_EX_LTRREADING | WS_EX_RIGHTSCROLLBAR | WS_EX_NOACTIVATE | WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT); + SetWindowLongPtr(m_windowsIntegration.windowHandle(), GWL_STYLE, WS_POPUP); // Ether for one Screen or for all if ((QGuiApplication::screens().length() == activeScreensList().length()) && (activeScreensList().length() != 1)) { @@ -421,95 +229,174 @@ void WinWindow::configureWindowGeometry() } else if (activeScreensList().length() > 1) { setupWallpaperForMultipleScreens(activeScreensList()); } - - m_window.setResizeMode(QQuickView::ResizeMode::SizeRootObjectToView); - m_window.setWidth(width()); - m_window.setHeight(height()); - qInfo() << "Setup " << width() << height(); - m_window.setSource(QUrl("qrc:/qml/ScreenPlayWallpaper/qml/Wallpaper.qml")); - m_window.hide(); + m_window.show(); } -BOOL CALLBACK FindTheDesiredWnd(HWND hWnd, LPARAM lParam) +std::tuple WinWindow::mapVirtualKeyToQtKey(UINT vkCode) { - DWORD dwStyle = (DWORD)GetWindowLong(hWnd, GWL_STYLE); - if ((dwStyle & WS_MAXIMIZE) != 0) { - *(reinterpret_cast(lParam)) = hWnd; - return false; // stop enumerating - } - return true; // keep enumerating -} + switch (vkCode) { + case VK_BACK: + return { Qt::Key_Backspace, QString() }; + case VK_TAB: + return { Qt::Key_Tab, QString("\t") }; + case VK_CLEAR: + return { Qt::Key_Clear, QString() }; + case VK_RETURN: + return { Qt::Key_Return, QString("\r") }; + // ... rest of the cases ... + case VK_SPACE: + return { Qt::Key_Space, QString(" ") }; + // Extra keys + case 0x21: // '!' + return { Qt::Key_Exclam, QString("!") }; + case 0x40: // '@' + return { Qt::Key_At, QString("@") }; + case 0x23: // '#' + return { Qt::Key_NumberSign, QString("#") }; + case 0x24: // '$' + return { Qt::Key_Dollar, QString("$") }; + case 0x25: // '%' + return { Qt::Key_Percent, QString("%") }; + case 0x5E: // '^' + return { Qt::Key_AsciiCircum, QString("^") }; + case 0x26: // '&' + return { Qt::Key_Ampersand, QString("&") }; + case 0x2A: // '*' + return { Qt::Key_Asterisk, QString("*") }; + case 0x28: // '(' + return { Qt::Key_ParenLeft, QString("(") }; + case 0x29: // ')' + return { Qt::Key_ParenRight, QString(")") }; + case 0x5F: // '_' + return { Qt::Key_Underscore, QString("_") }; + case 0x2B: // '+' + return { Qt::Key_Plus, QString("+") }; + case 0x2D: // '-' + return { Qt::Key_Minus, QString("-") }; + case 0x3D: // '=' + return { Qt::Key_Equal, QString("=") }; + case 0x5B: // '[' + return { Qt::Key_BracketLeft, QString("[") }; + case 0x5D: // ']' + return { Qt::Key_BracketRight, QString("]") }; + case 0x7B: // '{' + return { Qt::Key_BraceLeft, QString("{") }; + case 0x7D: // '}' + return { Qt::Key_BraceRight, QString("}") }; + case 0x3B: // ';' + return { Qt::Key_Semicolon, QString(";") }; + case 0x27: // ''' + return { Qt::Key_Apostrophe, QString("'") }; + case 0x3A: // ':' + return { Qt::Key_Colon, QString(":") }; + case 0x22: // '"' + return { Qt::Key_QuoteDbl, QString("\"") }; + case 0x2F: // '/' + return { Qt::Key_Slash, QString("/") }; + case 0x2E: // '.' + return { Qt::Key_Period, QString(".") }; + case 0x3E: // '>' + return { Qt::Key_Greater, QString(">") }; + case 0x2C: // ',' + return { Qt::Key_Comma, QString(",") }; + case 0x3F: // '?' + return { Qt::Key_Question, QString("?") }; + // Numeric keys + case 0x30: + return { Qt::Key_0, QString("0") }; + case 0x31: + return { Qt::Key_1, QString("1") }; + case 0x32: + return { Qt::Key_2, QString("2") }; + case 0x33: + return { Qt::Key_3, QString("3") }; + case 0x34: + return { Qt::Key_4, QString("4") }; + case 0x35: + return { Qt::Key_5, QString("5") }; + case 0x36: + return { Qt::Key_6, QString("6") }; + case 0x37: + return { Qt::Key_7, QString("7") }; + case 0x38: + return { Qt::Key_8, QString("8") }; + case 0x39: + return { Qt::Key_9, QString("9") }; -BOOL CALLBACK GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -{ - Q_UNUSED(hdcMonitor) - Q_UNUSED(lprcMonitor) - - auto info = (sEnumInfo*)dwData; - if (info->hMonitor == hMonitor) - return FALSE; - ++info->iIndex; - return TRUE; -} - -int GetMonitorIndex(HMONITOR hMonitor) -{ - sEnumInfo info; - info.hMonitor = hMonitor; - - if (EnumDisplayMonitors(NULL, NULL, GetMonitorByHandle, (LPARAM)&info)) - return -1; - - return info.iIndex; -} - -/*! - \brief This method is called via a fixed interval to detect if a window completely - covers a monitor. If then sets visualPaused for QML to pause the content. -*/ -void WinWindow::checkForFullScreenWindow() -{ - - HWND hFoundWnd = nullptr; - EnumWindows(&FindTheDesiredWnd, reinterpret_cast(&hFoundWnd)); - - // True if one window has WS_MAXIMIZE - if (hFoundWnd != nullptr) { - DWORD dwFlags = 0; - HMONITOR monitor = MonitorFromWindow(hFoundWnd, dwFlags); - HMONITOR wallpaper = MonitorFromWindow(m_windowHandle, dwFlags); - int monitorIndex = GetMonitorIndex(monitor); - int wallpaperIndex = GetMonitorIndex(wallpaper); - // qDebug() << monitorIndex << wallpaperIndex; - - // If the window that has WS_MAXIMIZE is at the same monitor as this wallpaper - if (monitorIndex == wallpaperIndex) { - - setVisualsPaused(true); - } else { - setVisualsPaused(false); - } - - } else { - setVisualsPaused(false); + // Alphabet keys + case 0x41: + return { Qt::Key_A, QString("a") }; + case 0x42: + return { Qt::Key_B, QString("b") }; + case 0x43: + return { Qt::Key_C, QString("c") }; + case 0x44: + return { Qt::Key_D, QString("d") }; + case 0x45: + return { Qt::Key_E, QString("e") }; + case 0x46: + return { Qt::Key_F, QString("f") }; + case 0x47: + return { Qt::Key_G, QString("g") }; + case 0x48: + return { Qt::Key_H, QString("h") }; + case 0x49: + return { Qt::Key_I, QString("i") }; + case 0x4A: + return { Qt::Key_J, QString("j") }; + case 0x4B: + return { Qt::Key_K, QString("k") }; + case 0x4C: + return { Qt::Key_L, QString("l") }; + case 0x4D: + return { Qt::Key_M, QString("m") }; + case 0x4E: + return { Qt::Key_N, QString("n") }; + case 0x4F: + return { Qt::Key_O, QString("o") }; + case 0x50: + return { Qt::Key_P, QString("p") }; + case 0x51: + return { Qt::Key_Q, QString("q") }; + case 0x52: + return { Qt::Key_R, QString("r") }; + case 0x53: + return { Qt::Key_S, QString("s") }; + case 0x54: + return { Qt::Key_T, QString("t") }; + case 0x55: + return { Qt::Key_U, QString("u") }; + case 0x56: + return { Qt::Key_V, QString("v") }; + case 0x57: + return { Qt::Key_W, QString("w") }; + case 0x58: + return { Qt::Key_X, QString("x") }; + case 0x59: + return { Qt::Key_Y, QString("y") }; + case 0x5A: + return { Qt::Key_Z, QString("z") }; + default: + return { Qt::Key_unknown, QString() }; } } + /*! \brief Custom exit method to force a redraw of the window so that the default desktop wallpaper can be seen agian. */ void WinWindow::terminate() { - using ScreenPlay::InstalledType::InstalledType; - if (type() != InstalledType::VideoWallpaper && type() != InstalledType::GifWallpaper) { - UnhookWindowsHookEx(g_mouseHook); - } - ShowWindow(m_windowHandle, SW_HIDE); + + ShowWindow(m_windowsIntegration.windowHandle(), SW_HIDE); // Force refresh so that we display the regular // desktop wallpaper again - ShowWindow(m_windowHandleWorker, SW_HIDE); - ShowWindow(m_windowHandleWorker, SW_SHOW); + ShowWindow(m_windowsIntegration.windowHandleWorker(), SW_HIDE); + ShowWindow(m_windowsIntegration.windowHandleWorker(), SW_SHOW); + + m_windowsIntegration.unhookKeyboard(); + m_windowsIntegration.unhookMouse(); QGuiApplication::quit(); } @@ -524,4 +411,12 @@ void WinWindow::clearComponentCache() m_window.engine()->clearComponentCache(); } +void WinWindow::checkForFullScreenWindow() +{ + bool hasFullscreenWindow = m_windowsIntegration.checkForFullScreenWindow(m_windowsIntegration.windowHandle()); + + setVisualsPaused(hasFullscreenWindow); +} +} + #include "moc_winwindow.cpp" diff --git a/ScreenPlayWallpaper/src/winwindow.h b/ScreenPlayWallpaper/src/winwindow.h index d2b674a9..a4744236 100644 --- a/ScreenPlayWallpaper/src/winwindow.h +++ b/ScreenPlayWallpaper/src/winwindow.h @@ -18,6 +18,9 @@ #include "basewindow.h" #include "windowsdesktopproperties.h" +#include "windowsintegration.h" + +namespace ScreenPlay { class WinWindow : public BaseWindow { Q_OBJECT @@ -27,7 +30,7 @@ class WinWindow : public BaseWindow { public: WindowsDesktopProperties* windowsDesktopProperties() const { return m_windowsDesktopProperties.get(); } - ScreenPlay::WallpaperExitCode start() override; + WallpaperExit::Code start() override; public slots: void setVisible(bool show) override; @@ -52,11 +55,8 @@ private: void setupWallpaperForOneScreen(int activeScreen); void setupWallpaperForAllScreens(); void setupWallpaperForMultipleScreens(const QVector& activeScreensList); - void setupWindowMouseHook(); - bool searchWorkerWindowToParentTo(); void configureWindowGeometry(); - bool hasWindowScaling() const; - float getScaling(const int monitorIndex) const; + std::tuple mapVirtualKeyToQtKey(UINT vkCode); private slots: void checkForFullScreenWindow(); @@ -64,9 +64,9 @@ private slots: private: QPoint m_zeroPoint {}; QQuickView m_window; - HWND m_windowHandle {}; - HWND m_windowHandleWorker {}; + WindowsIntegration m_windowsIntegration; QTimer m_checkForFullScreenWindowTimer; QTimer m_reconfigureTimer; std::unique_ptr m_windowsDesktopProperties; }; +} diff --git a/ScreenPlayWeather/CMakeLists.txt b/ScreenPlayWeather/CMakeLists.txt index 028f56a6..07caeaf3 100644 --- a/ScreenPlayWeather/CMakeLists.txt +++ b/ScreenPlayWeather/CMakeLists.txt @@ -8,6 +8,7 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_AUTOMOC ON) set(CMAKE_CXX_STANDARD_REQUIRED ON) +find_package(LibArchive REQUIRED) find_package( Qt6 COMPONENTS Core Quick @@ -242,7 +243,7 @@ set(RESOURCES assets/icons/wi-windy.svg) qt_add_library(${PROJECT_NAME} STATIC) -target_link_libraries(${PROJECT_NAME} PUBLIC ScreenPlayUtil) +target_link_libraries(${PROJECT_NAME} PUBLIC ScreenPlayUtil ScreenPlayUtilplugin) target_include_directories(${PROJECT_NAME} PUBLIC src/) qt_add_qml_module( @@ -266,4 +267,9 @@ qt_add_qml_module( if(${SCREENPLAY_TESTS}) qt_add_executable(tst_ScreenPlayWeather src/TestMain.cpp) target_link_libraries(tst_ScreenPlayWeather PRIVATE Qt6::Quick ${PROJECT_NAME}plugin) + + if(APPLE) + set_target_properties(tst_ScreenPlayWeather PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/") + endif() endif() diff --git a/ScreenPlayWeather/src/TestMain.cpp b/ScreenPlayWeather/src/TestMain.cpp index ae4115bb..1612e4bf 100644 --- a/ScreenPlayWeather/src/TestMain.cpp +++ b/ScreenPlayWeather/src/TestMain.cpp @@ -4,6 +4,7 @@ #include Q_IMPORT_QML_PLUGIN(ScreenPlayWeatherPlugin) +Q_IMPORT_QML_PLUGIN(ScreenPlayUtilPlugin) int main(int argc, char* argv[]) { diff --git a/ScreenPlayWeather/src/screenplayweather.cpp b/ScreenPlayWeather/src/screenplayweather.cpp index b9d485e3..d72a6f91 100644 --- a/ScreenPlayWeather/src/screenplayweather.cpp +++ b/ScreenPlayWeather/src/screenplayweather.cpp @@ -31,7 +31,7 @@ void ScreenPlayWeather::updateLatitudeLongtitude(const QString& city) if (data.size() <= 0) return; - const auto msgOpt = ScreenPlayUtil::parseQByteArrayToQJsonObject(data); + const auto msgOpt = ScreenPlay::Util().parseQByteArrayToQJsonObject(data); if (!msgOpt.has_value()) return; @@ -80,13 +80,13 @@ void ScreenPlayWeather::update() request.setUrl(url); qInfo() << url; auto* reply = m_networkAccessManager.get(request); - QObject::connect(reply, &QNetworkReply::finished, this, [this, reply]() { const QByteArray data = reply->readAll(); if (data.size() <= 0) return; - const auto msgOpt = ScreenPlayUtil::parseQByteArrayToQJsonObject(data); + ScreenPlay::Util util; + const auto msgOpt = util.parseQByteArrayToQJsonObject(data); if (!msgOpt.has_value()) return; @@ -113,10 +113,10 @@ void ScreenPlayWeather::update() day->set_sunrise(QDateTime::fromString(sunrise.at(i).toString(), m_dataTimeFormat).toString("mm:ss")); day->set_sunset(QDateTime::fromString(sunset.at(i).toString(), m_dataTimeFormat).toString("mm:ss")); day->set_weatherCode(weathercode.at(i).toInt()); - day->set_temperature_2m_min(ScreenPlayUtil::roundDecimalPlaces(temperature_2m_min.at(i).toDouble())); - day->set_temperature_2m_max(ScreenPlayUtil::roundDecimalPlaces(temperature_2m_max.at(i).toDouble())); + day->set_temperature_2m_min(util.roundDecimalPlaces(temperature_2m_min.at(i).toDouble())); + day->set_temperature_2m_max(util.roundDecimalPlaces(temperature_2m_max.at(i).toDouble())); day->set_precipitationHours(precipitation_hours.at(i).toInt()); - day->set_precipitationSum(ScreenPlayUtil::roundDecimalPlaces(precipitation_sum.at(i).toDouble())); + day->set_precipitationSum(util.roundDecimalPlaces(precipitation_sum.at(i).toDouble())); m_days.append(&m_days, std::move(day)); } const auto hourly = msgOpt->value("hourly").toObject(); diff --git a/ScreenPlayWidget/CMakeLists.txt b/ScreenPlayWidget/CMakeLists.txt index 66af75f5..c0a10c7d 100644 --- a/ScreenPlayWidget/CMakeLists.txt +++ b/ScreenPlayWidget/CMakeLists.txt @@ -41,6 +41,7 @@ target_link_libraries( ${PROJECT_NAME} PRIVATE ScreenPlaySDK ScreenPlayUtil + ScreenPlayUtilplugin ScreenPlayWeatherplugin Qt6::Quick Qt6::Gui @@ -52,7 +53,7 @@ target_link_libraries( Qt6::WebEngineQuick) if(WIN32) - target_link_libraries(${PROJECT_NAME} PRIVATE ScreenPlaySysInfoplugin) + target_link_libraries(${PROJECT_NAME} PRIVATE ScreenPlaySysInfoplugin ScreenPlayUtilplugin) endif() qt_add_qml_module( @@ -76,7 +77,7 @@ if(WIN32) set_property(TARGET ${PROJECT_NAME} PROPERTY WIN32_EXECUTABLE true) endif() -if(APPLE AND NOT OSX_BUNDLE) +if(APPLE) set_target_properties(${PROJECT_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/") endif() diff --git a/ScreenPlayWidget/main.cpp b/ScreenPlayWidget/main.cpp index cffc4841..f7390775 100644 --- a/ScreenPlayWidget/main.cpp +++ b/ScreenPlayWidget/main.cpp @@ -8,16 +8,18 @@ #include #include +#include "ScreenPlayUtil/logginghandler.h" #include "src/widgetwindow.h" #if defined(Q_OS_WIN) Q_IMPORT_QML_PLUGIN(ScreenPlaySysInfoPlugin) #endif -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) #include "ScreenPlayUtil/macutils.h" #endif Q_IMPORT_QML_PLUGIN(ScreenPlayWeatherPlugin) +Q_IMPORT_QML_PLUGIN(ScreenPlayUtilPlugin) int main(int argc, char* argv[]) { @@ -32,6 +34,7 @@ int main(int argc, char* argv[]) #endif QGuiApplication app(argc, argv); + std::unique_ptr logging; const QStringList argumentList = app.arguments(); @@ -83,16 +86,18 @@ int main(int argc, char* argv[]) qWarning() << "Could not parse PositionY value to int: " << argumentList.at(5); positionY = 0; } - + const QString appID = argumentList.at(2); WidgetWindow spwmw( argumentList.at(1), // Project path, - argumentList.at(2), // AppID + appID, // AppID argumentList.at(3), // Type QPoint { positionX, positionY }); -#if defined(Q_OS_OSX) +#if defined(Q_OS_MACOS) MacUtils::showDockIcon(false); #endif - - return app.exec(); + logging = std::make_unique("ScreenPlayWidget_" + appID); + const int status = app.exec(); + logging.reset(); + return status; } diff --git a/ScreenPlayWidget/qml/Widget.qml b/ScreenPlayWidget/qml/Widget.qml index 01ba4570..601dfa84 100644 --- a/ScreenPlayWidget/qml/Widget.qml +++ b/ScreenPlayWidget/qml/Widget.qml @@ -2,7 +2,6 @@ import QtQuick import QtQuick.Controls import QtWebEngine import ScreenPlayWidget -import ScreenPlay.Enums.InstalledType import ScreenPlayUtil as Util Item { @@ -77,10 +76,10 @@ Item { asynchronous: true Component.onCompleted: { switch (Widget.type) { - case InstalledType.QMLWidget: + case ContentTypes.InstalledType.QMLWidget: loader.source = Qt.resolvedUrl(Widget.projectSourceFileAbsolute); break; - case InstalledType.HTMLWidget: + case ContentTypes.InstalledType.HTMLWidget: loader.sourceComponent = webViewComponent; break; } diff --git a/ScreenPlayWidget/src/widgetwindow.cpp b/ScreenPlayWidget/src/widgetwindow.cpp index f1d62cb5..7a7d9bab 100644 --- a/ScreenPlayWidget/src/widgetwindow.cpp +++ b/ScreenPlayWidget/src/widgetwindow.cpp @@ -32,14 +32,6 @@ WidgetWindow::WidgetWindow( , m_sdk { std::make_unique(appID, type) } , m_debugMode { debugMode } { - - qRegisterMetaType(); - qmlRegisterUncreatableMetaObject(ScreenPlay::InstalledType::staticMetaObject, - "ScreenPlay.Enums.InstalledType", - 1, 0, - "InstalledType", - "Error: only enums"); - Qt::WindowFlags flags = m_window.flags(); if (QSysInfo::productType() == "macos") { // Setting it as a SlashScreen causes the window to hide on focus lost @@ -56,12 +48,13 @@ WidgetWindow::WidgetWindow( setWindowBlur(); #endif + ScreenPlay::Util util; if (projectPath == "test") { setProjectSourceFileAbsolute({ "qrc:/qml/ScreenPlayWidget/qml/Test.qml" }); - setType(ScreenPlay::InstalledType::InstalledType::QMLWidget); + setType(ScreenPlay::ContentTypes::InstalledType::QMLWidget); } else { setProjectPath(projectPath); - auto projectOpt = ScreenPlayUtil::openJsonFileToObject(m_projectPath + "/project.json"); + auto projectOpt = util.openJsonFileToObject(m_projectPath + "/project.json"); if (!projectOpt.has_value()) { qWarning() << "Unable to parse project file!"; return; @@ -71,7 +64,7 @@ WidgetWindow::WidgetWindow( setProjectSourceFile(m_project.value("file").toString()); setProjectSourceFileAbsolute(QUrl::fromLocalFile(m_projectPath + "/" + projectSourceFile())); - if (auto typeOpt = ScreenPlayUtil::getInstalledTypeFromString(m_project.value("type").toString())) { + if (auto typeOpt = util.getInstalledTypeFromString(m_project.value("type").toString())) { setType(typeOpt.value()); } else { qWarning() << "Cannot parse Wallpaper type from value" << m_project.value("type"); diff --git a/ScreenPlayWidget/src/widgetwindow.h b/ScreenPlayWidget/src/widgetwindow.h index 48ed7547..d987fbe3 100644 --- a/ScreenPlayWidget/src/widgetwindow.h +++ b/ScreenPlayWidget/src/widgetwindow.h @@ -43,14 +43,14 @@ public: Q_PROPERTY(QString projectSourceFile READ projectSourceFile WRITE setProjectSourceFile NOTIFY projectSourceFileChanged) Q_PROPERTY(QUrl projectSourceFileAbsolute READ projectSourceFileAbsolute WRITE setProjectSourceFileAbsolute NOTIFY projectSourceFileAbsoluteChanged) Q_PROPERTY(QPoint position READ position WRITE setPosition NOTIFY positionChanged) - Q_PROPERTY(ScreenPlay::InstalledType::InstalledType type READ type WRITE setType NOTIFY typeChanged) + Q_PROPERTY(ScreenPlay::ContentTypes::InstalledType type READ type WRITE setType NOTIFY typeChanged) Q_PROPERTY(ScreenPlaySDK* sdk READ sdk WRITE setSdk NOTIFY sdkChanged) Q_PROPERTY(bool debugMode READ debugMode WRITE setDebugMode NOTIFY debugModeChanged) QString appID() const { return m_appID; } QPoint position() const { return m_position; } const QString& projectPath() const { return m_projectPath; } - ScreenPlay::InstalledType::InstalledType type() const { return m_type; } + ScreenPlay::ContentTypes::InstalledType type() const { return m_type; } const QString& projectSourceFile() const { return m_projectSourceFile; } const QUrl& projectSourceFileAbsolute() const { return m_projectSourceFileAbsolute; } ScreenPlaySDK* sdk() const { return m_sdk.get(); } @@ -58,12 +58,12 @@ public: signals: void qmlExit(); - void reloadQML(const ScreenPlay::InstalledType::InstalledType oldType); + void reloadQML(const ScreenPlay::ContentTypes::InstalledType oldType); void appIDChanged(QString appID); void qmlSceneValueReceived(QString key, QString value); void positionChanged(QPoint position); void projectPathChanged(const QString& projectPath); - void typeChanged(ScreenPlay::InstalledType::InstalledType); + void typeChanged(ScreenPlay::ContentTypes::InstalledType); void projectSourceFileChanged(const QString& projectSourceFile); void projectSourceFileAbsoluteChanged(const QUrl& projectSourceFileAbsolute); void sdkChanged(ScreenPlaySDK* sdk); @@ -111,7 +111,7 @@ public slots: emit projectPathChanged(m_projectPath); } - void setType(ScreenPlay::InstalledType::InstalledType Type) + void setType(ScreenPlay::ContentTypes::InstalledType Type) { if (m_type == Type) return; @@ -165,7 +165,7 @@ private: QQuickView m_window; std::unique_ptr m_sdk; QTimer m_positionMessageLimiter; - ScreenPlay::InstalledType::InstalledType m_type; + ScreenPlay::ContentTypes::InstalledType m_type; QFileSystemWatcher m_fileSystemWatcher; QTimer m_liveReloadLimiter; QUrl m_projectSourceFileAbsolute; diff --git a/ScreenPlayWorkshop/CMakeLists.txt b/ScreenPlayWorkshop/CMakeLists.txt index b7981fa6..ebfa318a 100644 --- a/ScreenPlayWorkshop/CMakeLists.txt +++ b/ScreenPlayWorkshop/CMakeLists.txt @@ -8,6 +8,7 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_AUTOMOC ON) set(CMAKE_CXX_STANDARD_REQUIRED ON) +find_package(LibArchive REQUIRED) find_package( Qt6 COMPONENTS Core Quick QuickControls2 @@ -100,8 +101,7 @@ target_link_libraries( Qt6::Quick ${STEAM_LIB} ScreenPlayUtil - SteamSDK - SteamSDKQtEnums) + SteamSDK) qt_add_qml_module( ${PROJECT_NAME} @@ -122,14 +122,11 @@ qt_add_qml_module( ${RESOURCES}) if(${SCREENPLAY_STEAM}) - if(APPLE AND NOT OSX_BUNDLE) + if(APPLE) set(MACOS_FRAMEWORKS_DIR ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ScreenPlay.app/Contents/MacOS/) file(MAKE_DIRECTORY ${MACOS_FRAMEWORKS_DIR}) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/steam_appid.txt ${MACOS_FRAMEWORKS_DIR} COPYONLY) configure_file(${STEAM_BIN} ${MACOS_FRAMEWORKS_DIR} COPYONLY) - else() - configure_file(${CMAKE_CURRENT_SOURCE_DIR}/steam_appid.txt ${CMAKE_BINARY_DIR}/bin/steam_appid.txt COPYONLY) - configure_file(${STEAM_BIN} ${CMAKE_BINARY_DIR}/bin/ COPYONLY) endif() if(${SCREENPLAY_TESTS}) @@ -140,7 +137,11 @@ if(${SCREENPLAY_STEAM}) Qt6::QuickControls2 ${PROJECT_NAME}plugin ScreenPlayUtilplugin - SteamSDK - SteamSDKQtEnums) + SteamSDK) + + if(APPLE) + set_target_properties(tst_ScreenPlayWorkshop PROPERTIES RUNTIME_OUTPUT_DIRECTORY + "${CMAKE_BINARY_DIR}/bin/ScreenPlay.app/Contents/MacOS/") + endif() endif() endif() diff --git a/ScreenPlayWorkshop/SteamSDK/CMakeLists.txt b/ScreenPlayWorkshop/SteamSDK/CMakeLists.txt index 12d0e127..45c37197 100644 --- a/ScreenPlayWorkshop/SteamSDK/CMakeLists.txt +++ b/ScreenPlayWorkshop/SteamSDK/CMakeLists.txt @@ -4,7 +4,7 @@ set(CMAKE_CXX_STANDARD 20) set(CMAKE_AUTORCC ON) set(CMAKE_AUTOMOC ON) -find_package(Qt6 COMPONENTS Core) +find_package(Qt6 COMPONENTS Core Quick) set(HEADER public/steam/isteamapplist.h @@ -54,11 +54,5 @@ set(HEADER if(${SCREENPLAY_STEAM}) qt_add_library(${PROJECT_NAME} STATIC ${HEADER}) target_include_directories(${PROJECT_NAME} PUBLIC public/) - target_link_libraries(${PROJECT_NAME}) + target_link_libraries(${PROJECT_NAME} PUBLIC ScreenPlayUtil) endif() - -# We allaways need the generated enums as a workaround to register these enums in app.cpp. Registering in the ScreenPlayWorkshop plugin does -# not work for some reason. -qt_add_library(SteamSDKQtEnums STATIC public/steam/steam_qt_enums_generated.h) -target_include_directories(SteamSDKQtEnums PUBLIC public/) -target_link_libraries(SteamSDKQtEnums PRIVATE Qt6::Core) diff --git a/ScreenPlayWorkshop/SteamSDK/generate_qt_enums.py b/ScreenPlayWorkshop/SteamSDK/generate_qt_enums.py index cd0c8948..36640c4c 100644 --- a/ScreenPlayWorkshop/SteamSDK/generate_qt_enums.py +++ b/ScreenPlayWorkshop/SteamSDK/generate_qt_enums.py @@ -16,7 +16,7 @@ def createEnum(name,valueList): enum_string += "\n{" enum_string += "\t"+ enum_string_values enum_string += " };" - enum_string += "\nQ_ENUM_NS(" + name +")" + enum_string += "\nQ_ENUM(" + name +")" enum_string += "\n\n" return enum_string @@ -33,15 +33,23 @@ if __name__ == '__main__': #pragma once #include +#include -namespace ScreenPlayWorkshopSteamEnums { +namespace ScreenPlay { - Q_NAMESPACE +class Steam : public QObject { + Q_OBJECT + QML_ELEMENT + QML_UNCREATABLE("") + Q_CLASSINFO("RegisterEnumClassesUnscoped", "false") + +public: + explicit Steam(); """ file_end = """ - +}; } """ @@ -58,7 +66,7 @@ namespace ScreenPlayWorkshopSteamEnums { file_complete += file_content file_complete += file_end - with open('public/steam/steam_qt_enums_generated.h', 'w') as outfile: + with open('steamenumsgenerated.h', 'w') as outfile: outfile.write(file_complete) print("Update write") diff --git a/ScreenPlayWorkshop/SteamSDK/public/steam/steam_qt_enums_generated.h b/ScreenPlayWorkshop/SteamSDK/public/steam/steam_qt_enums_generated.h deleted file mode 100644 index e0d00c3b..00000000 --- a/ScreenPlayWorkshop/SteamSDK/public/steam/steam_qt_enums_generated.h +++ /dev/null @@ -1,2173 +0,0 @@ -// GENERATED FILE DO NOT EDIT -// TO REGENERATE run ScreenPlayInternal\SteamSDK -// > python.exe updateEnums.py - -#pragma once -#include - -namespace ScreenPlayWorkshopSteamEnums { - -Q_NAMESPACE - -enum class ESteamIPType { - K_ESteamIPTypeIPv4 = 0, - K_ESteamIPTypeIPv6 = 1, -}; -Q_ENUM_NS(ESteamIPType) - -enum class EUniverse { - K_EUniverseInvalid = 0, - K_EUniversePublic = 1, - K_EUniverseBeta = 2, - K_EUniverseInternal = 3, - K_EUniverseDev = 4, - K_EUniverseMax = 5, -}; -Q_ENUM_NS(EUniverse) - -enum class EResult { - K_EResultNone = 0, - K_EResultOK = 1, - K_EResultFail = 2, - K_EResultNoConnection = 3, - K_EResultInvalidPassword = 5, - K_EResultLoggedInElsewhere = 6, - K_EResultInvalidProtocolVer = 7, - K_EResultInvalidParam = 8, - K_EResultFileNotFound = 9, - K_EResultBusy = 10, - K_EResultInvalidState = 11, - K_EResultInvalidName = 12, - K_EResultInvalidEmail = 13, - K_EResultDuplicateName = 14, - K_EResultAccessDenied = 15, - K_EResultTimeout = 16, - K_EResultBanned = 17, - K_EResultAccountNotFound = 18, - K_EResultInvalidSteamID = 19, - K_EResultServiceUnavailable = 20, - K_EResultNotLoggedOn = 21, - K_EResultPending = 22, - K_EResultEncryptionFailure = 23, - K_EResultInsufficientPrivilege = 24, - K_EResultLimitExceeded = 25, - K_EResultRevoked = 26, - K_EResultExpired = 27, - K_EResultAlreadyRedeemed = 28, - K_EResultDuplicateRequest = 29, - K_EResultAlreadyOwned = 30, - K_EResultIPNotFound = 31, - K_EResultPersistFailed = 32, - K_EResultLockingFailed = 33, - K_EResultLogonSessionReplaced = 34, - K_EResultConnectFailed = 35, - K_EResultHandshakeFailed = 36, - K_EResultIOFailure = 37, - K_EResultRemoteDisconnect = 38, - K_EResultShoppingCartNotFound = 39, - K_EResultBlocked = 40, - K_EResultIgnored = 41, - K_EResultNoMatch = 42, - K_EResultAccountDisabled = 43, - K_EResultServiceReadOnly = 44, - K_EResultAccountNotFeatured = 45, - K_EResultAdministratorOK = 46, - K_EResultContentVersion = 47, - K_EResultTryAnotherCM = 48, - K_EResultPasswordRequiredToKickSession = 49, - K_EResultAlreadyLoggedInElsewhere = 50, - K_EResultSuspended = 51, - K_EResultCancelled = 52, - K_EResultDataCorruption = 53, - K_EResultDiskFull = 54, - K_EResultRemoteCallFailed = 55, - K_EResultPasswordUnset = 56, - K_EResultExternalAccountUnlinked = 57, - K_EResultPSNTicketInvalid = 58, - K_EResultExternalAccountAlreadyLinked = 59, - K_EResultRemoteFileConflict = 60, - K_EResultIllegalPassword = 61, - K_EResultSameAsPreviousValue = 62, - K_EResultAccountLogonDenied = 63, - K_EResultCannotUseOldPassword = 64, - K_EResultInvalidLoginAuthCode = 65, - K_EResultAccountLogonDeniedNoMail = 66, - K_EResultHardwareNotCapableOfIPT = 67, - K_EResultIPTInitError = 68, - K_EResultParentalControlRestricted = 69, - K_EResultFacebookQueryError = 70, - K_EResultExpiredLoginAuthCode = 71, - K_EResultIPLoginRestrictionFailed = 72, - K_EResultAccountLockedDown = 73, - K_EResultAccountLogonDeniedVerifiedEmailRequired = 74, - K_EResultNoMatchingURL = 75, - K_EResultBadResponse = 76, - K_EResultRequirePasswordReEntry = 77, - K_EResultValueOutOfRange = 78, - K_EResultUnexpectedError = 79, - K_EResultDisabled = 80, - K_EResultInvalidCEGSubmission = 81, - K_EResultRestrictedDevice = 82, - K_EResultRegionLocked = 83, - K_EResultRateLimitExceeded = 84, - K_EResultAccountLoginDeniedNeedTwoFactor = 85, - K_EResultItemDeleted = 86, - K_EResultAccountLoginDeniedThrottle = 87, - K_EResultTwoFactorCodeMismatch = 88, - K_EResultTwoFactorActivationCodeMismatch = 89, - K_EResultAccountAssociatedToMultiplePartners = 90, - K_EResultNotModified = 91, - K_EResultNoMobileDevice = 92, - K_EResultTimeNotSynced = 93, - K_EResultSmsCodeFailed = 94, - K_EResultAccountLimitExceeded = 95, - K_EResultAccountActivityLimitExceeded = 96, - K_EResultPhoneActivityLimitExceeded = 97, - K_EResultRefundToWallet = 98, - K_EResultEmailSendFailure = 99, - K_EResultNotSettled = 100, - K_EResultNeedCaptcha = 101, - K_EResultGSLTDenied = 102, - K_EResultGSOwnerDenied = 103, - K_EResultInvalidItemType = 104, - K_EResultIPBanned = 105, - K_EResultGSLTExpired = 106, - K_EResultInsufficientFunds = 107, - K_EResultTooManyPending = 108, - K_EResultNoSiteLicensesFound = 109, - K_EResultWGNetworkSendExceeded = 110, - K_EResultAccountNotFriends = 111, - K_EResultLimitedUserAccount = 112, - K_EResultCantRemoveItem = 113, - K_EResultAccountDeleted = 114, - K_EResultExistingUserCancelledLicense = 115, - K_EResultCommunityCooldown = 116, - K_EResultNoLauncherSpecified = 117, - K_EResultMustAgreeToSSA = 118, - K_EResultLauncherMigrated = 119, - K_EResultSteamRealmMismatch = 120, - K_EResultInvalidSignature = 121, - K_EResultParseFailure = 122, - K_EResultNoVerifiedPhone = 123, - K_EResultInsufficientBattery = 124, - K_EResultChargerRequired = 125, - K_EResultCachedCredentialInvalid = 126, - K_EResultPhoneNumberIsVOIP = 127, -}; -Q_ENUM_NS(EResult) - -enum class EVoiceResult { - K_EVoiceResultOK = 0, - K_EVoiceResultNotInitialized = 1, - K_EVoiceResultNotRecording = 2, - K_EVoiceResultNoData = 3, - K_EVoiceResultBufferTooSmall = 4, - K_EVoiceResultDataCorrupted = 5, - K_EVoiceResultRestricted = 6, - K_EVoiceResultUnsupportedCodec = 7, - K_EVoiceResultReceiverOutOfDate = 8, - K_EVoiceResultReceiverDidNotAnswer = 9, -}; -Q_ENUM_NS(EVoiceResult) - -enum class EDenyReason { - K_EDenyInvalid = 0, - K_EDenyInvalidVersion = 1, - K_EDenyGeneric = 2, - K_EDenyNotLoggedOn = 3, - K_EDenyNoLicense = 4, - K_EDenyCheater = 5, - K_EDenyLoggedInElseWhere = 6, - K_EDenyUnknownText = 7, - K_EDenyIncompatibleAnticheat = 8, - K_EDenyMemoryCorruption = 9, - K_EDenyIncompatibleSoftware = 10, - K_EDenySteamConnectionLost = 11, - K_EDenySteamConnectionError = 12, - K_EDenySteamResponseTimedOut = 13, - K_EDenySteamValidationStalled = 14, - K_EDenySteamOwnerLeftGuestUser = 15, -}; -Q_ENUM_NS(EDenyReason) - -enum class EBeginAuthSessionResult { - K_EBeginAuthSessionResultOK = 0, - K_EBeginAuthSessionResultInvalidTicket = 1, - K_EBeginAuthSessionResultDuplicateRequest = 2, - K_EBeginAuthSessionResultInvalidVersion = 3, - K_EBeginAuthSessionResultGameMismatch = 4, - K_EBeginAuthSessionResultExpiredTicket = 5, -}; -Q_ENUM_NS(EBeginAuthSessionResult) - -enum class EAuthSessionResponse { - K_EAuthSessionResponseOK = 0, - K_EAuthSessionResponseUserNotConnectedToSteam = 1, - K_EAuthSessionResponseNoLicenseOrExpired = 2, - K_EAuthSessionResponseVACBanned = 3, - K_EAuthSessionResponseLoggedInElseWhere = 4, - K_EAuthSessionResponseVACCheckTimedOut = 5, - K_EAuthSessionResponseAuthTicketCanceled = 6, - K_EAuthSessionResponseAuthTicketInvalidAlreadyUsed = 7, - K_EAuthSessionResponseAuthTicketInvalid = 8, - K_EAuthSessionResponsePublisherIssuedBan = 9, - K_EAuthSessionResponseAuthTicketNetworkIdentityFailure = 10, -}; -Q_ENUM_NS(EAuthSessionResponse) - -enum class EUserHasLicenseForAppResult { - K_EUserHasLicenseResultHasLicense = 0, - K_EUserHasLicenseResultDoesNotHaveLicense = 1, - K_EUserHasLicenseResultNoAuth = 2, -}; -Q_ENUM_NS(EUserHasLicenseForAppResult) - -enum class EAccountType { - K_EAccountTypeInvalid = 0, - K_EAccountTypeIndividual = 1, - K_EAccountTypeMultiseat = 2, - K_EAccountTypeGameServer = 3, - K_EAccountTypeAnonGameServer = 4, - K_EAccountTypePending = 5, - K_EAccountTypeContentServer = 6, - K_EAccountTypeClan = 7, - K_EAccountTypeChat = 8, - K_EAccountTypeConsoleUser = 9, - K_EAccountTypeAnonUser = 10, - K_EAccountTypeMax = 11, -}; -Q_ENUM_NS(EAccountType) - -enum class EChatEntryType { - K_EChatEntryTypeInvalid = 0, - K_EChatEntryTypeChatMsg = 1, - K_EChatEntryTypeTyping = 2, - K_EChatEntryTypeInviteGame = 3, - K_EChatEntryTypeEmote = 4, - K_EChatEntryTypeLeftConversation = 6, - K_EChatEntryTypeEntered = 7, - K_EChatEntryTypeWasKicked = 8, - K_EChatEntryTypeWasBanned = 9, - K_EChatEntryTypeDisconnected = 10, - K_EChatEntryTypeHistoricalChat = 11, - K_EChatEntryTypeLinkBlocked = 14, -}; -Q_ENUM_NS(EChatEntryType) - -enum class EChatRoomEnterResponse { - K_EChatRoomEnterResponseSuccess = 1, - K_EChatRoomEnterResponseDoesntExist = 2, - K_EChatRoomEnterResponseNotAllowed = 3, - K_EChatRoomEnterResponseFull = 4, - K_EChatRoomEnterResponseError = 5, - K_EChatRoomEnterResponseBanned = 6, - K_EChatRoomEnterResponseLimited = 7, - K_EChatRoomEnterResponseClanDisabled = 8, - K_EChatRoomEnterResponseCommunityBan = 9, - K_EChatRoomEnterResponseMemberBlockedYou = 10, - K_EChatRoomEnterResponseYouBlockedMember = 11, - K_EChatRoomEnterResponseRatelimitExceeded = 15, -}; -Q_ENUM_NS(EChatRoomEnterResponse) - -enum class EChatSteamIDInstanceFlags { - K_EChatAccountInstanceMask = 4095, - K_EChatInstanceFlagClan = 524288, - K_EChatInstanceFlagLobby = 262144, - K_EChatInstanceFlagMMSLobby = 131072, -}; -Q_ENUM_NS(EChatSteamIDInstanceFlags) - -enum class ENotificationPosition { - K_EPositionInvalid = -1, - K_EPositionTopLeft = 0, - K_EPositionTopRight = 1, - K_EPositionBottomLeft = 2, - K_EPositionBottomRight = 3, -}; -Q_ENUM_NS(ENotificationPosition) - -enum class EBroadcastUploadResult { - K_EBroadcastUploadResultNone = 0, - K_EBroadcastUploadResultOK = 1, - K_EBroadcastUploadResultInitFailed = 2, - K_EBroadcastUploadResultFrameFailed = 3, - K_EBroadcastUploadResultTimeout = 4, - K_EBroadcastUploadResultBandwidthExceeded = 5, - K_EBroadcastUploadResultLowFPS = 6, - K_EBroadcastUploadResultMissingKeyFrames = 7, - K_EBroadcastUploadResultNoConnection = 8, - K_EBroadcastUploadResultRelayFailed = 9, - K_EBroadcastUploadResultSettingsChanged = 10, - K_EBroadcastUploadResultMissingAudio = 11, - K_EBroadcastUploadResultTooFarBehind = 12, - K_EBroadcastUploadResultTranscodeBehind = 13, - K_EBroadcastUploadResultNotAllowedToPlay = 14, - K_EBroadcastUploadResultBusy = 15, - K_EBroadcastUploadResultBanned = 16, - K_EBroadcastUploadResultAlreadyActive = 17, - K_EBroadcastUploadResultForcedOff = 18, - K_EBroadcastUploadResultAudioBehind = 19, - K_EBroadcastUploadResultShutdown = 20, - K_EBroadcastUploadResultDisconnect = 21, - K_EBroadcastUploadResultVideoInitFailed = 22, - K_EBroadcastUploadResultAudioInitFailed = 23, -}; -Q_ENUM_NS(EBroadcastUploadResult) - -enum class EMarketNotAllowedReasonFlags { - K_EMarketNotAllowedReason_None = 0, - K_EMarketNotAllowedReason_TemporaryFailure = 1, - K_EMarketNotAllowedReason_AccountDisabled = 2, - K_EMarketNotAllowedReason_AccountLockedDown = 4, - K_EMarketNotAllowedReason_AccountLimited = 8, - K_EMarketNotAllowedReason_TradeBanned = 16, - K_EMarketNotAllowedReason_AccountNotTrusted = 32, - K_EMarketNotAllowedReason_SteamGuardNotEnabled = 64, - K_EMarketNotAllowedReason_SteamGuardOnlyRecentlyEnabled = 128, - K_EMarketNotAllowedReason_RecentPasswordReset = 256, - K_EMarketNotAllowedReason_NewPaymentMethod = 512, - K_EMarketNotAllowedReason_InvalidCookie = 1024, - K_EMarketNotAllowedReason_UsingNewDevice = 2048, - K_EMarketNotAllowedReason_RecentSelfRefund = 4096, - K_EMarketNotAllowedReason_NewPaymentMethodCannotBeVerified = 8192, - K_EMarketNotAllowedReason_NoRecentPurchases = 16384, - K_EMarketNotAllowedReason_AcceptedWalletGift = 32768, -}; -Q_ENUM_NS(EMarketNotAllowedReasonFlags) - -enum class EDurationControlProgress { - K_EDurationControlProgress_Full = 0, - K_EDurationControlProgress_Half = 1, - K_EDurationControlProgress_None = 2, - K_EDurationControl_ExitSoon_3h = 3, - K_EDurationControl_ExitSoon_5h = 4, - K_EDurationControl_ExitSoon_Night = 5, -}; -Q_ENUM_NS(EDurationControlProgress) - -enum class EDurationControlNotification { - K_EDurationControlNotification_None = 0, - K_EDurationControlNotification_1Hour = 1, - K_EDurationControlNotification_3Hours = 2, - K_EDurationControlNotification_HalfProgress = 3, - K_EDurationControlNotification_NoProgress = 4, - K_EDurationControlNotification_ExitSoon_3h = 5, - K_EDurationControlNotification_ExitSoon_5h = 6, - K_EDurationControlNotification_ExitSoon_Night = 7, -}; -Q_ENUM_NS(EDurationControlNotification) - -enum class EDurationControlOnlineState { - K_EDurationControlOnlineState_Invalid = 0, - K_EDurationControlOnlineState_Offline = 1, - K_EDurationControlOnlineState_Online = 2, - K_EDurationControlOnlineState_OnlineHighPri = 3, -}; -Q_ENUM_NS(EDurationControlOnlineState) - -enum class EGameSearchErrorCode_t { - K_EGameSearchErrorCode_OK = 1, - K_EGameSearchErrorCode_Failed_Search_Already_In_Progress = 2, - K_EGameSearchErrorCode_Failed_No_Search_In_Progress = 3, - K_EGameSearchErrorCode_Failed_Not_Lobby_Leader = 4, - K_EGameSearchErrorCode_Failed_No_Host_Available = 5, - K_EGameSearchErrorCode_Failed_Search_Params_Invalid = 6, - K_EGameSearchErrorCode_Failed_Offline = 7, - K_EGameSearchErrorCode_Failed_NotAuthorized = 8, - K_EGameSearchErrorCode_Failed_Unknown_Error = 9, -}; -Q_ENUM_NS(EGameSearchErrorCode_t) - -enum class EPlayerResult_t { - K_EPlayerResultFailedToConnect = 1, - K_EPlayerResultAbandoned = 2, - K_EPlayerResultKicked = 3, - K_EPlayerResultIncomplete = 4, - K_EPlayerResultCompleted = 5, -}; -Q_ENUM_NS(EPlayerResult_t) - -enum class ESteamIPv6ConnectivityProtocol { - K_ESteamIPv6ConnectivityProtocol_Invalid = 0, - K_ESteamIPv6ConnectivityProtocol_HTTP = 1, - K_ESteamIPv6ConnectivityProtocol_UDP = 2, -}; -Q_ENUM_NS(ESteamIPv6ConnectivityProtocol) - -enum class ESteamIPv6ConnectivityState { - K_ESteamIPv6ConnectivityState_Unknown = 0, - K_ESteamIPv6ConnectivityState_Good = 1, - K_ESteamIPv6ConnectivityState_Bad = 2, -}; -Q_ENUM_NS(ESteamIPv6ConnectivityState) - -enum class EFriendRelationship { - K_EFriendRelationshipNone = 0, - K_EFriendRelationshipBlocked = 1, - K_EFriendRelationshipRequestRecipient = 2, - K_EFriendRelationshipFriend = 3, - K_EFriendRelationshipRequestInitiator = 4, - K_EFriendRelationshipIgnored = 5, - K_EFriendRelationshipIgnoredFriend = 6, - K_EFriendRelationshipSuggested_DEPRECATED = 7, - K_EFriendRelationshipMax = 8, -}; -Q_ENUM_NS(EFriendRelationship) - -enum class EPersonaState { - K_EPersonaStateOffline = 0, - K_EPersonaStateOnline = 1, - K_EPersonaStateBusy = 2, - K_EPersonaStateAway = 3, - K_EPersonaStateSnooze = 4, - K_EPersonaStateLookingToTrade = 5, - K_EPersonaStateLookingToPlay = 6, - K_EPersonaStateInvisible = 7, - K_EPersonaStateMax = 8, -}; -Q_ENUM_NS(EPersonaState) - -enum class EFriendFlags { - K_EFriendFlagNone = 0, - K_EFriendFlagBlocked = 1, - K_EFriendFlagFriendshipRequested = 2, - K_EFriendFlagImmediate = 4, - K_EFriendFlagClanMember = 8, - K_EFriendFlagOnGameServer = 16, - K_EFriendFlagRequestingFriendship = 128, - K_EFriendFlagRequestingInfo = 256, - K_EFriendFlagIgnored = 512, - K_EFriendFlagIgnoredFriend = 1024, - K_EFriendFlagChatMember = 4096, - K_EFriendFlagAll = 65535, -}; -Q_ENUM_NS(EFriendFlags) - -enum class EUserRestriction { - K_nUserRestrictionNone = 0, - K_nUserRestrictionUnknown = 1, - K_nUserRestrictionAnyChat = 2, - K_nUserRestrictionVoiceChat = 4, - K_nUserRestrictionGroupChat = 8, - K_nUserRestrictionRating = 16, - K_nUserRestrictionGameInvites = 32, - K_nUserRestrictionTrading = 64, -}; -Q_ENUM_NS(EUserRestriction) - -enum class EOverlayToStoreFlag { - K_EOverlayToStoreFlag_None = 0, - K_EOverlayToStoreFlag_AddToCart = 1, - K_EOverlayToStoreFlag_AddToCartAndShow = 2, -}; -Q_ENUM_NS(EOverlayToStoreFlag) - -enum class EActivateGameOverlayToWebPageMode { - K_EActivateGameOverlayToWebPageMode_Default = 0, - K_EActivateGameOverlayToWebPageMode_Modal = 1, -}; -Q_ENUM_NS(EActivateGameOverlayToWebPageMode) - -enum class ECommunityProfileItemType { - K_ECommunityProfileItemType_AnimatedAvatar = 0, - K_ECommunityProfileItemType_AvatarFrame = 1, - K_ECommunityProfileItemType_ProfileModifier = 2, - K_ECommunityProfileItemType_ProfileBackground = 3, - K_ECommunityProfileItemType_MiniProfileBackground = 4, -}; -Q_ENUM_NS(ECommunityProfileItemType) - -enum class ECommunityProfileItemProperty { - K_ECommunityProfileItemProperty_ImageSmall = 0, - K_ECommunityProfileItemProperty_ImageLarge = 1, - K_ECommunityProfileItemProperty_InternalName = 2, - K_ECommunityProfileItemProperty_Title = 3, - K_ECommunityProfileItemProperty_Description = 4, - K_ECommunityProfileItemProperty_AppID = 5, - K_ECommunityProfileItemProperty_TypeID = 6, - K_ECommunityProfileItemProperty_Class = 7, - K_ECommunityProfileItemProperty_MovieWebM = 8, - K_ECommunityProfileItemProperty_MovieMP4 = 9, - K_ECommunityProfileItemProperty_MovieWebMSmall = 10, - K_ECommunityProfileItemProperty_MovieMP4Small = 11, -}; -Q_ENUM_NS(ECommunityProfileItemProperty) - -enum class EPersonaChange { - K_EPersonaChangeName = 1, - K_EPersonaChangeStatus = 2, - K_EPersonaChangeComeOnline = 4, - K_EPersonaChangeGoneOffline = 8, - K_EPersonaChangeGamePlayed = 16, - K_EPersonaChangeGameServer = 32, - K_EPersonaChangeAvatar = 64, - K_EPersonaChangeJoinedSource = 128, - K_EPersonaChangeLeftSource = 256, - K_EPersonaChangeRelationshipChanged = 512, - K_EPersonaChangeNameFirstSet = 1024, - K_EPersonaChangeBroadcast = 2048, - K_EPersonaChangeNickname = 4096, - K_EPersonaChangeSteamLevel = 8192, - K_EPersonaChangeRichPresence = 16384, -}; -Q_ENUM_NS(EPersonaChange) - -enum class ESteamAPICallFailure { - K_ESteamAPICallFailureNone = -1, - K_ESteamAPICallFailureSteamGone = 0, - K_ESteamAPICallFailureNetworkFailure = 1, - K_ESteamAPICallFailureInvalidHandle = 2, - K_ESteamAPICallFailureMismatchedCallback = 3, -}; -Q_ENUM_NS(ESteamAPICallFailure) - -enum class EGamepadTextInputMode { - K_EGamepadTextInputModeNormal = 0, - K_EGamepadTextInputModePassword = 1, -}; -Q_ENUM_NS(EGamepadTextInputMode) - -enum class EGamepadTextInputLineMode { - K_EGamepadTextInputLineModeSingleLine = 0, - K_EGamepadTextInputLineModeMultipleLines = 1, -}; -Q_ENUM_NS(EGamepadTextInputLineMode) - -enum class EFloatingGamepadTextInputMode { - K_EFloatingGamepadTextInputModeModeSingleLine = 0, - K_EFloatingGamepadTextInputModeModeMultipleLines = 1, - K_EFloatingGamepadTextInputModeModeEmail = 2, - K_EFloatingGamepadTextInputModeModeNumeric = 3, -}; -Q_ENUM_NS(EFloatingGamepadTextInputMode) - -enum class ETextFilteringContext { - K_ETextFilteringContextUnknown = 0, - K_ETextFilteringContextGameContent = 1, - K_ETextFilteringContextChat = 2, - K_ETextFilteringContextName = 3, -}; -Q_ENUM_NS(ETextFilteringContext) - -enum class ECheckFileSignature { - K_ECheckFileSignatureInvalidSignature = 0, - K_ECheckFileSignatureValidSignature = 1, - K_ECheckFileSignatureFileNotFound = 2, - K_ECheckFileSignatureNoSignaturesFoundForThisApp = 3, - K_ECheckFileSignatureNoSignaturesFoundForThisFile = 4, -}; -Q_ENUM_NS(ECheckFileSignature) - -enum class EMatchMakingServerResponse { - EServerResponded = 0, - EServerFailedToRespond = 1, - ENoServersListedOnMasterServer = 2, -}; -Q_ENUM_NS(EMatchMakingServerResponse) - -enum class ELobbyType { - K_ELobbyTypePrivate = 0, - K_ELobbyTypeFriendsOnly = 1, - K_ELobbyTypePublic = 2, - K_ELobbyTypeInvisible = 3, - K_ELobbyTypePrivateUnique = 4, -}; -Q_ENUM_NS(ELobbyType) - -enum class ELobbyComparison { - K_ELobbyComparisonEqualToOrLessThan = -2, - K_ELobbyComparisonLessThan = -1, - K_ELobbyComparisonEqual = 0, - K_ELobbyComparisonGreaterThan = 1, - K_ELobbyComparisonEqualToOrGreaterThan = 2, - K_ELobbyComparisonNotEqual = 3, -}; -Q_ENUM_NS(ELobbyComparison) - -enum class ELobbyDistanceFilter { - K_ELobbyDistanceFilterClose = 0, - K_ELobbyDistanceFilterDefault = 1, - K_ELobbyDistanceFilterFar = 2, - K_ELobbyDistanceFilterWorldwide = 3, -}; -Q_ENUM_NS(ELobbyDistanceFilter) - -enum class EChatMemberStateChange { - K_EChatMemberStateChangeEntered = 1, - K_EChatMemberStateChangeLeft = 2, - K_EChatMemberStateChangeDisconnected = 4, - K_EChatMemberStateChangeKicked = 8, - K_EChatMemberStateChangeBanned = 16, -}; -Q_ENUM_NS(EChatMemberStateChange) - -enum class ESteamPartyBeaconLocationType { - K_ESteamPartyBeaconLocationType_Invalid = 0, - K_ESteamPartyBeaconLocationType_ChatGroup = 1, - K_ESteamPartyBeaconLocationType_Max = 2, -}; -Q_ENUM_NS(ESteamPartyBeaconLocationType) - -enum class ESteamPartyBeaconLocationData { - K_ESteamPartyBeaconLocationDataInvalid = 0, - K_ESteamPartyBeaconLocationDataName = 1, - K_ESteamPartyBeaconLocationDataIconURLSmall = 2, - K_ESteamPartyBeaconLocationDataIconURLMedium = 3, - K_ESteamPartyBeaconLocationDataIconURLLarge = 4, -}; -Q_ENUM_NS(ESteamPartyBeaconLocationData) - -enum class ERemoteStoragePlatform { - K_ERemoteStoragePlatformNone = 0, - K_ERemoteStoragePlatformWindows = 1, - K_ERemoteStoragePlatformOSX = 2, - K_ERemoteStoragePlatformPS3 = 4, - K_ERemoteStoragePlatformLinux = 8, - K_ERemoteStoragePlatformSwitch = 16, - K_ERemoteStoragePlatformAndroid = 32, - K_ERemoteStoragePlatformIOS = 64, - K_ERemoteStoragePlatformAll = -1, -}; -Q_ENUM_NS(ERemoteStoragePlatform) - -enum class ERemoteStoragePublishedFileVisibility { - K_ERemoteStoragePublishedFileVisibilityPublic = 0, - K_ERemoteStoragePublishedFileVisibilityFriendsOnly = 1, - K_ERemoteStoragePublishedFileVisibilityPrivate = 2, - K_ERemoteStoragePublishedFileVisibilityUnlisted = 3, -}; -Q_ENUM_NS(ERemoteStoragePublishedFileVisibility) - -enum class EWorkshopFileType { - K_EWorkshopFileTypeFirst = 0, - K_EWorkshopFileTypeCommunity = 0, - K_EWorkshopFileTypeMicrotransaction = 1, - K_EWorkshopFileTypeCollection = 2, - K_EWorkshopFileTypeArt = 3, - K_EWorkshopFileTypeVideo = 4, - K_EWorkshopFileTypeScreenshot = 5, - K_EWorkshopFileTypeGame = 6, - K_EWorkshopFileTypeSoftware = 7, - K_EWorkshopFileTypeConcept = 8, - K_EWorkshopFileTypeWebGuide = 9, - K_EWorkshopFileTypeIntegratedGuide = 10, - K_EWorkshopFileTypeMerch = 11, - K_EWorkshopFileTypeControllerBinding = 12, - K_EWorkshopFileTypeSteamworksAccessInvite = 13, - K_EWorkshopFileTypeSteamVideo = 14, - K_EWorkshopFileTypeGameManagedItem = 15, - K_EWorkshopFileTypeMax = 16, -}; -Q_ENUM_NS(EWorkshopFileType) - -enum class EWorkshopVote { - K_EWorkshopVoteUnvoted = 0, - K_EWorkshopVoteFor = 1, - K_EWorkshopVoteAgainst = 2, - K_EWorkshopVoteLater = 3, -}; -Q_ENUM_NS(EWorkshopVote) - -enum class EWorkshopFileAction { - K_EWorkshopFileActionPlayed = 0, - K_EWorkshopFileActionCompleted = 1, -}; -Q_ENUM_NS(EWorkshopFileAction) - -enum class EWorkshopEnumerationType { - K_EWorkshopEnumerationTypeRankedByVote = 0, - K_EWorkshopEnumerationTypeRecent = 1, - K_EWorkshopEnumerationTypeTrending = 2, - K_EWorkshopEnumerationTypeFavoritesOfFriends = 3, - K_EWorkshopEnumerationTypeVotedByFriends = 4, - K_EWorkshopEnumerationTypeContentByFriends = 5, - K_EWorkshopEnumerationTypeRecentFromFollowedUsers = 6, -}; -Q_ENUM_NS(EWorkshopEnumerationType) - -enum class EWorkshopVideoProvider { - K_EWorkshopVideoProviderNone = 0, - K_EWorkshopVideoProviderYoutube = 1, -}; -Q_ENUM_NS(EWorkshopVideoProvider) - -enum class EUGCReadAction { - K_EUGCRead_ContinueReadingUntilFinished = 0, - K_EUGCRead_ContinueReading = 1, - K_EUGCRead_Close = 2, -}; -Q_ENUM_NS(EUGCReadAction) - -enum class ERemoteStorageLocalFileChange { - K_ERemoteStorageLocalFileChange_Invalid = 0, - K_ERemoteStorageLocalFileChange_FileUpdated = 1, - K_ERemoteStorageLocalFileChange_FileDeleted = 2, -}; -Q_ENUM_NS(ERemoteStorageLocalFileChange) - -enum class ERemoteStorageFilePathType { - K_ERemoteStorageFilePathType_Invalid = 0, - K_ERemoteStorageFilePathType_Absolute = 1, - K_ERemoteStorageFilePathType_APIFilename = 2, -}; -Q_ENUM_NS(ERemoteStorageFilePathType) - -enum class ELeaderboardDataRequest { - K_ELeaderboardDataRequestGlobal = 0, - K_ELeaderboardDataRequestGlobalAroundUser = 1, - K_ELeaderboardDataRequestFriends = 2, - K_ELeaderboardDataRequestUsers = 3, -}; -Q_ENUM_NS(ELeaderboardDataRequest) - -enum class ELeaderboardSortMethod { - K_ELeaderboardSortMethodNone = 0, - K_ELeaderboardSortMethodAscending = 1, - K_ELeaderboardSortMethodDescending = 2, -}; -Q_ENUM_NS(ELeaderboardSortMethod) - -enum class ELeaderboardDisplayType { - K_ELeaderboardDisplayTypeNone = 0, - K_ELeaderboardDisplayTypeNumeric = 1, - K_ELeaderboardDisplayTypeTimeSeconds = 2, - K_ELeaderboardDisplayTypeTimeMilliSeconds = 3, -}; -Q_ENUM_NS(ELeaderboardDisplayType) - -enum class ELeaderboardUploadScoreMethod { - K_ELeaderboardUploadScoreMethodNone = 0, - K_ELeaderboardUploadScoreMethodKeepBest = 1, - K_ELeaderboardUploadScoreMethodForceUpdate = 2, -}; -Q_ENUM_NS(ELeaderboardUploadScoreMethod) - -enum class EP2PSessionError { - K_EP2PSessionErrorNone = 0, - K_EP2PSessionErrorNoRightsToApp = 2, - K_EP2PSessionErrorTimeout = 4, - K_EP2PSessionErrorNotRunningApp_DELETED = 1, - K_EP2PSessionErrorDestinationNotLoggedIn_DELETED = 3, - K_EP2PSessionErrorMax = 5, -}; -Q_ENUM_NS(EP2PSessionError) - -enum class EP2PSend { - K_EP2PSendUnreliable = 0, - K_EP2PSendUnreliableNoDelay = 1, - K_EP2PSendReliable = 2, - K_EP2PSendReliableWithBuffering = 3, -}; -Q_ENUM_NS(EP2PSend) - -enum class ESNetSocketState { - K_ESNetSocketStateInvalid = 0, - K_ESNetSocketStateConnected = 1, - K_ESNetSocketStateInitiated = 10, - K_ESNetSocketStateLocalCandidatesFound = 11, - K_ESNetSocketStateReceivedRemoteCandidates = 12, - K_ESNetSocketStateChallengeHandshake = 15, - K_ESNetSocketStateDisconnecting = 21, - K_ESNetSocketStateLocalDisconnect = 22, - K_ESNetSocketStateTimeoutDuringConnect = 23, - K_ESNetSocketStateRemoteEndDisconnected = 24, - K_ESNetSocketStateConnectionBroken = 25, -}; -Q_ENUM_NS(ESNetSocketState) - -enum class ESNetSocketConnectionType { - K_ESNetSocketConnectionTypeNotConnected = 0, - K_ESNetSocketConnectionTypeUDP = 1, - K_ESNetSocketConnectionTypeUDPRelay = 2, -}; -Q_ENUM_NS(ESNetSocketConnectionType) - -enum class EVRScreenshotType { - K_EVRScreenshotType_None = 0, - K_EVRScreenshotType_Mono = 1, - K_EVRScreenshotType_Stereo = 2, - K_EVRScreenshotType_MonoCubemap = 3, - K_EVRScreenshotType_MonoPanorama = 4, - K_EVRScreenshotType_StereoPanorama = 5, -}; -Q_ENUM_NS(EVRScreenshotType) - -enum class AudioPlayback_Status { - AudioPlayback_Undefined = 0, - AudioPlayback_Playing = 1, - AudioPlayback_Paused = 2, - AudioPlayback_Idle = 3, -}; -Q_ENUM_NS(AudioPlayback_Status) - -enum class EHTTPMethod { - K_EHTTPMethodInvalid = 0, - K_EHTTPMethodGET = 1, - K_EHTTPMethodHEAD = 2, - K_EHTTPMethodPOST = 3, - K_EHTTPMethodPUT = 4, - K_EHTTPMethodDELETE = 5, - K_EHTTPMethodOPTIONS = 6, - K_EHTTPMethodPATCH = 7, -}; -Q_ENUM_NS(EHTTPMethod) - -enum class EHTTPStatusCode { - K_EHTTPStatusCodeInvalid = 0, - K_EHTTPStatusCode100Continue = 100, - K_EHTTPStatusCode101SwitchingProtocols = 101, - K_EHTTPStatusCode200OK = 200, - K_EHTTPStatusCode201Created = 201, - K_EHTTPStatusCode202Accepted = 202, - K_EHTTPStatusCode203NonAuthoritative = 203, - K_EHTTPStatusCode204NoContent = 204, - K_EHTTPStatusCode205ResetContent = 205, - K_EHTTPStatusCode206PartialContent = 206, - K_EHTTPStatusCode300MultipleChoices = 300, - K_EHTTPStatusCode301MovedPermanently = 301, - K_EHTTPStatusCode302Found = 302, - K_EHTTPStatusCode303SeeOther = 303, - K_EHTTPStatusCode304NotModified = 304, - K_EHTTPStatusCode305UseProxy = 305, - K_EHTTPStatusCode307TemporaryRedirect = 307, - K_EHTTPStatusCode308PermanentRedirect = 308, - K_EHTTPStatusCode400BadRequest = 400, - K_EHTTPStatusCode401Unauthorized = 401, - K_EHTTPStatusCode402PaymentRequired = 402, - K_EHTTPStatusCode403Forbidden = 403, - K_EHTTPStatusCode404NotFound = 404, - K_EHTTPStatusCode405MethodNotAllowed = 405, - K_EHTTPStatusCode406NotAcceptable = 406, - K_EHTTPStatusCode407ProxyAuthRequired = 407, - K_EHTTPStatusCode408RequestTimeout = 408, - K_EHTTPStatusCode409Conflict = 409, - K_EHTTPStatusCode410Gone = 410, - K_EHTTPStatusCode411LengthRequired = 411, - K_EHTTPStatusCode412PreconditionFailed = 412, - K_EHTTPStatusCode413RequestEntityTooLarge = 413, - K_EHTTPStatusCode414RequestURITooLong = 414, - K_EHTTPStatusCode415UnsupportedMediaType = 415, - K_EHTTPStatusCode416RequestedRangeNotSatisfiable = 416, - K_EHTTPStatusCode417ExpectationFailed = 417, - K_EHTTPStatusCode4xxUnknown = 418, - K_EHTTPStatusCode429TooManyRequests = 429, - K_EHTTPStatusCode444ConnectionClosed = 444, - K_EHTTPStatusCode500InternalServerError = 500, - K_EHTTPStatusCode501NotImplemented = 501, - K_EHTTPStatusCode502BadGateway = 502, - K_EHTTPStatusCode503ServiceUnavailable = 503, - K_EHTTPStatusCode504GatewayTimeout = 504, - K_EHTTPStatusCode505HTTPVersionNotSupported = 505, - K_EHTTPStatusCode5xxUnknown = 599, -}; -Q_ENUM_NS(EHTTPStatusCode) - -enum class EInputSourceMode { - K_EInputSourceMode_None = 0, - K_EInputSourceMode_Dpad = 1, - K_EInputSourceMode_Buttons = 2, - K_EInputSourceMode_FourButtons = 3, - K_EInputSourceMode_AbsoluteMouse = 4, - K_EInputSourceMode_RelativeMouse = 5, - K_EInputSourceMode_JoystickMove = 6, - K_EInputSourceMode_JoystickMouse = 7, - K_EInputSourceMode_JoystickCamera = 8, - K_EInputSourceMode_ScrollWheel = 9, - K_EInputSourceMode_Trigger = 10, - K_EInputSourceMode_TouchMenu = 11, - K_EInputSourceMode_MouseJoystick = 12, - K_EInputSourceMode_MouseRegion = 13, - K_EInputSourceMode_RadialMenu = 14, - K_EInputSourceMode_SingleButton = 15, - K_EInputSourceMode_Switches = 16, -}; -Q_ENUM_NS(EInputSourceMode) - -enum class EInputActionOrigin { - K_EInputActionOrigin_None = 0, - K_EInputActionOrigin_SteamController_A = 1, - K_EInputActionOrigin_SteamController_B = 2, - K_EInputActionOrigin_SteamController_X = 3, - K_EInputActionOrigin_SteamController_Y = 4, - K_EInputActionOrigin_SteamController_LeftBumper = 5, - K_EInputActionOrigin_SteamController_RightBumper = 6, - K_EInputActionOrigin_SteamController_LeftGrip = 7, - K_EInputActionOrigin_SteamController_RightGrip = 8, - K_EInputActionOrigin_SteamController_Start = 9, - K_EInputActionOrigin_SteamController_Back = 10, - K_EInputActionOrigin_SteamController_LeftPad_Touch = 11, - K_EInputActionOrigin_SteamController_LeftPad_Swipe = 12, - K_EInputActionOrigin_SteamController_LeftPad_Click = 13, - K_EInputActionOrigin_SteamController_LeftPad_DPadNorth = 14, - K_EInputActionOrigin_SteamController_LeftPad_DPadSouth = 15, - K_EInputActionOrigin_SteamController_LeftPad_DPadWest = 16, - K_EInputActionOrigin_SteamController_LeftPad_DPadEast = 17, - K_EInputActionOrigin_SteamController_RightPad_Touch = 18, - K_EInputActionOrigin_SteamController_RightPad_Swipe = 19, - K_EInputActionOrigin_SteamController_RightPad_Click = 20, - K_EInputActionOrigin_SteamController_RightPad_DPadNorth = 21, - K_EInputActionOrigin_SteamController_RightPad_DPadSouth = 22, - K_EInputActionOrigin_SteamController_RightPad_DPadWest = 23, - K_EInputActionOrigin_SteamController_RightPad_DPadEast = 24, - K_EInputActionOrigin_SteamController_LeftTrigger_Pull = 25, - K_EInputActionOrigin_SteamController_LeftTrigger_Click = 26, - K_EInputActionOrigin_SteamController_RightTrigger_Pull = 27, - K_EInputActionOrigin_SteamController_RightTrigger_Click = 28, - K_EInputActionOrigin_SteamController_LeftStick_Move = 29, - K_EInputActionOrigin_SteamController_LeftStick_Click = 30, - K_EInputActionOrigin_SteamController_LeftStick_DPadNorth = 31, - K_EInputActionOrigin_SteamController_LeftStick_DPadSouth = 32, - K_EInputActionOrigin_SteamController_LeftStick_DPadWest = 33, - K_EInputActionOrigin_SteamController_LeftStick_DPadEast = 34, - K_EInputActionOrigin_SteamController_Gyro_Move = 35, - K_EInputActionOrigin_SteamController_Gyro_Pitch = 36, - K_EInputActionOrigin_SteamController_Gyro_Yaw = 37, - K_EInputActionOrigin_SteamController_Gyro_Roll = 38, - K_EInputActionOrigin_SteamController_Reserved0 = 39, - K_EInputActionOrigin_SteamController_Reserved1 = 40, - K_EInputActionOrigin_SteamController_Reserved2 = 41, - K_EInputActionOrigin_SteamController_Reserved3 = 42, - K_EInputActionOrigin_SteamController_Reserved4 = 43, - K_EInputActionOrigin_SteamController_Reserved5 = 44, - K_EInputActionOrigin_SteamController_Reserved6 = 45, - K_EInputActionOrigin_SteamController_Reserved7 = 46, - K_EInputActionOrigin_SteamController_Reserved8 = 47, - K_EInputActionOrigin_SteamController_Reserved9 = 48, - K_EInputActionOrigin_SteamController_Reserved10 = 49, - K_EInputActionOrigin_PS4_X = 50, - K_EInputActionOrigin_PS4_Circle = 51, - K_EInputActionOrigin_PS4_Triangle = 52, - K_EInputActionOrigin_PS4_Square = 53, - K_EInputActionOrigin_PS4_LeftBumper = 54, - K_EInputActionOrigin_PS4_RightBumper = 55, - K_EInputActionOrigin_PS4_Options = 56, - K_EInputActionOrigin_PS4_Share = 57, - K_EInputActionOrigin_PS4_LeftPad_Touch = 58, - K_EInputActionOrigin_PS4_LeftPad_Swipe = 59, - K_EInputActionOrigin_PS4_LeftPad_Click = 60, - K_EInputActionOrigin_PS4_LeftPad_DPadNorth = 61, - K_EInputActionOrigin_PS4_LeftPad_DPadSouth = 62, - K_EInputActionOrigin_PS4_LeftPad_DPadWest = 63, - K_EInputActionOrigin_PS4_LeftPad_DPadEast = 64, - K_EInputActionOrigin_PS4_RightPad_Touch = 65, - K_EInputActionOrigin_PS4_RightPad_Swipe = 66, - K_EInputActionOrigin_PS4_RightPad_Click = 67, - K_EInputActionOrigin_PS4_RightPad_DPadNorth = 68, - K_EInputActionOrigin_PS4_RightPad_DPadSouth = 69, - K_EInputActionOrigin_PS4_RightPad_DPadWest = 70, - K_EInputActionOrigin_PS4_RightPad_DPadEast = 71, - K_EInputActionOrigin_PS4_CenterPad_Touch = 72, - K_EInputActionOrigin_PS4_CenterPad_Swipe = 73, - K_EInputActionOrigin_PS4_CenterPad_Click = 74, - K_EInputActionOrigin_PS4_CenterPad_DPadNorth = 75, - K_EInputActionOrigin_PS4_CenterPad_DPadSouth = 76, - K_EInputActionOrigin_PS4_CenterPad_DPadWest = 77, - K_EInputActionOrigin_PS4_CenterPad_DPadEast = 78, - K_EInputActionOrigin_PS4_LeftTrigger_Pull = 79, - K_EInputActionOrigin_PS4_LeftTrigger_Click = 80, - K_EInputActionOrigin_PS4_RightTrigger_Pull = 81, - K_EInputActionOrigin_PS4_RightTrigger_Click = 82, - K_EInputActionOrigin_PS4_LeftStick_Move = 83, - K_EInputActionOrigin_PS4_LeftStick_Click = 84, - K_EInputActionOrigin_PS4_LeftStick_DPadNorth = 85, - K_EInputActionOrigin_PS4_LeftStick_DPadSouth = 86, - K_EInputActionOrigin_PS4_LeftStick_DPadWest = 87, - K_EInputActionOrigin_PS4_LeftStick_DPadEast = 88, - K_EInputActionOrigin_PS4_RightStick_Move = 89, - K_EInputActionOrigin_PS4_RightStick_Click = 90, - K_EInputActionOrigin_PS4_RightStick_DPadNorth = 91, - K_EInputActionOrigin_PS4_RightStick_DPadSouth = 92, - K_EInputActionOrigin_PS4_RightStick_DPadWest = 93, - K_EInputActionOrigin_PS4_RightStick_DPadEast = 94, - K_EInputActionOrigin_PS4_DPad_North = 95, - K_EInputActionOrigin_PS4_DPad_South = 96, - K_EInputActionOrigin_PS4_DPad_West = 97, - K_EInputActionOrigin_PS4_DPad_East = 98, - K_EInputActionOrigin_PS4_Gyro_Move = 99, - K_EInputActionOrigin_PS4_Gyro_Pitch = 100, - K_EInputActionOrigin_PS4_Gyro_Yaw = 101, - K_EInputActionOrigin_PS4_Gyro_Roll = 102, - K_EInputActionOrigin_PS4_DPad_Move = 103, - K_EInputActionOrigin_PS4_Reserved1 = 104, - K_EInputActionOrigin_PS4_Reserved2 = 105, - K_EInputActionOrigin_PS4_Reserved3 = 106, - K_EInputActionOrigin_PS4_Reserved4 = 107, - K_EInputActionOrigin_PS4_Reserved5 = 108, - K_EInputActionOrigin_PS4_Reserved6 = 109, - K_EInputActionOrigin_PS4_Reserved7 = 110, - K_EInputActionOrigin_PS4_Reserved8 = 111, - K_EInputActionOrigin_PS4_Reserved9 = 112, - K_EInputActionOrigin_PS4_Reserved10 = 113, - K_EInputActionOrigin_XBoxOne_A = 114, - K_EInputActionOrigin_XBoxOne_B = 115, - K_EInputActionOrigin_XBoxOne_X = 116, - K_EInputActionOrigin_XBoxOne_Y = 117, - K_EInputActionOrigin_XBoxOne_LeftBumper = 118, - K_EInputActionOrigin_XBoxOne_RightBumper = 119, - K_EInputActionOrigin_XBoxOne_Menu = 120, - K_EInputActionOrigin_XBoxOne_View = 121, - K_EInputActionOrigin_XBoxOne_LeftTrigger_Pull = 122, - K_EInputActionOrigin_XBoxOne_LeftTrigger_Click = 123, - K_EInputActionOrigin_XBoxOne_RightTrigger_Pull = 124, - K_EInputActionOrigin_XBoxOne_RightTrigger_Click = 125, - K_EInputActionOrigin_XBoxOne_LeftStick_Move = 126, - K_EInputActionOrigin_XBoxOne_LeftStick_Click = 127, - K_EInputActionOrigin_XBoxOne_LeftStick_DPadNorth = 128, - K_EInputActionOrigin_XBoxOne_LeftStick_DPadSouth = 129, - K_EInputActionOrigin_XBoxOne_LeftStick_DPadWest = 130, - K_EInputActionOrigin_XBoxOne_LeftStick_DPadEast = 131, - K_EInputActionOrigin_XBoxOne_RightStick_Move = 132, - K_EInputActionOrigin_XBoxOne_RightStick_Click = 133, - K_EInputActionOrigin_XBoxOne_RightStick_DPadNorth = 134, - K_EInputActionOrigin_XBoxOne_RightStick_DPadSouth = 135, - K_EInputActionOrigin_XBoxOne_RightStick_DPadWest = 136, - K_EInputActionOrigin_XBoxOne_RightStick_DPadEast = 137, - K_EInputActionOrigin_XBoxOne_DPad_North = 138, - K_EInputActionOrigin_XBoxOne_DPad_South = 139, - K_EInputActionOrigin_XBoxOne_DPad_West = 140, - K_EInputActionOrigin_XBoxOne_DPad_East = 141, - K_EInputActionOrigin_XBoxOne_DPad_Move = 142, - K_EInputActionOrigin_XBoxOne_LeftGrip_Lower = 143, - K_EInputActionOrigin_XBoxOne_LeftGrip_Upper = 144, - K_EInputActionOrigin_XBoxOne_RightGrip_Lower = 145, - K_EInputActionOrigin_XBoxOne_RightGrip_Upper = 146, - K_EInputActionOrigin_XBoxOne_Share = 147, - K_EInputActionOrigin_XBoxOne_Reserved6 = 148, - K_EInputActionOrigin_XBoxOne_Reserved7 = 149, - K_EInputActionOrigin_XBoxOne_Reserved8 = 150, - K_EInputActionOrigin_XBoxOne_Reserved9 = 151, - K_EInputActionOrigin_XBoxOne_Reserved10 = 152, - K_EInputActionOrigin_XBox360_A = 153, - K_EInputActionOrigin_XBox360_B = 154, - K_EInputActionOrigin_XBox360_X = 155, - K_EInputActionOrigin_XBox360_Y = 156, - K_EInputActionOrigin_XBox360_LeftBumper = 157, - K_EInputActionOrigin_XBox360_RightBumper = 158, - K_EInputActionOrigin_XBox360_Start = 159, - K_EInputActionOrigin_XBox360_Back = 160, - K_EInputActionOrigin_XBox360_LeftTrigger_Pull = 161, - K_EInputActionOrigin_XBox360_LeftTrigger_Click = 162, - K_EInputActionOrigin_XBox360_RightTrigger_Pull = 163, - K_EInputActionOrigin_XBox360_RightTrigger_Click = 164, - K_EInputActionOrigin_XBox360_LeftStick_Move = 165, - K_EInputActionOrigin_XBox360_LeftStick_Click = 166, - K_EInputActionOrigin_XBox360_LeftStick_DPadNorth = 167, - K_EInputActionOrigin_XBox360_LeftStick_DPadSouth = 168, - K_EInputActionOrigin_XBox360_LeftStick_DPadWest = 169, - K_EInputActionOrigin_XBox360_LeftStick_DPadEast = 170, - K_EInputActionOrigin_XBox360_RightStick_Move = 171, - K_EInputActionOrigin_XBox360_RightStick_Click = 172, - K_EInputActionOrigin_XBox360_RightStick_DPadNorth = 173, - K_EInputActionOrigin_XBox360_RightStick_DPadSouth = 174, - K_EInputActionOrigin_XBox360_RightStick_DPadWest = 175, - K_EInputActionOrigin_XBox360_RightStick_DPadEast = 176, - K_EInputActionOrigin_XBox360_DPad_North = 177, - K_EInputActionOrigin_XBox360_DPad_South = 178, - K_EInputActionOrigin_XBox360_DPad_West = 179, - K_EInputActionOrigin_XBox360_DPad_East = 180, - K_EInputActionOrigin_XBox360_DPad_Move = 181, - K_EInputActionOrigin_XBox360_Reserved1 = 182, - K_EInputActionOrigin_XBox360_Reserved2 = 183, - K_EInputActionOrigin_XBox360_Reserved3 = 184, - K_EInputActionOrigin_XBox360_Reserved4 = 185, - K_EInputActionOrigin_XBox360_Reserved5 = 186, - K_EInputActionOrigin_XBox360_Reserved6 = 187, - K_EInputActionOrigin_XBox360_Reserved7 = 188, - K_EInputActionOrigin_XBox360_Reserved8 = 189, - K_EInputActionOrigin_XBox360_Reserved9 = 190, - K_EInputActionOrigin_XBox360_Reserved10 = 191, - K_EInputActionOrigin_Switch_A = 192, - K_EInputActionOrigin_Switch_B = 193, - K_EInputActionOrigin_Switch_X = 194, - K_EInputActionOrigin_Switch_Y = 195, - K_EInputActionOrigin_Switch_LeftBumper = 196, - K_EInputActionOrigin_Switch_RightBumper = 197, - K_EInputActionOrigin_Switch_Plus = 198, - K_EInputActionOrigin_Switch_Minus = 199, - K_EInputActionOrigin_Switch_Capture = 200, - K_EInputActionOrigin_Switch_LeftTrigger_Pull = 201, - K_EInputActionOrigin_Switch_LeftTrigger_Click = 202, - K_EInputActionOrigin_Switch_RightTrigger_Pull = 203, - K_EInputActionOrigin_Switch_RightTrigger_Click = 204, - K_EInputActionOrigin_Switch_LeftStick_Move = 205, - K_EInputActionOrigin_Switch_LeftStick_Click = 206, - K_EInputActionOrigin_Switch_LeftStick_DPadNorth = 207, - K_EInputActionOrigin_Switch_LeftStick_DPadSouth = 208, - K_EInputActionOrigin_Switch_LeftStick_DPadWest = 209, - K_EInputActionOrigin_Switch_LeftStick_DPadEast = 210, - K_EInputActionOrigin_Switch_RightStick_Move = 211, - K_EInputActionOrigin_Switch_RightStick_Click = 212, - K_EInputActionOrigin_Switch_RightStick_DPadNorth = 213, - K_EInputActionOrigin_Switch_RightStick_DPadSouth = 214, - K_EInputActionOrigin_Switch_RightStick_DPadWest = 215, - K_EInputActionOrigin_Switch_RightStick_DPadEast = 216, - K_EInputActionOrigin_Switch_DPad_North = 217, - K_EInputActionOrigin_Switch_DPad_South = 218, - K_EInputActionOrigin_Switch_DPad_West = 219, - K_EInputActionOrigin_Switch_DPad_East = 220, - K_EInputActionOrigin_Switch_ProGyro_Move = 221, - K_EInputActionOrigin_Switch_ProGyro_Pitch = 222, - K_EInputActionOrigin_Switch_ProGyro_Yaw = 223, - K_EInputActionOrigin_Switch_ProGyro_Roll = 224, - K_EInputActionOrigin_Switch_DPad_Move = 225, - K_EInputActionOrigin_Switch_Reserved1 = 226, - K_EInputActionOrigin_Switch_Reserved2 = 227, - K_EInputActionOrigin_Switch_Reserved3 = 228, - K_EInputActionOrigin_Switch_Reserved4 = 229, - K_EInputActionOrigin_Switch_Reserved5 = 230, - K_EInputActionOrigin_Switch_Reserved6 = 231, - K_EInputActionOrigin_Switch_Reserved7 = 232, - K_EInputActionOrigin_Switch_Reserved8 = 233, - K_EInputActionOrigin_Switch_Reserved9 = 234, - K_EInputActionOrigin_Switch_Reserved10 = 235, - K_EInputActionOrigin_Switch_RightGyro_Move = 236, - K_EInputActionOrigin_Switch_RightGyro_Pitch = 237, - K_EInputActionOrigin_Switch_RightGyro_Yaw = 238, - K_EInputActionOrigin_Switch_RightGyro_Roll = 239, - K_EInputActionOrigin_Switch_LeftGyro_Move = 240, - K_EInputActionOrigin_Switch_LeftGyro_Pitch = 241, - K_EInputActionOrigin_Switch_LeftGyro_Yaw = 242, - K_EInputActionOrigin_Switch_LeftGyro_Roll = 243, - K_EInputActionOrigin_Switch_LeftGrip_Lower = 244, - K_EInputActionOrigin_Switch_LeftGrip_Upper = 245, - K_EInputActionOrigin_Switch_RightGrip_Lower = 246, - K_EInputActionOrigin_Switch_RightGrip_Upper = 247, - K_EInputActionOrigin_Switch_JoyConButton_N = 248, - K_EInputActionOrigin_Switch_JoyConButton_E = 249, - K_EInputActionOrigin_Switch_JoyConButton_S = 250, - K_EInputActionOrigin_Switch_JoyConButton_W = 251, - K_EInputActionOrigin_Switch_Reserved15 = 252, - K_EInputActionOrigin_Switch_Reserved16 = 253, - K_EInputActionOrigin_Switch_Reserved17 = 254, - K_EInputActionOrigin_Switch_Reserved18 = 255, - K_EInputActionOrigin_Switch_Reserved19 = 256, - K_EInputActionOrigin_Switch_Reserved20 = 257, - K_EInputActionOrigin_PS5_X = 258, - K_EInputActionOrigin_PS5_Circle = 259, - K_EInputActionOrigin_PS5_Triangle = 260, - K_EInputActionOrigin_PS5_Square = 261, - K_EInputActionOrigin_PS5_LeftBumper = 262, - K_EInputActionOrigin_PS5_RightBumper = 263, - K_EInputActionOrigin_PS5_Option = 264, - K_EInputActionOrigin_PS5_Create = 265, - K_EInputActionOrigin_PS5_Mute = 266, - K_EInputActionOrigin_PS5_LeftPad_Touch = 267, - K_EInputActionOrigin_PS5_LeftPad_Swipe = 268, - K_EInputActionOrigin_PS5_LeftPad_Click = 269, - K_EInputActionOrigin_PS5_LeftPad_DPadNorth = 270, - K_EInputActionOrigin_PS5_LeftPad_DPadSouth = 271, - K_EInputActionOrigin_PS5_LeftPad_DPadWest = 272, - K_EInputActionOrigin_PS5_LeftPad_DPadEast = 273, - K_EInputActionOrigin_PS5_RightPad_Touch = 274, - K_EInputActionOrigin_PS5_RightPad_Swipe = 275, - K_EInputActionOrigin_PS5_RightPad_Click = 276, - K_EInputActionOrigin_PS5_RightPad_DPadNorth = 277, - K_EInputActionOrigin_PS5_RightPad_DPadSouth = 278, - K_EInputActionOrigin_PS5_RightPad_DPadWest = 279, - K_EInputActionOrigin_PS5_RightPad_DPadEast = 280, - K_EInputActionOrigin_PS5_CenterPad_Touch = 281, - K_EInputActionOrigin_PS5_CenterPad_Swipe = 282, - K_EInputActionOrigin_PS5_CenterPad_Click = 283, - K_EInputActionOrigin_PS5_CenterPad_DPadNorth = 284, - K_EInputActionOrigin_PS5_CenterPad_DPadSouth = 285, - K_EInputActionOrigin_PS5_CenterPad_DPadWest = 286, - K_EInputActionOrigin_PS5_CenterPad_DPadEast = 287, - K_EInputActionOrigin_PS5_LeftTrigger_Pull = 288, - K_EInputActionOrigin_PS5_LeftTrigger_Click = 289, - K_EInputActionOrigin_PS5_RightTrigger_Pull = 290, - K_EInputActionOrigin_PS5_RightTrigger_Click = 291, - K_EInputActionOrigin_PS5_LeftStick_Move = 292, - K_EInputActionOrigin_PS5_LeftStick_Click = 293, - K_EInputActionOrigin_PS5_LeftStick_DPadNorth = 294, - K_EInputActionOrigin_PS5_LeftStick_DPadSouth = 295, - K_EInputActionOrigin_PS5_LeftStick_DPadWest = 296, - K_EInputActionOrigin_PS5_LeftStick_DPadEast = 297, - K_EInputActionOrigin_PS5_RightStick_Move = 298, - K_EInputActionOrigin_PS5_RightStick_Click = 299, - K_EInputActionOrigin_PS5_RightStick_DPadNorth = 300, - K_EInputActionOrigin_PS5_RightStick_DPadSouth = 301, - K_EInputActionOrigin_PS5_RightStick_DPadWest = 302, - K_EInputActionOrigin_PS5_RightStick_DPadEast = 303, - K_EInputActionOrigin_PS5_DPad_North = 304, - K_EInputActionOrigin_PS5_DPad_South = 305, - K_EInputActionOrigin_PS5_DPad_West = 306, - K_EInputActionOrigin_PS5_DPad_East = 307, - K_EInputActionOrigin_PS5_Gyro_Move = 308, - K_EInputActionOrigin_PS5_Gyro_Pitch = 309, - K_EInputActionOrigin_PS5_Gyro_Yaw = 310, - K_EInputActionOrigin_PS5_Gyro_Roll = 311, - K_EInputActionOrigin_PS5_DPad_Move = 312, - K_EInputActionOrigin_PS5_LeftGrip = 313, - K_EInputActionOrigin_PS5_RightGrip = 314, - K_EInputActionOrigin_PS5_LeftFn = 315, - K_EInputActionOrigin_PS5_RightFn = 316, - K_EInputActionOrigin_PS5_Reserved5 = 317, - K_EInputActionOrigin_PS5_Reserved6 = 318, - K_EInputActionOrigin_PS5_Reserved7 = 319, - K_EInputActionOrigin_PS5_Reserved8 = 320, - K_EInputActionOrigin_PS5_Reserved9 = 321, - K_EInputActionOrigin_PS5_Reserved10 = 322, - K_EInputActionOrigin_PS5_Reserved11 = 323, - K_EInputActionOrigin_PS5_Reserved12 = 324, - K_EInputActionOrigin_PS5_Reserved13 = 325, - K_EInputActionOrigin_PS5_Reserved14 = 326, - K_EInputActionOrigin_PS5_Reserved15 = 327, - K_EInputActionOrigin_PS5_Reserved16 = 328, - K_EInputActionOrigin_PS5_Reserved17 = 329, - K_EInputActionOrigin_PS5_Reserved18 = 330, - K_EInputActionOrigin_PS5_Reserved19 = 331, - K_EInputActionOrigin_PS5_Reserved20 = 332, - K_EInputActionOrigin_SteamDeck_A = 333, - K_EInputActionOrigin_SteamDeck_B = 334, - K_EInputActionOrigin_SteamDeck_X = 335, - K_EInputActionOrigin_SteamDeck_Y = 336, - K_EInputActionOrigin_SteamDeck_L1 = 337, - K_EInputActionOrigin_SteamDeck_R1 = 338, - K_EInputActionOrigin_SteamDeck_Menu = 339, - K_EInputActionOrigin_SteamDeck_View = 340, - K_EInputActionOrigin_SteamDeck_LeftPad_Touch = 341, - K_EInputActionOrigin_SteamDeck_LeftPad_Swipe = 342, - K_EInputActionOrigin_SteamDeck_LeftPad_Click = 343, - K_EInputActionOrigin_SteamDeck_LeftPad_DPadNorth = 344, - K_EInputActionOrigin_SteamDeck_LeftPad_DPadSouth = 345, - K_EInputActionOrigin_SteamDeck_LeftPad_DPadWest = 346, - K_EInputActionOrigin_SteamDeck_LeftPad_DPadEast = 347, - K_EInputActionOrigin_SteamDeck_RightPad_Touch = 348, - K_EInputActionOrigin_SteamDeck_RightPad_Swipe = 349, - K_EInputActionOrigin_SteamDeck_RightPad_Click = 350, - K_EInputActionOrigin_SteamDeck_RightPad_DPadNorth = 351, - K_EInputActionOrigin_SteamDeck_RightPad_DPadSouth = 352, - K_EInputActionOrigin_SteamDeck_RightPad_DPadWest = 353, - K_EInputActionOrigin_SteamDeck_RightPad_DPadEast = 354, - K_EInputActionOrigin_SteamDeck_L2_SoftPull = 355, - K_EInputActionOrigin_SteamDeck_L2 = 356, - K_EInputActionOrigin_SteamDeck_R2_SoftPull = 357, - K_EInputActionOrigin_SteamDeck_R2 = 358, - K_EInputActionOrigin_SteamDeck_LeftStick_Move = 359, - K_EInputActionOrigin_SteamDeck_L3 = 360, - K_EInputActionOrigin_SteamDeck_LeftStick_DPadNorth = 361, - K_EInputActionOrigin_SteamDeck_LeftStick_DPadSouth = 362, - K_EInputActionOrigin_SteamDeck_LeftStick_DPadWest = 363, - K_EInputActionOrigin_SteamDeck_LeftStick_DPadEast = 364, - K_EInputActionOrigin_SteamDeck_LeftStick_Touch = 365, - K_EInputActionOrigin_SteamDeck_RightStick_Move = 366, - K_EInputActionOrigin_SteamDeck_R3 = 367, - K_EInputActionOrigin_SteamDeck_RightStick_DPadNorth = 368, - K_EInputActionOrigin_SteamDeck_RightStick_DPadSouth = 369, - K_EInputActionOrigin_SteamDeck_RightStick_DPadWest = 370, - K_EInputActionOrigin_SteamDeck_RightStick_DPadEast = 371, - K_EInputActionOrigin_SteamDeck_RightStick_Touch = 372, - K_EInputActionOrigin_SteamDeck_L4 = 373, - K_EInputActionOrigin_SteamDeck_R4 = 374, - K_EInputActionOrigin_SteamDeck_L5 = 375, - K_EInputActionOrigin_SteamDeck_R5 = 376, - K_EInputActionOrigin_SteamDeck_DPad_Move = 377, - K_EInputActionOrigin_SteamDeck_DPad_North = 378, - K_EInputActionOrigin_SteamDeck_DPad_South = 379, - K_EInputActionOrigin_SteamDeck_DPad_West = 380, - K_EInputActionOrigin_SteamDeck_DPad_East = 381, - K_EInputActionOrigin_SteamDeck_Gyro_Move = 382, - K_EInputActionOrigin_SteamDeck_Gyro_Pitch = 383, - K_EInputActionOrigin_SteamDeck_Gyro_Yaw = 384, - K_EInputActionOrigin_SteamDeck_Gyro_Roll = 385, - K_EInputActionOrigin_SteamDeck_Reserved1 = 386, - K_EInputActionOrigin_SteamDeck_Reserved2 = 387, - K_EInputActionOrigin_SteamDeck_Reserved3 = 388, - K_EInputActionOrigin_SteamDeck_Reserved4 = 389, - K_EInputActionOrigin_SteamDeck_Reserved5 = 390, - K_EInputActionOrigin_SteamDeck_Reserved6 = 391, - K_EInputActionOrigin_SteamDeck_Reserved7 = 392, - K_EInputActionOrigin_SteamDeck_Reserved8 = 393, - K_EInputActionOrigin_SteamDeck_Reserved9 = 394, - K_EInputActionOrigin_SteamDeck_Reserved10 = 395, - K_EInputActionOrigin_SteamDeck_Reserved11 = 396, - K_EInputActionOrigin_SteamDeck_Reserved12 = 397, - K_EInputActionOrigin_SteamDeck_Reserved13 = 398, - K_EInputActionOrigin_SteamDeck_Reserved14 = 399, - K_EInputActionOrigin_SteamDeck_Reserved15 = 400, - K_EInputActionOrigin_SteamDeck_Reserved16 = 401, - K_EInputActionOrigin_SteamDeck_Reserved17 = 402, - K_EInputActionOrigin_SteamDeck_Reserved18 = 403, - K_EInputActionOrigin_SteamDeck_Reserved19 = 404, - K_EInputActionOrigin_SteamDeck_Reserved20 = 405, - K_EInputActionOrigin_Count = 406, - K_EInputActionOrigin_MaximumPossibleValue = 32767, -}; -Q_ENUM_NS(EInputActionOrigin) - -enum class EXboxOrigin { - K_EXboxOrigin_A = 0, - K_EXboxOrigin_B = 1, - K_EXboxOrigin_X = 2, - K_EXboxOrigin_Y = 3, - K_EXboxOrigin_LeftBumper = 4, - K_EXboxOrigin_RightBumper = 5, - K_EXboxOrigin_Menu = 6, - K_EXboxOrigin_View = 7, - K_EXboxOrigin_LeftTrigger_Pull = 8, - K_EXboxOrigin_LeftTrigger_Click = 9, - K_EXboxOrigin_RightTrigger_Pull = 10, - K_EXboxOrigin_RightTrigger_Click = 11, - K_EXboxOrigin_LeftStick_Move = 12, - K_EXboxOrigin_LeftStick_Click = 13, - K_EXboxOrigin_LeftStick_DPadNorth = 14, - K_EXboxOrigin_LeftStick_DPadSouth = 15, - K_EXboxOrigin_LeftStick_DPadWest = 16, - K_EXboxOrigin_LeftStick_DPadEast = 17, - K_EXboxOrigin_RightStick_Move = 18, - K_EXboxOrigin_RightStick_Click = 19, - K_EXboxOrigin_RightStick_DPadNorth = 20, - K_EXboxOrigin_RightStick_DPadSouth = 21, - K_EXboxOrigin_RightStick_DPadWest = 22, - K_EXboxOrigin_RightStick_DPadEast = 23, - K_EXboxOrigin_DPad_North = 24, - K_EXboxOrigin_DPad_South = 25, - K_EXboxOrigin_DPad_West = 26, - K_EXboxOrigin_DPad_East = 27, - K_EXboxOrigin_Count = 28, -}; -Q_ENUM_NS(EXboxOrigin) - -enum class ESteamControllerPad { - K_ESteamControllerPad_Left = 0, - K_ESteamControllerPad_Right = 1, -}; -Q_ENUM_NS(ESteamControllerPad) - -enum class EControllerHapticLocation { - K_EControllerHapticLocation_Left = 1, - K_EControllerHapticLocation_Right = 2, - K_EControllerHapticLocation_Both = 3, -}; -Q_ENUM_NS(EControllerHapticLocation) - -enum class EControllerHapticType { - K_EControllerHapticType_Off = 0, - K_EControllerHapticType_Tick = 1, - K_EControllerHapticType_Click = 2, -}; -Q_ENUM_NS(EControllerHapticType) - -enum class ESteamInputType { - K_ESteamInputType_Unknown = 0, - K_ESteamInputType_SteamController = 1, - K_ESteamInputType_XBox360Controller = 2, - K_ESteamInputType_XBoxOneController = 3, - K_ESteamInputType_GenericGamepad = 4, - K_ESteamInputType_PS4Controller = 5, - K_ESteamInputType_AppleMFiController = 6, - K_ESteamInputType_AndroidController = 7, - K_ESteamInputType_SwitchJoyConPair = 8, - K_ESteamInputType_SwitchJoyConSingle = 9, - K_ESteamInputType_SwitchProController = 10, - K_ESteamInputType_MobileTouch = 11, - K_ESteamInputType_PS3Controller = 12, - K_ESteamInputType_PS5Controller = 13, - K_ESteamInputType_SteamDeckController = 14, - K_ESteamInputType_Count = 15, - K_ESteamInputType_MaximumPossibleValue = 255, -}; -Q_ENUM_NS(ESteamInputType) - -enum class ESteamInputConfigurationEnableType { - K_ESteamInputConfigurationEnableType_None = 0, - K_ESteamInputConfigurationEnableType_Playstation = 1, - K_ESteamInputConfigurationEnableType_Xbox = 2, - K_ESteamInputConfigurationEnableType_Generic = 4, - K_ESteamInputConfigurationEnableType_Switch = 8, -}; -Q_ENUM_NS(ESteamInputConfigurationEnableType) - -enum class ESteamInputLEDFlag { - K_ESteamInputLEDFlag_SetColor = 0, - K_ESteamInputLEDFlag_RestoreUserDefault = 1, -}; -Q_ENUM_NS(ESteamInputLEDFlag) - -enum class ESteamInputGlyphSize { - K_ESteamInputGlyphSize_Small = 0, - K_ESteamInputGlyphSize_Medium = 1, - K_ESteamInputGlyphSize_Large = 2, - K_ESteamInputGlyphSize_Count = 3, -}; -Q_ENUM_NS(ESteamInputGlyphSize) - -enum class ESteamInputGlyphStyle { - ESteamInputGlyphStyle_Knockout = 0, - ESteamInputGlyphStyle_Light = 1, - ESteamInputGlyphStyle_Dark = 2, - ESteamInputGlyphStyle_NeutralColorABXY = 16, - ESteamInputGlyphStyle_SolidABXY = 32, -}; -Q_ENUM_NS(ESteamInputGlyphStyle) - -enum class ESteamInputActionEventType { - ESteamInputActionEventType_DigitalAction = 0, - ESteamInputActionEventType_AnalogAction = 1, -}; -Q_ENUM_NS(ESteamInputActionEventType) - -enum class EControllerActionOrigin { - K_EControllerActionOrigin_None = 0, - K_EControllerActionOrigin_A = 1, - K_EControllerActionOrigin_B = 2, - K_EControllerActionOrigin_X = 3, - K_EControllerActionOrigin_Y = 4, - K_EControllerActionOrigin_LeftBumper = 5, - K_EControllerActionOrigin_RightBumper = 6, - K_EControllerActionOrigin_LeftGrip = 7, - K_EControllerActionOrigin_RightGrip = 8, - K_EControllerActionOrigin_Start = 9, - K_EControllerActionOrigin_Back = 10, - K_EControllerActionOrigin_LeftPad_Touch = 11, - K_EControllerActionOrigin_LeftPad_Swipe = 12, - K_EControllerActionOrigin_LeftPad_Click = 13, - K_EControllerActionOrigin_LeftPad_DPadNorth = 14, - K_EControllerActionOrigin_LeftPad_DPadSouth = 15, - K_EControllerActionOrigin_LeftPad_DPadWest = 16, - K_EControllerActionOrigin_LeftPad_DPadEast = 17, - K_EControllerActionOrigin_RightPad_Touch = 18, - K_EControllerActionOrigin_RightPad_Swipe = 19, - K_EControllerActionOrigin_RightPad_Click = 20, - K_EControllerActionOrigin_RightPad_DPadNorth = 21, - K_EControllerActionOrigin_RightPad_DPadSouth = 22, - K_EControllerActionOrigin_RightPad_DPadWest = 23, - K_EControllerActionOrigin_RightPad_DPadEast = 24, - K_EControllerActionOrigin_LeftTrigger_Pull = 25, - K_EControllerActionOrigin_LeftTrigger_Click = 26, - K_EControllerActionOrigin_RightTrigger_Pull = 27, - K_EControllerActionOrigin_RightTrigger_Click = 28, - K_EControllerActionOrigin_LeftStick_Move = 29, - K_EControllerActionOrigin_LeftStick_Click = 30, - K_EControllerActionOrigin_LeftStick_DPadNorth = 31, - K_EControllerActionOrigin_LeftStick_DPadSouth = 32, - K_EControllerActionOrigin_LeftStick_DPadWest = 33, - K_EControllerActionOrigin_LeftStick_DPadEast = 34, - K_EControllerActionOrigin_Gyro_Move = 35, - K_EControllerActionOrigin_Gyro_Pitch = 36, - K_EControllerActionOrigin_Gyro_Yaw = 37, - K_EControllerActionOrigin_Gyro_Roll = 38, - K_EControllerActionOrigin_PS4_X = 39, - K_EControllerActionOrigin_PS4_Circle = 40, - K_EControllerActionOrigin_PS4_Triangle = 41, - K_EControllerActionOrigin_PS4_Square = 42, - K_EControllerActionOrigin_PS4_LeftBumper = 43, - K_EControllerActionOrigin_PS4_RightBumper = 44, - K_EControllerActionOrigin_PS4_Options = 45, - K_EControllerActionOrigin_PS4_Share = 46, - K_EControllerActionOrigin_PS4_LeftPad_Touch = 47, - K_EControllerActionOrigin_PS4_LeftPad_Swipe = 48, - K_EControllerActionOrigin_PS4_LeftPad_Click = 49, - K_EControllerActionOrigin_PS4_LeftPad_DPadNorth = 50, - K_EControllerActionOrigin_PS4_LeftPad_DPadSouth = 51, - K_EControllerActionOrigin_PS4_LeftPad_DPadWest = 52, - K_EControllerActionOrigin_PS4_LeftPad_DPadEast = 53, - K_EControllerActionOrigin_PS4_RightPad_Touch = 54, - K_EControllerActionOrigin_PS4_RightPad_Swipe = 55, - K_EControllerActionOrigin_PS4_RightPad_Click = 56, - K_EControllerActionOrigin_PS4_RightPad_DPadNorth = 57, - K_EControllerActionOrigin_PS4_RightPad_DPadSouth = 58, - K_EControllerActionOrigin_PS4_RightPad_DPadWest = 59, - K_EControllerActionOrigin_PS4_RightPad_DPadEast = 60, - K_EControllerActionOrigin_PS4_CenterPad_Touch = 61, - K_EControllerActionOrigin_PS4_CenterPad_Swipe = 62, - K_EControllerActionOrigin_PS4_CenterPad_Click = 63, - K_EControllerActionOrigin_PS4_CenterPad_DPadNorth = 64, - K_EControllerActionOrigin_PS4_CenterPad_DPadSouth = 65, - K_EControllerActionOrigin_PS4_CenterPad_DPadWest = 66, - K_EControllerActionOrigin_PS4_CenterPad_DPadEast = 67, - K_EControllerActionOrigin_PS4_LeftTrigger_Pull = 68, - K_EControllerActionOrigin_PS4_LeftTrigger_Click = 69, - K_EControllerActionOrigin_PS4_RightTrigger_Pull = 70, - K_EControllerActionOrigin_PS4_RightTrigger_Click = 71, - K_EControllerActionOrigin_PS4_LeftStick_Move = 72, - K_EControllerActionOrigin_PS4_LeftStick_Click = 73, - K_EControllerActionOrigin_PS4_LeftStick_DPadNorth = 74, - K_EControllerActionOrigin_PS4_LeftStick_DPadSouth = 75, - K_EControllerActionOrigin_PS4_LeftStick_DPadWest = 76, - K_EControllerActionOrigin_PS4_LeftStick_DPadEast = 77, - K_EControllerActionOrigin_PS4_RightStick_Move = 78, - K_EControllerActionOrigin_PS4_RightStick_Click = 79, - K_EControllerActionOrigin_PS4_RightStick_DPadNorth = 80, - K_EControllerActionOrigin_PS4_RightStick_DPadSouth = 81, - K_EControllerActionOrigin_PS4_RightStick_DPadWest = 82, - K_EControllerActionOrigin_PS4_RightStick_DPadEast = 83, - K_EControllerActionOrigin_PS4_DPad_North = 84, - K_EControllerActionOrigin_PS4_DPad_South = 85, - K_EControllerActionOrigin_PS4_DPad_West = 86, - K_EControllerActionOrigin_PS4_DPad_East = 87, - K_EControllerActionOrigin_PS4_Gyro_Move = 88, - K_EControllerActionOrigin_PS4_Gyro_Pitch = 89, - K_EControllerActionOrigin_PS4_Gyro_Yaw = 90, - K_EControllerActionOrigin_PS4_Gyro_Roll = 91, - K_EControllerActionOrigin_XBoxOne_A = 92, - K_EControllerActionOrigin_XBoxOne_B = 93, - K_EControllerActionOrigin_XBoxOne_X = 94, - K_EControllerActionOrigin_XBoxOne_Y = 95, - K_EControllerActionOrigin_XBoxOne_LeftBumper = 96, - K_EControllerActionOrigin_XBoxOne_RightBumper = 97, - K_EControllerActionOrigin_XBoxOne_Menu = 98, - K_EControllerActionOrigin_XBoxOne_View = 99, - K_EControllerActionOrigin_XBoxOne_LeftTrigger_Pull = 100, - K_EControllerActionOrigin_XBoxOne_LeftTrigger_Click = 101, - K_EControllerActionOrigin_XBoxOne_RightTrigger_Pull = 102, - K_EControllerActionOrigin_XBoxOne_RightTrigger_Click = 103, - K_EControllerActionOrigin_XBoxOne_LeftStick_Move = 104, - K_EControllerActionOrigin_XBoxOne_LeftStick_Click = 105, - K_EControllerActionOrigin_XBoxOne_LeftStick_DPadNorth = 106, - K_EControllerActionOrigin_XBoxOne_LeftStick_DPadSouth = 107, - K_EControllerActionOrigin_XBoxOne_LeftStick_DPadWest = 108, - K_EControllerActionOrigin_XBoxOne_LeftStick_DPadEast = 109, - K_EControllerActionOrigin_XBoxOne_RightStick_Move = 110, - K_EControllerActionOrigin_XBoxOne_RightStick_Click = 111, - K_EControllerActionOrigin_XBoxOne_RightStick_DPadNorth = 112, - K_EControllerActionOrigin_XBoxOne_RightStick_DPadSouth = 113, - K_EControllerActionOrigin_XBoxOne_RightStick_DPadWest = 114, - K_EControllerActionOrigin_XBoxOne_RightStick_DPadEast = 115, - K_EControllerActionOrigin_XBoxOne_DPad_North = 116, - K_EControllerActionOrigin_XBoxOne_DPad_South = 117, - K_EControllerActionOrigin_XBoxOne_DPad_West = 118, - K_EControllerActionOrigin_XBoxOne_DPad_East = 119, - K_EControllerActionOrigin_XBox360_A = 120, - K_EControllerActionOrigin_XBox360_B = 121, - K_EControllerActionOrigin_XBox360_X = 122, - K_EControllerActionOrigin_XBox360_Y = 123, - K_EControllerActionOrigin_XBox360_LeftBumper = 124, - K_EControllerActionOrigin_XBox360_RightBumper = 125, - K_EControllerActionOrigin_XBox360_Start = 126, - K_EControllerActionOrigin_XBox360_Back = 127, - K_EControllerActionOrigin_XBox360_LeftTrigger_Pull = 128, - K_EControllerActionOrigin_XBox360_LeftTrigger_Click = 129, - K_EControllerActionOrigin_XBox360_RightTrigger_Pull = 130, - K_EControllerActionOrigin_XBox360_RightTrigger_Click = 131, - K_EControllerActionOrigin_XBox360_LeftStick_Move = 132, - K_EControllerActionOrigin_XBox360_LeftStick_Click = 133, - K_EControllerActionOrigin_XBox360_LeftStick_DPadNorth = 134, - K_EControllerActionOrigin_XBox360_LeftStick_DPadSouth = 135, - K_EControllerActionOrigin_XBox360_LeftStick_DPadWest = 136, - K_EControllerActionOrigin_XBox360_LeftStick_DPadEast = 137, - K_EControllerActionOrigin_XBox360_RightStick_Move = 138, - K_EControllerActionOrigin_XBox360_RightStick_Click = 139, - K_EControllerActionOrigin_XBox360_RightStick_DPadNorth = 140, - K_EControllerActionOrigin_XBox360_RightStick_DPadSouth = 141, - K_EControllerActionOrigin_XBox360_RightStick_DPadWest = 142, - K_EControllerActionOrigin_XBox360_RightStick_DPadEast = 143, - K_EControllerActionOrigin_XBox360_DPad_North = 144, - K_EControllerActionOrigin_XBox360_DPad_South = 145, - K_EControllerActionOrigin_XBox360_DPad_West = 146, - K_EControllerActionOrigin_XBox360_DPad_East = 147, - K_EControllerActionOrigin_SteamV2_A = 148, - K_EControllerActionOrigin_SteamV2_B = 149, - K_EControllerActionOrigin_SteamV2_X = 150, - K_EControllerActionOrigin_SteamV2_Y = 151, - K_EControllerActionOrigin_SteamV2_LeftBumper = 152, - K_EControllerActionOrigin_SteamV2_RightBumper = 153, - K_EControllerActionOrigin_SteamV2_LeftGrip_Lower = 154, - K_EControllerActionOrigin_SteamV2_LeftGrip_Upper = 155, - K_EControllerActionOrigin_SteamV2_RightGrip_Lower = 156, - K_EControllerActionOrigin_SteamV2_RightGrip_Upper = 157, - K_EControllerActionOrigin_SteamV2_LeftBumper_Pressure = 158, - K_EControllerActionOrigin_SteamV2_RightBumper_Pressure = 159, - K_EControllerActionOrigin_SteamV2_LeftGrip_Pressure = 160, - K_EControllerActionOrigin_SteamV2_RightGrip_Pressure = 161, - K_EControllerActionOrigin_SteamV2_LeftGrip_Upper_Pressure = 162, - K_EControllerActionOrigin_SteamV2_RightGrip_Upper_Pressure = 163, - K_EControllerActionOrigin_SteamV2_Start = 164, - K_EControllerActionOrigin_SteamV2_Back = 165, - K_EControllerActionOrigin_SteamV2_LeftPad_Touch = 166, - K_EControllerActionOrigin_SteamV2_LeftPad_Swipe = 167, - K_EControllerActionOrigin_SteamV2_LeftPad_Click = 168, - K_EControllerActionOrigin_SteamV2_LeftPad_Pressure = 169, - K_EControllerActionOrigin_SteamV2_LeftPad_DPadNorth = 170, - K_EControllerActionOrigin_SteamV2_LeftPad_DPadSouth = 171, - K_EControllerActionOrigin_SteamV2_LeftPad_DPadWest = 172, - K_EControllerActionOrigin_SteamV2_LeftPad_DPadEast = 173, - K_EControllerActionOrigin_SteamV2_RightPad_Touch = 174, - K_EControllerActionOrigin_SteamV2_RightPad_Swipe = 175, - K_EControllerActionOrigin_SteamV2_RightPad_Click = 176, - K_EControllerActionOrigin_SteamV2_RightPad_Pressure = 177, - K_EControllerActionOrigin_SteamV2_RightPad_DPadNorth = 178, - K_EControllerActionOrigin_SteamV2_RightPad_DPadSouth = 179, - K_EControllerActionOrigin_SteamV2_RightPad_DPadWest = 180, - K_EControllerActionOrigin_SteamV2_RightPad_DPadEast = 181, - K_EControllerActionOrigin_SteamV2_LeftTrigger_Pull = 182, - K_EControllerActionOrigin_SteamV2_LeftTrigger_Click = 183, - K_EControllerActionOrigin_SteamV2_RightTrigger_Pull = 184, - K_EControllerActionOrigin_SteamV2_RightTrigger_Click = 185, - K_EControllerActionOrigin_SteamV2_LeftStick_Move = 186, - K_EControllerActionOrigin_SteamV2_LeftStick_Click = 187, - K_EControllerActionOrigin_SteamV2_LeftStick_DPadNorth = 188, - K_EControllerActionOrigin_SteamV2_LeftStick_DPadSouth = 189, - K_EControllerActionOrigin_SteamV2_LeftStick_DPadWest = 190, - K_EControllerActionOrigin_SteamV2_LeftStick_DPadEast = 191, - K_EControllerActionOrigin_SteamV2_Gyro_Move = 192, - K_EControllerActionOrigin_SteamV2_Gyro_Pitch = 193, - K_EControllerActionOrigin_SteamV2_Gyro_Yaw = 194, - K_EControllerActionOrigin_SteamV2_Gyro_Roll = 195, - K_EControllerActionOrigin_Switch_A = 196, - K_EControllerActionOrigin_Switch_B = 197, - K_EControllerActionOrigin_Switch_X = 198, - K_EControllerActionOrigin_Switch_Y = 199, - K_EControllerActionOrigin_Switch_LeftBumper = 200, - K_EControllerActionOrigin_Switch_RightBumper = 201, - K_EControllerActionOrigin_Switch_Plus = 202, - K_EControllerActionOrigin_Switch_Minus = 203, - K_EControllerActionOrigin_Switch_Capture = 204, - K_EControllerActionOrigin_Switch_LeftTrigger_Pull = 205, - K_EControllerActionOrigin_Switch_LeftTrigger_Click = 206, - K_EControllerActionOrigin_Switch_RightTrigger_Pull = 207, - K_EControllerActionOrigin_Switch_RightTrigger_Click = 208, - K_EControllerActionOrigin_Switch_LeftStick_Move = 209, - K_EControllerActionOrigin_Switch_LeftStick_Click = 210, - K_EControllerActionOrigin_Switch_LeftStick_DPadNorth = 211, - K_EControllerActionOrigin_Switch_LeftStick_DPadSouth = 212, - K_EControllerActionOrigin_Switch_LeftStick_DPadWest = 213, - K_EControllerActionOrigin_Switch_LeftStick_DPadEast = 214, - K_EControllerActionOrigin_Switch_RightStick_Move = 215, - K_EControllerActionOrigin_Switch_RightStick_Click = 216, - K_EControllerActionOrigin_Switch_RightStick_DPadNorth = 217, - K_EControllerActionOrigin_Switch_RightStick_DPadSouth = 218, - K_EControllerActionOrigin_Switch_RightStick_DPadWest = 219, - K_EControllerActionOrigin_Switch_RightStick_DPadEast = 220, - K_EControllerActionOrigin_Switch_DPad_North = 221, - K_EControllerActionOrigin_Switch_DPad_South = 222, - K_EControllerActionOrigin_Switch_DPad_West = 223, - K_EControllerActionOrigin_Switch_DPad_East = 224, - K_EControllerActionOrigin_Switch_ProGyro_Move = 225, - K_EControllerActionOrigin_Switch_ProGyro_Pitch = 226, - K_EControllerActionOrigin_Switch_ProGyro_Yaw = 227, - K_EControllerActionOrigin_Switch_ProGyro_Roll = 228, - K_EControllerActionOrigin_Switch_RightGyro_Move = 229, - K_EControllerActionOrigin_Switch_RightGyro_Pitch = 230, - K_EControllerActionOrigin_Switch_RightGyro_Yaw = 231, - K_EControllerActionOrigin_Switch_RightGyro_Roll = 232, - K_EControllerActionOrigin_Switch_LeftGyro_Move = 233, - K_EControllerActionOrigin_Switch_LeftGyro_Pitch = 234, - K_EControllerActionOrigin_Switch_LeftGyro_Yaw = 235, - K_EControllerActionOrigin_Switch_LeftGyro_Roll = 236, - K_EControllerActionOrigin_Switch_LeftGrip_Lower = 237, - K_EControllerActionOrigin_Switch_LeftGrip_Upper = 238, - K_EControllerActionOrigin_Switch_RightGrip_Lower = 239, - K_EControllerActionOrigin_Switch_RightGrip_Upper = 240, - K_EControllerActionOrigin_PS4_DPad_Move = 241, - K_EControllerActionOrigin_XBoxOne_DPad_Move = 242, - K_EControllerActionOrigin_XBox360_DPad_Move = 243, - K_EControllerActionOrigin_Switch_DPad_Move = 244, - K_EControllerActionOrigin_PS5_X = 245, - K_EControllerActionOrigin_PS5_Circle = 246, - K_EControllerActionOrigin_PS5_Triangle = 247, - K_EControllerActionOrigin_PS5_Square = 248, - K_EControllerActionOrigin_PS5_LeftBumper = 249, - K_EControllerActionOrigin_PS5_RightBumper = 250, - K_EControllerActionOrigin_PS5_Option = 251, - K_EControllerActionOrigin_PS5_Create = 252, - K_EControllerActionOrigin_PS5_Mute = 253, - K_EControllerActionOrigin_PS5_LeftPad_Touch = 254, - K_EControllerActionOrigin_PS5_LeftPad_Swipe = 255, - K_EControllerActionOrigin_PS5_LeftPad_Click = 256, - K_EControllerActionOrigin_PS5_LeftPad_DPadNorth = 257, - K_EControllerActionOrigin_PS5_LeftPad_DPadSouth = 258, - K_EControllerActionOrigin_PS5_LeftPad_DPadWest = 259, - K_EControllerActionOrigin_PS5_LeftPad_DPadEast = 260, - K_EControllerActionOrigin_PS5_RightPad_Touch = 261, - K_EControllerActionOrigin_PS5_RightPad_Swipe = 262, - K_EControllerActionOrigin_PS5_RightPad_Click = 263, - K_EControllerActionOrigin_PS5_RightPad_DPadNorth = 264, - K_EControllerActionOrigin_PS5_RightPad_DPadSouth = 265, - K_EControllerActionOrigin_PS5_RightPad_DPadWest = 266, - K_EControllerActionOrigin_PS5_RightPad_DPadEast = 267, - K_EControllerActionOrigin_PS5_CenterPad_Touch = 268, - K_EControllerActionOrigin_PS5_CenterPad_Swipe = 269, - K_EControllerActionOrigin_PS5_CenterPad_Click = 270, - K_EControllerActionOrigin_PS5_CenterPad_DPadNorth = 271, - K_EControllerActionOrigin_PS5_CenterPad_DPadSouth = 272, - K_EControllerActionOrigin_PS5_CenterPad_DPadWest = 273, - K_EControllerActionOrigin_PS5_CenterPad_DPadEast = 274, - K_EControllerActionOrigin_PS5_LeftTrigger_Pull = 275, - K_EControllerActionOrigin_PS5_LeftTrigger_Click = 276, - K_EControllerActionOrigin_PS5_RightTrigger_Pull = 277, - K_EControllerActionOrigin_PS5_RightTrigger_Click = 278, - K_EControllerActionOrigin_PS5_LeftStick_Move = 279, - K_EControllerActionOrigin_PS5_LeftStick_Click = 280, - K_EControllerActionOrigin_PS5_LeftStick_DPadNorth = 281, - K_EControllerActionOrigin_PS5_LeftStick_DPadSouth = 282, - K_EControllerActionOrigin_PS5_LeftStick_DPadWest = 283, - K_EControllerActionOrigin_PS5_LeftStick_DPadEast = 284, - K_EControllerActionOrigin_PS5_RightStick_Move = 285, - K_EControllerActionOrigin_PS5_RightStick_Click = 286, - K_EControllerActionOrigin_PS5_RightStick_DPadNorth = 287, - K_EControllerActionOrigin_PS5_RightStick_DPadSouth = 288, - K_EControllerActionOrigin_PS5_RightStick_DPadWest = 289, - K_EControllerActionOrigin_PS5_RightStick_DPadEast = 290, - K_EControllerActionOrigin_PS5_DPad_Move = 291, - K_EControllerActionOrigin_PS5_DPad_North = 292, - K_EControllerActionOrigin_PS5_DPad_South = 293, - K_EControllerActionOrigin_PS5_DPad_West = 294, - K_EControllerActionOrigin_PS5_DPad_East = 295, - K_EControllerActionOrigin_PS5_Gyro_Move = 296, - K_EControllerActionOrigin_PS5_Gyro_Pitch = 297, - K_EControllerActionOrigin_PS5_Gyro_Yaw = 298, - K_EControllerActionOrigin_PS5_Gyro_Roll = 299, - K_EControllerActionOrigin_XBoxOne_LeftGrip_Lower = 300, - K_EControllerActionOrigin_XBoxOne_LeftGrip_Upper = 301, - K_EControllerActionOrigin_XBoxOne_RightGrip_Lower = 302, - K_EControllerActionOrigin_XBoxOne_RightGrip_Upper = 303, - K_EControllerActionOrigin_XBoxOne_Share = 304, - K_EControllerActionOrigin_SteamDeck_A = 305, - K_EControllerActionOrigin_SteamDeck_B = 306, - K_EControllerActionOrigin_SteamDeck_X = 307, - K_EControllerActionOrigin_SteamDeck_Y = 308, - K_EControllerActionOrigin_SteamDeck_L1 = 309, - K_EControllerActionOrigin_SteamDeck_R1 = 310, - K_EControllerActionOrigin_SteamDeck_Menu = 311, - K_EControllerActionOrigin_SteamDeck_View = 312, - K_EControllerActionOrigin_SteamDeck_LeftPad_Touch = 313, - K_EControllerActionOrigin_SteamDeck_LeftPad_Swipe = 314, - K_EControllerActionOrigin_SteamDeck_LeftPad_Click = 315, - K_EControllerActionOrigin_SteamDeck_LeftPad_DPadNorth = 316, - K_EControllerActionOrigin_SteamDeck_LeftPad_DPadSouth = 317, - K_EControllerActionOrigin_SteamDeck_LeftPad_DPadWest = 318, - K_EControllerActionOrigin_SteamDeck_LeftPad_DPadEast = 319, - K_EControllerActionOrigin_SteamDeck_RightPad_Touch = 320, - K_EControllerActionOrigin_SteamDeck_RightPad_Swipe = 321, - K_EControllerActionOrigin_SteamDeck_RightPad_Click = 322, - K_EControllerActionOrigin_SteamDeck_RightPad_DPadNorth = 323, - K_EControllerActionOrigin_SteamDeck_RightPad_DPadSouth = 324, - K_EControllerActionOrigin_SteamDeck_RightPad_DPadWest = 325, - K_EControllerActionOrigin_SteamDeck_RightPad_DPadEast = 326, - K_EControllerActionOrigin_SteamDeck_L2_SoftPull = 327, - K_EControllerActionOrigin_SteamDeck_L2 = 328, - K_EControllerActionOrigin_SteamDeck_R2_SoftPull = 329, - K_EControllerActionOrigin_SteamDeck_R2 = 330, - K_EControllerActionOrigin_SteamDeck_LeftStick_Move = 331, - K_EControllerActionOrigin_SteamDeck_L3 = 332, - K_EControllerActionOrigin_SteamDeck_LeftStick_DPadNorth = 333, - K_EControllerActionOrigin_SteamDeck_LeftStick_DPadSouth = 334, - K_EControllerActionOrigin_SteamDeck_LeftStick_DPadWest = 335, - K_EControllerActionOrigin_SteamDeck_LeftStick_DPadEast = 336, - K_EControllerActionOrigin_SteamDeck_LeftStick_Touch = 337, - K_EControllerActionOrigin_SteamDeck_RightStick_Move = 338, - K_EControllerActionOrigin_SteamDeck_R3 = 339, - K_EControllerActionOrigin_SteamDeck_RightStick_DPadNorth = 340, - K_EControllerActionOrigin_SteamDeck_RightStick_DPadSouth = 341, - K_EControllerActionOrigin_SteamDeck_RightStick_DPadWest = 342, - K_EControllerActionOrigin_SteamDeck_RightStick_DPadEast = 343, - K_EControllerActionOrigin_SteamDeck_RightStick_Touch = 344, - K_EControllerActionOrigin_SteamDeck_L4 = 345, - K_EControllerActionOrigin_SteamDeck_R4 = 346, - K_EControllerActionOrigin_SteamDeck_L5 = 347, - K_EControllerActionOrigin_SteamDeck_R5 = 348, - K_EControllerActionOrigin_SteamDeck_DPad_Move = 349, - K_EControllerActionOrigin_SteamDeck_DPad_North = 350, - K_EControllerActionOrigin_SteamDeck_DPad_South = 351, - K_EControllerActionOrigin_SteamDeck_DPad_West = 352, - K_EControllerActionOrigin_SteamDeck_DPad_East = 353, - K_EControllerActionOrigin_SteamDeck_Gyro_Move = 354, - K_EControllerActionOrigin_SteamDeck_Gyro_Pitch = 355, - K_EControllerActionOrigin_SteamDeck_Gyro_Yaw = 356, - K_EControllerActionOrigin_SteamDeck_Gyro_Roll = 357, - K_EControllerActionOrigin_SteamDeck_Reserved1 = 358, - K_EControllerActionOrigin_SteamDeck_Reserved2 = 359, - K_EControllerActionOrigin_SteamDeck_Reserved3 = 360, - K_EControllerActionOrigin_SteamDeck_Reserved4 = 361, - K_EControllerActionOrigin_SteamDeck_Reserved5 = 362, - K_EControllerActionOrigin_SteamDeck_Reserved6 = 363, - K_EControllerActionOrigin_SteamDeck_Reserved7 = 364, - K_EControllerActionOrigin_SteamDeck_Reserved8 = 365, - K_EControllerActionOrigin_SteamDeck_Reserved9 = 366, - K_EControllerActionOrigin_SteamDeck_Reserved10 = 367, - K_EControllerActionOrigin_SteamDeck_Reserved11 = 368, - K_EControllerActionOrigin_SteamDeck_Reserved12 = 369, - K_EControllerActionOrigin_SteamDeck_Reserved13 = 370, - K_EControllerActionOrigin_SteamDeck_Reserved14 = 371, - K_EControllerActionOrigin_SteamDeck_Reserved15 = 372, - K_EControllerActionOrigin_SteamDeck_Reserved16 = 373, - K_EControllerActionOrigin_SteamDeck_Reserved17 = 374, - K_EControllerActionOrigin_SteamDeck_Reserved18 = 375, - K_EControllerActionOrigin_SteamDeck_Reserved19 = 376, - K_EControllerActionOrigin_SteamDeck_Reserved20 = 377, - K_EControllerActionOrigin_Switch_JoyConButton_N = 378, - K_EControllerActionOrigin_Switch_JoyConButton_E = 379, - K_EControllerActionOrigin_Switch_JoyConButton_S = 380, - K_EControllerActionOrigin_Switch_JoyConButton_W = 381, - K_EControllerActionOrigin_PS5_LeftGrip = 382, - K_EControllerActionOrigin_PS5_RightGrip = 383, - K_EControllerActionOrigin_PS5_LeftFn = 384, - K_EControllerActionOrigin_PS5_RightFn = 385, - K_EControllerActionOrigin_Count = 386, - K_EControllerActionOrigin_MaximumPossibleValue = 32767, -}; -Q_ENUM_NS(EControllerActionOrigin) - -enum class ESteamControllerLEDFlag { - K_ESteamControllerLEDFlag_SetColor = 0, - K_ESteamControllerLEDFlag_RestoreUserDefault = 1, -}; -Q_ENUM_NS(ESteamControllerLEDFlag) - -enum class EUGCMatchingUGCType { - K_EUGCMatchingUGCType_Items = 0, - K_EUGCMatchingUGCType_Items_Mtx = 1, - K_EUGCMatchingUGCType_Items_ReadyToUse = 2, - K_EUGCMatchingUGCType_Collections = 3, - K_EUGCMatchingUGCType_Artwork = 4, - K_EUGCMatchingUGCType_Videos = 5, - K_EUGCMatchingUGCType_Screenshots = 6, - K_EUGCMatchingUGCType_AllGuides = 7, - K_EUGCMatchingUGCType_WebGuides = 8, - K_EUGCMatchingUGCType_IntegratedGuides = 9, - K_EUGCMatchingUGCType_UsableInGame = 10, - K_EUGCMatchingUGCType_ControllerBindings = 11, - K_EUGCMatchingUGCType_GameManagedItems = 12, - K_EUGCMatchingUGCType_All = -1, -}; -Q_ENUM_NS(EUGCMatchingUGCType) - -enum class EUserUGCList { - K_EUserUGCList_Published = 0, - K_EUserUGCList_VotedOn = 1, - K_EUserUGCList_VotedUp = 2, - K_EUserUGCList_VotedDown = 3, - K_EUserUGCList_WillVoteLater = 4, - K_EUserUGCList_Favorited = 5, - K_EUserUGCList_Subscribed = 6, - K_EUserUGCList_UsedOrPlayed = 7, - K_EUserUGCList_Followed = 8, -}; -Q_ENUM_NS(EUserUGCList) - -enum class EUserUGCListSortOrder { - K_EUserUGCListSortOrder_CreationOrderDesc = 0, - K_EUserUGCListSortOrder_CreationOrderAsc = 1, - K_EUserUGCListSortOrder_TitleAsc = 2, - K_EUserUGCListSortOrder_LastUpdatedDesc = 3, - K_EUserUGCListSortOrder_SubscriptionDateDesc = 4, - K_EUserUGCListSortOrder_VoteScoreDesc = 5, - K_EUserUGCListSortOrder_ForModeration = 6, -}; -Q_ENUM_NS(EUserUGCListSortOrder) - -enum class EUGCQuery { - K_EUGCQuery_RankedByVote = 0, - K_EUGCQuery_RankedByPublicationDate = 1, - K_EUGCQuery_AcceptedForGameRankedByAcceptanceDate = 2, - K_EUGCQuery_RankedByTrend = 3, - K_EUGCQuery_FavoritedByFriendsRankedByPublicationDate = 4, - K_EUGCQuery_CreatedByFriendsRankedByPublicationDate = 5, - K_EUGCQuery_RankedByNumTimesReported = 6, - K_EUGCQuery_CreatedByFollowedUsersRankedByPublicationDate = 7, - K_EUGCQuery_NotYetRated = 8, - K_EUGCQuery_RankedByTotalVotesAsc = 9, - K_EUGCQuery_RankedByVotesUp = 10, - K_EUGCQuery_RankedByTextSearch = 11, - K_EUGCQuery_RankedByTotalUniqueSubscriptions = 12, - K_EUGCQuery_RankedByPlaytimeTrend = 13, - K_EUGCQuery_RankedByTotalPlaytime = 14, - K_EUGCQuery_RankedByAveragePlaytimeTrend = 15, - K_EUGCQuery_RankedByLifetimeAveragePlaytime = 16, - K_EUGCQuery_RankedByPlaytimeSessionsTrend = 17, - K_EUGCQuery_RankedByLifetimePlaytimeSessions = 18, - K_EUGCQuery_RankedByLastUpdatedDate = 19, -}; -Q_ENUM_NS(EUGCQuery) - -enum class EItemUpdateStatus { - K_EItemUpdateStatusInvalid = 0, - K_EItemUpdateStatusPreparingConfig = 1, - K_EItemUpdateStatusPreparingContent = 2, - K_EItemUpdateStatusUploadingContent = 3, - K_EItemUpdateStatusUploadingPreviewFile = 4, - K_EItemUpdateStatusCommittingChanges = 5, -}; -Q_ENUM_NS(EItemUpdateStatus) - -enum class EItemState { - K_EItemStateNone = 0, - K_EItemStateSubscribed = 1, - K_EItemStateLegacyItem = 2, - K_EItemStateInstalled = 4, - K_EItemStateNeedsUpdate = 8, - K_EItemStateDownloading = 16, - K_EItemStateDownloadPending = 32, -}; -Q_ENUM_NS(EItemState) - -enum class EItemStatistic { - K_EItemStatistic_NumSubscriptions = 0, - K_EItemStatistic_NumFavorites = 1, - K_EItemStatistic_NumFollowers = 2, - K_EItemStatistic_NumUniqueSubscriptions = 3, - K_EItemStatistic_NumUniqueFavorites = 4, - K_EItemStatistic_NumUniqueFollowers = 5, - K_EItemStatistic_NumUniqueWebsiteViews = 6, - K_EItemStatistic_ReportScore = 7, - K_EItemStatistic_NumSecondsPlayed = 8, - K_EItemStatistic_NumPlaytimeSessions = 9, - K_EItemStatistic_NumComments = 10, - K_EItemStatistic_NumSecondsPlayedDuringTimePeriod = 11, - K_EItemStatistic_NumPlaytimeSessionsDuringTimePeriod = 12, -}; -Q_ENUM_NS(EItemStatistic) - -enum class EItemPreviewType { - K_EItemPreviewType_Image = 0, - K_EItemPreviewType_YouTubeVideo = 1, - K_EItemPreviewType_Sketchfab = 2, - K_EItemPreviewType_EnvironmentMap_HorizontalCross = 3, - K_EItemPreviewType_EnvironmentMap_LatLong = 4, - K_EItemPreviewType_ReservedMax = 255, -}; -Q_ENUM_NS(EItemPreviewType) - -enum class EUGCContentDescriptorID { - K_EUGCContentDescriptor_NudityOrSexualContent = 1, - K_EUGCContentDescriptor_FrequentViolenceOrGore = 2, - K_EUGCContentDescriptor_AdultOnlySexualContent = 3, - K_EUGCContentDescriptor_GratuitousSexualContent = 4, - K_EUGCContentDescriptor_AnyMatureContent = 5, -}; -Q_ENUM_NS(EUGCContentDescriptorID) - -enum class ESteamItemFlags { - K_ESteamItemNoTrade = 1, - K_ESteamItemRemoved = 256, - K_ESteamItemConsumed = 512, -}; -Q_ENUM_NS(ESteamItemFlags) - -enum class EParentalFeature { - K_EFeatureInvalid = 0, - K_EFeatureStore = 1, - K_EFeatureCommunity = 2, - K_EFeatureProfile = 3, - K_EFeatureFriends = 4, - K_EFeatureNews = 5, - K_EFeatureTrading = 6, - K_EFeatureSettings = 7, - K_EFeatureConsole = 8, - K_EFeatureBrowser = 9, - K_EFeatureParentalSetup = 10, - K_EFeatureLibrary = 11, - K_EFeatureTest = 12, - K_EFeatureSiteLicense = 13, - K_EFeatureKioskMode = 14, - K_EFeatureMax = 15, -}; -Q_ENUM_NS(EParentalFeature) - -enum class ESteamDeviceFormFactor { - K_ESteamDeviceFormFactorUnknown = 0, - K_ESteamDeviceFormFactorPhone = 1, - K_ESteamDeviceFormFactorTablet = 2, - K_ESteamDeviceFormFactorComputer = 3, - K_ESteamDeviceFormFactorTV = 4, -}; -Q_ENUM_NS(ESteamDeviceFormFactor) - -enum class ESteamNetworkingAvailability { - K_ESteamNetworkingAvailability_CannotTry = -102, - K_ESteamNetworkingAvailability_Failed = -101, - K_ESteamNetworkingAvailability_Previously = -100, - K_ESteamNetworkingAvailability_Retrying = -10, - K_ESteamNetworkingAvailability_NeverTried = 1, - K_ESteamNetworkingAvailability_Waiting = 2, - K_ESteamNetworkingAvailability_Attempting = 3, - K_ESteamNetworkingAvailability_Current = 100, - K_ESteamNetworkingAvailability_Unknown = 0, - K_ESteamNetworkingAvailability__Force32bit = 2147483647, -}; -Q_ENUM_NS(ESteamNetworkingAvailability) - -enum class ESteamNetworkingIdentityType { - K_ESteamNetworkingIdentityType_Invalid = 0, - K_ESteamNetworkingIdentityType_SteamID = 16, - K_ESteamNetworkingIdentityType_XboxPairwiseID = 17, - K_ESteamNetworkingIdentityType_SonyPSN = 18, - K_ESteamNetworkingIdentityType_GoogleStadia = 19, - K_ESteamNetworkingIdentityType_IPAddress = 1, - K_ESteamNetworkingIdentityType_GenericString = 2, - K_ESteamNetworkingIdentityType_GenericBytes = 3, - K_ESteamNetworkingIdentityType_UnknownType = 4, - K_ESteamNetworkingIdentityType__Force32bit = 2147483647, -}; -Q_ENUM_NS(ESteamNetworkingIdentityType) - -enum class ESteamNetworkingFakeIPType { - K_ESteamNetworkingFakeIPType_Invalid = 0, - K_ESteamNetworkingFakeIPType_NotFake = 1, - K_ESteamNetworkingFakeIPType_GlobalIPv4 = 2, - K_ESteamNetworkingFakeIPType_LocalIPv4 = 3, - K_ESteamNetworkingFakeIPType__Force32Bit = 2147483647, -}; -Q_ENUM_NS(ESteamNetworkingFakeIPType) - -enum class ESteamNetworkingConnectionState { - K_ESteamNetworkingConnectionState_None = 0, - K_ESteamNetworkingConnectionState_Connecting = 1, - K_ESteamNetworkingConnectionState_FindingRoute = 2, - K_ESteamNetworkingConnectionState_Connected = 3, - K_ESteamNetworkingConnectionState_ClosedByPeer = 4, - K_ESteamNetworkingConnectionState_ProblemDetectedLocally = 5, - K_ESteamNetworkingConnectionState_FinWait = -1, - K_ESteamNetworkingConnectionState_Linger = -2, - K_ESteamNetworkingConnectionState_Dead = -3, - K_ESteamNetworkingConnectionState__Force32Bit = 2147483647, -}; -Q_ENUM_NS(ESteamNetworkingConnectionState) - -enum class ESteamNetConnectionEnd { - K_ESteamNetConnectionEnd_Invalid = 0, - K_ESteamNetConnectionEnd_App_Min = 1000, - K_ESteamNetConnectionEnd_App_Generic = 1000, - K_ESteamNetConnectionEnd_App_Max = 1999, - K_ESteamNetConnectionEnd_AppException_Min = 2000, - K_ESteamNetConnectionEnd_AppException_Generic = 2000, - K_ESteamNetConnectionEnd_AppException_Max = 2999, - K_ESteamNetConnectionEnd_Local_Min = 3000, - K_ESteamNetConnectionEnd_Local_OfflineMode = 3001, - K_ESteamNetConnectionEnd_Local_ManyRelayConnectivity = 3002, - K_ESteamNetConnectionEnd_Local_HostedServerPrimaryRelay = 3003, - K_ESteamNetConnectionEnd_Local_NetworkConfig = 3004, - K_ESteamNetConnectionEnd_Local_Rights = 3005, - K_ESteamNetConnectionEnd_Local_P2P_ICE_NoPublicAddresses = 3006, - K_ESteamNetConnectionEnd_Local_Max = 3999, - K_ESteamNetConnectionEnd_Remote_Min = 4000, - K_ESteamNetConnectionEnd_Remote_Timeout = 4001, - K_ESteamNetConnectionEnd_Remote_BadCrypt = 4002, - K_ESteamNetConnectionEnd_Remote_BadCert = 4003, - K_ESteamNetConnectionEnd_Remote_BadProtocolVersion = 4006, - K_ESteamNetConnectionEnd_Remote_P2P_ICE_NoPublicAddresses = 4007, - K_ESteamNetConnectionEnd_Remote_Max = 4999, - K_ESteamNetConnectionEnd_Misc_Min = 5000, - K_ESteamNetConnectionEnd_Misc_Generic = 5001, - K_ESteamNetConnectionEnd_Misc_InternalError = 5002, - K_ESteamNetConnectionEnd_Misc_Timeout = 5003, - K_ESteamNetConnectionEnd_Misc_SteamConnectivity = 5005, - K_ESteamNetConnectionEnd_Misc_NoRelaySessionsToClient = 5006, - K_ESteamNetConnectionEnd_Misc_P2P_Rendezvous = 5008, - K_ESteamNetConnectionEnd_Misc_P2P_NAT_Firewall = 5009, - K_ESteamNetConnectionEnd_Misc_PeerSentNoConnection = 5010, - K_ESteamNetConnectionEnd_Misc_Max = 5999, - K_ESteamNetConnectionEnd__Force32Bit = 2147483647, -}; -Q_ENUM_NS(ESteamNetConnectionEnd) - -enum class ESteamNetworkingConfigScope { - K_ESteamNetworkingConfig_Global = 1, - K_ESteamNetworkingConfig_SocketsInterface = 2, - K_ESteamNetworkingConfig_ListenSocket = 3, - K_ESteamNetworkingConfig_Connection = 4, - K_ESteamNetworkingConfigScope__Force32Bit = 2147483647, -}; -Q_ENUM_NS(ESteamNetworkingConfigScope) - -enum class ESteamNetworkingConfigDataType { - K_ESteamNetworkingConfig_Int32 = 1, - K_ESteamNetworkingConfig_Int64 = 2, - K_ESteamNetworkingConfig_Float = 3, - K_ESteamNetworkingConfig_String = 4, - K_ESteamNetworkingConfig_Ptr = 5, - K_ESteamNetworkingConfigDataType__Force32Bit = 2147483647, -}; -Q_ENUM_NS(ESteamNetworkingConfigDataType) - -enum class ESteamNetworkingConfigValue { - K_ESteamNetworkingConfig_Invalid = 0, - K_ESteamNetworkingConfig_TimeoutInitial = 24, - K_ESteamNetworkingConfig_TimeoutConnected = 25, - K_ESteamNetworkingConfig_SendBufferSize = 9, - K_ESteamNetworkingConfig_ConnectionUserData = 40, - K_ESteamNetworkingConfig_SendRateMin = 10, - K_ESteamNetworkingConfig_SendRateMax = 11, - K_ESteamNetworkingConfig_NagleTime = 12, - K_ESteamNetworkingConfig_IP_AllowWithoutAuth = 23, - K_ESteamNetworkingConfig_MTU_PacketSize = 32, - K_ESteamNetworkingConfig_MTU_DataSize = 33, - K_ESteamNetworkingConfig_Unencrypted = 34, - K_ESteamNetworkingConfig_SymmetricConnect = 37, - K_ESteamNetworkingConfig_LocalVirtualPort = 38, - K_ESteamNetworkingConfig_DualWifi_Enable = 39, - K_ESteamNetworkingConfig_EnableDiagnosticsUI = 46, - K_ESteamNetworkingConfig_FakePacketLoss_Send = 2, - K_ESteamNetworkingConfig_FakePacketLoss_Recv = 3, - K_ESteamNetworkingConfig_FakePacketLag_Send = 4, - K_ESteamNetworkingConfig_FakePacketLag_Recv = 5, - K_ESteamNetworkingConfig_FakePacketReorder_Send = 6, - K_ESteamNetworkingConfig_FakePacketReorder_Recv = 7, - K_ESteamNetworkingConfig_FakePacketReorder_Time = 8, - K_ESteamNetworkingConfig_FakePacketDup_Send = 26, - K_ESteamNetworkingConfig_FakePacketDup_Recv = 27, - K_ESteamNetworkingConfig_FakePacketDup_TimeMax = 28, - K_ESteamNetworkingConfig_PacketTraceMaxBytes = 41, - K_ESteamNetworkingConfig_FakeRateLimit_Send_Rate = 42, - K_ESteamNetworkingConfig_FakeRateLimit_Send_Burst = 43, - K_ESteamNetworkingConfig_FakeRateLimit_Recv_Rate = 44, - K_ESteamNetworkingConfig_FakeRateLimit_Recv_Burst = 45, - K_ESteamNetworkingConfig_Callback_ConnectionStatusChanged = 201, - K_ESteamNetworkingConfig_Callback_AuthStatusChanged = 202, - K_ESteamNetworkingConfig_Callback_RelayNetworkStatusChanged = 203, - K_ESteamNetworkingConfig_Callback_MessagesSessionRequest = 204, - K_ESteamNetworkingConfig_Callback_MessagesSessionFailed = 205, - K_ESteamNetworkingConfig_Callback_CreateConnectionSignaling = 206, - K_ESteamNetworkingConfig_Callback_FakeIPResult = 207, - K_ESteamNetworkingConfig_P2P_STUN_ServerList = 103, - K_ESteamNetworkingConfig_P2P_Transport_ICE_Enable = 104, - K_ESteamNetworkingConfig_P2P_Transport_ICE_Penalty = 105, - K_ESteamNetworkingConfig_P2P_Transport_SDR_Penalty = 106, - K_ESteamNetworkingConfig_P2P_TURN_ServerList = 107, - K_ESteamNetworkingConfig_P2P_TURN_UserList = 108, - K_ESteamNetworkingConfig_P2P_TURN_PassList = 109, - K_ESteamNetworkingConfig_P2P_Transport_ICE_Implementation = 110, - K_ESteamNetworkingConfig_SDRClient_ConsecutitivePingTimeoutsFailInitial = 19, - K_ESteamNetworkingConfig_SDRClient_ConsecutitivePingTimeoutsFail = 20, - K_ESteamNetworkingConfig_SDRClient_MinPingsBeforePingAccurate = 21, - K_ESteamNetworkingConfig_SDRClient_SingleSocket = 22, - K_ESteamNetworkingConfig_SDRClient_ForceRelayCluster = 29, - K_ESteamNetworkingConfig_SDRClient_DebugTicketAddress = 30, - K_ESteamNetworkingConfig_SDRClient_ForceProxyAddr = 31, - K_ESteamNetworkingConfig_SDRClient_FakeClusterPing = 36, - K_ESteamNetworkingConfig_LogLevel_AckRTT = 13, - K_ESteamNetworkingConfig_LogLevel_PacketDecode = 14, - K_ESteamNetworkingConfig_LogLevel_Message = 15, - K_ESteamNetworkingConfig_LogLevel_PacketGaps = 16, - K_ESteamNetworkingConfig_LogLevel_P2PRendezvous = 17, - K_ESteamNetworkingConfig_LogLevel_SDRRelayPings = 18, - K_ESteamNetworkingConfig_DELETED_EnumerateDevVars = 35, - K_ESteamNetworkingConfigValue__Force32Bit = 2147483647, -}; -Q_ENUM_NS(ESteamNetworkingConfigValue) - -enum class ESteamNetworkingGetConfigValueResult { - K_ESteamNetworkingGetConfigValue_BadValue = -1, - K_ESteamNetworkingGetConfigValue_BadScopeObj = -2, - K_ESteamNetworkingGetConfigValue_BufferTooSmall = -3, - K_ESteamNetworkingGetConfigValue_OK = 1, - K_ESteamNetworkingGetConfigValue_OKInherited = 2, - K_ESteamNetworkingGetConfigValueResult__Force32Bit = 2147483647, -}; -Q_ENUM_NS(ESteamNetworkingGetConfigValueResult) - -enum class ESteamNetworkingSocketsDebugOutputType { - K_ESteamNetworkingSocketsDebugOutputType_None = 0, - K_ESteamNetworkingSocketsDebugOutputType_Bug = 1, - K_ESteamNetworkingSocketsDebugOutputType_Error = 2, - K_ESteamNetworkingSocketsDebugOutputType_Important = 3, - K_ESteamNetworkingSocketsDebugOutputType_Warning = 4, - K_ESteamNetworkingSocketsDebugOutputType_Msg = 5, - K_ESteamNetworkingSocketsDebugOutputType_Verbose = 6, - K_ESteamNetworkingSocketsDebugOutputType_Debug = 7, - K_ESteamNetworkingSocketsDebugOutputType_Everything = 8, - K_ESteamNetworkingSocketsDebugOutputType__Force32Bit = 2147483647, -}; -Q_ENUM_NS(ESteamNetworkingSocketsDebugOutputType) - -enum class EServerMode { - EServerModeInvalid = 0, - EServerModeNoAuthentication = 1, - EServerModeAuthentication = 2, - EServerModeAuthenticationAndSecure = 3, -}; -Q_ENUM_NS(EServerMode) - -} diff --git a/ScreenPlayWorkshop/qml/SteamWorkshop.qml b/ScreenPlayWorkshop/qml/SteamWorkshop.qml index 9b808137..cf532f7f 100644 --- a/ScreenPlayWorkshop/qml/SteamWorkshop.qml +++ b/ScreenPlayWorkshop/qml/SteamWorkshop.qml @@ -4,7 +4,7 @@ import QtQuick.Controls.Material import Qt5Compat.GraphicalEffects import QtQuick.Layouts import ScreenPlayWorkshop -import WorkshopEnums +import ScreenPlayUtil import "upload/" Item { diff --git a/ScreenPlayWorkshop/qml/SteamWorkshopStartPage.qml b/ScreenPlayWorkshop/qml/SteamWorkshopStartPage.qml index b2ea7101..b6de009d 100644 --- a/ScreenPlayWorkshop/qml/SteamWorkshopStartPage.qml +++ b/ScreenPlayWorkshop/qml/SteamWorkshopStartPage.qml @@ -4,7 +4,7 @@ import QtQuick.Controls.Material import Qt5Compat.GraphicalEffects import QtQuick.Layouts import ScreenPlayWorkshop -import WorkshopEnums +import ScreenPlayUtil as Util import "upload/" Item { @@ -319,7 +319,7 @@ Item { print("EDITING FINISHED", root.state); if (tiSearch.text === "") { Qt.callLater(function () { - root.steamWorkshop.searchWorkshop(SteamEnums.K_EUGCQuery_RankedByTrend); + root.steamWorkshop.searchWorkshop(Util.Steam.EUGCQuery.K_EUGCQuery_RankedByTrend); }); return; } @@ -344,7 +344,7 @@ Item { root.state = "searching"; tiSearch.clear(); Qt.callLater(function () { - root.steamWorkshop.searchWorkshop(SteamEnums.K_EUGCQuery_RankedByTrend); + root.steamWorkshop.searchWorkshop(Util.Steam.EUGCQuery.K_EUGCQuery_RankedByTrend); }); return; } @@ -400,34 +400,34 @@ Item { currentIndex: 2 Layout.preferredHeight: searchWrapper.height model: [{ - "value": SteamEnums.k_EUGCQuery_RankedByVote, + "value": Util.Steam.EUGCQuery.K_EUGCQuery_RankedByVote, "text": qsTr("Ranked By Vote") }, { - "value": SteamEnums.K_EUGCQuery_RankedByPublicationDate, + "value": Util.Steam.EUGCQuery.K_EUGCQuery_RankedByPublicationDate, "text": qsTr("Publication Date") }, { - "value": SteamEnums.K_EUGCQuery_RankedByTrend, + "value": Util.Steam.EUGCQuery.K_EUGCQuery_RankedByTrend, "text": qsTr("Ranked By Trend") }, { - "value": SteamEnums.K_EUGCQuery_FavoritedByFriendsRankedByPublicationDate, + "value": Util.Steam.EUGCQuery.K_EUGCQuery_FavoritedByFriendsRankedByPublicationDate, "text": qsTr("Favorited By Friends") }, { - "value": SteamEnums.K_EUGCQuery_CreatedByFriendsRankedByPublicationDate, + "value": Util.Steam.EUGCQuery.K_EUGCQuery_CreatedByFriendsRankedByPublicationDate, "text": qsTr("Created By Friends") }, { - "value": SteamEnums.K_EUGCQuery_CreatedByFollowedUsersRankedByPublicationDate, + "value": Util.Steam.EUGCQuery.K_EUGCQuery_CreatedByFollowedUsersRankedByPublicationDate, "text": qsTr("Created By Followed Users") }, { - "value": SteamEnums.K_EUGCQuery_NotYetRated, + "value": Util.Steam.EUGCQuery.K_EUGCQuery_NotYetRated, "text": qsTr("Not Yet Rated") }, { - "value": SteamEnums.K_EUGCQuery_RankedByTotalVotesAsc, + "value": Util.Steam.EUGCQuery.K_EUGCQuery_RankedByTotalVotesAsc, "text": qsTr("Total VotesAsc") }, { - "value": SteamEnums.K_EUGCQuery_RankedByVotesUp, + "value": Util.Steam.EUGCQuery.K_EUGCQuery_RankedByVotesUp, "text": qsTr("Votes Up") }, { - "value": SteamEnums.K_EUGCQuery_RankedByTotalUniqueSubscriptions, + "value": Util.Steam.EUGCQuery.K_EUGCQuery_RankedByTotalUniqueSubscriptions, "text": qsTr("Total Unique Subscriptions") }] onActivated: { @@ -481,7 +481,7 @@ Item { onClicked: { root.state = "searching"; root.steamWorkshop.workshopListModel.setCurrentPage(root.steamWorkshop.workshopListModel.currentPage - 1); - root.steamWorkshop.searchWorkshop(SteamEnums.K_EUGCQuery_RankedByTrend); + root.steamWorkshop.searchWorkshop(Util.Steam.EUGCQuery.K_EUGCQuery_RankedByTrend); } } @@ -502,7 +502,7 @@ Item { onClicked: { root.state = "searching"; root.steamWorkshop.workshopListModel.setCurrentPage(root.steamWorkshop.workshopListModel.currentPage + 1); - root.steamWorkshop.searchWorkshop(SteamEnums.K_EUGCQuery_RankedByTrend); + root.steamWorkshop.searchWorkshop(Util.Steam.EUGCQuery.K_EUGCQuery_RankedByTrend); } } @@ -512,7 +512,7 @@ Item { } } - Behavior on contentHeight { + Behavior on contentHeight { PropertyAnimation { duration: 400 property: "contentHeight" diff --git a/ScreenPlayWorkshop/qml/Workshop.qml b/ScreenPlayWorkshop/qml/Workshop.qml index d590c414..44d6bc5f 100644 --- a/ScreenPlayWorkshop/qml/Workshop.qml +++ b/ScreenPlayWorkshop/qml/Workshop.qml @@ -3,7 +3,6 @@ import QtQuick.Controls import QtQuick.Controls.Material import Qt5Compat.GraphicalEffects import QtQuick.Layouts -import Settings import ScreenPlay Item { diff --git a/ScreenPlayWorkshop/qml/upload/UploadProjectItem.qml b/ScreenPlayWorkshop/qml/upload/UploadProjectItem.qml index 124ada92..1691fc9e 100644 --- a/ScreenPlayWorkshop/qml/upload/UploadProjectItem.qml +++ b/ScreenPlayWorkshop/qml/upload/UploadProjectItem.qml @@ -5,7 +5,7 @@ import QtQuick.Controls.Material import QtQuick.Layouts import QtQuick.Controls.Material.impl import ScreenPlayWorkshop -import WorkshopEnums +import ScreenPlayUtil Page { id: root diff --git a/ScreenPlayWorkshop/src/TestMain.cpp b/ScreenPlayWorkshop/src/TestMain.cpp index 1c2e1fde..cff39913 100644 --- a/ScreenPlayWorkshop/src/TestMain.cpp +++ b/ScreenPlayWorkshop/src/TestMain.cpp @@ -1,25 +1,17 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only -#include "steam/steam_qt_enums_generated.h" +#include "ScreenPlayUtil/steamenumsgenerated.h" #include #include #include #include Q_IMPORT_QML_PLUGIN(ScreenPlayWorkshopPlugin) +Q_IMPORT_QML_PLUGIN(ScreenPlayUtilPlugin) int main(int argc, char* argv[]) { QGuiApplication app(argc, argv); - // TODO: This is a workaround because I don't know how to - // init this in the ScreenPlayWorkshop plugin. - // Move to workshop plugin. - qmlRegisterUncreatableMetaObject(ScreenPlayWorkshopSteamEnums::staticMetaObject, - "WorkshopEnums", - 1, 0, - "SteamEnums", - "Error: only enums"); - // Must be set so we can access the global ScreenPlay settings like install path. QGuiApplication::setOrganizationName("ScreenPlay"); QGuiApplication::setOrganizationDomain("screen-play.app"); diff --git a/ScreenPlayWorkshop/src/steamapiwrapper.cpp b/ScreenPlayWorkshop/src/steamapiwrapper.cpp index 6f214f24..a3f6d483 100644 --- a/ScreenPlayWorkshop/src/steamapiwrapper.cpp +++ b/ScreenPlayWorkshop/src/steamapiwrapper.cpp @@ -10,7 +10,7 @@ #include "steam/steamtypes.h" #include "steamapiwrapper.h" -namespace SteamApiWrapper { +namespace ScreenPlay { bool setItemTags(const QVariant& updateHandle, const QStringList& tags) { auto pTags = std::make_unique(); diff --git a/ScreenPlayWorkshop/src/steamapiwrapper.h b/ScreenPlayWorkshop/src/steamapiwrapper.h index 983dbfac..eb8d7ac9 100644 --- a/ScreenPlayWorkshop/src/steamapiwrapper.h +++ b/ScreenPlayWorkshop/src/steamapiwrapper.h @@ -3,23 +3,23 @@ #include #include -#include "steam/steam_qt_enums_generated.h" +#include "ScreenPlayUtil/steamenumsgenerated.h" #include "steam/steamtypes.h" -namespace SteamApiWrapper { +namespace ScreenPlay { struct ItemUpdateData { QString m_title; QString m_description; QString m_updateLanguage; QString m_metadata; - ScreenPlayWorkshopSteamEnums::ERemoteStoragePublishedFileVisibility visibility; + ScreenPlay::Steam::ERemoteStoragePublishedFileVisibility visibility; QStringList m_tags; QString m_content; // update item content from this local folder QString m_preview; QMap m_keyValueTag; // add new key-value tags for the item. Note that there can be multiple values for a tag. QString m_changeNote; - QPair m_previewFile; - QPair m_previewVideo; + QPair m_previewFile; + QPair m_previewVideo; const char* title() const { return m_title.toUtf8().data(); } const char* description() const { return m_description.toUtf8().data(); } diff --git a/ScreenPlayWorkshop/src/steamworkshop.cpp b/ScreenPlayWorkshop/src/steamworkshop.cpp index 59db47ab..c07c4408 100644 --- a/ScreenPlayWorkshop/src/steamworkshop.cpp +++ b/ScreenPlayWorkshop/src/steamworkshop.cpp @@ -208,7 +208,7 @@ void SteamWorkshop::subscribeItem(const QVariant publishedFileID) m_steamAccount->loadAmountSubscribedItems(); } -bool SteamWorkshop::searchWorkshop(const ScreenPlayWorkshopSteamEnums::EUGCQuery enumEUGCQuery) +bool SteamWorkshop::searchWorkshop(const ScreenPlay::Steam::EUGCQuery enumEUGCQuery) { qInfo() << "searchWorkshop"; @@ -339,7 +339,7 @@ bool SteamWorkshop::queryWorkshopItemFromHandle(SteamWorkshopListModel* listMode return true; } -void SteamWorkshop::searchWorkshopByText(const QString text, const ScreenPlayWorkshopSteamEnums::EUGCQuery rankedBy) +void SteamWorkshop::searchWorkshopByText(const QString text, const ScreenPlay::Steam::EUGCQuery rankedBy) { qInfo() << "searchWorkshopByText" << text; diff --git a/ScreenPlayWorkshop/src/steamworkshop.h b/ScreenPlayWorkshop/src/steamworkshop.h index 18d6c977..694308c3 100644 --- a/ScreenPlayWorkshop/src/steamworkshop.h +++ b/ScreenPlayWorkshop/src/steamworkshop.h @@ -17,8 +17,8 @@ #include // Steam +#include "ScreenPlayUtil/steamenumsgenerated.h" #include "steam/steam_api.h" -#include "steam/steam_qt_enums_generated.h" #include "steamaccount.h" #include "steamworkshoplistmodel.h" @@ -87,9 +87,9 @@ public slots: void requestWorkshopItemDetails(const QVariant publishedFileID); void vote(const QVariant publishedFileID, const bool voteUp); void subscribeItem(const QVariant publishedFileID); - bool searchWorkshop(const ScreenPlayWorkshopSteamEnums::EUGCQuery enumEUGCQuery); + bool searchWorkshop(const ScreenPlay::Steam::EUGCQuery enumEUGCQuery); void searchWorkshopByText(const QString text, - const ScreenPlayWorkshopSteamEnums::EUGCQuery rankedBy = ScreenPlayWorkshopSteamEnums::EUGCQuery::K_EUGCQuery_RankedByTrend); + const ScreenPlay::Steam::EUGCQuery rankedBy = ScreenPlay::Steam::EUGCQuery::K_EUGCQuery_RankedByTrend); bool checkAndSetQueryActive() { diff --git a/ScreenPlayWorkshop/src/steamworkshopitem.cpp b/ScreenPlayWorkshop/src/steamworkshopitem.cpp index 5b5b4e3e..46dccc58 100644 --- a/ScreenPlayWorkshop/src/steamworkshopitem.cpp +++ b/ScreenPlayWorkshop/src/steamworkshopitem.cpp @@ -55,9 +55,9 @@ void SteamWorkshopItem::uploadItemToWorkshop(CreateItemResult_t* pCallback, bool return; } - const QString absoluteContentPath = ScreenPlayUtil::toLocal(m_absolutePath.toString()); - - auto jsonObjectOpt = ScreenPlayUtil::openJsonFileToObject(absoluteContentPath + "/project.json"); + ScreenPlay::Util util; + const QString absoluteContentPath = util.toLocal(m_absolutePath.toString()); + auto jsonObjectOpt = util.openJsonFileToObject(absoluteContentPath + "/project.json"); if (!jsonObjectOpt.has_value()) { qWarning() << "Unable to load project file"; @@ -187,7 +187,7 @@ void SteamWorkshopItem::submitItemUpdateStatus(SubmitItemUpdateResult_t* pCallba if (pCallback->m_bUserNeedsToAcceptWorkshopLegalAgreement) emit userNeedsToAcceptWorkshopLegalAgreement(); - setStatus(static_cast(pCallback->m_eResult)); + setStatus(static_cast(pCallback->m_eResult)); switch (pCallback->m_eResult) { case EResult::k_EResultOK: { @@ -212,9 +212,10 @@ void SteamWorkshopItem::submitItemUpdateStatus(SubmitItemUpdateResult_t* pCallba void SteamWorkshopItem::saveWorkshopID() { + ScreenPlay::Util util; const QString path = QUrl::fromUserInput(m_absolutePath.toString() + "/project.json").toLocalFile(); qInfo() << m_absolutePath << m_publishedFileId << path; - auto jsonProject = ScreenPlayUtil::openJsonFileToObject(path); + auto jsonProject = util.openJsonFileToObject(path); if (!jsonProject.has_value()) { qWarning() << "Could not parse project file!"; @@ -225,7 +226,7 @@ void SteamWorkshopItem::saveWorkshopID() jsonObject.insert("workshopid", m_publishedFileId.toString()); qInfo() << "Writing workshopID: " << m_publishedFileId.toString() << "into: " << path; - if (!ScreenPlayUtil::writeJsonObjectToFile(path, jsonObject)) { + if (!util.writeJsonObjectToFile(path, jsonObject)) { qWarning() << "Could not write project file!"; } } diff --git a/ScreenPlayWorkshop/src/steamworkshopitem.h b/ScreenPlayWorkshop/src/steamworkshopitem.h index 8500fcf1..9f0492fe 100644 --- a/ScreenPlayWorkshop/src/steamworkshopitem.h +++ b/ScreenPlayWorkshop/src/steamworkshopitem.h @@ -15,10 +15,10 @@ #include // Steam +#include "ScreenPlayUtil/steamenumsgenerated.h" #include "cstring" #include "stdlib.h" #include "steam/steam_api.h" -#include "steam/steam_qt_enums_generated.h" #include "ScreenPlayUtil/util.h" #include "steamapiwrapper.h" @@ -32,7 +32,7 @@ class SteamWorkshopItem : public QObject { Q_PROPERTY(QUrl absolutePath READ absolutePath WRITE setAbsolutePath NOTIFY absolutePathChanged) Q_PROPERTY(int uploadProgress READ uploadProgress WRITE setUploadProgress NOTIFY uploadProgressChanged) Q_PROPERTY(QUrl absolutePreviewImagePath READ absolutePreviewImagePath WRITE setAbsolutePreviewImagePath NOTIFY absolutePreviewImagePathChanged) - Q_PROPERTY(ScreenPlayWorkshopSteamEnums::EResult status READ status WRITE setStatus NOTIFY statusChanged) + Q_PROPERTY(ScreenPlay::Steam::EResult status READ status WRITE setStatus NOTIFY statusChanged) Q_PROPERTY(QVariant publishedFileId READ publishedFileId WRITE setPublishedFileId NOTIFY publishedFileIdChanged) public: @@ -45,7 +45,7 @@ public: QUrl absolutePath() const { return m_absolutePath; } int uploadProgress() const { return m_uploadProgress; } QUrl absolutePreviewImagePath() const { return m_absolutePreviewImagePath; } - ScreenPlayWorkshopSteamEnums::EResult status() const { return m_status; } + ScreenPlay::Steam::EResult status() const { return m_status; } QVariant publishedFileId() const { return m_publishedFileId; } public slots: @@ -90,7 +90,7 @@ public slots: emit absolutePreviewImagePathChanged(m_absolutePreviewImagePath); } - void setStatus(ScreenPlayWorkshopSteamEnums::EResult status) + void setStatus(ScreenPlay::Steam::EResult status) { if (m_status == status) return; @@ -115,7 +115,7 @@ signals: void removeThis(SteamWorkshopItem* item); void absolutePreviewImagePathChanged(QUrl absolutePreviewImagePath); void uploadComplete(bool successful); - void statusChanged(ScreenPlayWorkshopSteamEnums::EResult status); + void statusChanged(ScreenPlay::Steam::EResult status); void uploadFailed(const quint64 m_PublishedFileId); void userNeedsToAcceptWorkshopLegalAgreement(); void publishedFileIdChanged(QVariant publishedFileId); @@ -136,7 +136,7 @@ private: quint64 m_appID { 0 }; const int m_updateTimerInterval { 500 }; int m_uploadProgress { 0 }; // 0 - 100 - ScreenPlayWorkshopSteamEnums::EResult m_status { ScreenPlayWorkshopSteamEnums::EResult::K_EResultNone }; + ScreenPlay::Steam::EResult m_status { ScreenPlay::Steam::EResult::K_EResultNone }; UGCUpdateHandle_t m_UGCUpdateHandle { 0 }; SubmitItemUpdateResult_t m_submitItemUpdateResultHanlde; QTimer m_updateTimer; diff --git a/ScreenPlayWorkshop/src/steamworkshoplistmodel.h b/ScreenPlayWorkshop/src/steamworkshoplistmodel.h index e8a05846..2d4ced8e 100644 --- a/ScreenPlayWorkshop/src/steamworkshoplistmodel.h +++ b/ScreenPlayWorkshop/src/steamworkshoplistmodel.h @@ -11,10 +11,10 @@ #include "workshopitem.h" // Steam +#include "ScreenPlayUtil/steamenumsgenerated.h" #include "cstring" #include "stdlib.h" #include "steam/steam_api.h" -#include "steam/steam_qt_enums_generated.h" /*! \class Steam Workshop List Model diff --git a/ScreenPlayWorkshop/src/uploadlistmodel.h b/ScreenPlayWorkshop/src/uploadlistmodel.h index 238b511c..d9db8153 100644 --- a/ScreenPlayWorkshop/src/uploadlistmodel.h +++ b/ScreenPlayWorkshop/src/uploadlistmodel.h @@ -6,7 +6,7 @@ #include #include -#include "steam/steam_qt_enums_generated.h" +#include "ScreenPlayUtil/steamenumsgenerated.h" #include "steamworkshopitem.h" namespace ScreenPlayWorkshop { @@ -116,12 +116,12 @@ public slots: QObject::connect(item.get(), &SteamWorkshopItem::uploadComplete, this, [=](bool successful) { onDataChanged(); }); - QObject::connect(item.get(), &SteamWorkshopItem::statusChanged, this, [=](ScreenPlayWorkshopSteamEnums::EResult status) { + QObject::connect(item.get(), &SteamWorkshopItem::statusChanged, this, [=](ScreenPlay::Steam::EResult status) { onDataChanged(); bool allItemsUploaded = std::all_of(m_uploadListModelItems.cbegin(), m_uploadListModelItems.cend(), [](const auto& item) { const auto status = item->status(); - return status == ScreenPlayWorkshopSteamEnums::EResult::K_EResultOK || status == ScreenPlayWorkshopSteamEnums::EResult::K_EResultFail; + return status == ScreenPlay::Steam::EResult::K_EResultOK || status == ScreenPlay::Steam::EResult::K_EResultFail; }); if (allItemsUploaded) { diff --git a/ThirdParty/CMakeLists.txt b/ThirdParty/CMakeLists.txt index 01ad0a83..684f2937 100644 --- a/ThirdParty/CMakeLists.txt +++ b/ThirdParty/CMakeLists.txt @@ -11,24 +11,22 @@ FetchContent_Populate( FetchContent_Populate( qml-plausible GIT_REPOSITORY https://gitlab.com/kelteseth/qml-plausible.git - GIT_TAG 5069ba3bf25663ea06be8b94c398d6c61058d4d5 + GIT_TAG 322d8e17cab77b496f0d7fafb19f6dcda4193ed7 # Workaround because: 1. QtCreator cannot handle QML_ELEMENT stuff when it is in bin folder # https://bugreports.qt.io/browse/QTCREATORBUG-27083 SOURCE_DIR ${THIRD_PARTY_PATH}/qml-plausible) - - add_subdirectory(qml-plausible) add_subdirectory(QArchive) if(UNIX AND NOT APPLE) -FetchContent_Populate( - qt-layer-shell - GIT_REPOSITORY https://github.com/KDE/layer-shell-qt.git - GIT_TAG 721c0ae334554eb2396a2d4d3358f896b8c77412 - # Workaround because: 1. QtCreator cannot handle QML_ELEMENT stuff when it is in bin folder - # https://bugreports.qt.io/browse/QTCREATORBUG-27083 - SOURCE_DIR ${THIRD_PARTY_PATH}/qt-layer-shell) + FetchContent_Populate( + qt-layer-shell + GIT_REPOSITORY https://github.com/KDE/layer-shell-qt.git + GIT_TAG 721c0ae334554eb2396a2d4d3358f896b8c77412 + # Workaround because: 1. QtCreator cannot handle QML_ELEMENT stuff when it is in bin folder + # https://bugreports.qt.io/browse/QTCREATORBUG-27083 + SOURCE_DIR ${THIRD_PARTY_PATH}/qt-layer-shell) add_subdirectory(qt-layer-shell) -endif() \ No newline at end of file +endif() diff --git a/Tools/CMakeLists.txt b/Tools/CMakeLists.txt index fe0069a5..d48f0245 100644 --- a/Tools/CMakeLists.txt +++ b/Tools/CMakeLists.txt @@ -9,3 +9,10 @@ add_custom_target( ${PROJECT_NAME} SOURCES ${FILES} ${PYTHON} COMMENT "Dummy target to list these files in the IDE") + +set(GODOT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../ThirdParty/Godot") + +if(WIN32 AND ${SCREENPLAY_GODOT}) + # Todo: Add Linux and Mac support + configure_file(${GODOT_PATH}/${GODOT_EDITOR_NAME} ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/ COPYONLY) +endif() diff --git a/Tools/Steam/ContentBuilder/builder_osx/crashhandler.dylib b/Tools/Steam/ContentBuilder/builder_osx/crashhandler.dylib index f03ebedc..af656277 100755 Binary files a/Tools/Steam/ContentBuilder/builder_osx/crashhandler.dylib and b/Tools/Steam/ContentBuilder/builder_osx/crashhandler.dylib differ diff --git a/Tools/Steam/ContentBuilder/builder_osx/steamcmd b/Tools/Steam/ContentBuilder/builder_osx/steamcmd index 72f04ff3..c7379948 100755 Binary files a/Tools/Steam/ContentBuilder/builder_osx/steamcmd and b/Tools/Steam/ContentBuilder/builder_osx/steamcmd differ diff --git a/Tools/build.py b/Tools/build.py index 7f312a90..d73c0d7b 100755 --- a/Tools/build.py +++ b/Tools/build.py @@ -13,7 +13,8 @@ from build_config import BuildConfig from typing import Tuple from pathlib import Path import macos_sign -from util import sha256, cd_repo_root_path, repo_root_path, zipdir, run, get_vs_env_dict, get_latest_git_tag, parse_semver, semver_to_string +import build_godot +from util import sha256, cd_repo_root_path, repo_root_path, zipdir, run, get_vs_env_dict, get_latest_git_tag, parse_semver, semver_to_string, check_universal_binary from sys import stdout stdout.reconfigure(encoding='utf-8') @@ -50,6 +51,13 @@ def execute( build_result = build(build_config, build_result) build_duration = time.time() - step_time print(f"โฑ๏ธ build_duration: {build_duration}s") + + + # Build Godot Wallpaper + # Note: This must happen after building ScreenPlay! + if platform.system() == "Windows": + build_godot.build_godot(str(build_config.bin_dir), build_config.build_type) + # Copies all needed libraries and assets into the bin folder step_time = time.time() @@ -70,10 +78,26 @@ def execute( print(f"โฑ๏ธ build_installer_duration: {build_installer_duration}s") if platform.system() == "Darwin": + # TODO FIX installer signing + return if (build_config.sign_osx): + # Base directory + base_dir = Path(build_config.build_folder) + + # Paths for the original and new filenames + original_file = base_dir / 'ScreenPlay-Installer-ScreenPlayComponent.dmg' + new_file = base_dir / 'ScreenPlay-Installer.dmg' + + # Renaming the file + try: + original_file.rename(new_file) + print(f"File renamed successfully to {new_file}") + except OSError as error: + print(f"Error: {error}") + print( - f"Sign ScreenPlay-installer.dmg at: {build_config.bin_dir}") - macos_sign.sign_dmg(build_config=build_config) + f"Sign ScreenPlay-installer.dmg at: {new_file}") + macos_sign.sign_dmg(build_config) # Create a zip file of the build if platform.system() != "Darwin": @@ -211,6 +235,8 @@ def package(build_config: BuildConfig): build_bin_dir=build_bin_dir, app="ScreenPlayWallpaper"), cwd=cwd) run(cmd=cmd_raw.format(qt_bin_path=qt_bin_path, repo_root_path=source_path, build_bin_dir=build_bin_dir, app="ScreenPlayWidget"), cwd=cwd) + + check_universal_binary() if platform.system() == "Windows": print("Executing deploy commands...") @@ -278,14 +304,6 @@ def package(build_config: BuildConfig): print("Copy: ", file, build_config.bin_dir) shutil.copy2(file, build_config.bin_dir) - # Use Qt OpenSSLv3 - openSLL_path = Path( - f"{defines.QT_PATH}/Tools/OpenSSLv3/Win_x64/bin").resolve() - for file in openSLL_path.iterdir(): - if file.suffix == ".dll" and file.is_file(): - print("Copy: ", file, build_config.bin_dir) - shutil.copy2(file, build_config.bin_dir) - if not platform.system() == "Darwin": file_endings = [".ninja_deps", ".ninja", ".ninja_log", ".lib", ".a", ".exp", ".manifest", ".cmake", ".cbp", "CMakeCache.txt"] @@ -294,6 +312,7 @@ def package(build_config: BuildConfig): if file.is_file(): print("Remove: %s" % file.resolve()) file.unlink() + def build_installer(build_config: BuildConfig, build_result: BuildResult): @@ -384,7 +403,7 @@ if __name__ == "__main__": qt_ifw_version = args.qt_installer_version_overwrite print("Using Qt installer framework version {qt_ifw_version}") - build_type = args.build_type + build_type = args.build_type.lower() build_steam = "OFF" if args.build_steam: diff --git a/Tools/build_config.py b/Tools/build_config.py index 0241c29b..6099cd71 100644 --- a/Tools/build_config.py +++ b/Tools/build_config.py @@ -1,6 +1,7 @@ +#!/usr/bin/python3 +# SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only class BuildConfig: root_path: str - cmake_osx_architectures: str cmake_target_triplet: str package: bool osx_bundle: str @@ -25,5 +26,6 @@ class BuildConfig: build_deploy: str build_type: str build_architecture: str + build_godot: str create_installer: str sign_osx: bool diff --git a/Tools/build_godot.py b/Tools/build_godot.py new file mode 100644 index 00000000..e3e9eef0 --- /dev/null +++ b/Tools/build_godot.py @@ -0,0 +1,76 @@ +#!/usr/bin/python3 +# SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only +import os +import util +import shutil +import defines +from pathlib import Path +from execute_util import execute +import argparse + + +def main(): + # Parse build folder as arugment + + parser = argparse.ArgumentParser(description='Build K3000Map to the bin build folder: D:/Backup/Code/Qt/build_ScreenPlay_Qt_6.6.1_MSVC_Debug/bin') + parser.add_argument('--build_path', dest="build_path", type=str, help='Build folder') + parser.add_argument('--skip_if_exists', dest="skip_if_exists", default=False, action="store_true", help='Skips the build if the index.html file exists. This is used for faster CMake configure') + + args = parser.parse_args() + + if not args.build_path: + print("ERROR: Please specify the build folder") + print("py build_godot.py --build_path D:/Backup/Code/Qt/build_ScreenPlay_Qt_6.6.1_MSVC_Debug/bin/") + exit() + + # if build path exists and contains a index.html file, skip the build + if args.skip_if_exists: + screenPlayWallpaperGodot_executable = Path(args.build_path).joinpath(defines.SCREENPLAYWALLPAPER_GODOT_EXECUTABLE) + if screenPlayWallpaperGodot_executable.exists: + print(f"Skipping build, because {defines.SCREENPLAYWALLPAPER_GODOT_EXECUTABLE} exists") + exit(1) + + abs_build_path = args.build_path + if not os.path.isabs(args.build_path): + abs_build_path = os.path.abspath(os.path.join(os.getcwd(), args.build_path)) + + if 'Debug' in abs_build_path: + build_type = "debug" + else: + build_type = "release" + + build_godot(abs_build_path, build_type) + +def build_godot(abs_build_path: str, build_type: str): + project_path = Path(util.repo_root_path()).joinpath("ScreenPlayWallpaper/Godot/ScreenPlayGodot").resolve() + apps_path = os.path.join(defines.THIRDPATH_PATH,"Godot") + godot_executable = os.path.join(apps_path, defines.GODOT_EDITOR_EXECUTABLE) + screenPlayWallpaperGodot_executable = Path(abs_build_path).joinpath(defines.SCREENPLAYWALLPAPER_GODOT_EXECUTABLE).resolve() + + if 'debug' in build_type: + export_type = " --export-debug" + else: + export_type = " --export-release" + export_command = f'"{godot_executable}" -v --headless {export_type} "Windows Desktop" "{screenPlayWallpaperGodot_executable}"' + + # We get random error on successful export, so lets ignore it + execute(command=export_command,workingDir=project_path,ignore_error=True) + + if 'Debug' in abs_build_path: + lib_name = "ScreenPlayGodotWallpaper-d.dll" + else: + lib_name = "ScreenPlayGodotWallpaper.dll" + + # Construct the source path for the DLL + dll_source_path = project_path.joinpath(f"ScreenPlayGodotWallpaper/lib/Windows-AMD64/{lib_name}") + + # Print a warning message + print(f"โš ๏ธ Copying {dll_source_path} to {abs_build_path}") + + # Copy the DLL + shutil.copy(dll_source_path, abs_build_path) + + + +if __name__ == "__main__": + main() diff --git a/Tools/build_result.py b/Tools/build_result.py index d253123b..bebb2619 100644 --- a/Tools/build_result.py +++ b/Tools/build_result.py @@ -1,7 +1,7 @@ - +#!/usr/bin/python3 +# SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only from pathlib import Path - class BuildResult: # Windows example with absolute paths: # [...]/build-x64-windows-release/ diff --git a/Tools/check_format_qml.py b/Tools/check_format_qml.py index f824c114..2e463767 100644 --- a/Tools/check_format_qml.py +++ b/Tools/check_format_qml.py @@ -1,4 +1,5 @@ #!/usr/bin/python3 +# SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only import os import subprocess import argparse diff --git a/Tools/create_sha512.py b/Tools/create_sha512.py index 79ee704d..b17b1a99 100644 --- a/Tools/create_sha512.py +++ b/Tools/create_sha512.py @@ -1,3 +1,5 @@ +#!/usr/bin/python3 +# SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only import hashlib import os from pathlib import Path diff --git a/Tools/defines.py b/Tools/defines.py index 3650ae32..3bb50ee5 100644 --- a/Tools/defines.py +++ b/Tools/defines.py @@ -18,13 +18,46 @@ elif sys.platform == "linux": OS = "linux" QT_PLATFORM = "gcc_64" -QT_PATH = path = Path(os.path.join( - os.path.realpath(__file__), "../../../aqt")).resolve() -QT_VERSION = "6.5.2" +REPO_PATH = Path(__file__, "../../").resolve() +THIRDPATH_PATH = Path(REPO_PATH, "ThirdParty").resolve() +QT_PATH = path = Path(REPO_PATH, "../aqt").resolve() +QT_VERSION = "6.6.1" QT_BIN_PATH = QT_PATH.joinpath(f"{QT_VERSION}/{QT_PLATFORM}/bin") QT_TOOLS_PATH = QT_PATH.joinpath("Tools/") QT_IFW_VERSION = "4.6" -# 02.06.2023 https://gitlab.com/kelteseth/screenplay-vcpkg : -VCPKG_VERSION = "f06975f46d8c7a1dad916e1e997584f77ae0c34a" +# 25.11.2023 https://gitlab.com/kelteseth/screenplay-vcpkg : +VCPKG_VERSION = "cabba0d0379b78e34d0a0d37edb4c459c5a03337" +VCPKG_BASE_PACKAGES = [ + "curl", + "openssl", + "cpp-httplib", + "libarchive", + "fmt", + "catch2" + ] PYTHON_EXECUTABLE = "python" if sys.platform == "win32" else "python3" -FFMPEG_VERSION = "5.0.1" +FFMPEG_VERSION = "6.1" +GODOT_VERSION = "4.2" +GODOT_RELEASE_TYPE = "stable" +GODOT_DOWNLOAD_SERVER = "https://github.com/godotengine/godot-builds/releases/download" +if sys.platform == "win32": + SCREENPLAYWALLPAPER_GODOT_EXECUTABLE = "ScreenPlayWallpaperGodot.exe" + GODOT_EDITOR_EXECUTABLE = f"Godot_v{GODOT_VERSION}-{GODOT_RELEASE_TYPE}_win64.exe" + GODOT_EDITOR_DOWNLOAD_NAME = GODOT_EDITOR_EXECUTABLE + ".zip" + GODOT_TEMPLATES_PATH = os.path.join(os.getenv( + 'APPDATA'), f"Godot/templates/{GODOT_VERSION}.{GODOT_RELEASE_TYPE}") +elif sys.platform == "darwin": + SCREENPLAYWALLPAPER_GODOT_EXECUTABLE = "ScreenPlayWallpaperGodot.app" + # Godot_v4.2-beta6_macos.universal.zip + GODOT_EDITOR_EXECUTABLE = "Godot.app" + GODOT_EDITOR_DOWNLOAD_NAME = f"Godot_v{GODOT_VERSION}-{GODOT_RELEASE_TYPE}_macos.universal.zip" + GODOT_TEMPLATES_PATH = "TODO" +elif sys.platform == "linux": + SCREENPLAYWALLPAPER_GODOT_EXECUTABLE = "ScreenPlayWallpaperGodot" + # Godot_v4.2-beta6_linux.x86_64 + GODOT_EDITOR_EXECUTABLE = f"Godot_v{GODOT_VERSION}-{GODOT_RELEASE_TYPE}_linux.x86_64" + GODOT_EDITOR_DOWNLOAD_NAME = GODOT_EDITOR_EXECUTABLE + ".zip" + # /home/eli/.local/share/godot/templates/ + GODOT_TEMPLATES_PATH = os.path.join( + Path.home(), f".local/share/godot/templates/{GODOT_VERSION}.{GODOT_RELEASE_TYPE}") + diff --git a/Tools/download_ffmpeg.py b/Tools/download_ffmpeg.py index cd48ac63..959bfd15 100644 --- a/Tools/download_ffmpeg.py +++ b/Tools/download_ffmpeg.py @@ -1,14 +1,17 @@ #!/usr/bin/python3 # SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only from fileinput import filename +import sys from zipfile import ZipFile import platform from urllib.request import urlopen +import subprocess import os import defines from shutil import move, rmtree from util import cd_repo_root_path from sys import stdout +from defines import FFMPEG_VERSION stdout.reconfigure(encoding='utf-8') @@ -99,13 +102,44 @@ def download_prebuild_ffmpeg_windows(extraction_path: str): extract_zip_executables(extraction_path, ffmpeg_path_and_filename) -def execute(): +def execute() ->bool: # Make sure the script is always started from the same folder root_path = cd_repo_root_path() extraction_path = os.path.join(root_path, "ThirdParty/ffmpeg") + ffmpeg_binary_path = os.path.join(extraction_path, "ffmpeg") # Adjust this if FFmpeg binary is inside another subdirectory + + if sys.platform == "win32": + ffmpeg_binary_path += ".exe" + + # Check if ffmpeg is already installed and matches the required version + if os.path.isfile(ffmpeg_binary_path): + result = subprocess.run([ffmpeg_binary_path, "-version"], capture_output=True, text=True) + output = result.stdout + version_line = next((line for line in output.split('\n') if 'ffmpeg version' in line), None) + if version_line: + installed_version = version_line.split(' ')[2].split('-')[0] + if installed_version == FFMPEG_VERSION: + print(f"FFmpeg version {installed_version} is already installed.") + return True + else: + print(f"FFmpeg version {installed_version} found, but version {FFMPEG_VERSION} is required.") + + try: + if os.path.exists(extraction_path): + rmtree(extraction_path) + print("Directory removed successfully.") + except Exception as e: + print(f"An error occurred while trying to remove the directory: {str(e)}") + return False + + try: + if os.path.exists(extraction_path): + rmtree(extraction_path) + print("Directory removed successfully.") + except Exception as e: + print(f"An error occurred while trying to remove the directory: {str(e)}") + return False - if os.path.exists(extraction_path): - rmtree(extraction_path) os.makedirs(extraction_path) @@ -113,6 +147,8 @@ def execute(): download_prebuild_ffmpeg_windows(extraction_path) elif platform.system() == "Darwin": download_prebuild_ffmpeg_mac(extraction_path) + + return True if __name__ == "__main__": diff --git a/Tools/macos_make_universal.py b/Tools/macos_make_universal.py new file mode 100644 index 00000000..b3817a4a --- /dev/null +++ b/Tools/macos_make_universal.py @@ -0,0 +1,95 @@ +#!/usr/bin/python3 +# SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only +from distutils.dir_util import mkpath +import os +import subprocess +from pathlib import Path +import util +from util import run, run_and_capture_output +from sys import stdout + +stdout.reconfigure(encoding='utf-8') + + +def listfiles(path): + files = [] + ignored = ('.DS_Store',) # Ignored files + print(f"WALK: {path}") + + for dirName, _, fileList in os.walk(path): + for fname in fileList: + if fname in ignored: + continue # Skip ignored files + + file_path = os.path.join(dirName, fname) + if os.path.isfile(file_path) and (fname.endswith('.a')): + files.append(file_path) + if os.path.islink(file_path): + print(f"Warning: file {file_path} is a symlink!") + print("Symlink target: ", os.readlink(file_path)) + return files + +def is_mach_o_binary(file_path): + """ + Check if a file is a Mach-O binary using the file command. + """ + try: + result = subprocess.run(["file", file_path], capture_output=True, text=True) + return 'Mach-O' in result.stdout + except Exception as e: + print(f"Error checking file type of {file_path}: {e}") + return False + +# Merges x64 and arm64 vcpkg build into universal +def run_lipo(): + workspace_path = util.workspace_path() + vcpkg_installed_path = str(Path(workspace_path).joinpath("vcpkg/installed/").absolute()) + arm64_dir = f"{vcpkg_installed_path}/arm64-osx" + x64_dir = f"{vcpkg_installed_path}/x64-osx" + universal_dir = f"{vcpkg_installed_path}/64-osx-universal" + # Ensure the universal directory is created and empty + run(f"rm -rf {universal_dir}", workspace_path) + # Copy the x64 build as a base for the universal build + run(f"cp -a {arm64_dir} {universal_dir}", workspace_path) + + files = listfiles(str(universal_dir)) + + for file in files: + # Extract the relative path for file + rel_path = os.path.relpath(file, universal_dir) + + # Construct the corresponding arm64 and x64 file paths + arm64_file = os.path.join(arm64_dir, rel_path) + x64_file = os.path.join(x64_dir, rel_path) + universal_file = file # file is already in universal_dir + + #and is_mach_o_binary(arm64_file) + if os.path.exists(x64_file) : + run(f"lipo -create {arm64_file} {x64_file} -output {universal_file}") + print(f"Processing binary file: {universal_file}") + run(f"lipo -info {universal_file}") + else: + print(f"Skipping non-binary file: {universal_file}") + +def check_fat_binary(): + # Ensure the script starts from the correct directory + workspace_path = Path(util.workspace_path()) + + dir = 'vcpkg/installed/64-osx-universal' + universal_dir = str(workspace_path.joinpath(dir)) + print(f"check_fat_binary {universal_dir}") + files = listfiles(universal_dir) + + for file in files: + out = run_and_capture_output(f"lipo -info {file}") + if out.startswith('Non-fat'): + out = out.replace("\n","") + print(f"โŒ {out}") + else: + print(f"โœ… {file}") +def execute(): + run_lipo() + check_fat_binary() + +if __name__ == "__main__": + execute() diff --git a/Tools/macos_sign.py b/Tools/macos_sign.py index 49ba8ce4..4aade6f4 100644 --- a/Tools/macos_sign.py +++ b/Tools/macos_sign.py @@ -48,7 +48,7 @@ def sign(build_config: BuildConfig): def sign_dmg(build_config: BuildConfig): # Sign the DMG - run("codesign -f -s \"Developer ID Application: Elias Steurer (V887LHYKRH)\" --timestamp --options \"runtime\" -f --deep \"ScreenPlay-Installer.dmg\"", cwd=build_config.build_folder) + run("codesign -f -s \"3rd Party Mac Developer Installer: Elias Steurer (V887LHYKRH)\" --timestamp -f --deep \"ScreenPlay-Installer.dmg\"", cwd=build_config.build_folder) # Verify the DMG's signature run("codesign --verify --verbose=4 \"ScreenPlay-Installer.dmg\"", diff --git a/Tools/requirements.txt b/Tools/requirements.txt index 9a567f28..f7a1531a 100644 --- a/Tools/requirements.txt +++ b/Tools/requirements.txt @@ -1,2 +1,3 @@ cmake-format -aqtinstall \ No newline at end of file +aqtinstall +requests \ No newline at end of file diff --git a/Tools/setup.py b/Tools/setup.py index 81db9512..4a16b8d4 100755 --- a/Tools/setup.py +++ b/Tools/setup.py @@ -7,7 +7,9 @@ import download_ffmpeg import defines import argparse import util +import macos_make_universal import datetime +import setup_godot from sys import stdout stdout.reconfigure(encoding='utf-8') @@ -53,17 +55,15 @@ def download(aqt_path: Path, qt_platform: Path): qt_packages = "qtwaylandcompositor " os = "linux" - # Windows: python -m aqt list-qt windows desktop --modules 6.5.2 win64_msvc2019_64 - # Linux: python3 -m aqt list-qt linux desktop --modules 6.5.2 gcc_64 qt_packages += "qt3d qtquick3d qtconnectivity qt5compat qtimageformats qtmultimedia qtshadertools qtwebchannel qtwebengine qtwebsockets qtwebview qtpositioning" + # Windows: python -m aqt list-qt windows desktop --modules 6.6.1 win64_msvc2019_64 + # Linux: python3 -m aqt list-qt linux desktop --modules 6.6.1 gcc_64 print(f"Downloading: {qt_packages} to {aqt_path}") execute(f"{defines.PYTHON_EXECUTABLE} -m aqt install-qt -O {aqt_path} {os} desktop {defines.QT_VERSION} {qt_platform} -m {qt_packages}") # Tools can only be installed one at the time: # see: python -m aqt list-tool windows desktop - tools = ["tools_ifw", "tools_qtcreator", "tools_ninja", "tools_cmake"] - if system() == "Windows": - tools += ["tools_opensslv3_x64"] + tools = ["tools_ifw"] for tool in tools: execute( f"{defines.PYTHON_EXECUTABLE} -m aqt install-tool -O {aqt_path} {os} desktop {tool}") @@ -105,22 +105,22 @@ def setup_qt(): def main(): parser = argparse.ArgumentParser( description='Build and Package ScreenPlay') - parser.add_argument('-skip-aqt', action="store_true", dest="skip_aqt", - help="Downloads QtCreator and needed binaries \Windows: C:\aqt\nLinux & macOS:~/aqt/.") + parser.add_argument('--skip-aqt', action="store_true", dest="skip_aqt", + help="Downloads QtCreator and needed binaries Windows: C:\\aqt\\nLinux & macOS:~/aqt/.") args = parser.parse_args() root_path = Path(util.cd_repo_root_path()) project_source_parent_path = root_path.joinpath("../").resolve() vcpkg_path = project_source_parent_path.joinpath("vcpkg").resolve() - vcpkg_packages_list = [ - "curl", - "cpp-httplib", - "libarchive" - ] - if not args.skip_aqt: - setup_qt() + vcpkg_packages_list = defines.VCPKG_BASE_PACKAGES - download_ffmpeg.execute() + if system() != "Darwin": + if not setup_godot.execute(): + raise RuntimeError("Unable to download godot") + + if not download_ffmpeg.execute(): + raise RuntimeError("Unable to download ffmpeg") + if system() == "Windows": vcpkg_command = "vcpkg.exe" @@ -137,7 +137,7 @@ def main(): platform_command.add("chmod +x bootstrap-vcpkg.sh", vcpkg_path) platform_command.add("./bootstrap-vcpkg.sh", vcpkg_path, False) platform_command.add("chmod +x vcpkg", vcpkg_path) - vcpkg_triplet = ["64-osx-universal"] + vcpkg_triplet = ["x64-osx","arm64-osx"] elif system() == "Linux": vcpkg_command = "./vcpkg" # vcpkg_packages_list.append("infoware[opengl]") @@ -150,7 +150,7 @@ def main(): raise NotImplementedError("Unknown system: {}".format(system())) print(f"Clone into {vcpkg_path}") - execute("git clone https://gitlab.com/kelteseth/screenplay-vcpkg vcpkg", + execute("git clone https://github.com/microsoft/vcpkg vcpkg", project_source_parent_path, True) execute("git fetch", vcpkg_path) execute(f"git checkout {defines.VCPKG_VERSION}", vcpkg_path) @@ -164,6 +164,14 @@ def main(): vcpkg_packages = " ".join(vcpkg_packages_list) execute( f"{vcpkg_command} install {vcpkg_packages} --triplet {triplet} --recurse", vcpkg_path, False) + + # Combine x64 and arm + if system() == "Darwin": + macos_make_universal.execute() + + if not args.skip_aqt: + setup_qt() + if __name__ == "__main__": diff --git a/Tools/setup_godot.py b/Tools/setup_godot.py new file mode 100644 index 00000000..32de041b --- /dev/null +++ b/Tools/setup_godot.py @@ -0,0 +1,115 @@ +#!/usr/bin/python3 +# SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only +import os +import sys +import shutil +import util +from pathlib import Path +import defines +import util + +def download_godot(exe_zip_filename: str, export_templates: str, download_destination_path: str) -> bool: + # https://github.com/godotengine/godot-builds/releases/download/4.2-beta6/Godot_v4.2-beta6_win64.exe.zip + subfolder = f"{defines.GODOT_VERSION}-{defines.GODOT_RELEASE_TYPE}" + base_url = f"{defines.GODOT_DOWNLOAD_SERVER}/{subfolder}" + + download_export_templates = f"{base_url}/{export_templates}" + exe_destination_filepath = os.path.join( + download_destination_path, exe_zip_filename) + export_templates_destination_path = os.path.join( + download_destination_path, export_templates) + + # Godot adds ".stable" to the folder names for full releases: "AppData/Roaming/Godot/templates/4.2.stable": + download_editor = f"{base_url}/{exe_zip_filename}" + print(f"โฌ‡๏ธ Downloading Godot editor {download_editor}") + util.download(download_editor, exe_destination_filepath, False) + print(f"โฌ‡๏ธ Downloading Godot export templates {download_export_templates}") + util.download(download_export_templates, + export_templates_destination_path, False) + + return True + + +def unzip_godot(exe_zip_filepath: str, export_templates_filepath: str, destination_path: str) -> bool: + print("๐Ÿช› Unzip Godot") + util.unzip(exe_zip_filepath, destination_path) + + # The export templates contain a templates subfolder in which the content is. This is bad because it clashes + # with the folder structure where the version comes after: /home/eli/.local/share/godot/export_templates/ + # Rename: AppData\Roaming\Godot\export_templates\templates + # to : AppData\Roaming\Godot\export_templates\3.4.stable + godot_templates_dir = "" + if sys.platform == "win32": + godot_templates_dir = os.path.join( + os.getenv('APPDATA'), "Godot/export_templates") + elif sys.platform == "linux": + godot_templates_dir = os.path.join( + str(Path.home()), ".local/share/godot/export_templates") + os.makedirs(godot_templates_dir, exist_ok=True) + export_templates_destination_version = f"{godot_templates_dir}/{defines.GODOT_VERSION}.{defines.GODOT_RELEASE_TYPE}" + + # Remove previous folder + if os.path.exists(export_templates_destination_version): + print(f"Remove previous export templates folder: {export_templates_destination_version}") + shutil.rmtree(export_templates_destination_version) + + util.unzip(export_templates_filepath, godot_templates_dir) + os.rename(os.path.join(godot_templates_dir, "templates"), + export_templates_destination_version) + + print(f"๐Ÿšฎ Remove {exe_zip_filepath}") + try: + os.remove(exe_zip_filepath) + except OSError as error: + print(f"Error deleting file: {error}") + return False + + print(f"๐Ÿšฎ Remove {export_templates_filepath}") + try: + os.remove(export_templates_filepath) + except OSError as error: + print(f"Error deleting file: {error}") + return False + + return True + + +def setup_godot() -> bool: + print(f"๐Ÿš€ Set up GODOT version {defines.GODOT_VERSION} {defines.GODOT_RELEASE_TYPE}") + destination_path = os.path.join(defines.THIRDPATH_PATH, "Godot") + export_templates = f"Godot_v{defines.GODOT_VERSION}-{defines.GODOT_RELEASE_TYPE}_export_templates.tpz" + export_templates_filepath = os.path.join( + destination_path, export_templates) + exe_zip_filepath = os.path.join(destination_path, defines.GODOT_EDITOR_DOWNLOAD_NAME) + download_godot( defines.GODOT_EDITOR_DOWNLOAD_NAME, + export_templates, destination_path) + if not unzip_godot(exe_zip_filepath, export_templates_filepath, destination_path): + return False + + # Linux needs to change file permission to be able to run godot + if sys.platform == "linux": + command = f"chmod +x {defines.GODOT_EDITOR_EXECUTABLE}" + print(f"Make editor executable: {command} at {destination_path}") + util.run(command,destination_path) + + return True + + +def execute() -> bool: + # Assuming repo_root_path() returns the git repo root path + repo_path = Path(util.repo_root_path()) + godot_path = repo_path / "ThirdParty" / "Godot" + + # Create the directory if it doesn't exist + godot_path.mkdir(parents=True, exist_ok=True) + + # Check if Godot executable already exists + for file in godot_path.iterdir(): + if defines.GODOT_EDITOR_EXECUTABLE in str(file): + print(f"Godot v{defines.GODOT_EDITOR_EXECUTABLE} already exists.") + return True + + return setup_godot() + +if __name__ == "__main__": + execute() diff --git a/Tools/util.py b/Tools/util.py index 5a24cca1..8d127a2b 100644 --- a/Tools/util.py +++ b/Tools/util.py @@ -9,6 +9,27 @@ import os import re import subprocess from sys import stdout +import zipfile +import urllib.request +import sys +import ssl + +def progress(count: int, block_size: int, total_size: int): + percent = int(count * block_size * 100 / total_size) + sys.stdout.write("\rDownload: {}%".format(percent)) + sys.stdout.flush() + +# disable broken progress bar in CI +def download(url: str, filename: str, show_progress: bool = True): + # This is needed for downloading from https sites + # see https://programmerah.com/python-error-certificate-verify-failed-certificate-has-expired-40374/ + ssl._create_default_https_context = ssl._create_unverified_context + + if show_progress: + urllib.request.urlretrieve(url, filename, progress) + else: + urllib.request.urlretrieve(url, filename) + stdout.reconfigure(encoding='utf-8') @@ -42,6 +63,11 @@ def repo_root_path() -> str: return os.path.realpath(path) +def workspace_path() -> str: + # One folder above the repo + path = os.path.join(repo_root_path(), "../") + return os.path.realpath(path) + def cd_repo_root_path() -> str: # Make sure the script is always started from the same # ScreenPlay root folder @@ -144,3 +170,49 @@ def semver_to_string(semver_dict): if semver_dict['pre_release']: version_str += f"-{semver_dict['pre_release']}" return version_str + + +def unzip(zip_path: str, destination_path: str, specific_file: str = None): + with zipfile.ZipFile(zip_path, 'r') as zip_ref: + if specific_file: + zip_ref.extract(specific_file, path=destination_path) + else: + zip_ref.extractall(path=destination_path) + + +def listfiles(path): + files = [] + extensions = ('.dylib', '.so','') + ignored = ('qmldir') + print(f"WALK: {path}") + for dirName, subdirList, fileList in os.walk(path): + dir = dirName.replace(path, '') + for fname in fileList: + if Path(fname).suffix in extensions and not fname in ignored: + file = path + os.path.join(dir, fname) + if(os.path.isfile(file)): + files.append(file) + if os.path.islink(file): + print(f"Warning: file {file} is a symlink!") + print("Symlink target: ", os.readlink(file)) + return files + + +def check_universal_binary(): + dir = 'build-64-osx-universal-release/bin/ScreenPlay.app/Contents' + path = Path(repo_root_path()).joinpath(dir).absolute() + print(f"Checking files at: {path}") + files = listfiles(str(path)) + none_fat_found = False + none_fat_files = [] + for file in files: + out = run_and_capture_output(f"lipo -info {file}") + if out.startswith('Non-fat'): + none_fat_found = True + none_fat_files.append(file) + if none_fat_found: + print("โŒ None universal binaries found") + for file in none_fat_files: + print(f"โŒ {file}") + else: + print("โœ… All files are a universal binaries") \ No newline at end of file