From c9498b366e808fd72cfe6f70c4259be3c6918acd Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Sun, 12 Nov 2023 07:32:45 +0100 Subject: [PATCH 01/32] Remove old code --- ScreenPlay/src/monitorlistmodel.cpp | 20 ++-- ScreenPlayWallpaper/src/windowshook.cpp | 111 ------------------- ScreenPlayWallpaper/src/windowshook.h | 41 ------- ScreenPlayWallpaper/src/windowsintegration.h | 31 ------ Tools/setup.py | 2 +- 5 files changed, 11 insertions(+), 194 deletions(-) delete mode 100644 ScreenPlayWallpaper/src/windowshook.cpp delete mode 100644 ScreenPlayWallpaper/src/windowshook.h diff --git a/ScreenPlay/src/monitorlistmodel.cpp b/ScreenPlay/src/monitorlistmodel.cpp index a5d2e954..4a3fdfd0 100644 --- a/ScreenPlay/src/monitorlistmodel.cpp +++ b/ScreenPlay/src/monitorlistmodel.cpp @@ -114,16 +114,15 @@ void MonitorListModel::loadMonitors() #ifdef Q_OS_WIN QModelIndex index; - 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); } @@ -132,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, @@ -145,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/ScreenPlayWallpaper/src/windowshook.cpp b/ScreenPlayWallpaper/src/windowshook.cpp deleted file mode 100644 index 032721f0..00000000 --- a/ScreenPlayWallpaper/src/windowshook.cpp +++ /dev/null @@ -1,111 +0,0 @@ -#include "windowshook.h" - -BOOL CALLBACK WinMonitorStats::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(static_cast(pThis->hdcMonitors.size())); - - // qInfo() << std::abs(lprcMonitor->right - lprcMonitor->left) << std::abs(lprcMonitor->top - lprcMonitor->bottom); - - return TRUE; -} -/*! - \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; -} - -bool WindowsHook::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(&windowHandleWorker)); -} - -/*! - \brief Returns scaling factor as reported by Windows. -*/ -float WindowsHook::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 WindowsHook::hasWindowScaling() const -{ - auto enumMonitorCallback = [](HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) -> BOOL { - int scaling = GetDeviceCaps(hdcMonitor, LOGPIXELSX) / 96; - if (scaling != 1) { - *(bool*)dwData = true; - return false; // Stop enumeration - } - return true; // Continue enumeration - }; - - bool hasScaling = false; - EnumDisplayMonitors(NULL, NULL, enumMonitorCallback, (LPARAM)&hasScaling); - - return hasScaling; -} \ No newline at end of file diff --git a/ScreenPlayWallpaper/src/windowshook.h b/ScreenPlayWallpaper/src/windowshook.h deleted file mode 100644 index d291b36e..00000000 --- a/ScreenPlayWallpaper/src/windowshook.h +++ /dev/null @@ -1,41 +0,0 @@ -#pragma once - -#ifndef NOMINMAX -#define NOMINMAX -#endif -#include -#include -#include -#include -#include - -struct WinMonitorStats { - - WinMonitorStats() - { - EnumDisplayMonitors(NULL, NULL, MonitorEnum, (LPARAM)this); - } - - static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData); - std::vector iMonitors; - std::vector hMonitors; - std::vector hdcMonitors; - std::vector rcMonitors; - std::vector scaleFactor; - std::vector> sizes; - int index = 0; -}; - -struct Point { - int x = 0; - int y = 0; -}; - -struct WindowsHook { - bool searchWorkerWindowToParentTo(); - float getScaling(const int monitorIndex) const; - bool hasWindowScaling() const; - HWND windowHandle {}; - HWND windowHandleWorker {}; - Point zeroPoint; -}; \ No newline at end of file diff --git a/ScreenPlayWallpaper/src/windowsintegration.h b/ScreenPlayWallpaper/src/windowsintegration.h index b455150e..14cf94a6 100644 --- a/ScreenPlayWallpaper/src/windowsintegration.h +++ b/ScreenPlayWallpaper/src/windowsintegration.h @@ -41,38 +41,7 @@ BOOL CALLBACK GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcM BOOL CALLBACK FindTheDesiredWnd(HWND hWnd, LPARAM lParam); BOOL WINAPI SearchForWorkerWindow(HWND hwnd, LPARAM lparam); -struct WinMonitorStats { - WinMonitorStats() - { - EnumDisplayMonitors(NULL, NULL, MonitorEnum, (LPARAM)this); - } - - 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()); - - return TRUE; - } - std::vector iMonitors; - std::vector hMonitors; - std::vector hdcMonitors; - std::vector rcMonitors; - std::vector scaleFactor; - std::vector> sizes; -}; struct Point { int x = 0; diff --git a/Tools/setup.py b/Tools/setup.py index 89fdaa1d..53d8589d 100755 --- a/Tools/setup.py +++ b/Tools/setup.py @@ -107,7 +107,7 @@ 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/.") + help="Downloads QtCreator and needed binaries Windows: C:\\aqt\\nLinux & macOS:~/aqt/.") parser.add_argument('--setup-godot', action="store_true", dest="setup_godot", help="Downloads Godot Editor.") args = parser.parse_args() From 33f744e0f4adb10e43e47741d8fba75b39ed6ca5 Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Thu, 16 Nov 2023 08:00:10 +0100 Subject: [PATCH 02/32] Add basic Godot wizard --- ScreenPlay/CMakeLists.txt | 3 + ScreenPlay/inc/public/ScreenPlay/wizards.h | 9 ++ ScreenPlay/qml/Create/CreateSidebar.qml | 8 ++ .../qml/Create/Wizards/GodotWallpaper.qml | 101 ++++++++++++++++++ .../WizardsFiles/Godot_v5/project.godot | 15 +++ .../WizardsFiles/Godot_v5/wallpaper.tscn | 16 +++ ScreenPlay/src/wizards.cpp | 67 ++++++++++++ 7 files changed, 219 insertions(+) create mode 100644 ScreenPlay/qml/Create/Wizards/GodotWallpaper.qml create mode 100644 ScreenPlay/qml/Create/WizardsFiles/Godot_v5/project.godot create mode 100644 ScreenPlay/qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn diff --git a/ScreenPlay/CMakeLists.txt b/ScreenPlay/CMakeLists.txt index 584b1c55..edcf9319 100644 --- a/ScreenPlay/CMakeLists.txt +++ b/ScreenPlay/CMakeLists.txt @@ -73,11 +73,14 @@ set(QML qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml qml/Create/Wizards/ImportWebm/ImportWebmInit.qml qml/Create/Wizards/QMLWallpaper.qml + qml/Create/Wizards/GodotWallpaper.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/Create/WizardsFiles/Godot_v5/project.godot + qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn qml/Installed/Installed.qml qml/Installed/InstalledNavigation.qml qml/Installed/InstalledWelcomeScreen.qml diff --git a/ScreenPlay/inc/public/ScreenPlay/wizards.h b/ScreenPlay/inc/public/ScreenPlay/wizards.h index 10abc659..93ba97c0 100644 --- a/ScreenPlay/inc/public/ScreenPlay/wizards.h +++ b/ScreenPlay/inc/public/ScreenPlay/wizards.h @@ -82,6 +82,15 @@ 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, diff --git a/ScreenPlay/qml/Create/CreateSidebar.qml b/ScreenPlay/qml/Create/CreateSidebar.qml index bf1ef42b..04f66cac 100644 --- a/ScreenPlay/qml/Create/CreateSidebar.qml +++ b/ScreenPlay/qml/Create/CreateSidebar.qml @@ -87,6 +87,14 @@ Rectangle { objectName: "" } + ListElement { + headline: qsTr("Godot Wallpaper") + 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/Wizards/GodotWallpaper.qml b/ScreenPlay/qml/Create/Wizards/GodotWallpaper.qml new file mode 100644 index 00000000..4f31d195 --- /dev/null +++ b/ScreenPlay/qml/Create/Wizards/GodotWallpaper.qml @@ -0,0 +1,101 @@ +import QtQuick +import Qt5Compat.GraphicalEffects +import QtQuick.Controls +import QtQuick.Controls.Material +import QtQuick.Layouts +import ScreenPlayApp +import ScreenPlay +import ScreenPlay.Create +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/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/wallpaper.tscn b/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn new file mode 100644 index 00000000..d488b39d --- /dev/null +++ b/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn @@ -0,0 +1,16 @@ +[gd_scene format=3 uid="uid://d105uliklnkd5"] + +[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) + +[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/src/wizards.cpp b/ScreenPlay/src/wizards.cpp index 5fd438b1..45d2756e 100644 --- a/ScreenPlay/src/wizards.cpp +++ b/ScreenPlay/src/wizards.cpp @@ -289,6 +289,73 @@ 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 = ScreenPlayUtil::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::GodotWallpaper).toString()); + obj.insert("file", "wallpaper.tscn"); + + if (!previewThumbnail.isEmpty()) { + if (!Util::copyPreviewThumbnail(obj, previewThumbnail, workingPath)) { + emit widgetCreationFinished(WizardResult::CopyPreviewThumbnailError); + return; + } + } + + if (!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")) { + emit widgetCreationFinished(WizardResult::WriteProjectFileError); + return; + } + + if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/Godot_v5/project.godot", workingPath + "/project.godot")) { + qWarning() << "Could not write main.qml"; + return; + } + if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn", workingPath + "/wallpaper.tscn")) { + qWarning() << "Could not write main.qml"; + return; + } + + emit widgetCreationFinished(WizardResult::Ok, workingPath); + }); +} + void Wizards::createGifWallpaper( const QString& title, const QString& licenseName, From 6a9cda9df3da7c66b3471b5860810449a2d0fc7a Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Thu, 16 Nov 2023 08:02:53 +0100 Subject: [PATCH 03/32] Fix icon --- ScreenPlay/qml/Settings/Settings.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ScreenPlay/qml/Settings/Settings.qml b/ScreenPlay/qml/Settings/Settings.qml index b84dd0a8..67f48434 100644 --- a/ScreenPlay/qml/Settings/Settings.qml +++ b/ScreenPlay/qml/Settings/Settings.qml @@ -403,7 +403,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 From b72c9904b20f55a59942cd6f5a5d54c4c5031848 Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Thu, 16 Nov 2023 09:41:11 +0100 Subject: [PATCH 04/32] Fix godot download --- Tools/defines.py | 13 +++++++++---- Tools/setup.py | 2 +- Tools/setup_godot.py | 43 +++++++++++++++++++++++-------------------- 3 files changed, 33 insertions(+), 25 deletions(-) diff --git a/Tools/defines.py b/Tools/defines.py index 362a0fe7..7e577b74 100644 --- a/Tools/defines.py +++ b/Tools/defines.py @@ -37,20 +37,25 @@ VCPKG_BASE_PACKAGES = [ PYTHON_EXECUTABLE = "python" if sys.platform == "win32" else "python3" FFMPEG_VERSION = "6.0" GODOT_VERSION = "4.2" -GODOT_RELEASE_TYPE = "beta5" -GODOT_DOWNLOAD_SERVER = "https://downloads.tuxfamily.org/godotengine" +GODOT_RELEASE_TYPE = "beta6" +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_EDITOR_EXECUTABLE = f"Godot_v{GODOT_VERSION}-{GODOT_RELEASE_TYPE}_osx.universal" + # 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_EDITOR_EXECUTABLE = f"Godot_v{GODOT_VERSION}-{GODOT_RELEASE_TYPE}_x11.64" + # 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/setup.py b/Tools/setup.py index 53d8589d..765c9847 100755 --- a/Tools/setup.py +++ b/Tools/setup.py @@ -117,7 +117,7 @@ def main(): vcpkg_path = project_source_parent_path.joinpath("vcpkg").resolve() vcpkg_packages_list = defines.VCPKG_BASE_PACKAGES - if system() == "Windows" and args.setup_godot: + if system() != "Darwin" and args.setup_godot: if not setup_godot.execute(): raise RuntimeError("Unable to download godot") diff --git a/Tools/setup_godot.py b/Tools/setup_godot.py index d8c39d7b..6456c9ff 100644 --- a/Tools/setup_godot.py +++ b/Tools/setup_godot.py @@ -8,19 +8,22 @@ from pathlib import Path import defines import util -def download_godot(version: str, exe_zip_filename: str, export_templates: str, download_destination_path: str) -> bool: - # https://downloads.tuxfamily.org/godotengine/4.2/beta4/Godot_v4.2-beta4_win64.exe.zip - # https://downloads.tuxfamily.org/godotengine/4.2/Godot_v4.2-beta4_win64.exe.zip - download_export_templates = f"{defines.GODOT_DOWNLOAD_SERVER}/{version}/{defines.GODOT_RELEASE_TYPE}/{export_templates}" +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/3.4.stable": - print(f"Downloading Godot from {defines.GODOT_DOWNLOAD_SERVER}/") - download_link = f"{defines.GODOT_DOWNLOAD_SERVER}/{version}/{defines.GODOT_RELEASE_TYPE}/{exe_zip_filename}" - util.download(download_link, exe_destination_filepath, False) + # 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) @@ -28,7 +31,7 @@ def download_godot(version: str, exe_zip_filename: str, export_templates: str, d def unzip_godot(exe_zip_filepath: str, export_templates_filepath: str, destination_path: str) -> bool: - print("Unzip Godot") + 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 @@ -38,10 +41,10 @@ def unzip_godot(exe_zip_filepath: str, export_templates_filepath: str, destinati godot_templates_dir = "" if sys.platform == "win32": godot_templates_dir = os.path.join( - os.getenv('APPDATA'), "Godot/templates/") + os.getenv('APPDATA'), "Godot/templates") elif sys.platform == "linux": godot_templates_dir = os.path.join( - str(Path.home()), ".local/share/godot/templates/") + str(Path.home()), ".local/share/godot/templates") os.makedirs(godot_templates_dir, exist_ok=True) export_templates_destination_version = f"{godot_templates_dir}/{defines.GODOT_VERSION}.{defines.GODOT_RELEASE_TYPE}" @@ -54,14 +57,14 @@ def unzip_godot(exe_zip_filepath: str, export_templates_filepath: str, destinati os.rename(os.path.join(godot_templates_dir, "templates"), export_templates_destination_version) - print(f"Remove {exe_zip_filepath}") + 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}") + print(f"🚮 Remove {export_templates_filepath}") try: os.remove(export_templates_filepath) except OSError as error: @@ -72,22 +75,22 @@ def unzip_godot(exe_zip_filepath: str, export_templates_filepath: str, destinati def setup_godot() -> bool: - print(f"Set up GODOT version {defines.GODOT_VERSION} {defines.GODOT_RELEASE_TYPE}") + 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_filename = defines.GODOT_EDITOR_EXECUTABLE + '.zip' - exe_zip_filepath = os.path.join(destination_path, exe_zip_filename) - download_godot(defines.GODOT_VERSION, exe_zip_filename, + 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": - execute(f"chmod +x {defines.GODOT_EDITOR_EXECUTABLE}", - destination_path, False) + command = f"chmod +x {defines.GODOT_EDITOR_EXECUTABLE}" + print(f"Make editor executable: {command} at {destination_path}") + util.run(command,destination_path) return True From 269b70093de2bd6d40bf00ff0d3f601ba34546b4 Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Thu, 16 Nov 2023 09:52:35 +0100 Subject: [PATCH 05/32] Fix extraction of export template folder name changes in Godot 4 --- Tools/setup.py | 4 +--- Tools/setup_godot.py | 10 +++++----- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/Tools/setup.py b/Tools/setup.py index 765c9847..ef3163e0 100755 --- a/Tools/setup.py +++ b/Tools/setup.py @@ -108,8 +108,6 @@ def main(): 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('--setup-godot', action="store_true", dest="setup_godot", - help="Downloads Godot Editor.") args = parser.parse_args() root_path = Path(util.cd_repo_root_path()) @@ -117,7 +115,7 @@ def main(): vcpkg_path = project_source_parent_path.joinpath("vcpkg").resolve() vcpkg_packages_list = defines.VCPKG_BASE_PACKAGES - if system() != "Darwin" and args.setup_godot: + if system() != "Darwin": if not setup_godot.execute(): raise RuntimeError("Unable to download godot") diff --git a/Tools/setup_godot.py b/Tools/setup_godot.py index 6456c9ff..32de041b 100644 --- a/Tools/setup_godot.py +++ b/Tools/setup_godot.py @@ -35,16 +35,16 @@ def unzip_godot(exe_zip_filepath: str, export_templates_filepath: str, destinati 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: AppData\Roaming\Godot\templates\3.3.4.stable - # Rename: AppData\Roaming\Godot\templates\templates - # to : AppData\Roaming\Godot\templates\3.4.stable + # 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/templates") + os.getenv('APPDATA'), "Godot/export_templates") elif sys.platform == "linux": godot_templates_dir = os.path.join( - str(Path.home()), ".local/share/godot/templates") + 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}" From 85e8d8abc8e6eb2565278e9ba899760a4b802fff Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Thu, 16 Nov 2023 11:15:29 +0100 Subject: [PATCH 06/32] Fix setting version number --- CMake/CMakeVariables.h.in | 1 + CMake/GenerateCMakeVariableHeader.cmake | 12 +++++++----- CMakeLists.txt | 6 +++--- ScreenPlay/src/app.cpp | 3 ++- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/CMake/CMakeVariables.h.in b/CMake/CMakeVariables.h.in index 662516a7..85654134 100644 --- a/CMake/CMakeVariables.h.in +++ b/CMake/CMakeVariables.h.in @@ -1,5 +1,6 @@ #pragma once +#define SCREENPLAY_VERSION "@SCREENPLAY_VERSION@" #define SCREENPLAY_SOURCE_DIR "@SCREENPLAY_SOURCE_DIR@" #define SCREENPLAY_GODOT_VERSION "@SCREENPLAY_GODOT_VERSION@" #define SCREENPLAY_GODOT_RELEASE_TYPE "@SCREENPLAY_GODOT_RELEASE_TYPE@" diff --git a/CMake/GenerateCMakeVariableHeader.cmake b/CMake/GenerateCMakeVariableHeader.cmake index 7325133a..33401597 100644 --- a/CMake/GenerateCMakeVariableHeader.cmake +++ b/CMake/GenerateCMakeVariableHeader.cmake @@ -1,9 +1,9 @@ -# ! 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) # NOTE: Also add to CMakeVariables.h.in ! @@ -12,6 +12,7 @@ function(generate_cmake_variable_header TARGET) 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}") @@ -19,7 +20,7 @@ function(generate_cmake_variable_header TARGET) if(${SCREENPLAY_DEPLOY}) set(SCREENPLAY_DEPLOY_VERSION 1) endif() - + set(SCREENPLAY_STEAM_VERSION 0) if(${SCREENPLAY_STEAM}) set(SCREENPLAY_STEAM_VERSION 1) @@ -27,7 +28,8 @@ function(generate_cmake_variable_header TARGET) # 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}) diff --git a/CMakeLists.txt b/CMakeLists.txt index 17a1347e..7e70f0bb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ 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) @@ -13,7 +13,7 @@ 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) @@ -166,7 +166,6 @@ if(${SCREENPLAY_INSTALLER}) endif() message(STATUS "[PROJECT] CMAKE_MODULE_PATH = ${CMAKE_MODULE_PATH}") -message(STATUS "[PROJECT] PROJECT_VERSION = ${PROJECT_VERSION}") 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}") @@ -176,6 +175,7 @@ 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}") diff --git a/ScreenPlay/src/app.cpp b/ScreenPlay/src/app.cpp index d8ba84f6..06ac8417 100644 --- a/ScreenPlay/src/app.cpp +++ b/ScreenPlay/src/app.cpp @@ -5,6 +5,7 @@ #include "ScreenPlayUtil/macutils.h" #endif +#include "ScreenPlay/CMakeVariables.h" #include "app.h" #include "steam/steam_qt_enums_generated.h" #include @@ -71,7 +72,7 @@ App::App() 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/"; From 0e6079fe9f59e27a40d9cc9f21b514daf8a26130 Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Thu, 16 Nov 2023 11:15:44 +0100 Subject: [PATCH 07/32] Fix Godot version --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7e70f0bb..0e86ec5c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -58,7 +58,7 @@ set(VCPKG_BIN_PATH "${VCPKG_INSTALLED_PATH}/bin") # Godot Editor set(GODOT_VERSION "v4.2") -set(GODOT_RELEASE_TYPE "beta4") +set(GODOT_RELEASE_TYPE "beta6") if(WIN32) set(GODOT_EDITOR_NAME "Godot_${GODOT_VERSION}-${GODOT_RELEASE_TYPE}_win64.exe") From 99e427b6cbcc97d813cc6b6e04bf6681a66df7c6 Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Thu, 16 Nov 2023 11:39:09 +0100 Subject: [PATCH 08/32] Add quick settings to tray icon Fix navigation and multi loading of installed content Fix installed reloading on content change and fix reload timer no limit the triggering, but always trigger 500ms later Fix settings checkbox triggering always when entering settings page Fix create wizard change page to installed --- .../public/ScreenPlay/installedlistmodel.h | 1 + ScreenPlay/main.qml | 114 ++++++++++-------- ScreenPlay/qml/Create/CreateSidebar.qml | 4 +- ScreenPlay/qml/Installed/Installed.qml | 3 +- ScreenPlay/qml/Navigation/Navigation.qml | 32 +++-- ScreenPlay/qml/Settings/SettingBool.qml | 2 +- ScreenPlay/qml/TrayIcon.qml | 104 +++++++++++++--- ScreenPlay/src/installedlistmodel.cpp | 25 ++-- ScreenPlayUtil/src/projectfile.cpp | 6 +- 9 files changed, 190 insertions(+), 101 deletions(-) diff --git a/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h b/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h index 32bdd3dc..cc0ce26a 100644 --- a/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h +++ b/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h @@ -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/main.qml b/ScreenPlay/main.qml index 4ec06b04..3a6077cd 100644 --- a/ScreenPlay/main.qml +++ b/ScreenPlay/main.qml @@ -23,40 +23,45 @@ ApplicationWindow { function setTheme(theme) { switch (theme) { case Settings.System: - root.Material.theme = Material.System; - break; + root.Material.theme = Material.System + break case Settings.Dark: - root.Material.theme = Material.Dark; - break; + root.Material.theme = Material.Dark + break case Settings.Light: - root.Material.theme = Material.Light; - break; + root.Material.theme = Material.Light + break } } function switchPage(name) { if (nav.currentNavigationName === name) { if (name === "Installed") - App.installedListModel.reset(); + App.installedListModel.reset() } if (name === "Installed") { - stackView.replace("qrc:/qml/ScreenPlayApp/qml/Installed/Installed.qml", { - "sidebar": sidebar - }); - return; + stackView.replace( + "qrc:/qml/ScreenPlayApp/qml/Installed/Installed.qml", { + "sidebar": sidebar + }) + return } - stackView.replace("qrc:/qml/ScreenPlayApp/qml/" + name + "/" + name + ".qml", { - "modalSource": content - }); - sidebar.state = "inactive"; + stackView.replace( + "qrc:/qml/ScreenPlayApp/qml/" + name + "/" + name + ".qml", + { + "modalSource": content + }) + nav.setNavigation(name) + sidebar.state = "inactive" } - color: Material.theme === Material.Dark ? Qt.darker(Material.background) : Material.background + color: Material.theme === Material.Dark ? Qt.darker( + Material.background) : Material.background // Set visible if the -silent parameter was not set (see app.cpp end of constructor). visible: false width: 1400 height: 810 - title: "ScreenPlay Alpha - V" + App.version() + title: "ScreenPlay Alpha - v" + App.version() minimumHeight: 450 minimumWidth: 1050 @@ -72,25 +77,29 @@ 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) { - App.exit(); - } - const alwaysMinimize = settings.value("alwaysMinimize", null); - if (alwaysMinimize === null) { - console.error("Unable to retreive alwaysMinimize setting"); - } - if (alwaysMinimize === "true") { - root.hide(); - App.showDockIcon(false); - return; - } - exitDialog.open(); - } + close.accepted = false + if (App.screenPlayManager.activeWallpaperCounter === 0 + && App.screenPlayManager.activeWidgetsCounter === 0) { + App.exit() + } + const alwaysMinimize = settings.value("alwaysMinimize", null) + if (alwaysMinimize === null) { + console.error( + "Unable to retreive alwaysMinimize setting") + } + if (alwaysMinimize === "true") { + root.hide() + App.showDockIcon(false) + return + } + exitDialog.open() + } QCore.Settings { id: settings @@ -103,14 +112,15 @@ ApplicationWindow { } Component.onCompleted: { - setTheme(App.settings.theme); + setTheme(App.settings.theme) stackView.push("qrc:/qml/ScreenPlayApp/qml/Installed/Installed.qml", { - "sidebar": sidebar - }); + "sidebar": sidebar + }) if (!App.settings.silentStart) { - App.showDockIcon(true); - root.show(); + App.showDockIcon(true) + root.show() } + App.installedListModel.reset(); } Item { @@ -140,7 +150,7 @@ ApplicationWindow { Connections { function onThemeChanged(theme) { - setTheme(theme); + setTheme(theme) } target: App.settings @@ -148,7 +158,7 @@ ApplicationWindow { Connections { function onRequestNavigation(nav) { - switchPage(nav); + switchPage(nav) } target: App.util @@ -156,16 +166,18 @@ ApplicationWindow { Connections { function onRequestRaise() { - App.showDockIcon(true); - root.show(); + App.showDockIcon(true) + root.show() } function onActiveWidgetsCounterChanged() { - plausible.pageView("widget/count/" + App.screenPlayManager.activeWidgetsCounter); + plausible.pageView( + "widget/count/" + App.screenPlayManager.activeWidgetsCounter) } function onActiveWallpaperCounterChanged() { - plausible.pageView("wallpaper/count/" + App.screenPlayManager.activeWallpaperCounter); + plausible.pageView( + "wallpaper/count/" + App.screenPlayManager.activeWallpaperCounter) } target: App.screenPlayManager @@ -223,16 +235,16 @@ ApplicationWindow { Connections { function onSetSidebarActive(active) { if (active) - sidebar.state = "active"; + sidebar.state = "active" else - sidebar.state = "inactive"; + sidebar.state = "inactive" } function onSetNavigationItem(pos) { if (pos === 0) - nav.onPageChanged("Create"); + nav.onPageChanged("Create") else - nav.onPageChanged("Workshop"); + nav.onPageChanged("Workshop") } target: stackView.currentItem @@ -261,8 +273,8 @@ ApplicationWindow { } onChangePage: function (name) { - monitors.close(); - switchPage(name); + monitors.close() + switchPage(name) } } } diff --git a/ScreenPlay/qml/Create/CreateSidebar.qml b/ScreenPlay/qml/Create/CreateSidebar.qml index 04f66cac..50bb7aab 100644 --- a/ScreenPlay/qml/Create/CreateSidebar.qml +++ b/ScreenPlay/qml/Create/CreateSidebar.qml @@ -42,9 +42,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); } diff --git a/ScreenPlay/qml/Installed/Installed.qml b/ScreenPlay/qml/Installed/Installed.qml index 5ca7e255..d3b39704 100644 --- a/ScreenPlay/qml/Installed/Installed.qml +++ b/ScreenPlay/qml/Installed/Installed.qml @@ -41,7 +41,6 @@ Item { StackView.onActivated: { navWrapper.state = "in"; - App.installedListFilter.sortBySearchType(SearchType.All); checkIsContentInstalled(); } @@ -257,7 +256,7 @@ Item { Menu { id: contextMenu objectName: "installedItemContextMenu" - + // Must be var to support 64-bit size! property var publishedFileID: 0 property url absoluteStoragePath property string fileName diff --git a/ScreenPlay/qml/Navigation/Navigation.qml b/ScreenPlay/qml/Navigation/Navigation.qml index 16b5c639..6f6c4d87 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,13 @@ 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++) { + print(navArray[i].objectName) + if (navArray[i].objectName === name) { navArray[i].state = "active"; root.currentNavigationName = name; + tabBar.currentIndex = navArray[i].index } else { navArray[i].state = "inactive"; } @@ -70,7 +70,7 @@ Rectangle { } TabBar { - id: row + id: tabBar height: 50 currentIndex: 2 @@ -84,55 +84,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 +147,7 @@ Rectangle { font.pointSize: 12 height: parent.height width: implicitWidth + property int index: 0 background: Item { } font.capitalization: Font.MixedCase @@ -278,7 +284,7 @@ Rectangle { name: "disabled" PropertyChanges { - target: row + target: tabBar opacity: 0.3 } } @@ -289,7 +295,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/TrayIcon.qml b/ScreenPlay/qml/TrayIcon.qml index 6e946522..38db305e 100644 --- a/ScreenPlay/qml/TrayIcon.qml +++ b/ScreenPlay/qml/TrayIcon.qml @@ -14,28 +14,90 @@ SystemTrayIcon { onActivated: function (reason) { switch (reason) { case SystemTrayIcon.Unknown: - break; + break case SystemTrayIcon.Context: - break; + break case SystemTrayIcon.DoubleClick: - window.show(); - break; + window.show() + break case SystemTrayIcon.Trigger: - break; + break case SystemTrayIcon.MiddleClick: - break; + break } } + function open(){ + App.showDockIcon(true) + window.show() + + } + menu: Menu { MenuItem { + id: miOpenScreenPlay text: qsTr("Open ScreenPlay") onTriggered: { - App.showDockIcon(true); - window.show(); + root.open() + } + } + MenuItem { + id: miChangeWallpaperSettings + text: qsTr("Change Wallpaper settings") + onTriggered: { + root.open() + App.util.setNavigation("Installed"); + App.util.setToggleWallpaperConfiguration() + } + } + MenuItem { + separator: true + } + + MenuItem { + text: qsTr("Browse Workshop") + onTriggered: { + root.open() + App.util.setNavigation("Workshop"); } } + MenuItem { + id: miCreate + text: qsTr("Create new Wallpaper or Widgets") + onTriggered: { + root.open() + App.util.setNavigation("Create"); + } + } + MenuItem { + id: miSettings + text: qsTr("Settings") + onTriggered: { + root.open() + App.util.setNavigation("Settings"); + } + } + + MenuItem { + separator: true + } + MenuItem { + text: qsTr("Forums") + onTriggered: { + Qt.openUrlExternally("https://forum.screen-play.app/") + } + } + MenuItem { + text: qsTr("Frequently Asked Questions (FAQ)") + onTriggered: { + Qt.openUrlExternally( + "https://kelteseth.gitlab.io/ScreenPlayDocs/Frequently%20Asked%20Questions/") + } + } + MenuItem { + separator: true + } MenuItem { id: miMuteAll @@ -44,13 +106,13 @@ SystemTrayIcon { text: qsTr("Mute all") onTriggered: { if (miMuteAll.isMuted) { - isMuted = false; - miMuteAll.text = qsTr("Mute all"); - App.screenPlayManager.setAllWallpaperValue("muted", "true"); + isMuted = false + miMuteAll.text = qsTr("Mute all") + App.screenPlayManager.setAllWallpaperValue("muted", "true") } else { - isMuted = true; - miMuteAll.text = qsTr("Unmute all"); - App.screenPlayManager.setAllWallpaperValue("muted", "false"); + isMuted = true + miMuteAll.text = qsTr("Unmute all") + App.screenPlayManager.setAllWallpaperValue("muted", "false") } } } @@ -63,13 +125,15 @@ SystemTrayIcon { text: qsTr("Pause all") onTriggered: { if (miStopAll.isPlaying) { - isPlaying = false; - miStopAll.text = qsTr("Pause all"); - App.screenPlayManager.setAllWallpaperValue("isPlaying", "true"); + isPlaying = false + miStopAll.text = qsTr("Pause all") + App.screenPlayManager.setAllWallpaperValue("isPlaying", + "true") } else { - isPlaying = true; - miStopAll.text = qsTr("Play all"); - App.screenPlayManager.setAllWallpaperValue("isPlaying", "false"); + isPlaying = true + miStopAll.text = qsTr("Play all") + App.screenPlayManager.setAllWallpaperValue("isPlaying", + "false") } } } diff --git a/ScreenPlay/src/installedlistmodel.cpp b/ScreenPlay/src/installedlistmodel.cpp index faf4a2e9..7fbf57fa 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); } /*! @@ -288,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/ScreenPlayUtil/src/projectfile.cpp b/ScreenPlayUtil/src/projectfile.cpp index b756d1cf..b58394c6 100644 --- a/ScreenPlayUtil/src/projectfile.cpp +++ b/ScreenPlayUtil/src/projectfile.cpp @@ -105,13 +105,13 @@ bool ProjectFile::init() 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!"); + // 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"); + // qWarning("Eyeball to h264 because of .mp4"); } else if (file.endsWith(".webm")) { videoCodec = ScreenPlay::VideoCodec::VideoCodec::VP8; - qWarning("Eyeball to VP8 because of .webm"); + // qWarning("Eyeball to VP8 because of .webm"); } } From 893844f023c285914cf95c3e12cf544ab4d309bf Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Thu, 16 Nov 2023 13:27:50 +0100 Subject: [PATCH 09/32] Add edit menu entry --- ScreenPlay/CMakeLists.txt | 1 + ScreenPlay/inc/public/ScreenPlay/util.h | 5 +- ScreenPlay/inc/public/ScreenPlay/wizards.h | 6 +- ScreenPlay/qml/Installed/Installed.qml | 169 ++++++++++++-------- ScreenPlay/qml/Installed/ScreenPlayItem.qml | 1 + ScreenPlay/src/app.cpp | 3 +- ScreenPlay/src/profilelistmodel.cpp | 4 +- ScreenPlay/src/util.cpp | 13 +- 8 files changed, 129 insertions(+), 73 deletions(-) diff --git a/ScreenPlay/CMakeLists.txt b/ScreenPlay/CMakeLists.txt index edcf9319..73391ae7 100644 --- a/ScreenPlay/CMakeLists.txt +++ b/ScreenPlay/CMakeLists.txt @@ -185,6 +185,7 @@ set(RESOURCES assets/icons/icon_widgets.svg assets/icons/icon_window.svg assets/icons/item_banner_new.svg + assets/icons/icon_edit.svg assets/icons/monitor_setup.svg assets/icons/steam_default_avatar.png assets/images/Early_Access.png diff --git a/ScreenPlay/inc/public/ScreenPlay/util.h b/ScreenPlay/inc/public/ScreenPlay/util.h index 2d2eaf59..2502d653 100644 --- a/ScreenPlay/inc/public/ScreenPlay/util.h +++ b/ScreenPlay/inc/public/ScreenPlay/util.h @@ -58,7 +58,8 @@ class Util : public QObject { Q_PROPERTY(QString debugMessages READ debugMessages NOTIFY debugMessagesChanged) public: - Util(); + Util( + const std::shared_ptr& globalVariables); ~Util(); QString debugMessages() const { return m_debugMessages; } @@ -82,6 +83,7 @@ public slots: void openFolderInExplorer(const QString& url) const; QString toLocal(const QString& url) const; bool exportProject(QString contentPath, QString exportFileName); + bool openGodotEditor(QString contentPath) const; bool importProject(QString archivePath, QString extractionPath); void requestAllLicenses(); void requestDataProtection(); @@ -124,6 +126,7 @@ private: QFuture m_requestAllLicensesFuture; std::unique_ptr m_compressor; std::unique_ptr m_extractor; + const std::shared_ptr& m_globalVariables; }; } diff --git a/ScreenPlay/inc/public/ScreenPlay/wizards.h b/ScreenPlay/inc/public/ScreenPlay/wizards.h index 93ba97c0..aff61fc6 100644 --- a/ScreenPlay/inc/public/ScreenPlay/wizards.h +++ b/ScreenPlay/inc/public/ScreenPlay/wizards.h @@ -34,9 +34,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, diff --git a/ScreenPlay/qml/Installed/Installed.qml b/ScreenPlay/qml/Installed/Installed.qml index d3b39704..1c4c9470 100644 --- a/ScreenPlay/qml/Installed/Installed.qml +++ b/ScreenPlay/qml/Installed/Installed.qml @@ -25,23 +25,23 @@ Item { function checkIsContentInstalled() { if (App.installedListModel.count === 0) { - loaderHelp.active = true; - gridView.footerItem.isVisible = true; - gridView.visible = false; - navWrapper.visible = false; + loaderHelp.active = true + gridView.footerItem.isVisible = true + gridView.visible = false + navWrapper.visible = false } else { - loaderHelp.active = false; - gridView.footerItem.isVisible = false; - refresh = false; - gridView.contentY = -82; - gridView.visible = true; - navWrapper.visible = true; + loaderHelp.active = false + gridView.footerItem.isVisible = false + refresh = false + gridView.contentY = -82 + gridView.visible = true + navWrapper.visible = true } } StackView.onActivated: { - navWrapper.state = "in"; - checkIsContentInstalled(); + navWrapper.state = "in" + checkIsContentInstalled() } Action { @@ -51,12 +51,12 @@ Item { Connections { function onInstalledLoadingFinished() { - checkIsContentInstalled(); + checkIsContentInstalled() } function onCountChanged(count) { if (count === 0) - checkIsContentInstalled(); + checkIsContentInstalled() } target: App.installedListModel @@ -71,7 +71,7 @@ Item { Connections { function onSortChanged() { - gridView.positionViewAtBeginning(); + gridView.positionViewAtBeginning() } target: App.installedListFilter @@ -128,12 +128,12 @@ Item { } onContentYChanged: { if (contentY <= -180) - gridView.headerItem.isVisible = true; + gridView.headerItem.isVisible = true else - gridView.headerItem.isVisible = false; + gridView.headerItem.isVisible = false //Pull to refresh if (contentY <= -180 && !refresh && !isDragging) - App.installedListModel.reset(); + App.installedListModel.reset() } anchors { @@ -150,11 +150,11 @@ Item { opacity: 0 onIsVisibleChanged: { if (isVisible) { - txtHeader.color = Material.accent; - txtHeader.text = qsTr("Refreshing!"); + txtHeader.color = Material.accent + txtHeader.text = qsTr("Refreshing!") } else { - txtHeader.color = "gray"; - txtHeader.text = qsTr("Pull to refresh!"); + txtHeader.color = "gray" + txtHeader.text = qsTr("Pull to refresh!") } } @@ -162,7 +162,7 @@ Item { interval: 150 running: true onTriggered: { - animFadeIn.start(); + animFadeIn.start() } } @@ -206,7 +206,7 @@ Item { interval: 400 running: true onTriggered: { - animFadeInTxtFooter.start(); + animFadeInTxtFooter.start() } } @@ -236,15 +236,23 @@ Item { isScrolling: gridView.isScrolling onOpenContextMenu: function (position) { // Set the menu to the current item informations - contextMenu.publishedFileID = delegate.publishedFileID; - contextMenu.absoluteStoragePath = delegate.absoluteStoragePath; - contextMenu.fileName = delegate.customTitle; - const pos = delegate.mapToItem(root, position.x, position.y); + 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; - contextMenu.popup(pos.x, pos.y); + return + if (delegate.type === InstalledType.GodotWallpaper) { + contextMenu.godotItem = editGodotWallpaperComp.createObject() + contextMenu.insertItem(0, contextMenu.godotItem) + } + contextMenu.popup(pos.x, pos.y) } } @@ -252,21 +260,37 @@ Item { snapMode: ScrollBar.SnapOnRelease } } + Component { + id: editGodotWallpaperComp + MenuItem { + text: qsTr("Edit Wallpaper") + objectName: "editWallpaper" + enabled: contextMenu.type === InstalledType.GodotWallpaper + icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_edit.svg" + onClicked: { + App.util.openGodotEditor(contextMenu.absoluteStoragePath) + } + } + } 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") objectName: "openFolder" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_folder_open.svg" onClicked: { - App.util.openFolderInExplorer(contextMenu.absoluteStoragePath); + App.util.openFolderInExplorer(contextMenu.absoluteStoragePath) } } @@ -275,10 +299,12 @@ Item { objectName: enabled ? "removeItem" : "removeWorkshopItem" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_import_export_.svg" onClicked: { - exportFileDialog.absoluteStoragePath = contextMenu.absoluteStoragePath; - let urlFileName = QCore.StandardPaths.writableLocation(QCore.StandardPaths.DesktopLocation) + "/" + contextMenu.fileName + ".screenplay"; - exportFileDialog.currentFile = urlFileName; - exportFileDialog.open(); + exportFileDialog.absoluteStoragePath = contextMenu.absoluteStoragePath + let urlFileName = QCore.StandardPaths.writableLocation( + QCore.StandardPaths.DesktopLocation) + "/" + + contextMenu.fileName + ".screenplay" + exportFileDialog.currentFile = urlFileName + exportFileDialog.open() } } @@ -286,18 +312,21 @@ Item { text: enabled ? qsTr("Remove Item") : qsTr("Remove via Workshop") objectName: enabled ? "removeItem" : "removeWorkshopItem" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_delete.svg" - enabled: contextMenu.publishedFileID === 0 || !App.settings.steamVersion + enabled: contextMenu.publishedFileID === 0 + || !App.settings.steamVersion onClicked: { - deleteDialog.open(); + deleteDialog.open() } } MenuItem { text: qsTr("Open Workshop Page") - enabled: contextMenu.publishedFileID !== 0 && App.settings.steamVersion + enabled: contextMenu.publishedFileID !== 0 + && App.settings.steamVersion icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_steam.svg" onClicked: { - Qt.openUrlExternally("steam://url/CommunityFilePage/" + contextMenu.publishedFileID); + Qt.openUrlExternally( + "steam://url/CommunityFilePage/" + contextMenu.publishedFileID) } } } @@ -310,8 +339,9 @@ Item { modalSource: root.modalSource anchors.centerIn: Overlay.overlay onAccepted: { - root.sidebar.clear(); - App.installedListModel.deinstallItemAt(contextMenu.absoluteStoragePath); + root.sidebar.clear() + App.installedListModel.deinstallItemAt( + contextMenu.absoluteStoragePath) } } @@ -320,7 +350,7 @@ Item { fileMode: FileDialog.SaveFile property string absoluteStoragePath onAccepted: { - exportFileProgressDialog.open(); + exportFileProgressDialog.open() } } @@ -333,7 +363,9 @@ Item { modalSource: root.modalSource closePolicy: Popup.NoAutoClose onOpened: { - const success = App.util.exportProject(exportFileDialog.absoluteStoragePath, exportFileDialog.currentFile); + const success = App.util.exportProject( + exportFileDialog.absoluteStoragePath, + exportFileDialog.currentFile) } onClosed: exportProgressBar.value = 0 ColumnLayout { @@ -358,10 +390,10 @@ Item { id: exportConnections target: App.util function onCompressionProgressChanged(file, proc, total, br, bt) { - exportProgressBar.value = (br * 100 / bt); + exportProgressBar.value = (br * 100 / bt) } function onCompressionFinished() { - exportFileProgressDialog.close(); + exportFileProgressDialog.close() } } } @@ -381,28 +413,31 @@ Item { anchors.fill: parent property string filePath onEntered: function (drag) { - dropPopup.open(); + dropPopup.open() } onDropped: function (drop) { - dropPopup.close(); - dropArea.enabled = false; + dropPopup.close() + dropArea.enabled = false if (drop.urls.length > 1) { - importProjectErrorDialog.title = qsTr("We only support adding one item at once."); - importProjectErrorDialog.open(); - return; + importProjectErrorDialog.title = qsTr( + "We only support adding one item at once.") + importProjectErrorDialog.open() + return } - var file = ""; // Convert url to string - file = "" + drop.urls[0]; + 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."); - importProjectErrorDialog.open(); - return; + importProjectErrorDialog.title = qsTr( + "File type not supported. We only support '.screenplay' files.") + importProjectErrorDialog.open() + return } - importDialog.open(); - dropArea.filePath = file; + importDialog.open() + dropArea.filePath = file } onExited: { - dropPopup.close(); + dropPopup.close() } Util.Dialog { @@ -423,9 +458,11 @@ Item { closePolicy: Popup.NoAutoClose onClosed: importProgressBar.value = 0 onOpened: { - const success = App.util.importProject(dropArea.filePath, App.globalVariables.localStoragePath); - print("finished", success); - dropArea.filePath = ""; + const success = App.util.importProject( + dropArea.filePath, + App.globalVariables.localStoragePath) + print("finished", success) + dropArea.filePath = "" } ColumnLayout { width: parent.width @@ -447,10 +484,10 @@ Item { id: importConnections target: App.util function onExtractionProgressChanged(file, proc, total, br, bt) { - importProgressBar.value = (br * 100 / bt); + importProgressBar.value = (br * 100 / bt) } function onExtractionFinished() { - importDialog.close(); + importDialog.close() } } } @@ -466,8 +503,8 @@ Item { modal: true onOpened: fileDropAnimation.state = "fileDrop" onClosed: { - fileDropAnimation.state = ""; - dropArea.enabled = true; + fileDropAnimation.state = "" + dropArea.enabled = true } Util.FileDropAnimation { diff --git a/ScreenPlay/qml/Installed/ScreenPlayItem.qml b/ScreenPlay/qml/Installed/ScreenPlayItem.qml index e91f4167..79ef8247 100644 --- a/ScreenPlay/qml/Installed/ScreenPlayItem.qml +++ b/ScreenPlay/qml/Installed/ScreenPlayItem.qml @@ -14,6 +14,7 @@ Item { property string screenId property url absoluteStoragePath property int type: InstalledType.Unknown + // Must be var to make it work wit 64bit ints property var publishedFileID: 0 property int itemIndex property bool isScrolling: false diff --git a/ScreenPlay/src/app.cpp b/ScreenPlay/src/app.cpp index 06ac8417..3bd9cde9 100644 --- a/ScreenPlay/src/app.cpp +++ b/ScreenPlay/src/app.cpp @@ -138,10 +138,9 @@ void App::init() 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_globalVariables); m_profileListModel = make_shared(m_globalVariables); m_settings = make_shared(m_globalVariables); m_installedListModel = make_shared(m_globalVariables, m_settings); 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/util.cpp b/ScreenPlay/src/util.cpp index 669a91d6..7743c8c9 100644 --- a/ScreenPlay/src/util.cpp +++ b/ScreenPlay/src/util.cpp @@ -23,8 +23,10 @@ namespace ScreenPlay { /*! \brief Constructor. */ -Util::Util() +Util::Util( + const std::shared_ptr& globalVariables) : QObject(nullptr) + , m_globalVariables { globalVariables } { m_extractor = std::make_unique(); m_compressor = std::make_unique(); @@ -144,6 +146,15 @@ bool Util::exportProject(QString contentPath, QString exportFileName) return true; } +bool Util::openGodotEditor(QString contentPath) const +{ + const QList godotCmd = { "--editor", "--path", toLocal(contentPath) }; + QProcess process; + process.setProgram(m_globalVariables->godotEditorExecutablePath().toString()); + process.setArguments(godotCmd); + return process.startDetached(); +} + /*! \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. From f6495d1eaad5bb1927e139b88e342f3a391b29af Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Thu, 16 Nov 2023 13:28:11 +0100 Subject: [PATCH 10/32] Add missing file --- ScreenPlay/assets/icons/icon_edit.svg | 1 + 1 file changed, 1 insertion(+) create mode 100644 ScreenPlay/assets/icons/icon_edit.svg 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 From 11faefdbfd3c4c11d46ce726a85ef0d50275d951 Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Thu, 16 Nov 2023 13:43:19 +0100 Subject: [PATCH 11/32] Add godot build copy as custom cmake step --- ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt b/ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt index 60ea81de..b09722ae 100644 --- a/ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt +++ b/ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt @@ -32,8 +32,16 @@ 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" +) -target_compile_features(${PROJECT_NAME} PRIVATE cxx_std_17) # 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). From 7ea263dc2fecf9f8367746bfb89a7f0aae03f67d Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Fri, 17 Nov 2023 13:37:47 +0100 Subject: [PATCH 12/32] Add Godot export_presets to wizard to fix package of pck file Update godot-cpp Format all files Fix Godot wallpaper setup on primary screen --- Content/wallpaper_godot_fjord/project.godot | 2 +- ScreenPlay/CMakeLists.txt | 9 +- ScreenPlay/inc/public/ScreenPlay/wizards.h | 1 - ScreenPlay/main.qml | 109 ++++++------ ScreenPlay/qml/Create/CreateSidebar.qml | 1 - .../WizardsFiles/Godot_v5/export_presets.cfg | 15 ++ ScreenPlay/qml/Installed/Installed.qml | 160 ++++++++---------- ScreenPlay/qml/Navigation/Navigation.qml | 5 +- ScreenPlay/qml/TrayIcon.qml | 62 ++++--- ScreenPlay/src/monitorlistmodel.cpp | 4 +- ScreenPlay/src/wizards.cpp | 15 +- .../Godot/GDExtention/CMakeLists.txt | 11 +- .../Godot/GDExtention/extern/godot-cpp | 2 +- .../src/ScreenPlayGodotWallpaper.cpp | 106 ++++++------ .../Godot/ScreenPlayGodot/main.gd | 2 +- ScreenPlayWallpaper/qml/Test.qml | 9 +- .../src/windowsintegration.cpp | 8 +- ScreenPlayWallpaper/src/windowsintegration.h | 26 +-- 18 files changed, 274 insertions(+), 273 deletions(-) create mode 100644 ScreenPlay/qml/Create/WizardsFiles/Godot_v5/export_presets.cfg diff --git a/Content/wallpaper_godot_fjord/project.godot b/Content/wallpaper_godot_fjord/project.godot index cdad8da6..d60e8d8a 100644 --- a/Content/wallpaper_godot_fjord/project.godot +++ b/Content/wallpaper_godot_fjord/project.godot @@ -12,7 +12,7 @@ config_version=5 config/name="Fjord" run/main_scene="res://wallpaper.tscn" -config/features=PackedStringArray("4.1", "Mobile") +config/features=PackedStringArray("4.2", "Mobile") config/icon="res://icon.svg" [rendering] diff --git a/ScreenPlay/CMakeLists.txt b/ScreenPlay/CMakeLists.txt index 73391ae7..7736f125 100644 --- a/ScreenPlay/CMakeLists.txt +++ b/ScreenPlay/CMakeLists.txt @@ -60,6 +60,7 @@ set(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,14 +74,14 @@ set(QML qml/Create/Wizards/ImportWebm/ImportWebmConvert.qml qml/Create/Wizards/ImportWebm/ImportWebmInit.qml qml/Create/Wizards/QMLWallpaper.qml - qml/Create/Wizards/GodotWallpaper.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/Create/WizardsFiles/Godot_v5/export_presets.cfg qml/Create/WizardsFiles/Godot_v5/project.godot qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn + qml/Create/WizardsFiles/QMLWallpaperMain.qml + qml/Create/WizardsFiles/QMLWidgetMain.qml qml/Installed/Installed.qml qml/Installed/InstalledNavigation.qml qml/Installed/InstalledWelcomeScreen.qml @@ -149,6 +150,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 @@ -185,7 +187,6 @@ set(RESOURCES assets/icons/icon_widgets.svg assets/icons/icon_window.svg assets/icons/item_banner_new.svg - assets/icons/icon_edit.svg assets/icons/monitor_setup.svg assets/icons/steam_default_avatar.png assets/images/Early_Access.png diff --git a/ScreenPlay/inc/public/ScreenPlay/wizards.h b/ScreenPlay/inc/public/ScreenPlay/wizards.h index aff61fc6..2150ef30 100644 --- a/ScreenPlay/inc/public/ScreenPlay/wizards.h +++ b/ScreenPlay/inc/public/ScreenPlay/wizards.h @@ -84,7 +84,6 @@ public slots: const QString& previewThumbnail, const QVector& tags); - void createGodotWallpaper( const QString& title, const QString& licenseName, diff --git a/ScreenPlay/main.qml b/ScreenPlay/main.qml index 3a6077cd..06a58e21 100644 --- a/ScreenPlay/main.qml +++ b/ScreenPlay/main.qml @@ -23,40 +23,36 @@ ApplicationWindow { function setTheme(theme) { switch (theme) { case Settings.System: - root.Material.theme = Material.System - break + root.Material.theme = Material.System; + break; case Settings.Dark: - root.Material.theme = Material.Dark - break + root.Material.theme = Material.Dark; + break; case Settings.Light: - root.Material.theme = Material.Light - break + root.Material.theme = Material.Light; + break; } } function switchPage(name) { if (nav.currentNavigationName === name) { if (name === "Installed") - App.installedListModel.reset() + App.installedListModel.reset(); } if (name === "Installed") { - stackView.replace( - "qrc:/qml/ScreenPlayApp/qml/Installed/Installed.qml", { - "sidebar": sidebar - }) - return + stackView.replace("qrc:/qml/ScreenPlayApp/qml/Installed/Installed.qml", { + "sidebar": sidebar + }); + return; } - stackView.replace( - "qrc:/qml/ScreenPlayApp/qml/" + name + "/" + name + ".qml", - { - "modalSource": content - }) - nav.setNavigation(name) - sidebar.state = "inactive" + stackView.replace("qrc:/qml/ScreenPlayApp/qml/" + name + "/" + name + ".qml", { + "modalSource": content + }); + nav.setNavigation(name); + sidebar.state = "inactive"; } - color: Material.theme === Material.Dark ? Qt.darker( - Material.background) : Material.background + color: Material.theme === Material.Dark ? Qt.darker(Material.background) : Material.background // Set visible if the -silent parameter was not set (see app.cpp end of constructor). visible: false width: 1400 @@ -78,28 +74,25 @@ ApplicationWindow { Material.accent: Material.color(Material.Orange) onVisibilityChanged: { if (root.visibility !== 2) - return - + return; } onClosing: close => { - close.accepted = false - if (App.screenPlayManager.activeWallpaperCounter === 0 - && App.screenPlayManager.activeWidgetsCounter === 0) { - App.exit() - } - const alwaysMinimize = settings.value("alwaysMinimize", null) - if (alwaysMinimize === null) { - console.error( - "Unable to retreive alwaysMinimize setting") - } - if (alwaysMinimize === "true") { - root.hide() - App.showDockIcon(false) - return - } - exitDialog.open() - } + close.accepted = false; + if (App.screenPlayManager.activeWallpaperCounter === 0 && App.screenPlayManager.activeWidgetsCounter === 0) { + App.exit(); + } + const alwaysMinimize = settings.value("alwaysMinimize", null); + if (alwaysMinimize === null) { + console.error("Unable to retreive alwaysMinimize setting"); + } + if (alwaysMinimize === "true") { + root.hide(); + App.showDockIcon(false); + return; + } + exitDialog.open(); + } QCore.Settings { id: settings @@ -112,13 +105,13 @@ ApplicationWindow { } Component.onCompleted: { - setTheme(App.settings.theme) + setTheme(App.settings.theme); stackView.push("qrc:/qml/ScreenPlayApp/qml/Installed/Installed.qml", { - "sidebar": sidebar - }) + "sidebar": sidebar + }); if (!App.settings.silentStart) { - App.showDockIcon(true) - root.show() + App.showDockIcon(true); + root.show(); } App.installedListModel.reset(); } @@ -150,7 +143,7 @@ ApplicationWindow { Connections { function onThemeChanged(theme) { - setTheme(theme) + setTheme(theme); } target: App.settings @@ -158,7 +151,7 @@ ApplicationWindow { Connections { function onRequestNavigation(nav) { - switchPage(nav) + switchPage(nav); } target: App.util @@ -166,18 +159,16 @@ ApplicationWindow { Connections { function onRequestRaise() { - App.showDockIcon(true) - root.show() + App.showDockIcon(true); + root.show(); } function onActiveWidgetsCounterChanged() { - plausible.pageView( - "widget/count/" + App.screenPlayManager.activeWidgetsCounter) + plausible.pageView("widget/count/" + App.screenPlayManager.activeWidgetsCounter); } function onActiveWallpaperCounterChanged() { - plausible.pageView( - "wallpaper/count/" + App.screenPlayManager.activeWallpaperCounter) + plausible.pageView("wallpaper/count/" + App.screenPlayManager.activeWallpaperCounter); } target: App.screenPlayManager @@ -235,16 +226,16 @@ ApplicationWindow { Connections { function onSetSidebarActive(active) { if (active) - sidebar.state = "active" + sidebar.state = "active"; else - sidebar.state = "inactive" + sidebar.state = "inactive"; } function onSetNavigationItem(pos) { if (pos === 0) - nav.onPageChanged("Create") + nav.onPageChanged("Create"); else - nav.onPageChanged("Workshop") + nav.onPageChanged("Workshop"); } target: stackView.currentItem @@ -273,8 +264,8 @@ ApplicationWindow { } onChangePage: function (name) { - monitors.close() - switchPage(name) + monitors.close(); + switchPage(name); } } } diff --git a/ScreenPlay/qml/Create/CreateSidebar.qml b/ScreenPlay/qml/Create/CreateSidebar.qml index 50bb7aab..a46fe60b 100644 --- a/ScreenPlay/qml/Create/CreateSidebar.qml +++ b/ScreenPlay/qml/Create/CreateSidebar.qml @@ -92,7 +92,6 @@ Rectangle { objectName: "" } - ListElement { headline: qsTr("QML Wallpaper") source: "qrc:/qml/ScreenPlayApp/qml/Create/Wizards/QMLWallpaper.qml" 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/Installed/Installed.qml b/ScreenPlay/qml/Installed/Installed.qml index 1c4c9470..a4e82ca7 100644 --- a/ScreenPlay/qml/Installed/Installed.qml +++ b/ScreenPlay/qml/Installed/Installed.qml @@ -25,23 +25,23 @@ Item { function checkIsContentInstalled() { if (App.installedListModel.count === 0) { - loaderHelp.active = true - gridView.footerItem.isVisible = true - gridView.visible = false - navWrapper.visible = false + loaderHelp.active = true; + gridView.footerItem.isVisible = true; + gridView.visible = false; + navWrapper.visible = false; } else { - loaderHelp.active = false - gridView.footerItem.isVisible = false - refresh = false - gridView.contentY = -82 - gridView.visible = true - navWrapper.visible = true + loaderHelp.active = false; + gridView.footerItem.isVisible = false; + refresh = false; + gridView.contentY = -82; + gridView.visible = true; + navWrapper.visible = true; } } StackView.onActivated: { - navWrapper.state = "in" - checkIsContentInstalled() + navWrapper.state = "in"; + checkIsContentInstalled(); } Action { @@ -51,12 +51,12 @@ Item { Connections { function onInstalledLoadingFinished() { - checkIsContentInstalled() + checkIsContentInstalled(); } function onCountChanged(count) { if (count === 0) - checkIsContentInstalled() + checkIsContentInstalled(); } target: App.installedListModel @@ -71,7 +71,7 @@ Item { Connections { function onSortChanged() { - gridView.positionViewAtBeginning() + gridView.positionViewAtBeginning(); } target: App.installedListFilter @@ -85,8 +85,6 @@ Item { property bool isScrolling: gridView.verticalVelocity !== 0 boundsBehavior: Flickable.DragOverBounds - maximumFlickVelocity: 3000 - flickDeceleration: 7500 anchors.fill: parent cellWidth: 340 cellHeight: 200 @@ -128,12 +126,12 @@ Item { } onContentYChanged: { if (contentY <= -180) - gridView.headerItem.isVisible = true + gridView.headerItem.isVisible = true; else - gridView.headerItem.isVisible = false + gridView.headerItem.isVisible = false; //Pull to refresh if (contentY <= -180 && !refresh && !isDragging) - App.installedListModel.reset() + App.installedListModel.reset(); } anchors { @@ -150,11 +148,11 @@ Item { opacity: 0 onIsVisibleChanged: { if (isVisible) { - txtHeader.color = Material.accent - txtHeader.text = qsTr("Refreshing!") + txtHeader.color = Material.accent; + txtHeader.text = qsTr("Refreshing!"); } else { - txtHeader.color = "gray" - txtHeader.text = qsTr("Pull to refresh!") + txtHeader.color = "gray"; + txtHeader.text = qsTr("Pull to refresh!"); } } @@ -162,7 +160,7 @@ Item { interval: 150 running: true onTriggered: { - animFadeIn.start() + animFadeIn.start(); } } @@ -206,7 +204,7 @@ Item { interval: 400 running: true onTriggered: { - animFadeInTxtFooter.start() + animFadeInTxtFooter.start(); } } @@ -236,23 +234,23 @@ Item { isScrolling: gridView.isScrolling onOpenContextMenu: function (position) { // Set the menu to the current item informations - 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) + 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 + return; if (delegate.type === InstalledType.GodotWallpaper) { - contextMenu.godotItem = editGodotWallpaperComp.createObject() - contextMenu.insertItem(0, contextMenu.godotItem) + contextMenu.godotItem = editGodotWallpaperComp.createObject(); + contextMenu.insertItem(0, contextMenu.godotItem); } - contextMenu.popup(pos.x, pos.y) + contextMenu.popup(pos.x, pos.y); } } @@ -269,7 +267,7 @@ Item { enabled: contextMenu.type === InstalledType.GodotWallpaper icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_edit.svg" onClicked: { - App.util.openGodotEditor(contextMenu.absoluteStoragePath) + App.util.openGodotEditor(contextMenu.absoluteStoragePath); } } } @@ -290,7 +288,7 @@ Item { objectName: "openFolder" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_folder_open.svg" onClicked: { - App.util.openFolderInExplorer(contextMenu.absoluteStoragePath) + App.util.openFolderInExplorer(contextMenu.absoluteStoragePath); } } @@ -299,12 +297,10 @@ Item { objectName: enabled ? "removeItem" : "removeWorkshopItem" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_import_export_.svg" onClicked: { - exportFileDialog.absoluteStoragePath = contextMenu.absoluteStoragePath - let urlFileName = QCore.StandardPaths.writableLocation( - QCore.StandardPaths.DesktopLocation) + "/" - + contextMenu.fileName + ".screenplay" - exportFileDialog.currentFile = urlFileName - exportFileDialog.open() + exportFileDialog.absoluteStoragePath = contextMenu.absoluteStoragePath; + let urlFileName = QCore.StandardPaths.writableLocation(QCore.StandardPaths.DesktopLocation) + "/" + contextMenu.fileName + ".screenplay"; + exportFileDialog.currentFile = urlFileName; + exportFileDialog.open(); } } @@ -312,21 +308,18 @@ Item { text: enabled ? qsTr("Remove Item") : qsTr("Remove via Workshop") objectName: enabled ? "removeItem" : "removeWorkshopItem" icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_delete.svg" - enabled: contextMenu.publishedFileID === 0 - || !App.settings.steamVersion + enabled: contextMenu.publishedFileID === 0 || !App.settings.steamVersion onClicked: { - deleteDialog.open() + deleteDialog.open(); } } MenuItem { text: qsTr("Open Workshop Page") - enabled: contextMenu.publishedFileID !== 0 - && App.settings.steamVersion + enabled: contextMenu.publishedFileID !== 0 && App.settings.steamVersion icon.source: "qrc:/qml/ScreenPlayApp/assets/icons/icon_steam.svg" onClicked: { - Qt.openUrlExternally( - "steam://url/CommunityFilePage/" + contextMenu.publishedFileID) + Qt.openUrlExternally("steam://url/CommunityFilePage/" + contextMenu.publishedFileID); } } } @@ -339,9 +332,8 @@ Item { modalSource: root.modalSource anchors.centerIn: Overlay.overlay onAccepted: { - root.sidebar.clear() - App.installedListModel.deinstallItemAt( - contextMenu.absoluteStoragePath) + root.sidebar.clear(); + App.installedListModel.deinstallItemAt(contextMenu.absoluteStoragePath); } } @@ -350,7 +342,7 @@ Item { fileMode: FileDialog.SaveFile property string absoluteStoragePath onAccepted: { - exportFileProgressDialog.open() + exportFileProgressDialog.open(); } } @@ -363,9 +355,7 @@ Item { modalSource: root.modalSource closePolicy: Popup.NoAutoClose onOpened: { - const success = App.util.exportProject( - exportFileDialog.absoluteStoragePath, - exportFileDialog.currentFile) + const success = App.util.exportProject(exportFileDialog.absoluteStoragePath, exportFileDialog.currentFile); } onClosed: exportProgressBar.value = 0 ColumnLayout { @@ -390,10 +380,10 @@ Item { id: exportConnections target: App.util function onCompressionProgressChanged(file, proc, total, br, bt) { - exportProgressBar.value = (br * 100 / bt) + exportProgressBar.value = (br * 100 / bt); } function onCompressionFinished() { - exportFileProgressDialog.close() + exportFileProgressDialog.close(); } } } @@ -413,31 +403,29 @@ Item { anchors.fill: parent property string filePath onEntered: function (drag) { - dropPopup.open() + dropPopup.open(); } onDropped: function (drop) { - dropPopup.close() - dropArea.enabled = false + dropPopup.close(); + dropArea.enabled = false; if (drop.urls.length > 1) { - importProjectErrorDialog.title = qsTr( - "We only support adding one item at once.") - importProjectErrorDialog.open() - return + importProjectErrorDialog.title = qsTr("We only support adding one item at once."); + importProjectErrorDialog.open(); + return; } - var file = "" + var file = ""; // Convert url to string - file = "" + drop.urls[0] + file = "" + drop.urls[0]; if (!file.endsWith('.screenplay')) { - importProjectErrorDialog.title = qsTr( - "File type not supported. We only support '.screenplay' files.") - importProjectErrorDialog.open() - return + importProjectErrorDialog.title = qsTr("File type not supported. We only support '.screenplay' files."); + importProjectErrorDialog.open(); + return; } - importDialog.open() - dropArea.filePath = file + importDialog.open(); + dropArea.filePath = file; } onExited: { - dropPopup.close() + dropPopup.close(); } Util.Dialog { @@ -458,11 +446,9 @@ Item { closePolicy: Popup.NoAutoClose onClosed: importProgressBar.value = 0 onOpened: { - const success = App.util.importProject( - dropArea.filePath, - App.globalVariables.localStoragePath) - print("finished", success) - dropArea.filePath = "" + const success = App.util.importProject(dropArea.filePath, App.globalVariables.localStoragePath); + print("finished", success); + dropArea.filePath = ""; } ColumnLayout { width: parent.width @@ -484,10 +470,10 @@ Item { id: importConnections target: App.util function onExtractionProgressChanged(file, proc, total, br, bt) { - importProgressBar.value = (br * 100 / bt) + importProgressBar.value = (br * 100 / bt); } function onExtractionFinished() { - importDialog.close() + importDialog.close(); } } } @@ -503,8 +489,8 @@ Item { modal: true onOpened: fileDropAnimation.state = "fileDrop" onClosed: { - fileDropAnimation.state = "" - dropArea.enabled = true + fileDropAnimation.state = ""; + dropArea.enabled = true; } Util.FileDropAnimation { diff --git a/ScreenPlay/qml/Navigation/Navigation.qml b/ScreenPlay/qml/Navigation/Navigation.qml index 6f6c4d87..42bacd6b 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,navCommunity, navSettings] + property var navArray: [navCreate, navWorkshop, navInstalled, navCommunity, navSettings] property bool navActive: true property Item modalSource property int iconWidth: 16 @@ -30,11 +30,10 @@ Rectangle { } function setNavigation(name) { for (var i = 0; i < navArray.length; i++) { - print(navArray[i].objectName) if (navArray[i].objectName === name) { navArray[i].state = "active"; root.currentNavigationName = name; - tabBar.currentIndex = navArray[i].index + tabBar.currentIndex = navArray[i].index; } else { navArray[i].state = "inactive"; } diff --git a/ScreenPlay/qml/TrayIcon.qml b/ScreenPlay/qml/TrayIcon.qml index 38db305e..6543e5f5 100644 --- a/ScreenPlay/qml/TrayIcon.qml +++ b/ScreenPlay/qml/TrayIcon.qml @@ -14,23 +14,22 @@ SystemTrayIcon { onActivated: function (reason) { switch (reason) { case SystemTrayIcon.Unknown: - break + break; case SystemTrayIcon.Context: - break + break; case SystemTrayIcon.DoubleClick: - window.show() - break + window.show(); + break; case SystemTrayIcon.Trigger: - break + break; case SystemTrayIcon.MiddleClick: - break + break; } } - function open(){ - App.showDockIcon(true) - window.show() - + function open() { + App.showDockIcon(true); + window.show(); } menu: Menu { @@ -38,16 +37,16 @@ SystemTrayIcon { id: miOpenScreenPlay text: qsTr("Open ScreenPlay") onTriggered: { - root.open() + root.open(); } } MenuItem { id: miChangeWallpaperSettings text: qsTr("Change Wallpaper settings") onTriggered: { - root.open() + root.open(); App.util.setNavigation("Installed"); - App.util.setToggleWallpaperConfiguration() + App.util.setToggleWallpaperConfiguration(); } } MenuItem { @@ -57,7 +56,7 @@ SystemTrayIcon { MenuItem { text: qsTr("Browse Workshop") onTriggered: { - root.open() + root.open(); App.util.setNavigation("Workshop"); } } @@ -66,7 +65,7 @@ SystemTrayIcon { id: miCreate text: qsTr("Create new Wallpaper or Widgets") onTriggered: { - root.open() + root.open(); App.util.setNavigation("Create"); } } @@ -74,7 +73,7 @@ SystemTrayIcon { id: miSettings text: qsTr("Settings") onTriggered: { - root.open() + root.open(); App.util.setNavigation("Settings"); } } @@ -85,14 +84,13 @@ SystemTrayIcon { MenuItem { text: qsTr("Forums") onTriggered: { - Qt.openUrlExternally("https://forum.screen-play.app/") + Qt.openUrlExternally("https://forum.screen-play.app/"); } } MenuItem { text: qsTr("Frequently Asked Questions (FAQ)") onTriggered: { - Qt.openUrlExternally( - "https://kelteseth.gitlab.io/ScreenPlayDocs/Frequently%20Asked%20Questions/") + Qt.openUrlExternally("https://kelteseth.gitlab.io/ScreenPlayDocs/Frequently%20Asked%20Questions/"); } } MenuItem { @@ -106,13 +104,13 @@ SystemTrayIcon { text: qsTr("Mute all") onTriggered: { if (miMuteAll.isMuted) { - isMuted = false - miMuteAll.text = qsTr("Mute all") - App.screenPlayManager.setAllWallpaperValue("muted", "true") + isMuted = false; + miMuteAll.text = qsTr("Mute all"); + App.screenPlayManager.setAllWallpaperValue("muted", "true"); } else { - isMuted = true - miMuteAll.text = qsTr("Unmute all") - App.screenPlayManager.setAllWallpaperValue("muted", "false") + isMuted = true; + miMuteAll.text = qsTr("Unmute all"); + App.screenPlayManager.setAllWallpaperValue("muted", "false"); } } } @@ -125,15 +123,13 @@ SystemTrayIcon { text: qsTr("Pause all") onTriggered: { if (miStopAll.isPlaying) { - isPlaying = false - miStopAll.text = qsTr("Pause all") - App.screenPlayManager.setAllWallpaperValue("isPlaying", - "true") + isPlaying = false; + miStopAll.text = qsTr("Pause all"); + App.screenPlayManager.setAllWallpaperValue("isPlaying", "true"); } else { - isPlaying = true - miStopAll.text = qsTr("Play all") - App.screenPlayManager.setAllWallpaperValue("isPlaying", - "false") + isPlaying = true; + miStopAll.text = qsTr("Play all"); + App.screenPlayManager.setAllWallpaperValue("isPlaying", "false"); } } } diff --git a/ScreenPlay/src/monitorlistmodel.cpp b/ScreenPlay/src/monitorlistmodel.cpp index 4a3fdfd0..904d57ce 100644 --- a/ScreenPlay/src/monitorlistmodel.cpp +++ b/ScreenPlay/src/monitorlistmodel.cpp @@ -114,7 +114,7 @@ void MonitorListModel::loadMonitors() #ifdef Q_OS_WIN QModelIndex index; - auto monitors = WindowsIntegration().GetAllMonitors(); + auto monitors = WindowsIntegration().getAllMonitors(); // This offset lets us center the monitor selection view in the center int offsetX = 0; @@ -131,7 +131,7 @@ void MonitorListModel::loadMonitors() } } - for(int i = 0; auto& monitor : monitors) { + 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; diff --git a/ScreenPlay/src/wizards.cpp b/ScreenPlay/src/wizards.cpp index 45d2756e..952cd541 100644 --- a/ScreenPlay/src/wizards.cpp +++ b/ScreenPlay/src/wizards.cpp @@ -289,7 +289,6 @@ void Wizards::createQMLWallpaper( }); } - /*! \brief . */ @@ -337,18 +336,26 @@ void Wizards::createGodotWallpaper( return; } - if (!Util::writeSettings(obj, workingPath + "/project.json")) { emit widgetCreationFinished(WizardResult::WriteProjectFileError); return; } if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/Godot_v5/project.godot", workingPath + "/project.godot")) { - qWarning() << "Could not write main.qml"; + qWarning() << "Could not write project.godot"; return; } + if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn", workingPath + "/wallpaper.tscn")) { - qWarning() << "Could not write main.qml"; + 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 (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/Godot_v5/export_presets.cfg", workingPath + "/export_presets.cfg")) { + qWarning() << "Could not write export_presets.cfg"; return; } diff --git a/ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt b/ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt index b09722ae..a201be38 100644 --- a/ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt +++ b/ScreenPlayWallpaper/Godot/GDExtention/CMakeLists.txt @@ -32,16 +32,15 @@ project(ScreenPlayGodotWallpaper LANGUAGES CXX) # Create our library add_library(${PROJECT_NAME} SHARED) -# Runs after compilation -# Enable executing python scripts +# Runs after compilation Enable executing python scripts find_package(Python COMPONENTS Interpreter) -add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD +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" -) - + 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). diff --git a/ScreenPlayWallpaper/Godot/GDExtention/extern/godot-cpp b/ScreenPlayWallpaper/Godot/GDExtention/extern/godot-cpp index c1196a1a..c4b7b08c 160000 --- a/ScreenPlayWallpaper/Godot/GDExtention/extern/godot-cpp +++ b/ScreenPlayWallpaper/Godot/GDExtention/extern/godot-cpp @@ -1 +1 @@ -Subproject commit c1196a1ab0a1ca166d0e5e2f08f9fe4156118c5e +Subproject commit c4b7b08c917e4dd41e4a53d28660b7358e60d7b1 diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp index 8d124242..b219fb0f 100644 --- a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp @@ -74,18 +74,26 @@ bool ScreenPlayGodotWallpaper::configureWindowGeometry() bool ScreenPlayGodotWallpaper::init(int activeScreen) { auto* displayServer = DisplayServer::get_singleton(); - { - int64_t handle_int = displayServer->window_get_native_handle(godot::DisplayServer::HandleType::WINDOW_HANDLE, activeScreen); - HWND hwnd = reinterpret_cast(static_cast(handle_int)); - m_windowsIntegration.setWindowHandle(hwnd); + + 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; } - hideFromTaskbar(m_windowsIntegration.windowHandle()); if (!configureWindowGeometry()) { return false; } - ShowWindow(m_windowsIntegration.windowHandle(), SW_HIDE); - + 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)); }; @@ -101,38 +109,38 @@ bool ScreenPlayGodotWallpaper::init(int activeScreen) SetWindowText(m_windowsIntegration.windowHandle(), windowTitle.c_str()); ShowWindow(m_windowsIntegration.windowHandle(), SW_SHOW); - m_windowsIntegration.setupWindowMouseHook(); + // 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 - } + // 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); - } - }); + // 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; } @@ -222,18 +230,6 @@ void ScreenPlayGodotWallpaper::messageReceived(const std::string& key, const std std::cerr << "Out of range: " << oor.what() << std::endl; } } -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::exit() { // Somehow this gets called at editor startup @@ -247,6 +243,18 @@ bool ScreenPlayGodotWallpaper::exit() 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; diff --git a/ScreenPlayWallpaper/Godot/ScreenPlayGodot/main.gd b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/main.gd index 96b4569a..dbf71198 100644 --- a/ScreenPlayWallpaper/Godot/ScreenPlayGodot/main.gd +++ b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/main.gd @@ -55,7 +55,7 @@ func _ready(): # yet setup via screenplay_manager.init() get_tree().quit() return - Engine.set_max_fps(24) + Engine.set_max_fps(144) var ok = screen_play_wallpaper.init(screen_play_wallpaper.get_activeScreensList()[0]) if not ok: diff --git a/ScreenPlayWallpaper/qml/Test.qml b/ScreenPlayWallpaper/qml/Test.qml index befb8cc3..1f292e03 100644 --- a/ScreenPlayWallpaper/qml/Test.qml +++ b/ScreenPlayWallpaper/qml/Test.qml @@ -216,20 +216,17 @@ Rectangle { spacing: 20 TextField { placeholderText: "Edit me" - } Button { text: "Exit" onClicked: { - Qt.callLater(function () { - Wallpaper.terminate(); - }); + Qt.callLater(function () { + Wallpaper.terminate(); + }); } } - } - MultimediaView { width: 1000 height: 400 diff --git a/ScreenPlayWallpaper/src/windowsintegration.cpp b/ScreenPlayWallpaper/src/windowsintegration.cpp index 5841bd6e..def9feef 100644 --- a/ScreenPlayWallpaper/src/windowsintegration.cpp +++ b/ScreenPlayWallpaper/src/windowsintegration.cpp @@ -68,7 +68,7 @@ BOOL SearchForWorkerWindow(HWND hwnd, LPARAM lparam) return TRUE; } -std::vector WindowsIntegration::GetAllMonitors() +std::vector WindowsIntegration::getAllMonitors() { std::vector monitors; @@ -150,7 +150,7 @@ WindowsIntegration::MonitorResult WindowsIntegration::setupWallpaperForOneScreen return { std::nullopt, MonitorResultStatus::WorkerWindowHandleInvalidError }; } - std::vector monitors = GetAllMonitors(); + std::vector monitors = getAllMonitors(); for (const auto& monitor : monitors) { monitor.print(); if (monitor.index != activeScreen) @@ -212,7 +212,7 @@ WindowsIntegration::MonitorResult WindowsIntegration::setupWallpaperForOneScreen */ WindowsIntegration::SpanResult WindowsIntegration::setupWallpaperForMultipleScreens(const std::vector& activeScreens) { - std::vector monitors = GetAllMonitors(); + std::vector monitors = getAllMonitors(); int leftmost = INT_MAX; int topmost = INT_MAX; @@ -272,7 +272,7 @@ WindowsIntegration::SpanResult WindowsIntegration::setupWallpaperForMultipleScre */ WindowsIntegration::SpanResult WindowsIntegration::setupWallpaperForAllScreens() { - std::vector monitors = GetAllMonitors(); + std::vector monitors = getAllMonitors(); int leftmost = INT_MAX; int topmost = INT_MAX; diff --git a/ScreenPlayWallpaper/src/windowsintegration.h b/ScreenPlayWallpaper/src/windowsintegration.h index 14cf94a6..6643bd3d 100644 --- a/ScreenPlayWallpaper/src/windowsintegration.h +++ b/ScreenPlayWallpaper/src/windowsintegration.h @@ -7,6 +7,7 @@ // Do not change windows.h order ! #include +#include #include #include #include @@ -22,16 +23,21 @@ struct 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 << "Monitor Info:" << std::endl; - std::cout << "Monitor ID: " << monitorID << std::endl; - std::cout << "Index: " << index << std::endl; - std::cout << "Position: (" << position.left << ", " << position.top << ", " - << position.right << ", " << position.bottom << ")" << std::endl; - std::cout << "Size: (" << size.cx << "x" << size.cy << ")" << std::endl; - std::cout << "Scale Factor: " << scaleFactor << std::endl; + std::cout << toString() << std::endl; } }; @@ -41,8 +47,6 @@ BOOL CALLBACK GetMonitorByHandle(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcM BOOL CALLBACK FindTheDesiredWnd(HWND hWnd, LPARAM lParam); BOOL WINAPI SearchForWorkerWindow(HWND hwnd, LPARAM lparam); - - struct Point { int x = 0; int y = 0; @@ -81,7 +85,7 @@ public: bool searchWorkerWindowToParentTo(); float getScaling(const int monitorIndex) const; - std::vector GetAllMonitors(); + std::vector getAllMonitors(); int GetMonitorIndex(HMONITOR hMonitor); bool checkForFullScreenWindow(HWND windowHandle); WindowsIntegration::MonitorResult setupWallpaperForOneScreen(const int activeScreen, std::function updateWindowSize); From 395fe67bd4b1bd27c50199e99f700588f74ae3b6 Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Wed, 22 Nov 2023 10:33:00 +0100 Subject: [PATCH 13/32] Fix uninstalling items Path vairable changed and the logic did not make sense. First remove the item so that the qml engine removes all open images then remove the files. --- .../public/ScreenPlay/installedlistmodel.h | 2 +- ScreenPlay/qml/Installed/Installed.qml | 4 ++- ScreenPlay/src/installedlistmodel.cpp | 34 +++++++++---------- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h b/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h index cc0ce26a..86b3f3ab 100644 --- a/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h +++ b/ScreenPlay/inc/public/ScreenPlay/installedlistmodel.h @@ -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) { diff --git a/ScreenPlay/qml/Installed/Installed.qml b/ScreenPlay/qml/Installed/Installed.qml index a4e82ca7..92e03bf4 100644 --- a/ScreenPlay/qml/Installed/Installed.qml +++ b/ScreenPlay/qml/Installed/Installed.qml @@ -333,7 +333,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) + } } } diff --git a/ScreenPlay/src/installedlistmodel.cpp b/ScreenPlay/src/installedlistmodel.cpp index 7fbf57fa..ed555713 100644 --- a/ScreenPlay/src/installedlistmodel.cpp +++ b/ScreenPlay/src/installedlistmodel.cpp @@ -59,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 = ScreenPlayUtil::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()) { @@ -115,6 +114,7 @@ void InstalledListModel::deinstallItemAt(const QString& absoluteStoragePath) m_fileSystemWatcher.blockSignals(false); }); }); + return true; } /*! From fafd85d403a4e39796d4ef55abd5acff7c2f99e7 Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Wed, 22 Nov 2023 11:55:21 +0100 Subject: [PATCH 14/32] Fix website wallpaper not included in installed --- ScreenPlayUtil/src/projectfile.cpp | 31 ++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) diff --git a/ScreenPlayUtil/src/projectfile.cpp b/ScreenPlayUtil/src/projectfile.cpp index b58394c6..13fb6f68 100644 --- a/ScreenPlayUtil/src/projectfile.cpp +++ b/ScreenPlayUtil/src/projectfile.cpp @@ -36,22 +36,25 @@ bool ProjectFile::init() } type = typeParsed.value(); - // Required: - if (!obj.contains("file")) + // File is required. Website Wallpaper doe not have a file, but a url + if (!obj.contains("file") && type != ScreenPlay::InstalledType::InstalledType::WebsiteWallpaper) return false; - file = obj.value("file").toString(); - if (type == ScreenPlay::InstalledType::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; + if (type != ScreenPlay::InstalledType::InstalledType::WebsiteWallpaper) { + file = obj.value("file").toString(); + + if (type == ScreenPlay::InstalledType::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; + } } } From a21829ea0527aac3c022aa9f2e2da0a88c1fbd3e Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Wed, 22 Nov 2023 11:57:48 +0100 Subject: [PATCH 15/32] Add default thumbnail image creation in wizards --- ScreenPlay/inc/public/ScreenPlay/wizards.h | 1 + ScreenPlay/src/wizards.cpp | 87 +++++++++++++++++----- 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/ScreenPlay/inc/public/ScreenPlay/wizards.h b/ScreenPlay/inc/public/ScreenPlay/wizards.h index 2150ef30..2c00ebfd 100644 --- a/ScreenPlay/inc/public/ScreenPlay/wizards.h +++ b/ScreenPlay/inc/public/ScreenPlay/wizards.h @@ -113,6 +113,7 @@ 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; diff --git a/ScreenPlay/src/wizards.cpp b/ScreenPlay/src/wizards.cpp index 952cd541..3094ceb6 100644 --- a/ScreenPlay/src/wizards.cpp +++ b/ScreenPlay/src/wizards.cpp @@ -1,6 +1,10 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "ScreenPlay/wizards.h" #include "ScreenPlayUtil/util.h" +#include +#include +#include +#include namespace ScreenPlay { /*! @@ -67,15 +71,13 @@ void Wizards::createQMLWidget(const QString& title, } 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 (!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")) { @@ -136,13 +138,13 @@ 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 (!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")) { @@ -201,15 +203,13 @@ void Wizards::createHTMLWallpaper( } 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 (!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")) { @@ -260,6 +260,9 @@ void Wizards::createQMLWallpaper( emit widgetCreationFinished(WizardResult::CopyPreviewThumbnailError); return; } + } else { + obj.insert("preview", "preview.png"); + createPreviewImage(title, workingPath); } if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/assets/wizards/" + licenseFile, workingPath + "/" + licenseFile)) { @@ -328,6 +331,9 @@ void Wizards::createGodotWallpaper( emit widgetCreationFinished(WizardResult::CopyPreviewThumbnailError); return; } + } else { + obj.insert("preview", "preview.png"); + createPreviewImage(title, workingPath); } if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/assets/wizards/" + licenseFile, workingPath + "/" + licenseFile)) { @@ -452,6 +458,9 @@ void Wizards::createWebsiteWallpaper( emit widgetCreationFinished(WizardResult::CopyPreviewThumbnailError); return; } + } else { + obj.insert("preview", "preview.png"); + createPreviewImage(title, workingPath); } if (!Util::writeSettings(obj, workingPath + "/project.json")) { @@ -482,6 +491,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 + QColor colors[] = { QColor("#B71C1C"), QColor("#1B5E20"), QColor("#0D47A1"), QColor("#FFD600"), QColor("#4A148C") }; + 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, colors[randomIndex1].darker()); // Dark color + gradient.setColorAt(1, colors[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.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" From 0185d6d95249e3cc5d7ff180aff4c0a84ce20567 Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Thu, 23 Nov 2023 11:37:50 +0100 Subject: [PATCH 16/32] Add proper Godot package export caching We now have 3 versions saved in the godot project.json. version: Project version. Every version bump will trigger a reexport. We just save the major and minor version for now. Godot does have pretty good version compability. We will need this information later when we upgrade to newer Godot versions godotVersionMajor godotVersionMinor Update to latest Godot RC1 --- CMake/CMakeVariables.h.in | 2 + CMake/GenerateCMakeVariableHeader.cmake | 8 ++- CMakeLists.txt | 19 +++++-- .../public/ScreenPlay/screenplaywallpaper.h | 8 ++- ScreenPlay/src/screenplaywallpaper.cpp | 51 +++++++++++++++---- ScreenPlay/src/wizards.cpp | 8 +++ .../src/ScreenPlayGodotWallpaper.cpp | 13 +++++ .../src/ScreenPlayGodotWallpaper.h | 4 ++ .../Godot/ScreenPlayGodot/main.gd | 5 +- .../Godot/ScreenPlayGodot/project.godot | 8 +-- Tools/defines.py | 2 +- 11 files changed, 104 insertions(+), 24 deletions(-) diff --git a/CMake/CMakeVariables.h.in b/CMake/CMakeVariables.h.in index 85654134..930271db 100644 --- a/CMake/CMakeVariables.h.in +++ b/CMake/CMakeVariables.h.in @@ -3,6 +3,8 @@ #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@" diff --git a/CMake/GenerateCMakeVariableHeader.cmake b/CMake/GenerateCMakeVariableHeader.cmake index 33401597..1329b2c2 100644 --- a/CMake/GenerateCMakeVariableHeader.cmake +++ b/CMake/GenerateCMakeVariableHeader.cmake @@ -6,9 +6,15 @@ # Example generate_cmake_variable_header(${PROJECT_NAME}) # function(generate_cmake_variable_header TARGET) - # NOTE: Also add to CMakeVariables.h.in ! + # ⚠️ 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}") diff --git a/CMakeLists.txt b/CMakeLists.txt index 0e86ec5c..1a47c10e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,15 +57,26 @@ set(VCPKG_INSTALLED_PATH "${VCPKG_PATH}/installed/${VCPKG_ARCH}") set(VCPKG_BIN_PATH "${VCPKG_INSTALLED_PATH}/bin") # Godot Editor -set(GODOT_VERSION "v4.2") -set(GODOT_RELEASE_TYPE "beta6") +set(GODOT_VERSION_MAJOR "4") +set(GODOT_VERSION_MINOR "2") +set(GODOT_VERSION_PATCH "") + +set(GODOT_RELEASE_TYPE "rc1") +# 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}-${GODOT_RELEASE_TYPE}_win64.exe") + 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}-${GODOT_RELEASE_TYPE}_linux.x86_64") + set(GODOT_EDITOR_NAME "Godot_${GODOT_VERSION}_linux.x86_64") else() message(FATAL_ERROR "Unsupported OS") endif() diff --git a/ScreenPlay/inc/public/ScreenPlay/screenplaywallpaper.h b/ScreenPlay/inc/public/ScreenPlay/screenplaywallpaper.h index 271b128b..33fd323e 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" @@ -210,7 +213,7 @@ public slots: } private: - bool exportGodotProject(const QString& absolutePath, int timeoutMilliseconds = 30000); + bool exportGodotProject(); private: const std::shared_ptr m_globalVariables; @@ -218,6 +221,7 @@ private: const std::shared_ptr m_settings; ProjectSettingsListModel m_projectSettingsListModel; + QJsonObject m_projectJson; QVector m_screenNumber; QProcess m_process; QString m_previewImage; diff --git a/ScreenPlay/src/screenplaywallpaper.cpp b/ScreenPlay/src/screenplaywallpaper.cpp index f8c91aa1..2732c3a4 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, @@ -42,7 +43,10 @@ ScreenPlayWallpaper::ScreenPlayWallpaper(const QVector& screenNumber, , m_playbackRate { playbackRate } , m_settings { settings } { - + std::optional projectOpt = ScreenPlayUtil::openJsonFileToObject(absolutePath + "/project.json"); + if (projectOpt.has_value()) { + m_projectJson = projectOpt.value(); + } QJsonObject projectSettingsListModelProperties; if (type == InstalledType::InstalledType::VideoWallpaper) { projectSettingsListModelProperties.insert("volume", m_volume); @@ -66,7 +70,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); @@ -92,13 +96,22 @@ ScreenPlayWallpaper::ScreenPlayWallpaper(const QVector& screenNumber, if (m_type != InstalledType::InstalledType::GodotWallpaper) { m_appArgumentsList.append(" --disable-features=HardwareMediaKeyHandling"); } + if (m_type == InstalledType::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 == InstalledType::InstalledType::GodotWallpaper) { - exportGodotProject(m_absolutePath); + if (!exportGodotProject()) + return false; } + m_process.setArguments(m_appArgumentsList); if (m_type == InstalledType::InstalledType::GodotWallpaper) { m_process.setProgram(m_globalVariables->godotWallpaperExecutablePath().toString()); @@ -293,22 +306,40 @@ bool ScreenPlayWallpaper::replace( return success; } -bool ScreenPlayWallpaper::exportGodotProject(const QString& absolutePath, int timeoutMilliseconds) +/*! + \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", "project.zip" }; + 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(absolutePath); + 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; @@ -331,9 +362,9 @@ bool ScreenPlayWallpaper::exportGodotProject(const QString& absolutePath, int ti } // Check if the project.zip file was created - QString zipPath = QDir(absolutePath).filePath("project.zip"); + QString zipPath = QDir(m_absolutePath).filePath(packageFileName); if (!QFile::exists(zipPath)) { - qCritical() << "Expected export file (project.zip) was not created."; + qCritical() << "Expected export file (" << packageFileName << ") was not created."; return false; } @@ -342,7 +373,7 @@ bool ScreenPlayWallpaper::exportGodotProject(const QString& absolutePath, int ti // but for simplicity, we're just checking its size here) QFileInfo zipInfo(zipPath); if (zipInfo.size() <= 0) { - qCritical() << "The exported project.zip file seems to be invalid."; + qCritical() << "The exported " << packageFileName << " file seems to be invalid."; return false; } diff --git a/ScreenPlay/src/wizards.cpp b/ScreenPlay/src/wizards.cpp index 3094ceb6..78d4f709 100644 --- a/ScreenPlay/src/wizards.cpp +++ b/ScreenPlay/src/wizards.cpp @@ -1,5 +1,6 @@ // SPDX-License-Identifier: LicenseRef-EliasSteurerTachiom OR AGPL-3.0-only #include "ScreenPlay/wizards.h" +#include "ScreenPlay/CMakeVariables.h" #include "ScreenPlayUtil/util.h" #include #include @@ -322,6 +323,13 @@ void Wizards::createGodotWallpaper( 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", ScreenPlayUtil::fillArray(tags)); obj.insert("type", QVariant::fromValue(InstalledType::InstalledType::GodotWallpaper).toString()); obj.insert("file", "wallpaper.tscn"); diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp index b219fb0f..7476a1d6 100644 --- a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.cpp @@ -33,6 +33,9 @@ void ScreenPlayGodotWallpaper::_bind_methods() 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); @@ -54,6 +57,16 @@ void ScreenPlayGodotWallpaper::hideFromTaskbar(HWND hwnd) 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()) { diff --git a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.h b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.h index ea1d12ff..b8fcb18b 100644 --- a/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.h +++ b/ScreenPlayWallpaper/Godot/GDExtention/src/ScreenPlayGodotWallpaper.h @@ -57,6 +57,9 @@ public: bool send_ping(); bool exit(); + godot::String get_projectPackageFile() const; + void set_projectPackageFile(const godot::String& projectPackageFile); + protected: static void _bind_methods(); @@ -70,6 +73,7 @@ private: godot::String m_appID = ""; godot::String m_projectPath = ""; + godot::String m_projectPackageFile = ""; WindowsIntegration m_windowsIntegration; double m_timesinceLastRead = 0.0; bool m_pipeConnected = false; diff --git a/ScreenPlayWallpaper/Godot/ScreenPlayGodot/main.gd b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/main.gd index dbf71198..71d21a4c 100644 --- a/ScreenPlayWallpaper/Godot/ScreenPlayGodot/main.gd +++ b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/main.gd @@ -44,7 +44,7 @@ func _ready(): get_tree().quit() return #screen_play_wallpaper.set_projectPath("C:\\Code\\cpp\\ScreenPlay\\ScreenPlay\\Content\\wallpaper_godot_fjord") - path = screen_play_wallpaper.get_projectPath() + "/project.zip" + path = screen_play_wallpaper.get_projectPath() + "/" + screen_play_wallpaper.get_projectPackageFile() else: get_tree().quit() return @@ -99,7 +99,7 @@ func parse_args(): if args[0] == "res://main.tscn": offset = 1 - if args.size() < 7: # Adjust this number based on the expected number of arguments + if args.size() < 8: # Adjust this number based on the expected number of arguments print("Not enough arguments provided!") return false @@ -122,6 +122,7 @@ func parse_args(): 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()) diff --git a/ScreenPlayWallpaper/Godot/ScreenPlayGodot/project.godot b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/project.godot index cb14a4c2..d48bcd61 100644 --- a/ScreenPlayWallpaper/Godot/ScreenPlayGodot/project.godot +++ b/ScreenPlayWallpaper/Godot/ScreenPlayGodot/project.godot @@ -23,14 +23,14 @@ config/icon="res://icon.svg" window/size/viewport_width=1 window/size/viewport_height=1 -window/size/mode=1 -window/size/initial_position_type=0 -window/size/initial_position=Vector2i(9999999, 9999999) +window/size/resizable=false window/size/borderless=true +window/size/transparent=true +window/energy_saving/keep_screen_on=false [editor] -run/main_run_args="\"0\" \"C:/Code/Cpp/ScreenPlay/ScreenPlay/Content/wallpaper_godot_fjord\" \"appID=test\" \"1\" \"Cover\" \"GodotWallpaper\" \"1\"" +run/main_run_args="\"1\" \"C:/Code/Cpp/ScreenPlay/ScreenPlay/Content/wallpaper_godot_fjord\" \"appID=test\" \"1\" \"Cover\" \"GodotWallpaper\" \"1\" \"project-v1.zip\"" [filesystem] diff --git a/Tools/defines.py b/Tools/defines.py index 7e577b74..39466cc2 100644 --- a/Tools/defines.py +++ b/Tools/defines.py @@ -37,7 +37,7 @@ VCPKG_BASE_PACKAGES = [ PYTHON_EXECUTABLE = "python" if sys.platform == "win32" else "python3" FFMPEG_VERSION = "6.0" GODOT_VERSION = "4.2" -GODOT_RELEASE_TYPE = "beta6" +GODOT_RELEASE_TYPE = "rc1" GODOT_DOWNLOAD_SERVER = "https://github.com/godotengine/godot-builds/releases/download" if sys.platform == "win32": SCREENPLAYWALLPAPER_GODOT_EXECUTABLE = "ScreenPlayWallpaperGodot.exe" From 972bdc6db335d15e8741d6d9c66d15a1cd0746b7 Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Thu, 23 Nov 2023 11:38:36 +0100 Subject: [PATCH 17/32] Change preview font to Noto Sans Light Move colors to member --- ScreenPlay/inc/public/ScreenPlay/wizards.h | 8 ++++++++ ScreenPlay/src/wizards.cpp | 6 +++--- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/ScreenPlay/inc/public/ScreenPlay/wizards.h b/ScreenPlay/inc/public/ScreenPlay/wizards.h index 2c00ebfd..6a342689 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 @@ -117,5 +118,12 @@ private: private: QFuture m_wizardFuture; + QVector m_gradientColors = { + QColor("#B71C1C"), + QColor("#1B5E20"), + QColor("#0D47A1"), + QColor("#FFD600"), + QColor("#4A148C") + }; }; } diff --git a/ScreenPlay/src/wizards.cpp b/ScreenPlay/src/wizards.cpp index 78d4f709..4deb51b8 100644 --- a/ScreenPlay/src/wizards.cpp +++ b/ScreenPlay/src/wizards.cpp @@ -511,14 +511,13 @@ void Wizards::createPreviewImage(const QString& name, const QString& targetPath) // Step 2: Select Random Colors (example colors, replace with Material colors) // These are just placeholder colors, replace with actual Material colors - QColor colors[] = { QColor("#B71C1C"), QColor("#1B5E20"), QColor("#0D47A1"), QColor("#FFD600"), QColor("#4A148C") }; 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, colors[randomIndex1].darker()); // Dark color - gradient.setColorAt(1, colors[randomIndex2].lighter()); // Bright color + gradient.setColorAt(0, m_gradientColors[randomIndex1].darker()); // Dark color + gradient.setColorAt(1, m_gradientColors[randomIndex2].lighter()); // Bright color painter.fillRect(image.rect(), gradient); @@ -527,6 +526,7 @@ void Wizards::createPreviewImage(const QString& name, const QString& targetPath) 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); From 226fddd72210312e0018be5fed818b8bb25dda20 Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Thu, 23 Nov 2023 11:39:45 +0100 Subject: [PATCH 18/32] Refactor code for const and explicitly disable qml creation --- ScreenPlay/inc/public/ScreenPlay/create.h | 1 + ScreenPlay/inc/public/ScreenPlay/globalvariables.h | 1 + ScreenPlay/inc/public/ScreenPlay/monitorlistmodel.h | 1 + ScreenPlay/inc/public/ScreenPlay/screenplaymanager.h | 1 + ScreenPlay/inc/public/ScreenPlay/screenplaywallpaper.h | 8 +------- ScreenPlay/inc/public/ScreenPlay/screenplaywidget.h | 1 + ScreenPlay/src/screenplaymanager.cpp | 6 +++--- ScreenPlay/src/screenplaywallpaper.cpp | 2 +- 8 files changed, 10 insertions(+), 11 deletions(-) diff --git a/ScreenPlay/inc/public/ScreenPlay/create.h b/ScreenPlay/inc/public/ScreenPlay/create.h index ebadca23..511540be 100644 --- a/ScreenPlay/inc/public/ScreenPlay/create.h +++ b/ScreenPlay/inc/public/ScreenPlay/create.h @@ -32,6 +32,7 @@ namespace ScreenPlay { class Create : public QObject { Q_OBJECT QML_ELEMENT + QML_UNCREATABLE("") Q_PROPERTY(QString workingDir READ workingDir WRITE setWorkingDir NOTIFY workingDirChanged) Q_PROPERTY(float progress READ progress WRITE setProgress NOTIFY progressChanged) diff --git a/ScreenPlay/inc/public/ScreenPlay/globalvariables.h b/ScreenPlay/inc/public/ScreenPlay/globalvariables.h index 7b7a6a15..9d317aa2 100644 --- a/ScreenPlay/inc/public/ScreenPlay/globalvariables.h +++ b/ScreenPlay/inc/public/ScreenPlay/globalvariables.h @@ -16,6 +16,7 @@ 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 FINAL) diff --git a/ScreenPlay/inc/public/ScreenPlay/monitorlistmodel.h b/ScreenPlay/inc/public/ScreenPlay/monitorlistmodel.h index ed80ce6e..068c8d28 100644 --- a/ScreenPlay/inc/public/ScreenPlay/monitorlistmodel.h +++ b/ScreenPlay/inc/public/ScreenPlay/monitorlistmodel.h @@ -41,6 +41,7 @@ struct Monitor { class MonitorListModel : public QAbstractListModel { Q_OBJECT QML_ELEMENT + QML_UNCREATABLE("") public: explicit MonitorListModel(QObject* parent = nullptr); diff --git a/ScreenPlay/inc/public/ScreenPlay/screenplaymanager.h b/ScreenPlay/inc/public/ScreenPlay/screenplaymanager.h index 7c15c7de..8de67422 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) diff --git a/ScreenPlay/inc/public/ScreenPlay/screenplaywallpaper.h b/ScreenPlay/inc/public/ScreenPlay/screenplaywallpaper.h index 33fd323e..81c7f38b 100644 --- a/ScreenPlay/inc/public/ScreenPlay/screenplaywallpaper.h +++ b/ScreenPlay/inc/public/ScreenPlay/screenplaywallpaper.h @@ -22,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) public: - // Default constructor needed for qml engine - ScreenPlayWallpaper() { } - explicit ScreenPlayWallpaper( const QVector& screenNumber, const std::shared_ptr& globalVariables, diff --git a/ScreenPlay/inc/public/ScreenPlay/screenplaywidget.h b/ScreenPlay/inc/public/ScreenPlay/screenplaywidget.h index fa6e587f..9090902f 100644 --- a/ScreenPlay/inc/public/ScreenPlay/screenplaywidget.h +++ b/ScreenPlay/inc/public/ScreenPlay/screenplaywidget.h @@ -23,6 +23,7 @@ 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) diff --git a/ScreenPlay/src/screenplaymanager.cpp b/ScreenPlay/src/screenplaymanager.cpp index ebc8dec2..7357bcb6 100644 --- a/ScreenPlay/src/screenplaymanager.cpp +++ b/ScreenPlay/src/screenplaymanager.cpp @@ -303,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( @@ -514,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()); } diff --git a/ScreenPlay/src/screenplaywallpaper.cpp b/ScreenPlay/src/screenplaywallpaper.cpp index 2732c3a4..6b90cad0 100644 --- a/ScreenPlay/src/screenplaywallpaper.cpp +++ b/ScreenPlay/src/screenplaywallpaper.cpp @@ -139,7 +139,7 @@ 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); } From ce397137c929e2d8c230ede6f2dcc18b2adfc73e Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Thu, 23 Nov 2023 12:22:04 +0100 Subject: [PATCH 19/32] Add spinner script to default wallpaper --- ScreenPlay/CMakeLists.txt | 1 + ScreenPlay/qml/Create/WizardsFiles/Godot_v5/spinner.gd | 6 ++++++ ScreenPlay/qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn | 5 ++++- ScreenPlay/src/wizards.cpp | 5 +++++ 4 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 ScreenPlay/qml/Create/WizardsFiles/Godot_v5/spinner.gd diff --git a/ScreenPlay/CMakeLists.txt b/ScreenPlay/CMakeLists.txt index 7736f125..db71df4f 100644 --- a/ScreenPlay/CMakeLists.txt +++ b/ScreenPlay/CMakeLists.txt @@ -79,6 +79,7 @@ set(QML qml/Create/Wizards/WizardPage.qml 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/QMLWallpaperMain.qml qml/Create/WizardsFiles/QMLWidgetMain.qml 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 index d488b39d..714824ae 100644 --- a/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn +++ b/ScreenPlay/qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn @@ -1,4 +1,6 @@ -[gd_scene format=3 uid="uid://d105uliklnkd5"] +[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"] @@ -7,6 +9,7 @@ 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) diff --git a/ScreenPlay/src/wizards.cpp b/ScreenPlay/src/wizards.cpp index 4deb51b8..ad1aadbf 100644 --- a/ScreenPlay/src/wizards.cpp +++ b/ScreenPlay/src/wizards.cpp @@ -360,6 +360,11 @@ void Wizards::createGodotWallpaper( return; } + if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/Godot_v5/spinner.gd", workingPath + "/spinner.gd")) { + qWarning() << "Could not write spinner.gd"; + return; + } + if (!Util::writeFileFromQrc(":/qml/ScreenPlayApp/qml/Create/WizardsFiles/Godot_v5/wallpaper.tscn", workingPath + "/wallpaper.tscn")) { qWarning() << "Could not write wallpaper.tscn"; return; From 2f7719d05662707b2ee93397c53b1e04e79f521a Mon Sep 17 00:00:00 2001 From: Elias Steurer Date: Thu, 23 Nov 2023 12:22:58 +0100 Subject: [PATCH 20/32] Cleanup unused files --- ScreenPlay/CMakeLists.txt | 5 +---- ScreenPlay/assets/particle/backgroundGlow.png | Bin 117301 -> 0 bytes ScreenPlay/assets/particle/dot.png | Bin 3306 -> 0 bytes ScreenPlay/assets/shader/movingcolorramp.fsh | 18 ------------------ ScreenPlay/assets/tests/video_import.mp4 | Bin 18418424 -> 0 bytes .../WizardsFiles}/QmlProject.qmlproject | 0 ScreenPlay/src/wizards.cpp | 2 +- ScreenPlay/tests/tst_main.cpp | 2 +- ScreenPlayWallpaper/CMakeLists.txt | 2 +- ScreenPlayWallpaper/qml/Test.qml | 8 -------- 10 files changed, 4 insertions(+), 33 deletions(-) delete mode 100644 ScreenPlay/assets/particle/backgroundGlow.png delete mode 100644 ScreenPlay/assets/particle/dot.png delete mode 100644 ScreenPlay/assets/shader/movingcolorramp.fsh delete mode 100644 ScreenPlay/assets/tests/video_import.mp4 rename ScreenPlay/{assets/wizards => qml/Create/WizardsFiles}/QmlProject.qmlproject (100%) diff --git a/ScreenPlay/CMakeLists.txt b/ScreenPlay/CMakeLists.txt index db71df4f..f3fe18fb 100644 --- a/ScreenPlay/CMakeLists.txt +++ b/ScreenPlay/CMakeLists.txt @@ -207,9 +207,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 @@ -238,7 +235,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 @@ -247,6 +243,7 @@ set(RESOURCES legal/OpenSSL.txt profiles.json qml/Create/WizardsFiles/HTMLWallpaperMain.html + qml/Create/WizardsFiles/QmlProject.qmlproject qml/Create/WizardsFiles/HTMLWidgetMain.html qml/Create/WizardsFiles/QMLWallpaperMain.qml qml/Create/WizardsFiles/QMLWidgetMain.qml diff --git a/ScreenPlay/assets/particle/backgroundGlow.png b/ScreenPlay/assets/particle/backgroundGlow.png deleted file mode 100644 index ba18cc8dd73d2d28e18b52815f74999d3ddf7cbe..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 117301 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ưC}ZQ$KUgC+9M_1I{+4T6C3zH9JD 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

Xzh<4)4{gf|LA_&47Ol0B8w-2mjbpqL7=> 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 diff --git a/ScreenPlay/assets/particle/dot.png b/ScreenPlay/assets/particle/dot.png deleted file mode 100644 index 082a04d18253f8d348320c2068cb02d3635f1b0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3306 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­emHwJd5aHyGU@x(* zhinH*Ynz|)X6_HYBgI~u(*ty>`6*G;*HvN(r80(rFnRvU+T?(0K}L;j{^wm@J-%D~ za7#2!uI57k`WV~lyoKOa33%Ll+d6nVRsw>uZMImxCG?m#&zC8{`2Fg$fPQ~#MUg|+ zL%i{K^ADB&D^o8#@xThI8a!t=i3|{k!yf|biGqzmI?MR5nwt)7kQj!Qs)95+bD`)PyaVjcN4i=Q@OtIX!}*LHOI z5hF(4&nqxi2yh-z{xc07sYs;LASl>buyK0~n1n6W>~>jX8rrw*5)COH?BcTuj=9

rV7fn0cV9r*%w>zJd$`rbzq@KIZg5~C8 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%0AQ<4o2I&4 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