Placing procedural foliage spawners in code?

Does anyone know how to go about placing and modifying foliage generators in C++ code? I’ve followed the tutorial on how to place them in-editor, detailed [here][1], and now I’m trying to create a plugin that can place them using code. This is as far as I’ve gotten, thanks to miscellaneous help posts scattered around the UE4 AnswerHub:

UWorld* const World = GEditor->GetEditorWorldContext().World();
SpawnLocation = FVector(-30.f, -1300.f, 300.f);

AProceduralFoliageVolume* Cube = Cast<AProceduralFoliageVolume>(GEditor->AddActor(World->GetCurrentLevel(), AProceduralFoliageVolume::StaticClass(), FTransform(SpawnLocation)));

UCubeBuilder* Builder = NewObject<UCubeBuilder>(UCubeBuilder::StaticClass());
Cube->BrushBuilder = Builder;
Cube->Brush = Cast<UModel>(World->GetDefaultBrush());
Builder->X = 200.f;
Builder->Y = 200.f;
Builder->Z = 300.f;
Builder->PostEditChange();
Builder->Build(World, World->GetDefaultBrush());

The code places a procedural foliage volume, but it has no “volume” to it (see picture below). On the left is my volume, placed in code, and on the right is a volume placed manually in the editor (ignore the solid sample map cubes in the background). My last block of code is trying to give it a visible volume by using brushes, but it’s been unsuccessful so far. Changing the values in the details panel under “Brush Settings” doesn’t help.

94506-volume_example.png

If I somehow manage to get it to show up in the level editor, I’m also stumped as to how I will be able to modify the different foliage spawner attributes in code (types of foliage to spawn, relating a foliage spawner to the foliage volume, etc). ProceduralFoliageVolume.h and ProceduralFoliageSpawner.h don’t seem to have any methods or member variables that are publicly accessible and applicable to this situation, at least to my eyes.

Help with any of the above issues would be appreciated.

After more searching today, it looks like generating volumes through code isn’t really supported at all, since BrushComponents are very hard to build in code. Granted, this is a post from 2 years ago, but since I still can’t find any examples I’m guessing that the situation hasn’t changed. I’d be happy for someone to prove me wrong, though.

I’ve now moved on to moving/resizing/modifying existing foliage spawners in a level, using TActorIterator to iterate over all of them and change each one. I can set the scale (using SetActorScale3D) and location (SetActorLocation) without a problem. However, I still don’t know how much I can do with the foliage attributes, so the last paragraph of my question still stands.

Figured out a workaround. Instead of trying to spawn a volume in code and initialize all its parameters, you can base everything off an volume you already spawned in the editor. Like so:

AProceduralFoliageVolume* ClonedVolume = Cast<AProceduralFoliageVolume>(GEditor->AddActor(World->GetCurrentLevel(), AProceduralFoliageVolume::StaticClass(), FTransform(CloneLocation)));
				
ClonedVolume->BrushComponent->Brush = OriginalVolume->BrushComponent->Brush;
ClonedVolume->BrushComponent->BrushBodySetup = OriginalVolume->BrushComponent->BrushBodySetup;
				
ClonedVolume->ProceduralComponent->FoliageSpawner = OriginalVolume->ProceduralComponent->FoliageSpawner;
ClonedVolume->ProceduralComponent->TileOverlap = OriginalVolume->ProceduralComponent->TileOverlap;
ClonedVolume->ProceduralComponent->bShowDebugTiles = OriginalVolume->ProceduralComponent->bShowDebugTiles;

ClonedVolume->Brush = OriginalVolume->Brush;
ClonedVolume->BrushBuilder = OriginalVolume->BrushBuilder;
ClonedVolume->BrushColor = OriginalVolume->BrushColor;
ClonedVolume->BrushType = OriginalVolume->BrushType;
				
ClonedVolume->BrushBuilder->Build(World, Cast<ABrush>(ClonedVolume->Brush));
ClonedVolume->MarkComponentsRenderStateDirty();

Works like a charm.

So you basically don’t spawn any volumes? Why do you need to replicate the functionality of the foliage spawners then?