moire: wordmark opacity and glow sliders

cd4c494 · Gabriel Morell · 2026-09-29 23:00

10 files +67 -3

Files changed

modified README.md
+2 −1
@@ -79,7 +79,8 @@ transitions pass through the purples of a real twilight rather than
79 79 grey.
80 80
81 81 A checkbox writes "NEIAM" in the bottom right corner, in the theme's
82 −accent colour, in B612 Mono Bold at 12% of the screen height; the package pulls
82 +accent colour, in B612 Mono Bold at 12% of the screen height, with
83 +sliders for its opacity and for a soft glow around it; the package pulls
83 84 in the font (`fonts-b612` / `firstyear-b612-fonts`).
84 85
85 86 Settings trade smoothness for power: frame rate (30 by default) and
modified moire/theme/contents/config/main.xml
+11 −0
@@ -55,6 +55,17 @@
55 55 <label>Write NEIAM in the bottom right corner</label>
56 56 <default>false</default>
57 57 </entry>
58 + <entry name="WordmarkOpacity" type="Double">
59 + <default>1</default>
60 + <min>0</min>
61 + <max>1</max>
62 + </entry>
63 + <entry name="WordmarkGlow" type="Double">
64 + <label>A soft halo around the wordmark, in its colour</label>
65 + <default>0</default>
66 + <min>0</min>
67 + <max>1</max>
68 + </entry>
58 69
59 70 <entry name="ThemeMode" type="String">
60 71 <label>static, or sun to follow the time of day with each phase's theme and pattern</label>
modified moire/theme/contents/ui/Field.qml
+23 −2
@@ -6,6 +6,7 @@
6 6 // precision, and handed to the shader as positions and a wrapped
7 7 // phase: the shader holds no clock that could lose precision.
8 8 import QtQuick 2.15
9 +import QtQuick.Effects
9 10
10 11 Item {
11 12 id: field
@@ -33,6 +34,8 @@ Item {
33 34 property int frameRate: 30
34 35 // "NEIAM" in the bottom right, in the ink colour.
35 36 property bool wordmark: false
37 + property real wordmarkOpacity: 1 // 0-1
38 + property real wordmarkGlow: 0 // 0-1, a soft halo in the ink colour
36 39
37 40 property color base: "#661e1e"
38 41 property color deep: "#470005"
@@ -141,10 +144,12 @@ Item {
141 144 }
142 145
143 146 // B612 Mono comes from fonts-b612 / firstyear-b612-fonts, which the
144 − // package depends on.
147 + // package depends on. The text itself is hidden and drawn through
148 + // the effect below, which adds the glow and applies the opacity to
149 + // letters and glow together.
145 150 Text {
146 151 id: mark
147 − visible: field.wordmark
152 + visible: false
148 153 anchors { right: parent.right; bottom: parent.bottom; margins: field.height * 0.04 }
149 154 text: "NEIAM"
150 155 color: field.ink
@@ -154,6 +159,22 @@ Item {
154 159 FontMetrics { id: fontMetrics; font: mark.font }
155 160 }
156 161
162 + MultiEffect {
163 + source: mark
164 + anchors.fill: mark
165 + visible: field.wordmark
166 + opacity: field.wordmarkOpacity
167 + // An unoffset shadow in the ink colour is a glow.
168 + shadowEnabled: field.wordmarkGlow > 0
169 + shadowColor: field.ink
170 + shadowHorizontalOffset: 0
171 + shadowVerticalOffset: 0
172 + shadowBlur: 1
173 + blurMax: Math.round(field.height * 0.04)
174 + shadowScale: 1 + 0.04 * field.wordmarkGlow
175 + shadowOpacity: Math.min(1, field.wordmarkGlow * 1.2)
176 + }
177 +
157 178 Timer {
158 179 running: field.speed > 0 && field.visible
159 180 repeat: true
modified moire/theme/contents/ui/config.qml
+29 −0
@@ -18,6 +18,8 @@ Kirigami.FormLayout {
18 18 property double cfg_Speed
19 19 property int cfg_FrameRate
20 20 property bool cfg_Wordmark
21 + property double cfg_WordmarkOpacity
22 + property double cfg_WordmarkGlow
21 23 property bool cfg_ForegroundBokeh
22 24 property bool cfg_Glints
23 25 property bool cfg_Breathing
@@ -85,6 +87,19 @@ Kirigami.FormLayout {
85 87 PatternBox { choices: root.layers; value: parent.pattern; onPicked: v => parent.patternPicked(v) }
86 88 }
87 89
90 + // A 0-1 setting as a slider with its percentage beside it.
91 + component PercentSlider: RowLayout {
92 + property double value
93 + signal moved(double value)
94 + QQC2.Slider {
95 + id: slider
96 + from: 0; to: 1; stepSize: 0.05
97 + value: parent.value
98 + onMoved: parent.moved(value)
99 + }
100 + QQC2.Label { text: Math.round(slider.value * 100) + "%" }
101 + }
102 +
88 103 component TimeField: QQC2.TextField {
89 104 inputMask: "99:99"
90 105 validator: RegularExpressionValidator { regularExpression: /([01]\d|2[0-3]):[0-5]\d/ }
@@ -305,4 +320,18 @@ Kirigami.FormLayout {
305 320 checked: root.cfg_Wordmark
306 321 onToggled: root.cfg_Wordmark = checked
307 322 }
323 +
324 + PercentSlider {
325 + Kirigami.FormData.label: "Opacity:"
326 + enabled: root.cfg_Wordmark
327 + value: root.cfg_WordmarkOpacity
328 + onMoved: v => root.cfg_WordmarkOpacity = v
329 + }
330 +
331 + PercentSlider {
332 + Kirigami.FormData.label: "Glow:"
333 + enabled: root.cfg_Wordmark
334 + value: root.cfg_WordmarkGlow
335 + onMoved: v => root.cfg_WordmarkGlow = v
336 + }
308 337 }
modified moire/theme/contents/ui/main.qml
+2 −0
@@ -40,6 +40,8 @@ WallpaperItem {
40 40 breathing: root.cfg.Breathing
41 41 grain: root.cfg.Grain
42 42 dither: root.cfg.Dither
43 + wordmarkOpacity: root.cfg.WordmarkOpacity
44 + wordmarkGlow: root.cfg.WordmarkGlow
43 45 speed: root.cfg.Speed
44 46 frameRate: root.cfg.FrameRate
45 47 wordmark: root.cfg.Wordmark

Parents: be2c05b