content: module Playhead where
  import Rumpus
  
  
  start :: Start
  start = do
      
      beatsKnob    <- addKnob "Beats"    (Stepped (map show [1..64])) 7
      tempoKnob    <- addKnob "Tempo"    (Linear 80 120) 100
      heightKnob   <- addKnob "Height"   (Linear 1 4) 1
  
      thisID <- ask
      playHead <- spawnChild $ do
          myShape      ==> Cube
          myBodyFlags  ==> [Ungrabbable]
          myBody       ==> Detector
          mySize       ==> 0
          myUpdate     ==> do
              tempo    <- readKnob tempoKnob
              -- Move playhead
              beats    <- readKnob beatsKnob
              height   <- readKnob heightKnob
              now      <- (* (tempo/60)) <$> getNow
              let time = mod' now (max 1 beats)
                  x    = time / 4
                  size = V3 0.01 height 1
  
              setAttachmentOffset (position (V3 x 0 0))
  
              ---- Scale in/out
              --let timeR    = beats - time
              --    scaleIn  = min time  0.2 * recip 0.2
              --    scaleOut = min timeR 0.2 * recip 0.2
              --    scale    = min 1 $ scaleIn * scaleOut
  
              --setSize (realToFrac scale * size)
              setSize size
              return ()
          myCollisionBegan ==> \hitEntityID _ ->
              -- Ignore hitting our own code-slab
              when (hitEntityID /= thisID) $ do
                flashColor <- getEntityColor hitEntityID
                animateColor flashColor (V4 1 1 1 1) 0.2
      attachEntity playHead (position (V3 0 0 0))
  
      -- track
      spawnChild $ do
          myShape ==> Cube
          myUpdate ==> do
              beats <- (/4) <$> readKnob beatsKnob
              setPose (position (V3 (beats / 2) 0 0))
              setSize (V3 beats 0.01 0.01)
  
      -- Quantize playhead position on release
      myDragEnded ==> do
          V3 x y z <- getPosition
          let quantPos = V3
                  (quantizeToF (1/8)  x)
                  (quantizeToF (1/24) y)
                  (quantizeToF (1/8)  z)
          animatePositionTo quantPos 0.3
  
          V3 x y z <- getRotationEuler
          let quantRot = eulerToQuat $ V3
                  (quantizeToF (pi/4) x)
                  (quantizeToF (pi/4) y)
                  (quantizeToF (pi/4) z)
          animateRotationTo quantRot 0.3
          -- Save quantized position
          setDelayedAction 0.3 (sceneWatcherSaveEntity =<< ask)
  
      return ()
  
  
  -- 1 GL Unit == 4 beats
  -- 1 beat == 60/bpm seconds