#[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
impl Vec2
Sourcepub const NEG_INFINITY: Vec2
pub const NEG_INFINITY: Vec2
All f32::NEG_INFINITY
.
Sourcepub const USES_CORE_SIMD: bool = false
pub const USES_CORE_SIMD: bool = false
Vec2 uses Rust Portable SIMD
Sourcepub const USES_SCALAR_MATH: bool = true
pub const USES_SCALAR_MATH: bool = true
Vec2 uses scalar math
Sourcepub const USES_WASM32_SIMD: bool = false
pub const USES_WASM32_SIMD: bool = false
Vec2 uses WebAssembly 128-bit SIMD
Sourcepub const fn new(x: f32, y: f32) -> Vec2
pub const fn new(x: f32, y: f32) -> Vec2
Creates a new vector.
Examples found in repository?
More examples
18const EXTENT: Vec2 = Vec2::new(1172.0, 520.0);
19const PLOT_SIZE: Vec2 = Vec2::splat(80.0);
20
21fn setup(mut commands: Commands) {
22 commands.spawn(Camera2d);
23
24 let text_font = TextFont {
25 font_size: 10.0,
26 ..default()
27 };
28
29 let chunks = [
30 // "In" row
31 EaseFunction::SineIn,
32 EaseFunction::QuadraticIn,
33 EaseFunction::CubicIn,
34 EaseFunction::QuarticIn,
35 EaseFunction::QuinticIn,
36 EaseFunction::SmoothStepIn,
37 EaseFunction::SmootherStepIn,
38 EaseFunction::CircularIn,
39 EaseFunction::ExponentialIn,
40 EaseFunction::ElasticIn,
41 EaseFunction::BackIn,
42 EaseFunction::BounceIn,
43 // "Out" row
44 EaseFunction::SineOut,
45 EaseFunction::QuadraticOut,
46 EaseFunction::CubicOut,
47 EaseFunction::QuarticOut,
48 EaseFunction::QuinticOut,
49 EaseFunction::SmoothStepOut,
50 EaseFunction::SmootherStepOut,
51 EaseFunction::CircularOut,
52 EaseFunction::ExponentialOut,
53 EaseFunction::ElasticOut,
54 EaseFunction::BackOut,
55 EaseFunction::BounceOut,
56 // "InOut" row
57 EaseFunction::SineInOut,
58 EaseFunction::QuadraticInOut,
59 EaseFunction::CubicInOut,
60 EaseFunction::QuarticInOut,
61 EaseFunction::QuinticInOut,
62 EaseFunction::SmoothStep,
63 EaseFunction::SmootherStep,
64 EaseFunction::CircularInOut,
65 EaseFunction::ExponentialInOut,
66 EaseFunction::ElasticInOut,
67 EaseFunction::BackInOut,
68 EaseFunction::BounceInOut,
69 // "Other" row
70 EaseFunction::Linear,
71 EaseFunction::Steps(4, JumpAt::End),
72 EaseFunction::Steps(4, JumpAt::Start),
73 EaseFunction::Steps(4, JumpAt::Both),
74 EaseFunction::Steps(4, JumpAt::None),
75 EaseFunction::Elastic(50.0),
76 ]
77 .chunks(COLS);
78
79 let max_rows = chunks.clone().count();
80
81 let half_extent = EXTENT / 2.;
82 let half_size = PLOT_SIZE / 2.;
83
84 for (row, functions) in chunks.enumerate() {
85 for (col, function) in functions.iter().enumerate() {
86 let color = Hsla::hsl(col as f32 / COLS as f32 * 360.0, 0.8, 0.75).into();
87 commands.spawn((
88 EaseFunctionPlot(*function, color),
89 Transform::from_xyz(
90 -half_extent.x + EXTENT.x / (COLS - 1) as f32 * col as f32,
91 half_extent.y - EXTENT.y / (max_rows - 1) as f32 * row as f32,
92 0.0,
93 ),
94 children![
95 (
96 Sprite::from_color(color, Vec2::splat(5.0)),
97 Transform::from_xyz(half_size.x + 5.0, -half_size.y, 0.0),
98 ),
99 (
100 Sprite::from_color(color, Vec2::splat(4.0)),
101 Transform::from_xyz(-half_size.x, -half_size.y, 0.0),
102 ),
103 (
104 Text2d(format!("{function:?}")),
105 text_font.clone(),
106 TextColor(color),
107 Transform::from_xyz(0.0, -half_size.y - 15.0, 0.0),
108 )
109 ],
110 ));
111 }
112 }
113 commands.spawn((
114 Text::default(),
115 Node {
116 position_type: PositionType::Absolute,
117 top: px(12),
118 left: px(12),
119 ..default()
120 },
121 ));
122}
123
124fn display_curves(
125 mut gizmos: Gizmos,
126 ease_functions: Query<(&EaseFunctionPlot, &Transform, &Children)>,
127 mut transforms: Query<&mut Transform, Without<EaseFunctionPlot>>,
128 mut ui_text: Single<&mut Text>,
129 time: Res<Time>,
130) {
131 let samples = 100;
132 let duration = 2.5;
133 let time_margin = 0.5;
134
135 let now = ((time.elapsed_secs() % (duration + time_margin * 2.0) - time_margin) / duration)
136 .clamp(0.0, 1.0);
137
138 ui_text.0 = format!("Progress: {now:.2}");
139
140 for (EaseFunctionPlot(function, color), transform, children) in &ease_functions {
141 let center = transform.translation.xy();
142 let half_size = PLOT_SIZE / 2.0;
143
144 // Draw a box around the curve
145 gizmos.linestrip_2d(
146 [
147 center + half_size,
148 center + half_size * Vec2::new(-1., 1.),
149 center + half_size * Vec2::new(-1., -1.),
150 center + half_size * Vec2::new(1., -1.),
151 center + half_size,
152 ],
153 color.darker(0.4),
154 );
155
156 // Draw the curve
157 let f = EasingCurve::new(0.0, 1.0, *function);
158 let drawn_curve = f
159 .by_ref()
160 .graph()
161 .map(|(x, y)| center - half_size + Vec2::new(x, y) * PLOT_SIZE);
162 gizmos.curve_2d(
163 &drawn_curve,
164 drawn_curve.domain().spaced_points(samples).unwrap(),
165 *color,
166 );
167
168 // Show progress along the curve for the current time
169 let y = f.sample(now).unwrap() * PLOT_SIZE.y;
170 transforms.get_mut(children[0]).unwrap().translation.y = -half_size.y + y;
171 transforms.get_mut(children[1]).unwrap().translation =
172 -half_size.extend(0.0) + Vec3::new(now * PLOT_SIZE.x, y, 0.0);
173
174 // Show horizontal bar at y value
175 gizmos.linestrip_2d(
176 [
177 center - half_size + Vec2::Y * y,
178 center - half_size + Vec2::new(PLOT_SIZE.x, y),
179 ],
180 color.darker(0.2),
181 );
182 }
183}
14const PADDLE_SIZE: Vec2 = Vec2::new(120.0, 20.0);
15const GAP_BETWEEN_PADDLE_AND_FLOOR: f32 = 60.0;
16const PADDLE_SPEED: f32 = 500.0;
17// How close can the paddle get to the wall
18const PADDLE_PADDING: f32 = 10.0;
19
20// We set the z-value of the ball to 1 so it renders on top in the case of overlapping sprites.
21const BALL_STARTING_POSITION: Vec3 = Vec3::new(0.0, -50.0, 1.0);
22const BALL_DIAMETER: f32 = 30.;
23const BALL_SPEED: f32 = 400.0;
24const INITIAL_BALL_DIRECTION: Vec2 = Vec2::new(0.5, -0.5);
25
26const WALL_THICKNESS: f32 = 10.0;
27// x coordinates
28const LEFT_WALL: f32 = -450.;
29const RIGHT_WALL: f32 = 450.;
30// y coordinates
31const BOTTOM_WALL: f32 = -300.;
32const TOP_WALL: f32 = 300.;
33
34const BRICK_SIZE: Vec2 = Vec2::new(100., 30.);
35// These values are exact
36const GAP_BETWEEN_PADDLE_AND_BRICKS: f32 = 270.0;
37const GAP_BETWEEN_BRICKS: f32 = 5.0;
38// These values are lower bounds, as the number of bricks is computed
39const GAP_BETWEEN_BRICKS_AND_CEILING: f32 = 20.0;
40const GAP_BETWEEN_BRICKS_AND_SIDES: f32 = 20.0;
41
42const SCOREBOARD_FONT_SIZE: f32 = 33.0;
43const SCOREBOARD_TEXT_PADDING: Val = Val::Px(5.0);
44
45const BACKGROUND_COLOR: Color = Color::srgb(0.9, 0.9, 0.9);
46const PADDLE_COLOR: Color = Color::srgb(0.3, 0.3, 0.7);
47const BALL_COLOR: Color = Color::srgb(1.0, 0.5, 0.5);
48const BRICK_COLOR: Color = Color::srgb(0.5, 0.5, 1.0);
49const WALL_COLOR: Color = Color::srgb(0.8, 0.8, 0.8);
50const TEXT_COLOR: Color = Color::srgb(0.5, 0.5, 1.0);
51const SCORE_COLOR: Color = Color::srgb(1.0, 0.5, 0.5);
52
53fn main() {
54 App::new()
55 .add_plugins(DefaultPlugins)
56 .add_plugins(
57 stepping::SteppingPlugin::default()
58 .add_schedule(Update)
59 .add_schedule(FixedUpdate)
60 .at(percent(35), percent(50)),
61 )
62 .insert_resource(Score(0))
63 .insert_resource(ClearColor(BACKGROUND_COLOR))
64 .add_systems(Startup, setup)
65 // Add our gameplay simulation systems to the fixed timestep schedule
66 // which runs at 64 Hz by default
67 .add_systems(
68 FixedUpdate,
69 (apply_velocity, move_paddle, check_for_collisions)
70 // `chain`ing systems together runs them in order
71 .chain(),
72 )
73 .add_systems(Update, update_scoreboard)
74 .add_observer(play_collision_sound)
75 .run();
76}
77
78#[derive(Component)]
79struct Paddle;
80
81#[derive(Component)]
82struct Ball;
83
84#[derive(Component, Deref, DerefMut)]
85struct Velocity(Vec2);
86
87#[derive(Event)]
88struct BallCollided;
89
90#[derive(Component)]
91struct Brick;
92
93#[derive(Resource, Deref)]
94struct CollisionSound(Handle<AudioSource>);
95
96// Default must be implemented to define this as a required component for the Wall component below
97#[derive(Component, Default)]
98struct Collider;
99
100// This is a collection of the components that define a "Wall" in our game
101#[derive(Component)]
102#[require(Sprite, Transform, Collider)]
103struct Wall;
104
105/// Which side of the arena is this wall located on?
106enum WallLocation {
107 Left,
108 Right,
109 Bottom,
110 Top,
111}
112
113impl WallLocation {
114 /// Location of the *center* of the wall, used in `transform.translation()`
115 fn position(&self) -> Vec2 {
116 match self {
117 WallLocation::Left => Vec2::new(LEFT_WALL, 0.),
118 WallLocation::Right => Vec2::new(RIGHT_WALL, 0.),
119 WallLocation::Bottom => Vec2::new(0., BOTTOM_WALL),
120 WallLocation::Top => Vec2::new(0., TOP_WALL),
121 }
122 }
123
124 /// (x, y) dimensions of the wall, used in `transform.scale()`
125 fn size(&self) -> Vec2 {
126 let arena_height = TOP_WALL - BOTTOM_WALL;
127 let arena_width = RIGHT_WALL - LEFT_WALL;
128 // Make sure we haven't messed up our constants
129 assert!(arena_height > 0.0);
130 assert!(arena_width > 0.0);
131
132 match self {
133 WallLocation::Left | WallLocation::Right => {
134 Vec2::new(WALL_THICKNESS, arena_height + WALL_THICKNESS)
135 }
136 WallLocation::Bottom | WallLocation::Top => {
137 Vec2::new(arena_width + WALL_THICKNESS, WALL_THICKNESS)
138 }
139 }
140 }
141}
142
143impl Wall {
144 // This "builder method" allows us to reuse logic across our wall entities,
145 // making our code easier to read and less prone to bugs when we change the logic
146 // Notice the use of Sprite and Transform alongside Wall, overwriting the default values defined for the required components
147 fn new(location: WallLocation) -> (Wall, Sprite, Transform) {
148 (
149 Wall,
150 Sprite::from_color(WALL_COLOR, Vec2::ONE),
151 Transform {
152 // We need to convert our Vec2 into a Vec3, by giving it a z-coordinate
153 // This is used to determine the order of our sprites
154 translation: location.position().extend(0.0),
155 // The z-scale of 2D objects must always be 1.0,
156 // or their ordering will be affected in surprising ways.
157 // See https://github.com/bevyengine/bevy/issues/4149
158 scale: location.size().extend(1.0),
159 ..default()
160 },
161 )
162 }
163}
164
165// This resource tracks the game's score
166#[derive(Resource, Deref, DerefMut)]
167struct Score(usize);
168
169#[derive(Component)]
170struct ScoreboardUi;
171
172// Add the game's entities to our world
173fn setup(
174 mut commands: Commands,
175 mut meshes: ResMut<Assets<Mesh>>,
176 mut materials: ResMut<Assets<ColorMaterial>>,
177 asset_server: Res<AssetServer>,
178) {
179 // Camera
180 commands.spawn(Camera2d);
181
182 // Sound
183 let ball_collision_sound = asset_server.load("sounds/breakout_collision.ogg");
184 commands.insert_resource(CollisionSound(ball_collision_sound));
185
186 // Paddle
187 let paddle_y = BOTTOM_WALL + GAP_BETWEEN_PADDLE_AND_FLOOR;
188
189 commands.spawn((
190 Sprite::from_color(PADDLE_COLOR, Vec2::ONE),
191 Transform {
192 translation: Vec3::new(0.0, paddle_y, 0.0),
193 scale: PADDLE_SIZE.extend(1.0),
194 ..default()
195 },
196 Paddle,
197 Collider,
198 ));
199
200 // Ball
201 commands.spawn((
202 Mesh2d(meshes.add(Circle::default())),
203 MeshMaterial2d(materials.add(BALL_COLOR)),
204 Transform::from_translation(BALL_STARTING_POSITION)
205 .with_scale(Vec2::splat(BALL_DIAMETER).extend(1.)),
206 Ball,
207 Velocity(INITIAL_BALL_DIRECTION.normalize() * BALL_SPEED),
208 ));
209
210 // Scoreboard
211 commands.spawn((
212 Text::new("Score: "),
213 TextFont {
214 font_size: SCOREBOARD_FONT_SIZE,
215 ..default()
216 },
217 TextColor(TEXT_COLOR),
218 ScoreboardUi,
219 Node {
220 position_type: PositionType::Absolute,
221 top: SCOREBOARD_TEXT_PADDING,
222 left: SCOREBOARD_TEXT_PADDING,
223 ..default()
224 },
225 children![(
226 TextSpan::default(),
227 TextFont {
228 font_size: SCOREBOARD_FONT_SIZE,
229 ..default()
230 },
231 TextColor(SCORE_COLOR),
232 )],
233 ));
234
235 // Walls
236 commands.spawn(Wall::new(WallLocation::Left));
237 commands.spawn(Wall::new(WallLocation::Right));
238 commands.spawn(Wall::new(WallLocation::Bottom));
239 commands.spawn(Wall::new(WallLocation::Top));
240
241 // Bricks
242 let total_width_of_bricks = (RIGHT_WALL - LEFT_WALL) - 2. * GAP_BETWEEN_BRICKS_AND_SIDES;
243 let bottom_edge_of_bricks = paddle_y + GAP_BETWEEN_PADDLE_AND_BRICKS;
244 let total_height_of_bricks = TOP_WALL - bottom_edge_of_bricks - GAP_BETWEEN_BRICKS_AND_CEILING;
245
246 assert!(total_width_of_bricks > 0.0);
247 assert!(total_height_of_bricks > 0.0);
248
249 // Given the space available, compute how many rows and columns of bricks we can fit
250 let n_columns = (total_width_of_bricks / (BRICK_SIZE.x + GAP_BETWEEN_BRICKS)).floor() as usize;
251 let n_rows = (total_height_of_bricks / (BRICK_SIZE.y + GAP_BETWEEN_BRICKS)).floor() as usize;
252 let n_vertical_gaps = n_columns - 1;
253
254 // Because we need to round the number of columns,
255 // the space on the top and sides of the bricks only captures a lower bound, not an exact value
256 let center_of_bricks = (LEFT_WALL + RIGHT_WALL) / 2.0;
257 let left_edge_of_bricks = center_of_bricks
258 // Space taken up by the bricks
259 - (n_columns as f32 / 2.0 * BRICK_SIZE.x)
260 // Space taken up by the gaps
261 - n_vertical_gaps as f32 / 2.0 * GAP_BETWEEN_BRICKS;
262
263 // In Bevy, the `translation` of an entity describes the center point,
264 // not its bottom-left corner
265 let offset_x = left_edge_of_bricks + BRICK_SIZE.x / 2.;
266 let offset_y = bottom_edge_of_bricks + BRICK_SIZE.y / 2.;
267
268 for row in 0..n_rows {
269 for column in 0..n_columns {
270 let brick_position = Vec2::new(
271 offset_x + column as f32 * (BRICK_SIZE.x + GAP_BETWEEN_BRICKS),
272 offset_y + row as f32 * (BRICK_SIZE.y + GAP_BETWEEN_BRICKS),
273 );
274
275 // brick
276 commands.spawn((
277 Sprite {
278 color: BRICK_COLOR,
279 ..default()
280 },
281 Transform {
282 translation: brick_position.extend(0.0),
283 scale: Vec3::new(BRICK_SIZE.x, BRICK_SIZE.y, 1.0),
284 ..default()
285 },
286 Brick,
287 Collider,
288 ));
289 }
290 }
291}
150const RECTANGLE: Rectangle = Rectangle {
151 half_size: Vec2::new(SMALL_2D, BIG_2D),
152};
153const CUBOID: Cuboid = Cuboid {
154 half_size: Vec3::new(BIG_3D, SMALL_3D, BIG_3D),
155};
156
157const CIRCLE: Circle = Circle { radius: BIG_2D };
158const SPHERE: Sphere = Sphere { radius: BIG_3D };
159
160const ELLIPSE: Ellipse = Ellipse {
161 half_size: Vec2::new(BIG_2D, SMALL_2D),
162};
163
164const TRIANGLE_2D: Triangle2d = Triangle2d {
165 vertices: [
166 Vec2::new(BIG_2D, 0.0),
167 Vec2::new(0.0, BIG_2D),
168 Vec2::new(-BIG_2D, 0.0),
169 ],
170};
171
172const TRIANGLE_3D: Triangle3d = Triangle3d {
173 vertices: [
174 Vec3::new(BIG_3D, 0.0, 0.0),
175 Vec3::new(0.0, BIG_3D, 0.0),
176 Vec3::new(-BIG_3D, 0.0, 0.0),
177 ],
178};
179
180const PLANE_2D: Plane2d = Plane2d { normal: Dir2::Y };
181const PLANE_3D: Plane3d = Plane3d {
182 normal: Dir3::Y,
183 half_size: Vec2::new(BIG_3D, BIG_3D),
184};
185
186const LINE2D: Line2d = Line2d { direction: Dir2::X };
187const LINE3D: Line3d = Line3d { direction: Dir3::X };
188
189const SEGMENT_2D: Segment2d = Segment2d {
190 vertices: [Vec2::new(-BIG_2D / 2., 0.), Vec2::new(BIG_2D / 2., 0.)],
191};
192
193const SEGMENT_3D: Segment3d = Segment3d {
194 vertices: [
195 Vec3::new(-BIG_3D / 2., 0., 0.),
196 Vec3::new(BIG_3D / 2., 0., 0.),
197 ],
198};
199
200const REGULAR_POLYGON: RegularPolygon = RegularPolygon {
201 circumcircle: Circle { radius: BIG_2D },
202 sides: 5,
203};
204
205const CAPSULE_2D: Capsule2d = Capsule2d {
206 radius: SMALL_2D,
207 half_length: SMALL_2D,
208};
209const CAPSULE_3D: Capsule3d = Capsule3d {
210 radius: SMALL_3D,
211 half_length: SMALL_3D,
212};
213
214const CYLINDER: Cylinder = Cylinder {
215 radius: SMALL_3D,
216 half_height: SMALL_3D,
217};
218
219const CONE: Cone = Cone {
220 radius: BIG_3D,
221 height: BIG_3D,
222};
223
224const CONICAL_FRUSTUM: ConicalFrustum = ConicalFrustum {
225 radius_top: BIG_3D,
226 radius_bottom: SMALL_3D,
227 height: BIG_3D,
228};
229
230const ANNULUS: Annulus = Annulus {
231 inner_circle: Circle { radius: SMALL_2D },
232 outer_circle: Circle { radius: BIG_2D },
233};
234
235const TORUS: Torus = Torus {
236 minor_radius: SMALL_3D / 2.0,
237 major_radius: SMALL_3D * 1.5,
238};
239
240const TETRAHEDRON: Tetrahedron = Tetrahedron {
241 vertices: [
242 Vec3::new(-BIG_3D, 0.0, 0.0),
243 Vec3::new(BIG_3D, 0.0, 0.0),
244 Vec3::new(0.0, 0.0, -BIG_3D * 1.67),
245 Vec3::new(0.0, BIG_3D * 1.67, -BIG_3D * 0.5),
246 ],
247};
248
249const ARC: Arc2d = Arc2d {
250 radius: BIG_2D,
251 half_angle: std::f32::consts::FRAC_PI_4,
252};
253
254const CIRCULAR_SECTOR: CircularSector = CircularSector {
255 arc: Arc2d {
256 radius: BIG_2D,
257 half_angle: std::f32::consts::FRAC_PI_4,
258 },
259};
260
261const CIRCULAR_SEGMENT: CircularSegment = CircularSegment {
262 arc: Arc2d {
263 radius: BIG_2D,
264 half_angle: std::f32::consts::FRAC_PI_4,
265 },
266};
267
268fn setup_cameras(mut commands: Commands) {
269 let start_in_2d = true;
270 let make_camera = |is_active| Camera {
271 is_active,
272 ..Default::default()
273 };
274
275 commands.spawn((Camera2d, make_camera(start_in_2d)));
276
277 commands.spawn((
278 Camera3d::default(),
279 make_camera(!start_in_2d),
280 Transform::from_xyz(0.0, 10.0, 0.0).looking_at(Vec3::ZERO, Vec3::Z),
281 ));
282}
283
284fn setup_ambient_light(mut ambient_light: ResMut<AmbientLight>) {
285 ambient_light.brightness = 50.0;
286}
287
288fn setup_lights(mut commands: Commands) {
289 commands.spawn((
290 PointLight {
291 intensity: 5000.0,
292 ..default()
293 },
294 Transform::from_translation(Vec3::new(-LEFT_RIGHT_OFFSET_3D, 2.0, 0.0))
295 .looking_at(Vec3::new(-LEFT_RIGHT_OFFSET_3D, 0.0, 0.0), Vec3::Y),
296 ));
297}
298
299/// Marker component for header text
300#[derive(Debug, Clone, Component, Default, Reflect)]
301pub struct HeaderText;
302
303/// Marker component for header node
304#[derive(Debug, Clone, Component, Default, Reflect)]
305pub struct HeaderNode;
306
307fn update_active_cameras(
308 state: Res<State<CameraActive>>,
309 camera_2d: Single<(Entity, &mut Camera), With<Camera2d>>,
310 camera_3d: Single<(Entity, &mut Camera), (With<Camera3d>, Without<Camera2d>)>,
311 mut text: Query<&mut UiTargetCamera, With<HeaderNode>>,
312) {
313 let (entity_2d, mut cam_2d) = camera_2d.into_inner();
314 let (entity_3d, mut cam_3d) = camera_3d.into_inner();
315 let is_camera_2d_active = matches!(*state.get(), CameraActive::Dim2);
316
317 cam_2d.is_active = is_camera_2d_active;
318 cam_3d.is_active = !is_camera_2d_active;
319
320 let active_camera = if is_camera_2d_active {
321 entity_2d
322 } else {
323 entity_3d
324 };
325
326 text.iter_mut().for_each(|mut target_camera| {
327 *target_camera = UiTargetCamera(active_camera);
328 });
329}
330
331fn switch_cameras(current: Res<State<CameraActive>>, mut next: ResMut<NextState<CameraActive>>) {
332 let next_state = match current.get() {
333 CameraActive::Dim2 => CameraActive::Dim3,
334 CameraActive::Dim3 => CameraActive::Dim2,
335 };
336 next.set(next_state);
337}
338
339fn setup_text(mut commands: Commands, cameras: Query<(Entity, &Camera)>) {
340 let active_camera = cameras
341 .iter()
342 .find_map(|(entity, camera)| camera.is_active.then_some(entity))
343 .expect("run condition ensures existence");
344 commands.spawn((
345 HeaderNode,
346 Node {
347 justify_self: JustifySelf::Center,
348 top: px(5),
349 ..Default::default()
350 },
351 UiTargetCamera(active_camera),
352 children![(
353 Text::default(),
354 HeaderText,
355 TextLayout::new_with_justify(Justify::Center),
356 children![
357 TextSpan::new("Primitive: "),
358 TextSpan(format!("{text}", text = PrimitiveSelected::default())),
359 TextSpan::new("\n\n"),
360 TextSpan::new(
361 "Press 'C' to switch between 2D and 3D mode\n\
362 Press 'Up' or 'Down' to switch to the next/previous primitive",
363 ),
364 TextSpan::new("\n\n"),
365 TextSpan::new("(If nothing is displayed, there's no rendering support yet)",),
366 ]
367 )],
368 ));
369}
370
371fn update_text(
372 primitive_state: Res<State<PrimitiveSelected>>,
373 header: Query<Entity, With<HeaderText>>,
374 mut writer: TextUiWriter,
375) {
376 let new_text = format!("{text}", text = primitive_state.get());
377 header.iter().for_each(|header_text| {
378 if let Some(mut text) = writer.get_text(header_text, 2) {
379 (*text).clone_from(&new_text);
380 };
381 });
382}
383
384fn switch_to_next_primitive(
385 current: Res<State<PrimitiveSelected>>,
386 mut next: ResMut<NextState<PrimitiveSelected>>,
387) {
388 let next_state = current.get().next();
389 next.set(next_state);
390}
391
392fn switch_to_previous_primitive(
393 current: Res<State<PrimitiveSelected>>,
394 mut next: ResMut<NextState<PrimitiveSelected>>,
395) {
396 let next_state = current.get().previous();
397 next.set(next_state);
398}
399
400fn in_mode(active: CameraActive) -> impl Fn(Res<State<CameraActive>>) -> bool {
401 move |state| *state.get() == active
402}
403
404fn draw_gizmos_2d(mut gizmos: Gizmos, state: Res<State<PrimitiveSelected>>, time: Res<Time>) {
405 const POSITION: Vec2 = Vec2::new(-LEFT_RIGHT_OFFSET_2D, 0.0);
406 let angle = time.elapsed_secs();
407 let isometry = Isometry2d::new(POSITION, Rot2::radians(angle));
408 let color = Color::WHITE;
409
410 #[expect(
411 clippy::match_same_arms,
412 reason = "Certain primitives don't have any 2D rendering support yet."
413 )]
414 match state.get() {
415 PrimitiveSelected::RectangleAndCuboid => {
416 gizmos.primitive_2d(&RECTANGLE, isometry, color);
417 }
418 PrimitiveSelected::CircleAndSphere => {
419 gizmos.primitive_2d(&CIRCLE, isometry, color);
420 }
421 PrimitiveSelected::Ellipse => drop(gizmos.primitive_2d(&ELLIPSE, isometry, color)),
422 PrimitiveSelected::Triangle => gizmos.primitive_2d(&TRIANGLE_2D, isometry, color),
423 PrimitiveSelected::Plane => gizmos.primitive_2d(&PLANE_2D, isometry, color),
424 PrimitiveSelected::Line => drop(gizmos.primitive_2d(&LINE2D, isometry, color)),
425 PrimitiveSelected::Segment => {
426 drop(gizmos.primitive_2d(&SEGMENT_2D, isometry, color));
427 }
428 PrimitiveSelected::Polyline => gizmos.primitive_2d(
429 &Polyline2d {
430 vertices: vec![
431 Vec2::new(-BIG_2D, -SMALL_2D),
432 Vec2::new(-SMALL_2D, SMALL_2D),
433 Vec2::new(SMALL_2D, -SMALL_2D),
434 Vec2::new(BIG_2D, SMALL_2D),
435 ],
436 },
437 isometry,
438 color,
439 ),
440 PrimitiveSelected::Polygon => gizmos.primitive_2d(
441 &Polygon {
442 vertices: vec![
443 Vec2::new(-BIG_2D, -SMALL_2D),
444 Vec2::new(BIG_2D, -SMALL_2D),
445 Vec2::new(BIG_2D, SMALL_2D),
446 Vec2::new(0.0, 0.0),
447 Vec2::new(-BIG_2D, SMALL_2D),
448 ],
449 },
450 isometry,
451 color,
452 ),
453 PrimitiveSelected::RegularPolygon => {
454 gizmos.primitive_2d(®ULAR_POLYGON, isometry, color);
455 }
456 PrimitiveSelected::Capsule => gizmos.primitive_2d(&CAPSULE_2D, isometry, color),
457 PrimitiveSelected::Cylinder => {}
458 PrimitiveSelected::Cone => {}
459 PrimitiveSelected::ConicalFrustum => {}
460 PrimitiveSelected::Torus => drop(gizmos.primitive_2d(&ANNULUS, isometry, color)),
461 PrimitiveSelected::Tetrahedron => {}
462 PrimitiveSelected::Arc => gizmos.primitive_2d(&ARC, isometry, color),
463 PrimitiveSelected::CircularSector => {
464 gizmos.primitive_2d(&CIRCULAR_SECTOR, isometry, color);
465 }
466 PrimitiveSelected::CircularSegment => {
467 gizmos.primitive_2d(&CIRCULAR_SEGMENT, isometry, color);
468 }
469 }
470}
73fn spawn_curve_sprite<T: CurveColor>(commands: &mut Commands, y: f32, points: [T; 4]) {
74 commands.spawn((
75 Sprite::sized(Vec2::new(75., 75.)),
76 Transform::from_xyz(0., y, 0.),
77 Curve(CubicBezier::new([points]).to_curve().unwrap()),
78 ));
79}
80
81fn spawn_mixed_sprite<T: MixedColor>(commands: &mut Commands, y: f32, colors: [T; 4]) {
82 commands.spawn((
83 Transform::from_xyz(0., y, 0.),
84 Sprite::sized(Vec2::new(75., 75.)),
85 Mixed(colors),
86 ));
87}
- examples/math/custom_primitives.rs
- examples/window/window_resizing.rs
- examples/3d/motion_blur.rs
- tests/window/minimizing.rs
- tests/window/resizing.rs
- examples/camera/first_person_view_model.rs
- examples/movement/physics_in_fixed_timestep.rs
- examples/ecs/parallel_query.rs
- examples/ui/scroll.rs
- examples/remote/server.rs
- examples/ecs/fallible_params.rs
- examples/2d/wireframe_2d.rs
- examples/stress_tests/many_sprites.rs
- examples/testbed/2d.rs
- examples/math/bounding_2d.rs
- examples/stress_tests/many_animated_sprites.rs
- examples/stress_tests/many_text2d.rs
- examples/2d/2d_shapes.rs
- examples/camera/2d_on_ui.rs
- examples/3d/light_textures.rs
- examples/2d/cpu_draw.rs
- examples/gizmos/2d_gizmos.rs
- examples/testbed/ui.rs
- examples/asset/repeated_texture.rs
- examples/2d/sprite_slice.rs
- examples/2d/mesh2d_repeated_texture.rs
- examples/gizmos/3d_gizmos.rs
- examples/3d/auto_exposure.rs
- examples/stress_tests/many_cubes.rs
- examples/ui/scrollbars.rs
- examples/2d/sprite_scale.rs
- examples/2d/text2d.rs
- examples/3d/camera_sub_view.rs
Sourcepub const fn splat(v: f32) -> Vec2
pub const fn splat(v: f32) -> Vec2
Creates a vector with all elements set to v
.
Examples found in repository?
19const PLOT_SIZE: Vec2 = Vec2::splat(80.0);
20
21fn setup(mut commands: Commands) {
22 commands.spawn(Camera2d);
23
24 let text_font = TextFont {
25 font_size: 10.0,
26 ..default()
27 };
28
29 let chunks = [
30 // "In" row
31 EaseFunction::SineIn,
32 EaseFunction::QuadraticIn,
33 EaseFunction::CubicIn,
34 EaseFunction::QuarticIn,
35 EaseFunction::QuinticIn,
36 EaseFunction::SmoothStepIn,
37 EaseFunction::SmootherStepIn,
38 EaseFunction::CircularIn,
39 EaseFunction::ExponentialIn,
40 EaseFunction::ElasticIn,
41 EaseFunction::BackIn,
42 EaseFunction::BounceIn,
43 // "Out" row
44 EaseFunction::SineOut,
45 EaseFunction::QuadraticOut,
46 EaseFunction::CubicOut,
47 EaseFunction::QuarticOut,
48 EaseFunction::QuinticOut,
49 EaseFunction::SmoothStepOut,
50 EaseFunction::SmootherStepOut,
51 EaseFunction::CircularOut,
52 EaseFunction::ExponentialOut,
53 EaseFunction::ElasticOut,
54 EaseFunction::BackOut,
55 EaseFunction::BounceOut,
56 // "InOut" row
57 EaseFunction::SineInOut,
58 EaseFunction::QuadraticInOut,
59 EaseFunction::CubicInOut,
60 EaseFunction::QuarticInOut,
61 EaseFunction::QuinticInOut,
62 EaseFunction::SmoothStep,
63 EaseFunction::SmootherStep,
64 EaseFunction::CircularInOut,
65 EaseFunction::ExponentialInOut,
66 EaseFunction::ElasticInOut,
67 EaseFunction::BackInOut,
68 EaseFunction::BounceInOut,
69 // "Other" row
70 EaseFunction::Linear,
71 EaseFunction::Steps(4, JumpAt::End),
72 EaseFunction::Steps(4, JumpAt::Start),
73 EaseFunction::Steps(4, JumpAt::Both),
74 EaseFunction::Steps(4, JumpAt::None),
75 EaseFunction::Elastic(50.0),
76 ]
77 .chunks(COLS);
78
79 let max_rows = chunks.clone().count();
80
81 let half_extent = EXTENT / 2.;
82 let half_size = PLOT_SIZE / 2.;
83
84 for (row, functions) in chunks.enumerate() {
85 for (col, function) in functions.iter().enumerate() {
86 let color = Hsla::hsl(col as f32 / COLS as f32 * 360.0, 0.8, 0.75).into();
87 commands.spawn((
88 EaseFunctionPlot(*function, color),
89 Transform::from_xyz(
90 -half_extent.x + EXTENT.x / (COLS - 1) as f32 * col as f32,
91 half_extent.y - EXTENT.y / (max_rows - 1) as f32 * row as f32,
92 0.0,
93 ),
94 children![
95 (
96 Sprite::from_color(color, Vec2::splat(5.0)),
97 Transform::from_xyz(half_size.x + 5.0, -half_size.y, 0.0),
98 ),
99 (
100 Sprite::from_color(color, Vec2::splat(4.0)),
101 Transform::from_xyz(-half_size.x, -half_size.y, 0.0),
102 ),
103 (
104 Text2d(format!("{function:?}")),
105 text_font.clone(),
106 TextColor(color),
107 Transform::from_xyz(0.0, -half_size.y - 15.0, 0.0),
108 )
109 ],
110 ));
111 }
112 }
113 commands.spawn((
114 Text::default(),
115 Node {
116 position_type: PositionType::Absolute,
117 top: px(12),
118 left: px(12),
119 ..default()
120 },
121 ));
122}
More examples
86static LIGHTMAPS: [(&str, Rect); 5] = [
87 (
88 "Plane",
89 uv_rect_opengl(Vec2::splat(0.026), Vec2::splat(0.710)),
90 ),
91 (
92 "SheenChair_fabric",
93 uv_rect_opengl(vec2(0.7864, 0.02377), vec2(0.1910, 0.1912)),
94 ),
95 (
96 "SheenChair_label",
97 uv_rect_opengl(vec2(0.275, -0.016), vec2(0.858, 0.486)),
98 ),
99 (
100 "SheenChair_metal",
101 uv_rect_opengl(vec2(0.998, 0.506), vec2(-0.029, -0.067)),
102 ),
103 (
104 "SheenChair_wood",
105 uv_rect_opengl(vec2(0.787, 0.257), vec2(0.179, 0.177)),
106 ),
107];
108
109static SPHERE_UV_RECT: Rect = uv_rect_opengl(vec2(0.788, 0.484), Vec2::splat(0.062));
196fn spawn_plane(
197 commands: &mut Commands,
198 meshes: &mut Assets<Mesh>,
199 show_depth_texture_materials: &mut Assets<ShowDepthTextureMaterial>,
200 demo_depth_texture: &DemoDepthTexture,
201) {
202 let plane_handle = meshes.add(Plane3d::new(Vec3::Z, Vec2::splat(2.0)));
203 let show_depth_texture_material = show_depth_texture_materials.add(ShowDepthTextureMaterial {
204 depth_texture: Some(demo_depth_texture.0.clone()),
205 });
206 commands.spawn((
207 Mesh3d(plane_handle),
208 MeshMaterial3d(show_depth_texture_material),
209 Transform::from_xyz(10.0, 4.0, 0.0).with_scale(Vec3::splat(2.5)),
210 ));
211}
218fn spawn_decals(commands: &mut Commands, asset_server: &AssetServer) {
219 let image = asset_server.load("branding/icon.png");
220
221 commands.spawn((
222 ClusteredDecal {
223 image: image.clone(),
224 // Tint with red.
225 tag: 1,
226 },
227 calculate_initial_decal_transform(vec3(1.0, 3.0, 5.0), Vec3::ZERO, Vec2::splat(1.1)),
228 Selection::DecalA,
229 ));
230
231 commands.spawn((
232 ClusteredDecal {
233 image: image.clone(),
234 // Tint with blue.
235 tag: 2,
236 },
237 calculate_initial_decal_transform(vec3(-2.0, -1.0, 4.0), Vec3::ZERO, Vec2::splat(2.0)),
238 Selection::DecalB,
239 ));
240}
10fn spawn_system(mut commands: Commands, asset_server: Res<AssetServer>) {
11 commands.spawn(Camera2d);
12 let texture = asset_server.load("branding/icon.png");
13
14 // We're seeding the PRNG here to make this example deterministic for testing purposes.
15 // This isn't strictly required in practical use unless you need your app to be deterministic.
16 let mut rng = ChaCha8Rng::seed_from_u64(19878367467713);
17 for z in 0..128 {
18 commands.spawn((
19 Sprite::from_image(texture.clone()),
20 Transform::from_scale(Vec3::splat(0.1))
21 .with_translation(Vec2::splat(0.0).extend(z as f32)),
22 Velocity(20.0 * Vec2::new(rng.random::<f32>() - 0.5, rng.random::<f32>() - 0.5)),
23 ));
24 }
25}
- examples/math/bounding_2d.rs
- examples/camera/first_person_view_model.rs
- examples/math/custom_primitives.rs
- examples/ui/ui_transform.rs
- examples/stress_tests/many_sprites.rs
- examples/audio/spatial_audio_2d.rs
- examples/testbed/2d.rs
- examples/games/contributors.rs
- examples/stress_tests/many_animated_sprites.rs
- examples/2d/bloom_2d.rs
- examples/stress_tests/many_text2d.rs
- examples/3d/ssr.rs
- examples/time/virtual_time.rs
- examples/picking/sprite_picking.rs
- examples/gizmos/2d_gizmos.rs
- examples/2d/mesh2d_alpha_mode.rs
- examples/testbed/ui.rs
- examples/2d/sprite_slice.rs
- examples/gizmos/3d_gizmos.rs
- examples/stress_tests/many_cubes.rs
- examples/stress_tests/bevymark.rs
- examples/games/breakout.rs
- examples/games/desk_toy.rs
Sourcepub fn map<F>(self, f: F) -> Vec2
pub fn map<F>(self, f: F) -> Vec2
Returns a vector containing each element of self
modified by a mapping function f
.
Sourcepub fn select(mask: BVec2, if_true: Vec2, if_false: Vec2) -> Vec2
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
.
Sourcepub const fn from_array(a: [f32; 2]) -> Vec2
pub const fn from_array(a: [f32; 2]) -> Vec2
Creates a new vector from an array.
Sourcepub const fn from_slice(slice: &[f32]) -> Vec2
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.
Sourcepub fn write_to_slice(self, slice: &mut [f32])
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.
Sourcepub const fn extend(self, z: f32) -> Vec3
pub const fn extend(self, z: f32) -> Vec3
Creates a 3D vector from self
and the given z
value.
Examples found in repository?
More examples
337fn rotate_camera(
338 time: Res<Time>,
339 mut camera_query: Query<&mut Transform, With<Camera3d>>,
340 app_status: Res<AppStatus>,
341) {
342 if !app_status.rotating {
343 return;
344 }
345
346 for mut transform in camera_query.iter_mut() {
347 transform.translation = Vec2::from_angle(time.delta_secs() * PI / 5.0)
348 .rotate(transform.translation.xz())
349 .extend(transform.translation.y)
350 .xzy();
351 transform.look_at(Vec3::ZERO, Vec3::Y);
352 }
353}
349fn rotate_camera(
350 mut camera_query: Query<&mut Transform, With<Camera3d>>,
351 time: Res<Time>,
352 app_status: Res<AppStatus>,
353) {
354 if !app_status.rotating {
355 return;
356 }
357
358 for mut transform in camera_query.iter_mut() {
359 transform.translation = Vec2::from_angle(ROTATION_SPEED * time.delta_secs())
360 .rotate(transform.translation.xz())
361 .extend(transform.translation.y)
362 .xzy();
363 transform.look_at(Vec3::ZERO, Vec3::Y);
364 }
365}
62fn system(config: Res<Config>, time: Res<Time>, mut draw: Gizmos) {
63 if !config.fancy {
64 for _ in 0..(config.line_count / SYSTEM_COUNT) {
65 draw.line(Vec3::NEG_Y, Vec3::Y, Color::BLACK);
66 }
67 } else {
68 for i in 0..(config.line_count / SYSTEM_COUNT) {
69 let angle = i as f32 / (config.line_count / SYSTEM_COUNT) as f32 * TAU;
70
71 let vector = Vec2::from(ops::sin_cos(angle)).extend(ops::sin(time.elapsed_secs()));
72 let start_color = LinearRgba::rgb(vector.x, vector.z, 0.5);
73 let end_color = LinearRgba::rgb(-vector.z, -vector.y, 0.5);
74
75 draw.line_gradient(vector, -vector, start_color, end_color);
76 }
77 }
78}
- examples/games/breakout.rs
- examples/ecs/parallel_query.rs
- examples/camera/2d_top_down_camera.rs
- examples/2d/rotation.rs
- examples/2d/2d_viewport_to_world.rs
- examples/stress_tests/many_sprites.rs
- examples/testbed/2d.rs
- examples/stress_tests/many_animated_sprites.rs
- examples/stress_tests/many_text2d.rs
- examples/animation/easing_functions.rs
- examples/3d/light_textures.rs
- examples/time/virtual_time.rs
- examples/gizmos/3d_gizmos.rs
- examples/games/desk_toy.rs
- examples/2d/text2d.rs
Sourcepub fn dot(self, rhs: Vec2) -> f32
pub fn dot(self, rhs: Vec2) -> f32
Computes the dot product of self
and rhs
.
Examples found in repository?
195fn rotate_to_player_system(
196 time: Res<Time>,
197 mut query: Query<(&RotateToPlayer, &mut Transform), Without<Player>>,
198 player_transform: Single<&Transform, With<Player>>,
199) {
200 // Get the player translation in 2D
201 let player_translation = player_transform.translation.xy();
202
203 for (config, mut enemy_transform) in &mut query {
204 // Get the enemy ship forward vector in 2D (already unit length)
205 let enemy_forward = (enemy_transform.rotation * Vec3::Y).xy();
206
207 // Get the vector from the enemy ship to the player ship in 2D and normalize it.
208 let to_player = (player_translation - enemy_transform.translation.xy()).normalize();
209
210 // Get the dot product between the enemy forward vector and the direction to the player.
211 let forward_dot_player = enemy_forward.dot(to_player);
212
213 // If the dot product is approximately 1.0 then the enemy is already facing the player and
214 // we can early out.
215 if (forward_dot_player - 1.0).abs() < f32::EPSILON {
216 continue;
217 }
218
219 // Get the right vector of the enemy ship in 2D (already unit length)
220 let enemy_right = (enemy_transform.rotation * Vec3::X).xy();
221
222 // Get the dot product of the enemy right vector and the direction to the player ship.
223 // If the dot product is negative them we need to rotate counter clockwise, if it is
224 // positive we need to rotate clockwise. Note that `copysign` will still return 1.0 if the
225 // dot product is 0.0 (because the player is directly behind the enemy, so perpendicular
226 // with the right vector).
227 let right_dot_player = enemy_right.dot(to_player);
228
229 // Determine the sign of rotation from the right dot player. We need to negate the sign
230 // here as the 2D bevy co-ordinate system rotates around +Z, which is pointing out of the
231 // screen. Due to the right hand rule, positive rotation around +Z is counter clockwise and
232 // negative is clockwise.
233 let rotation_sign = -f32::copysign(1.0, right_dot_player);
234
235 // Limit rotation so we don't overshoot the target. We need to convert our dot product to
236 // an angle here so we can get an angle of rotation to clamp against.
237 let max_angle = ops::acos(forward_dot_player.clamp(-1.0, 1.0)); // Clamp acos for safety
238
239 // Calculate angle of rotation with limit
240 let rotation_angle =
241 rotation_sign * (config.rotation_speed * time.delta_secs()).min(max_angle);
242
243 // Rotate the enemy to face the player
244 enemy_transform.rotate_z(rotation_angle);
245 }
246}
Sourcepub fn dot_into_vec(self, rhs: Vec2) -> Vec2
pub fn dot_into_vec(self, rhs: Vec2) -> Vec2
Returns a vector where every component is the dot product of self
and rhs
.
Sourcepub fn min(self, rhs: Vec2) -> Vec2
pub fn min(self, rhs: Vec2) -> Vec2
Returns a vector containing the minimum values for each element of self
and rhs
.
In other words this computes [min(x, rhs.x), min(self.y, rhs.y), ..]
.
NaN propogation does not follow IEEE 754-2008 semantics for minNum and may differ on different SIMD architectures.
Examples found in repository?
321 fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
322 let isometry = isometry.into();
323
324 // The center of the circle at the center of the right wing of the heart
325 let circle_center = isometry.rotation * Vec2::new(self.radius, 0.0);
326 // The maximum X and Y positions of the two circles of the wings of the heart.
327 let max_circle = circle_center.abs() + Vec2::splat(self.radius);
328 // Since the two circles of the heart are mirrored around the origin, the minimum position is the negative of the maximum.
329 let min_circle = -max_circle;
330
331 // The position of the tip at the bottom of the heart
332 let tip_position = isometry.rotation * Vec2::new(0.0, -self.radius * (1. + SQRT_2));
333
334 Aabb2d {
335 min: isometry.translation + min_circle.min(tip_position),
336 max: isometry.translation + max_circle.max(tip_position),
337 }
338 }
Sourcepub fn max(self, rhs: Vec2) -> Vec2
pub fn max(self, rhs: Vec2) -> Vec2
Returns a vector containing the maximum values for each element of self
and rhs
.
In other words this computes [max(self.x, rhs.x), max(self.y, rhs.y), ..]
.
NaN propogation does not follow IEEE 754-2008 semantics for maxNum and may differ on different SIMD architectures.
Examples found in repository?
321 fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
322 let isometry = isometry.into();
323
324 // The center of the circle at the center of the right wing of the heart
325 let circle_center = isometry.rotation * Vec2::new(self.radius, 0.0);
326 // The maximum X and Y positions of the two circles of the wings of the heart.
327 let max_circle = circle_center.abs() + Vec2::splat(self.radius);
328 // Since the two circles of the heart are mirrored around the origin, the minimum position is the negative of the maximum.
329 let min_circle = -max_circle;
330
331 // The position of the tip at the bottom of the heart
332 let tip_position = isometry.rotation * Vec2::new(0.0, -self.radius * (1. + SQRT_2));
333
334 Aabb2d {
335 min: isometry.translation + min_circle.min(tip_position),
336 max: isometry.translation + max_circle.max(tip_position),
337 }
338 }
More examples
22fn setup(mut commands: Commands) {
23 let w = 60;
24 let h = 40;
25
26 commands.spawn(Camera2d);
27 commands.insert_resource(UiScale(0.5));
28
29 commands
30 .spawn((
31 Node {
32 width: percent(100),
33 height: percent(100),
34 overflow: Overflow::scroll(),
35 ..Default::default()
36 },
37 ScrollPosition(Vec2::ZERO),
38 ScrollableNode,
39 ScrollStart(Vec2::ZERO),
40 ))
41 .observe(
42 |drag: On<Pointer<Drag>>,
43 ui_scale: Res<UiScale>,
44 mut scroll_position_query: Query<
45 (&mut ScrollPosition, &ScrollStart),
46 With<ScrollableNode>,
47 >| {
48 if let Ok((mut scroll_position, start)) = scroll_position_query.single_mut() {
49 scroll_position.0 = (start.0 - drag.distance / ui_scale.0).max(Vec2::ZERO);
50 }
51 },
52 )
53 .observe(
54 |drag_start: On<Pointer<DragStart>>,
55 mut scroll_position_query: Query<
56 (&ComputedNode, &mut ScrollStart),
57 With<ScrollableNode>,
58 >| {
59 if drag_start.entity != drag_start.original_event_target() {
60 return;
61 }
62 if let Ok((computed_node, mut start)) = scroll_position_query.single_mut() {
63 start.0 = computed_node.scroll_position * computed_node.inverse_scale_factor;
64 }
65 },
66 )
67 .with_children(|commands| {
68 commands
69 .spawn(Node {
70 display: Display::Grid,
71 grid_template_rows: RepeatedGridTrack::px(w as i32, 100.),
72 grid_template_columns: RepeatedGridTrack::px(h as i32, 100.),
73 ..default()
74 })
75 .with_children(|commands| {
76 for y in 0..h {
77 for x in 0..w {
78 let tile_color = if (x + y) % 2 == 1 {
79 let hue = ((x as f32 / w as f32) * 270.0)
80 + ((y as f32 / h as f32) * 90.0);
81 Color::hsl(hue, 1., 0.5)
82 } else {
83 Color::BLACK
84 };
85 commands.spawn((
86 Node {
87 grid_row: GridPlacement::start(y + 1),
88 grid_column: GridPlacement::start(x + 1),
89 ..default()
90 },
91 Pickable {
92 should_block_lower: false,
93 is_hoverable: true,
94 },
95 TileColor(tile_color),
96 BackgroundColor(tile_color),
97 ))
98 .observe(|over: On<Pointer<Over>>, mut query: Query<&mut BackgroundColor>,| {
99 if let Ok(mut background_color) = query.get_mut(over.entity) {
100 background_color.0 = RED.into();
101 }
102 })
103 .observe(|out: On<Pointer<Out>>, mut query: Query<(&mut BackgroundColor, &TileColor)>| {
104 if let Ok((mut background_color, tile_color)) = query.get_mut(out.entity) {
105 background_color.0 = tile_color.0;
106 }
107 });
108 }
109 }
110 });
111 });
112}
Sourcepub fn clamp(self, min: Vec2, max: Vec2) -> Vec2
pub fn clamp(self, min: Vec2, max: Vec2) -> Vec2
Component-wise clamping of values, similar to f32::clamp
.
Each element in min
must be less-or-equal to the corresponding element in max
.
NaN propogation does not follow IEEE 754-2008 semantics and may differ on different SIMD architectures.
§Panics
Will panic if min
is greater than max
when glam_assert
is enabled.
Examples found in repository?
34fn button_system(
35 mut interaction_query: Query<
36 (
37 &Interaction,
38 &mut BackgroundColor,
39 Option<&RotateButton>,
40 Option<&ScaleButton>,
41 ),
42 (Changed<Interaction>, With<Button>),
43 >,
44 mut rotator_query: Query<&mut UiTransform, With<TargetNode>>,
45) {
46 for (interaction, mut color, maybe_rotate, maybe_scale) in &mut interaction_query {
47 match *interaction {
48 Interaction::Pressed => {
49 *color = PRESSED_BUTTON.into();
50 if let Some(step) = maybe_rotate {
51 for mut transform in rotator_query.iter_mut() {
52 transform.rotation *= step.0;
53 }
54 }
55 if let Some(step) = maybe_scale {
56 for mut transform in rotator_query.iter_mut() {
57 transform.scale += step.0;
58 transform.scale =
59 transform.scale.clamp(Vec2::splat(0.25), Vec2::splat(3.0));
60 }
61 }
62 }
63 Interaction::Hovered => {
64 *color = HOVERED_BUTTON.into();
65 }
66 Interaction::None => {
67 *color = NORMAL_BUTTON.into();
68 }
69 }
70 }
71}
Sourcepub fn min_element(self) -> f32
pub fn min_element(self) -> f32
Returns the horizontal minimum of self
.
In other words this computes min(x, y, ..)
.
NaN propogation does not follow IEEE 754-2008 semantics and may differ on different SIMD architectures.
Sourcepub fn max_element(self) -> f32
pub fn max_element(self) -> f32
Returns the horizontal maximum of self
.
In other words this computes max(x, y, ..)
.
NaN propogation does not follow IEEE 754-2008 semantics and may differ on different SIMD architectures.
Sourcepub fn min_position(self) -> usize
pub fn min_position(self) -> usize
Returns the index of the first minimum element of self
.
Sourcepub fn max_position(self) -> usize
pub fn max_position(self) -> usize
Returns the index of the first maximum element of self
.
Sourcepub fn element_sum(self) -> f32
pub fn element_sum(self) -> f32
Returns the sum of all elements of self
.
In other words, this computes self.x + self.y + ..
.
Sourcepub fn element_product(self) -> f32
pub fn element_product(self) -> f32
Returns the product of all elements of self
.
In other words, this computes self.x * self.y * ..
.
Sourcepub fn cmpeq(self, rhs: Vec2) -> BVec2
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.
Sourcepub fn cmpne(self, rhs: Vec2) -> BVec2
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.
Sourcepub fn cmpge(self, rhs: Vec2) -> BVec2
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.
Sourcepub fn cmpgt(self, rhs: Vec2) -> BVec2
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.
Sourcepub fn cmple(self, rhs: Vec2) -> BVec2
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.
Sourcepub fn cmplt(self, rhs: Vec2) -> BVec2
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.
Sourcepub fn abs(self) -> Vec2
pub fn abs(self) -> Vec2
Returns a vector containing the absolute value of each element of self
.
Examples found in repository?
321 fn aabb_2d(&self, isometry: impl Into<Isometry2d>) -> Aabb2d {
322 let isometry = isometry.into();
323
324 // The center of the circle at the center of the right wing of the heart
325 let circle_center = isometry.rotation * Vec2::new(self.radius, 0.0);
326 // The maximum X and Y positions of the two circles of the wings of the heart.
327 let max_circle = circle_center.abs() + Vec2::splat(self.radius);
328 // Since the two circles of the heart are mirrored around the origin, the minimum position is the negative of the maximum.
329 let min_circle = -max_circle;
330
331 // The position of the tip at the bottom of the heart
332 let tip_position = isometry.rotation * Vec2::new(0.0, -self.radius * (1. + SQRT_2));
333
334 Aabb2d {
335 min: isometry.translation + min_circle.min(tip_position),
336 max: isometry.translation + max_circle.max(tip_position),
337 }
338 }
Sourcepub fn signum(self) -> Vec2
pub fn signum(self) -> Vec2
Returns a vector with elements representing the sign of self
.
1.0
if the number is positive,+0.0
orINFINITY
-1.0
if the number is negative,-0.0
orNEG_INFINITY
NAN
if the number isNAN
Sourcepub fn copysign(self, rhs: Vec2) -> Vec2
pub fn copysign(self, rhs: Vec2) -> Vec2
Returns a vector with signs of rhs
and the magnitudes of self
.
Sourcepub fn is_negative_bitmask(self) -> u32
pub fn is_negative_bitmask(self) -> u32
Returns a bitmask with the lowest 2 bits set to the sign bits from the elements of self
.
A negative element results in a 1
bit and a positive element in a 0
bit. Element x
goes
into the first lowest bit, element y
into the second, etc.
An element is negative if it has a negative sign, including -0.0, NaNs with negative sign bit and negative infinity.
Sourcepub fn is_finite(self) -> bool
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
.
Sourcepub fn is_finite_mask(self) -> BVec2
pub fn is_finite_mask(self) -> BVec2
Performs is_finite
on each element of self, returning a vector mask of the results.
In other words, this computes [x.is_finite(), y.is_finite(), ...]
.
Sourcepub fn is_nan_mask(self) -> BVec2
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(), ...]
.
Sourcepub fn length(self) -> f32
pub fn length(self) -> f32
Computes the length of self
.
Examples found in repository?
246fn start_drag(
247 mut commands: Commands,
248 cursor_world_pos: Res<CursorWorldPos>,
249 bevy_logo_transform: Single<&Transform, With<BevyLogo>>,
250) {
251 // If the cursor is not within the primary window skip this system
252 let Some(cursor_world_pos) = cursor_world_pos.0 else {
253 return;
254 };
255
256 // Get the offset from the cursor to the Bevy logo sprite
257 let drag_offset = bevy_logo_transform.translation.truncate() - cursor_world_pos;
258
259 // If the cursor is within the Bevy logo radius start the drag operation and remember the offset of the cursor from the origin
260 if drag_offset.length() < BEVY_LOGO_RADIUS {
261 commands.insert_resource(DragOperation(drag_offset));
262 }
263}
264
265/// Stop the current drag operation
266fn end_drag(mut commands: Commands) {
267 commands.remove_resource::<DragOperation>();
268}
269
270/// Drag the Bevy logo
271fn drag(
272 drag_offset: Res<DragOperation>,
273 cursor_world_pos: Res<CursorWorldPos>,
274 time: Res<Time>,
275 mut bevy_transform: Single<&mut Transform, With<BevyLogo>>,
276 mut q_pupils: Query<&mut Pupil>,
277) {
278 // If the cursor is not within the primary window skip this system
279 let Some(cursor_world_pos) = cursor_world_pos.0 else {
280 return;
281 };
282
283 // Calculate the new translation of the Bevy logo based on cursor and drag offset
284 let new_translation = cursor_world_pos + drag_offset.0;
285
286 // Calculate how fast we are dragging the Bevy logo (unit/second)
287 let drag_velocity =
288 (new_translation - bevy_transform.translation.truncate()) / time.delta_secs();
289
290 // Update the translation of Bevy logo transform to new translation
291 bevy_transform.translation = new_translation.extend(bevy_transform.translation.z);
292
293 // Add the cursor drag velocity in the opposite direction to each pupil.
294 // Remember pupils are using local coordinates to move. So when the Bevy logo moves right they need to move left to
295 // simulate inertia, otherwise they will move fixed to the parent.
296 for mut pupil in &mut q_pupils {
297 pupil.velocity -= drag_velocity;
298 }
299}
300
301/// Quit when the user right clicks the Bevy logo
302fn quit(
303 cursor_world_pos: Res<CursorWorldPos>,
304 mut app_exit: MessageWriter<AppExit>,
305 bevy_logo_transform: Single<&Transform, With<BevyLogo>>,
306) {
307 // If the cursor is not within the primary window skip this system
308 let Some(cursor_world_pos) = cursor_world_pos.0 else {
309 return;
310 };
311
312 // If the cursor is within the Bevy logo radius send the [`AppExit`] event to quit the app
313 if bevy_logo_transform
314 .translation
315 .truncate()
316 .distance(cursor_world_pos)
317 < BEVY_LOGO_RADIUS
318 {
319 app_exit.write(AppExit::Success);
320 }
321}
322
323/// Enable transparency for the window and make it on top
324fn toggle_transparency(
325 mut commands: Commands,
326 mut window_transparency: ResMut<WindowTransparency>,
327 mut q_instructions_text: Query<&mut Visibility, With<InstructionsText>>,
328 mut primary_window: Single<&mut Window, With<PrimaryWindow>>,
329) {
330 // Toggle the window transparency resource
331 window_transparency.0 = !window_transparency.0;
332
333 // Show or hide the instructions text
334 for mut visibility in &mut q_instructions_text {
335 *visibility = if window_transparency.0 {
336 Visibility::Hidden
337 } else {
338 Visibility::Visible
339 };
340 }
341
342 // Remove the primary window's decorations (e.g. borders), make it always on top of other desktop windows, and set the clear color to transparent
343 // only if window transparency is enabled
344 let clear_color;
345 (
346 primary_window.decorations,
347 primary_window.window_level,
348 clear_color,
349 ) = if window_transparency.0 {
350 (false, WindowLevel::AlwaysOnTop, Color::NONE)
351 } else {
352 (true, WindowLevel::Normal, WINDOW_CLEAR_COLOR)
353 };
354
355 // Set the clear color
356 commands.insert_resource(ClearColor(clear_color));
357}
358
359/// Move the pupils and bounce them around
360fn move_pupils(time: Res<Time>, mut q_pupils: Query<(&mut Pupil, &mut Transform)>) {
361 for (mut pupil, mut transform) in &mut q_pupils {
362 // The wiggle radius is how much the pupil can move within the eye
363 let wiggle_radius = pupil.eye_radius - pupil.pupil_radius;
364 // Store the Z component
365 let z = transform.translation.z;
366 // Truncate the Z component to make the calculations be on [`Vec2`]
367 let mut translation = transform.translation.truncate();
368 // Decay the pupil velocity
369 pupil.velocity *= ops::powf(0.04f32, time.delta_secs());
370 // Move the pupil
371 translation += pupil.velocity * time.delta_secs();
372 // If the pupil hit the outside border of the eye, limit the translation to be within the wiggle radius and invert the velocity.
373 // This is not physically accurate but it's good enough for the googly eyes effect.
374 if translation.length() > wiggle_radius {
375 translation = translation.normalize() * wiggle_radius;
376 // Invert and decrease the velocity of the pupil when it bounces
377 pupil.velocity *= -0.75;
378 }
379 // Update the entity transform with the new translation after reading the Z component
380 transform.translation = translation.extend(z);
381 }
382}
Sourcepub fn length_squared(self) -> f32
pub fn length_squared(self) -> f32
Computes the squared length of self
.
This is faster than length()
as it avoids a square root operation.
Sourcepub fn length_recip(self) -> f32
pub fn length_recip(self) -> f32
Computes 1.0 / length()
.
For valid results, self
must not be of length zero.
Examples found in repository?
384fn process_move_input(
385 mut selections: Query<(&mut Transform, &Selection)>,
386 mouse_buttons: Res<ButtonInput<MouseButton>>,
387 mouse_motion: Res<AccumulatedMouseMotion>,
388 app_status: Res<AppStatus>,
389) {
390 // Only process drags when movement is selected.
391 if !mouse_buttons.pressed(MouseButton::Left) || app_status.drag_mode != DragMode::Move {
392 return;
393 }
394
395 for (mut transform, selection) in &mut selections {
396 if app_status.selection != *selection {
397 continue;
398 }
399
400 let position = transform.translation;
401
402 // Convert to spherical coordinates.
403 let radius = position.length();
404 let mut theta = acos(position.y / radius);
405 let mut phi = position.z.signum() * acos(position.x * position.xz().length_recip());
406
407 // Camera movement is the inverse of object movement.
408 let (phi_factor, theta_factor) = match *selection {
409 Selection::Camera => (1.0, -1.0),
410 Selection::DecalA | Selection::DecalB => (-1.0, 1.0),
411 };
412
413 // Adjust the spherical coordinates. Clamp the inclination to (0, π).
414 phi += phi_factor * mouse_motion.delta.x * MOVE_SPEED;
415 theta = f32::clamp(
416 theta + theta_factor * mouse_motion.delta.y * MOVE_SPEED,
417 0.001,
418 PI - 0.001,
419 );
420
421 // Convert spherical coordinates back to Cartesian coordinates.
422 transform.translation =
423 radius * vec3(sin(theta) * cos(phi), cos(theta), sin(theta) * sin(phi));
424
425 // Look at the center, but preserve the previous roll angle.
426 let roll = transform.rotation.to_euler(EulerRot::YXZ).2;
427 transform.look_at(Vec3::ZERO, Vec3::Y);
428 let (yaw, pitch, _) = transform.rotation.to_euler(EulerRot::YXZ);
429 transform.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll);
430 }
431}
More examples
461fn process_move_input(
462 mut selections: Query<(&mut Transform, &Selection)>,
463 mouse_buttons: Res<ButtonInput<MouseButton>>,
464 mouse_motion: Res<AccumulatedMouseMotion>,
465 app_status: Res<AppStatus>,
466) {
467 // Only process drags when movement is selected.
468 if !mouse_buttons.pressed(MouseButton::Left) || app_status.drag_mode != DragMode::Move {
469 return;
470 }
471
472 for (mut transform, selection) in &mut selections {
473 if app_status.selection != *selection {
474 continue;
475 }
476
477 // use simple movement for the point light
478 if *selection == Selection::PointLight {
479 transform.translation +=
480 (mouse_motion.delta * Vec2::new(1.0, -1.0) * MOVE_SPEED).extend(0.0);
481 return;
482 }
483
484 let position = transform.translation;
485
486 // Convert to spherical coordinates.
487 let radius = position.length();
488 let mut theta = acos(position.y / radius);
489 let mut phi = position.z.signum() * acos(position.x * position.xz().length_recip());
490
491 // Camera movement is the inverse of object movement.
492 let (phi_factor, theta_factor) = match *selection {
493 Selection::Camera => (1.0, -1.0),
494 _ => (-1.0, 1.0),
495 };
496
497 // Adjust the spherical coordinates. Clamp the inclination to (0, π).
498 phi += phi_factor * mouse_motion.delta.x * MOVE_SPEED;
499 theta = f32::clamp(
500 theta + theta_factor * mouse_motion.delta.y * MOVE_SPEED,
501 0.001,
502 PI - 0.001,
503 );
504
505 // Convert spherical coordinates back to Cartesian coordinates.
506 transform.translation =
507 radius * vec3(sin(theta) * cos(phi), cos(theta), sin(theta) * sin(phi));
508
509 // Look at the center, but preserve the previous roll angle.
510 let roll = transform.rotation.to_euler(EulerRot::YXZ).2;
511 transform.look_at(Vec3::ZERO, Vec3::Y);
512 let (yaw, pitch, _) = transform.rotation.to_euler(EulerRot::YXZ);
513 transform.rotation = Quat::from_euler(EulerRot::YXZ, yaw, pitch, roll);
514 }
515}
Sourcepub fn distance(self, rhs: Vec2) -> f32
pub fn distance(self, rhs: Vec2) -> f32
Computes the Euclidean distance between two points in space.
Examples found in repository?
220fn update_cursor_hit_test(
221 cursor_world_pos: Res<CursorWorldPos>,
222 primary_window: Single<(&Window, &mut CursorOptions), With<PrimaryWindow>>,
223 bevy_logo_transform: Single<&Transform, With<BevyLogo>>,
224) {
225 let (window, mut cursor_options) = primary_window.into_inner();
226 // If the window has decorations (e.g. a border) then it should be clickable
227 if window.decorations {
228 cursor_options.hit_test = true;
229 return;
230 }
231
232 // If the cursor is not within the window we don't need to update whether the window is clickable or not
233 let Some(cursor_world_pos) = cursor_world_pos.0 else {
234 return;
235 };
236
237 // If the cursor is within the radius of the Bevy logo make the window clickable otherwise the window is not clickable
238 cursor_options.hit_test = bevy_logo_transform
239 .translation
240 .truncate()
241 .distance(cursor_world_pos)
242 < BEVY_LOGO_RADIUS;
243}
244
245/// Start the drag operation and record the offset we started dragging from
246fn start_drag(
247 mut commands: Commands,
248 cursor_world_pos: Res<CursorWorldPos>,
249 bevy_logo_transform: Single<&Transform, With<BevyLogo>>,
250) {
251 // If the cursor is not within the primary window skip this system
252 let Some(cursor_world_pos) = cursor_world_pos.0 else {
253 return;
254 };
255
256 // Get the offset from the cursor to the Bevy logo sprite
257 let drag_offset = bevy_logo_transform.translation.truncate() - cursor_world_pos;
258
259 // If the cursor is within the Bevy logo radius start the drag operation and remember the offset of the cursor from the origin
260 if drag_offset.length() < BEVY_LOGO_RADIUS {
261 commands.insert_resource(DragOperation(drag_offset));
262 }
263}
264
265/// Stop the current drag operation
266fn end_drag(mut commands: Commands) {
267 commands.remove_resource::<DragOperation>();
268}
269
270/// Drag the Bevy logo
271fn drag(
272 drag_offset: Res<DragOperation>,
273 cursor_world_pos: Res<CursorWorldPos>,
274 time: Res<Time>,
275 mut bevy_transform: Single<&mut Transform, With<BevyLogo>>,
276 mut q_pupils: Query<&mut Pupil>,
277) {
278 // If the cursor is not within the primary window skip this system
279 let Some(cursor_world_pos) = cursor_world_pos.0 else {
280 return;
281 };
282
283 // Calculate the new translation of the Bevy logo based on cursor and drag offset
284 let new_translation = cursor_world_pos + drag_offset.0;
285
286 // Calculate how fast we are dragging the Bevy logo (unit/second)
287 let drag_velocity =
288 (new_translation - bevy_transform.translation.truncate()) / time.delta_secs();
289
290 // Update the translation of Bevy logo transform to new translation
291 bevy_transform.translation = new_translation.extend(bevy_transform.translation.z);
292
293 // Add the cursor drag velocity in the opposite direction to each pupil.
294 // Remember pupils are using local coordinates to move. So when the Bevy logo moves right they need to move left to
295 // simulate inertia, otherwise they will move fixed to the parent.
296 for mut pupil in &mut q_pupils {
297 pupil.velocity -= drag_velocity;
298 }
299}
300
301/// Quit when the user right clicks the Bevy logo
302fn quit(
303 cursor_world_pos: Res<CursorWorldPos>,
304 mut app_exit: MessageWriter<AppExit>,
305 bevy_logo_transform: Single<&Transform, With<BevyLogo>>,
306) {
307 // If the cursor is not within the primary window skip this system
308 let Some(cursor_world_pos) = cursor_world_pos.0 else {
309 return;
310 };
311
312 // If the cursor is within the Bevy logo radius send the [`AppExit`] event to quit the app
313 if bevy_logo_transform
314 .translation
315 .truncate()
316 .distance(cursor_world_pos)
317 < BEVY_LOGO_RADIUS
318 {
319 app_exit.write(AppExit::Success);
320 }
321}
More examples
10fn main() {
11 App::new()
12 .add_plugins(DefaultPlugins)
13 .init_resource::<SpatialIndex>()
14 .add_systems(Startup, setup)
15 .add_systems(Update, (draw_shapes, handle_click))
16 // Observers are systems that run when an event is "triggered". This observer runs whenever
17 // `ExplodeMines` is triggered.
18 .add_observer(
19 |explode_mines: On<ExplodeMines>,
20 mines: Query<&Mine>,
21 index: Res<SpatialIndex>,
22 mut commands: Commands| {
23 // Access resources
24 for entity in index.get_nearby(explode_mines.pos) {
25 // Run queries
26 let mine = mines.get(entity).unwrap();
27 if mine.pos.distance(explode_mines.pos) < mine.size + explode_mines.radius {
28 // And queue commands, including triggering additional events
29 // Here we trigger the `Explode` event for entity `e`
30 commands.trigger(Explode { entity });
31 }
32 }
33 },
34 )
35 // This observer runs whenever the `Mine` component is added to an entity, and places it in a simple spatial index.
36 .add_observer(on_add_mine)
37 // This observer runs whenever the `Mine` component is removed from an entity (including despawning it)
38 // and removes it from the spatial index.
39 .add_observer(on_remove_mine)
40 .run();
41}
38fn setup(mut commands: Commands, mut images: ResMut<Assets<Image>>) {
39 commands.spawn(Camera2d);
40
41 // Create an image that we are going to draw into
42 let mut image = Image::new_fill(
43 // 2D image of size 256x256
44 Extent3d {
45 width: IMAGE_WIDTH,
46 height: IMAGE_HEIGHT,
47 depth_or_array_layers: 1,
48 },
49 TextureDimension::D2,
50 // Initialize it with a beige color
51 &(css::BEIGE.to_u8_array()),
52 // Use the same encoding as the color we set
53 TextureFormat::Rgba8UnormSrgb,
54 RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD,
55 );
56
57 // To make it extra fancy, we can set the Alpha of each pixel,
58 // so that it fades out in a circular fashion.
59 for y in 0..IMAGE_HEIGHT {
60 for x in 0..IMAGE_WIDTH {
61 let center = Vec2::new(IMAGE_WIDTH as f32 / 2.0, IMAGE_HEIGHT as f32 / 2.0);
62 let max_radius = IMAGE_HEIGHT.min(IMAGE_WIDTH) as f32 / 2.0;
63 let r = Vec2::new(x as f32, y as f32).distance(center);
64 let a = 1.0 - (r / max_radius).clamp(0.0, 1.0);
65
66 // Here we will set the A value by accessing the raw data bytes.
67 // (it is the 4th byte of each pixel, as per our `TextureFormat`)
68
69 // Find our pixel by its coordinates
70 let pixel_bytes = image.pixel_bytes_mut(UVec3::new(x, y, 0)).unwrap();
71 // Convert our f32 to u8
72 pixel_bytes[3] = (a * u8::MAX as f32) as u8;
73 }
74 }
75
76 // Add it to Bevy's assets, so it can be used for rendering
77 // this will give us a handle we can use
78 // (to display it in a sprite, or as part of UI, etc.)
79 let handle = images.add(image);
80
81 // Create a sprite entity using our image
82 commands.spawn(Sprite::from_image(handle.clone()));
83 commands.insert_resource(MyProcGenImage(handle));
84
85 // We're seeding the PRNG here to make this example deterministic for testing purposes.
86 // This isn't strictly required in practical use unless you need your app to be deterministic.
87 let seeded_rng = ChaCha8Rng::seed_from_u64(19878367467712);
88 commands.insert_resource(SeededRng(seeded_rng));
89}
Sourcepub fn distance_squared(self, rhs: Vec2) -> f32
pub fn distance_squared(self, rhs: Vec2) -> f32
Compute the squared euclidean distance between two points in space.
Sourcepub fn div_euclid(self, rhs: Vec2) -> Vec2
pub fn div_euclid(self, rhs: Vec2) -> Vec2
Returns the element-wise quotient of [Euclidean division] of self
by rhs
.
Sourcepub fn rem_euclid(self, rhs: Vec2) -> Vec2
pub fn rem_euclid(self, rhs: Vec2) -> Vec2
Returns the element-wise remainder of Euclidean division of self
by rhs
.
Sourcepub fn normalize(self) -> Vec2
pub fn normalize(self) -> Vec2
Returns self
normalized to length 1.0.
For valid results, self
must be finite and not of length zero, nor very close to zero.
See also Self::try_normalize()
and Self::normalize_or_zero()
.
§Panics
Will panic if the resulting normalized vector is not finite when glam_assert
is enabled.
Examples found in repository?
154fn snap_to_player_system(
155 mut query: Query<&mut Transform, (With<SnapToPlayer>, Without<Player>)>,
156 player_transform: Single<&Transform, With<Player>>,
157) {
158 // Get the player translation in 2D
159 let player_translation = player_transform.translation.xy();
160
161 for mut enemy_transform in &mut query {
162 // Get the vector from the enemy ship to the player ship in 2D and normalize it.
163 let to_player = (player_translation - enemy_transform.translation.xy()).normalize();
164
165 // Get the quaternion to rotate from the initial enemy facing direction to the direction
166 // facing the player
167 let rotate_to_player = Quat::from_rotation_arc(Vec3::Y, to_player.extend(0.));
168
169 // Rotate the enemy to face the player
170 enemy_transform.rotation = rotate_to_player;
171 }
172}
173
174/// Demonstrates rotating an enemy ship to face the player ship at a given rotation speed.
175///
176/// This method uses the vector dot product to determine if the enemy is facing the player and
177/// if not, which way to rotate to face the player. The dot product on two unit length vectors
178/// will return a value between -1.0 and +1.0 which tells us the following about the two vectors:
179///
180/// * If the result is 1.0 the vectors are pointing in the same direction, the angle between them is
181/// 0 degrees.
182/// * If the result is 0.0 the vectors are perpendicular, the angle between them is 90 degrees.
183/// * If the result is -1.0 the vectors are parallel but pointing in opposite directions, the angle
184/// between them is 180 degrees.
185/// * If the result is positive the vectors are pointing in roughly the same direction, the angle
186/// between them is greater than 0 and less than 90 degrees.
187/// * If the result is negative the vectors are pointing in roughly opposite directions, the angle
188/// between them is greater than 90 and less than 180 degrees.
189///
190/// It is possible to get the angle by taking the arc cosine (`acos`) of the dot product. It is
191/// often unnecessary to do this though. Beware than `acos` will return `NaN` if the input is less
192/// than -1.0 or greater than 1.0. This can happen even when working with unit vectors due to
193/// floating point precision loss, so it pays to clamp your dot product value before calling
194/// `acos`.
195fn rotate_to_player_system(
196 time: Res<Time>,
197 mut query: Query<(&RotateToPlayer, &mut Transform), Without<Player>>,
198 player_transform: Single<&Transform, With<Player>>,
199) {
200 // Get the player translation in 2D
201 let player_translation = player_transform.translation.xy();
202
203 for (config, mut enemy_transform) in &mut query {
204 // Get the enemy ship forward vector in 2D (already unit length)
205 let enemy_forward = (enemy_transform.rotation * Vec3::Y).xy();
206
207 // Get the vector from the enemy ship to the player ship in 2D and normalize it.
208 let to_player = (player_translation - enemy_transform.translation.xy()).normalize();
209
210 // Get the dot product between the enemy forward vector and the direction to the player.
211 let forward_dot_player = enemy_forward.dot(to_player);
212
213 // If the dot product is approximately 1.0 then the enemy is already facing the player and
214 // we can early out.
215 if (forward_dot_player - 1.0).abs() < f32::EPSILON {
216 continue;
217 }
218
219 // Get the right vector of the enemy ship in 2D (already unit length)
220 let enemy_right = (enemy_transform.rotation * Vec3::X).xy();
221
222 // Get the dot product of the enemy right vector and the direction to the player ship.
223 // If the dot product is negative them we need to rotate counter clockwise, if it is
224 // positive we need to rotate clockwise. Note that `copysign` will still return 1.0 if the
225 // dot product is 0.0 (because the player is directly behind the enemy, so perpendicular
226 // with the right vector).
227 let right_dot_player = enemy_right.dot(to_player);
228
229 // Determine the sign of rotation from the right dot player. We need to negate the sign
230 // here as the 2D bevy co-ordinate system rotates around +Z, which is pointing out of the
231 // screen. Due to the right hand rule, positive rotation around +Z is counter clockwise and
232 // negative is clockwise.
233 let rotation_sign = -f32::copysign(1.0, right_dot_player);
234
235 // Limit rotation so we don't overshoot the target. We need to convert our dot product to
236 // an angle here so we can get an angle of rotation to clamp against.
237 let max_angle = ops::acos(forward_dot_player.clamp(-1.0, 1.0)); // Clamp acos for safety
238
239 // Calculate angle of rotation with limit
240 let rotation_angle =
241 rotation_sign * (config.rotation_speed * time.delta_secs()).min(max_angle);
242
243 // Rotate the enemy to face the player
244 enemy_transform.rotate_z(rotation_angle);
245 }
246}
More examples
456 fn perimeter(&self) -> Vec<PerimeterSegment> {
457 let resolution = self.resolution as u32;
458 vec![
459 // The left wing of the heart
460 PerimeterSegment::Smooth {
461 // The normals of the first and last vertices of smooth segments have to be specified manually.
462 first_normal: Vec2::X,
463 last_normal: Vec2::new(-1.0, -1.0).normalize(),
464 // These indices are used to index into the `ATTRIBUTE_POSITION` vec of your 2D mesh.
465 indices: (0..resolution).collect(),
466 },
467 // The bottom tip of the heart
468 PerimeterSegment::Flat {
469 indices: vec![resolution - 1, resolution, resolution + 1],
470 },
471 // The right wing of the heart
472 PerimeterSegment::Smooth {
473 first_normal: Vec2::new(1.0, -1.0).normalize(),
474 last_normal: Vec2::NEG_X,
475 indices: (resolution + 1..2 * resolution).chain([0]).collect(),
476 },
477 ]
478 }
360fn move_pupils(time: Res<Time>, mut q_pupils: Query<(&mut Pupil, &mut Transform)>) {
361 for (mut pupil, mut transform) in &mut q_pupils {
362 // The wiggle radius is how much the pupil can move within the eye
363 let wiggle_radius = pupil.eye_radius - pupil.pupil_radius;
364 // Store the Z component
365 let z = transform.translation.z;
366 // Truncate the Z component to make the calculations be on [`Vec2`]
367 let mut translation = transform.translation.truncate();
368 // Decay the pupil velocity
369 pupil.velocity *= ops::powf(0.04f32, time.delta_secs());
370 // Move the pupil
371 translation += pupil.velocity * time.delta_secs();
372 // If the pupil hit the outside border of the eye, limit the translation to be within the wiggle radius and invert the velocity.
373 // This is not physically accurate but it's good enough for the googly eyes effect.
374 if translation.length() > wiggle_radius {
375 translation = translation.normalize() * wiggle_radius;
376 // Invert and decrease the velocity of the pupil when it bounces
377 pupil.velocity *= -0.75;
378 }
379 // Update the entity transform with the new translation after reading the Z component
380 transform.translation = translation.extend(z);
381 }
382}
173fn setup(
174 mut commands: Commands,
175 mut meshes: ResMut<Assets<Mesh>>,
176 mut materials: ResMut<Assets<ColorMaterial>>,
177 asset_server: Res<AssetServer>,
178) {
179 // Camera
180 commands.spawn(Camera2d);
181
182 // Sound
183 let ball_collision_sound = asset_server.load("sounds/breakout_collision.ogg");
184 commands.insert_resource(CollisionSound(ball_collision_sound));
185
186 // Paddle
187 let paddle_y = BOTTOM_WALL + GAP_BETWEEN_PADDLE_AND_FLOOR;
188
189 commands.spawn((
190 Sprite::from_color(PADDLE_COLOR, Vec2::ONE),
191 Transform {
192 translation: Vec3::new(0.0, paddle_y, 0.0),
193 scale: PADDLE_SIZE.extend(1.0),
194 ..default()
195 },
196 Paddle,
197 Collider,
198 ));
199
200 // Ball
201 commands.spawn((
202 Mesh2d(meshes.add(Circle::default())),
203 MeshMaterial2d(materials.add(BALL_COLOR)),
204 Transform::from_translation(BALL_STARTING_POSITION)
205 .with_scale(Vec2::splat(BALL_DIAMETER).extend(1.)),
206 Ball,
207 Velocity(INITIAL_BALL_DIRECTION.normalize() * BALL_SPEED),
208 ));
209
210 // Scoreboard
211 commands.spawn((
212 Text::new("Score: "),
213 TextFont {
214 font_size: SCOREBOARD_FONT_SIZE,
215 ..default()
216 },
217 TextColor(TEXT_COLOR),
218 ScoreboardUi,
219 Node {
220 position_type: PositionType::Absolute,
221 top: SCOREBOARD_TEXT_PADDING,
222 left: SCOREBOARD_TEXT_PADDING,
223 ..default()
224 },
225 children![(
226 TextSpan::default(),
227 TextFont {
228 font_size: SCOREBOARD_FONT_SIZE,
229 ..default()
230 },
231 TextColor(SCORE_COLOR),
232 )],
233 ));
234
235 // Walls
236 commands.spawn(Wall::new(WallLocation::Left));
237 commands.spawn(Wall::new(WallLocation::Right));
238 commands.spawn(Wall::new(WallLocation::Bottom));
239 commands.spawn(Wall::new(WallLocation::Top));
240
241 // Bricks
242 let total_width_of_bricks = (RIGHT_WALL - LEFT_WALL) - 2. * GAP_BETWEEN_BRICKS_AND_SIDES;
243 let bottom_edge_of_bricks = paddle_y + GAP_BETWEEN_PADDLE_AND_BRICKS;
244 let total_height_of_bricks = TOP_WALL - bottom_edge_of_bricks - GAP_BETWEEN_BRICKS_AND_CEILING;
245
246 assert!(total_width_of_bricks > 0.0);
247 assert!(total_height_of_bricks > 0.0);
248
249 // Given the space available, compute how many rows and columns of bricks we can fit
250 let n_columns = (total_width_of_bricks / (BRICK_SIZE.x + GAP_BETWEEN_BRICKS)).floor() as usize;
251 let n_rows = (total_height_of_bricks / (BRICK_SIZE.y + GAP_BETWEEN_BRICKS)).floor() as usize;
252 let n_vertical_gaps = n_columns - 1;
253
254 // Because we need to round the number of columns,
255 // the space on the top and sides of the bricks only captures a lower bound, not an exact value
256 let center_of_bricks = (LEFT_WALL + RIGHT_WALL) / 2.0;
257 let left_edge_of_bricks = center_of_bricks
258 // Space taken up by the bricks
259 - (n_columns as f32 / 2.0 * BRICK_SIZE.x)
260 // Space taken up by the gaps
261 - n_vertical_gaps as f32 / 2.0 * GAP_BETWEEN_BRICKS;
262
263 // In Bevy, the `translation` of an entity describes the center point,
264 // not its bottom-left corner
265 let offset_x = left_edge_of_bricks + BRICK_SIZE.x / 2.;
266 let offset_y = bottom_edge_of_bricks + BRICK_SIZE.y / 2.;
267
268 for row in 0..n_rows {
269 for column in 0..n_columns {
270 let brick_position = Vec2::new(
271 offset_x + column as f32 * (BRICK_SIZE.x + GAP_BETWEEN_BRICKS),
272 offset_y + row as f32 * (BRICK_SIZE.y + GAP_BETWEEN_BRICKS),
273 );
274
275 // brick
276 commands.spawn((
277 Sprite {
278 color: BRICK_COLOR,
279 ..default()
280 },
281 Transform {
282 translation: brick_position.extend(0.0),
283 scale: Vec3::new(BRICK_SIZE.x, BRICK_SIZE.y, 1.0),
284 ..default()
285 },
286 Brick,
287 Collider,
288 ));
289 }
290 }
291}
Sourcepub fn try_normalize(self) -> Option<Vec2>
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()
.
Sourcepub fn normalize_or(self, fallback: Vec2) -> Vec2
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()
.
Sourcepub fn normalize_or_zero(self) -> Vec2
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?
88fn move_player(
89 mut player: Single<&mut Transform, With<Player>>,
90 time: Res<Time>,
91 kb_input: Res<ButtonInput<KeyCode>>,
92) {
93 let mut direction = Vec2::ZERO;
94
95 if kb_input.pressed(KeyCode::KeyW) {
96 direction.y += 1.;
97 }
98
99 if kb_input.pressed(KeyCode::KeyS) {
100 direction.y -= 1.;
101 }
102
103 if kb_input.pressed(KeyCode::KeyA) {
104 direction.x -= 1.;
105 }
106
107 if kb_input.pressed(KeyCode::KeyD) {
108 direction.x += 1.;
109 }
110
111 // Progressively update the player's position over time. Normalize the
112 // direction vector to prevent it from exceeding a magnitude of 1 when
113 // moving diagonally.
114 let move_delta = direction.normalize_or_zero() * PLAYER_SPEED * time.delta_secs();
115 player.translation += move_delta.extend(0.);
116}
More examples
226fn resize_image(
227 image_mesh: Query<(&MeshMaterial3d<StandardMaterial>, &Mesh3d), With<HDRViewer>>,
228 materials: Res<Assets<StandardMaterial>>,
229 mut meshes: ResMut<Assets<Mesh>>,
230 images: Res<Assets<Image>>,
231 mut image_event_reader: MessageReader<AssetEvent<Image>>,
232) {
233 for event in image_event_reader.read() {
234 let (AssetEvent::Added { id } | AssetEvent::Modified { id }) = event else {
235 continue;
236 };
237
238 for (mat_h, mesh_h) in &image_mesh {
239 let Some(mat) = materials.get(mat_h) else {
240 continue;
241 };
242
243 let Some(ref base_color_texture) = mat.base_color_texture else {
244 continue;
245 };
246
247 if *id != base_color_texture.id() {
248 continue;
249 };
250
251 let Some(image_changed) = images.get(*id) else {
252 continue;
253 };
254
255 let size = image_changed.size_f32().normalize_or_zero() * 1.4;
256 // Resize Mesh
257 let quad = Mesh::from(Rectangle::from_size(size));
258 meshes.insert(mesh_h, quad).unwrap();
259 }
260 }
261}
Sourcepub fn normalize_and_length(self) -> (Vec2, f32)
pub fn normalize_and_length(self) -> (Vec2, f32)
Returns self
normalized to length 1.0 and the length of self
.
If self
is zero length then (Self::X, 0.0)
is returned.
Sourcepub fn is_normalized(self) -> bool
pub fn is_normalized(self) -> bool
Returns whether self
is length 1.0
or not.
Uses a precision threshold of approximately 1e-4
.
Sourcepub fn project_onto(self, rhs: Vec2) -> Vec2
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.
Sourcepub fn reject_from(self, rhs: Vec2) -> Vec2
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.
Sourcepub fn project_onto_normalized(self, rhs: Vec2) -> Vec2
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.
Sourcepub fn reject_from_normalized(self, rhs: Vec2) -> Vec2
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.
Sourcepub fn round(self) -> Vec2
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.
Sourcepub fn floor(self) -> Vec2
pub fn floor(self) -> Vec2
Returns a vector containing the largest integer less than or equal to a number for each
element of self
.
Sourcepub fn ceil(self) -> Vec2
pub fn ceil(self) -> Vec2
Returns a vector containing the smallest integer greater than or equal to a number for
each element of self
.
Sourcepub fn trunc(self) -> Vec2
pub fn trunc(self) -> Vec2
Returns a vector containing the integer part each element of self
. This means numbers are
always truncated towards zero.
Sourcepub fn fract(self) -> Vec2
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.
Sourcepub fn fract_gl(self) -> Vec2
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.
Sourcepub fn exp(self) -> Vec2
pub fn exp(self) -> Vec2
Returns a vector containing e^self
(the exponential function) for each element of
self
.
Sourcepub fn powf(self, n: f32) -> Vec2
pub fn powf(self, n: f32) -> Vec2
Returns a vector containing each element of self
raised to the power of n
.
Sourcepub fn recip(self) -> Vec2
pub fn recip(self) -> Vec2
Returns a vector containing the reciprocal 1.0/n
of each element of self
.
Sourcepub fn lerp(self, rhs: Vec2, s: f32) -> Vec2
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.
Sourcepub fn move_towards(&self, rhs: Vec2, d: f32) -> Vec2
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
.
Sourcepub fn midpoint(self, rhs: Vec2) -> Vec2
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.
Sourcepub fn abs_diff_eq(self, rhs: Vec2, max_abs_diff: f32) -> bool
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.
Sourcepub fn clamp_length(self, min: f32, max: f32) -> Vec2
pub fn clamp_length(self, min: f32, max: f32) -> Vec2
Returns a vector with a length no less than min
and no more than max
.
§Panics
Will panic if min
is greater than max
, or if either min
or max
is negative, when glam_assert
is enabled.
Sourcepub fn clamp_length_max(self, max: f32) -> Vec2
pub fn clamp_length_max(self, max: f32) -> Vec2
Returns a vector with a length no more than max
.
§Panics
Will panic if max
is negative when glam_assert
is enabled.
Sourcepub fn clamp_length_min(self, min: f32) -> Vec2
pub fn clamp_length_min(self, min: f32) -> Vec2
Returns a vector with a length no less than min
.
§Panics
Will panic if min
is negative when glam_assert
is enabled.
Sourcepub fn mul_add(self, a: Vec2, b: Vec2) -> Vec2
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.
Sourcepub fn reflect(self, normal: Vec2) -> Vec2
pub fn reflect(self, normal: Vec2) -> Vec2
Returns the reflection vector for a given incident vector self
and surface normal
normal
.
normal
must be normalized.
§Panics
Will panic if normal
is not normalized when glam_assert
is enabled.
Sourcepub fn refract(self, normal: Vec2, eta: f32) -> Vec2
pub fn refract(self, normal: Vec2, eta: f32) -> Vec2
Returns the refraction direction for a given incident vector self
, surface normal
normal
and ratio of indices of refraction, eta
. When total internal reflection occurs,
a zero vector will be returned.
self
and normal
must be normalized.
§Panics
Will panic if self
or normal
is not normalized when glam_assert
is enabled.
Sourcepub fn from_angle(angle: f32) -> Vec2
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?
337fn rotate_camera(
338 time: Res<Time>,
339 mut camera_query: Query<&mut Transform, With<Camera3d>>,
340 app_status: Res<AppStatus>,
341) {
342 if !app_status.rotating {
343 return;
344 }
345
346 for mut transform in camera_query.iter_mut() {
347 transform.translation = Vec2::from_angle(time.delta_secs() * PI / 5.0)
348 .rotate(transform.translation.xz())
349 .extend(transform.translation.y)
350 .xzy();
351 transform.look_at(Vec3::ZERO, Vec3::Y);
352 }
353}
More examples
349fn rotate_camera(
350 mut camera_query: Query<&mut Transform, With<Camera3d>>,
351 time: Res<Time>,
352 app_status: Res<AppStatus>,
353) {
354 if !app_status.rotating {
355 return;
356 }
357
358 for mut transform in camera_query.iter_mut() {
359 transform.translation = Vec2::from_angle(ROTATION_SPEED * time.delta_secs())
360 .rotate(transform.translation.xz())
361 .extend(transform.translation.y)
362 .xzy();
363 transform.look_at(Vec3::ZERO, Vec3::Y);
364 }
365}
92fn draw(
93 my_handle: Res<MyProcGenImage>,
94 mut images: ResMut<Assets<Image>>,
95 // Used to keep track of where we are
96 mut i: Local<u32>,
97 mut draw_color: Local<Color>,
98 mut seeded_rng: ResMut<SeededRng>,
99) {
100 if *i == 0 {
101 // Generate a random color on first run.
102 *draw_color = Color::linear_rgb(
103 seeded_rng.0.random(),
104 seeded_rng.0.random(),
105 seeded_rng.0.random(),
106 );
107 }
108
109 // Get the image from Bevy's asset storage.
110 let image = images.get_mut(&my_handle.0).expect("Image not found");
111
112 // Compute the position of the pixel to draw.
113
114 let center = Vec2::new(IMAGE_WIDTH as f32 / 2.0, IMAGE_HEIGHT as f32 / 2.0);
115 let max_radius = IMAGE_HEIGHT.min(IMAGE_WIDTH) as f32 / 2.0;
116 let rot_speed = 0.0123;
117 let period = 0.12345;
118
119 let r = ops::sin(*i as f32 * period) * max_radius;
120 let xy = Vec2::from_angle(*i as f32 * rot_speed) * r + center;
121 let (x, y) = (xy.x as u32, xy.y as u32);
122
123 // Get the old color of that pixel.
124 let old_color = image.get_color_at(x, y).unwrap();
125
126 // If the old color is our current color, change our drawing color.
127 let tolerance = 1.0 / 255.0;
128 if old_color.distance(&draw_color) <= tolerance {
129 *draw_color = Color::linear_rgb(
130 seeded_rng.0.random(),
131 seeded_rng.0.random(),
132 seeded_rng.0.random(),
133 );
134 }
135
136 // Set the new color, but keep old alpha value from image.
137 image
138 .set_color_at(x, y, draw_color.with_alpha(old_color.alpha()))
139 .unwrap();
140
141 *i += 1;
142}
40fn draw_example_collection(
41 mut gizmos: Gizmos,
42 mut my_gizmos: Gizmos<MyRoundGizmos>,
43 time: Res<Time>,
44) {
45 let sin_t_scaled = ops::sin(time.elapsed_secs()) * 50.;
46 gizmos.line_2d(Vec2::Y * -sin_t_scaled, Vec2::splat(-80.), RED);
47 gizmos.ray_2d(Vec2::Y * sin_t_scaled, Vec2::splat(80.), LIME);
48
49 gizmos
50 .grid_2d(
51 Isometry2d::IDENTITY,
52 UVec2::new(16, 9),
53 Vec2::new(80., 80.),
54 // Dark gray
55 LinearRgba::gray(0.05),
56 )
57 .outer_edges();
58
59 // Triangle
60 gizmos.linestrip_gradient_2d([
61 (Vec2::Y * 300., BLUE),
62 (Vec2::new(-255., -155.), RED),
63 (Vec2::new(255., -155.), LIME),
64 (Vec2::Y * 300., BLUE),
65 ]);
66
67 gizmos.rect_2d(Isometry2d::IDENTITY, Vec2::splat(650.), BLACK);
68
69 gizmos.cross_2d(Vec2::new(-160., 120.), 12., FUCHSIA);
70
71 let domain = Interval::EVERYWHERE;
72 let curve = FunctionCurve::new(domain, |t| Vec2::new(t, ops::sin(t / 25.0) * 100.0));
73 let resolution = ((ops::sin(time.elapsed_secs()) + 1.0) * 50.0) as usize;
74 let times_and_colors = (0..=resolution)
75 .map(|n| n as f32 / resolution as f32)
76 .map(|t| (t - 0.5) * 600.0)
77 .map(|t| (t, TEAL.mix(&HOT_PINK, (t + 300.0) / 600.0)));
78 gizmos.curve_gradient_2d(curve, times_and_colors);
79
80 my_gizmos
81 .rounded_rect_2d(Isometry2d::IDENTITY, Vec2::splat(630.), BLACK)
82 .corner_radius(ops::cos(time.elapsed_secs() / 3.) * 100.);
83
84 // Circles have 32 line-segments by default.
85 // You may want to increase this for larger circles.
86 my_gizmos
87 .circle_2d(Isometry2d::IDENTITY, 300., NAVY)
88 .resolution(64);
89
90 my_gizmos.ellipse_2d(
91 Rot2::radians(time.elapsed_secs() % TAU),
92 Vec2::new(100., 200.),
93 YELLOW_GREEN,
94 );
95
96 // Arcs default resolution is linearly interpolated between
97 // 1 and 32, using the arc length as scalar.
98 my_gizmos.arc_2d(
99 Rot2::radians(sin_t_scaled / 10.),
100 FRAC_PI_2,
101 310.,
102 ORANGE_RED,
103 );
104 my_gizmos.arc_2d(Isometry2d::IDENTITY, FRAC_PI_2, 80.0, ORANGE_RED);
105 my_gizmos.long_arc_2d_between(Vec2::ZERO, Vec2::X * 20.0, Vec2::Y * 20.0, ORANGE_RED);
106 my_gizmos.short_arc_2d_between(Vec2::ZERO, Vec2::X * 40.0, Vec2::Y * 40.0, ORANGE_RED);
107
108 gizmos.arrow_2d(
109 Vec2::ZERO,
110 Vec2::from_angle(sin_t_scaled / -10. + PI / 2.) * 50.,
111 YELLOW,
112 );
113
114 // You can create more complex arrows using the arrow builder.
115 gizmos
116 .arrow_2d(
117 Vec2::ZERO,
118 Vec2::from_angle(sin_t_scaled / -10.) * 50.,
119 GREEN,
120 )
121 .with_double_end()
122 .with_tip_length(10.);
123}
Sourcepub fn to_angle(self) -> f32
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.
pub fn angle_between(self, rhs: Vec2) -> f32
Sourcepub fn angle_to(self, rhs: Vec2) -> f32
pub fn angle_to(self, rhs: Vec2) -> f32
Returns the angle of rotation (in radians) from self
to rhs
in the range [-π, +π]
.
The inputs do not need to be unit vectors however they must be non-zero.
Sourcepub fn perp_dot(self, rhs: Vec2) -> f32
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.
Sourcepub fn rotate(self, rhs: Vec2) -> Vec2
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?
337fn rotate_camera(
338 time: Res<Time>,
339 mut camera_query: Query<&mut Transform, With<Camera3d>>,
340 app_status: Res<AppStatus>,
341) {
342 if !app_status.rotating {
343 return;
344 }
345
346 for mut transform in camera_query.iter_mut() {
347 transform.translation = Vec2::from_angle(time.delta_secs() * PI / 5.0)
348 .rotate(transform.translation.xz())
349 .extend(transform.translation.y)
350 .xzy();
351 transform.look_at(Vec3::ZERO, Vec3::Y);
352 }
353}
More examples
349fn rotate_camera(
350 mut camera_query: Query<&mut Transform, With<Camera3d>>,
351 time: Res<Time>,
352 app_status: Res<AppStatus>,
353) {
354 if !app_status.rotating {
355 return;
356 }
357
358 for mut transform in camera_query.iter_mut() {
359 transform.translation = Vec2::from_angle(ROTATION_SPEED * time.delta_secs())
360 .rotate(transform.translation.xz())
361 .extend(transform.translation.y)
362 .xzy();
363 transform.look_at(Vec3::ZERO, Vec3::Y);
364 }
365}
Sourcepub fn rotate_towards(&self, rhs: Vec2, max_angle: f32) -> Vec2
pub fn rotate_towards(&self, rhs: Vec2, max_angle: f32) -> Vec2
Rotates towards rhs
up to max_angle
(in radians).
When max_angle
is 0.0
, the result will be equal to self
. When max_angle
is equal to
self.angle_between(rhs)
, the result will be parallel to rhs
. If max_angle
is negative,
rotates towards the exact opposite of rhs
. Will not go past the target.
Sourcepub fn as_i16vec2(&self) -> I16Vec2
pub fn as_i16vec2(&self) -> I16Vec2
Casts all elements of self
to i16
.
Sourcepub fn as_u16vec2(&self) -> U16Vec2
pub fn as_u16vec2(&self) -> U16Vec2
Casts all elements of self
to u16
.
Sourcepub fn as_uvec2(&self) -> UVec2
pub fn as_uvec2(&self) -> UVec2
Casts all elements of self
to u32
.
Examples found in repository?
121fn setup(
122 mut commands: Commands,
123 mut meshes: ResMut<Assets<Mesh>>,
124 mut materials: ResMut<Assets<ColorMaterial>>,
125 window: Single<&Window>,
126) {
127 let window_size = window.resolution.physical_size().as_vec2();
128
129 // Initialize centered, non-window-filling viewport
130 commands.spawn((
131 Camera2d,
132 Camera {
133 viewport: Some(Viewport {
134 physical_position: (window_size * 0.125).as_uvec2(),
135 physical_size: (window_size * 0.75).as_uvec2(),
136 ..default()
137 }),
138 ..default()
139 },
140 ));
141
142 // Create a minimal UI explaining how to interact with the example
143 commands.spawn((
144 Text::new(
145 "Move the mouse to see the circle follow your cursor.\n\
146 Use the arrow keys to move the camera.\n\
147 Use the comma and period keys to zoom in and out.\n\
148 Use the WASD keys to move the viewport.\n\
149 Use the IJKL keys to resize the viewport.",
150 ),
151 Node {
152 position_type: PositionType::Absolute,
153 top: px(12),
154 left: px(12),
155 ..default()
156 },
157 ));
158
159 // Add mesh to make camera movement visible
160 commands.spawn((
161 Mesh2d(meshes.add(Rectangle::new(40.0, 20.0))),
162 MeshMaterial2d(materials.add(Color::from(GREEN))),
163 ));
164
165 // Add background to visualize viewport bounds
166 commands.spawn((
167 Mesh2d(meshes.add(Rectangle::new(50000.0, 50000.0))),
168 MeshMaterial2d(materials.add(Color::linear_rgb(0.01, 0.01, 0.01))),
169 Transform::from_translation(Vec3::new(0.0, 0.0, -200.0)),
170 ));
171}
Sourcepub fn as_i64vec2(&self) -> I64Vec2
pub fn as_i64vec2(&self) -> I64Vec2
Casts all elements of self
to i64
.
Sourcepub fn as_u64vec2(&self) -> U64Vec2
pub fn as_u64vec2(&self) -> U64Vec2
Casts all elements of self
to u64
.
Sourcepub fn as_usizevec2(&self) -> USizeVec2
pub fn as_usizevec2(&self) -> USizeVec2
Casts all elements of self
to usize
.
Trait Implementations§
Source§impl AddAssign<&Vec2> for Vec2
impl AddAssign<&Vec2> for Vec2
Source§fn add_assign(&mut self, rhs: &Vec2)
fn add_assign(&mut self, rhs: &Vec2)
+=
operation. Read moreSource§impl AddAssign<&f32> for Vec2
impl AddAssign<&f32> for Vec2
Source§fn add_assign(&mut self, rhs: &f32)
fn add_assign(&mut self, rhs: &f32)
+=
operation. Read moreSource§impl AddAssign<f32> for Vec2
impl AddAssign<f32> for Vec2
Source§fn add_assign(&mut self, rhs: f32)
fn add_assign(&mut self, rhs: f32)
+=
operation. Read moreSource§impl AddAssign for Vec2
impl AddAssign for Vec2
Source§fn add_assign(&mut self, rhs: Vec2)
fn add_assign(&mut self, rhs: Vec2)
+=
operation. Read moreSource§impl Animatable for Vec2
impl Animatable for Vec2
Source§impl AsMutVectorParts<f32, 2> for Vec2
impl AsMutVectorParts<f32, 2> for Vec2
fn as_mut_parts(&mut self) -> &mut [f32; 2]
Source§impl AsRefVectorParts<f32, 2> for Vec2
impl AsRefVectorParts<f32, 2> for Vec2
fn as_ref_parts(&self) -> &[f32; 2]
Source§impl CreateFrom for Vec2
impl CreateFrom for Vec2
Source§impl<'de> Deserialize<'de> for Vec2
Deserialize expects a sequence of 2 values.
impl<'de> Deserialize<'de> for Vec2
Deserialize expects a sequence of 2 values.
Source§fn deserialize<D>(
deserializer: D,
) -> Result<Vec2, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
fn deserialize<D>(
deserializer: D,
) -> Result<Vec2, <D as Deserializer<'de>>::Error>where
D: Deserializer<'de>,
Source§impl DivAssign<&Vec2> for Vec2
impl DivAssign<&Vec2> for Vec2
Source§fn div_assign(&mut self, rhs: &Vec2)
fn div_assign(&mut self, rhs: &Vec2)
/=
operation. Read moreSource§impl DivAssign<&f32> for Vec2
impl DivAssign<&f32> for Vec2
Source§fn div_assign(&mut self, rhs: &f32)
fn div_assign(&mut self, rhs: &f32)
/=
operation. Read moreSource§impl DivAssign<f32> for Vec2
impl DivAssign<f32> for Vec2
Source§fn div_assign(&mut self, rhs: f32)
fn div_assign(&mut self, rhs: f32)
/=
operation. Read moreSource§impl DivAssign for Vec2
impl DivAssign for Vec2
Source§fn div_assign(&mut self, rhs: Vec2)
fn div_assign(&mut self, rhs: Vec2)
/=
operation. Read moreSource§impl From<Vec2> for Isometry2d
impl From<Vec2> for Isometry2d
Source§fn from(translation: Vec2) -> Isometry2d
fn from(translation: Vec2) -> Isometry2d
Source§impl From<Vec2> for ScrollPosition
impl From<Vec2> for ScrollPosition
Source§fn from(value: Vec2) -> ScrollPosition
fn from(value: Vec2) -> ScrollPosition
Source§impl From<Vec2> for TextBounds
impl From<Vec2> for TextBounds
Source§fn from(v: Vec2) -> TextBounds
fn from(v: Vec2) -> TextBounds
Source§impl FromIterator<Vec2> for Polygon
impl FromIterator<Vec2> for Polygon
Source§impl FromIterator<Vec2> for Polyline2d
impl FromIterator<Vec2> for Polyline2d
Source§fn from_iter<I>(iter: I) -> Polyline2dwhere
I: IntoIterator<Item = Vec2>,
fn from_iter<I>(iter: I) -> Polyline2dwhere
I: IntoIterator<Item = Vec2>,
Source§impl FromReflect for Vec2
impl FromReflect for Vec2
Source§fn from_reflect(reflect: &(dyn PartialReflect + 'static)) -> Option<Vec2>
fn from_reflect(reflect: &(dyn PartialReflect + 'static)) -> Option<Vec2>
Self
from a reflected value.Source§fn take_from_reflect(
reflect: Box<dyn PartialReflect>,
) -> Result<Self, Box<dyn PartialReflect>>
fn take_from_reflect( reflect: Box<dyn PartialReflect>, ) -> Result<Self, Box<dyn PartialReflect>>
Self
using,
constructing the value using from_reflect
if that fails. Read moreSource§impl FromVectorParts<f32, 2> for Vec2
impl FromVectorParts<f32, 2> for Vec2
Source§impl GetTypeRegistration for Vec2
impl GetTypeRegistration for Vec2
Source§fn get_type_registration() -> TypeRegistration
fn get_type_registration() -> TypeRegistration
TypeRegistration
for this type.Source§fn register_type_dependencies(registry: &mut TypeRegistry)
fn register_type_dependencies(registry: &mut TypeRegistry)
Source§impl IntoReturn for Vec2
impl IntoReturn for Vec2
Source§impl Mul<Vec2> for Isometry2d
impl Mul<Vec2> for Isometry2d
Source§impl MulAssign<&Vec2> for Vec2
impl MulAssign<&Vec2> for Vec2
Source§fn mul_assign(&mut self, rhs: &Vec2)
fn mul_assign(&mut self, rhs: &Vec2)
*=
operation. Read moreSource§impl MulAssign<&f32> for Vec2
impl MulAssign<&f32> for Vec2
Source§fn mul_assign(&mut self, rhs: &f32)
fn mul_assign(&mut self, rhs: &f32)
*=
operation. Read moreSource§impl MulAssign<f32> for Vec2
impl MulAssign<f32> for Vec2
Source§fn mul_assign(&mut self, rhs: f32)
fn mul_assign(&mut self, rhs: f32)
*=
operation. Read moreSource§impl MulAssign for Vec2
impl MulAssign for Vec2
Source§fn mul_assign(&mut self, rhs: Vec2)
fn mul_assign(&mut self, rhs: Vec2)
*=
operation. Read moreSource§impl NormedVectorSpace for Vec2
impl NormedVectorSpace for Vec2
Source§fn norm_squared(self) -> f32
fn norm_squared(self) -> f32
NormedVectorSpace::norm
.Source§fn distance(self, rhs: Self) -> Self::Scalar
fn distance(self, rhs: Self) -> Self::Scalar
Source§fn distance_squared(self, rhs: Self) -> Self::Scalar
fn distance_squared(self, rhs: Self) -> Self::Scalar
NormedVectorSpace::distance
.Source§impl PartialReflect for Vec2
impl PartialReflect for Vec2
Source§fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
fn get_represented_type_info(&self) -> Option<&'static TypeInfo>
Source§fn try_apply(
&mut self,
value: &(dyn PartialReflect + 'static),
) -> Result<(), ApplyError>
fn try_apply( &mut self, value: &(dyn PartialReflect + 'static), ) -> Result<(), ApplyError>
Source§fn reflect_kind(&self) -> ReflectKind
fn reflect_kind(&self) -> ReflectKind
Source§fn reflect_ref(&self) -> ReflectRef<'_>
fn reflect_ref(&self) -> ReflectRef<'_>
Source§fn reflect_mut(&mut self) -> ReflectMut<'_>
fn reflect_mut(&mut self) -> ReflectMut<'_>
Source§fn reflect_owned(self: Box<Vec2>) -> ReflectOwned
fn reflect_owned(self: Box<Vec2>) -> ReflectOwned
Source§fn try_into_reflect(
self: Box<Vec2>,
) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>
fn try_into_reflect( self: Box<Vec2>, ) -> Result<Box<dyn Reflect>, Box<dyn PartialReflect>>
Source§fn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>
fn try_as_reflect(&self) -> Option<&(dyn Reflect + 'static)>
Source§fn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>
fn try_as_reflect_mut(&mut self) -> Option<&mut (dyn Reflect + 'static)>
Source§fn into_partial_reflect(self: Box<Vec2>) -> Box<dyn PartialReflect>
fn into_partial_reflect(self: Box<Vec2>) -> Box<dyn PartialReflect>
Source§fn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static)
fn as_partial_reflect(&self) -> &(dyn PartialReflect + 'static)
Source§fn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static)
fn as_partial_reflect_mut(&mut self) -> &mut (dyn PartialReflect + 'static)
Source§fn reflect_partial_eq(
&self,
value: &(dyn PartialReflect + 'static),
) -> Option<bool>
fn reflect_partial_eq( &self, value: &(dyn PartialReflect + 'static), ) -> Option<bool>
Source§fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
fn debug(&self, f: &mut Formatter<'_>) -> Result<(), Error>
Source§fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError>
fn reflect_clone(&self) -> Result<Box<dyn Reflect>, ReflectCloneError>
Self
using reflection. Read moreSource§fn apply(&mut self, value: &(dyn PartialReflect + 'static))
fn apply(&mut self, value: &(dyn PartialReflect + 'static))
Source§fn to_dynamic(&self) -> Box<dyn PartialReflect>
fn to_dynamic(&self) -> Box<dyn PartialReflect>
Source§fn reflect_clone_and_take<T>(&self) -> Result<T, ReflectCloneError>
fn reflect_clone_and_take<T>(&self) -> Result<T, ReflectCloneError>
PartialReflect
, combines reflect_clone
and
take
in a useful fashion, automatically constructing an appropriate
ReflectCloneError
if the downcast fails. Read moreSource§fn reflect_hash(&self) -> Option<u64>
fn reflect_hash(&self) -> Option<u64>
Source§fn is_dynamic(&self) -> bool
fn is_dynamic(&self) -> bool
Source§impl Reflect for Vec2
impl Reflect for Vec2
Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut dyn Any
. Read moreSource§fn into_reflect(self: Box<Vec2>) -> Box<dyn Reflect>
fn into_reflect(self: Box<Vec2>) -> Box<dyn Reflect>
Source§fn as_reflect(&self) -> &(dyn Reflect + 'static)
fn as_reflect(&self) -> &(dyn Reflect + 'static)
Source§fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)
fn as_reflect_mut(&mut self) -> &mut (dyn Reflect + 'static)
Source§impl RemAssign<&Vec2> for Vec2
impl RemAssign<&Vec2> for Vec2
Source§fn rem_assign(&mut self, rhs: &Vec2)
fn rem_assign(&mut self, rhs: &Vec2)
%=
operation. Read moreSource§impl RemAssign<&f32> for Vec2
impl RemAssign<&f32> for Vec2
Source§fn rem_assign(&mut self, rhs: &f32)
fn rem_assign(&mut self, rhs: &f32)
%=
operation. Read moreSource§impl RemAssign<f32> for Vec2
impl RemAssign<f32> for Vec2
Source§fn rem_assign(&mut self, rhs: f32)
fn rem_assign(&mut self, rhs: f32)
%=
operation. Read moreSource§impl RemAssign for Vec2
impl RemAssign for Vec2
Source§fn rem_assign(&mut self, rhs: Vec2)
fn rem_assign(&mut self, rhs: Vec2)
%=
operation. Read moreSource§impl SampleUniform for Vec2
impl SampleUniform for Vec2
Source§type Sampler = UniformVec2<UniformFloat<f32>>
type Sampler = UniformVec2<UniformFloat<f32>>
UniformSampler
implementation supporting type X
.Source§impl Serialize for Vec2
Serialize as a sequence of 2 values.
impl Serialize for Vec2
Serialize as a sequence of 2 values.
Source§fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
fn serialize<S>(
&self,
serializer: S,
) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>where
S: Serializer,
Source§impl ShaderSize for Vec2where
f32: ShaderSize,
impl ShaderSize for Vec2where
f32: ShaderSize,
Source§const SHADER_SIZE: NonZero<u64> = _
const SHADER_SIZE: NonZero<u64> = _
ShaderType::min_size
)Source§impl ShaderType for Vec2where
f32: ShaderSize,
impl ShaderType for Vec2where
f32: ShaderSize,
Source§fn assert_uniform_compat()
fn assert_uniform_compat()
Self
meets the requirements of the
uniform address space restrictions on stored values and the
uniform address space layout constraints Read moreSource§impl Struct for Vec2
impl Struct for Vec2
Source§fn field(&self, name: &str) -> Option<&(dyn PartialReflect + 'static)>
fn field(&self, name: &str) -> Option<&(dyn PartialReflect + 'static)>
name
as a &dyn PartialReflect
.Source§fn field_mut(
&mut self,
name: &str,
) -> Option<&mut (dyn PartialReflect + 'static)>
fn field_mut( &mut self, name: &str, ) -> Option<&mut (dyn PartialReflect + 'static)>
name
as a
&mut dyn PartialReflect
.Source§fn field_at(&self, index: usize) -> Option<&(dyn PartialReflect + 'static)>
fn field_at(&self, index: usize) -> Option<&(dyn PartialReflect + 'static)>
index
as a
&dyn PartialReflect
.Source§fn field_at_mut(
&mut self,
index: usize,
) -> Option<&mut (dyn PartialReflect + 'static)>
fn field_at_mut( &mut self, index: usize, ) -> Option<&mut (dyn PartialReflect + 'static)>
index
as a &mut dyn PartialReflect
.Source§fn name_at(&self, index: usize) -> Option<&str>
fn name_at(&self, index: usize) -> Option<&str>
index
.Source§fn iter_fields(&self) -> FieldIter<'_> ⓘ
fn iter_fields(&self) -> FieldIter<'_> ⓘ
Source§fn to_dynamic_struct(&self) -> DynamicStruct
fn to_dynamic_struct(&self) -> DynamicStruct
DynamicStruct
from this struct.Source§fn get_represented_struct_info(&self) -> Option<&'static StructInfo>
fn get_represented_struct_info(&self) -> Option<&'static StructInfo>
None
if TypeInfo
is not available.Source§impl SubAssign<&Vec2> for Vec2
impl SubAssign<&Vec2> for Vec2
Source§fn sub_assign(&mut self, rhs: &Vec2)
fn sub_assign(&mut self, rhs: &Vec2)
-=
operation. Read moreSource§impl SubAssign<&f32> for Vec2
impl SubAssign<&f32> for Vec2
Source§fn sub_assign(&mut self, rhs: &f32)
fn sub_assign(&mut self, rhs: &f32)
-=
operation. Read moreSource§impl SubAssign<f32> for Vec2
impl SubAssign<f32> for Vec2
Source§fn sub_assign(&mut self, rhs: f32)
fn sub_assign(&mut self, rhs: f32)
-=
operation. Read moreSource§impl SubAssign for Vec2
impl SubAssign for Vec2
Source§fn sub_assign(&mut self, rhs: Vec2)
fn sub_assign(&mut self, rhs: Vec2)
-=
operation. Read moreSource§impl TryFrom<Vec2> for AspectRatio
impl TryFrom<Vec2> for AspectRatio
Source§impl TypePath for Vec2
impl TypePath for Vec2
Source§fn type_path() -> &'static str
fn type_path() -> &'static str
Source§fn short_type_path() -> &'static str
fn short_type_path() -> &'static str
Source§fn type_ident() -> Option<&'static str>
fn type_ident() -> Option<&'static str>
Source§fn crate_name() -> Option<&'static str>
fn crate_name() -> Option<&'static str>
Source§impl Vec2Swizzles for Vec2
impl Vec2Swizzles for Vec2
type Vec3 = Vec3
type Vec4 = Vec4
fn xx(self) -> Vec2
fn yx(self) -> Vec2
fn yy(self) -> Vec2
fn xxx(self) -> Vec3
fn xxy(self) -> Vec3
fn xyx(self) -> Vec3
fn xyy(self) -> Vec3
fn yxx(self) -> Vec3
fn yxy(self) -> Vec3
fn yyx(self) -> Vec3
fn yyy(self) -> Vec3
fn xxxx(self) -> Vec4
fn xxxy(self) -> Vec4
fn xxyx(self) -> Vec4
fn xxyy(self) -> Vec4
fn xyxx(self) -> Vec4
fn xyxy(self) -> Vec4
fn xyyx(self) -> Vec4
fn xyyy(self) -> Vec4
fn yxxx(self) -> Vec4
fn yxxy(self) -> Vec4
fn yxyx(self) -> Vec4
fn yxyy(self) -> Vec4
fn yyxx(self) -> Vec4
fn yyxy(self) -> Vec4
fn yyyx(self) -> Vec4
fn yyyy(self) -> Vec4
fn xy(self) -> Self
Source§impl VectorSpace for Vec2
impl VectorSpace for Vec2
Source§impl WriteInto for Vec2
impl WriteInto for Vec2
fn write_into<B>(&self, writer: &mut Writer<B>)where
B: BufferMut,
impl Copy for Vec2
impl Pod for Vec2
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, U> AsBindGroupShaderType<U> for T
impl<T, U> AsBindGroupShaderType<U> for T
Source§fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
fn as_bind_group_shader_type(&self, _images: &RenderAssets<GpuImage>) -> U
T
ShaderType
for self
. When used in AsBindGroup
derives, it is safe to assume that all images in self
exist.Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CheckedBitPattern for Twhere
T: AnyBitPattern,
impl<T> CheckedBitPattern for Twhere
T: AnyBitPattern,
Source§type Bits = T
type Bits = T
Self
must have the same layout as the specified Bits
except for
the possible invalid bit patterns being checked during
is_valid_bit_pattern
.Source§fn is_valid_bit_pattern(_bits: &T) -> bool
fn is_valid_bit_pattern(_bits: &T) -> bool
bits
as &Self
.Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
, which can then be
downcast
into Box<dyn ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
, which can then be further
downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait>
(where Trait: Downcast
) to Box<dyn Any>
. Box<dyn Any>
can
then be further downcast
into Box<ConcreteType>
where ConcreteType
implements Trait
.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait>
(where Trait: Downcast
) to Rc<Any>
. Rc<Any>
can then be
further downcast
into Rc<ConcreteType>
where ConcreteType
implements Trait
.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &Any
’s vtable from &Trait
’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait
(where Trait: Downcast
) to &Any
. This is needed since Rust cannot
generate &mut Any
’s vtable from &mut Trait
’s.Source§impl<T> DowncastSend for T
impl<T> DowncastSend for T
Source§impl<T> DowncastSync for T
impl<T> DowncastSync for T
Source§impl<T> DynamicTypePath for Twhere
T: TypePath,
impl<T> DynamicTypePath for Twhere
T: TypePath,
Source§fn reflect_type_path(&self) -> &str
fn reflect_type_path(&self) -> &str
TypePath::type_path
.Source§fn reflect_short_type_path(&self) -> &str
fn reflect_short_type_path(&self) -> &str
Source§fn reflect_type_ident(&self) -> Option<&str>
fn reflect_type_ident(&self) -> Option<&str>
TypePath::type_ident
.Source§fn reflect_crate_name(&self) -> Option<&str>
fn reflect_crate_name(&self) -> Option<&str>
TypePath::crate_name
.Source§fn reflect_module_path(&self) -> Option<&str>
fn reflect_module_path(&self) -> Option<&str>
Source§impl<T> DynamicTyped for Twhere
T: Typed,
impl<T> DynamicTyped for Twhere
T: Typed,
Source§fn reflect_type_info(&self) -> &'static TypeInfo
fn reflect_type_info(&self) -> &'static TypeInfo
Typed::type_info
.Source§impl<V> Ease for Vwhere
V: VectorSpace<Scalar = f32>,
impl<V> Ease for Vwhere
V: VectorSpace<Scalar = f32>,
Source§fn interpolating_curve_unbounded(start: V, end: V) -> impl Curve<V>
fn interpolating_curve_unbounded(start: V, end: V) -> impl Curve<V>
Source§impl<T> FmtForward for T
impl<T> FmtForward for T
Source§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.Source§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self
to use its Display
implementation when
Debug
-formatted.Source§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self
to use its LowerExp
implementation when
Debug
-formatted.Source§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self
to use its LowerHex
implementation when
Debug
-formatted.Source§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.Source§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self
to use its Pointer
implementation when
Debug
-formatted.Source§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self
to use its UpperExp
implementation when
Debug
-formatted.Source§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self
to use its UpperHex
implementation when
Debug
-formatted.Source§impl<S> FromSample<S> for S
impl<S> FromSample<S> for S
fn from_sample_(s: S) -> S
Source§impl<T> FromWorld for Twhere
T: Default,
impl<T> FromWorld for Twhere
T: Default,
Source§fn from_world(_world: &mut World) -> T
fn from_world(_world: &mut World) -> T
Creates Self
using default()
.
Source§impl<S> GetField for Swhere
S: Struct,
impl<S> GetField for Swhere
S: Struct,
Source§impl<T> GetPath for T
impl<T> GetPath for T
Source§fn reflect_path<'p>(
&self,
path: impl ReflectPath<'p>,
) -> Result<&(dyn PartialReflect + 'static), ReflectPathError<'p>>
fn reflect_path<'p>( &self, path: impl ReflectPath<'p>, ) -> Result<&(dyn PartialReflect + 'static), ReflectPathError<'p>>
path
. Read moreSource§fn reflect_path_mut<'p>(
&mut self,
path: impl ReflectPath<'p>,
) -> Result<&mut (dyn PartialReflect + 'static), ReflectPathError<'p>>
fn reflect_path_mut<'p>( &mut self, path: impl ReflectPath<'p>, ) -> Result<&mut (dyn PartialReflect + 'static), ReflectPathError<'p>>
path
. Read moreSource§fn path<'p, T>(
&self,
path: impl ReflectPath<'p>,
) -> Result<&T, ReflectPathError<'p>>where
T: Reflect,
fn path<'p, T>(
&self,
path: impl ReflectPath<'p>,
) -> Result<&T, ReflectPathError<'p>>where
T: Reflect,
path
. Read moreSource§fn path_mut<'p, T>(
&mut self,
path: impl ReflectPath<'p>,
) -> Result<&mut T, ReflectPathError<'p>>where
T: Reflect,
fn path_mut<'p, T>(
&mut self,
path: impl ReflectPath<'p>,
) -> Result<&mut T, ReflectPathError<'p>>where
T: Reflect,
path
. Read moreSource§impl<V> HasTangent for Vwhere
V: VectorSpace,
impl<V> HasTangent for Vwhere
V: VectorSpace,
Source§impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
impl<T, W> HasTypeWitness<W> for Twhere
W: MakeTypeWitness<Arg = T>,
T: ?Sized,
Source§impl<T> Identity for Twhere
T: ?Sized,
impl<T> Identity for Twhere
T: ?Sized,
Source§impl<T> InitializeFromFunction<T> for T
impl<T> InitializeFromFunction<T> for T
Source§fn initialize_from_function(f: fn() -> T) -> T
fn initialize_from_function(f: fn() -> T) -> T
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
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 moreSource§impl<T> IntoResult<T> for T
impl<T> IntoResult<T> for T
Source§fn into_result(self) -> Result<T, RunSystemError>
fn into_result(self) -> Result<T, RunSystemError>
Source§impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
impl<F, T> IntoSample<T> for Fwhere
T: FromSample<F>,
fn into_sample(self) -> T
Source§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
Source§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
Source§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read moreSource§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read moreSource§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
Source§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
Source§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self
, then passes self.as_ref()
into the pipe function.Source§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self
, then passes self.as_mut()
into the pipe
function.Source§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self
, then passes self.deref()
into the pipe function.Source§impl<T> Pointable for T
impl<T> Pointable for T
Source§impl<R, P> ReadPrimitive<R> for P
impl<R, P> ReadPrimitive<R> for P
Source§fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
fn read_from_little_endian(read: &mut R) -> Result<Self, Error>
ReadEndian::read_from_little_endian()
.Source§impl<Borrowed> SampleBorrow<Borrowed> for Borrowedwhere
Borrowed: SampleUniform,
impl<Borrowed> SampleBorrow<Borrowed> for Borrowedwhere
Borrowed: SampleUniform,
Source§fn borrow(&self) -> &Borrowed
fn borrow(&self) -> &Borrowed
Borrow::borrow
Source§impl<T> Serialize for T
impl<T> Serialize for T
fn erased_serialize(&self, serializer: &mut dyn Serializer) -> Result<(), Error>
fn do_erased_serialize( &self, serializer: &mut dyn Serializer, ) -> Result<(), ErrorImpl>
Source§impl<Ret> SpawnIfAsync<(), Ret> for Ret
impl<Ret> SpawnIfAsync<(), Ret> for Ret
Source§impl<V> StableInterpolate for Vwhere
V: NormedVectorSpace<Scalar = f32>,
impl<V> StableInterpolate for Vwhere
V: NormedVectorSpace<Scalar = f32>,
Source§fn interpolate_stable(&self, other: &V, t: f32) -> V
fn interpolate_stable(&self, other: &V, t: f32) -> V
other
given value using the parameter t
. At
t = 0.0
, a value equivalent to self
is recovered, while t = 1.0
recovers a value
equivalent to other
, with intermediate values interpolating between the two.
See the trait-level documentation for details.Source§fn interpolate_stable_assign(&mut self, other: &Self, t: f32)
fn interpolate_stable_assign(&mut self, other: &Self, t: f32)
interpolate_stable
that assigns the result to self
for convenience.Source§fn smooth_nudge(&mut self, target: &Self, decay_rate: f32, delta: f32)
fn smooth_nudge(&mut self, target: &Self, decay_rate: f32, delta: f32)
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 moreSource§impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
impl<T, O> SuperFrom<T> for Owhere
O: From<T>,
Source§fn super_from(input: T) -> O
fn super_from(input: T) -> O
Source§impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
impl<T, O, M> SuperInto<O, M> for Twhere
O: SuperFrom<T, M>,
Source§fn super_into(self) -> O
fn super_into(self) -> O
Source§impl<T> Tap for T
impl<T> Tap for T
Source§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B>
of a value. Read moreSource§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B>
of a value. Read moreSource§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R>
view of a value. Read moreSource§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R>
view of a value. Read moreSource§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target
of a value. Read moreSource§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target
of a value. Read moreSource§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.Source§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow()
only in debug builds, and is erased in release
builds.Source§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref()
only in debug builds, and is erased in release
builds.Source§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut()
only in debug builds, and is erased in release
builds.Source§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref()
only in debug builds, and is erased in release
builds.