Struct bevy::math::prelude::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 fn new(x: f32, y: f32) -> Vec2

Creates a new vector.

Examples found in repository?
examples/tools/gamepad_viewer.rs (line 13)
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
const START_SIZE: Vec2 = Vec2::new(30., 15.);
const TRIGGER_SIZE: Vec2 = Vec2::new(70., 20.);
const STICK_BOUNDS_SIZE: f32 = 100.;

const BUTTONS_X: f32 = 150.;
const BUTTONS_Y: f32 = 80.;
const STICKS_X: f32 = 150.;
const STICKS_Y: f32 = -135.;

const NORMAL_BUTTON_COLOR: Color = Color::srgb(0.3, 0.3, 0.3);
const ACTIVE_BUTTON_COLOR: Color = Color::srgb(0.5, 0., 0.5);
const LIVE_COLOR: Color = Color::srgb(0.4, 0.4, 0.4);
const DEAD_COLOR: Color = Color::srgb(0.13, 0.13, 0.13);

#[derive(Component, Deref)]
struct ReactTo(GamepadButtonType);
#[derive(Component)]
struct MoveWithAxes {
    x_axis: GamepadAxisType,
    y_axis: GamepadAxisType,
    scale: f32,
}
#[derive(Component)]
struct TextWithAxes {
    x_axis: GamepadAxisType,
    y_axis: GamepadAxisType,
}
#[derive(Component, Deref)]
struct TextWithButtonValue(GamepadButtonType);

#[derive(Component)]
struct ConnectedGamepadsText;

#[derive(Resource)]
struct ButtonMaterials {
    normal: Handle<ColorMaterial>,
    active: Handle<ColorMaterial>,
}
impl FromWorld for ButtonMaterials {
    fn from_world(world: &mut World) -> Self {
        Self {
            normal: world.add_asset(NORMAL_BUTTON_COLOR),
            active: world.add_asset(ACTIVE_BUTTON_COLOR),
        }
    }
}
#[derive(Resource)]
struct ButtonMeshes {
    circle: Mesh2dHandle,
    triangle: Mesh2dHandle,
    start_pause: Mesh2dHandle,
    trigger: Mesh2dHandle,
}
impl FromWorld for ButtonMeshes {
    fn from_world(world: &mut World) -> Self {
        Self {
            circle: world.add_asset(Circle::new(BUTTON_RADIUS)).into(),
            triangle: world
                .add_asset(RegularPolygon::new(BUTTON_RADIUS, 3))
                .into(),
            start_pause: world.add_asset(Rectangle::from_size(START_SIZE)).into(),
            trigger: world.add_asset(Rectangle::from_size(TRIGGER_SIZE)).into(),
        }
    }
}

#[derive(Bundle)]
struct GamepadButtonBundle {
    mesh_bundle: MaterialMesh2dBundle<ColorMaterial>,
    react_to: ReactTo,
}

impl GamepadButtonBundle {
    pub fn new(
        button_type: GamepadButtonType,
        mesh: Mesh2dHandle,
        material: Handle<ColorMaterial>,
        x: f32,
        y: f32,
    ) -> Self {
        Self {
            mesh_bundle: MaterialMesh2dBundle {
                mesh,
                material,
                transform: Transform::from_xyz(x, y, 0.),
                ..default()
            },
            react_to: ReactTo(button_type),
        }
    }

    pub fn with_rotation(mut self, angle: f32) -> Self {
        self.mesh_bundle.transform.rotation = Quat::from_rotation_z(angle);
        self
    }
}

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .init_resource::<ButtonMaterials>()
        .init_resource::<ButtonMeshes>()
        .add_systems(
            Startup,
            (setup, setup_sticks, setup_triggers, setup_connected),
        )
        .add_systems(
            Update,
            (
                update_buttons,
                update_button_values,
                update_axes,
                update_connected,
            ),
        )
        .run();
}

fn setup(mut commands: Commands, meshes: Res<ButtonMeshes>, materials: Res<ButtonMaterials>) {
    commands.spawn(Camera2dBundle::default());

    // Buttons

    commands
        .spawn(SpatialBundle {
            transform: Transform::from_xyz(BUTTONS_X, BUTTONS_Y, 0.),
            ..default()
        })
        .with_children(|parent| {
            parent.spawn(GamepadButtonBundle::new(
                GamepadButtonType::North,
                meshes.circle.clone(),
                materials.normal.clone(),
                0.,
                BUTTON_CLUSTER_RADIUS,
            ));
            parent.spawn(GamepadButtonBundle::new(
                GamepadButtonType::South,
                meshes.circle.clone(),
                materials.normal.clone(),
                0.,
                -BUTTON_CLUSTER_RADIUS,
            ));
            parent.spawn(GamepadButtonBundle::new(
                GamepadButtonType::West,
                meshes.circle.clone(),
                materials.normal.clone(),
                -BUTTON_CLUSTER_RADIUS,
                0.,
            ));
            parent.spawn(GamepadButtonBundle::new(
                GamepadButtonType::East,
                meshes.circle.clone(),
                materials.normal.clone(),
                BUTTON_CLUSTER_RADIUS,
                0.,
            ));
        });

    // Start and Pause

    commands.spawn(GamepadButtonBundle::new(
        GamepadButtonType::Select,
        meshes.start_pause.clone(),
        materials.normal.clone(),
        -30.,
        BUTTONS_Y,
    ));

    commands.spawn(GamepadButtonBundle::new(
        GamepadButtonType::Start,
        meshes.start_pause.clone(),
        materials.normal.clone(),
        30.,
        BUTTONS_Y,
    ));

    // D-Pad

    commands
        .spawn(SpatialBundle {
            transform: Transform::from_xyz(-BUTTONS_X, BUTTONS_Y, 0.),
            ..default()
        })
        .with_children(|parent| {
            parent.spawn(GamepadButtonBundle::new(
                GamepadButtonType::DPadUp,
                meshes.triangle.clone(),
                materials.normal.clone(),
                0.,
                BUTTON_CLUSTER_RADIUS,
            ));
            parent.spawn(
                GamepadButtonBundle::new(
                    GamepadButtonType::DPadDown,
                    meshes.triangle.clone(),
                    materials.normal.clone(),
                    0.,
                    -BUTTON_CLUSTER_RADIUS,
                )
                .with_rotation(PI),
            );
            parent.spawn(
                GamepadButtonBundle::new(
                    GamepadButtonType::DPadLeft,
                    meshes.triangle.clone(),
                    materials.normal.clone(),
                    -BUTTON_CLUSTER_RADIUS,
                    0.,
                )
                .with_rotation(PI / 2.),
            );
            parent.spawn(
                GamepadButtonBundle::new(
                    GamepadButtonType::DPadRight,
                    meshes.triangle.clone(),
                    materials.normal.clone(),
                    BUTTON_CLUSTER_RADIUS,
                    0.,
                )
                .with_rotation(-PI / 2.),
            );
        });

    // Triggers

    commands.spawn(GamepadButtonBundle::new(
        GamepadButtonType::LeftTrigger,
        meshes.trigger.clone(),
        materials.normal.clone(),
        -BUTTONS_X,
        BUTTONS_Y + 115.,
    ));

    commands.spawn(GamepadButtonBundle::new(
        GamepadButtonType::RightTrigger,
        meshes.trigger.clone(),
        materials.normal.clone(),
        BUTTONS_X,
        BUTTONS_Y + 115.,
    ));
}

fn setup_sticks(
    mut commands: Commands,
    meshes: Res<ButtonMeshes>,
    materials: Res<ButtonMaterials>,
    gamepad_settings: Res<GamepadSettings>,
) {
    let dead_upper =
        STICK_BOUNDS_SIZE * gamepad_settings.default_axis_settings.deadzone_upperbound();
    let dead_lower =
        STICK_BOUNDS_SIZE * gamepad_settings.default_axis_settings.deadzone_lowerbound();
    let dead_size = dead_lower.abs() + dead_upper.abs();
    let dead_mid = (dead_lower + dead_upper) / 2.0;

    let live_upper =
        STICK_BOUNDS_SIZE * gamepad_settings.default_axis_settings.livezone_upperbound();
    let live_lower =
        STICK_BOUNDS_SIZE * gamepad_settings.default_axis_settings.livezone_lowerbound();
    let live_size = live_lower.abs() + live_upper.abs();
    let live_mid = (live_lower + live_upper) / 2.0;

    let mut spawn_stick = |x_pos, y_pos, x_axis, y_axis, button| {
        commands
            .spawn(SpatialBundle {
                transform: Transform::from_xyz(x_pos, y_pos, 0.),
                ..default()
            })
            .with_children(|parent| {
                // full extent
                parent.spawn(SpriteBundle {
                    sprite: Sprite {
                        custom_size: Some(Vec2::splat(STICK_BOUNDS_SIZE * 2.)),
                        color: DEAD_COLOR,
                        ..default()
                    },
                    ..default()
                });
                // live zone
                parent.spawn(SpriteBundle {
                    transform: Transform::from_xyz(live_mid, live_mid, 2.),
                    sprite: Sprite {
                        custom_size: Some(Vec2::new(live_size, live_size)),
                        color: LIVE_COLOR,
                        ..default()
                    },
                    ..default()
                });
                // dead zone
                parent.spawn(SpriteBundle {
                    transform: Transform::from_xyz(dead_mid, dead_mid, 3.),
                    sprite: Sprite {
                        custom_size: Some(Vec2::new(dead_size, dead_size)),
                        color: DEAD_COLOR,
                        ..default()
                    },
                    ..default()
                });
                // text
                let style = TextStyle {
                    font_size: 16.,
                    ..default()
                };
                parent.spawn((
                    Text2dBundle {
                        transform: Transform::from_xyz(0., STICK_BOUNDS_SIZE + 2., 4.),
                        text: Text::from_sections([
                            TextSection {
                                value: format!("{:.3}", 0.),
                                style: style.clone(),
                            },
                            TextSection {
                                value: ", ".to_string(),
                                style: style.clone(),
                            },
                            TextSection {
                                value: format!("{:.3}", 0.),
                                style,
                            },
                        ]),
                        text_anchor: Anchor::BottomCenter,
                        ..default()
                    },
                    TextWithAxes { x_axis, y_axis },
                ));
                // cursor
                parent.spawn((
                    MaterialMesh2dBundle {
                        mesh: meshes.circle.clone(),
                        material: materials.normal.clone(),
                        transform: Transform::from_xyz(0., 0., 5.)
                            .with_scale(Vec2::splat(0.15).extend(1.)),
                        ..default()
                    },
                    MoveWithAxes {
                        x_axis,
                        y_axis,
                        scale: STICK_BOUNDS_SIZE,
                    },
                    ReactTo(button),
                ));
            });
    };

    spawn_stick(
        -STICKS_X,
        STICKS_Y,
        GamepadAxisType::LeftStickX,
        GamepadAxisType::LeftStickY,
        GamepadButtonType::LeftThumb,
    );
    spawn_stick(
        STICKS_X,
        STICKS_Y,
        GamepadAxisType::RightStickX,
        GamepadAxisType::RightStickY,
        GamepadButtonType::RightThumb,
    );
}
More examples
Hide additional examples
examples/2d/rotation.rs (line 5)
5
const BOUNDS: Vec2 = Vec2::new(1200.0, 640.0);
examples/games/breakout.rs (line 15)
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
const PADDLE_SIZE: Vec2 = Vec2::new(120.0, 20.0);
const GAP_BETWEEN_PADDLE_AND_FLOOR: f32 = 60.0;
const PADDLE_SPEED: f32 = 500.0;
// How close can the paddle get to the wall
const PADDLE_PADDING: f32 = 10.0;

// We set the z-value of the ball to 1 so it renders on top in the case of overlapping sprites.
const BALL_STARTING_POSITION: Vec3 = Vec3::new(0.0, -50.0, 1.0);
const BALL_DIAMETER: f32 = 30.;
const BALL_SPEED: f32 = 400.0;
const INITIAL_BALL_DIRECTION: Vec2 = Vec2::new(0.5, -0.5);

const WALL_THICKNESS: f32 = 10.0;
// x coordinates
const LEFT_WALL: f32 = -450.;
const RIGHT_WALL: f32 = 450.;
// y coordinates
const BOTTOM_WALL: f32 = -300.;
const TOP_WALL: f32 = 300.;

const BRICK_SIZE: Vec2 = Vec2::new(100., 30.);
// These values are exact
const GAP_BETWEEN_PADDLE_AND_BRICKS: f32 = 270.0;
const GAP_BETWEEN_BRICKS: f32 = 5.0;
// These values are lower bounds, as the number of bricks is computed
const GAP_BETWEEN_BRICKS_AND_CEILING: f32 = 20.0;
const GAP_BETWEEN_BRICKS_AND_SIDES: f32 = 20.0;

const SCOREBOARD_FONT_SIZE: f32 = 40.0;
const SCOREBOARD_TEXT_PADDING: Val = Val::Px(5.0);

