4
4
5
5
use core:: cmp:: Reverse ;
6
6
7
- use crate :: { Sprite , TextureAtlas , TextureAtlasLayout } ;
7
+ use crate :: { Sprite , TextureAtlasLayout } ;
8
8
use bevy_app:: prelude:: * ;
9
9
use bevy_asset:: prelude:: * ;
10
10
use bevy_ecs:: prelude:: * ;
@@ -32,8 +32,6 @@ pub fn sprite_picking(
32
32
sprite_query : Query < (
33
33
Entity ,
34
34
& Sprite ,
35
- Option < & TextureAtlas > ,
36
- & Handle < Image > ,
37
35
& GlobalTransform ,
38
36
Option < & PickingBehavior > ,
39
37
& ViewVisibility ,
@@ -42,9 +40,9 @@ pub fn sprite_picking(
42
40
) {
43
41
let mut sorted_sprites: Vec < _ > = sprite_query
44
42
. iter ( )
45
- . filter ( |x| !x. 4 . affine ( ) . is_nan ( ) )
43
+ . filter ( |x| !x. 2 . affine ( ) . is_nan ( ) )
46
44
. collect ( ) ;
47
- sorted_sprites. sort_by_key ( |x| Reverse ( FloatOrd ( x. 4 . translation ( ) . z ) ) ) ;
45
+ sorted_sprites. sort_by_key ( |x| Reverse ( FloatOrd ( x. 2 . translation ( ) . z ) ) ) ;
48
46
49
47
let primary_window = primary_window. get_single ( ) . ok ( ) ;
50
48
@@ -77,82 +75,79 @@ pub fn sprite_picking(
77
75
. iter ( )
78
76
. copied ( )
79
77
. filter ( |( .., visibility) | visibility. get ( ) )
80
- . filter_map (
81
- |( entity, sprite, atlas, image, sprite_transform, picking_behavior, ..) | {
82
- if blocked {
83
- return None ;
84
- }
85
-
86
- // Hit box in sprite coordinate system
87
- let extents = match ( sprite. custom_size , atlas) {
88
- ( Some ( custom_size) , _) => custom_size,
89
- ( None , None ) => images. get ( image) ?. size ( ) . as_vec2 ( ) ,
90
- ( None , Some ( atlas) ) => texture_atlas_layout
91
- . get ( & atlas. layout )
92
- . and_then ( |layout| layout. textures . get ( atlas. index ) )
93
- // Dropped atlas layouts and indexes out of bounds are rendered as a sprite
94
- . map_or ( images. get ( image) ?. size ( ) . as_vec2 ( ) , |rect| {
95
- rect. size ( ) . as_vec2 ( )
96
- } ) ,
97
- } ;
98
- let anchor = sprite. anchor . as_vec ( ) ;
99
- let center = -anchor * extents;
100
- let rect = Rect :: from_center_half_size ( center, extents / 2.0 ) ;
101
-
102
- // Transform cursor line segment to sprite coordinate system
103
- let world_to_sprite = sprite_transform. affine ( ) . inverse ( ) ;
104
- let cursor_start_sprite =
105
- world_to_sprite. transform_point3 ( cursor_ray_world. origin ) ;
106
- let cursor_end_sprite = world_to_sprite. transform_point3 ( cursor_ray_end) ;
107
-
108
- // Find where the cursor segment intersects the plane Z=0 (which is the sprite's
109
- // plane in sprite-local space). It may not intersect if, for example, we're
110
- // viewing the sprite side-on
111
- if cursor_start_sprite. z == cursor_end_sprite. z {
112
- // Cursor ray is parallel to the sprite and misses it
113
- return None ;
114
- }
115
- let lerp_factor =
116
- f32:: inverse_lerp ( cursor_start_sprite. z , cursor_end_sprite. z , 0.0 ) ;
117
- if !( 0.0 ..=1.0 ) . contains ( & lerp_factor) {
118
- // Lerp factor is out of range, meaning that while an infinite line cast by
119
- // the cursor would intersect the sprite, the sprite is not between the
120
- // camera's near and far planes
121
- return None ;
122
- }
123
- // Otherwise we can interpolate the xy of the start and end positions by the
124
- // lerp factor to get the cursor position in sprite space!
125
- let cursor_pos_sprite = cursor_start_sprite
126
- . lerp ( cursor_end_sprite, lerp_factor)
127
- . xy ( ) ;
128
-
129
- let is_cursor_in_sprite = rect. contains ( cursor_pos_sprite) ;
130
-
131
- blocked = is_cursor_in_sprite
132
- && picking_behavior. map ( |p| p. should_block_lower ) != Some ( false ) ;
133
-
134
- is_cursor_in_sprite. then ( || {
135
- let hit_pos_world =
136
- sprite_transform. transform_point ( cursor_pos_sprite. extend ( 0.0 ) ) ;
137
- // Transform point from world to camera space to get the Z distance
138
- let hit_pos_cam = cam_transform
139
- . affine ( )
140
- . inverse ( )
141
- . transform_point3 ( hit_pos_world) ;
142
- // HitData requires a depth as calculated from the camera's near clipping plane
143
- let depth = -cam_ortho. near - hit_pos_cam. z ;
144
- (
145
- entity,
146
- HitData :: new (
147
- cam_entity,
148
- depth,
149
- Some ( hit_pos_world) ,
150
- Some ( * sprite_transform. back ( ) ) ,
151
- ) ,
152
- )
153
- } )
154
- } ,
155
- )
78
+ . filter_map ( |( entity, sprite, sprite_transform, picking_behavior, ..) | {
79
+ if blocked {
80
+ return None ;
81
+ }
82
+
83
+ // Hit box in sprite coordinate system
84
+ let extents = match ( sprite. custom_size , & sprite. texture_atlas ) {
85
+ ( Some ( custom_size) , _) => custom_size,
86
+ ( None , None ) => images. get ( & sprite. image ) ?. size ( ) . as_vec2 ( ) ,
87
+ ( None , Some ( atlas) ) => texture_atlas_layout
88
+ . get ( & atlas. layout )
89
+ . and_then ( |layout| layout. textures . get ( atlas. index ) )
90
+ // Dropped atlas layouts and indexes out of bounds are rendered as a sprite
91
+ . map_or ( images. get ( & sprite. image ) ?. size ( ) . as_vec2 ( ) , |rect| {
92
+ rect. size ( ) . as_vec2 ( )
93
+ } ) ,
94
+ } ;
95
+ let anchor = sprite. anchor . as_vec ( ) ;
96
+ let center = -anchor * extents;
97
+ let rect = Rect :: from_center_half_size ( center, extents / 2.0 ) ;
98
+
99
+ // Transform cursor line segment to sprite coordinate system
100
+ let world_to_sprite = sprite_transform. affine ( ) . inverse ( ) ;
101
+ let cursor_start_sprite = world_to_sprite. transform_point3 ( cursor_ray_world. origin ) ;
102
+ let cursor_end_sprite = world_to_sprite. transform_point3 ( cursor_ray_end) ;
103
+
104
+ // Find where the cursor segment intersects the plane Z=0 (which is the sprite's
105
+ // plane in sprite-local space). It may not intersect if, for example, we're
106
+ // viewing the sprite side-on
107
+ if cursor_start_sprite. z == cursor_end_sprite. z {
108
+ // Cursor ray is parallel to the sprite and misses it
109
+ return None ;
110
+ }
111
+ let lerp_factor =
112
+ f32:: inverse_lerp ( cursor_start_sprite. z , cursor_end_sprite. z , 0.0 ) ;
113
+ if !( 0.0 ..=1.0 ) . contains ( & lerp_factor) {
114
+ // Lerp factor is out of range, meaning that while an infinite line cast by
115
+ // the cursor would intersect the sprite, the sprite is not between the
116
+ // camera's near and far planes
117
+ return None ;
118
+ }
119
+ // Otherwise we can interpolate the xy of the start and end positions by the
120
+ // lerp factor to get the cursor position in sprite space!
121
+ let cursor_pos_sprite = cursor_start_sprite
122
+ . lerp ( cursor_end_sprite, lerp_factor)
123
+ . xy ( ) ;
124
+
125
+ let is_cursor_in_sprite = rect. contains ( cursor_pos_sprite) ;
126
+
127
+ blocked = is_cursor_in_sprite
128
+ && picking_behavior. map ( |p| p. should_block_lower ) != Some ( false ) ;
129
+
130
+ is_cursor_in_sprite. then ( || {
131
+ let hit_pos_world =
132
+ sprite_transform. transform_point ( cursor_pos_sprite. extend ( 0.0 ) ) ;
133
+ // Transform point from world to camera space to get the Z distance
134
+ let hit_pos_cam = cam_transform
135
+ . affine ( )
136
+ . inverse ( )
137
+ . transform_point3 ( hit_pos_world) ;
138
+ // HitData requires a depth as calculated from the camera's near clipping plane
139
+ let depth = -cam_ortho. near - hit_pos_cam. z ;
140
+ (
141
+ entity,
142
+ HitData :: new (
143
+ cam_entity,
144
+ depth,
145
+ Some ( hit_pos_world) ,
146
+ Some ( * sprite_transform. back ( ) ) ,
147
+ ) ,
148
+ )
149
+ } )
150
+ } )
156
151
. collect ( ) ;
157
152
158
153
let order = camera. order as f32 ;
0 commit comments