@devaloop/devalang 0.0.1-beta.1 → 0.0.1-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/.devalang +9 -10
  2. package/Cargo.toml +5 -4
  3. package/README.md +7 -5
  4. package/docs/CHANGELOG.md +42 -0
  5. package/docs/ROADMAP.md +5 -1
  6. package/docs/TODO.md +3 -14
  7. package/examples/bus.deva +10 -0
  8. package/examples/effect.deva +2 -0
  9. package/examples/filter.deva +11 -0
  10. package/examples/lfo.deva +9 -0
  11. package/examples/synth.deva +11 -1
  12. package/examples/synth_types.deva +17 -0
  13. package/out-tsc/core/functions/index.d.ts +5 -0
  14. package/out-tsc/core/functions/index.js +11 -0
  15. package/out-tsc/pkg/devalang_core.d.ts +2 -0
  16. package/out-tsc/pkg/devalang_core.js +17 -2
  17. package/out-tsc/pkg/devalang_core_bg.wasm.d.ts +8 -7
  18. package/package.json +1 -1
  19. package/project-version.json +3 -3
  20. package/rust/cli/bank/api.rs +122 -122
  21. package/rust/cli/bank/commands.rs +33 -2
  22. package/rust/cli/bank/mod.rs +29 -29
  23. package/rust/cli/build/commands.rs +53 -3
  24. package/rust/cli/build/mod.rs +2 -2
  25. package/rust/cli/build/process.rs +26 -7
  26. package/rust/cli/check/mod.rs +2 -2
  27. package/rust/cli/discover/commands.rs +253 -253
  28. package/rust/cli/discover/config.rs +111 -111
  29. package/rust/cli/discover/fs.rs +19 -19
  30. package/rust/cli/discover/install.rs +103 -103
  31. package/rust/cli/discover/metadata.rs +48 -48
  32. package/rust/cli/discover/mod.rs +5 -5
  33. package/rust/cli/install/addon.rs +118 -118
  34. package/rust/cli/install/bank.rs +22 -3
  35. package/rust/cli/install/commands.rs +35 -35
  36. package/rust/cli/install/mod.rs +4 -4
  37. package/rust/cli/install/plugin.rs +80 -61
  38. package/rust/cli/login/commands.rs +124 -124
  39. package/rust/cli/mod.rs +12 -12
  40. package/rust/cli/parser.rs +46 -1
  41. package/rust/cli/play/commands.rs +71 -20
  42. package/rust/cli/play/mod.rs +5 -5
  43. package/rust/cli/play/process.rs +14 -5
  44. package/rust/cli/play/realtime.rs +91 -91
  45. package/rust/cli/telemetry/commands.rs +22 -22
  46. package/rust/cli/telemetry/event_creator.rs +80 -80
  47. package/rust/cli/telemetry/mod.rs +3 -3
  48. package/rust/cli/telemetry/send.rs +51 -51
  49. package/rust/cli/template/commands.rs +69 -69
  50. package/rust/config/driver.rs +112 -103
  51. package/rust/config/mod.rs +3 -3
  52. package/rust/config/ops.rs +26 -26
  53. package/rust/config/settings.rs +101 -101
  54. package/rust/core/audio/engine/driver.rs +220 -0
  55. package/rust/core/audio/engine/export.rs +169 -0
  56. package/rust/core/audio/engine/helpers.rs +178 -170
  57. package/rust/core/audio/engine/mod.rs +51 -2
  58. package/rust/core/audio/engine/notes/dsp.rs +85 -0
  59. package/rust/core/audio/engine/notes/mod.rs +44 -0
  60. package/rust/core/audio/engine/notes/params.rs +294 -0
  61. package/rust/core/audio/engine/sample/insert.rs +199 -0
  62. package/rust/core/audio/engine/sample/mod.rs +40 -0
  63. package/rust/core/audio/engine/sample/padding.rs +170 -0
  64. package/rust/core/audio/evaluator/condition.rs +61 -0
  65. package/rust/core/audio/evaluator/mod.rs +9 -0
  66. package/rust/core/audio/{evaluator.rs → evaluator/numeric.rs} +1 -159
  67. package/rust/core/audio/evaluator/rhs.rs +16 -0
  68. package/rust/core/audio/evaluator/string_expr.rs +94 -0
  69. package/rust/core/audio/interpreter/driver.rs +55 -23
  70. package/rust/core/audio/interpreter/mod.rs +1 -13
  71. package/rust/core/audio/interpreter/statements/arrow_call/interprete.rs +175 -0
  72. package/rust/core/audio/interpreter/statements/arrow_call/methods/chord.rs +384 -0
  73. package/rust/core/audio/interpreter/statements/arrow_call/methods/mod.rs +2 -0
  74. package/rust/core/audio/interpreter/statements/arrow_call/methods/note.rs +316 -0
  75. package/rust/core/audio/interpreter/statements/arrow_call/mod.rs +3 -0
  76. package/rust/core/audio/interpreter/statements/arrow_call/types/arp.rs +192 -0
  77. package/rust/core/audio/interpreter/statements/arrow_call/types/mod.rs +24 -0
  78. package/rust/core/audio/interpreter/statements/arrow_call/types/pad.rs +116 -0
  79. package/rust/core/audio/interpreter/statements/arrow_call/types/pluck.rs +97 -0
  80. package/rust/core/audio/interpreter/statements/arrow_call/types/sub.rs +100 -0
  81. package/rust/core/audio/interpreter/{automate.rs → statements/automate.rs} +16 -18
  82. package/rust/core/audio/interpreter/{call.rs → statements/call.rs} +5 -4
  83. package/rust/core/audio/interpreter/{condition.rs → statements/condition.rs} +2 -1
  84. package/rust/core/audio/interpreter/{function.rs → statements/function.rs} +2 -4
  85. package/rust/core/audio/interpreter/{let_.rs → statements/let_.rs} +2 -4
  86. package/rust/core/audio/interpreter/{load.rs → statements/load.rs} +2 -4
  87. package/rust/core/audio/interpreter/{loop_.rs → statements/loop_.rs} +2 -1
  88. package/rust/core/audio/interpreter/statements/mod.rs +12 -0
  89. package/rust/core/audio/interpreter/{sleep.rs → statements/sleep.rs} +28 -28
  90. package/rust/core/audio/interpreter/{spawn.rs → statements/spawn.rs} +3 -2
  91. package/rust/core/audio/interpreter/{tempo.rs → statements/tempo.rs} +40 -40
  92. package/rust/core/audio/interpreter/{trigger.rs → statements/trigger.rs} +1 -1
  93. package/rust/core/audio/loader/trigger.rs +2 -1
  94. package/rust/core/audio/mod.rs +6 -7
  95. package/rust/core/audio/player.rs +70 -70
  96. package/rust/core/audio/special/easing.rs +189 -189
  97. package/rust/core/audio/special/env.rs +45 -45
  98. package/rust/core/audio/special/math.rs +134 -134
  99. package/rust/core/audio/special/mod.rs +9 -9
  100. package/rust/core/audio/special/modulator.rs +143 -143
  101. package/rust/core/builder/mod.rs +45 -2
  102. package/rust/core/debugger/lexer.rs +27 -27
  103. package/rust/core/debugger/{module.rs → logs.rs} +3 -6
  104. package/rust/core/debugger/mod.rs +30 -30
  105. package/rust/core/debugger/preprocessor.rs +27 -27
  106. package/rust/core/debugger/store.rs +2 -4
  107. package/rust/core/error/mod.rs +269 -269
  108. package/rust/core/lexer/driver.rs +59 -61
  109. package/rust/core/lexer/handler/arrow.rs +82 -82
  110. package/rust/core/lexer/handler/at.rs +21 -21
  111. package/rust/core/lexer/handler/brace.rs +41 -41
  112. package/rust/core/lexer/handler/colon.rs +21 -21
  113. package/rust/core/lexer/handler/comment.rs +30 -30
  114. package/rust/core/lexer/handler/dot.rs +21 -21
  115. package/rust/core/lexer/handler/driver.rs +337 -337
  116. package/rust/core/lexer/handler/identifier.rs +47 -47
  117. package/rust/core/lexer/handler/indent.rs +66 -66
  118. package/rust/core/lexer/handler/mod.rs +15 -15
  119. package/rust/core/lexer/handler/newline.rs +23 -23
  120. package/rust/core/lexer/handler/number.rs +31 -31
  121. package/rust/core/lexer/handler/operator.rs +46 -46
  122. package/rust/core/lexer/handler/parenthesis.rs +41 -41
  123. package/rust/core/lexer/handler/slash.rs +21 -21
  124. package/rust/core/lexer/handler/string.rs +63 -63
  125. package/rust/core/lexer/mod.rs +3 -3
  126. package/rust/core/mod.rs +0 -1
  127. package/rust/core/parser/driver/block.rs +111 -0
  128. package/rust/core/parser/driver/cursor.rs +82 -0
  129. package/rust/core/parser/driver/driver_impl.rs +139 -0
  130. package/rust/core/parser/driver/mod.rs +6 -0
  131. package/rust/core/parser/driver/parse_array.rs +120 -0
  132. package/rust/core/parser/driver/parse_map.rs +223 -0
  133. package/rust/core/parser/driver/parser.rs +160 -0
  134. package/rust/core/parser/handler/arrow_call.rs +28 -4
  135. package/rust/core/parser/handler/at.rs +279 -279
  136. package/rust/core/parser/handler/bank.rs +104 -104
  137. package/rust/core/parser/handler/condition.rs +83 -83
  138. package/rust/core/parser/handler/dot.rs +148 -148
  139. package/rust/core/parser/handler/identifier/automate.rs +254 -254
  140. package/rust/core/parser/handler/identifier/call.rs +91 -91
  141. package/rust/core/parser/handler/identifier/emit.rs +70 -70
  142. package/rust/core/parser/handler/identifier/function.rs +113 -113
  143. package/rust/core/parser/handler/identifier/group.rs +89 -89
  144. package/rust/core/parser/handler/identifier/let_.rs +173 -173
  145. package/rust/core/parser/handler/identifier/mod.rs +55 -55
  146. package/rust/core/parser/handler/identifier/on.rs +107 -107
  147. package/rust/core/parser/handler/identifier/print.rs +49 -49
  148. package/rust/core/parser/handler/identifier/sleep.rs +96 -43
  149. package/rust/core/parser/handler/identifier/spawn.rs +91 -91
  150. package/rust/core/parser/handler/identifier/synth.rs +135 -135
  151. package/rust/core/parser/handler/loop_.rs +194 -194
  152. package/rust/core/parser/handler/mod.rs +9 -9
  153. package/rust/core/parser/handler/pattern.rs +1 -1
  154. package/rust/core/parser/handler/tempo.rs +105 -57
  155. package/rust/core/parser/statement.rs +10 -11
  156. package/rust/core/plugin/loader.rs +1 -1
  157. package/rust/core/plugin/mod.rs +2 -2
  158. package/rust/core/plugin/runner/mod.rs +11 -0
  159. package/rust/core/plugin/{runner.rs → runner/non_wasm.rs} +297 -347
  160. package/rust/core/plugin/runner/wasm32.rs +43 -0
  161. package/rust/core/preprocessor/loader/inject.rs +278 -0
  162. package/rust/core/preprocessor/loader/loader_helpers.rs +110 -0
  163. package/rust/core/preprocessor/loader/mod.rs +235 -0
  164. package/rust/core/preprocessor/module.rs +2 -7
  165. package/rust/core/preprocessor/{processor.rs → processor/handlers.rs} +6 -13
  166. package/rust/core/preprocessor/processor/mod.rs +1 -0
  167. package/rust/core/preprocessor/resolver/bank.rs +49 -49
  168. package/rust/core/preprocessor/resolver/call.rs +124 -124
  169. package/rust/core/preprocessor/resolver/condition.rs +95 -95
  170. package/rust/core/preprocessor/resolver/driver.rs +324 -324
  171. package/rust/core/preprocessor/resolver/function.rs +2 -2
  172. package/rust/core/preprocessor/resolver/group.rs +46 -18
  173. package/rust/core/preprocessor/resolver/let_.rs +32 -32
  174. package/rust/core/preprocessor/resolver/loop_.rs +318 -318
  175. package/rust/core/preprocessor/resolver/mod.rs +16 -16
  176. package/rust/core/preprocessor/resolver/pattern.rs +83 -83
  177. package/rust/core/preprocessor/resolver/spawn.rs +99 -99
  178. package/rust/core/preprocessor/resolver/synth.rs +54 -54
  179. package/rust/core/preprocessor/resolver/tempo.rs +48 -48
  180. package/rust/core/preprocessor/resolver/trigger.rs +116 -116
  181. package/rust/core/preprocessor/resolver/value.rs +176 -176
  182. package/rust/core/store/global.rs +2 -6
  183. package/rust/core/store/mod.rs +1 -5
  184. package/rust/lib.rs +18 -3
  185. package/rust/main.rs +27 -3
  186. package/rust/types/Cargo.toml +1 -1
  187. package/rust/types/src/addons.rs +55 -55
  188. package/rust/types/src/config.rs +84 -74
  189. package/rust/types/src/lib.rs +15 -12
  190. package/rust/types/src/plugin.rs +20 -0
  191. package/rust/types/src/store.rs +139 -0
  192. package/rust/types/src/telemetry.rs +85 -85
  193. package/rust/utils/Cargo.toml +2 -2
  194. package/rust/utils/src/file.rs +94 -94
  195. package/rust/utils/src/first_usage.rs +97 -97
  196. package/rust/utils/src/lib.rs +9 -9
  197. package/rust/utils/src/logger.rs +200 -200
  198. package/rust/utils/src/path.rs +129 -88
  199. package/rust/utils/src/signature.rs +41 -41
  200. package/rust/utils/src/spinner.rs +20 -20
  201. package/rust/utils/src/version.rs +27 -27
  202. package/rust/utils/src/watcher.rs +46 -46
  203. package/rust/web/api.rs +5 -5
  204. package/rust/web/cdn.rs +34 -34
  205. package/rust/web/mod.rs +3 -3
  206. package/tests/integration.rs +21 -21
  207. package/typescript/core/functions/index.ts +11 -0
  208. package/typescript/pkg/devalang_core.ts +20 -4
  209. package/rust/core/audio/engine/sample.rs +0 -366
  210. package/rust/core/audio/engine/synth.rs +0 -325
  211. package/rust/core/audio/interpreter/arrow_call.rs +0 -311
  212. package/rust/core/audio/renderer.rs +0 -54
  213. package/rust/core/parser/driver.rs +0 -584
  214. package/rust/core/preprocessor/loader.rs +0 -637
  215. package/rust/core/store/export.rs +0 -28
  216. package/rust/core/store/function.rs +0 -40
  217. package/rust/core/store/import.rs +0 -28
  218. package/rust/core/store/variable.rs +0 -51
  219. package/rust/core/utils/mod.rs +0 -1
  220. package/rust/core/utils/path.rs +0 -37
