Skip to main content

Vec2

Struct Vec2 

Source
#[repr(C)]
pub struct Vec2 { pub x: f32, pub y: f32, }
Expand description

A 2-dimensional vector.

Fields§

§x: f32§y: f32

Implementations§

Source§

impl Vec2

Source

pub const ZERO: Vec2

All zeroes.

Source

pub const ONE: Vec2

All ones.

Source

pub const NEG_ONE: Vec2

All negative ones.

Source

pub const MIN: Vec2

All f32::MIN.

Source

pub const MAX: Vec2

All f32::MAX.

Source

pub const NAN: Vec2

All f32::NAN.

Source

pub const INFINITY: Vec2

All f32::INFINITY.

Source

pub const NEG_INFINITY: Vec2

All f32::NEG_INFINITY.

Source

pub const X: Vec2

A unit vector pointing along the positive X axis.

Source

pub const Y: Vec2

A unit vector pointing along the positive Y axis.

Source

pub const NEG_X: Vec2

A unit vector pointing along the negative X axis.

Source

pub const NEG_Y: Vec2

A unit vector pointing along the negative Y axis.

Source

pub const AXES: [Vec2; 2]

The unit axes.

Source

pub const USES_CORE_SIMD: bool = false

Vec2 uses Rust Portable SIMD

Source

pub const USES_NEON: bool = false

Vec2 uses Arm NEON

Source

pub const USES_SCALAR_MATH: bool = true

Vec2 uses scalar math

Source

pub const USES_SSE2: bool = false

Vec2 uses Intel SSE2

Source

pub const USES_WASM_SIMD: bool = false

Vec2 uses WebAssembly 128-bit SIMD

Source

pub const USES_WASM32_SIMD: bool = false

👎Deprecated since 0.31.0:

Renamed to USES_WASM_SIMD

Source

pub const fn new(x: f32, y: f32) -> Vec2

Creates a new vector.

Examples found in repository?
examples/2d/rotation.rs (line 5)
5const BOUNDS: Vec2 = Vec2::new(1200.0, 640.0);
More examples
Hide additional examples
examples/animation/easing_functions.rs (line 18)
18const EXTENT: Vec2 = Vec2::new(1172.0, 520.0);
19const PLOT_SIZE: Vec2 = Vec2::splat(80.0);
20
21fn setup(mut commands: Commands) {
22    commands.spawn(Camera2d);
23
24    let text_font = TextFont {
25        font_size: FontSize::Px(10.0),
26        ..default()
27    };
28
29    let chunks = [
30        // "In" row
31        EaseFunction::SineIn,
32        EaseFunction::QuadraticIn,
33        EaseFunction::CubicIn,
34        EaseFunction::QuarticIn,
35        EaseFunction::QuinticIn,
36        EaseFunction::SmoothStepIn,
37        EaseFunction::SmootherStepIn,
38        EaseFunction::CircularIn,
39        EaseFunction::ExponentialIn,
40        EaseFunction::ElasticIn,
41        EaseFunction::BackIn,
42        EaseFunction::BounceIn,
43        // "Out" row
44        EaseFunction::SineOut,
45        EaseFunction::QuadraticOut,
46        EaseFunction::CubicOut,
47        EaseFunction::QuarticOut,
48        EaseFunction::QuinticOut,
49        EaseFunction::SmoothStepOut,
50        EaseFunction::SmootherStepOut,
51        EaseFunction::CircularOut,
52        EaseFunction::ExponentialOut,
53        EaseFunction::ElasticOut,
54        EaseFunction::BackOut,
55        EaseFunction::BounceOut,
56        // "InOut" row
57        EaseFunction::SineInOut,
58        EaseFunction::QuadraticInOut,
59        EaseFunction::CubicInOut,
60        EaseFunction::QuarticInOut,
61        EaseFunction::QuinticInOut,
62        EaseFunction::SmoothStep,
63        EaseFunction::SmootherStep,
64        EaseFunction::CircularInOut,
65        EaseFunction::ExponentialInOut,
66        EaseFunction::ElasticInOut,
67        EaseFunction::BackInOut,
68        EaseFunction::BounceInOut,
69        // "Other" row
70        EaseFunction::Linear,
71        EaseFunction::Steps(4, JumpAt::End),
72        EaseFunction::Steps(4, JumpAt::Start),
73        EaseFunction::Steps(4, JumpAt::Both),
74        EaseFunction::Steps(4, JumpAt::None),
75        EaseFunction::Elastic(50.0),
76    ]
77    .chunks(COLS);
78
79    let max_rows = chunks.clone().count();
80
81    let half_extent = EXTENT / 2.;
82    let half_size = PLOT_SIZE / 2.;
83
84    for (row, functions) in chunks.enumerate() {
85        for (col, function) in functions.iter().enumerate() {
86            let color = Hsla::hsl(col as f32 / COLS as f32 * 360.0, 0.8, 0.75).into();
87            commands.spawn((
88                EaseFunctionPlot(*function, color),
89                Transform::from_xyz(
90                    -half_extent.x + EXTENT.x / (COLS - 1) as f32 * col as f32,
91                    half_extent.y - EXTENT.y / (max_rows - 1) as f32 * row as f32,
92                    0.0,
93                ),
94                children![
95                    (
96                        Sprite::from_color(color, Vec2::splat(5.0)),
97                        Transform::from_xyz(half_size.x + 5.0, -half_size.y, 0.0),
98                    ),
99                    (
100                        Sprite::from_color(color, Vec2::splat(4.0)),
101                        Transform::from_xyz(-half_size.x, -half_size.y, 0.0),
102                    ),
103                    (
104                        Text2d(format!("{function:?}")),
105                        text_font.clone(),
106                        TextColor(color),
107                        Transform::from_xyz(0.0, -half_size.y - 15.0, 0.0),
108                    )
109                ],
110            ));
111        }
112    }
113    commands.spawn((
114        Text::default(),
115        Node {
116            position_type: PositionType::Absolute,
117            top: px(12),
118            left: px(12),
119            ..default()
120        },
121    ));
122}
123
124fn display_curves(
125    mut gizmos: Gizmos,
126    ease_functions: Query<(&EaseFunctionPlot, &Transform, &Children)>,
127    mut transforms: Query<&mut Transform, Without<EaseFunctionPlot>>,
128    mut ui_text: Single<&mut Text>,
129    time: Res<Time>,
130) {
131    let samples = 100;
132    let duration = 2.5;
133    let time_margin = 0.5;
134
135    let now = ((time.elapsed_secs() % (duration + time_margin * 2.0) - time_margin) / duration)
136        .clamp(0.0, 1.0);
137
138    ui_text.0 = format!("Progress: {now:.2}");
139
140    for (EaseFunctionPlot(function, color), transform, children) in &ease_functions {
141        let center = transform.translation.xy();
142        let half_size = PLOT_SIZE / 2.0;
143
144        // Draw a box around the curve
145        gizmos.linestrip_2d(
146            [
147                center + half_size,
148                center + half_size * Vec2::new(-1., 1.),
149                center + half_size * Vec2::new(-1., -1.),
150                center + half_size * Vec2::new(1., -1.),
151                center + half_size,
152            ],
153            color.darker(0.4),
154        );
155
156        // Draw the curve
157        let f = EasingCurve::new(0.0, 1.0, *function);
158        let drawn_curve = f
159            .by_ref()
160            .graph()
161            .map(|(x, y)| center - half_size + Vec2::new(x, y) * PLOT_SIZE);
162        gizmos.curve_2d(
163            &drawn_curve,
164            drawn_curve.domain().spaced_points(samples).unwrap(),
165            *color,
166        );
167
168        // Show progress along the curve for the current time
169        let y = f.sample(now).unwrap() * PLOT_SIZE.y;
170        transforms.get_mut(children[0]).unwrap().translation.y = -half_size.y + y;
171        transforms.get_mut(children[1]).unwrap().translation =
172            -half_size.extend(0.0) + Vec3::new(now * PLOT_SIZE.x, y, 0.0);
173
174        // Show horizontal bar at y value
175        gizmos.linestrip_2d(
176            [
177                center - half_size + Vec2::Y * y,
178                center - half_size + Vec2::new(PLOT_SIZE.x, y),
179            ],
180            color.darker(0.2),
181        );
182    }
183}
examples/showcase/breakout.rs (line 14)
14const PADDLE_SIZE: Vec2 = Vec2::new(120.0, 20.0);
15const GAP_BETWEEN_PADDLE_AND_FLOOR: f32 = 60.0;
16const PADDLE_SPEED: f32 = 500.0;
17// How close can the paddle get to the wall
18const PADDLE_PADDING: f32 = 10.0;
19
20// We set the z-value of the ball to 1 so it renders on top in the case of overlapping sprites.
21const BALL_STARTING_POSITION: Vec3 = Vec3::new(0.0, -50.0, 1.0);
22const BALL_DIAMETER: f32 = 30.;
23const BALL_SPEED: f32 = 400.0;
24const INITIAL_BALL_DIRECTION: Vec2 = Vec2::new(0.5, -0.5);
25
26const WALL_THICKNESS: f32 = 10.0;
27// x coordinates
28const LEFT_WALL: f32 = -450.;
29const RIGHT_WALL: f32 = 450.;
30// y coordinates
31const BOTTOM_WALL: f32 = -300.;
32const TOP_WALL: f32 = 300.;
33
34const BRICK_SIZE: Vec2 = Vec2::new(100., 30.);
35// These values are exact
36const GAP_BETWEEN_PADDLE_AND_BRICKS: f32 = 270.0;
37const GAP_BETWEEN_BRICKS: f32 = 5.0;
38// These values are lower bounds, as the number of bricks is computed
39const GAP_BETWEEN_BRICKS_AND_CEILING: f32 = 20.0;
40const GAP_BETWEEN_BRICKS_AND_SIDES: f32 = 20.0;
41
42const SCOREBOARD_FONT_SIZE: FontSize = FontSize::Px(33.0);
43const SCOREBOARD_TEXT_PADDING: Val = Val::Px(5.0);
44
45const BACKGROUND_COLOR: Color = Color::srgb(0.9, 0.9, 0.9);
46const PADDLE_COLOR: Color = Color::srgb(0.3, 0.3, 0.7);
47const BALL_COLOR: Color = Color::srgb(1.0, 0.5, 0.5);
48const BRICK_COLOR: Color = Color::srgb(0.5, 0.5, 1.0);
49const WALL_COLOR: Color = Color::srgb(0.8, 0.8, 0.8);
50const TEXT_COLOR: Color = Color::srgb(0.5, 0.5, 1.0);
51const SCORE_COLOR: Color = Color::srgb(1.0, 0.5, 0.5);
52
53fn main() {
54    App::new()
55        .add_plugins(DefaultPlugins)
56        .add_plugins(
57            stepping::SteppingPlugin::default()
58                .add_schedule(Update)
59                .at(percent(35), percent(50)),
60        )
61        .insert_resource(Score(0))
62        .insert_resource(ClearColor(BACKGROUND_COLOR))
63        .add_systems(Startup, setup)
64        // Add our simulation systems to the update schedule
65        // which is called once per frame.
66        .add_systems(
67            Update,
68            (apply_velocity, move_paddle, check_for_collisions)
69                // `chain`ing systems together runs them in order
70                .chain(),
71        )
72        .add_systems(Update, update_scoreboard)
73        .add_observer(play_collision_sound)
74        .run();
75}
76
77#[derive(Component)]
78struct Paddle;
79
80#[derive(Component)]
81struct Ball;
82
83#[derive(Component, Deref, DerefMut)]
84struct Velocity(Vec2);
85
86#[derive(Event)]
87struct BallCollided;
88
89#[derive(Component)]
90struct Brick;
91
92#[derive(Resource, Deref)]
93struct CollisionSound(Handle<AudioSource>);
94
95// Default must be implemented to define this as a required component for the Wall component below
96#[derive(Component, Default)]
97struct Collider;
98
99// This is a collection of the components that define a "Wall" in our game
100#[derive(Component)]
101#[require(Sprite, Transform, Collider)]
102struct Wall;
103
104/// Which side of the arena is this wall located on?
105enum WallLocation {
106    Left,
107    Right,
108    Bottom,
109    Top,
110}
111
112impl WallLocation {
113    /// Location of the *center* of the wall, used in `transform.translation()`
114    fn position(&self) -> Vec2 {
115        match self {
116            WallLocation::Left => Vec2::new(LEFT_WALL, 0.),
117            WallLocation::Right => Vec2::new(RIGHT_WALL, 0.),
118            WallLocation::Bottom => Vec2::new(0., BOTTOM_WALL),
119            WallLocation::Top => Vec2::new(0., TOP_WALL),
120        }
121    }
122
123    /// (x, y) dimensions of the wall, used in `transform.scale()`
124    fn size(&self) -> Vec2 {
125        let arena_height = TOP_WALL - BOTTOM_WALL;
126        let arena_width = RIGHT_WALL - LEFT_WALL;
127        // Make sure we haven't messed up our constants
128        assert!(arena_height > 0.0);
129        assert!(arena_width > 0.0);
130
131        match self {
132            WallLocation::Left | WallLocation::Right => {
133                Vec2::new(WALL_THICKNESS, arena_height + WALL_THICKNESS)
134            }
135            WallLocation::Bottom | WallLocation::Top => {
136                Vec2::new(arena_width + WALL_THICKNESS, WALL_THICKNESS)
137            }
138        }
139    }
140}
141
142impl Wall {
143    // This "builder method" allows us to reuse logic across our wall entities,
144    // making our code easier to read and less prone to bugs when we change the logic
145    // Notice the use of Sprite and Transform alongside Wall, overwriting the default values defined for the required components
146    fn new(location: WallLocation) -> (Wall, Sprite, Transform) {
147        (
148            Wall,
149            Sprite::from_color(WALL_COLOR, Vec2::ONE),
150            Transform {
151                // We need to convert our Vec2 into a Vec3, by giving it a z-coordinate
152                // This is used to determine the order of our sprites
153                translation: location.position().extend(0.0),
154                // The z-scale of 2D objects must always be 1.0,
155                // or their ordering will be affected in surprising ways.
156                // See https://github.com/bevyengine/bevy/issues/4149
157                scale: location.size().extend(1.0),
158                ..default()
159            },
160        )
161    }
162}
163
164// This resource tracks the game's score
165#[derive(Resource, Deref, DerefMut)]
166struct Score(usize);
167
168#[derive(Component)]
169struct ScoreboardUi;
170
171// Add the game's entities to our world
172fn setup(
173    mut commands: Commands,
174    mut meshes: ResMut<Assets<Mesh>>,
175    mut materials: ResMut<Assets<ColorMaterial>>,
176    asset_server: Res<AssetServer>,
177) {
178    // Camera
179    commands.spawn(Camera2d);
180
181    // Sound
182    let ball_collision_sound = asset_server.load("sounds/breakout_collision.ogg");
183    commands.insert_resource(CollisionSound(ball_collision_sound));
184
185    // Paddle
186    let paddle_y = BOTTOM_WALL + GAP_BETWEEN_PADDLE_AND_FLOOR;
187
188    commands.spawn((
189        Sprite::from_color(PADDLE_COLOR, Vec2::ONE),
190        Transform {
191            translation: Vec3::new(0.0, paddle_y, 0.0),
192            scale: PADDLE_SIZE.extend(1.0),
193            ..default()
194        },
195        Paddle,
196        Collider,
197    ));
198
199    // Ball
200    commands.spawn((
201        Mesh2d(meshes.add(Circle::default())),
202        MeshMaterial2d(materials.add(BALL_COLOR)),
203        Transform::from_translation(BALL_STARTING_POSITION)
204            .with_scale(Vec2::splat(BALL_DIAMETER).extend(1.)),
205        Ball,
206        Velocity(INITIAL_BALL_DIRECTION.normalize() * BALL_SPEED),
207    ));
208
209    // Scoreboard
210    commands.spawn((
211        Text::new("Score: "),
212        TextFont {
213            font_size: SCOREBOARD_FONT_SIZE,
214            ..default()
215        },
216        TextColor(TEXT_COLOR),
217        ScoreboardUi,
218        Node {
219            position_type: PositionType::Absolute,
220            top: SCOREBOARD_TEXT_PADDING,
221            left: SCOREBOARD_TEXT_PADDING,
222            ..default()
223        },
224        children![(
225            TextSpan::default(),
226            TextFont {
227                font_size: SCOREBOARD_FONT_SIZE,
228                ..default()
229            },
230            TextColor(SCORE_COLOR),
231        )],
232    ));
233
234    // Walls
235    commands.spawn(Wall::new(WallLocation::Left));
236    commands.spawn(Wall::new(WallLocation::Right));
237    commands.spawn(Wall::new(WallLocation::Bottom));
238    commands.spawn(Wall::new(WallLocation::Top));
239
240    // Bricks
241    let total_width_of_bricks = (RIGHT_WALL - LEFT_WALL) - 2. * GAP_BETWEEN_BRICKS_AND_SIDES;
242    let bottom_edge_of_bricks = paddle_y + GAP_BETWEEN_PADDLE_AND_BRICKS;
243    let total_height_of_bricks = TOP_WALL - bottom_edge_of_bricks - GAP_BETWEEN_BRICKS_AND_CEILING;
244
245    assert!(total_width_of_bricks > 0.0);
246    assert!(total_height_of_bricks > 0.0);
247
248    // Given the space available, compute how many rows and columns of bricks we can fit
249    let n_columns = (total_width_of_bricks / (BRICK_SIZE.x + GAP_BETWEEN_BRICKS)).floor() as usize;
250    let n_rows = (total_height_of_bricks / (BRICK_SIZE.y + GAP_BETWEEN_BRICKS)).floor() as usize;
251    let n_vertical_gaps = n_columns - 1;
252
253    // Because we need to round the number of columns,
254    // the space on the top and sides of the bricks only captures a lower bound, not an exact value
255    let center_of_bricks = (LEFT_WALL + RIGHT_WALL) / 2.0;
256    let left_edge_of_bricks = center_of_bricks
257        // Space taken up by the bricks
258        - (n_columns as f32 / 2.0 * BRICK_SIZE.x)
259        // Space taken up by the gaps
260        - n_vertical_gaps as f32 / 2.0 * GAP_BETWEEN_BRICKS;
261
262    // In Bevy, the `translation` of an entity describes the center point,
263    // not its bottom-left corner
264    let offset_x = left_edge_of_bricks + BRICK_SIZE.x / 2.;
265    let offset_y = bottom_edge_of_bricks + BRICK_SIZE.y / 2.;
266
267    for row in 0..n_rows {
268        for column in 0..n_columns {
269            let brick_position = Vec2::new(
270                offset_x + column as f32 * (BRICK_SIZE.x + GAP_BETWEEN_BRICKS),
271                offset_y + row as f32 * (BRICK_SIZE.y + GAP_BETWEEN_BRICKS),
272            );
273
274            // brick
275            commands.spawn((
276                Sprite {
277                    color: BRICK_COLOR,
278                    ..default()
279                },
280                Transform {
281                    translation: brick_position.extend(0.0),
282                    scale: Vec3::new(BRICK_SIZE.x, BRICK_SIZE.y, 1.0),
283                    ..default()
284                },
285                Brick,
286                Collider,
287            ));
288        }
289    }
290}
examples/math/render_primitives.rs (line 154)
153const RECTANGLE: Rectangle = Rectangle {
154    half_size: Vec2::new(SMALL_2D, BIG_2D),
155};
156const CUBOID: Cuboid = Cuboid {
157    half_size: Vec3::new(BIG_3D, SMALL_3D, BIG_3D),
158};
159
160const CIRCLE: Circle = Circle { radius: BIG_2D };
161const SPHERE: Sphere = Sphere { radius: BIG_3D };
162
163const ELLIPSE: Ellipse = Ellipse {
164    half_size: Vec2::new(BIG_2D, SMALL_2D),
165};
166
167const TRIANGLE_2D: Triangle2d = Triangle2d {
168    vertices: [
169        Vec2::new(BIG_2D, 0.0),
170        Vec2::new(0.0, BIG_2D),
171        Vec2::new(-BIG_2D, 0.0),
172    ],
173};
174
175const TRIANGLE_3D: Triangle3d = Triangle3d {
176    vertices: [
177        Vec3::new(BIG_3D, 0.0, 0.0),
178        Vec3::new(0.0, BIG_3D, 0.0),
179        Vec3::new(-BIG_3D, 0.0, 0.0),
180    ],
181};
182
183const PLANE_2D: Plane2d = Plane2d { normal: Dir2::Y };
184const PLANE_3D: Plane3d = Plane3d {
185    normal: Dir3::Y,
186    half_size: Vec2::new(BIG_3D, BIG_3D),
187};
188
189const LINE_2D: Line2d = Line2d { direction: Dir2::X };
190const LINE_3D: Line3d = Line3d { direction: Dir3::X };
191
192const SEGMENT_2D: Segment2d = Segment2d {
193    vertices: [Vec2::new(-BIG_2D / 2., 0.), Vec2::new(BIG_2D / 2., 0.)],
194};
195
196const SEGMENT_3D: Segment3d = Segment3d {
197    vertices: [
198        Vec3::new(-BIG_3D / 2., 0., 0.),
199        Vec3::new(BIG_3D / 2., 0., 0.),
200    ],
201};
202
203const POLYLINE_2D_VERTICES: [Vec2; 4] = [
204    Vec2::new(-BIG_2D, -SMALL_2D),
205    Vec2::new(-SMALL_2D, SMALL_2D),
206    Vec2::new(SMALL_2D, -SMALL_2D),
207    Vec2::new(BIG_2D, SMALL_2D),
208];
209
210const POLYLINE_3D_VERTICES: [Vec3; 4] = [
211    Vec3::new(-BIG_3D, -SMALL_3D, -SMALL_3D),
212    Vec3::new(SMALL_3D, SMALL_3D, 0.0),
213    Vec3::new(-SMALL_3D, -SMALL_3D, 0.0),
214    Vec3::new(BIG_3D, SMALL_3D, SMALL_3D),
215];
216
217const CONVEX_POLYGON_VERTICES: [Vec2; 5] = [
218    Vec2::new(-BIG_2D, -SMALL_2D),
219    Vec2::new(BIG_2D, -SMALL_2D),
220    Vec2::new(BIG_2D, SMALL_2D),
221    Vec2::new(BIG_2D / 2.0, SMALL_2D * 2.0),
222    Vec2::new(-BIG_2D, SMALL_2D),
223];
224
225const REGULAR_POLYGON: RegularPolygon = RegularPolygon {
226    circumcircle: Circle { radius: BIG_2D },
227    sides: 5,
228};
229
230const CAPSULE_2D: Capsule2d = Capsule2d {
231    radius: SMALL_2D,
232    half_length: SMALL_2D,
233};
234
235const CAPSULE_3D: Capsule3d = Capsule3d {
236    radius: SMALL_3D,
237    half_length: SMALL_3D,
238};
239
240const CYLINDER: Cylinder = Cylinder {
241    radius: SMALL_3D,
242    half_height: SMALL_3D,
243};
244
245const CONE: Cone = Cone {
246    radius: BIG_3D,
247    height: BIG_3D,
248};
249
250const CONICAL_FRUSTUM: ConicalFrustum = ConicalFrustum {
251    radius_top: BIG_3D,
252    radius_bottom: SMALL_3D,
253    height: BIG_3D,
254};
255
256const ANNULUS: Annulus = Annulus {
257    inner_circle: Circle { radius: SMALL_2D },
258    outer_circle: Circle { radius: BIG_2D },
259};
260
261const TORUS: Torus = Torus {
262    minor_radius: SMALL_3D / 2.0,
263    major_radius: SMALL_3D * 1.5,
264};
265
266const TETRAHEDRON: Tetrahedron = Tetrahedron {
267    vertices: [
268        Vec3::new(-BIG_3D, 0.0, 0.0),
269        Vec3::new(BIG_3D, 0.0, 0.0),
270        Vec3::new(0.0, 0.0, -BIG_3D * 1.67),
271        Vec3::new(0.0, BIG_3D * 1.67, -BIG_3D * 0.5),
272    ],
273};
274
275const ARC: Arc2d = Arc2d {
276    radius: BIG_2D,
277    half_angle: std::f32::consts::FRAC_PI_4,
278};
279
280const CIRCULAR_SECTOR: CircularSector = CircularSector {
281    arc: Arc2d {
282        radius: BIG_2D,
283        half_angle: std::f32::consts::FRAC_PI_4,
284    },
285};
286
287const CIRCULAR_SEGMENT: CircularSegment = CircularSegment {
288    arc: Arc2d {
289        radius: BIG_2D,
290        half_angle: std::f32::consts::FRAC_PI_4,
291    },
292};
293
294fn setup_cameras(mut commands: Commands) {
295    let start_in_2d = true;
296    let make_camera = |is_active| Camera {
297        is_active,
298        ..Default::default()
299    };
300
301    commands.spawn((Camera2d, make_camera(start_in_2d)));
302
303    commands.spawn((
304        Camera3d::default(),
305        make_camera(!start_in_2d),
306        Transform::from_xyz(0.0, 10.0, 0.0).looking_at(Vec3::ZERO, Vec3::Z),
307    ));
308}
309
310fn setup_ambient_light(mut ambient_light: ResMut<GlobalAmbientLight>) {
311    ambient_light.brightness = 50.0;
312}
313
314fn setup_lights(mut commands: Commands) {
315    commands.spawn((
316        PointLight {
317            intensity: 5000.0,
318            ..default()
319        },
320        Transform::from_translation(Vec3::new(-LEFT_RIGHT_OFFSET_3D, 2.0, 0.0))
321            .looking_at(Vec3::new(-LEFT_RIGHT_OFFSET_3D, 0.0, 0.0), Vec3::Y),
322    ));
323}
324
325/// Marker component for header text
326#[derive(Debug, Clone, Component, Default, Reflect)]
327pub struct HeaderText;
328
329/// Marker component for header node
330#[derive(Debug, Clone, Component, Default, Reflect)]
331pub struct HeaderNode;
332
333fn update_active_cameras(
334    state: Res<State<CameraActive>>,
335    camera_2d: Single<(Entity, &mut Camera), With<Camera2d>>,
336    camera_3d: Single<(Entity, &mut Camera), (With<Camera3d>, Without<Camera2d>)>,
337    mut text: Query<&mut UiTargetCamera, With<HeaderNode>>,
338) {
339    let (entity_2d, mut cam_2d) = camera_2d.into_inner();
340    let (entity_3d, mut cam_3d) = camera_3d.into_inner();
341    let is_camera_2d_active = matches!(*state.get(), CameraActive::Dim2);
342
343    cam_2d.is_active = is_camera_2d_active;
344    cam_3d.is_active = !is_camera_2d_active;
345
346    let active_camera = if is_camera_2d_active {
347        entity_2d
348    } else {
349        entity_3d
350    };
351
352    text.iter_mut().for_each(|mut target_camera| {
353        *target_camera = UiTargetCamera(active_camera);
354    });
355}
356
357fn switch_cameras(current: Res<State<CameraActive>>, mut next: ResMut<NextState<CameraActive>>) {
358    let next_state = match current.get() {
359        CameraActive::Dim2 => CameraActive::Dim3,
360        CameraActive::Dim3 => CameraActive::Dim2,
361    };
362    next.set(next_state);
363}
364
365fn setup_text(mut commands: Commands, cameras: Query<(Entity, &Camera)>) {
366    let active_camera = cameras
367        .iter()
368        .find_map(|(entity, camera)| camera.is_active.then_some(entity))
369        .expect("run condition ensures existence");
370    commands.spawn((
371        HeaderNode,
372        Node {
373            justify_self: JustifySelf::Center,
374            top: px(5),
375            ..Default::default()
376        },
377        UiTargetCamera(active_camera),
378        children![(
379            Text::default(),
380            HeaderText,
381            TextLayout::justify(Justify::Center),
382            children![
383                TextSpan::new("Primitive: "),
384                TextSpan(format!("{text}", text = PrimitiveSelected::default())),
385                TextSpan::new("\n\n"),
386                TextSpan::new(
387                    "Press 'C' to switch between 2D and 3D mode\n\
388                    Press 'Up' or 'Down' to switch to the next/previous primitive",
389                ),
390                TextSpan::new("\n\n"),
391                TextSpan::new("(If nothing is displayed, there's no rendering support yet)",),
392            ]
393        )],
394    ));
395}
396
397fn update_text(
398    primitive_state: Res<State<PrimitiveSelected>>,
399    header: Query<Entity, With<HeaderText>>,
400    mut writer: TextUiWriter,
401) {
402    let new_text = format!("{text}", text = primitive_state.get());
403    header.iter().for_each(|header_text| {
404        if let Some(mut text) = writer.get_text(header_text, 2) {
405            (*text).clone_from(&new_text);
406        };
407    });
408}
409
410fn switch_to_next_primitive(
411    current: Res<State<PrimitiveSelected>>,
412    mut next: ResMut<NextState<PrimitiveSelected>>,
413) {
414    let next_state = current.get().next();
415    next.set(next_state);
416}
417
418fn switch_to_previous_primitive(
419    current: Res<State<PrimitiveSelected>>,
420    mut next: ResMut<NextState<PrimitiveSelected>>,
421) {
422    let next_state = current.get().previous();
423    next.set(next_state);
424}
425
426fn in_mode(active: CameraActive) -> impl Fn(Res<State<CameraActive>>) -> bool {
427    move |state| *state.get() == active
428}
429
430fn draw_gizmos_2d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time: Res<Time>) {
431    const POSITION: Vec2 = Vec2::new(-LEFT_RIGHT_OFFSET_2D, 0.0);
432    let angle = time.elapsed_secs();
433    let isometry = Isometry2d::new(POSITION, Rot2::radians(angle));
434    let color = Color::WHITE;
435
436    #[expect(
437        clippy::match_same_arms,
438        reason = "Certain primitives don't have any 2D rendering support yet."
439    )]
440    match state.get() {
441        PrimitiveSelected::RectangleAndCuboid => {
442            gizmos.primitive_2d(&RECTANGLE, isometry, color);
443        }
444        PrimitiveSelected::CircleAndSphere => {
445            gizmos.primitive_2d(&CIRCLE, isometry, color);
446        }
447        PrimitiveSelected::Ellipse => drop(gizmos.primitive_2d(&ELLIPSE, isometry, color)),
448        PrimitiveSelected::Triangle => gizmos.primitive_2d(&TRIANGLE_2D, isometry, color),
449        PrimitiveSelected::Plane => gizmos.primitive_2d(&PLANE_2D, isometry, color),
450        PrimitiveSelected::Line => drop(gizmos.primitive_2d(&LINE_2D, isometry, color)),
451        PrimitiveSelected::Segment => {
452            drop(gizmos.primitive_2d(&SEGMENT_2D, isometry, color));
453        }
454        PrimitiveSelected::Polyline => gizmos.primitive_2d(
455            &Polyline2d {
456                vertices: POLYLINE_2D_VERTICES.to_vec(),
457            },
458            isometry,
459            color,
460        ),
461        PrimitiveSelected::ConvexPolygon => gizmos.primitive_2d(
462            &Polygon::from(ConvexPolygon::new(CONVEX_POLYGON_VERTICES).unwrap()),
463            isometry,
464            color,
465        ),
466        PrimitiveSelected::Polygon => gizmos.primitive_2d(
467            &Polygon {
468                vertices: vec![
469                    Vec2::new(-BIG_2D, -SMALL_2D),
470                    Vec2::new(BIG_2D, -SMALL_2D),
471                    Vec2::new(BIG_2D, SMALL_2D),
472                    Vec2::new(0.0, 0.0),
473                    Vec2::new(-BIG_2D, SMALL_2D),
474                ],
475            },
476            isometry,
477            color,
478        ),
479        PrimitiveSelected::RegularPolygon => {
480            gizmos.primitive_2d(&REGULAR_POLYGON, isometry, color);
481        }
482        PrimitiveSelected::Capsule => gizmos.primitive_2d(&CAPSULE_2D, isometry, color),
483        PrimitiveSelected::Cylinder => {}
484        PrimitiveSelected::Cone => {}
485        PrimitiveSelected::ConicalFrustum => {}
486        PrimitiveSelected::Torus => drop(gizmos.primitive_2d(&ANNULUS, isometry, color)),
487        PrimitiveSelected::Tetrahedron => {}
488        PrimitiveSelected::Arc => gizmos.primitive_2d(&ARC, isometry, color),
489        PrimitiveSelected::CircularSector => {
490            gizmos.primitive_2d(&CIRCULAR_SECTOR, isometry, color);
491        }
492        PrimitiveSelected::CircularSegment => {
493            gizmos.primitive_2d(&CIRCULAR_SEGMENT, isometry, color);
494        }
495    }
496}
examples/animation/color_animation.rs (line 75)
73fn spawn_curve_sprite<T: CurveColor>(commands: &mut Commands, y: f32, points: [T; 4]) {
74    commands.spawn((
75        Sprite::sized(Vec2::new(75., 75.)),
76        Transform::from_xyz(0., y, 0.),
77        Curve(CubicBezier::new([points]).to_curve().unwrap()),
78    ));
79}
80
81fn spawn_mixed_sprite<T: MixedColor>(commands: &mut Commands, y: f32, colors: [T; 4]) {
82    commands.spawn((
83        Transform::from_xyz(0., y, 0.),
84        Sprite::sized(Vec2::new(75., 75.)),
85        Mixed(colors),
86    ));
87}
examples/ecs/observers.rs (lines 74-77)
72    fn random(rand: &mut ChaCha8Rng) -> Self {
73        Mine {
74            pos: Vec2::new(
75                (rand.random::<f32>() - 0.5) * 1200.0,
76                (rand.random::<f32>() - 0.5) * 600.0,
77            ),
78            size: 4.0 + rand.random::<f32>() * 16.0,
79        }
80    }
Source

