From 9106ce47f44f15fa6dd12c000bcfbaea62009ac2 Mon Sep 17 00:00:00 2001 From: Julian Date: Fri, 11 Sep 2026 09:12:39 +0200 Subject: [PATCH] Build only one window layout, so the eyes stop jumping Main.qml declared both layouts at once: the small per-object windows and the full-screen overlay. Both of them write the controller's catCenter, which is where the eyes look for the cursor. Two bindings on one property overwrite each other, so catCenter alternated every frame between the cat window's real centre and the hidden overlay's, whose height is zero. look.y flipped between -0.495 and 1.0 sixty times a second and the pupils jumped with it. Each layout now sits behind its own Loader and only the one the platform needs is built. The small windows moved into Desktop.qml so a single component can hold all three of them. Measured in the running app while walking, the eye's vertical travel went from 2.6 px to 0.40 px, and look.y is now a single steady value. It also stops a second, invisible cat from animating in the background. Co-Authored-By: Claude Opus 5 --- CMakeLists.txt | 2 +- qml/Desktop.qml | 31 +++++++++++++++++++++++++++++++ qml/Main.qml | 41 ++++++++++++++++++----------------------- 3 files changed, 50 insertions(+), 24 deletions(-) create mode 100644 qml/Desktop.qml diff --git a/CMakeLists.txt b/CMakeLists.txt index bf636b5..9143fbc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ qt_add_executable(tncat target_include_directories(tncat PRIVATE src) # QML files live in qml/ but register at the module root (TNCat.Main etc.) -set(TNCAT_QML Main Cat Chip Cup CatWindow ChipWindow CupWindow OverlayWindow +set(TNCAT_QML Main Desktop Cat Chip Cup CatWindow ChipWindow CupWindow OverlayWindow SettingsWindow AppButton AppSlider AppToggle SettingsGroup CatDefs) foreach(qmlfile IN LISTS TNCAT_QML) set_source_files_properties(qml/${qmlfile}.qml PROPERTIES QT_RESOURCE_ALIAS ${qmlfile}.qml) diff --git a/qml/Desktop.qml b/qml/Desktop.qml new file mode 100644 index 0000000..fa4d168 --- /dev/null +++ b/qml/Desktop.qml @@ -0,0 +1,31 @@ +pragma ComponentBehavior: Bound +import QtQuick +import TNCat + +// The layout for platforms that let a client place its own window: one small +// window per object, moved around the screen by the app. +QtObject { + id: desktop + + required property CatController cat + required property AppSettings settings + + signal settingsRequested() + + readonly property CatWindow catWindow: CatWindow { + cat: desktop.cat + settings: desktop.settings + visible: true + onSettingsRequested: desktop.settingsRequested() + } + + readonly property ChipWindow chipWindow: ChipWindow { + cat: desktop.cat + settings: desktop.settings + } + + readonly property CupWindow cupWindow: CupWindow { + cat: desktop.cat + settings: desktop.settings + } +} diff --git a/qml/Main.qml b/qml/Main.qml index b590384..70820b3 100644 --- a/qml/Main.qml +++ b/qml/Main.qml @@ -2,7 +2,9 @@ pragma ComponentBehavior: Bound import QtQuick import TNCat -// Root is not a window: which windows exist depends on the platform. +// Root is not a window. Exactly one of the two layouts is built, because both +// of them drive the controller's catCenter; having both alive made the two +// bindings overwrite each other every frame and the eyes jumped with them. QtObject { id: app @@ -15,30 +17,23 @@ QtObject { settingsWindow.requestActivate() } - readonly property CatWindow catWindow: CatWindow { - cat: app.cat - settings: app.settings - visible: !Platform.overlayMode - onSettingsRequested: app.openSettings() + readonly property Loader desktopLoader: Loader { + active: !Platform.overlayMode + sourceComponent: Desktop { + cat: app.cat + settings: app.settings + onSettingsRequested: app.openSettings() + } } - readonly property ChipWindow chipWindow: ChipWindow { - cat: app.cat - settings: app.settings - visible: !Platform.overlayMode && app.cat.chipVisible - } - - readonly property CupWindow cupWindow: CupWindow { - cat: app.cat - settings: app.settings - visible: !Platform.overlayMode && app.cat.cupVisible - } - - readonly property OverlayWindow overlayWindow: OverlayWindow { - cat: app.cat - settings: app.settings - overlayActive: Platform.overlayMode - onSettingsRequested: app.openSettings() + readonly property Loader overlayLoader: Loader { + active: Platform.overlayMode + sourceComponent: OverlayWindow { + cat: app.cat + settings: app.settings + overlayActive: true + onSettingsRequested: app.openSettings() + } } readonly property SettingsWindow settingsWindow: SettingsWindow {