(define-module (catbird mixins) #:use-module (catbird config) #:use-module (chickadee math vector) #:use-module (chickadee scripting) #:use-module (ice-9 exceptions) #:use-module (oop goops) #:use-module (srfi srfi-9) #:export ( name rank sort-by-rank/ascending parent attach detach on-enter on-exit on-attach on-detach update update/around agenda on-pause on-resume paused? pause resume run-script stop-scripts visible? on-show on-hide show hide render render/around render/before position) #:replace (pause)) (define-class () (name #:accessor name #:init-keyword #:name #:init-value #f)) ;; For Z sorting objects and such. (define-class () (rank #:accessor rank #:init-keyword #:rank #:init-value 0)) (define (sort-by-rank/ascending lst) (sort lst (lambda (a b) (< (rank a) (rank b))))) ;;; ;;; Containable ;;; (define-class () (parent #:accessor parent #:init-form #f)) (define-method (on-enter (child )) #t) (define-method (on-exit (child )) #t) (define-method (on-attach parent (child )) #t) (define-method (on-detach parent (child )) #t) (define-method (attach (obj ) container) (when (parent obj) (raise-exception (make-exception-with-message "object already has a parent"))) (set! (parent obj) container) (on-enter obj) (on-attach container obj)) (define-method (detach (obj )) (unless (parent obj) (raise-exception (make-exception-with-message "object has no parent"))) (on-detach (parent obj) obj) (on-exit obj) (set! (parent obj) #f)) ;;; ;;; Updatable ;;; (define-class ()) (define-method (update (obj ) dt) #t) (define-method (update/around (obj ) dt) (update obj dt)) ;;; ;;; Scriptable ;;; (define-class () (paused? #:accessor paused? #:init-form #f #:init-keyword #:paused?) (agenda #:getter agenda #:init-thunk make-agenda)) (define-method (on-pause (obj )) #t) (define-method (on-resume (obj )) #t) (define-method (pause (obj )) (unless (paused? obj) (set! (paused? obj) #t) (on-pause obj))) (define-method (resume (obj )) (when (paused? obj) (set! (paused? obj) #f) (on-resume obj))) (define-method (update/around (obj ) dt) (unless (paused? obj) (with-agenda (agenda obj) (update-agenda dt) (next-method)))) (define-syntax-rule (run-script obj body ...) (with-agenda (agenda obj) (script body ...))) (define-method (stop-scripts obj) (with-agenda (agenda obj) (clear-agenda))) ;;; ;;; Renderable ;;; (define-class () (visible? #:accessor visible? #:init-form #t #:init-keyword #:visible?)) (define-method (on-show (obj )) #t) (define-method (on-hide (obj )) #t) (define-method (show (obj )) (set! (visible? obj) #t) (on-show obj)) (define-method (hide (obj )) (set! (visible? obj) #f) (on-hide obj)) (define-method (render (obj ) alpha) #t) (define-method (render/before (obj ) alpha) #t) (define-method (render/around (obj ) alpha) (when (visible? obj) (render/before obj alpha) (render obj alpha))) ;;; ;;; Movable ;;; (define-class () (position #:accessor position #:init-keyword #:position #:init-form (vec2 0.0 0.0))) (define-class () (position #:accessor position #:init-keyword #:position #:init-form (vec3 0.0 0.0 0.0)))