const BACKGROUND_COLOR: Color = Color::srgb(0.9, 0.9, 0.9);
const PADDLE_COLOR: Color = Color::srgb(0.3, 0.3, 0.7);
const BALL_COLOR: Color = Color::srgb(1.0, 0.5, 0.5);
const BRICK_COLOR: Color = Color::srgb(0.5, 0.5, 1.0);
const WALL_COLOR: Color = Color::srgb(0.8, 0.8, 0.8);
const TEXT_COLOR: Color = Color::srgb(0.5, 0.5, 1.0);
const SCORE_COLOR: Color = Color::srgb(1.0, 0.5, 0.5);

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .add_plugins(
            stepping::SteppingPlugin::default()
                .add_schedule(Update)
                .add_schedule(FixedUpdate)
                .at(Val::Percent(35.0), Val::Percent(50.0)),
        )
        .insert_resource(Score(0))
        .insert_resource(ClearColor(BACKGROUND_COLOR))
        .add_event::<CollisionEvent>()
        .add_systems(Startup, setup)
        // Add our gameplay simulation systems to the fixed timestep schedule
        // which runs at 64 Hz by default
        .add_systems(
            FixedUpdate,
            (
                apply_velocity,
                move_paddle,
                check_for_collisions,
                play_collision_sound,
            )
                // `chain`ing systems together runs them in order
                .chain(),
        )
        .add_systems(Update, update_scoreboard)
        .run();
}

#[derive(Component)]
struct Paddle;

#[derive(Component)]
struct Ball;

#[derive(Component, Deref, DerefMut)]
struct Velocity(Vec2);

#[derive(Component)]
struct Collider;

#[derive(Event, Default)]
struct CollisionEvent;

#[derive(Component)]
struct Brick;

#[derive(Resource, Deref)]
struct CollisionSound(Handle<AudioSource>);

// This bundle is a collection of the components that define a "wall" in our game
#[derive(Bundle)]
struct WallBundle {
    // You can nest bundles inside of other bundles like this
    // Allowing you to compose their functionality
    sprite_bundle: SpriteBundle,
    collider: Collider,
}

/// Which side of the arena is this wall located on?
enum WallLocation {
    Left,
    Right,
    Bottom,
    Top,
}

impl WallLocation {
    /// Location of the *center* of the wall, used in `transform.translation()`
    fn position(&self) -> Vec2 {
        match self {
            WallLocation::Left => Vec2::new(LEFT_WALL, 0.),
            WallLocation::Right => Vec2::new(RIGHT_WALL, 0.),
            WallLocation::Bottom => Vec2::new(0., BOTTOM_WALL),
            WallLocation::Top => Vec2::new(0., TOP_WALL),
        }
    }

    /// (x, y) dimensions of the wall, used in `transform.scale()`
    fn size(&self) -> Vec2 {
        let arena_height = TOP_WALL - BOTTOM_WALL;
        let arena_width = RIGHT_WALL - LEFT_WALL;
        // Make sure we haven't messed up our constants
        assert!(arena_height > 0.0);
        assert!(arena_width > 0.0);

        match self {
            WallLocation::Left | WallLocation::Right => {
                Vec2::new(WALL_THICKNESS, arena_height + WALL_THICKNESS)
            }
            WallLocation::Bottom | WallLocation::Top => {
                Vec2::new(arena_width + WALL_THICKNESS, WALL_THICKNESS)
            }
        }
    }
}

impl WallBundle {
    // This "builder method" allows us to reuse logic across our wall entities,
    // making our code easier to read and less prone to bugs when we change the logic
    fn new(location: WallLocation) -> WallBundle {
        WallBundle {
            sprite_bundle: SpriteBundle {
                transform: Transform {
                    // We need to convert our Vec2 into a Vec3, by giving it a z-coordinate
                    // This is used to determine the order of our sprites
                    translation: location.position().extend(0.0),
                    // The z-scale of 2D objects must always be 1.0,
                    // or their ordering will be affected in surprising ways.
                    // See https://github.com/bevyengine/bevy/issues/4149
                    scale: location.size().extend(1.0),
                    ..default()
                },
                sprite: Sprite {
                    color: WALL_COLOR,
                    ..default()
                },
                ..default()
            },
            collider: Collider,
        }
    }
}

// This resource tracks the game's score
#[derive(Resource, Deref, DerefMut)]
struct Score(usize);

#[derive(Component)]
struct ScoreboardUi;

// Add the game's entities to our world
fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
    asset_server: Res<AssetServer>,
) {
    // Camera
    commands.spawn(Camera2dBundle::default());

    // Sound
    let ball_collision_sound = asset_server.load("sounds/breakout_collision.ogg");
    commands.insert_resource(CollisionSound(ball_collision_sound));

    // Paddle
    let paddle_y = BOTTOM_WALL + GAP_BETWEEN_PADDLE_AND_FLOOR;

    commands.spawn((
        SpriteBundle {
            transform: Transform {
                translation: Vec3::new(0.0, paddle_y, 0.0),
                scale: PADDLE_SIZE.extend(1.0),
                ..default()
            },
            sprite: Sprite {
                color: PADDLE_COLOR,
                ..default()
            },
            ..default()
        },
        Paddle,
        Collider,
    ));

    // Ball
    commands.spawn((
        MaterialMesh2dBundle {
            mesh: meshes.add(Circle::default()).into(),
            material: materials.add(BALL_COLOR),
            transform: Transform::from_translation(BALL_STARTING_POSITION)
                .with_scale(Vec2::splat(BALL_DIAMETER).extend(1.)),
            ..default()
        },
        Ball,
        Velocity(INITIAL_BALL_DIRECTION.normalize() * BALL_SPEED),
    ));

    // Scoreboard
    commands.spawn((
        ScoreboardUi,
        TextBundle::from_sections([
            TextSection::new(
                "Score: ",
                TextStyle {
                    font_size: SCOREBOARD_FONT_SIZE,
                    color: TEXT_COLOR,
                    ..default()
                },
            ),
            TextSection::from_style(TextStyle {
                font_size: SCOREBOARD_FONT_SIZE,
                color: SCORE_COLOR,
                ..default()
            }),
        ])
        .with_style(Style {
            position_type: PositionType::Absolute,
            top: SCOREBOARD_TEXT_PADDING,
            left: SCOREBOARD_TEXT_PADDING,
            ..default()
        }),
    ));

    // Walls
    commands.spawn(WallBundle::new(WallLocation::Left));
    commands.spawn(WallBundle::new(WallLocation::Right));
    commands.spawn(WallBundle::new(WallLocation::Bottom));
    commands.spawn(WallBundle::new(WallLocation::Top));

    // Bricks
    let total_width_of_bricks = (RIGHT_WALL - LEFT_WALL) - 2. * GAP_BETWEEN_BRICKS_AND_SIDES;
    let bottom_edge_of_bricks = paddle_y + GAP_BETWEEN_PADDLE_AND_BRICKS;
    let total_height_of_bricks = TOP_WALL - bottom_edge_of_bricks - GAP_BETWEEN_BRICKS_AND_CEILING;

    assert!(total_width_of_bricks > 0.0);
    assert!(total_height_of_bricks > 0.0);

    // Given the space available, compute how many rows and columns of bricks we can fit
    let n_columns = (total_width_of_bricks / (BRICK_SIZE.x + GAP_BETWEEN_BRICKS)).floor() as usize;
    let n_rows = (total_height_of_bricks / (BRICK_SIZE.y + GAP_BETWEEN_BRICKS)).floor() as usize;
    let n_vertical_gaps = n_columns - 1;

    // Because we need to round the number of columns,
    // the space on the top and sides of the bricks only captures a lower bound, not an exact value
    let center_of_bricks = (LEFT_WALL + RIGHT_WALL) / 2.0;
    let left_edge_of_bricks = center_of_bricks
        // Space taken up by the bricks
        - (n_columns as f32 / 2.0 * BRICK_SIZE.x)
        // Space taken up by the gaps
        - n_vertical_gaps as f32 / 2.0 * GAP_BETWEEN_BRICKS;

    // In Bevy, the `translation` of an entity describes the center point,
    // not its bottom-left corner
    let offset_x = left_edge_of_bricks + BRICK_SIZE.x / 2.;
    let offset_y = bottom_edge_of_bricks + BRICK_SIZE.y / 2.;

    for row in 0..n_rows {
        for column in 0..n_columns {
            let brick_position = Vec2::new(
                offset_x + column as f32 * (BRICK_SIZE.x + GAP_BETWEEN_BRICKS),
                offset_y + row as f32 * (BRICK_SIZE.y + GAP_BETWEEN_BRICKS),
            );

            // brick
            commands.spawn((
                SpriteBundle {
                    sprite: Sprite {
                        color: BRICK_COLOR,
                        ..default()
                    },
                    transform: Transform {
                        translation: brick_position.extend(0.0),
                        scale: Vec3::new(BRICK_SIZE.x, BRICK_SIZE.y, 1.0),
                        ..default()
                    },
                    ..default()
                },
                Brick,
                Collider,
            ));
        }
    }
}
examples/math/render_primitives.rs (line 154)
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
const RECTANGLE: Rectangle = Rectangle {
    half_size: Vec2::new(SMALL_2D, BIG_2D),
};
const CUBOID: Cuboid = Cuboid {
    half_size: Vec3::new(BIG_3D, SMALL_3D, BIG_3D),
};

const CIRCLE: Circle = Circle { radius: BIG_2D };
const SPHERE: Sphere = Sphere { radius: BIG_3D };

const ELLIPSE: Ellipse = Ellipse {
    half_size: Vec2::new(BIG_2D, SMALL_2D),
};

const TRIANGLE_2D: Triangle2d = Triangle2d {
    vertices: [
        Vec2::new(BIG_2D, 0.0),
        Vec2::new(0.0, BIG_2D),
        Vec2::new(-BIG_2D, 0.0),
    ],
};

const TRIANGLE_3D: Triangle3d = Triangle3d {
    vertices: [
        Vec3::new(BIG_3D, 0.0, 0.0),
        Vec3::new(0.0, BIG_3D, 0.0),
        Vec3::new(-BIG_3D, 0.0, 0.0),
    ],
};

const PLANE_2D: Plane2d = Plane2d { normal: Dir2::Y };
const PLANE_3D: Plane3d = Plane3d {
    normal: Dir3::Y,
    half_size: Vec2::new(BIG_3D, BIG_3D),
};

const LINE2D: Line2d = Line2d { direction: Dir2::X };
const LINE3D: Line3d = Line3d { direction: Dir3::X };

const SEGMENT_2D: Segment2d = Segment2d {
    direction: Dir2::X,
    half_length: BIG_2D,
};
const SEGMENT_3D: Segment3d = Segment3d {
    direction: Dir3::X,
    half_length: BIG_3D,
};

const POLYLINE_2D: Polyline2d<4> = Polyline2d {
    vertices: [
        Vec2::new(-BIG_2D, -SMALL_2D),
        Vec2::new(-SMALL_2D, SMALL_2D),
        Vec2::new(SMALL_2D, -SMALL_2D),
        Vec2::new(BIG_2D, SMALL_2D),
    ],
};
const POLYLINE_3D: Polyline3d<4> = Polyline3d {
    vertices: [
        Vec3::new(-BIG_3D, -SMALL_3D, -SMALL_3D),
        Vec3::new(SMALL_3D, SMALL_3D, 0.0),
        Vec3::new(-SMALL_3D, -SMALL_3D, 0.0),
        Vec3::new(BIG_3D, SMALL_3D, SMALL_3D),
    ],
};

const POLYGON_2D: Polygon<5> = Polygon {
    vertices: [
        Vec2::new(-BIG_2D, -SMALL_2D),
        Vec2::new(BIG_2D, -SMALL_2D),
        Vec2::new(BIG_2D, SMALL_2D),
        Vec2::new(0.0, 0.0),
        Vec2::new(-BIG_2D, SMALL_2D),
    ],
};

const REGULAR_POLYGON: RegularPolygon = RegularPolygon {
    circumcircle: Circle { radius: BIG_2D },
    sides: 5,
};

const CAPSULE_2D: Capsule2d = Capsule2d {
    radius: SMALL_2D,
    half_length: SMALL_2D,
};
const CAPSULE_3D: Capsule3d = Capsule3d {
    radius: SMALL_3D,
    half_length: SMALL_3D,
};

const CYLINDER: Cylinder = Cylinder {
    radius: SMALL_3D,
    half_height: SMALL_3D,
};

const CONE: Cone = Cone {
    radius: BIG_3D,
    height: BIG_3D,
};

const CONICAL_FRUSTUM: ConicalFrustum = ConicalFrustum {
    radius_top: BIG_3D,
    radius_bottom: SMALL_3D,
    height: BIG_3D,
};

const ANNULUS: Annulus = Annulus {
    inner_circle: Circle { radius: SMALL_2D },
    outer_circle: Circle { radius: BIG_2D },
};

const TORUS: Torus = Torus {
    minor_radius: SMALL_3D / 2.0,
    major_radius: SMALL_3D * 1.5,
};

const TETRAHEDRON: Tetrahedron = Tetrahedron {
    vertices: [
        Vec3::new(-BIG_3D, 0.0, 0.0),
        Vec3::new(BIG_3D, 0.0, 0.0),
        Vec3::new(0.0, 0.0, -BIG_3D * 1.67),
        Vec3::new(0.0, BIG_3D * 1.67, -BIG_3D * 0.5),
    ],
};

const ARC: Arc2d = Arc2d {
    radius: BIG_2D,
    half_angle: std::f32::consts::FRAC_PI_4,
};

const CIRCULAR_SECTOR: CircularSector = CircularSector {
    arc: Arc2d {
        radius: BIG_2D,
        half_angle: std::f32::consts::FRAC_PI_4,
    },
};

const CIRCULAR_SEGMENT: CircularSegment = CircularSegment {
    arc: Arc2d {
        radius: BIG_2D,
        half_angle: std::f32::consts::FRAC_PI_4,
    },
};

fn setup_cameras(mut commands: Commands) {
    let start_in_2d = true;
    let make_camera = |is_active| Camera {
        is_active,
        ..Default::default()
    };

    commands.spawn(Camera2dBundle {
        camera: make_camera(start_in_2d),
        ..Default::default()
    });

    commands.spawn(Camera3dBundle {
        camera: make_camera(!start_in_2d),
        transform: Transform::from_xyz(0.0, 10.0, 0.0).looking_at(Vec3::ZERO, Vec3::Z),
        ..Default::default()
    });
}

fn setup_ambient_light(mut ambient_light: ResMut<AmbientLight>) {
    ambient_light.brightness = 50.0;
}

fn setup_lights(mut commands: Commands) {
    commands.spawn(PointLightBundle {
        point_light: PointLight {
            intensity: 5000.0,
            ..default()
        },
        transform: Transform::from_translation(Vec3::new(-LEFT_RIGHT_OFFSET_3D, 2.0, 0.0))
            .looking_at(Vec3::new(-LEFT_RIGHT_OFFSET_3D, 0.0, 0.0), Vec3::Y),
        ..default()
    });
}

/// Marker component for header text
#[derive(Debug, Clone, Component, Default, Reflect)]
pub struct HeaderText;

/// Marker component for header node
#[derive(Debug, Clone, Component, Default, Reflect)]
pub struct HeaderNode;

fn update_active_cameras(
    state: Res<State<CameraActive>>,
    mut camera_2d: Query<(Entity, &mut Camera), With<Camera2d>>,
    mut camera_3d: Query<(Entity, &mut Camera), (With<Camera3d>, Without<Camera2d>)>,
    mut text: Query<&mut TargetCamera, With<HeaderNode>>,
) {
    let (entity_2d, mut cam_2d) = camera_2d.single_mut();
    let (entity_3d, mut cam_3d) = camera_3d.single_mut();
    let is_camera_2d_active = matches!(*state.get(), CameraActive::Dim2);

    cam_2d.is_active = is_camera_2d_active;
    cam_3d.is_active = !is_camera_2d_active;

    let active_camera = if is_camera_2d_active {
        entity_2d
    } else {
        entity_3d
    };

    text.iter_mut().for_each(|mut target_camera| {
        *target_camera = TargetCamera(active_camera);
    });
}

fn switch_cameras(current: Res<State<CameraActive>>, mut next: ResMut<NextState<CameraActive>>) {
    let next_state = match current.get() {
        CameraActive::Dim2 => CameraActive::Dim3,
        CameraActive::Dim3 => CameraActive::Dim2,
    };
    next.set(next_state);
}

fn setup_text(mut commands: Commands, cameras: Query<(Entity, &Camera)>) {
    let active_camera = cameras
        .iter()
        .find_map(|(entity, camera)| camera.is_active.then_some(entity))
        .expect("run condition ensures existence");
    let text = format!("{text}", text = PrimitiveSelected::default());
    let style = TextStyle::default();
    let instructions = "Press 'C' to switch between 2D and 3D mode\n\
        Press 'Up' or 'Down' to switch to the next/previous primitive";
    let text = [
        TextSection::new("Primitive: ", style.clone()),
        TextSection::new(text, style.clone()),
        TextSection::new("\n\n", style.clone()),
        TextSection::new(instructions, style.clone()),
        TextSection::new("\n\n", style.clone()),
        TextSection::new(
            "(If nothing is displayed, there's no rendering support yet)",
            style.clone(),
        ),
    ];

    commands
        .spawn((
            HeaderNode,
            NodeBundle {
                style: Style {
                    justify_self: JustifySelf::Center,
                    top: Val::Px(5.0),
                    ..Default::default()
                },
                ..Default::default()
            },
            TargetCamera(active_camera),
        ))
        .with_children(|parent| {
            parent.spawn((
                HeaderText,
                TextBundle::from_sections(text).with_text_justify(JustifyText::Center),
            ));
        });
}

fn update_text(
    primitive_state: Res<State<PrimitiveSelected>>,
    mut header: Query<&mut Text, With<HeaderText>>,
) {
    let new_text = format!("{text}", text = primitive_state.get());
    header.iter_mut().for_each(|mut header_text| {
        if let Some(kind) = header_text.sections.get_mut(1) {
            kind.value.clone_from(&new_text);
        };
    });
}

fn switch_to_next_primitive(
    current: Res<State<PrimitiveSelected>>,
    mut next: ResMut<NextState<PrimitiveSelected>>,
) {
    let next_state = current.get().next();
    next.set(next_state);
}

fn switch_to_previous_primitive(
    current: Res<State<PrimitiveSelected>>,
    mut next: ResMut<NextState<PrimitiveSelected>>,
) {
    let next_state = current.get().previous();
    next.set(next_state);
}

fn in_mode(active: CameraActive) -> impl Fn(Res<State<CameraActive>>) -> bool {
    move |state| *state.get() == active
}

fn draw_gizmos_2d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time: Res<Time>) {
    const POSITION: Vec2 = Vec2::new(-LEFT_RIGHT_OFFSET_2D, 0.0);
examples/ecs/observers.rs (lines 54-57)
52
53
54
55
56
57
58
59
60
    fn random(rand: &mut ChaCha8Rng) -> Self {
        Mine {
            pos: Vec2::new(
                (rand.gen::<f32>() - 0.5) * 1200.0,
                (rand.gen::<f32>() - 0.5) * 600.0,
            ),
            size: 4.0 + rand.gen::<f32>() * 16.0,
        }
    }
examples/math/custom_primitives.rs (line 37)
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
const PROJECTION_2D: Projection = Projection::Orthographic(OrthographicProjection {
    near: -1.0,
    far: 10.0,
    scale: 1.0,
    viewport_origin: Vec2::new(0.5, 0.5),
    scaling_mode: ScalingMode::AutoMax {
        max_width: 8.0,
        max_height: 20.0,
    },
    area: Rect {
        min: Vec2::NEG_ONE,
        max: Vec2::ONE,
    },
});

// The transform of the camera in 3D
const TRANSFORM_3D: Transform = Transform {
    translation: Vec3::ZERO,
    // The camera is pointing at the 3D shape
    rotation: Quat::from_xyzw(-0.14521316, -0.0, -0.0, 0.98940045),
    scale: Vec3::ONE,
};
// The projection used for the camera in 3D
const PROJECTION_3D: Projection = Projection::Perspective(PerspectiveProjection {
    fov: PI / 4.0,
    near: 0.1,
    far: 1000.0,
    aspect_ratio: 1.0,
});

/// State for tracking the currently displayed shape
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, States, Default, Reflect)]
enum CameraActive {
    #[default]
    /// The 2D shape is displayed
    Dim2,
    /// The 3D shape is displayed
    Dim3,
}

/// State for tracking the currently displayed shape
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, States, Default, Reflect)]
enum BoundingShape {
    #[default]
    /// No bounding shapes
    None,
    /// The bounding sphere or circle of the shape
    BoundingSphere,
    /// The Axis Aligned Bounding Box (AABB) of the shape
    BoundingBox,
}

/// A marker component for our 2D shapes so we can query them separately from the camera
#[derive(Component)]
struct Shape2d;

/// A marker component for our 3D shapes so we can query them separately from the camera
#[derive(Component)]
struct Shape3d;

fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .init_state::<BoundingShape>()
        .init_state::<CameraActive>()
        .add_systems(Startup, setup)
        .add_systems(
            Update,
            (
                (rotate_2d_shapes, bounding_shapes_2d).run_if(in_state(CameraActive::Dim2)),
                (rotate_3d_shapes, bounding_shapes_3d).run_if(in_state(CameraActive::Dim3)),
                update_bounding_shape.run_if(input_just_pressed(KeyCode::KeyB)),
                switch_cameras.run_if(input_just_pressed(KeyCode::Space)),
            ),
        )
        .run();
}

fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    // Spawn the camera
    commands.spawn(Camera3dBundle {
        transform: TRANSFORM_2D,
        projection: PROJECTION_2D,
        ..Default::default()
    });

    // Spawn the 2D heart
    commands.spawn((
        PbrBundle {
            // We can use the methods defined on the meshbuilder to customize the mesh.
            mesh: meshes.add(HEART.mesh().resolution(50)),
            material: materials.add(StandardMaterial {
                emissive: RED.into(),
                base_color: RED.into(),
                ..Default::default()
            }),
            transform: Transform::from_xyz(0.0, 0.0, 0.0),
            ..default()
        },
        Shape2d,
    ));

    // Spawn an extrusion of the heart.
    commands.spawn((
        PbrBundle {
            transform: Transform::from_xyz(0., -3., -10.)
                .with_rotation(Quat::from_rotation_x(-PI / 4.)),
            // We can set a custom resolution for the round parts of the extrusion aswell.
            mesh: meshes.add(EXTRUSION.mesh().resolution(50)),
            material: materials.add(StandardMaterial {
                base_color: RED.into(),
                ..Default::default()
            }),
            ..Default::default()
        },
        Shape3d,
    ));

    // Point light for 3D
    commands.spawn(PointLightBundle {
        point_light: PointLight {
            shadows_enabled: true,
            intensity: 10_000_000.,
            range: 100.0,
            shadow_depth_bias: 0.2,
            ..default()
        },
        transform: Transform::from_xyz(8.0, 12.0, 1.0),
        ..default()
    });

    // Example instructions
    commands.spawn(
        TextBundle::from_section(
            "Press 'B' to toggle between no bounding shapes, bounding boxes (AABBs) and bounding spheres / circles\n\
            Press 'Space' to switch between 3D and 2D",
            TextStyle::default(),
        )
        .with_style(Style {
            position_type: PositionType::Absolute,
            top: Val::Px(12.0),
            left: Val::Px(12.0),
            ..default()
        }),
    );
}

// Rotate the 2D shapes.
fn rotate_2d_shapes(mut shapes: Query<&mut Transform, With<Shape2d>>, time: Res<Time>) {
    let elapsed_seconds = time.elapsed_seconds();

    for mut transform in shapes.iter_mut() {
        transform.rotation = Quat::from_rotation_z(elapsed_seconds);
    }
}

// Draw bounding boxes or circles for the 2D shapes.
fn bounding_shapes_2d(
    shapes: Query<&Transform, With<Shape2d>>,
    mut gizmos: Gizmos,
    bounding_shape: Res<State<BoundingShape>>,
) {
    for transform in shapes.iter() {
        // Get the rotation angle from the 3D rotation.
        let rotation = transform.rotation.to_scaled_axis().z;

        match bounding_shape.get() {
            BoundingShape::None => (),
            BoundingShape::BoundingBox => {
                // Get the AABB of the primitive with the rotation and translation of the mesh.
                let aabb = HEART.aabb_2d(transform.translation.xy(), rotation);

                gizmos.rect_2d(aabb.center(), 0., aabb.half_size() * 2., WHITE);
            }
            BoundingShape::BoundingSphere => {
                // Get the bounding sphere of the primitive with the rotation and translation of the mesh.
                let bounding_circle = HEART.bounding_circle(transform.translation.xy(), rotation);

                gizmos
                    .circle_2d(bounding_circle.center(), bounding_circle.radius(), WHITE)
                    .resolution(64);
            }
        }
    }
}

// Rotate the 3D shapes.
fn rotate_3d_shapes(mut shapes: Query<&mut Transform, With<Shape3d>>, time: Res<Time>) {
    let delta_seconds = time.delta_seconds();

    for mut transform in shapes.iter_mut() {
        transform.rotate_y(delta_seconds);
    }
}

// Draw the AABBs or bounding spheres for the 3D shapes.
fn bounding_shapes_3d(
    shapes: Query<&Transform, With<Shape3d>>,
    mut gizmos: Gizmos,
    bounding_shape: Res<State<BoundingShape>>,
) {
    for transform in shapes.iter() {
        match bounding_shape.get() {
            BoundingShape::None => (),
            BoundingShape::BoundingBox => {
                // Get the AABB of the extrusion with the rotation and translation of the mesh.
                let aabb = EXTRUSION.aabb_3d(transform.translation, transform.rotation);

                gizmos.primitive_3d(
                    &Cuboid::from_size(Vec3::from(aabb.half_size()) * 2.),
                    aabb.center().into(),
                    Quat::IDENTITY,
                    WHITE,
                );
            }
            BoundingShape::BoundingSphere => {
                // Get the bounding sphere of the extrusion with the rotation and translation of the mesh.
                let bounding_sphere =
                    EXTRUSION.bounding_sphere(transform.translation, transform.rotation);

                gizmos.sphere(
                    bounding_sphere.center().into(),
                    Quat::IDENTITY,
                    bounding_sphere.radius(),
                    WHITE,
                );
            }
        }
    }
}

// Switch to the next bounding shape.
fn update_bounding_shape(
    current: Res<State<BoundingShape>>,
    mut next: ResMut<NextState<BoundingShape>>,
) {
    next.set(match current.get() {
        BoundingShape::None => BoundingShape::BoundingBox,
        BoundingShape::BoundingBox => BoundingShape::BoundingSphere,
        BoundingShape::BoundingSphere => BoundingShape::None,
    });
}