pub const fn splat(v: f32) -> Vec2

Creates a vector with all elements set to v.

Examples found in repository?
examples/animation/easing_functions.rs (line 19)
19const PLOT_SIZE: Vec2 = Vec2::splat(80.0);
20
21fn setup(mut commands: Commands) {
22    commands.spawn(Camera2d);
23
24    let text_font = TextFont {
25        font_size: FontSize::Px(10.0),
26        ..default()
27    };
28
29    let chunks = [
30        // "In" row
31        EaseFunction::SineIn,
32        EaseFunction::QuadraticIn,
33        EaseFunction::CubicIn,
34        EaseFunction::QuarticIn,
35        EaseFunction::QuinticIn,
36        EaseFunction::SmoothStepIn,
37        EaseFunction::SmootherStepIn,
38        EaseFunction::CircularIn,
39        EaseFunction::ExponentialIn,
40        EaseFunction::ElasticIn,
41        EaseFunction::BackIn,
42        EaseFunction::BounceIn,
43        // "Out" row
44        EaseFunction::SineOut,
45        EaseFunction::QuadraticOut,
46        EaseFunction::CubicOut,
47        EaseFunction::QuarticOut,
48        EaseFunction::QuinticOut,
49        EaseFunction::SmoothStepOut,
50        EaseFunction::SmootherStepOut,
51        EaseFunction::CircularOut,
52        EaseFunction::ExponentialOut,
53        EaseFunction::ElasticOut,
54        EaseFunction::BackOut,
55        EaseFunction::BounceOut,
56        // "InOut" row
57        EaseFunction::SineInOut,
58        EaseFunction::QuadraticInOut,
59        EaseFunction::CubicInOut,
60        EaseFunction::QuarticInOut,
61        EaseFunction::QuinticInOut,
62        EaseFunction::SmoothStep,
63        EaseFunction::SmootherStep,
64        EaseFunction::CircularInOut,
65        EaseFunction::ExponentialInOut,
66        EaseFunction::ElasticInOut,
67        EaseFunction::BackInOut,
68        EaseFunction::BounceInOut,
69        // "Other" row
70        EaseFunction::Linear,
71        EaseFunction::Steps(4, JumpAt::End),
72        EaseFunction::Steps(4, JumpAt::Start),
73        EaseFunction::Steps(4, JumpAt::Both),
74        EaseFunction::Steps(4, JumpAt::None),
75        EaseFunction::Elastic(50.0),
76    ]
77    .chunks(COLS);
78
79    let max_rows = chunks.clone().count();
80
81    let half_extent = EXTENT / 2.;
82    let half_size = PLOT_SIZE / 2.;
83
84    for (row, functions) in chunks.enumerate() {
85        for (col, function) in functions.iter().enumerate() {
86            let color = Hsla::hsl(col as f32 / COLS as f32 * 360.0, 0.8, 0.75).into();
87            commands.spawn((
88                EaseFunctionPlot(*function, color),
89                Transform::from_xyz(
90                    -half_extent.x + EXTENT.x / (COLS - 1) as f32 * col as f32,
91                    half_extent.y - EXTENT.y / (max_rows - 1) as f32 * row as f32,
92                    0.0,
93                ),
94                children![
95                    (
96                        Sprite::from_color(color, Vec2::splat(5.0)),
97                        Transform::from_xyz(half_size.x + 5.0, -half_size.y, 0.0),
98                    ),
99                    (
100                        Sprite::from_color(color, Vec2::splat(4.0)),
101                        Transform::from_xyz(-half_size.x, -half_size.y, 0.0),
102                    ),
103                    (
104                        Text2d(format!("{function:?}")),
105                        text_font.clone(),
106                        TextColor(color),
107                        Transform::from_xyz(0.0, -half_size.y - 15.0, 0.0),
108                    )
109                ],
110            ));
111        }
112    }
113    commands.spawn((
114        Text::default(),
115        Node {
116            position_type: PositionType::Absolute,
117            top: px(12),
118            left: px(12),
119            ..default()
120        },
121    ));
122}
More examples
Hide additional examples
examples/ecs/delayed_commands.rs (line 19)
19const SQUARE_SIZE: Vec2 = Vec2::splat(45.0);
examples/2d/sprite_tile.rs (line 47)
41fn animate(mut sprites: Query<&mut Sprite>, mut state: ResMut<AnimationState>, time: Res<Time>) {
42    if state.current >= state.max || state.current <= state.min {
43        state.speed = -state.speed;
44    };
45    state.current += state.speed * time.delta_secs();
46    for mut sprite in &mut sprites {
47        sprite.custom_size = Some(Vec2::splat(state.current));
48    }
49}
examples/3d/mixed_lighting.rs (line 89)
86static LIGHTMAPS: [(&str, Rect); 5] = [
87    (
88        "Plane",
89        uv_rect_opengl(Vec2::splat(0.026), Vec2::splat(0.710)),
90    ),
91    (
92        "SheenChair_fabric",
93        uv_rect_opengl(vec2(0.7864, 0.02377), vec2(0.1910, 0.1912)),
94    ),
95    (
96        "SheenChair_label",
97        uv_rect_opengl(vec2(0.275, -0.016), vec2(0.858, 0.486)),
98    ),
99    (
100        "SheenChair_metal",
101        uv_rect_opengl(vec2(0.998, 0.506), vec2(-0.029, -0.067)),
102    ),
103    (
104        "SheenChair_wood",
105        uv_rect_opengl(vec2(0.787, 0.257), vec2(0.179, 0.177)),
106    ),
107];
108
109static SPHERE_UV_RECT: Rect = uv_rect_opengl(vec2(0.788, 0.484), Vec2::splat(0.062));
examples/3d/ssr.rs (line 330)
324fn spawn_metallic_base(
325    commands: &mut Commands,
326    meshes: &mut Assets<Mesh>,
327    standard_materials: &mut Assets<StandardMaterial>,
328) {
329    commands.spawn((
330        Mesh3d(meshes.add(Plane3d::new(Vec3::Y, Vec2::splat(1.0)))),
331        MeshMaterial3d(standard_materials.add(StandardMaterial {
332            base_color: Color::from(bevy::color::palettes::css::DARK_GRAY),
333            metallic: 1.0,
334            perceptual_roughness: 0.3,
335            ..default()
336        })),
337        Transform::from_scale(Vec3::splat(100.0)),
338        MetallicBaseModel,
339        Visibility::Hidden,
340    ));
341}
342
343// Spawns the non-metallic base.
344fn spawn_non_metallic_base(
345    commands: &mut Commands,
346    meshes: &mut Assets<Mesh>,
347    standard_materials: &mut Assets<StandardMaterial>,
348) {
349    commands.spawn((
350        Mesh3d(meshes.add(Plane3d::new(Vec3::Y, Vec2::splat(1.0)))),
351        MeshMaterial3d(standard_materials.add(StandardMaterial {
352            base_color: Color::from(bevy::color::palettes::css::RED),
353            metallic: 0.0,
354            perceptual_roughness: 0.2,
355            ..default()
356        })),
357        Transform::from_scale(Vec3::splat(100.0)),
358        RedPlaneBaseModel,
359        Visibility::Hidden,
360    ));
361}
362
363// Spawns the water plane.
364fn spawn_water(
365    commands: &mut Commands,
366    asset_server: &AssetServer,
367    meshes: &mut Assets<Mesh>,
368    water_materials: &mut Assets<ExtendedMaterial<StandardMaterial, Water>>,
369) {
370    commands.spawn((
371        Mesh3d(meshes.add(Plane3d::new(Vec3::Y, Vec2::splat(1.0)))),
372        MeshMaterial3d(
373            water_materials.add(ExtendedMaterial {
374                base: StandardMaterial {
375                    base_color: BLACK.into(),
376                    perceptual_roughness: 0.09,
377                    ..default()
378                },
379                extension: Water {
380                    normals: asset_server
381                        .load_builder()
382                        .with_settings::<ImageLoaderSettings>(|settings| {
383                            settings.is_srgb = false;
384                            settings.sampler = ImageSampler::Descriptor(ImageSamplerDescriptor {
385                                address_mode_u: ImageAddressMode::Repeat,
386                                address_mode_v: ImageAddressMode::Repeat,
387                                mag_filter: ImageFilterMode::Linear,
388                                min_filter: ImageFilterMode::Linear,
389                                ..default()
390                            });
391                        })
392                        .load("textures/water_normals.png"),
393                    // These water settings are just random values to create some
394                    // variety.
395                    settings: WaterSettings {
396                        octave_vectors: [
397                            vec4(0.080, 0.059, 0.073, -0.062),
398                            vec4(0.153, 0.138, -0.149, -0.195),
399                        ],
400                        octave_scales: vec4(1.0, 2.1, 7.9, 14.9) * 5.0,
401                        octave_strengths: vec4(0.16, 0.18, 0.093, 0.044),
402                    },
403                },
404            }),
405        ),
406        Transform::from_scale(Vec3::splat(100.0)),
407        WaterModel,
408    ));
409}
examples/shader_advanced/render_depth_to_texture.rs (line 223)
217fn spawn_plane(
218    commands: &mut Commands,
219    meshes: &mut Assets<Mesh>,
220    show_depth_texture_materials: &mut Assets<ShowDepthTextureMaterial>,
221    demo_depth_texture: &DemoDepthTexture,
222) {
223    let plane_handle = meshes.add(Plane3d::new(Vec3::Z, Vec2::splat(2.0)));
224    let show_depth_texture_material = show_depth_texture_materials.add(ShowDepthTextureMaterial {
225        depth_texture: Some(demo_depth_texture.0.clone()),
226    });
227    commands.spawn((
228        Mesh3d(plane_handle),
229        MeshMaterial3d(show_depth_texture_material),
230        Transform::from_xyz(10.0, 4.0, 0.0).with_scale(Vec3::splat(2.5)),
231    ));
232}
Source

pub fn map<F>(self, f: F) -> Vec2
where F: Fn(f32) -> f32,

Returns a vector containing each element of self modified by a mapping function f.

Source

pub fn select(mask: BVec2, if_true: Vec2, if_false: Vec2) -> Vec2

Creates a vector from the elements in if_true and if_false, selecting which to use for each element of self.

A true element in the mask uses the corresponding element from if_true, and false uses the element from if_false.

Source

pub const fn from_array(a: [f32; 2]) -> Vec2

Creates a new vector from an array.

Source

pub const fn to_array(&self) -> [f32; 2]

Converts self to [x, y]

Source

pub const fn from_slice(slice: &[f32]) -> Vec2

Creates a vector from the first 2 values in slice.

§Panics

Panics if slice is less than 2 elements long.

Source

pub fn write_to_slice(self, slice: &mut [f32])

Writes the elements of self to the first 2 elements in slice.

§Panics

Panics if slice is less than 2 elements long.

Source

pub const fn extend(self, z: f32) -> Vec3

Creates a 3D vector from self and the given z value.

