Skip to content

Commit

Permalink
Drop Cassette.jl by rewriting animation handlers
Browse files Browse the repository at this point in the history
  • Loading branch information
rdeits committed Nov 4, 2024
1 parent bb20d4d commit 7a53a95
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 65 deletions.
2 changes: 0 additions & 2 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ version = "0.16.3"

[deps]
Base64 = "2a0f44e3-6c83-55bd-87e4-b1978d98bd5f"
Cassette = "7057c7e9-c182-5462-911a-8362d720325c"
Colors = "5ae59095-9a9b-59fe-a467-6f913c188581"
CoordinateTransformations = "150eb455-5306-5404-9cee-2592286d6298"
DocStringExtensions = "ffbed154-4ef7-542d-bbb7-c09d3a79fcae"
Expand All @@ -26,7 +25,6 @@ Tar = "a4e569a6-e804-4fa4-b0f3-eef7a1d5b13e"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[compat]
Cassette = "0.2.5, 0.3"
Colors = "0.9, 0.10, 0.11, 0.12"
CoordinateTransformations = "0.5, 0.6"
DocStringExtensions = "0.5, 0.6, 0.7, 0.8, 0.9"
Expand Down
8 changes: 4 additions & 4 deletions notebooks/animation.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@
"metadata": {},
"outputs": [],
"source": [
"anim = Animation()\n",
"anim = Animation(vis)\n",
"\n",
"atframe(anim, 0) do\n",
" # within the context of atframe, calls to \n",
Expand Down Expand Up @@ -153,7 +153,7 @@
"metadata": {},
"outputs": [],
"source": [
"anim = Animation()\n",
"anim = Animation(vis)\n",
"\n",
"atframe(anim, 0) do\n",
" settransform!(vis[\"/Cameras/default\"], Translation(0, 0, 0))\n",
Expand All @@ -179,7 +179,7 @@
"metadata": {},
"outputs": [],
"source": [
"anim = Animation()\n",
"anim = Animation(vis)\n",
"\n",
"atframe(anim, 0) do\n",
" setprop!(vis[\"/Cameras/default/rotated/<object>\"], \"zoom\", 1.0)\n",
Expand Down Expand Up @@ -226,7 +226,7 @@
"metadata": {},
"outputs": [],
"source": [
"anim = Animation()\n",
"anim = Animation(vis)\n",
"atframe(anim, 0) do\n",
" setvisible!(vis[:sphere], false)\n",
" settransform!(vis[:box1], Translation(0.0, 0, 0))\n",
Expand Down
30 changes: 29 additions & 1 deletion src/MeshCat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ using Sockets: listen, @ip_str, IPAddr, IPv4, IPv6
using Base64: base64encode
using MsgPack: MsgPack, pack
using Pkg.Artifacts: @artifact_str
import Cassette
import FFMPEG
import HTTP
import Logging
Expand Down Expand Up @@ -102,6 +101,35 @@ abstract type AbstractMaterial end
include("util.jl")
include("trees.jl")
using .SceneTrees

struct AnimationContext
animation
frame::Int
end

"""
Low-level type which manages the actual meshcat server. See [`Visualizer`](@ref)
for the public-facing interface.
"""
mutable struct CoreVisualizer
tree::SceneNode
connections::Set{HTTP.WebSockets.WebSocket}
host::IPAddr
port::Int
server::HTTP.Server
animation_contexts::Vector{AnimationContext}

function CoreVisualizer(host::IPAddr = ip"127.0.0.1", default_port=8700)
connections = Set([])
tree = SceneNode()
port = find_open_port(host, default_port, 500)
core = new(tree, connections, host, port)
core.server = start_server(core)
core.animation_contexts = AnimationContext[]
return core
end
end

include("mesh_files.jl")
include("geometry.jl")
include("objects.jl")
Expand Down
21 changes: 12 additions & 9 deletions src/animations.jl
Original file line number Diff line number Diff line change
Expand Up @@ -46,17 +46,19 @@ function Base.merge!(a::AnimationClip, others::AnimationClip...)
end

struct Animation
clips::Dict{Path, AnimationClip}
visualizer::CoreVisualizer
default_framerate::Int
end
clips::Dict{Path, AnimationClip}

"""
Create a new animation. See [`atframe`](@ref) to adjust object poses or properties
in that animation.
"""
Create a new animation. See [`atframe`](@ref) to adjust object poses or properties
in that animation.
$(TYPEDSIGNATURES)
"""
Animation(visualizer::CoreVisualizer; fps=30) = new(visualizer, fps, Dict())
end

$(TYPEDSIGNATURES)
"""
Animation(fps::Int=30) = Animation(Dict{Path, AnimationClip}(), fps)

"""
Merge multiple animations, storing the result in `a`.
Expand All @@ -65,6 +67,7 @@ $(TYPEDSIGNATURES)
"""
function Base.merge!(a::Animation, others::Animation...)
for other in others
@assert a.visualizer === other.visualizer
@assert a.default_framerate == other.default_framerate
merge!(merge!, a.clips, other.clips) # merge clips recursively
end
Expand All @@ -80,7 +83,7 @@ The animations may involve the same properties or different properties
(animations of the same property on the same path will have their events
interleaved). All animations must have the same framerate.
"""
Base.merge(a::Animation, others::Animation...) = merge!(Animation(a.default_framerate), a, others...)
Base.merge(a::Animation, others::Animation...) = merge!(Animation(a.visualizer; fps=a.default_framerate), a, others...)

"""
Convert the `.tar` file of still images produced by the meshcat "record" feature
Expand Down
31 changes: 7 additions & 24 deletions src/atframe.jl
Original file line number Diff line number Diff line change
Expand Up @@ -47,28 +47,6 @@ end

js_position(t::Transformation) = convert(Vector, t(SVector(0., 0, 0)))

Cassette.@context AnimationCtx

function Cassette.overdub(ctx::AnimationCtx, ::typeof(settransform!), vis::Visualizer, tform::Transformation)
animation, frame = ctx.metadata
clip = getclip!(animation, vis.path)
_setprop!(clip, frame, "scale", "vector3", js_scaling(tform))
_setprop!(clip, frame, "position", "vector3", js_position(tform))
_setprop!(clip, frame, "quaternion", "quaternion", js_quaternion(tform))
end

function Cassette.overdub(ctx::AnimationCtx, ::typeof(setprop!), vis::Visualizer, prop::AbstractString, value)
animation, frame = ctx.metadata
clip = getclip!(animation, vis.path)
_setprop!(clip, frame, prop, get_property_type(prop), value)
end

function Cassette.overdub(ctx::AnimationCtx, ::typeof(setprop!), vis::Visualizer, prop::AbstractString, jstype::AbstractString, value)
animation, frame = ctx.metadata
clip = getclip!(animation, vis.path)
_setprop!(clip, frame, prop, jstype, value)
end

"""
Call the given function `f`, but intercept any `settransform!` or `setprop!` calls
and apply them to the given animation at the given frame instead.
Expand All @@ -81,7 +59,7 @@ Usage:
vis = Visualizer()
setobject!(vis[:cube], Rect(Vec(0.0, 0.0, 0.0), Vec(0.5, 0.5, 0.5)))
anim = Animation()
anim = Animation(vis)
# At frame 0, set the cube's position to be the origin
atframe(anim, 0) do
Expand All @@ -97,6 +75,11 @@ setanimation!(vis, anim)
```
"""
function atframe(f, animation::Animation, frame::Integer)
Cassette.overdub(AnimationCtx(metadata=(animation, frame)), f)
push!(animation.visualizer.animation_contexts, AnimationContext(animation, frame))
try
f()
finally
pop!(animation.visualizer.animation_contexts)
end
return animation
end
57 changes: 34 additions & 23 deletions src/visualizer.jl
Original file line number Diff line number Diff line change
@@ -1,24 +1,3 @@
"""
Low-level type which manages the actual meshcat server. See [`Visualizer`](@ref)
for the public-facing interface.
"""
mutable struct CoreVisualizer
tree::SceneNode
connections::Set{HTTP.WebSockets.WebSocket}
host::IPAddr
port::Int
server::HTTP.Server

function CoreVisualizer(host::IPAddr = ip"127.0.0.1", default_port=8700)
connections = Set([])
tree = SceneNode()
port = find_open_port(host, default_port, 500)
core = new(tree, connections, host, port)
core.server = start_server(core)
return core
end
end

function find_open_port(host, default_port, max_retries)
for port in default_port:(default_port + max_retries)
server = try
Expand Down Expand Up @@ -217,7 +196,15 @@ of its parents, so setting the transform of `vis[:group1]` affects the poses of
the objects at `vis[:group1][:box1]` and `vis[:group1][:box2]`.
"""
function settransform!(vis::Visualizer, tform::Transformation)
send(vis.core, SetTransform(tform, vis.path))
if !isempty(vis.core.animation_contexts)
ctx = last(vis.core.animation_contexts)
clip = getclip!(ctx.animation, vis.path)
_setprop!(clip, ctx.frame, "scale", "vector3", js_scaling(tform))
_setprop!(clip, ctx.frame, "position", "vector3", js_position(tform))
_setprop!(clip, ctx.frame, "quaternion", "quaternion", js_quaternion(tform))
else
send(vis.core, SetTransform(tform, vis.path))
end
vis
end

Expand All @@ -240,7 +227,29 @@ $(TYPEDSIGNATURES)
with the Base.setproperty! function introduced in Julia v0.7)
"""
function setprop!(vis::Visualizer, property::AbstractString, value)
send(vis.core, SetProperty(vis.path, property, value))
if !isempty(vis.core.animation_contexts)
ctx = last(vis.core.animation_contexts)
clip = getclip!(ctx.animation, vis.path)
_setprop!(clip, ctx.frame, property, get_property_type(property), value)
else
send(vis.core, SetProperty(vis.path, property, value))
end
vis
end

"""
Variation of `setprop!` which accepts an explicit type for the underlying JS property. This property type is only used within an animation context.
$(TYPEDSIGNATURES)
"""
function setprop!(vis::Visualizer, property::AbstractString, jstype::AbstractString, value)
if !isempty(vis.core.animation_contexts)
ctx = last(vis.core.animation_contexts)
clip = getclip!(ctx.animation, vis.path)
_setprop!(clip, ctx.frame, property, jstype, value)
else
send(vis.core, SetProperty(vis.path, property, value))
end
vis
end

Expand Down Expand Up @@ -275,3 +284,5 @@ For example, if you have `vis::Visualizer` with path `/meshcat/foo`, you can do
"""
Base.getindex(vis::Visualizer, path...) =
Visualizer(vis.core, joinpath(vis.path, path...))

Animation(vis::Visualizer, args...; kw...) = Animation(vis.core, args...; kw...)
4 changes: 2 additions & 2 deletions test/visualizer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -236,15 +236,15 @@ end
end

@testset "Animation" begin
anim1 = Animation()
anim1 = Animation(vis)
atframe(anim1, 0) do
settransform!(vis[:shapes][:box], Translation(0., 0, 0))
end
atframe(anim1, 30) do
settransform!(vis[:shapes][:box], Translation(2., 0, 0) LinearMap(RotZ/2)))
end
setanimation!(vis, anim1)
anim2 = Animation()
anim2 = Animation(vis)
atframe(anim2, 0) do
setprop!(vis["/Cameras/default/rotated/<object>"], "zoom", 1)
end
Expand Down

0 comments on commit 7a53a95

Please sign in to comment.