// Switch between 2D and 3D cameras.
fn switch_cameras(
    current: Res<State<CameraActive>>,
    mut next: ResMut<NextState<CameraActive>>,
    mut camera: Query<(&mut Transform, &mut Projection)>,
) {
    let next_state = match current.get() {
        CameraActive::Dim2 => CameraActive::Dim3,
        CameraActive::Dim3 => CameraActive::Dim2,
    };
    next.set(next_state);

    let (mut transform, mut projection) = camera.single_mut();
    match next_state {
        CameraActive::Dim2 => {
            *transform = TRANSFORM_2D;
            *projection = PROJECTION_2D;
        }
        CameraActive::Dim3 => {
            *transform = TRANSFORM_3D;
            *projection = PROJECTION_3D;
        }
    };
}

/// A custom 2D heart primitive. The heart is made up of two circles centered at `Vec2::new(±radius, 0.)` each with the same `radius`.
/// The tip of the heart connects the two circles at a 45° angle from `Vec3::NEG_Y`.
#[derive(Copy, Clone)]
struct Heart {
    /// The radius of each wing of the heart
    radius: f32,
}

// The `Primitive2d` or `Primitive3d` trait is required by almost all other traits for primitives in bevy.
// Depending on your shape, you should implement either one of them.
impl Primitive2d for Heart {}

impl Heart {
    const fn new(radius: f32) -> Self {
        Self { radius }
    }
}

// The `Measured2d` and `Measured3d` traits are used to compute the perimeter, the area or the volume of a primitive.
// If you implement `Measured2d` for a 2D primitive, `Measured3d` is automatically implemented for `Extrusion<T>`.
impl Measured2d for Heart {
    fn perimeter(&self) -> f32 {
        self.radius * (2.5 * PI + 2f32.powf(1.5) + 2.0)
    }

    fn area(&self) -> f32 {
        let circle_area = PI * self.radius * self.radius;
        let triangle_area = self.radius * self.radius * (1.0 + 2f32.sqrt()) / 2.0;
        let cutout = triangle_area - circle_area * 3.0 / 16.0;

        2.0 * circle_area + 4.0 * cutout
    }
}

// The `Bounded2d` or `Bounded3d` traits are used to compute the Axis Aligned Bounding Boxes or bounding circles / spheres for primitives.
impl Bounded2d for Heart {
    fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
        let rotation = rotation.into();
        // The center of the circle at the center of the right wing of the heart
        let circle_center = rotation * Vec2::new(self.radius, 0.0);
        // The maximum X and Y positions of the two circles of the wings of the heart.
        let max_circle = circle_center.abs() + Vec2::splat(self.radius);
        // Since the two circles of the heart are mirrored around the origin, the minimum position is the negative of the maximum.
        let min_circle = -max_circle;

        // The position of the tip at the bottom of the heart
        let tip_position = rotation * Vec2::new(0.0, -self.radius * (1. + SQRT_2));

        Aabb2d {
            min: translation + min_circle.min(tip_position),
            max: translation + max_circle.max(tip_position),
        }
    }

    fn bounding_circle(&self, translation: Vec2, rotation: impl Into<Rot2>) -> BoundingCircle {
        // The bounding circle of the heart is not at its origin. This `offset` is the offset between the center of the bounding circle and its translation.
        let offset = self.radius / 2f32.powf(1.5);
        // The center of the bounding circle
        let center = translation + rotation.into() * Vec2::new(0.0, -offset);
        // The radius of the bounding circle
        let radius = self.radius * (1.0 + 2f32.sqrt()) - offset;

        BoundingCircle::new(center, radius)
    }
}
// You can implement the `BoundedExtrusion` trait to implement `Bounded3d for Extrusion<Heart>`. There is a default implementation for both AABBs and bounding spheres,
// but you may be able to find faster solutions for your specific primitives.
impl BoundedExtrusion for Heart {}

// You can use the `Meshable` trait to create a `MeshBuilder` for the primitive.
impl Meshable for Heart {
    // The meshbuilder can be used to create the actual mesh for that primitive.
    type Output = HeartMeshBuilder;

    fn mesh(&self) -> Self::Output {
        Self::Output {
            heart: *self,
            resolution: 32,
        }
    }
}

// You can include any additional information needed for meshing the primitive in the meshbuilder.
struct HeartMeshBuilder {
    heart: Heart,
    // The resolution determines the amount of vertices used for each wing of the heart
    resolution: usize,
}

// This trait is needed so that the configuration methods of the builder of the primitive are also available for the builder for the extrusion.
// If you do not want to support these configuration options for extrusions you can just implement them for your 2D mesh builder.
trait HeartBuilder {
    /// Set the resolution for each of the wings of the heart.
    fn resolution(self, resolution: usize) -> Self;
}

impl HeartBuilder for HeartMeshBuilder {
    fn resolution(mut self, resolution: usize) -> Self {
        self.resolution = resolution;
        self
    }
}

impl HeartBuilder for ExtrusionBuilder<Heart> {
    fn resolution(mut self, resolution: usize) -> Self {
        self.base_builder.resolution = resolution;
        self
    }
}

impl MeshBuilder for HeartMeshBuilder {
    // This is where you should build the actual mesh.
    fn build(&self) -> Mesh {
        let radius = self.heart.radius;
        // The curved parts of each wing (half) of the heart have an angle of `PI * 1.25` or 225°
        let wing_angle = PI * 1.25;

        // We create buffers for the vertices, their normals and UVs, as well as the indices used to connect the vertices.
        let mut vertices = Vec::with_capacity(2 * self.resolution);
        let mut uvs = Vec::with_capacity(2 * self.resolution);
        let mut indices = Vec::with_capacity(6 * self.resolution - 9);
        // Since the heart is flat, we know all the normals are identical already.
        let normals = vec![[0f32, 0f32, 1f32]; 2 * self.resolution];

        // The point in the middle of the two curved parts of the heart
        vertices.push([0.0; 3]);
        uvs.push([0.5, 0.5]);

        // The left wing of the heart, starting from the point in the middle.
        for i in 1..self.resolution {
            let angle = (i as f32 / self.resolution as f32) * wing_angle;
            let (sin, cos) = angle.sin_cos();
            vertices.push([radius * (cos - 1.0), radius * sin, 0.0]);
            uvs.push([0.5 - (cos - 1.0) / 4., 0.5 - sin / 2.]);
        }

        // The bottom tip of the heart
        vertices.push([0.0, radius * (-1. - SQRT_2), 0.0]);
        uvs.push([0.5, 1.]);

        // The right wing of the heart, starting from the bottom most point and going towards the middle point.
        for i in 0..self.resolution - 1 {
            let angle = (i as f32 / self.resolution as f32) * wing_angle - PI / 4.;
            let (sin, cos) = angle.sin_cos();
            vertices.push([radius * (cos + 1.0), radius * sin, 0.0]);
            uvs.push([0.5 - (cos + 1.0) / 4., 0.5 - sin / 2.]);
        }

        // This is where we build all the triangles from the points created above.
        // Each triangle has one corner on the middle point with the other two being adjacent points on the perimeter of the heart.
        for i in 2..2 * self.resolution as u32 {
            indices.extend_from_slice(&[i - 1, i, 0]);
        }

        // Here, the actual `Mesh` is created. We set the indices, vertices, normals and UVs created above and specify the topology of the mesh.
        Mesh::new(
            bevy::render::mesh::PrimitiveTopology::TriangleList,
            RenderAssetUsages::default(),
        )
        .with_inserted_indices(bevy::render::mesh::Indices::U32(indices))
        .with_inserted_attribute(Mesh::ATTRIBUTE_POSITION, vertices)
        .with_inserted_attribute(Mesh::ATTRIBUTE_NORMAL, normals)
        .with_inserted_attribute(Mesh::ATTRIBUTE_UV_0, uvs)
    }
}

// The `Extrudable` trait can be used to easily implement meshing for extrusions.
impl Extrudable for HeartMeshBuilder {
    fn perimeter(&self) -> Vec<bevy::render::mesh::PerimeterSegment> {
        let resolution = self.resolution as u32;
        vec![
            // The left wing of the heart
            PerimeterSegment::Smooth {
                // The normals of the first and last vertices of smooth segments have to be specified manually.
                first_normal: Vec2::X,
                last_normal: Vec2::new(-1.0, -1.0).normalize(),
                // These indices are used to index into the `ATTRIBUTE_POSITION` vec of your 2D mesh.
                indices: (0..resolution).collect(),
            },
            // The bottom tip of the heart
            PerimeterSegment::Flat {
                indices: vec![resolution - 1, resolution, resolution + 1],
            },
            // The right wing of the heart
            PerimeterSegment::Smooth {
                first_normal: Vec2::new(1.0, -1.0).normalize(),
                last_normal: Vec2::NEG_X,
                indices: (resolution + 1..2 * resolution).chain([0]).collect(),
            },
        ]
    }
source

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

Creates a vector with all elements set to v.

Examples found in repository?
examples/2d/sprite_tile.rs (line 48)
42
43
44
45
46
47
48
49
50
fn animate(mut sprites: Query<&mut Sprite>, mut state: ResMut<AnimationState>, time: Res<Time>) {
    if state.current >= state.max || state.current <= state.min {
        state.speed = -state.speed;
    };
    state.current += state.speed * time.delta_seconds();
    for mut sprite in &mut sprites {
        sprite.custom_size = Some(Vec2::splat(state.current));
    }
}
More examples
Hide additional examples
examples/2d/bounding_2d.rs (line 338)
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
fn aabb_cast_system(
    mut gizmos: Gizmos,
    time: Res<Time>,
    mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
) {
    let ray_cast = get_and_draw_ray(&mut gizmos, &time);
    let aabb_cast = AabbCast2d {
        aabb: Aabb2d::new(Vec2::ZERO, Vec2::splat(15.)),
        ray: ray_cast,
    };

    for (volume, mut intersects) in volumes.iter_mut() {
        let toi = match *volume {
            CurrentVolume::Aabb(a) => aabb_cast.aabb_collision_at(a),
            CurrentVolume::Circle(_) => None,
        };

        **intersects = toi.is_some();
        if let Some(toi) = toi {
            gizmos.rect_2d(
                aabb_cast.ray.ray.origin + *aabb_cast.ray.ray.direction * toi,
                0.,
                aabb_cast.aabb.half_size() * 2.,
                LIME,
            );
        }
    }
}

fn bounding_circle_cast_system(
    mut gizmos: Gizmos,
    time: Res<Time>,
    mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
) {
    let ray_cast = get_and_draw_ray(&mut gizmos, &time);
    let circle_cast = BoundingCircleCast {
        circle: BoundingCircle::new(Vec2::ZERO, 15.),
        ray: ray_cast,
    };

    for (volume, mut intersects) in volumes.iter_mut() {
        let toi = match *volume {
            CurrentVolume::Aabb(_) => None,
            CurrentVolume::Circle(c) => circle_cast.circle_collision_at(c),
        };

        **intersects = toi.is_some();
        if let Some(toi) = toi {
            gizmos.circle_2d(
                circle_cast.ray.ray.origin + *circle_cast.ray.ray.direction * toi,
                circle_cast.circle.radius(),
                LIME,
            );
        }
    }
}

fn get_intersection_position(time: &Time) -> Vec2 {
    let x = (0.8 * time.elapsed_seconds()).cos() * 250.;
    let y = (0.4 * time.elapsed_seconds()).sin() * 100.;
    Vec2::new(x, y)
}

fn aabb_intersection_system(
    mut gizmos: Gizmos,
    time: Res<Time>,
    mut volumes: Query<(&CurrentVolume, &mut Intersects)>,
) {
    let center = get_intersection_position(&time);
    let aabb = Aabb2d::new(center, Vec2::splat(50.));
    gizmos.rect_2d(center, 0., aabb.half_size() * 2., YELLOW);

    for (volume, mut intersects) in volumes.iter_mut() {
        let hit = match volume {
            CurrentVolume::Aabb(a) => aabb.intersects(a),
            CurrentVolume::Circle(c) => aabb.intersects(c),
        };

        **intersects = hit;
    }
}
examples/math/custom_primitives.rs (line 346)
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
    fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
        let rotation = rotation.into();
        // The center of the circle at the center of the right wing of the heart
        let circle_center = rotation * Vec2::new(self.radius, 0.0);
        // The maximum X and Y positions of the two circles of the wings of the heart.
        let max_circle = circle_center.abs() + Vec2::splat(self.radius);
        // Since the two circles of the heart are mirrored around the origin, the minimum position is the negative of the maximum.
        let min_circle = -max_circle;

        // The position of the tip at the bottom of the heart
        let tip_position = rotation * Vec2::new(0.0, -self.radius * (1. + SQRT_2));

        Aabb2d {
            min: translation + min_circle.min(tip_position),
            max: translation + max_circle.max(tip_position),
        }
    }