Examples found in repository?
examples/3d/clustered_decals.rs (line 342)
338fn calculate_initial_decal_transform(start: Vec3, looking_at: Vec3, size: Vec2) -> Transform {
339    let direction = looking_at - start;
340    let center = start + direction * 0.5;
341    Transform::from_translation(center)
342        .with_scale((size * 0.5).extend(direction.length()))
343        .looking_to(direction, Vec3::Y)
344}
More examples
Hide additional examples
examples/math/cubic_splines.rs (line 176)
169fn draw_curve(curve: Res<Curve>, mut gizmos: Gizmos) {
170    let Some(ref curve) = curve.0 else {
171        return;
172    };
173    // Scale resolution with curve length so it doesn't degrade as the length increases.
174    let resolution = 100 * curve.segments().len();
175    gizmos.linestrip(
176        curve.iter_positions(resolution).map(|pt| pt.extend(0.0)),
177        Color::srgb(1.0, 1.0, 1.0),
178    );
179}
examples/ecs/fallible_params.rs (line 129)
124fn move_targets(mut enemies: Populated<(&mut Transform, &mut Enemy)>, time: Res<Time>) {
125    for (mut transform, mut target) in &mut *enemies {
126        target.rotation += target.rotation_speed * time.delta_secs();
127        transform.rotation = Quat::from_rotation_z(target.rotation);
128        let offset = transform.right() * target.radius;
129        transform.translation = target.origin.extend(0.0) + offset;
130    }
131}
examples/3d/reflection_probes.rs (line 355)
343fn rotate_camera(
344    time: Res<Time>,
345    mut camera_query: Query<&mut Transform, With<Camera3d>>,
346    app_status: Res<AppStatus>,
347) {
348    if !app_status.rotating {
349        return;
350    }
351
352    for mut transform in camera_query.iter_mut() {
353        transform.translation = Vec2::from_angle(time.delta_secs() * PI / 5.0)
354            .rotate(transform.translation.xz())
355            .extend(transform.translation.y)
356            .xzy();
357        transform.look_at(Vec3::ZERO, Vec3::Y);
358    }
359}
examples/3d/irradiance_volumes.rs (line 361)
349fn rotate_camera(
350    mut camera_query: Query<&mut Transform, With<Camera3d>>,
351    time: Res<Time>,
352    app_status: Res<AppStatus>,
353) {
354    if !app_status.rotating {
355        return;
356    }
357
358    for mut transform in camera_query.iter_mut() {
359        transform.translation = Vec2::from_angle(ROTATION_SPEED * time.delta_secs())
360            .rotate(transform.translation.xz())
361            .extend(transform.translation.y)
362            .xzy();
363        transform.look_at(Vec3::ZERO, Vec3::Y);
364    }
365}
examples/2d/dynamic_mip_generation.rs (line 438)
427fn animate_image_scale(
428    mut animated_images_query: Query<&mut Transform, With<AnimatedImage>>,
429    windows_query: Query<&Window, With<PrimaryWindow>>,
430    app_status: Res<AppStatus>,
431    time: Res<Time>,
432) {
433    let window_size = windows_query.iter().next().unwrap().size();
434    let animated_mesh_size = app_status.animated_mesh_size(window_size);
435
436    for mut animated_image_transform in &mut animated_images_query {
437        animated_image_transform.scale =
438            animated_mesh_size.extend(1.0) * triangle_wave(time.elapsed_secs(), ANIMATION_PERIOD);
439    }
440}
441
442/// Evaluates a [triangle wave] with the given wavelength.
443///
444/// This is used as part of [`animate_image_scale`], to derive the scale from
445/// the current elapsed time.
446///
447/// [triangle wave]: https://en.wikipedia.org/wiki/Triangle_wave#Definition
448fn triangle_wave(time: f32, wavelength: f32) -> f32 {
449    2.0 * ops::abs(time / wavelength - ops::floor(time / wavelength + 0.5))
450}
451
452/// Adds the top mipmap level of the image to [`MipGenerationJobs`].
453///
454/// Note that this must run in the render world, not the main world, as
455/// [`MipGenerationJobs`] is a resource that exists in the former. Consequently,
456/// it must use [`Extract`] to access main world resources.
457fn extract_mipmap_source_image(
458    mipmap_source_image: Extract<Res<MipmapSourceImage>>,
459    app_status: Extract<Res<AppStatus>>,
460    mut mip_generation_jobs: ResMut<MipGenerationJobs>,
461) {
462    if app_status.enable_mip_generation == EnableMipGeneration::On {
463        mip_generation_jobs.add(MIP_GENERATION_PHASE_ID, mipmap_source_image.id());
464    }
465}
466
467/// Updates the widgets at the bottom of the screen to reflect the settings that
468/// the user has chosen.
469fn update_radio_buttons(
470    mut widgets: Query<
471        (
472            Entity,
473            Option<&mut BackgroundColor>,
474            Has<Text>,
475            &WidgetClickSender<AppSetting>,
476        ),
477        Or<(With<RadioButton>, With<RadioButtonText>)>,
478    >,
479    app_status: Res<AppStatus>,
480    mut writer: TextUiWriter,
481) {
482    for (entity, image, has_text, sender) in widgets.iter_mut() {
483        let selected = match **sender {
484            AppSetting::RegenerateTopMipLevel => continue,
485            AppSetting::EnableMipGeneration(enable_mip_generation) => {
486                enable_mip_generation == app_status.enable_mip_generation
487            }
488            AppSetting::ImageWidth(image_width) => image_width == app_status.image_width,
489            AppSetting::ImageHeight(image_height) => image_height == app_status.image_height,
490        };
491
492        if let Some(mut bg_color) = image {
493            widgets::update_ui_radio_button(&mut bg_color, selected);
494        }
495        if has_text {
496            widgets::update_ui_radio_button_text(entity, &mut writer, selected);
497        }
498    }
499}
500
501/// Handles a request from the user to change application settings via the UI.
502///
503/// This also handles clicks on the "Regenerate Top Mip Level" button.
504fn handle_app_setting_change(
505    mut events: MessageReader<WidgetClickEvent<AppSetting>>,
506    mut app_status: ResMut<AppStatus>,
507    mut regenerate_image_message_writer: MessageWriter<RegenerateImage>,
508) {
509    for event in events.read() {
510        // If this is a setting, update the setting. Fall through if, in
511        // addition to updating the setting, we need to regenerate the image.
512        match **event {
513            AppSetting::EnableMipGeneration(enable_mip_generation) => {
514                app_status.enable_mip_generation = enable_mip_generation;
515                continue;
516            }
517
518            AppSetting::RegenerateTopMipLevel => {}
519            AppSetting::ImageWidth(image_size) => app_status.image_width = image_size,
520            AppSetting::ImageHeight(image_size) => app_status.image_height = image_size,
521        }
522
523        // Schedule the image to be regenerated.
524        regenerate_image_message_writer.write(RegenerateImage);
525    }
526}
527
528/// Handles resize events for the window.
529///
530/// Resizing the window invalidates the image and repositions all image views.
531/// (Regenerating the image isn't strictly necessary, but it's simplest to have
532/// a single function that both regenerates the image and recreates the image
533/// views.)
534fn handle_window_resize_events(
535    mut events: MessageReader<WindowResized>,
536    mut regenerate_image_message_writer: MessageWriter<RegenerateImage>,
537) {
538    for _ in events.read() {
539        regenerate_image_message_writer.write(RegenerateImage);
540    }
541}
542
543/// Recreates the image, as well as all views that show the image, when a
544/// [`RegenerateImage`] message is received.
545///
546/// The views that show the image consist of the animated mesh on the left side
547/// of the window and the column of mipmap level views on the right side of the
548/// window.
549fn regenerate_image_when_requested(
550    mut commands: Commands,
551    image_views_query: Query<Entity, With<ImageView>>,
552    windows_query: Query<&Window, With<PrimaryWindow>>,
553    app_assets: Res<AppAssets>,
554    mut app_status: ResMut<AppStatus>,
555    mut images: ResMut<Assets<Image>>,
556    mut single_mip_level_materials: ResMut<Assets<SingleMipLevelMaterial>>,
557    mut color_materials: ResMut<Assets<ColorMaterial>>,
558    mut message_reader: MessageReader<RegenerateImage>,
559) {
560    // Only do this at most once per frame, or else the despawn logic below will
561    // get confused.
562    if message_reader.read().count() == 0 {
563        return;
564    }
565
566    // Despawn all entities that show the image.
567    for entity in image_views_query.iter() {
568        commands.entity(entity).despawn();
569    }
570
571    // Regenerate the image.
572    let image_handle = app_status.regenerate_mipmap_source_image(&mut commands, &mut images);
573
574    // Respawn the animated image view on the left side of the window.
575    spawn_animated_mesh(
576        &mut commands,
577        &app_status,
578        &app_assets,
579        &windows_query,
580        &mut color_materials,
581        &image_handle,
582    );
583
584    // Respawn the column of mip level views on the right side of the window.
585    spawn_mip_level_views(
586        &mut commands,
587        &app_status,
588        &app_assets,
589        &windows_query,
590        &mut single_mip_level_materials,
591        &image_handle,
592    );
593}
594
595/// Spawns the image on the left that continually changes scale.
596///
597/// Continually changing scale effectively cycles though each mip level,
598/// demonstrating the difference between mip level images being present and mip
599/// level image being absent.
600fn spawn_animated_mesh(
601    commands: &mut Commands,
602    app_status: &AppStatus,
603    app_assets: &AppAssets,
604    windows_query: &Query<&Window, With<PrimaryWindow>>,
605    color_materials: &mut Assets<ColorMaterial>,
606    image_handle: &Handle<Image>,
607) {
608    let window_size = windows_query.iter().next().unwrap().size();
609    let animated_mesh_area_size = app_status.animated_mesh_area_size(window_size);
610    let animated_mesh_size = app_status.animated_mesh_size(window_size);
611
612    commands.spawn((
613        Mesh2d(app_assets.rectangle.clone()),
614        MeshMaterial2d(color_materials.add(ColorMaterial {
615            texture: Some(image_handle.clone()),
616            ..default()
617        })),
618        Transform::from_translation(
619            (animated_mesh_area_size * 0.5 - window_size * 0.5).extend(0.0),
620        )
621        .with_scale(animated_mesh_size.extend(1.0)),
622        AnimatedImage,
623        ImageView,
624    ));
625}
626
627/// Creates the column on the right side of the window that displays each mip
628/// level by itself.
629fn spawn_mip_level_views(
630    commands: &mut Commands,
631    app_status: &AppStatus,
632    app_assets: &AppAssets,
633    windows_query: &Query<&Window, With<PrimaryWindow>>,
634    single_mip_level_materials: &mut Assets<SingleMipLevelMaterial>,
635    image_handle: &Handle<Image>,
636) {
637    let window_size = windows_query.iter().next().unwrap().size();
638
639    // Calculate the placement of the column of mipmap levels.
640    let max_slice_size = app_status.max_mip_slice_size(window_size);
641    let y_origin = app_status.vertical_mip_slice_origin(window_size);
642    let y_spacing = app_status.vertical_mip_slice_spacing(window_size);
643    let x_origin = app_status.horizontal_mip_slice_origin(window_size);
644
645    for (mip_level, mip_size) in MipmapSizeIterator::new(app_status).enumerate() {
646        let y_center = y_origin - y_spacing * mip_level as f32;
647
648        // Size each image to fit its container, preserving aspect ratio.
649        let mut slice_size = mip_size.as_vec2();
650        let ratios = max_slice_size / slice_size;
651        let slice_scale = ratios.x.min(ratios.y).min(1.0);
652        slice_size *= slice_scale;
653
654        // Spawn the image. Use the `SingleMipLevelMaterial` with its custom
655        // shader so that only the mip level in question is displayed.
656        commands.spawn((
657            Mesh2d(app_assets.rectangle.clone()),
658            MeshMaterial2d(single_mip_level_materials.add(SingleMipLevelMaterial {
659                mip_level: mip_level as u32,
660                texture: image_handle.clone(),
661            })),
662            Transform::from_xyz(x_origin, y_center, 0.0).with_scale(slice_size.extend(1.0)),
663            ImageView,
664        ));
665
666        // Display a label to the side.
667        commands.spawn((
668            Text2d::new(format!(
669                "Level {}\n{}×{}",
670                mip_level, mip_size.x, mip_size.y
671            )),
672            app_assets.text_font.clone(),
673            TextLayout::justify(Justify::Center),
674            Text2dShadow::default(),
675            Transform::from_xyz(x_origin - max_slice_size.x * 0.5 - 64.0, y_center, 0.0),
676            ImageView,
677        ));
678    }
679}
Source

pub fn with_x(self, x: f32) -> Vec2

Creates a 2D vector from self with the given value of x.

Source

pub fn with_y(self, y: f32) -> Vec2

Creates a 2D vector from self with the given value of y.

Source

pub fn dot(self, rhs: Vec2) -> f32

Computes the dot product of self and rhs.

Examples found in repository?
examples/2d/rotation.rs (line 211)
195fn rotate_to_player_system(
196    time: Res<Time>,
197    mut query: Query<(&RotateToPlayer, &mut Transform), Without<Player>>,
198    player_transform: Single<&Transform, With<Player>>,
199) {
200    // Get the player translation in 2D
201    let player_translation = player_transform.translation.xy();
202
203    for (config, mut enemy_transform) in &mut query {
204        // Get the enemy ship forward vector in 2D (already unit length)
205        let enemy_forward = (enemy_transform.rotation * Vec3::Y).xy();
206
207        // Get the vector from the enemy ship to the player ship in 2D and normalize it.
208        let to_player = (player_translation - enemy_transform.translation.xy()).normalize();
209
210        // Get the dot product between the enemy forward vector and the direction to the player.
211        let forward_dot_player = enemy_forward.dot(to_player);
212
213        // If the dot product is approximately 1.0 then the enemy is already facing the player and
214        // we can early out.
215        if (forward_dot_player - 1.0).abs() < f32::EPSILON {
216            continue;
217        }
218
219        // Get the right vector of the enemy ship in 2D (already unit length)
220        let enemy_right = (enemy_transform.rotation * Vec3::X).xy();
221
222        // Get the dot product of the enemy right vector and the direction to the player ship.
223        // If the dot product is negative them we need to rotate counter clockwise, if it is
224        // positive we need to rotate clockwise. Note that `copysign` will still return 1.0 if the
225        // dot product is 0.0 (because the player is directly behind the enemy, so perpendicular
226        // with the right vector).
227        let right_dot_player = enemy_right.dot(to_player);
228
229        // Determine the sign of rotation from the right dot player. We need to negate the sign
230        // here as the 2D bevy co-ordinate system rotates around +Z, which is pointing out of the
231        // screen. Due to the right hand rule, positive rotation around +Z is counter clockwise and
232        // negative is clockwise.
233        let rotation_sign = -f32::copysign(1.0, right_dot_player);
234
235        // Limit rotation so we don't overshoot the target. We need to convert our dot product to
236        // an angle here so we can get an angle of rotation to clamp against.
237        let max_angle = ops::acos(forward_dot_player.clamp(-1.0, 1.0)); // Clamp acos for safety
238
239        // Calculate angle of rotation with limit
240        let rotation_angle =
241            rotation_sign * (config.rotation_speed * time.delta_secs()).min(max_angle);
242
243        // Rotate the enemy to face the player
244        enemy_transform.rotate_z(rotation_angle);
245    }
246}
Source

pub fn dot_into_vec(self, rhs: Vec2) -> Vec2

Returns a vector where every component is the dot product of self and rhs.

Source

pub fn min(self, rhs: Vec2) -> Vec2

Returns a vector containing the minimum values for each element of self and rhs.

In other words this computes [min(x, rhs.x), min(self.y, rhs.y), ..].

NaN propogation does not follow IEEE 754-2008 semantics for minNum and may differ on different SIMD architectures.

Examples found in repository?
examples/math/custom_primitives.rs (line 449)
435    fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
436        let isometry = isometry.into();
437
438        // The center of the circle at the center of the right wing of the heart
439        let circle_center = isometry.rotation * Vec2::new(self.radius, 0.0);
440        // The maximum X and Y positions of the two circles of the wings of the heart.
441        let max_circle = circle_center.abs() + Vec2::splat(self.radius);
442        // Since the two circles of the heart are mirrored around the origin, the minimum position is the negative of the maximum.
443        let min_circle = -max_circle;
444
445        // The position of the tip at the bottom of the heart
446        let tip_position = isometry.rotation * Vec2::new(0.0, -self.radius * (1. + SQRT_2));
447
448        Aabb2d {
449            min: isometry.translation + min_circle.min(tip_position),
450            max: isometry.translation + max_circle.max(tip_position),
451        }
452    }
Source

pub fn max(self, rhs: Vec2) -> Vec2

Returns a vector containing the maximum values for each element of self and rhs.

In other words this computes [max(self.x, rhs.x), max(self.y, rhs.y), ..].

NaN propogation does not follow IEEE 754-2008 semantics for maxNum and may differ on different SIMD architectures.

Examples found in repository?
examples/math/custom_primitives.rs (line 450)
435    fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
436        let isometry = isometry.into();
437
438        // The center of the circle at the center of the right wing of the heart
439        let circle_center = isometry.rotation * Vec2::new(self.radius, 0.0);
440        // The maximum X and Y positions of the two circles of the wings of the heart.
441        let max_circle = circle_center.abs() + Vec2::splat(self.radius);
442        // Since the two circles of the heart are mirrored around the origin, the minimum position is the negative of the maximum.
443        let min_circle = -max_circle;
444
445        // The position of the tip at the bottom of the heart
446        let tip_position = isometry.rotation * Vec2::new(0.0, -self.radius * (1. + SQRT_2));
447
448        Aabb2d {
449            min: isometry.translation + min_circle.min(tip_position),
450            max: isometry.translation + max_circle.max(tip_position),
451        }
452    }
More examples
Hide additional examples
examples/ui/scroll_and_overflow/drag_to_scroll.rs (line 49)
22fn setup(mut commands: Commands) {
23    let w = 60;
24    let h = 40;
25
26    commands.spawn(Camera2d);
27    commands.insert_resource(UiScale(0.5));
28
29    commands
30        .spawn((
31            Node {
32                width: percent(100),
33                height: percent(100),
34                overflow: Overflow::scroll(),
35                ..Default::default()
36            },
37            ScrollPosition(Vec2::ZERO),
38            ScrollableNode,
39            ScrollStart(Vec2::ZERO),
40        ))
41        .observe(
42            |drag: On<Pointer<Drag>>,
43             ui_scale: Res<UiScale>,
44             mut scroll_position_query: Query<
45                (&mut ScrollPosition, &ScrollStart),
46                With<ScrollableNode>,
47            >| {
48                if let Ok((mut scroll_position, start)) = scroll_position_query.single_mut() {
49                    scroll_position.0 = (start.0 - drag.distance / ui_scale.0).max(Vec2::ZERO);
50                }
51            },
52        )
53        .observe(
54            |_: On<Pointer<DragStart>>,
55             mut scroll_position_query: Query<
56                (&ComputedNode, &mut ScrollStart),
57                With<ScrollableNode>,
58            >| {
59                if let Ok((computed_node, mut start)) = scroll_position_query.single_mut() {
60                    start.0 = computed_node.scroll_position * computed_node.inverse_scale_factor;
61                }
62            },
63        )
64        .with_children(|commands| {
65            commands
66                .spawn((
67                    Node {
68                        display: Display::Grid,
69                        grid_template_rows: RepeatedGridTrack::px(w as i32, 100.),
70                        grid_template_columns: RepeatedGridTrack::px(h as i32, 100.),
71                        ..default()
72                    },
73                    Pickable {
74                        is_hoverable: false,
75                        should_block_lower: true,
76                    }
77                ))
78                .with_children(|commands| {
79                    for y in 0..h {
80                        for x in 0..w {
81                            let tile_color = if (x + y) % 2 == 1 {
82                                let hue = ((x as f32 / w as f32) * 270.0)
83                                    + ((y as f32 / h as f32) * 90.0);
84                                Color::hsl(hue, 1., 0.5)
85                            } else {
86                                Color::BLACK
87                            };
88                            commands.spawn((
89                                Node {
90                                    grid_row: GridPlacement::start(y + 1),
91                                    grid_column: GridPlacement::start(x + 1),
92                                    ..default()
93                                },
94                                Pickable {
95                                    should_block_lower: false,
96                                    is_hoverable: true,
97                                },
98                                TileColor(tile_color),
99                                BackgroundColor(tile_color),
100                            ))
101                            .observe(|over: On<Pointer<Over>>, mut query: Query<&mut BackgroundColor>,| {
102                                if let Ok(mut background_color) = query.get_mut(over.entity) {
103                                    background_color.0 = RED.into();
104                                }
105                            })
106                            .observe(|out: On<Pointer<Out>>, mut query: Query<(&mut BackgroundColor, &TileColor)>| {
107                                if let Ok((mut background_color, tile_color)) = query.get_mut(out.entity) {
108                                    background_color.0 = tile_color.0;
109                                }
110                            });
111                        }
112                    }
113                });
114        });
115}
Source

pub fn clamp(self, min: Vec2, max: Vec2) -> Vec2

Component-wise clamping of values, similar to f32::clamp.

Each element in min must be less-or-equal to the corresponding element in max.

NaN propogation does not follow IEEE 754-2008 semantics and may differ on different SIMD architectures.

§Panics

Will panic if min is greater than max when glam_assert is enabled.

Examples found in repository?
examples/ui/ui_transform.rs (line 59)
34fn button_system(
35    mut interaction_query: Query<
36        (
37            &Interaction,
38            &mut BackgroundColor,
39            Option<&RotateButton>,
40            Option<&ScaleButton>,
41        ),
42        (Changed<Interaction>, With<Button>),
43    >,
44    mut rotator_query: Query<&mut UiTransform, With<TargetNode>>,
45) {
46    for (interaction, mut color, maybe_rotate, maybe_scale) in &mut interaction_query {
47        match *interaction {
48            Interaction::Pressed => {
49                *color = PRESSED_BUTTON.into();
50                if let Some(step) = maybe_rotate {
51                    for mut transform in rotator_query.iter_mut() {
52                        transform.rotation *= step.0;
53                    }
54                }
55                if let Some(step) = maybe_scale {
56                    for mut transform in rotator_query.iter_mut() {
57                        transform.scale += step.0;
58                        transform.scale =
59                            transform.scale.clamp(Vec2::splat(0.25), Vec2::splat(3.0));
60                    }
61                }
62            }
63            Interaction::Hovered => {
64                *color = HOVERED_BUTTON.into();
65            }
66            Interaction::None => {
67                *color = NORMAL_BUTTON.into();
68            }
69        }
70    }
71}
Source

pub fn min_element(self) -> f32

Returns the horizontal minimum of self.

In other words this computes min(x, y, ..).

NaN propogation does not follow IEEE 754-2008 semantics and may differ on different SIMD architectures.

Source

pub fn max_element(self) -> f32

Returns the horizontal maximum of self.

In other words this computes max(x, y, ..).

NaN propogation does not follow IEEE 754-2008 semantics and may differ on different SIMD architectures.

Source

pub fn min_position(self) -> usize

Returns the index of the first minimum element of self.

Source

pub fn max_position(self) -> usize

Returns the index of the first maximum element of self.

Source

pub fn element_sum(self) -> f32

Returns the sum of all elements of self.

In other words, this computes self.x + self.y + ...

Source

pub fn element_product(self) -> f32

Returns the product of all elements of self.

In other words, this computes self.x * self.y * ...

Source

pub fn cmpeq(self, rhs: Vec2) -> BVec2

Returns a vector mask containing the result of a == comparison for each element of self and rhs.

In other words, this computes [self.x == rhs.x, self.y == rhs.y, ..] for all elements.

Source

pub fn cmpne(self, rhs: Vec2) -> BVec2

Returns a vector mask containing the result of a != comparison for each element of self and rhs.

In other words this computes [self.x != rhs.x, self.y != rhs.y, ..] for all elements.

Source

pub fn cmpge(self, rhs: Vec2) -> BVec2

Returns a vector mask containing the result of a >= comparison for each element of self and rhs.

In other words this computes [self.x >= rhs.x, self.y >= rhs.y, ..] for all elements.

Source

pub fn cmpgt(self, rhs: Vec2) -> BVec2

Returns a vector mask containing the result of a > comparison for each element of self and rhs.

In other words this computes [self.x > rhs.x, self.y > rhs.y, ..] for all elements.

Source

pub fn cmple(self, rhs: Vec2) -> BVec2

Returns a vector mask containing the result of a <= comparison for each element of self and rhs.

In other words this computes [self.x <= rhs.x, self.y <= rhs.y, ..] for all elements.

Source

pub fn cmplt(self, rhs: Vec2) -> BVec2

Returns a vector mask containing the result of a < comparison for each element of self and rhs.

In other words this computes [self.x < rhs.x, self.y < rhs.y, ..] for all elements.

Source

pub fn abs(self) -> Vec2

Returns a vector containing the absolute value of each element of self.

Examples found in repository?
examples/math/custom_primitives.rs (line 441)
435    fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
436        let isometry = isometry.into();
437
438        // The center of the circle at the center of the right wing of the heart
439        let circle_center = isometry.rotation * Vec2::new(self.radius, 0.0);
440        // The maximum X and Y positions of the two circles of the wings of the heart.
441        let max_circle = circle_center.abs() + Vec2::splat(self.radius);
442        // Since the two circles of the heart are mirrored around the origin, the minimum position is the negative of the maximum.
443        let min_circle = -max_circle;
444
445        // The position of the tip at the bottom of the heart
446        let tip_position = isometry.rotation * Vec2::new(0.0, -self.radius * (1. + SQRT_2));
447
448        Aabb2d {
449            min: isometry.translation + min_circle.min(tip_position),
450            max: isometry.translation + max_circle.max(tip_position),
451        }
452    }
Source

pub fn signum(self) -> Vec2

Returns a vector with elements representing the sign of self.

  • 1.0 if the number is positive, +0.0 or INFINITY
  • -1.0 if the number is negative, -0.0 or NEG_INFINITY
  • NAN if the number is NAN
Source

pub fn copysign(self, rhs: Vec2) -> Vec2

Returns a vector with signs of rhs and the magnitudes of self.

Source

pub fn is_negative_bitmask(self) -> u32

Returns a bitmask with the lowest 2 bits set to the sign bits from the elements of self.

A negative element results in a 1 bit and a positive element in a 0 bit. Element x goes into the first lowest bit, element y into the second, etc.

An element is negative if it has a negative sign, including -0.0, NaNs with negative sign bit and negative infinity.

Source

pub fn is_finite(self) -> bool

Returns true if, and only if, all elements are finite. If any element is either NaN, positive or negative infinity, this will return false.

Source

pub fn is_finite_mask(self) -> BVec2

Performs is_finite on each element of self, returning a vector mask of the results.

In other words, this computes [x.is_finite(), y.is_finite(), ...].

Source

pub fn is_nan(self) -> bool

Returns true if any elements are NaN.

Source

pub fn is_nan_mask(self) -> BVec2

Performs is_nan on each element of self, returning a vector mask of the results.

In other words, this computes [x.is_nan(), y.is_nan(), ...].

Source

pub fn length(self) -> f32

Computes the length of self.

