summaryrefslogtreecommitdiff
path: root/chickadee/render/sprite.scm
diff options
context:
space:
mode:
Diffstat (limited to 'chickadee/render/sprite.scm')
-rw-r--r--chickadee/render/sprite.scm285
1 files changed, 125 insertions, 160 deletions
diff --git a/chickadee/render/sprite.scm b/chickadee/render/sprite.scm
index 38b1594..c284ff4 100644
--- a/chickadee/render/sprite.scm
+++ b/chickadee/render/sprite.scm
@@ -27,8 +27,10 @@
#:use-module (chickadee render shader)
#:use-module (chickadee render texture)
#:use-module (chickadee render buffer)
- #:export (draw-sprite
+ #:export (draw-sprite*
+ draw-sprite
with-batched-sprites
+ draw-nine-patch*
draw-nine-patch))
(define default-shader
@@ -325,190 +327,107 @@ void main (void) {
(lambda ()
(set! *batch?* #f)))))
-(define texture-gl-size
- (@@ (chickadee render texture) texture-gl-size))
-(define texture-region-gl-size
- (@@ (chickadee render texture) texture-region-gl-size))
-(define texture-region-gl-rect
- (@@ (chickadee render texture) texture-region-gl-rect))
+(define* (draw-sprite* texture rect matrix #:key
+ (blend-mode 'alpha)
+ (texcoords (texture-gl-rect texture))
+ (shader (force default-shader)))
+ (if *batch?*
+ (draw-sprite-batched texture rect matrix blend-mode
+ shader texcoords)
+ (draw-sprite-unbatched texture rect matrix blend-mode
+ shader texcoords)))
-(define %default-texcoords (make-rect 0.0 0.0 1.0 1.0))
-(define %default-offset (vec2 0.0 0.0))
+(define %null-vec2 (vec2 0.0 0.0))
+(define %default-scale (vec2 1.0 1.0))
(define draw-sprite
- (let ((rect (make-rect 0.0 0.0 0.0 0.0))
- (tmp-matrix (make-null-matrix4))
- (%matrix (make-null-matrix4)))
+ (let ((matrix (make-null-matrix4)))
(lambda* (texture
- region
+ position
#:key
- (scale 1.0)
- (rotation 0)
- matrix
- (offset %default-offset)
+ (origin %null-vec2)
+ (scale %default-scale)
+ (rotation 0.0)
(blend-mode 'alpha)
- (texcoords
- (if (texture-region? texture)
- (texture-region-gl-rect texture)
- %default-texcoords))
+ (rect (texture-rect texture))
(shader (force default-shader)))
- "Draw TEXTURE over the area defined by the rect REGION. Instead
-of a rect, REGION may be a vec2 representing the position of the
-sprite, in which case the width and height of the sprite corresponds
-to the size of the texture. TEXTURE may be a texture or a texture
-region.
+ "Draw TEXTURE at POSITION.
+Optionally, other transformations may be applied to the sprite.
ROTATION specifies the angle to rotate the sprite, in radians. SCALE
-specifies the scaling factor. No scaling or rotation is applied by
-default. Alternatively, MATRIX may be specified, in which case
-ROTATION and SCALE are ignored and the given transformation matrix is
-used instead. All transformations are applied relative to the lower
-left corner of the sprite by default. This can be changed by
-specifying an OFFSET vector.
+specifies the scaling factor as a 2D vector. All transformations are
+applied relative to ORIGIN, a 2D vector.
+
+By default, alpha blending is used but can be changed by specifying
+BLEND-MODE.
-By default, alpha
-blending is used but can be changed by setting BLEND-MODE. Finally,
-advanced users may pass SHADER to change the way the sprite is
+Advanced users may pass SHADER to change the way the sprite is
rendered entirely."
- (let* ((size (if (texture-region? texture)
- (texture-region-gl-size texture)
- (texture-gl-size texture)))
- (texture (if (texture-region? texture)
- (texture-region-texture texture)
- texture))
- (matrix (cond
- (matrix matrix) ; user-specified matrix
- ((or rotation scale) ; compute matrix on-the-fly
- (matrix4-identity! %matrix)
- (unless (zero? rotation)
- (matrix4-rotate-z! tmp-matrix rotation)
- (matrix4-mult! %matrix %matrix tmp-matrix))
- (unless (= scale 1.0)
- (matrix4-scale! tmp-matrix scale)
- (matrix4-mult! %matrix %matrix tmp-matrix))
- (matrix4-translate! tmp-matrix region)
- (matrix4-mult! %matrix %matrix tmp-matrix)
- %matrix)
- ;; No transformation needed, in which case we
- ;; use no matrix at all in order to save cycles
- ;; and not waste time multiplying against the
- ;; identity matrix.
- (else #f))))
- (cond
- ((and (rect? region)
- (not matrix)
- (zero? rotation) ; no rotation
- (= scale 1.0)) ; no scale
- ;; We won't be using a transformation matrix.
- ;; Just apply the offset.
- (set-rect-x! rect (- (rect-x region) (vec2-x offset)))
- (set-rect-y! rect (- (rect-y region) (vec2-y offset)))
- (set-rect-width! rect (rect-width region))
- (set-rect-height! rect (rect-height region)))
- ((rect? region)
- ;; We will be using a transformation matrix, so
- ;; ignore the region's X and Y coordinates as
- ;; those will be accounted for in the
- ;; translation matrix.
- (set-rect-x! rect (- (vec2-x offset)))
- (set-rect-y! rect (- (vec2-y offset)))
- (set-rect-width! rect (rect-width region))
- (set-rect-height! rect (rect-height region)))
- ((and (not matrix)
- (zero? rotation)
- (= scale 1.0))
- ;; No region specified and no transformation
- ;; matrix. Use texture width/height for the
- ;; dimensions of the region.
- (set-rect-x! rect (- (vec2-x region) (vec2-x offset)))
- (set-rect-y! rect (- (vec2-y region) (vec2-y offset)))
- (set-rect-width! rect (f32vector-ref size 0))
- (set-rect-height! rect (f32vector-ref size 1)))
- (else
- ;; No region specified but we will be using a
- ;; transformation matrix.
- (set-rect-x! rect (- (vec2-x offset)))
- (set-rect-y! rect (- (vec2-y offset)))
- (set-rect-width! rect (f32vector-ref size 0))
- (set-rect-height! rect (f32vector-ref size 1))))
- (if *batch?*
- (draw-sprite-batched texture rect matrix blend-mode
- shader texcoords)
- (draw-sprite-unbatched texture rect matrix blend-mode
- shader texcoords))))))
+ (matrix4-2d-transform! matrix
+ #:origin origin
+ #:position position
+ #:rotation rotation
+ #:scale scale)
+ (draw-sprite* texture (texture-rect texture) matrix
+ #:blend-mode blend-mode
+ #:shader shader))))
;;;
;;; Nine Patches
;;;
-(define draw-nine-patch
- (let ((rect (make-rect 0.0 0.0 0.0 0.0))
- (trect (make-rect 0.0 0.0 0.0 0.0)))
- (lambda* (texture region #:key (margin 0)
- (top-margin margin) (bottom-margin margin)
- (left-margin margin) (right-margin margin)
- (offset %default-offset)
- (rotation 0)
- (scale 1.0)
- matrix
- (blend-mode 'alpha)
- (shader (force default-shader)))
- "Draw a \"nine patch\" sprite. A nine patch sprite renders
-TEXTURE as a WIDTH x HEIGHT rectangle whose stretchable areas are
-defined by the given margin measurements. The corners are never
-stretched, the left and right edges may be stretched vertically, the
-top and bottom edges may be stretched horizontally, and the center may
-be stretched in both directions. This rendering technique is
-particularly well suited for resizable windows and buttons in
-graphical user interfaces.
-
-MARGIN specifies the margin size for all sides of the nine patch. To
-make margins of differing sizes, the TOP-MARGIN, BOTTOM-MARGIN,
-LEFT-MARGIN, and RIGHT-MARGIN arguments may be used."
- (let* ((texcoords (if (texture-region? texture)
- (texture-region-gl-rect texture)
- %default-texcoords))
- (texsize (if (texture-region? texture)
- (texture-region-gl-size texture)
- (texture-gl-size texture)))
- (w (rect-width region))
- (h (rect-height region))
- (border-x1 (rect-left region))
- (border-y1 (rect-bottom region))
- (border-x2 (rect-right region))
- (border-y2 (rect-top region))
+(define draw-nine-patch*
+ (let ((%rect (make-rect 0.0 0.0 0.0 0.0))
+ (texcoords (make-rect 0.0 0.0 0.0 0.0)))
+ (lambda* (texture
+ rect
+ matrix
+ #:key
+ (margin 0.0)
+ (top-margin margin)
+ (bottom-margin margin)
+ (left-margin margin)
+ (right-margin margin)
+ (blend-mode 'alpha)
+ (shader (force default-shader)))
+ (let* ((x (rect-x rect))
+ (y (rect-y rect))
+ (w (rect-width rect))
+ (h (rect-height rect))
+ (border-x1 x)
+ (border-y1 y)
+ (border-x2 (+ x w))
+ (border-y2 (+ y h))
(fill-x1 (+ border-x1 left-margin))
(fill-y1 (+ border-y1 bottom-margin))
(fill-x2 (- border-x2 right-margin))
(fill-y2 (- border-y2 top-margin))
- (tw (f32vector-ref texsize 0))
- (th (f32vector-ref texsize 1))
- (border-s1 (rect-left texcoords))
- (border-t1 (rect-bottom texcoords))
- (border-s2 (rect-right texcoords))
- (border-t2 (rect-top texcoords))
+ (prect (texture-rect texture))
+ (trect (texture-gl-rect texture))
+ (tw (rect-width prect))
+ (th (rect-height prect))
+ (border-s1 (rect-left trect))
+ (border-t1 (rect-bottom trect))
+ (border-s2 (rect-right trect))
+ (border-t2 (rect-top trect))
(fill-s1 (+ border-s1 (/ left-margin tw)))
(fill-t1 (+ border-t1 (/ bottom-margin th)))
(fill-s2 (- border-s2 (/ right-margin tw)))
(fill-t2 (- border-t2 (/ top-margin th))))
(define (draw-piece x1 y1 x2 y2 s1 t1 s2 t2)
- (set-rect-x! rect x1)
- (set-rect-y! rect y1)
- (set-rect-width! rect (- x2 x1))
- (set-rect-height! rect (- y2 y1))
- (set-rect-x! trect s1)
- (set-rect-y! trect t1)
- (set-rect-width! trect (- s2 s1))
- (set-rect-height! trect (- t2 t1))
- (draw-sprite texture rect
- #:texcoords trect
- #:offset offset
- #:scale scale
- #:rotation rotation
- #:matrix matrix
- #:blend-mode blend-mode
- #:shader shader))
+ (set-rect-x! %rect x1)
+ (set-rect-y! %rect y1)
+ (set-rect-width! %rect (- x2 x1))
+ (set-rect-height! %rect (- y2 y1))
+ (set-rect-x! texcoords s1)
+ (set-rect-y! texcoords t1)
+ (set-rect-width! texcoords (- s2 s1))
+ (set-rect-height! texcoords (- t2 t1))
+ (draw-sprite* texture %rect matrix
+ #:texcoords texcoords
+ #:blend-mode blend-mode
+ #:shader shader))
(with-batched-sprites
;; bottom-left
(draw-piece border-x1 border-y1 fill-x1 fill-y1
@@ -516,7 +435,7 @@ LEFT-MARGIN, and RIGHT-MARGIN arguments may be used."
;; bottom-center
(draw-piece fill-x1 border-y1 fill-x2 fill-y1
fill-s1 border-t1 fill-s2 fill-t1)
- ;; dbottom-right
+ ;; bottom-right
(draw-piece fill-x2 border-y1 border-x2 fill-y1
fill-s2 border-t1 border-s2 fill-t1)
;; center-left
@@ -537,3 +456,49 @@ LEFT-MARGIN, and RIGHT-MARGIN arguments may be used."
;; top-right
(draw-piece fill-x2 fill-y2 border-x2 border-y2
fill-s2 fill-t2 border-s2 border-t2))))))
+
+(define draw-nine-patch
+ (let ((position (vec2 0.0 0.0))
+ (%rect (make-rect 0.0 0.0 0.0 0.0))
+ (matrix (make-null-matrix4)))
+ (lambda* (texture
+ rect
+ #:key
+ (margin 0.0)
+ (top-margin margin) (bottom-margin margin)
+ (left-margin margin) (right-margin margin)
+ (origin %null-vec2)
+ (rotation 0.0)
+ (scale %default-scale)
+ (blend-mode 'alpha)
+ (shader (force default-shader)))
+ "Draw a \"nine patch\" sprite. A nine patch sprite renders
+TEXTURE on the rectangular area RECT whose stretchable areas are
+defined by the given margin measurements. The corners are never
+stretched, the left and right edges may be stretched vertically, the
+top and bottom edges may be stretched horizontally, and the center may
+be stretched in both directions. This rendering technique is
+particularly well suited for resizable windows and buttons in
+graphical user interfaces.
+
+MARGIN specifies the margin size for all sides of the nine patch. To
+make margins of differing sizes, the TOP-MARGIN, BOTTOM-MARGIN,
+LEFT-MARGIN, and RIGHT-MARGIN arguments may be used."
+ (set-rect-x! %rect 0.0)
+ (set-rect-y! %rect 0.0)
+ (set-rect-width! %rect (rect-width rect))
+ (set-rect-height! %rect (rect-height rect))
+ (set-vec2-x! position (rect-x rect))
+ (set-vec2-y! position (rect-y rect))
+ (matrix4-2d-transform! matrix
+ #:origin origin
+ #:position position
+ #:rotation rotation
+ #:scale scale)
+ (draw-nine-patch* texture %rect matrix
+ #:top-margin top-margin
+ #:bottom-margin bottom-margin
+ #:left-margin left-margin
+ #:right-margin right-margin
+ #:blend-mode blend-mode
+ #:shader shader))))