feat(B07 CAD): 337-2 마-2 ZOOM 덧물음 · Shift+우클릭 스냅 메뉴 · 고르기 ALL/L/P · 그립 종료(X) · ↶↷ 끊고 되돌림 · snapped 캐스트 지움
- ZOOM(Z): 「윈도우 구석 지정, 축척 비율 (nX 또는 nXP) 입력 또는 [전체(A)/범위(E)/이전(P)/윈도우(W)] <실시간>:」 덧물음 · E · A = 범위 · P = 앞 화면 · W · 누름 = 두 구석 윈도우 · 2X = 배율 곱 · 빈 Enter = 실시간 안내 · 중심 · 동적 · 축척 · 객체 = 없음 안내 · 'Z 투명 · ⛶ 단추 = 바로 범위 - 약속 더함: SubPrompt.onText(꼴이 정해지지 않은 글 · nX) — routeTyped 가 덧물음에 먼저 물음 · undefined = 사다리 그대로(브레인 알림) - Shift+우클릭: 점 물음에서만 한 번 스냅 메뉴(시작점에서 · 두 점 사이의 중간 · 끝점 · 중간점 · 교차점 · 중심 · 사분점 · 수직 · 노드 · 근처점 · 없음) → 고른 이름을 친 것과 같은 길 · Esc · 바깥 누름 = 메뉴만 닫음(ic/snap-menu.ts) - 고르기 숨은 키워드 ALL · L · P(선택 도구 첫 점 대기 · 쉼 · 명령 안 자식) — 앞 고름에 더함 · 「n개를 찾음, 총 m개」 - 그립 물음 새 꼴 「** 신축 ** 신축점 지정 또는 [종료(X)]:」 · X = 놓음 · 기준점(B) · 복사(C) · 명령 취소(U) 없음 안내 - ↶ ↷ 단추 = undoCommand · redoCommand(끊고 되돌림) · 우클릭 = 명령 중 Enter · 쉴 때 반복(가-1 길 · 시험) - 시험: mouse-acad 마-2 더함(21) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Se7ytqbohmBQnfYpwYFnYf
This commit is contained in:
@@ -1,10 +1,11 @@
|
||||
/**
|
||||
* 그립 편집 도구 — 선택 도구에서 그립을 집으면 켜진다(뜨거운 그립).
|
||||
* 오토캐드처럼 누르고-옮기고-누르기 · 끌어 놓기 둘 다(누름 · 뗌 가름은 input-controller) ·
|
||||
* 거리 숫자 = 그립 점에서 커서 쪽(N8) · 좌표 · Esc = 그립 놓음.
|
||||
* 거리 숫자 = 그립 점에서 커서 쪽(N8) · 좌표 · Esc · 종료(X) = 그립 놓음.
|
||||
*/
|
||||
import type { Point } from '@flatten-js/core';
|
||||
import { Actor, assign, createMachine } from 'xstate';
|
||||
import type { OptionSpec, PromptSpec } from '../commands/prompt';
|
||||
import type { Entity } from '../entities/Entity';
|
||||
import { getPointFromEvent } from '../helpers/get-point-from-event';
|
||||
import { type Grip, applyGrip } from '../helpers/grips';
|
||||
@@ -20,6 +21,24 @@ import { Tool } from '../tools';
|
||||
import { selectToolStateMachine } from './select-tool';
|
||||
import { ActorEvent, type PointInputEvent, type StateEvent, type ToolContext } from './tool.types';
|
||||
|
||||
const gripOption = (key: string, kw: string, label: string): OptionSpec => ({
|
||||
key,
|
||||
kw,
|
||||
en: key,
|
||||
label,
|
||||
});
|
||||
|
||||
/** 오토캐드 그립 신축 줄 — 종료(X)만 · 기준점(B) · 복사(C) · 명령 취소(U) 는 뺌 */
|
||||
const GRIP_PROMPT: PromptSpec = {
|
||||
text: '** 신축 ** 신축점 지정',
|
||||
options: [gripOption('EXIT', 'X', '종료')],
|
||||
absent: [
|
||||
gripOption('BASE', 'B', '기준점'),
|
||||
gripOption('COPY', 'C', '복사'),
|
||||
gripOption('UNDO', 'U', '명령 취소'),
|
||||
],
|
||||
};
|
||||
|
||||
let editedEntity: Entity | null = null;
|
||||
let editedGrip: Grip | null = null;
|
||||
|
||||
@@ -64,7 +83,7 @@ export const gripEditToolStateMachine = createMachine(
|
||||
},
|
||||
[GripEditState.WAITING_FOR_TARGET_POINT]: {
|
||||
description: '그립을 옮길 위치를 지정한다',
|
||||
meta: { instructions: '** 신축 ** 신축점 지정' },
|
||||
meta: { kind: 'point', prompt: GRIP_PROMPT },
|
||||
on: {
|
||||
[ActorEvent.DRAW]: { actions: GripEditAction.DRAW_TEMP_GRIP_EDIT },
|
||||
[ActorEvent.MOUSE_CLICK]: {
|
||||
@@ -80,6 +99,7 @@ export const gripEditToolStateMachine = createMachine(
|
||||
actions: [GripEditAction.APPLY_GRIP_EDIT, GripEditAction.SWITCH_TO_SELECT_TOOL],
|
||||
},
|
||||
[ActorEvent.ESC]: { actions: GripEditAction.SWITCH_TO_SELECT_TOOL },
|
||||
'OPTION.EXIT': { actions: GripEditAction.SWITCH_TO_SELECT_TOOL },
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -31,6 +31,7 @@ import {
|
||||
setSelectedEntityIds,
|
||||
} from '../state';
|
||||
import { Tool } from '../tools';
|
||||
import { previousSelection } from '../commands/prompt';
|
||||
import { startGripEdit } from './grip-edit-tool';
|
||||
import type { SelectContext } from './select-tool';
|
||||
import type { MouseClickEvent } from './tool.types';
|
||||
@@ -113,6 +114,26 @@ export function combineSelection(ids: string[], mode: 'add' | 'remove' | 'toggle
|
||||
return [...before, ...ids.filter((id) => !before.includes(id))];
|
||||
}
|
||||
|
||||
/** 알림 줄 — 입력 층이 붙임(`ic/selecting.ts` · prompt-input 을 바로 부르면 불러오기 고리) */
|
||||
let notice: (text: string) => void = () => {};
|
||||
export const setKeywordNotice = (sink: (text: string) => void): void => {
|
||||
notice = sink;
|
||||
};
|
||||
|
||||
/** 고르기 키워드 — 전체(ALL = Ctrl+A 와 같은 목록) · 최종(LAST = 집을 수 있는 마지막) · 이전(P) · 앞 고름에 더함 */
|
||||
export function selectByKeyword(key: 'ALL' | 'LAST' | 'PREVIOUS'): void {
|
||||
const pickable = getPickableEntities();
|
||||
const found =
|
||||
key === 'ALL'
|
||||
? pickable.map((entity) => entity.id)
|
||||
: key === 'LAST'
|
||||
? pickable.slice(-1).map((entity) => entity.id)
|
||||
: previousSelection().filter((id) => pickable.some((entity) => entity.id === id));
|
||||
const ids = combineSelection(expandSelectionWithGroups(found), 'add');
|
||||
setSelectedEntityIds(ids);
|
||||
notice(`${found.length}개를 찾음, 총 ${ids.length}개`);
|
||||
}
|
||||
|
||||
/** 그립 집기 · 그리기 — 쉴 때 · 고칠 수 있는 도면만 */
|
||||
export const gripsEditable = (): boolean =>
|
||||
!isViewOnly() &&
|
||||
|
||||
@@ -14,6 +14,7 @@ import { assign, createMachine } from 'xstate';
|
||||
import {
|
||||
drawTempSelectionRectangle,
|
||||
handleFirstSelectionPoint,
|
||||
selectByKeyword,
|
||||
selectEntitiesInsideRectangle,
|
||||
} from './select-tool.helpers';
|
||||
|
||||
@@ -76,6 +77,10 @@ export const selectToolStateMachine = createMachine(
|
||||
actions: SelectAction.DELETE_SELECTED_ENTITIES,
|
||||
target: SelectState.INIT,
|
||||
},
|
||||
// 고르기 숨은 키워드(SELECT_OBJECTS) — 전체 · 최종 · 이전
|
||||
'OPTION.ALL': { actions: () => selectByKeyword('ALL') },
|
||||
'OPTION.LAST': { actions: () => selectByKeyword('LAST') },
|
||||
'OPTION.PREVIOUS': { actions: () => selectByKeyword('PREVIOUS') },
|
||||
},
|
||||
},
|
||||
[SelectState.CHECK_SELECTION]: {
|
||||
|
||||
Reference in New Issue
Block a user