Examples found in repository?
examples/showcase/desk_toy.rs (line 260)
246fn start_drag(
247    mut commands: Commands,
248    cursor_world_pos: Res<CursorWorldPos>,
249    bevy_logo_transform: Single<&Transform, With<BevyLogo>>,
250) {
251    // If the cursor is not within the primary window skip this system
252    let Some(cursor_world_pos) = cursor_world_pos.0 else {
253        return;
254    };
255
256    // Get the offset from the cursor to the Bevy logo sprite
257    let drag_offset = bevy_logo_transform.translation.truncate() - cursor_world_pos;
258
259    // If the cursor is within the Bevy logo radius start the drag operation and remember the offset of the cursor from the origin
260    if drag_offset.length() < BEVY_LOGO_RADIUS {
261        commands.insert_resource(DragOperation(drag_offset));
262    }
263}
264
265/// Stop the current drag operation
266fn end_drag(mut commands: Commands) {
267    commands.remove_resource::<DragOperation>();
268}
269
270/// Drag the Bevy logo
271fn drag(
272    drag_offset: Res<DragOperation>,
273    cursor_world_pos: Res<CursorWorldPos>,
274    time: Res<Time>,
275    mut bevy_transform: Single<&mut Transform, With<BevyLogo>>,
276    mut q_pupils: Query<&mut Pupil>,
277) {
278    // If the cursor is not within the primary window skip this system
279    let Some(cursor_world_pos) = cursor_world_pos.0 else {
280        return;
281    };
282
283    // Calculate the new translation of the Bevy logo based on cursor and drag offset
284    let new_translation = cursor_world_pos + drag_offset.0;
285
286    // Calculate how fast we are dragging the Bevy logo (unit/second)
287    let drag_velocity =
288        (new_translation - bevy_transform.translation.truncate()) / time.delta_secs();
289
290    // Update the translation of Bevy logo transform to new translation
291    bevy_transform.translation = new_translation.extend(bevy_transform.translation.z);
292
293    // Add the cursor drag velocity in the opposite direction to each pupil.
294    // Remember pupils are using local coordinates to move. So when the Bevy logo moves right they need to move left to
295    // simulate inertia, otherwise they will move fixed to the parent.
296    for mut pupil in &mut q_pupils {
297        pupil.velocity -= drag_velocity;
298    }
299}
300
301/// Quit when the user right clicks the Bevy logo
302fn quit(
303    cursor_world_pos: Res<CursorWorldPos>,
304    mut app_exit: MessageWriter<AppExit>,
305    bevy_logo_transform: Single<&Transform, With<BevyLogo>>,
306) {
307    // If the cursor is not within the primary window skip this system
308    let Some(cursor_world_pos) = cursor_world_pos.0 else {
309        return;
310    };
311
312    // If the cursor is within the Bevy logo radius send the [`AppExit`] event to quit the app
313    if bevy_logo_transform
314        .translation
315        .truncate()
316        .distance(cursor_world_pos)
317        < BEVY_LOGO_RADIUS
318    {
319        app_exit.write(AppExit::Success);
320    }
321}
322
323/// Enable transparency for the window and make it on top
324fn toggle_transparency(
325    mut commands: Commands,
326    mut window_transparency: ResMut<WindowTransparency>,
327    mut q_instructions_text: Query<&mut Visibility, With<InstructionsText>>,
328    mut primary_window: Single<&mut Window, With<PrimaryWindow>>,
329) {
330    // Toggle the window transparency resource
331    window_transparency.0 = !window_transparency.0;
332
333    // Show or hide the instructions text
334    for mut visibility in &mut q_instructions_text {
335        *visibility = if window_transparency.0 {
336            Visibility::Hidden
337        } else {
338            Visibility::Visible
339        };
340    }
341
342    // Remove the primary window's decorations (e.g. borders), make it always on top of other desktop windows, and set the clear color to transparent
343    // only if window transparency is enabled
344    let clear_color;
345    (
346        primary_window.decorations,
347        primary_window.window_level,
348        clear_color,
349    ) = if window_transparency.0 {
350        (false, WindowLevel::AlwaysOnTop, Color::NONE)
351    } else {
352        (true, WindowLevel::Normal, WINDOW_CLEAR_COLOR)
353    };
354
355    // Set the clear color
356    commands.insert_resource(ClearColor(clear_color));
357}
358
359/// Move the pupils and bounce them around
360fn move_pupils(time: Res<Time>, mut q_pupils: Query<(&mut Pupil, &mut Transform)>) {
361    for (mut pupil, mut transform) in &mut q_pupils {
362        // The wiggle radius is how much the pupil can move within the eye
363        let wiggle_radius = pupil.eye_radius - pupil.pupil_radius;
364        // Store the Z component
365        let z = transform.translation.z;
366        // Truncate the Z component to make the calculations be on [`Vec2`]
367        let mut translation = transform.translation.truncate();
368        // Decay the pupil velocity
369        pupil.velocity *= ops::powf(0.04f32, time.delta_secs());
370        // Move the pupil
371        translation += pupil.velocity * time.delta_secs();
372        // If the pupil hit the outside border of the eye, limit the translation to be within the wiggle radius and invert the velocity.
373        // This is not physically accurate but it's good enough for the googly eyes effect.
374        if translation.length() > wiggle_radius {
375            translation = translation.normalize() * wiggle_radius;
376            // Invert and decrease the velocity of the pupil when it bounces
377            pupil.velocity *= -0.75;
378        }
379        // Update the entity transform with the new translation after reading the Z component
380        transform.translation = translation.extend(z);
381    }
382}
More examples
Hide additional examples
examples/3d/light_probe_blending.rs (line 523)
497fn handle_camera_mode_change(
498    mut commands: Commands,
499    cameras_query: Query<(Entity, &Transform), With<Camera3d>>,
500    sphere_query: Query<&Transform, (With<ReflectiveSphere>, Without<Camera3d>)>,
501    mut help_text_query: Query<&mut Text, With<HelpText>>,
502    mut windows_query: Query<&mut CursorOptions>,
503    mut app_status: ResMut<AppStatus>,
504    mut messages: MessageReader<WidgetClickEvent<CameraMode>>,
505) {
506    let Some(sphere_transform) = sphere_query.iter().next() else {
507        return;
508    };
509
510    let mut any_changes = false;
511    for message in messages.read() {
512        app_status.camera_mode = **message;
513
514        match **message {
515            CameraMode::Orbit => {
516                for (camera_entity, camera_transform) in &cameras_query {
517                    // Convert from Cartesian coordinates back to spherical
518                    // coordinates.
519                    let relative_camera_position =
520                        camera_transform.translation - sphere_transform.translation;
521                    let radius = relative_camera_position.length();
522                    let inclination = atan2(
523                        relative_camera_position.xz().length() / radius,
524                        relative_camera_position.y / radius,
525                    );
526                    let azimuth = atan2(
527                        relative_camera_position.z * relative_camera_position.xz().length_recip(),
528                        relative_camera_position.x * relative_camera_position.xz().length_recip(),
529                    );
530
531                    commands
532                        .entity(camera_entity)
533                        .remove::<FreeCamera>()
534                        .insert(OrbitCamera {
535                            radius,
536                            inclination,
537                            azimuth,
538                        });
539                }
540            }
541
542            CameraMode::Free => {
543                for (camera_entity, _) in &cameras_query {
544                    commands
545                        .entity(camera_entity)
546                        .remove::<OrbitCamera>()
547                        .insert(FreeCamera::default());
548                }
549            }
550        }
551
552        any_changes = true;
553    }
554
555    if any_changes {
556        set_help_text(&app_status, &mut help_text_query);
557
558        // Reset the cursor grab mode, because the free camera controller may
559        // have enabled it, and we don't want the cursor to disappear.
560        for mut cursor_options in &mut windows_query {
561            cursor_options.grab_mode = CursorGrabMode::None;
562            cursor_options.visible = true;
563        }
564    }
565}
Source

pub fn length_squared(self) -> f32

Computes the squared length of self.

This is faster than length() as it avoids a square root operation.

Source

pub fn length_recip(self) -> f32

Computes 1.0 / length().

For valid results, self must not be of length zero.

Examples found in repository?
examples/3d/clustered_decals.rs (line 407)
386fn process_move_input(
387    mut selections: Query<(&mut Transform, &Selection)>,
388    mouse_buttons: Res<ButtonInput<MouseButton>>,
389    mouse_motion: Res<AccumulatedMouseMotion>,
390    app_status: Res<AppStatus>,
391) {
392    // Only process drags when movement is selected.
393    if !mouse_buttons.pressed(MouseButton::Left) || app_status.drag_mode != DragMode::Move {
394        return;
395    }
396
397    for (mut transform, selection) in &mut selections {
398        if app_status.selection != *selection {
399            continue;
400        }
401
402        let position = transform.translation;
403
404        // Convert to spherical coordinates.
405        let radius = position.length();
406        let mut theta = acos(position.y / radius);
407        let mut phi = position.z.signum() * acos(position.x * position.xz().length_recip());
408
409        // Camera movement is the inverse of object movement.
410        let (phi_factor, theta_factor) = match *selection {
411            Selection::Camera => (1.0, -1.0),
412            Selection::DecalA | Selection::DecalB => (-1.0, 1.0),
413        };
414
415        // Adjust the spherical coordinates. Clamp the inclination to (0, π).
416        phi += phi_factor * mouse_motion.delta.x * MOVE_SPEED;
417        theta = f32::clamp(
418            theta + theta_factor * mouse_motion.delta.y * MOVE_SPEED,
419            0.001,
420            PI - 0.001,
421        );
422
423        // Convert spherical coordinates back to Cartesian coordinates.
424        transform.translation =
425            radius * vec3(sin(theta) * cos(phi), cos(theta), sin(theta) * sin(phi));
426
427        // Look at the center, but preserve the previous roll angle.
428        let roll = transform.rotation.to_euler(EulerRot::YXZ).2;
429        transform.look_at(Vec3::ZERO, Vec3::Y);
430        let (yaw, pitch, _) = transform.rotation.to_euler(EulerRot::YXZ);
431        transform.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll);
432    }
433}
More examples
Hide additional examples
examples/3d/light_textures.rs (line 489)
461fn process_move_input(
462    mut selections: Query<(&mut Transform, &Selection)>,
463    mouse_buttons: Res<ButtonInput<MouseButton>>,
464    mouse_motion: Res<AccumulatedMouseMotion>,
465    app_status: Res<AppStatus>,
466) {
467    // Only process drags when movement is selected.
468    if !mouse_buttons.pressed(MouseButton::Left) || app_status.drag_mode != DragMode::Move {
469        return;
470    }
471
472    for (mut transform, selection) in &mut selections {
473        if app_status.selection != *selection {
474            continue;
475        }
476
477        // use simple movement for the point light
478        if *selection == Selection::PointLight {
479            transform.translation +=
480                (mouse_motion.delta * Vec2::new(1.0, -1.0) * MOVE_SPEED).extend(0.0);
481            return;
482        }
483
484        let position = transform.translation;
485
486        // Convert to spherical coordinates.
487        let radius = position.length();
488        let mut theta = acos(position.y / radius);
489        let mut phi = position.z.signum() * acos(position.x * position.xz().length_recip());
490
491        // Camera movement is the inverse of object movement.
492        let (phi_factor, theta_factor) = match *selection {
493            Selection::Camera => (1.0, -1.0),
494            _ => (-1.0, 1.0),
495        };
496
497        // Adjust the spherical coordinates. Clamp the inclination to (0, π).
498        phi += phi_factor * mouse_motion.delta.x * MOVE_SPEED;
499        theta = f32::clamp(
500            theta + theta_factor * mouse_motion.delta.y * MOVE_SPEED,
501            0.001,
502            PI - 0.001,
503        );
504
505        // Convert spherical coordinates back to Cartesian coordinates.
506        transform.translation =
507            radius * vec3(sin(theta) * cos(phi), cos(theta), sin(theta) * sin(phi));
508
509        // Look at the center, but preserve the previous roll angle.
510        let roll = transform.rotation.to_euler(EulerRot::YXZ).2;
511        transform.look_at(Vec3::ZERO, Vec3::Y);
512        let (yaw, pitch, _) = transform.rotation.to_euler(EulerRot::YXZ);
513        transform.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll);
514    }
515}
examples/3d/light_probe_blending.rs (line 527)
497fn handle_camera_mode_change(
498    mut commands: Commands,
499    cameras_query: Query<(Entity, &Transform), With<Camera3d>>,
500    sphere_query: Query<&Transform, (With<ReflectiveSphere>, Without<Camera3d>)>,
501    mut help_text_query: Query<&mut Text, With<HelpText>>,
502    mut windows_query: Query<&mut CursorOptions>,
503    mut app_status: ResMut<AppStatus>,
504    mut messages: MessageReader<WidgetClickEvent<CameraMode>>,
505) {
506    let Some(sphere_transform) = sphere_query.iter().next() else {
507        return;
508    };
509
510    let mut any_changes = false;
511    for message in messages.read() {
512        app_status.camera_mode = **message;
513
514        match **message {
515            CameraMode::Orbit => {
516                for (camera_entity, camera_transform) in &cameras_query {
517                    // Convert from Cartesian coordinates back to spherical
518                    // coordinates.
519                    let relative_camera_position =
520                        camera_transform.translation - sphere_transform.translation;
521                    let radius = relative_camera_position.length();
522                    let inclination = atan2(
523                        relative_camera_position.xz().length() / radius,
524                        relative_camera_position.y / radius,
525                    );
526                    let azimuth = atan2(
527                        relative_camera_position.z * relative_camera_position.xz().length_recip(),
528                        relative_camera_position.x * relative_camera_position.xz().length_recip(),
529                    );
530
531                    commands
532                        .entity(camera_entity)
533                        .remove::<FreeCamera>()
534                        .insert(OrbitCamera {
535                            radius,
536                            inclination,
537                            azimuth,
538                        });
539                }
540            }
541
542            CameraMode::Free => {
543                for (camera_entity, _) in &cameras_query {
544                    commands
545                        .entity(camera_entity)
546                        .remove::<OrbitCamera>()
547                        .insert(FreeCamera::default());
548                }
549            }
550        }
551
552        any_changes = true;
553    }
554
555    if any_changes {
556        set_help_text(&app_status, &mut help_text_query);
557
558        // Reset the cursor grab mode, because the free camera controller may
559        // have enabled it, and we don't want the cursor to disappear.
560        for mut cursor_options in &mut windows_query {
561            cursor_options.grab_mode = CursorGrabMode::None;
562            cursor_options.visible = true;
563        }
564    }
565}
Source

pub fn distance(self, rhs: Vec2) -> f32

Computes the Euclidean distance between two points in space.

Examples found in repository?
examples/showcase/desk_toy.rs (line 241)
220fn update_cursor_hit_test(
221    cursor_world_pos: Res<CursorWorldPos>,
222    primary_window: Single<(&Window, &mut CursorOptions), With<PrimaryWindow>>,
223    bevy_logo_transform: Single<&Transform, With<BevyLogo>>,
224) {
225    let (window, mut cursor_options) = primary_window.into_inner();
226    // If the window has decorations (e.g. a border) then it should be clickable
227    if window.decorations {
228        cursor_options.hit_test = true;
229        return;
230    }
231
232    // If the cursor is not within the window we don't need to update whether the window is clickable or not
233    let Some(cursor_world_pos) = cursor_world_pos.0 else {
234        return;
235    };
236
237    // If the cursor is within the radius of the Bevy logo make the window clickable otherwise the window is not clickable
238    cursor_options.hit_test = bevy_logo_transform
239        .translation
240        .truncate()
241        .distance(cursor_world_pos)
242        < BEVY_LOGO_RADIUS;
243}
244
245/// Start the drag operation and record the offset we started dragging from
246fn start_drag(
247    mut commands: Commands,
248    cursor_world_pos: Res<CursorWorldPos>,
249    bevy_logo_transform: Single<&Transform, With<BevyLogo>>,
250) {
251    // If the cursor is not within the primary window skip this system
252    let Some(cursor_world_pos) = cursor_world_pos.0 else {
253        return;
254    };
255
256    // Get the offset from the cursor to the Bevy logo sprite
257    let drag_offset = bevy_logo_transform.translation.truncate() - cursor_world_pos;
258
259    // If the cursor is within the Bevy logo radius start the drag operation and remember the offset of the cursor from the origin
260    if drag_offset.length() < BEVY_LOGO_RADIUS {
261        commands.insert_resource(DragOperation(drag_offset));
262    }
263}
264
265/// Stop the current drag operation
266fn end_drag(mut commands: Commands) {
267    commands.remove_resource::<DragOperation>();
268}
269
270/// Drag the Bevy logo
271fn drag(
272    drag_offset: Res<DragOperation>,
273    cursor_world_pos: Res<CursorWorldPos>,
274    time: Res<Time>,
275    mut bevy_transform: Single<&mut Transform, With<BevyLogo>>,
276    mut q_pupils: Query<&mut Pupil>,
277) {
278    // If the cursor is not within the primary window skip this system
279    let Some(cursor_world_pos) = cursor_world_pos.0 else {
280        return;
281    };
282
283    // Calculate the new translation of the Bevy logo based on cursor and drag offset
284    let new_translation = cursor_world_pos + drag_offset.0;
285
286    // Calculate how fast we are dragging the Bevy logo (unit/second)
287    let drag_velocity =
288        (new_translation - bevy_transform.translation.truncate()) / time.delta_secs();
289
290    // Update the translation of Bevy logo transform to new translation
291    bevy_transform.translation = new_translation.extend(bevy_transform.translation.z);
292
293    // Add the cursor drag velocity in the opposite direction to each pupil.
294    // Remember pupils are using local coordinates to move. So when the Bevy logo moves right they need to move left to
295    // simulate inertia, otherwise they will move fixed to the parent.
296    for mut pupil in &mut q_pupils {
297        pupil.velocity -= drag_velocity;
298    }
299}
300
301/// Quit when the user right clicks the Bevy logo
302fn quit(
303    cursor_world_pos: Res<CursorWorldPos>,
304    mut app_exit: MessageWriter<AppExit>,
305    bevy_logo_transform: Single<&Transform, With<BevyLogo>>,
306) {
307    // If the cursor is not within the primary window skip this system
308    let Some(cursor_world_pos) = cursor_world_pos.0 else {
309        return;
310    };
311
312    // If the cursor is within the Bevy logo radius send the [`AppExit`] event to quit the app
313    if bevy_logo_transform
314        .translation
315        .truncate()
316        .distance(cursor_world_pos)
317        < BEVY_LOGO_RADIUS
318    {
319        app_exit.write(AppExit::Success);
320    }
321}
More examples
Hide additional examples
examples/ecs/delayed_commands.rs (line 49)
34fn click(
35    click: On<Pointer<Click>>,
36    mut commands: Commands,
37    squares: Query<(Entity, &Transform), With<BlinkySquare>>,
38    cameras: Query<(&Camera, &GlobalTransform)>,
39) {
40    let (camera, camera_transform) = cameras.single().unwrap();
41    let mut delayed = commands.delayed();
42    for (entity, transform) in squares.iter() {
43        // convert the pointer position to world position
44        let mouse_world_pos = camera
45            .viewport_to_world_2d(camera_transform, click.pointer_location.position)
46            .unwrap();
47
48        // delay the blinkiness by distance to cursor
49        let dist = mouse_world_pos.distance(transform.translation.truncate());
50        let delay = dist / 1000.0;
51        delayed
52            .secs(delay)
53            .entity(entity)
54            .insert(Sprite::from_color(Color::WHITE, SQUARE_SIZE));
55        delayed
56            .secs(delay + 0.1)
57            .entity(entity)
58            .insert(Sprite::from_color(Color::BLACK, SQUARE_SIZE));
59    }
60}
examples/ecs/observers.rs (line 29)
8fn main() {
9    App::new()
10        .add_plugins(DefaultPlugins)
11        .init_resource::<SpatialIndex>()
12        .init_resource::<ExplosionsEnabled>()
13        .add_systems(Startup, setup)
14        .add_systems(Update, (draw_shapes, handle_click, toggle_explosions))
15        // Observers are systems that run when an event is "triggered". This observer runs whenever
16        // `ExplodeMines` is triggered.
17        //
18        // Observers can have run conditions, just like systems! This observer only runs when
19        // explosions are enabled. Press Space to toggle.
20        .add_observer(
21            (|explode_mines: On<ExplodeMines>,
22              mines: Query<&Mine>,
23              index: Res<SpatialIndex>,
24              mut commands: Commands| {
25                // Access resources
26                for entity in index.get_nearby(explode_mines.pos) {
27                    // Run queries
28                    let mine = mines.get(entity).unwrap();
29                    if mine.pos.distance(explode_mines.pos) < mine.size + explode_mines.radius {
30                        // And queue commands, including triggering additional events
31                        // Here we trigger the `Explode` event for entity `e`
32                        commands.trigger(Explode { entity });
33                    }
34                }
35            })
36            .run_if(|enabled: Res<ExplosionsEnabled>| enabled.0),
37        )
38        // This observer runs whenever the `Mine` component is added to an entity, and places it in a simple spatial index.
39        .add_observer(on_add_mine)
40        // This observer runs whenever the `Mine` component is removed from an entity (including despawning it)
41        // and removes it from the spatial index.
42        .add_observer(on_remove_mine)
43        .run();
44}
examples/2d/cpu_draw.rs (line 63)
38fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
39    commands.spawn(Camera2d);
40
41    // Create an image that we are going to draw into
42    let mut image = Image::new_fill(
43        // 2D image of size 256x256
44        Extent3d {
45            width: IMAGE_WIDTH,
46            height: IMAGE_HEIGHT,
47            depth_or_array_layers: 1,
48        },
49        TextureDimension::D2,
50        // Initialize it with a beige color
51        &(css::BEIGE.to_u8_array()),
52        // Use the same encoding as the color we set
53        TextureFormat::Rgba8UnormSrgb,
54        RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD,
55    );
56
57    // To make it extra fancy, we can set the Alpha of each pixel,
58    // so that it fades out in a circular fashion.
59    for y in 0..IMAGE_HEIGHT {
60        for x in 0..IMAGE_WIDTH {
61            let center = Vec2::new(IMAGE_WIDTH as f32 / 2.0, IMAGE_HEIGHT as f32 / 2.0);
62            let max_radius = IMAGE_HEIGHT.min(IMAGE_WIDTH) as f32 / 2.0;
63            let r = Vec2::new(x as f32, y as f32).distance(center);
64            let a = 1.0 - (r / max_radius).clamp(0.0, 1.0);
65
66            // Here we will set the A value by accessing the raw data bytes.
67            // (it is the 4th byte of each pixel, as per our `TextureFormat`)
68
69            // Find our pixel by its coordinates
70            let pixel_bytes = image.pixel_bytes_mut(UVec3::new(x, y, 0)).unwrap();
71            // Convert our f32 to u8
72            pixel_bytes[3] = (a * u8::MAX as f32) as u8;
73        }
74    }
75
76    // Add it to Bevy's assets, so it can be used for rendering
77    // this will give us a handle we can use
78    // (to display it in a sprite, or as part of UI, etc.)
79    let handle = images.add(image);
80
81    // Create a sprite entity using our image
82    commands.spawn(Sprite::from_image(handle.clone()));
83    commands.insert_resource(MyProcGenImage(handle));
84
85    // We're seeding the PRNG here to make this example deterministic for testing purposes.
86    // This isn't strictly required in practical use unless you need your app to be deterministic.
87    let seeded_rng = ChaCha8Rng::seed_from_u64(19878367467712);
88    commands.insert_resource(SeededRng(seeded_rng));
89}
Source

pub fn distance_squared(self, rhs: Vec2) -> f32

Compute the squared euclidean distance between two points in space.

Source

pub fn div_euclid(self, rhs: Vec2) -> Vec2

Returns the element-wise quotient of [Euclidean division] of self by rhs.

Source

pub fn rem_euclid(self, rhs: Vec2) -> Vec2

Returns the element-wise remainder of Euclidean division of self by rhs.

Source

pub fn normalize(self) -> Vec2

Returns self normalized to length 1.0.

For valid results, self must be finite and not of length zero, nor very close to zero.

See also Self::try_normalize() and Self::normalize_or_zero().

§Panics

Will panic if the resulting normalized vector is not finite when glam_assert is enabled.

