1
1
//! This example demonstrates how to use the `Camera::viewport_to_world_2d` method.
2
2
3
- use bevy:: { color:: palettes:: basic:: WHITE , prelude:: * } ;
3
+ use bevy:: render:: camera:: Viewport ;
4
+ use bevy:: {
5
+ color:: palettes:: { basic:: WHITE , css:: GREEN } ,
6
+ prelude:: * ,
7
+ } ;
4
8
5
9
fn main ( ) {
6
10
App :: new ( )
7
11
. add_plugins ( DefaultPlugins )
8
12
. add_systems ( Startup , setup)
9
- . add_systems ( Update , draw_cursor)
13
+ . add_systems ( Update , ( draw_cursor, controls , viewport_border_gizmos ) )
10
14
. run ( ) ;
11
15
}
12
16
@@ -26,24 +30,142 @@ fn draw_cursor(
26
30
} ;
27
31
28
32
// Calculate a world position based on the cursor's position.
29
- let Ok ( point ) = camera. viewport_to_world_2d ( camera_transform, cursor_position) else {
33
+ let Ok ( world_pos ) = camera. viewport_to_world_2d ( camera_transform, cursor_position) else {
30
34
return ;
31
35
} ;
32
36
33
- gizmos. circle_2d ( point, 10. , WHITE ) ;
37
+ // To test Camera::world_to_viewport, convert result back to viewport space and then back to world space.
38
+ let Ok ( viewport_check) = camera. world_to_viewport ( camera_transform, world_pos. extend ( 0.0 ) )
39
+ else {
40
+ return ;
41
+ } ;
42
+ let Ok ( world_check) = camera. viewport_to_world_2d ( camera_transform, viewport_check. xy ( ) ) else {
43
+ return ;
44
+ } ;
45
+
46
+ gizmos. circle_2d ( world_pos, 10. , WHITE ) ;
47
+ // Should be the same as world_pos
48
+ gizmos. circle_2d ( world_check, 8. , GREEN ) ;
49
+ }
50
+
51
+ fn viewport_border_gizmos ( camera_query : Single < ( & Camera , & GlobalTransform ) > , mut gizmos : Gizmos ) {
52
+ let ( camera, camera_transform) = * camera_query;
53
+ let Some ( viewport) = camera. logical_viewport_rect ( ) else {
54
+ return ;
55
+ } ;
56
+
57
+ let Ok ( min) = camera. viewport_to_world_2d ( camera_transform, viewport. min ) else {
58
+ return ;
59
+ } ;
60
+ let Ok ( max) = camera. viewport_to_world_2d ( camera_transform, viewport. max ) else {
61
+ return ;
62
+ } ;
63
+
64
+ gizmos. line_2d ( Vec2 :: new ( min. x , min. y ) , Vec2 :: new ( max. x , min. y ) , WHITE ) ;
65
+ gizmos. line_2d ( Vec2 :: new ( max. x , min. y ) , Vec2 :: new ( max. x , max. y ) , WHITE ) ;
66
+ gizmos. line_2d ( Vec2 :: new ( max. x , max. y ) , Vec2 :: new ( min. x , max. y ) , WHITE ) ;
67
+ gizmos. line_2d ( Vec2 :: new ( min. x , max. y ) , Vec2 :: new ( min. x , min. y ) , WHITE ) ;
34
68
}
35
69
36
- fn setup ( mut commands : Commands ) {
37
- commands. spawn ( Camera2d ) ;
70
+ fn controls (
71
+ mut camera_query : Query < ( & mut Camera , & mut Transform ) > ,
72
+ input : Res < ButtonInput < KeyCode > > ,
73
+ ) {
74
+ for ( mut camera, mut transform) in camera_query. iter_mut ( ) {
75
+ if input. pressed ( KeyCode :: ArrowUp ) {
76
+ transform. translation . y += 3.0 ;
77
+ }
78
+ if input. pressed ( KeyCode :: ArrowDown ) {
79
+ transform. translation . y -= 3.0 ;
80
+ }
81
+ if input. pressed ( KeyCode :: ArrowLeft ) {
82
+ transform. translation . x -= 3.0 ;
83
+ }
84
+ if input. pressed ( KeyCode :: ArrowRight ) {
85
+ transform. translation . x += 3.0 ;
86
+ }
87
+
88
+ if input. pressed ( KeyCode :: Comma ) {
89
+ transform. scale *= 0.95 ;
90
+ }
91
+
92
+ if input. pressed ( KeyCode :: Period ) {
93
+ transform. scale *= 1.05 ;
94
+ }
95
+
96
+ if let Some ( viewport) = camera. viewport . as_mut ( ) {
97
+ if input. pressed ( KeyCode :: KeyW ) {
98
+ viewport. physical_position . y = viewport. physical_position . y . saturating_sub ( 3 ) ;
99
+ }
100
+ if input. pressed ( KeyCode :: KeyS ) {
101
+ viewport. physical_position . y =
102
+ ( viewport. physical_position . y + 3 ) . min ( 720 - viewport. physical_size . y ) ;
103
+ }
104
+ if input. pressed ( KeyCode :: KeyA ) {
105
+ viewport. physical_position . x = viewport. physical_position . x . saturating_sub ( 3 ) ;
106
+ }
107
+ if input. pressed ( KeyCode :: KeyD ) {
108
+ viewport. physical_position . x =
109
+ ( viewport. physical_position . x + 3 ) . min ( 1280 - viewport. physical_size . x ) ;
110
+ }
111
+
112
+ if input. pressed ( KeyCode :: KeyI ) {
113
+ viewport. physical_size . y =
114
+ viewport. physical_size . y . checked_sub ( 3 ) . unwrap_or ( 1 ) . max ( 1 ) ;
115
+ }
116
+ if input. pressed ( KeyCode :: KeyK ) {
117
+ viewport. physical_size . y = ( viewport. physical_size . y + 3 ) . min ( 720 ) ;
118
+ }
119
+ if input. pressed ( KeyCode :: KeyJ ) {
120
+ viewport. physical_size . x =
121
+ viewport. physical_size . x . checked_sub ( 3 ) . unwrap_or ( 1 ) . max ( 1 ) ;
122
+ }
123
+ if input. pressed ( KeyCode :: KeyL ) {
124
+ viewport. physical_size . x = ( viewport. physical_size . x + 3 ) . min ( 1280 ) ;
125
+ }
126
+
127
+ let max_viewport_size = UVec2 :: new ( 1280 , 720 ) - viewport. physical_position ;
128
+ viewport. physical_size = viewport. physical_size . min ( max_viewport_size) ;
129
+ }
130
+ }
131
+ }
132
+
133
+ fn setup (
134
+ mut commands : Commands ,
135
+ mut meshes : ResMut < Assets < Mesh > > ,
136
+ mut materials : ResMut < Assets < ColorMaterial > > ,
137
+ ) {
138
+ commands. spawn ( (
139
+ Camera2d ,
140
+ Camera {
141
+ viewport : Some ( Viewport {
142
+ physical_position : UVec2 :: new ( 320 , 180 ) ,
143
+ physical_size : UVec2 :: new ( 640 , 360 ) ,
144
+ ..default ( )
145
+ } ) ,
146
+ ..default ( )
147
+ } ,
148
+ ) ) ;
38
149
39
150
// Create a minimal UI explaining how to interact with the example
40
151
commands. spawn ( (
41
- Text :: new ( "Move the mouse to see the circle follow your cursor." ) ,
152
+ Text :: new (
153
+ "Move the mouse to see the circle follow your cursor.\n \
154
+ Use the arrow keys to move the camera.\n \
155
+ Use the comma and period keys to zoom in and out.\n \
156
+ Use the WASD keys to move the viewport.\n \
157
+ Use the IJKL keys to resize the viewport.",
158
+ ) ,
42
159
Node {
43
160
position_type : PositionType :: Absolute ,
44
161
top : Val :: Px ( 12.0 ) ,
45
162
left : Val :: Px ( 12.0 ) ,
46
163
..default ( )
47
164
} ,
48
165
) ) ;
166
+
167
+ commands. spawn ( (
168
+ Mesh2d ( meshes. add ( Rectangle :: new ( 10.0 , 20.0 ) ) ) ,
169
+ MeshMaterial2d ( materials. add ( Color :: from ( GREEN ) ) ) ,
170
+ ) ) ;
49
171
}
0 commit comments