You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A Rotate slider for the Pool: a constant, slow carousel of the whole field about the layout centre, layered under Flow / Spiral / Droplets and under the stirred current. It's a parameter rather than a mode so it composes: Hold + Rotate is a painted picture that orbits; Droplets + Rotate is ripples on a turning pond. Spiral (gesture-shaped, settles) and the current (stirred, decays) are unchanged — Rotate is the one thing that keeps turning on its own.
@wavegrid/pool
PoolSettings.rotate?: number// -1..1, default 0; sign = direction (positive = clockwise on screen)ROTATE_LAP_SECONDS=20// full deflection = one lap in 20 srotateOmega(r)=clamp(r,-1,1)*2π/ROTATE_LAP_SECONDS
In PoolField.step, rotOmega eases toward rotateOmega(settings.rotate) on a 3 s clock (so moving the slider never jerks the lights), and every source — blobs and droplet rings — is rotated about (0.5, 0.5) by rotOmega·dt after its own motion. Uses the layout square's centre, not the fixtures, so it works for any configured layout.
Server
pool_settings accepts rotate, clamped to −1..1, non-numbers ignored; persisted with the other Pool settings, echoed to all UIs.
UI
Bipolar slider in the Pool group (centre = off, double-click resets), readout shows ↻/↺ and magnitude. app.tsx includes rotate in the server-echo comparison so other iPads' changes propagate.
Tests
pool: rotate: 1 carries a held spot ~a quarter lap in 5 s (minus the ease-in), radius preserved; -0.5 goes the other way; 0 stays put.
server: clamp (-3 → -1) and type validation ('fast' ignored).
🟢 Orphaned spiral comment above rotateOmega (pool-field.ts:164) — Inserting rotateOmega (pool-field.ts:166) and its doc comment between the pre-existing spiral-spin comment and spiralOmega orphaned that comment, so it now sits above rotateOmega (where its 'a lap takes 20s to 2min' text is wrong — rotateOmega always laps in ROTATE_LAP_SECONDS) while spiralOmega at line 170 is left without its description.
This PR introduces per-source rotation (rotateOmega), spiral-drift motion, and expanded pool settings on both sides of the wire, plus UI controls on the pool tab. The server validates and clamps the new numeric rotate setting (falling back to the previous value), broadcasts the extended pool_settings DTO, and tests cover the new field.
Files
Change
packages/pool/src/pool-field.ts + test
Adds rotateOmega/spiral-drift motion math and its unit tests.
packages/server/src/server.ts + test
Broadens pool_settings DTO with rotate validation/clamping and broadcast.
packages/ui/src/app.tsx, pool-tab.tsx
Adds rotate/spread/turn UI controls wired to the new settings.
Reviewers focused on correctness, the realtime messaging schema, and the animation math. The one low-severity issue is a displaced JSDoc comment that now misdescribes rotateOmega and leaves spiralOmega undocumented; no functional defects were confirmed, so this is a merge-with-comment rather than a request for changes.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
A Rotate slider for the Pool: a constant, slow carousel of the whole field about the layout centre, layered under Flow / Spiral / Droplets and under the stirred current. It's a parameter rather than a mode so it composes: Hold + Rotate is a painted picture that orbits; Droplets + Rotate is ripples on a turning pond. Spiral (gesture-shaped, settles) and the current (stirred, decays) are unchanged — Rotate is the one thing that keeps turning on its own.
@wavegrid/poolIn
PoolField.step,rotOmegaeases towardrotateOmega(settings.rotate)on a 3 s clock (so moving the slider never jerks the lights), and every source — blobs and droplet rings — is rotated about(0.5, 0.5)byrotOmega·dtafter its own motion. Uses the layout square's centre, not the fixtures, so it works for any configured layout.Server
pool_settingsacceptsrotate, clamped to −1..1, non-numbers ignored; persisted with the other Pool settings, echoed to all UIs.UI
Bipolar slider in the Pool group (centre = off, double-click resets), readout shows ↻/↺ and magnitude.
app.tsxincludesrotatein the server-echo comparison so other iPads' changes propagate.Tests
rotate: 1carries a held spot ~a quarter lap in 5 s (minus the ease-in), radius preserved;-0.5goes the other way;0stays put.-3 → -1) and type validation ('fast'ignored).Link to Devin session: https://app.devin.ai/sessions/c4872c2982734093bdee80d04a7d5ceb
Open in Devin Desktop: https://app.devin.ai/desktop/session/c4872c2982734093bdee80d04a7d5ceb?variant=devin
Requested by: @pyramation