examples/camera/first_person_view_model.rs (line 151)
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
fn spawn_world_model(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<StandardMaterial>>,
) {
    let floor = meshes.add(Plane3d::new(Vec3::Y, Vec2::splat(10.0)));
    let cube = meshes.add(Cuboid::new(2.0, 0.5, 1.0));
    let material = materials.add(Color::WHITE);

    // The world model camera will render the floor and the cubes spawned in this system.
    // Assigning no `RenderLayers` component defaults to layer 0.

    commands.spawn(MaterialMeshBundle {
        mesh: floor,
        material: material.clone(),
        ..default()
    });

    commands.spawn(MaterialMeshBundle {
        mesh: cube.clone(),
        material: material.clone(),
        transform: Transform::from_xyz(0.0, 0.25, -3.0),
        ..default()
    });

    commands.spawn(MaterialMeshBundle {
        mesh: cube,
        material,
        transform: Transform::from_xyz(0.75, 1.75, 0.0),
        ..default()
    });
}
examples/stress_tests/many_sprites.rs (line 63)
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
fn setup(mut commands: Commands, assets: Res<AssetServer>, color_tint: Res<ColorTint>) {
    warn!(include_str!("warning_string.txt"));

    let mut rng = rand::thread_rng();

    let tile_size = Vec2::splat(64.0);
    let map_size = Vec2::splat(320.0);

    let half_x = (map_size.x / 2.0) as i32;
    let half_y = (map_size.y / 2.0) as i32;

    let sprite_handle = assets.load("branding/icon.png");

    // Spawns the camera

    commands.spawn(Camera2dBundle::default());

    // Builds and spawns the sprites
    let mut sprites = vec![];
    for y in -half_y..half_y {
        for x in -half_x..half_x {
            let position = Vec2::new(x as f32, y as f32);
            let translation = (position * tile_size).extend(rng.gen::<f32>());
            let rotation = Quat::from_rotation_z(rng.gen::<f32>());
            let scale = Vec3::splat(rng.gen::<f32>() * 2.0);

            sprites.push(SpriteBundle {
                texture: sprite_handle.clone(),
                transform: Transform {
                    translation,
                    rotation,
                    scale,
                },
                sprite: Sprite {
                    custom_size: Some(tile_size),
                    color: if color_tint.0 {
                        COLORS[rng.gen_range(0..3)]
                    } else {
                        Color::WHITE
                    },
                    ..default()
                },
                ..default()
            });
        }
    }
    commands.spawn_batch(sprites);
}
examples/gizmos/2d_gizmos.rs (line 47)
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
fn draw_example_collection(
    mut gizmos: Gizmos,
    mut my_gizmos: Gizmos<MyRoundGizmos>,
    time: Res<Time>,
) {
    let sin = time.elapsed_seconds().sin() * 50.;
    gizmos.line_2d(Vec2::Y * -sin, Vec2::splat(-80.), RED);
    gizmos.ray_2d(Vec2::Y * sin, Vec2::splat(80.), LIME);

    gizmos
        .grid_2d(
            Vec2::ZERO,
            0.0,
            UVec2::new(16, 9),
            Vec2::new(80., 80.),
            // Dark gray
            LinearRgba::gray(0.05),
        )
        .outer_edges();

    // Triangle
    gizmos.linestrip_gradient_2d([
        (Vec2::Y * 300., BLUE),
        (Vec2::new(-255., -155.), RED),
        (Vec2::new(255., -155.), LIME),
        (Vec2::Y * 300., BLUE),
    ]);

    gizmos.rect_2d(Vec2::ZERO, 0., Vec2::splat(650.), BLACK);

    gizmos.cross_2d(Vec2::new(-160., 120.), 0., 12., FUCHSIA);

    my_gizmos
        .rounded_rect_2d(Vec2::ZERO, 0., Vec2::splat(630.), BLACK)
        .corner_radius((time.elapsed_seconds() / 3.).cos() * 100.);

    // Circles have 32 line-segments by default.
    // You may want to increase this for larger circles.
    my_gizmos.circle_2d(Vec2::ZERO, 300., NAVY).resolution(64);

    my_gizmos.ellipse_2d(
        Vec2::ZERO,
        time.elapsed_seconds() % TAU,
        Vec2::new(100., 200.),
        YELLOW_GREEN,
    );

    // Arcs default resolution is linearly interpolated between
    // 1 and 32, using the arc length as scalar.
    my_gizmos.arc_2d(Vec2::ZERO, sin / 10., PI / 2., 310., ORANGE_RED);

    gizmos.arrow_2d(
        Vec2::ZERO,
        Vec2::from_angle(sin / -10. + PI / 2.) * 50.,
        YELLOW,
    );

    // You can create more complex arrows using the arrow builder.
    gizmos
        .arrow_2d(Vec2::ZERO, Vec2::from_angle(sin / -10.) * 50., GREEN)
        .with_double_end()
        .with_tip_length(10.);
}
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]

[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/reflection_probes.rs (line 317)
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
fn rotate_camera(
    time: Res<Time>,
    mut camera_query: Query<&mut Transform, With<Camera3d>>,
    app_status: Res<AppStatus>,
) {
    if !app_status.rotating {
        return;
    }

    for mut transform in camera_query.iter_mut() {
        transform.translation = Vec2::from_angle(time.delta_seconds() * PI / 5.0)
            .rotate(transform.translation.xz())
            .extend(transform.translation.y)
            .xzy();
        transform.look_at(Vec3::ZERO, Vec3::Y);
    }
}
More examples
Hide additional examples
examples/3d/irradiance_volumes.rs (line 378)
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
fn rotate_camera(
    mut camera_query: Query<&mut Transform, With<Camera3d>>,
    time: Res<Time>,
    app_status: Res<AppStatus>,
) {
    if !app_status.rotating {
        return;
    }

    for mut transform in camera_query.iter_mut() {
        transform.translation = Vec2::from_angle(ROTATION_SPEED * time.delta_seconds())
            .rotate(transform.translation.xz())
            .extend(transform.translation.y)
            .xzy();
        transform.look_at(Vec3::ZERO, Vec3::Y);
    }
}
examples/ecs/parallel_query.rs (line 43)
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
fn move_system(mut sprites: Query<(&mut Transform, &Velocity)>) {
    // Compute the new location of each sprite in parallel on the
    // ComputeTaskPool
    //
    // This example is only for demonstrative purposes. Using a
    // ParallelIterator for an inexpensive operation like addition on only 128
    // elements will not typically be faster than just using a normal Iterator.
    // See the ParallelIterator documentation for more information on when
    // to use or not use ParallelIterator over a normal Iterator.
    sprites
        .par_iter_mut()
        .for_each(|(mut transform, velocity)| {
            transform.translation += velocity.extend(0.0);
        });
}
examples/stress_tests/many_gizmos.rs (line 73)
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
fn system(config: Res<Config>, time: Res<Time>, mut draw: Gizmos) {
    if !config.fancy {
        for _ in 0..(config.line_count / SYSTEM_COUNT) {
            draw.line(Vec3::NEG_Y, Vec3::Y, Color::BLACK);
        }
    } else {
        for i in 0..(config.line_count / SYSTEM_COUNT) {
            let angle = i as f32 / (config.line_count / SYSTEM_COUNT) as f32 * TAU;

            let vector = Vec2::from(angle.sin_cos()).extend(time.elapsed_seconds().sin());
            let start_color = LinearRgba::rgb(vector.x, vector.z, 0.5);
            let end_color = LinearRgba::rgb(-vector.z, -vector.y, 0.5);

            draw.line_gradient(vector, -vector, start_color, end_color);
        }
    }
}
examples/2d/rotation.rs (line 173)
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
fn snap_to_player_system(
    mut query: Query<&mut Transform, (With<SnapToPlayer>, Without<Player>)>,
    player_query: Query<&Transform, With<Player>>,
) {
    let player_transform = player_query.single();
    // get the player translation in 2D
    let player_translation = player_transform.translation.xy();

    for mut enemy_transform in &mut query {
        // get the vector from the enemy ship to the player ship in 2D and normalize it.
        let to_player = (player_translation - enemy_transform.translation.xy()).normalize();

        // get the quaternion to rotate from the initial enemy facing direction to the direction
        // facing the player
        let rotate_to_player = Quat::from_rotation_arc(Vec3::Y, to_player.extend(0.));

        // rotate the enemy to face the player
        enemy_transform.rotation = rotate_to_player;
    }
}
examples/camera/2d_top_down_camera.rs (line 145)
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
fn move_player(
    mut player: Query<&mut Transform, With<Player>>,
    time: Res<Time>,
    kb_input: Res<ButtonInput<KeyCode>>,
) {
    let Ok(mut player) = player.get_single_mut() else {
        return;
    };

    let mut direction = Vec2::ZERO;

    if kb_input.pressed(KeyCode::KeyW) {
        direction.y += 1.;
    }

    if kb_input.pressed(KeyCode::KeyS) {
        direction.y -= 1.;
    }

    if kb_input.pressed(KeyCode::KeyA) {
        direction.x -= 1.;
    }

    if kb_input.pressed(KeyCode::KeyD) {
        direction.x += 1.;
    }

    // Progressively update the player's position over time. Normalize the
    // direction vector to prevent it from exceeding a magnitude of 1 when
    // moving diagonally.
    let move_delta = direction.normalize_or_zero() * PLAYER_SPEED * time.delta_seconds();
    player.translation += move_delta.extend(0.);
}
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 218)
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
fn rotate_to_player_system(
    time: Res<Time>,
    mut query: Query<(&RotateToPlayer, &mut Transform), Without<Player>>,
    player_query: Query<&Transform, With<Player>>,
) {
    let player_transform = player_query.single();
    // get the player translation in 2D
    let player_translation = player_transform.translation.xy();

    for (config, mut enemy_transform) in &mut query {
        // get the enemy ship forward vector in 2D (already unit length)
        let enemy_forward = (enemy_transform.rotation * Vec3::Y).xy();

        // get the vector from the enemy ship to the player ship in 2D and normalize it.
        let to_player = (player_translation - enemy_transform.translation.xy()).normalize();

        // get the dot product between the enemy forward vector and the direction to the player.
        let forward_dot_player = enemy_forward.dot(to_player);

        // if the dot product is approximately 1.0 then the enemy is already facing the player and
        // we can early out.
        if (forward_dot_player - 1.0).abs() < f32::EPSILON {
            continue;
        }

        // get the right vector of the enemy ship in 2D (already unit length)
        let enemy_right = (enemy_transform.rotation * Vec3::X).xy();

        // get the dot product of the enemy right vector and the direction to the player ship.
        // if the dot product is negative them we need to rotate counter clockwise, if it is
        // positive we need to rotate clockwise. Note that `copysign` will still return 1.0 if the
        // dot product is 0.0 (because the player is directly behind the enemy, so perpendicular
        // with the right vector).
        let right_dot_player = enemy_right.dot(to_player);

        // determine the sign of rotation from the right dot player. We need to negate the sign
        // here as the 2D bevy co-ordinate system rotates around +Z, which is pointing out of the
        // screen. Due to the right hand rule, positive rotation around +Z is counter clockwise and
        // negative is clockwise.
        let rotation_sign = -f32::copysign(1.0, right_dot_player);

        // limit rotation so we don't overshoot the target. We need to convert our dot product to
        // an angle here so we can get an angle of rotation to clamp against.
        let max_angle = forward_dot_player.clamp(-1.0, 1.0).acos(); // clamp acos for safety

        // calculate angle of rotation with limit
        let rotation_angle =
            rotation_sign * (config.rotation_speed * time.delta_seconds()).min(max_angle);

        // rotate the enemy to face the player
        enemy_transform.rotate_z(rotation_angle);
    }
}
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 [self.x.min(rhs.x), self.y.min(rhs.y), ..].

Examples found in repository?
examples/math/custom_primitives.rs (line 354)
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
    fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
        let rotation = rotation.into();
        // The center of the circle at the center of the right wing of the heart
        let circle_center = rotation * Vec2::new(self.radius, 0.0);
        // The maximum X and Y positions of the two circles of the wings of the heart.
        let max_circle = circle_center.abs() + Vec2::splat(self.radius);
        // Since the two circles of the heart are mirrored around the origin, the minimum position is the negative of the maximum.
        let min_circle = -max_circle;

        // The position of the tip at the bottom of the heart
        let tip_position = rotation * Vec2::new(0.0, -self.radius * (1. + SQRT_2));

        Aabb2d {
            min: translation + min_circle.min(tip_position),
            max: translation + max_circle.max(tip_position),
        }
    }
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 [self.x.max(rhs.x), self.y.max(rhs.y), ..].

Examples found in repository?
examples/math/custom_primitives.rs (line 355)
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
    fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
        let rotation = rotation.into();
        // The center of the circle at the center of the right wing of the heart
        let circle_center = rotation * Vec2::new(self.radius, 0.0);
        // The maximum X and Y positions of the two circles of the wings of the heart.
        let max_circle = circle_center.abs() + Vec2::splat(self.radius);
        // Since the two circles of the heart are mirrored around the origin, the minimum position is the negative of the maximum.
        let min_circle = -max_circle;

        // The position of the tip at the bottom of the heart
        let tip_position = rotation * Vec2::new(0.0, -self.radius * (1. + SQRT_2));

        Aabb2d {
            min: translation + min_circle.min(tip_position),
            max: translation + max_circle.max(tip_position),
        }
    }
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.

§Panics

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

source

pub fn min_element(self) -> f32

Returns the horizontal minimum of self.

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

source

pub fn max_element(self) -> f32

