Add a coffee break

Every so often a mug appears at the cat's nose, it sits down, dips its head in
and takes a few slow sips while steam rises. M01, optional stop.

The mug lives in its own click-through window like the chip, or inside the
overlay on Wayland. It goes away as soon as the cat is petted, dragged, sent to
sleep or moves on to something else, so no mug is ever left standing.

Also renames OverlayWindow's mode flag, which shadowed QWindow::active.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
JulianandClaude Opus 5 committed 2026-09-10 23:00:22 +02:00
1 parent 0f1df75a1d
commit 403ac30b3a
14 files changed
+283 -18

No files matched your search

+24 -2
View File
@@ -14,6 +14,7 @@ Item {
property bool petted: false
property point look: Qt.point(0, 0)
property bool showCodes: true
property real sipDip: 0
// The cat announces what it is doing in the machine's own language.
readonly property string moodCode: mood === "running" || mood === "chasing" ? "G00"
@@ -22,6 +23,7 @@ Item {
: mood === "grooming" ? "M08"
: mood === "stretching" ? "G28"
: mood === "sleeping" ? "M30"
: mood === "drinking" ? "M01"
: ""
readonly property bool dark: coat.hslLightness < 0.45
@@ -36,7 +38,8 @@ Item {
readonly property bool running: mood === "running" || mood === "chasing"
readonly property bool moving: (walking || running) && !lifted
readonly property bool sleeping: mood === "sleeping"
readonly property bool happy: mood === "loving" || mood === "grooming" || mood === "stretching" || petted
readonly property bool happy: mood === "loving" || mood === "grooming" || mood === "stretching"
|| mood === "drinking" || petted
readonly property real unit: width / 100
// tail pose (design units); swish is added on top by the idle animation
@@ -531,6 +534,17 @@ Item {
onMoodCodeChanged: if (showCodes && moodCode.length > 0) codeFlash.restart()
// Head dips into the mug, holds, comes back up.
SequentialAnimation {
running: cat.mood === "drinking" && !cat.lifted
loops: Animation.Infinite
alwaysRunToEnd: true
NumberAnimation { target: cat; property: "sipDip"; to: 13; duration: 700; easing.type: Easing.InOutQuad }
PauseAnimation { duration: 900 }
NumberAnimation { target: cat; property: "sipDip"; to: 0; duration: 600; easing.type: Easing.InOutQuad }
PauseAnimation { duration: 1400 }
}
states: [
State {
name: "running"
@@ -566,6 +580,13 @@ Item {
PropertyChanges { head.y: 24; head.x: 44; head.rotation: 4 }
PropertyChanges { cat.tailC1X: 24; cat.tailC1Y: 86; cat.tailC2X: 60; cat.tailC2Y: 90; cat.tailX: 76; cat.tailY: 78 }
},
State {
name: "drinking"
when: cat.mood === "drinking" && !cat.lifted
PropertyChanges { body.x: 32; body.y: 42; body.width: 42; body.height: 38 }
PropertyChanges { head.x: 50; head.y: 20 + cat.sipDip; head.rotation: 16 }
PropertyChanges { cat.tailC1X: 26; cat.tailC1Y: 84; cat.tailC2X: 40; cat.tailC2Y: 88; cat.tailX: 52; cat.tailY: 80 }
},
State {
name: "batting"
when: cat.mood === "batting" && !cat.lifted
@@ -588,5 +609,6 @@ Item {
NumberAnimation { target: shadow; properties: "opacity,scale"; duration: 260 }
}
readonly property bool seated: mood === "sitting" || mood === "loving" || mood === "alert" || mood === "grooming"
readonly property bool seated: mood === "sitting" || mood === "loving" || mood === "alert"
|| mood === "grooming" || mood === "drinking"
}