Feat: Add advanced rendering controls and validation for foliage settings
This commit is contained in:
119
src/app/App.tsx
119
src/app/App.tsx
@@ -19021,6 +19021,125 @@ export function App({ store, draftStorage = null, initialStatusMessage }: AppPro
|
|||||||
/>
|
/>
|
||||||
</label>
|
</label>
|
||||||
|
|
||||||
|
<div className="form-section">
|
||||||
|
<div className="label">Foliage</div>
|
||||||
|
<label className="form-field form-field--toggle">
|
||||||
|
<span className="label">Enabled</span>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
checked={advancedRendering.foliage.enabled}
|
||||||
|
onChange={(event) =>
|
||||||
|
applyAdvancedRenderingFoliageEnabled(
|
||||||
|
event.currentTarget.checked
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<div className="vector-inputs vector-inputs--two">
|
||||||
|
<label className="form-field">
|
||||||
|
<span className="label">Density</span>
|
||||||
|
<input
|
||||||
|
className="text-input"
|
||||||
|
type="number"
|
||||||
|
min={MIN_FOLIAGE_QUALITY_DENSITY_MULTIPLIER}
|
||||||
|
max={MAX_FOLIAGE_QUALITY_DENSITY_MULTIPLIER}
|
||||||
|
step="0.05"
|
||||||
|
value={
|
||||||
|
advancedRenderingFoliageDensityMultiplierDraft
|
||||||
|
}
|
||||||
|
onChange={(event) =>
|
||||||
|
setAdvancedRenderingFoliageDensityMultiplierDraft(
|
||||||
|
event.currentTarget.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onBlur={
|
||||||
|
applyAdvancedRenderingFoliageDensityMultiplier
|
||||||
|
}
|
||||||
|
onKeyDown={(event) =>
|
||||||
|
handleDraftVectorKeyDown(
|
||||||
|
event,
|
||||||
|
applyAdvancedRenderingFoliageDensityMultiplier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onKeyUp={(event) =>
|
||||||
|
handleNumberInputKeyUp(
|
||||||
|
event,
|
||||||
|
applyAdvancedRenderingFoliageDensityMultiplier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onPointerUp={(event) =>
|
||||||
|
handleNumberInputPointerUp(
|
||||||
|
event,
|
||||||
|
applyAdvancedRenderingFoliageDensityMultiplier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
<label className="form-field">
|
||||||
|
<span className="label">Distance</span>
|
||||||
|
<input
|
||||||
|
className="text-input"
|
||||||
|
type="number"
|
||||||
|
min={
|
||||||
|
MIN_FOLIAGE_QUALITY_MAX_DISTANCE_MULTIPLIER
|
||||||
|
}
|
||||||
|
max={
|
||||||
|
MAX_FOLIAGE_QUALITY_MAX_DISTANCE_MULTIPLIER
|
||||||
|
}
|
||||||
|
step="0.05"
|
||||||
|
value={
|
||||||
|
advancedRenderingFoliageMaxDistanceMultiplierDraft
|
||||||
|
}
|
||||||
|
onChange={(event) =>
|
||||||
|
setAdvancedRenderingFoliageMaxDistanceMultiplierDraft(
|
||||||
|
event.currentTarget.value
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onBlur={
|
||||||
|
applyAdvancedRenderingFoliageMaxDistanceMultiplier
|
||||||
|
}
|
||||||
|
onKeyDown={(event) =>
|
||||||
|
handleDraftVectorKeyDown(
|
||||||
|
event,
|
||||||
|
applyAdvancedRenderingFoliageMaxDistanceMultiplier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onKeyUp={(event) =>
|
||||||
|
handleNumberInputKeyUp(
|
||||||
|
event,
|
||||||
|
applyAdvancedRenderingFoliageMaxDistanceMultiplier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
onPointerUp={(event) =>
|
||||||
|
handleNumberInputPointerUp(
|
||||||
|
event,
|
||||||
|
applyAdvancedRenderingFoliageMaxDistanceMultiplier
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<label className="form-field">
|
||||||
|
<span className="label">Shadows</span>
|
||||||
|
<select
|
||||||
|
className="select-input"
|
||||||
|
value={advancedRendering.foliage.shadows}
|
||||||
|
onChange={(event) =>
|
||||||
|
applyAdvancedRenderingFoliageShadows(
|
||||||
|
event.currentTarget
|
||||||
|
.value as FoliageQualityShadowMode
|
||||||
|
)
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{FOLIAGE_QUALITY_SHADOW_MODES.map((shadowMode) => (
|
||||||
|
<option key={shadowMode} value={shadowMode}>
|
||||||
|
{formatFoliageQualityShadowModeLabel(shadowMode)}
|
||||||
|
</option>
|
||||||
|
))}
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
|
||||||
{!advancedRendering.enabled ? null : (
|
{!advancedRendering.enabled ? null : (
|
||||||
<>
|
<>
|
||||||
<div className="form-section">
|
<div className="form-section">
|
||||||
|
|||||||
@@ -1713,6 +1713,13 @@ describe("validateSceneDocument", () => {
|
|||||||
density: Number.NaN,
|
density: Number.NaN,
|
||||||
sourceSize: 0,
|
sourceSize: 0,
|
||||||
samples: 0
|
samples: 0
|
||||||
|
},
|
||||||
|
foliage: {
|
||||||
|
...document.world.advancedRendering.foliage,
|
||||||
|
enabled: "yes",
|
||||||
|
densityMultiplier: 3,
|
||||||
|
maxDistanceMultiplier: 0,
|
||||||
|
shadows: "close"
|
||||||
}
|
}
|
||||||
} as any;
|
} as any;
|
||||||
|
|
||||||
@@ -1852,6 +1859,22 @@ describe("validateSceneDocument", () => {
|
|||||||
code: "invalid-advanced-rendering-god-rays-samples",
|
code: "invalid-advanced-rendering-god-rays-samples",
|
||||||
path: "world.advancedRendering.godRays.samples"
|
path: "world.advancedRendering.godRays.samples"
|
||||||
}),
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
code: "invalid-foliage-quality-enabled",
|
||||||
|
path: "world.advancedRendering.foliage.enabled"
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
code: "invalid-foliage-quality-density-multiplier",
|
||||||
|
path: "world.advancedRendering.foliage.densityMultiplier"
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
code: "invalid-foliage-quality-max-distance-multiplier",
|
||||||
|
path: "world.advancedRendering.foliage.maxDistanceMultiplier"
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
code: "invalid-foliage-quality-shadows",
|
||||||
|
path: "world.advancedRendering.foliage.shadows"
|
||||||
|
}),
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
code: "invalid-advanced-rendering-fog-path",
|
code: "invalid-advanced-rendering-fog-path",
|
||||||
path: "world.advancedRendering.fogPath"
|
path: "world.advancedRendering.fogPath"
|
||||||
|
|||||||
Reference in New Issue
Block a user