1 ;;; Gacela, a GNU Guile extension for fast games development
2 ;;; Copyright (C) 2009 by Javier Sancho Fernandez <jsf at jsancho dot org>
4 ;;; This program is free software: you can redistribute it and/or modify
5 ;;; it under the terms of the GNU General Public License as published by
6 ;;; the Free Software Foundation, either version 3 of the License, or
7 ;;; (at your option) any later version.
9 ;;; This program is distributed in the hope that it will be useful,
10 ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ;;; GNU General Public License for more details.
14 ;;; You should have received a copy of the GNU General Public License
15 ;;; along with this program. If not, see <http://www.gnu.org/licenses/>.
18 (define-module (gacela views)
19 #:use-module (gacela gacela)
20 #:use-module ((gacela video) #:renamer (symbol-prefix-proc 'video:))
21 #:use-module ((gacela gl) #:select (glPushMatrix glPopMatrix))
22 #:use-module (ice-9 optargs))
28 (make-record-type "view"
29 '(id controllers meshes priority)
31 (format port "#<view: ~a meshes>"
32 (length (view-meshes record))))))
34 (define (make-view controllers meshes priority) ((record-constructor view-type) (gensym) controllers meshes priority))
35 (define view? (record-predicate view-type))
36 (define view-id (record-accessor view-type 'id))
37 (define view-meshes (record-accessor view-type 'meshes))
38 (define view-meshes-set! (record-modifier view-type 'meshes))
39 (define view-controllers (record-accessor view-type 'controllers))
40 (define view-controllers-set! (record-modifier view-type 'controllers))
41 (define view-priority (record-accessor view-type 'priority))
43 ;(defmacro* view (#:key (priority 0) . elements)
44 (define-macro (view-elements . elements)
45 (cond ((null? elements) `'(() ()))
47 `(let ((l (view-elements ,@(cdr elements))))
48 ,(let ((e (car elements)))
50 (list (car l) (cons ,e (cadr l))))
52 (list (cons ,(if (list? e) e `(lambda () (,e))) (car l))
56 (define* (view2 #:key (priority 0) . elements)
57 (let ((controllers '())
60 (cond ((not (null? elements))
61 (cond ((mesh? (car elements)) (set! meshes (cons (car elements) meshes)))
62 ((procedure? (car elements)) (set! controllers (cons (car elements) controllers))))
70 (define activated-views '())
72 (define (sort-views views-alist)
75 (< (view-priority (cdr v1)) (view-priority (cdr v2))))))
77 (define (activate-view view)
79 (sort-views (assoc-set! activated-views (view-id view) view)))
82 (define (view-actived? view)
83 (and (assoc (view-id view) activated-views) #t))
85 (define (view-priority-set! view priority)
86 ((record-modifier view-type 'priority) view priority)
87 (if (view-actived? view)
88 (set! activated-views (sort-views activated-views))))
90 (define current-view #f)
92 (define* (run-views #:optional (views activated-views))
93 (cond ((not (null? views))
94 (set! current-view (cdar views))
95 ;((view-body current-view))
96 (draw-meshes (view-meshes current-view))
97 (run-views (cdr views)))))
99 (define (draw-meshes meshes)
100 (cond ((not (null? meshes))
102 (lambda () (mesh-draw (cdar meshes)))
103 (lambda (key . args) #f))
104 (draw-meshes (cdr meshes)))))
107 ;(define default-view (activate-view (make-view (lambda () #f))))
113 (make-record-type "mesh"
114 '(draw translate turn rotate inner-properties inner-property properties properties-set! property property-set!)
115 (lambda (record port)
116 (format port "#<mesh: ~a" (mesh-inner-property record 'type))
117 (for-each (lambda (x)
118 (cond (((@ (gacela utils) bound?) (cdr x))
119 (format port " ~a" x))))
120 (mesh-properties record))
121 (display ">" port))))
124 (define mesh? (record-predicate mesh-type))
126 (define* (make-mesh proc #:optional type)
128 (record-constructor mesh-type)
129 (let ((px 0) (py 0) (pz 0)
134 (let ((inner-properties
136 `((id . ,id) (type . ,type) (x . ,px) (y . ,py) (z . ,pz) (ax . ,ax) (ay . ,ay) (az . ,az) (rx . ,rx) (ry . ,ry) (rz . ,rz)))))
140 (video:glmatrix-block
141 (video:rotate ax ay az)
142 (video:translate px py pz)
143 (video:rotate rx ry rz)
165 (assoc-ref (inner-properties) prop-name))
169 (lambda (new-properties)
171 (set! properties new-properties))
174 (assoc-ref properties prop-name))
175 (lambda (prop-name value)
177 (set! properties (assoc-set! properties prop-name value))))))))
179 (define (mesh-draw mesh)
180 (((record-accessor mesh-type 'draw) mesh)))
182 (define (mesh-inner-properties mesh)
183 (((record-accessor mesh-type 'inner-properties) mesh)))
185 (define (mesh-inner-property mesh prop-name)
186 (((record-accessor mesh-type 'inner-property) mesh) prop-name))
188 (define (mesh-properties mesh)
189 (((record-accessor mesh-type 'properties) mesh)))
191 (define (mesh-properties-set! mesh new-properties)
192 (((record-accessor mesh-type 'properties-set!) mesh) new-properties))
194 (define (mesh-property mesh prop-name)
195 (((record-accessor mesh-type 'property) mesh) prop-name))
197 (define (mesh-property-set! mesh prop-name value)
198 (((record-accessor mesh-type 'property-set!) mesh) prop-name value))
200 (define* (show mesh #:optional (view current-view))
201 (let ((id (mesh-inner-property mesh 'id))
202 (table (view-meshes view)))
203 (if (not (assoc-ref table id))
204 (view-meshes-set! view (assoc-set! table id mesh))))
207 (define* (hide mesh #:optional (view current-view))
208 (let ((id (mesh-inner-property mesh 'id))
209 (table (view-meshes view)))
210 (if (assoc-ref table id)
211 (view-meshes-set! view (assoc-remove! table id))))
214 (define* (translate mesh x y #:optional (z 0))
215 (((record-accessor mesh-type 'translate) mesh) x y z)
218 (define (turn mesh . params)
219 (apply ((record-accessor mesh-type 'turn) mesh)
220 (if (>= (length params) 3)
222 (list 0 0 (car params))))
225 (define (rotate mesh . params)
226 (apply ((record-accessor mesh-type 'rotate) mesh)
227 (if (>= (length params) 3)
229 (list 0 0 (car params))))
235 (defmacro* define-primitive (proc #:optional type)
237 (let ((m (make-mesh (lambda (props) (apply ,proc ((@ (gacela utils) arguments-apply) ,proc props))) ,type)))
238 (mesh-properties-set! m ((@ (gacela utils) arguments-calling) ,proc params))
241 (define-macro (define-primitives . symbols)
242 (cond ((null? symbols)
245 (let ((origin (caar symbols))
246 (dest (cadar symbols)))
248 (define ,origin (define-primitive ,dest ',origin))
249 (define-primitives ,@(cdr symbols)))))))
252 (rectangle video:draw-rectangle)
253 (square video:draw-square))
256 ;;; Adding extensions to the main loop
257 (add-extension! run-views 10)
260 (module-map (lambda (sym var)
261 (if (not (eq? sym '%module-public-interface))
262 (module-export! (current-module) (list sym))))