-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Animations #1173
Comments
Thanks for writing this up. I do feel pretty strongly that leaving Primer as a pure language and writing interpreters in frontends is probably the best approach of the ideas discussed thus far. The only drawback is that we'd likely need to implement those interpreters in TypeScript, but on the other hand, that probably makes sense anyway, as there are many amazing libraries for writing animations, games, etc. in the JavaScript/web ecosystem. |
I just found out about this project, which may provide some inspiration: |
In #1164 we add proof-of-concept support for creating animations with Primer. We have a new ADT,
Picture
, representing 2D images, and a primitive functionanimate : Integer → (Integer → Picture) → Animation
, whereAnimation
is a new primitive type. The arguments are a duration, in seconds, and a description of how to render each frame. This is inspired by the API of pure functional animation libraries such as Haskell's Gloss.This issue outlines the work that remains. Some of these points will be expanding in to their own issues in due course.
(I've folded in one or two important points from @brprice's notes on this topic, but there's more there on inspirations, alternative APIs and example animations we'd like to support)
Implementation
The one major current limitation is around the kinds of functions which we can pass as the second argument to
animate
without the evaluator getting stuck. This is explained further in #1169.We implement
Animation
internally as a base-64 encoding of a GIF, for ease of use by clients. The conversion fromList Picture
to GIF is implemented via thediagrams
library with theRasterific
backend. This is probably not what we want to use beyond the prototyping stage:diagrams
manual actually warns against using the library for real-time processing for performance reasons.diagrams
to generate one frame at a time, performance is likely to become even more of a concern with the need for constant back-and-forth between client and server, though this part would be mitigated by compiling the Haskell code to WASM, as we intend to eventually for other parts of the library (Compileprimer
to a Wasm target #1104).We may well be better off leaving interpretation up to clients, e.g. implement a renderer in JS for
primer-app
. This slightly contradicts our "dumb frontend" philosophy, but it shouldn't be too bad, since mapping from Primer'sPicture
ADT to SVG is very straightforward in principle.Some more minor issues have been left out of the initial PR due its proof-of-concept nature (and particularly the hope that we might ditch the new primitives completely in favour of the projections-based approach discussed below):
Animation
to the Hedgehog generators, i.e.genPrimCon
in bothRaw
andTyped
modules.Picture
is in thePrimitives
module despite being a non-primitive type. This is because theanimate
primitive function needsPicture
, which in turn depends on the primitive typeInt
.Builtins
andPrelude
#766).diagrams
is quite a heavy dependency. Though this could be difficult, since our primitives aren't really extensible.fromInteger
conversions going on inexprToDiagram
due todiagrams
' use ofDouble
. Ultimately we'll want to use floats, as discussed below.Student-facing API
Animation
type is currently unique in that we can't directly construct it. It only appears as an output of a function. This works fine, but we should at least consider disabling pattern matching for it (currently we insert a wildcard pattern and don't allow any others).Picture
type doesn't have all the flexibility students are likely to want:red
,width
,radius
.Compound
) could have friendlier names.Colour
a separate type might be easier to work with.Polygon : [(Int, Int)] -> Picture
Rectangle
,Triangle
etc. could be implemented in terms of this.RegularPolygon : Int -> Picture
Sprite
? This would probably have to be a primitive with it's own logic for editing.(Number -> Number) -> Opts -> Picture
.diagrams
makes it very easy, in order to keep the API simple.beside
(fromdiagrams
) for easier composition. While we're usingdiagrams
ourselves, this would be trivial to implement as a constructor ofPicture
. But implementing it as a Primer function would allow students to see how it works.play
function, rather than justanimate
.play
(or even the intermediatesimulate
) would be a polymorphic primitive (in theworld
/state
type), which is something which may take a little work to support, since we had previously assumed we'd never want such a thing. See source comment "Since no primitive functions are polymorphic [...]".Alternative approach via projections
After the initial work on #1164 was completed, we discussed the possibility of dropping the primitive
Animation
type in favour of a projections system, which we have long wanted anyway for lists and text. Our output would then just be an alternative view ofList Picture
. It would also be useful to be able to project a singlePicture
as a static output.This feels more principled than the current, rather ad-hoc approach where we have a primitive type with no support for directly creating it (i.e. it only appears as the result of a primitive function), and special support for displaying it (whereas every other type at least looks like a normal tree node).
The fact that we'd require no primitive function or type at all to support animations would also actually solve several implementation issues, particularly #1169.
A few open questions:
play
primitive?The text was updated successfully, but these errors were encountered: