diff --git a/src/app/App.tsx b/src/app/App.tsx index 376a0b76..327c0994 100644 --- a/src/app/App.tsx +++ b/src/app/App.tsx @@ -1940,6 +1940,27 @@ export function App({ store, initialStatusMessage }: AppProps) { : materialInspectorScope === "face" ? selectedFaceMaterial : null; + const materialInspectorActiveLabel = + materialInspectorScope === "brush" ? "Whole Solid" : "Active Face"; + const materialInspectorActiveValue = + materialInspectorScope === "brush" + ? "All Six Faces" + : selectedFaceId === null + ? null + : BOX_FACE_LABELS[selectedFaceId]; + const materialInspectorMaterialSummary = + materialInspectorScope === "brush" && selectedBrushHasMixedFaceMaterials + ? "Mixed across faces" + : materialInspectorMaterial?.name ?? + (materialInspectorMaterialId === null + ? "Fallback face color" + : materialInspectorMaterialId ?? "Fallback face color"); + const materialInspectorUvState = + materialInspectorScope === "brush" && selectedBrush !== null + ? selectedBrush.faces[BOX_FACE_IDS[0]].uv + : materialInspectorScope === "face" + ? selectedFace?.uv ?? null + : null; const selectedModelAsset = selectedModelInstance !== null ? (editorState.document.assets[selectedModelInstance.assetId] ?? null) @@ -10505,23 +10526,26 @@ export function App({ store, initialStatusMessage }: AppProps) { createUpdateBoxBrushAllFaceUvsCommand({ brushId: selectedBrush.id, label: "Fit solid face UVs to face", - updateUvState: (uvState, faceId) => { - const material = - uvState === undefined + updateUvState: (_, faceId) => { + const currentMaterialId = selectedBrush.faces[faceId].materialId; + const currentMaterial = + currentMaterialId === null ? null - : currentMaterialId => currentMaterialId; - return materialInspectorMaterialId === undefined || - materialInspectorMaterial === null + : editorState.document.materials[currentMaterialId] ?? null; + + return currentMaterial === null ? createFitToFaceBoxBrushFaceUvState(selectedBrush, faceId) : createFitToMaterialTileBoxBrushFaceUvState( selectedBrush, faceId, - getStarterMaterialTileSizeMeters(materialInspectorMaterial) + getStarterMaterialTileSizeMeters(currentMaterial) ); } }) ); - setStatusMessage("Fit all selected whitebox face UVs to their face bounds."); + setStatusMessage( + "Fit all face UVs on the selected whitebox to their face bounds and tile size." + ); return; } @@ -18650,29 +18674,39 @@ export function App({ store, initialStatusMessage }: AppProps) { ) - ) : whiteboxSelectionMode !== "face" ? ( + ) : materialInspectorScope === null ? (
- Switch to Face mode or choose a face chip to edit - materials and UVs. -
- ) : selectedFace === null || selectedFaceId === null ? ( -
- Select a face to edit its material and UV transform. + {whiteboxSelectionMode === "face" + ? "Select a face to edit its material and UV transform." + : "Select a whitebox to edit material and UVs across all faces."}
) : ( <>
-
Active Face
+
+ {materialInspectorActiveLabel} +
- {BOX_FACE_LABELS[selectedFaceId]} + {materialInspectorActiveValue}
- Material:{" "} - {selectedFaceMaterial?.name ?? "Fallback face color"} + Material: {materialInspectorMaterialSummary}
+ {materialInspectorScope === "brush" ? ( +
+ Edits here apply to all six faces. +
+ ) : null} + {materialInspectorScope === "brush" && + selectedBrushHasMixedFaceUvs ? ( +
+ Mixed UV transforms will be overwritten where you + edit them here. +
+ ) : null}
@@ -18683,7 +18717,7 @@ export function App({ store, initialStatusMessage }: AppProps) { key={material.id} type="button" data-testid={`material-button-${material.id}`} - className={`material-item ${selectedFace.materialId === material.id ? "material-item--active" : ""}`} + className={`material-item ${materialInspectorMaterialId === material.id ? "material-item--active" : ""}`} onClick={() => applyFaceMaterial(material.id)} > { const nextValue = event.currentTarget.value; setUvOffsetDraft((draft) => ({ @@ -18747,6 +18787,12 @@ export function App({ store, initialStatusMessage }: AppProps) { type="number" step="0.125" value={uvOffsetDraft.y} + placeholder={ + materialInspectorScope === "brush" && + uvOffsetDraft.y === "" + ? "Mixed" + : undefined + } onChange={(event) => { const nextValue = event.currentTarget.value; setUvOffsetDraft((draft) => ({ @@ -18777,6 +18823,12 @@ export function App({ store, initialStatusMessage }: AppProps) { min="0.001" step="0.125" value={uvScaleDraft.x} + placeholder={ + materialInspectorScope === "brush" && + uvScaleDraft.x === "" + ? "Mixed" + : undefined + } onChange={(event) => { const nextValue = event.currentTarget.value; setUvScaleDraft((draft) => ({ @@ -18801,6 +18853,12 @@ export function App({ store, initialStatusMessage }: AppProps) { min="0.001" step="0.125" value={uvScaleDraft.y} + placeholder={ + materialInspectorScope === "brush" && + uvScaleDraft.y === "" + ? "Mixed" + : undefined + } onChange={(event) => { const nextValue = event.currentTarget.value; setUvScaleDraft((draft) => ({ @@ -18860,13 +18918,35 @@ export function App({ store, initialStatusMessage }: AppProps) {
UV Flags
-
- Rotation {selectedFace.uv.rotationQuarterTurns * 90}° -
-
- U {selectedFace.uv.flipU ? "flipped" : "normal"} · V{" "} - {selectedFace.uv.flipV ? "flipped" : "normal"} -
+ {materialInspectorScope === "brush" && + selectedBrushHasMixedFaceUvs ? ( + <> +
Mixed across faces
+
+ Rotation, flips, or numeric UV transforms differ + across this solid. +
+ + ) : materialInspectorUvState === null ? null : ( + <> +
+ Rotation{" "} + {materialInspectorUvState.rotationQuarterTurns * + 90} + ° +
+
+ U{" "} + {materialInspectorUvState.flipU + ? "flipped" + : "normal"}{" "} + · V{" "} + {materialInspectorUvState.flipV + ? "flipped" + : "normal"} +
+ + )}
)}