toto10's picture
Upload folder using huggingface_hub (#4)
ea35075
raw
history blame
11.1 kB
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 (<ObjectContext.Provider value={{objects, updateObjects}}>
{children}
</ObjectContext.Provider>);
}
function processNode(node, handleSelectedObject, setSelectedObj, transformControlMap) {
if (!node) {
return null;
}
if (!(treeItemObjNames.includes(node.name) || node.name.startsWith("mainObject"))) {
return null;
}
return (<TreeItem key={node.uuid} nodeId={node.uuid} label={node.name || node.type} onClick={(objEvent) => {
const objName = objEvent.target.innerHTML;
handleSelectedObject(objName, transformControlMap[objName]);
setSelectedObj(objName);
}}>
{node.children && node.children.map((child) => processNode(child, handleSelectedObject, setSelectedObj, transformControlMap))}
</TreeItem>);
}
function ScenePanel({
refreshSceneTree,
handleSelectedObject,
setVisible,
setCameraNear,
setCameraFar,
setCameraFOV,
setCanvasBgColor,
removeObject
}) {
return (<ObjectProvider>
<SceneTreeWrapper refreshSceneTree={refreshSceneTree} handleSelectedObject={handleSelectedObject}
setVisible={setVisible}
setCameraNear={setCameraNear} setCameraFar={setCameraFar} setCameraFOV={setCameraFOV}
setCanvasBgColor={setCanvasBgColor} removeObject={removeObject}/>
</ObjectProvider>)
}
function SceneTree({handleSelectedObject, setSelectedObj, transformControlMap}) {
const {objects} = useObjectUpdate();
return (<TreeView
defaultCollapseIcon={<ExpandMoreIcon/>}
defaultExpandIcon={<ChevronRightIcon/>}
defaultEndIcon={<div/>}
>
{processNode(objects.object, handleSelectedObject, setSelectedObj, transformControlMap)}
</TreeView>);
}
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 (<div>
<Box mb={1} mt={1}>
<Accordion>
<AccordionSummary expandIcon={<ExpandMoreIcon/>}>
Scene
</AccordionSummary>
<AccordionDetails>
<SceneTree handleSelectedObject={handleSelectedObject} setSelectedObj={setSelectedObj}
transformControlMap={transformControlMap}/>
<Button variant="contained" color="primary" fullWidth sx={{margin: '2px'}}
onClick={refreshSceneTree}>Refresh Scene Tree</Button>
{(transformControlObjNames.includes(selectedObj) || (selectedObj && selectedObj.startsWith("mainObject"))) &&
<FormControl>
<FormLabel>Operate</FormLabel>
<RadioGroup
aria-labelledby="operate-radio-buttons-group-label"
defaultValue="none"
name="operate-radio-buttons-group"
row={true}
onChange={(event) => {
handleSelectedObject(selectedObj, event.target.value);
const updatedMap = {...transformControlMap};
updatedMap[selectedObj] = event.target.value;
setTransformControlMap(updatedMap);
}}
>
<FormControlLabel value="none" control={<Radio/>} label="None"
checked={transformControlMap[selectedObj] === "none" || !transformControlMap[selectedObj]}/>
<FormControlLabel value="translate" control={<Radio/>} label="Translate"
checked={transformControlMap[selectedObj] === "translate"}/>
<FormControlLabel value="rotate" control={<Radio/>} label="Rotate"
checked={transformControlMap[selectedObj] === "rotate"}/>
</RadioGroup>
</FormControl>}
{(visibleControlObjNames.includes(selectedObj) || (selectedObj && selectedObj.startsWith("mainObject"))) &&
<FormControlLabel
control={
<Checkbox
checked={visibleMap[selectedObj] || !(selectedObj in visibleMap)}
onChange={(event) => {
setVisible(selectedObj, event.target.checked);
const updatedMap = {...visibleMap};
updatedMap[selectedObj] = event.target.checked;
setVisibleMap(updatedMap);
}}
color="primary"
/>
}
label='Visible'
/>
}
{
selectedObj === "Preview Camera" && <Box width="100%">
<Typography gutterBottom>Near</Typography>
<Slider min={0.1} max={100}
valueLabelDisplay="auto"
step={0.1}
value={near}
onChange={(event, newValue) => {
setNear(newValue);
setCameraNear(newValue);
}}
aria-labelledby="continuous-slider"
/>
<Typography gutterBottom>Far</Typography>
<Slider min={0.1} max={20000}
valueLabelDisplay="auto"
value={far}
onChange={(event, newValue) => {
setFar(newValue);
setCameraFar(newValue)
}}
aria-labelledby="continuous-slider"
/>
<Typography gutterBottom>FOV</Typography>
<Slider min={1} max={100}
valueLabelDisplay="auto"
value={fov}
onChange={(event, newValue) => {
setFOV(newValue);
setCameraFOV(newValue);
}}
aria-labelledby="continuous-slider"
/>
</Box>
}
{
selectedObj && selectedObj.startsWith("mainObject") &&
<Button variant="contained" color="primary" fullWidth sx={{margin: '2px'}}
onClick={() => {
removeObject(selectedObj);
refreshSceneTree();
setSelectedObj(null);
}}>Remove</Button>
}
{
selectedObj === "Scene" && <SketchPicker
color={bgColor}
onChangeComplete={(color) => {
setBgColor(color);
setCanvasBgColor(color);
}}
disableAlpha={true}
/>
}
</AccordionDetails>
</Accordion>
</Box>
</div>);
}
export default ScenePanel;