Examples found in repository?
examples/2d/rotation.rs (line 163)
154fn snap_to_player_system(
155    mut query: Query<&mut Transform, (With<SnapToPlayer>, Without<Player>)>,
156    player_transform: Single<&Transform, With<Player>>,
157) {
158    // Get the player translation in 2D
159    let player_translation = player_transform.translation.xy();
160
161    for mut enemy_transform in &mut query {
162        // Get the vector from the enemy ship to the player ship in 2D and normalize it.
163        let to_player = (player_translation - enemy_transform.translation.xy()).normalize();
164
165        // Get the quaternion to rotate from the initial enemy facing direction to the direction
166        // facing the player
167        let rotate_to_player = Quat::from_rotation_arc(Vec3::Y, to_player.extend(0.));
168
169        // Rotate the enemy to face the player
170        enemy_transform.rotation = rotate_to_player;
171    }
172}
173
174/// Demonstrates rotating an enemy ship to face the player ship at a given rotation speed.
175///
176/// This method uses the vector dot product to determine if the enemy is facing the player and
177/// if not, which way to rotate to face the player. The dot product on two unit length vectors
178/// will return a value between -1.0 and +1.0 which tells us the following about the two vectors:
179///
180/// * If the result is 1.0 the vectors are pointing in the same direction, the angle between them is
181///   0 degrees.
182/// * If the result is 0.0 the vectors are perpendicular, the angle between them is 90 degrees.
183/// * If the result is -1.0 the vectors are parallel but pointing in opposite directions, the angle
184///   between them is 180 degrees.
185/// * If the result is positive the vectors are pointing in roughly the same direction, the angle
186///   between them is greater than 0 and less than 90 degrees.
187/// * If the result is negative the vectors are pointing in roughly opposite directions, the angle
188///   between them is greater than 90 and less than 180 degrees.
189///
190/// It is possible to get the angle by taking the arc cosine (`acos`) of the dot product. It is
191/// often unnecessary to do this though. Beware than `acos` will return `NaN` if the input is less
192/// than -1.0 or greater than 1.0. This can happen even when working with unit vectors due to
193/// floating point precision loss, so it pays to clamp your dot product value before calling
194/// `acos`.
195fn rotate_to_player_system(
196    time: Res<Time>,
197    mut query: Query<(&RotateToPlayer, &mut Transform), Without<Player>>,
198    player_transform: Single<&Transform, With<Player>>,
199) {
200    // Get the player translation in 2D
201    let player_translation = player_transform.translation.xy();
202
203    for (config, mut enemy_transform) in &mut query {
204        // Get the enemy ship forward vector in 2D (already unit length)
205        let enemy_forward = (enemy_transform.rotation * Vec3::Y).xy();
206
207        // Get the vector from the enemy ship to the player ship in 2D and normalize it.
208        let to_player = (player_translation - enemy_transform.translation.xy()).normalize();
209
210        // Get the dot product between the enemy forward vector and the direction to the player.
211        let forward_dot_player = enemy_forward.dot(to_player);
212
213        // If the dot product is approximately 1.0 then the enemy is already facing the player and
214        // we can early out.
215        if (forward_dot_player - 1.0).abs() < f32::EPSILON {
216            continue;
217        }
218
219        // Get the right vector of the enemy ship in 2D (already unit length)
220        let enemy_right = (enemy_transform.rotation * Vec3::X).xy();
221
222        // Get the dot product of the enemy right vector and the direction to the player ship.
223        // If the dot product is negative them we need to rotate counter clockwise, if it is
224        // positive we need to rotate clockwise. Note that `copysign` will still return 1.0 if the
225        // dot product is 0.0 (because the player is directly behind the enemy, so perpendicular
226        // with the right vector).
227        let right_dot_player = enemy_right.dot(to_player);
228
229        // Determine the sign of rotation from the right dot player. We need to negate the sign
230        // here as the 2D bevy co-ordinate system rotates around +Z, which is pointing out of the
231        // screen. Due to the right hand rule, positive rotation around +Z is counter clockwise and
232        // negative is clockwise.
233        let rotation_sign = -f32::copysign(1.0, right_dot_player);
234
235        // Limit rotation so we don't overshoot the target. We need to convert our dot product to
236        // an angle here so we can get an angle of rotation to clamp against.
237        let max_angle = ops::acos(forward_dot_player.clamp(-1.0, 1.0)); // Clamp acos for safety
238
239        // Calculate angle of rotation with limit
240        let rotation_angle =
241            rotation_sign * (config.rotation_speed * time.delta_secs()).min(max_angle);
242
243        // Rotate the enemy to face the player
244        enemy_transform.rotate_z(rotation_angle);
245    }
246}
More examples
Hide additional examples
examples/math/custom_primitives.rs (line 577)
570    fn perimeter(&self) -> Vec<PerimeterSegment> {
571        let resolution = self.resolution as u32;
572        vec![
573            // The left wing of the heart
574            PerimeterSegment::Smooth {
575                // The normals of the first and last vertices of smooth segments have to be specified manually.
576                first_normal: Vec2::X,
577                last_normal: Vec2::new(-1.0, -1.0).normalize(),
578                // These indices are used to index into the `ATTRIBUTE_POSITION` vec of your 2D mesh.
579                indices: (0..resolution).collect(),
580            },
581            // The bottom tip of the heart
582            PerimeterSegment::Flat {
583                indices: vec![resolution - 1, resolution, resolution + 1],
584            },
585            // The right wing of the heart
586            PerimeterSegment::Smooth {
587                first_normal: Vec2::new(1.0, -1.0).normalize(),
588                last_normal: Vec2::NEG_X,
589                indices: (resolution + 1..2 * resolution).chain([0]).collect(),
590            },
591        ]
592    }
examples/showcase/desk_toy.rs (line 375)
360fn move_pupils(time: Res<Time>, mut q_pupils: Query<(&mut Pupil, &mut Transform)>) {
361    for (mut pupil, mut transform) in &mut q_pupils {
362        // The wiggle radius is how much the pupil can move within the eye
363        let wiggle_radius = pupil.eye_radius - pupil.pupil_radius;
364        // Store the Z component
365        let z = transform.translation.z;
366        // Truncate the Z component to make the calculations be on [`Vec2`]
367        let mut translation = transform.translation.truncate();
368        // Decay the pupil velocity
369        pupil.velocity *= ops::powf(0.04f32, time.delta_secs());
370        // Move the pupil
371        translation += pupil.velocity * time.delta_secs();
372        // If the pupil hit the outside border of the eye, limit the translation to be within the wiggle radius and invert the velocity.
373        // This is not physically accurate but it's good enough for the googly eyes effect.
374        if translation.length() > wiggle_radius {
375            translation = translation.normalize() * wiggle_radius;
376            // Invert and decrease the velocity of the pupil when it bounces
377            pupil.velocity *= -0.75;
378        }
379        // Update the entity transform with the new translation after reading the Z component
380        transform.translation = translation.extend(z);
381    }
382}
examples/showcase/breakout.rs (line 206)
172fn setup(
173    mut commands: Commands,
174    mut meshes: ResMut<Assets<Mesh>>,
175    mut materials: ResMut<Assets<ColorMaterial>>,
176    asset_server: Res<AssetServer>,
177) {
178    // Camera
179    commands.spawn(Camera2d);
180
181    // Sound
182    let ball_collision_sound = asset_server.load("sounds/breakout_collision.ogg");
183    commands.insert_resource(CollisionSound(ball_collision_sound));
184
185    // Paddle
186    let paddle_y = BOTTOM_WALL + GAP_BETWEEN_PADDLE_AND_FLOOR;
187
188    commands.spawn((
189        Sprite::from_color(PADDLE_COLOR, Vec2::ONE),
190        Transform {
191            translation: Vec3::new(0.0, paddle_y, 0.0),
192            scale: PADDLE_SIZE.extend(1.0),
193            ..default()
194        },
195        Paddle,
196        Collider,
197    ));
198
199    // Ball
200    commands.spawn((
201        Mesh2d(meshes.add(Circle::default())),
202        MeshMaterial2d(materials.add(BALL_COLOR)),
203        Transform::from_translation(BALL_STARTING_POSITION)
204            .with_scale(Vec2::splat(BALL_DIAMETER).extend(1.)),
205        Ball,
206        Velocity(INITIAL_BALL_DIRECTION.normalize() * BALL_SPEED),
207    ));
208
209    // Scoreboard
210    commands.spawn((
211        Text::new("Score: "),
212        TextFont {
213            font_size: SCOREBOARD_FONT_SIZE,
214            ..default()
215        },
216        TextColor(TEXT_COLOR),
217        ScoreboardUi,
218        Node {
219            position_type: PositionType::Absolute,
220            top: SCOREBOARD_TEXT_PADDING,
221            left: SCOREBOARD_TEXT_PADDING,
222            ..default()
223        },
224        children![(
225            TextSpan::default(),
226            TextFont {
227                font_size: SCOREBOARD_FONT_SIZE,
228                ..default()
229            },
230            TextColor(SCORE_COLOR),
231        )],
232    ));
233
234    // Walls
235    commands.spawn(Wall::new(WallLocation::Left));
236    commands.spawn(Wall::new(WallLocation::Right));
237    commands.spawn(Wall::new(WallLocation::Bottom));
238    commands.spawn(Wall::new(WallLocation::Top));
239
240    // Bricks
241    let total_width_of_bricks = (RIGHT_WALL - LEFT_WALL) - 2. * GAP_BETWEEN_BRICKS_AND_SIDES;
242    let bottom_edge_of_bricks = paddle_y + GAP_BETWEEN_PADDLE_AND_BRICKS;
243    let total_height_of_bricks = TOP_WALL - bottom_edge_of_bricks - GAP_BETWEEN_BRICKS_AND_CEILING;
244
245    assert!(total_width_of_bricks > 0.0);
246    assert!(total_height_of_bricks > 0.0);
247
248    // Given the space available, compute how many rows and columns of bricks we can fit
249    let n_columns = (total_width_of_bricks / (BRICK_SIZE.x + GAP_BETWEEN_BRICKS)).floor() as usize;
250    let n_rows = (total_height_of_bricks / (BRICK_SIZE.y + GAP_BETWEEN_BRICKS)).floor() as usize;
251    let n_vertical_gaps = n_columns - 1;
252
253    // Because we need to round the number of columns,
254    // the space on the top and sides of the bricks only captures a lower bound, not an exact value
255    let center_of_bricks = (LEFT_WALL + RIGHT_WALL) / 2.0;
256    let left_edge_of_bricks = center_of_bricks
257        // Space taken up by the bricks
258        - (n_columns as f32 / 2.0 * BRICK_SIZE.x)
259        // Space taken up by the gaps
260        - n_vertical_gaps as f32 / 2.0 * GAP_BETWEEN_BRICKS;
261
262    // In Bevy, the `translation` of an entity describes the center point,
263    // not its bottom-left corner
264    let offset_x = left_edge_of_bricks + BRICK_SIZE.x / 2.;
265    let offset_y = bottom_edge_of_bricks + BRICK_SIZE.y / 2.;
266
267    for row in 0..n_rows {
268        for column in 0..n_columns {
269            let brick_position = Vec2::new(
270                offset_x + column as f32 * (BRICK_SIZE.x + GAP_BETWEEN_BRICKS),
271                offset_y + row as f32 * (BRICK_SIZE.y + GAP_BETWEEN_BRICKS),
272            );
273
274            // brick
275            commands.spawn((
276                Sprite {
277                    color: BRICK_COLOR,
278                    ..default()
279                },
280                Transform {
281                    translation: brick_position.extend(0.0),
282                    scale: Vec3::new(BRICK_SIZE.x, BRICK_SIZE.y, 1.0),
283                    ..default()
284                },
285                Brick,
286                Collider,
287            ));
288        }
289    }
290}
Source

pub fn try_normalize(self) -> Option<Vec2>

Returns self normalized to length 1.0 if possible, else returns None.

In particular, if the input is zero (or very close to zero), or non-finite, the result of this operation will be None.

See also Self::normalize_or_zero().

Source

pub fn normalize_or(self, fallback: Vec2) -> Vec2

Returns self normalized to length 1.0 if possible, else returns a fallback value.

In particular, if the input is zero (or very close to zero), or non-finite, the result of this operation will be the fallback value.

See also Self::try_normalize().

Source

pub fn normalize_or_zero(self) -> Vec2

Returns self normalized to length 1.0 if possible, else returns zero.

In particular, if the input is zero (or very close to zero), or non-finite, the result of this operation will be zero.

See also Self::try_normalize().

Examples found in repository?
examples/camera/2d_top_down_camera.rs (line 114)
88fn move_player(
89    mut player: Single<&mut Transform, With<Player>>,
90    time: Res<Time>,
91    kb_input: Res<ButtonInput<KeyCode>>,
92) {
93    let mut direction = Vec2::ZERO;
94
95    if kb_input.pressed(KeyCode::KeyW) {
96        direction.y += 1.;
97    }
98
99    if kb_input.pressed(KeyCode::KeyS) {
100        direction.y -= 1.;
101    }
102
103    if kb_input.pressed(KeyCode::KeyA) {
104        direction.x -= 1.;
105    }
106
107    if kb_input.pressed(KeyCode::KeyD) {
108        direction.x += 1.;
109    }
110
111    // Progressively update the player's position over time. Normalize the
112    // direction vector to prevent it from exceeding a magnitude of 1 when
113    // moving diagonally.
114    let move_delta = direction.normalize_or_zero() * PLAYER_SPEED * time.delta_secs();
115    player.translation += move_delta.extend(0.);
116}
More examples
Hide additional examples
examples/3d/tonemapping.rs (line 256)
227fn resize_image(
228    image_mesh: Query<(&MeshMaterial3d<StandardMaterial>, &Mesh3d), With<HDRViewer>>,
229    materials: Res<Assets<StandardMaterial>>,
230    mut meshes: ResMut<Assets<Mesh>>,
231    images: Res<Assets<Image>>,
232    mut image_event_reader: MessageReader<AssetEvent<Image>>,
233) {
234    for event in image_event_reader.read() {
235        let (AssetEvent::Added { id } | AssetEvent::Modified { id }) = event else {
236            continue;
237        };
238
239        for (mat_h, mesh_h) in &image_mesh {
240            let Some(mat) = materials.get(mat_h) else {
241                continue;
242            };
243
244            let Some(ref base_color_texture) = mat.base_color_texture else {
245                continue;
246            };
247
248            if *id != base_color_texture.id() {
249                continue;
250            };
251
252            let Some(image_changed) = images.get(*id) else {
253                continue;
254            };
255
256            let size = image_changed.size_f32().normalize_or_zero() * 1.4;
257            // Resize Mesh
258            let quad = Mesh::from(Rectangle::from_size(size));
259            meshes.insert(mesh_h, quad).unwrap();
260        }
261    }
262}
Source

pub fn normalize_and_length(self) -> (Vec2, f32)

Returns self normalized to length 1.0 and the length of self.

If self is zero length then (Self::X, 0.0) is returned.

Source

pub fn is_normalized(self) -> bool

Returns whether self is length 1.0 or not.

Uses a precision threshold of approximately 1e-4.

Source

pub fn project_onto(self, rhs: Vec2) -> Vec2

Returns the vector projection of self onto rhs.

rhs must be of non-zero length.

§Panics

Will panic if rhs is zero length when glam_assert is enabled.

Source

pub fn reject_from(self, rhs: Vec2) -> Vec2

Returns the vector rejection of self from rhs.

The vector rejection is the vector perpendicular to the projection of self onto rhs, in rhs words the result of self - self.project_onto(rhs).

rhs must be of non-zero length.

§Panics

Will panic if rhs has a length of zero when glam_assert is enabled.

Source

pub fn project_onto_normalized(self, rhs: Vec2) -> Vec2

Returns the vector projection of self onto rhs.

rhs must be normalized.

§Panics

Will panic if rhs is not normalized when glam_assert is enabled.

Source

pub fn reject_from_normalized(self, rhs: Vec2) -> Vec2

Returns the vector rejection of self from rhs.

The vector rejection is the vector perpendicular to the projection of self onto rhs, in rhs words the result of self - self.project_onto(rhs).

rhs must be normalized.

§Panics

Will panic if rhs is not normalized when glam_assert is enabled.

Source

pub fn round(self) -> Vec2

Returns a vector containing the nearest integer to a number for each element of self. Round half-way cases away from 0.0.

Source

pub fn floor(self) -> Vec2

Returns a vector containing the largest integer less than or equal to a number for each element of self.

Examples found in repository?
examples/asset/asset_saving.rs (line 236)
208fn try_plot(
209    event: On<TryPlot>,
210    sprite: Query<(&Sprite, &Anchor, &GlobalTransform), With<SpriteToSave>>,
211    camera: Single<(&Camera, &GlobalTransform)>,
212    texture_atlases: Res<Assets<TextureAtlasLayout>>,
213    draw_color: Res<DrawColor>,
214    mut images: ResMut<Assets<Image>>,
215) {
216    let Ok((sprite, anchor, sprite_transform)) = sprite.get(event.entity) else {
217        return;
218    };
219    let (camera, camera_transform) = camera.into_inner();
220    let Ok(world_position) = camera.viewport_to_world_2d(camera_transform, event.location.position)
221    else {
222        return;
223    };
224    let relative_to_sprite = sprite_transform
225        .affine()
226        .inverse()
227        .transform_point3(world_position.extend(0.0));
228    let Ok(pixel_space) = sprite.compute_pixel_space_point(
229        relative_to_sprite.xy(),
230        *anchor,
231        &images,
232        &texture_atlases,
233    ) else {
234        return;
235    };
236    let pixel_coordinates = pixel_space.floor().as_uvec2();
237    let mut image = images.get_mut(&sprite.image).unwrap();
238    // For an actual drawing app, you'd at least draw a line from the last point, but this is
239    // simpler.
240    image
241        .set_color_at(pixel_coordinates.x, pixel_coordinates.y, draw_color.0)
242        .unwrap();
243}
Source

pub fn ceil(self) -> Vec2

Returns a vector containing the smallest integer greater than or equal to a number for each element of self.

Examples found in repository?
examples/stress_tests/many_cubes.rs (line 259)
161fn setup(
162    mut commands: Commands,
163    args: Res<Args>,
164    mesh_assets: ResMut<Assets<Mesh>>,
165    material_assets: ResMut<Assets<StandardMaterial>>,
166    images: ResMut<Assets<Image>>,
167) {
168    warn!(include_str!("warning_string.txt"));
169
170    let args = args.into_inner();
171    let images = images.into_inner();
172    let material_assets = material_assets.into_inner();
173    let mesh_assets = mesh_assets.into_inner();
174
175    let meshes = init_meshes(args, mesh_assets);
176
177    let material_textures = init_textures(args, images);
178    let materials = init_materials(args, &material_textures, material_assets);
179
180    // We're seeding the PRNG here to make this example deterministic for testing purposes.
181    // This isn't strictly required in practical use unless you need your app to be deterministic.
182    let mut material_rng = ChaCha8Rng::seed_from_u64(42);
183    match args.layout {
184        Layout::Sphere => {
185            // NOTE: This pattern is good for testing performance of culling as it provides roughly
186            // the same number of visible meshes regardless of the viewing angle.
187            let n_points: usize = args.instance_count;
188            // NOTE: f64 is used to avoid precision issues that produce visual artifacts in the distribution
189            let radius = WIDTH as f64 * 2.5;
190            let golden_ratio = 0.5f64 * (1.0f64 + 5.0f64.sqrt());
191            for i in 0..n_points {
192                let spherical_polar_theta_phi =
193                    fibonacci_spiral_on_sphere(golden_ratio, i, n_points);
194                let unit_sphere_p = spherical_polar_to_cartesian(spherical_polar_theta_phi);
195                let (mesh, transform) = meshes.choose(&mut material_rng).unwrap();
196                commands
197                    .spawn((
198                        Mesh3d(mesh.clone()),
199                        MeshMaterial3d(materials.choose(&mut material_rng).unwrap().clone()),
200                        Transform::from_translation((radius * unit_sphere_p).as_vec3())
201                            .looking_at(Vec3::ZERO, Vec3::Y)
202                            .mul_transform(*transform),
203                    ))
204                    .insert_if(NoFrustumCulling, || args.no_frustum_culling)
205                    .insert_if(NoAutomaticBatching, || args.no_automatic_batching)
206                    .insert_if(NoCpuCulling, || args.no_cpu_culling);
207            }
208
209            // camera
210            let mut camera = commands.spawn(Camera3d::default());
211            if args.no_indirect_drawing {
212                camera.insert(NoIndirectDrawing);
213            }
214            if args.no_cpu_culling {
215                camera.insert(NoCpuCulling);
216            }
217            if args.motion_blur {
218                camera.insert((
219                    MotionBlur {
220                        // Use an unrealistically large shutter angle so that motion blur is clearly visible.
221                        shutter_angle: 3.0,
222                        ..Default::default()
223                    },
224                    // MSAA and MotionBlur are not compatible on WebGL.
225                    #[cfg(all(
226                        feature = "webgl2",
227                        target_arch = "wasm32",
228                        not(feature = "webgpu")
229                    ))]
230                    Msaa::Off,
231                ));
232            }
233
234            // Inside-out box around the meshes onto which shadows are cast (though you cannot see them...)
235            commands.spawn((
236                Mesh3d(mesh_assets.add(Cuboid::from_size(Vec3::splat(radius as f32 * 2.2)))),
237                MeshMaterial3d(material_assets.add(StandardMaterial::from(Color::WHITE))),
238                Transform::from_scale(-Vec3::ONE),
239                NotShadowCaster,
240            ));
241        }
242        Layout::Cube => {
243            // NOTE: This pattern is good for demonstrating that frustum culling is working correctly
244            // as the number of visible meshes rises and falls depending on the viewing angle.
245            let scale = 2.5;
246
247            // Scale the width and height by the same factor so that we have the
248            // right number of instances.
249            // Because of the moiré pattern check and the fact that we're
250            // spawning 4 instances per trip around the inner loop below, we're
251            // solving the following equation for the factor variable:
252            //
253            //      4 * (9/10 * factor * width * 9/10 * factor * height) = count
254            //
255            // The solution is the value below.
256            let factor = (5.0 / 9.0) * sqrt(args.instance_count as f32)
257                / (sqrt(HEIGHT as f32) * sqrt(WIDTH as f32));
258            let dimensions = (vec2(WIDTH as f32, HEIGHT as f32) * factor)
259                .ceil()
260                .as_uvec2();
261
262            for x in 0..dimensions.x {
263                for y in 0..dimensions.y {
264                    // introduce spaces to break any kind of moiré pattern
265                    if x % 10 == 0 || y % 10 == 0 {
266                        continue;
267                    }
268                    // cube
269                    commands
270                        .spawn((
271                            Mesh3d(meshes.choose(&mut material_rng).unwrap().0.clone()),
272                            MeshMaterial3d(materials.choose(&mut material_rng).unwrap().clone()),
273                            Transform::from_xyz((x as f32) * scale, (y as f32) * scale, 0.0),
274                        ))
275                        .insert_if(NoCpuCulling, || args.no_cpu_culling);
276                    commands
277                        .spawn((
278                            Mesh3d(meshes.choose(&mut material_rng).unwrap().0.clone()),
279                            MeshMaterial3d(materials.choose(&mut material_rng).unwrap().clone()),
280                            Transform::from_xyz(
281                                (x as f32) * scale,
282                                dimensions.y as f32 * scale,
283                                (y as f32) * scale,
284                            ),
285                        ))
286                        .insert_if(NoCpuCulling, || args.no_cpu_culling);
287                    commands
288                        .spawn((
289                            Mesh3d(meshes.choose(&mut material_rng).unwrap().0.clone()),
290                            MeshMaterial3d(materials.choose(&mut material_rng).unwrap().clone()),
291                            Transform::from_xyz((x as f32) * scale, 0.0, (y as f32) * scale),
292                        ))
293                        .insert_if(NoCpuCulling, || args.no_cpu_culling);
294                    commands
295                        .spawn((
296                            Mesh3d(meshes.choose(&mut material_rng).unwrap().0.clone()),
297                            MeshMaterial3d(materials.choose(&mut material_rng).unwrap().clone()),
298                            Transform::from_xyz(0.0, (x as f32) * scale, (y as f32) * scale),
299                        ))
300                        .insert_if(NoCpuCulling, || args.no_cpu_culling);
301                }
302            }
303            // camera
304            let center = 0.5
305                * scale
306                * Vec3::new(
307                    dimensions.x as f32,
308                    dimensions.y as f32,
309                    dimensions.x as f32,
310                );
311            commands.spawn((Camera3d::default(), Transform::from_translation(center)));
312            // Inside-out box around the meshes onto which shadows are cast (though you cannot see them...)
313            commands.spawn((
314                Mesh3d(mesh_assets.add(Cuboid::from_size(2.0 * 1.1 * center))),
315                MeshMaterial3d(material_assets.add(StandardMaterial::from(Color::WHITE))),
316                Transform::from_scale(-Vec3::ONE).with_translation(center),
317                NotShadowCaster,
318            ));
319        }
320        Layout::Dense => {
321            // NOTE: This pattern is good for demonstrating a dense configuration of cubes
322            // overlapping each other, all within the camera frustum.
323            let count = args.instance_count;
324            let size = cbrt(count as f32).round();
325            let gap = 1.25;
326
327            for i in 0..count {
328                let x = i as f32 % size;
329                let y = (i as f32 / size) % size;
330                let z = i as f32 / (size * size);
331                let pos = Vec3::new(x * gap, y * gap, z * gap);
332                commands
333                    .spawn((
334                        Mesh3d(meshes.choose(&mut material_rng).unwrap().0.clone()),
335                        MeshMaterial3d(materials.choose(&mut material_rng).unwrap().clone()),
336                        Transform::from_translation(pos),
337                    ))
338                    .insert_if(NoCpuCulling, || args.no_cpu_culling);
339            }
340
341            // camera
342            commands.spawn((
343                Camera3d::default(),
344                Transform::from_xyz(100.0, 90.0, 100.0)
345                    .looking_at(Vec3::new(0.0, -10.0, 0.0), Vec3::Y),
346            ));
347        }
348    }
349
350    commands.spawn((
351        DirectionalLight {
352            shadow_maps_enabled: args.shadows,
353            ..default()
354        },
355        Transform::IDENTITY.looking_at(Vec3::new(0.0, -1.0, -1.0), Vec3::Y),
356    ));
357}
Source

pub fn trunc(self) -> Vec2

Returns a vector containing the integer part each element of self. This means numbers are always truncated towards zero.

Source

pub fn step(self, rhs: Vec2) -> Vec2

Returns a vector containing 0.0 if rhs < self and 1.0 otherwise.

Similar to glsl’s step(edge, x), which translates into edge.step(x)

Source

pub fn saturate(self) -> Vec2

