vydd / sketch

A Common Lisp framework for the creation of electronic art, visual design, game prototyping, game making, computer graphics, exploration of human-computer interaction, and more.
MIT License
1.4k stars 67 forks source link

Evaluation order in DEFSKETCH #8

Closed phmarek closed 8 years ago

phmarek commented 8 years ago

I tried this:

(DEFSKETCH xxx (...)
    ((x-left 1.0d0)
     (x-right 1.0d0)
     (x-step (/ (- x-right x-left) width))
...))

but that fails with "unbound variable". Can/should that be similar to LET*, perhaps?

vydd commented 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))
phmarek commented 8 years ago

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)?

vydd commented 8 years ago

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))
phmarek commented 8 years ago

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...

vydd commented 8 years ago

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.

phmarek commented 8 years ago

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>
vydd commented 8 years ago

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!

phmarek commented 8 years ago
; 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?

vydd commented 8 years ago

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.

vydd commented 8 years ago

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!