Download

ComponentVisualizer doesn't work for StaticMeshActor placements

I’m working on a VR project where I am trying a different sort of teleport movement. Imagine the ground in the game has been subdivided into a grid of room-scale sized chunks. Rather than teleport to a specific position you would teleport to whatever room scale sized rectangle you happened to be pointing at.

To help author my maps, I wanted to add a ComponentVisualizer that would draw the bounds of the nearest room-scale sized chunk as I am positioning props in the environment. This is working great for some placements (e.g. lights, skysphere), but not for StaticMeshActor placements like floor pieces and furniture. I attached a debugger and saw that my DrawVisualization call isn’t even getting hit when I select those placements in the editor.

I registered the ComponentVisualizer to draw for USceneComponent:


if (Visualizer.IsValid())
{
	GUnrealEd->RegisterComponentVisualizer(USceneComponent::StaticClass()->GetFName(), Visualizer);
	Visualizer->OnRegister();
}

Anyone know what might be going wrong for me? Thanks in advance for the help! :slight_smile:

It will be getting overridden by engine-level visualizers that are registered for derived classes of USceneComponent. So you only see your own for component types that don’t already have a visualizer. Try calling UnregisterComponentVisualizer
to see if you can remove the default engine ones.

Thanks for the reply!

I went ahead and gave that a naive attempt at what you described without any success.


if (Visualizer.IsValid())
{
	GUnrealEd->UnregisterComponentVisualizer(USceneComponent::StaticClass()->GetFName());
	GUnrealEd->RegisterComponentVisualizer(USceneComponent::StaticClass()->GetFName(), Visualizer);
	Visualizer->OnRegister();
}


Even if it worked, I’m concerned about what the engine-level visualizers would have been doing for me that I’d now be missing.

Is there a way I can maybe create my own empty component that I specify always exists on any map placement? Then I could hook up the visualizer to that component to avoid any conflicts…

I meant to remove for the specific classes that have their own visualizers, for example


GUnrealEd->UnregisterComponentVisualizer(UStaticMeshComponent::StaticClass()->GetFName());

But yeah this is a bit of a hack. You probably don’t want a visualizer attached to everything placed in your map, since it’s really these regions that you’re visualizing, not the actors themselves.
Does this grid have some representation in the level, some actor for example that defines it? It would make sense to add a visualizer to that, and have it draw based on what the current editor selection is perhaps.

Right now I was hoping to simply raycast against a plane and do a division on the x/y results to figure out what “cell” I’m in for movement. Or to put it another way, I wasn’t necessarily planning to add editor markup to define the grid. I simply wanted to build content around where those boundaries happened to fall mathematically (e.g. every 2 meters in x, every 2.5 meters in y, or something along those lines).

It’s entirely likely that I’ll end up needing a system to mark out which cells on the grid are usable and can be traveled to, at which point I would create a component to put on a custom blueprint object which tracks that data along with a component visualizer to help me draw and edit included cells. I would have that object simply floating somewhere in the map and would select it to author that data.

At the end of the day though, I still need to see the grid when placing a table or chair, and I wouldn’t want to have that grid object also selected and getting translated/rotated while I work just to get the data visualization.

Maybe there is a way for the visualization to not be selection based so that if I place an object in a map with a custom component to handle my grid, it ALWAYS draws some additional visualization whether or not it is selected?

But you only want to draw a visualization relating to the currently selected object, correct? In that case, forcing yourself to add a custom component to every single object you want to put in your map would be overkill.

You should probably create a custom primitive component (rather than a visualizer) to do the rendering, that way you have complete control over when it gets drawn. It could be an editor-only component. Add a single actor containing that component to your map, and let it do the drawing, regardless of whether it is itself selected or not. You’ll need to add a listener for changes in editor selection in order to determine what the component should draw.

Awesome! This totally sounds like the way to go, but I’m having trouble figuring out the specifics. Maybe you (or another equally amazing/helpful individual) can help:

  1. How do I create an “editor only” component? When I google this most of the results are about editor only actors. So maybe I make a regular component and put it on an editor only actor? (Not 100 percent sure how to specify an actor as editor only yet)

  2. I went ahead and created a custom component, but I’m having trouble finding a virtual “draw” function to override to render the grid lines.

  3. Maybe instead of overriding a draw function like I specified in #2 above, maybe I just need a visualizer for this new custom component, but I’m not certain yet how to have it “always on.”

  4. How do I intercept the selection changed “event” in code so I can update the drawing in my component or visualizer?

I’m still digging through documentation but if anyone can help out with any of these 4 topics it would be a huge help! :slight_smile:

Thanks so much for all the assistance so far. I feel like I’m getting close to a solution!

Component visualizer approach is a lot simpler, if you can have it draw at all times. I don’t know if that’s possible though.

If you need to go the other route, you have to create a primitive scene proxy that does the drawing for the component on the render thread, it’s a bit involved. I have a slightly outdated example online here, but you can find more complete and up to date examples in the engine code.

Look at USelection in Selection.h for a changed event you can bind to.