Returns a vector containing all elements of self clamped to the range of [0, 1].

Source

pub fn fract(self) -> Vec2

Returns a vector containing the fractional part of the vector as self - self.trunc().

Note that this differs from the GLSL implementation of fract which returns self - self.floor().

Note that this is fast but not precise for large numbers.

Source

pub fn fract_gl(self) -> Vec2

Returns a vector containing the fractional part of the vector as self - self.floor().

Note that this differs from the Rust implementation of fract which returns self - self.trunc().

Note that this is fast but not precise for large numbers.

Source

pub fn exp(self) -> Vec2

Returns a vector containing e^self (the exponential function) for each element of self.

Source

pub fn exp2(self) -> Vec2

Returns a vector containing 2^self for each element of self.

Source

pub fn ln(self) -> Vec2

Returns a vector containing the natural logarithm for each element of self. This returns NaN when the element is negative and negative infinity when the element is zero.

Source

pub fn log2(self) -> Vec2

Returns a vector containing the base 2 logarithm for each element of self. This returns NaN when the element is negative and negative infinity when the element is zero.

Source

pub fn powf(self, n: f32) -> Vec2

Returns a vector containing each element of self raised to the power of n.

Source

pub fn sqrt(self) -> Vec2

Returns a vector containing the square root for each element of self. This returns NaN when the element is negative.

Source

pub fn cos(self) -> Vec2

Returns a vector containing the cosine for each element of self.

Source

pub fn sin(self) -> Vec2

Returns a vector containing the sine for each element of self.

Source

pub fn sin_cos(self) -> (Vec2, Vec2)

Returns a tuple of two vectors containing the sine and cosine for each element of self.

Source

pub fn recip(self) -> Vec2

Returns a vector containing the reciprocal 1.0/n of each element of self.

Source

pub fn lerp(self, rhs: Vec2, s: f32) -> Vec2

Performs a linear interpolation between self and rhs based on the value s.

When s is 0.0, the result will be equal to self. When s is 1.0, the result will be equal to rhs. When s is outside of range [0, 1], the result is linearly extrapolated.

Source

pub fn move_towards(self, rhs: Vec2, d: f32) -> Vec2

Moves towards rhs based on the value d.

When d is 0.0, the result will be equal to self. When d is equal to self.distance(rhs), the result will be equal to rhs. Will not go past rhs.

Source

pub fn midpoint(self, rhs: Vec2) -> Vec2

Calculates the midpoint between self and rhs.

The midpoint is the average of, or halfway point between, two vectors. a.midpoint(b) should yield the same result as a.lerp(b, 0.5) while being slightly cheaper to compute.

Source

pub fn abs_diff_eq(self, rhs: Vec2, max_abs_diff: f32) -> bool

Returns true if the absolute difference of all elements between self and rhs is less than or equal to max_abs_diff.

This can be used to compare if two vectors contain similar elements. It works best when comparing with a known value. The max_abs_diff that should be used used depends on the values being compared against.

For more see comparing floating point numbers.

Source

pub fn clamp_length(self, min: f32, max: f32) -> Vec2

Returns a vector with a length no less than min and no more than max.

§Panics

Will panic if min is greater than max, or if either min or max is negative, when glam_assert is enabled.

Source

pub fn clamp_length_max(self, max: f32) -> Vec2

Returns a vector with a length no more than max.

§Panics

Will panic if max is negative when glam_assert is enabled.

Source

pub fn clamp_length_min(self, min: f32) -> Vec2

Returns a vector with a length no less than min.

§Panics

Will panic if min is negative when glam_assert is enabled.

Source

pub fn mul_add(self, a: Vec2, b: Vec2) -> Vec2

Fused multiply-add. Computes (self * a) + b element-wise with only one rounding error, yielding a more accurate result than an unfused multiply-add.

Using mul_add may be more performant than an unfused multiply-add if the target architecture has a dedicated fma CPU instruction. However, this is not always true, and will be heavily dependant on designing algorithms with specific target hardware in mind.

Source

pub fn reflect(self, normal: Vec2) -> Vec2

Returns the reflection vector for a given incident vector self and surface normal normal.

normal must be normalized.

§Panics

Will panic if normal is not normalized when glam_assert is enabled.

Source

pub fn refract(self, normal: Vec2, eta: f32) -> Vec2

Returns the refraction direction for a given incident vector self, surface normal normal and ratio of indices of refraction, eta. When total internal reflection occurs, a zero vector will be returned.

self and normal must be normalized.

§Panics

Will panic if self or normal is not normalized when glam_assert is enabled.

Source

pub fn from_angle(angle: f32) -> Vec2

Creates a 2D vector containing [angle.cos(), angle.sin()]. This can be used in conjunction with the rotate() method, e.g. Vec2::from_angle(PI).rotate(Vec2::Y) will create the vector [-1, 0] and rotate Vec2::Y around it returning -Vec2::Y.

Examples found in repository?
examples/3d/reflection_probes.rs (line 353)
343fn rotate_camera(
344    time: Res<Time>,
345    mut camera_query: Query<&mut Transform, With<Camera3d>>,
346    app_status: Res<AppStatus>,
347) {
348    if !app_status.rotating {
349        return;
350    }
351
352    for mut transform in camera_query.iter_mut() {
353        transform.translation = Vec2::from_angle(time.delta_secs() * PI / 5.0)
354            .rotate(transform.translation.xz())
355            .extend(transform.translation.y)
356            .xzy();
357        transform.look_at(Vec3::ZERO, Vec3::Y);
358    }
359}
More examples
Hide additional examples
examples/3d/irradiance_volumes.rs (line 359)
349fn rotate_camera(
350    mut camera_query: Query<&mut Transform, With<Camera3d>>,
351    time: Res<Time>,
352    app_status: Res<AppStatus>,
353) {
354    if !app_status.rotating {
355        return;
356    }
357
358    for mut transform in camera_query.iter_mut() {
359        transform.translation = Vec2::from_angle(ROTATION_SPEED * time.delta_secs())
360            .rotate(transform.translation.xz())
361            .extend(transform.translation.y)
362            .xzy();
363        transform.look_at(Vec3::ZERO, Vec3::Y);
364    }
365}
examples/2d/cpu_draw.rs (line 120)
92fn draw(
93    my_handle: Res<MyProcGenImage>,
94    mut images: ResMut<Assets<Image>>,
95    // Used to keep track of where we are
96    mut i: Local<u32>,
97    mut draw_color: Local<Color>,
98    mut seeded_rng: ResMut<SeededRng>,
99) {
100    if *i == 0 {
101        // Generate a random color on first run.
102        *draw_color = Color::linear_rgb(
103            seeded_rng.0.random(),
104            seeded_rng.0.random(),
105            seeded_rng.0.random(),
106        );
107    }
108
109    // Get the image from Bevy's asset storage.
110    let mut image = images.get_mut(&my_handle.0).expect("Image not found");
111
112    // Compute the position of the pixel to draw.
113
114    let center = Vec2::new(IMAGE_WIDTH as f32 / 2.0, IMAGE_HEIGHT as f32 / 2.0);
115    let max_radius = IMAGE_HEIGHT.min(IMAGE_WIDTH) as f32 / 2.0;
116    let rot_speed = 0.0123;
117    let period = 0.12345;
118
119    let r = ops::sin(*i as f32 * period) * max_radius;
120    let xy = Vec2::from_angle(*i as f32 * rot_speed) * r + center;
121    let (x, y) = (xy.x as u32, xy.y as u32);
122
123    // Get the old color of that pixel.
124    let old_color = image.get_color_at(x, y).unwrap();
125
126    // If the old color is our current color, change our drawing color.
127    let tolerance = 1.0 / 255.0;
128    if old_color.distance(&draw_color) <= tolerance {
129        *draw_color = Color::linear_rgb(
130            seeded_rng.0.random(),
131            seeded_rng.0.random(),
132            seeded_rng.0.random(),
133        );
134    }
135
136    // Set the new color, but keep old alpha value from image.
137    image
138        .set_color_at(x, y, draw_color.with_alpha(old_color.alpha()))
139        .unwrap();
140
141    *i += 1;
142}
examples/3d/clustered_decal_maps.rs (line 331)
281fn spawn_decal(
282    mut commands: Commands,
283    app_status: Res<AppStatus>,
284    app_textures: Res<AppTextures>,
285    time: Res<Time>,
286    mut decal_spawn_timer: Local<Option<Timer>>,
287    mut seeded_rng: ResMut<SeededRng>,
288) {
289    // Tick the decal spawn timer. Check to see if we should spawn a new decal,
290    // and bail out if it's not yet time to.
291    let decal_spawn_timer = decal_spawn_timer
292        .get_or_insert_with(|| Timer::new(Duration::from_millis(1000), TimerMode::Repeating));
293    decal_spawn_timer.tick(time.delta());
294    if !decal_spawn_timer.just_finished() {
295        return;
296    }
297
298    // Generate a random position along the plane.
299    let decal_position = vec3(
300        seeded_rng.0.random_range(-PLANE_HALF_SIZE..PLANE_HALF_SIZE),
301        seeded_rng.0.random_range(-PLANE_HALF_SIZE..PLANE_HALF_SIZE),
302        0.0,
303    );
304
305    // Generate a random size for the decal.
306    let decal_size = seeded_rng.0.random_range(DECAL_MIN_SIZE..DECAL_MAX_SIZE);
307
308    // Generate a random rotation for the decal.
309    let theta = seeded_rng.0.random_range(0.0f32..PI);
310
311    // Now spawn the decal.
312    commands.spawn((
313        // Apply the textures.
314        ClusteredDecal {
315            base_color_texture: Some(app_textures.decal_base_color_texture.clone()),
316            normal_map_texture: Some(app_textures.decal_normal_map_texture.clone()),
317            metallic_roughness_texture: Some(
318                app_textures.decal_metallic_roughness_map_texture.clone(),
319            ),
320            emissive_texture: if app_status.emissive_decals {
321                Some(app_textures.decal_emissive_texture.clone())
322            } else {
323                None
324            },
325            ..ClusteredDecal::default()
326        },
327        // Spawn the decal at the right place. Note that the scale is initially
328        // zero; we'll animate it later.
329        Transform::from_translation(decal_position)
330            .with_scale(Vec3::ZERO)
331            .looking_to(Vec3::Z, Vec3::ZERO.with_xy(Vec2::from_angle(theta))),
332        // Create the component that tracks the animation state.
333        ExampleDecal {
334            size: decal_size,
335            state: ExampleDecalState::AnimatingIn(Timer::new(
336                DECAL_ANIMATE_IN_DURATION,
337                TimerMode::Once,
338            )),
339        },
340    ));
341}
examples/gizmos/2d_gizmos.rs (line 111)
41fn draw_example_collection(
42    mut gizmos: Gizmos,
43    mut my_gizmos: Gizmos<MyRoundGizmos>,
44    time: Res<Time>,
45) {
46    let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
47    gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
48    gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
49
50    gizmos
51        .grid_2d(
52            Isometry2d::IDENTITY,
53            UVec2::new(16, 9),
54            Vec2::new(80., 80.),
55            // Dark gray
56            LinearRgba::gray(0.05),
57        )
58        .outer_edges();
59
60    // Triangle
61    gizmos.linestrip_gradient_2d([
62        (Vec2::Y * 300., BLUE),
63        (Vec2::new(-255., -155.), RED),
64        (Vec2::new(255., -155.), LIME),
65        (Vec2::Y * 300., BLUE),
66    ]);
67
68    gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
69
70    gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
71
72    let domain = Interval::EVERYWHERE;
73    let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
74    let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
75    let times_and_colors = (0..=resolution)
76        .map(|n| n as f32 / resolution as f32)
77        .map(|t| (t - 0.5) * 600.0)
78        .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
79    gizmos.curve_gradient_2d(curve, times_and_colors);
80
81    my_gizmos
82        .rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
83        .corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
84
85    // Circles have 32 line-segments by default.
86    // You may want to increase this for larger circles.
87    my_gizmos
88        .circle_2d(Isometry2d::IDENTITY, 300., NAVY)
89        .resolution(64);
90
91    my_gizmos.ellipse_2d(
92        Rot2::radians(time.elapsed_secs() % TAU),
93        Vec2::new(100., 200.),
94        YELLOW_GREEN,
95    );
96
97    // Arcs default resolution is linearly interpolated between
98    // 1 and 32, using the arc length as scalar.
99    my_gizmos.arc_2d(
100        Rot2::radians(sin_t_scaled / 10.),
101        FRAC_PI_2,
102        310.,
103        ORANGE_RED,
104    );
105    my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
106    my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
107    my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
108
109    gizmos.arrow_2d(
110        Vec2::ZERO,
111        Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
112        YELLOW,
113    );
114
115    // You can create more complex arrows using the arrow builder.
116    gizmos
117        .arrow_2d(
118            Vec2::ZERO,
119            Vec2::from_angle(sin_t_scaled / -10.) * 50.,
120            GREEN,
121        )
122        .with_double_end()
123        .with_tip_length(10.);
124}
Source

pub fn to_angle(self) -> f32

Returns the angle (in radians) of this vector in the range [-π, +π].

The input does not need to be a unit vector however it must be non-zero.

Examples found in repository?
examples/2d/rotate_to_cursor.rs (line 56)
38fn player_movement_system(
39    mut player: Single<&mut Transform, With<Player>>,
40    camera_query: Single<(&Camera, &GlobalTransform)>,
41    window: Single<&Window>,
42) {
43    let (camera, camera_transform) = *camera_query;
44
45    if let Some(cursor_position) = window.cursor_position()
46        // Calculate a world position based on the cursor's position.
47        && let Ok(cursor_world_pos) = camera.viewport_to_world_2d(camera_transform, cursor_position)
48    {
49        // The angle an entity needs to rotate to face a point is defined
50        // by the vector between the two points (Vec2 - Vec2), which we can then
51        // turn into radians using to_angle.
52        //
53        // FRAC_PI_2 is because our sprite's ship is facing "up" so we rotate it an additional 90 degrees
54        // so that it faces the cursor.
55        player.rotation = Quat::from_rotation_z(
56            (cursor_world_pos - player.translation.xy()).to_angle() - FRAC_PI_2,
57        );
58    }
59}
Source

pub fn angle_to(self, rhs: Vec2) -> f32

Returns the angle of rotation (in radians) from self to rhs in the range [-π, +π].

The inputs do not need to be unit vectors however they must be non-zero.

Source

pub fn perp(self) -> Vec2

Returns a vector that is equal to self rotated by 90 degrees.

Source

pub fn perp_dot(self, rhs: Vec2) -> f32

The perpendicular dot product of self and rhs. Also known as the wedge product, 2D cross product, and determinant.

Source

pub fn rotate(self, rhs: Vec2) -> Vec2

Returns rhs rotated by the angle of self. If self is normalized, then this just rotation. This is what you usually want. Otherwise, it will be like a rotation with a multiplication by self’s length.

This can be used in conjunction with the from_angle() method, e.g. Vec2::from_angle(PI).rotate(Vec2::Y) will create the vector [-1, 0] and rotate Vec2::Y around it returning -Vec2::Y.

Examples found in repository?
examples/3d/reflection_probes.rs (line 354)
343fn rotate_camera(
344    time: Res<Time>,
345    mut camera_query: Query<&mut Transform, With<Camera3d>>,
346    app_status: Res<AppStatus>,
347) {
348    if !app_status.rotating {
349        return;
350    }
351
352    for mut transform in camera_query.iter_mut() {
353        transform.translation = Vec2::from_angle(time.delta_secs() * PI / 5.0)
354            .rotate(transform.translation.xz())
355            .extend(transform.translation.y)
356            .xzy();
357        transform.look_at(Vec3::ZERO, Vec3::Y);
358    }
359}
More examples
Hide additional examples
examples/3d/irradiance_volumes.rs (line 360)
349fn rotate_camera(
350    mut camera_query: Query<&mut Transform, With<Camera3d>>,
351    time: Res<Time>,
352    app_status: Res<AppStatus>,
353) {
354    if !app_status.rotating {
355        return;
356    }
357
358    for mut transform in camera_query.iter_mut() {
359        transform.translation = Vec2::from_angle(ROTATION_SPEED * time.delta_secs())
360            .rotate(transform.translation.xz())
361            .extend(transform.translation.y)
362            .xzy();
363        transform.look_at(Vec3::ZERO, Vec3::Y);
364    }
365}
Source

pub fn rotate_towards(self, rhs: Vec2, max_angle: f32) -> Vec2

Rotates towards rhs up to max_angle (in radians).

When max_angle is 0.0, the result will be equal to self. When max_angle is equal to self.angle_between(rhs), the result will be parallel to rhs. If max_angle is negative, rotates towards the exact opposite of rhs. Will not go past the target.

Source

pub fn as_dvec2(self) -> DVec2

Casts all elements of self to f64.

Source

pub fn as_i8vec2(self) -> I8Vec2

Casts all elements of self to i8.

Source

pub fn as_u8vec2(self) -> U8Vec2

Casts all elements of self to u8.

Source

pub fn as_i16vec2(self) -> I16Vec2

Casts all elements of self to i16.

Source

pub fn as_u16vec2(self) -> U16Vec2

Casts all elements of self to u16.

Source

pub fn as_ivec2(self) -> IVec2

Casts all elements of self to i32.

Source

pub fn as_uvec2(self) -> UVec2

Casts all elements of self to u32.

