모듈 redo undo 시 선택되어 있는것 해제
This commit is contained in:
parent
39f4b0130f
commit
b775af1911
@ -17,7 +17,7 @@ import {
|
|||||||
import { outerLinePointsState } from '@/store/outerLineAtom'
|
import { outerLinePointsState } from '@/store/outerLineAtom'
|
||||||
import { selectedMenuState } from '@/store/menuAtom'
|
import { selectedMenuState } from '@/store/menuAtom'
|
||||||
import { pendingPopupState, popupState } from '@/store/popupAtom'
|
import { pendingPopupState, popupState } from '@/store/popupAtom'
|
||||||
import { MENU, POLYGON_TYPE, SAVE_KEY } from '@/common/common'
|
import { POLYGON_TYPE, SAVE_KEY } from '@/common/common'
|
||||||
|
|
||||||
const MAX_HISTORY = 3
|
const MAX_HISTORY = 3
|
||||||
|
|
||||||
@ -70,13 +70,12 @@ function _restoreFromJSON(canvas, snapshot, restoreAtomSnapshot, rebuildCanvasAt
|
|||||||
canvas.loadFromJSON(snapshot.canvasJSON, () => {
|
canvas.loadFromJSON(snapshot.canvasJSON, () => {
|
||||||
rebuildCanvasAtoms()
|
rebuildCanvasAtoms()
|
||||||
|
|
||||||
// undo/redo 후 모듈 설치영역이 active 인 채로 남으면
|
canvas.discardActiveObject()
|
||||||
// 사용자가 다시 클릭하지 않아도 선택된 것처럼 보여 자동 배치 등 부작용 발생.
|
canvas.getObjects().forEach((obj) => {
|
||||||
// 활성 객체가 MODULE_SETUP_SURFACE 이면 선택 해제한다.
|
if (obj.type === 'QPolygon' && obj.name === POLYGON_TYPE.MODULE) {
|
||||||
const active = canvas.getActiveObject()
|
obj.set({ stroke: 'black', strokeWidth: 0.3 })
|
||||||
if (active && active.name === POLYGON_TYPE.MODULE_SETUP_SURFACE) {
|
}
|
||||||
canvas.discardActiveObject()
|
})
|
||||||
}
|
|
||||||
|
|
||||||
canvas.renderAll()
|
canvas.renderAll()
|
||||||
restoreAtomSnapshot(snapshot.atomSnapshot)
|
restoreAtomSnapshot(snapshot.atomSnapshot)
|
||||||
@ -92,6 +91,7 @@ function _restoreFromJSON(canvas, snapshot, restoreAtomSnapshot, rebuildCanvasAt
|
|||||||
}, 50)
|
}, 50)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 순환 참조만 안전하게 건너뛰는 JSON 직렬화
|
// 순환 참조만 안전하게 건너뛰는 JSON 직렬화
|
||||||
// WeakSet 방식은 공유 참조(같은 배열이 여러 곳에서 참조)까지 제거하므로 사용 불가
|
// WeakSet 방식은 공유 참조(같은 배열이 여러 곳에서 참조)까지 제거하므로 사용 불가
|
||||||
// 대신 조상 경로(ancestors) 스택으로 진짜 순환만 감지
|
// 대신 조상 경로(ancestors) 스택으로 진짜 순환만 감지
|
||||||
@ -364,7 +364,9 @@ export function useUndoRedo() {
|
|||||||
if (polygon.id) {
|
if (polygon.id) {
|
||||||
polygon.texts = lengthTextsByParent.get(polygon.id) || []
|
polygon.texts = lengthTextsByParent.get(polygon.id) || []
|
||||||
}
|
}
|
||||||
} catch (e) { /* skip */ }
|
} catch (e) {
|
||||||
|
/* skip */
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// Group 내부 QPolygon(도머 등)도 동일하게 내부 라인 인스턴스만 재구축한다.
|
// Group 내부 QPolygon(도머 등)도 동일하게 내부 라인 인스턴스만 재구축한다.
|
||||||
@ -379,7 +381,9 @@ export function useUndoRedo() {
|
|||||||
if (child.id) {
|
if (child.id) {
|
||||||
child.texts = lengthTextsByParent.get(child.id) || []
|
child.texts = lengthTextsByParent.get(child.id) || []
|
||||||
}
|
}
|
||||||
} catch (e) { /* skip */ }
|
} catch (e) {
|
||||||
|
/* skip */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -409,40 +413,43 @@ export function useUndoRedo() {
|
|||||||
}
|
}
|
||||||
}, [canvas])
|
}, [canvas])
|
||||||
|
|
||||||
const saveSnapshot = useCallback((atomOverrides = null, { force = false } = {}) => {
|
const saveSnapshot = useCallback(
|
||||||
if (!canvas || _isRestoring) return
|
(atomOverrides = null, { force = false } = {}) => {
|
||||||
|
if (!canvas || _isRestoring) return
|
||||||
|
|
||||||
// 외벽선/배치면/지붕형상 수동설정 등 그리기 진행 중에는 스냅샷을 쌓지 않는다 (force 시 예외)
|
// 외벽선/배치면/지붕형상 수동설정 등 그리기 진행 중에는 스냅샷을 쌓지 않는다 (force 시 예외)
|
||||||
if (!force && (_isDrawing || isDrawing)) return
|
if (!force && (_isDrawing || isDrawing)) return
|
||||||
|
|
||||||
// snapshot 전에 mouseLine 제거
|
// snapshot 전에 mouseLine 제거
|
||||||
const mouseLines = canvas.getObjects().filter((obj) => obj.name === 'mouseLine')
|
const mouseLines = canvas.getObjects().filter((obj) => obj.name === 'mouseLine')
|
||||||
mouseLines.forEach((obj) => canvas.remove(obj))
|
mouseLines.forEach((obj) => canvas.remove(obj))
|
||||||
|
|
||||||
const canvasJSON = getCanvasSnapshot()
|
const canvasJSON = getCanvasSnapshot()
|
||||||
if (!canvasJSON) return
|
if (!canvasJSON) return
|
||||||
|
|
||||||
const atomSnapshot = getAtomSnapshot()
|
const atomSnapshot = getAtomSnapshot()
|
||||||
|
|
||||||
// atomOverrides 로 비동기 state 반영이 안 된 값을 즉시 덮어쓸 수 있다
|
// atomOverrides 로 비동기 state 반영이 안 된 값을 즉시 덮어쓸 수 있다
|
||||||
if (atomOverrides) {
|
if (atomOverrides) {
|
||||||
Object.assign(atomSnapshot, atomOverrides)
|
Object.assign(atomSnapshot, atomOverrides)
|
||||||
}
|
|
||||||
|
|
||||||
const snapshot = {
|
|
||||||
canvasJSON,
|
|
||||||
atomSnapshot,
|
|
||||||
}
|
|
||||||
|
|
||||||
setUndoStack((prev) => {
|
|
||||||
const newStack = [...prev, snapshot]
|
|
||||||
if (newStack.length > MAX_HISTORY) {
|
|
||||||
return newStack.slice(newStack.length - MAX_HISTORY)
|
|
||||||
}
|
}
|
||||||
return newStack
|
|
||||||
})
|
const snapshot = {
|
||||||
setRedoStack([])
|
canvasJSON,
|
||||||
}, [canvas, currentMenu, isDrawing, getCanvasSnapshot, getAtomSnapshot])
|
atomSnapshot,
|
||||||
|
}
|
||||||
|
|
||||||
|
setUndoStack((prev) => {
|
||||||
|
const newStack = [...prev, snapshot]
|
||||||
|
if (newStack.length > MAX_HISTORY) {
|
||||||
|
return newStack.slice(newStack.length - MAX_HISTORY)
|
||||||
|
}
|
||||||
|
return newStack
|
||||||
|
})
|
||||||
|
setRedoStack([])
|
||||||
|
},
|
||||||
|
[canvas, currentMenu, isDrawing, getCanvasSnapshot, getAtomSnapshot],
|
||||||
|
)
|
||||||
|
|
||||||
const closeAllPopups = useCallback(() => {
|
const closeAllPopups = useCallback(() => {
|
||||||
setPopup((prev) => ({
|
setPopup((prev) => ({
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user