mirror of
https://github.com/bevyengine/bevy.git
synced 2026-07-01 00:05:45 -04:00
create-pull-request/patch
12 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
846b196cda |
Deploy Docs - Build Docs step: Resolve most Warnings (#23343)
# Objective - Resolve most of the warnings in the Build Docs step of Deploy Docs, you can see them here: https://github.com/bevyengine/bevy/actions/runs/23021953246/job/66860356132 ## Solution - Resolve most of the warnings - The `doc_cfg` feature should only be enabled with `docsrs`, not `docsrs_dep` (I just followed this pattern from other crates tbh like `bevy_math` and `bevy_material`) - I unlinked example docs that references non public items within the example itself - I corrected some links Note: I didn’t fix the warnings concerning the macros in bevy-reflect for `tuple.rs` because I’m not macro savvy. If someone knows what to do in those cases (should I just remove the `$(#[$meta])*` lines cause they’re not in use?), just let me know and I can do it (or you can open a pull!) --------- Co-authored-by: François Mockers <francois.mockers@vleue.com> |
||
|
|
e696fa7526 |
Debug Frustum Culling Usage Example (#22900)
# Objective - Fixes #22881 . Now that we have Aabb & Frustum Gizmos, let’s provide an example of their usage! ## Solution - A new usage example focused on debugging frustum culling. Using a free camera, you can inspect a scene with another stationary camera that has its frustum visualized and various shapes that interact with the frustum. ## Testing `cargo run --example debug_frustum_culling --features=“free_camera”` https://github.com/user-attachments/assets/08add970-4e80-4ac1-a81b-32b691f0a803 --------- Co-authored-by: Quinn Mueller <1271721+Smerom@users.noreply.github.com> |
||
|
|
6ca4769128 |
Minimal responsive FontSize support (#22614)
# Objective
Add responsive font sizes supporting rem and viewport units to
`bevy_text` with minimal changes to the APIs and systems.
## Solution
Introduce a new `FontSize` enum:
```rust
pub enum FontSize {
/// Font Size in logical pixels.
Px(f32),
/// Font size as a percentage of the viewport width.
Vw(f32),
/// Font size as a percentage of the viewport height.
Vh(f32),
/// Font size as a percentage of the smaller of the viewport width and height.
VMin(f32),
/// Font size as a percentage of the larger of the viewport width and height.
VMax(f32),
/// Font Size relative to the value of the `RemSize` resource.
Rem(f32),
}
```
This replaces the `f32` value of `TextFont`'s `font_size` field.
The viewport variants work the same way as their respective `Val`
counterparts.
`Rem` values are multiplied by the value of the `RemSize` resource
(which newtypes an `f32`).
`FontSize` provides an `eval` method that takes a logical viewport size
and rem base size and returns an `f32` logical font size. The resolved
logical font size is then written into the `Attributes` passed to Cosmic
Text by `TextPipeline::update_buffer`.
Any text implementation using `bevy_text` must now provide viewport and
rem base values when calling `TextPipeline::update_buffer` or
`create_measure`.
`Text2d` uses the size of the primary window to resolve viewport values
(or `Vec2::splat(1000)` if no primary window is found). This is a
deliberate compromise, a single `Text2d` can be rendered to multiple
viewports using `RenderLayers`, so it's difficult to find a rule for
which viewport size should be chosen.
### Change detection
`ComputedTextBlock` has two new fields: `uses_viewport_sizes` and
`uses_rem_sizes`, which are set to true in `TextPipeline::update_buffer`
iff any text section in the block uses viewport or rem font sizes,
respectively.
The `ComputedTextBlock::needs_rerender` method has been modified to take
take two bool parameters:
```rust
pub fn needs_rerender(
&self,
is_viewport_size_changed: bool,
is_rem_size_changed: bool,
) -> bool {
self.needs_rerender
|| (is_viewport_size_changed && self.uses_viewport_sizes)
|| (is_rem_size_changed && self.uses_rem_sizes)
}
```
This ensures that text reupdates will also be scheduled if one of the text section's uses a viewport font size and the local viewport size changed, or if one of the text section's uses a rem font size and the rem size changed.
#### Limitations
There are some limitations because we don't have any sort of font style inheritance yet:
* "rem" units aren't proper rem units, and just based on the value of a resource.
* "em" units are resolved based on inherited font size, so can't be implemented without inheritance support.
#### Notes
* This PR is quite small and not very technical. Reviewers don't need to be especially familiar with `bevy_text`. Most of the changes are to the examples.
* We could consider using `Val` instead of `FontSize`, then we could use `Val`'s constructor functions which would be much nicer, but some variants might not have sensible interpretations in both UI and Text2d contexts. Also we'd have to make `Val` accessible to `bevy_text`.
## Testing
The changes to the text systems are relatively trivial and easy to understand. I already added a minor change to the `text` example to use `Vh` font size for the "hello bevy" text in the bottom right corner. If you change the size of the window, you should see the text change size in response. The text initially flickers before it updates because of some unrelated asset/image changes that mean that font textures aren't ready until the frame after the text update that changes the font size.
Most of the example migrations were automated using regular expressions, and there are bound to be mistakes in those changes. It's infeasible to check every single example thoroughly, but it's early enough in the release cycle that I don't think we should be too worried if a few bugs slip in.
---------
Co-authored-by: Kevin Chen <chen.kevin.f@gmail.com>
|
||
|
|
a37c14ce95 |
Add BorderRadius to Node (#21781)
# Objective There was discussion in the `Next Generation Scene/UI` about adding `BackgroundColor` to `Node`. I don't know about that, but it reminded me that border radius isn't part of `Node`. All the other properties that affect a `Node`'s shape are there, border radius should be there too. ## Solution * Add a `border_radius: BorderRadius` field. * Remove the `Component` derive from `BorderRadius`. ## Testing The internal changes are relatively trivial. There could be mistakes in the examples though, because of the large number of changes. |
||
|
|
eda118d033 |
Event Rearchitecture (#20731)
There is general consensus that our terminology for Events, "entity events", Observers, and BufferedEvents needs clarity. Additionally, many of us also agree that the current Observer system would benefit from additional static-ness: currently it is assumed that you can use events in pretty much any context, and they all go through the exact same code path. Alice put forth a proposal to [Overhaul Observers](https://hackmd.io/@bevy/rk4S92hmlg), and we have already partially implemented it for 0.17. I think it does a great job of outlining many of the issues at play, and it solves them reasonably well. But I _also_ think the proposed solution isn't yet ideal. Given that it is already partially implemented for 0.17, it is a breaking change, _and_ given that we have already broken the Observer API a number of times, I think we need to sort this out before the next release. This is a big changeset, but it is _largely_ just a reframing of what is already there. I haven't fundamentally changed the behaviors. I've just refined and constrained in a way that allows us to do what we are currently doing in a clearer, simpler, and more performant way. First, I'll give some quick notes on Alice's proposal (which you all should read if you haven't yet!): ### Notes on Alice's Proposal - I like the move toward a more static API - I think we've gone too far down the "separate terminology" path. The proposal introduces a zoo of apis, terms, and "subterms". I think we need to simplify our concepts and names to make this all easier to talk about and use in practice. - BroadcastEvent feels like the wrong name. EntityEvent is also "broadcast" in the exact same way - BufferedEvent is a completely different system than EntityEvent and BroadcastEvent. This muddles concepts too much. It needs its own standalone, single-word concept name. - "Universal observers": I think this should be fully context driven, rather than needing encoding in the API. - I agree we can't get rid of buffered events, and that merging them with "broadcast events" isn't helpful - I'm not quite sure how we'd make the proposed PropagateEvent subtrait work transparently. This can't be "layered on top" as a trait. It needs to be baked in at more fundamental level. * I don't like `app.add_broadcast_observers()`, `app.add_universal_observers()`, `Observer::entity_observer`, `Observer::broadcast`, etc. The `On` event should statically determine whether an observer is an "entity observer" or a "broadcast" Observer. This would already be encoded in the type system and is therefore something we can do on the developer's behalf. Likewise, any observer being registered at a top level is inherently _not_ a specific entity observer. All of these variants serve to make users guess and poke around in a way that is unnecessary. I want simple one word concept names, single constructors, etc. ### Proposed Principals - Static-ness: - Events should only be usable in the context they were defined to be used. - When triggered, Observers should *only* have access to fields and behaviors that are relevant: - Dont return Option or PLACEHOLDER: the field or function shouldn't exist - Entity events that don't support propagation shouldn't expose that functionality - Don't do unnecessary work at runtime - Event triggers shouldn't branch through every potential event code path - Don't clone potentially large lists of event context unnecessarily (Ex: we currently clone the component list for every observer invocation) - Minimize codegen - Don't recompile things redundantly. - Don't compile unnecessary code paths. - Clear and Simple - Minimize the number of concept names floating around, and lock each concept down heavily to a specific context - I'm convinced at this point that "buffered events" and "observer events" sharing concept names is wrong. We need two clean and clear terms, and I'm willing to give "buffered events" a slightly worse name if it means "observer events" can be nicer. - Don't throw the concept name "Event" out ... it is a very good name. Instead, constrain it to one specific thing. - Minimize our API surface - Events contain all context, including what used to be the "target". This lets people define the "target" name that makes the most sense for the context, and lets the documentation fully describe the context of that "target". ### Concepts - **Event** (the thing you "observe") - Rationale: "Event" is the clear choice for this concept. An "event" feels like something that happens in real time. "Event observers" are things that observe events when they occur (are triggered). Additionally, this is the concept that "propagates", and "event propagation" is a term people understand. - **Trigger**: (the verb that "causes" events to happen for targets). Events are Triggered. This can include additional context/ data that is passed to observers / informs the trigger behavior. Events have _exactly_ one Trigger. If you want a different trigger behavior, define a new event. This makes the system more static, more predictable, and easier to understand and document. `world.trigger_ref_with` makes it possible to pass in mutable reference to your own Trigger data, making it possible to customize the input trigger data and read out the final trigger data. - **Observer** (the thing that "observes" events): An event's `Trigger` determines which observers will run. - **Event Types**: You can build any "type" of event. The concept of a "target" has been removed. Instead, define a `Trigger` that expects a specific kind of event (ex: `E: EntityEvent`). - **EntityEvent** We add a new `EntityEvent` trait, which defines an `event.entity()` accessor. This is used by the `Trigger` impls : `EntityTrigger`, `PropagateEntityTrigger`, and `EntityComponentsTrigger`. - **Message** (the buffered thing you "read" and "write") - `Message` is a solid metaphor for what this is ... it is data that is written and then at some later point read by someone / something else. I expect existing consumers of "buffered events" to lament this name change, as "event" feels nicer. But having a separate name is within everyone's best interest. - **MessageReader** (the thing that reads messages) - **MessageWriter** (the thing that writes messages) ### The Changes - `Event` trait changes - Event is now used exclusively by Observers - Added `Event::Trigger`, which defines what trigger implementation this event will use - Added the `Trigger` trait - All of the shared / hard-coded observer trigger logic has been broken out into individual context-specific Trigger traits. - "Trigger Targets" have been removed. - Instead, Events, in combination with their Trigger impl, decide how they will be triggered. In general, this means that Events now include their "targets" as fields on the event. - APIs like `trigger_targets` have been replaced by `trigger`, which can now be used for any `Event` - `EntityEvent` trait changes - Propagation config has been removed from the `EntityEvent` trait. It now lives on the `Trigger` trait (specifically the `PropagateEntityTrigger` trait). - `EntityEvent` now provides `entity / entity_mut` accessors for the Event it is implemented for - `EntityEvent` defaults to having no propagation (uses the simpler `EntityTrigger`) - `#[entity_event(propagate)]` enables the "default" propagation logic (uses ChildOf). The existing `#[entity_event(traversal = X)]` has been renamed to `#[entity_event(propagate = X)` - Deriving `EntityEvent` requires either a single `MyEvent(Entity)`, the `entity` field name (`MyEvent { entity: Entity}`), or `MyEvent { #[event_entity] custom: Entity }` - Animation event changes - Animation events now have their own `AnimationEvent` trait, which sets the `AnimationEventTrigger`. This allows developers to pass in events that _dont_ include the Entity field (as this is set by the system). The custom trigger also opens the doors to cheaply passing in additional animation system context, accessible through `On` - `EntityComponentsTrigger` - The built in Add/Remove/etc lifecycle events now use the `EntityComponentsTrigger`, which passes in the components as additional state. This _significantly_ cuts down on clones, as it does a borrow rather than cloning the list into _each_ observer execution. - Each event now has an `entity` field. - Style changes - Prefer the event name for variables: `explode: On<Explode>` not `event: On<Explode>` - Prefer using the direct field name for the entity on entity events, rather than `event.entity()`. This allows us to use more specific names where appropriate, provides better / more contextual docs, and coaches developers to think of `On<MyEvent>` _as_ the event itself. Take a look at the changes to the examples and the built-in events to see what this looks like in practice. ### Downsides - Moving the "target" into the event adds some new constraints: - Triggering the same event for multiple entities requires multiple trigger calls. For "expensive" events (ex: lots of data attached to the event), this will be more awkward. Your options become: - Create multiple instances of the event, cloning the expensive data - Use `trigger_ref`, and mutate the event on each call to change the target. - Move the "expensive" shared data into the Trigger, and use `trigger_ref_with`` - We could build a new EntityEvent method that abstracts over the "event mutation" behavior and provides something like the old `trigger_target` behavior. - Use a different `EntityTargetTrigger` (not currently provided by bevy, but we could), which brings back the old behavior. This would be used with `trigger_with` to replicate the old pattern: `world.trigger_with(MyEvent, [e1, e2].into())` (or we could make the `into()` implicit) - Bubbling the event involves mutating the event to set the entity. This means that `trigger_ref` will result in the event's `EntityEvent::entity()` being the final bubbled entity instead of the initial entity. - Some APIs (trivially) benefit from the "target entity" being separate from the event. Specifically, this new API requires changes to the "Animation Event" system in AnimationPlayer. I think this is actually a good change set, as it allows us to: - Cheaply expose more animation state as part of a new AnimationEventTrigger impl - Move that "implict" entity target provided by the AnimationPlayer into the AnimationEventTrigger - Encode the "animation event trigger-ness" of the event into the type itself (by requiring `#[event(trigger = AnimationEventTrigger)]`) - By not implementing Default for AnimationEventTrigger, we can block animation events from being fired manually by the user. ### Draft TODO - [x] Fill in documentation and update existing docs - [ ] Benchmark: I expect this impl to be significantly faster. There might also be tangible binary size improvements, as I've removed a lot of redundant codegen. - [x] Update release notes and migration guides ### Next Steps - The `BufferedEvent -> Message` rename was not included to keep the size down. Fixes #19648 --------- Co-authored-by: Alice Cecile <alice.i.cecile@gmail.com> Co-authored-by: Jan Hohenheim <jan@hohenheim.ch> |
||
|
|
13877fa84d |
Add a new trait to accept more types in the Val-helper functions (#20551)
# Objective - Allow the `Val`-helper functions to accept more types besides just `f32` Fixes #20549 ## Solution - Adds a new trait that can be implemented for numbers - That trait has a method that converts `self` to `f32` ## Testing - I tested it using Rust's testing framework (although I didn't leave the tests in, as I don't deem them important enough) <details> <summary>Rust test</summary> ```rust #[cfg(test)] mod tests { use super::*; #[test] fn test_val_helpers_work() { let p = px(10_u8); assert_eq!(p, Val::Px(10.0)); let p = px(10_u16); assert_eq!(p, Val::Px(10.0)); let p = px(10_u32); assert_eq!(p, Val::Px(10.0)); let p = px(10_u64); assert_eq!(p, Val::Px(10.0)); let p = px(10_u128); assert_eq!(p, Val::Px(10.0)); let p = px(10_i8); assert_eq!(p, Val::Px(10.0)); let p = px(10_i16); assert_eq!(p, Val::Px(10.0)); let p = px(10_i32); assert_eq!(p, Val::Px(10.0)); let p = px(10_i64); assert_eq!(p, Val::Px(10.0)); let p = px(10_i128); assert_eq!(p, Val::Px(10.0)); let p = px(10.3_f32); assert_eq!(p, Val::Px(10.3)); let p = px(10.6_f64); assert_eq!(p, Val::Px(10.6)); } } ``` </details> --- ## Showcase ```rust // Same as Val::Px(10.) px(10); px(10_u8); px(10.0); ``` |
||
|
|
5058f8a9e6 |
Improve On Terminology (#20648)
# Objective Fixes #19263 (and expands on it) Within `Observers`, we have started to distance ourselves from the "trigger" terminology. Specifically, we have renamed `Trigger` to `On`. I think this was a very good move, but we're currently in an awkward middle ground state. Users interact with `On` as if it were an event: `On<E>` exposes the event and derefs directly to it. I think we should embrace this mindset fully, in the interest of clarity. ## Solution - Rename all `trigger: On<SomeEvent>` cases to `event: On<SomeEvent>`. - Rename `On::target` to `On::entity`. This reads _much_ better when writing `query.get(event.entity())` and pairs more effectively with the `EntityEvent` terminology. - Rename `On::original_target` to `On::original_entity`, for the same reasons. - Take advantage of the `Deref` behavior where appropriate ```rust // Before entity.observe(|trigger: On<Explode>| { println!("{} exploded!", trigger.target()); }) // After entity.observe(|event: On<Explode>| { println!("{} exploded!", event.entity()); }) ``` |
||
|
|
877d278785 |
Remove unnecessary + use<> (#20180)
# Objective Including `use<>` where it is not needed is abhorrent to my sensibilities ## Solution Begone foul demon! |
||
|
|
92e65d5eb1 | Upgrade to Rust 1.88 (#19825) | ||
|
|
8f08d6bc86 |
Move usages folder to usage (#19757)
# Objective There were 2 folders inside of `examples`, each with 1 example, and with similar folder names. ## Solution Move the example in the `usages` folder to `usage`. ## Testing `cargo run -p ci` |
||
|
|
2e37783242 |
Move cooldown example instruction text according to example visual guidelines (#19381)
# Objective Use the same text positioning as other examples that have instruction text. See https://bevyengine.org/learn/contribute/helping-out/creating-examples/#visual-guidelines |
||
|
|
923c2ad281 |
New cooldown example (#19234)
# Objective We want to extend our examples with a new category "usage" to demonstrate common use cases (see bevyengine/bevy-website#2131). This PR adds an example of animated cooldowns on button clicks. ## Solution - New example in "usage" directory - Implement a cooldown with an animated child Node ## Testing - I ran this on Linux - [x] test web (with bevy CLI: `bevy run --example cooldown web --open`) --------- Co-authored-by: Thierry Berger <contact@thierryberger.com> Co-authored-by: Ida "Iyes" <40234599+inodentry@users.noreply.github.com> |