Files
Aislo/B07_DesignDetail/openwebcad/src/helpers/draw.ts
T
eomsangdonandClaude Opus 5 e599884888 feat(B07): 그립으로 고치고, 음수·극좌표를 받고, 편집분을 잃지 않는다
조사표 8~13절 검토에서 "기본 기능"으로 고른 것을 반영한다.

- 좌표 입력: 절대·상대 좌표가 양수만 받아 `@-100,50`을 거부했다. 부호를 허용하고
  극좌표 `@거리<각도`·`거리<각도`를 더했다. `-`·`+`가 확대·축소 단축키로 먼저
  잡혀 음수의 첫 글자를 먹고 있어 그 두 단축키를 뺐다(줌은 휠·뷰 막대·명령).
- 그립 편집: 선택 객체에 그립을 그리고 집어서 옮긴다. 선 끝점·중점, 폴리선 정점,
  사각형 모서리, 원 중심·반지름, 문자·점 기준점. 폴리선은 세그먼트 중점을 끌면
  정점이 늘고 정점 위 Ctrl+클릭이면 준다. 형상 필드가 private이라 공개 생성자로
  다시 만들어 바꿔 끼우고 id·도면층·색·그룹을 물려받는다.
- 자동 백업·복구: 5초 디바운스로 복구 전용 키에 저장하고, 시작할 때 백업이 있으면
  눌러서 되살리는 안내를 띄운다. 저장(QSAVE)에 성공하면 백업을 지운다.
- 선택 순환: 같은 자리를 다시 클릭하면 겹친 후보를 차례로 돌린다.
- 상태막대: `극좌표 추적` 버튼이 `직교`와 같은 onClick이라 같은 일을 하고 있었다.
  각각 45°·90°를 켜고 끄도록 고치고, 스냅 추적 토글과 F3·F7·F8·F10을 붙였다.
- 문자 굵게·기울임을 캔버스·SVG·JSON·스타일 패널에 연결했다.
- 조사표: 이미 되어 있던 5건의 표기를 정정하고, 출력·내보내기(9절)는 결재창 이후
  PDF·DXF·DWG로 반영할 것이라 보류(P)로 구분해 사유를 남겼다.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-30 14:43:46 +09:00

73 lines
2.2 KiB
TypeScript

import { compact } from 'es-toolkit';
import { HOVERED_SNAP_POINT_TIME } from '../App.consts';
import type { ScreenCanvasDrawController } from '../drawControllers/screenCanvas.drawController';
import {
getAngleGuideEntities,
getDebugEntities,
getEntities,
getGhostHelperEntities,
getHighlightedEntityIds,
getHoveredSnapPoints,
getInputController,
getSelectedEntities,
getShouldDrawCursor,
getSnapPoint,
getSnapPointOnAngleGuide,
} from '../state';
import {
drawCursor,
drawDebugEntities,
drawEntities,
drawGrips,
drawHelpers,
drawSnapPoint,
} from './draw-functions';
import { getClosestSnapPoint } from './get-closest-snap-point';
import { isPointEqual } from './is-point-equal';
import { drawScene } from './scene-cache';
/**
* Hover highlight is excluded from the static scene cache (it changes every
* mouse move) — re-draw the few highlighted entities on top of the blit.
*/
function drawHighlightedEntities(drawController: ScreenCanvasDrawController) {
const highlightedIds = getHighlightedEntityIds();
if (!highlightedIds.length) return;
const idSet = new Set(highlightedIds);
drawEntities(
drawController,
getEntities().filter((entity) => idSet.has(entity.id))
);
}
export function draw(drawController: ScreenCanvasDrawController) {
drawController.clear();
// Static scene (all entities): cached bitmap blit, rebuilt only when needed.
drawScene(drawController, performance.now());
drawHighlightedEntities(drawController);
drawGrips(drawController, getSelectedEntities());
drawHelpers(drawController, getAngleGuideEntities());
drawEntities(drawController, getGhostHelperEntities());
drawDebugEntities(drawController, getDebugEntities());
const { snapPoint: closestSnapPoint } = getClosestSnapPoint(
compact([getSnapPoint(), getSnapPointOnAngleGuide()]),
drawController.getWorldMouseLocation()
);
const isMarked =
!!closestSnapPoint &&
getHoveredSnapPoints().some(
(hoveredSnapPoint) =>
hoveredSnapPoint.milliSecondsHovered > HOVERED_SNAP_POINT_TIME &&
isPointEqual(hoveredSnapPoint.snapPoint.point, closestSnapPoint.point)
);
drawSnapPoint(drawController, closestSnapPoint, isMarked);
if (getShouldDrawCursor()) {
drawCursor(drawController);
getInputController().draw(drawController);
}
}