cog_task/action/core/
par.rs

1use crate::action::{Action, ActionSignal, Props, StatefulAction, DEFAULT, INFINITE, VISUAL};
2use crate::comm::{QWriter, Signal, SignalId};
3use crate::resource::{IoManager, ResourceAddr, ResourceManager};
4use crate::server::{AsyncSignal, Config, State, SyncSignal};
5use eframe::egui;
6use eyre::Result;
7use itertools::Itertools;
8use serde::{Deserialize, Serialize};
9use std::collections::BTreeSet;
10
11#[derive(Debug, Deserialize, Serialize)]
12pub struct Par(
13    Vec<Box<dyn Action>>,
14    #[serde(default)] Vec<Box<dyn Action>>,
15    #[serde(default)] Require,
16);
17
18stateful!(Par {
19    primary: Vec<Box<dyn StatefulAction>>,
20    secondary: Vec<Box<dyn StatefulAction>>,
21    require: Require,
22});
23
24#[derive(Debug, Clone, Copy, Deserialize, Serialize)]
25#[serde(rename_all = "snake_case")]
26pub enum Require {
27    All,
28    Any,
29}
30
31impl Default for Require {
32    fn default() -> Self {
33        Require::All
34    }
35}
36
37impl Par {
38    pub fn new(
39        primary: Vec<Box<dyn Action>>,
40        secondary: Vec<Box<dyn Action>>,
41        require: Require,
42    ) -> Self {
43        Self(primary, secondary, require)
44    }
45}
46
47impl Action for Par {
48    #[inline]
49    fn in_signals(&self) -> BTreeSet<SignalId> {
50        let mut signals = BTreeSet::new();
51        for c in self.0.iter() {
52            signals.extend(c.in_signals());
53        }
54        for c in self.1.iter() {
55            signals.extend(c.in_signals());
56        }
57        signals
58    }
59
60    #[inline]
61    fn out_signals(&self) -> BTreeSet<SignalId> {
62        let mut signals = BTreeSet::new();
63        for c in self.0.iter() {
64            signals.extend(c.out_signals());
65        }
66        for c in self.1.iter() {
67            signals.extend(c.out_signals());
68        }
69        signals
70    }
71
72    #[inline]
73    fn resources(&self, config: &Config) -> Vec<ResourceAddr> {
74        self.0
75            .iter()
76            .chain(self.1.iter())
77            .flat_map(|c| c.resources(config))
78            .unique()
79            .collect()
80    }
81
82    fn stateful(
83        &self,
84        io: &IoManager,
85        res: &ResourceManager,
86        config: &Config,
87        sync_writer: &QWriter<SyncSignal>,
88        async_writer: &QWriter<AsyncSignal>,
89    ) -> Result<Box<dyn StatefulAction>> {
90        let mut primary = vec![];
91        for c in self.0.iter() {
92            primary.push(c.stateful(io, res, config, sync_writer, async_writer)?);
93        }
94
95        let mut secondary = vec![];
96        for c in self.1.iter() {
97            secondary.push(c.stateful(io, res, config, sync_writer, async_writer)?);
98        }
99
100        Ok(Box::new(StatefulPar {
101            done: false,
102            primary,
103            secondary,
104            require: self.2,
105        }))
106    }
107}
108
109impl StatefulPar {
110    pub fn push_primary(&mut self, child: impl Into<Box<dyn StatefulAction>>) {
111        self.primary.push(child.into());
112    }
113
114    pub fn push_secondary(&mut self, child: impl Into<Box<dyn StatefulAction>>) {
115        self.secondary.push(child.into());
116    }
117}
118
119impl StatefulAction for StatefulPar {
120    impl_stateful!();
121
122    #[inline]
123    fn props(&self) -> Props {
124        let mut props = DEFAULT;
125
126        for c in self.primary.iter() {
127            let c = c.props();
128            if c.visual() {
129                props |= VISUAL;
130            }
131            if c.infinite() {
132                props |= INFINITE;
133            }
134        }
135
136        for c in self.secondary.iter() {
137            let c = c.props();
138            if c.visual() {
139                props |= VISUAL;
140            }
141        }
142
143        props.into()
144    }
145
146    #[inline]
147    fn start(
148        &mut self,
149        sync_writer: &mut QWriter<SyncSignal>,
150        async_writer: &mut QWriter<AsyncSignal>,
151        state: &State,
152    ) -> Result<Signal> {
153        let mut news = vec![];
154        if self.primary.is_empty() {
155            self.done = true;
156            sync_writer.push(SyncSignal::UpdateGraph);
157        } else {
158            for c in self.primary.iter_mut().chain(self.secondary.iter_mut()) {
159                news.extend(c.start(sync_writer, async_writer, state)?);
160            }
161        }
162
163        Ok(news.into())
164    }
165
166    #[inline]
167    fn update(
168        &mut self,
169        signal: &ActionSignal,
170        sync_writer: &mut QWriter<SyncSignal>,
171        async_writer: &mut QWriter<AsyncSignal>,
172        state: &State,
173    ) -> Result<Signal> {
174        let mut done = vec![];
175        let mut news = vec![];
176        let mut finished = false;
177        for (i, c) in self.primary.iter_mut().enumerate() {
178            news.extend(c.update(signal, sync_writer, async_writer, state)?);
179
180            if c.is_over()? {
181                news.extend(c.stop(sync_writer, async_writer, state)?);
182                done.push(i);
183            }
184        }
185        if matches!(self.require, Require::Any) && !done.is_empty() {
186            finished = true;
187        }
188        for i in done.into_iter().rev() {
189            self.primary.remove(i);
190        }
191        if self.primary.is_empty() {
192            finished = true;
193        }
194
195        let mut done = vec![];
196        for (i, c) in self.secondary.iter_mut().enumerate() {
197            news.extend(c.update(signal, sync_writer, async_writer, state)?);
198
199            if c.is_over()? {
200                news.extend(c.stop(sync_writer, async_writer, state)?);
201                done.push(i);
202            }
203        }
204        for i in done.into_iter().rev() {
205            self.secondary.remove(i);
206        }
207
208        if finished {
209            self.done = true;
210        }
211
212        Ok(news.into())
213    }
214
215    fn show(
216        &mut self,
217        ui: &mut egui::Ui,
218        sync_writer: &mut QWriter<SyncSignal>,
219        async_writer: &mut QWriter<AsyncSignal>,
220        state: &State,
221    ) -> Result<()> {
222        if let Some(c) = self.primary.iter_mut().find(|c| c.props().visual()) {
223            c.show(ui, sync_writer, async_writer, state)
224        } else if let Some(c) = self.secondary.iter_mut().find(|c| c.props().visual()) {
225            c.show(ui, sync_writer, async_writer, state)
226        } else {
227            Ok(())
228        }
229    }
230
231    #[inline]
232    fn stop(
233        &mut self,
234        sync_writer: &mut QWriter<SyncSignal>,
235        async_writer: &mut QWriter<AsyncSignal>,
236        state: &State,
237    ) -> Result<Signal> {
238        let mut news = vec![];
239        let children = self.primary.iter_mut().chain(self.secondary.iter_mut());
240        for c in children {
241            news.extend(c.stop(sync_writer, async_writer, state)?);
242        }
243        Ok(news.into())
244    }
245}