81 lines
2.9 KiB
JavaScript
81 lines
2.9 KiB
JavaScript
/*
|
|
* Copyright (c) 2025-2026 Taras Greben
|
|
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Commercial-pcb-retrace
|
|
* See LICENSE file for details.
|
|
*/
|
|
|
|
// ── State ─────────────────────────────────────────────────────
|
|
// Single mutable app state object. All modules share this reference.
|
|
export const S = {
|
|
components: [], // [{id, ref, value, type, x, y, rotation, flipX, pins:[{name,net}], pcbX, pcbY}]
|
|
nets: [], // [{name, nodes:[{ref,pin}], color, isWip}]
|
|
wires: [], // [{id, net, points:[{x,y}], pinA, pinB}]
|
|
|
|
// Viewport
|
|
viewX: 0, viewY: 0, zoom: 1,
|
|
|
|
// Interaction
|
|
dragging: null, // {compId, ox, oy}
|
|
wireDrag: null, // unused after WireBender migration, kept for compat
|
|
panning: false,
|
|
panStart: null, // {x, y, vx, vy}
|
|
|
|
// Selection
|
|
selectedComp: null,
|
|
selectedWire: null, // {wireId, segIdx, axis}
|
|
selectedNet: null,
|
|
|
|
// Hover
|
|
hoverComp: null,
|
|
hoverWireSeg: null, // {wireId, segIdx, axis}
|
|
|
|
// History (undo)
|
|
history: [],
|
|
|
|
// Junction dots — written by layout.js after each route
|
|
junctionPoints: [], // [{x, y, net}]
|
|
|
|
// Component label hints from WireBender
|
|
componentLabels: {}, // { [compId]: ComponentLabelHint }
|
|
|
|
hasData: false,
|
|
};
|
|
|
|
// ── Global constants ─────────────────────────────────────────
|
|
export const GRID = 20; // snap grid, px
|
|
export const MARGIN = 10; // routing clearance around component bodies, px
|
|
|
|
export const NET_COLORS = [
|
|
'#00e5a0', '#00a8ff', '#ff6b35', '#f0c040', '#a78bfa',
|
|
'#f472b6', '#34d399', '#fb923c', '#60a5fa', '#4ade80',
|
|
'#e879f9', '#2dd4bf', '#fbbf24', '#f87171', '#818cf8',
|
|
];
|
|
|
|
// ── Canvas context (set once by app.js after DOM ready) ───────
|
|
export let canvas, ctx;
|
|
export function initCanvas(canvasEl) {
|
|
canvas = canvasEl;
|
|
ctx = canvasEl.getContext('2d');
|
|
// console.log('[schema] initCanvas:', canvasEl, 'ctx:', !!ctx);
|
|
}
|
|
|
|
// ── Coordinate helpers ────────────────────────────────────────
|
|
export const s2w = (sx, sy) => ({
|
|
x: (sx - canvas.width / 2 - S.viewX) / S.zoom,
|
|
y: (sy - canvas.height / 2 - S.viewY) / S.zoom,
|
|
});
|
|
export const w2s = (wx, wy) => ({
|
|
x: wx * S.zoom + canvas.width / 2 + S.viewX,
|
|
y: wy * S.zoom + canvas.height / 2 + S.viewY,
|
|
});
|
|
export const snap = v => Math.round(v / GRID) * GRID;
|
|
|
|
// ── Net color lookup ──────────────────────────────────────────
|
|
export function getNetColor(name) {
|
|
const net = S.nets.find(x => x.name === name);
|
|
if (net?.color) return net.color;
|
|
// Fallback: stable hash so same name always gets same color
|
|
let h = 0;
|
|
for (const c of (name || '')) h = (h * 31 + c.charCodeAt(0)) & 0xffff;
|
|
return NET_COLORS[h % NET_COLORS.length];
|
|
}
|