(module (downstroke entity) * (import scheme (chicken base) (only srfi-1 fold alist-delete)) ;; Entities = alists with shared keys (#:type, #:x, #:y, #:width, #:height, ...). (define (make-entity x y w h) `((#:type . none) (#:x . ,x) (#:y . ,y) (#:width . ,w) (#:height . ,h))) (define (entity-ref entity key #!optional default) (cond ((assq key entity) => cdr) ((procedure? default) (default)) (else default))) (define (entity-type entity) (entity-ref entity #:type #f)) (define (entity-set entity key val) (cons (cons key val) (alist-delete key entity eq?))) (define (entity-set-many entity pairs) (fold (lambda (pair working-ent) (entity-set working-ent (car pair) (cdr pair))) entity pairs)) (define (entity-update entity key proc #!optional default) (entity-set entity key (proc (entity-ref entity key default)))) ;; #:skip-pipelines — list of symbols naming frame pipeline steps to skip for this ;; entity. Physics documents the built-in step names (see docs/physics.org). Other ;; subsystems (e.g. animation, rendering) may reserve additional symbols later and ;; use the same predicate and define-pipeline macro. (define (entity-skips-pipeline? entity step) (let ((skips (entity-ref entity #:skip-pipelines '()))) (and (pair? skips) (memq step skips)))) (define-syntax define-pipeline (syntax-rules () ((define-pipeline (identifier name) (scene entity dt) :guard guard (body ...)) (define (identifier scene entity dt) (if (or (not guard) (entity-skips-pipeline? entity (quote name))) entity (body ...)))) ((define-pipeline (identifier name) (scene entity dt) (body ...)) (define (identifier scene entity dt) (if (entity-skips-pipeline? entity (quote name)) entity (body ...)))))) ) ;; End of entity