asdfg
This commit is contained in:
parent
f6d7412744
commit
091afc2b5c
77 changed files with 4405 additions and 8223 deletions
|
|
@ -395,13 +395,23 @@
|
|||
result.boardId = board.id || "";
|
||||
result.direction = port.direction;
|
||||
result.signalActive = port.direction === "output" ? Boolean(board._circuitOutputState?.[port.id]) : Boolean(board._circuitInputState?.[port.id]);
|
||||
result._signalDetectorSources = port.direction === "output"
|
||||
? [...(board._circuitOutputDetectorSources?.[port.id] || [])]
|
||||
: [...(board._circuitInputDetectorSources?.[port.id] || [])];
|
||||
return result;
|
||||
}
|
||||
|
||||
function evaluate(board, inputValues = null) {
|
||||
function evaluate(board, inputValues = null, inputProvenance = null) {
|
||||
const config = ensureConfig(board);
|
||||
const inputs = Object.create(null);
|
||||
for (const port of config.inputs) inputs[port.id] = Boolean(inputValues ? inputValues[port.id] : board?._circuitInputState?.[port.id]);
|
||||
const inputDetectorSources = Object.create(null);
|
||||
for (const port of config.inputs) {
|
||||
inputs[port.id] = Boolean(inputValues ? inputValues[port.id] : board?._circuitInputState?.[port.id]);
|
||||
const rawSources = inputProvenance ? inputProvenance[port.id] : board?._circuitInputDetectorSources?.[port.id];
|
||||
inputDetectorSources[port.id] = inputs[port.id]
|
||||
? [...new Set(Array.isArray(rawSources) ? rawSources.filter(Boolean) : [])]
|
||||
: [];
|
||||
}
|
||||
|
||||
const parent = new Map();
|
||||
const rank = new Map();
|
||||
|
|
@ -511,18 +521,74 @@
|
|||
return Boolean(value);
|
||||
}
|
||||
|
||||
const netDetectorSources = new Map();
|
||||
const nodeDetectorSources = Object.create(null);
|
||||
const visitingSourceNodes = new Set();
|
||||
const visitingSourceNets = new Set();
|
||||
const unionSources = (...lists) => [...new Set(lists.flatMap(list => Array.isArray(list) ? list : []))];
|
||||
|
||||
function driverDetectorSources(token) {
|
||||
if (token.startsWith("i:")) {
|
||||
const id = token.slice(2);
|
||||
return inputs[id] ? inputDetectorSources[id] || [] : [];
|
||||
}
|
||||
const match = /^n:([^:]+):o$/.exec(token);
|
||||
return match ? nodeSourceValue(match[1]) : [];
|
||||
}
|
||||
|
||||
function netSourceValue(token) {
|
||||
const root = find(token);
|
||||
if (netDetectorSources.has(root)) return netDetectorSources.get(root);
|
||||
if (visitingSourceNets.has(root)) return [];
|
||||
visitingSourceNets.add(root);
|
||||
let sources = [];
|
||||
for (const member of members.get(root) || [token]) {
|
||||
if ((member.startsWith("i:") || /^n:[^:]+:o$/.test(member)) && driverValue(member)) {
|
||||
sources = unionSources(sources, driverDetectorSources(member));
|
||||
}
|
||||
}
|
||||
visitingSourceNets.delete(root);
|
||||
netDetectorSources.set(root, sources);
|
||||
return sources;
|
||||
}
|
||||
|
||||
function nodeSourceValue(id) {
|
||||
if (Object.prototype.hasOwnProperty.call(nodeDetectorSources, id)) return nodeDetectorSources[id];
|
||||
if (visitingSourceNodes.has(id) || !nodeValue(id)) return [];
|
||||
const node = nodeMap.get(id);
|
||||
if (!node || unstableNodes.has(id) || node.type === "on" || node.type === "not") {
|
||||
nodeDetectorSources[id] = [];
|
||||
return [];
|
||||
}
|
||||
visitingSourceNodes.add(id);
|
||||
let sources = netSourceValue(`n:${id}:a`);
|
||||
if (node.type === "and") sources = unionSources(sources, netSourceValue(`n:${id}:b`));
|
||||
visitingSourceNodes.delete(id);
|
||||
nodeDetectorSources[id] = sources;
|
||||
return sources;
|
||||
}
|
||||
|
||||
const outputs = Object.create(null);
|
||||
for (const port of config.outputs) outputs[port.id] = netValue(`o:${port.id}`);
|
||||
const outputDetectorSources = Object.create(null);
|
||||
for (const port of config.outputs) {
|
||||
outputs[port.id] = netValue(`o:${port.id}`);
|
||||
outputDetectorSources[port.id] = outputs[port.id] ? netSourceValue(`o:${port.id}`) : [];
|
||||
}
|
||||
if (board) {
|
||||
board._circuitInputState = inputs;
|
||||
board._circuitInputDetectorSources = inputDetectorSources;
|
||||
board._circuitNodeState = nodeValues;
|
||||
board._circuitOutputState = outputs;
|
||||
board._circuitOutputDetectorSources = outputDetectorSources;
|
||||
for (const port of config.outputs) {
|
||||
const term = terminal(board, `o:${port.id}`);
|
||||
if (term) term.signalActive = Boolean(outputs[port.id]);
|
||||
if (term) {
|
||||
term.signalActive = Boolean(outputs[port.id]);
|
||||
term._signalDetectorSources = [...(outputDetectorSources[port.id] || [])];
|
||||
}
|
||||
}
|
||||
}
|
||||
return { inputs, nodes: nodeValues, outputs };
|
||||
return { inputs, nodes: nodeValues, outputs, inputDetectorSources, outputDetectorSources };
|
||||
}
|
||||
|
||||
function nearestPin(config, x, y, maxDistance = 17) {
|
||||
|
|
@ -698,7 +764,11 @@
|
|||
dialog = document.createElement("div");
|
||||
dialog.id = "circuitBoardEditor";
|
||||
dialog.className = "rotator-editor circuit-grid-editor hidden";
|
||||
dialog.innerHTML = `<div class="rotator-editor-panel circuit-grid-panel" role="dialog" aria-modal="true" aria-labelledby="circuitBoardTitle">
|
||||
dialog.setAttribute("role", "dialog");
|
||||
dialog.setAttribute("aria-modal", "true");
|
||||
dialog.setAttribute("aria-labelledby", "circuitBoardTitle");
|
||||
dialog.setAttribute("aria-hidden", "true");
|
||||
dialog.innerHTML = `<div class="rotator-editor-panel circuit-grid-panel">
|
||||
<div class="rotator-editor-titlebar"><h2 id="circuitBoardTitle">\u57fa\u76e4</h2><button class="rotator-editor-close" type="button" data-action="close" aria-label="\u9589\u3058\u308b">\u00d7</button></div>
|
||||
<div class="circuit-port-count-controls">
|
||||
<label>\u6a2a\u5e45 <button type="button" data-grid-delta="cols:-1">\u2212</button><input id="circuitGridCols" type="number" min="${MIN_COLS}" max="${MAX_COLS}" step="1"><button type="button" data-grid-delta="cols:1">\uff0b</button></label>
|
||||
|
|
@ -1089,12 +1159,16 @@
|
|||
dialog.querySelector("[data-action=clear]").onclick = () => { snapshot(); draft.nodes = []; draft.wires = []; draw(); };
|
||||
dialog.querySelector("[data-action=reset]").onclick = () => { snapshot(); draft = defaultConfig(); syncControls(); resizeCanvas(); draw(); };
|
||||
const close = () => {
|
||||
dialog.classList.add("hidden");
|
||||
if (global.TarinaiManagedDialogs?.close) global.TarinaiManagedDialogs.close(dialog);
|
||||
else { dialog.classList.add("hidden"); dialog.setAttribute("aria-hidden", "true"); }
|
||||
document.removeEventListener("keydown", handleEditorKeydown, true);
|
||||
canvas.onpointerdown = null; canvas.onpointermove = null; canvas.onpointerup = null; canvas.onpointercancel = null; canvas.onpointerleave = null; canvas.oncontextmenu = null;
|
||||
};
|
||||
dialog.querySelector("[data-action=close]").onclick = close;
|
||||
dialog.querySelector("[data-action=cancel]").onclick = close;
|
||||
if (dialog._tarinaiCloseRequestHandler) dialog.removeEventListener("tarinai:dialog-close-request", dialog._tarinaiCloseRequestHandler);
|
||||
dialog._tarinaiCloseRequestHandler = close;
|
||||
dialog.addEventListener("tarinai:dialog-close-request", close);
|
||||
dialog.querySelector("[data-action=save]").onclick = () => {
|
||||
applySerializedConfig(board, draft); evaluate(board); remapAttachedWireEndpoints(board, worldRef);
|
||||
if (worldRef) { worldRef.drawListDirty = true; worldRef.markSpatialDirty?.("circuit-board-edited"); }
|
||||
|
|
@ -1102,7 +1176,10 @@
|
|||
global.render?.(); close();
|
||||
};
|
||||
dialog.onclick = event => { if (event.target === dialog) close(); };
|
||||
syncControls(); resizeCanvas(); setTool("wire"); dialog.classList.remove("hidden"); draw();
|
||||
syncControls(); resizeCanvas(); setTool("wire");
|
||||
if (global.TarinaiManagedDialogs?.open) global.TarinaiManagedDialogs.open(dialog, document.activeElement);
|
||||
else { dialog.classList.remove("hidden"); dialog.setAttribute("aria-hidden", "false"); }
|
||||
draw();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue