Skip to content

Commit bce9eef

Browse files
Major overhaul for cutting and react state
1 parent 8610d78 commit bce9eef

15 files changed

Lines changed: 719 additions & 411 deletions

package-lock.json

Lines changed: 23 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
"martinez-polygon-clipping": "^0.7.4",
5656
"p-map": "^7.0.4",
5757
"poisson-disk-sampling": "^2.3.1",
58+
"polygon-clipping": "^0.15.7",
5859
"polygon-offset": "^0.3.2",
5960
"react": "^19.2.3",
6061
"react-dom": "^19.2.3",

src/components/LayerListItem.jsx

Lines changed: 95 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2-
import { Box, ListItemText, IconButton, ListItem, ListItemAvatar, Avatar, ListItemButton, Link, Button, ButtonBase, Typography, CircularProgress, Accordion, AccordionDetails, AccordionSummary, Slider, Stack, Tooltip, TextField, MenuItem, Collapse } from '@mui/material';
2+
import { Box, ListItemText, IconButton, ListItem, ListItemAvatar, Avatar, ListItemButton, Link, Button, ButtonBase, Typography, CircularProgress, Accordion, AccordionDetails, AccordionSummary, Slider, Stack, Tooltip, TextField, MenuItem, Collapse, Chip } from '@mui/material';
33
import RouteIcon from '@mui/icons-material/Route';
44
import ZoomInIcon from '@mui/icons-material/ZoomIn';
5+
import ErrorIcon from '@mui/icons-material/Error';
56
import VisibilityIcon from '@mui/icons-material/Visibility';
67
import VisibilityOffIcon from '@mui/icons-material/VisibilityOff';
78
import RefreshIcon from '@mui/icons-material/Refresh';
@@ -18,7 +19,6 @@ export default function LayerListItem({
1819
onExpand,
1920
onZoom,
2021
onCurveEdit,
21-
onSettingChanged,
2222
}) {
2323
const { updateLayerById } = useMeshery();
2424
const [spacing, setSpacing] = useState(layer.spacing);
@@ -102,7 +102,7 @@ export default function LayerListItem({
102102
}, [spacing, digDepth, digDistance, digCurve]);
103103

104104
const isDisabled = useMemo(() => {
105-
return !layer.mesh || layer.pending || !layer.conformed;
105+
return layer.error || !layer.mesh || layer.pending || !layer.conformed;
106106
}, [layer]);
107107

108108
return (
@@ -119,12 +119,22 @@ export default function LayerListItem({
119119
}}
120120
onClick={handleClick}
121121
>
122-
{isDisabled ? (
123-
<CircularProgress size={15} />
122+
{layer.error ? (
123+
<Tooltip title={layer.error}>
124+
<ErrorIcon color="error" />
125+
</Tooltip>
124126
) : (
125-
<Avatar sx={{ backgroundColor: `#${layer.color}`, width: 15, height: 15 }}>{' '}</Avatar>
127+
isDisabled ? (
128+
<CircularProgress size={15} />
129+
) : (
130+
<Avatar sx={{ backgroundColor: `#${layer.color}`, width: 15, height: 15 }}>{' '}</Avatar>
131+
)
126132
)}
127-
<Box sx={{ flex: 1 }}>{layer.id}</Box>
133+
<Box sx={{ flex: 1 }}>
134+
<Typography component="span">{layer.surface}</Typography>{' '}
135+
<Typography color="textSecondary" component="span">{layer.name}</Typography>
136+
137+
</Box>
128138
<Box>
129139
{expanded ? <ExpandLessIcon /> : <ExpandMoreIcon />}
130140
</Box>
@@ -145,82 +155,86 @@ export default function LayerListItem({
145155
</IconButton>
146156
</Tooltip>
147157
</Box>
148-
149-
<Stack direction="column" spacing={1} sx={{ px: 2, pb: 2 }}>
150-
<Typography sx={{ m: 0 }} variant="h6">Triangle Spacing</Typography>
151-
<Stack direction="row" alignItems="center" spacing={1}>
152-
<Typography variant="body2">{spacing.toFixed(2)}</Typography>
153-
<Slider
154-
size="small"
155-
disabled={isDisabled}
156-
value={spacing}
157-
min={0.2}
158-
max={5}
159-
step={0.05}
160-
onChange={handleSpacingChange}
161-
/>
162-
</Stack>
163-
{layer.dig?.depth ? (
164-
<>
165-
<Typography sx={{ m: 0 }} variant="h6">Dig Depth</Typography>
166-
<Stack direction="row" alignItems="center" spacing={1}>
167-
<Typography variant="body2">{digDepth}</Typography>
168-
<Slider
169-
size="small"
170-
value={digDepth}
171-
disabled={isDisabled}
172-
min={0.01}
173-
max={10}
174-
step={0.01}
175-
onChange={handleDigDepthChange}
176-
/>
177-
</Stack>
178-
<Typography sx={{ m: 0 }} variant="h6">Dig Distance</Typography>
179-
<Stack direction="row" alignItems="center" spacing={1}>
180-
<Typography variant="body2">{digDistance}</Typography>
181-
<Slider
182-
size="small"
183-
value={digDistance}
184-
disabled={isDisabled}
185-
min={0.05}
186-
max={1}
187-
step={0.01}
188-
onChange={handleDigDistanceChange}
189-
/>
190-
</Stack>
191-
192-
<Typography sx={{ m: 0 }} variant="h6">Dig Curve</Typography>
193-
<Stack direction="row">
194-
<TextField select={true} value={layer.dig.curve} onChange={handleDigCurveChange} fullWidth={true} size="small">
195-
<MenuItem value="smooth">Smoothstep</MenuItem>
196-
<MenuItem value="linear">Linear</MenuItem>
197-
<MenuItem value="sine">Sine</MenuItem>
198-
{/* <MenuItem value="pow">Expo</MenuItem> */}
199-
<MenuItem value="bezier">Bezier</MenuItem>
200-
</TextField>
201-
202-
203-
<IconButton
204-
disabled={layer.dig.curve !== 'bezier'}
205-
onClick={() => setCurveEditorOpen(true)}
206-
>
207-
<RouteIcon />
208-
</IconButton>
209-
</Stack>
210-
211-
{/* <Typography sx={{ m: 0 }} variant="h6">Expo Power</Typography>
158+
{layer.error ? (
159+
<Box>{layer.error}</Box>
160+
) : (
161+
162+
<Stack direction="column" spacing={1} sx={{ px: 2, pb: 2 }}>
163+
<Typography sx={{ m: 0 }} variant="h6">Triangle Spacing</Typography>
164+
<Stack direction="row" alignItems="center" spacing={1}>
165+
<Typography variant="body2">{(spacing || 0).toFixed(2)}</Typography>
212166
<Slider
213167
size="small"
214-
value={layer.dig.curvePower}
215-
min={1}
216-
max={20}
217-
step={1}
218-
onChange={handleDigSmoothExpoChange}
219-
/> */}
220-
221-
</>
222-
) : null}
223-
</Stack>
168+
disabled={isDisabled}
169+
value={spacing}
170+
min={0.2}
171+
max={5}
172+
step={0.05}
173+
onChange={handleSpacingChange}
174+
/>
175+
</Stack>
176+
{layer.dig?.depth ? (
177+
<>
178+
<Typography sx={{ m: 0 }} variant="h6">Dig Depth</Typography>
179+
<Stack direction="row" alignItems="center" spacing={1}>
180+
<Typography variant="body2">{digDepth}</Typography>
181+
<Slider
182+
size="small"
183+
value={digDepth}
184+
disabled={isDisabled}
185+
min={0.01}
186+
max={10}
187+
step={0.01}
188+
onChange={handleDigDepthChange}
189+
/>
190+
</Stack>
191+
<Typography sx={{ m: 0 }} variant="h6">Dig Distance</Typography>
192+
<Stack direction="row" alignItems="center" spacing={1}>
193+
<Typography variant="body2">{digDistance}</Typography>
194+
<Slider
195+
size="small"
196+
value={digDistance}
197+
disabled={isDisabled}
198+
min={0.05}
199+
max={1}
200+
step={0.01}
201+
onChange={handleDigDistanceChange}
202+
/>
203+
</Stack>
204+
205+
<Typography sx={{ m: 0 }} variant="h6">Dig Curve</Typography>
206+
<Stack direction="row">
207+
<TextField select={true} value={layer.dig.curve} onChange={handleDigCurveChange} fullWidth={true} size="small">
208+
<MenuItem value="smooth">Smoothstep</MenuItem>
209+
<MenuItem value="linear">Linear</MenuItem>
210+
<MenuItem value="sine">Sine</MenuItem>
211+
{/* <MenuItem value="pow">Expo</MenuItem> */}
212+
<MenuItem value="bezier">Bezier</MenuItem>
213+
</TextField>
214+
215+
216+
<IconButton
217+
disabled={layer.dig.curve !== 'bezier'}
218+
onClick={() => setCurveEditorOpen(true)}
219+
>
220+
<RouteIcon />
221+
</IconButton>
222+
</Stack>
223+
224+
{/* <Typography sx={{ m: 0 }} variant="h6">Expo Power</Typography>
225+
<Slider
226+
size="small"
227+
value={layer.dig.curvePower}
228+
min={1}
229+
max={20}
230+
step={1}
231+
onChange={handleDigSmoothExpoChange}
232+
/> */}
233+
234+
</>
235+
) : null}
236+
</Stack>
237+
)}
224238

225239
</Collapse>
226240
</Box>

src/components/LayerSettings.jsx

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,14 @@ export default function LayerSettings() {
3232
heightScale: parseInt(tempHeight, 10),
3333
terrainSmoothingRadius: parseInt(tempSmooth, 10)
3434
}));
35-
}, 100);
35+
}, 800);
3636
}, [tempHeight, tempSmooth]);
3737