@@ -1,189 +1,189 @@
1
- use crate::core::store::variable::VariableTable;
2
-
3
- // Basic easing functions operating on t in [0,1]
4
- fn easing_value(func: &str, t: f32) -> Option<f32> {
5
- let x = t.clamp(0.0, 1.0);
6
- match func {
7
- "linear" => Some(x),
8
- "easeInQuad" => Some(x * x),
9
- "easeOutQuad" => Some(x * (2.0 - x)),
10
- "easeInOutQuad" => {
11
- if x < 0.5 {
12
- Some(2.0 * x * x)
13
- } else {
14
- Some(-1.0 + (4.0 - 2.0 * x) * x)
15
- }
16
- }
17
- // Cubic
18
- "easeInCubic" => Some(x * x * x),
19
- "easeOutCubic" => Some(1.0 - (1.0 - x).powi(3)),
20
- "easeInOutCubic" => {
21
- if x < 0.5 {
22
- Some(4.0 * x * x * x)
23
- } else {
24
- Some(1.0 - (-2.0 * x + 2.0).powi(3) / 2.0)
25
- }
26
- }
27
- // Quartic
28
- "easeInQuart" => Some(x.powi(4)),
29
- "easeOutQuart" => Some(1.0 - (1.0 - x).powi(4)),
30
- "easeInOutQuart" => {
31
- if x < 0.5 {
32
- Some(8.0 * x.powi(4))
33
- } else {
34
- Some(1.0 - (-2.0 * x + 2.0).powi(4) / 2.0)
35
- }
36
- }
37
- // Exponential
38
- "easeInExpo" => Some(if x <= 0.0 {
39
- 0.0
40
- } else {
41
- 2.0_f32.powf(10.0 * x - 10.0)
42
- }),
43
- "easeOutExpo" => Some(if x >= 1.0 {
44
- 1.0
45
- } else {
46
- 1.0 - 2.0_f32.powf(-10.0 * x)
47
- }),
48
- "easeInOutExpo" => Some(if x <= 0.0 {
49
- 0.0
50
- } else if x >= 1.0 {
51
- 1.0
52
- } else if x < 0.5 {
53
- 2.0_f32.powf(20.0 * x - 10.0) / 2.0
54
- } else {
55
- (2.0 - 2.0_f32.powf(-20.0 * x + 10.0)) / 2.0
56
- }),
57
- // Back (overshoot c ~ 1.70158)
58
- "easeInBack" => {
59
- let c = 1.70158;
60
- Some((c + 1.0) * x * x * x - c * x * x)
61
- }
62
- "easeOutBack" => {
63
- let c = 1.70158;
64
- let y = 1.0 - x;
65
- Some(1.0 - ((c + 1.0) * y * y * y - c * y * y))
66
- }
67
- "easeInOutBack" => {
68
- let c1 = 1.70158;
69
- let c2 = c1 * 1.525;
70
- let x2 = x * 2.0;
71
- if x2 < 1.0 {
72
- Some((x2 * x2 * ((c2 + 1.0) * x2 - c2)) / 2.0)
73
- } else {
74
- let x2 = x2 - 2.0;
75
- Some((x2 * x2 * ((c2 + 1.0) * x2 + c2)) / 2.0 + 1.0)
76
- }
77
- }
78
- // Elastic
79
- "easeInElastic" => {
80
- if x == 0.0 {
81
- Some(0.0)
82
- } else if x == 1.0 {
83
- Some(1.0)
84
- } else {
85
- let c = 2.0 * std::f32::consts::PI / 3.0;
86
- Some(-(2.0_f32.powf(10.0 * x - 10.0)) * ((x * 10.0 - 10.75) * c).sin())
87
- }
88
- }
89
- "easeOutElastic" => {
90
- if x == 0.0 {
91
- Some(0.0)
92
- } else if x == 1.0 {
93
- Some(1.0)
94
- } else {
95
- let c = 2.0 * std::f32::consts::PI / 3.0;
96
- Some(2.0_f32.powf(-10.0 * x) * ((x * 10.0 - 0.75) * c).sin() + 1.0)
97
- }
98
- }
99
- "easeInOutElastic" => {
100
- if x == 0.0 {
101
- Some(0.0)
102
- } else if x == 1.0 {
103
- Some(1.0)
104
- } else {
105
- let c = 2.0 * std::f32::consts::PI / 4.5;
106
- if x < 0.5 {
107
- Some(-(2.0_f32.powf(20.0 * x - 10.0)) * ((20.0 * x - 11.125) * c).sin() / 2.0)
108
- } else {
109
- Some(
110
- 2.0_f32.powf(-20.0 * x + 10.0) * ((20.0 * x - 11.125) * c).sin() / 2.0
111
- + 1.0,
112
- )
113
- }
114
- }
115
- }
116
- // Bounce helpers
117
- "easeInBounce" => Some(1.0 - bounce_out(1.0 - x)),
118
- "easeOutBounce" => Some(bounce_out(x)),
119
- "easeInOutBounce" => Some(if x < 0.5 {
120
- (1.0 - bounce_out(1.0 - 2.0 * x)) / 2.0
121
- } else {
122
- (1.0 + bounce_out(2.0 * x - 1.0)) / 2.0
123
- }),
124
- _ => None,
125
- }
126
- }
127
-
128
- fn bounce_out(x: f32) -> f32 {
129
- let n1 = 7.5625;
130
- let d1 = 2.75;
131
- if x < 1.0 / d1 {
132
- n1 * x * x
133
- } else if x < 2.0 / d1 {
134
- let x = x - 1.5 / d1;
135
- n1 * x * x + 0.75
136
- } else if x < 2.5 / d1 {
137
- let x = x - 2.25 / d1;
138
- n1 * x * x + 0.9375
139
- } else {
140
- let x = x - 2.625 / d1;
141
- n1 * x * x + 0.984375
142
- }
143
- }
144
-
145
- // Find and evaluate the first $easing.<fn>(...) occurrence in the string.
146
- // Accepts a single argument expression producing t in [0,1].
147
- pub fn find_and_eval_first_easing_call<EvalFn>(
148
- s: &str,
149
- eval: EvalFn,
150
- vars: &VariableTable,
151
- bpm: f32,
152
- beat: f32,
153
- ) -> Option<String>
154
- where
155
- EvalFn: Fn(&str, &VariableTable, f32, f32) -> Option<f32>,
156
- {
157
- let start = s.find("$easing.")?;
158
- let open_rel = s[start..].find('(')?;
159
- let open = start + open_rel;
160
- let func = &s[start + 9..open];
161
-
162
- // Find matching close parenthesis
163
- let mut depth: i32 = 0;
164
- let mut close_abs: Option<usize> = None;
165
- for (i, ch) in s[open..].char_indices() {
166
- match ch {
167
- '(' => depth += 1,
168
- ')' => {
169
- depth -= 1;
170
- if depth == 0 {
171
- close_abs = Some(open + i);
172
- break;
173
- }
174
- }
175
- _ => {}
176
- }
177
- }
178
- let close = close_abs?;
179
-
180
- let inner = &s[open + 1..close];
181
- let t = eval(inner, vars, bpm, beat)?;
182
- let result = easing_value(func, t)?;
183
-
184
- let mut replaced = String::new();
185
- replaced.push_str(&s[..start]);
186
- replaced.push_str(&result.to_string());
187
- replaced.push_str(&s[close + 1..]);
188
- Some(replaced)
189
- }
1
+ use devalang_types::VariableTable;
2
+
3
+ // Basic easing functions operating on t in [0,1]
4
+ fn easing_value(func: &str, t: f32) -> Option<f32> {
5
+ let x = t.clamp(0.0, 1.0);
6
+ match func {
7
+ "linear" => Some(x),
8
+ "easeInQuad" => Some(x * x),
9
+ "easeOutQuad" => Some(x * (2.0 - x)),
10
+ "easeInOutQuad" => {
11
+ if x < 0.5 {
12
+ Some(2.0 * x * x)
13
+ } else {
14
+ Some(-1.0 + (4.0 - 2.0 * x) * x)
15
+ }
16
+ }
17
+ // Cubic
18
+ "easeInCubic" => Some(x * x * x),
19
+ "easeOutCubic" => Some(1.0 - (1.0 - x).powi(3)),
20
+ "easeInOutCubic" => {
21
+ if x < 0.5 {
22
+ Some(4.0 * x * x * x)
23
+ } else {
24
+ Some(1.0 - (-2.0 * x + 2.0).powi(3) / 2.0)
25
+ }
26
+ }
27
+ // Quartic
28
+ "easeInQuart" => Some(x.powi(4)),
29
+ "easeOutQuart" => Some(1.0 - (1.0 - x).powi(4)),
30
+ "easeInOutQuart" => {
31
+ if x < 0.5 {
32
+ Some(8.0 * x.powi(4))
33
+ } else {
34
+ Some(1.0 - (-2.0 * x + 2.0).powi(4) / 2.0)
35
+ }
36
+ }
37
+ // Exponential
38
+ "easeInExpo" => Some(if x <= 0.0 {
39
+ 0.0
40
+ } else {
41
+ 2.0_f32.powf(10.0 * x - 10.0)
42
+ }),
43
+ "easeOutExpo" => Some(if x >= 1.0 {
44
+ 1.0
45
+ } else {
46
+ 1.0 - 2.0_f32.powf(-10.0 * x)
47
+ }),
48
+ "easeInOutExpo" => Some(if x <= 0.0 {
49
+ 0.0
50
+ } else if x >= 1.0 {
51
+ 1.0
52
+ } else if x < 0.5 {
53
+ 2.0_f32.powf(20.0 * x - 10.0) / 2.0
54
+ } else {
55
+ (2.0 - 2.0_f32.powf(-20.0 * x + 10.0)) / 2.0
56
+ }),
57
+ // Back (overshoot c ~ 1.70158)
58
+ "easeInBack" => {
59
+ let c = 1.70158;
60
+ Some((c + 1.0) * x * x * x - c * x * x)
61
+ }
62
+ "easeOutBack" => {
63
+ let c = 1.70158;
64
+ let y = 1.0 - x;
65
+ Some(1.0 - ((c + 1.0) * y * y * y - c * y * y))
66
+ }
67
+ "easeInOutBack" => {
68
+ let c1 = 1.70158;
69
+ let c2 = c1 * 1.525;
70
+ let x2 = x * 2.0;
71
+ if x2 < 1.0 {
72
+ Some((x2 * x2 * ((c2 + 1.0) * x2 - c2)) / 2.0)
73
+ } else {
74
+ let x2 = x2 - 2.0;
75
+ Some((x2 * x2 * ((c2 + 1.0) * x2 + c2)) / 2.0 + 1.0)
76
+ }
77
+ }
78
+ // Elastic
79
+ "easeInElastic" => {
80
+ if x == 0.0 {
81
+ Some(0.0)
82
+ } else if x == 1.0 {
83
+ Some(1.0)
84
+ } else {
85
+ let c = 2.0 * std::f32::consts::PI / 3.0;
86
+ Some(-(2.0_f32.powf(10.0 * x - 10.0)) * ((x * 10.0 - 10.75) * c).sin())
87
+ }
88
+ }
89
+ "easeOutElastic" => {
90
+ if x == 0.0 {
91
+ Some(0.0)
92
+ } else if x == 1.0 {
93
+ Some(1.0)
94
+ } else {
95
+ let c = 2.0 * std::f32::consts::PI / 3.0;
96
+ Some(2.0_f32.powf(-10.0 * x) * ((x * 10.0 - 0.75) * c).sin() + 1.0)
97
+ }
98
+ }
99
+ "easeInOutElastic" => {
100
+ if x == 0.0 {
101
+ Some(0.0)
102
+ } else if x == 1.0 {
103
+ Some(1.0)
104
+ } else {
105
+ let c = 2.0 * std::f32::consts::PI / 4.5;
106
+ if x < 0.5 {
107
+ Some(-(2.0_f32.powf(20.0 * x - 10.0)) * ((20.0 * x - 11.125) * c).sin() / 2.0)
108
+ } else {
109
+ Some(
110
+ 2.0_f32.powf(-20.0 * x + 10.0) * ((20.0 * x - 11.125) * c).sin() / 2.0
111
+ + 1.0,
112
+ )
113
+ }
114
+ }
115
+ }
116
+ // Bounce helpers
117
+ "easeInBounce" => Some(1.0 - bounce_out(1.0 - x)),
118
+ "easeOutBounce" => Some(bounce_out(x)),
119
+ "easeInOutBounce" => Some(if x < 0.5 {
120
+ (1.0 - bounce_out(1.0 - 2.0 * x)) / 2.0
121
+ } else {
122
+ (1.0 + bounce_out(2.0 * x - 1.0)) / 2.0
123
+ }),
124
+ _ => None,
125
+ }
126
+ }
127
+
128
+ fn bounce_out(x: f32) -> f32 {
129
+ let n1 = 7.5625;
130
+ let d1 = 2.75;
131
+ if x < 1.0 / d1 {
132
+ n1 * x * x
133
+ } else if x < 2.0 / d1 {
134
+ let x = x - 1.5 / d1;
135
+ n1 * x * x + 0.75
136
+ } else if x < 2.5 / d1 {
137
+ let x = x - 2.25 / d1;
138
+ n1 * x * x + 0.9375
139
+ } else {
140
+ let x = x - 2.625 / d1;
141
+ n1 * x * x + 0.984375
142
+ }
143
+ }
144
+
145
+ // Find and evaluate the first $easing.<fn>(...) occurrence in the string.
146
+ // Accepts a single argument expression producing t in [0,1].
147
+ pub fn find_and_eval_first_easing_call<EvalFn>(
148
+ s: &str,
149
+ eval: EvalFn,
150
+ vars: &VariableTable,
151
+ bpm: f32,
152
+ beat: f32,
153
+ ) -> Option<String>
154
+ where
155
+ EvalFn: Fn(&str, &VariableTable, f32, f32) -> Option<f32>,
156
+ {
157
+ let start = s.find("$easing.")?;
158
+ let open_rel = s[start..].find('(')?;
159
+ let open = start + open_rel;
160
+ let func = &s[start + 9..open];
161
+
162
+ // Find matching close parenthesis
163
+ let mut depth: i32 = 0;
164
+ let mut close_abs: Option<usize> = None;
165
+ for (i, ch) in s[open..].char_indices() {
166
+ match ch {
167
+ '(' => depth += 1,
168
+ ')' => {
169
+ depth -= 1;
170
+ if depth == 0 {
171
+ close_abs = Some(open + i);
172
+ break;
173
+ }
174
+ }
175
+ _ => {}
176
+ }
177
+ }
178
+ let close = close_abs?;
179
+
180
+ let inner = &s[open + 1..close];
181
+ let t = eval(inner, vars, bpm, beat)?;
182
+ let result = easing_value(func, t)?;
183
+
184
+ let mut replaced = String::new();
185
+ replaced.push_str(&s[..start]);
186
+ replaced.push_str(&result.to_string());
187
+ replaced.push_str(&s[close + 1..]);
188
+ Some(replaced)
189
+ }
@@ -1,45 +1,45 @@
1
- use devalang_types::Value;
2
-
3
- use crate::core::store::variable::VariableTable;
4
- use std::sync::OnceLock;
5
- use std::time::{SystemTime, UNIX_EPOCH};
6
-
7
- static SESSION_SEED: OnceLock<f32> = OnceLock::new();
8
-
9
- pub fn get_session_seed() -> f32 {
10
- *SESSION_SEED.get_or_init(|| {
11
- let now = SystemTime::now()
12
- .duration_since(UNIX_EPOCH)
13
- .unwrap_or_default();
14
- // Build a stable 0..1 seed from nanos
15
- let nanos = now.subsec_nanos();
16
- ((nanos as f32) / 1_000_000_000.0).clamp(0.0, 1.0)
17
- })
18
- }
19
-
20
- // Resolve special environment variables like $env.bpm, $env.beat, $env.position
21
- // For now, $env.position is treated as an alias of beat.
22
- pub fn resolve_env_atom(atom: &str, bpm: f32, beat: f32) -> Option<f32> {
23
- match atom {
24
- "$env.bpm" => Some(bpm),
25
- "$env.beat" => Some(beat),
26
- "$env.position" => Some(beat),
27
- // Optional seed for deterministic randomness
28
- "$env.seed" => Some(get_session_seed()),
29
- _ => None,
30
- }
31
- }
32
-
33
- // Utility: resolve an identifier or numeric literal to f32 using the variable table
34
- pub fn resolve_atom_or_var(atom: &str, vars: &VariableTable, bpm: f32, beat: f32) -> Option<f32> {
35
- if let Some(v) = resolve_env_atom(atom, bpm, beat) {
36
- return Some(v);
37
- }
38
- if let Ok(n) = atom.parse::<f32>() {
39
- return Some(n);
40
- }
41
- if let Some(Value::Number(n)) = vars.get(atom) {
42
- return Some(*n);
43
- }
44
- None
45
- }
1
+ use devalang_types::Value;
2
+
3
+ use devalang_types::VariableTable;
4
+ use std::sync::OnceLock;
5
+ use std::time::{SystemTime, UNIX_EPOCH};
6
+
7
+ static SESSION_SEED: OnceLock<f32> = OnceLock::new();
8
+
9
+ pub fn get_session_seed() -> f32 {
10
+ *SESSION_SEED.get_or_init(|| {
11
+ let now = SystemTime::now()
12
+ .duration_since(UNIX_EPOCH)
13
+ .unwrap_or_default();
14
+ // Build a stable 0..1 seed from nanos
15
+ let nanos = now.subsec_nanos();
16
+ ((nanos as f32) / 1_000_000_000.0).clamp(0.0, 1.0)
17
+ })
18
+ }
19
+
20
+ // Resolve special environment variables like $env.bpm, $env.beat, $env.position
21
+ // For now, $env.position is treated as an alias of beat.
22
+ pub fn resolve_env_atom(atom: &str, bpm: f32, beat: f32) -> Option<f32> {
23
+ match atom {
24
+ "$env.bpm" => Some(bpm),
25
+ "$env.beat" => Some(beat),
26
+ "$env.position" => Some(beat),
27
+ // Optional seed for deterministic randomness
28
+ "$env.seed" => Some(get_session_seed()),
29
+ _ => None,
30
+ }
31
+ }
32
+
33
+ // Utility: resolve an identifier or numeric literal to f32 using the variable table
34
+ pub fn resolve_atom_or_var(atom: &str, vars: &VariableTable, bpm: f32, beat: f32) -> Option<f32> {
35
+ if let Some(v) = resolve_env_atom(atom, bpm, beat) {
36
+ return Some(v);
37
+ }
38
+ if let Ok(n) = atom.parse::<f32>() {
39
+ return Some(n);
40
+ }
41
+ if let Some(Value::Number(n)) = vars.get(atom) {
42
+ return Some(*n);
43
+ }
44
+ None
45
+ }