bevy_map_scatter/
events.rs1use bevy::prelude::*;
2use crossbeam_channel::{Receiver, Sender};
3use map_scatter::prelude::{EventSink, ScatterEvent, ScatterEventKind};
4
5#[derive(Debug, Copy, Clone, PartialEq, Eq)]
7pub enum ScatterEventPriority {
8 High,
9 Low,
10}
11
12#[derive(Debug, Clone)]
14pub struct ScatterEventFilter {
15 pub emit_run_events: bool,
17 pub emit_layer_events: bool,
19 pub emit_position_evaluated: bool,
21 pub emit_placement_made: bool,
23 pub emit_overlay_generated: bool,
25 pub emit_warnings: bool,
27}
28
29impl ScatterEventFilter {
30 pub fn high_level() -> Self {
32 Self {
33 emit_run_events: true,
34 emit_layer_events: true,
35 emit_position_evaluated: false,
36 emit_placement_made: false,
37 emit_overlay_generated: true,
38 emit_warnings: true,
39 }
40 }
41
42 pub fn verbose() -> Self {
44 Self {
45 emit_run_events: true,
46 emit_layer_events: true,
47 emit_position_evaluated: true,
48 emit_placement_made: true,
49 emit_overlay_generated: true,
50 emit_warnings: true,
51 }
52 }
53
54 pub fn wants(&self, kind: ScatterEventKind) -> bool {
55 match kind {
56 ScatterEventKind::RunStarted | ScatterEventKind::RunFinished => self.emit_run_events,
57 ScatterEventKind::LayerStarted | ScatterEventKind::LayerFinished => {
58 self.emit_layer_events
59 }
60 ScatterEventKind::PositionEvaluated => self.emit_position_evaluated,
61 ScatterEventKind::PlacementMade => self.emit_placement_made,
62 ScatterEventKind::OverlayGenerated => self.emit_overlay_generated,
63 ScatterEventKind::Warning => self.emit_warnings,
64 }
65 }
66
67 pub fn priority(kind: ScatterEventKind) -> ScatterEventPriority {
68 match kind {
69 ScatterEventKind::PositionEvaluated | ScatterEventKind::PlacementMade => {
70 ScatterEventPriority::Low
71 }
72 _ => ScatterEventPriority::High,
73 }
74 }
75}
76
77impl Default for ScatterEventFilter {
78 fn default() -> Self {
79 Self::high_level()
80 }
81}
82
83#[derive(Resource, Debug, Clone)]
85pub struct ScatterBusConfig {
86 pub capacity: usize,
88 pub filter: ScatterEventFilter,
90}
91
92impl ScatterBusConfig {
93 pub fn new(capacity: usize, filter: ScatterEventFilter) -> Self {
94 Self { capacity, filter }
95 }
96
97 pub fn with_capacity(mut self, capacity: usize) -> Self {
98 self.capacity = capacity;
99 self
100 }
101
102 pub fn with_filter(mut self, filter: ScatterEventFilter) -> Self {
103 self.filter = filter;
104 self
105 }
106}
107
108impl Default for ScatterBusConfig {
109 fn default() -> Self {
110 Self {
111 capacity: 1024,
112 filter: ScatterEventFilter::high_level(),
113 }
114 }
115}
116
117#[non_exhaustive]
119#[derive(Message, Debug, Clone)]
120pub struct ScatterMessage {
121 pub request_entity: Entity,
123 pub event: ScatterEvent,
125}
126
127#[derive(Resource, Clone)]
129pub struct ScatterBus {
130 tx: Sender<ScatterMessage>,
132 rx: Receiver<ScatterMessage>,
134 config: ScatterBusConfig,
135}
136
137impl ScatterBus {
138 pub fn new(config: ScatterBusConfig) -> Self {
139 let (tx, rx) = crossbeam_channel::bounded(config.capacity);
140 Self { tx, rx, config }
141 }
142
143 pub fn sender(&self) -> &Sender<ScatterMessage> {
144 &self.tx
145 }
146
147 pub fn receiver(&self) -> &Receiver<ScatterMessage> {
148 &self.rx
149 }
150
151 pub fn config(&self) -> &ScatterBusConfig {
152 &self.config
153 }
154
155 pub fn filter(&self) -> &ScatterEventFilter {
156 &self.config.filter
157 }
158}
159
160impl FromWorld for ScatterBus {
161 fn from_world(world: &mut World) -> Self {
162 let config = world
163 .get_resource::<ScatterBusConfig>()
164 .cloned()
165 .unwrap_or_default();
166 Self::new(config)
167 }
168}
169
170pub struct ChannelSink {
172 pub request: Entity,
174 pub tx: Sender<ScatterMessage>,
176 pub filter: ScatterEventFilter,
178}
179
180impl EventSink for ChannelSink {
181 #[inline]
182 fn send(&mut self, event: ScatterEvent) {
183 let kind = event.kind();
184 if !self.filter.wants(kind) {
185 return;
186 }
187 let message = ScatterMessage {
188 request_entity: self.request,
189 event,
190 };
191 match ScatterEventFilter::priority(kind) {
192 ScatterEventPriority::High => {
193 let _ = self.tx.send(message);
194 }
195 ScatterEventPriority::Low => {
196 let _ = self.tx.try_send(message);
197 }
198 }
199 }
200
201 fn wants(&self, kind: ScatterEventKind) -> bool {
202 self.filter.wants(kind)
203 }
204}