This is a proof-of-concept for the API.
The goals for this tiny visual live-coding library is to:
- Avoid bundlers.
- Native JS module (dynamic "import").
- No runtime overhead.
Here is the current experiment:
Concepts
In order to achieve the zero overhead goal, to link between connected "blocks" in the render-tree, we need:
- A context propagation phase going from top to bottom.
- A linking phase returning children update functions from bottom to top.
- A call or update phase with the result.
Render tree
Here is the tree for this example:
[ main ]
[ anim.Loop ]
[ three.WebGLRenderer ]
[ three.Scene ]
[ three.Mesh -----------------------------------]
[ three.Rotation.x ] [ three.Rotation.y ] [ ... ]
[ time.Now ] [ time.Now ] [ ... ]
three.Mesh
import { Context, Node } from './context'
// Context phase (1)
// The 'object3D' received here is the three.Scene
export function init({ THREE, object3D, cache, detached }: Context): Node {
const mesh = cache('object3D', () => {
const dim = 1
const geometry = new THREE.BoxGeometry(dim, dim, dim)
const material = new THREE.MeshPhongMaterial({
color: 0x156289,
emissive: 0x072534,
side: THREE.DoubleSide,
flatShading: true,
})
const mesh = new THREE.Mesh(geometry, material)
object3D.add(mesh)
return mesh
})
if (detached) {
if (mesh.parent) {
mesh.parent.remove(mesh)
}
}
// Context update. Now 'object3D' for children is the
// cube mesh.
return { object3D: mesh }
}
three.Rotate.x
import { Context, Node } from './context'
// Context phase (1)
// The 'object3D' object is the cube from three.Mesh
export function init({ object3D, detached }: Context): Node {
const rotation = object3D.rotation
rotation.x = 0
if (detached) {
return {}
}
return {
// Link phase (2)
// Arguments are the linked children.
link({ number: rotateX }) {
const x = rotateX || () => 0
return {
// Update phase (3)
update() {
rotation.x = x()
},
}
},
}
}
time.Now
import { Context, Node } from './context'
// Context phase (1)
// Receives the "time" object from anim.Loop far up
// in the tree.
export function init({ time }: Context): Node {
return {
// Link phase (2)
// Does not have children
link: () => ({
// Update phase (3)
// Returns a number. This is the function called by
// three.Rotation.x on update.
number: () => time.now,
}),
}
}
Full code on github: https://github.com/tuist-org/tuist
If you read this far, please leave a comment :-)
Top comments (0)