diff --git a/viewer/index.html b/viewer/index.html index 423c2f4..ffcfe8f 100644 --- a/viewer/index.html +++ b/viewer/index.html @@ -149,7 +149,7 @@ h2 { font-size: var(--prism-type-body-sm); line-height: var(--prism-lh-title); f /* 버튼 — primary 화면당 1개 (BT-1), 히트 영역 44px (HT-1) */ button { font: inherit; font-size: var(--prism-type-body-sm); font-weight: 500; line-height: 1.2; - min-height: 2.75rem; padding: var(--prism-space-050) var(--prism-space-100); white-space: nowrap; + min-height: 2.25rem; padding: var(--prism-space-050) var(--prism-space-100); white-space: nowrap; border: var(--prism-stroke-hairline) solid var(--prism-border-default); border-radius: var(--prism-radius-md); background: var(--prism-bg-card); color: var(--prism-text-body); cursor: pointer; } @@ -420,11 +420,22 @@ let selected = null, isolate = false; const hiddenSel = new Set(); let world = null; +// 지보패턴별 색: 패턴 순번(측점 순)마다 dv 토큰을 쓰고, 7번째부터는 배경과 50% 혼합한 명도 차로 구분 +const patIdx = {}; +function patCss(p) { const k = patIdx[p] ?? 0; return 'color-mix(in srgb, var(--prism-dv-' + (k % 6 + 1) + ') ' + (k >= 6 ? 50 : 100) + '%, var(--prism-bg-canvas))'; } +function patColor(p) { + const k = patIdx[p] ?? 0; + const c = new THREE.Color(tok('--prism-dv-' + (k % 6 + 1))); + if (k >= 6) c.lerp(new THREE.Color(tok('--prism-bg-canvas')), 0.5); + return c; +} + function refreshColors() { scene.background = new THREE.Color(tok('--prism-bg-canvas')); for (const m of meshes) { - const p = PART[m.userData.group]; - m.material.color.set(tok(p ? p.token : '--prism-text-subtle')); + const u = m.userData, p = PART[u.group]; + if (u.group === '라이닝' && u.pattern) m.material.color.copy(patColor(u.pattern)); + else m.material.color.set(tok(p ? p.token : '--prism-text-subtle')); } if (selected) selected.material.emissive.set(tok('--prism-text-heading')); } @@ -563,11 +574,16 @@ Promise.all([ refreshColors(); // 지보패턴 체크박스 - const pats = [...new Set(meta.components.filter((x) => x.pattern).map((x) => x.pattern))]; + const firstFrom = {}; + for (const c of meta.components) if (c.pattern && c.from_sta != null) firstFrom[c.pattern] = Math.min(firstFrom[c.pattern] ?? Infinity, c.from_sta); + const pats = Object.keys(firstFrom).sort((a, b) => firstFrom[a] - firstFrom[b]); + pats.forEach((p, i) => { patIdx[p] = i; }); + refreshColors(); for (const p of pats) { patternOn[p] = true; const lab = document.createElement('label'); lab.className = 'opt'; const cb = document.createElement('input'); cb.type = 'checkbox'; cb.checked = true; + cb.style.accentColor = patCss(p); cb.addEventListener('change', () => { patternOn[p] = cb.checked; applyVisibility(); }); const span = document.createElement('span'); span.textContent = p; lab.append(cb, span); $('pats').appendChild(lab);