ControlWidgetDomains.hpp
1 #pragma once
2 #include <Process/Dataflow/Port.hpp>
3 
4 #include <score/tools/Debug.hpp>
5 
6 #include <ossia/detail/math.hpp>
7 #include <ossia/network/domain/domain.hpp>
8 
9 #include <type_traits>
10 
11 namespace WidgetFactory
12 {
13 
15 {
16  static constexpr double to01(double min, double range, double val) noexcept
17  {
18  return (val - min) / range;
19  }
20 
21  static constexpr double from01(double min, double range, double val) noexcept
22  {
23  return min + val * range;
24  }
25 
26  template <typename T>
27  static double to01(const T& slider, double val) noexcept
28  {
29  auto min = slider.getMin();
30  auto max = slider.getMax();
31  if(max - min == 0)
32  max = min + 1;
33  return to01(min, max - min, val);
34  }
35 
36  template <typename T>
37  static double from01(const T& slider, double val) noexcept
38  {
39  auto min = slider.getMin();
40  auto max = slider.getMax();
41  if(max - min == 0)
42  max = min + 1;
43  return from01(min, max - min, val);
44  }
45 
46  template <typename T>
47  static ossia::vec2f to01(const T& slider, ossia::vec2f val) noexcept
48  {
49  ossia::vec2f res;
50  const auto min = slider.getMin();
51  const auto max = slider.getMax();
52  res[0] = to01(min[0], max[0] - min[0], val[0]);
53  res[1] = to01(min[1], max[1] - min[1], val[1]);
54  return res;
55  }
56 
57  template <typename T>
58  static ossia::vec2f from01(const T& slider, ossia::vec2f val) noexcept
59  {
60  ossia::vec2f res;
61  const auto min = slider.getMin();
62  const auto max = slider.getMax();
63  res[0] = from01(min[0], max[0] - min[0], val[0]);
64  res[1] = from01(min[1], max[1] - min[1], val[1]);
65  return res;
66  }
67 
68  template <typename T>
69  static ossia::vec3f to01(const T& slider, ossia::vec3f val) noexcept
70  {
71  ossia::vec3f res;
72  const auto min = slider.getMin();
73  const auto max = slider.getMax();
74  res[0] = to01(min[0], max[0] - min[0], val[0]);
75  res[1] = to01(min[1], max[1] - min[1], val[1]);
76  res[2] = to01(min[2], max[2] - min[2], val[2]);
77  return res;
78  }
79 
80  template <typename T>
81  static ossia::vec3f from01(const T& slider, ossia::vec3f val) noexcept
82  {
83  ossia::vec3f res;
84  const auto min = slider.getMin();
85  const auto max = slider.getMax();
86  res[0] = from01(min[0], max[0] - min[0], val[0]);
87  res[1] = from01(min[1], max[1] - min[1], val[1]);
88  res[2] = from01(min[2], max[2] - min[2], val[2]);
89  return res;
90  }
91 
92  template <typename T>
93  static ossia::vec4f to01(const T& slider, ossia::vec4f val) noexcept
94  {
95  ossia::vec4f res;
96  const auto min = slider.getMin();
97  const auto max = slider.getMax();
98  res[0] = to01(min[0], max[0] - min[0], val[0]);
99  res[1] = to01(min[1], max[1] - min[1], val[1]);
100  res[2] = to01(min[2], max[2] - min[2], val[2]);
101  res[3] = to01(min[3], max[3] - min[3], val[3]);
102  return res;
103  }
104 
105  template <typename T>
106  static ossia::vec4f from01(const T& slider, ossia::vec4f val) noexcept
107  {
108  ossia::vec4f res;
109  const auto min = slider.getMin();
110  const auto max = slider.getMax();
111  res[0] = from01(min[0], max[0] - min[0], val[0]);
112  res[1] = from01(min[1], max[1] - min[1], val[1]);
113  res[2] = from01(min[2], max[2] - min[2], val[2]);
114  res[3] = from01(min[3], max[3] - min[3], val[3]);
115  return res;
116  }
117 };
118 
120 {
121  static double to01(double min, double range, double val) noexcept
122  {
123  return ossia::log_to_normalized(min, range, val);
124  }
125 
126  static double from01(double min, double range, double val) noexcept
127  {
128  return ossia::normalized_to_log(min, range, val);
129  }
130 
131  template <typename T>
132  static double to01(const T& slider, double val) noexcept
133  {
134  auto min = slider.getMin();
135  auto max = slider.getMax();
136  if(max - min == 0)
137  max = min + 1;
138  return to01(min, max - min, val);
139  }
140 
141  template <typename T>
142  static double from01(const T& slider, double val) noexcept
143  {
144  auto min = slider.getMin();
145  auto max = slider.getMax();
146  if(max - min == 0)
147  max = min + 1;
148  return from01(min, max - min, val);
149  }
150 };
151 
152 template <typename Norm_T>
154 {
155  double min{};
156  double max{};
157  template <typename T>
158  FixedNormalizer(const T& slider)
159  {
160  min = slider.getMin();
161  max = slider.getMax();
162  if(max - min == 0)
163  max = min + 1;
164  }
165 
166  constexpr double to01(double val) const noexcept
167  {
168  return Norm_T::to01(min, max - min, val);
169  }
170 
171  constexpr double from01(double val) const noexcept
172  {
173  return Norm_T::from01(min, max - min, val);
174  }
175 };
176 
177 template <typename Norm_T, typename Slider_T>
179 {
180  const Slider_T& slider;
181 
182  UpdatingNormalizer(const Slider_T& sl)
183  : slider{sl}
184  {
185  }
186 
187  constexpr double to01(double val) const noexcept { return Norm_T::to01(slider, val); }
188 
189  constexpr double from01(double val) const noexcept
190  {
191  return Norm_T::from01(slider, val);
192  }
193 };
194 
195 template <typename T, typename Control_T, typename Widget_T>
196 static void bindFloatDomain(const T& slider, Control_T& inlet, Widget_T& widget)
197 {
198  auto min = slider.getMin();
199  auto max = slider.getMax();
200  if(max - min == 0)
201  max = min + 1;
202 
203  widget.setRange(min, max);
204 
205  if constexpr(std::is_base_of_v<Process::ControlInlet, T>)
206  {
207  SCORE_ASSERT(&slider == &inlet);
208  QObject::connect(&inlet, &Control_T::domainChanged, &widget, [&slider, &widget] {
209  auto min = slider.getMin();
210  auto max = slider.getMax();
211  if(max - min == 0)
212  max = min + 1;
213 
214  widget.setRange(min, max);
215  });
216  }
217 }
218 
219 template <typename T, typename Control_T, typename Widget_T>
220 static void bindIntDomain(const T& slider, Control_T& inlet, Widget_T& widget)
221 {
222  auto min = slider.getMin();
223  auto max = slider.getMax();
224  if(max - min == 0)
225  max = min + 1;
226 
227  widget.setRange(min, max);
228 
229  if constexpr(std::is_base_of_v<Process::ControlInlet, T>)
230  {
231  SCORE_ASSERT(&slider == &inlet);
232  QObject::connect(&inlet, &Control_T::domainChanged, &widget, [&slider, &widget] {
233  auto min = slider.getMin();
234  auto max = slider.getMax();
235  if(max - min == 0)
236  max = min + 1;
237 
238  widget.setRange(min, max);
239  });
240  }
241 }
242 
243 template <typename T, typename Control_T, typename Widget_T>
244 static void bindVec2Domain(const T& slider, Control_T& inlet, Widget_T& widget)
245 {
246  auto update_range = [&widget, &inlet] {
247  auto min = ossia::get_min(inlet.domain());
248  auto max = ossia::get_max(inlet.domain());
249  auto min_float = min.template target<float>();
250  auto max_float = max.template target<float>();
251  if(min_float && max_float)
252  {
253  if(*max_float - *min_float == 0)
254  *max_float = *min_float + 1;
255  widget.setRange({*min_float, *min_float}, {*max_float, *max_float});
256  }
257  else
258  {
259  auto min_vec2 = min.template target<ossia::vec2f>();
260  auto max_vec2 = max.template target<ossia::vec2f>();
261  if(min_vec2 && max_vec2)
262  {
263  auto& min = *min_vec2;
264  auto& max = *max_vec2;
265  for(std::size_t i = 0; i < min.size(); i++)
266  {
267  if(max[i] - min[i] == 0)
268  max[i] = min[i] + 1;
269  }
270 
271  widget.setRange(min, max);
272  }
273  }
274  };
275 
276  update_range();
277 
278  if constexpr(std::is_base_of_v<Process::ControlInlet, T>)
279  {
280  SCORE_ASSERT(&slider == &inlet);
281  QObject::connect(&inlet, &Control_T::domainChanged, &widget, update_range);
282  }
283 }
284 
285 template <typename T, typename Control_T, typename Widget_T>
286 static void bindVec3Domain(const T& slider, Control_T& inlet, Widget_T& widget)
287 {
288  auto update_range = [&widget, &inlet] {
289  auto min = ossia::get_min(inlet.domain());
290  auto max = ossia::get_max(inlet.domain());
291  auto min_float = min.template target<float>();
292  auto max_float = max.template target<float>();
293  if(min_float && max_float)
294  {
295  if(*max_float - *min_float == 0)
296  *max_float = *min_float + 1;
297  widget.setRange(
298  {*min_float, *min_float, *min_float}, {*max_float, *max_float, *max_float});
299  }
300  else
301  {
302  auto min_vec3 = min.template target<ossia::vec3f>();
303  auto max_vec3 = max.template target<ossia::vec3f>();
304  if(min_vec3 && max_vec3)
305  {
306  auto& min = *min_vec3;
307  auto& max = *max_vec3;
308  for(std::size_t i = 0; i < min.size(); i++)
309  {
310  if(max[i] - min[i] == 0)
311  max[i] = min[i] + 1;
312  }
313 
314  widget.setRange(min, max);
315  }
316  }
317  };
318 
319  update_range();
320 
321  if constexpr(std::is_base_of_v<Process::ControlInlet, T>)
322  {
323  SCORE_ASSERT(&slider == &inlet);
324  QObject::connect(&inlet, &Control_T::domainChanged, &widget, update_range);
325  }
326 }
327 }
Definition: ControlWidgetDomains.hpp:154
Definition: ControlWidgetDomains.hpp:15
Definition: ControlWidgetDomains.hpp:120
Definition: ControlWidgetDomains.hpp:179