X-Git-Url: https://git.jsancho.org/?a=blobdiff_plain;f=src%2Fviews.scm;h=8e2c21cf47c6f7b6a366ad272bb37bf39f8aa49e;hb=bdc03bcc2da4d01745fb542d7a7d642b888b691e;hp=4f35b568b0257bb94008f2614dc48e82b12f5148;hpb=edf14e07f9f1db66cb75f10af54551034171725e;p=gacela.git diff --git a/src/views.scm b/src/views.scm index 4f35b56..8e2c21c 100644 --- a/src/views.scm +++ b/src/views.scm @@ -15,19 +15,243 @@ ;;; along with this program. If not, see . -(define-module (gacela draw) +(define-module (gacela views) #:use-module (gacela gacela) #:use-module ((gacela video) #:renamer (symbol-prefix-proc 'video:)) #:use-module ((gacela gl) #:select (glPushMatrix glPopMatrix)) #:use-module (ice-9 optargs)) -(define-macro (define-view name content) - `(begin - (hash-set! active-views ',name (lambda () (video:glmatrix-block ,content))) - ',name)) -(define (square . params) - (define-view tmp (apply video:draw-square params))) +;;; Views + +(define view-type + (make-record-type "view" + '(id controllers meshes priority) + (lambda (record port) + (format port "#" + (length (view-meshes record)))))) + +(define (make-view controllers meshes priority) ((record-constructor view-type) (gensym) controllers meshes priority)) +(define view? (record-predicate view-type)) +(define view-id (record-accessor view-type 'id)) +(define view-meshes (record-accessor view-type 'meshes)) +(define view-meshes-set! (record-modifier view-type 'meshes)) +(define view-controllers (record-accessor view-type 'controllers)) +(define view-controllers-set! (record-modifier view-type 'controllers)) +(define view-priority (record-accessor view-type 'priority)) + +(defmacro* view (#:key (priority 0) . elements) + `(let ((e (view-elements ,@elements))) + (make-view (car e) (cadr e) ,priority))) + +(define-macro (view-elements . elements) + (cond ((null? elements) `'(() ())) + (else + `(let ((l (view-elements ,@(cdr elements)))) + ,(let ((e (car elements))) + `(cond ((mesh? ,e) + (list (car l) (cons ,e (cadr l)))) + ((procedure? ,e) + (list (cons ,(if (list? e) e `(lambda () (,e))) (car l)) + (cadr l))) + (else l))))))) + +(define (controllers-list list controllers) + (cond ((null? controllers) + list) + ((list? (car controllers)) + (assoc-set! (controllers-list list (cdr controllers)) (caar controllers) (cadar controllers))) + (else + (assoc-set! (controllers-list list (cdr controllers)) (gensym) (car controllers))))) + +(define activated-views '()) + +(define (sort-views views-alist) + (sort views-alist + (lambda (v1 v2) + (< (view-priority (cdr v1)) (view-priority (cdr v2)))))) + +(define (activate-view view) + (set! activated-views + (sort-views (assoc-set! activated-views (view-id view) view))) + view) + +(define (view-actived? view) + (and (assoc (view-id view) activated-views) #t)) + +(define (view-priority-set! view priority) + ((record-modifier view-type 'priority) view priority) + (if (view-actived? view) + (set! activated-views (sort-views activated-views)))) + +(define current-view #f) + +(define* (run-views #:optional (views activated-views)) + (cond ((not (null? views)) + (set! current-view (cdar views)) + ;((view-body current-view)) + (draw-meshes (view-meshes current-view)) + (run-views (cdr views))))) + +(define (draw-meshes meshes) + (cond ((not (null? meshes)) + (catch #t + (lambda () (mesh-draw (cdar meshes))) + (lambda (key . args) #f)) + (draw-meshes (cdr meshes))))) + + +;(define default-view (activate-view (make-view (lambda () #f)))) + + +;;; Meshes + +(define mesh-type + (make-record-type "mesh" + '(draw translate turn rotate inner-properties inner-property properties properties-set! property property-set!) + (lambda (record port) + (format port "#" port)))) + +(define mesh? (record-predicate mesh-type)) + +(define* (make-mesh proc #:optional type) + (apply + (record-constructor mesh-type) + (let ((px 0) (py 0) (pz 0) + (ax 0) (ay 0) (az 0) + (rx 0) (ry 0) (rz 0) + (id (gensym)) + (properties '())) + (let ((inner-properties + (lambda () + `((id . ,id) (type . ,type) (x . ,px) (y . ,py) (z . ,pz) (ax . ,ax) (ay . ,ay) (az . ,az) (rx . ,rx) (ry . ,ry) (rz . ,rz))))) + (list + (lambda () + "draw" + (video:glmatrix-block + (video:rotate ax ay az) + (video:translate px py pz) + (video:rotate rx ry rz) + (proc properties))) + (lambda (x y z) + "translate" + (set! px (+ px x)) + (set! py (+ py y)) + (set! pz (+ pz z))) + (lambda (x y z) + "turn" + (set! ax (+ ax x)) + (set! ay (+ ay y)) + (set! az (+ az z))) + (lambda (x y z) + "rotate" + (set! rx (+ rx x)) + (set! ry (+ ry y)) + (set! rz (+ rz z))) + (lambda () + "inner-properties" + (inner-properties)) + (lambda (prop-name) + "inner-property" + (assoc-ref (inner-properties) prop-name)) + (lambda () + "properties" + properties) + (lambda (new-properties) + "properties-set!" + (set! properties new-properties)) + (lambda (prop-name) + "property" + (assoc-ref properties prop-name)) + (lambda (prop-name value) + "property-set!" + (set! properties (assoc-set! properties prop-name value)))))))) + +(define (mesh-draw mesh) + (((record-accessor mesh-type 'draw) mesh))) + +(define (mesh-inner-properties mesh) + (((record-accessor mesh-type 'inner-properties) mesh))) + +(define (mesh-inner-property mesh prop-name) + (((record-accessor mesh-type 'inner-property) mesh) prop-name)) + +(define (mesh-properties mesh) + (((record-accessor mesh-type 'properties) mesh))) + +(define (mesh-properties-set! mesh new-properties) + (((record-accessor mesh-type 'properties-set!) mesh) new-properties)) + +(define (mesh-property mesh prop-name) + (((record-accessor mesh-type 'property) mesh) prop-name)) + +(define (mesh-property-set! mesh prop-name value) + (((record-accessor mesh-type 'property-set!) mesh) prop-name value)) + +(define* (show mesh #:optional (view current-view)) + (let ((id (mesh-inner-property mesh 'id)) + (table (view-meshes view))) + (if (not (assoc-ref table id)) + (view-meshes-set! view (assoc-set! table id mesh)))) + mesh) + +(define* (hide mesh #:optional (view current-view)) + (let ((id (mesh-inner-property mesh 'id)) + (table (view-meshes view))) + (if (assoc-ref table id) + (view-meshes-set! view (assoc-remove! table id)))) + mesh) + +(define* (translate mesh x y #:optional (z 0)) + (((record-accessor mesh-type 'translate) mesh) x y z) + mesh) + +(define (turn mesh . params) + (apply ((record-accessor mesh-type 'turn) mesh) + (if (>= (length params) 3) + params + (list 0 0 (car params)))) + mesh) + +(define (rotate mesh . params) + (apply ((record-accessor mesh-type 'rotate) mesh) + (if (>= (length params) 3) + params + (list 0 0 (car params)))) + mesh) + + +;;; Primitives + +(defmacro* define-primitive (proc #:optional type) + `(lambda (. params) + (let ((m (make-mesh (lambda (props) (apply ,proc ((@ (gacela utils) arguments-apply) ,proc props))) ,type))) + (mesh-properties-set! m ((@ (gacela utils) arguments-calling) ,proc params)) + m))) + +(define-macro (define-primitives . symbols) + (cond ((null? symbols) + `#t) + (else + (let ((origin (caar symbols)) + (dest (cadar symbols))) + `(begin + (define ,origin (define-primitive ,dest ',origin)) + (define-primitives ,@(cdr symbols))))))) + +(define-primitives + (rectangle video:draw-rectangle) + (square video:draw-square)) + + +;;; Adding extensions to the main loop +(add-extension! run-views 10) + (module-map (lambda (sym var) (if (not (eq? sym '%module-public-interface))