OSSIA
Open Scenario System for Interactive Application
tick_policies.hpp
1 #pragma once
2 #include <ossia/dataflow/graph_node.hpp>
4 #include <ossia/detail/timed_vec.hpp>
5 
6 #include <tuplet/tuple.hpp>
7 
8 #include <bitset>
9 
10 namespace ossia::safe_nodes
11 {
12 template <typename T, typename U>
13 auto timestamp(const std::pair<T, U>& p)
14 {
15  return p.first;
16 }
17 template <typename T>
18 auto timestamp(const T& p)
19 {
20  return p.timestamp;
21 }
22 
23 struct precise_tick
24 {
25  template <typename TickFun, typename... Args>
26  void operator()(
27  TickFun&& f, const ossia::token_request& req, const ossia::timed_vec<Args>&... arg)
28  {
29  using namespace tuplet;
30  auto iterators = tuplet::make_tuple(arg.begin()...);
31  const auto last_iterators = tuplet::make_tuple(--arg.end()...);
32 
33  // while all the it are != arg.rbegin(),
34  // increment the smallest one
35  // call a tick with this at the new date
36 
37  auto reached_end = [&] {
38  bool b = true;
39  ossia::for_each_in_range<sizeof...(arg)>(
40  [&b, &iterators, &last_iterators](auto i) {
41  b &= (tuplet::get<i.value>(iterators) == tuplet::get<i.value>(last_iterators));
42  });
43  return b;
44  };
45 
46  // const auto parent_dur = req.date / req.position;
47  auto call_f = [&](ossia::time_value cur) {
48  ossia::token_request r = req;
49  // TODO r.date +=
50  tuplet::apply(
51  [&](const auto&... it) { std::forward<TickFun>(f)(r, it->second...); },
52  iterators);
53  };
54 
55  ossia::time_value current_time = req.offset;
56  while(!reached_end())
57  {
58  // run a tick with the current values (TODO pass the current time too)
59  call_f(current_time);
60 
61  std::bitset<sizeof...(Args)> to_increment;
62  to_increment.reset();
63  auto min = ossia::Infinite;
64 
65  ossia::for_each_in_range<sizeof...(arg)>([&](auto idx_t) {
66  constexpr auto idx = idx_t.value;
67  auto& it = tuplet::get<idx>(iterators);
68  if(it != tuplet::get<idx>(last_iterators))
69  {
70  auto next = it;
71  ++next;
72  const auto next_ts = time_value{timestamp(*next)};
73  const auto diff = next_ts - current_time;
74  if(diff < 0_tv)
75  {
76  // token before offset, we increment in all cases
77  it = next;
78  return;
79  }
80 
81  if(diff < min)
82  {
83  min = diff;
84  to_increment.reset();
85  to_increment.set(idx);
86  }
87  else if(diff == min)
88  {
89  to_increment.set(idx);
90  }
91  }
92  });
93 
94  current_time += min;
95  ossia::for_each_in_range<sizeof...(arg)>([&](auto idx_t) {
96  constexpr auto idx = idx_t.value;
97  if(to_increment.test(idx))
98  {
99  ++tuplet::get<idx>(iterators);
100  }
101  });
102  }
103 
104  call_f(current_time);
105  }
106 };
107 
108 struct default_tick_controls
109 {
110  template <typename TickFun, typename... Args>
111  void operator()(
112  TickFun&& f, const ossia::token_request& req, const ossia::timed_vec<Args>&... arg)
113  {
114  f(req, arg...);
115  }
116 };
117 struct default_tick
118 {
119  template <typename TickFun, typename... Args>
120  void operator()(TickFun&& f, const ossia::token_request& req)
121  {
122  f(req);
123  }
124 };
125 
126 struct last_tick
127 {
128  template <typename TickFun, typename... Args>
129  void operator()(
130  TickFun&& f, const ossia::token_request& req, const ossia::timed_vec<Args>&... arg)
131  {
132  // TODO use largest date instead
133  tuplet::apply(
134  [&](const auto&... it) { std::forward<TickFun>(f)(req, it->second...); },
135  tuplet::make_tuple(--arg.end()...));
136  }
137 };
138 
139 struct last_tick_values
140 {
141  template <typename TickFun, typename... Args>
142  void operator()(TickFun&& f, const ossia::token_request& req, const Args&... arg)
143  {
144  std::forward<TickFun>(f)(req, arg...);
145  }
146 };
147 
148 // pass first and last in a struct ev_t { T& first, last; }
149 // advanced case: regress?
150 struct first_last_tick
151 {
152  template <typename TickFun, typename... Args>
153  void operator()(
154  TickFun&& f, const ossia::token_request& req, const ossia::timed_vec<Args>&... arg)
155  {
156  // TODO use correct dates
157  tuplet::apply(
158  [&](const auto&... it) { std::forward<TickFun>(f)(req, it->second...); },
159  tuplet::make_tuple({arg.begin(), --arg.end()}...));
160  }
161 };
162 }
constexpr OSSIA_INLINE auto min(const T a, const U b) noexcept -> typename std::conditional<(sizeof(T) > sizeof(U)), T, U >::type
min function tailored for values
Definition: math.hpp:125
The time_value class.
Definition: ossia/editor/scenario/time_value.hpp:28