import React, {createContext, useContext, useState, useEffect, useRef} from 'react'; import {TreeView, TreeItem} from '@mui/lab'; import {styled} from '@mui/system'; import Box from '@mui/material/Box'; import ExpandMoreIcon from "@mui/icons-material/ExpandMore"; import ChevronRightIcon from '@mui/icons-material/ChevronRight'; import { Accordion, AccordionSummary, AccordionDetails, Button, FormControl, Radio, RadioGroup, FormLabel, FormControlLabel, Typography } from '@mui/material'; import Checkbox from "@mui/material/Checkbox"; import Slider from "@mui/material/Slider"; import {SketchPicker} from "react-color"; import NumberInput from "./NumberInput.js"; const CustomTreeView = styled(TreeView)` height: 240px; overflow-y: auto; `; const transformControlObjNames = ["Hemisphere Light", "Directional Light"]; let transformControlValues = {"Hemisphere Light": "none", "Directional Light": "none"}; const treeItemObjNames = ["Scene", "mainObject", "Hemisphere Light", "Directional Light", "Ground", "Grid", "Axis", "Preview Camera"]; const visibleControlObjNames = ["Directional Light", "Ground", "Grid", "Axis"]; let visibleValues = {"Directional Light": true, "Ground": true, "Grid": true, "Axis": true}; const ObjectContext = createContext([]); function useObjectUpdate() { const context = useContext(ObjectContext); if (!context) { throw new Error('useObjectUpdate must be used within ObjectProvider'); } return context; } function ObjectProvider({children}) { const [objects, setObjects] = useState([]); const updateObjects = (newObjects) => { setObjects(newObjects); }; return ( {children} ); } function processNode(node, handleSelectedObject, setSelectedObj, transformControlMap) { if (!node) { return null; } if (!(treeItemObjNames.includes(node.name) || node.name.startsWith("mainObject"))) { return null; } return ( { const objName = objEvent.target.innerHTML; handleSelectedObject(objName, transformControlMap[objName]); setSelectedObj(objName); }}> {node.children && node.children.map((child) => processNode(child, handleSelectedObject, setSelectedObj, transformControlMap))} ); } function ScenePanel({ refreshSceneTree, handleSelectedObject, setVisible, setCameraNear, setCameraFar, setCameraFOV, setCanvasBgColor, removeObject }) { return ( ) } function SceneTree({handleSelectedObject, setSelectedObj, transformControlMap}) { const {objects} = useObjectUpdate(); return (} defaultExpandIcon={} defaultEndIcon={
} > {processNode(objects.object, handleSelectedObject, setSelectedObj, transformControlMap)} ); } function SceneTreeWrapper({ refreshSceneTree, handleSelectedObject, setVisible, setCameraNear, setCameraFar, setCameraFOV, setCanvasBgColor, removeObject }) { const [selectedObj, setSelectedObj] = useState(null); const [far, setFar] = useState(1000); const [near, setNear] = useState(0.1); const [fov, setFOV] = useState(45); const [visibleMap, setVisibleMap] = useState(visibleValues); const [transformControlMap, setTransformControlMap] = useState(transformControlValues); const [bgColor, setBgColor] = useState(); const {updateObjects} = useObjectUpdate(); const updateObjectsRef = useRef(); updateObjectsRef.current = updateObjects; useEffect(() => { window.updateObjects = (newObjects) => { if (updateObjectsRef.current) { updateObjectsRef.current(newObjects); } }; return () => { window.updateObjects = null; }; }, []); return (
}> Scene {(transformControlObjNames.includes(selectedObj) || (selectedObj && selectedObj.startsWith("mainObject"))) && Operate { handleSelectedObject(selectedObj, event.target.value); const updatedMap = {...transformControlMap}; updatedMap[selectedObj] = event.target.value; setTransformControlMap(updatedMap); }} > } label="None" checked={transformControlMap[selectedObj] === "none" || !transformControlMap[selectedObj]}/> } label="Translate" checked={transformControlMap[selectedObj] === "translate"}/> } label="Rotate" checked={transformControlMap[selectedObj] === "rotate"}/> } {(visibleControlObjNames.includes(selectedObj) || (selectedObj && selectedObj.startsWith("mainObject"))) && { setVisible(selectedObj, event.target.checked); const updatedMap = {...visibleMap}; updatedMap[selectedObj] = event.target.checked; setVisibleMap(updatedMap); }} color="primary" /> } label='Visible' /> } { selectedObj === "Preview Camera" && Near { setNear(newValue); setCameraNear(newValue); }} aria-labelledby="continuous-slider" /> Far { setFar(newValue); setCameraFar(newValue) }} aria-labelledby="continuous-slider" /> FOV { setFOV(newValue); setCameraFOV(newValue); }} aria-labelledby="continuous-slider" /> } { selectedObj && selectedObj.startsWith("mainObject") && } { selectedObj === "Scene" && { setBgColor(color); setCanvasBgColor(color); }} disableAlpha={true} /> }
); } export default ScenePanel;