cog_task/action/core/
seq.rs

1use crate::action::{Action, ActionSignal, Props, StatefulAction, DEFAULT};
2use crate::comm::{QWriter, Signal, SignalId};
3use crate::resource::{IoManager, ResourceAddr, ResourceManager};
4use crate::server::{AsyncSignal, Config, State, SyncSignal};
5use eframe::egui;
6use eyre::{eyre, Result};
7use itertools::Itertools;
8use serde::{Deserialize, Serialize};
9use std::collections::{BTreeSet, VecDeque};
10
11#[derive(Debug, Deserialize, Serialize)]
12pub struct Seq(Vec<Box<dyn Action>>);
13
14stateful!(Seq {
15    children: VecDeque<Box<dyn StatefulAction>>,
16});
17
18impl Seq {
19    pub fn new(children: Vec<Box<dyn Action>>) -> Self {
20        Self(children)
21    }
22}
23
24impl Action for Seq {
25    #[inline]
26    fn in_signals(&self) -> BTreeSet<SignalId> {
27        let mut signals = BTreeSet::new();
28        for c in self.0.iter() {
29            signals.extend(c.in_signals());
30        }
31        signals
32    }
33
34    #[inline]
35    fn out_signals(&self) -> BTreeSet<SignalId> {
36        let mut signals = BTreeSet::new();
37        for c in self.0.iter() {
38            signals.extend(c.out_signals());
39        }
40        signals
41    }
42
43    #[inline]
44    fn resources(&self, config: &Config) -> Vec<ResourceAddr> {
45        self.0
46            .iter()
47            .flat_map(|c| c.resources(config))
48            .unique()
49            .collect()
50    }
51
52    fn stateful(
53        &self,
54        io: &IoManager,
55        res: &ResourceManager,
56        config: &Config,
57        sync_writer: &QWriter<SyncSignal>,
58        async_writer: &QWriter<AsyncSignal>,
59    ) -> Result<Box<dyn StatefulAction>> {
60        let mut children: VecDeque<_> = VecDeque::with_capacity(self.0.len());
61        for c in self.0.iter() {
62            children.push_back(c.stateful(io, res, config, sync_writer, async_writer)?);
63        }
64
65        for c in children.iter().take(children.len() - 1) {
66            if c.props().infinite() {
67                return Err(eyre!("Only the final action in a `Seq` can be infinite."));
68            }
69        }
70
71        Ok(Box::new(StatefulSeq {
72            done: false,
73            children,
74        }))
75    }
76}
77
78impl StatefulSeq {
79    pub fn push(&mut self, child: impl Into<Box<dyn StatefulAction>>) {
80        self.children.push_back(child.into());
81    }
82}
83
84impl StatefulAction for StatefulSeq {
85    impl_stateful!();
86
87    #[inline(always)]
88    fn props(&self) -> Props {
89        if let Some(c) = self.children.get(0) {
90            c.props()
91        } else {
92            DEFAULT.into()
93        }
94    }
95
96    #[inline]
97    fn start(
98        &mut self,
99        sync_writer: &mut QWriter<SyncSignal>,
100        async_writer: &mut QWriter<AsyncSignal>,
101        state: &State,
102    ) -> Result<Signal> {
103        if let Some(c) = self.children.get_mut(0) {
104            c.start(sync_writer, async_writer, state)
105        } else {
106            self.done = true;
107            sync_writer.push(SyncSignal::UpdateGraph);
108            Ok(Signal::none())
109        }
110    }
111
112    #[inline]
113    fn update(
114        &mut self,
115        signal: &ActionSignal,
116        sync_writer: &mut QWriter<SyncSignal>,
117        async_writer: &mut QWriter<AsyncSignal>,
118        state: &State,
119    ) -> Result<Signal> {
120        if let Some(c) = self.children.get_mut(0) {
121            let mut news = vec![];
122            news.extend(c.update(signal, sync_writer, async_writer, state)?);
123
124            if c.is_over()? {
125                news.extend(self.children.pop_front().unwrap().stop(
126                    sync_writer,
127                    async_writer,
128                    state,
129                )?);
130
131                if let Some(c) = self.children.get_mut(0) {
132                    news.extend(c.start(sync_writer, async_writer, state)?);
133                } else {
134                    self.done = true;
135                }
136            }
137
138            Ok(news.into())
139        } else {
140            Ok(Signal::none())
141        }
142    }
143
144    fn show(
145        &mut self,
146        ui: &mut egui::Ui,
147        sync_writer: &mut QWriter<SyncSignal>,
148        async_writer: &mut QWriter<AsyncSignal>,
149        state: &State,
150    ) -> Result<()> {
151        if let Some(c) = self.children.get_mut(0) {
152            c.show(ui, sync_writer, async_writer, state)
153        } else {
154            Ok(())
155        }
156    }
157
158    #[inline]
159    fn stop(
160        &mut self,
161        sync_writer: &mut QWriter<SyncSignal>,
162        async_writer: &mut QWriter<AsyncSignal>,
163        state: &State,
164    ) -> Result<Signal> {
165        if let Some(c) = self.children.get_mut(0) {
166            c.stop(sync_writer, async_writer, state)
167        } else {
168            Ok(Signal::none())
169        }
170    }
171}