OSSIA
Open Scenario System for Interactive Application
dataspace_merge.hpp
1 #pragma once
3 #include <ossia/network/dataspace/value_with_unit.hpp>
6 
7 namespace ossia
8 {
9 template <typename T>
10 T convert(float f)
11 {
12  return f;
13 }
14 
15 namespace detail
16 {
17 
18 template <typename T>
19 struct is_array
20 {
21  static const constexpr bool value = value_trait<std::remove_const_t<T>>::is_array;
22 };
23 
24 template <typename T, typename U, typename = void>
25 struct whole_value_merger_helper;
26 
27 template <typename T>
28 using strong_value_impl_t = decltype(T::dataspace_value);
29 
30 template <typename T, typename U>
31 const constexpr bool both_iterable
32  = is_array<strong_value_impl_t<T>>::value&& is_array<U>::value&&
33  ossia::value_trait<U>::ossia_enum
35 template <typename T, typename U>
36 const constexpr bool first_iterable
37  = is_array<strong_value_impl_t<T>>::value && !is_array<U>::value;
38 template <typename T, typename U>
39 const constexpr bool second_iterable
40  = !is_array<strong_value_impl_t<T>>::value && is_array<U>::value
41  && ossia::value_trait<U>::ossia_enum != ossia::val_type::MAP;
42 template <typename T, typename U>
43 const constexpr bool neither_iterable
44  = !is_array<strong_value_impl_t<T>>::value && !is_array<U>::value;
45 
46 template <typename T, typename U>
47 using enable_if_both_iterable = std::enable_if_t<both_iterable<T, U>>;
48 template <typename T, typename U>
49 using enable_if_first_iterable = std::enable_if_t<first_iterable<T, U>>;
50 template <typename T, typename U>
51 using enable_if_second_iterable = std::enable_if_t<second_iterable<T, U>>;
52 template <typename T, typename U>
53 using enable_if_neither_iterable = std::enable_if_t<neither_iterable<T, U>>;
54 
55 // Case where both T and U are array types, e.g. RGB && List, or CMYK &&
56 // Vec2f...
57 template <typename T, typename U>
58 struct whole_value_merger_helper<T, U, enable_if_both_iterable<T, U>>
59 {
60  ossia::value_with_unit operator()(T value_unit, const U& value)
61  {
62  // copy the most possible values. T's value will be fixed at compile time.
63  const auto n = std::min(value_unit.dataspace_value.size(), value.size());
64  for(std::size_t i = 0; i < n; i++)
65  {
66  value_unit.dataspace_value[i] = ossia::convert<
67  std::remove_reference_t<decltype(value_unit.dataspace_value[i])>>(value[i]);
68  }
69  return value_unit;
70  }
71 };
72 
73 // Case "rgb" and "float" -> does not make sense, we return the input
74 template <typename T, typename U>
75 struct whole_value_merger_helper<T, U, enable_if_first_iterable<T, U>>
76 {
77  OSSIA_INLINE ossia::value_with_unit operator()(T value_unit, const U& value)
78  {
79  return value_unit;
80  }
81 };
82 
83 // Case "centimeter" and "list" -> does not make sense, we return the input
84 template <typename T, typename U>
85 struct whole_value_merger_helper<T, U, enable_if_second_iterable<T, U>>
86 {
87  OSSIA_INLINE ossia::value_with_unit operator()(T value_unit, const U& value)
88  {
89  return value_unit;
90  }
91 };
92 
93 // Case "centimeter" and "float"
94 template <typename T, typename U>
95 struct whole_value_merger_helper<T, U, enable_if_neither_iterable<T, U>>
96 {
97  OSSIA_INLINE ossia::value_with_unit operator()(T value_unit, const U& value)
98  {
99  value_unit.dataspace_value = value;
100  return value_unit;
101  }
102 };
103 
104 template <typename T, typename U, typename = void>
105 struct partial_value_merger_helper;
106 
107 // T and U are both array types, and we want to merge a single element of U
108 // into T.
109 // This is only valid for destination_index with one depth level : e.g. vu[i]
110 // == v[i]
111 // since all units only have one depth level.
112 template <typename T, typename U>
113 struct partial_value_merger_helper<T, U, enable_if_both_iterable<T, U>>
114 {
116  operator()(T value_unit, const U& value, const ossia::destination_index& idx)
117  {
118  auto i = idx[0];
119  if((int64_t)value_unit.dataspace_value.size() > i && (int64_t)value.size() > i)
120  {
121  value_unit.dataspace_value[i] = ossia::convert<
122  std::remove_reference_t<decltype(value_unit.dataspace_value[i])>>(value[i]);
123  }
124 
125  return value_unit;
126  }
127 
128  template <std::size_t N>
130  operator()(T value_unit, const U& value, const std::bitset<N>& idx)
131  {
132  if(handle_vec(value_unit.dataspace_value, value, idx))
133  return value_unit;
134  return {};
135  }
136 
137  template <std::size_t N>
138  bool handle_vec(
139  std::array<float, N>& src, const std::array<float, N>& incoming,
140  const std::bitset<N>& idx)
141  {
142  for(std::size_t i = 0; i < N; i++)
143  {
144  if(idx.test(i))
145  {
146  src[i] = incoming[i];
147  }
148  }
149  return true;
150  }
151 
152  template <typename... Args>
153  OSSIA_INLINE bool handle_vec(Args&&...)
154  {
155  return false;
156  }
157 };
158 
159 template <typename T, typename U>
160 struct partial_value_merger_helper<T, U, enable_if_first_iterable<T, U>>
161 {
163  operator()(T value_unit, const U& value, const ossia::destination_index& idx)
164  {
165  auto i = idx[0];
166  value_unit.dataspace_value[i] = ossia::convert<
167  std::remove_reference_t<decltype(value_unit.dataspace_value[i])>>(value);
168  return value_unit;
169  }
170 
171  template <std::size_t N>
172  OSSIA_INLINE ossia::value_with_unit
173  operator()(T value_unit, const U& value, const std::bitset<N>& idx)
174  {
175  return {};
176  }
177 };
178 
179 template <typename T, typename U>
180 struct partial_value_merger_helper<T, U, enable_if_second_iterable<T, U>>
181 {
182  OSSIA_INLINE ossia::value_with_unit
183  operator()(T value_unit, const U& value, const ossia::destination_index& idx)
184  {
185  return value_unit;
186  }
187 
188  template <std::size_t N>
189  OSSIA_INLINE ossia::value_with_unit
190  operator()(T value_unit, const U& value, const std::bitset<N>& idx)
191  {
192  return {};
193  }
194 };
195 
196 template <typename T, typename U>
197 struct partial_value_merger_helper<T, U, enable_if_neither_iterable<T, U>>
198 {
199  OSSIA_INLINE ossia::value_with_unit
200  operator()(T value_unit, const U& value, const ossia::destination_index& idx)
201  {
202  return value_unit;
203  }
204 
205  template <std::size_t N>
206  OSSIA_INLINE ossia::value_with_unit
207  operator()(T value_unit, const U& value, const std::bitset<N>& idx)
208  {
209  return {};
210  }
211 };
212 
213 struct value_merger
214 {
215  const ossia::destination_index& index;
216 
217  template <typename T, typename U>
218  ossia::value_with_unit operator()(const strong_value<T>& value_unit, const U& value)
219  {
220  auto n = index.size();
221  switch(n)
222  {
223  case 0:
224  return whole_value_merger_helper<strong_value<T>, U>{}(value_unit, value);
225  case 1:
226  // The index is where the value should go
227  return partial_value_merger_helper<strong_value<T>, U>{}(
228  value_unit, value, index);
229  default:
230  // Cannot merge anything
231  return value_unit;
232  }
233  }
234 
235  template <typename T>
236  OSSIA_INLINE ossia::value_with_unit
237  operator()(const strong_value<T>& value_unit, impulse value)
238  {
239  return value_unit;
240  }
241  template <typename T>
242  OSSIA_INLINE ossia::value_with_unit
243  operator()(const strong_value<T>& value_unit, const value_map_type& value)
244  {
245  return value_unit;
246  }
247  template <typename T>
248  OSSIA_INLINE ossia::value_with_unit
249  operator()(const strong_value<T>& value_unit, const std::string& value)
250  {
251  return value_unit;
252  }
253 };
254 
255 template <std::size_t N>
256 struct vec_value_merger
257 {
258  const std::bitset<N>& index;
259 
260  template <typename T, typename U>
261  OSSIA_INLINE ossia::value_with_unit
262  operator()(const strong_value<T>& value_unit, const U& value)
263  {
264  return {};
265  }
266 
267  template <typename T>
269  operator()(const strong_value<T>& value_unit, const std::array<float, N>& value)
270  {
271  if(index.all())
272  return whole_value_merger_helper<strong_value<T>, std::array<float, N>>{}(
273  value_unit, value);
274  else if(index.any())
275  return partial_value_merger_helper<strong_value<T>, std::array<float, N>>{}(
276  value_unit, value, index);
277  else
278  return value_unit;
279  }
280 };
281 }
282 }
Definition: git_info.h:7
@ MAP
std::vector<value>
bool is_array(const ossia::value &val)
is_numeric True if the value is of an array type (list, vec...)
Definition: value.cpp:631
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
ossia::small_vector< int32_t, 2 > destination_index
Definition: destination_index.hpp:40
Definition: value_with_unit.hpp:13