Commit Graph

14 Commits

Author SHA1 Message Date
Carter Anderson 535cf401cc Reframe old "scene" terminology as "world serialization" (#23630)
Part 2 of #23619 

In **Bevy 0.19** we are landing a subset of Bevy's Next Generation Scene
system (often known as BSN), which now lives in the `bevy_scene` /
`bevy::scene` crate. However the old `bevy_scene` system still needs to
stick around for a bit longer, as it provides some features that Bevy's
Next Generation Scene system doesn't (yet!):

1. It is not _yet_ possible to write a World _to_ BSN, so the old system
is still necessary for "round trip World serialization".
2. The GLTF scene loader has not yet been ported to BSN, so the old
system is still necessary to spawn GLTF scenes in Bevy.

For this reason, we have renamed the old `bevy_scene` crate to
`bevy_world_serialization`. If you were referencing `bevy_scene::*` or
`bevy::scene::*` types, rename those paths to
`bevy_world_serialization::*` and `bevy::world_serialization::*`
respectively.

Additionally, to avoid confusion / conflicts with the new scene system,
all "scene" terminology / types have been reframed as "world
serialization":

- `Scene` -> `WorldAsset` (as this was always just a World wrapper)
- `SceneRoot` -> `WorldAssetRoot`
- `DynamicScene` -> `DynamicWorld`
    - `DynamicScene::from_scene` -> `DynamicWorld::from_world_asset`
- `DynamicSceneBuilder` -> `DynamicWorldBuilder`
- `DynamicSceneRoot` -> `DynamicWorldRoot`
- `SceneInstanceReady` -> `WorldInstanceReady`
- `SceneLoader` -> `WorldAssetLoader`
- `ScenePlugin` -> `WorldSerializationPlugin`
- `SceneRootTemplate` -> `WorldAssetRootTemplate`
- `SceneSpawner` -> `WorldInstanceSpawner`
- `SceneFilter` -> `WorldFilter`
- `SceneLoaderError` -> `WorldAssetLoaderError`
- `SceneSpawnError` -> `WorldInstanceSpawnError`

Note that I went with `bevy_world_serialization` over
`bevy_ecs_serialization`, as that is what all of the internal features
described themselves as. I think it is both more specific and does a
better job of making itself decoupled from `bevy_ecs` proper.
2026-04-04 00:31:47 +00:00
Chris Biscardi bce6592e77 Async handler hook mesh (#23376)
# Objective

the Gltf on_gltf_primitive hook is reasonably hard to use.

We don't have a "straight to gpu" `bevy_mesh::Mesh` format, which means
our glTF support is predicated on doing transformations like draco,
meshopt, etc on load. This makes Bevy's mesh interface, well,
`bevy_mesh::Mesh`.

Continuing that thread, extensions like [draco mesh
compression](https://github.com/KhronosGroup/glTF/blob/f966a3fbabeaed32f3f807750e35aaffc59bf4ca/extensions/2.0/Khronos/KHR_draco_mesh_compression/README.md)
are **fully responsible** for decompression in the loading process.
While this somewhat obviously includes vertex data, this includes *all
attributes* including position, normal, weights, joints, and custom
data.

This makes it the responsibility *of the draco decompression processing*
to turn the compressed data into a `Mesh`, and our APIs should reflect
that rather than providing gltf objects to users.

## Solution

To do this, we must allow the extension to create its own `Mesh`, as
well as pass any settings from the loader that are relevant, like
`load_meshes`, into the hook.

This means the responsibility for creating the `Mesh`, handling
decompression, calling the appropriate conversion functions, etc is more
directly placed on the extension processor.

## Testing

ran a bunch of the gltf examples, including animated mesh and extension
examples, and they run as usual. The "regular path" should be unchanged.
Only the path through the primitive hook should have any differences.

---

## Showcase

[this
codebase](https://github.com/ChristopherBiscardi/async-primitive-hook-gltf-extension-bevy/blob/d7f1622b170b4f6450ce5c3a51f8aa7f2780fc84/src/lib.rs)
is incredibly messy, but proves the point well. There is no mention of
gltf Documents in user code. By contrast, @jiangheng90 has wonderfully
provided an *actual* draco implementation
[here](https://github.com/jiangheng90-opensource/bevy_gltf_draco/blob/a8d19783e9cbc24acadda66db2a773d5fc447fd6/src/khr_draco_mesh_compression.rs)
which uses the current gltf-document-related apis.

By doing this we simplify handling for users, giving more control to
compression implementations, and reduce the "weird error cases" the
previous API had.

This image has a regular gltf on the left, and the draco compressed
version on the right.

<img width="1250" height="782" alt="screenshot-2026-03-15-at-20 36
39@2x"
src="https://github.com/user-attachments/assets/6c7cec6f-1f95-4126-8223-3a82aecac5ae"
/>

Builds on top of #23026 to make sure we keep the async support.

---------

Co-authored-by: jiangheng <jiangheng90@live.com>
2026-03-20 03:31:07 +00:00
Chris Biscardi 9762c65926 Enable modification of AnimationClips in glTF processing (#23305)
# Objective

Enable mutable access to `AnimationClip`s loaded in the glTF loader, so
that events can be added to them.

This is an alternative to https://github.com/bevyengine/bevy/pull/23199
that doesn't use handles to access `AnimationClip`s.

## Solution

Replace the old individual `on_animation` hook that passed a
`Handle<AnimationClip>` with a version that passes exclusive access to
the `AnimationClip`. This requires moving the hook in the loader code to
pass access through before the handles are created.

```rust
    /// Called when an individual animation is processed
    fn on_animation(
        &mut self,
        load_context: &mut LoadContext<'_>,
        gltf_animation: &gltf::Animation,
        animation_clip: &mut AnimationClip,
    ) {
    }
```

This has the drawback of needing to separate the adding of
`AnimationClip` events and the actual usage of the
`Handle<AnimationClip>` as they are not accessible at the same time.

## Testing

```
cargo run --example gltf_extension_animation_graph
```

## Showcase

Added the smoke particles from the non-gltf animation events example.




https://github.com/user-attachments/assets/1570fb4e-7fbd-4c8d-97bf-5fc21cc6592f
2026-03-16 19:55:18 +00:00
Chris Biscardi 380e894e82 rename gltf_render_enabled to gltf_enable_standard_materials (#22944)
# Objective

We currently describe the new `gltf_render_enabled` flag as "disabling
PBR rendering", which is much broader than what it does in practice. In
its current form it controls the construction and insertion of
`StandardMaterial`s on entities, but does not affect the PBR rendering
functionality of the application, or of glTF assets. (A user could still
create their own `StandardMaterial`s or `StandardMaterial` extensions
and insert them on the required meshes).

## Solution

Rename the flag to more accurately depict what it does in practice,
which is enable/disable the automatic construction and insertion of
`StandardMaterial`s when a glTF file is loading.

## Testing

There's only one example that turns this off, `gltf_extension_mesh_2d`,
which continues to run as expected.

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
2026-02-18 00:32:19 +00:00
Rostyslav Lesovyi 9fd2637846 Add tools to avoid unnecessary AssetEvent::Modified events that lead to rendering performance costs (#16751) (#22460)
# Objective

- Fixes #16751

## Solution

- `Assets::get_mut` now returns a wrapper `AssetMut` type instead of
`&mut impl Asset`.
- `AssetMut` implements `Deref` and `DerefMut`.
- `DerefMut` marks assets as changed.
- when dropped `AssetMut` will add `AssetEvent::Modified` event to a
queue only in case asset was marked as changed.

## Testing

- Did you test these changes? If so, how?
  - No unit tests were added, change is pretty straightforward.
  - Test project: https://github.com/MatrixDev/bevy-feature-16751-test.
    - With change: ~100 fps.
    - Without change: ~15 fps.
- Are there any parts that need more testing?
- I don't really see how this can break anything or add a measurable
overhead.
- `AssetEvent::Modified` will now be sent after the asset was modified
instead of before. It should not affect anything but still worth noting.
- How can other people (reviewers) test your changes? Is there anything
specific they need to know?
- Have a big amount of entities that constantly update their materials.
- Properties of those materials should be animated in a stepped maned
(like changing color every 0.1 seconds).
  - Update material only if value has actually changed:
```rust
if material.base_color != new_color {
    material.base_color = new_color;
}
```
- If relevant, what platforms did you test these changes on, and are
there any important ones you can't test?
  - tested on macos (Mackbook M1)
  - not a platform-specific issue

PS: This is my first PR, so please don’t judge.
2026-02-10 18:39:37 +00:00
Daniel Skates 0af11aa692 Invert bevy_gltf dependency with bevy_pbr (#22569)
# Objective

- `bevy_gltf` depends on `bevy_pbr` , with a tight coupling between the
scene definition and the rendering of the scene. This prevents artistic
rendering of GLTFs.

## Solution

- `bevy_gltf` loads as a `GltfMaterial` , and `PbrPlugin` inserts an
extension to translator to `StandardMaterial`
- Based on feedback from https://github.com/Zeophlite/bevy/pull/6 

## Testing

- `cargo run --example animated_mesh`

---------

Co-authored-by: atlv <email@atlasdostal.com>
2026-02-06 19:20:16 +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
Chris Biscardi 487d9729c8 re-enable gltf extension handler examples on wasm (#22591)
# Objective

Currently the `GltfExtensionHandler` examples are disabled on wasm due
to an issue with API availability on wasm

## Solution

Use the correct APIs in the examples, flagged by platform.

## Testing

```
bevy run --example gltf_extension_animation_graph web
bevy run --example gltf_extension_mesh_2d web
```

## Showcase

<img width="1920" height="1080" alt="screenshot-2026-01-18-at-16 04 48"
src="https://github.com/user-attachments/assets/d6a42c52-48da-4ad7-b4c2-ea512a06a5e5"
/>
<img width="1920" height="1080" alt="screenshot-2026-01-18-at-16 05 20"
src="https://github.com/user-attachments/assets/b2066d3a-e07e-43f6-9490-0ca0f77e5810"
/>
2026-01-19 07:49:45 +00:00
Aevyrie a88af65738 Contact Shadows (#22382)
# Objective

- Implement contact shadows to add fine shadow detail where shadow
cascades cannot.

## Solution

- Extend our existing pbr implementation using our existing raymarching
functions.

---

## Showcase

<img width="1824" height="1180" alt="image"
src="https://github.com/user-attachments/assets/e93b79c5-c596-4a9e-b94d-20bdde1d863b"
/>

<img width="1824" height="1180" alt="image"
src="https://github.com/user-attachments/assets/0fd7dffa-60b8-4b92-8fad-7f993d4d89dd"
/>


https://github.com/user-attachments/assets/e74b190d-9ae3-4aaf-97f0-b520930a0667


https://github.com/user-attachments/assets/e80ccb26-bbaa-4d25-a823-8ea12354c5b9


https://github.com/user-attachments/assets/b04f4b00-92bd-4a2f-b7dd-5157d8fbe0ab

<img width="1073" height="685" alt="image"
src="https://github.com/user-attachments/assets/b7629908-dd32-48db-8ee7-a4d2dd8f66c2"
/>

<img width="1073" height="685" alt="image"
src="https://github.com/user-attachments/assets/3de0258e-9191-4180-ac57-41b32e1205bd"
/>

<img width="1073" height="685" alt="image"
src="https://github.com/user-attachments/assets/951477f9-e9a9-426f-ae8d-18ae50cc7b85"
/>

<img width="1073" height="685" alt="image"
src="https://github.com/user-attachments/assets/2291453c-da57-4fcc-a6b0-f60f6eac6cbb"
/>

<img width="1073" height="685" alt="image"
src="https://github.com/user-attachments/assets/5820cdff-ea54-4294-b520-2a8d8dc24996"
/>

<img width="1073" height="685" alt="image"
src="https://github.com/user-attachments/assets/3ea16481-7689-4e99-87e2-1589f1532e4c"
/>

---------

Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>
Co-authored-by: charlotte 🌸 <charlotte.c.mcelwain@gmail.com>
2026-01-13 21:51:39 +00:00
Chris Biscardi 86224b5cb2 Refactor GltfExtensionHandler Hooks (#22114)
As it turns out, many glTF extensions require accessing the data from
other extensions.

Trying to isolate and scope access is much less helpful than exposing
the glTF objects for consumers to take what they want.

This includes

- extension data in the "others" category (anything the gltf crate
doesn't support explicitly)
- the functions that return the extension data the gltf crate *does*
have hardcoded support for
- names and any other available data

---

The diff for users is that they

- no longer have to worry about defining extension ids to process
- no longer have to worry about multiple calls due to those ids
- now have to use `.extension_value()`, `.name()`, or similar to get
relevant data
- Can now access `.light()` or any other data built-in to the gltf
crate, such as
[`.variants`](https://docs.rs/gltf/1.4.1/gltf/struct.Document.html#method.variants)
for `KHR_materials_variants`.

An example diff on the user side can be viewed in the update commit for
the Skein PR:
https://github.com/rust-adventure/skein/pull/89/changes/ac1e510c9d136d60c23decd68b10f35f6e24f76b
2025-12-15 02:18:20 +00:00
Chris Biscardi e7b64b6b04 Add support for arbitrary/third party glTF Extension processing via GltfExtensionHandler (#22106)
# Objective

Currently Bevy doesn't support arbitrary glTF extensions. The ones it
does support are hardcoded.

We should support glTF extensions, as this is a primary mechanism for
sharing behavior via data exported from applications like Blender.

I personally have found usecases in exporting component data, lightmap
textures/information, and processing other kinds of data
(AnimationGraph, 3d meshes into 2d, etc).

## Solution

This PR introduces a new `GltfExtensionHandler` trait that users can
implement and add to the glTF loader processing via inserting into a
Resource.

There are two example processors currently added, with a third that I'd
like to add after this PR.

- `examples/gltf/gltf_extension_animation_graph.rs` duplicates the
functionality of `animation_mesh`, constructing AnimationGraphs via
extension processing and applying them to be played on the relevant
nodes.
- `examples/gltf/gltf_extension_mesh_2d.rs` duplicates the functionality
of the `custom_gltf_vertex_attribute` example, showing how the extension
processing could be used to convert 3d meshes to 2d meshes alongside
custom materials.

Both of these examples re-use existing assets and thus don't *actually
use* extension data, but show how one could access the relevant data to
say, only convert specifically labelled Mesh3ds to 2d, or process many
animations into multiple graphs based on extension-data based labelling
introduced in Blender.

A third example I want to introduce after this PR is the same core
functionality Skein requires: an example that uses reflected component
data stored in glTF extensions and inserts that data onto the relevant
entities, resulting in scenes that are "ready to go".

## Comparison to Extras

In comparison to extensions: data placed in glTF extras is well
supported through the `GltfExtras` category of components.

Extras only support adding an additional `extras` field to any object.

Data stored in extras is application-specific. It should be usable by
Bevy developers to implement their own, application-specific, data
transfer. This is supported by applications like Blender through the
application of Custom Properties.

Once data is used by more than one application, it belongs in a glTF
extension.

## What is a glTF Extension?

Extensions are named with a prefix like `KHR` or `EXT`. Bevy has already
reserved the `BEVY` namespace for this, which is listed in the official
[prefix
list](https://github.com/KhronosGroup/glTF/blob/7bbd90978cad06389eee3a36882c5ef2f2039faf/extensions/Prefixes.md).

For a glTF file, an extension must be listed in `extensionsUsed` and
optionally `extensionsRequired`.

```
{
    "extensionsRequired": [
        "KHR_texture_transform"
    ],
    "extensionsUsed": [
        "KHR_texture_transform"
    ]
}
```

Extension data is allowed in any place extras are also allowed, but also
allow much more flexibility.

Extensions are also allowed to define global data, add additional binary
chunks, and more.

For meshes, extensions can add additional attribute names, accessor
types, and/or component types

`KHR_lights_punctual` is a contained and understandable example of an
extension:
https://github.com/KhronosGroup/glTF/blob/7bbd90978cad06389eee3a36882c5ef2f2039faf/extensions/2.0/Khronos/KHR_lights_punctual/README.md
. This one happens to be already hardcoded into Bevy's handling, so it
doesn't benefit from arbitrary extension processing, but there are
additional
[ratified](https://github.com/KhronosGroup/glTF/tree/7bbd90978cad06389eee3a36882c5ef2f2039faf/extensions#ratified-khronos-extensions)
and
[in-progress](https://github.com/KhronosGroup/glTF/tree/7bbd90978cad06389eee3a36882c5ef2f2039faf/extensions#in-progress-khronos-and-multi-vendor-extensions-and-projects)
extensions, as well as
[vendor](https://github.com/KhronosGroup/glTF/tree/7bbd90978cad06389eee3a36882c5ef2f2039faf/extensions#vendor-extensions)
and other arbitrary extensions that would benefit from userland support.

## Implementation

This initial implementation is reasonably minimal: enabling extension
processing for objects/etc as they're loaded which may also define
extension data, including the scene world. This may leave out useful
functionality; as detailed in the next section: "What's not
implemented".

Extension handlers are defined by implementing a trait which can
optionally define hooks and data.
Extension handler data is cloned to start with a fresh slate for each
glTF load, which limits scope to "one glTF load".
So while state can be maintained across hooks during a single load,
users who want to combine or handle multiple glTF assets should do so in
the main app, not in an extension handler.
Following this, because the extensions are stored as `dyn GltfExtension`
*and* we want to clone them to isolate state to a single load,
`dyn_clone` must be included as a workaround to enable this cloning.

An extension handler has to be added to the list of handler by accessing
a `Resource` and pushing an instantiated handler into it.
This Resource keeps the list of extension handlers so that a new glTF
loader can bootstrap them.

The design of the hooks is such that:

- If no extensions handlers are registered, none are called for
processing
- If an extension handler is defined, it receives all "events"
- handlers are defined by a trait, and default implementations are
called if an override is not specified.
    - default implementations are no-ops

It is important that extensions receive all events because certain
information is not embedded in extension data.
For example, processing animation data into an animation graph could
require both processing animations with extension data, tracking the
animation roots through hooks like `on_node`, *and* applying those
graphs in the `on_scene_completed` hook.

- Extension data is passed to hooks as `Option<&serde_json::Value>`
which is only passing references around as the data has already been
converted to `Value` by the `gltf` crate.
- `LoadContext` is required for creating any new additional assets, like
`AnimationGraph`s.
- *scene* World access is provided in hooks like `on_scene_completed`,
which allows calculating data over the course of a glTF load and
applying it to a Scene.

### What's not implemented

This PR chooses to *not* implement some features that it could. Instead
the approach in this PR is to offer up the data that Bevy has already
processed to extensions to do more with that data.

- Overriding `load_image`/`process_loaded_texture`
- This could allow projects like bevy_web_codecs, [which currently forks
the entire gltf
loader](https://github.com/jf908/bevy_web_codecs/tree/373bbf29be6555c7603fd6867a01159ab0f20fed/bevy_web_codecs_gltf).
Associated [issue](https://github.com/bevyengine/bevy/issues/21185).
However I believe this needs some design work dedicated to what exactly
happens here to support that use case.
- This PR doesn't include any refactoring of the glTF loader, which I
feel is important for a first merge.
- ~~There is some benefit to passing in the relevant `gltf::*` object to
every hook. For example, I believe this is the only way to access
extension data for `KHR_lights_punctual`, and
[`KHR_materials_variants`](https://docs.rs/gltf/1.4.1/gltf/struct.Document.html#method.variants)
or other extensions with "built-in" support. I haven't done this in all
places.~~ (edit: after external implementation I decided this was a good
idea and added it to more places)

## Testing

```
cargo run --example gltf_extension_animation_graph
cargo run --example gltf_extension_mesh_2d
```

---

## Showcase

Both examples running:


https://github.com/user-attachments/assets/f9e7c3c9-cdad-4d33-ace7-7c2ca5469d5e



https://github.com/user-attachments/assets/baa9bc92-ca3b-46ad-a3f0-2f74bbc29b68


<details>
<summary>An example that showcases converting Mesh3d to Mesh2d</summary>

```rust
#[derive(Default, Clone)]
struct GltfExtensionProcessorToMesh2d;

impl GltfExtensionProcessor for GltfExtensionProcessorToMesh2d {
    fn extension_ids(&self) -> &'static [&'static str] {
        &[""]
    }

    fn dyn_clone(&self) -> Box<dyn GltfExtensionHandler> {
        Box::new((*self).clone())
    }

    fn on_spawn_mesh_and_material(
        &mut self,
        load_context: &mut LoadContext<'_>,
        _gltf_node: &gltf::Node,
        entity: &mut EntityWorldMut,
    ) {
        if let Some(mesh3d) = entity.get::<Mesh3d>()
            && let Some(_) = entity.get::<MeshMaterial3d<StandardMaterial>>()
        {
            let material_handle =
                load_context.add_loaded_labeled_asset("AColorMaterial", (CustomMaterial {}).into());
            let mesh_handle = mesh3d.0.clone();
            entity
                .remove::<(Mesh3d, MeshMaterial3d<StandardMaterial>)>()
                .insert((Mesh2d(mesh_handle), MeshMaterial2d(material_handle.clone())));
        }
    }
}
```

</details>

---------

Co-authored-by: Kristoffer Søholm <k.soeholm@gmail.com>
2025-12-14 21:25:07 +00:00
Lucas Franca 18a7c3092e Shortcircuit SceneInstanceReady on models that do not have ColorOverride (#21751)
# Objective

The `edit_material_on_gltf` example was iterating over all materials of
a Gltf even when it did not have `ColorOverride`.

## Solution

Shortcircuit observer if scene does not have `ColorOverride`

## Testing

Ran the example
2025-11-06 18:22:10 +00:00
Trashtalk217 d431f7e139 Split AmbientLight into two (#21595)
# Objective

For resources-as-components (#19731), structs mustn't doubly derive both
`Component` and `Resource`.

## Solution

Split `AmbientLight` in two: `AmbientLight` (the resource) and
`AmbientLightOverride` (the component).

## Testing

I initially made two structs `AmbientLightComponent` and
`AmbientLightResource`, and replaced every mention with the relevant one
to ensure that I didn't confuse the two.

## Notes

- I don't know if the names are correct. I kept the easiest name for the
resource, as that's the one most often used.
- I haven't provided any conversion methods as there are already plans
to replace the component variant with something else.

---------

Co-authored-by: atlv <email@atlasdostal.com>
2025-10-21 23:04:39 +00:00
Chris Biscardi 6da51ef236 move gltf examples to gltf category (#21141)
# Objective

In the context of this PR, there are two access patterns users have when
reaching for examples:

- "I have a glTF file and I need to figure out what to do with it"
- "I want to learn about Bevy feature X"

Users wanting to learn about Bevy features can go to any appropriately
named examples directory to learn more about that feature.
Users who have a glTF file currently have to scan different directories
to find glTF related functionality.
For example: looking in the 2d directory for custom vertex attribute
examples.

## Solution

Create a glTF category and move applicable examples there.

It is notable that a "gltf" directory *could* accept any example that
uses a glTF file, but this should not be the case.
The examples in this directory should be focused on the "I have a glTF
file and I'm trying to figure out how to work with it" access pattern.

If a glTF file is used "as data" to support a feature showcase, then it
is not "a gltf example". For example: spawning a Scene from a glTF file
is not enough to qualify an example for this directory.

I chose to call this directory "gltf" instead of using the "scene"
directory so as to leave "scene" for bsn examples in the future.

## Testing

```
cargo run --example custom_gltf_vertex_attribute
cargo run --example load_gltf
cargo run --example load_gltf_extras
cargo run --example query_gltf_primitives
cargo run --example update_gltf_scene
cargo run --example edit_material_on_gltf
cargo run --example gltf_skinned_mesh
```
2025-09-21 16:43:18 +00:00