Add support for applying terrain foliage mask patches

This commit is contained in:
2026-05-02 04:11:58 +02:00
parent bc4b8e1b3a
commit e9657dc22d

View File

@@ -5,6 +5,8 @@ import type {
TerrainSampleValuePatch TerrainSampleValuePatch
} from "../core/terrain-brush"; } from "../core/terrain-brush";
import { import {
getOrCreateTerrainFoliageMask,
isTerrainFoliageMaskEmpty,
markTerrainRenderSamplesDirty, markTerrainRenderSamplesDirty,
TERRAIN_LAYER_COUNT, TERRAIN_LAYER_COUNT,
updateTerrainBoundsCacheAfterHeightPatch, updateTerrainBoundsCacheAfterHeightPatch,
@@ -46,7 +48,11 @@ function assertValidPatchEntry(
} }
export function isTerrainBrushPatchEmpty(patch: TerrainBrushPatch): boolean { export function isTerrainBrushPatchEmpty(patch: TerrainBrushPatch): boolean {
return patch.heightSamples.length === 0 && patch.paintWeights.length === 0; return (
patch.heightSamples.length === 0 &&
patch.paintWeights.length === 0 &&
patch.foliageMaskValues.length === 0
);
} }
function mergeTerrainSampleIndexIntoBounds( function mergeTerrainSampleIndexIntoBounds(
@@ -80,7 +86,10 @@ export function createApplyTerrainBrushPatchCommand(
const patch: TerrainBrushPatch = { const patch: TerrainBrushPatch = {
terrainId: options.patch.terrainId, terrainId: options.patch.terrainId,
heightSamples: options.patch.heightSamples.map((entry) => ({ ...entry })), heightSamples: options.patch.heightSamples.map((entry) => ({ ...entry })),
paintWeights: options.patch.paintWeights.map((entry) => ({ ...entry })) paintWeights: options.patch.paintWeights.map((entry) => ({ ...entry })),
foliageMaskValues: options.patch.foliageMaskValues.map((entry) => ({
...entry
}))
}; };
let previousSelection: EditorSelection | null = null; let previousSelection: EditorSelection | null = null;
let previousToolMode: ToolMode | null = null; let previousToolMode: ToolMode | null = null;
@@ -132,6 +141,32 @@ export function createApplyTerrainBrushPatchCommand(
); );
} }
for (const entry of patch.foliageMaskValues) {
if (currentDocument.foliageLayers[entry.layerId] === undefined) {
throw new Error(
`Foliage layer ${entry.layerId} does not exist for terrain mask patch.`
);
}
const mask = getOrCreateTerrainFoliageMask(terrain, entry.layerId);
assertValidPatchEntry(
entry,
mask.values.length,
"Terrain foliage mask"
);
mask.values[entry.index] =
direction === "forward" ? entry.after : entry.before;
renderDirtyBounds = mergeTerrainSampleIndexIntoBounds(
renderDirtyBounds,
terrain,
entry.index
);
if (isTerrainFoliageMaskEmpty(mask)) {
delete terrain.foliageMasks[entry.layerId];
}
}
markTerrainRenderSamplesDirty(terrain, renderDirtyBounds); markTerrainRenderSamplesDirty(terrain, renderDirtyBounds);
context.setDocument({ context.setDocument({