# Renderloop updates in GLMakie.jl?

**URL:** <https://discourse.julialang.org/t/renderloop-updates-in-glmakie-jl/114397>\
**Category:** Visualization\
**Created:** [May 17, 2024, 1:48pm UTC](https://discourse.julialang.org/t/renderloop-updates-in-glmakie-jl/114397 "2024-05-17T13:48:56Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![dgleich](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dgleich/32/1494_2.png) [@dgleich](https://discourse.julialang.org/u/dgleich)\
**Post date:** [May 17, 2024, 1:48pm UTC](https://discourse.julialang.org/t/renderloop-updates-in-glmakie-jl/114397/1 "2024-05-17T13:48:56Z")

</div>

Context:  
I’m trying to recreate this demo [Collide force | D3 by Observable](https://d3js.org/d3-force/collide) in Makie.jl with [GraphPlayground.jl](https://github.com/dgleich/GraphPlayground.jl) (and do other demos from there too…)

Issue:  
What’s are different ways of driving the update loop in GLMakie.jl ?

Things I’ve tried:

1. Create an async task to update the positions
2. Buttons to start/stop the async task based on [Updating Makie plot based on button action - #7 by jules](https://discourse.julialang.org/t/updating-makie-plot-based-on-button-action/111706/7)
3. Create a new screen and use render\_tick to get notified when there is a new frame.
4. Figure out the current screen for the (scene.current\_screens[1].render\_tick) event.

The downsides to 1 and 2 are that I have to manage tasks.

The downside to 3 is that I have to start a new window.

The downside to 4 is that it seems really slow. Also, I have to call display on the scene first to get current\_screens to instantiate.

Are there other ways I should think about handling this?

Thanks!  
David

My solution right now for 3 is below. (4 is basically the same, but we don’t have to create a new screen and use scene.current\_screens[1] after calling display…)

```Julia
using GLMakie
using StableRNGs, GeometryBasics, GraphPlayground, GLMakie

# ## Setup the simulation 
rng = StableRNG(1)
n = 200
width = 564 
k = width/n
radiusdist = k:4k
radius = rand(rng, radiusdist, n)
#radius[1] = 10 # make the first point a fixed point
pos = [Point2f0(rand(rng, 0:width), rand(rng, 0:width)) for _ in 1:n]
pos = pos .- sum(pos) / length(pos) 
sim = ForceSimulation(pos, eachindex(pos); 
  position=PositionForce(;strength=0.01),
  collide=CollisionForce(;radius=radius.+1,iterations=3),
  charge=ManyBodyForce(strength=(i) -> i==1 ? -width*2/3 : 0.0, theta2=0.82),
  alpha=GraphPlayground.CoolingStepper(alpha_target=0.3),
  velocity_decay=0.9,)

# ## Setup the screen and scene 

screen2 = GLMakie.Screen(framerate=60.0, vsync=true, render_on_demand=false, title="GLMakie Playground")
scene = Scene(camera = campixel!, size = (width, width))  
GLMakie.display_scene!(screen2, scene)

# ## setup links between all the display elements and simulation 
pos2 = sim.positions[2:end] 
posobs = Observable(pos2 .+ Point2f0(width/2, width/2))
f = scatter!(scene, posobs, markersize=pi*radius[2:end]/1.11, markerspace=:pixel, strokewidth=0, strokecolor=:white, 
  )  
velobs = Observable(sim.velocities[2:end])
vscale = Observable(1.0)
# g = arrows!(scene, posobs, velobs; lengthscale = vscale)  

mppos = Observable(Point2f0(0,0))
scatter!(scene, mppos, markersize=pi*100/1.11, color=:grey, strokewidth=0, markerspace=:pixel)

on(events(scene).mouseposition) do mp
  if mp[1] < 0 || mp[1] > width || mp[2] < 0 || mp[2] > width
    sim.alpha.alpha_target = 0.0
  else
    sim.alpha.alpha_target = 0.3
  end
  fixnode!(sim, 1, mp .- Point2f0(width/2, width/2))
  notify(posobs)
end  

# ## Add the simulation update loop on render_tick. 
on(screen2.render_tick) do _
  #println("Frame")
  step!(sim)
  posobs[] = sim.positions[2:end] .+ Point2f0(width/2, width/2)
  velobs[] = sim.velocities[2:end]
  vscale[] = 10*sim.alpha.alpha
  mppos[] = sim.positions[1] .+ Point2f0(width/2, width/2)
end

display(scene)

## Old code using my own task to set updates... 
# This was an older approach where I just had a loop that tried to update at 60fps and changed the positions
# with render-on-demand. 
# But then I have to manage my own update task, which is annoying... 
#=
task, close = GraphPlayground.updateloop(scene) do dt
  step!(sim)
  posobs[] = sim.positions[2:end] .+ Point2f0(width/2, width/2)
  velobs[] = sim.velocities[2:end]
  vscale[] = 10*sim.alpha.alpha
  mppos[] = sim.positions[1] .+ Point2f0(width/2, width/2)
  return true 
end 

=#

```
