feat(view): colour the ③ 3D rebar by diameter or by member, with a legend
Role colours stay the default (spec §6.7). A control on ③ switches to diameter (nominal size, H and S of one size share a colour, Okabe–Ito palette) or member (받침블럭 · 코핑 · 기둥 · 확대기초). The legend lists only the items the model has. Highlighting and the state colours are unchanged. Approved 2026-10-23. Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
5d5ad7e997
commit
d35e27e7de
6 files changed
+176
-3
No files matched your search
+33
-1
@@ -12,7 +12,7 @@ import { applyCopy, DEFAULT_COPY_ITEMS, planCopy, type CopyItem } from './core/c
|
||||
import { pileGeometry } from './core/geometry';
|
||||
import { rebarSummary, type RebarRow } from './core/rebar/summary';
|
||||
import { shearSegments } from './core/rebar/coping';
|
||||
import { buildRebar3D, type RebarScene } from './view/rebar3d';
|
||||
import { buildRebar3D, type RebarColorMode, type RebarScene } from './view/rebar3d';
|
||||
import { DEFAULT_MATERIAL, FCK_MEMBERS, isAssumedMaterial, type FckByMember, type FckMember, type Material } from './core/rebar/common';
|
||||
import { allVisibleChecked, setVisibleChecked, type TypeFilter } from './core/selection';
|
||||
import { choose, defaultSummary, isSelectable, SHAPE_GROUPS, UNDEFINED_REASON, type MemberId } from './core/shape-options';
|
||||
@@ -80,6 +80,8 @@ const state = {
|
||||
fckByMember: {} as FckByMember,
|
||||
/** Bar highlighted on ③ after [보기] (시안 ③ 알림). */
|
||||
rebarFocus: null as string | null,
|
||||
/** Colour basis of the 3D rebar on ③: role (default), diameter, or member. */
|
||||
rebarColor: 'role' as RebarColorMode,
|
||||
/** Member tab on ③ (철근표). */
|
||||
rebarMember: 'coping' as RebarRow['member'],
|
||||
/** Member card selected on ② (시안 ② 부재 목록). */
|
||||
@@ -229,6 +231,7 @@ function setupScene(): void {
|
||||
if (pier?.model) {
|
||||
rebar3d = buildRebar3D(pier.model, state.material, state.fckByMember);
|
||||
rebar3d.group.visible = state.stage === 'rebar';
|
||||
rebar3d.setColorMode(state.rebarColor);
|
||||
world.add(rebar3d.group);
|
||||
const scene = buildPierScene(pier.model);
|
||||
for (const key of Object.keys(state.visible) as PartName[]) {
|
||||
@@ -415,6 +418,7 @@ function renderAll(): void {
|
||||
renderEditCard();
|
||||
renderPlan();
|
||||
renderRebar();
|
||||
renderRebarColor();
|
||||
scheduleBackup();
|
||||
}
|
||||
|
||||
@@ -765,6 +769,34 @@ const REBAR_MEMBERS: { id: RebarRow['member']; label: string }[] = [
|
||||
{ id: 'footing', label: '확대기초' },
|
||||
];
|
||||
|
||||
/** 3D colour basis buttons on ③ and their legend (spec §6.7). */
|
||||
function renderRebarColor(): void {
|
||||
for (const b of document.querySelectorAll<HTMLButtonElement>('#rebar-color button')) {
|
||||
b.setAttribute('aria-pressed', String(b.dataset.color === state.rebarColor));
|
||||
}
|
||||
const legend = $<HTMLUListElement>('rebar-legend');
|
||||
legend.replaceChildren();
|
||||
const items = rebar3d?.legend(state.rebarColor) ?? [];
|
||||
if (state.rebarColor === 'role') {
|
||||
legend.appendChild(el('li', '역할별 색 (명세 §6.7)', 'muted small'));
|
||||
}
|
||||
for (const item of items) {
|
||||
const li = el('li', undefined, 'rebar-legend-item');
|
||||
const swatch = el('span', undefined, 'swatch');
|
||||
swatch.style.background = item.color;
|
||||
li.append(swatch, el('span', item.label));
|
||||
legend.appendChild(li);
|
||||
}
|
||||
}
|
||||
|
||||
for (const b of document.querySelectorAll<HTMLButtonElement>('#rebar-color button')) {
|
||||
b.addEventListener('click', () => {
|
||||
state.rebarColor = b.dataset.color as RebarColorMode;
|
||||
rebar3d?.setColorMode(state.rebarColor);
|
||||
renderRebarColor();
|
||||
});
|
||||
}
|
||||
|
||||
function renderRebar(): void {
|
||||
const pier = activePier();
|
||||
// 교각 목록 with the 배근 status (시안 ③). The checks are the same as in ① and ②.
|
||||
|
||||
Reference in new issue
Block a user