Rename to TNCat, add chip chase, G-codes and a Wayland layout
The project is now TNCat, after HEIDENHAIN's TNC controls. Binary, QML module URI, settings path, bundle id and .desktop entry follow; the environment switches are TNCAT_*. Entertainment: a curled steel chip skitters in every minute or two, the cat runs it down and bats it away a few times before sitting back looking pleased. Mood changes flash the matching machine code above its head, G00 for a sprint, G01 for a stroll, M08 while it washes, G28 for a stretch, M30 for a nap. Window handling was split into two layouts. X11 and macOS keep one small window per object, positioned by the app. Wayland gets a screen-filling overlay whose input region is masked down to the cat, since a Wayland client cannot place its own window. Overlay mode is automatic there and available elsewhere via TNCAT_OVERLAY=1. Also adds a ground-line setting so the cat can walk above a softkey row. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
acef398f49
commit
0f1df75a1d
19 files changed
+817
-185
No files matched your search
+69
-6
@@ -13,6 +13,16 @@ Item {
|
||||
property bool lifted: false
|
||||
property bool petted: false
|
||||
property point look: Qt.point(0, 0)
|
||||
property bool showCodes: true
|
||||
|
||||
// The cat announces what it is doing in the machine's own language.
|
||||
readonly property string moodCode: mood === "running" || mood === "chasing" ? "G00"
|
||||
: mood === "walking" ? "G01"
|
||||
: mood === "sitting" ? "M00"
|
||||
: mood === "grooming" ? "M08"
|
||||
: mood === "stretching" ? "G28"
|
||||
: mood === "sleeping" ? "M30"
|
||||
: ""
|
||||
|
||||
readonly property bool dark: coat.hslLightness < 0.45
|
||||
readonly property color coatShade: Qt.darker(coat, 1.12)
|
||||
@@ -23,7 +33,7 @@ Item {
|
||||
readonly property color blush: "#f77d95"
|
||||
|
||||
readonly property bool walking: mood === "walking"
|
||||
readonly property bool running: mood === "running"
|
||||
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
|
||||
@@ -299,8 +309,8 @@ Item {
|
||||
id: eyeBall
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: eye.width * (cat.mood === "alert" ? 1.15 : 1)
|
||||
height: eye.height * eye.open * (cat.mood === "alert" ? 1.15 : 1)
|
||||
width: eye.width * (cat.mood === "alert" || cat.mood === "batting" ? 1.15 : 1)
|
||||
height: eye.height * eye.open * (cat.mood === "alert" || cat.mood === "batting" ? 1.15 : 1)
|
||||
radius: width / 2
|
||||
color: cat.eyeColor
|
||||
visible: eye.open > 0.08
|
||||
@@ -449,14 +459,17 @@ Item {
|
||||
// speech bubble: "!" / "z" / "♥"
|
||||
Text {
|
||||
id: bubble
|
||||
readonly property string glyph: cat.mood === "alert" ? "!" : cat.sleeping ? "z" : (cat.mood === "loving" || cat.petted) ? "♥" : ""
|
||||
readonly property string glyph: cat.mood === "alert" || cat.mood === "batting" ? "!"
|
||||
: cat.sleeping ? "z"
|
||||
: (cat.mood === "loving" || cat.petted) ? "♥" : ""
|
||||
x: 82; y: 4
|
||||
text: glyph
|
||||
visible: glyph.length > 0
|
||||
font.pixelSize: cat.mood === "alert" ? 22 : 16
|
||||
font.pixelSize: cat.mood === "alert" || cat.mood === "batting" ? 22 : 16
|
||||
font.bold: true
|
||||
font.family: "Helvetica Neue"
|
||||
color: cat.mood === "alert" ? "#f2a33c" : (glyph === "♥" ? "#f25f7a" : cat.ink)
|
||||
color: cat.mood === "alert" || cat.mood === "batting" ? "#f2a33c"
|
||||
: (glyph === "♥" ? "#ff5b7f" : cat.ink)
|
||||
transform: Scale { xScale: cat.facingRight ? 1 : -1; origin.x: bubble.width / 2 }
|
||||
Accessible.ignored: true
|
||||
|
||||
@@ -474,6 +487,50 @@ Item {
|
||||
}
|
||||
}
|
||||
|
||||
// Machine code tag above the head, flashed whenever the mood changes
|
||||
Item {
|
||||
id: codeTag
|
||||
x: 30; y: 2
|
||||
width: codeBg.width
|
||||
height: codeBg.height
|
||||
opacity: 0
|
||||
visible: cat.showCodes && opacity > 0.01
|
||||
transformOrigin: Item.Center
|
||||
transform: Scale { xScale: cat.facingRight ? 1 : -1; origin.x: codeTag.width / 2 }
|
||||
z: 10
|
||||
scale: cat.unit
|
||||
Accessible.ignored: true
|
||||
|
||||
Rectangle {
|
||||
id: codeBg
|
||||
width: codeText.implicitWidth + 10
|
||||
height: codeText.implicitHeight + 6
|
||||
radius: 4
|
||||
color: "#242833"
|
||||
opacity: 0.92
|
||||
antialiasing: true
|
||||
|
||||
Text {
|
||||
id: codeText
|
||||
anchors.centerIn: parent
|
||||
text: cat.moodCode
|
||||
color: "#8fd6ff"
|
||||
font.pixelSize: 11
|
||||
font.bold: true
|
||||
font.family: "Menlo"
|
||||
}
|
||||
}
|
||||
|
||||
SequentialAnimation {
|
||||
id: codeFlash
|
||||
NumberAnimation { target: codeTag; property: "opacity"; to: 1; duration: 160 }
|
||||
PauseAnimation { duration: 1500 }
|
||||
NumberAnimation { target: codeTag; property: "opacity"; to: 0; duration: 500 }
|
||||
}
|
||||
}
|
||||
|
||||
onMoodCodeChanged: if (showCodes && moodCode.length > 0) codeFlash.restart()
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "running"
|
||||
@@ -509,6 +566,12 @@ 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: "batting"
|
||||
when: cat.mood === "batting" && !cat.lifted
|
||||
PropertyChanges { body.rotation: -10; body.x: 26 }
|
||||
PropertyChanges { head.y: 10; head.x: 50 }
|
||||
},
|
||||
State {
|
||||
name: "lifted"
|
||||
when: cat.lifted
|
||||
|
||||
Reference in new issue
Block a user