~kylep/pipes

fe7ba8c3f5a46d7758926dffe386f0dd7a20d0be — Kyle Perik a month ago 94271dd
Add new devices for store and render
2 files changed, 57 insertions(+), 7 deletions(-)

M src/device.js
M src/utils.js
M src/device.js => src/device.js +39 -7
@@ 3,6 3,8 @@ let log = []
let eventLog = []
let ctx, canvas
let state = {}
let rendered = {}
let renderCalled = false
let errorBackoff = false

function initDevices () {


@@ 96,6 98,11 @@ function processEvent (payload) {
  }
  try {
    run([...payload, state], runningProgram.patterns, runningProgram.definitions).forEach(handle)
    if (renderCalled) {
      renderCalled = false
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      drawRendered(rendered, {x: 0, y: 0})
    }
  } catch (e) {
    reportError(e)
    errorBackoff = true


@@ 106,17 113,31 @@ function processEvent (payload) {
  }
}

function draw (element) {
function drawRendered (render, pos) {
  // Render this if it has a graphics element
  const newPos = (
    render.el && render.el.pos
      ? vecadd(pos, render.el.pos)
      : pos
  )
  if (render.el) {
    draw(render.el, newPos)
  }
  // Either way, draw each of the children as well
  Object.values(render.children || {}).forEach(v => drawRendered(v, newPos))
}

function draw (element, pos) {
  if (element.type === 'circle') {
    ctx.beginPath()
    ctx.arc(element.pos.x, element.pos.y, element.radius, 0, Math.PI * 2, true)
    ctx.arc(pos.x, pos.y, element.radius, 0, Math.PI * 2, true)
    ctx.stroke()
  } else if (element.type === 'clear') {
    ctx.clearRect(0, 0, canvas.width, canvas.height);
  } else if (element.type === 'line') {
    ctx.beginPath()
    ctx.moveTo(element.start.x, element.start.y)
    ctx.lineTo(element.end.x, element.end.y)
    ctx.moveTo(element.start.x + pos.x, element.start.y + pos.x)
    ctx.lineTo(element.end.x + pos.y, element.end.y + pos.y)
    ctx.stroke()
  } else {
    console.error('Unrecognized element type:', element.type)


@@ 130,14 151,25 @@ function handle (event) {
  if (!Array.isArray(event)) {
    return
  }
  const [type, value] = event;
  const [type, value, ...rest] = event;
  if (type === 'log') {
    logOutput(JSON.stringify(value))
  } else if (type === 'draw') {
    draw(value)
    draw(value, {x: 0, y: 0})
  } else if (type === 'render') {
    const paths = rest.flatMap(path => {
      return ['children', path]
    }).concat(['el'])
    rendered = withSetAtPath(paths, rendered, value);
    renderCalled = true
  } else if (type === 'store') {
    state = withSetAtPath(rest, state, value);
  } else if (type === 'set_state') {
    Object.keys(value).forEach(key => {
      state[key] = value[key]
      state = {
        ...state,
        [key]: value[key]
      }
    })
  }
}

M src/utils.js => src/utils.js +18 -0
@@ 36,3 36,21 @@ function setHiPPI(canvas, width, height) {

  return canvas;
}

function withSetAtPath (paths, partial, data) {
  if (paths.length === 0) {
    return data
  }
  const [path, ...otherPaths] = paths;
  return {
    ...(partial || {}),
    [path]: withSetAtPath(otherPaths, (partial || {})[path], data)
  }
}

function vecadd ({x: xa, y: ya}, {x: xb, y: yb}) {
  return {
    x: xa + xb,
    y: ya + yb
  }
}