Commit Graph

7 Commits

Author SHA1 Message Date
andriyDev 61127f6d01 Replace all different load variants in AssetServer with a builder. (#23663)
# Objective

- In 0.18, we had 10 different functions that load assets (I'm not even
counting `load_folder`).
- In 0.19, we've even added `load_erased` - but it unfortunately doesn't
support all the features that the other variants support.
- We apparently needed `load_acquire_with_settings_override` which 1)
loads the asset, 2) uses the settings provided, 3) allows reading
unapproved asset paths, and 4) drops a guard once the load completes.
- That's fine if that's necessary. But we needed to create an explicit
variant for that.
- We need fewer load paths!

## Solution

- Create a builder.
- Store all these options dynamically instead of statically handling
each case.
- Have the caller choose a particular "kind" of load when they are
ready: `load`, `load_erased`, `load_untyped`, or `load_untyped_async`.
- I intentionally didn't provide a `load_async` or `load_erased_async`,
since those can be replicated using `load`/`load_erased` +
`AssetServer::wait_for_asset_id` to get the exact same effect.

I am also intentionally leaving `NestedLoader` untouched in this PR, but
a followup will duplicate this API for `NestedLoader`, which should make
it easier to understand.

Unlike the `NestedLoader` API, we aren't doing any type-state craziness,
so the docs are much more clear: users don't need to understand how
type-state stuff works, they just call the handful of methods on the
type. The "cost" here is we now need to be careful about including the
cross product of loads between static asset type, runtime asset type, or
dynamic asset type, crossed with deferred or async. In theory, if we
added more kinds on either side, we would need to expand this cross
product a lot. In practice though, it seems unlikely there will be any
more variants there. (maybe there could be a blocking variant? I don't
think this is a popular opinion though).

A big con here is some somewhat common calls are now more verbose.
Specifically, `asset_server.load_with_settings()` has become
`asset_server.load_builder().with_settings().load()`. I am not really
concerned about this though, since it really isn't that painful.

## Testing

- Tests all pass!

---

## Showcase

Now instead of:

```rust
asset_server.load_acquire_with_settings_override("some_path", |settings: &mut GltfLoaderSettings| { ... }, my_lock_guard);
```

You can instead do:

```rust
asset_server.load_builder()
    .with_guard(my_lock_guard)
    .with_settings(|settings: &mut GltfLoaderSettings| { ... })
    .override_unapproved()
    .load("some_path");
```

We also now cover more variants! For example, you can now load an asset
untyped with a guard, or with override_unapproved, etc.

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-04-15 18:32:25 +00:00
ickshonpe f62d53dbca Bordered and padded content (#23510)
# Objective

Allow borders and padding on text and images.

Fixes #17300, #14498, #14789, #11557, #6879

## Solution

Remove filter for border values on content sized nodes.
Apply content offsets to content in rendering and picking.

## Testing

```
cargo run --example testbed_ui -- boxedcontent
```

```
cargo run --example image_node
```

```
cargo run --example editable_text
```

```
cargo run --example text_background_colors
```

## Showcase

<img width="1924" height="1127" alt="Screenshot 2026-03-25 113700"
src="https://github.com/user-attachments/assets/68be286b-ca0e-46c7-9295-973df77412e9"
/>

<img width="223" height="223" alt="birdd"
src="https://github.com/user-attachments/assets/e9f6e393-7ee9-498b-85d0-318abd702448"
/>
2026-03-25 17:13:34 +00:00
Tauan Binato e770373bd6 Fix image_node example's module-level doc comment (#23320)
# Objective

- Fixes #22651
- The `image_node` example has a mangled module-level doc comment:
`ImageNode is UI Node that render an Image.`

## Solution

- Rewrote the doc comment to be grammatically correct and use proper
intra-doc link syntax for `ImageNode`.

## Testing

- `cargo doc --workspace --no-deps` builds successfully.

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-03-14 05:30:21 +00:00
Trashtalk217 59e9ee3a1a Store Resources as components on singleton entities (#20934)
This is part of #19731.

# Resources as Components

## Motivation

More things should be entities. This simplifies the API, the lower-level
implementation and the tools we have for entities and components can be
used for other things in the engine. In particular, for resources, it is
really handy to have observers, which we currently don't have. See
#20821 under 1A, for a more specific use.

## Current Work

This removes the `resources` field from the world storage and instead
store the resources on singleton entities. For easy lookup, we add a
`HashMap<ComponentId, Entity>` to `World`, in order to quickly find the
singleton entity where the resource is stored.

Because we store resources on entities, we derive `Component` alongside
`Resource`, this means that

```rust
#[derive(Resource)]
struct Foo;
```
turns into
```rust
#[derive(Resource, Component)]
struct Foo;
```

This was also done for reflections, meaning that

```rust
#[derive(Resource, Reflect)]
#[refect(Resource)]
struct Bar;
```
becomes
```rust
#[derive(Resource, Component, Reflect)]
#[refect(Resource, Component)]
struct Bar;
```

In order to distinguish resource entities, they are tagged with the
`IsResource` component. Additionally, to ensure that they aren't queried
by accident, they are also tagged as being internal entities, which
means that they don't show up in queries by default.

## Drawbacks

- Currently you can't have a struct that is both a `Resource` and a
`Component`, because `Resource` expands to also implement `Component`,
this means that this throws a compiler error as it's implemented twice.
- Because every reflected Resource must also implement
`ReflectComponent` you need to import
`bevy_ecs::reflect::ReflectComponent` every time you use
`#[reflect(Resource)]`. This is kind of unintuitive.

## Future Work

- Simplify `Access` in the ECS, to only deal with components (and not
components *and* resources).
- Newtype `Res<Resource>` to `Single<Ref<Resource>>` (or something
similair).
- Eliminate `ReflectResource`.
- Take stabs at simplifying the public facing API.

---------

Co-authored-by: Carter Anderson <mcanders1@gmail.com>
Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: Dimitrios Loukadakis <dloukadakis@users.noreply.github.com>
2026-02-10 18:53:12 +00:00
WaterWhisperer d1dc09ae19 Use the shorthand functions to construct Vals and UiRects in examples (#22765)
# Objective

- Fixes #22753 

## Solution

- Replace `Val::Px` and `Val::Auto` with `px()` and `auto()` in examples

## Testing

- None
2026-02-02 23:27:19 +00:00
ickshonpe 6ca4769128 Minimal responsive FontSize support (#22614)
# Objective

Add responsive font sizes supporting rem and viewport units to
`bevy_text` with minimal changes to the APIs and systems.

## Solution

Introduce a new `FontSize` enum:

```rust
pub enum FontSize {
    /// Font Size in logical pixels.
    Px(f32),
    /// Font size as a percentage of the viewport width.
    Vw(f32),
    /// Font size as a percentage of the viewport height.
    Vh(f32),
    /// Font size as a percentage of the smaller of the viewport width and height.
    VMin(f32),
    /// Font size as a percentage of the larger of the viewport width and height.
    VMax(f32),
    /// Font Size relative to the value of the `RemSize` resource.
    Rem(f32),
}
```

This replaces the `f32` value of `TextFont`'s `font_size` field.

The viewport variants work the same way as their respective `Val`
counterparts.

`Rem` values are multiplied by the value of the `RemSize` resource
(which newtypes an `f32`).

`FontSize` provides an `eval` method that takes a logical viewport size
and rem base size and returns an `f32` logical font size. The resolved
logical font size is then written into the `Attributes` passed to Cosmic
Text by `TextPipeline::update_buffer`.

Any text implementation using `bevy_text` must now provide viewport and
rem base values when calling `TextPipeline::update_buffer` or
`create_measure`.

`Text2d` uses the size of the primary window to resolve viewport values
(or `Vec2::splat(1000)` if no primary window is found). This is a
deliberate compromise, a single `Text2d` can be rendered to multiple
viewports using `RenderLayers`, so it's difficult to find a rule for
which viewport size should be chosen.

### Change detection 

`ComputedTextBlock` has two new fields: `uses_viewport_sizes` and
`uses_rem_sizes`, which are set to true in `TextPipeline::update_buffer`
iff any text section in the block uses viewport or rem font sizes,
respectively.

The `ComputedTextBlock::needs_rerender` method has been modified to take
take two bool parameters:
```rust
    pub fn needs_rerender(
        &self,
        is_viewport_size_changed: bool,
        is_rem_size_changed: bool,
    ) -> bool {
        self.needs_rerender
            || (is_viewport_size_changed && self.uses_viewport_sizes)
            || (is_rem_size_changed && self.uses_rem_sizes)
    }
 ```
This ensures that text reupdates will also be scheduled if one of the text section's uses a viewport font size and the local viewport size changed, or if one of the text section's uses a rem font size and the rem size changed.

#### Limitations

There are some limitations because we don't have any sort of font style inheritance yet:

* "rem" units aren't proper rem units, and just based on the value of a resource. 
* "em" units are resolved based on inherited font size, so can't be implemented without inheritance support.

#### Notes

* This PR is quite small and not very technical. Reviewers don't need to be especially familiar with `bevy_text`. Most of the changes are to the examples.

* We could consider using `Val` instead of `FontSize`, then we could use `Val`'s constructor functions which would be much nicer, but some variants might not have sensible interpretations in both UI and Text2d contexts. Also we'd have to make `Val` accessible to `bevy_text`.

## Testing

The changes to the text systems are relatively trivial and easy to understand.  I already added a minor change to the `text` example to use `Vh` font size for the "hello bevy" text in the bottom right corner. If you change the size of the window, you should see the text change size in response. The text initially flickers before it updates because of some unrelated asset/image changes that mean that font textures aren't ready until the frame after the text update that changes the font size.

Most of the example migrations were automated using regular expressions, and there are bound to be mistakes in those changes. It's infeasible to check every single example thoroughly, but it's early enough in the release cycle that I don't think we should be too worried if a few bugs slip in.

---------

Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
2026-02-02 22:52:33 +00:00
WaterWhisperer 727a350fc6 Sort the UI examples into sub-dirs (#22727)
# Objective

- Fixes #22644

## Solution

- Create new subdirectories for categorization, and update the paths in
`Cargo.toml` and `README`.

## Testing

- `cargo check --example *`
2026-02-01 18:14:10 +00:00