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"}
+
+ >
+ )}
>
)}