From e232830057d7c15e51639dc496f575ec480e4d00 Mon Sep 17 00:00:00 2001 From: Kevin Galligan Date: Sat, 6 Apr 2024 18:09:23 +0100 Subject: [PATCH 1/2] First draft of supersketches. --- README.org | 2 +- t/supersketch.lisp | 81 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 t/supersketch.lisp diff --git a/README.org b/README.org index 0787b8e..07a340c 100644 --- a/README.org +++ b/README.org @@ -257,7 +257,7 @@ If you are used to working with colors in hex, like in CSS, you can use =(hex-to If you don't care about fiddling with the exact values, but still need different colors, you can use one of the following functions. ***** =(lerp-color (start-color end-color amount &key (mode :hsb)))= -Lerp is a shorthand for [[https://en.wikipedia.org/wiki/Linear_interpolation][linear interpolation]]. This function takes the starting color and the ending color, and returns the color between them, which is an =AMOUNT= away from the starting color. When =AMOUNT= equals zero, the returned color equals the starting color, and when =AMOUNT= equals one, the ending color is returned. Amounts between zero and one give colors that are "in-between". These colors are calculated according to the specified =MODE=, which is =:HSB= by default, meaning that the resulting color's hue is between the starting and ending hue, as is the case with its saturation and brightness. +Lerp is a shorthand for [[https://en.wikipedia.org/wiki/Linear_interpolation][linear interpolation]]. This function takes the starting color and the ending color, and returns the color between them, which is an =AMOUNT= away from the starting color. When =AMOUNT= equals zero, the returned color equals the starting color, and when =AMOUNT= equals one, the ending color is returned. Amounts between zero and one give colors that are "in-between". These colors are calculated according to the specified =MODE=, which is =:HSB= by default, meaning that the resulting color's hue is between the starting and ending hue, as is the case with its saturation and brightness. Any other keyword will result in RGB interpolation. #+BEGIN_SRC lisp (defsketch lerp-test ((title "lerp-color") (width 400) (height 100)) diff --git a/t/supersketch.lisp b/t/supersketch.lisp new file mode 100644 index 0000000..e10a91e --- /dev/null +++ b/t/supersketch.lisp @@ -0,0 +1,81 @@ +(defpackage :supersketch + (:use :cl) + (:local-nicknames (:s :sketch))) + +(in-package supersketch) + +(s:defsketch super1 + ((s:width 600) + (s:height 400) + (s:title "Supersketch 1 (shapes, colour, pens)")) + (s:background (s:gray 0.6)) + (s:rect 0 0 25 25) + (s:with-pen (s:make-pen :fill s:+red+ :stroke s:+blue+) + (s:circle 45 20 20)) + (s:with-pen (:weight 0 :fill (s:rgb 0 .8 .8)) + (s:ellipse 105 30 40 30)) + (s:with-pen (:weight 5 :stroke (s:hsb .1 .8 .6 .9)) + (s:line 145 25 180 25)) + (s:with-pen (:stroke (s:hash-color 10)) + (s:polyline 145 35 180 35 160 50)) + (s:with-pen (:fill (s:rgb-255 120 120 200)) + (s:polygon 185 20 250 25 200 50)) + (s:with-pen (:fill (s:hsb-360 300 50 80 200) :stroke (s:gray-255 20)) + (s:ngon 3 275 25 25 25)) + (s:with-pen (:fill (s:hex-to-color "#4bcdef")) + (s:ngon 4 325 25 25 25)) + (s:with-pen (:fill (s:lerp-color s:+red+ s:+blue+ .5)) + (s:ngon 5 375 25 25 25)) + (s:with-pen (:stroke (s:random-color)) + (s:bezier 0 75 25 100 50 60 125 75)) + (s:with-pen (s:make-pen :stroke s:+yellow+ :weight 4 :curve-steps 5) + (s:bezier 0 85 25 110 50 70 125 85)) + (s:with-pen (:fill (s:color-filter-grayscale s:+red+)) + (s:rect 0 150 20 40)) + (s:with-pen (:fill (s:color-filter-grayscale s:+indigo+ :average)) + (s:rect 20 150 20 40)) + (s:with-pen (:fill (s:color-filter-invert s:+red+)) + (s:rect 40 150 20 40)) + (s:with-pen (:fill (s:color-filter-rotate s:+red+)) + (s:rect 60 150 20 40)) + (s:with-pen (:fill (s:color-filter-hsb (s:hsb .5 .5 .5) + :hue .1 :saturation .1 :brightness .1)) + (s:rect 80 150 20 40))) + +(s:defsketch super2 + ((s:fullscreen t) + (s:title "Supersketch 2 (fullscreen)") + (s:circle (/ s:width 2) (/ s:height 2) 50) + (s:text "Circle should be in the middle." 0 0))) + +(s:defsketch super3 + ((s:resizable t) + (s:title "Supersketch 3 (resize, y-axis, text, close-on)") + (s:y-axis :up) + (s:close-on :space)) + (s:circle (/ s:width 2) (/ s:height 2) 50) + (s:text "Circle should stay in middle during window resize." 0 30) + (s:text "Exit with spacebar" 0 (/ s:height 2)) + (s:ngon 4 10 10 10 10) + (s:with-font (s:make-font :color s:+white+ :size 10) + (s:text "Square should be in bottom left." 0 (- s:height 20)))) + +(s:defsketch super4 + ((s:copy-pixels t) + (s:title "Supersketch 4 (copy-pixels)") + (i 0)) + ;; There should be 1 black circle (otherwise, first draw call has been + ;; overwritten somehow). + (s:with-pen (:fill (if (= 0 i) s:+black+ s:+white+)) + (s:circle (random s:width) (random s:height) 20)) + (incf i)) + +(defmethod s:setup ((instance super4) &key &allow-other-keys) + (s:background s:+blue+)) + +;; TODO (see readme): +;; - transforms +;; - text / font +;; - images +;; - input +;; - control flow From e0bc0a1681055eda616ab48a94d3fc8a251ba6ae Mon Sep 17 00:00:00 2001 From: Kevin Galligan Date: Sun, 7 Apr 2024 19:33:31 +0100 Subject: [PATCH 2/2] Cover remaining features. --- README.org | 2 +- t/sun.png | Bin 0 -> 16205 bytes t/super1.png | Bin 0 -> 3945 bytes t/supersketch.lisp | 97 +++++++++++++++++++++++++++++++++++++-------- 4 files changed, 82 insertions(+), 17 deletions(-) create mode 100644 t/sun.png create mode 100644 t/super1.png diff --git a/README.org b/README.org index 07a340c..3a59822 100644 --- a/README.org +++ b/README.org @@ -469,7 +469,7 @@ The font can be specified using =(make-font &key face color size line-height ali (text title 0 0 100))) #+END_SRC -=align= can be =:left=, =:centre= or =:right=, and determines whether the x & y coordinates correspond to the left end, centre, or right end of the text box. =line-height= determines the vertical space given to a line of text, scaled according to the font size, i.e. =:line-height 1= leaves just enough space so that the text on two lines won't overlap. +=align= can be =:left=, =:center= or =:right=, and determines whether the x & y coordinates correspond to the left end, centre, or right end of the text box. =line-height= determines the vertical space given to a line of text, scaled according to the font size, i.e. =:line-height 1= leaves just enough space so that the text on two lines won't overlap. *** Images First =(load-resource filename ...)= to load the image from a given file, then =(draw image &key x y width height)= to draw the image with its top-left corner at =(x, y)= and with the given =width= and =height=. If not provided, default =(x,y)= is =(0,0)= and =width= & =height= are taken from the image. diff --git a/t/sun.png b/t/sun.png new file mode 100644 index 0000000000000000000000000000000000000000..0ce408ca1fd9b95fa91bbbf0285516e116e94ea6 GIT binary patch literal 16205 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 literal 0 HcmV?d00001 diff --git a/t/super1.png b/t/super1.png new file mode 100644 index 0000000000000000000000000000000000000000..8bb00ed04a8207381702e7b27535523360b65673 GIT binary patch literal 3945 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 literal 0 HcmV?d00001 diff --git a/t/supersketch.lisp b/t/supersketch.lisp index e10a91e..72ed7cb 100644 --- a/t/supersketch.lisp +++ b/t/supersketch.lisp @@ -1,3 +1,6 @@ +(eval-when (:compile-toplevel :load-toplevel :execute) + (ql:quickload 'sketch)) + (defpackage :supersketch (:use :cl) (:local-nicknames (:s :sketch))) @@ -5,9 +8,10 @@ (in-package supersketch) (s:defsketch super1 - ((s:width 600) + ((s:width 400) (s:height 400) - (s:title "Supersketch 1 (shapes, colour, pens)")) + (s:title "Supersketch 1 (shapes, colour, pens, image)") + (pic (s:load-resource (s::relative-path "t/super1.png")))) (s:background (s:gray 0.6)) (s:rect 0 0 25 25) (s:with-pen (s:make-pen :fill s:+red+ :stroke s:+blue+) @@ -31,22 +35,46 @@ (s:with-pen (s:make-pen :stroke s:+yellow+ :weight 4 :curve-steps 5) (s:bezier 0 85 25 110 50 70 125 85)) (s:with-pen (:fill (s:color-filter-grayscale s:+red+)) - (s:rect 0 150 20 40)) + (s:rect 130 85 20 40)) (s:with-pen (:fill (s:color-filter-grayscale s:+indigo+ :average)) - (s:rect 20 150 20 40)) + (s:rect 150 85 20 40)) (s:with-pen (:fill (s:color-filter-invert s:+red+)) - (s:rect 40 150 20 40)) + (s:rect 170 85 20 40)) (s:with-pen (:fill (s:color-filter-rotate s:+red+)) - (s:rect 60 150 20 40)) + (s:rect 190 85 20 40)) (s:with-pen (:fill (s:color-filter-hsb (s:hsb .5 .5 .5) :hue .1 :saturation .1 :brightness .1)) - (s:rect 80 150 20 40))) + (s:rect 210 85 20 40)) + (let ((y (- (/ s:height 2) 20))) + (s:with-font (s:make-font :color s:+white+ + :size 10 + :line-height 1.2 + :align :center) + (s:text (format nil "Circle should be at center top of text box~%(Line 2) Image below should match (maybe system-dependent)") + (/ s:width 2) y)) + (s:circle (/ s:width 2) y 5) + (s:image pic 0 (+ y 60)))) (s:defsketch super2 ((s:fullscreen t) - (s:title "Supersketch 2 (fullscreen)") + (s:title "Supersketch 2 (fullscreen, image)") + (sun (s:load-resource (s::relative-path "t/sun.png"))) + (cx (/ s:width 2)) + (cy (/ s:height 2)) + (swidth (s:image-width sun)) + (sheight (s:image-height sun)) + (pics + (list (s:crop sun 0 0 (/ swidth 2) (/ sheight 2)) + (s:crop sun (/ swidth 2) 0 (/ swidth 2) (/ sheight 2)) + (s:crop sun 0 (/ swidth 2) (/ swidth 2) (/ sheight 2)) + (s:crop sun (/ swidth 2) (/ swidth 2) (/ swidth 2) (/ sheight 2)))) + (t0 0)) (s:circle (/ s:width 2) (/ s:height 2) 50) - (s:text "Circle should be in the middle." 0 0))) + (s:text "Circle should be in the middle Also testing image cropping." 0 0) + (loop for pic in pics + for (xmul ymul) in '((-1 -1) (1 -1) (-1 1) (1 1)) + do (s:image pic (+ cx (* xmul t0)) (+ cy (* ymul t0)))) + (setf t0 (mod (+ t0 .1) 40))) (s:defsketch super3 ((s:resizable t) @@ -55,7 +83,7 @@ (s:close-on :space)) (s:circle (/ s:width 2) (/ s:height 2) 50) (s:text "Circle should stay in middle during window resize." 0 30) - (s:text "Exit with spacebar" 0 (/ s:height 2)) + (s:text "Exit with spacebar." 0 (/ s:height 2)) (s:ngon 4 10 10 10 10) (s:with-font (s:make-font :color s:+white+ :size 10) (s:text "Square should be in bottom left." 0 (- s:height 20)))) @@ -73,9 +101,46 @@ (defmethod s:setup ((instance super4) &key &allow-other-keys) (s:background s:+blue+)) -;; TODO (see readme): -;; - transforms -;; - text / font -;; - images -;; - input -;; - control flow +(s:defsketch super5 + ((s:title "Supersketch 5 (transforms, control flow))")) + (s:with-font (s:make-font :size 14) + (s:text "Red squares should get bigger, white squares should rotate." + 0 50)) + (s:with-identity-matrix + (s:translate (/ s:width 2) (/ s:height 2)) + (s:with-pen (:weight 3 :stroke s:+white+) + (loop repeat 10 + do (progn + (s:ngon 4 0 0 50 50) + (s:rotate (/ 360 10)))))) + (s:with-pen (:fill s:+red+) + (dotimes (i 3) + (let ((sfactor (+ 1 (/ i 3)))) + (s:with-translate ((* i 50) 0) + (s:with-scale (sfactor sfactor) + (s:rect 0 0 25 25))))))) + +(s:defsketch super6 + ((s:title "Supersketch 6 (input, control flow, canvas)") + (s:copy-pixels t) + (cvs (let ((cvs (s:make-canvas 50 50))) + (loop repeat 100 + do (s:canvas-paint cvs s:+blue+ (random 50) (random 50))) + cvs)) + (coords nil)) + (s:with-font (s:make-font :color s:+white+) + (s:text "Press 'd' to add square." 0 0) + (s:text "Click to draw canvas somewhere." 0 50)) + (if coords + (when coords + (s:draw cvs :x (first coords) :y (second coords)) + (setf coords nil)) + (s:rect (random s:width) (random s:height) 20 20)) + (s:stop-loop)) + +(defmethod s:on-key ((instance super6) (key (eql :d)) (state (eql :up))) + (s:start-loop)) + +(defmethod s:on-click ((instance super6) x y) + (setf (super6-coords instance) (list x y)) + (s:start-loop))