- 저장 후 넘어감 → 저장 · 버리고 넘어감 → 폐기 · 다시 불러오기 → 새로고침 · 지우기 → 삭제 등 - test_303 · test_ui_loading 글 맞춤 Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_013QyNXY2TUKXCFMwAca2APG
88 lines
2.6 KiB
TypeScript
88 lines
2.6 KiB
TypeScript
/** 뷰 탭 — 탐색·재생성 명령 (조사표 7절 중 구현분) */
|
||
import { Point } from '@flatten-js/core';
|
||
import { toast } from 'react-toastify';
|
||
import type { CadCommand } from './command.types';
|
||
import { bumpSceneVersion } from '../helpers/scene-version';
|
||
import { getScreenCanvasDrawController, setEntities, getEntities } from '../state';
|
||
import { Tool } from '../tools';
|
||
import { selectToolStateMachine } from '../tools/select-tool';
|
||
import { startZoomPrompt } from '../inputController/zoom-prompt';
|
||
|
||
const zoomBy = (factor: number): string => {
|
||
const controller = getScreenCanvasDrawController();
|
||
const oldScale = controller.getScreenScale();
|
||
const newScale = Math.max(0.01, oldScale * factor);
|
||
// 배율만 바꾸면 화면이 월드 원점 쪽으로 늘어나 도면이 화면 밖으로 밀려난다.
|
||
// 휠 줌이 커서 밑 좌표를 붙잡아 두듯, 버튼 줌은 **화면 중심**의 월드 좌표를
|
||
// 붙잡아 둔다 (screen = (world - offset) * scale).
|
||
const canvasSize = controller.getCanvasSize();
|
||
const offset = controller.getScreenOffset();
|
||
const worldCenterX = offset.x + canvasSize.x / 2 / oldScale;
|
||
const worldCenterY = offset.y + canvasSize.y / 2 / oldScale;
|
||
controller.setScreenScale(newScale);
|
||
controller.setScreenOffset(
|
||
new Point(
|
||
worldCenterX - canvasSize.x / 2 / newScale,
|
||
worldCenterY - canvasSize.y / 2 / newScale
|
||
)
|
||
);
|
||
return `줌 ${Math.round(newScale * 100)}%`;
|
||
};
|
||
|
||
export const VIEW_COMMANDS: CadCommand[] = [
|
||
{
|
||
id: 'SELECT',
|
||
label: '선택',
|
||
glyph: '↖',
|
||
hint: '객체를 클릭하거나 선택 사각형으로 고른다',
|
||
tool: Tool.SELECT,
|
||
machine: selectToolStateMachine,
|
||
},
|
||
{
|
||
id: 'ZOOM',
|
||
label: '범위 줌',
|
||
aliases: ['Z'],
|
||
glyph: '⛶',
|
||
hint: '범위(E) · 전체(A) · 이전(P) · 윈도우(W) · 2X — 오토캐드 ZOOM(⛶ 버튼 = 바로 범위)',
|
||
run: () => {
|
||
startZoomPrompt(); // 덧물음 — 명령 중 'Z 도 같은 길
|
||
return '';
|
||
},
|
||
},
|
||
{
|
||
id: 'ZOOMIN',
|
||
label: '확대',
|
||
glyph: '+',
|
||
run: () => zoomBy(1.25),
|
||
},
|
||
{
|
||
id: 'ZOOMOUT',
|
||
label: '축소',
|
||
glyph: '-',
|
||
run: () => zoomBy(0.8),
|
||
},
|
||
{
|
||
id: 'REGEN',
|
||
label: '재생성',
|
||
aliases: ['RE'],
|
||
glyph: '⟳',
|
||
hint: '화면 캐시를 버리고 객체를 다시 그린다',
|
||
run: () => {
|
||
bumpSceneVersion();
|
||
setEntities([...getEntities()], false);
|
||
return '화면 재생성';
|
||
},
|
||
},
|
||
{
|
||
id: 'PAN',
|
||
label: '초점이동',
|
||
aliases: ['P'],
|
||
glyph: '✋',
|
||
hint: '휠 버튼을 누른 채 끌면 화면이 움직인다',
|
||
run: () => {
|
||
toast.info('휠 버튼을 누른 채 끌면 화면이 이동합니다.');
|
||
return '초점이동 안내';
|
||
},
|
||
},
|
||
];
|