Refactor: merge duplicated rules, split the largest files by topic (t21)
- One helper each for wall and mold refunds, tube edges and lanes, pipe text, piece dimensions, font lookup, reach circles and surface averaging. - previews, smooth, notebook, materials, worldgen and selection split into topic files (preview-drill, preview-selection, smooth-shaders, notebook-market, notebook-blueprints, material-tables, worldgen-helpers, selection-pickers, selection-panels). - Every suite's output identical apart from timings; seeds make the same worlds. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,80 @@
|
||||
// Selection previews: labelled tags, copy and cut boxes, and paste ghosts.
|
||||
// a small labelled tag drawn on the world (screen pixels)
|
||||
function drawTag(text, col, x, y, sub) {
|
||||
const ctx = R.ctx, u = Math.max(1, R.canvas.width / window.innerWidth);
|
||||
renderMonoFont();
|
||||
ctx.save();
|
||||
ctx.font = `700 ${Math.round(11 * u)}px ${R.monoFont}`; ctx.textBaseline = 'middle';
|
||||
const tw = ctx.measureText(text).width;
|
||||
ctx.font = `500 ${Math.round(11 * u)}px ${R.monoFont}`;
|
||||
const sw = sub ? ctx.measureText(sub).width + 8 * u : 0;
|
||||
const h = Math.round(19 * u), pad = 7 * u, w = tw + sw + pad * 2;
|
||||
x = Math.max(2, Math.min(R.canvas.width - w - 2, x)); y = Math.max(2, Math.min(R.canvas.height - h - 2, y));
|
||||
ctx.fillStyle = 'rgba(14,12,11,0.9)'; ctx.fillRect(x, y, w, h);
|
||||
ctx.fillStyle = `rgb(${col})`; ctx.fillRect(x, y, 3 * u, h);
|
||||
ctx.strokeStyle = `rgba(${col},0.8)`; ctx.lineWidth = u; ctx.strokeRect(x + u / 2, y + u / 2, w - u, h - u);
|
||||
ctx.font = `700 ${Math.round(11 * u)}px ${R.monoFont}`; ctx.fillStyle = `rgb(${col})`; ctx.fillText(text, x + pad, y + h / 2 + u * 0.5);
|
||||
if (sub) { ctx.font = `500 ${Math.round(11 * u)}px ${R.monoFont}`; ctx.fillStyle = 'rgba(231,220,203,0.9)'; ctx.fillText(sub, x + pad + tw + 8 * u, y + h / 2 + u * 0.5); }
|
||||
ctx.restore();
|
||||
}
|
||||
// Copy (teal) and cut (red, hatched): the box being dragged, what it would pick up, and a tag
|
||||
const SEL_COL = { copy: '92,186,166', cut: '239,106,85' };
|
||||
function drawSelection(mode, ax, ay) {
|
||||
const ctx = R.ctx, zp = R.zp, col = SEL_COL[mode], sd = GAME.selDrag;
|
||||
const sx = sd ? sd.x : ax, sy = sd ? sd.y : ay;
|
||||
const a = blockOf(Math.min(sx, ax), Math.min(sy, ay)), c = blockOf(Math.max(sx, ax), Math.max(sy, ay));
|
||||
const bw = c.bx - a.bx + 1, bh = c.by - a.by + 1;
|
||||
drawGrid(blockOf(ax, ay).bx, blockOf(ax, ay).by, 7);
|
||||
ctx.save();
|
||||
// what is inside: built blocks, and machines and molds that fit wholly inside
|
||||
let n = 0;
|
||||
if (sd) {
|
||||
ctx.fillStyle = `rgba(${col},${mode === 'cut' ? 0.42 : 0.3})`;
|
||||
for (let by = a.by; by <= c.by; by++) for (let bx = a.bx; bx <= c.bx; bx++) {
|
||||
if (bx < 0 || by < 0 || bx >= BW || by >= BH) continue;
|
||||
const b = by * BW + bx;
|
||||
if (blockP[b] && blockIntegrity(b) >= 8) { const [x, y, w, h] = blockRectPx(bx, by, 1, 1); ctx.fillRect(x, y, w, h); n++; }
|
||||
}
|
||||
ctx.strokeStyle = `rgba(${col},0.95)`; ctx.lineWidth = Math.max(1, zp * 0.35);
|
||||
for (const mm of machines) {
|
||||
if (!mm || PIECE_BY_ID[mm.type].fixed) continue;
|
||||
const P = PIECE_BY_ID[mm.type], mbx = mm.x / BS, mby = mm.y / BS;
|
||||
if (mbx >= a.bx && mby >= a.by && mbx + P.bw - 1 <= c.bx && mby + P.bh - 1 <= c.by) { const [x, y, w, h] = blockRectPx(mbx, mby, P.bw, P.bh); ctx.fillRect(x, y, w, h); ctx.strokeRect(x, y, w, h); n++; }
|
||||
}
|
||||
for (const mo of molds) {
|
||||
const md = MOLDS[mo.kind], mbx = mo.x / BS, mby = mo.y / BS;
|
||||
if (mbx >= a.bx && mby >= a.by && mbx + md.bw - 1 <= c.bx && mby + md.bh - 1 <= c.by) { const [x, y, w, h] = blockRectPx(mbx, mby, md.bw, md.bh); ctx.fillRect(x, y, w, h); ctx.strokeRect(x, y, w, h); n++; }
|
||||
}
|
||||
}
|
||||
const [x, y, w, h] = blockRectPx(a.bx, a.by, bw, bh);
|
||||
ctx.fillStyle = `rgba(${col},0.08)`; ctx.fillRect(x, y, w, h);
|
||||
if (mode === 'cut') {
|
||||
// red hatching: this will be taken down
|
||||
ctx.save(); ctx.beginPath(); ctx.rect(x, y, w, h); ctx.clip();
|
||||
ctx.strokeStyle = `rgba(${col},0.35)`; ctx.lineWidth = Math.max(1, zp * 0.25);
|
||||
const step = Math.max(8, zp * 2.5);
|
||||
ctx.beginPath(); for (let k = -h; k < w; k += step) { ctx.moveTo(x + k, y + h); ctx.lineTo(x + k + h, y); } ctx.stroke();
|
||||
ctx.restore();
|
||||
}
|
||||
ctx.strokeStyle = `rgba(${col},0.98)`; ctx.lineWidth = Math.max(1.5, zp * (mode === 'cut' ? 0.45 : 0.35));
|
||||
ctx.setLineDash([zp * 1.2, zp * 0.8]); ctx.lineDashOffset = -(R.frame * 0.4) % (zp * 2);
|
||||
ctx.strokeRect(x, y, w, h); ctx.setLineDash([]); ctx.lineDashOffset = 0;
|
||||
ctx.restore();
|
||||
const label = mode === 'cut' ? '✂ CUT' : '⧉ COPY';
|
||||
const sub = !sd ? 'drag a box' : n ? (mode === 'cut' ? `${plural(n, 'piece')} · let go to take down` : `${plural(n, 'piece')} · let go to copy`) : 'nothing built in here';
|
||||
drawTag(label, col, x, y - Math.round(23 * Math.max(1, R.canvas.width / window.innerWidth)), sub);
|
||||
}
|
||||
// Pasting: the clipboard follows the cursor, snapped to the grid
|
||||
function drawPastePreview() {
|
||||
const ctx = R.ctx, zp = R.zp, bp = GAME.clip, { bx: ox, by: oy } = stampOrigin(bp.bw, bp.bh);
|
||||
drawGrid(aimBlock().bx, aimBlock().by, 7);
|
||||
ctx.save();
|
||||
const [x, y, w, h] = blockRectPx(ox, oy, bp.bw, bp.bh);
|
||||
ctx.strokeStyle = 'rgba(92,186,166,0.85)'; ctx.setLineDash([zp, zp]); ctx.lineWidth = Math.max(1, zp * 0.3);
|
||||
ctx.strokeRect(x, y, w, h); ctx.setLineDash([]);
|
||||
for (const [dx, dy, code, v] of bp.blocks) { const [bx2, by2, bw2, bh2] = blockRectPx(ox + dx, oy + dy, 1, 1); ctx.fillStyle = `rgba(${previewColor(code, v)},0.5)`; ctx.fillRect(bx2, by2, bw2, bh2); }
|
||||
for (const [type, dx, dy] of bp.machines) { const P = PIECE_BY_ID[type]; const [mx, my, mw, mh] = blockRectPx(ox + dx, oy + dy, P.bw, P.bh); ctx.strokeStyle = 'rgba(255,210,122,0.8)'; ctx.strokeRect(mx, my, mw, mh); }
|
||||
for (const [k, dx, dy] of bp.molds) { const md = MOLDS[k]; const [mx, my, mw, mh] = blockRectPx(ox + dx, oy + dy, md.bw, md.bh); ctx.strokeStyle = 'rgba(255,190,90,0.8)'; ctx.strokeRect(mx, my, mw, mh); }
|
||||
ctx.restore();
|
||||
drawTag('PASTE', '92,186,166', x, y - Math.round(23 * Math.max(1, R.canvas.width / window.innerWidth)), 'click to place · R flips · Esc stops');
|
||||
}
|
||||
Reference in New Issue
Block a user