From aa5db23747bdf948066ea08be7e46cbbb1875d15 Mon Sep 17 00:00:00 2001 From: David Thompson Date: Thu, 12 Jan 2017 19:19:05 -0500 Subject: render: sprite: Add "nine patch" renderer. --- chickadee/render/sprite.scm | 100 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 96 insertions(+), 4 deletions(-) diff --git a/chickadee/render/sprite.scm b/chickadee/render/sprite.scm index 7e87494..f85ae93 100644 --- a/chickadee/render/sprite.scm +++ b/chickadee/render/sprite.scm @@ -27,7 +27,8 @@ #:use-module (chickadee render texture) #:use-module (chickadee render vertex-buffer) #:export (draw-sprite - with-batched-sprites)) + with-batched-sprites + draw-nine-patch)) (define default-shader (delay @@ -275,9 +276,10 @@ void main (void) { (lambda () (set! *batch?* #f))))) +(define %default-texture-rect (make-rect 0.0 0.0 1.0 1.0)) + (define draw-sprite - (let ((rect (make-rect 0.0 0.0 0.0 0.0)) - (default-texture-rect (make-rect 0.0 0.0 1.0 1.0))) + (let ((rect (make-rect 0.0 0.0 0.0 0.0))) (lambda* (texture dimensions #:key scale rotation (blend-mode 'alpha) texture-rect @@ -289,7 +291,7 @@ void main (void) { (set-rect-height! rect (texture-height texture)) rect) dimensions)) - (texture-rect (or texture-rect default-texture-rect))) + (texture-rect (or texture-rect %default-texture-rect))) (if *batch?* (draw-sprite-batched texture dimensions scale rotation blend-mode shader @@ -297,3 +299,93 @@ void main (void) { (draw-sprite-unbatched texture dimensions scale rotation blend-mode shader texture-rect)))))) + + +;;; +;;; 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 dimensions #:key (margin 0) + (top-margin margin) (bottom-margin margin) + (left-margin margin) (right-margin margin) + (texture-rect %default-texture-rect) + scale rotation (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* ((w (rect-width dimensions)) + (h (rect-height dimensions)) + (border-x1 (rect-left dimensions)) + (border-y1 (rect-bottom dimensions)) + (border-x2 (rect-right dimensions)) + (border-y2 (rect-top dimensions)) + (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 (texture-width texture)) + (th (texture-width texture)) + (border-s1 (rect-left texture-rect)) + (border-t1 (rect-bottom texture-rect)) + (border-s2 (rect-right texture-rect)) + (border-t2 (rect-top texture-rect)) + (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 + #:texture-rect trect + #:scale scale + #:rotation rotation + #:blend-mode blend-mode + #:shader shader)) + (with-batched-sprites + ;; bottom-left + (draw-piece border-x1 border-y1 fill-x1 fill-y1 + border-s1 border-t1 fill-s1 fill-t1) + ;; bottom-center + (draw-piece fill-x1 border-y1 fill-x2 fill-y1 + fill-s1 border-t1 fill-s2 fill-t1) + ;; dbottom-right + (draw-piece fill-x2 border-y1 border-x2 fill-y1 + fill-s2 border-t1 border-s2 fill-t1) + ;; center-left + (draw-piece border-x1 fill-y1 fill-x1 fill-y2 + border-s1 fill-t1 fill-s1 fill-t2) + ;; center + (draw-piece fill-x1 fill-y1 fill-x2 fill-y2 + fill-s1 fill-t1 fill-s2 fill-t2) + ;; center-right + (draw-piece fill-x2 fill-y1 border-x2 fill-y2 + fill-s2 fill-t1 border-s2 fill-t2) + ;; top-left + (draw-piece border-x1 fill-y2 fill-x1 border-y2 + border-s1 fill-t2 fill-s1 border-t2) + ;; top-center + (draw-piece fill-x1 fill-y2 fill-x2 border-y2 + fill-s1 fill-t2 fill-s2 border-t2) + ;; top-right + (draw-piece fill-x2 fill-y2 border-x2 border-y2 + fill-s2 fill-t2 border-s2 border-t2)))))) -- cgit v1.2.3