import { ANGLE_TYPE, canvasState, currentAngleTypeSelector, currentObjectState, pitchTextSelector } from '@/store/canvasAtom' import { useRecoilValue } from 'recoil' import { useEffect, useRef, useState } from 'react' import { useLine } from '@/hooks/useLine' import { useMessage } from '@/hooks/useMessage' import { useEvent } from '@/hooks/useEvent' import { LINE_TYPE, POLYGON_TYPE } from '@/common/common' import { useMode } from '@/hooks/useMode' import { usePolygon } from '@/hooks/usePolygon' import { outerLineFixState } from '@/store/outerLineAtom' import { useSwal } from '@/hooks/useSwal' import { usePopup } from '@/hooks/usePopup' import { getChonByDegree } from '@/util/canvas-util' //지붕형상 수동 설정 export function useRoofShapePassivitySetting(id) { const TYPES = { EAVES: 'eaves', GABLE: 'gable', SHED: 'shed', } const canvas = useRecoilValue(canvasState) const currentAngleType = useRecoilValue(currentAngleTypeSelector) const pitchText = useRecoilValue(pitchTextSelector) const { getMessage } = useMessage() const { showLine, hideLine, addPitchTextsByOuterLines } = useLine() const { swalFire } = useSwal() const { addCanvasMouseEventListener, initEvent } = useEvent() // const { addCanvasMouseEventListener, initEvent } = useContext(EventContext) const { drawRoofPolygon } = useMode() const { addPolygonByLines } = usePolygon() const currentObject = useRecoilValue(currentObjectState) const offsetRef = useRef(null) const pitchRef = useRef(null) const currentLineRef = useRef(null) const history = useRef([]) const [type, setType] = useState(TYPES.EAVES) const isFix = useRef(false) const initLines = useRef([]) const [isLoading, setIsLoading] = useState(false) const { closePopup } = usePopup() const buttons = [ { id: 1, name: getMessage('eaves'), type: TYPES.EAVES }, { id: 2, name: getMessage('gable'), type: TYPES.GABLE }, { id: 3, name: getMessage('windage'), type: TYPES.SHED }, ] const outerLineFix = useRecoilValue(outerLineFixState) useEffect(() => { const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') if (!outerLineFix || outerLines.length === 0) { swalFire({ text: '외벽선이 없습니다.' }) closePopup(id) return } setIsLoading(true) }, []) useEffect(() => { if (!isLoading) return addCanvasMouseEventListener('mouse:down', mouseDown) const wallLines = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.WALL) canvas?.remove(...wallLines) const outerLines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') initLines.current = outerLines.map((line) => ({ ...line })) outerLines.forEach((outerLine, idx) => { if (idx === 0) { currentLineRef.current = outerLine } outerLine.set({ selectable: true }) showLine(outerLine) outerLine.bringToFront() }) canvas?.renderAll() return () => { handleLineToPolygon() canvas?.discardActiveObject() initEvent() } }, [isLoading]) useEffect(() => { const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') let stroke, strokeWidth lines.forEach((line) => { if (line.attributes?.type === LINE_TYPE.WALLLINE.EAVES || line.attributes?.type === LINE_TYPE.WALLLINE.HIPANDGABLE) { stroke = '#45CD7D' strokeWidth = 4 } else if (line.attributes?.type === LINE_TYPE.WALLLINE.GABLE || line.attributes?.type === LINE_TYPE.WALLLINE.JERKINHEAD) { stroke = '#3FBAE6' strokeWidth = 4 } else { stroke = '#000000' strokeWidth = 4 } line.set({ stroke, strokeWidth, }) }) canvas.renderAll() if (!currentObject) { return } if (currentObject.name !== 'outerLine') { return } currentObject.set({ stroke: '#EA10AC', strokeWidth: 4, }) currentLineRef.current = currentObject canvas.renderAll() }, [currentObject]) const mouseDown = (e) => { if (!e.target) { currentLineRef.current = null return } if (e.target && e.target.name === 'outerLine') { currentLineRef.current = e.target } } const nextLineFocus = (selectedLine) => { const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') const index = lines.findIndex((line) => line === selectedLine) const nextLine = lines[index + 1] || lines[0] if (nextLine.attributes?.isFixed) { canvas.discardActiveObject() return } canvas.setActiveObject(nextLine) } const handleConfirm = () => { if (!currentLineRef.current) { alert('선택된 외곽선이 없습니다.') return } let attributes const offset = Number(offsetRef.current.value) / 10 if (type === TYPES.EAVES) { attributes = { type: LINE_TYPE.WALLLINE.EAVES, offset, pitch: currentAngleType === ANGLE_TYPE.SLOPE ? pitchRef.current.value : getChonByDegree(pitchRef.current.value), } } else if (type === TYPES.GABLE) { attributes = { type: LINE_TYPE.WALLLINE.GABLE, offset, } } else if (type === TYPES.SHED) { attributes = { type: LINE_TYPE.WALLLINE.SHED, offset, } } currentLineRef.current.set({ attributes: { ...attributes, isFixed: true }, }) history.current.push(currentLineRef.current) nextLineFocus(currentLineRef.current) } const handleRollback = () => { if (history.current.length === 0) { return } const lastLine = history.current.pop() delete lastLine.attributes lastLine.set({ stroke: '#000000', strokeWidth: 4, }) canvas.setActiveObject(lastLine) canvas.renderAll() } const handleSave = () => { isFix.current = true handleLineToPolygon() closePopup(id) } const handleLineToPolygon = () => { const roofBases = canvas.getObjects().filter((obj) => obj.name === POLYGON_TYPE.ROOF) const exceptObjs = canvas.getObjects().filter((obj) => obj.name !== 'outerLine' && obj.parent?.name !== 'outerLine') const lines = canvas.getObjects().filter((obj) => obj.name === 'outerLine') let checkedAllSetting = true lines.forEach((line) => { if (!line.attributes) { checkedAllSetting = false } }) if (!checkedAllSetting) { swalFire({ text: '설정이 완료되지 않은 외벽선이 있습니다.', icon: 'warning' }) return } exceptObjs.forEach((obj) => { canvas.remove(obj) }) lines.forEach((line) => { hideLine(line) }) let wall if (isFix.current) { wall = addPolygonByLines(lines, { name: POLYGON_TYPE.WALL, fill: 'transparent', stroke: 'black' }) } else { // 그냥 닫을 경우 처리 wall = addPolygonByLines([...initLines.current], { name: POLYGON_TYPE.WALL, fill: 'transparent', stroke: 'black', }) lines.forEach((line, idx) => { line.attributes = initLines.current[idx].attributes }) } wall.lines = [...lines] // 기존 그려진 지붕이 없다면 if (isFix.current) { // 완료 한 경우에는 지붕까지 그려줌 addPitchTextsByOuterLines() const roof = drawRoofPolygon(wall) } canvas.renderAll() } return { handleSave, handleConfirm, buttons, type, setType, TYPES, offsetRef, pitchRef, handleRollback, pitchText } }