traaains/sim/track/segment/commands/
remove.rs1use bevy::{
2 ecs::{entity::Entity, system::Command, world::World},
3 log::tracing,
4 state::state::{NextState, State},
5};
6
7use crate::{
8 sim::{
9 logical_graph::LogicalBlock,
10 track::{
11 node::{RemoveConnectionFor, TrackNode},
12 segment::{TrackSegment, signals_manager::SignalsManager},
13 },
14 },
15 ui::UiState,
16};
17
18pub struct RemoveSegment {
20 target: Entity,
22 despawn_nodes: bool,
24 despawn_block: bool,
26 despawn_signals: bool,
28}
29
30impl RemoveSegment {
31 pub fn new(target: Entity) -> Self {
32 Self {
33 target,
34 despawn_nodes: true,
35 despawn_block: true,
36 despawn_signals: true,
37 }
38 }
39
40 pub fn with_despawn_nodes(mut self, despawn_nodes: bool) -> Self {
41 self.despawn_nodes = despawn_nodes;
42 self
43 }
44
45 pub fn with_despawn_block(mut self, despawn_block: bool) -> Self {
46 self.despawn_block = despawn_block;
47 self
48 }
49
50 pub fn with_despawn_signals(mut self, despawn_signals: bool) -> Self {
51 self.despawn_signals = despawn_signals;
52 self
53 }
54
55 fn decrease_block_segments(world: &mut World, block: Entity, despawn: bool) -> bool {
58 let mut lb = world
59 .query::<&mut LogicalBlock>()
60 .get_mut(world, block)
61 .unwrap();
62
63 lb.number_of_segments -= 1;
64
65 if despawn && lb.number_of_segments == 0 {
66 tracing::debug!(
67 "Despawning block {} due to having no attached segments",
68 block
69 );
70 world.despawn(block);
71 true
72 } else {
73 false
74 }
75 }
76}
77
78impl Command for RemoveSegment {
79 type Out = Result<TrackSegment, &'static str>;
80
81 fn apply(self, world: &mut World) -> Self::Out {
82 let ui_state = world.resource::<State<UiState>>();
84 if let UiState::SegmentWindow { target } = ui_state.get()
85 && *target == self.target
86 {
87 world
88 .resource_mut::<NextState<UiState>>()
89 .set(UiState::Default);
90 }
91
92 let Some(ts) = world.entity_mut(self.target).take::<TrackSegment>() else {
93 panic!("RemoveSegment applied on a non-track segment entity!");
94 };
95
96 let block_despawned =
97 RemoveSegment::decrease_block_segments(world, ts.block, self.despawn_block);
98
99 for node in [ts.from_node, ts.to_node] {
100 if RemoveConnectionFor::new(node, self.target)
101 .with_despawn(self.despawn_nodes)
102 .apply(world)
103 == Ok(true)
104 {
105 continue;
106 }
107
108 let Ok(tn) = world.query::<&mut TrackNode>().get(world, node) else {
109 panic!("Applied RemoveSegment on a non-track node entity!")
110 };
111
112 let local_segments: Vec<_> = tn.connections.iter().map(|c| c.segment).collect();
113 let same_local_segments = local_segments
115 .into_iter()
116 .filter(|s| *s != self.target)
117 .map(|s| world.query::<&TrackSegment>().get(world, s).unwrap().block)
118 .any(|b| b == ts.block);
119
120 if !block_despawned && !same_local_segments {
121 let mut lb = world
122 .query::<&mut LogicalBlock>()
123 .get_mut(world, ts.block)
124 .unwrap();
125
126 let node_logical_conns: Vec<_> = lb
129 .connections
130 .range_mut(
131 &(node, Entity::from_bits(1)).into()
132 ..&(node, Entity::from_bits(u64::MAX)).into(),
133 )
134 .map(|(k, _)| k.clone())
135 .collect();
136
137 for key in node_logical_conns {
138 lb.connections.remove(&key);
139 }
140 }
141
142 let node_segments: Vec<_> = world
144 .query::<&TrackNode>()
145 .get(world, node)
146 .unwrap()
147 .connections
148 .iter()
149 .map(|c| c.segment)
150 .collect();
151
152 let node_blocks: Vec<_> = node_segments
153 .into_iter()
154 .map(|segment_id| {
155 world
156 .query::<&TrackSegment>()
157 .get(world, segment_id)
158 .unwrap()
159 .block
160 })
161 .collect();
162
163 for block in node_blocks {
164 let mut block = world
165 .query::<&mut LogicalBlock>()
166 .get_mut(world, block)
167 .unwrap();
168
169 block.connections.remove(&(node, self.target).into());
170 }
171 }
172
173 if self.despawn_signals {
174 let signals_manager = world
175 .entity_mut(self.target)
176 .take::<SignalsManager>()
177 .unwrap();
178
179 for (_, signal) in signals_manager.inner {
180 world.despawn(signal);
181 }
182 }
183
184 world.despawn(self.target);
186
187 Ok(ts)
188 }
189}