OSSIA
Open Scenario System for Interactive Application
Loading...
Searching...
No Matches
value_algorithms.hpp
1#pragma once
2#include <ossia/network/value/value.hpp>
3
4namespace ossia
5{
6// SourcePrecedence causes the merging of values
7// to occur only if the destination value is null
8// (it won't replace an existing value).
9
10template <bool SourcePrecedence = true>
11struct value_merger
12{
13 template <typename Value_T>
14 static void merge_value(ossia::value& dest, Value_T&& src)
15 {
16 if(!dest.valid())
17 {
18 dest = src;
19 return;
20 }
21 else
22 {
23 if(dest.valid() && src.valid())
24 {
25 switch(src.get_type())
26 {
28 auto& src_vec = src.template get<std::vector<ossia::value>>();
29 switch(dest.get_type())
30 {
32 merge_list(dest.get<std::vector<ossia::value>>(), src_vec);
33 break;
35 merge_list(dest.get<ossia::vec2f>(), src_vec);
36 break;
38 merge_list(dest.get<ossia::vec3f>(), src_vec);
39 break;
41 merge_list(dest.get<ossia::vec4f>(), src_vec);
42 break;
43 default:
44 break;
45 }
46 break;
47 }
49 auto& src_vec = src.template get<ossia::vec2f>();
50 switch(dest.get_type())
51 {
53 merge_list(dest.get<std::vector<ossia::value>>(), src_vec);
54 break;
56 merge_list(dest.get<ossia::vec2f>(), src_vec);
57 break;
59 merge_list(dest.get<ossia::vec3f>(), src_vec);
60 break;
62 merge_list(dest.get<ossia::vec4f>(), src_vec);
63 break;
64 default:
65 break;
66 }
67 break;
68 }
70 auto& src_vec = src.template get<ossia::vec3f>();
71 switch(dest.get_type())
72 {
74 merge_list(dest.get<std::vector<ossia::value>>(), src_vec);
75 break;
77 merge_list(dest.get<ossia::vec2f>(), src_vec);
78 break;
80 merge_list(dest.get<ossia::vec3f>(), src_vec);
81 break;
83 merge_list(dest.get<ossia::vec4f>(), src_vec);
84 break;
85 default:
86 break;
87 }
88 break;
89 }
91 auto& src_vec = src.template get<ossia::vec4f>();
92 switch(dest.get_type())
93 {
95 merge_list(dest.get<std::vector<ossia::value>>(), src_vec);
96 break;
98 merge_list(dest.get<ossia::vec2f>(), src_vec);
99 break;
101 merge_list(dest.get<ossia::vec3f>(), src_vec);
102 break;
104 merge_list(dest.get<ossia::vec4f>(), src_vec);
105 break;
106 default:
107 break;
108 }
109 break;
110 }
111 default: {
112 switch(dest.get_type())
113 {
115 set_first_value(
116 dest.get<std::vector<ossia::value>>(), std::forward<Value_T>(src));
117 break;
119 set_first_value(dest.get<ossia::vec2f>(), std::forward<Value_T>(src));
120 break;
122 set_first_value(dest.get<ossia::vec3f>(), std::forward<Value_T>(src));
123 break;
125 set_first_value(dest.get<ossia::vec4f>(), std::forward<Value_T>(src));
126 break;
127 default: {
128 // src overwrites dest
129 if(SourcePrecedence)
130 dest = std::forward<Value_T>(src);
131 return;
132 }
133 }
134 break;
135 }
136 }
137 return;
138 }
139 else
140 {
141 if(auto dest_list_ptr = dest.target<std::vector<ossia::value>>())
142 {
143 // Merge a single value in a list
144 set_first_value(*dest_list_ptr, std::forward<Value_T>(src));
145 return;
146 }
147 else if(auto src_list_ptr = src.template target<std::vector<ossia::value>>())
148 {
149 // If one of the two values is invalid, we always keep the other
150 if(src_list_ptr->empty())
151 {
152 std::vector<ossia::value> t{dest};
153 dest = std::move(t);
154 return;
155 }
156 else if(!(*src_list_ptr)[0].valid())
157 {
158 std::vector<ossia::value> t = *src_list_ptr;
159 t[0] = dest;
160 dest = std::move(t);
161 return;
162 }
163 else
164 {
165 // src overwrites dest
166 if(src.valid() && SourcePrecedence)
167 dest = std::forward<Value_T>(src);
168 return;
169 }
170 }
171 else
172 {
173 // src overwrites dest
174 if(src.valid() && SourcePrecedence)
175 dest = std::forward<Value_T>(src);
176 return;
177 }
178 }
179 }
180 }
181
182 template <typename Value_T>
183 static void insert_in_list(
184 std::vector<ossia::value>& t, Value_T&& v, const ossia::destination_index& idx)
185 {
186 std::vector<ossia::value>* cur_ptr = &t;
187 for(auto it = idx.begin(); it != idx.end();)
188 {
189 auto& cur = *cur_ptr;
190 std::size_t pos = *it;
191 if(cur.size() < pos + 1)
192 {
193 cur.resize(pos + 1);
194 }
195
196 if(++it == idx.end())
197 {
198 // We're at the deepest index position :
199 // we add the value at the current place.
200 merge_value(cur[pos], std::forward<Value_T>(v));
201 }
202 else
203 {
204 // We go through another depth layer.
205 if(auto sub_list = cur[pos].target<std::vector<ossia::value>>())
206 {
207 cur_ptr = sub_list;
208 }
209 else
210 {
211 // We put the current value at cur[pos] at index 0 of the
212 // newly-created sub-list.
213 std::vector<ossia::value> sub{std::move(cur[pos])};
214 cur[pos] = std::move(sub);
215
216 // And use it for the next iteration
217 cur_ptr = cur[pos].target<std::vector<ossia::value>>();
218 }
219 }
220 }
221 }
222
223 static void write_float(const ossia::value& val, float& f)
224 {
225 if(val.valid())
226 {
227 switch(val.get_type())
228 {
230 f = (float)val.template get<int32_t>();
231 break;
232 case ossia::val_type::FLOAT:
233 f = (float)val.template get<float>();
234 break;
236 f = (float)val.template get<bool>();
237 break;
238 default:
239 break;
240 }
241 }
242 }
243
244 template <std::size_t N, typename Value_T>
245 static void set_first_value(std::array<float, N>& t, Value_T&& val)
246 {
247 write_float(val, t[0]);
248 }
249
250 template <typename Value_T>
251 static void set_first_value(std::vector<ossia::value>& t, Value_T&& val)
252 {
253 if(t.empty())
254 {
255 t.push_back(std::forward<Value_T>(val));
256 }
257 else
258 {
259 merge_value(t[0], std::forward<Value_T>(val));
260 }
261 }
262
263 static void
264 merge_list(std::vector<ossia::value>& lhs, const std::vector<ossia::value>& rhs)
265 {
266 std::size_t n = rhs.size();
267 if(lhs.size() < n)
268 {
269 lhs.resize(n);
270 }
271
272 for(std::size_t i = 0u; i < n; i++)
273 {
274 merge_value(lhs[i], rhs[i]);
275 }
276 }
277 static void merge_list(std::vector<ossia::value>& lhs, std::vector<ossia::value>&& rhs)
278 {
279 std::size_t n = rhs.size();
280 if(lhs.size() < n)
281 {
282 lhs.resize(n);
283 }
284
285 for(std::size_t i = 0u; i < n; i++)
286 {
287 merge_value(lhs[i], std::move(rhs)[i]);
288 }
289 }
290
291 template <std::size_t N>
292 static void merge_list(std::vector<ossia::value>& lhs, const std::array<float, N>& rhs)
293 {
294 if(lhs.size() < N)
295 {
296 lhs.resize(N);
297 }
298
299 for(std::size_t i = 0u; i < N; i++)
300 {
301 lhs[i] = rhs[i];
302 }
303 }
304
305 template <std::size_t N>
306 static void merge_list(std::array<float, N>& lhs, const std::vector<ossia::value>& rhs)
307 {
308 const std::size_t n = std::min(N, rhs.size());
309 for(std::size_t i = 0u; i < n; i++)
310 {
311 write_float(rhs[i], lhs[i]);
312 }
313 }
314
315 template <std::size_t N, std::size_t M>
316 static void merge_list(std::array<float, N>& lhs, const std::array<float, M>& rhs)
317 {
318 const std::size_t n = std::min(N, M);
319 for(std::size_t i = 0u; i < n; i++)
320 {
321 lhs[i] = rhs[i];
322 }
323 }
324};
325
326namespace detail
327{
336{
337 const ossia::destination_index& index;
338 ossia::destination_index::const_iterator it;
339
340 ossia::value operator()(const std::vector<ossia::value>& t)
341 {
342 if(it == index.end())
343 {
344 return ossia::value{t};
345 }
346 else if((int64_t)t.size() > *it)
347 {
348 auto& val = t[*it];
349 ++it;
350 return val.apply(*this);
351 }
352 else
353 {
354 return {};
355 }
356 }
357
358 template <typename T>
359 ossia::value operator()(const T& t)
360 {
361 if(it == index.end())
362 {
363 return t;
364 }
365 else
366 {
367 return {};
368 }
369 }
370
371 template <std::size_t N>
372 ossia::value operator()(const std::array<float, N>& t)
373 {
374 if(it == index.end())
375 {
376 return t;
377 }
378 else if((int64_t)t.size() > *it)
379 {
380 if(it + 1 == index.end())
381 return float{t[*it]};
382 }
383
384 return {};
385 }
386
387 ossia::value operator()() { return {}; }
388};
389}
390}
The value class.
Definition value.hpp:173
Definition git_info.h:7
@ VEC3F
array<float, 2>
@ LIST
std::string
@ VEC4F
array<float, 3>
@ BOOL
ossia::impulse
ossia::small_vector< int32_t, 2 > destination_index
Definition destination_index.hpp:40
The destination_index_retriever struct Get the value associated with an index in a list....
Definition value_algorithms.hpp:336