Skip to content

Commit ee42997

Browse files
authored
Merge pull request #257 from rdeits/rd/drop-cassette
Drop Cassette.jl by rewriting animation handlers
2 parents f9a66eb + 69def60 commit ee42997

File tree

7 files changed

+89
-66
lines changed

7 files changed

+89
-66
lines changed

Project.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
name = "MeshCat"
22
uuid = "283c5d60-a78f-5afe-a0af-af636b173e11"
33
authors = ["Robin Deits <[email protected]>"]
4-
version = "0.16.3"
4+
version = "1.0.0"
55

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

2827
[compat]
29-
Cassette = "0.2.5, 0.3"
3028
Colors = "0.9, 0.10, 0.11, 0.12, 0.13"
3129
CoordinateTransformations = "0.5, 0.6"
3230
DocStringExtensions = "0.5, 0.6, 0.7, 0.8, 0.9"

notebooks/animation.ipynb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@
9595
"metadata": {},
9696
"outputs": [],
9797
"source": [
98-
"anim = Animation()\n",
98+
"anim = Animation(vis)\n",
9999
"\n",
100100
"atframe(anim, 0) do\n",
101101
" # within the context of atframe, calls to \n",
@@ -153,7 +153,7 @@
153153
"metadata": {},
154154
"outputs": [],
155155
"source": [
156-
"anim = Animation()\n",
156+
"anim = Animation(vis)\n",
157157
"\n",
158158
"atframe(anim, 0) do\n",
159159
" settransform!(vis[\"/Cameras/default\"], Translation(0, 0, 0))\n",
@@ -179,7 +179,7 @@
179179
"metadata": {},
180180
"outputs": [],
181181
"source": [
182-
"anim = Animation()\n",
182+
"anim = Animation(vis)\n",
183183
"\n",
184184
"atframe(anim, 0) do\n",
185185
" setprop!(vis[\"/Cameras/default/rotated/<object>\"], \"zoom\", 1.0)\n",
@@ -226,7 +226,7 @@
226226
"metadata": {},
227227
"outputs": [],
228228
"source": [
229-
"anim = Animation()\n",
229+
"anim = Animation(vis)\n",
230230
"atframe(anim, 0) do\n",
231231
" setvisible!(vis[:sphere], false)\n",
232232
" settransform!(vis[:box1], Translation(0.0, 0, 0))\n",

src/MeshCat.jl

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ using Sockets: listen, @ip_str, IPAddr, IPv4, IPv6
4141
using Base64: base64encode
4242
using MsgPack: MsgPack, pack
4343
using Pkg.Artifacts: @artifact_str
44-
import Cassette
4544
import FFMPEG
4645
import HTTP
4746
import Logging
@@ -102,6 +101,35 @@ abstract type AbstractMaterial end
102101
include("util.jl")
103102
include("trees.jl")
104103
using .SceneTrees
104+
105+
struct AnimationContext
106+
animation
107+
frame::Int
108+
end
109+
110+
"""
111+
Low-level type which manages the actual meshcat server. See [`Visualizer`](@ref)
112+
for the public-facing interface.
113+
"""
114+
mutable struct CoreVisualizer
115+
tree::SceneNode
116+
connections::Set{HTTP.WebSockets.WebSocket}
117+
host::IPAddr
118+
port::Int
119+
server::HTTP.Server
120+
animation_contexts::Vector{AnimationContext}
121+
122+
function CoreVisualizer(host::IPAddr = ip"127.0.0.1", default_port=8700)
123+
connections = Set([])
124+
tree = SceneNode()
125+
port = find_open_port(host, default_port, 500)
126+
core = new(tree, connections, host, port)
127+
core.server = start_server(core)
128+
core.animation_contexts = AnimationContext[]
129+
return core
130+
end
131+
end
132+
105133
include("mesh_files.jl")
106134
include("geometry.jl")
107135
include("objects.jl")

src/animations.jl

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,19 @@ function Base.merge!(a::AnimationClip, others::AnimationClip...)
4646
end
4747

4848
struct Animation
49-
clips::Dict{Path, AnimationClip}
49+
visualizer::CoreVisualizer
5050
default_framerate::Int
51-
end
51+
clips::Dict{Path, AnimationClip}
5252

53-
"""
54-
Create a new animation. See [`atframe`](@ref) to adjust object poses or properties
55-
in that animation.
53+
"""
54+
Create a new animation. See [`atframe`](@ref) to adjust object poses or properties
55+
in that animation.
56+
57+
$(TYPEDSIGNATURES)
58+
"""
59+
Animation(visualizer::CoreVisualizer; fps=30) = new(visualizer, fps, Dict())
60+
end
5661

57-
$(TYPEDSIGNATURES)
58-
"""
59-
Animation(fps::Int=30) = Animation(Dict{Path, AnimationClip}(), fps)
6062

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

8588
"""
8689
Convert the `.tar` file of still images produced by the meshcat "record" feature

src/atframe.jl

Lines changed: 7 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -47,28 +47,6 @@ end
4747

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

50-
Cassette.@context AnimationCtx
51-
52-
function Cassette.overdub(ctx::AnimationCtx, ::typeof(settransform!), vis::Visualizer, tform::Transformation)
53-
animation, frame = ctx.metadata
54-
clip = getclip!(animation, vis.path)
55-
_setprop!(clip, frame, "scale", "vector3", js_scaling(tform))
56-
_setprop!(clip, frame, "position", "vector3", js_position(tform))
57-
_setprop!(clip, frame, "quaternion", "quaternion", js_quaternion(tform))
58-
end
59-
60-
function Cassette.overdub(ctx::AnimationCtx, ::typeof(setprop!), vis::Visualizer, prop::AbstractString, value)
61-
animation, frame = ctx.metadata
62-
clip = getclip!(animation, vis.path)
63-
_setprop!(clip, frame, prop, get_property_type(prop), value)
64-
end
65-
66-
function Cassette.overdub(ctx::AnimationCtx, ::typeof(setprop!), vis::Visualizer, prop::AbstractString, jstype::AbstractString, value)
67-
animation, frame = ctx.metadata
68-
clip = getclip!(animation, vis.path)
69-
_setprop!(clip, frame, prop, jstype, value)
70-
end
71-
7250
"""
7351
Call the given function `f`, but intercept any `settransform!` or `setprop!` calls
7452
and apply them to the given animation at the given frame instead.
@@ -81,7 +59,7 @@ Usage:
8159
vis = Visualizer()
8260
setobject!(vis[:cube], Rect(Vec(0.0, 0.0, 0.0), Vec(0.5, 0.5, 0.5)))
8361
84-
anim = Animation()
62+
anim = Animation(vis)
8563
8664
# At frame 0, set the cube's position to be the origin
8765
atframe(anim, 0) do
@@ -97,6 +75,11 @@ setanimation!(vis, anim)
9775
```
9876
"""
9977
function atframe(f, animation::Animation, frame::Integer)
100-
Cassette.overdub(AnimationCtx(metadata=(animation, frame)), f)
78+
push!(animation.visualizer.animation_contexts, AnimationContext(animation, frame))
79+
try
80+
f()
81+
finally
82+
pop!(animation.visualizer.animation_contexts)
83+
end
10184
return animation
10285
end

src/visualizer.jl

Lines changed: 34 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,3 @@
1-
"""
2-
Low-level type which manages the actual meshcat server. See [`Visualizer`](@ref)
3-
for the public-facing interface.
4-
"""
5-
mutable struct CoreVisualizer
6-
tree::SceneNode
7-
connections::Set{HTTP.WebSockets.WebSocket}
8-
host::IPAddr
9-
port::Int
10-
server::HTTP.Server
11-
12-
function CoreVisualizer(host::IPAddr = ip"127.0.0.1", default_port=8700)
13-
connections = Set([])
14-
tree = SceneNode()
15-
port = find_open_port(host, default_port, 500)
16-
core = new(tree, connections, host, port)
17-
core.server = start_server(core)
18-
return core
19-
end
20-
end
21-
221
function find_open_port(host, default_port, max_retries)
232
for port in default_port:(default_port + max_retries)
243
server = try
@@ -217,7 +196,15 @@ of its parents, so setting the transform of `vis[:group1]` affects the poses of
217196
the objects at `vis[:group1][:box1]` and `vis[:group1][:box2]`.
218197
"""
219198
function settransform!(vis::Visualizer, tform::Transformation)
220-
send(vis.core, SetTransform(tform, vis.path))
199+
if !isempty(vis.core.animation_contexts)
200+
ctx = last(vis.core.animation_contexts)
201+
clip = getclip!(ctx.animation, vis.path)
202+
_setprop!(clip, ctx.frame, "scale", "vector3", js_scaling(tform))
203+
_setprop!(clip, ctx.frame, "position", "vector3", js_position(tform))
204+
_setprop!(clip, ctx.frame, "quaternion", "quaternion", js_quaternion(tform))
205+
else
206+
send(vis.core, SetTransform(tform, vis.path))
207+
end
221208
vis
222209
end
223210

@@ -240,7 +227,29 @@ $(TYPEDSIGNATURES)
240227
with the Base.setproperty! function introduced in Julia v0.7)
241228
"""
242229
function setprop!(vis::Visualizer, property::AbstractString, value)
243-
send(vis.core, SetProperty(vis.path, property, value))
230+
if !isempty(vis.core.animation_contexts)
231+
ctx = last(vis.core.animation_contexts)
232+
clip = getclip!(ctx.animation, vis.path)
233+
_setprop!(clip, ctx.frame, property, get_property_type(property), value)
234+
else
235+
send(vis.core, SetProperty(vis.path, property, value))
236+
end
237+
vis
238+
end
239+
240+
"""
241+
Variation of `setprop!` which accepts an explicit type for the underlying JS property. This property type is only used within an animation context.
242+
243+
$(TYPEDSIGNATURES)
244+
"""
245+
function setprop!(vis::Visualizer, property::AbstractString, jstype::AbstractString, value)
246+
if !isempty(vis.core.animation_contexts)
247+
ctx = last(vis.core.animation_contexts)
248+
clip = getclip!(ctx.animation, vis.path)
249+
_setprop!(clip, ctx.frame, property, jstype, value)
250+
else
251+
send(vis.core, SetProperty(vis.path, property, value))
252+
end
244253
vis
245254
end
246255

@@ -275,3 +284,5 @@ For example, if you have `vis::Visualizer` with path `/meshcat/foo`, you can do
275284
"""
276285
Base.getindex(vis::Visualizer, path...) =
277286
Visualizer(vis.core, joinpath(vis.path, path...))
287+
288+
Animation(vis::Visualizer, args...; kw...) = Animation(vis.core, args...; kw...)

test/visualizer.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,15 +236,15 @@ end
236236
end
237237

238238
@testset "Animation" begin
239-
anim1 = Animation()
239+
anim1 = Animation(vis)
240240
atframe(anim1, 0) do
241241
settransform!(vis[:shapes][:box], Translation(0., 0, 0))
242242
end
243243
atframe(anim1, 30) do
244244
settransform!(vis[:shapes][:box], Translation(2., 0, 0) LinearMap(RotZ/2)))
245245
end
246246
setanimation!(vis, anim1)
247-
anim2 = Animation()
247+
anim2 = Animation(vis)
248248
atframe(anim2, 0) do
249249
setprop!(vis["/Cameras/default/rotated/<object>"], "zoom", 1)
250250
end

0 commit comments

Comments
 (0)