So picts can display inline in the REPL. How do I make an animation that displays inline in the REPL?
(or at least, in drracket’s REPL)
Plot does it.
oh right!
got any examples handy?
Not to hand sorry. I’m assuming a timer.
A snip% can be a canvas% I think, so using a thread an a timer you should be able to animate it
why does it being a canvas% matter? (I have very little experience with racket’s GUI framework)
Check out the animated canvas package on PLaneT
a canvas holds the dc
I just remembered the animated map snip made by @alexharsanyi I’ll see if I can find the link to his blog
As @spdegabrielle says, the canvas holds a dc%, which is what you need to draw, and you can also ask the canvas to refresh, which is what you need to animate.
@laurent.orseau so this is as far as I’ve gotten: (define animation-snip%
(class
how do I make it both a snip%
and a canvas%
?
Hmm, I think you need to implement a new snip% instead, not a canvas% directly. I see Alex is typing, so he’ll be able to help more :slightly_smiling_face:
@notjack you only need to make it a snip%
, but than you’ll need to define a snip-class%
as well and there are a few more steps required: the snip will need to have a get-extent
and a draw
method defined, as well a copy
method if it needs to be displayed in the DrRacket REPL (because the REPL creates copies of all snips).
currently I’m starting from the pict-snip
code: https://github.com/racket/pict-snip/
that’s a canvas-snip%
the beginning of the blog post shows how to create a snip%, for DrRacket REPL use, you’ll need to add a copy
method to it.
and also note that DrRacket REPL will display a copy of the snip (good to know if you plan to interact with it from the GUI)
I don’t plan to interact with it from the GUI, but I do want it to automatically play the animation
more specifically: I have a list of picts, and I want to have them play one after the other with a second or so delay between picts. I’m currently using slideshow/play
to get it to play in a slideshow, but I’m only using that because it was easy. I’d really like something in the REPL.
ah, but you want a snip-canvas% instead, because the canvas-snip is a canvas with a single snip, so you still need a frame%
so just something like (animate-these-picts-please frame-picts #:framerate 2)
that turned into a movie playing in the repl at a rate of 2 FPS would be perfect
@alexharsanyi going through your chess snips post now, thank you so much for writing that
yup
I am not aware of any libraries which let you do this in the REPL, but it should not be too complex to write such a function by creating an animation-pict%
object with a list of picts
I’ve tried this before and the wall I hit was the animation part
I guess you should follow this: https://docs.racket-lang.org/gui/editor-overview.html?q=snip#%28part._snip-example%29
but it’s not straightforward though
@alexharsanyi Your whole series of blog posts on the GUI has been excellent.
Adapted from the docs.
in the interactions: (define sn (new circle-snip%))
sn
Then move the mouse over the snip, and draw is apparently called repeatedly. Looks slow but it’s a start
@notjack, here is a sample animation-snip% which cycles a list of picts: https://gist.github.com/alex-hhh/d6bdc9f9b671876d6726396e3c7b05c9
thanks
it occurs to me that is it is 1:20 am for @notjack
yes, I made poor choices tonight
Why is there an (make-object ...)
around the class
form? (define animation-snip-class
(make-object
(class snip-class% (super-new)
(send this set-classname "animation-snip-class"))))
you only need a single instance of the snip class. So I create an anonymous class derived from snip-class%
than create an object from that class and assign it to animation-snip-class
.
it’s a singleton object
I think there’s a util package somewhere that adds an object
form so you can do (object snip-class% (super-new) …)
that ought to be in the racket/class
library IMO
Well, I see that removing it leads to an error. But … The documentation says: > (send a-snip set-snipclass class) → void? > class : (is-a?/c snip-class%) And is-a?/c
can handle a class. > (is-a?/c type) → flat-contract? > type : (or/c class? interface?)
I think is-a/c?
takes a class and produces a contract that accepts an object of that class
so (is-a?/c snip-class%)
means “any snip-class% object”
You are right: > Accepts a class or interface and returns a flat contract that recognizes objects that instantiate the class/interface.
so the shorthand class
ought to be class-object
?
maybe? not sure
it gets all confusing because classes are first class values, but also not all values are objects
I am just speculating, but I think the snip hierarchy reuses the term “class” for something different than racket/class
so set-snip-class
assigns a “snip class” to a snip
that too
Maybe it accepted both before contracts were introduced?
The purpose of the snip class is to hold the “read” method for deserializing snips — it has no purpose in the example I shown, but snips without a snip class cannot be added to an editor, so it is required.
@alexharsanyi May I use that animation code you wrote in a library I’m writing under the apache 2 license? Will include a link to the gist in the source.
Yes, no problem
Thanks! If you want to see how I’m using it: https://github.com/jackfirth/planning/commit/e95c4dfa1867cbdd67088343dfe1f15a78236745
now, challenge mode: can I turn it into a gif or some other file I can copy-paste into a slack channel…
@notjack Here is an example of making a gif: https://github.com/soegaard/soegaard.github.io/blob/master/_src/posts/2013-06-21-running-man.scrbl#L90 It’s the source of this blog post: http://soegaard.github.io/blog/2013/06/21/running-man/
closest I can get so far is a few pictures of my planner solving a block-pushing puzzle:
@soegaard2 any ideas on how to get that to happen automatically when I select the animation snip and ctrl-C it?
The animation-snip needs to generate the gif and then put it on the paste board.
There must be a method that can be overriden to change the behaviour of “copy”.
ah well, future work
Giving my laptop fan a good run though
the gui doesn’t support gif, or at least on MacOs, copying gifs to the pasteboard, though images on the pasteboard can go into gui.
To add gifs to the macos pasteboard to require sending multiple representations so receiving applications can find an interpretation they can use. I presume it is much the same on linux and windows. I think the code is mostly in pasteboard, though I’ve not worked out how the snipclass copy method calls it.
https://github.com/racket/gui/blob/master/gui-lib/mred/private/wx/cocoa/clipboard.rkt
https://github.com/racket/gui/blob/master/gui-lib/mred/private/wx/cocoa/image.rkt
Is there a way to detect if a file path is a part of Racket or a package?
E.g., given #<path:/Applications/Racket v7.7/collects/racket/require.rkt>
or #<path:/Applications/Racket v7.7/share/pkgs/r5rs-lib/r5rs/private/r5rs-trans.rkt>
, return #t
because it belongs to Racket/its standard distribution.
Given #<path:/Users/sorawee/git/rosette/rosette/base/struct/struct.rkt>
and a package name rosette
, return #t
too
OK, I think whereis
/find-system-path
is the answer. Let’s see…
There’s also path->pkg
.
Thanks!
Is my assumption correct that (build-path (find-system-path 'collects-dir) 'up "share" "pkgs")
will always link to the default pkgs
?
Alternatively, given a package name (output of path->pkg
), how do I check if it’s a part of the standard distribution?
No, it depends on the configuration. I think you’re looking for find-pkgs-dir
.
Do you mean whether it’s implied by dependencies from main-distribution
? I think you’d have to explore the dependency tree.
Thanks. This is exactly what I need