Skip to content

Commit

Permalink
Add dev mode for faster animation
Browse files Browse the repository at this point in the history
  • Loading branch information
codejaeger committed Mar 26, 2021
1 parent af4f664 commit b933f60
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 10 deletions.
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@ Manifest.toml
.vscode/
test.png
test/current/
.commit
.commit
.dev
30 changes: 26 additions & 4 deletions src/Javis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ end
pathname="javis_GIBBERISH.gif",
tempdirectory="",
liveview=false,
ffmpeg_loglevel="panic"
ffmpeg_loglevel="panic",
compute_frames = :all
)
Renders all previously defined [`Object`](@ref) drawings to the user-defined `Video` as a gif or mp4.
Expand All @@ -184,6 +185,8 @@ Renders all previously defined [`Object`](@ref) drawings to the user-defined `Vi
- `ffmpeg_loglevel::String`:
- Can be used if there are errors with ffmpeg. Defaults to panic:
All other options are described here: https://ffmpeg.org/ffmpeg.html
- `compute_frames`: If specified to `:latest` and `dev_mode` is set for the current [`Video`](@ref),
then it reuses frames which do not have changed since last render. This speeds up the rendering time.
"""
function render(
video::Video;
Expand All @@ -192,6 +195,7 @@ function render(
liveview = false,
tempdirectory = "",
ffmpeg_loglevel = "panic",
compute_frames = :all,
)
objects = video.objects
frames = preprocess_frames!(objects)
Expand All @@ -217,10 +221,24 @@ function render(
end

filecounter = 1

dev_mode = get(CURRENT_VIDEO[1].defs, :dev_mode, false)
if dev_mode
last_frames = get(CURRENT_VIDEO[1].defs, :last_frames, frames)
tempdirectory = ".dev"
end

@showprogress 1 "Rendering frames..." for frame in frames
frame_image = convert.(RGB, get_javis_frame(video, objects, frame))
if !isempty(tempdirectory)
Images.save("$(tempdirectory)/$(lpad(filecounter, 10, "0")).png", frame_image)
if compute_frames == :latest && frame in last_frames
frame_image = Images.load("$(tempdirectory)/$(lpad(filecounter, 10, "0")).png")
else
frame_image = convert.(RGB, get_javis_frame(video, objects, frame))
if !isempty(tempdirectory)
Images.save(
"$(tempdirectory)/$(lpad(filecounter, 10, "0")).png",
frame_image,
)
end
end
if render_mp4
if frame == first(frames)
Expand Down Expand Up @@ -252,6 +270,10 @@ function render(
else
@error "Currently, only gif and mp4 creation is supported. Not a $ext."
end

if dev_mode
CURRENT_VIDEO[1].defs[:last_frames] = frames
end
return pathname
end

Expand Down
6 changes: 5 additions & 1 deletion src/structs/Object.jl
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,8 @@ function Object(frames, func::Function, start_pos::Union{Object,Point}; kwargs..
if isempty(CURRENT_VIDEO)
throw(ErrorException("A `Video` must be defined before an `Object`"))
end
CURRENT_VIDEO[1].defs[:last_frames] = frames

update_lastframes(frames)
opts = Dict(kwargs...)

if get(opts, :in_global_layer, false) && frames isa UnitRange
Expand Down Expand Up @@ -129,16 +130,19 @@ Here the scaling is applied to the rectangle for the first fifty frames.
- `action::Vector{<:AbstractAction}` - the actions applied to the objects
"""
function act!(object::AbstractObject, action::AbstractAction)
update_lastframes(action.frames.frames)
push!(object.actions, copy(action))
end

function act!(object::AbstractObject, actions::Vector{<:AbstractAction})
for action in actions
update_lastframes(action.frames.frames)
act!(object, action)
end
end

function act!(objects::Vector{<:AbstractObject}, action)
update_lastframes(action.frames.frames)
for object in objects
act!(object, action)
end
Expand Down
33 changes: 29 additions & 4 deletions src/structs/Video.jl
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,18 @@ const CURRENT_VIDEO = Array{Video,1}()


"""
Video(width, height)
Video(width, height; dev_mode = false)
Create a video with a certain `width` and `height` in pixel. The argument `dev_mode`
specifies whether to reuse frames during development specified by the `compute_frames`
paramter in render.
Create a video with a certain `width` and `height` in pixel.
This also sets `CURRENT_VIDEO`.
"""
function Video(width, height)
function Video(width, height; dev_mode = false)
# some luxor functions need a drawing ;)
Drawing()
video = Video(width, height, AbstractObject[], Int[], Dict{Symbol,Any}())
video = Video(width, height, AbstractObject[], Int[], Dict{Symbol,Any}(:dev_mode=>dev_mode))
if isempty(CURRENT_VIDEO)
push!(CURRENT_VIDEO, video)
else
Expand All @@ -45,3 +48,25 @@ function Video(width, height)
empty!(CURRENT_OBJECT)
return video
end

"""
update_lastframes(frames)
Updates the list of unchanged frames of the current video if `dev_mode` in [`Video`](@ref) is set.
# Warnings
Shows a warning if argument `frames` cannot be processed to update last frames. Possible
when frames passed is a [`RFrames`](@ref), which is fine since these will be newly added.
"""
function update_lastframes(frames::Any)
try
if typeof(frames) == UnitRange{Int64}
frames = Vector{Int}(frames)
end
if get(CURRENT_VIDEO[1].defs, :dev_mode, false)
CURRENT_VIDEO[1].defs[:last_frames] = setdiff(get(CURRENT_VIDEO[1].defs, :last_frames, Vector{Int}()), frames)
end
catch e
@warn "Argument `frames` with type $(typeof(frames)) passed to `update_lastframes` must have integer vector like type hence ignoring update."
end
end

0 comments on commit b933f60

Please sign in to comment.