Add examples/helpers/* as library examples (#18288)

# Objective

Some of Bevy's examples contain boilerplate which is split out into the
`helpers` folder. This allows examples to have access to common
functionality without building into Bevy directly. However, these
helpers are themselves quite high-quality code, and we do intend for
users to read them and even use them. But, we don't list them in the
examples document, and they aren't explicitly checked in CI, only
transitively through examples which import them.

## Solution

- Added `camera_controller` and `widgets` as library examples.

## Testing

- CI

---

## Notes

- Library examples are identical to any other example, just with
`crate-type = ["lib"]` in the `Cargo.toml`. Since they are marked as
libraries, they don't require a `main` function but do require public
items to be documented.
- Library examples opens the possibility of creating examples which
don't need to be actual runnable applications. This may be more
appropriate for certain ECS examples, and allows for adding helpers
which (currently) don't have an example that needs them without them
going stale.
- I learned about this as a concept during research for `no_std`
examples, but believe it has value for Bevy outside that specific niche.

---------

Co-authored-by: mgi388 <135186256+mgi388@users.noreply.github.com>
Co-authored-by: Carter Weinberg <weinbergcarter@gmail.com>
This commit is contained in:
Zachary Harrold 2025-03-14 03:34:16 +11:00 committed by GitHub
parent 4d47de8ad8
commit 6299e3de3b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 59 additions and 0 deletions

View File

@ -4263,3 +4263,27 @@ name = "Occlusion Culling"
description = "Demonstration of Occlusion Culling" description = "Demonstration of Occlusion Culling"
category = "3D Rendering" category = "3D Rendering"
wasm = false wasm = false
[[example]]
name = "camera_controller"
path = "examples/helpers/camera_controller.rs"
doc-scrape-examples = true
crate-type = ["lib"]
[package.metadata.example.camera_controller]
name = "Camera Controller"
description = "Example Free-Cam Styled Camera Controller"
category = "Helpers"
wasm = true
[[example]]
name = "widgets"
path = "examples/helpers/widgets.rs"
doc-scrape-examples = true
crate-type = ["lib"]
[package.metadata.example.widgets]
name = "Widgets"
description = "Example UI Widgets"
category = "Helpers"
wasm = true

View File

@ -51,6 +51,7 @@ git checkout v0.4.0
- [ECS (Entity Component System)](#ecs-entity-component-system) - [ECS (Entity Component System)](#ecs-entity-component-system)
- [Games](#games) - [Games](#games)
- [Gizmos](#gizmos) - [Gizmos](#gizmos)
- [Helpers](#helpers)
- [Input](#input) - [Input](#input)
- [Math](#math) - [Math](#math)
- [Movement](#movement) - [Movement](#movement)
@ -352,6 +353,13 @@ Example | Description
[Axes](../examples/gizmos/axes.rs) | Demonstrates the function of axes gizmos [Axes](../examples/gizmos/axes.rs) | Demonstrates the function of axes gizmos
[Light Gizmos](../examples/gizmos/light_gizmos.rs) | A scene showcasing light gizmos [Light Gizmos](../examples/gizmos/light_gizmos.rs) | A scene showcasing light gizmos
## Helpers
Example | Description
--- | ---
[Camera Controller](../examples/helpers/camera_controller.rs) | Example Free-Cam Styled Camera Controller
[Widgets](../examples/helpers/widgets.rs) | Example UI Widgets
## Input ## Input
Example | Description Example | Description

View File

@ -2,6 +2,8 @@
//! To use in your own application: //! To use in your own application:
//! - Copy the code for the [`CameraControllerPlugin`] and add the plugin to your App. //! - Copy the code for the [`CameraControllerPlugin`] and add the plugin to your App.
//! - Attach the [`CameraController`] component to an entity with a [`Camera3d`]. //! - Attach the [`CameraController`] component to an entity with a [`Camera3d`].
//!
//! Unlike other examples, which demonstrate an application, this demonstrates a plugin library.
use bevy::{ use bevy::{
input::mouse::{AccumulatedMouseMotion, AccumulatedMouseScroll, MouseScrollUnit}, input::mouse::{AccumulatedMouseMotion, AccumulatedMouseScroll, MouseScrollUnit},
@ -10,6 +12,7 @@ use bevy::{
}; };
use std::{f32::consts::*, fmt}; use std::{f32::consts::*, fmt};
/// A freecam-style camera controller plugin.
pub struct CameraControllerPlugin; pub struct CameraControllerPlugin;
impl Plugin for CameraControllerPlugin { impl Plugin for CameraControllerPlugin {
@ -23,26 +26,48 @@ impl Plugin for CameraControllerPlugin {
/// it because it felt nice. /// it because it felt nice.
pub const RADIANS_PER_DOT: f32 = 1.0 / 180.0; pub const RADIANS_PER_DOT: f32 = 1.0 / 180.0;
/// Camera controller [`Component`].
#[derive(Component)] #[derive(Component)]
pub struct CameraController { pub struct CameraController {
/// Enables this [`CameraController`] when `true`.
pub enabled: bool, pub enabled: bool,
/// Indicates if this controller has been initialized by the [`CameraControllerPlugin`].
pub initialized: bool, pub initialized: bool,
/// Multiplier for pitch and yaw rotation speed.
pub sensitivity: f32, pub sensitivity: f32,
/// [`KeyCode`] for forward translation.
pub key_forward: KeyCode, pub key_forward: KeyCode,
/// [`KeyCode`] for backward translation.
pub key_back: KeyCode, pub key_back: KeyCode,
/// [`KeyCode`] for left translation.
pub key_left: KeyCode, pub key_left: KeyCode,
/// [`KeyCode`] for right translation.
pub key_right: KeyCode, pub key_right: KeyCode,
/// [`KeyCode`] for up translation.
pub key_up: KeyCode, pub key_up: KeyCode,
/// [`KeyCode`] for down translation.
pub key_down: KeyCode, pub key_down: KeyCode,
/// [`KeyCode`] to use [`run_speed`](CameraController::run_speed) instead of
/// [`walk_speed`](CameraController::walk_speed) for translation.
pub key_run: KeyCode, pub key_run: KeyCode,
/// [`MouseButton`] for grabbing the mouse focus.
pub mouse_key_cursor_grab: MouseButton, pub mouse_key_cursor_grab: MouseButton,
/// [`KeyCode`] for grabbing the keyboard focus.
pub keyboard_key_toggle_cursor_grab: KeyCode, pub keyboard_key_toggle_cursor_grab: KeyCode,
/// Multiplier for unmodified translation speed.
pub walk_speed: f32, pub walk_speed: f32,
/// Multiplier for running translation speed.
pub run_speed: f32, pub run_speed: f32,
/// Multiplier for how the mouse scroll wheel modifies [`walk_speed`](CameraController::walk_speed)
/// and [`run_speed`](CameraController::run_speed).
pub scroll_factor: f32, pub scroll_factor: f32,
/// Friction factor used to exponentially decay [`velocity`](CameraController::velocity) over time.
pub friction: f32, pub friction: f32,
/// This [`CameraController`]'s pitch rotation.
pub pitch: f32, pub pitch: f32,
/// This [`CameraController`]'s yaw rotation.
pub yaw: f32, pub yaw: f32,
/// This [`CameraController`]'s translation velocity.
pub velocity: Vec3, pub velocity: Vec3,
} }

View File

@ -1,4 +1,6 @@
//! Simple widgets for example UI. //! Simple widgets for example UI.
//!
//! Unlike other examples, which demonstrate an application, this demonstrates a plugin library.
use bevy::{ecs::system::EntityCommands, prelude::*}; use bevy::{ecs::system::EntityCommands, prelude::*};