Returns the horizontal maximum of self.

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

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 346)
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
    fn aabb_2d(&self, translation: Vec2, rotation: impl Into<Rot2>) -> Aabb2d {
        let rotation = rotation.into();
        // The center of the circle at the center of the right wing of the heart
        let circle_center = rotation * Vec2::new(self.radius, 0.0);
        // The maximum X and Y positions of the two circles of the wings of the heart.
        let max_circle = circle_center.abs() + Vec2::splat(self.radius);
        // Since the two circles of the heart are mirrored around the origin, the minimum position is the negative of the maximum.
        let min_circle = -max_circle;

        // The position of the tip at the bottom of the heart
        let tip_position = rotation * Vec2::new(0.0, -self.radius * (1. + SQRT_2));

        Aabb2d {
            min: translation + min_circle.min(tip_position),
            max: translation + max_circle.max(tip_position),
        }
    }
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.

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_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(), z.is_nan(), w.is_nan()].

source

pub fn length(self) -> f32

Computes the length of self.

Examples found in repository?
examples/games/desk_toy.rs (line 274)
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
fn start_drag(
    mut commands: Commands,
    cursor_world_pos: Res<CursorWorldPos>,
    q_bevy_logo: Query<&Transform, With<BevyLogo>>,
) {
    // If the cursor is not within the primary window skip this system
    let Some(cursor_world_pos) = cursor_world_pos.0 else {
        return;
    };

    // Get the offset from the cursor to the Bevy logo sprite
    let bevy_logo_transform = q_bevy_logo.single();
    let drag_offset = bevy_logo_transform.translation.truncate() - cursor_world_pos;

    // If the cursor is within the Bevy logo radius start the drag operation and remember the offset of the cursor from the origin
    if drag_offset.length() < BEVY_LOGO_RADIUS {
        commands.insert_resource(DragOperation(drag_offset));
    }
}

/// Stop the current drag operation
fn end_drag(mut commands: Commands) {
    commands.remove_resource::<DragOperation>();
}

/// Drag the Bevy logo
fn drag(
    drag_offset: Res<DragOperation>,
    cursor_world_pos: Res<CursorWorldPos>,
    time: Res<Time>,
    mut q_bevy_logo: Query<&mut Transform, With<BevyLogo>>,
    mut q_pupils: Query<&mut Pupil>,
) {
    // If the cursor is not within the primary window skip this system
    let Some(cursor_world_pos) = cursor_world_pos.0 else {
        return;
    };

    // Get the current Bevy logo transform
    let mut bevy_transform = q_bevy_logo.single_mut();

    // Calculate the new translation of the Bevy logo based on cursor and drag offset
    let new_translation = cursor_world_pos + drag_offset.0;

    // Calculate how fast we are dragging the Bevy logo (unit/second)
    let drag_velocity =
        (new_translation - bevy_transform.translation.truncate()) / time.delta_seconds();

    // Update the translation of Bevy logo transform to new translation
    bevy_transform.translation = new_translation.extend(bevy_transform.translation.z);

    // Add the cursor drag velocity in the opposite direction to each pupil.
    // Remember pupils are using local coordinates to move. So when the Bevy logo moves right they need to move left to
    // simulate inertia, otherwise they will move fixed to the parent.
    for mut pupil in &mut q_pupils {
        pupil.velocity -= drag_velocity;
    }
}

/// Quit when the user right clicks the Bevy logo
fn quit(
    cursor_world_pos: Res<CursorWorldPos>,
    mut app_exit: EventWriter<AppExit>,
    q_bevy_logo: Query<&Transform, With<BevyLogo>>,
) {
    // If the cursor is not within the primary window skip this system
    let Some(cursor_world_pos) = cursor_world_pos.0 else {
        return;
    };

    // If the cursor is within the Bevy logo radius send the [`AppExit`] event to quit the app
    let bevy_logo_transform = q_bevy_logo.single();
    if bevy_logo_transform
        .translation
        .truncate()
        .distance(cursor_world_pos)
        < BEVY_LOGO_RADIUS
    {
        app_exit.send(AppExit::Success);
    }
}

/// Enable transparency for the window and make it on top
fn toggle_transparency(
    mut commands: Commands,
    mut window_transparency: ResMut<WindowTransparency>,
    mut q_instructions_text: Query<&mut Visibility, With<InstructionsText>>,
    mut q_primary_window: Query<&mut Window, With<PrimaryWindow>>,
) {
    // Toggle the window transparency resource
    window_transparency.0 = !window_transparency.0;

    // Show or hide the instructions text
    for mut visibility in &mut q_instructions_text {
        *visibility = if window_transparency.0 {
            Visibility::Hidden
        } else {
            Visibility::Visible
        };
    }

    // 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
    // only if window transparency is enabled
    let mut window = q_primary_window.single_mut();
    let clear_color;
    (window.decorations, window.window_level, clear_color) = if window_transparency.0 {
        (false, WindowLevel::AlwaysOnTop, Color::NONE)
    } else {
        (true, WindowLevel::Normal, WINDOW_CLEAR_COLOR)
    };

    // Set the clear color
    commands.insert_resource(ClearColor(clear_color));
}

/// Move the pupils and bounce them around
fn move_pupils(time: Res<Time>, mut q_pupils: Query<(&mut Pupil, &mut Transform)>) {
    for (mut pupil, mut transform) in &mut q_pupils {
        // The wiggle radius is how much the pupil can move within the eye
        let wiggle_radius = pupil.eye_radius - pupil.pupil_radius;
        // Store the Z component
        let z = transform.translation.z;
        // Truncate the Z component to make the calculations be on [`Vec2`]
        let mut translation = transform.translation.truncate();
        // Decay the pupil velocity
        pupil.velocity *= (0.04f32).powf(time.delta_seconds());
        // Move the pupil
        translation += pupil.velocity * time.delta_seconds();
        // If the pupil hit the outside border of the eye, limit the translation to be within the wiggle radius and invert the velocity.
        // This is not physically accurate but it's good enough for the googly eyes effect.
        if translation.length() > wiggle_radius {
            translation = translation.normalize() * wiggle_radius;
            // Invert and decrease the velocity of the pupil when it bounces
            pupil.velocity *= -0.75;
        }
        // Update the entity transform with the new translation after reading the Z component
        transform.translation = translation.extend(z);
    }
}
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.

source

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

Computes the Euclidean distance between two points in space.

Examples found in repository?
examples/games/desk_toy.rs (line 254)
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
fn update_cursor_hit_test(
    cursor_world_pos: Res<CursorWorldPos>,
    mut q_primary_window: Query<&mut Window, With<PrimaryWindow>>,
    q_bevy_logo: Query<&Transform, With<BevyLogo>>,
) {
    let mut primary_window = q_primary_window.single_mut();

    // If the window has decorations (e.g. a border) then it should be clickable
    if primary_window.decorations {
        primary_window.cursor.hit_test = true;
        return;
    }

    // If the cursor is not within the window we don't need to update whether the window is clickable or not
    let Some(cursor_world_pos) = cursor_world_pos.0 else {
        return;
    };

    // If the cursor is within the radius of the Bevy logo make the window clickable otherwise the window is not clickable
    let bevy_logo_transform = q_bevy_logo.single();
    primary_window.cursor.hit_test = bevy_logo_transform
        .translation
        .truncate()
        .distance(cursor_world_pos)
        < BEVY_LOGO_RADIUS;
}

/// Start the drag operation and record the offset we started dragging from
fn start_drag(
    mut commands: Commands,
    cursor_world_pos: Res<CursorWorldPos>,
    q_bevy_logo: Query<&Transform, With<BevyLogo>>,
) {
    // If the cursor is not within the primary window skip this system
    let Some(cursor_world_pos) = cursor_world_pos.0 else {
        return;
    };

    // Get the offset from the cursor to the Bevy logo sprite
    let bevy_logo_transform = q_bevy_logo.single();
    let drag_offset = bevy_logo_transform.translation.truncate() - cursor_world_pos;

    // If the cursor is within the Bevy logo radius start the drag operation and remember the offset of the cursor from the origin
    if drag_offset.length() < BEVY_LOGO_RADIUS {
        commands.insert_resource(DragOperation(drag_offset));
    }
}

/// Stop the current drag operation
fn end_drag(mut commands: Commands) {
    commands.remove_resource::<DragOperation>();
}

/// Drag the Bevy logo
fn drag(
    drag_offset: Res<DragOperation>,
    cursor_world_pos: Res<CursorWorldPos>,
    time: Res<Time>,
    mut q_bevy_logo: Query<&mut Transform, With<BevyLogo>>,
    mut q_pupils: Query<&mut Pupil>,
) {
    // If the cursor is not within the primary window skip this system
    let Some(cursor_world_pos) = cursor_world_pos.0 else {
        return;
    };

    // Get the current Bevy logo transform
    let mut bevy_transform = q_bevy_logo.single_mut();

    // Calculate the new translation of the Bevy logo based on cursor and drag offset
    let new_translation = cursor_world_pos + drag_offset.0;

    // Calculate how fast we are dragging the Bevy logo (unit/second)
    let drag_velocity =
        (new_translation - bevy_transform.translation.truncate()) / time.delta_seconds();

    // Update the translation of Bevy logo transform to new translation
    bevy_transform.translation = new_translation.extend(bevy_transform.translation.z);

    // Add the cursor drag velocity in the opposite direction to each pupil.
    // Remember pupils are using local coordinates to move. So when the Bevy logo moves right they need to move left to
    // simulate inertia, otherwise they will move fixed to the parent.
    for mut pupil in &mut q_pupils {
        pupil.velocity -= drag_velocity;
    }
}

/// Quit when the user right clicks the Bevy logo
fn quit(
    cursor_world_pos: Res<CursorWorldPos>,
    mut app_exit: EventWriter<AppExit>,
    q_bevy_logo: Query<&Transform, With<BevyLogo>>,
) {
    // If the cursor is not within the primary window skip this system
    let Some(cursor_world_pos) = cursor_world_pos.0 else {
        return;
    };

    // If the cursor is within the Bevy logo radius send the [`AppExit`] event to quit the app
    let bevy_logo_transform = q_bevy_logo.single();
    if bevy_logo_transform
        .translation
        .truncate()
        .distance(cursor_world_pos)
        < BEVY_LOGO_RADIUS
    {
        app_exit.send(AppExit::Success);
    }
}
More examples
Hide additional examples
examples/ecs/observers.rs (line 29)
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
fn main() {
    App::new()
        .add_plugins(DefaultPlugins)
        .init_resource::<SpatialIndex>()
        .add_systems(Startup, setup)
        .add_systems(Update, (draw_shapes, handle_click))
        // Observers are systems that run when an event is "triggered". This observer runs whenever
        // `ExplodeMines` is triggered.
        .observe(
            |trigger: Trigger<ExplodeMines>,
             mines: Query<&Mine>,
             index: Res<SpatialIndex>,
             mut commands: Commands| {
                // You can access the trigger data via the `Observer`
                let event = trigger.event();
                // Access resources
                for e in index.get_nearby(event.pos) {
                    // Run queries
                    let mine = mines.get(e).unwrap();
                    if mine.pos.distance(event.pos) < mine.size + event.radius {
                        // And queue commands, including triggering additional events
                        // Here we trigger the `Explode` event for entity `e`
                        commands.trigger_targets(Explode, e);
                    }
                }
            },
        )
        // This observer runs whenever the `Mine` component is added to an entity, and places it in a simple spatial index.
        .observe(on_add_mine)
        // This observer runs whenever the `Mine` component is removed from an entity (including despawning it)
        // and removes it from the spatial index.
        .observe(on_remove_mine)
        .run();
}
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 not be of length zero, nor very close to zero.

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

Panics

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

Examples found in repository?
examples/2d/rotation.rs (line 169)
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
fn snap_to_player_system(
    mut query: Query<&mut Transform, (With<SnapToPlayer>, Without<Player>)>,
    player_query: Query<&Transform, With<Player>>,
) {
    let player_transform = player_query.single();
    // get the player translation in 2D
    let player_translation = player_transform.translation.xy();

    for mut enemy_transform in &mut query {
        // get the vector from the enemy ship to the player ship in 2D and normalize it.
        let to_player = (player_translation - enemy_transform.translation.xy()).normalize();

        // get the quaternion to rotate from the initial enemy facing direction to the direction
        // facing the player
        let rotate_to_player = Quat::from_rotation_arc(Vec3::Y, to_player.extend(0.));

        // rotate the enemy to face the player
        enemy_transform.rotation = rotate_to_player;
    }
}

