1use std::marker::PhantomData;
2use bevy::{ ecs::system::EntityCommands, prelude::* };
3use crate::{
4 commands::UpdateOutputWireSet,
5 components::{ GateOutput, InputBundle, LogicGateFans, OutputBundle, Wire, WireBundle },
6 logic::signal::Signal,
7};
8
9pub trait LogicExt {
11 type EntityBuilder<'a> where Self: 'a;
12 type GateBuilder;
13 type WireBuilder;
14 type NoEvalWire;
15
16 fn spawn_gate(
18 &mut self,
19 bundle: impl Bundle
20 ) -> GateBuilder<'_, Self::GateBuilder, Unknown, Unknown>;
21 fn spawn_input(&mut self) -> Self::EntityBuilder<'_>;
22 fn spawn_output(&mut self) -> Self::EntityBuilder<'_>;
23 fn spawn_wire<I, O>(
24 &mut self,
25 from_gate: &GateData<I, Known>,
26 from_output: usize,
27 to_gate: &GateData<Known, O>,
28 to_input: usize
29 ) -> WireBuilder<'_, Self::WireBuilder>;
30
31 fn spawn_no_eval_wire(&mut self, from_output: Entity, to_input: Entity) -> Entity;
34}
35
36impl LogicExt for World {
37 type EntityBuilder<'a> = EntityWorldMut<'a>;
38 type GateBuilder = Self;
39 type WireBuilder = Self;
40 type NoEvalWire = Entity;
41
42 fn spawn_gate(&mut self, bundle: impl Bundle) -> GateBuilder<'_, Self::GateBuilder> {
43 let entity = self.spawn(bundle).id();
44 GateBuilder {
45 cmd: self,
46 data: GateData {
47 entity,
48 fans: LogicGateFans::default(),
49 _state: PhantomData,
50 },
51 }
52 }
53
54 fn spawn_input(&mut self) -> Self::EntityBuilder<'_> {
55 self.spawn(InputBundle::default())
56 }
57
58 fn spawn_output(&mut self) -> Self::EntityBuilder<'_> {
59 self.spawn(OutputBundle::default())
60 }
61
62 fn spawn_wire<I, O>(
69 &mut self,
70 from_gate: &GateData<I, Known>,
71 from_output: usize,
72 to_gate: &GateData<Known, O>,
73 to_input: usize
74 ) -> WireBuilder<'_, Self::WireBuilder> {
75 let from = from_gate.output(from_output);
76 let to = to_gate.input(to_input);
77 let entity = self.spawn((Signal::Undefined, Wire::new(from, to))).id();
78
79 self.get_mut::<GateOutput>(from)
80 .expect("from_gate entity does not have GateOutput component")
81 .wires.insert(entity);
82
83 WireBuilder {
84 cmd: self,
85 data: WireData {
86 entity,
87 from,
88 to,
89 from_gate: from_gate.id(),
90 to_gate: to_gate.id(),
91 },
92 }
93 }
94
95 fn spawn_no_eval_wire(&mut self, from_output: Entity, to_input: Entity) -> Entity {
96 let wire_entity = self
97 .spawn(WireBundle {
98 wire: Wire {
99 from: from_output,
100 to: to_input,
101 },
102 signal: Signal::default(),
103 })
104 .id();
105
106 self.get_mut::<GateOutput>(from_output)
107 .expect("from_output entity does not have GateOutput component")
108 .wires.insert(wire_entity);
109
110 wire_entity
111 }
112}
113
114impl<'w, 's> LogicExt for Commands<'w, 's> {
115 type EntityBuilder<'a> = EntityCommands<'a> where Self: 'a;
116 type GateBuilder = Self;
117 type WireBuilder = Self;
118 type NoEvalWire = Entity;
119
120 fn spawn_gate(&mut self, bundle: impl Bundle) -> GateBuilder<'_, Self::GateBuilder> {
121 let entity = self.spawn(bundle).id();
122 GateBuilder {
123 cmd: self,
124 data: GateData {
125 entity,
126 fans: LogicGateFans::default(),
127 _state: PhantomData,
128 },
129 }
130 }
131
132 fn spawn_input(&mut self) -> Self::EntityBuilder<'_> {
133 self.spawn(InputBundle::default())
134 }
135
136 fn spawn_output(&mut self) -> Self::EntityBuilder<'_> {
137 self.spawn(OutputBundle::default())
138 }
139
140 fn spawn_wire<I, O>(
147 &mut self,
148 from_gate: &GateData<I, Known>,
149 from_output: usize,
150 to_gate: &GateData<Known, O>,
151 to_input: usize
152 ) -> WireBuilder<'_, Self::WireBuilder> {
153 let from = from_gate.output(from_output);
154 let to = to_gate.input(to_input);
155 let entity = self.spawn((Signal::Undefined, Wire::new(from, to))).id();
156
157 self.add(UpdateOutputWireSet::Add { output_entity: from, wire_entity: entity });
158
159 WireBuilder {
160 cmd: self,
161 data: WireData {
162 entity,
163 from,
164 to,
165 from_gate: from_gate.id(),
166 to_gate: to_gate.id(),
167 },
168 }
169 }
170
171 fn spawn_no_eval_wire(&mut self, from_output: Entity, to_input: Entity) -> Entity {
172 let wire_entity = self
173 .spawn(WireBundle {
174 wire: Wire {
175 from: from_output,
176 to: to_input,
177 },
178 signal: Signal::default(),
179 })
180 .id();
181
182 self.add(UpdateOutputWireSet::Add {
183 output_entity: from_output,
184 wire_entity,
185 });
186
187 wire_entity
188 }
189}
190
191#[derive(Debug, Clone, Copy)]
192pub struct Unknown;
193
194#[derive(Debug, Clone, Copy)]
195pub struct Known;
196
197#[derive(Debug, Clone, PartialEq, Eq)]
198pub struct GateData<I = Unknown, O = Unknown> {
199 entity: Entity,
200 fans: LogicGateFans,
201 _state: PhantomData<(I, O)>,
202}
203
204impl<I, O> GateData<I, O> {
205 pub fn id(&self) -> Entity {
206 self.entity
207 }
208
209 pub fn inputs(&self) -> &[Option<Entity>] {
210 &self.fans.inputs
211 }
212
213 pub fn outputs(&self) -> &[Option<Entity>] {
214 &self.fans.outputs
215 }
216}
217
218impl<O> GateData<Known, O> {
219 pub fn get_input(&self, index: usize) -> Option<Entity> {
223 self.fans.inputs.get(index).copied().flatten()
224 }
225
226 pub fn input(&self, index: usize) -> Entity {
230 self.fans.inputs[index].expect("input entity is None")
231 }
232}
233
234impl<I> GateData<I, Known> {
235 pub fn get_output(&self, index: usize) -> Option<Entity> {
239 self.fans.outputs.get(index).copied().flatten()
240 }
241
242 pub fn output(&self, index: usize) -> Entity {
246 self.fans.outputs[index].expect("input entity is None")
247 }
248}
249
250pub struct GateBuilder<'a, T, I = Unknown, O = Unknown> {
251 cmd: &'a mut T,
252 data: GateData<I, O>,
253}
254
255pub trait GateFanWorldMut {
257 fn modify_fan(&mut self, cmd: &mut EntityWorldMut, index: usize);
258}
259impl<T> GateFanWorldMut for T where T: FnMut(&mut EntityWorldMut, usize) {
260 fn modify_fan(&mut self, cmd: &mut EntityWorldMut, index: usize) {
261 self(cmd, index);
262 }
263}
264
265pub trait GateFanEntityMut {
266 fn modify_fan(&mut self, cmd: &mut EntityCommands, index: usize);
267}
268
269impl<T> GateFanEntityMut for T where T: FnMut(&mut EntityCommands, usize) {
270 fn modify_fan(&mut self, cmd: &mut EntityCommands, index: usize) {
271 self(cmd, index);
272 }
273}
274
275impl<'a, I, O> GateBuilder<'a, World, I, O> {
276 pub fn world(&mut self) -> &mut World {
277 self.cmd
278 }
279
280 pub fn entity_commands(&mut self) -> EntityWorldMut<'_> {
281 self.cmd.entity_mut(self.data.entity)
282 }
283
284 pub fn insert_bundle(mut self, bundle: impl Bundle) -> Self {
285 self.entity_commands().insert(bundle);
286 self
287 }
288
289 pub fn insert(&mut self, bundle: impl Bundle) -> &mut Self {
290 self.entity_commands().insert(bundle);
291 self
292 }
293}
294
295impl<'a, O> GateBuilder<'a, World, Unknown, O> {
296 pub fn with_inputs(self, count: usize) -> GateBuilder<'a, World, Known, O> {
297 let mut inputs = Vec::with_capacity(count);
298 self.cmd.entity_mut(self.data.entity).with_children(|gate| {
299 for _ in 0..count {
300 inputs.push(Some(gate.spawn(InputBundle::default()).id()));
301 }
302 });
303
304 GateBuilder {
305 cmd: self.cmd,
306 data: GateData {
307 entity: self.data.entity,
308 fans: LogicGateFans {
309 inputs,
310 outputs: self.data.fans.outputs,
311 },
312 _state: PhantomData,
313 },
314 }
315 }
316
317 pub fn build_inputs(
320 self,
321 count: usize,
322 mut builder: impl GateFanWorldMut
323 ) -> GateBuilder<'a, World, Known, O> {
324 let mut inputs = Vec::with_capacity(count);
325
326 self.cmd.entity_mut(self.data.entity).with_children(|gate| {
327 for i in 0..count {
328 let mut cmd = gate.spawn(InputBundle::default());
329 let input_entity = cmd.id();
330 inputs.push(Some(input_entity));
331 builder.modify_fan(&mut cmd, i);
332 }
333 });
334
335 GateBuilder {
336 cmd: self.cmd,
337 data: GateData {
338 entity: self.data.entity,
339 fans: LogicGateFans {
340 inputs,
341 outputs: self.data.fans.outputs,
342 },
343 _state: PhantomData,
344 },
345 }
346 }
347}
348
349impl<'a, I> GateBuilder<'a, World, I, Unknown> {
350 pub fn with_outputs(self, count: usize) -> GateBuilder<'a, World, I, Known> {
351 let mut outputs = Vec::with_capacity(count);
352 self.cmd.entity_mut(self.data.entity).with_children(|gate| {
353 for _ in 0..count {
354 outputs.push(Some(gate.spawn(OutputBundle::default()).id()));
355 }
356 });
357
358 GateBuilder {
359 cmd: self.cmd,
360 data: GateData {
361 entity: self.data.entity,
362 fans: LogicGateFans {
363 inputs: self.data.fans.inputs,
364 outputs,
365 },
366 _state: PhantomData,
367 },
368 }
369 }
370
371 pub fn build_outputs(
374 self,
375 count: usize,
376 mut builder: impl GateFanWorldMut
377 ) -> GateBuilder<'a, World, I, Known> {
378 let mut outputs = Vec::with_capacity(count);
379
380 self.cmd.entity_mut(self.data.entity).with_children(|gate| {
381 for i in 0..count {
382 let mut cmd = gate.spawn(OutputBundle::default());
383 let output_entity = cmd.id();
384 outputs.push(Some(output_entity));
385 builder.modify_fan(&mut cmd, i);
386 }
387 });
388
389 GateBuilder {
390 cmd: self.cmd,
391 data: GateData {
392 entity: self.data.entity,
393 fans: LogicGateFans {
394 inputs: self.data.fans.inputs,
395 outputs,
396 },
397 _state: PhantomData,
398 },
399 }
400 }
401}
402
403impl<'a, I, O> GateBuilder<'a, World, I, O> {
404 pub fn build(self) -> GateData<I, O> {
410 self.cmd
411 .entity_mut(self.data.entity)
412 .push_children(
413 &self.data.fans
414 .some_inputs()
415 .into_iter()
416 .chain(self.data.fans.some_outputs())
417 .collect::<Vec<_>>()
418 )
419 .insert(self.data.fans.clone());
420
421 self.data
422 }
423}
424
425impl<'w, 's, 'a, I, O> GateBuilder<'a, Commands<'w, 's>, I, O> {
428 pub fn entity_commands(&mut self) -> EntityCommands<'_> {
429 self.cmd.entity(self.data.entity)
430 }
431
432 pub fn insert_bundle(mut self, bundle: impl Bundle) -> Self {
433 self.entity_commands().insert(bundle);
434 self
435 }
436
437 pub fn insert(&mut self, bundle: impl Bundle) -> &mut Self {
438 self.entity_commands().insert(bundle);
439 self
440 }
441}
442
443impl<'w, 's, 'a, O> GateBuilder<'a, Commands<'w, 's>, Unknown, O> {
444 pub fn with_inputs(self, count: usize) -> GateBuilder<'a, Commands<'w, 's>, Known, O> {
445 let mut inputs = Vec::with_capacity(count);
446 self.cmd.entity(self.data.entity).with_children(|gate| {
447 for _ in 0..count {
448 inputs.push(Some(gate.spawn(InputBundle::default()).id()));
449 }
450 });
451
452 GateBuilder {
453 cmd: self.cmd,
454 data: GateData {
455 entity: self.data.entity,
456 fans: LogicGateFans {
457 inputs,
458 outputs: self.data.fans.outputs,
459 },
460 _state: PhantomData,
461 },
462 }
463 }
464
465 pub fn build_inputs(
468 self,
469 count: usize,
470 mut builder: impl GateFanEntityMut
471 ) -> GateBuilder<'a, Commands<'w, 's>, Known, O> {
472 let mut inputs = Vec::with_capacity(count);
473
474 self.cmd.entity(self.data.entity).with_children(|gate| {
475 for i in 0..count {
476 let mut cmd = gate.spawn(InputBundle::default());
477 let input_entity = cmd.id();
478 inputs.push(Some(input_entity));
479 builder.modify_fan(&mut cmd, i);
480 }
481 });
482
483 GateBuilder {
484 cmd: self.cmd,
485 data: GateData {
486 entity: self.data.entity,
487 fans: LogicGateFans {
488 inputs,
489 outputs: self.data.fans.outputs,
490 },
491 _state: PhantomData,
492 },
493 }
494 }
495}
496
497impl<'w, 's, 'a, I> GateBuilder<'a, Commands<'w, 's>, I, Unknown> {
498 pub fn with_outputs(self, count: usize) -> GateBuilder<'a, Commands<'w, 's>, I, Known> {
499 let mut outputs = Vec::with_capacity(count);
500 self.cmd.entity(self.data.entity).with_children(|gate| {
501 for _ in 0..count {
502 outputs.push(Some(gate.spawn(OutputBundle::default()).id()));
503 }
504 });
505
506 GateBuilder {
507 cmd: self.cmd,
508 data: GateData {
509 entity: self.data.entity,
510 fans: LogicGateFans {
511 inputs: self.data.fans.inputs,
512 outputs,
513 },
514 _state: PhantomData,
515 },
516 }
517 }
518
519 pub fn build_outputs(
522 self,
523 count: usize,
524 mut builder: impl GateFanEntityMut
525 ) -> GateBuilder<'a, Commands<'w, 's>, I, Known> {
526 let mut outputs = Vec::with_capacity(count);
527
528 self.cmd.entity(self.data.entity).with_children(|gate| {
529 for i in 0..count {
530 let mut cmd = gate.spawn(OutputBundle::default());
531 let output_entity = cmd.id();
532 outputs.push(Some(output_entity));
533 builder.modify_fan(&mut cmd, i);
534 }
535 });
536
537 GateBuilder {
538 cmd: self.cmd,
539 data: GateData {
540 entity: self.data.entity,
541 fans: LogicGateFans {
542 inputs: self.data.fans.inputs,
543 outputs,
544 },
545 _state: PhantomData,
546 },
547 }
548 }
549}
550
551impl<'w, 's, 'a, I, O> GateBuilder<'a, Commands<'w, 's>, I, O> {
552 pub fn build(self) -> GateData<I, O> {
558 self.cmd
559 .entity(self.data.entity)
560 .push_children(
561 &self.data.fans
562 .some_inputs()
563 .into_iter()
564 .chain(self.data.fans.some_outputs())
565 .collect::<Vec<_>>()
566 )
567 .insert(self.data.fans.clone());
568
569 self.data
570 }
571}
572
573#[derive(Debug, Clone, Copy, PartialEq, Eq)]
574pub struct WireData {
575 pub entity: Entity,
576 pub from: Entity,
577 pub from_gate: Entity,
578 pub to: Entity,
579 pub to_gate: Entity,
580}
581
582impl WireData {
583 #[inline]
584 pub const fn id(&self) -> Entity {
585 self.entity
586 }
587
588 #[doc(alias = "from")]
589 #[doc(alias = "sink")]
590 #[inline]
591 pub const fn input(&self) -> Entity {
592 self.from
593 }
594
595 #[doc(alias = "to")]
596 #[doc(alias = "source")]
597 #[inline]
598 pub const fn output(&self) -> Entity {
599 self.to
600 }
601}
602
603pub struct WireBuilder<'a, T> {
604 cmd: &'a mut T,
605 data: WireData,
606}
607
608impl<T> WireBuilder<'_, T> {
609 pub fn world(&mut self) -> &mut T {
610 self.cmd
611 }
612
613 pub const fn id(&self) -> Entity {
615 self.data.entity
616 }
617
618 #[doc(alias = "from")]
620 #[doc(alias = "sink")]
621 #[inline]
622 pub const fn input(&self) -> Entity {
623 self.data.from
624 }
625
626 #[doc(alias = "to")]
628 #[doc(alias = "source")]
629 #[inline]
630 pub const fn output(&self) -> Entity {
631 self.data.to
632 }
633}
634
635impl WireBuilder<'_, World> {
636 pub fn downgrade(self) -> WireData {
639 self.data
640 }
641
642 pub fn entity_commands(&mut self) -> EntityWorldMut<'_> {
643 self.cmd.entity_mut(self.data.entity)
644 }
645
646 pub fn insert(&mut self, bundle: impl Bundle) -> &mut Self {
647 self.entity_commands().insert(bundle);
648 self
649 }
650}
651
652impl<'w, 's> WireBuilder<'_, Commands<'w, 's>> {
653 pub fn downgrade(self) -> WireData {
656 self.data
657 }
658
659 pub fn entity_commands(&mut self) -> EntityCommands<'_> {
660 self.cmd.entity(self.data.entity)
661 }
662
663 pub fn insert(&mut self, bundle: impl Bundle) -> &mut Self {
664 self.entity_commands().insert(bundle);
665 self
666 }
667}