Examples found in repository?
examples/asset/asset_saving.rs (line 236)
208fn try_plot(
209    event: On<TryPlot>,
210    sprite: Query<(&Sprite, &Anchor, &GlobalTransform), With<SpriteToSave>>,
211    camera: Single<(&Camera, &GlobalTransform)>,
212    texture_atlases: Res<Assets<TextureAtlasLayout>>,
213    draw_color: Res<DrawColor>,
214    mut images: ResMut<Assets<Image>>,
215) {
216    let Ok((sprite, anchor, sprite_transform)) = sprite.get(event.entity) else {
217        return;
218    };
219    let (camera, camera_transform) = camera.into_inner();
220    let Ok(world_position) = camera.viewport_to_world_2d(camera_transform, event.location.position)
221    else {
222        return;
223    };
224    let relative_to_sprite = sprite_transform
225        .affine()
226        .inverse()
227        .transform_point3(world_position.extend(0.0));
228    let Ok(pixel_space) = sprite.compute_pixel_space_point(
229        relative_to_sprite.xy(),
230        *anchor,
231        &images,
232        &texture_atlases,
233    ) else {
234        return;
235    };
236    let pixel_coordinates = pixel_space.floor().as_uvec2();
237    let mut image = images.get_mut(&sprite.image).unwrap();
238    // For an actual drawing app, you'd at least draw a line from the last point, but this is
239    // simpler.
240    image
241        .set_color_at(pixel_coordinates.x, pixel_coordinates.y, draw_color.0)
242        .unwrap();
243}
More examples
Hide additional examples
examples/2d/2d_viewport_to_world.rs (line 82)
42fn controls(
43    camera_query: Single<(&mut Camera, &mut Transform, &mut Projection)>,
44    window: Single<&Window>,
45    input: Res<ButtonInput<KeyCode>>,
46    time: Res<Time<Fixed>>,
47) {
48    let (mut camera, mut transform, mut projection) = camera_query.into_inner();
49
50    let fspeed = 600.0 * time.delta_secs();
51    let uspeed = fspeed as u32;
52    let window_size = window.resolution.physical_size();
53
54    // Camera movement controls
55    if input.pressed(KeyCode::ArrowUp) {
56        transform.translation.y += fspeed;
57    }
58    if input.pressed(KeyCode::ArrowDown) {
59        transform.translation.y -= fspeed;
60    }
61    if input.pressed(KeyCode::ArrowLeft) {
62        transform.translation.x -= fspeed;
63    }
64    if input.pressed(KeyCode::ArrowRight) {
65        transform.translation.x += fspeed;
66    }
67
68    // Camera zoom controls
69    if let Projection::Orthographic(projection2d) = &mut *projection {
70        if input.pressed(KeyCode::Comma) {
71            projection2d.scale *= powf(4.0f32, time.delta_secs());
72        }
73
74        if input.pressed(KeyCode::Period) {
75            projection2d.scale *= powf(0.25f32, time.delta_secs());
76        }
77    }
78
79    if let Some(viewport) = camera.viewport.as_mut() {
80        // Reset viewport size on window resize
81        if viewport.physical_size.x > window_size.x || viewport.physical_size.y > window_size.y {
82            viewport.physical_size = (window_size.as_vec2() * 0.75).as_uvec2();
83        }
84
85        // Viewport movement controls
86        if input.pressed(KeyCode::KeyW) {
87            viewport.physical_position.y = viewport.physical_position.y.saturating_sub(uspeed);
88        }
89        if input.pressed(KeyCode::KeyS) {
90            viewport.physical_position.y += uspeed;
91        }
92        if input.pressed(KeyCode::KeyA) {
93            viewport.physical_position.x = viewport.physical_position.x.saturating_sub(uspeed);
94        }
95        if input.pressed(KeyCode::KeyD) {
96            viewport.physical_position.x += uspeed;
97        }
98
99        // Bound viewport position so it doesn't go off-screen
100        viewport.physical_position = viewport
101            .physical_position
102            .min(window_size - viewport.physical_size);
103
104        // Viewport size controls
105        if input.pressed(KeyCode::KeyI) {
106            viewport.physical_size.y = viewport.physical_size.y.saturating_sub(uspeed);
107        }
108        if input.pressed(KeyCode::KeyK) {
109            viewport.physical_size.y += uspeed;
110        }
111        if input.pressed(KeyCode::KeyJ) {
112            viewport.physical_size.x = viewport.physical_size.x.saturating_sub(uspeed);
113        }
114        if input.pressed(KeyCode::KeyL) {
115            viewport.physical_size.x += uspeed;
116        }
117
118        // Bound viewport size so it doesn't go off-screen
119        viewport.physical_size = viewport
120            .physical_size
121            .min(window_size - viewport.physical_position)
122            .max(UVec2::new(20, 20));
123    }
124}
125
126fn setup(
127    mut commands: Commands,
128    mut meshes: ResMut<Assets<Mesh>>,
129    mut materials: ResMut<Assets<ColorMaterial>>,
130    window: Single<&Window>,
131) {
132    let window_size = window.resolution.physical_size().as_vec2();
133
134    // Initialize centered, non-window-filling viewport
135    commands.spawn((
136        Camera2d,
137        Camera {
138            viewport: Some(Viewport {
139                physical_position: (window_size * 0.125).as_uvec2(),
140                physical_size: (window_size * 0.75).as_uvec2(),
141                ..default()
142            }),
143            ..default()
144        },
145    ));
146
147    // Create a minimal UI explaining how to interact with the example
148    commands.spawn((
149        Text::new(
150            "Move the mouse to see the circle follow your cursor.\n\
151                    Use the arrow keys to move the camera.\n\
152                    Use the comma and period keys to zoom in and out.\n\
153                    Use the WASD keys to move the viewport.\n\
154                    Use the IJKL keys to resize the viewport.",
155        ),
156        Node {
157            position_type: PositionType::Absolute,
158            top: px(12),
159            left: px(12),
160            ..default()
161        },
162    ));
163
164    // Add mesh to make camera movement visible
165    commands.spawn((
166        Mesh2d(meshes.add(Rectangle::new(40.0, 20.0))),
167        MeshMaterial2d(materials.add(Color::from(GREEN))),
168    ));
169
170    // Add background to visualize viewport bounds
171    commands.spawn((
172        Mesh2d(meshes.add(Rectangle::new(50000.0, 50000.0))),
173        MeshMaterial2d(materials.add(Color::linear_rgb(0.01, 0.01, 0.01))),
174        Transform::from_translation(Vec3::new(0.0, 0.0, -200.0)),
175    ));
176}
examples/stress_tests/many_cubes.rs (line 260)
161fn setup(
162    mut commands: Commands,
163    args: Res<Args>,
164    mesh_assets: ResMut<Assets<Mesh>>,
165    material_assets: ResMut<Assets<StandardMaterial>>,
166    images: ResMut<Assets<Image>>,
167) {
168    warn!(include_str!("warning_string.txt"));
169
170    let args = args.into_inner();
171    let images = images.into_inner();
172    let material_assets = material_assets.into_inner();
173    let mesh_assets = mesh_assets.into_inner();
174
175    let meshes = init_meshes(args, mesh_assets);
176
177    let material_textures = init_textures(args, images);
178    let materials = init_materials(args, &material_textures, material_assets);
179
180    // We're seeding the PRNG here to make this example deterministic for testing purposes.
181    // This isn't strictly required in practical use unless you need your app to be deterministic.
182    let mut material_rng = ChaCha8Rng::seed_from_u64(42);
183    match args.layout {
184        Layout::Sphere => {
185            // NOTE: This pattern is good for testing performance of culling as it provides roughly
186            // the same number of visible meshes regardless of the viewing angle.
187            let n_points: usize = args.instance_count;
188            // NOTE: f64 is used to avoid precision issues that produce visual artifacts in the distribution
189            let radius = WIDTH as f64 * 2.5;
190            let golden_ratio = 0.5f64 * (1.0f64 + 5.0f64.sqrt());
191            for i in 0..n_points {
192                let spherical_polar_theta_phi =
193                    fibonacci_spiral_on_sphere(golden_ratio, i, n_points);
194                let unit_sphere_p = spherical_polar_to_cartesian(spherical_polar_theta_phi);
195                let (mesh, transform) = meshes.choose(&mut material_rng).unwrap();
196                commands
197                    .spawn((
198                        Mesh3d(mesh.clone()),
199                        MeshMaterial3d(materials.choose(&mut material_rng).unwrap().clone()),
200                        Transform::from_translation((radius * unit_sphere_p).as_vec3())
201                            .looking_at(Vec3::ZERO, Vec3::Y)
202                            .mul_transform(*transform),
203                    ))
204                    .insert_if(NoFrustumCulling, || args.no_frustum_culling)
205                    .insert_if(NoAutomaticBatching, || args.no_automatic_batching)
206                    .insert_if(NoCpuCulling, || args.no_cpu_culling);
207            }
208
209            // camera
210            let mut camera = commands.spawn(Camera3d::default());
211            if args.no_indirect_drawing {
212                camera.insert(NoIndirectDrawing);
213            }
214            if args.no_cpu_culling {
215                camera.insert(NoCpuCulling);
216            }
217            if args.motion_blur {
218                camera.insert((
219                    MotionBlur {
220                        // Use an unrealistically large shutter angle so that motion blur is clearly visible.
221                        shutter_angle: 3.0,
222                        ..Default::default()
223                    },
224                    // MSAA and MotionBlur are not compatible on WebGL.
225                    #[cfg(all(
226                        feature = "webgl2",
227                        target_arch = "wasm32",
228                        not(feature = "webgpu")
229                    ))]
230                    Msaa::Off,
231                ));
232            }
233
234            // Inside-out box around the meshes onto which shadows are cast (though you cannot see them...)
235            commands.spawn((
236                Mesh3d(mesh_assets.add(Cuboid::from_size(Vec3::splat(radius as f32 * 2.2)))),
237                MeshMaterial3d(material_assets.add(StandardMaterial::from(Color::WHITE))),
238                Transform::from_scale(-Vec3::ONE),
239                NotShadowCaster,
240            ));
241        }
242        Layout::Cube => {
243            // NOTE: This pattern is good for demonstrating that frustum culling is working correctly
244            // as the number of visible meshes rises and falls depending on the viewing angle.
245            let scale = 2.5;
246
247            // Scale the width and height by the same factor so that we have the
248            // right number of instances.
249            // Because of the moiré pattern check and the fact that we're
250            // spawning 4 instances per trip around the inner loop below, we're
251            // solving the following equation for the factor variable:
252            //
253            //      4 * (9/10 * factor * width * 9/10 * factor * height) = count
254            //
255            // The solution is the value below.
256            let factor = (5.0 / 9.0) * sqrt(args.instance_count as f32)
257                / (sqrt(HEIGHT as f32) * sqrt(WIDTH as f32));
258            let dimensions = (vec2(WIDTH as f32, HEIGHT as f32) * factor)
259                .ceil()
260                .as_uvec2();
261
262            for x in 0..dimensions.x {
263                for y in 0..dimensions.y {
264                    // introduce spaces to break any kind of moiré pattern
265                    if x % 10 == 0 || y % 10 == 0 {
266                        continue;
267                    }
268                    // cube
269                    commands
270                        .spawn((
271                            Mesh3d(meshes.choose(&mut material_rng).unwrap().0.clone()),
272                            MeshMaterial3d(materials.choose(&mut material_rng).unwrap().clone()),
273                            Transform::from_xyz((x as f32) * scale, (y as f32) * scale, 0.0),
274                        ))
275                        .insert_if(NoCpuCulling, || args.no_cpu_culling);
276                    commands
277                        .spawn((
278                            Mesh3d(meshes.choose(&mut material_rng).unwrap().0.clone()),
279                            MeshMaterial3d(materials.choose(&mut material_rng).unwrap().clone()),
280                            Transform::from_xyz(
281                                (x as f32) * scale,
282                                dimensions.y as f32 * scale,
283                                (y as f32) * scale,
284                            ),
285                        ))
286                        .insert_if(NoCpuCulling, || args.no_cpu_culling);
287                    commands
288                        .spawn((
289                            Mesh3d(meshes.choose(&mut material_rng).unwrap().0.clone()),
290                            MeshMaterial3d(materials.choose(&mut material_rng).unwrap().clone()),
291                            Transform::from_xyz((x as f32) * scale, 0.0, (y as f32) * scale),
292                        ))
293                        .insert_if(NoCpuCulling, || args.no_cpu_culling);
294                    commands
295                        .spawn((
296                            Mesh3d(meshes.choose(&mut material_rng).unwrap().0.clone()),
297                            MeshMaterial3d(materials.choose(&mut material_rng).unwrap().clone()),
298                            Transform::from_xyz(0.0, (x as f32) * scale, (y as f32) * scale),
299                        ))
300                        .insert_if(NoCpuCulling, || args.no_cpu_culling);
301                }
302            }
303            // camera
304            let center = 0.5
305                * scale
306                * Vec3::new(
307                    dimensions.x as f32,
308                    dimensions.y as f32,
309                    dimensions.x as f32,
310                );
311            commands.spawn((Camera3d::default(), Transform::from_translation(center)));
312            // Inside-out box around the meshes onto which shadows are cast (though you cannot see them...)
313            commands.spawn((
314                Mesh3d(mesh_assets.add(Cuboid::from_size(2.0 * 1.1 * center))),
315                MeshMaterial3d(material_assets.add(StandardMaterial::from(Color::WHITE))),
316                Transform::from_scale(-Vec3::ONE).with_translation(center),
317                NotShadowCaster,
318            ));
319        }
320        Layout::Dense => {
321            // NOTE: This pattern is good for demonstrating a dense configuration of cubes
322            // overlapping each other, all within the camera frustum.
323            let count = args.instance_count;
324            let size = cbrt(count as f32).round();
325            let gap = 1.25;
326
327            for i in 0..count {
328                let x = i as f32 % size;
329                let y = (i as f32 / size) % size;
330                let z = i as f32 / (size * size);
331                let pos = Vec3::new(x * gap, y * gap, z * gap);
332                commands
333                    .spawn((
334                        Mesh3d(meshes.choose(&mut material_rng).unwrap().0.clone()),
335                        MeshMaterial3d(materials.choose(&mut material_rng).unwrap().clone()),
336                        Transform::from_translation(pos),
337                    ))
338                    .insert_if(NoCpuCulling, || args.no_cpu_culling);
339            }
340
341            // camera
342            commands.spawn((
343                Camera3d::default(),
344                Transform::from_xyz(100.0, 90.0, 100.0)
345                    .looking_at(Vec3::new(0.0, -10.0, 0.0), Vec3::Y),
346            ));
347        }
348    }
349
350    commands.spawn((
351        DirectionalLight {
352            shadow_maps_enabled: args.shadows,
353            ..default()
354        },
355        Transform::IDENTITY.looking_at(Vec3::new(0.0, -1.0, -1.0), Vec3::Y),
356    ));
357}
Source

pub fn as_i64vec2(self) -> I64Vec2

Casts all elements of self to i64.

Source

pub fn as_u64vec2(self) -> U64Vec2

Casts all elements of self to u64.

Source

pub fn as_isizevec2(self) -> ISizeVec2

Casts all elements of self to isize.

Source

pub fn as_usizevec2(self) -> USizeVec2

Casts all elements of self to usize.

Trait Implementations§

Source§

impl Add for Vec2

Source§

type Output = Vec2

The resulting type after applying the + operator.
Source§

fn add(self, rhs: Vec2) -> Vec2

Performs the + operation. Read more
Source§

impl Add<&Vec2> for Vec2

Source§

type Output = Vec2

The resulting type after applying the + operator.
Source§

fn add(self, rhs: &Vec2) -> Vec2

Performs the + operation. Read more
Source§

impl Add<&Vec2> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the + operator.
Source§

fn add(self, rhs: &Vec2) -> Vec2

Performs the + operation. Read more
Source§

impl Add<&Vec2> for f32

Source§

type Output = Vec2

The resulting type after applying the + operator.
Source§

fn add(self, rhs: &Vec2) -> Vec2

Performs the + operation. Read more
Source§

impl Add<&Vec2> for &f32

Source§

type Output = Vec2

The resulting type after applying the + operator.
Source§

fn add(self, rhs: &Vec2) -> Vec2

Performs the + operation. Read more
Source§

impl Add<&f32> for Vec2

Source§

type Output = Vec2

The resulting type after applying the + operator.
Source§

fn add(self, rhs: &f32) -> Vec2

Performs the + operation. Read more
Source§

impl Add<&f32> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the + operator.
Source§

fn add(self, rhs: &f32) -> Vec2

Performs the + operation. Read more
Source§

impl Add<Vec2> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the + operator.
Source§

fn add(self, rhs: Vec2) -> Vec2

Performs the + operation. Read more
Source§

impl Add<Vec2> for f32

Source§

type Output = Vec2

The resulting type after applying the + operator.
Source§

fn add(self, rhs: Vec2) -> Vec2

Performs the + operation. Read more
Source§

impl Add<Vec2> for &f32

Source§

type Output = Vec2

The resulting type after applying the + operator.
Source§

fn add(self, rhs: Vec2) -> Vec2

Performs the + operation. Read more
Source§

impl Add<f32> for Vec2

Source§

type Output = Vec2

The resulting type after applying the + operator.
Source§

fn add(self, rhs: f32) -> Vec2

Performs the + operation. Read more
Source§

impl Add<f32> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the + operator.
Source§

fn add(self, rhs: f32) -> Vec2

Performs the + operation. Read more
Source§

impl AddAssign for Vec2

Source§

fn add_assign(&mut self, rhs: Vec2)

Performs the += operation. Read more
Source§

impl AddAssign<&Vec2> for Vec2

Source§

fn add_assign(&mut self, rhs: &Vec2)

Performs the += operation. Read more
Source§

impl AddAssign<&f32> for Vec2

Source§

fn add_assign(&mut self, rhs: &f32)

Performs the += operation. Read more
Source§

impl AddAssign<f32> for Vec2

Source§

fn add_assign(&mut self, rhs: f32)

Performs the += operation. Read more
Source§

impl Animatable for Vec2

Source§

fn interpolate(a: &Vec2, b: &Vec2, t: f32) -> Vec2

Interpolates between a and b with an interpolation factor of time. Read more
Source§

fn blend(inputs: impl Iterator<Item = BlendInput<Vec2>>) -> Vec2

Blends one or more values together. Read more
Source§

impl AsMut<[f32; 2]> for Vec2

Source§

fn as_mut(&mut self) -> &mut [f32; 2]

Converts this type into a mutable reference of the (usually inferred) input type.
Source§

impl AsMutVectorParts<f32, 2> for Vec2
where Vec2: AsMut<[f32; 2]>, f32: VectorScalar,

Source§

fn as_mut_parts(&mut self) -> &mut [f32; 2]

Source§

impl AsRef<[f32; 2]> for Vec2

Source§

fn as_ref(&self) -> &[f32; 2]

Converts this type into a shared reference of the (usually inferred) input type.
Source§

impl AsRefVectorParts<f32, 2> for Vec2
where Vec2: AsRef<[f32; 2]>, f32: VectorScalar,

Source§

fn as_ref_parts(&self) -> &[f32; 2]

Source§

impl Clone for Vec2

Source§

fn clone(&self) -> Vec2

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Copy for Vec2

Source§

impl CreateFrom for Vec2

Source§

fn create_from<B>(reader: &mut Reader<B>) -> Vec2
where B: BufferRef,

Source§

impl Debug for Vec2

Source§

fn fmt(&self, fmt: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Default for Vec2

Source§

fn default() -> Vec2

Returns the “default value” for a type. Read more
Source§

impl<'de> Deserialize<'de> for Vec2

Deserialize expects a sequence of 2 values.

Source§

fn deserialize<D>( deserializer: D, ) -> Result<Vec2, <D as Deserializer<'de>>::Error>
where D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Display for Vec2

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Formats the value using the given formatter. Read more
Source§

impl Div for Vec2

Source§

type Output = Vec2

The resulting type after applying the / operator.
Source§

fn div(self, rhs: Vec2) -> Vec2

Performs the / operation. Read more
Source§

impl Div<&Vec2> for Vec2

Source§

type Output = Vec2

The resulting type after applying the / operator.
Source§

fn div(self, rhs: &Vec2) -> Vec2

Performs the / operation. Read more
Source§

impl Div<&Vec2> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the / operator.
Source§

fn div(self, rhs: &Vec2) -> Vec2

Performs the / operation. Read more
Source§

impl Div<&Vec2> for f32

Source§

type Output = Vec2

The resulting type after applying the / operator.
Source§

fn div(self, rhs: &Vec2) -> Vec2

Performs the / operation. Read more
Source§

impl Div<&Vec2> for &f32

Source§

type Output = Vec2

The resulting type after applying the / operator.
Source§

fn div(self, rhs: &Vec2) -> Vec2

Performs the / operation. Read more
Source§

impl Div<&f32> for Vec2

Source§

type Output = Vec2

The resulting type after applying the / operator.
Source§

fn div(self, rhs: &f32) -> Vec2

Performs the / operation. Read more
Source§

impl Div<&f32> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the / operator.
Source§

fn div(self, rhs: &f32) -> Vec2

Performs the / operation. Read more
Source§

impl Div<Vec2> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the / operator.
Source§

fn div(self, rhs: Vec2) -> Vec2

Performs the / operation. Read more
Source§

impl Div<Vec2> for f32

Source§

type Output = Vec2

The resulting type after applying the / operator.
Source§

fn div(self, rhs: Vec2) -> Vec2

Performs the / operation. Read more
Source§

impl Div<Vec2> for &f32

Source§

type Output = Vec2

The resulting type after applying the / operator.
Source§

fn div(self, rhs: Vec2) -> Vec2

Performs the / operation. Read more
Source§

impl Div<f32> for Vec2

Source§

type Output = Vec2

The resulting type after applying the / operator.
Source§

fn div(self, rhs: f32) -> Vec2

Performs the / operation. Read more
Source§

impl Div<f32> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the / operator.
Source§

fn div(self, rhs: f32) -> Vec2

Performs the / operation. Read more
Source§

impl DivAssign for Vec2

Source§

fn div_assign(&mut self, rhs: Vec2)

Performs the /= operation. Read more
Source§

impl DivAssign<&Vec2> for Vec2

Source§

fn div_assign(&mut self, rhs: &Vec2)

Performs the /= operation. Read more
Source§

impl DivAssign<&f32> for Vec2

Source§

fn div_assign(&mut self, rhs: &f32)

Performs the /= operation. Read more
Source§

impl DivAssign<f32> for Vec2

Source§

fn div_assign(&mut self, rhs: f32)

Performs the /= operation. Read more
Source§

impl From<(f32, f32)> for Vec2

Source§

fn from(t: (f32, f32)) -> Vec2

Converts to this type from the input type.
Source§

impl From<BVec2> for Vec2

Source§

fn from(v: BVec2) -> Vec2

Converts to this type from the input type.
Source§

impl From<Dir2> for Vec2

Source§

fn from(value: Dir2) -> Vec2

Converts to this type from the input type.
Source§

impl From<Vec2> for [f32; 2]

Source§

fn from(v: Vec2) -> [f32; 2]

Converts to this type from the input type.
Source§

impl From<Vec2> for DVec2

Source§

fn from(v: Vec2) -> DVec2

Converts to this type from the input type.
Source§

impl From<Vec2> for Isometry2d

Source§

fn from(translation: Vec2) -> Isometry2d

Converts to this type from the input type.
Source§

impl From<Vec2> for TextBounds

Source§

fn from(v: Vec2) -> TextBounds

Converts to this type from the input type.
Source§

impl From<Vec2> for ScrollPosition

Source§

fn from(value: Vec2) -> ScrollPosition

Converts to this type from the input type.
Source§

impl From<Vec2> for Anchor

Source§

fn from(value: Vec2) -> Anchor

Converts to this type from the input type.
Source§

impl From<[f32; 2]> for Vec2

Source§

fn from(a: [f32; 2]) -> Vec2

Converts to this type from the input type.
Source§

impl FromArg for Vec2

Source§

type This<'from_arg> = Vec2

The type to convert into. Read more
Source§

fn from_arg(arg: Arg<'_>) -> Result<<Vec2 as FromArg>::This<'_>, ArgError>

Creates an item from an argument. Read more
Source§

impl FromIterator<Vec2> for Polyline2d

Available on crate feature alloc only.
Source§

fn from_iter<I>(iter: I) -> Polyline2d
where I: IntoIterator<Item = Vec2>,

Creates a value from an iterator. Read more
Source§

impl FromIterator<Vec2> for Polygon

Available on crate feature alloc only.
Source§

fn from_iter<I>(iter: I) -> Polygon
where I: IntoIterator<Item = Vec2>,

Creates a value from an iterator. Read more
Source§

impl FromReflect for Vec2

Source§

fn from_reflect(reflect: &(dyn PartialReflect + 'static)) -> Option<Vec2>

Constructs a concrete instance of Self from a reflected value.
Source§

fn take_from_reflect( reflect: Box<dyn PartialReflect>, ) -> Result<Self, Box<dyn PartialReflect>>

Attempts to downcast the given value to Self using, constructing the value using from_reflect if that fails. Read more
Source§

impl FromVectorParts<f32, 2> for Vec2
where Vec2: From<[f32; 2]>, f32: VectorScalar,

Source§

fn from_parts(parts: [f32; 2]) -> Vec2

Source§

impl GetOwnership for Vec2

Source§

fn ownership() -> Ownership

Returns the ownership of Self.
Source§

impl GetTypeRegistration for Vec2

Source§

fn get_type_registration() -> TypeRegistration

Returns the default TypeRegistration for this type.
Source§

fn register_type_dependencies(registry: &mut TypeRegistry)

Registers other types needed by this type. Read more
Source§

impl Index<usize> for Vec2

Source§

type Output = f32

The returned type after indexing.
Source§

fn index(&self, index: usize) -> &<Vec2 as Index<usize>>::Output

Performs the indexing (container[index]) operation. Read more
Source§

impl IndexMut<usize> for Vec2

Source§

fn index_mut(&mut self, index: usize) -> &mut <Vec2 as Index<usize>>::Output

Performs the mutable indexing (container[index]) operation. Read more
Source§

impl IntoReturn for Vec2

Source§

fn into_return<'into_return>(self) -> Return<'into_return>
where Vec2: 'into_return,

Converts Self into a Return value.
Source§

impl Mul for Vec2

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: Vec2) -> Vec2

Performs the * operation. Read more
Source§

impl Mul<&Vec2> for Vec2

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &Vec2) -> Vec2

Performs the * operation. Read more
Source§

impl Mul<&Vec2> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &Vec2) -> Vec2

Performs the * operation. Read more
Source§

impl Mul<&Vec2> for f32

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &Vec2) -> Vec2

Performs the * operation. Read more
Source§

impl Mul<&Vec2> for &f32

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &Vec2) -> Vec2

Performs the * operation. Read more
Source§

impl Mul<&Vec2> for Mat2

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &Vec2) -> Vec2

Performs the * operation. Read more
Source§

impl Mul<&Vec2> for &Mat2

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &Vec2) -> Vec2

Performs the * operation. Read more
Source§

impl Mul<&f32> for Vec2

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &f32) -> Vec2

Performs the * operation. Read more
Source§

impl Mul<&f32> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: &f32) -> Vec2

Performs the * operation. Read more
Source§

impl Mul<Vec2> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: Vec2) -> Vec2

Performs the * operation. Read more
Source§

impl Mul<Vec2> for f32

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: Vec2) -> Vec2

Performs the * operation. Read more
Source§

impl Mul<Vec2> for &f32

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: Vec2) -> Vec2

Performs the * operation. Read more
Source§

impl Mul<Vec2> for Mat2

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: Vec2) -> <Mat2 as Mul<Vec2>>::Output

Performs the * operation. Read more
Source§

impl Mul<Vec2> for &Mat2

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: Vec2) -> Vec2

Performs the * operation. Read more
Source§

impl Mul<Vec2> for Isometry2d

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: Vec2) -> <Isometry2d as Mul<Vec2>>::Output

Performs the * operation. Read more
Source§

impl Mul<Vec2> for Rot2

Source§

fn mul(self, rhs: Vec2) -> <Rot2 as Mul<Vec2>>::Output

Rotates a Vec2 by a Rot2.

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

impl Mul<Vec2> for UiGlobalTransform

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, value: Vec2) -> Vec2

Performs the * operation. Read more
Source§

impl Mul<f32> for Vec2

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: f32) -> Vec2

Performs the * operation. Read more
Source§

impl Mul<f32> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the * operator.
Source§

fn mul(self, rhs: f32) -> Vec2

Performs the * operation. Read more
Source§

impl MulAssign for Vec2

Source§

fn mul_assign(&mut self, rhs: Vec2)

Performs the *= operation. Read more
Source§

impl MulAssign<&Vec2> for Vec2

Source§

fn mul_assign(&mut self, rhs: &Vec2)

Performs the *= operation. Read more
Source§

impl MulAssign<&f32> for Vec2

Source§

fn mul_assign(&mut self, rhs: &f32)

Performs the *= operation. Read more
Source§

impl MulAssign<f32> for Vec2

Source§

fn mul_assign(&mut self, rhs: f32)

Performs the *= operation. Read more
Source§

impl Neg for Vec2

Source§

type Output = Vec2

The resulting type after applying the - operator.
Source§

fn neg(self) -> Vec2

Performs the unary - operation. Read more
Source§

impl Neg for &Vec2

Source§

type Output = Vec2

The resulting type after applying the - operator.
Source§

fn neg(self) -> Vec2

Performs the unary - operation. Read more
Source§

impl NormedVectorSpace for Vec2

Source§

fn norm(self) -> f32

The size of this element. The return value should always be nonnegative.
Source§

fn norm_squared(self) -> f32

The squared norm of this element. Computing this is often faster than computing NormedVectorSpace::norm.
Source§

fn distance(self, rhs: Self) -> Self::Scalar

The distance between this element and another, as determined by the norm.
Source§

fn distance_squared(self, rhs: Self) -> Self::Scalar

The squared distance between this element and another, as determined by the norm. Note that this is often faster to compute in practice than NormedVectorSpace::distance.
Source§

impl PartialEq for Vec2

Source§

fn eq(&self, other: &Vec2) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 (const: unstable) · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl PartialReflect for Vec2

Source§

fn get_represented_type_info(&self) -> Option<&'static TypeInfo>

Returns the TypeInfo of the type represented by this value. Read more
Source§

fn try_apply( &mut self, value: &(dyn PartialReflect + 'static), ) -> Result<(), ApplyError>

Tries to apply a reflected value to this value. Read more
Source§

fn reflect_kind(&self) -> ReflectKind

Returns a zero-sized enumeration of “kinds” of type. Read more
Source§

fn reflect_ref(&self) -> ReflectRef<'_>

Returns an immutable enumeration of “kinds” of type. Read more
Source§

fn reflect_mut(&mut self) -> ReflectMut<'_>

Returns a mutable enumeration of “kinds” of type. Read more
Source§

fn reflect_owned(self: Box<Vec2>) -> ReflectOwned

Returns an owned enumeration of “kinds” of type. Read more
Source§

fn try_into_reflect( self: Box<Vec2>, ) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>

Attempts to cast this type to a boxed, fully-reflected value.
Source§

fn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>

Attempts to cast this type to a fully-reflected value.
Source§

fn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>

Attempts to cast this type to a mutable, fully-reflected value.
Source§

fn into_partial_reflect(self: Box<Vec2>) -> Box<dyn PartialReflect>

Casts this type to a boxed, reflected value. Read more
Source§

fn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static)

Casts this type to a reflected value. Read more
Source§

fn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static)

Casts this type to a mutable, reflected value. Read more
Source§

