Merge remote-tracking branch 'origin/sub_laptop_8' into main_laptop_1
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