/// Demonstrates rotating an enemy ship to face the player ship at a given rotation speed.
///
/// This method uses the vector dot product to determine if the enemy is facing the player and
/// if not, which way to rotate to face the player. The dot product on two unit length vectors
/// will return a value between -1.0 and +1.0 which tells us the following about the two vectors:
///
/// * If the result is 1.0 the vectors are pointing in the same direction, the angle between them is
///   0 degrees.
/// * If the result is 0.0 the vectors are perpendicular, the angle between them is 90 degrees.
/// * If the result is -1.0 the vectors are parallel but pointing in opposite directions, the angle
///   between them is 180 degrees.
/// * If the result is positive the vectors are pointing in roughly the same direction, the angle
///   between them is greater than 0 and less than 90 degrees.
/// * If the result is negative the vectors are pointing in roughly opposite directions, the angle
///   between them is greater than 90 and less than 180 degrees.
///
/// It is possible to get the angle by taking the arc cosine (`acos`) of the dot product. It is
/// often unnecessary to do this though. Beware than `acos` will return `NaN` if the input is less
/// than -1.0 or greater than 1.0. This can happen even when working with unit vectors due to
/// floating point precision loss, so it pays to clamp your dot product value before calling
/// `acos`.
fn rotate_to_player_system(
    time: Res<Time>,
    mut query: Query<(&RotateToPlayer, &mut Transform), Without<Player>>,
    player_query: Query<&Transform, With<Player>>,
) {
    let player_transform = player_query.single();
    // get the player translation in 2D
    let player_translation = player_transform.translation.xy();

    for (config, mut enemy_transform) in &mut query {
        // get the enemy ship forward vector in 2D (already unit length)
        let enemy_forward = (enemy_transform.rotation * Vec3::Y).xy();

        // get the vector from the enemy ship to the player ship in 2D and normalize it.
        let to_player = (player_translation - enemy_transform.translation.xy()).normalize();

        // get the dot product between the enemy forward vector and the direction to the player.
        let forward_dot_player = enemy_forward.dot(to_player);

        // if the dot product is approximately 1.0 then the enemy is already facing the player and
        // we can early out.
        if (forward_dot_player - 1.0).abs() < f32::EPSILON {
            continue;
        }

        // get the right vector of the enemy ship in 2D (already unit length)
        let enemy_right = (enemy_transform.rotation * Vec3::X).xy();

        // get the dot product of the enemy right vector and the direction to the player ship.
        // if the dot product is negative them we need to rotate counter clockwise, if it is
        // positive we need to rotate clockwise. Note that `copysign` will still return 1.0 if the
        // dot product is 0.0 (because the player is directly behind the enemy, so perpendicular
        // with the right vector).
        let right_dot_player = enemy_right.dot(to_player);

        // determine the sign of rotation from the right dot player. We need to negate the sign
        // here as the 2D bevy co-ordinate system rotates around +Z, which is pointing out of the
        // screen. Due to the right hand rule, positive rotation around +Z is counter clockwise and
        // negative is clockwise.
        let rotation_sign = -f32::copysign(1.0, right_dot_player);

        // limit rotation so we don't overshoot the target. We need to convert our dot product to
        // an angle here so we can get an angle of rotation to clamp against.
        let max_angle = forward_dot_player.clamp(-1.0, 1.0).acos(); // clamp acos for safety

        // calculate angle of rotation with limit
        let rotation_angle =
            rotation_sign * (config.rotation_speed * time.delta_seconds()).min(max_angle);

        // rotate the enemy to face the player
        enemy_transform.rotate_z(rotation_angle);
    }
}
More examples
Hide additional examples
examples/math/custom_primitives.rs (line 480)
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
    fn perimeter(&self) -> Vec<bevy::render::mesh::PerimeterSegment> {
        let resolution = self.resolution as u32;
        vec![
            // The left wing of the heart
            PerimeterSegment::Smooth {
                // The normals of the first and last vertices of smooth segments have to be specified manually.
                first_normal: Vec2::X,
                last_normal: Vec2::new(-1.0, -1.0).normalize(),
                // These indices are used to index into the `ATTRIBUTE_POSITION` vec of your 2D mesh.
                indices: (0..resolution).collect(),
            },
            // The bottom tip of the heart
            PerimeterSegment::Flat {
                indices: vec![resolution - 1, resolution, resolution + 1],
            },
            // The right wing of the heart
            PerimeterSegment::Smooth {
                first_normal: Vec2::new(1.0, -1.0).normalize(),
                last_normal: Vec2::NEG_X,
                indices: (resolution + 1..2 * resolution).chain([0]).collect(),
            },
        ]
    }
examples/games/desk_toy.rs (line 390)
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
fn move_pupils(time: Res<Time>, mut q_pupils: Query<(&mut Pupil, &mut Transform)>) {
    for (mut pupil, mut transform) in &mut q_pupils {
        // The wiggle radius is how much the pupil can move within the eye
        let wiggle_radius = pupil.eye_radius - pupil.pupil_radius;
        // Store the Z component
        let z = transform.translation.z;
        // Truncate the Z component to make the calculations be on [`Vec2`]
        let mut translation = transform.translation.truncate();
        // Decay the pupil velocity
        pupil.velocity *= (0.04f32).powf(time.delta_seconds());
        // Move the pupil
        translation += pupil.velocity * time.delta_seconds();
        // If the pupil hit the outside border of the eye, limit the translation to be within the wiggle radius and invert the velocity.
        // This is not physically accurate but it's good enough for the googly eyes effect.
        if translation.length() > wiggle_radius {
            translation = translation.normalize() * wiggle_radius;
            // Invert and decrease the velocity of the pupil when it bounces
            pupil.velocity *= -0.75;
        }
        // Update the entity transform with the new translation after reading the Z component
        transform.translation = translation.extend(z);
    }
}
examples/games/breakout.rs (line 230)
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
fn setup(
    mut commands: Commands,
    mut meshes: ResMut<Assets<Mesh>>,
    mut materials: ResMut<Assets<ColorMaterial>>,
    asset_server: Res<AssetServer>,
) {
    // Camera
    commands.spawn(Camera2dBundle::default());

    // Sound
    let ball_collision_sound = asset_server.load("sounds/breakout_collision.ogg");
    commands.insert_resource(CollisionSound(ball_collision_sound));

    // Paddle
    let paddle_y = BOTTOM_WALL + GAP_BETWEEN_PADDLE_AND_FLOOR;

    commands.spawn((
        SpriteBundle {
            transform: Transform {
                translation: Vec3::new(0.0, paddle_y, 0.0),
                scale: PADDLE_SIZE.extend(1.0),
                ..default()
            },
            sprite: Sprite {
                color: PADDLE_COLOR,
                ..default()
            },
            ..default()
        },
        Paddle,
        Collider,
    ));

    // Ball
    commands.spawn((
        MaterialMesh2dBundle {
            mesh: meshes.add(Circle::default()).into(),
            material: materials.add(BALL_COLOR),
            transform: Transform::from_translation(BALL_STARTING_POSITION)
                .with_scale(Vec2::splat(BALL_DIAMETER).extend(1.)),
            ..default()
        },
        Ball,
        Velocity(INITIAL_BALL_DIRECTION.normalize() * BALL_SPEED),
    ));

    // Scoreboard
    commands.spawn((
        ScoreboardUi,
        TextBundle::from_sections([
            TextSection::new(
                "Score: ",
                TextStyle {
                    font_size: SCOREBOARD_FONT_SIZE,
                    color: TEXT_COLOR,
                    ..default()
                },
            ),
            TextSection::from_style(TextStyle {
                font_size: SCOREBOARD_FONT_SIZE,
                color: SCORE_COLOR,
                ..default()
            }),
        ])
        .with_style(Style {
            position_type: PositionType::Absolute,
            top: SCOREBOARD_TEXT_PADDING,
            left: SCOREBOARD_TEXT_PADDING,
            ..default()
        }),
    ));

    // Walls
    commands.spawn(WallBundle::new(WallLocation::Left));
    commands.spawn(WallBundle::new(WallLocation::Right));
    commands.spawn(WallBundle::new(WallLocation::Bottom));
    commands.spawn(WallBundle::new(WallLocation::Top));

    // Bricks
    let total_width_of_bricks = (RIGHT_WALL - LEFT_WALL) - 2. * GAP_BETWEEN_BRICKS_AND_SIDES;
    let bottom_edge_of_bricks = paddle_y + GAP_BETWEEN_PADDLE_AND_BRICKS;
    let total_height_of_bricks = TOP_WALL - bottom_edge_of_bricks - GAP_BETWEEN_BRICKS_AND_CEILING;

    assert!(total_width_of_bricks > 0.0);
    assert!(total_height_of_bricks > 0.0);

    // Given the space available, compute how many rows and columns of bricks we can fit
    let n_columns = (total_width_of_bricks / (BRICK_SIZE.x + GAP_BETWEEN_BRICKS)).floor() as usize;
    let n_rows = (total_height_of_bricks / (BRICK_SIZE.y + GAP_BETWEEN_BRICKS)).floor() as usize;
    let n_vertical_gaps = n_columns - 1;

    // Because we need to round the number of columns,
    // the space on the top and sides of the bricks only captures a lower bound, not an exact value
    let center_of_bricks = (LEFT_WALL + RIGHT_WALL) / 2.0;
    let left_edge_of_bricks = center_of_bricks
        // Space taken up by the bricks
        - (n_columns as f32 / 2.0 * BRICK_SIZE.x)
        // Space taken up by the gaps
        - n_vertical_gaps as f32 / 2.0 * GAP_BETWEEN_BRICKS;

    // In Bevy, the `translation` of an entity describes the center point,
    // not its bottom-left corner
    let offset_x = left_edge_of_bricks + BRICK_SIZE.x / 2.;
    let offset_y = bottom_edge_of_bricks + BRICK_SIZE.y / 2.;

    for row in 0..n_rows {
        for column in 0..n_columns {
            let brick_position = Vec2::new(
                offset_x + column as f32 * (BRICK_SIZE.x + GAP_BETWEEN_BRICKS),
                offset_y + row as f32 * (BRICK_SIZE.y + GAP_BETWEEN_BRICKS),
            );

            // brick
            commands.spawn((
                SpriteBundle {
                    sprite: Sprite {
                        color: BRICK_COLOR,
                        ..default()
                    },
                    transform: Transform {
                        translation: brick_position.extend(0.0),
                        scale: Vec3::new(BRICK_SIZE.x, BRICK_SIZE.y, 1.0),
                        ..default()
                    },
                    ..default()
                },
                Brick,
                Collider,
            ));
        }
    }
}
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 144)
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
fn move_player(
    mut player: Query<&mut Transform, With<Player>>,
    time: Res<Time>,
    kb_input: Res<ButtonInput<KeyCode>>,
) {
    let Ok(mut player) = player.get_single_mut() else {
        return;
    };

    let mut direction = Vec2::ZERO;

    if kb_input.pressed(KeyCode::KeyW) {
        direction.y += 1.;
    }

    if kb_input.pressed(KeyCode::KeyS) {
        direction.y -= 1.;
    }

    if kb_input.pressed(KeyCode::KeyA) {
        direction.x -= 1.;
    }

    if kb_input.pressed(KeyCode::KeyD) {
        direction.x += 1.;
    }

    // Progressively update the player's position over time. Normalize the
    // direction vector to prevent it from exceeding a magnitude of 1 when
    // moving diagonally.
    let move_delta = direction.normalize_or_zero() * PLAYER_SPEED * time.delta_seconds();
    player.translation += move_delta.extend(0.);
}
More examples
Hide additional examples
examples/3d/tonemapping.rs (line 272)
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
fn resize_image(
    image_mesh: Query<(&Handle<StandardMaterial>, &Handle<Mesh>), With<HDRViewer>>,
    materials: Res<Assets<StandardMaterial>>,
    mut meshes: ResMut<Assets<Mesh>>,
    images: Res<Assets<Image>>,
    mut image_events: EventReader<AssetEvent<Image>>,
) {
    for event in image_events.read() {
        let (AssetEvent::Added { id } | AssetEvent::Modified { id }) = event else {
            continue;
        };

        for (mat_h, mesh_h) in &image_mesh {
            let Some(mat) = materials.get(mat_h) else {
                continue;
            };

            let Some(ref base_color_texture) = mat.base_color_texture else {
                continue;
            };

            if *id != base_color_texture.id() {
                continue;
            };

            let Some(image_changed) = images.get(*id) else {
                continue;
            };

            let size = image_changed.size_f32().normalize_or_zero() * 1.4;
            // Resize Mesh
            let quad = Mesh::from(Rectangle::from_size(size));
            meshes.insert(mesh_h, quad);
        }
    }
}
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.

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.

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 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 powf(self, n: f32) -> Vec2

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

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 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

source

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

