mirror of
https://github.com/status-im/whispervis.git
synced 2025-02-01 16:04:56 +00:00
125 lines
3.4 KiB
Go
125 lines
3.4 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/gopherjs/gopherjs/js"
|
|
"github.com/gopherjs/vecty"
|
|
"github.com/status-im/simulation/propagation"
|
|
)
|
|
|
|
// TODO(divan): move this as variables to the frontend
|
|
const (
|
|
BlinkDecay = 100 * time.Millisecond // time for highlighted node/link to be active
|
|
AnimationSlowdown = 1 // slowdown factor for propagation animation
|
|
FPS = 60 // default FPS
|
|
)
|
|
|
|
// animate fires up as an requestAnimationFrame handler.
|
|
func (w *WebGLScene) animate() {
|
|
if w.renderer == nil {
|
|
return
|
|
}
|
|
|
|
w.controls.Update()
|
|
|
|
if FPS == 60 {
|
|
js.Global.Call("requestAnimationFrame", w.animate)
|
|
} else {
|
|
time.AfterFunc((1000/FPS)*time.Millisecond, func() {
|
|
js.Global.Call("requestAnimationFrame", w.animate)
|
|
})
|
|
}
|
|
|
|
if w.autoRotate {
|
|
pos := w.graphGroup.Object.Get("rotation")
|
|
coeff := 60 / FPS * 0.001 // rotate faster on lower FPS
|
|
pos.Set("y", pos.Get("y").Float()+coeff)
|
|
w.graphGroup.UpdateMatrix()
|
|
}
|
|
|
|
if w.wobble {
|
|
w.wobbling.Animate()
|
|
w.updatePositions()
|
|
}
|
|
|
|
// some render throttling magic to prevent wasting CPU/GPU while idle
|
|
// if auto rotation or other effects are active, render always
|
|
var needRendering bool = w.wobble || w.autoRotate
|
|
if !needRendering {
|
|
// else, consult render throttler
|
|
needRendering = w.rt.NeedRendering()
|
|
}
|
|
|
|
if needRendering {
|
|
w.renderer.Render(w.scene, w.camera)
|
|
w.rt.ReenableIfNeeded()
|
|
}
|
|
}
|
|
|
|
// ToggleAutoRotation switches auto rotation option.
|
|
func (w *WebGLScene) ToggleAutoRotation() {
|
|
w.autoRotate = !w.autoRotate
|
|
}
|
|
|
|
// ToggleWobbling switches wobbling option.
|
|
func (w *WebGLScene) ToggleWobbling() {
|
|
w.wobble = !w.wobble
|
|
}
|
|
|
|
// BlinkNode animates a single node blinking. Node specified by its idx.
|
|
func (w *WebGLScene) BlinkNode(id int) {
|
|
node := w.nodes[id]
|
|
node.Set("material", BlinkedNodeMaterial)
|
|
restore := func() { node.Object.Set("material", DefaultNodeMaterial) }
|
|
time.AfterFunc(BlinkDecay, restore)
|
|
|
|
}
|
|
|
|
// BlinkEdge animates a single edge blinking. Edge specified by its idx.
|
|
func (w *WebGLScene) BlinkEdge(id int) {
|
|
edge := w.lines[id]
|
|
edge.Set("material", BlinkedEdgeMaterial)
|
|
restore := func() { edge.Object.Set("material", DefaultEdgeMaterial) }
|
|
time.AfterFunc(BlinkDecay, restore)
|
|
}
|
|
|
|
// AnimatePropagation visualizes propagation of message based on plog.
|
|
func (w *WebGLScene) AnimatePropagation(plog *propagation.Log) {
|
|
fmt.Println("Animating plog")
|
|
w.rt.Disable()
|
|
for i, ts := range plog.Timestamps {
|
|
duration := time.Duration(time.Duration(ts) * time.Millisecond)
|
|
duration = duration * AnimationSlowdown
|
|
|
|
nodes := plog.Nodes[i]
|
|
edges := plog.Indices[i]
|
|
fn := func() {
|
|
// blink nodes for this timestamp
|
|
for _, idx := range nodes {
|
|
w.BlinkNode(idx)
|
|
}
|
|
// blink links for this timestamp
|
|
for _, idx := range edges {
|
|
w.BlinkEdge(idx)
|
|
}
|
|
}
|
|
time.AfterFunc(duration, fn)
|
|
}
|
|
}
|
|
|
|
// MouseMoveListener implements listener for mousemove events.
|
|
// We use it for disabling render throttling, as mousemove events
|
|
// correlates with user moving inside of the WebGL canvas. We
|
|
// may switch to use mousedown or drag events, but let's see how
|
|
// mousemove works.
|
|
// This is sort of a hack, as the proper approach would be to get
|
|
// data from controls code (w.controls.Update), but it's currently
|
|
// a JS code, so it's easier use this hack.
|
|
func (p *Page) MouseMoveListener(e *vecty.Event) {
|
|
if !p.webgl.rt.NeedRendering() {
|
|
p.webgl.rt.Disable()
|
|
}
|
|
}
|