starplast.ambient
A drifting field of soft colour blobs, behind the panels.
Ported from spaCR's ambient background so the two programs look like one pair of tools, and kept to the one animation that was asked for -- the blobs -- with the same controls under the same names: speed, size, density, blur.
The design decision worth carrying across: position is a pure function of the clock, two
independent sines per blob rather than a random walk. A walk accumulates error, cannot be rewound,
and gives a different picture every time a frame is dropped; a function of time can be asked for any
instant, which is what makes the field paintable at whatever rate the window can manage and
identical at the same t on any machine.
Blobs are seeded on a jittered grid rather than uniformly at random. With a dozen of them, uniform sampling reliably leaves one corner empty and puts three in the middle -- which reads as a bug in the drawing rather than as a random arrangement.
One blob: where it sits, how far and how fast it wanders, how it breathes.
A reproducible set of blobs, seeded on a jittered grid.
The pool is always rolled at the top of the density range and a prefix of it painted, so raising the density adds blobs rather than redrawing the ones already there: the random numbers are consumed in the same order either way, and blob 3 keeps the numbers blob 3 always had.
(cx, cy, radius, colour index) per blob, in pixels, at time t.
The blob field, painted behind everything else.
Transparent to the mouse -- it is scenery, and a background that swallowed a click on the panel in front of it would be a bug nobody could describe. The timer runs only while the widget is visible, because sixty repaints a second of a picture nobody is looking at is sixty repaints a second of a picture nobody is looking at.
Put this widget back at the bottom of its parent's children. True if it had to move.
It is an ordinary child of the window, lowered when it is built -- but Qt lowers a dock when
its tab is switched away from (QMainWindowLayout::tabChanged), so after one switch that
dock sits BELOW the background and comes back painted over: laid out, the right size,
isVisible() true, its widget repainting, and invisible. That was the blank panel reported
twice against 0.48 and 0.49 (instruction 58). Whoever restacks the window calls this after.
Stop animating. The field keeps its time, so starting again continues rather than jumps.