Feat: Implement comprehensive foliage layer management features (creation, renaming, deletion, and property updates)
This commit is contained in:
213
src/app/App.tsx
213
src/app/App.tsx
@@ -8995,6 +8995,219 @@ export function App({ store, draftStorage = null, initialStatusMessage }: AppPro
|
||||
}
|
||||
};
|
||||
|
||||
const handleCreateFoliageLayer = () => {
|
||||
try {
|
||||
const nextLayer = createFoliageLayer({
|
||||
name:
|
||||
foliageLayerList.length === 0
|
||||
? "Foliage Layer"
|
||||
: `Foliage Layer ${foliageLayerList.length + 1}`
|
||||
});
|
||||
|
||||
store.executeCommand(
|
||||
createCreateFoliageLayerCommand({
|
||||
layer: nextLayer,
|
||||
label: "Create foliage layer"
|
||||
})
|
||||
);
|
||||
setActiveFoliageLayerId(nextLayer.id);
|
||||
setStatusMessage(`Created ${nextLayer.name}.`);
|
||||
} catch (error) {
|
||||
setStatusMessage(getErrorMessage(error));
|
||||
}
|
||||
};
|
||||
|
||||
const updateFoliageLayer = (
|
||||
layer: FoliageLayer,
|
||||
label: string,
|
||||
successMessage: string
|
||||
) => {
|
||||
store.executeCommand(
|
||||
createUpdateFoliageLayerCommand({
|
||||
layer,
|
||||
label
|
||||
})
|
||||
);
|
||||
setStatusMessage(successMessage);
|
||||
};
|
||||
|
||||
const applyActiveFoliageLayerName = () => {
|
||||
if (activeFoliageLayer === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextName = foliageLayerNameDraft.trim();
|
||||
|
||||
if (nextName.length === 0) {
|
||||
setFoliageLayerNameDraft(activeFoliageLayer.name);
|
||||
setStatusMessage("Foliage layer name must not be empty.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (nextName === activeFoliageLayer.name) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const nextLayer = createFoliageLayer({
|
||||
...activeFoliageLayer,
|
||||
name: nextName
|
||||
});
|
||||
|
||||
updateFoliageLayer(
|
||||
nextLayer,
|
||||
"Rename foliage layer",
|
||||
`Renamed foliage layer to ${nextLayer.name}.`
|
||||
);
|
||||
} catch (error) {
|
||||
setStatusMessage(getErrorMessage(error));
|
||||
}
|
||||
};
|
||||
|
||||
const handleFoliageLayerEnabledChange = (
|
||||
layer: FoliageLayer,
|
||||
enabled: boolean
|
||||
) => {
|
||||
if (layer.enabled === enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const nextLayer = createFoliageLayer({
|
||||
...layer,
|
||||
enabled
|
||||
});
|
||||
|
||||
updateFoliageLayer(
|
||||
nextLayer,
|
||||
enabled ? "Enable foliage layer" : "Disable foliage layer",
|
||||
`${nextLayer.name} is now ${enabled ? "enabled" : "disabled"}.`
|
||||
);
|
||||
} catch (error) {
|
||||
setStatusMessage(getErrorMessage(error));
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteFoliageLayer = (layerId: string) => {
|
||||
const layer = editorState.document.foliageLayers[layerId];
|
||||
|
||||
if (layer === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!confirmDeleteSceneItem(layer.name)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const nextActiveLayer = foliageLayerList.find(
|
||||
(currentLayer) => currentLayer.id !== layerId
|
||||
);
|
||||
|
||||
store.executeCommand(createDeleteFoliageLayerCommand(layerId));
|
||||
setActiveFoliageLayerId(nextActiveLayer?.id ?? null);
|
||||
setStatusMessage(`Deleted ${layer.name}.`);
|
||||
} catch (error) {
|
||||
setStatusMessage(getErrorMessage(error));
|
||||
}
|
||||
};
|
||||
|
||||
const applyActiveFoliageLayerNumericField = (
|
||||
field: FoliageLayerNumericField
|
||||
) => {
|
||||
if (activeFoliageLayer === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const label = getFoliageLayerNumericFieldLabel(field);
|
||||
|
||||
try {
|
||||
const nextValue = readFoliageLayerNumericDraft(
|
||||
field,
|
||||
foliageLayerNumberDrafts[field]
|
||||
);
|
||||
|
||||
if (activeFoliageLayer[field] === nextValue) {
|
||||
setFoliageLayerNumberDrafts(
|
||||
createFoliageLayerNumberDrafts(activeFoliageLayer)
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
const nextLayer = createFoliageLayer({
|
||||
...activeFoliageLayer,
|
||||
[field]: nextValue
|
||||
});
|
||||
|
||||
updateFoliageLayer(
|
||||
nextLayer,
|
||||
`Set foliage ${label.toLowerCase()}`,
|
||||
`Updated ${activeFoliageLayer.name} ${label.toLowerCase()}.`
|
||||
);
|
||||
} catch (error) {
|
||||
setStatusMessage(getErrorMessage(error));
|
||||
}
|
||||
};
|
||||
|
||||
const handleFoliageLayerNumberDraftChange = (
|
||||
field: FoliageLayerNumericField,
|
||||
value: string
|
||||
) => {
|
||||
setFoliageLayerNumberDrafts((currentDrafts) => ({
|
||||
...currentDrafts,
|
||||
[field]: value
|
||||
}));
|
||||
};
|
||||
|
||||
const handleFoliagePrototypeSelectionChange = (
|
||||
prototypeId: string,
|
||||
selected: boolean
|
||||
) => {
|
||||
if (
|
||||
activeFoliageLayer === null ||
|
||||
!BUNDLED_FOLIAGE_PROTOTYPE_IDS.has(prototypeId)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const currentPrototypeIds = activeFoliageLayer.prototypeIds;
|
||||
const hasPrototypeId = currentPrototypeIds.includes(prototypeId);
|
||||
|
||||
if (hasPrototypeId === selected) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nextPrototypeIds = selected
|
||||
? [...currentPrototypeIds, prototypeId]
|
||||
: currentPrototypeIds.filter(
|
||||
(currentPrototypeId) => currentPrototypeId !== prototypeId
|
||||
);
|
||||
const validPrototypeIds = getValidFoliageLayerPrototypeIds(
|
||||
nextPrototypeIds,
|
||||
editorState.document.foliagePrototypes
|
||||
);
|
||||
|
||||
try {
|
||||
const prototype = BUNDLED_FOLIAGE_PROTOTYPES.find(
|
||||
(currentPrototype) => currentPrototype.id === prototypeId
|
||||
);
|
||||
const nextLayer = createFoliageLayer({
|
||||
...activeFoliageLayer,
|
||||
prototypeIds: validPrototypeIds
|
||||
});
|
||||
|
||||
updateFoliageLayer(
|
||||
nextLayer,
|
||||
selected ? "Add foliage prototype" : "Remove foliage prototype",
|
||||
`${prototype?.label ?? prototypeId} ${
|
||||
selected ? "added to" : "removed from"
|
||||
} ${nextLayer.name}.`
|
||||
);
|
||||
} catch (error) {
|
||||
setStatusMessage(getErrorMessage(error));
|
||||
}
|
||||
};
|
||||
|
||||
const handleArmTerrainBrushTool = (tool: TerrainBrushTool) => {
|
||||
if (selectedTerrain === null) {
|
||||
return;
|
||||
|
||||
Reference in New Issue
Block a user