Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Excessive logging from new mesh_picking backend #16065

Closed
rs017991 opened this issue Oct 23, 2024 · 14 comments · Fixed by #16110
Closed

Excessive logging from new mesh_picking backend #16065

rs017991 opened this issue Oct 23, 2024 · 14 comments · Fixed by #16110
Labels
A-Picking Pointing at and selecting objects of all sorts C-Bug An unexpected or incorrect behavior
Milestone

Comments

@rs017991
Copy link

Note: This is in regard to the new 0.15.0-rc.1 release candidate.
I understand that this is a pre-release, and considered waiting to see if the official release notes might shed light on this behaviour,
but thought you might want to know about the rough edges sooner than that.

The Issue

After updating to 0.15.0-rc.1, I get about a thousand of these every second:

ERROR bevy_picking::mesh_picking::ray_cast::intersections: Invalid intersection check: `TriangleList` is the only supported `PrimitiveTopology`

I am indeed using an alternate PrimitiveTopology, though I am not yet utilising any picking features within my code.

Each of the following is unclear to me:

  1. Why it needs to be logging this for every function call (or even every frame), vs using error_once!
  2. Why it is considered an error and not a warning (given that it is an optional feature)
  3. Why it is attempting to compute so many intersections (given that I'm not requesting such information in my systems)
  4. Why it even matters which PrimitiveTopology is used (the other variants work just fine elsewhere in Bevy)

Reproduction

You can reproduce this behaviour with the regular 3d/lines example, with one tweak:

  1. Change one or both usages of RenderAssetUsages::RENDER_WORLD to RenderAssetUsages::default()
  2. Run the example and move your mouse near the lines
@JMS55 JMS55 added this to the 0.15 milestone Oct 23, 2024
@JMS55 JMS55 added C-Bug An unexpected or incorrect behavior A-Picking Pointing at and selecting objects of all sorts labels Oct 23, 2024
@cart
Copy link
Member

cart commented Oct 25, 2024

Looking into this now

@cart
Copy link
Member

cart commented Oct 25, 2024

I think a core issue here is that we're computing mesh intersections across all spawned meshes by default. The performance tradeoff there is not what most people will want in actual games. Ex: when spawning a complex GLTF scene, pretty much nobody wants raw-mesh intersections.

The "pick any mesh by default" behavior really only makes sense in editor scenarios, which is not what our defaults should be optimizing for.

Physics collision shapes are generally used for in-game picking (similar in concept to SimplifiedMesh in our picking impl). That is already one form of opting in. But when a game developer is building a "click on something" feature, they will define a specific layer / mask to narrow the considered colliders down (prior to the computation of the intersections). This is another layer of opt-in explicitness.

At a bare minimum, we should disable the current mesh picking behavior by default. But I'll assert that the current picking behavior (a global PointerHits event queue) has very limited practical applications. What Bevy app developers will want in general for 3D use cases (and what we should push them toward) is a way to explicitly add collider types to their entities (generally simple / easy to compute shapes like AABBs, spheres, capsules, etc with actual meshes being special exceptions), define the layer those types live on, on-demand request a raycast, and then receive the set of matching items in their own collection. Some use cases might benefit from a global "what did I just click across all mesh types" feed, but I suspect, given the diversity of what might be rendered to the screen (and how selection demands will change based on game context), I'm not sure if its even a path we should be pushing people toward.

A generic PointerHits (or picking interaction) event across all types isn't going to cut it for most applications, both in 2d and 3d. I think its most practical application is debugging and editor scenarios. And even in those cases, I think finer and more intentional granularity would be good. It seems valuable to provide a way to "picking style" trigger observers for click and hover events (ex scenarios like "I want to write an observer for click/hover events when a 3d player collider is hovered"), but I think we need "scoping" to be an integral part of the system.

@cart
Copy link
Member

cart commented Oct 25, 2024

A generic PointerHits (or picking interaction) event across all types isn't going to cut it for most applications, both in 2d and 3d

I'll clarify that it is much more likely to be useful in 2D, and that the cost of enabling it by default would be low enough to be worth considering / people will even expect this to be available by default.

@NthTensor
Copy link
Contributor

NthTensor commented Oct 25, 2024

In terms of "pick any mesh by default behavior" I'm fine to have that off by default for 3D. The functionality is there if they want it, and should be easy enough to find an enable.

What Bevy app developers will want in general for 3D use cases (and what we should push them toward) is a way to explicitly add collider types to their entities (generally simple / easy to compute shapes like AABBs, spheres, capsules, etc with actual meshes being special exceptions), define the layer those types live on, on-demand request a raycast, and then receive the set of matching items in their own collection.

I agree, I do think this is probably going to be important. We could do a lot more to support this, and I know @Jondolf wants to. But I'm not sure I would use picking for that, that's just raycasting. The mesh-picking backend is intentionally very cut down and narrowly scoped, it's basically just intended for use in the examples (where it's very handy) and the editor prototypes (where it's basically required for a bunch of core interactions).

Just so we're all on the same page, PointerHits aren't really something users are supposed to consume. These events feed the HoverMap which tracks pointer hover state, and then this drives the Pointer<E> events (see the pointer_events system for more information).

So when you say

Some use cases might benefit from a global "what did I just click across all mesh types" feed, but I suspect, given the diversity of what might be rendered to the screen (and how selection demands will change based on game context), I'm not sure if its even a path we should be pushing people toward.

and

I think finer and more intentional granularity would be good. It seems valuable to provide a way to "picking style" trigger observers for click and hover events (ex scenarios like "I want to write an observer for click/hover events when a 3d player collider is hovered"), but I think we need "scoping" to be an integral part of the system.

I'm a little confused, because bevy_picking to me seems much closer to the latter than the former, and the mesh-picking back-end is a core part of making that higher level api run. Following your example, if you want to attach some on-click functionality to all player colliders, you can do something like the following.

world.observe(|trigger: Trigger<Pointer<Click>>, player_coliders: Query<&PlayerColider>| {
    if let Some(colider) = player_coliders.get(trigger.target()) {
        // add my logic to coliders here
    }
});

Please let me know if I'm misunderstanding your point.

@NthTensor
Copy link
Contributor

NthTensor commented Oct 25, 2024

Thinking about it, I'd be theoretically OK having basically all bevy_picking back-ends off by default. Maybe not UI.

@aevyrie
Copy link
Member

aevyrie commented Oct 25, 2024

@cart I think you might be fundamentally misunderstanding how this works. All of what you are saying is supported by composing backends. Backends ultimately decide the performance cost, not the picking plugin. PointerHits need to be a unified stream - that is what drives pointer events for any entity, it has nothing to do with the performance cost of raycasting. In normal use, you will usually see 0-1 of these events per frame per pointer.

I think a core issue here is that we're computing mesh intersections across all spawned meshes by default.

This is a function of the mesh picking backend settings. Downstream, bevy_mod_picking provides this type of backend for debug purposes, but you can also use components to instead opt-in to picking where you need it. Again, this raycasting backend is essentially for debugging. It's fast enough that it's fine for most scenes, but, as I've said before, bevy's default should probably be a physics or shader based backend. We aren't there yet though, and this provides a way to get things working for 3d cases right now. The point of this architecture is that it is completely modular, and users can choose whatever picking backends make sense for their use case. Users are free to disable this backend, and drop in one of the existing 3rd party avian or rapier backends.

The "pick any mesh by default" behavior really only makes sense in editor scenarios, which is not what our defaults should be optimizing for.

Agreed.

Physics collision shapes are generally used [..]

These implementation details can exist in the backends, specific to their implementation. For example, the various physics engine backends that mod_picking provides out of the box do use collision shapes like this, but it is specific to each integration, and what they support (e.g. raycast early exit and component filtering).

(a global PointerHits event queue) has very limited practical applications.

A generic PointerHits (or picking interaction) event across all types isn't going to cut it for most applications, both in 2d and 3d.

I completely disagree. This is what allows us to support rich picking events for any entity and across picking backends without prescribing how the hit tests are run. There is no cost to this - the raycasting backend behavior has nothing to do with the unified pointer hit stream.

@aevyrie
Copy link
Member

aevyrie commented Oct 25, 2024

To respond to the issue at hand:

  1. This is a bug in the mesh picking backend, we shouldn't be emitting errors, but we can document what kinds of meshes the backend supports. I don't see any reason why we couldn't support other topologies.
  2. The mesh picking backend should be off by default. Adding it when you need it should be a one liner add_plugin(). Keeping the rest of the picking plugins active has negligible performance cost - if there are no hit events to consume, there is no work to do.

@cart
Copy link
Member

cart commented Oct 26, 2024

@NthTensor

it's basically just intended for use in the examples (where it's very handy) and the editor prototypes (where it's basically required for a bunch of core interactions).

Yeah this is the space I think the current mesh backend is right for. Glad it seems we're all in agreement on this.

Just so we're all on the same page, PointerHits aren't really something users are supposed to consume. These events feed the HoverMap which tracks pointer hover state, and then this drives the Pointer events (see the pointer_events system for more information).

Fundamentally this is all still the same "feed" though in terms of signals being sent out.

Following your example, if you want to attach some on-click functionality to all player colliders, you can do something like the following.

This has a number of downsides. In the current impl, it implies that we're computing all intersections for all meshes ahead of time, computing a single global click result, and then filtering down to PlayerCollider.

@aevyrie

I think you might be fundamentally misunderstanding how this works

Pretty sure I'm not, but I'll keep an open mind. If after reading this message you still think I'm missing something, please let me know.

Backends ultimately decide the performance cost, not the picking plugin

I understood this much.

PointerHits need to be a unified stream - that is what drives pointer events for any entity

This is (one of) my fundamental sticking points (the other being the much more pressing concern of the current mesh picking backend not being a suitable default, which it sounds like we all agree on). I'm asserting that a single unified "pointer event" (and how these relate to each other, such as blocking hover events across entities and types of entities) isn't fine enough granularity for many use cases, especially in 3D. It makes presumptions:

Hover (Over / Out) requirements are tied to click (Down or Up) requirements when it comes to "blocking". This makes sense in UI and editor scenarios, where generally the only question you need to answer is "is this interactable" (if yes, enable is_hoverable) and "does it block when determining other hovers or clicks" (if yes, enable should_block_lower). In game scenarios, this is much more fluid. You could easily want to have hover information for something your mouse is over, that is not "clickable" where the hover observer triggers when it is behind something that is clickable (and blocks other clickables).

The system also assumes that the "click stop" information is fixed. Real world apps will have more complicated use cases that fall outside the "ui pointer model". Ex: "click the item under my mouse with the highest rarity". Or based on the state computed this frame, the player might be in "item selection mode", "enemy selection mode", or some combination of the two. This context could be determined based on what is under the mouse currently.

A very solid chunk of picking scenarios are best expressed as "describe what intersections you want to check", "retrieve the list of matches", and "from that list select zero or more entities".

I'm definitely not saying that the picking system as implemented today is not useful or that it needs to fundamentally change. bevy_picking solves very real problems and I love that it is pluggable. I'm just saying it isn't a complete answer, and that a huge chunk of the "mesh picking" scenarios in 3D (but also sprite picking in 2D) will not be covered by a global "2d-ui-style" hover/click system (at least in its current form).

My one primary goal for this discussion was to convince people that the current mesh picking backend should not be enabled by default (which seems to have been successful). My secondary goals are to (a) convince people that bevy_picking in its current form is not a one-size-fits-all solution for picking (I suspect this won't be hard or contentious), and (b) get people thinking about ways to provide some of the UX benefits of bevy_picking (observers, hover event, etc) in the context of more diverse pointer-picking and raycast operations. I suspect that there is potential for unification or capability-sharing between bevy_picking and the more diverse app-logic-driven raycasting/picking scenarios. But maybe its best to treat them as fully separate implementations!

I apologize for my phrasing in these cases: "A generic PointerHits (or picking interaction) event across all types isn't going to cut it for most applications" and "I'll assert that the current picking behavior (a global PointerHits event queue) has very limited practical applications". I could have phrased this (more accurately) in a way that didn't minimize the very real / common / valuable scenarios covered by bevy_picking.

I also think that a bevy_picking backend fed by user-provided colliders is practical, within the current bevy_picking paradigm. But again, it doesn't feel like it even closely resembles a complete solve to the picking problem. It will work for simple things (which is a large set of things!), and then when the user's / app's needs expand, they'll need to move to a different system.

This is a bug in the mesh picking backend, we shouldn't be emitting errors, but we can document what kinds of meshes the backend supports. I don't see any reason why we couldn't support other topologies.

Agreed. Not being able to pick something doesn't feel like an error to me, unless the developer has explicitly asked for it to be pickable.

The mesh picking backend should be off by default. Adding it when you need it should be a one liner add_plugin(). Keeping the rest of the picking plugins active has negligible performance cost - if there are no hit events to consume, there is no work to do.

Agreed. UI picking makes perfect sense / should of course be enabled by default. Sprite picking falls into a similar category, although 2D games are where I think we start to see the limits of the current unified picking system.

@Zennii
Copy link

Zennii commented Oct 26, 2024

I'd like to throw my own experience with it in as well, as I hit something similar the other day when updating. I'm using custom attributes with my meshes, so for example I'm packing vertex positions into a u32. This lead to massive spam of Mesh does not contain vertex positions, because the picking system looks for the common way to store vertex positions. I don't really have a problem with that, but I was surprised that it was not so easy to disable bevy_picking. Here's the order I considered my options. My initial instinct was that I could change necessary settings through .set(PickingPlugin { ... }) on DefaultPlugins similar to how the WindowPlugin and some others work, but that didn't seem to be the case. I didn't want to manually insert all the default plugins except the PickingPlugin so I skipped that idea. So I tried to just disable the feature flag, but I realized it's tied to the UI too and I probably want that, so that wasn't an option. The only way I found to solve the problem was to have a Startup that modified the MeshPickingBackendSettings to set require_markers to true (IMO true as default kind of makes more sense), and that's what I went with, but it doesn't seem like it should be necessary to need a Startup tied into this process

@aevyrie
Copy link
Member

aevyrie commented Oct 26, 2024

@cart

A very solid chunk of picking scenarios are best expressed as "describe what intersections you want to check", "retrieve the list of matches", and "from that list select zero or more entities".

You are describing the existing raycasting API (and those of rapier/avian) verbatim. My point is that this has nothing to do with picking. Please bear with me.

You can invent endlessly complex hypothetical scenarios, but you always have the option of writing a backend that has the performance and layer traversal characteristics you want for your game. If your use case truly does not fit into the paradigm of UI pointer interactions (which seems incredibly unlikely to me), then... don't use the UI pointer interactions. You still have the full ECS toolkit at your disposal.

Finding out which thing is directly under the pointer is not as trivial as raycasting into the scene. You can have multiple cameras being layered with UI and each other. The entities on screen are often rendered in completely different ways: UI, 3d meshes, 2d meshes, gizmos, custom renderers. You need to be able to have multiple sources of hit tests that can interleave properly to match the order of what is on screen. That is the hard problem that "picking" solves.

You could easily want to have hover information for something your mouse is over, that is not "clickable" where the hover observer triggers when it is behind something that is clickable (and blocks other clickables).

This is what backends are intended for! Just because the picking spec says you should report the top hit(s) and send event(s), that doesn't preclude you from bolting on your own custom logic for entities behind the hoverable ones. You can trigger those hover handlers manually, skipping the built-in focus logic entirely. The focus system is just one way to trigger the pointer events, it (shouldn't) own them.

The system also assumes that the "click stop" information is fixed. Real world apps will have more complicated use cases that fall outside the "ui pointer model". Ex: "click the item under my mouse with the highest rarity". Or based on the state computed this frame, the player might be in "item selection mode", "enemy selection mode", or some combination of the two. This context could be determined based on what is under the mouse currently.

I just don't see what this has to do with picking. If what you are doing falls outside of the UI pointer model, and all you want to do is hit tests, then do hit tests however you want! I don't see why you can't run arbitrary hit tests and trigger click handlers yourself.

The focus system is the entire point of entities participating in the combined stream of hits (i.e. "picking"). If you don't want the focus system, you can still use picking functionality that lives above (pointer events) and below (pointer locations, hit tests) the focus system. This combined focus system is something that I really don't want to lose.

I do want to add that I've been repeatedly encouraging others to make a better frontend (pointer events). @NthTensor has done a great job porting the mod_picking version of pointer events to observers, but I'm not particularly attached to it. The frontend was an early attempt at ECS callbacks that predates bevy's observers by more than a year, iirc.

I'd also support improvements to the focus system, but I want to be sure we don't end up losing what is, I think, the most valuable part of the picking plugin's current design.

@NthTensor
Copy link
Contributor

NthTensor commented Oct 26, 2024

I think I understand now: My sense is that we are still talking past each-other a little bit. You are coming at this from a much more user-focused prospective than we are (which is good imo) but it also seems like maybe you have not actually tried building the abstractions you are talking about using the new system. I say this, because I think the new system is pretty great for what you are talking about, even if it's only one of the necessary building blocks.

This has a number of downsides. In the current impl, it implies that we're computing all intersections for all meshes ahead of time, computing a single global click result, and then filtering down to PlayerCollider.

It's probably worth noting that we are not computing a global result, as I think you are aware. A pointer can end up hovering multiple entities, and PickingBehavior allows you to configure if a certain entity "blocks" lower hits or not, and you can also opt-in or opt-out of hovering.

Hover (Over / Out) requirements are tied to click (Down or Up) requirements when it comes to "blocking". This makes sense in UI and editor scenarios, where generally the only question you need to answer is "is this interactable" (if yes, enable is_hoverable) and "does it block when determining other hovers or clicks" (if yes, enable should_block_lower). In game scenarios, this is much more fluid. You could easily want to have hover information for something your mouse is over, that is not "clickable" where the hover observer triggers when it is behind something that is clickable (and blocks other clickables).

This is true within the picking system but you can also just turn off blocking entirely and figure out what interrupts what in user code. It's just an optimization for when these are tied, which is often.

The system also assumes that the "click stop" information is fixed. Real world apps will have more complicated use cases that fall outside the "ui pointer model". Ex: "click the item under my mouse with the highest rarity". Or based on the state computed this frame, the player might be in "item selection mode", "enemy selection mode", or some combination of the two. This context could be determined based on what is under the mouse currently.

I see, and I don't disagree. But the feedback I've gotten from the few early adopters is that they are pretty painlessly building their own custom "selectors" on top of the bevy picking observer events. Architect of ruin has implemented a heuristics based selection system using it, by combining observers and some additional event streams.

You seem to be saying that this functionality should be easier to build, or provided in the engine core. That makes sense, and I think the existing picking HoverMap is probably still, on the lowest level, the right tool for the job. Are we talking about making the picking front-end smarter and more modular? I think that would be great.

I'm just saying it isn't a complete answer, and that a huge chunk of the "mesh picking" scenarios in 3D (but also sprite picking in 2D) will not be covered by a global "2d-ui-style" hover/click system (at least in its current form).

I'm tentatively with you. I think picking is quite flexible, and the feedback i've gotten from users so far is that they are building more complex interactions on top of picking rather than along side it.

My one primary goal for this discussion was to convince people that the current mesh picking backend should not be enabled by default (which seems to have been successful). My secondary goals are to (a) convince people that bevy_picking in its current form is not a one-size-fits-all solution for picking (I suspect this won't be hard or contentious), and (b) get people thinking about ways to provide some of the UX benefits of bevy_picking (observers, hover event, etc) in the context of more diverse pointer-picking and raycast operations.

Yep. I'm with you for both of these, I think. But @aevyrie and I are asking about scope and relevancy: how much of this is really "picking" and how much is a more general question about bevy's preferred approach to user interaction behavior?


I really want to make sure we're on the same page here, so here's a little description of what bevy_picking actually is for. Sorry if this is repeating information you already know.

The fundamental task of bevy_picking is to take points on windows, images, and textures and relate those positions to the entities "visually beneath" those points. This is very simple: back-ends turn PointerLocations into PointerHits events for every entity they hit.

The second tasks of bevy_picking is to drive the positions of those points by mouse/touch-pointer/stylus input events, and expose the input interactions to the entities beneath those pointers via dispatching Pointer<E> triggers.

Connecting these two modules together is the HoverMap, which tracks which pointer is "hovering" which entities, and which can be used to build more complex interactions that are still driven by raw pointer input.

It seems to me that you are suggesting a third task, and it's still not entirely clear to me what it is.

@cart
Copy link
Member

cart commented Oct 26, 2024

@aevyrie

You are describing the existing raycasting API
Finding out which thing is directly under the pointer is not as trivial as raycasting into the scene. That is the hard problem that "picking" solves.
The focus system is the entire point of entities participating in the combined stream of hits

I know. Please give me the benefit of the doubt here. I've used raycasting APIs extensively, both in the context of Bevy and elsewhere. I also know what picking is, as you have defined it (which is aligned with how pretty much everyone defines it). I know why bevy_picking exists, and I think its existence is well motivated and justified. I like the current implementation (which I have reviewed extensively). We don't need to argue about this, as there is nothing to argue about.

One potential hangup here seems to be whether we regard "picking" as "asking questions about what is under my mouse and returning those results" or "finding what is directly under the pointer, solving the specific 'exposing hits across sources, sorting them, and picking the closest' problem". I'm happy to accept that definition and call the scenarios I've described something else. I believe they exist somewhere on the spectrum between "arbitrary raycast scenarios" and "picking a depth sorted result under my mouse, taking blocking into account", in such a way that we might be able to share infrastructure in places (ex: over/out hover tracking, events, etc). But for clarity and to avoid further controversy, I will no longer refer to the more general scenarios as "picking".

You can trigger those hover handlers manually, skipping the built-in focus logic entirely. The focus system is just one way to trigger the pointer events, it (shouldn't) own them.

This is the category of thing I was trying to touch on (sharing infrastructure with the more general "asking questions about what is/was under my mouse" scenarios). This is the "3rd scenario" as @NthTensor described it, which is what I was trying to describe above.

@NthTensor

It's probably worth noting that we are not computing a global result, as I think you are aware. A pointer can end up hovering multiple entities, and PickingBehavior allows you to configure if a certain entity "blocks" lower hits or not, and you can also opt-in or opt-out of hovering.

The "global" result I'm talking about is the "depth sort and block" result, which determines if hover and click events are fired. The choices made by an entity above you (provided by an arbitrary backend) affect whether your hover or click events fire. There is (currently) no way to say "I want hover events no matter what is above me" for a specific entity. The system assumes there is one question to answer each frame (what is being "picked" as defined by bevy_picking, accounting for blocking configuration). If you need to ask multiple questions with multiple constraints in a given frame, or if you need to ask a question that the current system doesn't allow you to ask, you are on your own.

Again, I fully acknowledge that this is a Good Thing for picking. We want that. But with a singular focus on answering the "picking question" we have prevented a category of other questions from being asked. HoverMap cannot be used to answer these questions, because it is also informed by that global sort and the general picking system constraints (again ... picking is a good thing and the way it is implemented is good).

My "3rd scenario" is "when people want to ask questions about what is under their mouse (and what was under their mouse) that the global picking sort behavior and individual entity configuration cannot answer (edit: or that a single configuration of that system cannot answer within a given frame) , how can we make that as efficient and ergonomic as possible, and potentially reuse infrastructure that has already been built". Some various (not necessarily related) ideas:

  1. bevy_picking is already getting fed raw (unfiltered) hits from backends via PointerHits events. This is a great design that enables us to build on top of it. When we have a "new" question to ask, rather than recompute this data again via new raycasts, we could instead consume that event feed and then filter it down based on arbitrary criteria (and perhaps filter down to only the backends or entities we want to consider).
  2. bevy_picking computes a (private / Local) Overmap from the PointerHits events. To my knowledge this contains everything necessary to compute arbitrary over/out events (including new arbitrary derived "filtered" over/out results with different criteria, in the style of the current HoverMap). We could discuss making this (or something like it) public.
  3. We could consider generalizing the PointerHits -> Overmap -> SOME_FILTERING_PROCESS -> Event Triggers system in such a way that allows someone to define some high level PointerQueryPlugin::<T: PointerQuery>::new() that would generate over/out (and perhaps down/up) event triggers based on some PointerQuery impl. Where T could be something like "filter to entities with Rarity, sort by Rarity, and select the 3 rarest entities". The user just defines the filters and selectors and the query does the remaining tracking stuff. In/out events would be fired based on what has just become one of the 3 rarest entities under the cursor (or what has just stopped being one of those entities).
  4. We could consider doing something like (3), but generalized to "arbitrary raycasts", not "cursor raycasts".

I hope that helps convey where my head is at / illustrates that overlap + generalization is possible. Again this was all a secondary concern relative to disabling the current mesh picking backend by default. We don't have to engage with these ideas further if they are uninteresting to you. Certainly not a high priority right now.

@aevyrie
Copy link
Member

aevyrie commented Oct 26, 2024

@cart I'd like to continue discussing this, but maybe we should start a new issue? I'm worried we are OT for this particular issue, and I've opened a PR that would close this if merged.

Edit: I'll create one.

@NthTensor
Copy link
Contributor

NthTensor commented Oct 27, 2024

Ok, now I understand and I think I'm totally on board. Thanks for explaining, sorry about the confusion.

We can continue that off-shoot in the other thread. For now, I totally support your more direct suggestions for the mesh picking backend.

github-merge-queue bot pushed a commit that referenced this issue Oct 27, 2024
# Objective

- Mesh picking is noisy when a non triangle list is used
- Mesh picking runs even when users don't need it
- Resolve #16065 

## Solution

- Don't add the mesh picking plugin by default
- Remove error spam
mockersf pushed a commit that referenced this issue Oct 27, 2024
# Objective

- Mesh picking is noisy when a non triangle list is used
- Mesh picking runs even when users don't need it
- Resolve #16065 

## Solution

- Don't add the mesh picking plugin by default
- Remove error spam
grace125 added a commit to grace125/bevy that referenced this issue Oct 28, 2024
commit 78a4bea
Author: ickshonpe <david.curthoys@googlemail.com>
Date:   Sun Oct 27 22:39:32 2024 +0000

    Move `ContentSize` requirements from `Node` to the widget defining components (bevyengine#16083)

    # Objective

    Missed this in the required components PR review. `ContentSize` isn't
    used by regular UI nodes, only those with intrinsically sized content
    that needs a measure func.

    ## Solution

    Remove `ContentSize` from `Node`'s required components and add it to the
    required components of `Text` and `UiImage`.

    ---------

    Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>

commit c4c1c8f
Author: mgi388 <135186256+mgi388@users.noreply.github.com>
Date:   Mon Oct 28 09:38:07 2024 +1100

    Undeprecate is_playing_animation (bevyengine#16121)

    # Objective

    - Fixes bevyengine#16098

    ## Solution

    - Undeprecate `is_playing_animation` and copy the docs from
    `animation_is_playing` to it.

    ## Testing

    - CI

    ## Migration

    https://github.com/bevyengine/bevy-website/blob/68e9a34e3068ed2e7db5ae0b4b32feac94a589dd/release-content/0.15/migration-guides/_guides.toml#L13-L17
    needs to be removed.

commit 3d72f49
Author: ickshonpe <david.curthoys@googlemail.com>
Date:   Sun Oct 27 20:08:51 2024 +0000

    Layout rounding debug example (bevyengine#16096)

    # Objective

    Simple example for debugging layout rounding errors.

    <img width="1039" height="752" alt="layout_rounding_debug"
    src="https://github.com/user-attachments/assets/12673000-e267-467e-b25b-3f8001c1347c">

    Any white lines are gaps in the layout caused by coordinate rounding
    errors.

commit 86ee8e4
Author: ickshonpe <david.curthoys@googlemail.com>
Date:   Sun Oct 27 19:14:46 2024 +0000

    Move `UiImage` from `ui_node` to the `widget::image` module (bevyengine#16084)

    # Objective

    `UiImage` isn't just a general image component now, it's the defining
    component for the image widget so it belongs in the image widget's
    module.

commit d01db9b
Author: Hexroll by Pen, Dice & Paper <143178036+hexroll@users.noreply.github.com>
Date:   Sun Oct 27 19:08:34 2024 +0000

    Adding alpha_threshold to OrderIndependentTransparencySettings for user-level optimization (bevyengine#16090)

    # Objective

    Order independent transparency can filter fragment writes based on the
    alpha value and it is currently hard-coded to anything higher than 0.0.
    By making that value configurable, users can optimize fragment writes,
    potentially reducing the number of layers needed and improving
    performance in favor of some transparency quality.

    ## Solution

    This PR adds `alpha_threshold` to the
    OrderIndependentTransparencySettings component and uses the struct to
    configure a corresponding shader uniform. This uniform is then used
    instead of the hard-coded value.

    To configure OIT with a custom alpha threshold, use:

    ```rust
    fn setup(mut commands: Commands) {
        commands.spawn((
            Camera3d::default(),
            OrderIndependentTransparencySettings {
                layer_count: 8,
                alpha_threshold: 0.2,
            },
        ));
    }
    ```

    ## Testing

    I tested this change using the included OIT example, as well as with two
    additional projects.

    ## Migration Guide

    If you previously explicitly initialized
    OrderIndependentTransparencySettings with your own `layer_count`, you
    will now have to add either a `..default()` statement or an explicit
    `alpha_threshold` value:

    ```rust
    fn setup(mut commands: Commands) {
        commands.spawn((
            Camera3d::default(),
            OrderIndependentTransparencySettings {
                layer_count: 16,
                ..default()
            },
        ));
    }
    ```

    ---------

    Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>

commit 3fc2bd7
Author: Rob Parrett <robparrett@gmail.com>
Date:   Sun Oct 27 12:06:19 2024 -0700

    Cosmetic tweaks to `query_gltf_primitives` (bevyengine#16102)

    # Objective

    This example is really confusing to look at and tell at a glance whether
    it's broken or not.

    It's displaying a strange shape -- a cube with two vertices stretched in
    a couple dimensions at an odd angle, and doing its vertex position
    modification in a way where the intent isn't obvious.

    ## Solution

    - Change the gltf geometry so that the object is a recognizable regular
    shape
    - Change the vertex modification so that the entire cube top is being
    "lifted" from the cube
    - Adjust colors, lighting, and camera location so we can see what's
    going on
    - Also remove some irrelevant shadow and environment map setup

    ## Before

    ![Image](https://github.com/user-attachments/assets/e5dd5075-0480-49d4-b1ed-cf1fe6106f3c)

    ## After

    <img width="1280" alt="image"
    src="https://github.com/user-attachments/assets/59cab60d-efbc-47c3-8688-e4544b462421">

commit 7451900
Author: Miles Silberling-Cook <NthTensor@users.noreply.github.com>
Date:   Sun Oct 27 15:05:31 2024 -0400

    Emit picking event streams (bevyengine#16105)

    # Objective

    In `bevy_mod_picking` events are accessible through event listeners or
    `EventReader`s. When I replaced event listeners with observers, I
    removed the `EventReader` for simplicity. This adds it back.

    ## Solution

    All picking events are now properly registered, and can be accessed
    through `EventReader<Pointer<E>>`. `Pointer` now tracks the entity the
    event targeted initially, and this can also be helpful in observers
    (which don't currently do this).

    ## Testing

    The picking examples run fine. This shouldn't really change anything.

    ---------

    Co-authored-by: Aevyrie <aevyrie@gmail.com>

commit 54b323e
Author: Aevyrie <aevyrie@gmail.com>
Date:   Sun Oct 27 12:03:48 2024 -0700

    Mesh picking fixes (bevyengine#16110)

    # Objective

    - Mesh picking is noisy when a non triangle list is used
    - Mesh picking runs even when users don't need it
    - Resolve bevyengine#16065

    ## Solution

    - Don't add the mesh picking plugin by default
    - Remove error spam

commit a644ac7
Author: Tau Gärtli <git@tau.garden>
Date:   Sun Oct 27 20:01:50 2024 +0100

    More `#[doc(fake_variadic)]` goodness (bevyengine#16108)

    This PR adds `#[doc(fake_variadic)]` to that were previously not
    supported by rustdoc.

    Thanks to an [upstream
    contribution](rust-lang/rust#132115) by yours
    truly, `#[doc(fake_variadic)]` is now supported on impls such as `impl
    QueryData for AnyOf<(T, ...)>` 🎉
    Requires the latest nightly compiler (2024-10-25) which is already
    available on [docs.rs](https://docs.rs/about/builds).

    ![image](https://github.com/user-attachments/assets/68589c7e-f68f-44fb-9a7b-09d24ccf19c9)

    ![image](https://github.com/user-attachments/assets/f09d20d6-d89b-471b-9a81-4a72c8968178)

    This means that the impl sections for `QueryData` and `QueryFilter` are
    now nice and tidy ✨

    ---

    I also added `fake_variadic` to some impls that use
    `all_tuples_with_size`, however I'm not entirely happy because the docs
    are slightly misleading now:

    ![image](https://github.com/user-attachments/assets/fac93d08-dc02-430f-9f34-c97456256c56)

    Note that the docs say `IntoBindGroupLayoutEntryBuilderArray<1>` instead
    of
    `IntoBindGroupLayoutEntryBuilderArray<N>`.

commit 60b2c7c
Author: François Mockers <mockersf@gmail.com>
Date:   Fri Oct 25 22:14:39 2024 +0200

    fix bevy_dev_tools build (bevyengine#16099)

    # Objective

    - bevy_dev_tools 0.15.0-rc.1 failed to build docs
    - it use bevy_text feature in bevy_ui but it's not enabled by default
    - https://docs.rs/crate/bevy_dev_tools/0.15.0-rc.1
    -
    ## Solution

    - enable bevy_text feature of bevy_ui

commit 7c59317
Author: BD103 <59022059+BD103@users.noreply.github.com>
Date:   Fri Oct 25 16:11:51 2024 -0400

    Fix `bevy_picking` plugin suffixes (bevyengine#16082)

    # Objective

    - `MeshPickingBackend` and `SpritePickingBackend` do not have the
    `Plugin` suffix
    - `DefaultPickingPlugins` is masquerading as a `Plugin` when in reality
    it should be a `PluginGroup`
    - Fixes bevyengine#16081.

    ## Solution

    - Rename some structures:

    |Original Name|New Name|
    |-|-|
    |`MeshPickingBackend`|`MeshPickingPlugin`|
    |`MeshPickingBackendSettings`|`MeshPickingSettings`|
    |`SpritePickingBackend`|`SpritePickingPlugin`|
    |`UiPickingBackendPlugin`|`UiPickingPlugin`|

    - Make `DefaultPickingPlugins` a `PluginGroup`.
    - Because `DefaultPickingPlugins` is within the `DefaultPlugins` plugin
    group, I also added support for nested plugin groups to the
    `plugin_group!` macro.

    ## Testing

    - I used ripgrep to ensure all references were properly renamed.
    - For the `plugin_group!` macro, I used `cargo expand` to manually
    inspect the expansion of `DefaultPlugins`.

    ---

    ## Migration Guide

    > [!NOTE]
    >
    > All 3 of the changed structures were added after 0.14, so this does
    not need to be included in the 0.14 to 0.15 migration guide.

    - `MeshPickingBackend` is now named `MeshPickingPlugin`.
    - `MeshPickingBackendSettings` is now named `MeshPickingSettings`.
    - `SpritePickingBackend` is now named `SpritePickingPlugin`.
    - `UiPickingBackendPlugin` is now named `UiPickingPlugin`.
    - `DefaultPickingPlugins` is now a a `PluginGroup` instead of a
    `Plugin`.

commit 611ba8b
Author: Ludwig DUBOS <ludwig.dubos@pm.me>
Date:   Fri Oct 25 22:08:14 2024 +0200

    Add `AsyncSeekForwardExt` trait to allows a similar API to the previous Bevy version (bevyengine#16027)

    # Objective

    This PR introduces an `AsyncSeekForwardExt` trait, which I forgot in my
    previous PR bevyengine#14194.

    This new trait is analogous to `AsyncSeekExt` and allows all
    implementors of `AsyncSeekForward` to directly use the `seek_forward`
    function in async contexts.

    ## Solution

    - Implement a new `AsyncSeekForwardExt` trait
    - Automatically implement this trait for all types that implement
    `AsyncSeekForward`

    ## Showcase

    This new trait allows a similar API to the previous Bevy version:

    ```rust
    #[derive(Default)]
    struct UniverseLoader;

    #[derive(Asset, TypePath, Debug)]
    struct JustALilAsteroid([u8; 128]);

    impl AssetLoader for UniverseLoader {
        type Asset = JustALilAsteroid;
        type Settings = ();
        type Error = std::io::Error;

        async fn load<'a>(
            &'a self,
            reader: &'a mut Reader<'a>,
            _settings: &'a Self::Settings,
            _context: &'a mut LoadContext<'_>,
        ) -> Result<Self::Asset, Self::Error> {
            // read the asteroids entry table
            let entry_offset: u64 = /* ... */;
            let current_offset: u64 = reader.seek_forward(0).await?;

            // jump to the entry
            reader.seek_forward(entry_offset - current_offset).await?;

            let mut asteroid_buf = [0; 128];
            reader.read_exact(&mut asteroid_buf).await?;

            Ok(JustALilAsteroid(asteroid_buf))
        }

        fn extensions(&self) -> &[&str] {
            &["celestial"]
        }
    }
    ```

commit c6a66a7
Author: Patrick Walton <pcwalton@mimiga.net>
Date:   Thu Oct 24 14:16:00 2024 -0700

    Place percentage-closer soft shadows behind a feature gate to save on samplers. (bevyengine#16068)

    The two additional linear texture samplers that PCSS added caused us to
    blow past the limit on Apple Silicon macOS and WebGL. To fix the issue,
    this commit adds a `--feature pbr_pcss` feature gate that disables PCSS
    if not present.

    Closes bevyengine#15345.
    Closes bevyengine#15525.
    Closes bevyengine#15821.

    ---------

    Co-authored-by: Carter Anderson <mcanders1@gmail.com>
    Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>

commit 897404e
Author: Patrick Walton <pcwalton@mimiga.net>
Date:   Thu Oct 24 14:00:11 2024 -0700

    Reduce the clusterable object UBO size below 16384 for WebGL 2. (bevyengine#16069)

    The PCSS PR bevyengine#13497 increased the size of clusterable objects from 64
    bytes to 80 bytes but didn't decrease the UBO size to compensate, so we
    blew past the 16kB limit on WebGL 2. This commit fixes the issue by
    lowering the maximum number of clusterable objects to 204, which puts us
    under the 16kB limit again.

    Closes bevyengine#15998.

commit 9274bfe
Author: Carter Anderson <mcanders1@gmail.com>
Date:   Wed Oct 23 18:24:17 2024 -0500

    Move TextureAtlas into UiImage and remove impl Component for TextureAtlas (bevyengine#16072)

    # Objective

    Fixes bevyengine#16064

    ## Solution

    - Add TextureAtlas to `UiImage::texture_atlas`
    - Add `TextureAtlas::from_atlas_image` for parity with `Sprite`
    - Rename `UiImage::texture` to `UiImage::image` for parity with `Sprite`
    - Port relevant implementations and uses
    - Remove `derive(Component)` for `TextureAtlas`

    ---

    ## Migration Guide

    Before:
    ```rust
    commands.spawn((
      UiImage::new(image),
      TextureAtlas { index, layout },
    ));
    ```

    After:
    ```rust
    commands.spawn(UiImage::from_atlas_image(image, TextureAtlas { index, layout }));
    ```

    Before:
    ```rust
    commands.spawn(UiImage {
        texture: some_image,
        ..default()
    })
    ```

    After:
    ```rust
    commands.spawn(UiImage {
        image: some_image,
        ..default()
    })
    ```

commit 2cdad48
Author: Viktor Gustavsson <villor94@gmail.com>
Date:   Wed Oct 23 23:51:39 2024 +0200

    Ensure ghost nodes are skipped when getting parent clipping rect (bevyengine#16058)

    # Objective

    - Follow up on bevyengine#16044
    - `extract_uinode_borders` uses `bevy_hierarchy` directly instead of
    going through the traversal utilities, meaning it won't handle
    `GhostNode`s properly.

    ## Solution

    - Replaced the use of `bevy_hierarchy::Parent` with
    `UIChildren::get_parent`

    ## Testing

    - Ran the `overflow` example, clipping looks ok.

    ---

    ---------

    Co-authored-by: Carter Anderson <mcanders1@gmail.com>

commit c9a3f34
Author: ickshonpe <david.curthoys@googlemail.com>
Date:   Wed Oct 23 21:41:42 2024 +0100

    Fixes for a few minor borders and outlines bugs (bevyengine#16071)

    # Objective

    1. Nodes with `Display::None` set are removed from the layout and have
    no position or size. Outlines should not be drawn for a node with
    `Display::None` set.
    2. The outline and border colors are checked for transparency together.
    If only one of the two is transparent, both will get queued.
    3. The `node.is_empty()` check is insufficient to check if a border is
    present since a non-zero sized node can have a zero width border.

    ## Solution

    1. Add a check to `extract_uinode_borders` and ignore the node if
    `Display::None` is set.
    2. Filter the border and outline optional components by
    `is_fully_transparent`.
    3.  Check if all the border widths are zero instead.

    ## Testing

    I added dark cyan outlines around the left and right sections in the
    `display_and_visibility` example. If you run the example and set the
    outermost node to `Display::None` on the right, then you'll see the that
    the outline on the left disappears.

commit 7577895
Author: Carter Anderson <mcanders1@gmail.com>
Date:   Wed Oct 23 15:05:28 2024 -0500

    Use CosmicFontSystem in public bevy_text APIs and remove cosmic_text re-export (bevyengine#16063)

    # Objective

    Fixes bevyengine#16006

    ## Solution

    We currently re-export `cosmic_text`, which is seemingly motivated by
    the desire to use `cosmic_text::FontSystem` in `bevy_text` public APIs
    instead of our `CosmicFontSystem` resource wrapper type.

    This change makes `bevy_text` a "true" abstraction over `cosmic_text`
    (it in fact, was already built to be that way generally and has this one
    "leak").

    This allows us to remove the `cosmic_text` re-export, which helps clean
    up the Rust Analyzer imports and generally makes this a "cleaner" API.

commit 3fb6cef
Author: JMS55 <47158642+JMS55@users.noreply.github.com>
Date:   Wed Oct 23 12:18:49 2024 -0700

    Meshlet fill cluster buffers rewritten (bevyengine#15955)

    # Objective
    - Make the meshlet fill cluster buffers pass slightly faster
    - Address bevyengine#15920 for meshlets
    - Added PreviousGlobalTransform as a required meshlet component to avoid
    extra archetype moves, slightly alleviating
    bevyengine#14681 for meshlets
    - Enforce that MeshletPlugin::cluster_buffer_slots is not greater than
    2^25 (glitches will occur otherwise). Technically this field controls
    post-lod/culling cluster count, and the issue is on pre-lod/culling
    cluster count, but it's still valid now, and in the future this will be
    more true.

    Needs to be merged after bevyengine#15846
    and bevyengine#15886

    ## Solution

    - Old pass dispatched a thread per cluster, and did a binary search over
    the instances to find which instance the cluster belongs to, and what
    meshlet index within the instance it is.
    - New pass dispatches a workgroup per instance, and has the workgroup
    loop over all meshlets in the instance in order to write out the cluster
    data.
    - Use a push constant instead of arrayLength to fix the linked bug
    - Remap 1d->2d dispatch for software raster only if actually needed to
    save on spawning excess workgroups

    ## Testing

    - Did you test these changes? If so, how?
    - Ran the meshlet example, and an example with 1041 instances of 32217
    meshlets per instance. Profiled the second scene with nsight, went from
    0.55ms -> 0.40ms. Small savings. We're pretty much VRAM bandwidth bound
    at this point.
    - How can other people (reviewers) test your changes? Is there anything
    specific they need to know?
      - Run the meshlet example

    ## Changelog (non-meshlets)
    - PreviousGlobalTransform now implements the Default trait

commit 6d42830
Author: JMS55 <47158642+JMS55@users.noreply.github.com>
Date:   Wed Oct 23 09:56:50 2024 -0700

    Meshlet builder improvements redux (bevyengine#15886)

    Take a bunch more improvements from @zeux's nanite.cpp code.

    * Use position-only vertices (discard other attributes) to determine
    meshlet connectivity for grouping
    * Rather than using the lock borders flag when simplifying meshlet
    groups, provide the locked vertices ourselves. The lock borders flag
    locks the entire border of the meshlet group, but really we only want to
    lock the edges between meshlet groups - outwards facing edges are fine
    to unlock. This gives a really significant increase to the DAG quality.
    * Add back stuck meshlets (group has only a single meshlet,
    simplification failed) to the simplification queue to allow them to get
    used later on and have another attempt at simplifying
    * Target 8 meshlets per group instead of 4 (second biggest improvement
    after manual locks)
    * Provide a seed to metis for deterministic meshlet building
    * Misc other improvements

    We can remove the usage of unsafe after the next upstream meshopt
    release, but for now we need to use the ffi function directly. I'll do
    another round of improvements later, mainly attribute-aware
    simplification and using spatial weights for meshlet grouping.

    Need to merge bevyengine#15846 first.

commit 50d38f2
Author: akimakinai <105044389+akimakinai@users.noreply.github.com>
Date:   Wed Oct 23 08:29:58 2024 +0900

    Fix point light count limit (bevyengine#16062)

    # Objective

    - I made a mistake in bevyengine#15902, specifically [this
    diff](bevyengine@e2faedb)
    -- the `point_light_count` variable is used for all point lights, not
    just shadow mapped ones, so I cannot add `.min(max_texture_cubes)`
    there. (Despite `spot_light_count` having `.min(..)`)

    It may have broken code like this (where `index` is index of
    `point_light` vec):

    https://github.com/bevyengine/bevy/blob/9930df83ed42008f7eb2c02cc7350040f0250c2e/crates/bevy_pbr/src/render/light.rs#L848-L850

    and also causes panic here:

    https://github.com/bevyengine/bevy/blob/9930df83ed42008f7eb2c02cc7350040f0250c2e/crates/bevy_pbr/src/render/light.rs#L1173-L1174

    ## Solution

    - Adds `.min(max_texture_cubes)` directly to the loop where texture
    views for point lights are created.

    ## Testing

    - `lighting` example (with the directional light removed; original
    example doesn't crash as only 1 directional-or-spot light in total is
    shadow-mapped on webgl) no longer crashes on webgl

commit 2223f6e
Author: JMS55 <47158642+JMS55@users.noreply.github.com>
Date:   Tue Oct 22 16:05:40 2024 -0700

    Meshlet fix software rasterization (bevyengine#16049)

    # Objective
    1. Prevent weird glitches with stray pixels scattered around the scene

    ![image](https://github.com/user-attachments/assets/f12adb38-5996-4dc7-bea6-bd326b7317e1)
    2. Prevent weird glitchy full-screen triangles that pop-up and destroy
    perf (SW rasterizing huge triangles is slow)

    ![image](https://github.com/user-attachments/assets/d3705427-13a5-47bc-a54b-756f0409da0b)

    ## Solution
    1. Use floating point math in the SW rasterizer bounding box calculation
    to handle negative verticss, and add backface culling
    2. Force hardware raster for clusters that clip the near plane, and let
    the hardware rasterizer handle the clipping

    I also adjusted the SW rasterizer threshold to < 64 pixels (little bit
    better perf in my test scene, but still need to do a more comprehensive
    test), and enabled backface culling for the hardware raster pipeline.

    ## Testing

    - Did you test these changes? If so, how?
      - Yes, on an example scene. Issues no longer occur.
    - Are there any parts that need more testing?
      - No.
    - How can other people (reviewers) test your changes? Is there anything
    specific they need to know?
      - Run the meshlet example.

commit fe4f44b
Author: François Mockers <mockersf@gmail.com>
Date:   Wed Oct 23 00:37:04 2024 +0200

    crate publish order: bevy_animation depends on bevy_animation_derive (bevyengine#16060)

    # Objective

    - bevy_animation publication fails because of missed dependency
    - bevy_animation depends on bevy_animation_derive which is published
    after

    ## Solution

    - Reorder crates bevy_animation and bevy_animation_derive

commit fac0b34
Author: François Mockers <mockersf@gmail.com>
Date:   Tue Oct 22 22:21:19 2024 +0200

    remove reference to missing file in bevy_remote cargo.toml (bevyengine#16057)

    # Objective

    - bevy_remote Cargo.toml file references a readme that doesn't exist
    - This is blocking releasing the rc

    ## Solution

    - Remove the reference

commit 9d54fe0
Author: JMS55 <47158642+JMS55@users.noreply.github.com>
Date:   Tue Oct 22 13:14:30 2024 -0700

    Meshlet new error projection (bevyengine#15846)

    * New error projection code taken from @zeux's meshoptimizer nanite.cpp
    demo for determining LOD (thanks zeux!)
    * Builder: `compute_lod_group_data()`
    * Runtime: `lod_error_is_imperceptible()`

commit 9930df8
Author: ickshonpe <david.curthoys@googlemail.com>
Date:   Mon Oct 21 23:54:09 2024 +0100

    UI borders and outlines clipping fix (bevyengine#16044)

    # Objective

    fixes bevyengine#15502

    Clipped borders and outlines aren't drawn correctly.

    ### Borders aren't clipped

    Spawn two nodes with the same dimensions and border thickness, but clip
    on of the nodes so that only its top left quarter is visible:

    <img width="194" alt="clip"
    src="https://github.com/user-attachments/assets/2d3f6d28-aa20-44df-967a-677725828294">

    You can see that instead of clipping the border, instead the border is
    scaled to fit inside of the unclipped section.

    ```rust
    use bevy::color::palettes::css::BLUE;
    use bevy::prelude::*;
    use bevy::winit::WinitSettings;

    fn main() {
        App::new()
            .add_plugins(DefaultPlugins)
            .insert_resource(WinitSettings::desktop_app())
            .add_systems(Startup, setup)
            .run();
    }

    fn setup(mut commands: Commands) {
        commands.spawn(Camera2d);
        commands
            .spawn(Node {
                width: Val::Percent(100.),
                height: Val::Percent(100.),
                justify_content: JustifyContent::Center,
                align_items: AlignItems::Center,
                ..Default::default()
            })
            .with_children(|commands| {
                commands
                    .spawn(Node {
                        column_gap: Val::Px(10.),
                        ..Default::default()
                    })
                    .with_children(|commands| {
                        commands
                            .spawn(Node {
                                width: Val::Px(100.),
                                height: Val::Px(100.),
                                overflow: Overflow::clip(),
                                ..Default::default()
                            })
                            .with_child((
                                Node {
                                    position_type: PositionType::Absolute,
                                    width: Val::Px(100.),
                                    height: Val::Px(100.),
                                    border: UiRect::all(Val::Px(10.)),
                                    ..Default::default()
                                },
                                BackgroundColor(Color::WHITE),
                                BorderColor(BLUE.into()),
                            ));

                        commands
                            .spawn(Node {
                                width: Val::Px(50.),
                                height: Val::Px(50.),
                                overflow: Overflow::clip(),
                                ..Default::default()
                            })
                            .with_child((
                                Node {
                                    position_type: PositionType::Absolute,
                                    width: Val::Px(100.),
                                    height: Val::Px(100.),
                                    border: UiRect::all(Val::Px(10.)),
                                    ..Default::default()
                                },
                                BackgroundColor(Color::WHITE),
                                BorderColor(BLUE.into()),
                            ));
                    });
            });
    }
    ```

    You can also see this problem in the `overflow` example. If you hover
    over any of the clipped nodes you'll see that the outline only wraps the
    visible section of the node

    ### Outlines are clipped incorrectly

    A UI nodes Outline's are drawn outside of its bounds, so applying the
    local clipping rect to the outline doesn't make any sense.
    Instead an `Outline` should be clipped using its parent's clipping rect.

    ## Solution

    * Pass the `point` value into the vertex shader instead of calculating
    it in the shader.
    * In `extract_uinode_borders` use the parents clipping rect when
    clipping outlines.

    The extra parameter isn't a great solution I think, but I wanted to fix
    borders for the 0.15 release and this is the most minimal approach I
    could think of without replacing the whole shader and prepare function.

     ## Showcase

    <img width="149" alt="clipp"
    src="https://github.com/user-attachments/assets/19fbd3cc-e7cd-42e1-a5e0-fd92aad04dcd">

    ---------

    Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>

commit d0af199
Author: Stepan Koltsov <stepan.koltsov@gmail.com>
Date:   Mon Oct 21 16:57:52 2024 +0100

    Add a test for Mesh::triangles and fix for TriangleStrip (bevyengine#16026)

    # Objective

    - Illustrate behavior with a test
    - Fix a bug revealed by a test

    ## Solution

    - Add a test and fix

    ## Testing

    Test added.

commit 465d113
Author: Stepan Koltsov <stepan.koltsov@gmail.com>
Date:   Mon Oct 21 03:17:59 2024 +0100

    Replace TwoIterators with Either in bevy_animation (bevyengine#16036)

    # Objective

    - Less code
    - Better iterator (implements `size_hint` for example)

    ## Solution

    - Use `either`
    - This change is free because `bevy_animation` depends on `bevy_asset`,
    which already depends on `either`

    ## Testing

    CI

# Conflicts:
#	Cargo.toml
grace125 added a commit to grace125/bevy that referenced this issue Oct 28, 2024
commit 069291d
Author: Clar Fon <15850505+clarfonthey@users.noreply.github.com>
Date:   Mon Oct 28 17:15:00 2024 -0400

    Reduce compile time of bevy_ptr::OwnedPtr::make function (bevyengine#15644)

    ## Methodology

    A good metric that correlates with compile time is the amount of code
    generated by the compiler itself; even if the end binary is exactly the
    same size, having more copies of the same code can really slow down
    compile time, since it has to figure out whether it needs to include
    them or not.

    The measurement for this used was the [`cargo-llvm-lines`
    crate](https://docs.rs/crate/cargo-llvm-lines) which can measure which
    functions are generating the most lines of LLVM IR, which generally
    means more code compiled. The example compiled was the `breakout` game,
    to choose something that touches a decent portion of the engine.

    ## Solution

    Based upon the measurements, `bevy_ptr::OwnedPtr::make` was taking up
    4061 lines of LLVM IR in the example code. So, I separated part of this
    function into a less-monomorphised version to reduce the amount of
    generated code. This was by far the most lines emitted by any single
    function.

    ## Results

    After this change, only 2560 lines are emitted, accounting for a 36%
    decrease. I tried timing the results and it seemed like it did decrease
    compile times a bit, but honestly, the data is really noisy and I can't
    be bothered to compile bevy for hours on end to get enough data points.

    The tweak feels like an improvement, so, I'll offer it, however small.

commit 1add4bf
Author: ickshonpe <david.curthoys@googlemail.com>
Date:   Mon Oct 28 21:05:25 2024 +0000

    Rename `ComputedNode::calculated_size` to `size` (bevyengine#16131)

    # Objective

    Remove `calculated_` from the name `ComputedNode::calculated_size` as
    redundant, It's obvious from context that it's the resolved size value
    and it's inconsistant since none of other fields of `ComputedNode` have
    a `calculated_` prefix.

    ## Alternatives

    Rename all the fields of `ComputedNode` to `calculated_*`, this seems
    worse.

commit 33c4945
Author: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Date:   Mon Oct 28 13:01:25 2024 +0100

    Bump crate-ci/typos from 1.26.0 to 1.26.8 (bevyengine#16128)

    Bumps [crate-ci/typos](https://github.com/crate-ci/typos) from 1.26.0 to
    1.26.8.
    <details>
    <summary>Release notes</summary>
    <p><em>Sourced from <a
    href="https://github.com/crate-ci/typos/releases">crate-ci/typos's
    releases</a>.</em></p>
    <blockquote>
    <h2>v1.26.8</h2>
    <h2>[1.26.8] - 2024-10-24</h2>
    <h2>v1.26.3</h2>
    <h2>[1.26.3] - 2024-10-24</h2>
    <h3>Fixes</h3>
    <ul>
    <li>Accept <code>additionals</code></li>
    </ul>
    <h2>v1.26.2</h2>
    <h2>[1.26.2] - 2024-10-24</h2>
    <h3>Fixes</h3>
    <ul>
    <li>Accept <code>tesselate</code> variants</li>
    </ul>
    <h2>v1.26.1</h2>
    <h2>[1.26.1] - 2024-10-23</h2>
    <h3>Fixes</h3>
    <ul>
    <li>Respect <code>--force-exclude</code> for binary files</li>
    </ul>
    </blockquote>
    </details>
    <details>
    <summary>Changelog</summary>
    <p><em>Sourced from <a
    href="https://github.com/crate-ci/typos/blob/master/CHANGELOG.md">crate-ci/typos's
    changelog</a>.</em></p>
    <blockquote>
    <h2>[1.26.8] - 2024-10-24</h2>
    <h2>[1.26.7] - 2024-10-24</h2>
    <h2>[1.26.6] - 2024-10-24</h2>
    <h2>[1.26.5] - 2024-10-24</h2>
    <h2>[1.26.4] - 2024-10-24</h2>
    <h2>[1.26.3] - 2024-10-24</h2>
    <h3>Fixes</h3>
    <ul>
    <li>Accept <code>additionals</code></li>
    </ul>
    <h2>[1.26.2] - 2024-10-24</h2>
    <h3>Fixes</h3>
    <ul>
    <li>Accept <code>tesselate</code> variants</li>
    </ul>
    <h2>[1.26.1] - 2024-10-23</h2>
    <h3>Fixes</h3>
    <ul>
    <li>Respect <code>--force-exclude</code> for binary files</li>
    </ul>
    </blockquote>
    </details>
    <details>
    <summary>Commits</summary>
    <ul>
    <li><a
    href="https://github.com/crate-ci/typos/commit/0d9e0c2c1bd7f770f6eb90f87780848ca02fc12c"><code>0d9e0c2</code></a>
    chore: Release</li>
    <li><a
    href="https://github.com/crate-ci/typos/commit/e5385b07a020af945231c06d33ec490fb77fc7b0"><code>e5385b0</code></a>
    chore(ci): Fix new release process</li>
    <li><a
    href="https://github.com/crate-ci/typos/commit/f08d1171e28430953c39c15beb330811e20ecfe2"><code>f08d117</code></a>
    chore: Release</li>
    <li><a
    href="https://github.com/crate-ci/typos/commit/e6e172498c285b815f8cbe3ada1bf51f02fd3b9a"><code>e6e1724</code></a>
    chore(ci): Fix new release process</li>
    <li><a
    href="https://github.com/crate-ci/typos/commit/02afc59fd4633b33c1f7b14b96f46402477dcc75"><code>02afc59</code></a>
    chore: Release</li>
    <li><a
    href="https://github.com/crate-ci/typos/commit/f981a1cd200c62b7ce895f09d269b3ee688ccad9"><code>f981a1c</code></a>
    chore(ci): Fix new release process</li>
    <li><a
    href="https://github.com/crate-ci/typos/commit/afbc96c5d3760227ecd31b4ed5f80415beeaaa86"><code>afbc96c</code></a>
    chore: Release</li>
    <li><a
    href="https://github.com/crate-ci/typos/commit/d3dcaaeb2d5bb61eadbd393a8803745af7c81290"><code>d3dcaae</code></a>
    chore(ci): Fix new release process</li>
    <li><a
    href="https://github.com/crate-ci/typos/commit/fb8217bd5e6531ce9c1992dd571f7f23d8fdc9c4"><code>fb8217b</code></a>
    chore: Release</li>
    <li><a
    href="https://github.com/crate-ci/typos/commit/88ea8ea67dcd07e71f5c9e397a2669c639786dd8"><code>88ea8ea</code></a>
    chore(ci): Stage releases until done</li>
    <li>Additional commits viewable in <a
    href="https://github.com/crate-ci/typos/compare/v1.26.0...v1.26.8">compare
    view</a></li>
    </ul>
    </details>
    <br />

    [![Dependabot compatibility
    score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=crate-ci/typos&package-manager=github_actions&previous-version=1.26.0&new-version=1.26.8)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

    Dependabot will resolve any conflicts with this PR as long as you don't
    alter it yourself. You can also trigger a rebase manually by commenting
    `@dependabot rebase`.

    [//]: # (dependabot-automerge-start)
    [//]: # (dependabot-automerge-end)

    ---

    <details>
    <summary>Dependabot commands and options</summary>
    <br />

    You can trigger Dependabot actions by commenting on this PR:
    - `@dependabot rebase` will rebase this PR
    - `@dependabot recreate` will recreate this PR, overwriting any edits
    that have been made to it
    - `@dependabot merge` will merge this PR after your CI passes on it
    - `@dependabot squash and merge` will squash and merge this PR after
    your CI passes on it
    - `@dependabot cancel merge` will cancel a previously requested merge
    and block automerging
    - `@dependabot reopen` will reopen this PR if it is closed
    - `@dependabot close` will close this PR and stop Dependabot recreating
    it. You can achieve the same result by closing it manually
    - `@dependabot show <dependency name> ignore conditions` will show all
    of the ignore conditions of the specified dependency
    - `@dependabot ignore this major version` will close this PR and stop
    Dependabot creating any more for this major version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this minor version` will close this PR and stop
    Dependabot creating any more for this minor version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this dependency` will close this PR and stop
    Dependabot creating any more for this dependency (unless you reopen the
    PR or upgrade to it yourself)

    </details>

    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

commit 4b0efda
Author: mamekoro <86554319+mamekoro@users.noreply.github.com>
Date:   Mon Oct 28 12:26:35 2024 +0900

    Make some associated functions of `Color` const (bevyengine#16091)

    # Objective
    Make the following functions `const` that will be useful to define
    colors as constants.

    - `Color::srgb_from_array`
    - `Color::srgba_u8`
    - `Color::srgb_u8`

    The last two require Rust 1.82.0.

    ## Solution
    - Make them `const`
    - Change MSRV to 1.82.0

    ## Testing
    I tested bevy_color only. My machine does not have enough RAM capacity
    to test the whole bevy.

    `cargo test -p bevy_color`

commit 78a4bea
Author: ickshonpe <david.curthoys@googlemail.com>
Date:   Sun Oct 27 22:39:32 2024 +0000

    Move `ContentSize` requirements from `Node` to the widget defining components (bevyengine#16083)

    # Objective

    Missed this in the required components PR review. `ContentSize` isn't
    used by regular UI nodes, only those with intrinsically sized content
    that needs a measure func.

    ## Solution

    Remove `ContentSize` from `Node`'s required components and add it to the
    required components of `Text` and `UiImage`.

    ---------

    Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>

commit c4c1c8f
Author: mgi388 <135186256+mgi388@users.noreply.github.com>
Date:   Mon Oct 28 09:38:07 2024 +1100

    Undeprecate is_playing_animation (bevyengine#16121)

    # Objective

    - Fixes bevyengine#16098

    ## Solution

    - Undeprecate `is_playing_animation` and copy the docs from
    `animation_is_playing` to it.

    ## Testing

    - CI

    ## Migration

    https://github.com/bevyengine/bevy-website/blob/68e9a34e3068ed2e7db5ae0b4b32feac94a589dd/release-content/0.15/migration-guides/_guides.toml#L13-L17
    needs to be removed.

commit 3d72f49
Author: ickshonpe <david.curthoys@googlemail.com>
Date:   Sun Oct 27 20:08:51 2024 +0000

    Layout rounding debug example (bevyengine#16096)

    # Objective

    Simple example for debugging layout rounding errors.

    <img width="1039" height="752" alt="layout_rounding_debug"
    src="https://github.com/user-attachments/assets/12673000-e267-467e-b25b-3f8001c1347c">

    Any white lines are gaps in the layout caused by coordinate rounding
    errors.

commit 86ee8e4
Author: ickshonpe <david.curthoys@googlemail.com>
Date:   Sun Oct 27 19:14:46 2024 +0000

    Move `UiImage` from `ui_node` to the `widget::image` module (bevyengine#16084)

    # Objective

    `UiImage` isn't just a general image component now, it's the defining
    component for the image widget so it belongs in the image widget's
    module.

commit d01db9b
Author: Hexroll by Pen, Dice & Paper <143178036+hexroll@users.noreply.github.com>
Date:   Sun Oct 27 19:08:34 2024 +0000

    Adding alpha_threshold to OrderIndependentTransparencySettings for user-level optimization (bevyengine#16090)

    # Objective

    Order independent transparency can filter fragment writes based on the
    alpha value and it is currently hard-coded to anything higher than 0.0.
    By making that value configurable, users can optimize fragment writes,
    potentially reducing the number of layers needed and improving
    performance in favor of some transparency quality.

    ## Solution

    This PR adds `alpha_threshold` to the
    OrderIndependentTransparencySettings component and uses the struct to
    configure a corresponding shader uniform. This uniform is then used
    instead of the hard-coded value.

    To configure OIT with a custom alpha threshold, use:

    ```rust
    fn setup(mut commands: Commands) {
        commands.spawn((
            Camera3d::default(),
            OrderIndependentTransparencySettings {
                layer_count: 8,
                alpha_threshold: 0.2,
            },
        ));
    }
    ```

    ## Testing

    I tested this change using the included OIT example, as well as with two
    additional projects.

    ## Migration Guide

    If you previously explicitly initialized
    OrderIndependentTransparencySettings with your own `layer_count`, you
    will now have to add either a `..default()` statement or an explicit
    `alpha_threshold` value:

    ```rust
    fn setup(mut commands: Commands) {
        commands.spawn((
            Camera3d::default(),
            OrderIndependentTransparencySettings {
                layer_count: 16,
                ..default()
            },
        ));
    }
    ```

    ---------

    Co-authored-by: JMS55 <47158642+JMS55@users.noreply.github.com>

commit 3fc2bd7
Author: Rob Parrett <robparrett@gmail.com>
Date:   Sun Oct 27 12:06:19 2024 -0700

    Cosmetic tweaks to `query_gltf_primitives` (bevyengine#16102)

    # Objective

    This example is really confusing to look at and tell at a glance whether
    it's broken or not.

    It's displaying a strange shape -- a cube with two vertices stretched in
    a couple dimensions at an odd angle, and doing its vertex position
    modification in a way where the intent isn't obvious.

    ## Solution

    - Change the gltf geometry so that the object is a recognizable regular
    shape
    - Change the vertex modification so that the entire cube top is being
    "lifted" from the cube
    - Adjust colors, lighting, and camera location so we can see what's
    going on
    - Also remove some irrelevant shadow and environment map setup

    ## Before

    ![Image](https://github.com/user-attachments/assets/e5dd5075-0480-49d4-b1ed-cf1fe6106f3c)

    ## After

    <img width="1280" alt="image"
    src="https://github.com/user-attachments/assets/59cab60d-efbc-47c3-8688-e4544b462421">

commit 7451900
Author: Miles Silberling-Cook <NthTensor@users.noreply.github.com>
Date:   Sun Oct 27 15:05:31 2024 -0400

    Emit picking event streams (bevyengine#16105)

    # Objective

    In `bevy_mod_picking` events are accessible through event listeners or
    `EventReader`s. When I replaced event listeners with observers, I
    removed the `EventReader` for simplicity. This adds it back.

    ## Solution

    All picking events are now properly registered, and can be accessed
    through `EventReader<Pointer<E>>`. `Pointer` now tracks the entity the
    event targeted initially, and this can also be helpful in observers
    (which don't currently do this).

    ## Testing

    The picking examples run fine. This shouldn't really change anything.

    ---------

    Co-authored-by: Aevyrie <aevyrie@gmail.com>

commit 54b323e
Author: Aevyrie <aevyrie@gmail.com>
Date:   Sun Oct 27 12:03:48 2024 -0700

    Mesh picking fixes (bevyengine#16110)

    # Objective

    - Mesh picking is noisy when a non triangle list is used
    - Mesh picking runs even when users don't need it
    - Resolve bevyengine#16065

    ## Solution

    - Don't add the mesh picking plugin by default
    - Remove error spam

commit a644ac7
Author: Tau Gärtli <git@tau.garden>
Date:   Sun Oct 27 20:01:50 2024 +0100

    More `#[doc(fake_variadic)]` goodness (bevyengine#16108)

    This PR adds `#[doc(fake_variadic)]` to that were previously not
    supported by rustdoc.

    Thanks to an [upstream
    contribution](rust-lang/rust#132115) by yours
    truly, `#[doc(fake_variadic)]` is now supported on impls such as `impl
    QueryData for AnyOf<(T, ...)>` 🎉
    Requires the latest nightly compiler (2024-10-25) which is already
    available on [docs.rs](https://docs.rs/about/builds).

    ![image](https://github.com/user-attachments/assets/68589c7e-f68f-44fb-9a7b-09d24ccf19c9)

    ![image](https://github.com/user-attachments/assets/f09d20d6-d89b-471b-9a81-4a72c8968178)

    This means that the impl sections for `QueryData` and `QueryFilter` are
    now nice and tidy ✨

    ---

    I also added `fake_variadic` to some impls that use
    `all_tuples_with_size`, however I'm not entirely happy because the docs
    are slightly misleading now:

    ![image](https://github.com/user-attachments/assets/fac93d08-dc02-430f-9f34-c97456256c56)

    Note that the docs say `IntoBindGroupLayoutEntryBuilderArray<1>` instead
    of
    `IntoBindGroupLayoutEntryBuilderArray<N>`.

commit 60b2c7c
Author: François Mockers <mockersf@gmail.com>
Date:   Fri Oct 25 22:14:39 2024 +0200

    fix bevy_dev_tools build (bevyengine#16099)

    # Objective

    - bevy_dev_tools 0.15.0-rc.1 failed to build docs
    - it use bevy_text feature in bevy_ui but it's not enabled by default
    - https://docs.rs/crate/bevy_dev_tools/0.15.0-rc.1
    -
    ## Solution

    - enable bevy_text feature of bevy_ui

commit 7c59317
Author: BD103 <59022059+BD103@users.noreply.github.com>
Date:   Fri Oct 25 16:11:51 2024 -0400

    Fix `bevy_picking` plugin suffixes (bevyengine#16082)

    # Objective

    - `MeshPickingBackend` and `SpritePickingBackend` do not have the
    `Plugin` suffix
    - `DefaultPickingPlugins` is masquerading as a `Plugin` when in reality
    it should be a `PluginGroup`
    - Fixes bevyengine#16081.

    ## Solution

    - Rename some structures:

    |Original Name|New Name|
    |-|-|
    |`MeshPickingBackend`|`MeshPickingPlugin`|
    |`MeshPickingBackendSettings`|`MeshPickingSettings`|
    |`SpritePickingBackend`|`SpritePickingPlugin`|
    |`UiPickingBackendPlugin`|`UiPickingPlugin`|

    - Make `DefaultPickingPlugins` a `PluginGroup`.
    - Because `DefaultPickingPlugins` is within the `DefaultPlugins` plugin
    group, I also added support for nested plugin groups to the
    `plugin_group!` macro.

    ## Testing

    - I used ripgrep to ensure all references were properly renamed.
    - For the `plugin_group!` macro, I used `cargo expand` to manually
    inspect the expansion of `DefaultPlugins`.

    ---

    ## Migration Guide

    > [!NOTE]
    >
    > All 3 of the changed structures were added after 0.14, so this does
    not need to be included in the 0.14 to 0.15 migration guide.

    - `MeshPickingBackend` is now named `MeshPickingPlugin`.
    - `MeshPickingBackendSettings` is now named `MeshPickingSettings`.
    - `SpritePickingBackend` is now named `SpritePickingPlugin`.
    - `UiPickingBackendPlugin` is now named `UiPickingPlugin`.
    - `DefaultPickingPlugins` is now a a `PluginGroup` instead of a
    `Plugin`.

commit 611ba8b
Author: Ludwig DUBOS <ludwig.dubos@pm.me>
Date:   Fri Oct 25 22:08:14 2024 +0200

    Add `AsyncSeekForwardExt` trait to allows a similar API to the previous Bevy version (bevyengine#16027)

    # Objective

    This PR introduces an `AsyncSeekForwardExt` trait, which I forgot in my
    previous PR bevyengine#14194.

    This new trait is analogous to `AsyncSeekExt` and allows all
    implementors of `AsyncSeekForward` to directly use the `seek_forward`
    function in async contexts.

    ## Solution

    - Implement a new `AsyncSeekForwardExt` trait
    - Automatically implement this trait for all types that implement
    `AsyncSeekForward`

    ## Showcase

    This new trait allows a similar API to the previous Bevy version:

    ```rust
    #[derive(Default)]
    struct UniverseLoader;

    #[derive(Asset, TypePath, Debug)]
    struct JustALilAsteroid([u8; 128]);

    impl AssetLoader for UniverseLoader {
        type Asset = JustALilAsteroid;
        type Settings = ();
        type Error = std::io::Error;

        async fn load<'a>(
            &'a self,
            reader: &'a mut Reader<'a>,
            _settings: &'a Self::Settings,
            _context: &'a mut LoadContext<'_>,
        ) -> Result<Self::Asset, Self::Error> {
            // read the asteroids entry table
            let entry_offset: u64 = /* ... */;
            let current_offset: u64 = reader.seek_forward(0).await?;

            // jump to the entry
            reader.seek_forward(entry_offset - current_offset).await?;

            let mut asteroid_buf = [0; 128];
            reader.read_exact(&mut asteroid_buf).await?;

            Ok(JustALilAsteroid(asteroid_buf))
        }

        fn extensions(&self) -> &[&str] {
            &["celestial"]
        }
    }
    ```

commit c6a66a7
Author: Patrick Walton <pcwalton@mimiga.net>
Date:   Thu Oct 24 14:16:00 2024 -0700

    Place percentage-closer soft shadows behind a feature gate to save on samplers. (bevyengine#16068)

    The two additional linear texture samplers that PCSS added caused us to
    blow past the limit on Apple Silicon macOS and WebGL. To fix the issue,
    this commit adds a `--feature pbr_pcss` feature gate that disables PCSS
    if not present.

    Closes bevyengine#15345.
    Closes bevyengine#15525.
    Closes bevyengine#15821.

    ---------

    Co-authored-by: Carter Anderson <mcanders1@gmail.com>
    Co-authored-by: IceSentry <IceSentry@users.noreply.github.com>

commit 897404e
Author: Patrick Walton <pcwalton@mimiga.net>
Date:   Thu Oct 24 14:00:11 2024 -0700

    Reduce the clusterable object UBO size below 16384 for WebGL 2. (bevyengine#16069)

    The PCSS PR bevyengine#13497 increased the size of clusterable objects from 64
    bytes to 80 bytes but didn't decrease the UBO size to compensate, so we
    blew past the 16kB limit on WebGL 2. This commit fixes the issue by
    lowering the maximum number of clusterable objects to 204, which puts us
    under the 16kB limit again.

    Closes bevyengine#15998.

commit 9274bfe
Author: Carter Anderson <mcanders1@gmail.com>
Date:   Wed Oct 23 18:24:17 2024 -0500

    Move TextureAtlas into UiImage and remove impl Component for TextureAtlas (bevyengine#16072)

    # Objective

    Fixes bevyengine#16064

    ## Solution

    - Add TextureAtlas to `UiImage::texture_atlas`
    - Add `TextureAtlas::from_atlas_image` for parity with `Sprite`
    - Rename `UiImage::texture` to `UiImage::image` for parity with `Sprite`
    - Port relevant implementations and uses
    - Remove `derive(Component)` for `TextureAtlas`

    ---

    ## Migration Guide

    Before:
    ```rust
    commands.spawn((
      UiImage::new(image),
      TextureAtlas { index, layout },
    ));
    ```

    After:
    ```rust
    commands.spawn(UiImage::from_atlas_image(image, TextureAtlas { index, layout }));
    ```

    Before:
    ```rust
    commands.spawn(UiImage {
        texture: some_image,
        ..default()
    })
    ```

    After:
    ```rust
    commands.spawn(UiImage {
        image: some_image,
        ..default()
    })
    ```

commit 2cdad48
Author: Viktor Gustavsson <villor94@gmail.com>
Date:   Wed Oct 23 23:51:39 2024 +0200

    Ensure ghost nodes are skipped when getting parent clipping rect (bevyengine#16058)

    # Objective

    - Follow up on bevyengine#16044
    - `extract_uinode_borders` uses `bevy_hierarchy` directly instead of
    going through the traversal utilities, meaning it won't handle
    `GhostNode`s properly.

    ## Solution

    - Replaced the use of `bevy_hierarchy::Parent` with
    `UIChildren::get_parent`

    ## Testing

    - Ran the `overflow` example, clipping looks ok.

    ---

    ---------

    Co-authored-by: Carter Anderson <mcanders1@gmail.com>

commit c9a3f34
Author: ickshonpe <david.curthoys@googlemail.com>
Date:   Wed Oct 23 21:41:42 2024 +0100

    Fixes for a few minor borders and outlines bugs (bevyengine#16071)

    # Objective

    1. Nodes with `Display::None` set are removed from the layout and have
    no position or size. Outlines should not be drawn for a node with
    `Display::None` set.
    2. The outline and border colors are checked for transparency together.
    If only one of the two is transparent, both will get queued.
    3. The `node.is_empty()` check is insufficient to check if a border is
    present since a non-zero sized node can have a zero width border.

    ## Solution

    1. Add a check to `extract_uinode_borders` and ignore the node if
    `Display::None` is set.
    2. Filter the border and outline optional components by
    `is_fully_transparent`.
    3.  Check if all the border widths are zero instead.

    ## Testing

    I added dark cyan outlines around the left and right sections in the
    `display_and_visibility` example. If you run the example and set the
    outermost node to `Display::None` on the right, then you'll see the that
    the outline on the left disappears.

commit 7577895
Author: Carter Anderson <mcanders1@gmail.com>
Date:   Wed Oct 23 15:05:28 2024 -0500

    Use CosmicFontSystem in public bevy_text APIs and remove cosmic_text re-export (bevyengine#16063)

    # Objective

    Fixes bevyengine#16006

    ## Solution

    We currently re-export `cosmic_text`, which is seemingly motivated by
    the desire to use `cosmic_text::FontSystem` in `bevy_text` public APIs
    instead of our `CosmicFontSystem` resource wrapper type.

    This change makes `bevy_text` a "true" abstraction over `cosmic_text`
    (it in fact, was already built to be that way generally and has this one
    "leak").

    This allows us to remove the `cosmic_text` re-export, which helps clean
    up the Rust Analyzer imports and generally makes this a "cleaner" API.

commit 3fb6cef
Author: JMS55 <47158642+JMS55@users.noreply.github.com>
Date:   Wed Oct 23 12:18:49 2024 -0700

    Meshlet fill cluster buffers rewritten (bevyengine#15955)

    # Objective
    - Make the meshlet fill cluster buffers pass slightly faster
    - Address bevyengine#15920 for meshlets
    - Added PreviousGlobalTransform as a required meshlet component to avoid
    extra archetype moves, slightly alleviating
    bevyengine#14681 for meshlets
    - Enforce that MeshletPlugin::cluster_buffer_slots is not greater than
    2^25 (glitches will occur otherwise). Technically this field controls
    post-lod/culling cluster count, and the issue is on pre-lod/culling
    cluster count, but it's still valid now, and in the future this will be
    more true.

    Needs to be merged after bevyengine#15846
    and bevyengine#15886

    ## Solution

    - Old pass dispatched a thread per cluster, and did a binary search over
    the instances to find which instance the cluster belongs to, and what
    meshlet index within the instance it is.
    - New pass dispatches a workgroup per instance, and has the workgroup
    loop over all meshlets in the instance in order to write out the cluster
    data.
    - Use a push constant instead of arrayLength to fix the linked bug
    - Remap 1d->2d dispatch for software raster only if actually needed to
    save on spawning excess workgroups

    ## Testing

    - Did you test these changes? If so, how?
    - Ran the meshlet example, and an example with 1041 instances of 32217
    meshlets per instance. Profiled the second scene with nsight, went from
    0.55ms -> 0.40ms. Small savings. We're pretty much VRAM bandwidth bound
    at this point.
    - How can other people (reviewers) test your changes? Is there anything
    specific they need to know?
      - Run the meshlet example

    ## Changelog (non-meshlets)
    - PreviousGlobalTransform now implements the Default trait

commit 6d42830
Author: JMS55 <47158642+JMS55@users.noreply.github.com>
Date:   Wed Oct 23 09:56:50 2024 -0700

    Meshlet builder improvements redux (bevyengine#15886)

    Take a bunch more improvements from @zeux's nanite.cpp code.

    * Use position-only vertices (discard other attributes) to determine
    meshlet connectivity for grouping
    * Rather than using the lock borders flag when simplifying meshlet
    groups, provide the locked vertices ourselves. The lock borders flag
    locks the entire border of the meshlet group, but really we only want to
    lock the edges between meshlet groups - outwards facing edges are fine
    to unlock. This gives a really significant increase to the DAG quality.
    * Add back stuck meshlets (group has only a single meshlet,
    simplification failed) to the simplification queue to allow them to get
    used later on and have another attempt at simplifying
    * Target 8 meshlets per group instead of 4 (second biggest improvement
    after manual locks)
    * Provide a seed to metis for deterministic meshlet building
    * Misc other improvements

    We can remove the usage of unsafe after the next upstream meshopt
    release, but for now we need to use the ffi function directly. I'll do
    another round of improvements later, mainly attribute-aware
    simplification and using spatial weights for meshlet grouping.

    Need to merge bevyengine#15846 first.

commit 50d38f2
Author: akimakinai <105044389+akimakinai@users.noreply.github.com>
Date:   Wed Oct 23 08:29:58 2024 +0900

    Fix point light count limit (bevyengine#16062)

    # Objective

    - I made a mistake in bevyengine#15902, specifically [this
    diff](bevyengine@e2faedb)
    -- the `point_light_count` variable is used for all point lights, not
    just shadow mapped ones, so I cannot add `.min(max_texture_cubes)`
    there. (Despite `spot_light_count` having `.min(..)`)

    It may have broken code like this (where `index` is index of
    `point_light` vec):

    https://github.com/bevyengine/bevy/blob/9930df83ed42008f7eb2c02cc7350040f0250c2e/crates/bevy_pbr/src/render/light.rs#L848-L850

    and also causes panic here:

    https://github.com/bevyengine/bevy/blob/9930df83ed42008f7eb2c02cc7350040f0250c2e/crates/bevy_pbr/src/render/light.rs#L1173-L1174

    ## Solution

    - Adds `.min(max_texture_cubes)` directly to the loop where texture
    views for point lights are created.

    ## Testing

    - `lighting` example (with the directional light removed; original
    example doesn't crash as only 1 directional-or-spot light in total is
    shadow-mapped on webgl) no longer crashes on webgl

commit 2223f6e
Author: JMS55 <47158642+JMS55@users.noreply.github.com>
Date:   Tue Oct 22 16:05:40 2024 -0700

    Meshlet fix software rasterization (bevyengine#16049)

    # Objective
    1. Prevent weird glitches with stray pixels scattered around the scene

    ![image](https://github.com/user-attachments/assets/f12adb38-5996-4dc7-bea6-bd326b7317e1)
    2. Prevent weird glitchy full-screen triangles that pop-up and destroy
    perf (SW rasterizing huge triangles is slow)

    ![image](https://github.com/user-attachments/assets/d3705427-13a5-47bc-a54b-756f0409da0b)

    ## Solution
    1. Use floating point math in the SW rasterizer bounding box calculation
    to handle negative verticss, and add backface culling
    2. Force hardware raster for clusters that clip the near plane, and let
    the hardware rasterizer handle the clipping

    I also adjusted the SW rasterizer threshold to < 64 pixels (little bit
    better perf in my test scene, but still need to do a more comprehensive
    test), and enabled backface culling for the hardware raster pipeline.

    ## Testing

    - Did you test these changes? If so, how?
      - Yes, on an example scene. Issues no longer occur.
    - Are there any parts that need more testing?
      - No.
    - How can other people (reviewers) test your changes? Is there anything
    specific they need to know?
      - Run the meshlet example.

commit fe4f44b
Author: François Mockers <mockersf@gmail.com>
Date:   Wed Oct 23 00:37:04 2024 +0200

    crate publish order: bevy_animation depends on bevy_animation_derive (bevyengine#16060)

    # Objective

    - bevy_animation publication fails because of missed dependency
    - bevy_animation depends on bevy_animation_derive which is published
    after

    ## Solution

    - Reorder crates bevy_animation and bevy_animation_derive

commit fac0b34
Author: François Mockers <mockersf@gmail.com>
Date:   Tue Oct 22 22:21:19 2024 +0200

    remove reference to missing file in bevy_remote cargo.toml (bevyengine#16057)

    # Objective

    - bevy_remote Cargo.toml file references a readme that doesn't exist
    - This is blocking releasing the rc

    ## Solution

    - Remove the reference

commit 9d54fe0
Author: JMS55 <47158642+JMS55@users.noreply.github.com>
Date:   Tue Oct 22 13:14:30 2024 -0700

    Meshlet new error projection (bevyengine#15846)

    * New error projection code taken from @zeux's meshoptimizer nanite.cpp
    demo for determining LOD (thanks zeux!)
    * Builder: `compute_lod_group_data()`
    * Runtime: `lod_error_is_imperceptible()`

commit 9930df8
Author: ickshonpe <david.curthoys@googlemail.com>
Date:   Mon Oct 21 23:54:09 2024 +0100

    UI borders and outlines clipping fix (bevyengine#16044)

    # Objective

    fixes bevyengine#15502

    Clipped borders and outlines aren't drawn correctly.

    ### Borders aren't clipped

    Spawn two nodes with the same dimensions and border thickness, but clip
    on of the nodes so that only its top left quarter is visible:

    <img width="194" alt="clip"
    src="https://github.com/user-attachments/assets/2d3f6d28-aa20-44df-967a-677725828294">

    You can see that instead of clipping the border, instead the border is
    scaled to fit inside of the unclipped section.

    ```rust
    use bevy::color::palettes::css::BLUE;
    use bevy::prelude::*;
    use bevy::winit::WinitSettings;

    fn main() {
        App::new()
            .add_plugins(DefaultPlugins)
            .insert_resource(WinitSettings::desktop_app())
            .add_systems(Startup, setup)
            .run();
    }

    fn setup(mut commands: Commands) {
        commands.spawn(Camera2d);
        commands
            .spawn(Node {
                width: Val::Percent(100.),
                height: Val::Percent(100.),
                justify_content: JustifyContent::Center,
                align_items: AlignItems::Center,
                ..Default::default()
            })
            .with_children(|commands| {
                commands
                    .spawn(Node {
                        column_gap: Val::Px(10.),
                        ..Default::default()
                    })
                    .with_children(|commands| {
                        commands
                            .spawn(Node {
                                width: Val::Px(100.),
                                height: Val::Px(100.),
                                overflow: Overflow::clip(),
                                ..Default::default()
                            })
                            .with_child((
                                Node {
                                    position_type: PositionType::Absolute,
                                    width: Val::Px(100.),
                                    height: Val::Px(100.),
                                    border: UiRect::all(Val::Px(10.)),
                                    ..Default::default()
                                },
                                BackgroundColor(Color::WHITE),
                                BorderColor(BLUE.into()),
                            ));

                        commands
                            .spawn(Node {
                                width: Val::Px(50.),
                                height: Val::Px(50.),
                                overflow: Overflow::clip(),
                                ..Default::default()
                            })
                            .with_child((
                                Node {
                                    position_type: PositionType::Absolute,
                                    width: Val::Px(100.),
                                    height: Val::Px(100.),
                                    border: UiRect::all(Val::Px(10.)),
                                    ..Default::default()
                                },
                                BackgroundColor(Color::WHITE),
                                BorderColor(BLUE.into()),
                            ));
                    });
            });
    }
    ```

    You can also see this problem in the `overflow` example. If you hover
    over any of the clipped nodes you'll see that the outline only wraps the
    visible section of the node

    ### Outlines are clipped incorrectly

    A UI nodes Outline's are drawn outside of its bounds, so applying the
    local clipping rect to the outline doesn't make any sense.
    Instead an `Outline` should be clipped using its parent's clipping rect.

    ## Solution

    * Pass the `point` value into the vertex shader instead of calculating
    it in the shader.
    * In `extract_uinode_borders` use the parents clipping rect when
    clipping outlines.

    The extra parameter isn't a great solution I think, but I wanted to fix
    borders for the 0.15 release and this is the most minimal approach I
    could think of without replacing the whole shader and prepare function.

     ## Showcase

    <img width="149" alt="clipp"
    src="https://github.com/user-attachments/assets/19fbd3cc-e7cd-42e1-a5e0-fd92aad04dcd">

    ---------

    Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com>

commit d0af199
Author: Stepan Koltsov <stepan.koltsov@gmail.com>
Date:   Mon Oct 21 16:57:52 2024 +0100

    Add a test for Mesh::triangles and fix for TriangleStrip (bevyengine#16026)

    # Objective

    - Illustrate behavior with a test
    - Fix a bug revealed by a test

    ## Solution

    - Add a test and fix

    ## Testing

    Test added.

commit 465d113
Author: Stepan Koltsov <stepan.koltsov@gmail.com>
Date:   Mon Oct 21 03:17:59 2024 +0100

    Replace TwoIterators with Either in bevy_animation (bevyengine#16036)

    # Objective

    - Less code
    - Better iterator (implements `size_hint` for example)

    ## Solution

    - Use `either`
    - This change is free because `bevy_animation` depends on `bevy_asset`,
    which already depends on `either`

    ## Testing

    CI
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Picking Pointing at and selecting objects of all sorts C-Bug An unexpected or incorrect behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants