Custom Cursors, Picking, and Space games
2024-08-19
A PR for an implementation of Required Components went up this week. If you have crates that will be affected and are interested in the ongoing Next Generation Scene/UI work then this is an important PR to check out.
This week we see a number of quality-of-life improvements as well as great new lands like custom cursors. Other work merged this week feels like groundswell work than will make for a great 0.15 release.
We also see some interesting crates this week such as bevy_transform_interpolation
which aid the use of FixedTimesteps as well as some crates that slipped from last week's issue like leafwing-input-manger 0.15.
Custom Cursors
#14284 added custom cursors! In the updated window_settings
example you can see a number of different cursors including the Bevy Logo as a cursor, which you can tell is a cursor in this image as it extends over the edge of the application.
try_insert
Inserting components gets a boost this week with #14646 and #14787 which added panicking and non-panicking variants of insert_if_new
.
insert_if_new
will attempt to insert a component, and fail if the component already exists on the Entity. This is particularly interesting when Bundles have duplicate components like inserting a PbrBundle
onto an entity with a SpatialBundle
.
EntityCommands.trigger
#14752 adds a function to EntityCommands
to trigger observer events for the particular entity you're working with.
Mesh2d Improvements
Last week we saw an opaque pass with a depth texture get added to the 2d render pipelines. This week that work was optimized by moving from SortedRenderPhase
to BinnedRenderPhase
in #13091 and extended with a new alpha mask phase to support transparency in #14724. More Mesh2d improvements are being tracked in #13265.
Working Groups Documentation
A new post in the Bevy Discord #working-groups channel now gives a small explanation and routes people to more information.
Working groups are the primary way that Bevy collaborates on complex changes or large tasks, and one of the best ways to get started as a Bevy contributor. These are scoped, informal groups that design, implement and review a set of changes, or help out with things like preparing releases or running jams.
Curve Crew Working Group
#14700 continues last week's work from the Curve Crew and adds a Curve trait for general interoperation. This continues work described in the Curve RFC.
bevy_mod_picking upstreaming
The newly merged picking is made usable for UI elements in #14695. This enables Entity
s with the Pickable
component to trigger observers that can respond to pointer events like Click
for these entities.
Check out the new simple_picking
example to see how its used.
.observe(
|_click: Trigger<Pointer<Click>>,
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<StandardMaterial>>,
mut num: Local<usize>| {
commands.spawn(PbrBundle {
mesh: meshes.add(Cuboid::new(1.0, 1.0, 1.0)),
material: materials.add(Color::srgb_u8(124, 144, 255)),
transform: Transform::from_xyz(0.0, 0.5 + 1.1 * *num as f32, 0.0),
..default()
});
*num += 1;
},
)
Showcase
Bevy work from the #showcase channel in Discord and around the internet. Use hashtag #bevyengine.
Panoply
showcase
Progress on Panoply: an editor built with Quill.
Panoply allows for the speed of editing of a tile game, but allows greater flexibility in tile design and placement.
Overlays and grids are reactive gizmo-like drawing primitives from quill_overlay
. Tiles can be placed in the world using a series of thumbnails. The thumbnails are generated in a large scene with a single camera and a dedicated render target. Boolean operations are also supported.
Prime Visualizations
showcase
Plotting prime numbers in polar coordinates. With visually pleasing twinkling animations. Inspired by this video by 3Blue1Brown.
Source inspired FPS
showcase
This Source-inspired FPS introduced a number of new features and mechanics.
- Sprinting
- Inventory system
- Switchable weapon attachments
- Hit scan firing with bullet tracers
- Recoil (going to change the algorithm later)
- Aim down sights
- Aimed reloads, like in the newer Call of Duty games
kiwibert
showcase
Kiwibert is a Q*bert-inspired game built on bevy_ecs_tilemap and some leafwing-input-manager goodness for controls. Development is streamed on Twitch
bevy_transform_interpolation
showcase
An experiment in ergonomic general-purpose Transform
interpolation. Add some marker components to granularly enable interpolation for the properties you need:
use bevy::prelude::*;
use bevy_transform_interpolation::*;
// Note: Interpolation can also be enabled globally.
fn setup(mut commands: Commands) {
// Only interpolate translation.
commands.spawn((TransformBundle::default(), TranslationInterpolation));
// Interpolate the entire transform: translation, rotation, and scale.
commands.spawn((
TransformBundle::default(),
TransformInterpolationBundle::default(),
));
}
Now, all changes that happen to the Transform
in FixedUpdate
or other fixed timestep schedules will automatically be smoothed. Transform
can be still be modified in any schedule like normal, no separate "gameplay transforms" needed.
This approach makes the interpolation automatically compatible with physics engines and the majority of other ecosystem libraries without any modifications.
Spring: Spherical Interpolation using Numerical Gradient descent
showcase
Implementation of "Spherical Interpolation using Numerical Gradient descent" aka spring, a method of creating smooth splines between quaternions.
This starts with 8 keyframe quaternions that form a closed loop. The gradient descent doesn't work well when given too many values at once, so the authors of spring recommend gradually increasing the number of interpolation frames.
bevy_plotting
showcase
A demo of some gizmo plotting code extracted into a repo for general use. Its not available on crates.io, so either use it as inspiration or a git dependency.
// Data
let points = [
Vec2::new(0., 0.),
Vec2::new(1., 1.),
Vec2::new(2., 0.5)
];
// Position & size of plot
let bounds = Rect::from_center_size(
Vec2::ZERO,
Vec2::splat(100.)
);
draw_gizmo_line_plot_2d_raw(
points.iter(),
&mut gizmos,
bounds,
Vec2::ZERO,
Vec2::new(2., 1.),
Color::WHITE,
);
Space Mining Game
showcase
What is supposed to be a mining game with an excavator and destructible mountain. turned into more detailed space exploration this week, inspired by the big_space crate.
Crates
New releases to crates.io and substantial updates to existing projects
bevy_bsml
crate_release
bevy_bsml is a markup language & implementation inspired by svelte and tailwindcss.
Create your own reusable components, and handle reactivity using BsmlClasses
component in systems to add/remove classes. It's built on top of bevy_ui, so you can still use bevy_ui to manually interact with the ui node or styles.
(node) {
(text) { "hello world" }
}
leafwing-input-manager 0.15
crate_release
A straightforward but robust input-action manager for Bevy. You can read the full release notes, but the highlights are:
- clear separation of buttonlike, axislike and dual-axislike inputs and actions. No more wondering what it means for an analog stick to be pressed!
- fully extensible trait-based definition of user input kinds. Ever wanted to add VR support? Touch? Electric guitar? Now you can!
- powerful axis / dual axis processors: invert controls, scale axes, create deadzones and more!
- fixed time step support: safely and reliably check the action values in
FixedUpdate
. - better action disabling: bug-free* support for 4 disabling actions at 4 different levels of granularity.
bevy_serialization_extras
crate_release
A library that allows the editing of non-reflect components via wrapper components, and serialization of these components via moonshine-save
bevy_mod_reqwest
crate_release
bevy_mod_reqwest helps when trying to use reqwest with bevy, without having to deal with async stuff, and it works on both web and and native.
It now allows reacting to errors of the http requests using observer-style callback patterns
client
// Sends the created http request
.send(reqwest_request)
// The response from the http request can be reached using an observersystem
.on_response(|trigger: Trigger<ReqwestResponseEvent>| {
let response = trigger.event();
let data = response.as_str();
let status = response.status();
// let headers = req.response_headers();
bevy::log::info!("code: {status}, data: {data:?}");
})
// In case of request error, it can be reached using an observersystem
.on_error(|trigger: Trigger<ReqwestErrorEvent>| {
let e = &trigger.event().0;
bevy::log::info!("error: {e:?}");
});
bevy_djqf
crate_release
bevy disjoint query filters (djqf) crate provides macros and a trait to generate disjoint query filters for Bevy queries. In a somewhat extreme example the following:
fn complex_system(
a_query: Query<&mut Transform, (With<A>, Without<B>, Without<C>, Without<D>, Without<E>, Without<F>, Without<G>, ..., Without<Z>)>,
b_query: Query<&mut Transform, (Without<A>, With<B>, Without<C>, Without<D>, Without<E>, Without<F>, Without<G>, ..., Without<Z>)>,
...,
z_query: Query<&mut Transform, (Without<A>, Without<B>, Without<C>, Without<D>, Without<E>, Without<F>, Without<G>, ..., With<Z>)>,
) {
// ...
}
can be reduced to
fn complex_system(
a_query: Query<&mut Transform, <A as Disjoint>::Only>,
b_query: Query<&mut Transform, <B as Disjoint>::Only>,
...,
z_query: Query<&mut Transform, <Z as Disjoint>::Only>,
) {
// ...
}
bevy_htnp
crate_release
bevy_htnp provides Hierarchical Task Network Planning.
Hierarchical Task Networks are characterized by having a concrete set of specific primitive tasks that can be compounded into a sequence that affects the world around them. Because of bevy using ECS, individual task primitives can be modeled with a simple, and standard, bevy system. This plugin handles the heavy lifting of organizing those task primitives, loading and unloading specific components associated with those primitives, and cleaning up if something goes wrong.
bevy_gizmo_log
crate_release
bevy_gizmo_log lets you render gizmos through logging:
debug!(gizmo = arrow(Vec3::ZERO, Vec3::ONE, RED));
Dogoap Initial Release - Data-Oriented GOAP for Bevy
crate_release
Dogoap is Data-oriented, Goal-oriented Action Planning for Bevy. The crate sits somewhere between "utility AI" and "Hierarchical Task Networks".
The project has two crates:
dogoap
: a data-oriented GOAP planning librarybevy_dogoap
: Bevy library that integratesdogoap
with Bevy
Why would you use dogoap
?
- If you have NPCs that have to perform tasks that depend on each other
- Move to A
- pickup item X
- move to B
- drop item X
- If you want NPCs to be able to improvise themselves to how to reach a goal (aka "emergent behavior"), after you setup the actions
Live demonstration can be found here: https://victorb.github.io/dogoap/
The first release is an MVP, so if you try it out be sure to share feedback with the crate author.
bevy_simple_text_input 0.9
crate_release
bevy_simple_text_input
gains a few features in 0.9 including integration with Observers, new navigation shortcuts, and improvements to multiple active input support.
brusher v0.1.0
crate_release
Brusher is a engine-agnostic Constructive Solid Geometry crate with a game dev focus.
Brusher started as a port of csg.js and the API is heavily inspired by Hammer, Trenchboom, GTK Radiant, etc. Eventually, it will be a full backend API that you could use to build a level editor. And if you understand those editors you should be able to grasp this API pretty easily.
Features
- Boolean Operations: union, intersect, subtract
- Knife Operation: slice solids with planes, good for bevels
lightyear 0.17.0
crate_release
Lightyear is a full-featured client-server networking library. 0.17 introduces:
Added rollback for non-networked components
Previously, only components that were networked could be affected by rollback. However there's plenty of cases where you might want to rollback non-networked client components: for example animations or sounds. You can now call app.add_rollback::<C>()
to enable rollback for a non-networked component.
Seamless entity mapping
Previously, entity-mapping was only done on the receiver. (i.e. server spawns E1
, sends it to the client who spawns E2
and maintains a mapping from E1
to E2
). The mapping wasn't applied on the send-side, which meant that the client had to map the entity manually from E2
to E1
if they wanted to send a message about E2
. Entity mapping is now correctly applied in all directions, so you don't need to worry about it anymore.
Introducing authority transfer
Lightyear now has the concept of Authority
: the peer (client or server) that is simulating the entity and sending replication updates for it. Only one peer can have authority over an entity at any given time.
The server can freely transfer authority over an entity to other peers with the EntityCommands::transfer_authority(new_owner)
command.
The Replicate
bundles automatically provide you with authority over the entity you spawn; make sure to remember to update them if you're just adding Replicate
on the server to re-broadcast a client-authoritative entity to other clients.
In the demo video, the authority that simulates the ball keeps getting swapped as the ball gets close to players.
tiny_bail 0.2
crate_release
"Bailing" is defined by this tiny_bail
as an error-handling pattern that takes the middle path between unwrap and ?:
- Compared to unwrap: Bail will return, continue, or break instead of panicking.
- Compared to ?: Bail will log or ignore the error instead of propagating it.
tiny_bail
tries to optimize the act of writing let-else conditions like this:
let Ok(x) = query.get_single() else {
warn!("query requires exactly one result");
return;
}
using macros
*or_return!(list.last_mut()) += 1;
tiny_bail 0.2 adds support for break
variation macros.
Devlogs
vlog style updates from long-term projects
ThierryBerger - Bevy's 4th Birthday
devlog
Thierry is a Bevy contributor with a Unity and mobile development background. They maintain bevy_awesome_prod which is a curated list of production Bevy projects.
Their Bevy 4th Birthday post addresses the future, the community, and the Bevy project.
bd103 - Bevy 4th Birthday
devlog
bd103 does amazing work on Bevy's CI systems, including benchmarks and automated feature flag testing.
Their post reflects on their journey in the Bevy developer community.
Educational
Tutorials, deep dives, and other information on developing Bevy applications, games, and plugins
Detects default Handle in Bevy
educational
An article about how you can detect not-initialized assets in Bevy like TextureAtlas::default()
or Texture::default()
corCTF 2024 cybersecurity capture-the-flag with Bevy
educational
The recent corCTF 2024 cybersecurity capture-the-flag competition had a reverse-engineering challenge featuring a Bevy game called corMine. This post dives into reverse-engineering Bevy including how Bevy programs get optimized by the Rust compiler.
bevy_reflect: Function reflection benchmarks authored by MrGVSV
Replace UnsafeCell<World> usage with UnsafeWorldCell in CombinatorSystem authored by ItsDoot
Fix broken bezier curve benchmark authored by mweatherley
add `SystemIdMarker` `Component` to enable filtering for `SystemId` `Entity`s authored by databasedav
Make bevy_math's `libm` feature use `libm` for all `f32`methods with unspecified precision authored by mweatherley
View filter for batch_and_prepare_render_phase authored by re0312
Update WGPU to version 22 authored by callym
reflect: implement the unique reflect rfc authored by soqb
Use `#[doc(fake_variadic)]` to improve docs readability authored by bash
bevy_reflect: Reflect remote types authored by MrGVSV
document using `ObserverState` as filter for `Observer` `Entity`s authored by databasedav
Changed `Mesh::attributes*` functions to return `MeshVertexAttribute` authored by SarthakSingh31
Add custom cursors authored by eero-lehtinen
Support more kinds of system params in buildable systems. authored by chescock
Use BinnedRenderPhase for Opaque2d authored by IceSentry
Expose max_mip_dimension and uv_offset in BloomSettings. authored by Katsutoshii
Consistency between `Wireframe2d` and `Wireframe` authored by eckz
Fix CI bench compile check authored by hymm
Sync flags in docs.yml with `package.metadata.docs.rs` authored by bash
Fix world borrow for DeferredWorld::query authored by ItsDoot
hooking up observers and clicking for ui node authored by TotalKrill
Fix window position patch authored by eero-lehtinen
Enables bevy_render feature for bevy_gizmos dependency in bevy_dev_tools authored by maslabgamer
Document private items in dev-docs authored by BD103
Remove manual `apply_deferred` in `bevy_ui` authored by alice-i-cecile
A Curve trait for general interoperation — Part II authored by mweatherley
Add example demonstrating how to enable / disable diagnostics authored by Nihilistas
Add `RenderSet::FinalCleanup` for `World::clear_entities` authored by alice-i-cecile
Add entity `.trigger()` methods authored by benfrankel
feat: add `insert_if_new` (#14397) authored by jpetkau
Making `DynamicEnum::is_dynamic()` return true authored by eckz
Fix pass_span drop panic obscuring transparent 2d render errors authored by brianreavis
Add query reborrowing authored by SkiFire13
Improve ambiguity detection example / test authored by alice-i-cecile
Skip empty archetype/table authored by re0312
Add AlphaMask2d phase authored by IceSentry
Use `map_unchanged` in reflection instead of creating a `Mut` manually. authored by chescock
apply finished animations authored by robtfm
Remove redundant `ArchetypeComponentId` lookup in `Res` and `ResMut` authored by chescock
Add `Command` and co. to prelude authored by benfrankel
Remove Component derive for DepthOfFieldMode authored by callym
Don't ask for ResMut in `queue_view_auto_exposure_pipelines` authored by alice-i-cecile
Add `Reflect` derive to `bevy_a11y::Focus` authored by callym
Switch rotation & translation in grid gizmos authored by RobWalt
Add feature requirement info to image loading docs authored by bugsweeper
Ignore `PipelineCache` ambiguities authored by alice-i-cecile
Add `try_insert_with_new` authored by nsarlin
#14143 - fix bevy_ui padding authored by Nihilistas
add `const`s to curve module functions authored by RobWalt
bevy_reflect: Store functions as `DynamicClosure<'static>` in `FunctionRegistry` authored by MrGVSV
Want to contribute to Bevy?
Here you can find two types of potential contribution: Pull Requests that might need review and Issues that might need to be worked on.
Pull Requests Opened this week
Document that impl_reflect can only be used from within bevy_reflect due to orphan rule authored by ariofrio
Fix Gizmo joint rendering in webgpu authored by akimakinai
bevy_reflect: Add `#[reflect(readonly)]` attribute authored by MrGVSV
change filter fetch to be immutable authored by hymm
Fix `arc_2d` Gizmos authored by RobWalt
niche optimization for ComponentSparseSet::SparseArray authored by re0312
Add bevy_picking sprite backend authored by jnhyatt
Make QueryFilter an unsafe trait authored by chescock
add curve utilities to create curves interpolating/easing between two values authored by RobWalt
bevy_reflect: Add `ReflectBox` to remotely reflect `Box` authored by MrGVSV
Round UI in physical coordinates authored by eero-lehtinen
Link iOS example with `rustc`, and avoid C trampoline authored by madsmtm
Add conversions between Visibility and bool authored by Stanleeeeey
Fix error when closing window in 2d_viewport_to_world example authored by ramon-bernardo
Apply clippy::use_self authored by EdJoPaTo
Fix ecs example thread_rng duplicate creation authored by EdJoPaTo
add `RepeatCurve` and `ReverseCurve` `Curve` adaptors authored by RobWalt
Remove useless `Direction` field authored by rparrett
Required Components authored by cart
Issues Opened this week
UI rounding is applied before UI scaling authored by eero-lehtinen
Allow gizmos to render behind sprites authored by laundmo
Bevy needs better support for pre-multiplied alpha textures and sprites authored by SludgePhD
UI elements randomly disappear for some frames on specific android devices authored by MarcoMeijer
`CombinatorSystem` is unsound authored by SkiFire13
Track callsites of where observers are initially triggered. authored by ItsDoot
links in bevy/crates/bevy_ecs/README.md does not exist. authored by ozqs
Docs for Observer should mention what happens if you use a bundle in the `Trigger` authored by AlfredAn
Consider what to do with wgpu_trace feature authored by IceSentry
`embedded_asset!` does not work in multi-crate workspace + release build authored by benfrankel
Footgun when chaining observer registrations on World vs App authored by ItsDoot
Adding proc_macro `#[required(TransformComponent, ...)]` for Component. authored by Jerrody
AlphaToCoverage can't be used with base_color_texture authored by barsoosayque
Add button to enable/disable interpolation for physics_in_fixed_timestep example authored by ItsDoot
Update a TextureAtlas index based on the row and column of the TextureAtlasLayout::from_grid params authored by RomainMazB
bevy_animation::animate_targets crashes with "subtract with overflow" if there is an empty curve on AnimationClip authored by hukasu
Overlapping text is broken authored by hymm
`insert_if_new` does not have a non-panicking variant authored by Jondolf
`prepare_view_upscaling_pipelines` is ambiguous with dozens of other systems authored by alice-i-cecile
VertexOutput.uv throws [invalid field accessor `uv`] after migration to 0.14.1 authored by Arrekin
Stop special-casing UI leaf-node borders authored by alice-i-cecile
BorderlessFullscreen does not cover the menu bar on macOS authored by TarekAS
2D Motion Blur authored by victorb
Add a Command to trigger observers with statically known components authored by ItsDoot
Add a method to Trigger to get a list of the triggered component IDs authored by ItsDoot
per edge border colors authored by databasedav
Enable `unused_qualifications` lint at the workspace level authored by alice-i-cecile
Consider Enabling `apply_clones` Lint authored by killercup
Expose Required Component Info Through Reflection authored by killercup
Genenerate doc comments from Required Components authored by killercup
Follow-up: Make `bevy_math`'s `ops` public (and document the methods) authored by mweatherley
Regression involving padding authored by rparrett