chatcad / static /pro_ui.js
Samarjithbiswas's picture
Commercial overhaul: clean glass+taillight boundaries (conforming split), model-locked AI render (ControlNet img2img + paint tint), gesture control, workshop disassembly, part info cards, pro UI + new How-it-works
9032518 verified
Raw
History Blame Contribute Delete
4.89 kB
// pro_ui.js β€” injects a professional monochrome SVG icon set into the Car
// Studio panel and toolbar (COMSOL/ANSYS-style), and strips emoji from button
// labels. Pure presentation: no behaviour is touched.
(function () {
const P = { // 24x24 stroke paths, keyed by icon name
car: 'M4 15l1.5-4.5A2 2 0 0 1 7.4 9h9.2a2 2 0 0 1 1.9 1.5L20 15M4 15h16v3h-2M4 15v3h2m0 0a2 2 0 1 0 4 0m-4 0a2 2 0 1 1 4 0m4 0h4m0 0a2 2 0 1 0 4 0 2 2 0 0 0-4 0z',
roofDown: 'M12 3v10m0 0l-4-4m4 4l4-4M4 20h16',
roofUp: 'M12 21V11m0 0l-4 4m4-4l4 4M4 4h16',
resizeH: 'M3 12h18M7 8l-4 4 4 4M17 8l4 4-4 4',
resizeV: 'M12 3v18M8 7l4-4 4 4M8 17l4 4 4-4',
eye: 'M2 12s3.5-6 10-6 10 6 10 6-3.5 6-10 6-10-6-10-6z M12 9a3 3 0 1 0 0 6 3 3 0 0 0 0-6z',
search: 'M11 4a7 7 0 1 0 0 14 7 7 0 0 0 0-14zM21 21l-4.5-4.5',
wind: 'M3 8h9a3 3 0 1 0-3-3M3 12h13a3 3 0 1 1-3 3M3 16h7',
gauge: 'M12 4a8 8 0 0 0-8 8h4m8-8a8 8 0 0 1 8 8h-4M12 12l3-4M12 12a1.5 1.5 0 1 0 .01 0z',
layers: 'M12 3l9 5-9 5-9-5 9-5zM3 13l9 5 9-5M3 17l9 5 9-5',
sound: 'M4 10v4h4l5 4V6l-5 4H4zM16 9a4 4 0 0 1 0 6M18.5 6.5a8 8 0 0 1 0 11',
shield: 'M12 3l8 3v6c0 4.5-3.5 8-8 9-4.5-1-8-4.5-8-9V6l8-3z',
map: 'M9 4l6 2 6-2v14l-6 2-6-2-6 2V6l6-2zM9 4v14M15 6v14',
sliders: 'M4 8h10M18 8h2M4 16h4M12 16h8M14 5v6M8 13v6',
morph: 'M4 18c0-6 4-10 8-10s8 4 8 10M4 18h16M8 8a4 4 0 1 1 8 0',
play: 'M6 4l14 8-14 8V4z',
waves: 'M2 8c2-2 4-2 6 0s4 2 6 0 4-2 6 0M2 14c2-2 4-2 6 0s4 2 6 0 4-2 6 0',
camera: 'M4 8h3l2-3h6l2 3h3v11H4V8zM12 11a3.5 3.5 0 1 0 0 7 3.5 3.5 0 0 0 0-7z',
wand: 'M6 18L18 6M14 6h4v4M4 10l1-2 2-1-2-1-1-2-1 2-2 1 2 1 1 2zM19 15l.7-1.4L21 13l-1.3-.6L19 11l-.7 1.4L17 13l1.3.6L19 15z',
dots: 'M6 6h.01M12 6h.01M18 6h.01M6 12h.01M12 12h.01M18 12h.01M6 18h.01M12 18h.01M18 18h.01',
cube: 'M12 2l9 5v10l-9 5-9-5V7l9-5zM12 12l9-5M12 12v10M12 12L3 7',
grid: 'M4 4h16v16H4zM4 10h16M4 16h16M10 4v16M16 4v16',
xray: 'M12 3a9 9 0 1 0 0 18 9 9 0 0 0 0-18zM12 7v10M8 9.5h8M9 14h6',
hand: 'M14 6.5a2 2 0 1 1 4 0V11M10 6a2 2 0 1 1 4 0v5M6 8a2 2 0 1 1 4 0v4M6 12v3c0 3.5 2.5 6 6 6s6-2.5 6-6v-4',
wrench: 'M14.7 6.3a4.5 4.5 0 0 0-6.4 6.4l-4.6 4.6a1.5 1.5 0 0 0 2.1 2.1l4.6-4.6a4.5 4.5 0 0 0 6.4-6.4l-2.8 2.8-2.1-2.1 2.8-2.8z',
pencil: 'M4 20l1-4L17 4l3 3-12 12-4 1zM14 7l3 3',
crash: 'M12 3l2.1 4.7 5.1.5-3.8 3.4 1.1 5-4.5-2.6-4.5 2.6 1.1-5L4.8 8.2l5.1-.5L12 3z',
live: 'M3 12h4l3-8 4 16 3-8h4',
};
const svg = (name) => {
const s = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
s.setAttribute('viewBox', '0 0 24 24'); s.classList.add('pro-ic');
const p = document.createElementNS('http://www.w3.org/2000/svg', 'path');
p.setAttribute('d', P[name]); s.appendChild(p); return s;
};
// Car Studio buttons: match by label text (first match wins)
const RULES = [
[/^(sedan|coupe|suv|wagon)$/i, 'car'],
[/lower roof/i, 'roofDown'], [/raise roof/i, 'roofUp'],
[/longer|shorter|wider|narrower/i, 'resizeH'],
[/taller|^lower$/i, 'resizeV'],
[/interior|exterior/i, 'eye'], [/inspect/i, 'search'],
[/drag from image/i, 'camera'], [/drag/i, 'wind'],
[/pressure/i, 'gauge'], [/wall shear/i, 'layers'],
[/nvh/i, 'sound'], [/crash/i, 'crash'],
[/retrieve/i, 'search'], [/interpolate/i, 'sliders'],
[/design map/i, 'map'], [/deepsdf/i, 'morph'],
[/real cfd|openfoam/i, 'play'], [/flow field|wind flow/i, 'waves'],
[/live aero/i, 'live'],
[/photoreal/i, 'camera'], [/style render/i, 'wand'],
[/point cloud/i, 'dots'], [/solid mesh/i, 'cube'],
[/wireframe/i, 'grid'], [/x-?ray/i, 'xray'], [/shaded/i, 'cube'],
];
const EMOJI = /^[\s\u{1F000}-\u{1FAFF}\u{2600}-\u{27BF}\u{2B00}-\u{2BFF}\u{FE0F}\u{200D}βœοΈπŸ–πŸ”§πŸš—πŸ“·βœ¦πŸ’₯πŸŒ€πŸŽ¨]+/u;
function decorate() {
document.querySelectorAll('#carStudio .cs-btn').forEach(b => {
if (b.querySelector('svg.pro-ic')) return;
const label = b.textContent.trim();
for (const [re, ic] of RULES) {
if (re.test(label)) {
b.textContent = label.replace(EMOJI, '');
b.prepend(svg(ic));
break;
}
}
});
// toolbar buttons that still use emoji -> proper icons
const TB = { gestureBtn: 'hand', disasmBtn: 'wrench',
carSketchBtn: 'car', freehandPadBtn: 'pencil' };
for (const [id, ic] of Object.entries(TB)) {
const b = document.getElementById(id);
if (!b || b.querySelector('svg.pro-ic')) continue;
b.textContent = b.textContent.replace(EMOJI, '').trim();
b.prepend(svg(ic));
}
}
if (document.readyState === 'loading')
document.addEventListener('DOMContentLoaded', decorate);
else decorate();
// re-decorate when dynamic UI (e.g. parts panel) rebuilds buttons
setInterval(decorate, 4000);
})();