traaains/editor/track/placing/states/
current_step.rs1use std::fmt::Display;
2
3use bevy::{
4 asset::Assets,
5 ecs::{
6 entity::Entity,
7 observer::ObserverSystemExt,
8 query::With,
9 system::{Commands, Query, Res, ResMut, Single},
10 },
11 math::Vec2,
12 mesh::{Mesh, Mesh2d},
13 sprite_render::MeshMaterial2d,
14 state::{condition::in_state, state::SubStates},
15 transform::components::Transform,
16};
17use bezier::{Cubic, Linear, Quadratic};
18
19use crate::{
20 AssetType, AssetsManager,
21 editor::{
22 EditorState,
23 track::{
24 TrackEditorState,
25 placing::{
26 FromNodeType, LastConnectedBlock, NodeType, Placing, VirtualSegment,
27 take_points,
28 },
29 },
30 },
31 game::cursor::CursorPos,
32 shape::{BezierMeshProps, Shapes},
33 sim::track::node::{TrackNode, on_node_press_window},
34 utils::Meshable,
35};
36
37#[derive(Clone, Debug, Default, Eq, Hash, PartialEq, SubStates)]
38#[source(TrackEditorState = TrackEditorState::Placing)]
39pub enum CurrentStep {
40 #[default]
41 Zero,
42 Linear,
43 Quadratic,
44 Cubic,
45}
46
47impl Display for CurrentStep {
48 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
49 f.write_str(match self {
50 CurrentStep::Zero => "-",
51 CurrentStep::Linear => "Linear",
52 CurrentStep::Quadratic => "Quadratic",
53 CurrentStep::Cubic => "Cubic",
54 })
55 }
56}
57
58pub fn on_enter_constant(
61 mut cmd: Commands,
62 v_segment: Single<Entity, With<VirtualSegment>>,
63 unfinished_node: Option<Single<Entity, (With<TrackNode>, With<Placing>)>>,
64 mut last_connected_block: ResMut<LastConnectedBlock>,
65) {
66 cmd.entity(*v_segment).despawn();
67
68 if let Some(unfinished_node) = unfinished_node {
69 cmd.entity(*unfinished_node).despawn();
70 }
71 last_connected_block.0 = None;
73}
74
75pub fn on_exit_constant(
77 mut cmd: Commands,
78 q_nodes: Query<&Transform, With<TrackNode>>,
79 cursor_pos: Res<CursorPos>,
80 assets_manager: Res<AssetsManager>,
81 mut from_node_type: ResMut<FromNodeType>,
82 mut meshes: ResMut<Assets<Mesh>>,
83) {
84 let (from_node_id, virtual_segment_transform) = match *from_node_type {
85 FromNodeType(NodeType::Virtual) => (
86 cmd.spawn((
87 TrackNode::default(),
88 Placing,
89 Transform::from_translation(cursor_pos.0.extend(5.0)),
90 Mesh2d(
91 assets_manager
92 .meshes
93 .get(&AssetType::TrackNodeNormal)
94 .cloned()
95 .unwrap(),
96 ),
97 MeshMaterial2d(
98 assets_manager
99 .materials
100 .get(&AssetType::TrackNodeNormal)
101 .cloned()
102 .unwrap(),
103 ),
104 ))
105 .observe(on_node_press_window.run_if(in_state(EditorState::Viewing)))
106 .id(),
107 Transform::from_translation(cursor_pos.0.extend(0.0)),
108 ),
109 FromNodeType(NodeType::Physical(e)) => {
110 let mut transform = *q_nodes.get(e).unwrap();
111 transform.translation.z = 0.0;
112 (e, transform)
113 }
114 };
115
116 let shape = Linear::new([Vec2::ZERO, Vec2::new(1.0, 1.0)]);
117 let mesh = shape.mesh(BezierMeshProps::default());
118
119 cmd.spawn((
120 VirtualSegment {
121 shape: Shapes::Linear(shape),
122 from: from_node_id,
123 to: NodeType::Virtual,
124 },
125 Placing,
126 virtual_segment_transform,
127 Mesh2d(meshes.add(mesh)),
128 MeshMaterial2d(
129 assets_manager
130 .materials
131 .get(&AssetType::TrackSegmentGhost)
132 .cloned()
133 .unwrap(),
134 ),
135 ));
136
137 *from_node_type = FromNodeType(NodeType::Virtual);
138}
139
140pub fn on_linear_to_quadratic(
141 mut v_segment: Single<(&mut VirtualSegment, &mut Mesh2d), With<VirtualSegment>>,
142 mut meshes: ResMut<Assets<Mesh>>,
143) {
144 let [a, b] = take_points(&v_segment.0.shape);
145 let shape = Quadratic::new([a, b, b]);
146 v_segment.1.0 = meshes.add(shape.mesh(BezierMeshProps::default()));
147 v_segment.0.shape = Shapes::Quadratic(shape);
148 v_segment.0.to = NodeType::Virtual;
149}
150
151pub fn on_quadratic_to_linear(
152 mut v_segment: Single<(&mut VirtualSegment, &mut Mesh2d), With<VirtualSegment>>,
153 mut meshes: ResMut<Assets<Mesh>>,
154) {
155 let [a, b] = take_points(&v_segment.0.shape);
156 let shape = Linear::new([a, b]);
157 v_segment.1.0 = meshes.add(shape.mesh(BezierMeshProps::default()));
158 v_segment.0.shape = Shapes::Linear(shape);
159 v_segment.0.to = NodeType::Virtual;
160}
161
162pub fn on_quadratic_to_cubic(
163 mut v_segment: Single<(&mut VirtualSegment, &mut Mesh2d), With<VirtualSegment>>,
164 mut meshes: ResMut<Assets<Mesh>>,
165) {
166 let [a, b, c] = take_points(&v_segment.0.shape);
167 let shape = Cubic::new([a, b, c, c]);
168 v_segment.1.0 = meshes.add(shape.mesh(BezierMeshProps::default()));
169 v_segment.0.shape = Shapes::Cubic(shape);
170 v_segment.0.to = NodeType::Virtual;
171}
172
173pub fn on_cubic_to_quadratic(
174 mut v_segment: Single<(&mut VirtualSegment, &mut Mesh2d), With<VirtualSegment>>,
175 mut meshes: ResMut<Assets<Mesh>>,
176) {
177 let [a, b, c] = take_points(&v_segment.0.shape);
178 let shape = Quadratic::new([a, b, c]);
179 v_segment.1.0 = meshes.add(shape.mesh(BezierMeshProps::default()));
180 v_segment.0.shape = Shapes::Quadratic(shape);
181 v_segment.0.to = NodeType::Virtual;
182}
183
184pub fn on_cubic_to_linear(
185 mut v_segment: Single<(&mut VirtualSegment, &mut Mesh2d), With<VirtualSegment>>,
186 mut meshes: ResMut<Assets<Mesh>>,
187) {
188 let [a, b] = take_points(&v_segment.0.shape);
189 let shape = Linear::new([a, b]);
190 v_segment.1.0 = meshes.add(shape.mesh(BezierMeshProps::default()));
191 v_segment.0.shape = Shapes::Linear(shape);
192 v_segment.0.to = NodeType::Virtual;
193}