diff options
Diffstat (limited to 'chickadee/render/sprite.scm')
-rw-r--r-- | chickadee/render/sprite.scm | 285 |
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)))) |