gif macro and every/when syntax

This commit is contained in:
Thomas Breloff 2016-02-16 18:02:04 -05:00
parent 92c9e82dee
commit b8d136588c
2 changed files with 67 additions and 16 deletions

View File

@ -116,6 +116,7 @@ export
frame, frame,
gif, gif,
@animate, @animate,
@gif,
# recipes # recipes
PlotRecipe, PlotRecipe,

View File

@ -55,6 +55,69 @@ end
# ----------------------------------------------- # -----------------------------------------------
function _animate(forloop::Expr, args...; callgif = false)
if forloop.head != :for
error("@animate macro expects a for-block. got: $(forloop.head)")
end
# add the call to frame to the end of each iteration
animsym = gensym("anim")
countersym = gensym("counter")
block = forloop.args[2]
# create filter
n = length(args)
filterexpr = if n == 0
# no filter... every iteration gets a frame
true
elseif args[1] == :every
# filter every `freq` frames (starting with the first frame)
@assert n == 2
freq = args[2]
@assert isa(freq, Integer) && freq > 0
:(mod1($countersym, $freq) == 1)
elseif args[1] == :when
# filter on custom expression
@assert n == 2
args[2]
else
error("Unsupported animate filter: $args")
end
push!(block.args, :(if $filterexpr; frame($animsym); end))
push!(block.args, :($countersym += 1))
# add a final call to `gif(anim)`?
retval = callgif ? :(gif($animsym)) : animsym
# full expression:
esc(quote
$animsym = Animation() # init animation object
$countersym = 1 # init iteration counter
$forloop # for loop, saving a frame after each iteration
$retval # return the animation object, or the gif
end)
end
"""
Builds an `Animation` using one frame per loop iteration, then create an animated GIF.
Example:
```
p = plot(1)
@gif for x=0:0.1:5
push!(p, 1, sin(x))
end
```
"""
macro gif(forloop::Expr, args...)
_animate(forloop, args...; callgif = true)
end
""" """
Collect one frame per for-block iteration and return an `Animation` object. Collect one frame per for-block iteration and return an `Animation` object.
@ -65,22 +128,9 @@ Example:
anim = @animate for x=0:0.1:5 anim = @animate for x=0:0.1:5
push!(p, 1, sin(x)) push!(p, 1, sin(x))
end end
gif(anim)
``` ```
""" """
macro animate(forloop::Expr) macro animate(forloop::Expr, args...)
if forloop.head != :for _animate(forloop, args...)
error("@animate macro expects a for-block. got: $(forloop.head)")
end
# add the call to frame to the end of each iteration
animsym = gensym("anim")
block = forloop.args[2]
push!(block.args, :(frame($animsym)))
# full expression:
esc(quote
$animsym = Animation() # init animation object
$forloop # for loop, saving a frame after each iteration
$animsym # return the animation object
end)
end end