diff --git a/README.md b/README.md index b9132e62198a1d7c14f53c6614c9db610f430a5d..428e5c7aec318ff56b7b549f54cb33f860a7b37d 100644 --- a/README.md +++ b/README.md @@ -57,51 +57,48 @@ import { State } from './hunks.js' -function Name() { +// our function name actually doesn't matter: hunks in js are named by their +// location on disk +export default function Name() { // this fn attaches handles to our function-object, Hunkify(this) - // inputs, outputs, and state are objects. they have a type (string identifier) - // see 'typeset.js' - // a name (doesn't have to be unique), and we pass them a handle to ourselves... - let inA = new Input('number', 'name', this) - // inputs, outputs and state are all kept locally in these arrays, - // if we don't include them here, the manager will have a hard time finding them ... - this.inputs.push(inA) + // inputs, outputs, and state are objects. + // they each have a type and a name + let inA = this.input('string', 'quiet') + let outB = this.output('string', 'loud') - let outB = new Output('number', 'name', this) - this.outputs.push(outB) - - let stateItem = new State('string', 'name', 'startupValue') - this.states.push(stateItem) + // states take another argument: their default startup value + let stateItem = this.state('string', 'exclaim', '!') // State items also have change handlers, stateItem.onChange = (value) => { - // at this point, something external (probably a human) - // has requested that we change this state variable, + // at this point, a request to update this state item to the provided value + // has been made console.log('requests:', value) // we can reject that, by doing nothing here, or we can stateItem.set(value) + // or compute on it, set limits, etc } // hunks can choose to- or not- have init code. - // at init, the module has been loaded and state variables have been + // at init, the module has been loaded into the JS engine and state variables have been // recalled from any program save - so this is a good point // to check any of those, and setup accordingly ... this.init = () => { this.log('hello template world') } + // there are no rules within this closure, local functions, data, etc... let internalVariable = 'local globals' - - function internalFunc(data) { - // scoped function, not accessible externally - // do work, - return (data) + function internalFunc(str) { + let caps = str.toUpperCase() + caps += stateItem.value + return (caps) } // to divide time between hunks, each has a loop function - // this is the hunks' runtime: a manager calls this once-per-round + // this is the hunks' runtime, and is called repeatedly, as the process runs // here is where we check inputs, put to outputs, do work, etc this.loop = () => { // typically we check inputs and outputs first, @@ -114,12 +111,9 @@ function Name() { } } } - -// the hunk is also an ES6 module, this is how we export those: -export default Name ``` -Hunks with DOM elements (to render into the browser's window) are a *tad* more complicated, here's an example: +Hunks with DOM elements (to render custom html into the browser) are a bit more involved, here's a small example: ```javascript /* @@ -130,51 +124,51 @@ debugger ! log anything ! import { Hunkify, Input, Output, State } from '../hunks.js' -function Logger() { - Hunkify(this, 'Logger') +export default function ReferenceLogger() { + Hunkify(this) - let tolog = new Input('any', 'tolog', this) - this.inputs.push(tolog) + // hmm... + let tolog = new Input('reference', 'tolog', this) + this.inputs.push(tolog) - let prefix = new State('string', 'prefix', 'LOG:') - let logToConsole = new State('boolean', 'console', true) - this.states.push(prefix, logToConsole) + let prefix = new State('string', 'prefix', 'LOG:') + let logToConsole = new State('boolean', 'console', true) + this.states.push(prefix, logToConsole) - this.dom = {} + this.dom = {} - this.init = () => { - // manager calls this once - // it is loaded and state is updated (from program) - this.log('HELLO LOGGER') - this.dom = $('<div>').get(0) - } + this.init = () => { + this.dom = $('<div>').get(0) + } - this.onload = () => { - //error here - let text = $('<div>').addClass('txt').append('- >').get(0) - $(this.dom).append(text) - } + this.onload = () => { + //error here + let text = $('<div>').addClass('txt').append('- >').get(0) + $(this.dom).append(text) + } - this.loop = () => { - // this will be called once every round turn - // typically we check flow control first - if (tolog.io()) { - // an input is occupied, and the exit path is empty - let val = tolog.get() - if(Array.isArray(val)){ - val = val.join(', ') - } else if (typeof val === "boolean"){ - val = val.toString() - } - $(this.dom).children('.txt').html(val) - if (logToConsole.value === true) { - console.log(this.ind, prefix.value, val) - } - } + this.loop = () => { + // this will be called once every round turn + // typically we check flow control first + if (tolog.io()) { + // an input is occupied, and the exit path is empty + let raw = tolog.get() + let stringRep + if (Array.isArray(raw)) { + stringRep = raw.join(', ') + } else if (typeof raw === "boolean") { + stringRep = raw.toString() + } else { + // let js do w/e witchcraft it chooses + stringRep = raw + } + $(this.dom).children('.txt').html(stringRep) + if (logToConsole.value === true) { + console.log(this.ind, prefix.value, raw) + } } + } } - -export default Logger ``` For a more involved example, see [the linechart](hunks/data/linechart.js). diff --git a/hunks/adhoc/tpath.js b/hunks/adhoc/tpath.js index 04f67947f8a17f05b992a973df0488c9a0133944..649c41a28900bd46db185b3f6f389c6d5b8d813c 100644 --- a/hunks/adhoc/tpath.js +++ b/hunks/adhoc/tpath.js @@ -37,7 +37,7 @@ export default function TPFCOUT(){ let shortSet = this.state('boolean', 'shortpath', false) shortSet.onChange = (value) => { go = true - path = JSON.parse(JSON.stringify(shortpath.default.arr)) + path = JSON.parse(JSON.stringify(smallpath.default.arr)) } let sl2pathSet = this.state('boolean', 'sl2path', false) sl2pathSet.onChange = (value) => { diff --git a/hunks/interface/threejs_ghost.js b/hunks/interface/threejs_ghost.js index 456353193ac0169e47918582e73b11f0603f3382..8f3c089d4d3571485337dfec1eb235b39e1b7bcb 100644 --- a/hunks/interface/threejs_ghost.js +++ b/hunks/interface/threejs_ghost.js @@ -18,7 +18,7 @@ import { MeshLine, MeshLineMaterial } from '../../libs/three_meshline.module.js' let numSegs = 100 -export default function ThreeGhosts(){ +export default function ThreeGhosts() { Hunkify(this) let ptin = this.input('array', 'point') @@ -34,8 +34,8 @@ export default function ThreeGhosts(){ let lineWidth = 10 let geometry = new THREE.Geometry() let startSegLength = 100 / numSegs - for(let i = numSegs; i > 0; i --){ - geometry.vertices.push(new THREE.Vector3(startSegLength*i, startSegLength*i, startSegLength*i)) + for (let i = numSegs; i > 0; i--) { + geometry.vertices.push(new THREE.Vector3(startSegLength * i, startSegLength * i, startSegLength * i)) } let updatePts = [] @@ -47,9 +47,21 @@ export default function ThreeGhosts(){ resolution: new THREE.Vector2(width, height) }) + let pushToLine = (pt) => { + let v3 = new THREE.Vector3(pt[0], pt[1], pt[2]) + geometry.vertices.push(v3) + geometry.vertices.shift() + line.advance(v3) + } + let camera = new THREE.PerspectiveCamera(75, width / height, 1, 10000) camera.up.set(0, 0, 1) + let bbox = new THREE.Box3() + let bbCenter = new THREE.Vector3() + let bbSize = new THREE.Vector3() + console.log('line', line) + this.onload = (dom) => { let scene = new THREE.Scene() scene.background = new THREE.Color(0xc8e6e2) @@ -68,17 +80,36 @@ export default function ThreeGhosts(){ //let controls = new OrbitControls(camera, this.dom) //controls.update() camera.position.set(840, 100, 1300) - camera.lookAt(new THREE.Vector3(900,600,10)) + camera.lookAt(new THREE.Vector3(900, 600, 10)) + + console.log(line) let animate = function() { - requestAnimationFrame(animate) - if(updatePts.length > 0){ - let nextpt = updatePts.shift() - // advance removes the oldest position, so we should start w/ the # we want - line.advance(new THREE.Vector3(nextpt[0], nextpt[1], nextpt[2])) - } - //controls.update() - renderer.render(scene, camera) + // + // requestAnimationFrame(animate) + setTimeout(animate, 500) + if (updatePts.length > 0) { + let nextpt = updatePts.shift() + // advance removes the oldest position, so we should start w/ the # we want + pushToLine(nextpt) + // do bounding box... + bbox.setFromPoints(geometry.vertices) + bbox.getCenter(bbCenter) + bbox.getSize(bbSize) + const maxDim = Math.max(bbSize.x, bbSize.y, bbSize.z) + const fov = camera.fov * (Math.PI / 180) + let cameraZ = Math.abs(maxDim / 4 * Math.tan(fov * 2)) + cameraZ *= cameraZ + console.log(cameraZ) + camera.position.z = cameraZ + const minZ = bbox.min.z + const cameraToFarEdge = (minZ < 0) ? -minZ + cameraZ : cameraZ - minZ + camera.far = cameraToFarEdge * 3 + camera.updateProjectionMatrix() + camera.lookAt(bbCenter) + } + //controls.update() + renderer.render(scene, camera) } // kickstart animate() @@ -102,9 +133,8 @@ export default function ThreeGhosts(){ } this.loop = () => { - if(ptin.io()){ + if (ptin.io()) { updatePts.push(ptin.get()) - /* geometry.vertices.push(new THREE.Vector3(pt[0], pt[1], pt[2])) if(geometry.vertices.length > 32){ diff --git a/save/contexts/cuttlefish/0ghost.json b/save/contexts/cuttlefish/0ghost.json new file mode 100644 index 0000000000000000000000000000000000000000..9e5951fb5d41eb30dfbb9c024f1cd8249c0390c8 --- /dev/null +++ b/save/contexts/cuttlefish/0ghost.json @@ -0,0 +1,124 @@ +{ + "interpreterName": "cuttlefish", + "interpreterVersion": "v0.1", + "hunks": [ + { + "type": "manager", + "name": "nrol", + "inputs": [ + { + "name": "msgs", + "type": "byteArray" + } + ], + "outputs": [ + { + "name": "msgs", + "type": "byteArray", + "connections": [ + { + "inHunkIndex": "1", + "inHunkInput": "0" + } + ] + } + ] + }, + { + "type": "view", + "name": "tlview", + "inputs": [ + { + "name": "msgs", + "type": "byteArray" + } + ], + "outputs": [ + { + "name": "msgs", + "type": "byteArray", + "connections": [ + { + "inHunkIndex": "0", + "inHunkInput": "0" + } + ] + } + ] + }, + { + "type": "adhoc/tpath", + "name": "adhoc/tpath_2", + "outputs": [ + { + "name": "position", + "type": "array", + "connections": [ + { + "inHunkIndex": "3", + "inHunkInput": "0" + } + ] + } + ], + "states": [ + { + "name": "mm/pix", + "type": "number", + "value": "1" + }, + { + "name": "longpath", + "type": "boolean", + "value": "false" + }, + { + "name": "shortpath", + "type": "boolean", + "value": "false" + }, + { + "name": "sl2path", + "type": "boolean", + "value": "false" + } + ] + }, + { + "type": "adhoc/saturn", + "name": "adhoc/saturn_3", + "inputs": [ + { + "name": "posn", + "type": "array" + } + ], + "outputs": [ + { + "name": "posn", + "type": "array", + "connections": [ + { + "inHunkIndex": "4", + "inHunkInput": "0" + } + ] + }, + { + "name": "motionSegment", + "type": "MDmseg" + } + ] + }, + { + "type": "interface/threejs_ghost", + "name": "interface/threejs_ghost_5", + "inputs": [ + { + "name": "point", + "type": "array" + } + ] + } + ] +} \ No newline at end of file diff --git a/save/contexts/cuttlefish/dbg.json b/save/contexts/cuttlefish/dbg.json index 8686d30ff9841bc92dae745cf9a924d7ee97eb27..9e5951fb5d41eb30dfbb9c024f1cd8249c0390c8 100644 --- a/save/contexts/cuttlefish/dbg.json +++ b/save/contexts/cuttlefish/dbg.json @@ -63,7 +63,22 @@ ], "states": [ { - "name": "reset", + "name": "mm/pix", + "type": "number", + "value": "1" + }, + { + "name": "longpath", + "type": "boolean", + "value": "false" + }, + { + "name": "shortpath", + "type": "boolean", + "value": "false" + }, + { + "name": "sl2path", "type": "boolean", "value": "false" } @@ -90,22 +105,14 @@ ] }, { - "name": "outx", - "type": "number" - }, - { - "name": "outy", - "type": "number" - }, - { - "name": "outz", - "type": "number" + "name": "motionSegment", + "type": "MDmseg" } ] }, { "type": "interface/threejs_ghost", - "name": "interface/threejs_ghost_4", + "name": "interface/threejs_ghost_5", "inputs": [ { "name": "point", diff --git a/save/contexts/cuttlefish/ghost.json b/save/contexts/cuttlefish/ghost.json new file mode 100644 index 0000000000000000000000000000000000000000..9e5951fb5d41eb30dfbb9c024f1cd8249c0390c8 --- /dev/null +++ b/save/contexts/cuttlefish/ghost.json @@ -0,0 +1,124 @@ +{ + "interpreterName": "cuttlefish", + "interpreterVersion": "v0.1", + "hunks": [ + { + "type": "manager", + "name": "nrol", + "inputs": [ + { + "name": "msgs", + "type": "byteArray" + } + ], + "outputs": [ + { + "name": "msgs", + "type": "byteArray", + "connections": [ + { + "inHunkIndex": "1", + "inHunkInput": "0" + } + ] + } + ] + }, + { + "type": "view", + "name": "tlview", + "inputs": [ + { + "name": "msgs", + "type": "byteArray" + } + ], + "outputs": [ + { + "name": "msgs", + "type": "byteArray", + "connections": [ + { + "inHunkIndex": "0", + "inHunkInput": "0" + } + ] + } + ] + }, + { + "type": "adhoc/tpath", + "name": "adhoc/tpath_2", + "outputs": [ + { + "name": "position", + "type": "array", + "connections": [ + { + "inHunkIndex": "3", + "inHunkInput": "0" + } + ] + } + ], + "states": [ + { + "name": "mm/pix", + "type": "number", + "value": "1" + }, + { + "name": "longpath", + "type": "boolean", + "value": "false" + }, + { + "name": "shortpath", + "type": "boolean", + "value": "false" + }, + { + "name": "sl2path", + "type": "boolean", + "value": "false" + } + ] + }, + { + "type": "adhoc/saturn", + "name": "adhoc/saturn_3", + "inputs": [ + { + "name": "posn", + "type": "array" + } + ], + "outputs": [ + { + "name": "posn", + "type": "array", + "connections": [ + { + "inHunkIndex": "4", + "inHunkInput": "0" + } + ] + }, + { + "name": "motionSegment", + "type": "MDmseg" + } + ] + }, + { + "type": "interface/threejs_ghost", + "name": "interface/threejs_ghost_5", + "inputs": [ + { + "name": "point", + "type": "array" + } + ] + } + ] +} \ No newline at end of file