importAbstractPlotting:Plot,default_theme,plot!,to_valueusingAbstractPlottingstructSimulationgrid::Vector{Point3f0}end# Probably worth having a macro for this!functiondefault_theme(scene::SceneLike,::Type{<:Plot(Simulation)})Theme(advance=0,molecule_sizes=[0.08,0.04,0.04],molecule_colors=[:maroon,:deepskyblue2,:deepskyblue2])end# The recipe! - will get called for plot(!)(x::SimulationResult)functionAbstractPlotting.plot!(p::Plot(Simulation))sim=to_value(p[1])# first argument is the SimulationResult# when advance changes, get new positions from the simulationmpos=lift(p[:advance])doisim.grid.+rand(Point3f0,length(sim.grid)).*0.01f0end# size shouldn't change, so we might as well get the value instead of signalpos=to_value(mpos)N=length(pos)sizes=lift(p[:molecule_sizes])dosrepeat(s,outer=N÷3)endsizes=lift(p[:molecule_sizes])dosrepeat(s,outer=N÷3)endcolors=lift(p[:molecule_colors])docrepeat(c,outer=N÷3)endscene=meshscatter!(p,mpos,markersize=sizes,color=colors)indices=Int[]foriin1:3:Npush!(indices,i,i+1,i,i+2)endmeshplot=p.plots[end]# meshplot is the last plot we added to p# meshplot[1] -> the positions (first argument) converted to points, so# we don't do the conversion 2 times for linesegments!linesegments!(p,lift(x->view(x,indices),meshplot[1]))end# To write out a video of the whole simulationn=5r=range(-1,stop=1,length=n)grid=Point3f0.(r,reshape(r,(1,n,1)),reshape(r,(1,1,n)))molecules=map(1:(n^3)*3)doii3=((i-1)÷3)+1xy=0.1;z=0.08i%3==1&&returngrid[i3]i%3==2&&returngrid[i3]+Point3f0(xy,xy,z)i%3==0&&returngrid[i3]+Point3f0(-xy,xy,z)endresult=Simulation(molecules)scene=plot(result)N=100record(scene,"output.mp4",1:N)doiscene[end][:advance]=iend