Closed phmarek closed 8 years ago
If you're still interested in this feature, checkout feature/let-defsketch branch. The newest version of sdl2kit is needed for this to work, so get that as well.
There's only one binding form now; all window parameters are moved to the unified binding list and prefixed with sketch (sketch-width, sketch-title, etc.).
This makes it possible to do the following:
(defsketch foo
((x 2)
(sketch-width (* x 100))
(quux (- sketch-height (/ x 5))))
(rect 10 10 (* x 20) (* x 30))
Thanks, that sounds useful! Just as an idea - perhaps having something like this would be better?
(defsketch foo
((x 2)
((width sketch) (* x 100))
(quux (- sketch-height (/ x 5))))
(rect 10 10 (* x 20) (* x 30))
Reads a bit differently (reminds of accessors), but might be more expandable (and easier to deconstruct)?
That does look like a valid option in general, but I'm not sure how would people new to Common Lisp react to that - and I want them to be able to use Sketch too. I'm even thinking about removing the SKETCH- prefix (it's ugly, and the only reason for using it is for future proofing, so I don't break someone's code when I introduce FOO window option), and just documenting all special bindings/slots more thoroughly.
I'm also thinking about bringing back the window option plist, and expand its syntax for when you need to calculate any of those from initargs/other values. (Right, I haven't mentioned, initargs can override all of these).
This is how the updated plist might look like:
(defsketch foo (:title "Hello, World!" ; Same as before, would be referenced as TITLE
:width (w) ; No value yet (would default to 400 if needed), referenced as W
:height (h 200)) ; Default value is 200, referenced as H
((x 30)
(w (+ h (* x 3))))
(rect 100 100 x x))
Yeah, my (width foo)
(What I originally meant, not (width sketch)
!) was for futureproofing, too.
TBH, I wouldn't like to mix arbitrary variables with arbitrary class members - feels like an accident waiting to happen later on (especially with inheriting over several levels...).
"Action at a distance" is deprecated, right? ;)
well, how about exported but non-imported names?
(defsketch foo
((x 2)
(sketch:width (* x 100))
(quux (- sketch-height (/ x 5))))
(rect 10 10 (* x 20) (* x 30))
That reads much cleaner...
I think I finally got it. It ended up being the most similar to what you suggested.
(defsketch foo
((x 2)
(width (* x 100))
(height width))
(rect 0 0 (/ width 2) (/ height 2)))
(make-instance 'foo) ; 200x200 window and a 100x100 rect
(make-instance 'foo :width 300) ; 300x300 window and a 150x150 rect
(make-instance 'foo :width 200 :height 400) ; 200x400 window and a 100x200 rect
(make-instance 'foo :title "hello") ; 200x200 window with its title set to "hello", 100x100 rect
(make-instance 'foo :x 3 :height 100) ; 300x100 window and a 150x50 rect
If you have time, it would be great if you could help me test this by checking out the dev branch.
Current dev branch gives me compile warnings/errors:
DEFMETHOD INITIALIZE-INSTANCE :BEFORE (SKETCH)
...
; caught STYLE-WARNING:
; The variable INITARGS is defined but never used.
and
; caught ERROR:
; READ error during COMPILE-FILE:
;
; Symbol "LAST-WINDOW" not found in the KIT.SDL2 package.
;
; Line: 197, Column: 37, File-Position: 6756
;
; Stream: #<SB-INT:FORM-TRACKING-STREAM for file ... sketch.lisp>
Oh. Sorry about that. I fixed the first one, and pushed some changes I forgot about. Also, I didn't realize sdl2kit's LAST-WINDOW wasn't in QL yet, so just pull https://github.com/lispgames/sdl2kit to local-projects, pull the newest sketch changes, and everything should work correctly.
Thanks!
; file: /home/marek/.quicklisp/local-projects/sketch/src/font.lisp
; in: DEFUN SKETCH::MAKE-DEFAULT-FONT
; (SKETCH:MAKE-FONT :FACE
; (MAKE-INSTANCE 'SKETCH::TYPEFACE :FILENAME SKETCH::FILENAME :POINTER
; (SDL2-TTF:OPEN-FONT SKETCH::FILENAME 18))
; :COLOR SKETCH:+BLACK+ :SIZE 18)
;
; caught WARNING:
; undefined variable: SKETCH:+BLACK+
and some more.
After rewriting the DEFSKETCH form I now get these:
; caught STYLE-WARNING:
; The variable TITLE is defined but never used.
;
; caught STYLE-WARNING:
; The variable WIDTH is defined but never used.
;
; caught STYLE-WARNING:
; The variable HEIGHT is defined but never used.
;
; compilation unit finished
; caught 3 STYLE-WARNING conditions
But they're used - changing them changes the widget.
Great, thanks a lot!!
Just two more questions, please.
1) I guess that's bad in my design, but if I define height
and width
in these bindings, and then derive some other data from these - is there a simple way to keep the derivations up-to-date, even if I eg. resize the window?
Can I mark some bindings to make them automatically change themselves whenever necessary?
2) How do I get a list of "predefined" names, like width
, height
, title
? Can I DESCRIBE or INSPECT something?
1) Not yet via defsketch, but it's going to be possible in future. I started working on that in https://github.com/vydd/sketch/blob/dev/src/channels.lisp, but decided to make it more general and implement dataflow programming as a separate library. So, at some point you'll be able to pull up a window similar to this and thread your data wherever you want, or do the same thing from code. I will make the library MIT licensed.
Channels example:
(define-channel-observer (out :bar (* 2 (in :foo 3)))
(in :foo) ; ----> 3
(in :bar) ; ----> 6
(out :foo 5) ; ---> no value
(in :bar) ; ---> 10
(in :foo) ; ---> 5
2) Yeah, (mapcar #'car sketch::*default-slots*)
... maybe making that more public would be a good idea.
Hey,
I'm going to close this issue because I just merged these changes to master, so I think it's kinda confusing to leave it like this. If you have trouble using the new defsketch, or think I could enhance it more, please open a new issue.
Thanks!
I tried this:
but that fails with "unbound variable". Can/should that be similar to
LET*
, perhaps?