;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; THE PERISCORE
;;
;; click on red green or blue
;; then click inside the periscore
;;
;; grey clears existing nodes, which will be slowly
;; wiped over time but stop sounding immediately
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(gfx:set-alias *gfx:aa-on*)
(au:clear-graph)
(define synth (au:make-node "aumu" "dls " "appl"))
(au:connect-node synth 0 *au:output-node* 0)
(au:update-graph)
(au:midi-out (now) synth *io:midi-pc* 0 13 0)
(au:midi-out (now) synth *io:midi-pc* 1 14 0)
(au:midi-out (now) synth *io:midi-pc* 2 15 0)
(define canvas (gfx:make-canvas 600 620))
(io:register-mouse-events canvas)
(gfx:lock-canvas-size canvas 600 620)
(define moving-line (gfx:make-path))
(define nodes '())
(define colour '(1 0 0 1))
(define channel 0)
(define synth-a (gfx:make-circle 210 50 25))
(define synth-b (gfx:make-circle 270 50 25))
(define synth-c (gfx:make-circle 330 50 25))
(define synth-d (gfx:make-circle 390 50 25))
(define y-cross (gfx:make-rectangle 300 100 2 400))
(define x-cross (gfx:make-rectangle 100 300 400 2))
(define ring-a (gfx:make-circle 300 300 50))
(define ring-b (gfx:make-circle 300 300 100))
(define ring-c (gfx:make-circle 300 300 150))
(define ring-d (gfx:make-circle 300 300 200))
(define outer-bounds (gfx:make-circle 300 300 190))
(define text-style (gfx:make-text-style "Times-Roman" 72.0 (list 0.5 0.5 0.7 1)))
(gfx:clear-canvas (now) canvas '(0.0 0.0 0.2 1))
(define draw-target
(lambda ()
(let ((tc '(0.1 0.1 0.7 1))
(nc '()))
(gfx:draw-path (now) canvas ring-d
'(0.1 0.0 0.3 0.35) '(0.2 0.0 0.3 0.35) 1 *gfx:whole-path*)
(gfx:draw-path (now) canvas y-cross nc tc 1 *gfx:fill-path*)
(gfx:draw-path (now) canvas x-cross nc tc 1 *gfx:fill-path*)
(gfx:draw-path (now) canvas ring-a tc nc 1 *gfx:stroke-path*)
(gfx:draw-path (now) canvas ring-b tc nc 1 *gfx:stroke-path*)
(gfx:draw-path (now) canvas ring-c tc nc 1 *gfx:stroke-path*)
(gfx:draw-path (now) canvas ring-d tc nc 1 *gfx:stroke-path*))))
(define test
(lambda (time path cnt)
(if (= cnt 360)
(begin (set! cnt 0)
(draw-target)))
(gfx:rotate-path time path 1 300 300 *degrees*)
(map (lambda (node)
(if (gfx:point-in-path? path
(car (node 'centre))
(cdr (node 'centre)))
(begin (node 'play time)
(callback (+ time 2000) (lambda () (node 'draw))))))
nodes)
(gfx:draw-path (+ time 5) canvas path
'(0 0 0 0) '(0.7 0.7 0.9 0.1) 1 *gfx:fill-path*)
(callback (+ time 1000) 'test (+ time 2000) path (+ cnt 1))))
(define set-moving-line
(lambda ()
(gfx:set-start-point moving-line 300 300)
(gfx:add-line moving-line 300 500)
(gfx:add-line moving-line 305 500)
(gfx:add-line moving-line 305 300)
(gfx:close-path moving-line)))
(define clear
(lambda ()
(set! nodes '())))
(define io:mouse-down
(lambda (x y)
(cond ((gfx:point-in-path? synth-a x y)
(gfx:draw-path (now) canvas synth-a
'(1 1 1 1) '(1 0 0 1) 1 *gfx:whole-path*))
((gfx:point-in-path? synth-b x y)
(gfx:draw-path (now) canvas synth-b
'(1 1 1 1) '(0 1 0 1) 1 *gfx:whole-path*))
((gfx:point-in-path? synth-c x y)
(gfx:draw-path (now) canvas synth-c
'(1 1 1 1) '(0 0 1 1) 1 *gfx:whole-path*))
((gfx:point-in-path? synth-d x y)
(gfx:draw-path (now) canvas synth-d
'(1 1 1 1) '(0 0 0 1) 1 *gfx:whole-path*)))))
(define io:mouse-up
(lambda (x y)
(cond ((gfx:point-in-path? synth-a x y)
(gfx:draw-path (now) canvas synth-a
'(1 1 1 1) '(1 0.5 0.5 1) 1 *gfx:whole-path*)
(set! channel 0)
(set! colour '(1 0.5 0.5 0.5)))
((gfx:point-in-path? synth-b x y)
(gfx:draw-path (now) canvas synth-b
'(1 1 1 1) '(0.5 1 0.5 1) 1 *gfx:whole-path*)
(set! channel 1)
(set! colour '(0.5 1 0.5 0.5)))
((gfx:point-in-path? synth-c x y)
(gfx:draw-path (now) canvas synth-c
'(1 1 1 1) '(0.5 0.5 1 1) 1 *gfx:whole-path*)
(set! channel 2)
(set! colour '(0.5 0.5 1 0.5)))
((gfx:point-in-path? synth-d x y)
(gfx:draw-path (now) canvas synth-d
'(1 1 1 1) '(0.5 0.5 0.5 1) 1 *gfx:whole-path*)
(clear))
((gfx:point-in-path? outer-bounds x y)
(let ((n (make-node channel colour x y)))
(n 'draw)
(set! nodes (cons n nodes)))))))
(define make-node
(lambda (channel fill-colour x y)
(let* ((path (gfx:make-circle x y 10))
(rel-x (abs (- x 300)))
(rel-y (abs (- y 300)))
(pitch (sqrt (+ (* rel-x rel-x) (* rel-y rel-y))))
(end-time 0))
(lambda (sym . args)
(cond ((eq? sym 'play)
(if (< end-time (car args))
(begin (set! end-time (+ (car args) 44100))
(play-note (now) synth (* pitch 0.6) 80 4000 channel)
(gfx:draw-path (now) canvas path
'(0 0 0 0) '(0 0 0 0) 1 *gfx:fill-path*))))
((eq? sym 'point)
(gfx:get-path-point path))
((eq? sym 'centre)
(gfx:get-path-centre path))
((eq? sym 'draw)
(gfx:draw-path (now) canvas path
'(0 0 0 0) fill-colour 1 *gfx:fill-path*))
((eq? sym 'move)
(gfx:move-path (now) path (car args) (cadr args))))))))
(define start
(lambda ()
(set-moving-line)
(gfx:draw-text (now) canvas "Periscore" text-style '(170 510))
(gfx:draw-path (now) canvas synth-a '(1 1 1 1) '(1 0.5 0.5 1) 1 *gfx:whole-path*)
(gfx:draw-path (now) canvas synth-b '(1 1 1 1) '(0.5 1 0.5 1) 1 *gfx:whole-path*)
(gfx:draw-path (now) canvas synth-c '(1 1 1 1) '(0.5 0.5 1 1) 1 *gfx:whole-path*)
(gfx:draw-path (now) canvas synth-d '(1 1 1 1) '(0.5 0.5 0.5 1) 1 *gfx:whole-path*)
(draw-target)
(test (now) moving-line 0)))
(callback (+ (now) 20000) 'start)