Add UI controls for configuring road edge properties (profile, width, height, material)
This commit is contained in:
141
src/app/App.tsx
141
src/app/App.tsx
@@ -22291,6 +22291,143 @@ export function App({
|
|||||||
))}
|
))}
|
||||||
</select>
|
</select>
|
||||||
</label>
|
</label>
|
||||||
|
{(["left", "right"] as const).map((side) => {
|
||||||
|
const edge = selectedPath.road.edges[side];
|
||||||
|
const edgeLabel = side === "left" ? "Left Edge" : "Right Edge";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="form-section" key={side}>
|
||||||
|
<div className="label">{edgeLabel}</div>
|
||||||
|
<label className="form-field form-field--toggle">
|
||||||
|
<span className="label">Enable edge mesh</span>
|
||||||
|
<input
|
||||||
|
data-testid={`path-road-edge-${side}-enabled`}
|
||||||
|
type="checkbox"
|
||||||
|
checked={edge.enabled}
|
||||||
|
onChange={(event) =>
|
||||||
|
handlePathRoadEdgeChange(
|
||||||
|
side,
|
||||||
|
{
|
||||||
|
...edge,
|
||||||
|
enabled: event.currentTarget.checked
|
||||||
|
},
|
||||||
|
event.currentTarget.checked
|
||||||
|
? `Enabled ${edgeLabel.toLowerCase()} mesh.`
|
||||||
|
: `Disabled ${edgeLabel.toLowerCase()} mesh.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label className="form-field">
|
||||||
|
<span className="label">Profile</span>
|
||||||
|
<select
|
||||||
|
className="select-input"
|
||||||
|
data-testid={`path-road-edge-${side}-kind`}
|
||||||
|
value={edge.kind}
|
||||||
|
onChange={(event) =>
|
||||||
|
handlePathRoadEdgeChange(
|
||||||
|
side,
|
||||||
|
{
|
||||||
|
...edge,
|
||||||
|
kind: normalizeScenePathRoadEdgeKind(
|
||||||
|
event.currentTarget.value
|
||||||
|
)
|
||||||
|
},
|
||||||
|
`Updated ${edgeLabel.toLowerCase()} profile.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{(
|
||||||
|
[
|
||||||
|
"curb",
|
||||||
|
"softShoulder",
|
||||||
|
"bank",
|
||||||
|
"ditch"
|
||||||
|
] as const
|
||||||
|
).map((kind) => (
|
||||||
|
<option key={kind} value={kind}>
|
||||||
|
{getRoadEdgeKindLabel(kind)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label className="form-field">
|
||||||
|
<span className="label">Width</span>
|
||||||
|
<input
|
||||||
|
className="text-input"
|
||||||
|
data-testid={`path-road-edge-${side}-width`}
|
||||||
|
type="number"
|
||||||
|
min={0.01}
|
||||||
|
step={0.05}
|
||||||
|
value={edge.width}
|
||||||
|
onChange={(event) =>
|
||||||
|
handlePathRoadEdgeChange(
|
||||||
|
side,
|
||||||
|
{
|
||||||
|
...edge,
|
||||||
|
width: normalizeScenePathRoadEdgeWidth(
|
||||||
|
Number(event.currentTarget.value)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
`Updated ${edgeLabel.toLowerCase()} width.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label className="form-field">
|
||||||
|
<span className="label">Height</span>
|
||||||
|
<input
|
||||||
|
className="text-input"
|
||||||
|
data-testid={`path-road-edge-${side}-height`}
|
||||||
|
type="number"
|
||||||
|
min={0}
|
||||||
|
step={0.05}
|
||||||
|
value={edge.height}
|
||||||
|
onChange={(event) =>
|
||||||
|
handlePathRoadEdgeChange(
|
||||||
|
side,
|
||||||
|
{
|
||||||
|
...edge,
|
||||||
|
height: normalizeScenePathRoadEdgeHeight(
|
||||||
|
Number(event.currentTarget.value)
|
||||||
|
)
|
||||||
|
},
|
||||||
|
`Updated ${edgeLabel.toLowerCase()} height.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label className="form-field">
|
||||||
|
<span className="label">Material Placeholder</span>
|
||||||
|
<select
|
||||||
|
className="select-input"
|
||||||
|
data-testid={`path-road-edge-${side}-material`}
|
||||||
|
value={edge.materialId ?? ""}
|
||||||
|
onChange={(event) =>
|
||||||
|
handlePathRoadEdgeChange(
|
||||||
|
side,
|
||||||
|
{
|
||||||
|
...edge,
|
||||||
|
materialId:
|
||||||
|
normalizeScenePathRoadEdgeMaterialId(
|
||||||
|
event.currentTarget.value
|
||||||
|
)
|
||||||
|
},
|
||||||
|
`Updated ${edgeLabel.toLowerCase()} material.`
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<option value="">Profile fallback</option>
|
||||||
|
{materialList.map((material) => (
|
||||||
|
<option key={material.id} value={material.id}>
|
||||||
|
{material.name}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
})}
|
||||||
<div className="inline-actions">
|
<div className="inline-actions">
|
||||||
<button
|
<button
|
||||||
className="toolbar__button"
|
className="toolbar__button"
|
||||||
@@ -22307,8 +22444,8 @@ export function App({
|
|||||||
spline. Applying it patches terrain heights, terrain paint
|
spline. Applying it patches terrain heights, terrain paint
|
||||||
weights, auto-adds the selected road material to terrain
|
weights, auto-adds the selected road material to terrain
|
||||||
layers when there is room, and patches foliage blocker
|
layers when there is room, and patches foliage blocker
|
||||||
masks. It does not generate a
|
masks. Runtime/editor generated road and edge meshes stay
|
||||||
road mesh yet.
|
derived from these settings.
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user