traaains/editor/train/placing/states/
placed_state.rs1use std::fmt::Display;
2
3use bevy::{
4 asset::Assets,
5 ecs::{
6 entity::Entity,
7 query::With,
8 system::{Commands, Query, Res, ResMut, Single},
9 },
10 mesh::{Mesh, Mesh2d},
11 sprite_render::MeshMaterial2d,
12 state::state::{NextState, SubStates},
13 transform::components::Transform,
14};
15
16use crate::{
17 AssetType, AssetsManager,
18 editor::{
19 EditorState,
20 train::placing::{CurrentPlacingTrain, VirtualBogie, VirtualCarriage, VirtualTrain},
21 },
22 sim::{
23 Acceleration, Controls, Velocity,
24 track::pos::TrackPos,
25 train::{
26 Bogie, Carriage, CarriageBogies, Train, TrainMember, TrainMode,
27 on_carriage_press_window,
28 },
29 },
30 utils::Meshable,
31};
32
33use super::hovering::IsHoveringTrack;
34
35#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, SubStates)]
36#[source(IsHoveringTrack = IsHoveringTrack)]
37pub enum PlacedTrainState {
38 #[default]
39 Invalid,
40 Valid,
41}
42
43impl Display for PlacedTrainState {
44 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45 f.write_str(match self {
46 PlacedTrainState::Invalid => "Invalid",
47 PlacedTrainState::Valid => "Valid",
48 })
49 }
50}
51
52fn spawn_bogie(
53 cmd: &mut Commands,
54 q_bogies: Query<&TrackPos, With<VirtualBogie>>,
55 v_bogie: Entity,
56) -> Entity {
57 let bogie = q_bogies.get(v_bogie).unwrap();
58 cmd.entity(v_bogie).despawn();
59
60 cmd.spawn((Bogie { length: 0.0 }, *bogie, Transform::default()))
61 .id()
62}
63
64pub fn place_train(
66 mut cmd: Commands,
67 q_train: Single<(&VirtualTrain, &TrackPos)>,
68 q_carriages: Query<&VirtualCarriage>,
69 q_bogies: Query<&TrackPos, With<VirtualBogie>>,
70 curr_placing_train: Res<CurrentPlacingTrain>,
71 assets_manager: Res<AssetsManager>,
72 mut meshes: ResMut<Assets<Mesh>>,
73 mut next_state: ResMut<NextState<EditorState>>,
74) {
75 let mut carriages = Vec::new();
76 let mut total_mass = 0.0;
77 let mut total_power = 0.0;
78
79 for (carriage_ent, carriage_template) in q_train
80 .0
81 .carriages
82 .iter()
83 .zip(curr_placing_train.carriages.iter())
84 {
85 let virtual_carriage = q_carriages.get(*carriage_ent).unwrap();
86
87 let carriage_bogies = match virtual_carriage.bogies {
88 CarriageBogies::Single(v_bogie) => {
89 CarriageBogies::Single(spawn_bogie(&mut cmd, q_bogies, v_bogie))
90 }
91 CarriageBogies::Double { front, back } => CarriageBogies::Double {
92 front: spawn_bogie(&mut cmd, q_bogies, front),
93 back: spawn_bogie(&mut cmd, q_bogies, back),
94 },
95 };
96
97 let carriage = Carriage {
98 length: carriage_template.length,
99 width: carriage_template.width,
100 mass: carriage_template.mass,
101 power: carriage_template.power,
102 bogies: carriage_bogies,
103 };
104 let spawned_carriage = cmd
105 .spawn((
106 Transform::default(),
107 Mesh2d(meshes.add(carriage.mesh(()))),
108 MeshMaterial2d(
109 assets_manager
110 .materials
111 .get(&AssetType::CarriageNormal)
112 .cloned()
113 .unwrap(),
114 ),
115 carriage,
116 ))
117 .observe(on_carriage_press_window)
118 .id();
119
120 total_mass += carriage_template.mass;
121 total_power += carriage_template.power;
122 carriages.push(spawned_carriage);
123 }
124
125 let spawned_train = cmd
128 .spawn((
129 Train {
130 carriages: carriages.clone(),
131 total_mass,
132 total_power,
133 mode: TrainMode::Manual,
134 },
135 Acceleration::default(),
136 Velocity::default(),
137 Controls {
138 throttle: 0.0,
139 brake: 0.0,
140 },
141 ))
142 .id();
143
144 for c in carriages {
145 cmd.entity(c).insert(TrainMember {
146 parent: spawned_train,
147 });
148 }
149
150 next_state.set(EditorState::Viewing);
151}