Returns a vector with a length no less than min

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 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 315)
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
fn rotate_camera(
    time: Res<Time>,
    mut camera_query: Query<&mut Transform, With<Camera3d>>,
    app_status: Res<AppStatus>,
) {
    if !app_status.rotating {
        return;
    }

    for mut transform in camera_query.iter_mut() {
        transform.translation = Vec2::from_angle(time.delta_seconds() * PI / 5.0)
            .rotate(transform.translation.xz())
            .extend(transform.translation.y)
            .xzy();
        transform.look_at(Vec3::ZERO, Vec3::Y);
    }
}
More examples
Hide additional examples
examples/3d/irradiance_volumes.rs (line 376)
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
fn rotate_camera(
    mut camera_query: Query<&mut Transform, With<Camera3d>>,
    time: Res<Time>,
    app_status: Res<AppStatus>,
) {
    if !app_status.rotating {
        return;
    }

    for mut transform in camera_query.iter_mut() {
        transform.translation = Vec2::from_angle(ROTATION_SPEED * time.delta_seconds())
            .rotate(transform.translation.xz())
            .extend(transform.translation.y)
            .xzy();
        transform.look_at(Vec3::ZERO, Vec3::Y);
    }
}
examples/gizmos/2d_gizmos.rs (line 94)
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
fn draw_example_collection(
    mut gizmos: Gizmos,
    mut my_gizmos: Gizmos<MyRoundGizmos>,
    time: Res<Time>,
) {
    let sin = time.elapsed_seconds().sin() * 50.;
    gizmos.line_2d(Vec2::Y * -sin, Vec2::splat(-80.), RED);
    gizmos.ray_2d(Vec2::Y * sin, Vec2::splat(80.), LIME);

    gizmos
        .grid_2d(
            Vec2::ZERO,
            0.0,
            UVec2::new(16, 9),
            Vec2::new(80., 80.),
            // Dark gray
            LinearRgba::gray(0.05),
        )
        .outer_edges();

    // Triangle
    gizmos.linestrip_gradient_2d([
        (Vec2::Y * 300., BLUE),
        (Vec2::new(-255., -155.), RED),
        (Vec2::new(255., -155.), LIME),
        (Vec2::Y * 300., BLUE),
    ]);

    gizmos.rect_2d(Vec2::ZERO, 0., Vec2::splat(650.), BLACK);

    gizmos.cross_2d(Vec2::new(-160., 120.), 0., 12., FUCHSIA);

    my_gizmos
        .rounded_rect_2d(Vec2::ZERO, 0., Vec2::splat(630.), BLACK)
        .corner_radius((time.elapsed_seconds() / 3.).cos() * 100.);

    // Circles have 32 line-segments by default.
    // You may want to increase this for larger circles.
    my_gizmos.circle_2d(Vec2::ZERO, 300., NAVY).resolution(64);

    my_gizmos.ellipse_2d(
        Vec2::ZERO,
        time.elapsed_seconds() % TAU,
        Vec2::new(100., 200.),
        YELLOW_GREEN,
    );

    // Arcs default resolution is linearly interpolated between
    // 1 and 32, using the arc length as scalar.
    my_gizmos.arc_2d(Vec2::ZERO, sin / 10., PI / 2., 310., ORANGE_RED);

    gizmos.arrow_2d(
        Vec2::ZERO,
        Vec2::from_angle(sin / -10. + PI / 2.) * 50.,
        YELLOW,
    );

    // You can create more complex arrows using the arrow builder.
    gizmos
        .arrow_2d(Vec2::ZERO, Vec2::from_angle(sin / -10.) * 50., GREEN)
        .with_double_end()
        .with_tip_length(10.);
}
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.

source

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

Returns the angle (in radians) between self and 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.

Examples found in repository?
examples/3d/reflection_probes.rs (line 316)
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
fn rotate_camera(
    time: Res<Time>,
    mut camera_query: Query<&mut Transform, With<Camera3d>>,
    app_status: Res<AppStatus>,
) {
    if !app_status.rotating {
        return;
    }

    for mut transform in camera_query.iter_mut() {
        transform.translation = Vec2::from_angle(time.delta_seconds() * PI / 5.0)
            .rotate(transform.translation.xz())
            .extend(transform.translation.y)
            .xzy();
        transform.look_at(Vec3::ZERO, Vec3::Y);
    }
}
More examples
Hide additional examples
examples/3d/irradiance_volumes.rs (line 377)
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
fn rotate_camera(
    mut camera_query: Query<&mut Transform, With<Camera3d>>,
    time: Res<Time>,
    app_status: Res<AppStatus>,
) {
    if !app_status.rotating {
        return;
    }

    for mut transform in camera_query.iter_mut() {
        transform.translation = Vec2::from_angle(ROTATION_SPEED * time.delta_seconds())
            .rotate(transform.translation.xz())
            .extend(transform.translation.y)
            .xzy();
        transform.look_at(Vec3::ZERO, Vec3::Y);
    }
}
source

pub fn as_dvec2(&self) -> DVec2

Casts all elements of self to f64.

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.

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.

Trait Implementations§

source§

impl Add<Vec2> for f32

§

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

§

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 for Vec2

§

type Output = Vec2

The resulting type after applying the + operator.
source§

fn add(self, rhs: Vec2) -> 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 for Vec2

source§

fn add_assign(&mut self, rhs: Vec2)

Performs the += operation. Read more
§

impl Animatable for Vec2

§

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

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

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

Blends one or more values together. Read more
§

fn post_process(&mut self, _world: &World)

Post-processes the value using resources in the World. Most animatable types do not need to implement this.
source§

impl AsMut<[f32; 2]> for Vec2

Available on non-target_arch="spirv" only.
source§

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

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

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

§

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

source§

impl AsRef<[f32; 2]> for Vec2

Available on non-target_arch="spirv" only.
source§

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

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

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

§

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

source§

impl Clone for Vec2

source§

fn clone(&self) -> Vec2

Returns a copy of the value. Read more
1.0.0 · source§

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

Performs copy-assignment from source. Read more
§

impl CreateFrom for Vec2

§

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

source§

impl Debug for Vec2

Available on non-target_arch="spirv" only.
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

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

Available on non-target_arch="spirv" only.
source§

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

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

impl Div<Vec2> for f32

§

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

§

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 for Vec2

§

type Output = Vec2

The resulting type after applying the / operator.
source§

fn div(self, rhs: Vec2) -> 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 for Vec2

source§

fn div_assign(&mut self, rhs: Vec2)

Performs the /= operation. Read more
source§

impl From<[f32; 2]> for Vec2

source§

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

Converts to this type from the input type.
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.
§

impl From<Dir2> for Vec2

§

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 (f32, f32)

source§

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

Converts to this type from the input type.
§

impl From<Vec2> for AspectRatio

§

fn from(value: Vec2) -> AspectRatio

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.
§

impl From<Vec2> for WindowResolution

§

fn from(res: Vec2) -> WindowResolution

Converts to this type from the input type.
§

impl FromIterator<Vec2> for BoxedPolygon

§

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

Creates a value from an iterator. Read more
§

impl FromIterator<Vec2> for BoxedPolyline2d

§

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

Creates a value from an iterator. Read more
§

impl<const N: usize> FromIterator<Vec2> for Polygon<N>

§

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

Creates a value from an iterator. Read more
§

impl<const N: usize> FromIterator<Vec2> for Polyline2d<N>

§

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

Creates a value from an iterator. Read more
§

impl FromReflect for Vec2
where Vec2: Any + Send + Sync, f32: FromReflect + TypePath + RegisterForReflection,

§

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

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

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

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

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

§

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

§

impl GetTypeRegistration for Vec2
where Vec2: Any + Send + Sync, f32: FromReflect + TypePath + RegisterForReflection,

§

fn get_type_registration() -> TypeRegistration

Returns the default TypeRegistration for this type.
§

fn register_type_dependencies(registry: &mut TypeRegistry)

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

impl Index<usize> for Vec2

§

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 Mul<Vec2> for Mat2

§

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
§

impl Mul<Vec2> for Rot2

§

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

Rotates a Vec2 by a Rot2.

§

type Output = Vec2

The resulting type after applying the * operator.
source§

impl Mul<Vec2> for f32

§

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

§

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 for Vec2

§

type Output = Vec2

The resulting type after applying the * operator.
source§

fn mul(self, rhs: Vec2) -> 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 for Vec2

source§

fn mul_assign(&mut self, rhs: Vec2)

Performs the *= operation. Read more
source§

impl Neg for Vec2

§

type Output = Vec2

The resulting type after applying the - operator.
source§

fn neg(self) -> Vec2

Performs the unary - operation. Read more
§

impl NormedVectorSpace for Vec2

§

fn norm(self) -> f32

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

fn norm_squared(self) -> f32

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

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

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

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

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

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

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

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

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

source§

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

Method which takes an iterator and generates Self from the elements by multiplying the items.
source§

impl Product for Vec2

source§

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

Method which takes an iterator and generates Self from the elements by multiplying the items.
§

impl ReadFrom for Vec2

§

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

§

impl Reflect for Vec2
where Vec2: Any + Send + Sync, f32: FromReflect + TypePath + RegisterForReflection,

§

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

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

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

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

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

Returns the value as a &dyn Any.
§

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

Returns the value as a &mut dyn Any.
§

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

Casts this type to a boxed reflected value.
§

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

Casts this type to a reflected value.
§

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

Casts this type to a mutable reflected value.
§

fn clone_value(&self) -> Box<dyn Reflect>

Clones the value as a Reflect trait object. Read more
§

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
§

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

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

fn reflect_kind(&self) -> ReflectKind

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

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

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

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

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

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

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

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

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

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

Debug formatter for the value. Read more
§

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

Applies a reflected value to this value. Read more
§

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

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

fn serializable(&self) -> Option<Serializable<'_>>

Returns a serializable version of the value. Read more
§

fn is_dynamic(&self) -> bool

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

impl Rem<Vec2> for f32

§

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

§

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 for Vec2

§

type Output = Vec2

The resulting type after applying the % operator.
source§

fn rem(self, rhs: Vec2) -> 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 for Vec2

source§

fn rem_assign(&mut self, rhs: Vec2)

Performs the %= operation. Read more
source§

impl Serialize for Vec2

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
§

impl ShaderSize for Vec2
where f32: ShaderSize,

§

const SHADER_SIZE: NonZero<u64> = _

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

impl ShaderType for Vec2
where f32: ShaderSize,

§

fn min_size() -> NonZero<u64>

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

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

Returns the size of Self at runtime Read more
§

fn assert_uniform_compat()

§

impl Struct for Vec2
where Vec2: Any + Send + Sync, f32: FromReflect + TypePath + RegisterForReflection,

§

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

Returns a reference to the value of the field named name as a &dyn Reflect.
§

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

Returns a mutable reference to the value of the field named name as a &mut dyn Reflect.
§

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

Returns a reference to the value of the field with index index as a &dyn Reflect.
§

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

Returns a mutable reference to the value of the field with index index as a &mut dyn Reflect.
§

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

Returns the name of the field with index index.
§

fn field_len(&self) -> usize

Returns the number of fields in the struct.
§

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

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

fn clone_dynamic(&self) -> DynamicStruct

Clones the struct into a DynamicStruct.
source§

impl Sub<Vec2> for f32

§

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

§

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 for Vec2

§

type Output = Vec2

The resulting type after applying the - operator.
source§

fn sub(self, rhs: Vec2) -> 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 for Vec2

source§

fn sub_assign(&mut self, rhs: Vec2)

Performs the -= operation. Read more
source§

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

source§

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

Method which takes an iterator and generates Self from the elements by “summing up” the items.
source§

impl Sum for Vec2

source§

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

Method which takes an iterator and generates Self from the elements by “summing up” the items.
§

impl TryFrom<Vec2> for Dir2

§

type Error = InvalidDirectionError

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

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

Performs the conversion.
§

impl TypePath for Vec2
where Vec2: Any + Send + Sync,

§

fn type_path() -> &'static str

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

fn short_type_path() -> &'static str

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

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

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

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

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

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

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

impl Typed for Vec2
where Vec2: Any + Send + Sync, f32: FromReflect + TypePath + RegisterForReflection,

§

fn type_info() -> &'static TypeInfo

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

impl Vec2Swizzles for Vec2

§

type Vec3 = Vec3

§

type Vec4 = Vec4

source§

fn xx(self) -> Vec2

source§

fn xy(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

§

impl VectorSpace for Vec2

§

const ZERO: Vec2 = Vec2::ZERO

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

fn lerp(&self, rhs: Self, t: f32) -> 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
§

impl WriteInto for Vec2

§

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

source§

impl Zeroable for Vec2

§

fn zeroed() -> Self

source§

impl Copy for Vec2

source§

impl Pod for Vec2

source§

impl StructuralPartialEq for Vec2

Auto Trait Implementations§

§

impl Freeze for Vec2

§

impl RefUnwindSafe for Vec2

§

impl Send for Vec2

§

impl Sync for Vec2

§

impl Unpin 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
§

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

§

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
§

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

§

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.
§

fn is_valid_bit_pattern(_bits: &T) -> bool

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

impl<T> Downcast<T> for T

§

fn downcast(&self) -> &T

§

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

§

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.
§

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.
§

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.
§

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.
§

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

§

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

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

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

source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<S> FromSample<S> for S

§

fn from_sample_(s: S) -> S

§

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

§

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

Creates Self using data from the given World.
§

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

§

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

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

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

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

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

§

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

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

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

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

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
§

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
§

impl<T> Instrument for T

§

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

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

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
§

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

§

fn into_sample(self) -> T

§

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

§

type NoneType = T

§

fn null_value() -> T

The none-equivalent value.
§

impl<T> Pointable for T

§

const ALIGN: usize = _

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
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> Same for T

§

type Output = T

Should always be Self
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>

§

impl<V> StableInterpolate for V

§

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.
§

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

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

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> ToOwned for T
where T: Clone,

§

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
§

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

§

fn to_sample_(self) -> U

§

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

§

fn to_smolstr(&self) -> SmolStr

source§

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

source§

default fn to_string(&self) -> String

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

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

§

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>,

§

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.
§

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

§

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

§

impl<T> Upcast<T> for T

§

fn upcast(&self) -> Option<&T>

§

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

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

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
§

fn with_current_subscriber(self) -> WithDispatch<Self>

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

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

§

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

source§

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

§

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

§

impl<T> GpuArrayBufferable for T

§

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

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>,

§

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

§

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

§

impl<T> WasmNotSendSync for T
where T: WasmNotSend + WasmNotSync,

§

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