traaains/editor/train/placing/
observers.rs1use bevy::{
2 ecs::{
3 component::Component,
4 entity::Entity,
5 event::EntityEvent,
6 observer::On,
7 query::With,
8 system::{Query, Res, ResMut, Single},
9 },
10 picking::events::{PointerEnter, PointerLeave, PointerMove},
11 state::state::NextState,
12 transform::components::Transform,
13};
14use bezier::Bezier;
15
16use crate::{
17 editor::train::placing::{CurrentPlacingDir, VirtualTrain, states::hovering::HoveringTrack},
18 game::cursor::CursorPos,
19 sim::track::{pos::TrackPos, segment::TrackSegment},
20};
21
22#[derive(Component)]
23pub struct PlacingTrainObserver;
24
25pub fn on_segment_pointer_enter(
26 e: On<PointerEnter>,
27 q_segments: Query<Entity, With<TrackSegment>>,
28 mut next_state: ResMut<NextState<HoveringTrack>>,
29) {
30 if let Ok(segment) = q_segments.get(e.event_target()) {
31 next_state.set(HoveringTrack(Some(segment)));
32 }
33}
34
35pub fn on_segment_pointer_leave(
36 e: On<PointerLeave>,
37 q_segments: Query<Entity, With<TrackSegment>>,
38 mut next_state: ResMut<NextState<HoveringTrack>>,
39) {
40 if q_segments.get(e.event_target()).is_ok() {
41 next_state.set(HoveringTrack(None));
42 }
43}
44
45pub fn on_segment_pointer_move(
47 e: On<PointerMove>,
48 q_segments: Query<(Entity, &TrackSegment, &Transform)>,
49 mut virtual_train: Single<&mut TrackPos, With<VirtualTrain>>,
50 cursor_pos: Res<CursorPos>,
51 current_dir: Res<CurrentPlacingDir>,
52) {
53 let Ok((ts, ts_segment, ts_transform)) = q_segments.get(e.event_target()) else {
54 return;
55 };
56
57 let local_cursor = cursor_pos.0 - ts_transform.translation.truncate();
58 let curr_idx = ts_segment.shape.project(local_cursor);
59
60 virtual_train.segment = ts;
61 virtual_train.idx = curr_idx;
62 virtual_train.dir = Some(current_dir.0);
63}