Improve `Camera` naming and make `bevy_ui` respect cameras
- Dominant language
- Rust
- Stars
- 48.2k
- Forks
- 4.8k
- Avg merge
- 3d 22h
- Merged PRs (30d)
- 161
Description
Consider renaming `Camera` to something like `RenderSurface`. There isn't anything camera-like about our `Camera` component, and I think calling it a `RenderSurface` is more apt:
- It has a size and position (viewport rect) that directly ties to the dimensions of the image you are rendering.
- It has a target to render the 2d area to.
- It can be `order`ed with other render surfaces that have the same target.
This is why `bevy_picking` relies on `Camera` - because the `Camera` component really describes the 2d area that `Camera2d` and `Camera3d` render to.
Following that first thought, there is a natural one-to-one cardinality between a UI tree and it's `RenderSurface` (`Camera`). You can't really show a UI tree on multiple render surfaces, because the size of the UI is dependent on the size of the render surface it is given to lay out into.
This is why, when this came up last time, I suggested that UI trees should be children of a `RenderSurface` (`Camera`). It would also, IMO solve some of the DX issues. You aren't spawning a freestanding UI camera, a freestanding UI tree, then linking them with a `TargetCamera`, it would make way more sense to me if the UI tree used our existing relationship for this: parenting.
If you want to have multiple UI trees on the same image, well, you would have a unique `RenderSurface`(`Camera`) at the root of each of these trees. This is nice because the `order` of these UI's sharing the same render target is explicit.
```rs
// Instead of
let ui_camera = commands.spawn(Camera);
commands.spawn((Node, TargetCamera(ui_camera)).with_children(|| /*...*/);
// What happens if two UI roots target the same camera? How are they ordered?
commands.spawn((Node, TargetCamera(ui_camera)).with_children(|| /*...*/);
// Renaming `Camera` to `RenderSurface` to illustrate this is what it really means:
// Two UIs and a 3d camera rendering to the default window, with order specified
// The render surface *is* the root UI node: it sets the viewport that can be drawn
comands.spawn((RenderSurface { order: 0, .. }, Node)).with_children(|| /*...*/);
comands.spawn((RenderSurface { order: 1, .. }, Node)).with_children(|| /*...*/);
comands.spawn((RenderSurface { order: 3 }, Camera3d))
```
You can also see how the UI/3d/2d can share the same abstractions for viewports, camera order, render targets.
For example, rendering the UIs to the second window, with a particular order, using a different sub viewport:
```rs
comands
.spawn((RenderSurface { order: 0, viewport: Some(viewport_1), target: window_2 }, Node))
.with_children(|parent| parent.spawn(Node));
comands
.spawn((RenderSurface { order: 1, viewport: Some(viewport_2, target: window_2 }, Node))
.with_children(|parent| parent.spawn(Node));
```
Some relevant comments:
- @NthTensor: Oh, as an added benefit: people are constantly annoyed at how cumbersome it is to overlay 3d models on UI currently. This seems like it might be an interesting way to solve that little rough spot.
Contributor guide
Assessment
This issue has not been assessed yet.