;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;
;; DRAG GRAPHICS EXAMPLE
;;
;; Demonstrates direct manipulation of graphics.
;;
;; Drag two squares around a graphics window
;; using X and Y to control pitch and velocity.
;; Each square controls a different instrument.
;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; make sure that no audio units are already connected
(au:clear-graph)
;; Setup AudioGraph
; In this example two audio units are used. Their outputs
; are combined using an audio unit mixer, Apple's stereo mixer.
(define marimba (au:make-node "aumu" "dls " "appl"))
(define guitar (au:make-node "aumu" "dls " "appl"))
(define mixer (au:make-node "aumx" "smxr" "appl"))
(au:connect-node mixer 0 *au:output-node* 0)
(au:connect-node marimba 0 mixer 0)
(au:connect-node guitar 0 mixer 1)
(au:update-graph)
;; Set program changes
(au:midi-out (now) marimba *io:midi-pc* 0 12 0)
(au:midi-out (now) guitar *io:midi-pc* 0 25 0)
;; Set up graphics window and register
;; this process to receive mouse events
(define *canvas* (gfx:make-canvas))
(io:register-mouse-events *canvas*)
;; Setup Some Globals used to store the mouse position
(define *x* 0)
(define *y* 0)
; list containing (instrument path fill stroke)
; The "list" function constructs a list from the elements
; that follow it. In this case there are nested lists.
(define *marimba*
(list marimba (gfx:make-rectangle 300 200 50 100)
(list 1.0 0.0 0.0 1.0)
(list (random) (random) (random) 0.6)))
; list containing (instrument path fill stroke)
(define *guitar*
(list guitar (gfx:make-oval 100 100 50 100)
(list 1.0 0.0 0.0 1.0)
(list (random) (random) (random) 0.6)
(list 1.0 0.0 0.0 1.0)))
; Create a variable to hold the shape currently being dragged
(define *current* '())
;; Receives all io:mouse-down events
;; Clear (fill) the screen, draw both squares
;; Set *current* to be the shape the
;; mouse is currently inside (or set to null)
(define (io:mouse-down x y)
(set! *x* x)
(set! *y* y)
(gfx:clear-canvas (now) *canvas* '(0.2 0.0 0.0 1.0))
(gfx:draw-path (now) *canvas*
(cadr *marimba*)
(caddr *marimba*)
(cadddr *marimba*)
1.0
*gfx:whole-path*)
(gfx:draw-path (now) *canvas*
(cadr *guitar*)
(caddr *guitar*)
(cadddr *guitar*)
1.0
*gfx:whole-path*)
(cond ((gfx:point-in-path? (cadr *marimba*) x y)
(set! *current* *marimba*))
((gfx:point-in-path? (cadr *guitar*) x y)
(set! *current* *guitar*))
(else (set! *current* '()))))
;; Receives all io:mouse-up events
;; set *current* to null when mouse button released
(define (io:mouse-up x y)
(set! *current* '()))
;; Receives all io:mouse-drag events
;; 1) play note on *current* instrument
;; 2) wipe old square (keeping the stroke)
;; 3) move square
;; 4) draw square
; The function cadr gets the second element of a list
; caddr gets the third element of a list
; cadddr gets the fourth element of a list, etc...
(define io:mouse-drag
(lambda (x y)
(if (not (null? *current*))
(begin (play-note (+ (now) 1)
(car *current*)
(+ 10 (/ y 4)) (+ 0 (/ x 4)) 5000)
(gfx:draw-path (+ (now) 2) *canvas*
(cadr *current*)
'(0.2 0.0 0.0 1.0)
'(0.2 0.0 0.0 1.0))
(gfx:move-path (+ (now) 3) (cadr *current*) (- x *x*) (- y *y*))
(gfx:draw-path (+ (now) 4) *canvas*
(cadr *current*)
(caddr *current*)
(cadddr *current*))
(set! *x* x)
(set! *y* y)))))
;; Initialize
(define (start time)
(gfx:clear-canvas time
*canvas*
'(0.2 0.0 0.0 1.0))
(gfx:draw-path (+ time 1) *canvas*
(cadr *marimba*)
(caddr *marimba*)
(cadddr *marimba*))
(gfx:draw-path (+ time 1) *canvas*
(cadr *guitar*)
(caddr *guitar*)
(cadddr *guitar*)))
;; Start
(start (+ (now) *second*))