3838
return (
3939
<Box sx={{ px: 2, flexGrow: 0, flexShrink: 0 }}>
4040
<Typography sx={{ mb: 3 }} variant="h5" color="textSecondary">Settings</Typography>
4141
<Stack spacing={4}>
42-
<Tooltip title="The height scale of your terrain data. This can be found in your Course Terrain Tool stats file or from your Unity terrain settings">
42+
{/* <Tooltip title="The height scale of your terrain data. This can be found in your Course Terrain Tool stats file or from your Unity terrain settings"> */}
4343
<TextField
4444
fullWidth={true}
4545
label="Terrain Height (m)"
@@ -50,21 +50,12 @@ export default function LayerSettings() {
5050
size="small"
5151
onChange={handleScaleUpdate}
5252
/>
53-
</Tooltip>
54-
{/* <TextField
55-
fullWidth={true}
56-
label="Smoothing Strength"
57-
type="number"
58-
disabled={!settings.rawFilePath}
59-
value={settings.terrainSmoothingStrength}
60-
size="small"
61-
onChange={(e) => handleSmoothingUpdate(e, 'terrainSmoothingStrength')}
62-
/> */}
53+
{/* </Tooltip> */}
54+
6355
<TextField
6456
fullWidth={true}
6557
label="Terrain Smoothing"
6658
type="number"
67-
// disabled={!settings.rawFilePath}
6859
value={tempSmooth}
6960
size="small"
7061
onChange={handleSmoothingUpdate}

src/components/MeshLayer.jsx

Lines changed: 16 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,6 @@ import log from 'electron-log/renderer';
77
import { isPointInPolygon, distanceToPolygonEdge } from '../lib/mesh';
88

99
function cubicBezierY(points, t) {
10-
// points: [[x0,y0], [x1,y1], [x2,y2], [x3,y3]]
11-
// t: [0,1]
1210
const y0 = 1 - points[0][1];
1311
const y1 = 1 - points[1][1];
1412
const y2 = 1 - points[2][1];
@@ -39,7 +37,6 @@ function digMesh(original, positions, polygon, holes, digOptions) {
3937
insideList.push({ idx: i / 3, dist, point: [x, y, z] });
4038
}
4139
}
42-
console.log('maxDist', maxDist);
4340
const digDistance = distance * maxDist;
4441

4542
for (const obj of insideList) {
@@ -64,8 +61,6 @@ function digMesh(original, positions, polygon, holes, digOptions) {
6461
default:
6562
f = t * t * (3 - 2 * t);
6663
}
67-
// Lower the y (height) value
68-
// positions[obj.idx] -= f * depth;
6964
const [x, y, z] = obj.point;
7065
const reduce = (f * depth);
7166
positions.setXYZ(obj.idx, x, y - reduce, z);
@@ -86,7 +81,8 @@ function digMesh(original, positions, polygon, holes, digOptions) {
8681

8782
export default function MeshLayer(props) {
8883
const ref = useRef();
89-
84+
85+
const [firstLoad, setFirstLoad] = useState(false);
9086
const { generateMesh, conformMesh, finalHeightMap, settings, updateLayerById } = useMeshery();
9187
const [material, setMaterial] = useState(new THREE.MeshBasicMaterial({
9288
wireframe: settings.wireframe,
@@ -233,48 +229,44 @@ export default function MeshLayer(props) {
233229
props.layer.dig
234230
);
235231
positionAttr.needsUpdate = true;
236-
237-
// console.log('dig geometry', positionAttr.array);
238232
}, [props.layer, geometry]);
239233

240234
useEffect(() => {
241235
if (!props.layer.conformed) {
242236
return;
243237
}
244-
if (props.layer?.dig?.depth) {
245-
console.log('Dig mesh', props.layer);
246-
customDig();
238+
if (!props.layer?.dig?.depth) {
239+
return;
247240
}
248-
// conformMesh(props.layer).then(() => {
249-
// console.log('Done');
250-
// });
241+
customDig();
251242
}, [
252243
props.layer.dig?.depth,
253244
props.layer.dig?.distance,
254245
props.layer.dig?.curve,
255246
props.layer.dig?.curvePoints
256247
]);
257248

249+
250+
258251
useEffect(() => {
259252
if (!props.layer) {
260253
return;
261254
}
262-
console.log('layer created');
255+
if (!firstLoad) {
256+
// initial mesh generation is handled in the provider
257+
setFirstLoad(true);
258+
return;
259+
}
260+
log.info(`Regenerating mesh (${props.layer.id})`);
263261
generateMesh(props.layer).then(_response => {
264-
console.log('init-generateMesh', props.layer.id, _response.mesh);
265262
conformMesh({ ...props.layer, mesh: _response.mesh });
266-
// updateLayerById(props.layer.id, { mesh: response.mesh, conformed: false });
267263
});
268264
}, [props.layer.spacing]);
269265

270266
useEffect(() => {
271-
// if (props.layer) {
272-
console.log('update mat');
273-
material.opacity = props.layer.pending || !props.layer.conformed ? 0.3 : 1;
274-
// material.color = new THREE.Color('pink');
275-
material.needsUpdate = true;
276-
setMaterial(material);
277-
// }
267+
material.opacity = props.layer.pending || !props.layer.conformed ? 0.3 : 1;
268+
material.needsUpdate = true;
269+
setMaterial(material);
278270
}, [props.layer?.pending, props.layer?.conformed]);
279271

280272
useEffect(() => {

0 commit comments

Comments
 (0)