diff --git a/src/app/App.tsx b/src/app/App.tsx index df30d7e0..3c92eeb7 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -16194,6 +16194,284 @@ export function App({ store, draftStorage = null, initialStatusMessage }: AppPro + + + Bundled Library + + {SORTED_BUNDLED_FOLIAGE_PROTOTYPES.length} prototypes + + + Engine-owned GLB assets are available for authored foliage + layers. This panel does not create placed model instances. + + + + + Prototype Library + + {[ + ...SORTED_BUNDLED_FOLIAGE_PROTOTYPES, + ...customFoliagePrototypeList + ].map((prototype) => ( + + + + + {prototype.label} + + + {prototype.category} ·{" "} + {formatFoliagePrototypeSource(prototype)} + + + + + {formatFoliagePrototypeLodStatus(prototype)} + + + {formatFoliagePrototypeLodDistanceSummary(prototype)} + + + ))} + + + + + Scene Layers + + + Create Layer + + + + {foliageLayerList.length === 0 ? ( + + No foliage layers are authored for this scene. + + ) : ( + foliageLayerList.map((layer) => ( + + + + handleFoliageLayerEnabledChange( + layer, + event.currentTarget.checked + ) + } + /> + { + setActiveFoliageLayerId(layer.id); + setStatusMessage( + `${layer.name} is the active foliage layer.` + ); + }} + > + + {layer.name} + + + {layer.prototypeIds.length} prototype + {layer.prototypeIds.length === 1 ? "" : "s"} · + density {layer.density} + + + handleDeleteFoliageLayer(layer.id)} + > + x + + + + )) + )} + + + + {activeFoliageLayer === null ? null : ( + <> + + Active Layer + + Name + + setFoliageLayerNameDraft( + event.currentTarget.value + ) + } + onBlur={applyActiveFoliageLayerName} + onKeyDown={(event) => { + if (event.key === "Enter") { + applyActiveFoliageLayerName(); + } else if (event.key === "Escape") { + setFoliageLayerNameDraft( + activeFoliageLayer.name + ); + } + }} + /> + + + Enabled + + handleFoliageLayerEnabledChange( + activeFoliageLayer, + event.currentTarget.checked + ) + } + /> + + + Active layer state is editor UI state. The layer data + itself persists with the scene. + + + + + Scatter Settings + + {FOLIAGE_LAYER_NUMERIC_INPUTS.map((input) => ( + + {input.label} + + handleFoliageLayerNumberDraftChange( + input.field, + event.currentTarget.value + ) + } + onBlur={() => + applyActiveFoliageLayerNumericField( + input.field + ) + } + onKeyDown={(event) => + handleDraftVectorKeyDown(event, () => + applyActiveFoliageLayerNumericField( + input.field + ) + ) + } + onKeyUp={(event) => + handleNumberInputKeyUp(event, () => + applyActiveFoliageLayerNumericField( + input.field + ) + ) + } + onPointerUp={(event) => + handleNumberInputPointerUp(event, () => + applyActiveFoliageLayerNumericField( + input.field + ) + ) + } + /> + + ))} + + + + + Prototype Mix + + {SORTED_BUNDLED_FOLIAGE_PROTOTYPES.map( + (prototype) => ( + + + + handleFoliagePrototypeSelectionChange( + prototype.id, + event.currentTarget.checked + ) + } + /> + + + {prototype.label} + + + {prototype.category} ·{" "} + {formatFoliagePrototypeLodStatus( + prototype + )} + + + + + ) + )} + + + > + )} + + Clock