qcast-front/src/hooks/roofcover/useRoofShapePassivitySetting.js

258 lines
7.4 KiB
JavaScript

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 }
}