DEV Community

Cover image for Visual live-coding proof-of-concept
Maia Taewana
Maia Taewana

Posted on • Edited on

5 3

Visual live-coding proof-of-concept

This is a proof-of-concept for the API.

The goals for this tiny visual live-coding library is to:

  1. Avoid bundlers.
  2. Native JS module (dynamic "import").
  3. No runtime overhead.

Here is the current experiment:

Alt Text

Concepts

In order to achieve the zero overhead goal, to link between connected "blocks" in the render-tree, we need:

  1. A context propagation phase going from top to bottom.
  2. A linking phase returning children update functions from bottom to top.
  3. 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 ]         [ ... ]
Enter fullscreen mode Exit fullscreen mode

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 }
}
Enter fullscreen mode Exit fullscreen mode

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()
        },
      }
    },
  }
}
Enter fullscreen mode Exit fullscreen mode

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,
    }),
  }
}
Enter fullscreen mode Exit fullscreen mode

Full code on github: https://github.com/tuist-org/tuist

If you read this far, please leave a comment :-)

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay