diff --git a/README.md b/README.md index 39d7772ef6d3e716f16f8ef2d42451d4f7f15adc..66e653e48ce3e0f3dae4cb09e9b49d72ee6e14fb 100644 --- a/README.md +++ b/README.md @@ -3,14 +3,14 @@ ## what it do ... now ... -- happy with module writing? -- with setting? - - state variables look like variables in module writing - - system wraps in setters / getters - - system has this.state.onChange('varname', function(){ fn code }) - -- rewrite gcode module for new syntax - - test interal system: setup events, write gcode to gcode from terminal +- modules templates and state management seems ready to work +- want to make sensical pass-back objects: + - core server mod is memory representation + - interfaces strip of state-changing things + - and event particulars + - everytime we update anything, just send a complete representation back and forth, sweep on the other side + - and a top level: this is the thing we load and save from + - somehow links need to live in the module representations ... - refactor ui with new everything - terminal serves terminal input line (client, css) diff --git a/client/client.js b/client/client.js index b59e1e02cca039fb857a0838863e9e5db20faf1d..f3e786f5bc2aa2e965b9fda2d106e9355e4df24d 100644 --- a/client/client.js +++ b/client/client.js @@ -69,40 +69,6 @@ function socketRecv(evt) { } } -// return ul element with name and alt and link? -function buildMenu(tree) { - var menuDom = document.createElement('div') - menuDom.id = 'menu' - menuDom.style.left = lastPos.X + 'px' - menuDom.style.top = lastPos.Y + 'px' - for (key in tree) { - var ul = document.createElement('ul') - ul.innerHTML = key.toString() - for (subkey in tree[key]) { - var li = document.createElement('li') - var path = tree[key][subkey].path - li.innerHTML = subkey.toString() - li.id = path - li.addEventListener('click', function(evt) { - var data = this.id - socketSend('add module', data) - wrapper.removeChild(document.getElementById('menu')) - }) - ul.appendChild(li) - } - menuDom.appendChild(ul) - } - wrapper.append(menuDom) - - function rmListener(evt) { - var findMenu = document.getElementById('menu') - if (findMenu !== null && findMenu.id == 'menu') { - wrapper.removeChild(findMenu) - } - } - - document.addEventListener('click', rmListener) -} function addReps(reps){ // when adding links, we'll have to add all and then draw links @@ -119,9 +85,9 @@ function addRep(rep) { domElem.style.left = lastPos.X + 'px' domElem.style.top = lastPos.Y + 'px' - if(rep.ui != null){ - domElem.style.left = rep.ui.left +'px' - domElem.style.top = rep.ui.top + 'px' + if(rep.rep != null){ + domElem.style.left = rep.rep.left +'px' + domElem.style.top = rep.rep.top + 'px' } // more html: the title @@ -137,18 +103,29 @@ function addRep(rep) { rep.ui = {} rep.ui.domElem = domElem - // WRITE UI ELEMENTS - var uiElem = document.createElement('div') - uiElem.className = 'inside' - + // WRITE UI STATE ELEMENTS + var stateElem = document.createElement('div') + stateElem.className = 'state' + var datui = new dat.GUI({autoplace: false}) // rolling through the json object // make UI objects, on change each fires new fn to push state of obj // at server: how to do .onChange() ? console.log(rep) for (key in rep.state) { - console.log(key) + if (key.indexOf('_') !== 0 & key != 'emitters'){ + // confusion is here - getting only _ values, when send new state + // want to do it w/o these, for + // probably keep things very clear, sending only mod.states, tl.conn and mod.uis back and forth? + // write fn that wraps thos? + var newi = datui.add(rep.state, key) + newi.onFinishChange(function(value){ + putState(rep) + }) + } } - rep.ui.domElem.appendChild(uiElem) + rep.ui.dat = datui + stateElem.appendChild(datui.domElement) + rep.ui.domElem.appendChild(stateElem) // add this as well to the representation obj // WRITE INPUTS AND OUTPUTS @@ -173,7 +150,7 @@ function addRep(rep) { // now we'll append our objects to the top level container domElem.appendChild(inElem) domElem.appendChild(outElem) - domElem.appendChild(uiElem) + domElem.appendChild(stateElem) var clearElem = document.createElement('div') clearElem.className = 'clear' domElem.appendChild(clearElem) @@ -199,6 +176,43 @@ function addRep(rep) { wrapper.appendChild(rep.ui.domElem) } +// update state from server to UI +function changeState(data){ + /* + console.log(data.state) + + var oldState = reps[data.id].state + var newState = data.state + + for (key in newState) { + if (isStateKey(key)) { + if (oldState[key] != newState[key]) { + oldState[key] = newState[key] + console.log('changeState', key, 'to', newState[key], 'in', data.id) + } + } + } + */ +} + +function isStateKey(key){ + if(key.indexOf('_') == 0 || key == 'emitters' || key == 'onChange' || key == 'emitChange'){ + return false + } else { + return true + } +} + +// push new state from UI to server +function putState(rep) { + console.log('putting state', rep) + var data = { + id: rep.id, + state: rep.state + } + socketSend('put state', data) +} + var clkState = false var oClk = {} var tmpBz = {} @@ -252,22 +266,6 @@ function evtConnectHandler(clk) { } } -function changeState(mod){ - var ors = reps[mod.id].state - var nrs = mod.state - - for(key in nrs){ - if(ors[key] != nrs[key]){ - ors[key] = nrs[key] - console.log(ors) - for(var i in reps[mod.id].ui.dat.__controllers){ - reps[mod.id].ui.dat.__controllers[i].updateDisplay() - } - console.log(key, 'to', nrs[key], 'in', mod.id) - } - } -} - // need top level rep of program - nice to think of how to handle heirarchy later on? tl rep is internal rep ... is same ? // how to handle movement of rep, incl. svg - goes with moving mouse after 1st click: svg lives 'in' rep ? @@ -324,12 +322,39 @@ document.addEventListener('mousemove', function(evt) { }) */ -function newState(rep) { - var data = { - id: rep.id, - state: rep.state +// return ul element with name and alt and link? +function buildMenu(tree) { + var menuDom = document.createElement('div') + menuDom.id = 'menu' + menuDom.style.left = lastPos.X + 'px' + menuDom.style.top = lastPos.Y + 'px' + for (key in tree) { + var ul = document.createElement('ul') + ul.innerHTML = key.toString() + for (subkey in tree[key]) { + var li = document.createElement('li') + var path = tree[key][subkey].path + li.innerHTML = subkey.toString() + li.id = path + li.addEventListener('click', function(evt) { + var data = this.id + socketSend('add module', data) + wrapper.removeChild(document.getElementById('menu')) + }) + ul.appendChild(li) + } + menuDom.appendChild(ul) } - socketSend('put state', data) + wrapper.append(menuDom) + + function rmListener(evt) { + var findMenu = document.getElementById('menu') + if (findMenu !== null && findMenu.id == 'menu') { + wrapper.removeChild(findMenu) + } + } + + document.addEventListener('click', rmListener) } // init & hookup diff --git a/client/style.css b/client/style.css index 782e38e7fcec6a351d41530bbc45913f0ca4fa5f..35074a918d9c38459207afed9936d2d68822cb13 100644 --- a/client/style.css +++ b/client/style.css @@ -29,7 +29,7 @@ body { color: #eee; } -.inside { +.state { padding: 0 83px 0 83px; } diff --git a/old_wishlist.md b/old_wishlist.md new file mode 100644 index 0000000000000000000000000000000000000000..2273a4d3e2b366ca5d11942edf67b9d9e7ccde2a --- /dev/null +++ b/old_wishlist.md @@ -0,0 +1,51 @@ +## From John / Ryan / Tom + +PNG / Hairline no bueno -> no direct hairline instructions +rhino.black.png +rhino.png inversion issues / normalize A values? + +## Function +Data structure assembly... merge objects into array + usecase -> image combine, want to combine n number of images + input to 'combine' should be singular, of type array-of-images +Save PNG + +## Debug +TOP PICK reload mods from server in existing graph sketch +-> this as experiment on all mods through some global level, to add 'refresh' button + or do development tools in-mods so that you can IDE while u IDE :/ +2ND PICK sniffer / forwarding (fires events) tool that is type-agnostic & displays intelligently +3RD - RGBA Washer. Or better understanding. WTF +mods.log('message') reports mod id, time fired ... +rgb preview canvases get friendly packaged class, checkered background 2 c transparency + +## UI +scroll / zoom / pan +pipe inspektor +open-mod on double-click and text +copy / paste / duplicate +drag pipe, no click +full-size canvases open up scaled to screen, show scale factor, drag zoom ... + +## Nitpick +event does not fire when 'line loaded' -> have to re-select svg +distance transform 'aw snaps' when given un-thresholded rgba values + +### KiCad -> PNG via MODS +area fill +do full programs +commit programs + +on mods, api architecture ... open distributed operating systems + dna carrying programs, hairballs + APIs handing eachother their available calls: + mods-type program is UI for finding, viewing, editing graphs, all calls are object calls, JSON, can carry programs to execute (hard with C) + where the level shifts: kinematic modules -> design | hardware + js programs -> ? | hardware | C + design of components -> design of assemblies -> | hardware + + main beef is separation UI -> Business. Bug or Feature? UI should be program whose job it is to represent software. To mix is messy, results in code that is ultimately unreadable: presents too much complexity, not really accessible. + + UI program starts at UI and polls through some node to programs elsewhere... ? + + and a desire for easily included libraries: 3js, custom maths, etc \ No newline at end of file diff --git a/scratch.js b/scratch.js new file mode 100644 index 0000000000000000000000000000000000000000..3c9a5440974baa48640194368f9d97fd844522c0 --- /dev/null +++ b/scratch.js @@ -0,0 +1,14 @@ + +function writeStateRep(rep, key){ + // ui including different input types ... + button to fire? + var li = document.createElement('li') + li.appendChild(document.createTextNode(key + ':')) + var input = document.createElement('input') + input.type = 'text' + input.size = 20 + li.appendChild(input) + input.addEventListener('change', function(){ + console.log('update', rep.state, key) + }) + return li +} \ No newline at end of file diff --git a/server.js b/server.js index 02188f9796a24ce82d207d229dd5abdb047c2450..ad59c3a7f51ff2e14fd50815cca5f23b78a7dde2 100644 --- a/server.js +++ b/server.js @@ -38,8 +38,8 @@ wss.on('connection', (ws) => { sckt = ws // say hello socketSend('console', 'hello client') - // send current config - sendModules()() + // send current config as list of all modules + putReps() console.log('socket open on 8081') ws.on('message', (evt) => { socketRecv(evt) @@ -81,8 +81,8 @@ function socketRecv(evt) { case 'add module': addModule(data) break - case 'put ui': - uiChange(data) + case 'put state': + changeState(data) break case 'put link': putLink(data) @@ -122,24 +122,13 @@ term.rep = {} term.rep.left = 10 term.rep.top = 10 -/* gcode.rep = {} gcode.rep.left = 200 gcode.rep.top = 200 -*/ - -//console.log('modules at prgmem start', modules) - -function sendModules() { - for (md in modules) { - console.log(modules[md].state) - } - socketSend('put reps', modules) -} /* -PROGRAM EDITING +PROGRAM WRITING */ @@ -160,7 +149,7 @@ function addModule(path) { } else { mod.state['_' + item] = mod.state[item] mod.state[item] = {} - writeStateObject(mod.state, item) + writeStateObject(mod, item) } } @@ -169,7 +158,7 @@ function addModule(path) { // now roll and return representable object // first to UI - socketSend('put rep', mod) + putRep(mod) // also to fn call, in case writing program ? return mod } else { @@ -177,15 +166,19 @@ function addModule(path) { } } -function writeStateObject(obj, item) { - Object.defineProperty(obj, item, { +function writeStateObject(mod, item) { + Object.defineProperty(mod.state, item, { set: function(x) { + // update internal value this['_' + item] = x //console.log('SET', item, this['_' + item]) + // push to internal state change handler this.emitChange(item) + // update server (or in some cases, a confirmation) + putState(mod) } }) - Object.defineProperty(obj, item, { + Object.defineProperty(mod.state, item, { get: function() { //console.log('GET', item, this['_' + item]) return this['_' + item] @@ -193,22 +186,65 @@ function writeStateObject(obj, item) { }) } -function uiChange(data) { +/* + +PROGRAM UPDATING + +*/ + +//console.log('modules at prgmem start', modules) +function putReps() { + for (mod in modules) { + putRep(modules[mod]) + } +} + +function putRep(mod) { + // dump the whole mod, rep'd as json + socketSend('put rep', mod) +} + +// update state from UI to server +function changeState(data) { // of one module // should just recv all state, walk tree for differences - var oldUi = modules[data.id].ui - var newUi = data.ui - var id = data.id - console.log(os) - for (key in os) { - if (oldUi[key] !== newUi[key]) { - oldUi[key] = newUi[key] - // should run through SET fn attached to state ! - // console.log(key, 'to ', ns[key], 'in', data.id) + var oldState = modules[data.id].state + var newState = data.state + console.log('got new state', newState) + // rep only holds proper key-values w/o emitters, _values etc + for (key in newState) { + if (isStateKey(key)) { + console.log(key) + if (oldState[key] !== newState[key]) { + console.log('changeStatz', key, 'to', newState[key], 'in', data.id) + oldState[key] = newState[key] + console.log(oldState) + // deeb bug in here, watch this: + // console.log('changeStatz', key, 'to', newState[key], 'in', data.id) + // has to do with key... going away, changing, after set? wtf is that? + } } } } +function isStateKey(key){ + if(key.indexOf('_') == 0 || key == 'emitters' || key == 'onChange' || key == 'emitChange'){ + return false + } else { + return true + } +} + +// push new state from server to UI +function putState(mod) { + // push just the state to the individual mod + var data = { + id: mod.id, + state: mod.state + } + socketSend('put state', data) +} + function putLink(data) { var fromModule = modules.find((module) => { return module.id === data.from.id @@ -226,17 +262,6 @@ function putLink(data) { console.log('new from', fromModule) } -function put(data) { - switch (data.target) { - case 'state': - // match data.id - // check match data.rep.state on internal - break - default: - console.log('put req with no recognized type', data) - } -} - function buildMenu() { var tree = {} var dir = fs.readdirSync('./src')