fn reflect_partial_eq( &self, value: &(dyn PartialReflect + 'static), ) -> Option<bool>

Returns a “partial equality” comparison result. Read more
Source§

fn reflect_partial_cmp( &self, value: &(dyn PartialReflect + 'static), ) -> Option<Ordering>

Returns a “partial comparison” result. Read more
Source§

fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>

Debug formatter for the value. Read more
Source§

fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError>

Attempts to clone Self using reflection. Read more
Source§

fn apply(&mut self, value: &(dyn PartialReflect + 'static))

Applies a reflected value to this value. Read more
Source§

fn to_dynamic(&self) -> Box<dyn PartialReflect>

Converts this reflected value into its dynamic representation based on its kind. Read more
Source§

fn reflect_clone_and_take<T>(&self) -> Result<T, ReflectCloneError>
where T: 'static, Self: Sized + TypePath,

For a type implementing PartialReflect, combines reflect_clone and take in a useful fashion, automatically constructing an appropriate ReflectCloneError if the downcast fails.
Source§

fn reflect_hash(&self) -> Option<u64>

Returns a hash of the value (which includes the type). Read more
Source§

fn is_dynamic(&self) -> bool

Indicates whether or not this type is a dynamic type. Read more
Source§

impl Pod for Vec2

Source§

impl Product for Vec2

Source§

fn product<I>(iter: I) -> Vec2
where I: Iterator<Item = Vec2>,

Takes an iterator and generates Self from the elements by multiplying the items.
Source§

impl<'a> Product<&'a Vec2> for Vec2

Source§

fn product<I>(iter: I) -> Vec2
where I: Iterator<Item = &'a Vec2>,

Takes an iterator and generates Self from the elements by multiplying the items.
Source§

impl ReadFrom for Vec2

Source§

fn read_from<B>(&mut self, reader: &mut Reader<B>)
where B: BufferRef,

Source§

impl Reflect for Vec2

Source§

fn into_any(self: Box<Vec2>) -> Box<dyn Any>

Returns the value as a Box<dyn Any>. Read more
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Returns the value as a &dyn Any. Read more
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Returns the value as a &mut dyn Any. Read more
Source§

fn into_reflect(self: Box<Vec2>) -> Box<dyn Reflect>

Casts this type to a boxed, fully-reflected value.
Source§

fn as_reflect(&self) -> &(dyn Reflect + 'static)

Casts this type to a fully-reflected value.
Source§

fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)

Casts this type to a mutable, fully-reflected value.
Source§

fn set(&mut self, value: Box<dyn Reflect>) -> Result<(), Box<dyn Reflect>>

Performs a type-checked assignment of a reflected value to this value. Read more
Source§

impl Rem for Vec2

Source§

type Output = Vec2

The resulting type after applying the % operator.
Source§

fn rem(self, rhs: Vec2) -> Vec2

Performs the % operation. Read more
Source§

impl Rem<&Vec2> for Vec2

Source§

type Output = Vec2

The resulting type after applying the % operator.
Source§

fn rem(self, rhs: &Vec2) -> Vec2

Performs the % operation. Read more
Source§

impl Rem<&Vec2> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the % operator.
Source§

fn rem(self, rhs: &Vec2) -> Vec2

Performs the % operation. Read more
Source§

impl Rem<&Vec2> for f32

Source§

type Output = Vec2

The resulting type after applying the % operator.
Source§

fn rem(self, rhs: &Vec2) -> Vec2

Performs the % operation. Read more
Source§

impl Rem<&Vec2> for &f32

Source§

type Output = Vec2

The resulting type after applying the % operator.
Source§

fn rem(self, rhs: &Vec2) -> Vec2

Performs the % operation. Read more
Source§

impl Rem<&f32> for Vec2

Source§

type Output = Vec2

The resulting type after applying the % operator.
Source§

fn rem(self, rhs: &f32) -> Vec2

Performs the % operation. Read more
Source§

impl Rem<&f32> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the % operator.
Source§

fn rem(self, rhs: &f32) -> Vec2

Performs the % operation. Read more
Source§

impl Rem<Vec2> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the % operator.
Source§

fn rem(self, rhs: Vec2) -> Vec2

Performs the % operation. Read more
Source§

impl Rem<Vec2> for f32

Source§

type Output = Vec2

The resulting type after applying the % operator.
Source§

fn rem(self, rhs: Vec2) -> Vec2

Performs the % operation. Read more
Source§

impl Rem<Vec2> for &f32

Source§

type Output = Vec2

The resulting type after applying the % operator.
Source§

fn rem(self, rhs: Vec2) -> Vec2

Performs the % operation. Read more
Source§

impl Rem<f32> for Vec2

Source§

type Output = Vec2

The resulting type after applying the % operator.
Source§

fn rem(self, rhs: f32) -> Vec2

Performs the % operation. Read more
Source§

impl Rem<f32> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the % operator.
Source§

fn rem(self, rhs: f32) -> Vec2

Performs the % operation. Read more
Source§

impl RemAssign for Vec2

Source§

fn rem_assign(&mut self, rhs: Vec2)

Performs the %= operation. Read more
Source§

impl RemAssign<&Vec2> for Vec2

Source§

fn rem_assign(&mut self, rhs: &Vec2)

Performs the %= operation. Read more
Source§

impl RemAssign<&f32> for Vec2

Source§

fn rem_assign(&mut self, rhs: &f32)

Performs the %= operation. Read more
Source§

impl RemAssign<f32> for Vec2

Source§

fn rem_assign(&mut self, rhs: f32)

Performs the %= operation. Read more
Source§

impl SampleUniform for Vec2

Source§

type Sampler = UniformVec2<UniformFloat<f32>>

The UniformSampler implementation supporting type X.
Source§

impl Serialize for Vec2

Serialize as a sequence of 2 values.

Source§

fn serialize<S>( &self, serializer: S, ) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where S: Serializer,

Serialize this value into the given Serde serializer. Read more
Source§

impl ShaderSize for Vec2
where f32: ShaderSize,

Source§

const SHADER_SIZE: NonZero<u64> = _

Represents WGSL Size (equivalent to ShaderType::min_size)
Source§

impl ShaderType for Vec2
where f32: ShaderSize,

Source§

fn min_size() -> NonZero<u64>

Represents the minimum size of Self (equivalent to GPUBufferBindingLayout.minBindingSize) Read more
Source§

fn size(&self) -> NonZero<u64>

Returns the size of Self at runtime Read more
Source§

fn assert_uniform_compat()

Source§

impl Struct for Vec2

Source§

fn field(&self, name: &str) -> Option<&(dyn PartialReflect + 'static)>

Gets a reference to the value of the field named name as a &dyn PartialReflect.
Source§

fn field_mut( &mut self, name: &str, ) -> Option<&mut (dyn PartialReflect + 'static)>

Gets a mutable reference to the value of the field named name as a &mut dyn PartialReflect.
Source§

fn field_at(&self, index: usize) -> Option<&(dyn PartialReflect + 'static)>

Gets a reference to the value of the field with index index as a &dyn PartialReflect.
Source§

fn field_at_mut( &mut self, index: usize, ) -> Option<&mut (dyn PartialReflect + 'static)>

Gets a mutable reference to the value of the field with index index as a &mut dyn PartialReflect.
Source§

fn name_at(&self, index: usize) -> Option<&str>

Gets the name of the field with index index.
Source§

fn index_of_name(&self, name: &str) -> Option<usize>

Gets the index of the field with the given name.
Source§

fn field_len(&self) -> usize

Returns the number of fields in the struct.
Source§

fn iter_fields(&self) -> FieldIter<'_>

Returns an iterator over the values of the reflectable fields for this struct.
Source§

fn to_dynamic_struct(&self) -> DynamicStruct

Creates a new DynamicStruct from this struct.
Source§

fn get_represented_struct_info(&self) -> Option<&'static StructInfo>

Will return None if TypeInfo is not available.
Source§

impl StructuralPartialEq for Vec2

Source§

impl Sub for Vec2

Source§

type Output = Vec2

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: Vec2) -> Vec2

Performs the - operation. Read more
Source§

impl Sub<&Vec2> for Vec2

Source§

type Output = Vec2

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: &Vec2) -> Vec2

Performs the - operation. Read more
Source§

impl Sub<&Vec2> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: &Vec2) -> Vec2

Performs the - operation. Read more
Source§

impl Sub<&Vec2> for f32

Source§

type Output = Vec2

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: &Vec2) -> Vec2

Performs the - operation. Read more
Source§

impl Sub<&Vec2> for &f32

Source§

type Output = Vec2

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: &Vec2) -> Vec2

Performs the - operation. Read more
Source§

impl Sub<&f32> for Vec2

Source§

type Output = Vec2

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: &f32) -> Vec2

Performs the - operation. Read more
Source§

impl Sub<&f32> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: &f32) -> Vec2

Performs the - operation. Read more
Source§

impl Sub<Vec2> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: Vec2) -> Vec2

Performs the - operation. Read more
Source§

impl Sub<Vec2> for f32

Source§

type Output = Vec2

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: Vec2) -> Vec2

Performs the - operation. Read more
Source§

impl Sub<Vec2> for &f32

Source§

type Output = Vec2

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: Vec2) -> Vec2

Performs the - operation. Read more
Source§

impl Sub<f32> for Vec2

Source§

type Output = Vec2

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: f32) -> Vec2

Performs the - operation. Read more
Source§

impl Sub<f32> for &Vec2

Source§

type Output = Vec2

The resulting type after applying the - operator.
Source§

fn sub(self, rhs: f32) -> Vec2

Performs the - operation. Read more
Source§

impl SubAssign for Vec2

Source§

fn sub_assign(&mut self, rhs: Vec2)

Performs the -= operation. Read more
Source§

impl SubAssign<&Vec2> for Vec2

Source§

fn sub_assign(&mut self, rhs: &Vec2)

Performs the -= operation. Read more
Source§

impl SubAssign<&f32> for Vec2

Source§

fn sub_assign(&mut self, rhs: &f32)

Performs the -= operation. Read more
Source§

impl SubAssign<f32> for Vec2

Source§

fn sub_assign(&mut self, rhs: f32)

Performs the -= operation. Read more
Source§

impl Sum for Vec2

Source§

fn sum<I>(iter: I) -> Vec2
where I: Iterator<Item = Vec2>,

Takes an iterator and generates Self from the elements by “summing up” the items.
Source§

impl<'a> Sum<&'a Vec2> for Vec2

Source§

fn sum<I>(iter: I) -> Vec2
where I: Iterator<Item = &'a Vec2>,

Takes an iterator and generates Self from the elements by “summing up” the items.
Source§

impl TryFrom<Vec2> for AspectRatio

Source§

type Error = AspectRatioError

The type returned in the event of a conversion error.
Source§

fn try_from( value: Vec2, ) -> Result<AspectRatio, <AspectRatio as TryFrom<Vec2>>::Error>

Performs the conversion.
Source§

impl TryFrom<Vec2> for Dir2

Source§

type Error = InvalidDirectionError

The type returned in the event of a conversion error.
Source§

fn try_from(value: Vec2) -> Result<Dir2, <Dir2 as TryFrom<Vec2>>::Error>

Performs the conversion.
Source§

impl TypePath for Vec2

Source§

fn type_path() -> &'static str

Returns the fully qualified path of the underlying type. Read more
Source§

fn short_type_path() -> &'static str

Returns a short, pretty-print enabled path to the type. Read more
Source§

fn type_ident() -> Option<&'static str>

Returns the name of the type, or None if it is anonymous. Read more
Source§

fn crate_name() -> Option<&'static str>

Returns the name of the crate the type is in, or None if it is anonymous. Read more
Source§

fn module_path() -> Option<&'static str>

Returns the path to the module the type is in, or None if it is anonymous. Read more
Source§

impl Typed for Vec2

Source§

fn type_info() -> &'static TypeInfo

Returns the compile-time info for the underlying type.
Source§

impl Vec2Swizzles for Vec2

Source§

type Vec3 = Vec3

Source§

type Vec4 = Vec4

Source§

fn xx(self) -> Vec2

Source§

fn yx(self) -> Vec2

Source§

fn yy(self) -> Vec2

Source§

fn xxx(self) -> Vec3

Source§

fn xxy(self) -> Vec3

Source§

fn xyx(self) -> Vec3

Source§

fn xyy(self) -> Vec3

Source§

fn yxx(self) -> Vec3

Source§

fn yxy(self) -> Vec3

Source§

fn yyx(self) -> Vec3

Source§

fn yyy(self) -> Vec3

Source§

fn xxxx(self) -> Vec4

Source§

fn xxxy(self) -> Vec4

Source§

fn xxyx(self) -> Vec4

Source§

fn xxyy(self) -> Vec4

Source§

fn xyxx(self) -> Vec4

Source§

fn xyxy(self) -> Vec4

Source§

fn xyyx(self) -> Vec4

Source§

fn xyyy(self) -> Vec4

Source§

fn yxxx(self) -> Vec4

Source§

fn yxxy(self) -> Vec4

Source§

fn yxyx(self) -> Vec4

Source§

fn yxyy(self) -> Vec4

Source§

fn yyxx(self) -> Vec4

Source§

fn yyxy(self) -> Vec4

Source§

fn yyyx(self) -> Vec4

Source§

fn yyyy(self) -> Vec4

Source§

fn xy(self) -> Self

Source§

impl VectorSpace for Vec2

Source§

const ZERO: Vec2 = Vec2::ZERO

The zero vector, which is the identity of addition for the vector space type.
Source§

type Scalar = f32

The scalar type of this vector space.
Source§

fn lerp(self, rhs: Self, t: Self::Scalar) -> Self

Perform vector space linear interpolation between this element and another, based on the parameter t. When t is 0, self is recovered. When t is 1, rhs is recovered. Read more
Source§

impl WriteInto for Vec2

Source§

fn write_into<B>(&self, writer: &mut Writer<B>)
where B: BufferMut,

Source§

impl Zeroable for Vec2

Source§

fn zeroed() -> Self

Auto Trait Implementations§

§

impl Freeze for Vec2

§

impl RefUnwindSafe for Vec2

§

impl Send for Vec2

§

impl Sync for Vec2

§

impl Unpin for Vec2

§

impl UnsafeUnpin for Vec2

§

impl UnwindSafe for Vec2

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> AnyBitPattern for T
where T: Pod,

Source§

impl<T, U> AsBindGroupShaderType<U> for T
where U: ShaderType, &'a T: for<'a> Into<U>,

Source§

fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U

Return the T ShaderType for self. When used in AsBindGroup derives, it is safe to assume that all images in self exist.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> Brush for T
where T: Clone + PartialEq + Default + Debug,

Source§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CheckedBitPattern for T
where T: AnyBitPattern,

Source§

type Bits = T

Self must have the same layout as the specified Bits except for the possible invalid bit patterns being checked during is_valid_bit_pattern.
Source§

fn is_valid_bit_pattern(_bits: &T) -> bool

If this function returns true, then it must be valid to reinterpret bits as &Self.
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> ConditionalSend for T
where T: Send,

Source§

impl<T> Conv for T

Source§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,

Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<S, T> Duplex<S> for T
where T: FromSample<S> + ToSample<S>,

Source§

impl<T> DynamicTypePath for T
where T: TypePath,

Source§

impl<T> DynamicTyped for T
where T: Typed,

Source§

impl<V> Ease for V
where V: VectorSpace<Scalar = f32>,

Source§

fn interpolating_curve_unbounded(start: V, end: V) -> impl Curve<V>

Given start and end values, produce a curve with unlimited domain that: Read more
Source§

impl<T> ErasedDestructor for T
where T: 'static,

Source§

impl<T> FmtForward for T

Source§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
Source§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
Source§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
Source§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
Source§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
Source§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
Source§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
Source§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
Source§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<S> FromSample<S> for S

Source§

fn from_sample_(s: S) -> S

Source§

impl<T> FromTemplate for T
where T: Clone + Default + Unpin,

Source§

type Template = T

The Template for this type.
Source§

impl<T> FromWorld for T
where T: Default,

Source§

fn from_world(_world: &mut World) -> T

Creates Self using default().

Source§

impl<S> GetField for S
where S: Struct,

Source§

fn get_field<T>(&self, name: &str) -> Option<&T>
where T: Reflect,

Gets a reference to the value of the field named name, downcast to T.
Source§

fn get_field_mut<T>(&mut self, name: &str) -> Option<&mut T>
where T: Reflect,

Gets a mutable reference to the value of the field named name, downcast to T.
Source§

impl<T> GetPath for T
where T: Reflect + ?Sized,

Source§

fn reflect_path<'p>( &self, path: impl ReflectPath<'p>, ) -> Result<&(dyn PartialReflect + 'static), ReflectPathError<'p>>

Returns a reference to the value specified by path. Read more
Source§

fn reflect_path_mut<'p>( &mut self, path: impl ReflectPath<'p>, ) -> Result<&mut (dyn PartialReflect + 'static), ReflectPathError<'p>>

Returns a mutable reference to the value specified by path. Read more
Source§

fn path<'p, T>( &self, path: impl ReflectPath<'p>, ) -> Result<&T, ReflectPathError<'p>>
where T: Reflect,

Returns a statically typed reference to the value specified by path. Read more
Source§

fn path_mut<'p, T>( &mut self, path: impl ReflectPath<'p>, ) -> Result<&mut T, ReflectPathError<'p>>
where T: Reflect,

Returns a statically typed mutable reference to the value specified by path. Read more
Source§

impl<T> GpuArrayBufferable for T

Source§

impl<V> HasTangent for V
where V: VectorSpace,

Source§

type Tangent = V

The tangent type.
Source§

impl<T, W> HasTypeWitness<W> for T
where W: MakeTypeWitness<Arg = T>, T: ?Sized,

Source§

const WITNESS: W = W::MAKE

A constant of the type witness
Source§

impl<T> HitDataExtra for T
where T: Send + Sync + Debug + Any + 'static,

Source§

impl<T> Identity for T
where T: ?Sized,

Source§

const TYPE_EQ: TypeEq<T, <T as Identity>::Type> = TypeEq::NEW

Proof that Self is the same type as Self::Type, provides methods for casting between Self and Self::Type.
Source§

type Type = T

The same type as Self, used to emulate type equality bounds (T == U) with associated type equality constraints (T: Identity<Type = U>).
Source§

impl<T> InitializeFromFunction<T> for T

Source§

fn initialize_from_function(f: fn() -> T) -> T

Create an instance of this type from an initialization function
Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self>

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

impl<T> IntoResult<T> for T

Source§

fn into_result(self) -> Result<T, RunSystemError>

Converts this type into the system output type.
Source§

impl<F, T> IntoSample<T> for F
where T: FromSample<F>,

Source§

fn into_sample(self) -> T

Source§

impl<A> Is for A
where A: Any,

Source§

fn is<T>() -> bool
where T: Any,

Checks if the current type “is” another type, using a TypeId equality comparison. This is most useful in the context of generic logic. Read more
Source§

impl<T> NoUninit for T
where T: Pod,

Source§

impl<T> NoneValue for T
where T: Default,

Source§

type NoneType = T

Source§

fn null_value() -> T

The none-equivalent value.
Source§

impl<T, Rhs> NumAssignOps<Rhs> for T
where T: AddAssign<Rhs> + SubAssign<Rhs> + MulAssign<Rhs> + DivAssign<Rhs> + RemAssign<Rhs>,

Source§

impl<T, Rhs, Output> NumOps<Rhs, Output> for T
where T: Sub<Rhs, Output = Output> + Mul<Rhs, Output = Output> + Div<Rhs, Output = Output> + Add<Rhs, Output = Output> + Rem<Rhs, Output = Output>,

Source§

impl<G> PatchFromTemplate for G
where G: FromTemplate,

Source§

type Template = <G as FromTemplate>::Template

The Template that will be patched.
Source§

fn patch<F>(func: F) -> TemplatePatch<F, <G as PatchFromTemplate>::Template>
where F: FnOnce(&mut <G as PatchFromTemplate>::Template, &mut ResolveContext<'_>),

Takes a “patch function” func, and turns it into a TemplatePatch.
Source§

impl<T> PatchTemplate for T
where T: Template,

Source§

fn patch_template<F>(func: F) -> TemplatePatch<F, T>
where F: FnOnce(&mut T, &mut ResolveContext<'_>),

Takes a “patch function” func that patches this Template, and turns it into a TemplatePatch.
Source§

impl<T> Pipe for T
where T: ?Sized,

Source§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
Source§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> R
where R: 'a,

Mutably borrows self and passes that borrow into the pipe function. Read more
Source§

fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
Source§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
Source§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows self, then passes self.as_ref() into the pipe function.
Source§

fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.as_mut() into the pipe function.
Source§

fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
Source§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
Source§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<R, P> ReadPrimitive<R> for P
where R: Read + ReadEndian<P>, P: Default,

Source§

fn read_from_little_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_little_endian().
Source§

fn read_from_big_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_big_endian().
Source§

fn read_from_native_endian(read: &mut R) -> Result<Self, Error>

Read this value from the supplied reader. Same as ReadEndian::read_from_native_endian().
Source§

impl<T, Base> RefNum<Base> for T
where T: NumOps<Base, Base> + for<'r> NumOps<&'r Base, Base>,

Source§

impl<T> Reflectable for T

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<Borrowed> SampleBorrow<Borrowed> for Borrowed
where Borrowed: SampleUniform,

Source§

fn borrow(&self) -> &Borrowed

Immutably borrows from an owned value. See Borrow::borrow
Source§

impl<T> Serialize for T
where T: Serialize + ?Sized,

Source§

fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>

Source§

fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>

Source§

impl<T> Settings for T
where T: 'static + Send + Sync,

Source§

impl<Ret> SpawnIfAsync<(), Ret> for Ret

Source§

fn spawn(self) -> Ret

Spawn the value into the dioxus runtime if it is an async block
Source§

impl<V> StableInterpolate for V
where V: NormedVectorSpace<Scalar = f32>,

Source§

fn interpolate_stable(&self, other: &V, t: f32) -> V

Interpolate between this value and the other given value using the parameter t. At t = 0.0, a value equivalent to self is recovered, while t = 1.0 recovers a value equivalent to other, with intermediate values interpolating between the two. See the trait-level documentation for details.
Source§

fn interpolate_stable_assign(&mut self, other: &Self, t: f32)

A version of interpolate_stable that assigns the result to self for convenience.
Source§

fn smooth_nudge(&mut self, target: &Self, decay_rate: f32, delta: f32)

Smoothly nudge this value towards the target at a given decay rate. The decay_rate parameter controls how fast the distance between self and target decays relative to the units of delta; the intended usage is for decay_rate to generally remain fixed, while delta is something like delta_time from an updating system. This produces a smooth following of the target that is independent of framerate. Read more
Source§

impl<T, O> SuperFrom<T> for O
where O: From<T>,

Source§

fn super_from(input: T) -> O

Convert from a type to another type.
Source§

impl<T, O, M> SuperInto<O, M> for T
where O: SuperFrom<T, M>,

Source§

fn super_into(self) -> O

Convert from a type to another type.
Source§

impl<T> Tap for T

Source§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
Source§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
Source§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
Source§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
Source§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
Source§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
Source§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
Source§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
Source§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
Source§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .tap_borrow() only in debug builds, and is erased in release builds.
Source§

fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .tap_ref() only in debug builds, and is erased in release builds.
Source§

fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
Source§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
Source§

impl<T> Template for T
where T: Clone + Default + Unpin,

Source§

type Output = T

The type of value produced by this Template.
Source§

fn build_template( &self, _context: &mut TemplateContext<'_, '_>, ) -> Result<<T as Template>::Output, BevyError>

Uses this template and the given entity context to produce a Template::Output.
Source§

fn clone_template(&self) -> T

Clones this template. See Clone.
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> ToSample<U> for T
where U: FromSample<T>,

Source§

fn to_sample_(self) -> U

Source§

impl<T> ToSmolStr for T
where T: Display + ?Sized,

Source§

impl<T> ToString for T
where T: Display + ?Sized,

Source§

fn to_string(&self) -> String

Converts the given value to a String. Read more
Source§

impl<T> TryConv for T

Source§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> TryStableInterpolate for T

Source§

type Error = Infallible

Error produced when the value cannot be interpolated.
Source§

fn try_interpolate_stable( &self, other: &T, t: f32, ) -> Result<T, <T as TryStableInterpolate>::Error>

Attempt to interpolate the value. This may fail if the two interpolation values have different units, or if the type is not interpolable.
Source§

impl<T> TypeData for T
where T: 'static + Send + Sync + Clone,

Source§

fn clone_type_data(&self) -> Box<dyn TypeData>

Creates a type-erased clone of this value.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WasmNotSend for T
where T: Send,

Source§

impl<T> WasmNotSendSync for T

Source§

impl<T> WasmNotSync for T
where T: Sync,

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more