racket/collects/frtime/animation.ss
2005-08-12 16:07:40 +00:00

302 lines
10 KiB
Scheme

(module animation (lib "frtime.ss" "frtime")
(require (all-except "graphics.ss" make-posn posn-x posn-y make-rgb)
(lifted "graphics.ss" posn-x posn-y make-posn make-rgb)
(lib "match.ss")
(as-is:unchecked (lib "lang-ext.ss" "frtime") lift)
(lib "class.ss")
(lib "list.ss" "frtime")
(lib "etc.ss" "frtime")
(lib "math.ss" "frtime"))
(open-graphics)
(define fresh-anim
(let ([first #t])
(opt-lambda ([x 400] [y 400] [title "Animation - DrScheme"])
(if first
(set! first #f)
(begin
(set! window
(open-viewport title x y))
(set! pixmap
(open-pixmap "" x y))
(set! mouse-pos
(hold ((viewport-mouse-events window)
. ==> .
(lambda (ev) (make-posn
(send ev get-x)
(send ev get-y))))
(query-mouse-posn window)))
(set! key-strokes ((viewport-key-events window) . ==> . sixkey-value))
(set! left-clicks ((viewport-mouse-events window) . =#> . (lambda (ev) (send ev button-down? 'left))))
(set! middle-clicks ((viewport-mouse-events window) . =#> . (lambda (ev) (send ev button-down? 'middle))))
(set! right-clicks ((viewport-mouse-events window) . =#> . (lambda (ev) (send ev button-down? 'right)))))))))
(define window
(open-viewport "Animation - DrScheme" 400 400))
(define pixmap
(open-pixmap "" 400 400))
(define mouse-pos
(hold ((viewport-mouse-events window)
. =#=> .
(lambda (ev) (if (send ev moving?)
(make-posn
(send ev get-x)
(send ev get-y))
nothing)))
(query-mouse-posn window)))
(define filtered-keys (viewport-key-events window))
(define shift-down (hold (filtered-keys . ==> . sixkey-shift)))
(define control-down (hold (filtered-keys . ==> . sixkey-control)))
(define meta-down (hold (filtered-keys . ==> . sixkey-meta)))
(define alt-down (hold (filtered-keys . ==> . sixkey-alt)))
(define key-strokes ((viewport-key-events window) . ==> . sixkey-value))
(define left-clicks ((viewport-mouse-events window) . =#> . (lambda (ev) (send ev button-down? 'left))))
(define middle-clicks ((viewport-mouse-events window) . =#> . (lambda (ev) (send ev button-down? 'middle))))
(define right-clicks ((viewport-mouse-events window) . =#> . (lambda (ev) (send ev button-down? 'right))))
(define left-releases ((viewport-mouse-events window) . =#> . (lambda (ev) (send ev button-up? 'left))))
(define middle-releases ((viewport-mouse-events window) . =#> . (lambda (ev) (send ev button-up? 'middle))))
(define right-releases ((viewport-mouse-events window) . =#> . (lambda (ev) (send ev button-up? 'right))))
(define-struct ring (center radius color))
(define-struct solid-ellipse (ul w h color))
(define-struct graph-string (pos text color))
(define-struct line (p1 p2 color))
(define-struct rect (ul w h color))
(define-struct rrect (ur w h color))
(define-struct curve (xmin xmax ymin ymax fn))
(define-struct polygon (posn-list posn color))
(define-struct solid-polygon (posn-list posn color))
(define (make-circle center r color)
(make-solid-ellipse (make-posn (- (posn-x center) r)
(- (posn-y center) r))
(* 2 r) (* 2 r) color))
(define l (new-cell empty))
(define (display-shapes x)
(set-cell! l x))
(define (top-level-draw-list a-los)
((clear-viewport pixmap))
(draw-list a-los)
(copy-viewport pixmap window))
(define (draw-list a-los)
(for-each
(match-lambda
[(? undefined?) (void)]
[($ ring center radius color)
((draw-ellipse pixmap)
(make-posn (- (posn-x center) radius)
(- (posn-y center) radius))
(* 2 radius)
(* 2 radius)
color)]
[($ solid-ellipse ul w h color)
((draw-solid-ellipse pixmap) ul w h color)]
[($ graph-string pos text color) ((draw-string pixmap) pos text color)]
[($ line p1 p2 color) ((draw-line pixmap) p1 p2 color)]
[($ rect ul w h color)
(cond
[(and (>= w 0) (>= h 0)) ((draw-solid-rectangle pixmap) ul w h color)]
[(>= h 0) ((draw-solid-rectangle pixmap) (make-posn (+ (posn-x ul) w) (posn-y ul)) (- w) h color)]
[(>= w 0) ((draw-solid-rectangle pixmap) (make-posn (posn-x ul) (+ (posn-y ul) h)) w (- h) color)]
[else ((draw-solid-rectangle pixmap) (make-posn (+ (posn-x ul) w) (+ (posn-y ul) h)) (- w) (- h) color)])]
[($ polygon pts offset color) ((draw-polygon pixmap) pts offset color)]
[($ solid-polygon pts offset color) ((draw-solid-polygon pixmap) pts offset color)]
[(? list? x) (draw-list x)]
[(? void?) (void)])
a-los))
(define d (lift #t top-level-draw-list l))
(define-struct graph-color (fn xmin xmax ymin ymax))
(define (draw-graph-color pm gc)
(let ([dp (draw-pixel pm)])
(match gc
[($ graph-color fn xmin xmax ymin ymax)
(let ([xincr (/ (- xmax xmin) 300)]
[yincr (/ (- ymax ymin) 300)])
(let loop ([i 50] [y ymin])
(let loop ([j 50] [x xmin])
(dp (make-posn j i) (fn x y))
(when (< j 350)
(loop (add1 j) (+ x xincr))))
(when (< i 350)
(loop (add1 i) (+ y yincr)))))])))
(define (valid-posn? v)
(and (posn? v) (number? (posn-x v)) (number? (posn-y v))))
(define (key sym)
(key-strokes
. =#> .
(lambda (x) (eq? x (value-now sym)))))
(define (draw vp pm posl)
((clear-viewport pm))
(for-each (lambda (elt)
(cond
[(graph-color? elt) (draw-graph-color pm elt)]
[(string? elt) ((draw-string pm) (make-posn 8 20) elt)]
[(valid-posn? elt) ((draw-solid-ellipse pm)
(make-posn (- (posn-x elt) 10)
(- (posn-y elt) 10))
20 20
(make-rgb 0 .6 .6))]
[(and (cons? elt)
(valid-posn? (first elt))
(valid-posn? (rest elt))) ((draw-line pm)
(first elt)
(rest elt)
"black")]
[else (void)])) posl)
(copy-viewport pm vp))
#|
(define foldl
(case-lambda
[(f i l) (if (cons? l)
(foldl f (f (first l) i) (rest l))
i)]))
|#
(define (drop n l)
(if (empty? l)
empty
(if (<= n 0)
l
(drop (sub1 n) (rest l)))))
(define (inc-max n)
(lambda (x) (if (>= x n)
n
(add1 x))))
(define (dec-min n)
(lambda (x) (if (<= x n)
n
(sub1 x))))
(define (fix-rgb r g b)
(let ([fix (lambda (n) (min 1 (max 0 n)))])
(apply make-rgb (map fix (list r g b)))))
(define range-control
(opt-lambda (up down limit [init 0])
(accum-b
(merge-e (up . -=> . (inc-max limit))
(down . -=> . (dec-min 0)))
init)))
(define (keyboard-control up down limit)
(accum-b
(key-strokes
. =#=> .
(match-lambda
[(? (lambda (x) (eq? x up))) (inc-max limit)]
[(? (lambda (x) (eq? x down))) (dec-min 0)]
[_ nothing]))
0))
(define-struct wave-state (hz offset))
(define (wave hz)
(let* ([state (collect-b
(snapshot-e (changes hz) milliseconds)
(make-wave-state (value-now hz) 0)
(lambda (new-freq+time old-state)
(match new-freq+time
[(h1 t)
(match old-state
[($ wave-state h0 o0)
(make-wave-state
h1
(+ o0 (* .002 pi t (- h0 h1))))])])))])
(+ (lift #f wave-state-offset state)
(* milliseconds pi (lift #f wave-state-hz state) .002))))
(define (current-and-last-value signal)
(let ([init (value-now signal)])
(collect-b (changes signal)
(list init init)
(lambda (new-value previous-two)
(list new-value (first previous-two))))))
(define (last-value signal)
(second (current-and-last-value signal)))
; (define (last-value signal)
; (let ([init (value-now signal)])
; (rest
; (collect-b (changes signal)
; (cons init init)
; (lambda (new old-pair)
; (cons new (first old-pair)))))))
(define (posn+ . args)
(make-posn (apply + (map posn-x args))
(apply + (map posn-y args))))
(define (posn- . args)
(make-posn (apply - (map posn-x args))
(apply - (map posn-y args))))
(define (posn/ p s)
(make-posn (/ (posn-x p) s)
(/ (posn-y p) s)))
(define (posn* p s)
(make-posn (* (posn-x p) s)
(* (posn-y p) s)))
(define (posn-dot p1 p2)
(+ (* (posn-x p1) (posn-x p2))
(* (posn-y p1) (posn-y p2))))
(define (posn-len p)
(sqrt (+ (sqr (posn-x p)) (sqr (posn-y p)))))
(define (normalize p)
(posn/ p (posn-len p)))
(define (current-mouse-pos)
(value-now mouse-pos))
(define (clip x lo hi)
(if (< x lo)
lo
(if (> x hi)
hi
x)))
(define (posn-diff p1 p2)
(sqrt (+ (sqr (- (posn-x p1) (posn-x p2)))
(sqr (- (posn-y p1) (posn-y p2))))))
(define (posn-derivative p)
(make-posn (derivative (posn-x p)) (derivative (posn-y p))))
(define (posn-integral p)
(make-posn (integral (posn-x p)) (integral (posn-y p))))
(provide
(all-defined-except pixmap window draw-list l d
make-wave-state wave-state-hz wave-state-offset)
#;(lifted make-circle make-ring make-solid-ellipse make-rect make-line make-polygon make-solid-polygon
make-graph-string)
(all-from "graphics.ss")))