lux/word.rkt

152 lines
4.0 KiB
Racket
Raw Normal View History

2014-11-19 22:48:05 +00:00
#lang racket/base
(require racket/list
racket/match
racket/contract/base
racket/flonum
2018-11-15 14:23:14 +00:00
math/flonum
2014-11-19 22:48:05 +00:00
racket/format
racket/generic
lux/chaos)
(define-generics word
2014-11-21 18:26:01 +00:00
(word-fps word)
2014-11-19 22:48:05 +00:00
(word-label word frame-time)
2015-04-14 18:00:59 +00:00
(word-evt word)
2014-11-20 15:53:15 +00:00
(word-event word evt)
(word-tick word)
(word-output word)
(word-return word)
2014-11-19 22:48:05 +00:00
#:fallbacks
2014-11-21 18:26:01 +00:00
[(define (word-fps w)
60.0)
(define (word-label w frame-time)
2014-11-19 22:48:05 +00:00
(lux-standard-label "Lux" frame-time))
2015-04-14 18:00:59 +00:00
(define (word-evt w)
never-evt)
2014-11-20 15:53:15 +00:00
(define (word-event w e) w)
(define (word-tick w) w)
2014-11-22 18:54:08 +00:00
(define (word-output w) #f)
2014-11-20 15:53:15 +00:00
(define (word-return w) w)])
2014-11-19 22:48:05 +00:00
(define (lux-standard-label l frame-time)
2018-11-15 14:23:14 +00:00
(define fps (fl/ 1000.0 frame-time))
2014-11-19 22:48:05 +00:00
(~a l
": "
"Frame time: "
(~r frame-time
#:min-width 5
#:precision 1)
"ms; "
"FPS: "
2018-11-15 14:23:14 +00:00
(if (flinfinite? fps)
"inf"
(~r fps
#:min-width 10
#:precision 2))))
2014-11-19 22:48:05 +00:00
(define current-chaos (make-parameter #f))
(define (call-with-chaos c t)
2014-11-26 22:21:55 +00:00
(chaos-start! c)
2014-11-19 22:48:05 +00:00
(parameterize ([current-chaos c])
2014-11-26 22:21:55 +00:00
(begin0 (t)
(chaos-stop! c))))
2014-11-19 22:48:05 +00:00
(define (fiat-lux w)
(define c (current-chaos))
(unless c
(error 'fiat-lux "Not called within call-with-chaos"))
(factum-fiat-lux c w))
2015-09-04 13:18:16 +00:00
(define (compute-next-time start-time fps)
(define time-incr (fl* (fl/ 1.0 fps) 1000.0))
(define next-time (fl+ start-time time-incr))
next-time)
(define (continue-or-word-return next-w old-w k)
(cond
[(not next-w)
(word-return old-w)]
[else
(k next-w)]))
2014-11-19 22:48:05 +00:00
(define (factum-fiat-lux c w)
2015-09-04 13:18:16 +00:00
(define (output&process-input&wait frame-start-time w)
2015-11-17 20:09:07 +00:00
(define pre-output-time (current-inexact-milliseconds))
(chaos-output! c (word-output w))
2015-09-04 13:18:16 +00:00
(define frame-end-time (current-inexact-milliseconds))
(define frame-time (- frame-end-time frame-start-time))
2015-12-14 01:15:32 +00:00
#;(printf "W: ~v\tG: ~v\tT: ~v\n"
2018-11-15 14:23:14 +00:00
(- pre-output-time frame-start-time)
(- frame-end-time pre-output-time)
frame-time)
(define new-label (word-label w frame-time))
2015-09-04 13:18:16 +00:00
(chaos-label! c new-label)
2015-12-14 01:15:32 +00:00
;; Ideally we could compute how much time we have available for GC
;; and just use that so we never have any pauses. That's a very
;; big wish though.
(collect-garbage 'incremental)
2015-11-17 20:09:07 +00:00
(define fps (word-fps w))
2018-11-06 18:45:15 +00:00
(define next-time (compute-next-time frame-start-time #;frame-end-time fps))
2015-09-04 13:18:16 +00:00
(define deadline-evt (alarm-evt next-time))
(define input-enabled? (fl= 0.0 fps))
2015-09-04 13:18:16 +00:00
(define w-evt (word-evt w))
2015-09-04 13:18:16 +00:00
(define c-evt (chaos-event c))
(define w-or-c-evt (choice-evt w-evt c-evt))
(define continue
(λ (next-w)
(output&process-input&wait frame-end-time next-w)))
2015-09-04 13:18:16 +00:00
(define THE-W w)
(define wait-evt
(handle-evt deadline-evt
(λ (_)
(define next-w (word-tick THE-W))
(continue-or-word-return
next-w THE-W
continue))))
(define input-continue
(λ (next-w)
(cond
[input-enabled?
(output&process-input&wait frame-end-time next-w)]
[else
(set! THE-W next-w)
(process-input&wait)])))
(define input-evt
(handle-evt w-or-c-evt
(λ (e)
(define next-w (word-event THE-W e))
(continue-or-word-return
next-w THE-W
input-continue))))
(define both-evt
(choice-evt input-evt wait-evt))
(define timeout-f
(λ () (chaos-yield c both-evt)))
(define (process-input&wait)
(sync/timeout timeout-f input-evt))
2014-11-19 22:48:05 +00:00
(process-input&wait))
(chaos-swap! c (λ () (output&process-input&wait (current-inexact-milliseconds) w))))
2014-11-19 22:48:05 +00:00
(provide
gen:word
(contract-out
2014-11-22 18:54:08 +00:00
[word?
(-> any/c word?)]
2014-11-19 22:48:05 +00:00
[lux-standard-label
(-> string? flonum?
string?)]
[call-with-chaos
(-> chaos? (-> any)
any)]
[fiat-lux
(-> word?
any)]))