From 40c8a4cb97f185f2b18c0e78f96a895b1b3fe06d Mon Sep 17 00:00:00 2001 From: alyx <> Date: Fri, 4 Feb 2022 14:02:20 +0000 Subject: Initial commit --- grapher/script.js | 288 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 288 insertions(+) create mode 100644 grapher/script.js (limited to 'grapher/script.js') diff --git a/grapher/script.js b/grapher/script.js new file mode 100644 index 0000000..6057220 --- /dev/null +++ b/grapher/script.js @@ -0,0 +1,288 @@ +var v2data; +var graph; +var searcher; +const rootel = document.documentElement; + +const chips = []; + +/* +[ + { + i: func() -> {x:Number, y:Number} |
, + o: func() -> {x:Number, y:Number} |
+ } +] +*/ +const connections = []; + +var mode; +var targ; +var start; +var wirestate; +const lastmp = {x:0,y:0}; + +const graphPos = {x:0,y:0}; + +var canvas,ctx; + +const allTypes = []; + +function switchID(el, id) { + const old = document.getElementById(id); + if (old instanceof Element) old.id = ''; + if (el instanceof Element) el .id = id; +} + +function remtopx(value) {return value * parseFloat( getComputedStyle( document.documentElement ).fontSize )} + +function renderCurveBetweenPorts(outx, outy, inx, iny) { + var dist = (((outx - inx) ** 2) + ((outy - iny) ** 2)) ** 0.5; + var heightOfCurve = Math.abs(iny - outy); + var widthOfCurve = Math.abs(inx - outx); + var halfWidth = (inx - outx)/2; + + var cpbasex = (Math.abs((widthOfCurve * 2) / dist * 10) + 60) * (heightOfCurve / 150)**0.8; + + var cp1x = outx + cpbasex; + var cp2x = inx - cpbasex; + + //point(cp1x, outy); + //point(cp2x, iny); + //point(inx - outx, outy); + + ctx.beginPath(); + ctx.moveTo(outx,outy); + ctx.bezierCurveTo(cp1x, outy, cp2x, iny, inx, iny); + ctx.moveTo(outx,outy); + ctx.closePath(); + ctx.lineWidth = 5; + ctx.stroke(); +} + +function appendTypeUI(chip) { + const data = []; + + for(const key of Object.keys(chip.typeInfo)) { + data.push(`${key}: `); + let m = newEl('select', 'typeSelect'); + m.addEventListener('change', e => { + if (e.target.value) chip.currentOverrides[key] = e.target.value; + else delete chip.currentOverrides[key] + + delConnections(chip.el.children[0].children[0]); + chip.el.children[0].children[0].remove(); + chip.el.children[0].prepend(generateChipHTML(chip.nd, chip.currentOverrides)); + }); + + for(const type of chip.typeInfo[key]) { + let opt = newEl('option'); + opt.value = (type == chip.typeInfo[key][0]) ? '' : type; + opt.innerText = type; + m.appendChild(opt); + } + data.push(m, newEl('br')) + } + + const ui = newEl('div', 'ui'); + ui.append(...data); + chip.el.append(ui); +} + + +function delConnections(el) { + let tmp = connections.filter(con => !(((con.i instanceof Node) && el.contains(con.i)) || + ((con.o instanceof Node) && el.contains(con.o)) || + (con.i == el) || (con.i == el))); + connections.length = 0; + connections.push(...tmp); +} + +window.onload = async function() { + graph = document.getElementById("graph"); + searcher = document.getElementById("searcher"); + v2data = await fetch(/*"https://raw.githubusercontent.com/tyleo-rec/CircuitsV2Resources/master/misc/circuitsv2.json"/*/"/circuitsv2.json") + .then(res => res.json()); + + allTypes.push(...ListAllTypes(v2data.Nodes).sort((a,b) => (a.toLowerCase() > b.toLowerCase()) ? 1 : -1)); + + window.onmessage = function({data}) { + if (data.type == 'newChip') { + const types = {}; + const typeParams = v2data.Nodes[data.GUID].NodeDescs[0].ReadonlyTypeParams; + for (const desc of Object.keys(typeParams)) + types[desc] = [ + `${desc}: ${typeParams[desc]}`, + ...(typeParams[desc] == 'any' ? allTypes : typeParams[desc].match(/^\((.+)\)$/)[1].split(' | ')) + ]; + + const ne = newEl('div', 'chipbox'); + const chipcontainer = newEl('div', 'selUI'); + chipcontainer.append(generateChipHTML(v2data.Nodes[data.GUID].NodeDescs)); + ne.append(chipcontainer); + graph.append(ne); + const chip = { + el: ne, + typeInfo: types, + currentOverrides: [], + nd: v2data.Nodes[data.GUID].NodeDescs + }; + appendTypeUI(chip); + chips.push(chip); + console.log(types); + } + } + + graph.addEventListener('mousedown', function(e) { + if (e.button == 0) { + start = performance.now(); + targ = e.target; + if (e.target.parentElement.matches('.input')) { + if (!e.target.matches('.exec')) delConnections(e.target); + mode = 'wire_i-o'; + wirestate = { + i: e.target, + o: lastmp + }; + connections.push(wirestate); + } + + else if (e.target.parentElement.matches('.output')) { + if (e.target.matches('.exec')) delConnections(e.target); + mode = 'wire_o-i'; + wirestate = { + i: lastmp, + o: e.target + }; + connections.push(wirestate); + } + + else if (targ = ( + () => { + for (const node of chips) if (node.el.contains(e.target)) return node.el; + return false; + })() + ) + mode = 'drag'; + + else if (e.target == graph) switchID(null, 'selected') + } + }); + + rootel.addEventListener("mouseup", e => { + if (e.button == 0) { + switch (mode) { + case 'wire_i-o': + if (e.target.matches('.exec')) delConnections(e.target); + wirestate.o = e.target; + if (!e.target.parentElement.matches('.output')) + connections.pop(); + else if (wirestate.i.nextElementSibling.innerText != wirestate.o.nextElementSibling.innerText) + connections.pop(); + break; + case 'wire_o-i': + if (!e.target.matches('.exec')) delConnections(e.target); + wirestate.i = e.target; + if (!e.target.parentElement.matches('.input')) + connections.pop(); + else if (wirestate.i.nextElementSibling.innerText != wirestate.o.nextElementSibling.innerText) + connections.pop(); + break; + case 'drag': + if ((performance.now() - start) < 150 && !targ.children[0].matches('#selected')) { + switchID(targ.children[0], 'selected') + } + break; + } + mode = null; + } + }); + + rootel.addEventListener("mousemove", e => { + if (e.buttons & 4) { + graphPos.x += e.clientX - lastmp.x; + graphPos.y += e.clientY - lastmp.y; + graph.style.setProperty('--graphOffsetX', graphPos.x); + graph.style.setProperty('--graphOffsetY', graphPos.y); + } + switch (mode) { + case 'drag': + let newchipx = Number(targ.style.getPropertyValue('--chipOffsetX')) + e.clientX - lastmp.x; + let newchipy = Number(targ.style.getPropertyValue('--chipOffsetY')) + e.clientY - lastmp.y; + targ.style.setProperty('--chipOffsetX', newchipx); + targ.style.setProperty('--chipOffsetY', newchipy); + break; + } + lastmp.x = e.clientX; + lastmp.y = e.clientY; + }); + + + root.addEventListener("mousemove", e => { + root.style.setProperty('--mouse-x', (e.clientX - graphPos.x - searcher.clientWidth) + "px"); + root.style.setProperty('--mouse-y', (e.clientY - graphPos.y) + "px"); + }); + + function deleteSel() { + let sel = document.getElementById("selected").parentElement; + if (!sel) return; + delConnections(sel); + { + let tmp = chips.filter(chip => !(chip.el == sel)); + chips.length = 0; + chips.push(...tmp); + } + sel.remove(); + } + + root.addEventListener("keydown", e => { + switch (e.code) { + case 'Delete': + deleteSel(); + break; + } + }); + + + canvas = document.getElementById('canvas'); + ctx = canvas.getContext('2d'); + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + + window.addEventListener("resize", e => { + canvas.width = window.innerWidth; + canvas.height = window.innerHeight; + }); + + (async function updateanim(t) { + + + ctx.clearRect(0,0,window.innerWidth,window.innerHeight); + for(const wire of connections) { + const points = []; + + for (const point of [wire.o, wire.i]) { + if (point instanceof Element) { + let rects = point.getClientRects()[0]; + points.push(point == wire.i ? rects.left - remtopx(2) : rects.right + remtopx(1.5)); + points.push((rects.top + rects.bottom) / 2); + } else { + points.push(point.x); + points.push(point.y); + } + } + + if ((((points[0] >= -10) && (points[0] <= window.innerWidth)) && + ((points[1] >= -10) && (points[1] <= window.innerHeight))) || + (((points[2] >= -10) && (points[2] <= window.innerWidth)) && + ((points[3] >= -10) && (points[3] <= window.innerHeight)))) { + + var m = null; + for (const cls of (wire.i instanceof Element ? wire.i : wire.o).classList) m = m || portColors[cls]; + ctx.strokeStyle = m; + renderCurveBetweenPorts(...points); + } + } + + requestAnimationFrame(updateanim); + })() +} -- cgit v1.2.3-54-g00ecf