1use std::collections::HashSet;
2
3use evalexpr::{build_operator_tree, EvalexprError, HashMapContext, Node};
4use itertools::Itertools;
5use lerpable::{step, Lerpable};
6use murrelet_common::IdxInRange2d;
7use serde::{Deserialize, Deserializer};
8use serde_yaml::Location;
9
10use crate::{
11 expr::IntoExprWorldContext,
12 livecode::{GetLivecodeIdentifiers, LivecodeFromWorld},
13 state::LivecodeWorldState,
14 unitcells::UnitCellExprWorldContext,
15};
16
17#[derive(Debug)]
18pub enum LivecodeError {
19 Raw(String), EvalExpr(String, EvalexprError),
21 Io(String, std::io::Error),
22 NestGetExtra(String),
23 NestGetInvalid(String),
24 SerdeLoc(Location, String),
25 WGPU(String),
26}
27impl LivecodeError {}
28impl std::fmt::Display for LivecodeError {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 match self {
31 LivecodeError::Raw(msg) => write!(f, "{}", msg),
32 LivecodeError::EvalExpr(msg, err) => write!(f, "{}: {}", msg, err),
33 LivecodeError::Io(msg, err) => write!(f, "{}: {}", msg, err),
34 LivecodeError::NestGetExtra(err) => {
35 write!(f, "nest get has unusable tokens...: {}", err)
36 }
37 LivecodeError::NestGetInvalid(err) => {
38 write!(f, "nest get requested for odd thing...: {}", err)
39 }
40 LivecodeError::SerdeLoc(location, err) => {
41 let loc = format!("{},{}", location.line(), location.column());
43 write!(f, "parse_error :: loc: {}, err: {}", loc, err)
44 }
45 LivecodeError::WGPU(err) => write!(f, "shader parse error: {}", err),
46 }
47 }
48}
49
50impl std::error::Error for LivecodeError {}
51
52pub type LivecodeResult<T> = Result<T, LivecodeError>;
53
54#[derive(Debug, Clone, Deserialize)]
55#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
56#[serde(transparent)]
57pub struct AdditionalContextNode(#[cfg_attr(feature = "schemars", schemars(with = "String"))] Node);
58
59impl Default for AdditionalContextNode {
60 fn default() -> Self {
61 Self(build_operator_tree("").unwrap())
62 }
63}
64
65impl AdditionalContextNode {
66 pub fn eval_raw(&self, ctx: &mut HashMapContext) -> LivecodeResult<()> {
67 self.0
68 .eval_empty_with_context_mut(ctx)
69 .map_err(|err| LivecodeError::EvalExpr("error evaluating ctx".to_owned(), err))
70 }
71}
72
73impl Lerpable for AdditionalContextNode {
74 fn lerpify<T: lerpable::IsLerpingMethod>(&self, other: &Self, pct: &T) -> Self {
75 step(self, other, pct)
76 }
77}
78
79#[derive(Debug, Clone, Deserialize)]
80#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
81#[serde(untagged)]
82pub enum ControlVecElementRepeatMethod {
83 Single(usize),
84 Rect([usize; 2]),
85}
86impl ControlVecElementRepeatMethod {
87 fn len(&self) -> usize {
88 match self {
89 ControlVecElementRepeatMethod::Single(s) => *s,
90 ControlVecElementRepeatMethod::Rect(r) => r[0] * r[1],
91 }
92 }
93 fn iter(&self) -> Vec<IdxInRange2d> {
94 match self {
95 ControlVecElementRepeatMethod::Single(s) => {
96 let mut v = vec![];
97 for i in 0..*s {
98 v.push(IdxInRange2d::new(i, 1, *s));
99 }
100 v
101 }
102 ControlVecElementRepeatMethod::Rect(s) => {
103 let mut v = vec![];
104 for i in 0..s[0] {
105 for j in 0..s[1] {
106 v.push(IdxInRange2d::new_rect(i, j, s[0], s[1]));
107 }
108 }
109 v
110 }
111 }
112 }
113}
114
115#[derive(Debug, Clone, Deserialize)]
116#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
117pub struct ControlVecElementRepeat<Source> {
118 repeat: ControlVecElementRepeatMethod,
119 prefix: String,
121 what: Vec<Source>,
122}
123
124impl<T: GetLivecodeIdentifiers> GetLivecodeIdentifiers for ControlVecElement<T> {
125 fn variable_identifiers(&self) -> Vec<crate::livecode::LivecodeVariable> {
126 match self {
127 ControlVecElement::Single(c) => c.variable_identifiers(),
128 ControlVecElement::Repeat(c) => c
129 .what
130 .iter()
131 .flat_map(|x| x.variable_identifiers())
132 .collect::<HashSet<_>>()
133 .into_iter()
134 .collect_vec(),
135 }
136 }
137
138 fn function_identifiers(&self) -> Vec<crate::livecode::LivecodeFunction> {
139 match self {
140 ControlVecElement::Single(c) => c.function_identifiers(),
141 ControlVecElement::Repeat(c) => c
142 .what
143 .iter()
144 .flat_map(|x| x.function_identifiers())
145 .collect::<HashSet<_>>()
146 .into_iter()
147 .collect_vec(),
148 }
149 }
150}
151
152impl<Source> ControlVecElementRepeat<Source> {
153 pub fn eval_and_expand_vec<Target>(&self, w: &LivecodeWorldState) -> LivecodeResult<Vec<Target>>
154 where
155 Source: LivecodeFromWorld<Target>,
156 {
157 let mut result = Vec::with_capacity(self.repeat.len() * self.what.len());
158
159 let prefix = if self.prefix.is_empty() {
160 "i_".to_string()
161 } else {
162 format!("{}_", self.prefix)
163 };
164
165 for idx in self.repeat.iter() {
166 let expr =
167 UnitCellExprWorldContext::from_idx2d(idx, 1.0).as_expr_world_context_values();
168 let new_w = w.clone_with_vals(expr, &prefix)?;
169
170 for src in &self.what {
171 let o = src.o(&new_w)?;
172 result.push(o);
173 }
174 }
175 Ok(result)
176 }
177}
178
179#[derive(Debug, Clone)]
180#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
181pub enum ControlVecElement<Source> {
182 Single(Source),
183 Repeat(ControlVecElementRepeat<Source>),
184}
185
186impl<Source> ControlVecElement<Source> {
187 pub fn raw(c: Source) -> Self {
188 Self::Single(c)
189 }
190
191 pub fn eval_and_expand_vec<Target>(&self, w: &LivecodeWorldState) -> LivecodeResult<Vec<Target>>
192 where
193 Source: LivecodeFromWorld<Target>,
194 {
195 match self {
196 ControlVecElement::Single(c) => Ok(vec![c.o(w)?]),
197 ControlVecElement::Repeat(r) => r.eval_and_expand_vec(w),
198 }
199 }
200}
201
202impl<'de, Source> Deserialize<'de> for ControlVecElement<Source>
204where
205 Source: Deserialize<'de>,
206{
207 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
208 where
209 D: Deserializer<'de>,
210 {
211 let value = serde_yaml::Value::deserialize(deserializer)?;
212
213 let mut errors = Vec::new();
214
215 match Source::deserialize(value.clone()) {
217 Ok(single) => return Ok(ControlVecElement::Single(single)),
218 Err(e) => errors.push(format!("{}", e)),
219 }
220
221 match ControlVecElementRepeat::deserialize(value.clone()) {
223 Ok(repeat) => return Ok(ControlVecElement::Repeat(repeat)),
224 Err(e) => {
225 errors.push(format!("(repeat {})", e))
227 }
228 }
229
230 Err(serde::de::Error::custom(format!(
232 "ControlVecElement {}",
233 errors.join(" ")
234 )))
235 }
236}