feat: shift+drag to cut wires and create bus connectors

Hold Shift and drag across wires to create a BUS gate that groups
them together. The cut line shows a live preview with wire count.
BUS gates are pass-through (each input maps to its output) and
render as a thin cyan bar with ports on each side.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Jose Luis
2026-03-20 04:39:00 +01:00
parent 89d118f738
commit 99f0fefe5c
6 changed files with 376 additions and 14 deletions

View File

@@ -10,6 +10,7 @@ import { getLevel } from './levels.js';
import { saveState, loadState, exportAsFile, importFromFile } from './saveLoad.js';
import { enterComponentEditor, editComponentBlueprint, exitComponentEditor, updateComponentButtons, setResizeCallback } from './components.js';
import { getExampleList, loadExample } from './examples.js';
import { createBusFromCut } from './bus.js';
const PAN_SPEED = 40;
@@ -31,6 +32,14 @@ export function initEvents() {
// Convert to world coords for gate/port detection
const world = screenToWorld(e.offsetX, e.offsetY);
// Update bus cut line endpoint
if (state.busCutting) {
state.busCutting.endX = world.x;
state.busCutting.endY = world.y;
return;
}
state.hoveredPort = findPortAt(world.x, world.y);
state.hoveredGate = state.hoveredPort ? state.hoveredPort.gate : findGateAt(world.x, world.y);
@@ -65,6 +74,19 @@ export function initEvents() {
dragStartPos = { x: e.offsetX, y: e.offsetY };
dragMoved = false;
// Shift+click on empty space → start bus cut
if (e.shiftKey && !state.placingGate) {
const port = findPortAt(world.x, world.y);
const gate = findGateAt(world.x, world.y);
if (!port && !gate) {
state.busCutting = {
startX: world.x, startY: world.y,
endX: world.x, endY: world.y
};
return;
}
}
// Placing a new gate
if (state.placingGate) {
let w = GATE_W, h = GATE_H;
@@ -132,6 +154,13 @@ export function initEvents() {
});
canvas.addEventListener('mouseup', e => {
// Finish bus cut
if (state.busCutting) {
createBusFromCut();
state.busCutting = null;
return;
}
// Toggle INPUT/CLOCK only on click (no drag movement)
if (state.dragging && !dragMoved) {
const gate = state.dragging;