MayaFlux 1.0.0
Digital-First Multimedia Processing Framework
Loading...
Searching...
No Matches
Pattern.hpp
Go to the documentation of this file.
1#pragma once
2
4
5namespace MayaFlux::Vruta {
6class Routine;
7}
8
9namespace MayaFlux::Kriya {
10
11/**
12 * @concept PatternGenerator
13 * @brief A callable from a step index to a value
14 */
15template <typename Generator, typename Index>
16concept PatternGenerator = std::move_constructible<std::decay_t<Generator>>
17 && std::invocable<std::decay_t<Generator>&, Index>
18 && !std::is_void_v<std::invoke_result_t<std::decay_t<Generator>&, Index>>;
19
20/**
21 * @struct PatternTraits
22 * @brief Types a pattern derives from its generator and index
23 */
24template <typename Generator, typename Index>
26 using index_type = Index;
27 using generator_type = std::decay_t<Generator>;
28 using value_type = std::invoke_result_t<generator_type&, Index>;
29};
30
31/**
32 * @concept PatternCallback
33 * @brief A callable that accepts what the generator returns
34 */
35template <typename Callback, typename Value>
36concept PatternCallback = std::move_constructible<std::decay_t<Callback>>
37 && std::invocable<std::decay_t<Callback>&, Value>;
38
39/**
40 * @concept PatternCondition
41 * @brief A predicate on the step index
42 */
43template <typename Condition, typename Index>
44concept PatternCondition = std::move_constructible<std::decay_t<Condition>>
45 && std::predicate<std::decay_t<Condition>&, Index>;
46
47/**
48 * @concept PatternDurationSource
49 * @brief A callable from a pass number to the array of durations for that pass
50 */
51template <typename Source>
52concept PatternDurationSource = std::move_constructible<std::decay_t<Source>>
53 && std::invocable<std::decay_t<Source>&, uint64_t>
54 && std::ranges::input_range<std::invoke_result_t<std::decay_t<Source>&, uint64_t>>
55 && std::convertible_to<std::ranges::range_value_t<std::invoke_result_t<std::decay_t<Source>&, uint64_t>>, double>;
56
57/**
58 * @brief Creates a pattern whose next step runs when a condition holds
59 * @tparam Index Step index type, default uint64_t
60 * @param generator Callable from the step index to any value
61 * @param callback Callable that takes the generated value
62 * @param ready Condition for the step index, checked each time the routine resumes
63 * @param token Selects the routine type that runs the pattern
64 * @return The routine, or nullptr for an empty function or an unsupported token
65 *
66 * The routine suspends and checks `ready(index)` again until it holds, then runs
67 * `callback(generator(index))` and advances the index. The value type is
68 * whatever the generator returns, so no cast is involved. The condition can be
69 * anything that returns a bool: a Logic node's output, a flag, another routine's
70 * state. A condition that stays true runs one step per check.
71 *
72 * Tokens:
73 * - SAMPLE_ACCURATE: SoundRoutine
74 * - FRAME_ACCURATE: GraphicsRoutine
75 * - MULTI_RATE: CrossRoutine
76 * - CONDITIONAL: FreeRoutine on the condition thread
77 *
78 * A function that throws is logged and ends the pattern.
79 *
80 * ```cpp
81 * auto routine = Kriya::pattern(
82 * [](uint64_t step) { return glm::vec2(step, step * 2); },
83 * [](glm::vec2 point) { use(point); },
84 * [gate](uint64_t) { return gate->get_last_output() > 0.5; });
85 * scheduler->add_task(routine);
86 * ```
87 */
88template <std::incrementable Index = uint64_t, typename Generator, typename Callback, typename Condition>
92std::shared_ptr<Vruta::Routine> pattern(
93 Generator generator,
94 Callback callback,
95 Condition ready,
97
98/**
99 * @brief Creates a pattern whose steps are spaced by a list of durations
100 * @tparam Index Step index type, default uint64_t
101 * @param generator Callable from the step index to any value
102 * @param callback Callable that takes the generated value
103 * @param durations Seconds to wait after each step, stepped through in order and repeated
104 * @param token Selects the routine type that runs the pattern
105 * @return The routine, or nullptr for an empty function, an empty list or an unsupported token
106 *
107 * The first step runs at once. After step `i` the routine waits `durations[i % size]`, rounded
108 * to the routine's own units and never less than one unit. A single interval is a list of one:
109 * `pattern(gen, cb, { 0.125 })`. A throw from the generator or callback is logged and ends the
110 * pattern.
111 *
112 * ```cpp
113 * auto routine = Kriya::pattern(generate, apply, { 0.25, 0.25, 0.5 });
114 * scheduler->add_task(routine);
115 * ```
116 */
117template <std::incrementable Index = uint64_t, typename Generator, typename Callback>
120std::shared_ptr<Vruta::Routine> pattern(
121 Generator generator,
122 Callback callback,
123 std::vector<double> durations,
125
126/**
127 * @brief Creates a pattern whose durations come from a function that returns an array per pass
128 * @tparam Index Step index type, default uint64_t
129 * @param generator Callable from the step index to any value
130 * @param callback Callable that takes the generated value
131 * @param durations Callable from a pass number to a range of seconds
132 * @param token Selects the routine type that runs the pattern
133 * @return The routine, or nullptr for an empty function or an unsupported token
134 *
135 * The function is called with 0 for the first pass and again, with the next number, each time
136 * the array it returned has been used up. Durations are stepped through one per step. An empty
137 * array, or a throw from the function, ends the pattern after the step that asked for it. This
138 * lets the gaps change from pass to pass.
139 *
140 * ```cpp
141 * auto routine = Kriya::pattern(generate, apply, [](uint64_t pass) -> std::vector<double> {
142 * if (pass > 3) return {};
143 * return { 0.25, 0.25 * (pass + 1) };
144 * });
145 * ```
146 */
147template <std::incrementable Index = uint64_t, typename Generator, typename Callback, typename Source>
151std::shared_ptr<Vruta::Routine> pattern(
152 Generator generator,
153 Callback callback,
154 Source durations,
156
157/**
158 * @brief The std::any, uint64_t form of the condition driven pattern
159 *
160 * Compiled once in the library. Chosen when the three arguments are
161 * std::function objects of exactly these types; lambdas select the template.
162 */
163MAYAFLUX_API std::shared_ptr<Vruta::Routine> pattern(
164 std::function<std::any(uint64_t)> pattern_func,
165 std::function<void(std::any)> callback,
166 std::function<bool(uint64_t)> ready,
168
169} // namespace MayaFlux::Kriya
170
171#include "Pattern.inl"
PickCallback callback
Definition Picker.cpp:22
A callable that accepts what the generator returns.
Definition Pattern.hpp:36
A predicate on the step index.
Definition Pattern.hpp:44
A callable from a pass number to the array of durations for that pass.
Definition Pattern.hpp:52
A callable from a step index to a value.
Definition Pattern.hpp:16
std::shared_ptr< Vruta::Routine > pattern(std::function< std::any(uint64_t)> pattern_func, std::function< void(std::any)> callback, std::function< bool(uint64_t)> ready, Vruta::ProcessingToken token)
The std::any, uint64_t form of the condition driven pattern.
Definition Pattern.cpp:5
@ SAMPLE_ACCURATE
Coroutine is sample-accurate.
std::decay_t< Generator > generator_type
Definition Pattern.hpp:27
std::invoke_result_t< generator_type &, Index > value_type
Definition Pattern.hpp:28
Types a pattern derives from its generator and index.
Definition Pattern.hpp:25