Techt3o commited on
Commit
dd832c0
·
verified ·
1 Parent(s): e25ab6a

2c62cd0b0eb2c78fec26a20e2ee85f1e4f8dd6f649125667e3b449817773c6c1

Browse files
Files changed (50) hide show
  1. third-party/DPVO/Pangolin/components/pango_core/include/pangolin/utils/xml/rapidxml_print.hpp +421 -0
  2. third-party/DPVO/Pangolin/components/pango_core/include/pangolin/utils/xml/rapidxml_utils.hpp +122 -0
  3. third-party/DPVO/Pangolin/components/pango_core/include/sigslot/LICENCE +21 -0
  4. third-party/DPVO/Pangolin/components/pango_core/include/sigslot/README.md +717 -0
  5. third-party/DPVO/Pangolin/components/pango_core/include/sigslot/signal.hpp +1611 -0
  6. third-party/DPVO/Pangolin/components/pango_core/src/avx_math.cpp +553 -0
  7. third-party/DPVO/Pangolin/components/pango_core/src/dummy.cpp +0 -0
  8. third-party/DPVO/Pangolin/components/pango_core/src/factory/factory_help.cpp +145 -0
  9. third-party/DPVO/Pangolin/components/pango_core/src/factory/factory_registry.cpp +11 -0
  10. third-party/DPVO/Pangolin/components/pango_core/src/file_extension.cpp +247 -0
  11. third-party/DPVO/Pangolin/components/pango_core/src/file_utils.cpp +544 -0
  12. third-party/DPVO/Pangolin/components/pango_core/src/param_set.cpp +58 -0
  13. third-party/DPVO/Pangolin/components/pango_core/src/posix/condition_variable.cpp +89 -0
  14. third-party/DPVO/Pangolin/components/pango_core/src/posix/semaphore.cpp +83 -0
  15. third-party/DPVO/Pangolin/components/pango_core/src/posix/shared_memory_buffer.cpp +134 -0
  16. third-party/DPVO/Pangolin/components/pango_core/src/sigstate.cpp +60 -0
  17. third-party/DPVO/Pangolin/components/pango_core/src/threadedfilebuf.cpp +353 -0
  18. third-party/DPVO/Pangolin/components/pango_core/src/uri.cpp +105 -0
  19. third-party/DPVO/Pangolin/components/pango_core/tests/tests_uri.cpp +87 -0
  20. third-party/DPVO/Pangolin/components/pango_display/CMakeLists.txt +26 -0
  21. third-party/DPVO/Pangolin/components/pango_display/include/pangolin/console/ConsoleView.h +108 -0
  22. third-party/DPVO/Pangolin/components/pango_display/include/pangolin/console/InterpreterInterface.h +80 -0
  23. third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/attach.h +86 -0
  24. third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/default_font.h +7 -0
  25. third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/display.h +147 -0
  26. third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/display.hpp +47 -0
  27. third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/image_view.h +74 -0
  28. third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/process.h +59 -0
  29. third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/user_app.h +43 -0
  30. third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/view.h +231 -0
  31. third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/widgets.h +161 -0
  32. third-party/DPVO/Pangolin/components/pango_display/include/pangolin/handler/handler.h +139 -0
  33. third-party/DPVO/Pangolin/components/pango_display/include/pangolin/handler/handler_glbuffer.h +48 -0
  34. third-party/DPVO/Pangolin/components/pango_display/include/pangolin/handler/handler_image.h +166 -0
  35. third-party/DPVO/Pangolin/components/pango_display/src/ConsoleView.cpp +327 -0
  36. third-party/DPVO/Pangolin/components/pango_display/src/default_font.cpp +19 -0
  37. third-party/DPVO/Pangolin/components/pango_display/src/display.cpp +347 -0
  38. third-party/DPVO/Pangolin/components/pango_display/src/handler.cpp +472 -0
  39. third-party/DPVO/Pangolin/components/pango_display/src/handler_glbuffer.cpp +45 -0
  40. third-party/DPVO/Pangolin/components/pango_display/src/handler_image.cpp +526 -0
  41. third-party/DPVO/Pangolin/components/pango_display/src/image_view.cpp +227 -0
  42. third-party/DPVO/Pangolin/components/pango_display/src/pangolin_gl.cpp +94 -0
  43. third-party/DPVO/Pangolin/components/pango_display/src/pangolin_gl.h +102 -0
  44. third-party/DPVO/Pangolin/components/pango_display/src/process.cpp +161 -0
  45. third-party/DPVO/Pangolin/components/pango_display/src/view.cpp +508 -0
  46. third-party/DPVO/Pangolin/components/pango_display/src/widgets.cpp +787 -0
  47. third-party/DPVO/Pangolin/components/pango_geometry/CMakeLists.txt +21 -0
  48. third-party/DPVO/Pangolin/components/pango_geometry/include/pangolin/geometry/geometry.h +93 -0
  49. third-party/DPVO/Pangolin/components/pango_geometry/include/pangolin/geometry/geometry_obj.h +34 -0
  50. third-party/DPVO/Pangolin/components/pango_geometry/include/pangolin/geometry/geometry_ply.h +150 -0
third-party/DPVO/Pangolin/components/pango_core/include/pangolin/utils/xml/rapidxml_print.hpp ADDED
@@ -0,0 +1,421 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef RAPIDXML_PRINT_HPP_INCLUDED
2
+ #define RAPIDXML_PRINT_HPP_INCLUDED
3
+
4
+ // Copyright (C) 2006, 2009 Marcin Kalicinski
5
+ // Version 1.13
6
+ // Revision $DateTime: 2009/05/13 01:46:17 $
7
+ //! \file rapidxml_print.hpp This file contains rapidxml printer implementation
8
+
9
+ #include "rapidxml.hpp"
10
+
11
+ // Only include streams if not disabled
12
+ #ifndef RAPIDXML_NO_STREAMS
13
+ #include <ostream>
14
+ #include <iterator>
15
+ #endif
16
+
17
+ namespace rapidxml
18
+ {
19
+
20
+ ///////////////////////////////////////////////////////////////////////
21
+ // Printing flags
22
+
23
+ const int print_no_indenting = 0x1; //!< Printer flag instructing the printer to suppress indenting of XML. See print() function.
24
+
25
+ ///////////////////////////////////////////////////////////////////////
26
+ // Internal
27
+
28
+ //! \cond internal
29
+ namespace internal
30
+ {
31
+
32
+ ///////////////////////////////////////////////////////////////////////////
33
+ // Internal character operations
34
+
35
+ // Copy characters from given range to given output iterator
36
+ template<class OutIt, class Ch>
37
+ inline OutIt copy_chars(const Ch *begin, const Ch *end, OutIt out)
38
+ {
39
+ while (begin != end)
40
+ *out++ = *begin++;
41
+ return out;
42
+ }
43
+
44
+ // Copy characters from given range to given output iterator and expand
45
+ // characters into references (&lt; &gt; &apos; &quot; &amp;)
46
+ template<class OutIt, class Ch>
47
+ inline OutIt copy_and_expand_chars(const Ch *begin, const Ch *end, Ch noexpand, OutIt out)
48
+ {
49
+ while (begin != end)
50
+ {
51
+ if (*begin == noexpand)
52
+ {
53
+ *out++ = *begin; // No expansion, copy character
54
+ }
55
+ else
56
+ {
57
+ switch (*begin)
58
+ {
59
+ case Ch('<'):
60
+ *out++ = Ch('&'); *out++ = Ch('l'); *out++ = Ch('t'); *out++ = Ch(';');
61
+ break;
62
+ case Ch('>'):
63
+ *out++ = Ch('&'); *out++ = Ch('g'); *out++ = Ch('t'); *out++ = Ch(';');
64
+ break;
65
+ case Ch('\''):
66
+ *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('p'); *out++ = Ch('o'); *out++ = Ch('s'); *out++ = Ch(';');
67
+ break;
68
+ case Ch('"'):
69
+ *out++ = Ch('&'); *out++ = Ch('q'); *out++ = Ch('u'); *out++ = Ch('o'); *out++ = Ch('t'); *out++ = Ch(';');
70
+ break;
71
+ case Ch('&'):
72
+ *out++ = Ch('&'); *out++ = Ch('a'); *out++ = Ch('m'); *out++ = Ch('p'); *out++ = Ch(';');
73
+ break;
74
+ default:
75
+ *out++ = *begin; // No expansion, copy character
76
+ }
77
+ }
78
+ ++begin; // Step to next character
79
+ }
80
+ return out;
81
+ }
82
+
83
+ // Fill given output iterator with repetitions of the same character
84
+ template<class OutIt, class Ch>
85
+ inline OutIt fill_chars(OutIt out, int n, Ch ch)
86
+ {
87
+ for (int i = 0; i < n; ++i)
88
+ *out++ = ch;
89
+ return out;
90
+ }
91
+
92
+ // Find character
93
+ template<class Ch, Ch ch>
94
+ inline bool find_char(const Ch *begin, const Ch *end)
95
+ {
96
+ while (begin != end)
97
+ if (*begin++ == ch)
98
+ return true;
99
+ return false;
100
+ }
101
+
102
+ ///////////////////////////////////////////////////////////////////////////
103
+ // Internal printing operations
104
+
105
+ // Print node
106
+ template<class OutIt, class Ch>
107
+ inline OutIt print_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
108
+ {
109
+ // Print proper node type
110
+ switch (node->type())
111
+ {
112
+
113
+ // Document
114
+ case node_document:
115
+ out = print_children(out, node, flags, indent);
116
+ break;
117
+
118
+ // Element
119
+ case node_element:
120
+ out = print_element_node(out, node, flags, indent);
121
+ break;
122
+
123
+ // Data
124
+ case node_data:
125
+ out = print_data_node(out, node, flags, indent);
126
+ break;
127
+
128
+ // CDATA
129
+ case node_cdata:
130
+ out = print_cdata_node(out, node, flags, indent);
131
+ break;
132
+
133
+ // Declaration
134
+ case node_declaration:
135
+ out = print_declaration_node(out, node, flags, indent);
136
+ break;
137
+
138
+ // Comment
139
+ case node_comment:
140
+ out = print_comment_node(out, node, flags, indent);
141
+ break;
142
+
143
+ // Doctype
144
+ case node_doctype:
145
+ out = print_doctype_node(out, node, flags, indent);
146
+ break;
147
+
148
+ // Pi
149
+ case node_pi:
150
+ out = print_pi_node(out, node, flags, indent);
151
+ break;
152
+
153
+ // Unknown
154
+ default:
155
+ assert(0);
156
+ break;
157
+ }
158
+
159
+ // If indenting not disabled, add line break after node
160
+ if (!(flags & print_no_indenting))
161
+ *out = Ch('\n'), ++out;
162
+
163
+ // Return modified iterator
164
+ return out;
165
+ }
166
+
167
+ // Print children of the node
168
+ template<class OutIt, class Ch>
169
+ inline OutIt print_children(OutIt out, const xml_node<Ch> *node, int flags, int indent)
170
+ {
171
+ for (xml_node<Ch> *child = node->first_node(); child; child = child->next_sibling())
172
+ out = print_node(out, child, flags, indent);
173
+ return out;
174
+ }
175
+
176
+ // Print attributes of the node
177
+ template<class OutIt, class Ch>
178
+ inline OutIt print_attributes(OutIt out, const xml_node<Ch> *node, int flags)
179
+ {
180
+ for (xml_attribute<Ch> *attribute = node->first_attribute(); attribute; attribute = attribute->next_attribute())
181
+ {
182
+ if (attribute->name() && attribute->value())
183
+ {
184
+ // Print attribute name
185
+ *out = Ch(' '), ++out;
186
+ out = copy_chars(attribute->name(), attribute->name() + attribute->name_size(), out);
187
+ *out = Ch('='), ++out;
188
+ // Print attribute value using appropriate quote type
189
+ if (find_char<Ch, Ch('"')>(attribute->value(), attribute->value() + attribute->value_size()))
190
+ {
191
+ *out = Ch('\''), ++out;
192
+ out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('"'), out);
193
+ *out = Ch('\''), ++out;
194
+ }
195
+ else
196
+ {
197
+ *out = Ch('"'), ++out;
198
+ out = copy_and_expand_chars(attribute->value(), attribute->value() + attribute->value_size(), Ch('\''), out);
199
+ *out = Ch('"'), ++out;
200
+ }
201
+ }
202
+ }
203
+ return out;
204
+ }
205
+
206
+ // Print data node
207
+ template<class OutIt, class Ch>
208
+ inline OutIt print_data_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
209
+ {
210
+ assert(node->type() == node_data);
211
+ if (!(flags & print_no_indenting))
212
+ out = fill_chars(out, indent, Ch('\t'));
213
+ out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
214
+ return out;
215
+ }
216
+
217
+ // Print data node
218
+ template<class OutIt, class Ch>
219
+ inline OutIt print_cdata_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
220
+ {
221
+ assert(node->type() == node_cdata);
222
+ if (!(flags & print_no_indenting))
223
+ out = fill_chars(out, indent, Ch('\t'));
224
+ *out = Ch('<'); ++out;
225
+ *out = Ch('!'); ++out;
226
+ *out = Ch('['); ++out;
227
+ *out = Ch('C'); ++out;
228
+ *out = Ch('D'); ++out;
229
+ *out = Ch('A'); ++out;
230
+ *out = Ch('T'); ++out;
231
+ *out = Ch('A'); ++out;
232
+ *out = Ch('['); ++out;
233
+ out = copy_chars(node->value(), node->value() + node->value_size(), out);
234
+ *out = Ch(']'); ++out;
235
+ *out = Ch(']'); ++out;
236
+ *out = Ch('>'); ++out;
237
+ return out;
238
+ }
239
+
240
+ // Print element node
241
+ template<class OutIt, class Ch>
242
+ inline OutIt print_element_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
243
+ {
244
+ assert(node->type() == node_element);
245
+
246
+ // Print element name and attributes, if any
247
+ if (!(flags & print_no_indenting))
248
+ out = fill_chars(out, indent, Ch('\t'));
249
+ *out = Ch('<'), ++out;
250
+ out = copy_chars(node->name(), node->name() + node->name_size(), out);
251
+ out = print_attributes(out, node, flags);
252
+
253
+ // If node is childless
254
+ if (node->value_size() == 0 && !node->first_node())
255
+ {
256
+ // Print childless node tag ending
257
+ *out = Ch('/'), ++out;
258
+ *out = Ch('>'), ++out;
259
+ }
260
+ else
261
+ {
262
+ // Print normal node tag ending
263
+ *out = Ch('>'), ++out;
264
+
265
+ // Test if node contains a single data node only (and no other nodes)
266
+ xml_node<Ch> *child = node->first_node();
267
+ if (!child)
268
+ {
269
+ // If node has no children, only print its value without indenting
270
+ out = copy_and_expand_chars(node->value(), node->value() + node->value_size(), Ch(0), out);
271
+ }
272
+ else if (child->next_sibling() == 0 && child->type() == node_data)
273
+ {
274
+ // If node has a sole data child, only print its value without indenting
275
+ out = copy_and_expand_chars(child->value(), child->value() + child->value_size(), Ch(0), out);
276
+ }
277
+ else
278
+ {
279
+ // Print all children with full indenting
280
+ if (!(flags & print_no_indenting))
281
+ *out = Ch('\n'), ++out;
282
+ out = print_children(out, node, flags, indent + 1);
283
+ if (!(flags & print_no_indenting))
284
+ out = fill_chars(out, indent, Ch('\t'));
285
+ }
286
+
287
+ // Print node end
288
+ *out = Ch('<'), ++out;
289
+ *out = Ch('/'), ++out;
290
+ out = copy_chars(node->name(), node->name() + node->name_size(), out);
291
+ *out = Ch('>'), ++out;
292
+ }
293
+ return out;
294
+ }
295
+
296
+ // Print declaration node
297
+ template<class OutIt, class Ch>
298
+ inline OutIt print_declaration_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
299
+ {
300
+ // Print declaration start
301
+ if (!(flags & print_no_indenting))
302
+ out = fill_chars(out, indent, Ch('\t'));
303
+ *out = Ch('<'), ++out;
304
+ *out = Ch('?'), ++out;
305
+ *out = Ch('x'), ++out;
306
+ *out = Ch('m'), ++out;
307
+ *out = Ch('l'), ++out;
308
+
309
+ // Print attributes
310
+ out = print_attributes(out, node, flags);
311
+
312
+ // Print declaration end
313
+ *out = Ch('?'), ++out;
314
+ *out = Ch('>'), ++out;
315
+
316
+ return out;
317
+ }
318
+
319
+ // Print comment node
320
+ template<class OutIt, class Ch>
321
+ inline OutIt print_comment_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
322
+ {
323
+ assert(node->type() == node_comment);
324
+ if (!(flags & print_no_indenting))
325
+ out = fill_chars(out, indent, Ch('\t'));
326
+ *out = Ch('<'), ++out;
327
+ *out = Ch('!'), ++out;
328
+ *out = Ch('-'), ++out;
329
+ *out = Ch('-'), ++out;
330
+ out = copy_chars(node->value(), node->value() + node->value_size(), out);
331
+ *out = Ch('-'), ++out;
332
+ *out = Ch('-'), ++out;
333
+ *out = Ch('>'), ++out;
334
+ return out;
335
+ }
336
+
337
+ // Print doctype node
338
+ template<class OutIt, class Ch>
339
+ inline OutIt print_doctype_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
340
+ {
341
+ assert(node->type() == node_doctype);
342
+ if (!(flags & print_no_indenting))
343
+ out = fill_chars(out, indent, Ch('\t'));
344
+ *out = Ch('<'), ++out;
345
+ *out = Ch('!'), ++out;
346
+ *out = Ch('D'), ++out;
347
+ *out = Ch('O'), ++out;
348
+ *out = Ch('C'), ++out;
349
+ *out = Ch('T'), ++out;
350
+ *out = Ch('Y'), ++out;
351
+ *out = Ch('P'), ++out;
352
+ *out = Ch('E'), ++out;
353
+ *out = Ch(' '), ++out;
354
+ out = copy_chars(node->value(), node->value() + node->value_size(), out);
355
+ *out = Ch('>'), ++out;
356
+ return out;
357
+ }
358
+
359
+ // Print pi node
360
+ template<class OutIt, class Ch>
361
+ inline OutIt print_pi_node(OutIt out, const xml_node<Ch> *node, int flags, int indent)
362
+ {
363
+ assert(node->type() == node_pi);
364
+ if (!(flags & print_no_indenting))
365
+ out = fill_chars(out, indent, Ch('\t'));
366
+ *out = Ch('<'), ++out;
367
+ *out = Ch('?'), ++out;
368
+ out = copy_chars(node->name(), node->name() + node->name_size(), out);
369
+ *out = Ch(' '), ++out;
370
+ out = copy_chars(node->value(), node->value() + node->value_size(), out);
371
+ *out = Ch('?'), ++out;
372
+ *out = Ch('>'), ++out;
373
+ return out;
374
+ }
375
+
376
+ }
377
+ //! \endcond
378
+
379
+ ///////////////////////////////////////////////////////////////////////////
380
+ // Printing
381
+
382
+ //! Prints XML to given output iterator.
383
+ //! \param out Output iterator to print to.
384
+ //! \param node Node to be printed. Pass xml_document to print entire document.
385
+ //! \param flags Flags controlling how XML is printed.
386
+ //! \return Output iterator pointing to position immediately after last character of printed text.
387
+ template<class OutIt, class Ch>
388
+ inline OutIt print(OutIt out, const xml_node<Ch> &node, int flags = 0)
389
+ {
390
+ return internal::print_node(out, &node, flags, 0);
391
+ }
392
+
393
+ #ifndef RAPIDXML_NO_STREAMS
394
+
395
+ //! Prints XML to given output stream.
396
+ //! \param out Output stream to print to.
397
+ //! \param node Node to be printed. Pass xml_document to print entire document.
398
+ //! \param flags Flags controlling how XML is printed.
399
+ //! \return Output stream.
400
+ template<class Ch>
401
+ inline std::basic_ostream<Ch> &print(std::basic_ostream<Ch> &out, const xml_node<Ch> &node, int flags = 0)
402
+ {
403
+ print(std::ostream_iterator<Ch>(out), node, flags);
404
+ return out;
405
+ }
406
+
407
+ //! Prints formatted XML to given output stream. Uses default printing flags. Use print() function to customize printing process.
408
+ //! \param out Output stream to print to.
409
+ //! \param node Node to be printed.
410
+ //! \return Output stream.
411
+ template<class Ch>
412
+ inline std::basic_ostream<Ch> &operator <<(std::basic_ostream<Ch> &out, const xml_node<Ch> &node)
413
+ {
414
+ return print(out, node);
415
+ }
416
+
417
+ #endif
418
+
419
+ }
420
+
421
+ #endif
third-party/DPVO/Pangolin/components/pango_core/include/pangolin/utils/xml/rapidxml_utils.hpp ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #ifndef RAPIDXML_UTILS_HPP_INCLUDED
2
+ #define RAPIDXML_UTILS_HPP_INCLUDED
3
+
4
+ // Copyright (C) 2006, 2009 Marcin Kalicinski
5
+ // Version 1.13
6
+ // Revision $DateTime: 2009/05/13 01:46:17 $
7
+ //! \file rapidxml_utils.hpp This file contains high-level rapidxml utilities that can be useful
8
+ //! in certain simple scenarios. They should probably not be used if maximizing performance is the main objective.
9
+
10
+ #include "rapidxml.hpp"
11
+ #include <vector>
12
+ #include <string>
13
+ #include <fstream>
14
+ #include <stdexcept>
15
+
16
+ namespace rapidxml
17
+ {
18
+
19
+ //! Represents data loaded from a file
20
+ template<class Ch = char>
21
+ class file
22
+ {
23
+
24
+ public:
25
+
26
+ //! Loads file into the memory. Data will be automatically destroyed by the destructor.
27
+ //! \param filename Filename to load.
28
+ file(const char *filename)
29
+ {
30
+ using namespace std;
31
+
32
+ // Open stream
33
+ basic_ifstream<Ch> stream(filename, ios::binary);
34
+ if (!stream)
35
+ throw runtime_error(string("cannot open file ") + filename);
36
+ stream.unsetf(ios::skipws);
37
+
38
+ // Determine stream size
39
+ stream.seekg(0, ios::end);
40
+ size_t size = (size_t)stream.tellg();
41
+ stream.seekg(0);
42
+
43
+ // Load data and add terminating 0
44
+ m_data.resize(size + 1);
45
+ stream.read(&m_data.front(), static_cast<streamsize>(size));
46
+ m_data[size] = 0;
47
+ }
48
+
49
+ //! Loads file into the memory. Data will be automatically destroyed by the destructor
50
+ //! \param stream Stream to load from
51
+ file(std::basic_istream<Ch> &stream)
52
+ {
53
+ using namespace std;
54
+
55
+ // Load data and add terminating 0
56
+ stream.unsetf(ios::skipws);
57
+ m_data.assign(istreambuf_iterator<Ch>(stream), istreambuf_iterator<Ch>());
58
+ if (stream.fail() || stream.bad())
59
+ throw runtime_error("error reading stream");
60
+ m_data.push_back(0);
61
+ }
62
+
63
+ //! Gets file data.
64
+ //! \return Pointer to data of file.
65
+ Ch *data()
66
+ {
67
+ return &m_data.front();
68
+ }
69
+
70
+ //! Gets file data.
71
+ //! \return Pointer to data of file.
72
+ const Ch *data() const
73
+ {
74
+ return &m_data.front();
75
+ }
76
+
77
+ //! Gets file data size.
78
+ //! \return Size of file data, in characters.
79
+ std::size_t size() const
80
+ {
81
+ return m_data.size();
82
+ }
83
+
84
+ private:
85
+
86
+ std::vector<Ch> m_data; // File data
87
+
88
+ };
89
+
90
+ //! Counts children of node. Time complexity is O(n).
91
+ //! \return Number of children of node
92
+ template<class Ch>
93
+ inline std::size_t count_children(xml_node<Ch> *node)
94
+ {
95
+ xml_node<Ch> *child = node->first_node();
96
+ std::size_t count = 0;
97
+ while (child)
98
+ {
99
+ ++count;
100
+ child = child->next_sibling();
101
+ }
102
+ return count;
103
+ }
104
+
105
+ //! Counts attributes of node. Time complexity is O(n).
106
+ //! \return Number of attributes of node
107
+ template<class Ch>
108
+ inline std::size_t count_attributes(xml_node<Ch> *node)
109
+ {
110
+ xml_attribute<Ch> *attr = node->first_attribute();
111
+ std::size_t count = 0;
112
+ while (attr)
113
+ {
114
+ ++count;
115
+ attr = attr->next_attribute();
116
+ }
117
+ return count;
118
+ }
119
+
120
+ }
121
+
122
+ #endif
third-party/DPVO/Pangolin/components/pango_core/include/sigslot/LICENCE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2017 Pierre-Antoine Lacaze
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
third-party/DPVO/Pangolin/components/pango_core/include/sigslot/README.md ADDED
@@ -0,0 +1,717 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Sigslot, a signal-slot library
2
+
3
+ Sigslot is a header-only, thread safe implementation of signal-slots for C++.
4
+
5
+ ## Features
6
+
7
+ The main goal was to replace Boost.Signals2.
8
+
9
+ Apart from the usual features, it offers
10
+
11
+ - Thread safety,
12
+ - Object lifetime tracking for automatic slot disconnection (extensible through ADL),
13
+ - RAII connection management,
14
+ - Slot groups to enforce slots execution order,
15
+ - Reasonable performance. and a simple and straightforward implementation.
16
+
17
+ Sigslot is unit-tested and should be reliable and stable enough to replace Boost Signals2.
18
+
19
+ The tests run cleanly under the address, thread and undefined behaviour sanitizers.
20
+
21
+ Many implementations allow signal return types, Sigslot does not because I have
22
+ no use for them. If I can be convinced of otherwise I may change my mind later on.
23
+
24
+ ## Installation
25
+
26
+ No compilation or installation is required, just include `sigslot/signal.hpp`
27
+ and use it. Sigslot currently depends on a C++14 compliant compiler, but if need
28
+ arises it may be retrofitted to C++11. It is known to work with Clang 4.0 and GCC
29
+ 5.0+ compilers on GNU Linux, MSVC 2017 and up, Clang-cl and MinGW on Windows.
30
+
31
+ However, be aware of a potential gotcha on Windows with MSVC and Clang-Cl compilers,
32
+ which may need the `/OPT:NOICF` linker flags in exceptional situations. Read The
33
+ Implementation Details chapter for an explanation.
34
+
35
+ A CMake list file is supplied for installation purpose and generating a CMake import
36
+ module. This is the preferred installation method. The `Pal::Sigslot` imported target
37
+ is available and already applies the needed linker flags. It is also required for
38
+ examples and tests, which optionally depend on Qt5 and Boost for adapters unit tests.
39
+
40
+ ```cmake
41
+ # Using Sigslot from cmake
42
+ find_package(PalSigslot)
43
+
44
+ add_executable(MyExe main.cpp)
45
+ target_link_libraries(MyExe PRIVATE Pal::Sigslot)
46
+ ```
47
+
48
+ A configuration option `SIGSLOT_REDUCE_COMPILE_TIME` is available at configuration
49
+ time. When activated, it attempts to reduce code bloat by avoiding heavy template
50
+ instantiations resulting from calls to `std::make_shared`.
51
+ This option is off by default, but can be activated for those who wish to favor
52
+ code size and compilation time at the expanse of slightly less efficient code.
53
+
54
+ Installation may be done using the following instructions from the root directory:
55
+
56
+ ```sh
57
+ mkdir build && cd build
58
+ cmake .. -DSIGSLOT_REDUCE_COMPILE_TIME=ON -DCMAKE_INSTALL_PREFIX=~/local
59
+ cmake --build . --target install
60
+
61
+ # If you want to compile examples:
62
+ cmake --build . --target sigslot-examples
63
+
64
+ # And compile/execute unit tests:
65
+ cmake --build . --target sigslot-tests
66
+ ```
67
+
68
+ ### CMake FetchContent
69
+
70
+ `Pal::Sigslot` can also be integrated using the [FetchContent](https://cmake.org/cmake/help/latest/module/FetchContent.html) method.
71
+
72
+ ```cmake
73
+ include(FetchContent)
74
+
75
+ FetchContent_Declare(
76
+ sigslot
77
+ GIT_REPOSITORY https://github.com/palacaze/sigslot
78
+ GIT_TAG 19a6f0f5ea11fc121fe67f81fd5e491f2d7a4637 # v1.2.0
79
+ )
80
+ FetchContent_MakeAvailable(sigslot)
81
+
82
+ add_executable(MyExe main.cpp)
83
+ target_link_libraries(MyExe PRIVATE Pal::Sigslot)
84
+ ```
85
+
86
+ ## Documentation
87
+
88
+ Sigslot implements the signal-slot construct popular in UI frameworks, making it
89
+ easy to use the observer pattern or event-based programming. The main entry point
90
+ of the library is the `sigslot::signal<T...>` class template.
91
+
92
+ A signal is an object that can emit typed notifications, really values parametrized
93
+ after the signal class template parameters, and register any number of notification
94
+ handlers (callables) of compatible argument types to be executed with the values
95
+ supplied whenever a signal emission happens. In signal-slot parlance this is called
96
+ connecting a slot to a signal, where a "slot" represents a callable instance and
97
+ a "connection" can be thought of as a conceptual link from signal to slot.
98
+
99
+ All the snippets presented below are available in compilable source code form in
100
+ the example subdirectory.
101
+
102
+ ### Basic usage
103
+
104
+ Here is a first example that showcases the most basic features of the library.
105
+
106
+ We first declare a parameter-free signal `sig`, then we proceed to connect several
107
+ slots and at last emit a signal which triggers the invocation of every slot callable
108
+ connected beforehand. Notice how The library handles diverse forms of callables.
109
+
110
+ ```cpp
111
+ #include <sigslot/signal.hpp>
112
+ #include <iostream>
113
+
114
+ void f() { std::cout << "free function\n"; }
115
+
116
+ struct s {
117
+ void m() { std::cout << "member function\n"; }
118
+ static void sm() { std::cout << "static member function\n"; }
119
+ };
120
+
121
+ struct o {
122
+ void operator()() { std::cout << "function object\n"; }
123
+ };
124
+
125
+ int main() {
126
+ s d;
127
+ auto lambda = []() { std::cout << "lambda\n"; };
128
+ auto gen_lambda = [](auto && ...a) { std::cout << "generic lambda\n"; };
129
+
130
+ // declare a signal instance with no arguments
131
+ sigslot::signal<> sig;
132
+
133
+ // connect slots
134
+ sig.connect(f);
135
+ sig.connect(&s::m, &d);
136
+ sig.connect(&s::sm);
137
+ sig.connect(o());
138
+ sig.connect(lambda);
139
+ sig.connect(gen_lambda);
140
+
141
+ // emit a signal
142
+ sig();
143
+ }
144
+ ```
145
+
146
+ By default, the slot invocation order when emitting a signal is unspecified, please
147
+ do not rely on it being always the same. You may constrain a particular invocation
148
+ order by using slot groups, which are presented later on.
149
+
150
+ ### Signal with arguments
151
+
152
+ That first example was simple but not so useful, let us move on to a signal that
153
+ emits values instead. A signal can emit any number of arguments, below.
154
+
155
+ ```cpp
156
+ #include <sigslot/signal.hpp>
157
+ #include <iostream>
158
+ #include <string>
159
+
160
+ struct foo {
161
+ // Notice how we accept a double as first argument here.
162
+ // This is fine because float is convertible to double.
163
+ // 's' is a reference and can thus be modified.
164
+ void bar(double d, int i, bool b, std::string &s) {
165
+ s = b ? std::to_string(i) : std::to_string(d);
166
+ }
167
+ };
168
+
169
+ // Function objects can cope with default arguments and overloading.
170
+ // It does not work with static and member functions.
171
+ struct obj {
172
+ void operator()(float, int, bool, std::string &, int = 0) {
173
+ std::cout << "I was here\n";
174
+ }
175
+
176
+ void operator()() {}
177
+ };
178
+
179
+ int main() {
180
+ // declare a signal with float, int, bool and string& arguments
181
+ sigslot::signal<float, int, bool, std::string&> sig;
182
+
183
+ // a generic lambda that prints its arguments to stdout
184
+ auto printer = [] (auto a, auto && ...args) {
185
+ std::cout << a;
186
+ (void)std::initializer_list<int>{
187
+ ((void)(std::cout << " " << args), 1)...
188
+ };
189
+ std::cout << "\n";
190
+ };
191
+
192
+ // connect the slots
193
+ foo ff;
194
+ sig.connect(printer);
195
+ sig.connect(&foo::bar, &ff);
196
+ sig.connect(obj());
197
+
198
+ float f = 1.f;
199
+ short i = 2; // convertible to int
200
+ std::string s = "0";
201
+
202
+ // emit a signal
203
+ sig(f, i, false, s);
204
+ sig(f, i, true, s);
205
+ }
206
+ ```
207
+
208
+ As shown, slots arguments types don't need to be strictly identical to the signal
209
+ template parameters, being convertible-from is fine. Generic arguments are fine too,
210
+ as shown with the `printer` generic lambda (which could have been written as a
211
+ function template too).
212
+
213
+ Right now there are two limitations that I can think of with respect to callable
214
+ handling: default arguments and function overloading. Both are working correctly
215
+ in the case of function objects but will fail to compile with static and member
216
+ functions, for different but related reasons.
217
+
218
+ #### Coping with overloaded functions
219
+
220
+ Consider the following piece of code:
221
+
222
+ ```cpp
223
+ struct foo {
224
+ void bar(double d);
225
+ void bar();
226
+ };
227
+ ```
228
+
229
+ What should `&foo::bar` refer to? As per overloading, this pointer over member
230
+ function does not map to a unique symbol, so the compiler won't be able to pick
231
+ the right symbol. One way of resolving the right symbol is to explicitly cast the
232
+ function pointer to the right function type. Here is an example that does just that
233
+ using a little helper tool for a lighter syntax (In fact I will probably add this
234
+ to the library soon).
235
+
236
+ ```cpp
237
+ #include <sigslot/signal.hpp>
238
+
239
+ template <typename... Args, typename C>
240
+ constexpr auto overload(void (C::*ptr)(Args...)) {
241
+ return ptr;
242
+ }
243
+
244
+ template <typename... Args>
245
+ constexpr auto overload(void (*ptr)(Args...)) {
246
+ return ptr;
247
+ }
248
+
249
+ struct obj {
250
+ void operator()(int) const {}
251
+ void operator()() {}
252
+ };
253
+
254
+ struct foo {
255
+ void bar(int) {}
256
+ void bar() {}
257
+
258
+ static void baz(int) {}
259
+ static void baz() {}
260
+ };
261
+
262
+ void moo(int) {}
263
+ void moo() {}
264
+
265
+ int main() {
266
+ sigslot::signal<int> sig;
267
+
268
+ // connect the slots, casting to the right overload if necessary
269
+ foo ff;
270
+ sig.connect(overload<int>(&foo::bar), &ff);
271
+ sig.connect(overload<int>(&foo::baz));
272
+ sig.connect(overload<int>(&moo));
273
+ sig.connect(obj());
274
+
275
+ sig(0);
276
+
277
+ return 0;
278
+ }
279
+ ```
280
+
281
+ #### Coping with function with default arguments
282
+
283
+ Default arguments are not part of the function type signature, and can be redefined,
284
+ so they are really difficult to deal with. When connecting a slot to a signal, the
285
+ library determines if the supplied callable can be invoked with the signal argument
286
+ types, but at this point the existence of default function arguments is unknown
287
+ so there might be a mismatch in the number of arguments.
288
+
289
+ A simple work around for this use case would is to create a bind adapter, in fact
290
+ we can even make it quite generic like so:
291
+
292
+ ```cpp
293
+ #include <sigslot/signal.hpp>
294
+
295
+ #define ADAPT(func) \
296
+ [=](auto && ...a) { (func)(std::forward<decltype(a)>(a)...); }
297
+
298
+ void foo(int &i, int b = 1) {
299
+ i += b;
300
+ }
301
+
302
+ int main() {
303
+ int i = 0;
304
+
305
+ // fine, all the arguments are handled
306
+ sigslot::signal<int&, int> sig1;
307
+ sig1.connect(foo);
308
+ sig1(i, 2);
309
+
310
+ // must wrap in an adapter
311
+ i = 0;
312
+ sigslot::signal<int&> sig2;
313
+ sig2.connect(ADAPT(foo));
314
+ sig2(i);
315
+
316
+ return 0;
317
+ }
318
+ ```
319
+
320
+ ### Connection management
321
+
322
+ #### Connection object
323
+
324
+ What was not made apparent until now is that `signal::connect()` actually returns
325
+ a `sigslot::connection` object that may be used to manage the behaviour and lifetime
326
+ of a signal-slot connection. `sigslot::connection` is a lightweight object (basically
327
+ a `std::weak_ptr`) that allows interaction with an ongoing signal-slot connection
328
+ and exposes the following features:
329
+
330
+ - Status querying, that is testing whether a connection is valid, ongoing or facing destruction,
331
+ - Connection (un)blocking, which allows to temporarily disable the invocation of a slot when a signal is emitted,
332
+ - Disconnection of a slot, the destruction of a connection previously created via `signal::connect()`.
333
+
334
+ A `sigslot::connection` does not tie a connection to a scope: this is not a RAII
335
+ object, which explains why it can be copied. It can be however implicitly converted
336
+ into a `sigslot::scoped_connection` which destroys the connection when going out
337
+ of scope.
338
+
339
+ Here is an example illustrating some of those features:
340
+
341
+ ```cpp
342
+ #include <sigslot/signal.hpp>
343
+ #include <string>
344
+
345
+ int i = 0;
346
+
347
+ void f() { i += 1; }
348
+
349
+ int main() {
350
+ sigslot::signal<> sig;
351
+
352
+ // keep a sigslot::connection object
353
+ auto c1 = sig.connect(f);
354
+
355
+ // disconnection
356
+ sig(); // i == 1
357
+ c1.disconnect();
358
+ sig(); // i == 1
359
+
360
+ // scope based disconnection
361
+ {
362
+ sigslot::scoped_connection sc = sig.connect(f);
363
+ sig(); // i == 2
364
+ }
365
+
366
+ sig(); // i == 2;
367
+
368
+
369
+ // connection blocking
370
+ auto c2 = sig.connect(f);
371
+ sig(); // i == 3
372
+ c2.block();
373
+ sig(); // i == 3
374
+ c2.unblock();
375
+ sig(); // i == 4
376
+ }
377
+ ```
378
+
379
+ #### Extended connection signature
380
+
381
+ Sigslot supports an extended slot signature with an additional `sigslot::connection`
382
+ reference as first argument, which permits connection management from inside the
383
+ slot. This extended signature is accessible using the `connect_extended()` method.
384
+
385
+ ```cpp
386
+ #include <sigslot/signal.hpp>
387
+
388
+ int main() {
389
+ int i = 0;
390
+ sigslot::signal<> sig;
391
+
392
+ // extended connection
393
+ auto f = [](auto &con) {
394
+ i += 1; // do work
395
+ con.disconnect(); // then disconnects
396
+ };
397
+
398
+ sig.connect_extended(f);
399
+ sig(); // i == 1
400
+ sig(); // i == 1 because f was disconnected
401
+ }
402
+ ```
403
+
404
+ #### Automatic slot lifetime tracking
405
+
406
+ The user must make sure that the lifetime of a slot exceeds the one of a signal,
407
+ which may get tedious in complex software. To simplify this task, Sigslot can
408
+ automatically disconnect slot object whose lifetime it is able to track. In order
409
+ to do that, the slot must be convertible to a weak pointer of some form.
410
+
411
+ `std::shared_ptr` and `std::weak_ptr` are supported out of the box, and adapters
412
+ are provided to support `boost::shared_ptr`, `boost::weak_ptr` and Qt `QSharedPointer`,
413
+ `QWeakPointer` and any class deriving from `QObject`.
414
+
415
+ Other trackable objects can be added by declaring a `to_weak()` adapter function.
416
+
417
+ ```cpp
418
+ #include <sigslot/signal.hpp>
419
+ #include <sigslot/adapter/qt.hpp>
420
+
421
+ int sum = 0;
422
+
423
+ struct s {
424
+ void f(int i) { sum += i; }
425
+ };
426
+
427
+ class MyObject : public QObject {
428
+ Q_OBJECT
429
+ public:
430
+ void add(int i) const { sum += i; }
431
+ };
432
+
433
+ int main() {
434
+ sum = 0;
435
+ signal<int> sig;
436
+
437
+ // track lifetime of object and also connect to a member function
438
+ auto p = std::make_shared<s>();
439
+ sig.connect(&s::f, p);
440
+
441
+ sig(1); // sum == 1
442
+ p.reset();
443
+ sig(1); // sum == 1
444
+
445
+ // track an unrelated object lifetime
446
+ struct dummy;
447
+ auto l = [&](int i) { sum += i; };
448
+
449
+ auto d = std::make_shared<dummy>();
450
+ sig.connect(l, d);
451
+ sig(1); // sum == 2
452
+ d.reset();
453
+ sig(1); // sum == 2
454
+
455
+ // track a QObject
456
+ {
457
+ MyObject o;
458
+ sig.connect(&MyObject::add, &o);
459
+
460
+ sig(1); // sum == 3
461
+ }
462
+
463
+ sig(1); // sum == 3
464
+ }
465
+ ```
466
+
467
+ #### Intrusive slot lifetime tracking
468
+
469
+ Another way of ensuring automatic disconnection of pointer over member functions
470
+ slots is by explicitly inheriting from `sigslot::observer` or `sigslot::observer_st`.
471
+ The former is thread-safe, contrary to the later.
472
+
473
+ Here is an example usage.
474
+
475
+ ```cpp
476
+ #include <sigslot/signal.hpp>
477
+
478
+ int sum = 0;
479
+
480
+ struct s : sigslot::observer_st {
481
+ void f(int i) { sum += i; }
482
+ };
483
+
484
+ struct s_mt : sigslot::observer {
485
+ ~s_mt() {
486
+ // Needed to ensure proper disconnection prior to object destruction
487
+ // in multithreaded contexts.
488
+ this->disconnect_all();
489
+ }
490
+
491
+ void f(int i) { sum += i; }
492
+ };
493
+
494
+ int main() {
495
+ sum = 0;
496
+ signal<int> sig;
497
+
498
+ {
499
+ // Lifetime of object instance p is tracked
500
+ s p;
501
+ s_mt pm;
502
+ sig.connect(&s::f, &p);
503
+ sig.connect(&s_mt::f, &pm);
504
+ sig(1); // sum == 2
505
+ }
506
+
507
+ // The slots got disconnected at instance destruction
508
+ sig(1); // sum == 2
509
+ }
510
+ ```
511
+
512
+ The objects that use this intrusive approach may be connected to any number of
513
+ unrelated signals.
514
+
515
+ ### Disconnection without a connection object
516
+
517
+ Support for slot disconnection by supplying an appropriate function signature,
518
+ object pointer or tracker has been introduced in version 1.2.0.
519
+
520
+ One can disconnect any number of slots using the `signal::disconnect()` method,
521
+ which proposes 4 overloads to specify the disconnection criterion:
522
+
523
+ - The first takes a reference to a callable. Any kind of callable can be passed,
524
+ even pointers to member functions, function objects and lambdas,
525
+ - The second takes a pointer to an object, for slots bound to a pointer to member
526
+ function, or a tracking object,
527
+ - The third overload takes both kinds of arguments at the same time and can be
528
+ used to pinpoint a specific pair of object + callable.
529
+ - The last overload takes a group id and disconnects all the slots in this group.
530
+
531
+ Disconnection of lambdas is only possible for lambdas bound to a variable, due
532
+ to their uniqueness.
533
+
534
+ The second overload currently needs RTTI to disconnect from pointers to member
535
+ functions, function objects and lambdas. This limitation does not apply to free
536
+ and static member functions. The reasons stems from the fact that in C++, pointers
537
+ to member functions of unrelated types are not comparable, contrary to pointers to
538
+ free and static member functions. For instance, the pointer to member functions of
539
+ virtual methods of different classes can have the same address (they kind of store
540
+ the offset of the method into the vtable).
541
+
542
+ However, Sigslot can be compiled with RTTI disabled and the overload will be
543
+ deactivated for problematic cases.
544
+
545
+ As a side node, this feature admittedly added more code than anticipated at first
546
+ because it is a tricky and easy to get wrong. It has been designed carefully, with
547
+ correctness in mind, and does not have any hidden costs unless you actually use it.
548
+
549
+ Here is an example demonstrating the feature.
550
+
551
+ ```cpp
552
+ #include <sigslot/signal.hpp>
553
+ #include <string>
554
+
555
+ static int i = 0;
556
+
557
+ void f1() { i += 1; }
558
+ void f2() { i += 1; }
559
+
560
+ struct s {
561
+ void m1() { i += 1; }
562
+ void m2() { i += 1; }
563
+ void m3() { i += 1; }
564
+ };
565
+
566
+ struct o {
567
+ void operator()() { i += 1; }
568
+ };
569
+
570
+ int main() {
571
+ sigslot::signal<> sig;
572
+ s s1;
573
+ auto s2 = std::make_shared<s>();
574
+
575
+ auto lbd = [&] { i += 1; };
576
+
577
+ sig.connect(f1); // #1
578
+ sig.connect(f2); // #2
579
+ sig.connect(&s::m1, &s1); // #3
580
+ sig.connect(&s::m2, &s1); // #4
581
+ sig.connect(&s::m3, &s1); // #5
582
+ sig.connect(&s::m1, s2); // #6
583
+ sig.connect(&s::m2, s2); // #7
584
+ sig.connect(o{}); // #8
585
+ sig.connect(lbd); // #9
586
+
587
+ sig(); // i == 9
588
+
589
+ sig.disconnect(f2); // #2 is removed
590
+ sig.disconnect(&s::m1); // #3 and #6 are removed
591
+ sig.disconnect(o{}); // #8 and is removed
592
+ // sig.disconnect(&o::operator()); // same as the above, more efficient
593
+ sig.disconnect(lbd); // #9 and is removed
594
+ sig.disconnect(s2); // #7 is removed
595
+ sig.disconnect(&s::m3, &s1); // #5 is removed, not #4
596
+
597
+ sig(); // i == 11
598
+
599
+ sig.disconnect_all(); // remove all remaining slots
600
+ return 0;
601
+ }
602
+ ```
603
+
604
+ ### Enforcing slot invocation order with slot groups
605
+
606
+ From version 1.2.0, slots can be assigned a group id in order to control the
607
+ relative order of invocation of slots.
608
+
609
+ The order of invocation of slots in a same group is unspecified and should not be
610
+ relied upon, however slot groups are invoked in ascending group id order.
611
+ When the group id of a slot is not set, it is assigned to the group 0.
612
+ Group ids can have any value in the range of signed 32 bit integers.
613
+
614
+ ```cpp
615
+ #include <sigslot/signal.hpp>
616
+ #include <cstdio>
617
+ #include <limits>
618
+
619
+ int main() {
620
+ sigslot::signal<> sig;
621
+
622
+ // simply assigning a group id as last argument to connect
623
+ sig.connect([] { std::puts("Second"); }, 1);
624
+ sig.connect([] { std::puts("Last"); }, std::numeric_limits<sigslot::group_id>::max());
625
+ sig.connect([] { std::puts("First"); }, -10);
626
+ sig();
627
+
628
+ return 0;
629
+ }
630
+ ```
631
+
632
+ ### Thread safety
633
+
634
+ Thread safety is unit-tested. In particular, cross-signal emission and recursive
635
+ emission run fine in a multiple threads scenario.
636
+
637
+ `sigslot::signal` is a typedef to the more general `sigslot::signal_base` template
638
+ class, whose first template argument must be a Lockable type. This type will dictate
639
+ the locking policy of the class.
640
+
641
+ Sigslot offers 2 typedefs,
642
+
643
+ - `sigslot::signal` usable from multiple threads and uses std::mutex as a lockable.
644
+ In particular, connection, disconnection, emission and slot execution are thread
645
+ safe. It is also safe with recursive signal emission.
646
+ - `sigslot::signal_st` is a non thread-safe alternative, it trades safety for slightly
647
+ faster operation.
648
+
649
+
650
+ ## Implementation details
651
+
652
+ ### Using function pointers to disconnect slots
653
+
654
+ Comparing function pointers is a nightmare in C++. Here is a table demonstrating
655
+ the size and address of a variety of cases as a showcase:
656
+
657
+ ```cpp
658
+ void fun() {}
659
+
660
+ struct b1 {
661
+ virtual ~b1() = default;
662
+ static void sm() {}
663
+ void m() {}
664
+ virtual void vm() {}
665
+ };
666
+
667
+ struct b2 {
668
+ virtual ~b2() = default;
669
+ static void sm() {}
670
+ void m() {}
671
+ virtual void vm() {}
672
+ };
673
+
674
+ struct c {
675
+ virtual ~c() = default;
676
+ virtual void w() {}
677
+ };
678
+
679
+ struct d : b1 {
680
+ static void sm() {}
681
+ void m() {}
682
+ void vm() override {}
683
+ };
684
+
685
+ struct e : b1, c {
686
+ static void sm() {}
687
+ void m() {}
688
+ void vm() override{}
689
+ };
690
+ ```
691
+
692
+ | Symbol | GCC 9 Linux 64<br>Sizeof | GCC 9 Linux 64<br>Address | MSVC 16.6 32<br>Sizeof | MSVC 16.6 32<br>Address | GCC 8 Mingw 32<br>Sizeof | GCC 8 Mingw 32<br>Address | Clang-cl 9 32<br>Sizeof | Clang-cl 9 32<br>Address |
693
+ |---------|--------------------------|---------------------------|------------------------|-------------------------|--------------------------|---------------------------|-------------------------|--------------------------|
694
+ | fun | 8 | 0x802340 | 4 | 0x1311A6 | 4 | 0xF41540 | 4 | 0x0010AE |
695
+ | &b1::sm | 8 | 0xE03140 | 4 | 0x7612A5 | 4 | 0x308D40 | 4 | 0x0010AE |
696
+ | &b1::m | 16 | 0xF03240 | 4 | 0x1514A5 | 8 | 0x248D40 | 4 | 0x0010AE |
697
+ | &b1::vm | 16 | 0x11 | 4 | 0x9F11A5 | 8 | 0x09 | 4 | 0x8023AE |
698
+ | &b2::sm | 8 | 0x003340 | 4 | 0xA515A5 | 4 | 0x408D40 | 4 | 0x0010AE |
699
+ | &b2::m | 16 | 0x103440 | 4 | 0xEB10A5 | 8 | 0x348D40 | 4 | 0x0010AE |
700
+ | &b2::vm | 16 | 0x11 | 4 | 0x6A14A5 | 8 | 0x09 | 4 | 0x8023AE |
701
+ | &d::sm | 8 | 0x203440 | 4 | 0x2612A5 | 4 | 0x108D40 | 4 | 0x0010AE |
702
+ | &d::m | 16 | 0x303540 | 4 | 0x9D13A5 | 8 | 0x048D40 | 4 | 0x0010AE |
703
+ | &d::vm | 16 | 0x11 | 4 | 0x4412A5 | 8 | 0x09 | 4 | 0x8023AE |
704
+ | &e::sm | 8 | 0x403540 | 4 | 0xF911A5 | 4 | 0x208D40 | 4 | 0x0010AE |
705
+ | &e::m | 16 | 0x503640 | 8 | 0x8111A5 | 8 | 0x148D40 | 8 | 0x0010AE |
706
+ | &e::vm | 16 | 0x11 | 8 | 0xA911A5 | 8 | 0x09 | 8 | 0x8023AE |
707
+
708
+ MSVC and Clang-cl in Release mode optimize functions with the same definition by
709
+ merging them. This is a behaviour that can be deactivated with the `/OPT:NOICF`
710
+ linker option.
711
+ Sigslot tests and examples rely on a lot a identical callables which trigger this
712
+ behaviour, which is why it deactivates this particular optimization on the affected
713
+ compilers.
714
+
715
+ ### Known bugs
716
+
717
+ Using generic lambdas with GCC less than version 7.4 can trigger [Bug #68071](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68071).
third-party/DPVO/Pangolin/components/pango_core/include/sigslot/signal.hpp ADDED
@@ -0,0 +1,1611 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+ #include <atomic>
3
+ #include <memory>
4
+ #include <mutex>
5
+ #include <type_traits>
6
+ #include <utility>
7
+ #include <thread>
8
+ #include <vector>
9
+
10
+ #if defined __clang__ || (__GNUC__ > 5)
11
+ #define SIGSLOT_MAY_ALIAS __attribute__((__may_alias__))
12
+ #else
13
+ #define SIGSLOT_MAY_ALIAS
14
+ #endif
15
+
16
+ #if defined(__GXX_RTTI) || defined(__cpp_rtti) || defined(_CPPRTTI)
17
+ #define SIGSLOT_RTTI_ENABLED 1
18
+ #include <typeinfo>
19
+ #endif
20
+
21
+ namespace sigslot {
22
+
23
+ namespace detail {
24
+
25
+ // Used to detect an object of observer type
26
+ struct observer_type {};
27
+
28
+ } // namespace detail
29
+
30
+ namespace trait {
31
+
32
+ /// represent a list of types
33
+ template <typename...> struct typelist {};
34
+
35
+ /**
36
+ * Pointers that can be converted to a weak pointer concept for tracking
37
+ * purpose must implement the to_weak() function in order to make use of
38
+ * ADL to convert that type and make it usable
39
+ */
40
+
41
+ template <typename T>
42
+ std::weak_ptr<T> to_weak(std::weak_ptr<T> w) {
43
+ return w;
44
+ }
45
+
46
+ template <typename T>
47
+ std::weak_ptr<T> to_weak(std::shared_ptr<T> s) {
48
+ return s;
49
+ }
50
+
51
+ // tools
52
+ namespace detail {
53
+
54
+ template <typename...>
55
+ struct voider { using type = void; };
56
+
57
+ // void_t from c++17
58
+ template <typename...T>
59
+ using void_t = typename detail::voider<T...>::type;
60
+
61
+ template <typename, typename = void>
62
+ struct has_call_operator : std::false_type {};
63
+
64
+ template <typename F>
65
+ struct has_call_operator<F, void_t<decltype(&std::remove_reference<F>::type::operator())>>
66
+ : std::true_type {};
67
+
68
+ template <typename, typename, typename = void, typename = void>
69
+ struct is_callable : std::false_type {};
70
+
71
+ template <typename F, typename P, typename... T>
72
+ struct is_callable<F, P, typelist<T...>,
73
+ void_t<decltype(((*std::declval<P>()).*std::declval<F>())(std::declval<T>()...))>>
74
+ : std::true_type {};
75
+
76
+ template <typename F, typename... T>
77
+ struct is_callable<F, typelist<T...>,
78
+ void_t<decltype(std::declval<F>()(std::declval<T>()...))>>
79
+ : std::true_type {};
80
+
81
+
82
+ template <typename T, typename = void>
83
+ struct is_weak_ptr : std::false_type {};
84
+
85
+ template <typename T>
86
+ struct is_weak_ptr<T, void_t<decltype(std::declval<T>().expired()),
87
+ decltype(std::declval<T>().lock()),
88
+ decltype(std::declval<T>().reset())>>
89
+ : std::true_type {};
90
+
91
+ template <typename T, typename = void>
92
+ struct is_weak_ptr_compatible : std::false_type {};
93
+
94
+ template <typename T>
95
+ struct is_weak_ptr_compatible<T, void_t<decltype(to_weak(std::declval<T>()))>>
96
+ : is_weak_ptr<decltype(to_weak(std::declval<T>()))> {};
97
+
98
+ } // namespace detail
99
+
100
+ static constexpr bool with_rtti =
101
+ #ifdef SIGSLOT_RTTI_ENABLED
102
+ true;
103
+ #else
104
+ false;
105
+ #endif
106
+
107
+ /// determine if a pointer is convertible into a "weak" pointer
108
+ template <typename P>
109
+ constexpr bool is_weak_ptr_compatible_v = detail::is_weak_ptr_compatible<std::decay_t<P>>::value;
110
+
111
+ /// determine if a type T (Callable or Pmf) is callable with supplied arguments
112
+ template <typename L, typename... T>
113
+ constexpr bool is_callable_v = detail::is_callable<T..., L>::value;
114
+
115
+ template <typename T>
116
+ constexpr bool is_weak_ptr_v = detail::is_weak_ptr<T>::value;
117
+
118
+ template <typename T>
119
+ constexpr bool has_call_operator_v = detail::has_call_operator<T>::value;
120
+
121
+ template <typename T>
122
+ constexpr bool is_pointer_v = std::is_pointer<T>::value;
123
+
124
+ template <typename T>
125
+ constexpr bool is_func_v = std::is_function<T>::value;
126
+
127
+ template <typename T>
128
+ constexpr bool is_pmf_v = std::is_member_function_pointer<T>::value;
129
+
130
+ template <typename T>
131
+ constexpr bool is_observer_v = std::is_base_of<::sigslot::detail::observer_type,
132
+ std::remove_pointer_t<T>>::value;
133
+
134
+ } // namespace trait
135
+
136
+ template <typename, typename...>
137
+ class signal_base;
138
+
139
+ /**
140
+ * A group_id is used to identify a group of slots
141
+ */
142
+ using group_id = std::int32_t;
143
+
144
+ namespace detail {
145
+
146
+ /**
147
+ * The following function_traits and object_pointer series of templates are
148
+ * used to circumvent the type-erasing that takes place in the slot_base
149
+ * implementations. They are used to compare the stored functions and objects
150
+ * with another one for disconnection purpose.
151
+ */
152
+
153
+ /*
154
+ * Function pointers and member function pointers size differ from compiler to
155
+ * compiler, and for virtual members compared to non virtual members. On some
156
+ * compilers, multiple inheritance has an impact too. Hence, we form an union
157
+ * big enough to store any kind of function pointer.
158
+ */
159
+ namespace mock {
160
+
161
+ struct a { virtual ~a() = default; void f(); virtual void g(); };
162
+ struct b { virtual ~b() = default; virtual void h(); };
163
+ struct c : a, b { void g() override; };
164
+
165
+ union fun_types {
166
+ decltype(&c::g) m;
167
+ decltype(&a::g) v;
168
+ decltype(&a::f) d;
169
+ void (*f)();
170
+ void *o;
171
+ };
172
+
173
+ } // namespace mock
174
+
175
+ /*
176
+ * This union is used to compare function pointers
177
+ * Generic callables cannot be compared. Here we compare pointers but there is
178
+ * no guarantee that this always works.
179
+ */
180
+ union SIGSLOT_MAY_ALIAS func_ptr {
181
+ void* value() {
182
+ return &data[0];
183
+ }
184
+
185
+ const void* value() const {
186
+ return &data[0];
187
+ }
188
+
189
+ template <typename T>
190
+ T& value() {
191
+ return *static_cast<T*>(value());
192
+ }
193
+
194
+ template <typename T>
195
+ const T& value() const {
196
+ return *static_cast<const T*>(value());
197
+ }
198
+
199
+ inline explicit operator bool() const {
200
+ return value() != nullptr;
201
+ }
202
+
203
+ inline bool operator==(const func_ptr &o) const {
204
+ return std::equal(std::begin(data), std::end(data), std::begin(o.data));
205
+ }
206
+
207
+ mock::fun_types _;
208
+ char data[sizeof(mock::fun_types)];
209
+ };
210
+
211
+
212
+ template <typename T, typename = void>
213
+ struct function_traits {
214
+ static void ptr(const T &/*t*/, func_ptr &d) {
215
+ d.value<std::nullptr_t>() = nullptr;
216
+ }
217
+
218
+ static constexpr bool is_disconnectable = false;
219
+ static constexpr bool must_check_object = true;
220
+ };
221
+
222
+ template <typename T>
223
+ struct function_traits<T, std::enable_if_t<trait::is_func_v<T>>> {
224
+ static void ptr(T &t, func_ptr &d) {
225
+ d.value<T*>() = &t;
226
+ }
227
+
228
+ static constexpr bool is_disconnectable = true;
229
+ static constexpr bool must_check_object = false;
230
+ };
231
+
232
+ template <typename T>
233
+ struct function_traits<T*, std::enable_if_t<trait::is_func_v<T>>> {
234
+ static void ptr(T *t, func_ptr &d) {
235
+ d.value<T*>() = t;
236
+ }
237
+
238
+ static constexpr bool is_disconnectable = true;
239
+ static constexpr bool must_check_object = false;
240
+ };
241
+
242
+ template <typename T>
243
+ struct function_traits<T, std::enable_if_t<trait::is_pmf_v<T>>> {
244
+ static void ptr(const T &t, func_ptr &d) {
245
+ d.value<T>() = t;
246
+ }
247
+
248
+ static constexpr bool is_disconnectable = trait::with_rtti;
249
+ static constexpr bool must_check_object = true;
250
+ };
251
+
252
+ // for function objects, the assumption is that we are looking for the call operator
253
+ template <typename T>
254
+ struct function_traits<T, std::enable_if_t<trait::has_call_operator_v<T>>> {
255
+ using call_type = decltype(&std::remove_reference<T>::type::operator());
256
+
257
+ static void ptr(const T &/*t*/, func_ptr &d) {
258
+ function_traits<call_type>::ptr(&T::operator(), d);
259
+ }
260
+
261
+ static constexpr bool is_disconnectable = function_traits<call_type>::is_disconnectable;
262
+ static constexpr bool must_check_object = function_traits<call_type>::must_check_object;
263
+ };
264
+
265
+ template <typename T>
266
+ func_ptr get_function_ptr(const T &t) {
267
+ func_ptr d;
268
+ std::uninitialized_fill(std::begin(d.data), std::end(d.data), '\0');
269
+ function_traits<std::decay_t<T>>::ptr(t, d);
270
+ return d;
271
+ }
272
+
273
+ /*
274
+ * obj_ptr is used to store a pointer to an object.
275
+ * The object_pointer traits are needed to handle trackable objects correctly,
276
+ * as they are likely to not be pointers.
277
+ */
278
+ using obj_ptr = const void*;
279
+
280
+ template <typename T>
281
+ obj_ptr get_object_ptr(const T &t);
282
+
283
+ template <typename T, typename = void>
284
+ struct object_pointer {
285
+ static obj_ptr get(const T&) {
286
+ return nullptr;
287
+ }
288
+ };
289
+
290
+ template <typename T>
291
+ struct object_pointer<T*, std::enable_if_t<trait::is_pointer_v<T*>>> {
292
+ static obj_ptr get(const T *t) {
293
+ return reinterpret_cast<obj_ptr>(t);
294
+ }
295
+ };
296
+
297
+ template <typename T>
298
+ struct object_pointer<T, std::enable_if_t<trait::is_weak_ptr_v<T>>> {
299
+ static obj_ptr get(const T &t) {
300
+ auto p = t.lock();
301
+ return get_object_ptr(p);
302
+ }
303
+ };
304
+
305
+ template <typename T>
306
+ struct object_pointer<T, std::enable_if_t<!trait::is_pointer_v<T> &&
307
+ !trait::is_weak_ptr_v<T> &&
308
+ trait::is_weak_ptr_compatible_v<T>>>
309
+ {
310
+ static obj_ptr get(const T &t) {
311
+ return t ? reinterpret_cast<obj_ptr>(t.get()) : nullptr;
312
+ }
313
+ };
314
+
315
+ template <typename T>
316
+ obj_ptr get_object_ptr(const T &t) {
317
+ return object_pointer<T>::get(t);
318
+ }
319
+
320
+
321
+ // noop mutex for thread-unsafe use
322
+ struct null_mutex {
323
+ null_mutex() noexcept = default;
324
+ ~null_mutex() noexcept = default;
325
+ null_mutex(const null_mutex &) = delete;
326
+ null_mutex& operator=(const null_mutex &) = delete;
327
+ null_mutex(null_mutex &&) = delete;
328
+ null_mutex& operator=(null_mutex &&) = delete;
329
+
330
+ inline bool try_lock() noexcept { return true; }
331
+ inline void lock() noexcept {}
332
+ inline void unlock() noexcept {}
333
+ };
334
+
335
+ /**
336
+ * A spin mutex that yields, mostly for use in benchmarks and scenarii that invoke
337
+ * slots at a very high pace.
338
+ * One should almost always prefer a standard mutex over this.
339
+ */
340
+ struct spin_mutex {
341
+ spin_mutex() noexcept = default;
342
+ ~spin_mutex() noexcept = default;
343
+ spin_mutex(spin_mutex const&) = delete;
344
+ spin_mutex& operator=(const spin_mutex &) = delete;
345
+ spin_mutex(spin_mutex &&) = delete;
346
+ spin_mutex& operator=(spin_mutex &&) = delete;
347
+
348
+ void lock() noexcept {
349
+ while (true) {
350
+ while (!state.load(std::memory_order_relaxed)) {
351
+ std::this_thread::yield();
352
+ }
353
+
354
+ if (try_lock()) {
355
+ break;
356
+ }
357
+ }
358
+ }
359
+
360
+ bool try_lock() noexcept {
361
+ return state.exchange(false, std::memory_order_acquire);
362
+ }
363
+
364
+ void unlock() noexcept {
365
+ state.store(true, std::memory_order_release);
366
+ }
367
+
368
+ private:
369
+ std::atomic<bool> state {true};
370
+ };
371
+
372
+ /**
373
+ * A simple copy on write container that will be used to improve slot lists
374
+ * access efficiency in a multithreaded context.
375
+ */
376
+ template <typename T>
377
+ class copy_on_write {
378
+ struct payload {
379
+ payload() = default;
380
+
381
+ template <typename... Args>
382
+ explicit payload(Args && ...args)
383
+ : value(std::forward<Args>(args)...)
384
+ {}
385
+
386
+ std::atomic<std::size_t> count{1};
387
+ T value;
388
+ };
389
+
390
+ public:
391
+ using element_type = T;
392
+
393
+ copy_on_write()
394
+ : m_data(new payload)
395
+ {}
396
+
397
+ template <typename U>
398
+ explicit copy_on_write(U && x, std::enable_if_t<!std::is_same<std::decay_t<U>,
399
+ copy_on_write>::value>* = nullptr)
400
+ : m_data(new payload(std::forward<U>(x)))
401
+ {}
402
+
403
+ copy_on_write(const copy_on_write &x) noexcept
404
+ : m_data(x.m_data)
405
+ {
406
+ ++m_data->count;
407
+ }
408
+
409
+ copy_on_write(copy_on_write && x) noexcept
410
+ : m_data(x.m_data)
411
+ {
412
+ x.m_data = nullptr;
413
+ }
414
+
415
+ ~copy_on_write() {
416
+ if (m_data && (--m_data->count == 0)) {
417
+ delete m_data;
418
+ }
419
+ }
420
+
421
+ copy_on_write& operator=(const copy_on_write &x) noexcept {
422
+ if (&x != this) {
423
+ *this = copy_on_write(x);
424
+ }
425
+ return *this;
426
+ }
427
+
428
+ copy_on_write& operator=(copy_on_write && x) noexcept {
429
+ auto tmp = std::move(x);
430
+ swap(*this, tmp);
431
+ return *this;
432
+ }
433
+
434
+ element_type& write() {
435
+ if (!unique()) {
436
+ *this = copy_on_write(read());
437
+ }
438
+ return m_data->value;
439
+ }
440
+
441
+ const element_type& read() const noexcept {
442
+ return m_data->value;
443
+ }
444
+
445
+ friend inline void swap(copy_on_write &x, copy_on_write &y) noexcept {
446
+ using std::swap;
447
+ swap(x.m_data, y.m_data);
448
+ }
449
+
450
+ private:
451
+ bool unique() const noexcept {
452
+ return m_data->count == 1;
453
+ }
454
+
455
+ private:
456
+ payload *m_data;
457
+ };
458
+
459
+ /**
460
+ * Specializations for thread-safe code path
461
+ */
462
+ template <typename T>
463
+ const T& cow_read(const T &v) {
464
+ return v;
465
+ }
466
+
467
+ template <typename T>
468
+ const T& cow_read(copy_on_write<T> &v) {
469
+ return v.read();
470
+ }
471
+
472
+ template <typename T>
473
+ T& cow_write(T &v) {
474
+ return v;
475
+ }
476
+
477
+ template <typename T>
478
+ T& cow_write(copy_on_write<T> &v) {
479
+ return v.write();
480
+ }
481
+
482
+ /**
483
+ * std::make_shared instantiates a lot a templates, and makes both compilation time
484
+ * and executable size far bigger than they need to be. We offer a make_shared
485
+ * equivalent that will avoid most instantiations with the following tradeoffs:
486
+ * - Not exception safe,
487
+ * - Allocates a separate control block, and will thus make the code slower.
488
+ */
489
+ #ifdef SIGSLOT_REDUCE_COMPILE_TIME
490
+ template <typename B, typename D, typename ...Arg>
491
+ inline std::shared_ptr<B> make_shared(Arg && ... arg) {
492
+ return std::shared_ptr<B>(static_cast<B*>(new D(std::forward<Arg>(arg)...)));
493
+ }
494
+ #else
495
+ template <typename B, typename D, typename ...Arg>
496
+ inline std::shared_ptr<B> make_shared(Arg && ... arg) {
497
+ return std::static_pointer_cast<B>(std::make_shared<D>(std::forward<Arg>(arg)...));
498
+ }
499
+ #endif
500
+
501
+ /* slot_state holds slot type independent state, to be used to interact with
502
+ * slots indirectly through connection and scoped_connection objects.
503
+ */
504
+ class slot_state {
505
+ public:
506
+ constexpr slot_state(group_id gid) noexcept
507
+ : m_index(0)
508
+ , m_group(gid)
509
+ , m_connected(true)
510
+ , m_blocked(false)
511
+ {}
512
+
513
+ virtual ~slot_state() = default;
514
+
515
+ virtual bool connected() const noexcept { return m_connected; }
516
+
517
+ bool disconnect() noexcept {
518
+ bool ret = m_connected.exchange(false);
519
+ if (ret) {
520
+ do_disconnect();
521
+ }
522
+ return ret;
523
+ }
524
+
525
+ bool blocked() const noexcept { return m_blocked.load(); }
526
+ void block() noexcept { m_blocked.store(true); }
527
+ void unblock() noexcept { m_blocked.store(false); }
528
+
529
+ protected:
530
+ virtual void do_disconnect() {}
531
+
532
+ auto index() const {
533
+ return m_index;
534
+ }
535
+
536
+ auto& index() {
537
+ return m_index;
538
+ }
539
+
540
+ group_id group() const {
541
+ return m_group;
542
+ }
543
+
544
+ private:
545
+ template <typename, typename...>
546
+ friend class ::sigslot::signal_base;
547
+
548
+ std::size_t m_index; // index into the array of slot pointers inside the signal
549
+ const group_id m_group; // slot group this slot belongs to
550
+ std::atomic<bool> m_connected;
551
+ std::atomic<bool> m_blocked;
552
+ };
553
+
554
+ } // namespace detail
555
+
556
+ /**
557
+ * connection_blocker is a RAII object that blocks a connection until destruction
558
+ */
559
+ class connection_blocker {
560
+ public:
561
+ connection_blocker() = default;
562
+ ~connection_blocker() noexcept { release(); }
563
+
564
+ connection_blocker(const connection_blocker &) = delete;
565
+ connection_blocker & operator=(const connection_blocker &) = delete;
566
+
567
+ connection_blocker(connection_blocker && o) noexcept
568
+ : m_state{std::move(o.m_state)}
569
+ {}
570
+
571
+ connection_blocker & operator=(connection_blocker && o) noexcept {
572
+ release();
573
+ m_state.swap(o.m_state);
574
+ return *this;
575
+ }
576
+
577
+ private:
578
+ friend class connection;
579
+ explicit connection_blocker(std::weak_ptr<detail::slot_state> s) noexcept
580
+ : m_state{std::move(s)}
581
+ {
582
+ if (auto d = m_state.lock()) {
583
+ d->block();
584
+ }
585
+ }
586
+
587
+ void release() noexcept {
588
+ if (auto d = m_state.lock()) {
589
+ d->unblock();
590
+ }
591
+ }
592
+
593
+ private:
594
+ std::weak_ptr<detail::slot_state> m_state;
595
+ };
596
+
597
+
598
+ /**
599
+ * A connection object allows interaction with an ongoing slot connection
600
+ *
601
+ * It allows common actions such as connection blocking and disconnection.
602
+ * Note that connection is not a RAII object, one does not need to hold one
603
+ * such object to keep the signal-slot connection alive.
604
+ */
605
+ class connection {
606
+ public:
607
+ connection() = default;
608
+ virtual ~connection() = default;
609
+
610
+ connection(const connection &) noexcept = default;
611
+ connection & operator=(const connection &) noexcept = default;
612
+ connection(connection &&) noexcept = default;
613
+ connection & operator=(connection &&) noexcept = default;
614
+
615
+ bool valid() const noexcept {
616
+ return !m_state.expired();
617
+ }
618
+
619
+ bool connected() const noexcept {
620
+ const auto d = m_state.lock();
621
+ return d && d->connected();
622
+ }
623
+
624
+ bool disconnect() noexcept {
625
+ auto d = m_state.lock();
626
+ return d && d->disconnect();
627
+ }
628
+
629
+ bool blocked() const noexcept {
630
+ const auto d = m_state.lock();
631
+ return d && d->blocked();
632
+ }
633
+
634
+ void block() noexcept {
635
+ if (auto d = m_state.lock()) {
636
+ d->block();
637
+ }
638
+ }
639
+
640
+ void unblock() noexcept {
641
+ if (auto d = m_state.lock()) {
642
+ d->unblock();
643
+ }
644
+ }
645
+
646
+ connection_blocker blocker() const noexcept {
647
+ return connection_blocker{m_state};
648
+ }
649
+
650
+ protected:
651
+ template <typename, typename...> friend class signal_base;
652
+ explicit connection(std::weak_ptr<detail::slot_state> s) noexcept
653
+ : m_state{std::move(s)}
654
+ {}
655
+
656
+ protected:
657
+ std::weak_ptr<detail::slot_state> m_state;
658
+ };
659
+
660
+ /**
661
+ * scoped_connection is a RAII version of connection
662
+ * It disconnects the slot from the signal upon destruction.
663
+ */
664
+ class scoped_connection final : public connection {
665
+ public:
666
+ scoped_connection() = default;
667
+ ~scoped_connection() override {
668
+ disconnect();
669
+ }
670
+
671
+ /*implicit*/ scoped_connection(const connection &c) noexcept : connection(c) {}
672
+ /*implicit*/ scoped_connection(connection &&c) noexcept : connection(std::move(c)) {}
673
+
674
+ scoped_connection(const scoped_connection &) noexcept = delete;
675
+ scoped_connection & operator=(const scoped_connection &) noexcept = delete;
676
+
677
+ scoped_connection(scoped_connection && o) noexcept
678
+ : connection{std::move(o.m_state)}
679
+ {}
680
+
681
+ scoped_connection & operator=(scoped_connection && o) noexcept {
682
+ disconnect();
683
+ m_state.swap(o.m_state);
684
+ return *this;
685
+ }
686
+
687
+ private:
688
+ template <typename, typename...> friend class signal_base;
689
+ explicit scoped_connection(std::weak_ptr<detail::slot_state> s) noexcept
690
+ : connection{std::move(s)}
691
+ {}
692
+ };
693
+
694
+ /**
695
+ * Observer is a base class for intrusive lifetime tracking of objects.
696
+ *
697
+ * This is an alternative to trackable pointers, such as std::shared_ptr,
698
+ * and manual connection management by keeping connection objects in scope.
699
+ * Deriving from this class allows automatic disconnection of all the slots
700
+ * connected to any signal when an instance is destroyed.
701
+ */
702
+ template <typename Lockable>
703
+ struct observer_base : private detail::observer_type {
704
+ virtual ~observer_base() = default;
705
+
706
+ protected:
707
+ /**
708
+ * Disconnect all signals connected to this object.
709
+ *
710
+ * To avoid invocation of slots on a semi-destructed instance, which may happen
711
+ * in multi-threaded contexts, derived classes should call this method in their
712
+ * destructor. This will ensure proper disconnection prior to the destruction.
713
+ */
714
+ void disconnect_all() {
715
+ std::unique_lock<Lockable> _{m_mutex};
716
+ m_connections.clear();
717
+ }
718
+
719
+ private:
720
+ template <typename, typename ...>
721
+ friend class signal_base;
722
+
723
+ void add_connection(connection conn) {
724
+ std::unique_lock<Lockable> _{m_mutex};
725
+ m_connections.emplace_back(std::move(conn));
726
+ }
727
+
728
+ Lockable m_mutex;
729
+ std::vector<scoped_connection> m_connections;
730
+ };
731
+
732
+ /**
733
+ * Specialization of observer_base to be used in single threaded contexts.
734
+ */
735
+ using observer_st = observer_base<detail::null_mutex>;
736
+
737
+ /**
738
+ * Specialization of observer_base to be used in multi-threaded contexts.
739
+ */
740
+ using observer = observer_base<std::mutex>;
741
+
742
+
743
+ namespace detail {
744
+
745
+ // interface for cleanable objects, used to cleanup disconnected slots
746
+ struct cleanable {
747
+ virtual ~cleanable() = default;
748
+ virtual void clean(slot_state *) = 0;
749
+ };
750
+
751
+ template <typename...>
752
+ class slot_base;
753
+
754
+ template <typename... T>
755
+ using slot_ptr = std::shared_ptr<slot_base<T...>>;
756
+
757
+
758
+ /* A base class for slot objects. This base type only depends on slot argument
759
+ * types, it will be used as an element in an intrusive singly-linked list of
760
+ * slots, hence the public next member.
761
+ */
762
+ template <typename... Args>
763
+ class slot_base : public slot_state {
764
+ public:
765
+ using base_types = trait::typelist<Args...>;
766
+
767
+ explicit slot_base(cleanable &c, group_id gid)
768
+ : slot_state(gid)
769
+ , cleaner(c)
770
+ {}
771
+ ~slot_base() override = default;
772
+
773
+ // method effectively responsible for calling the "slot" function with
774
+ // supplied arguments whenever emission happens.
775
+ virtual void call_slot(Args...) = 0;
776
+
777
+ template <typename... U>
778
+ void operator()(U && ...u) {
779
+ if (slot_state::connected() && !slot_state::blocked()) {
780
+ call_slot(std::forward<U>(u)...);
781
+ }
782
+ }
783
+
784
+ // check if we are storing callable c
785
+ template <typename C>
786
+ bool has_callable(const C &c) const {
787
+ auto cp = get_function_ptr(c);
788
+ auto p = get_callable();
789
+ return cp && p && cp == p;
790
+ }
791
+
792
+ template <typename C>
793
+ std::enable_if_t<function_traits<C>::must_check_object, bool>
794
+ has_full_callable(const C &c) const {
795
+ return has_callable(c) && check_class_type<std::decay_t<C>>();
796
+ }
797
+
798
+ template <typename C>
799
+ std::enable_if_t<!function_traits<C>::must_check_object, bool>
800
+ has_full_callable(const C &c) const {
801
+ return has_callable(c);
802
+ }
803
+
804
+ // check if we are storing object o
805
+ template <typename O>
806
+ bool has_object(const O &o) const {
807
+ return get_object() == get_object_ptr(o);
808
+ }
809
+
810
+ protected:
811
+ void do_disconnect() final {
812
+ cleaner.clean(this);
813
+ }
814
+
815
+ // retieve a pointer to the object embedded in the slot
816
+ virtual obj_ptr get_object() const noexcept {
817
+ return nullptr;
818
+ }
819
+
820
+ // retieve a pointer to the callable embedded in the slot
821
+ virtual func_ptr get_callable() const noexcept {
822
+ return get_function_ptr(nullptr);
823
+ }
824
+
825
+ #ifdef SIGSLOT_RTTI_ENABLED
826
+ // retieve a pointer to the callable embedded in the slot
827
+ virtual const std::type_info& get_callable_type() const noexcept {
828
+ return typeid(nullptr);
829
+ }
830
+
831
+ private:
832
+ template <typename U>
833
+ bool check_class_type() const {
834
+ return typeid(U) == get_callable_type();
835
+ }
836
+
837
+ #else
838
+ template <typename U>
839
+ bool check_class_type() const {
840
+ return false;
841
+ }
842
+ #endif
843
+
844
+ private:
845
+ cleanable &cleaner;
846
+ };
847
+
848
+ /*
849
+ * A slot object holds state information, and a callable to to be called
850
+ * whenever the function call operator of its slot_base base class is called.
851
+ */
852
+ template <typename Func, typename... Args>
853
+ class slot final : public slot_base<Args...> {
854
+ public:
855
+ template <typename F, typename Gid>
856
+ constexpr slot(cleanable &c, F && f, Gid gid)
857
+ : slot_base<Args...>(c, gid)
858
+ , func{std::forward<F>(f)} {}
859
+
860
+ protected:
861
+ void call_slot(Args ...args) override {
862
+ func(args...);
863
+ }
864
+
865
+ func_ptr get_callable() const noexcept override {
866
+ return get_function_ptr(func);
867
+ }
868
+
869
+ #ifdef SIGSLOT_RTTI_ENABLED
870
+ const std::type_info& get_callable_type() const noexcept override {
871
+ return typeid(func);
872
+ }
873
+ #endif
874
+
875
+ private:
876
+ std::decay_t<Func> func;
877
+ };
878
+
879
+ /*
880
+ * Variation of slot that prepends a connection object to the callable
881
+ */
882
+ template <typename Func, typename... Args>
883
+ class slot_extended final : public slot_base<Args...> {
884
+ public:
885
+ template <typename F>
886
+ constexpr slot_extended(cleanable &c, F && f, group_id gid)
887
+ : slot_base<Args...>(c, gid)
888
+ , func{std::forward<F>(f)} {}
889
+
890
+ connection conn;
891
+
892
+ protected:
893
+ void call_slot(Args ...args) override {
894
+ func(conn, args...);
895
+ }
896
+
897
+ func_ptr get_callable() const noexcept override {
898
+ return get_function_ptr(func);
899
+ }
900
+
901
+ #ifdef SIGSLOT_RTTI_ENABLED
902
+ const std::type_info& get_callable_type() const noexcept override {
903
+ return typeid(func);
904
+ }
905
+ #endif
906
+
907
+ private:
908
+ std::decay_t<Func> func;
909
+ };
910
+
911
+ /*
912
+ * A slot object holds state information, an object and a pointer over member
913
+ * function to be called whenever the function call operator of its slot_base
914
+ * base class is called.
915
+ */
916
+ template <typename Pmf, typename Ptr, typename... Args>
917
+ class slot_pmf final : public slot_base<Args...> {
918
+ public:
919
+ template <typename F, typename P>
920
+ constexpr slot_pmf(cleanable &c, F && f, P && p, group_id gid)
921
+ : slot_base<Args...>(c, gid)
922
+ , pmf{std::forward<F>(f)}
923
+ , ptr{std::forward<P>(p)} {}
924
+
925
+ protected:
926
+ void call_slot(Args ...args) override {
927
+ ((*ptr).*pmf)(args...);
928
+ }
929
+
930
+ func_ptr get_callable() const noexcept override {
931
+ return get_function_ptr(pmf);
932
+ }
933
+
934
+ obj_ptr get_object() const noexcept override {
935
+ return get_object_ptr(ptr);
936
+ }
937
+
938
+ #ifdef SIGSLOT_RTTI_ENABLED
939
+ const std::type_info& get_callable_type() const noexcept override {
940
+ return typeid(pmf);
941
+ }
942
+ #endif
943
+
944
+ private:
945
+ std::decay_t<Pmf> pmf;
946
+ std::decay_t<Ptr> ptr;
947
+ };
948
+
949
+ /*
950
+ * Variation of slot that prepends a connection object to the callable
951
+ */
952
+ template <typename Pmf, typename Ptr, typename... Args>
953
+ class slot_pmf_extended final : public slot_base<Args...> {
954
+ public:
955
+ template <typename F, typename P>
956
+ constexpr slot_pmf_extended(cleanable &c, F && f, P && p, group_id gid)
957
+ : slot_base<Args...>(c, gid)
958
+ , pmf{std::forward<F>(f)}
959
+ , ptr{std::forward<P>(p)} {}
960
+
961
+ connection conn;
962
+
963
+ protected:
964
+ void call_slot(Args ...args) override {
965
+ ((*ptr).*pmf)(conn, args...);
966
+ }
967
+
968
+ func_ptr get_callable() const noexcept override {
969
+ return get_function_ptr(pmf);
970
+ }
971
+ obj_ptr get_object() const noexcept override {
972
+ return get_object_ptr(ptr);
973
+ }
974
+
975
+ #ifdef SIGSLOT_RTTI_ENABLED
976
+ const std::type_info& get_callable_type() const noexcept override {
977
+ return typeid(pmf);
978
+ }
979
+ #endif
980
+
981
+ private:
982
+ std::decay_t<Pmf> pmf;
983
+ std::decay_t<Ptr> ptr;
984
+ };
985
+
986
+ /*
987
+ * An implementation of a slot that tracks the life of a supplied object
988
+ * through a weak pointer in order to automatically disconnect the slot
989
+ * on said object destruction.
990
+ */
991
+ template <typename Func, typename WeakPtr, typename... Args>
992
+ class slot_tracked final : public slot_base<Args...> {
993
+ public:
994
+ template <typename F, typename P>
995
+ constexpr slot_tracked(cleanable &c, F && f, P && p, group_id gid)
996
+ : slot_base<Args...>(c, gid)
997
+ , func{std::forward<F>(f)}
998
+ , ptr{std::forward<P>(p)}
999
+ {}
1000
+
1001
+ bool connected() const noexcept override {
1002
+ return !ptr.expired() && slot_state::connected();
1003
+ }
1004
+
1005
+ protected:
1006
+ void call_slot(Args ...args) override {
1007
+ auto sp = ptr.lock();
1008
+ if (!sp) {
1009
+ slot_state::disconnect();
1010
+ return;
1011
+ }
1012
+ if (slot_state::connected()) {
1013
+ func(args...);
1014
+ }
1015
+ }
1016
+
1017
+ func_ptr get_callable() const noexcept override {
1018
+ return get_function_ptr(func);
1019
+ }
1020
+
1021
+ obj_ptr get_object() const noexcept override {
1022
+ return get_object_ptr(ptr);
1023
+ }
1024
+
1025
+ #ifdef SIGSLOT_RTTI_ENABLED
1026
+ const std::type_info& get_callable_type() const noexcept override {
1027
+ return typeid(func);
1028
+ }
1029
+ #endif
1030
+
1031
+ private:
1032
+ std::decay_t<Func> func;
1033
+ std::decay_t<WeakPtr> ptr;
1034
+ };
1035
+
1036
+ /*
1037
+ * An implementation of a slot as a pointer over member function, that tracks
1038
+ * the life of a supplied object through a weak pointer in order to automatically
1039
+ * disconnect the slot on said object destruction.
1040
+ */
1041
+ template <typename Pmf, typename WeakPtr, typename... Args>
1042
+ class slot_pmf_tracked final : public slot_base<Args...> {
1043
+ public:
1044
+ template <typename F, typename P>
1045
+ constexpr slot_pmf_tracked(cleanable &c, F && f, P && p, group_id gid)
1046
+ : slot_base<Args...>(c, gid)
1047
+ , pmf{std::forward<F>(f)}
1048
+ , ptr{std::forward<P>(p)}
1049
+ {}
1050
+
1051
+ bool connected() const noexcept override {
1052
+ return !ptr.expired() && slot_state::connected();
1053
+ }
1054
+
1055
+ protected:
1056
+ void call_slot(Args ...args) override {
1057
+ auto sp = ptr.lock();
1058
+ if (!sp) {
1059
+ slot_state::disconnect();
1060
+ return;
1061
+ }
1062
+ if (slot_state::connected()) {
1063
+ ((*sp).*pmf)(args...);
1064
+ }
1065
+ }
1066
+
1067
+ func_ptr get_callable() const noexcept override {
1068
+ return get_function_ptr(pmf);
1069
+ }
1070
+
1071
+ obj_ptr get_object() const noexcept override {
1072
+ return get_object_ptr(ptr);
1073
+ }
1074
+
1075
+ #ifdef SIGSLOT_RTTI_ENABLED
1076
+ const std::type_info& get_callable_type() const noexcept override {
1077
+ return typeid(pmf);
1078
+ }
1079
+ #endif
1080
+
1081
+ private:
1082
+ std::decay_t<Pmf> pmf;
1083
+ std::decay_t<WeakPtr> ptr;
1084
+ };
1085
+
1086
+ } // namespace detail
1087
+
1088
+
1089
+ /**
1090
+ * signal_base is an implementation of the observer pattern, through the use
1091
+ * of an emitting object and slots that are connected to the signal and called
1092
+ * with supplied arguments when a signal is emitted.
1093
+ *
1094
+ * signal_base is the general implementation, whose locking policy must be
1095
+ * set in order to decide thread safety guarantees. signal and signal_st
1096
+ * are partial specializations for multi-threaded and single-threaded use.
1097
+ *
1098
+ * It does not allow slots to return a value.
1099
+ *
1100
+ * Slot execution order can be constrained by assigning group ids to the slots.
1101
+ * The execution order of slots in a same group is unspecified and should not be
1102
+ * relied upon, however groups are executed in ascending group ids order. When
1103
+ * the group id of a slot is not set, it is assigned to the group 0. Group ids
1104
+ * can have any value in the range of signed 32 bit integers.
1105
+ *
1106
+ * @tparam Lockable a lock type to decide the lock policy
1107
+ * @tparam T... the argument types of the emitting and slots functions.
1108
+ */
1109
+ template <typename Lockable, typename... T>
1110
+ class signal_base final : public detail::cleanable {
1111
+ template <typename L>
1112
+ using is_thread_safe = std::integral_constant<bool, !std::is_same<L, detail::null_mutex>::value>;
1113
+
1114
+ template <typename U, typename L>
1115
+ using cow_type = std::conditional_t<is_thread_safe<L>::value,
1116
+ detail::copy_on_write<U>, U>;
1117
+
1118
+ template <typename U, typename L>
1119
+ using cow_copy_type = std::conditional_t<is_thread_safe<L>::value,
1120
+ detail::copy_on_write<U>, const U&>;
1121
+
1122
+ using lock_type = std::unique_lock<Lockable>;
1123
+ using slot_base = detail::slot_base<T...>;
1124
+ using slot_ptr = detail::slot_ptr<T...>;
1125
+ using slots_type = std::vector<slot_ptr>;
1126
+ struct group_type { slots_type slts; group_id gid; };
1127
+ using list_type = std::vector<group_type>; // kept ordered by ascending gid
1128
+
1129
+ public:
1130
+ using arg_list = trait::typelist<T...>;
1131
+ using ext_arg_list = trait::typelist<connection&, T...>;
1132
+
1133
+ signal_base() noexcept : m_block(false) {}
1134
+ ~signal_base() override {
1135
+ disconnect_all();
1136
+ }
1137
+
1138
+ signal_base(const signal_base&) = delete;
1139
+ signal_base & operator=(const signal_base&) = delete;
1140
+
1141
+ signal_base(signal_base && o) /* not noexcept */
1142
+ : m_block{o.m_block.load()}
1143
+ {
1144
+ lock_type lock(o.m_mutex);
1145
+ using std::swap;
1146
+ swap(m_slots, o.m_slots);
1147
+ }
1148
+
1149
+ signal_base & operator=(signal_base && o) /* not noexcept */ {
1150
+ lock_type lock1(m_mutex, std::defer_lock);
1151
+ lock_type lock2(o.m_mutex, std::defer_lock);
1152
+ std::lock(lock1, lock2);
1153
+
1154
+ using std::swap;
1155
+ swap(m_slots, o.m_slots);
1156
+ m_block.store(o.m_block.exchange(m_block.load()));
1157
+ return *this;
1158
+ }
1159
+
1160
+ /**
1161
+ * Emit a signal
1162
+ *
1163
+ * Effect: All non blocked and connected slot functions will be called
1164
+ * with supplied arguments.
1165
+ * Safety: With proper locking (see pal::signal), emission can happen from
1166
+ * multiple threads simultaneously. The guarantees only apply to the
1167
+ * signal object, it does not cover thread safety of potentially
1168
+ * shared state used in slot functions.
1169
+ *
1170
+ * @param a... arguments to emit
1171
+ */
1172
+ template <typename... U>
1173
+ void operator()(U && ...a) {
1174
+ if (m_block) {
1175
+ return;
1176
+ }
1177
+
1178
+ // Reference to the slots to execute them out of the lock
1179
+ // a copy may occur if another thread writes to it.
1180
+ cow_copy_type<list_type, Lockable> ref = slots_reference();
1181
+
1182
+ for (const auto &group : detail::cow_read(ref)) {
1183
+ for (const auto &s : group.slts) {
1184
+ s->operator()(a...);
1185
+ }
1186
+ }
1187
+ }
1188
+
1189
+ /**
1190
+ * Connect a callable of compatible arguments
1191
+ *
1192
+ * Effect: Creates and stores a new slot responsible for executing the
1193
+ * supplied callable for every subsequent signal emission.
1194
+ * Safety: Thread-safety depends on locking policy.
1195
+ *
1196
+ * @param c a callable
1197
+ * @param gid an identifier that can be used to order slot execution
1198
+ * @return a connection object that can be used to interact with the slot
1199
+ */
1200
+ template <typename Callable>
1201
+ std::enable_if_t<trait::is_callable_v<arg_list, Callable>, connection>
1202
+ connect(Callable && c, group_id gid = 0) {
1203
+ using slot_t = detail::slot<Callable, T...>;
1204
+ auto s = make_slot<slot_t>(std::forward<Callable>(c), gid);
1205
+ connection conn(s);
1206
+ add_slot(std::move(s));
1207
+ return conn;
1208
+ }
1209
+
1210
+ /**
1211
+ * Connect a callable with an additional connection argument
1212
+ *
1213
+ * The callable's first argument must be of type connection. This overload
1214
+ * the callable to manage it's own connection through this argument.
1215
+ *
1216
+ * @param c a callable
1217
+ * @param gid an identifier that can be used to order slot execution
1218
+ * @return a connection object that can be used to interact with the slot
1219
+ */
1220
+ template <typename Callable>
1221
+ std::enable_if_t<trait::is_callable_v<ext_arg_list, Callable>, connection>
1222
+ connect_extended(Callable && c, group_id gid = 0) {
1223
+ using slot_t = detail::slot_extended<Callable, T...>;
1224
+ auto s = make_slot<slot_t>(std::forward<Callable>(c), gid);
1225
+ connection conn(s);
1226
+ std::static_pointer_cast<slot_t>(s)->conn = conn;
1227
+ add_slot(std::move(s));
1228
+ return conn;
1229
+ }
1230
+
1231
+ /**
1232
+ * Overload of connect for pointers over member functions derived from
1233
+ * observer
1234
+ *
1235
+ * @param pmf a pointer over member function
1236
+ * @param ptr an object pointer derived from observer
1237
+ * @param gid an identifier that can be used to order slot execution
1238
+ * @return a connection object that can be used to interact with the slot
1239
+ */
1240
+ template <typename Pmf, typename Ptr>
1241
+ std::enable_if_t<trait::is_callable_v<arg_list, Pmf, Ptr> &&
1242
+ trait::is_observer_v<Ptr>, connection>
1243
+ connect(Pmf && pmf, Ptr && ptr, group_id gid = 0) {
1244
+ using slot_t = detail::slot_pmf<Pmf, Ptr, T...>;
1245
+ auto s = make_slot<slot_t>(std::forward<Pmf>(pmf), std::forward<Ptr>(ptr), gid);
1246
+ connection conn(s);
1247
+ add_slot(std::move(s));
1248
+ ptr->add_connection(conn);
1249
+ return conn;
1250
+ }
1251
+
1252
+ /**
1253
+ * Overload of connect for pointers over member functions
1254
+ *
1255
+ * @param pmf a pointer over member function
1256
+ * @param ptr an object pointer
1257
+ * @param gid an identifier that can be used to order slot execution
1258
+ * @return a connection object that can be used to interact with the slot
1259
+ */
1260
+ template <typename Pmf, typename Ptr>
1261
+ std::enable_if_t<trait::is_callable_v<arg_list, Pmf, Ptr> &&
1262
+ !trait::is_observer_v<Ptr> &&
1263
+ !trait::is_weak_ptr_compatible_v<Ptr>, connection>
1264
+ connect(Pmf && pmf, Ptr && ptr, group_id gid = 0) {
1265
+ using slot_t = detail::slot_pmf<Pmf, Ptr, T...>;
1266
+ auto s = make_slot<slot_t>(std::forward<Pmf>(pmf), std::forward<Ptr>(ptr), gid);
1267
+ connection conn(s);
1268
+ add_slot(std::move(s));
1269
+ return conn;
1270
+ }
1271
+
1272
+ /**
1273
+ * Overload of connect for pointer over member functions and
1274
+ *
1275
+ * @param pmf a pointer over member function
1276
+ * @param ptr an object pointer
1277
+ * @param gid an identifier that can be used to order slot execution
1278
+ * @return a connection object that can be used to interact with the slot
1279
+ */
1280
+ template <typename Pmf, typename Ptr>
1281
+ std::enable_if_t<trait::is_callable_v<ext_arg_list, Pmf, Ptr> &&
1282
+ !trait::is_weak_ptr_compatible_v<Ptr>, connection>
1283
+ connect_extended(Pmf && pmf, Ptr && ptr, group_id gid = 0) {
1284
+ using slot_t = detail::slot_pmf_extended<Pmf, Ptr, T...>;
1285
+ auto s = make_slot<slot_t>(std::forward<Pmf>(pmf), std::forward<Ptr>(ptr), gid);
1286
+ connection conn(s);
1287
+ std::static_pointer_cast<slot_t>(s)->conn = conn;
1288
+ add_slot(std::move(s));
1289
+ return conn;
1290
+ }
1291
+
1292
+ /**
1293
+ * Overload of connect for lifetime object tracking and automatic disconnection
1294
+ *
1295
+ * Ptr must be convertible to an object following a loose form of weak pointer
1296
+ * concept, by implementing the ADL-detected conversion function to_weak().
1297
+ *
1298
+ * This overload covers the case of a pointer over member function and a
1299
+ * trackable pointer of that class.
1300
+ *
1301
+ * Note: only weak references are stored, a slot does not extend the lifetime
1302
+ * of a suppied object.
1303
+ *
1304
+ * @param pmf a pointer over member function
1305
+ * @param ptr a trackable object pointer
1306
+ * @param gid an identifier that can be used to order slot execution
1307
+ * @return a connection object that can be used to interact with the slot
1308
+ */
1309
+ template <typename Pmf, typename Ptr>
1310
+ std::enable_if_t<!trait::is_callable_v<arg_list, Pmf> &&
1311
+ trait::is_weak_ptr_compatible_v<Ptr>, connection>
1312
+ connect(Pmf && pmf, Ptr && ptr, group_id gid = 0) {
1313
+ using trait::to_weak;
1314
+ auto w = to_weak(std::forward<Ptr>(ptr));
1315
+ using slot_t = detail::slot_pmf_tracked<Pmf, decltype(w), T...>;
1316
+ auto s = make_slot<slot_t>(std::forward<Pmf>(pmf), w, gid);
1317
+ connection conn(s);
1318
+ add_slot(std::move(s));
1319
+ return conn;
1320
+ }
1321
+
1322
+ /**
1323
+ * Overload of connect for lifetime object tracking and automatic disconnection
1324
+ *
1325
+ * Trackable must be convertible to an object following a loose form of weak
1326
+ * pointer concept, by implementing the ADL-detected conversion function to_weak().
1327
+ *
1328
+ * This overload covers the case of a standalone callable and unrelated trackable
1329
+ * object.
1330
+ *
1331
+ * Note: only weak references are stored, a slot does not extend the lifetime
1332
+ * of a suppied object.
1333
+ *
1334
+ * @param c a callable
1335
+ * @param ptr a trackable object pointer
1336
+ * @param gid an identifier that can be used to order slot execution
1337
+ * @return a connection object that can be used to interact with the slot
1338
+ */
1339
+ template <typename Callable, typename Trackable>
1340
+ std::enable_if_t<trait::is_callable_v<arg_list, Callable> &&
1341
+ trait::is_weak_ptr_compatible_v<Trackable>, connection>
1342
+ connect(Callable && c, Trackable && ptr, group_id gid = 0) {
1343
+ using trait::to_weak;
1344
+ auto w = to_weak(std::forward<Trackable>(ptr));
1345
+ using slot_t = detail::slot_tracked<Callable, decltype(w), T...>;
1346
+ auto s = make_slot<slot_t>(std::forward<Callable>(c), w, gid);
1347
+ connection conn(s);
1348
+ add_slot(std::move(s));
1349
+ return conn;
1350
+ }
1351
+
1352
+ /**
1353
+ * Creates a connection whose duration is tied to the return object
1354
+ * Use the same semantics as connect
1355
+ */
1356
+ template <typename... CallArgs>
1357
+ scoped_connection connect_scoped(CallArgs && ...args) {
1358
+ return connect(std::forward<CallArgs>(args)...);
1359
+ }
1360
+
1361
+ /**
1362
+ * Disconnect slots bound to a callable
1363
+ *
1364
+ * Effect: Disconnects all the slots bound to the callable in argument.
1365
+ * Safety: Thread-safety depends on locking policy.
1366
+ *
1367
+ * If the callable is a free or static member function, this overload is always
1368
+ * available. However, RTTI is needed for it to work for pointer to member
1369
+ * functions, function objects or and (references to) lambdas, because the
1370
+ * C++ spec does not mandate the pointers to member functions to be unique.
1371
+ *
1372
+ * @param c a callable
1373
+ * @return the number of disconnected slots
1374
+ */
1375
+ template <typename Callable>
1376
+ std::enable_if_t<(trait::is_callable_v<arg_list, Callable> ||
1377
+ trait::is_callable_v<ext_arg_list, Callable> ||
1378
+ trait::is_pmf_v<Callable>) &&
1379
+ detail::function_traits<Callable>::is_disconnectable, size_t>
1380
+ disconnect(const Callable &c) {
1381
+ return disconnect_if([&] (const auto &s) {
1382
+ return s->has_full_callable(c);
1383
+ });
1384
+ }
1385
+
1386
+ /**
1387
+ * Disconnect slots bound to this object
1388
+ *
1389
+ * Effect: Disconnects all the slots bound to the object or tracked object
1390
+ * in argument.
1391
+ * Safety: Thread-safety depends on locking policy.
1392
+ *
1393
+ * The object may be a pointer or trackable object.
1394
+ *
1395
+ * @param obj an object
1396
+ * @return the number of disconnected slots
1397
+ */
1398
+ template <typename Obj>
1399
+ std::enable_if_t<!trait::is_callable_v<arg_list, Obj> &&
1400
+ !trait::is_callable_v<ext_arg_list, Obj> &&
1401
+ !trait::is_pmf_v<Obj>, size_t>
1402
+ disconnect(const Obj &obj) {
1403
+ return disconnect_if([&] (const auto &s) {
1404
+ return s->has_object(obj);
1405
+ });
1406
+ }
1407
+
1408
+ /**
1409
+ * Disconnect slots bound both to a callable and object
1410
+ *
1411
+ * Effect: Disconnects all the slots bound to the callable and object in argument.
1412
+ * Safety: Thread-safety depends on locking policy.
1413
+ *
1414
+ * For naked pointers, the Callable is expected to be a pointer over member
1415
+ * function. If obj is trackable, any kind of Callable can be used.
1416
+ *
1417
+ * @param c a callable
1418
+ * @param obj an object
1419
+ * @return the number of disconnected slots
1420
+ */
1421
+ template <typename Callable, typename Obj>
1422
+ size_t disconnect(const Callable &c, const Obj &obj) {
1423
+ return disconnect_if([&] (const auto &s) {
1424
+ return s->has_object(obj) && s->has_callable(c);
1425
+ });
1426
+ }
1427
+
1428
+ /**
1429
+ * Disconnect slots in a particular group
1430
+ *
1431
+ * Effect: Disconnects all the slots in the group id in argument.
1432
+ * Safety: Thread-safety depends on locking policy.
1433
+ *
1434
+ * @param gid a group id
1435
+ * @return the number of disconnected slots
1436
+ */
1437
+ size_t disconnect(group_id gid) {
1438
+ lock_type lock(m_mutex);
1439
+ for (auto &group : detail::cow_write(m_slots)) {
1440
+ if (group.gid == gid) {
1441
+ size_t count = group.slts.size();
1442
+ group.slts.clear();
1443
+ return count;
1444
+ }
1445
+ }
1446
+ return 0;
1447
+ }
1448
+
1449
+ /**
1450
+ * Disconnects all the slots
1451
+ * Safety: Thread safety depends on locking policy
1452
+ */
1453
+ void disconnect_all() {
1454
+ lock_type lock(m_mutex);
1455
+ clear();
1456
+ }
1457
+
1458
+ /**
1459
+ * Blocks signal emission
1460
+ * Safety: thread safe
1461
+ */
1462
+ void block() noexcept {
1463
+ m_block.store(true);
1464
+ }
1465
+
1466
+ /**
1467
+ * Unblocks signal emission
1468
+ * Safety: thread safe
1469
+ */
1470
+ void unblock() noexcept {
1471
+ m_block.store(false);
1472
+ }
1473
+
1474
+ /**
1475
+ * Tests blocking state of signal emission
1476
+ */
1477
+ bool blocked() const noexcept {
1478
+ return m_block.load();
1479
+ }
1480
+
1481
+ /**
1482
+ * Get number of connected slots
1483
+ * Safety: thread safe
1484
+ */
1485
+ size_t slot_count() noexcept {
1486
+ cow_copy_type<list_type, Lockable> ref = slots_reference();
1487
+ size_t count = 0;
1488
+ for (const auto &g : detail::cow_read(ref)) {
1489
+ count += g.slts.size();
1490
+ }
1491
+ return count;
1492
+ }
1493
+
1494
+ protected:
1495
+ /**
1496
+ * remove disconnected slots
1497
+ */
1498
+ void clean(detail::slot_state *state) override {
1499
+ lock_type lock(m_mutex);
1500
+ const auto idx = state->index();
1501
+ const auto gid = state->group();
1502
+
1503
+ // find the group
1504
+ for (auto &group : detail::cow_write(m_slots)) {
1505
+ if (group.gid == gid) {
1506
+ auto &slts = group.slts;
1507
+
1508
+ // ensure we have the right slot, in case of concurrent cleaning
1509
+ if (idx < slts.size() && slts[idx] && slts[idx].get() == state) {
1510
+ std::swap(slts[idx], slts.back());
1511
+ slts[idx]->index() = idx;
1512
+ slts.pop_back();
1513
+ }
1514
+
1515
+ return;
1516
+ }
1517
+ }
1518
+ }
1519
+
1520
+ private:
1521
+ // used to get a reference to the slots for reading
1522
+ inline cow_copy_type<list_type, Lockable> slots_reference() {
1523
+ lock_type lock(m_mutex);
1524
+ return m_slots;
1525
+ }
1526
+
1527
+ // create a new slot
1528
+ template <typename Slot, typename... A>
1529
+ inline auto make_slot(A && ...a) {
1530
+ return detail::make_shared<slot_base, Slot>(*this, std::forward<A>(a)...);
1531
+ }
1532
+
1533
+ // add the slot to the list of slots of the right group
1534
+ void add_slot(slot_ptr &&s) {
1535
+ const group_id gid = s->group();
1536
+
1537
+ lock_type lock(m_mutex);
1538
+ auto &groups = detail::cow_write(m_slots);
1539
+
1540
+ // find the group
1541
+ auto it = groups.begin();
1542
+ while (it != groups.end() && it->gid < gid) {
1543
+ it++;
1544
+ }
1545
+
1546
+ // create a new group if necessary
1547
+ if (it == groups.end() || it->gid != gid) {
1548
+ it = groups.insert(it, {{}, gid});
1549
+ }
1550
+
1551
+ // add the slot
1552
+ s->index() = it->slts.size();
1553
+ it->slts.push_back(std::move(s));
1554
+ }
1555
+
1556
+ // disconnect a slot if a condition occurs
1557
+ template <typename Cond>
1558
+ size_t disconnect_if(Cond && cond) {
1559
+ lock_type lock(m_mutex);
1560
+ auto &groups = detail::cow_write(m_slots);
1561
+
1562
+ size_t count = 0;
1563
+
1564
+ for (auto &group : groups) {
1565
+ auto &slts = group.slts;
1566
+ size_t i = 0;
1567
+ while (i < slts.size()) {
1568
+ if (cond(slts[i])) {
1569
+ std::swap(slts[i], slts.back());
1570
+ slts[i]->index() = i;
1571
+ slts.pop_back();
1572
+ ++count;
1573
+ } else {
1574
+ ++i;
1575
+ }
1576
+ }
1577
+ }
1578
+
1579
+ return count;
1580
+ }
1581
+
1582
+ // to be called under lock: remove all the slots
1583
+ void clear() {
1584
+ detail::cow_write(m_slots).clear();
1585
+ }
1586
+
1587
+ private:
1588
+ Lockable m_mutex;
1589
+ cow_type<list_type, Lockable> m_slots;
1590
+ std::atomic<bool> m_block;
1591
+ };
1592
+
1593
+ /**
1594
+ * Specialization of signal_base to be used in single threaded contexts.
1595
+ * Slot connection, disconnection and signal emission are not thread-safe.
1596
+ * The performance improvement over the thread-safe variant is not impressive,
1597
+ * so this is not very useful.
1598
+ */
1599
+ template <typename... T>
1600
+ using signal_st = signal_base<detail::null_mutex, T...>;
1601
+
1602
+ /**
1603
+ * Specialization of signal_base to be used in multi-threaded contexts.
1604
+ * Slot connection, disconnection and signal emission are thread-safe.
1605
+ *
1606
+ * Recursive signal emission and emission cycles are supported too.
1607
+ */
1608
+ template <typename... T>
1609
+ using signal = signal_base<std::mutex, T...>;
1610
+
1611
+ } // namespace sigslot
third-party/DPVO/Pangolin/components/pango_core/src/avx_math.cpp ADDED
@@ -0,0 +1,553 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /*
2
+ AVX implementation of sin, cos, sincos, exp and log
3
+
4
+ Based on "sse_mathfun.h", by Julien Pommier
5
+ http://gruntthepeon.free.fr/ssemath/
6
+
7
+ Copyright (C) 2012 Giovanni Garberoglio
8
+ Interdisciplinary Laboratory for Computational Science (LISC)
9
+ Fondazione Bruno Kessler and University of Trento
10
+ via Sommarive, 18
11
+ I-38123 Trento (Italy)
12
+
13
+ This software is provided 'as-is', without any express or implied
14
+ warranty. In no event will the authors be held liable for any damages
15
+ arising from the use of this software.
16
+
17
+ Permission is granted to anyone to use this software for any purpose,
18
+ including commercial applications, and to alter it and redistribute it
19
+ freely, subject to the following restrictions:
20
+
21
+ 1. The origin of this software must not be misrepresented; you must not
22
+ claim that you wrote the original software. If you use this software
23
+ in a product, an acknowledgment in the product documentation would be
24
+ appreciated but is not required.
25
+ 2. Altered source versions must be plainly marked as such, and must not be
26
+ misrepresented as being the original software.
27
+ 3. This notice may not be removed or altered from any source distribution.
28
+
29
+ (this is the zlib license)
30
+ */
31
+
32
+ /*
33
+ From: http://software-lisc.fbk.eu/avx_mathfun/
34
+ */
35
+
36
+ #include <pangolin/utils/avx_math.h>
37
+
38
+ #ifdef __AVX2__
39
+ namespace pangolin
40
+ {
41
+ /* yes I know, the top of this file is quite ugly */
42
+ #ifdef _MSC_VER
43
+ # define ALIGN32_BEG __declspec(align(32))
44
+ # define ALIGN32_END
45
+ #else
46
+ # define ALIGN32_BEG
47
+ # define ALIGN32_END __attribute__((aligned(32)))
48
+ #endif
49
+
50
+ /* declare some AVX constants -- why can't I figure a better way to do that? */
51
+ #define _PS256_CONST(Name, Val) \
52
+ static const ALIGN32_BEG float _ps256_##Name[8] ALIGN32_END = { Val, Val, Val, Val, Val, Val, Val, Val }
53
+ #define _PI32_CONST256(Name, Val) \
54
+ static const ALIGN32_BEG int _pi32_256_##Name[8] ALIGN32_END = { Val, Val, Val, Val, Val, Val, Val, Val }
55
+ #define _PS256_CONST_TYPE(Name, Type, Val) \
56
+ static const ALIGN32_BEG Type _ps256_##Name[8] ALIGN32_END = { Val, Val, Val, Val, Val, Val, Val, Val }
57
+
58
+ _PS256_CONST(1 , 1.0f);
59
+ _PS256_CONST(0p5, 0.5f);
60
+ /* the smallest non denormalized float number */
61
+
62
+ #ifdef __GNUC__
63
+ #pragma GCC diagnostic push
64
+ #pragma GCC diagnostic ignored "-Wnarrowing"
65
+ #endif
66
+ _PS256_CONST_TYPE(min_norm_pos, int, 0x00800000);
67
+ _PS256_CONST_TYPE(inv_mant_mask, int, ~0x7f800000);
68
+ _PS256_CONST_TYPE(sign_mask, int, 0x80000000);
69
+ _PS256_CONST_TYPE(inv_sign_mask, int, ~0x80000000);
70
+ #ifdef __GNUC__
71
+ #pragma GCC diagnostic pop
72
+ #endif
73
+
74
+ _PI32_CONST256(0, 0);
75
+ _PI32_CONST256(1, 1);
76
+ _PI32_CONST256(inv1, ~1);
77
+ _PI32_CONST256(2, 2);
78
+ _PI32_CONST256(4, 4);
79
+ _PI32_CONST256(0x7f, 0x7f);
80
+ _PI32_CONST256(signbit, 0x7FFFFFFF);
81
+
82
+ _PS256_CONST(cephes_SQRTHF, 0.707106781186547524);
83
+ _PS256_CONST(cephes_log_p0, 7.0376836292E-2);
84
+ _PS256_CONST(cephes_log_p1, - 1.1514610310E-1);
85
+ _PS256_CONST(cephes_log_p2, 1.1676998740E-1);
86
+ _PS256_CONST(cephes_log_p3, - 1.2420140846E-1);
87
+ _PS256_CONST(cephes_log_p4, + 1.4249322787E-1);
88
+ _PS256_CONST(cephes_log_p5, - 1.6668057665E-1);
89
+ _PS256_CONST(cephes_log_p6, + 2.0000714765E-1);
90
+ _PS256_CONST(cephes_log_p7, - 2.4999993993E-1);
91
+ _PS256_CONST(cephes_log_p8, + 3.3333331174E-1);
92
+ _PS256_CONST(cephes_log_q1, -2.12194440e-4);
93
+ _PS256_CONST(cephes_log_q2, 0.693359375);
94
+
95
+ /* natural logarithm computed for 8 simultaneous float
96
+ return NaN for x <= 0
97
+ */
98
+ __m256 log256_ps(__m256 x) {
99
+ __m256i imm0;
100
+ __m256 one = *(__m256*)_ps256_1;
101
+
102
+ //__m256 invalid_mask = _mm256_cmple_ps(x, _mm256_setzero_ps());
103
+ __m256 invalid_mask = _mm256_cmp_ps(x, _mm256_setzero_ps(), _CMP_LE_OS);
104
+
105
+ x = _mm256_max_ps(x, *(__m256*)_ps256_min_norm_pos); /* cut off denormalized stuff */
106
+
107
+ // can be done with AVX2
108
+ imm0 = _mm256_srli_epi32(_mm256_castps_si256(x), 23);
109
+
110
+ /* keep only the fractional part */
111
+ x = _mm256_and_ps(x, *(__m256*)_ps256_inv_mant_mask);
112
+ x = _mm256_or_ps(x, *(__m256*)_ps256_0p5);
113
+
114
+ // this is again another AVX2 instruction
115
+ imm0 = _mm256_sub_epi32(imm0, *(__m256i*)_pi32_256_0x7f);
116
+ __m256 e = _mm256_cvtepi32_ps(imm0);
117
+
118
+ e = _mm256_add_ps(e, one);
119
+
120
+ /* part2:
121
+ if( x < SQRTHF ) {
122
+ e -= 1;
123
+ x = x + x - 1.0;
124
+ } else { x = x - 1.0; }
125
+ */
126
+ //__m256 mask = _mm256_cmplt_ps(x, *(__m256*)_ps256_cephes_SQRTHF);
127
+ __m256 mask = _mm256_cmp_ps(x, *(__m256*)_ps256_cephes_SQRTHF, _CMP_LT_OS);
128
+ __m256 tmp = _mm256_and_ps(x, mask);
129
+ x = _mm256_sub_ps(x, one);
130
+ e = _mm256_sub_ps(e, _mm256_and_ps(one, mask));
131
+ x = _mm256_add_ps(x, tmp);
132
+
133
+ __m256 z = _mm256_mul_ps(x,x);
134
+
135
+ __m256 y = *(__m256*)_ps256_cephes_log_p0;
136
+ y = _mm256_mul_ps(y, x);
137
+ y = _mm256_add_ps(y, *(__m256*)_ps256_cephes_log_p1);
138
+ y = _mm256_mul_ps(y, x);
139
+ y = _mm256_add_ps(y, *(__m256*)_ps256_cephes_log_p2);
140
+ y = _mm256_mul_ps(y, x);
141
+ y = _mm256_add_ps(y, *(__m256*)_ps256_cephes_log_p3);
142
+ y = _mm256_mul_ps(y, x);
143
+ y = _mm256_add_ps(y, *(__m256*)_ps256_cephes_log_p4);
144
+ y = _mm256_mul_ps(y, x);
145
+ y = _mm256_add_ps(y, *(__m256*)_ps256_cephes_log_p5);
146
+ y = _mm256_mul_ps(y, x);
147
+ y = _mm256_add_ps(y, *(__m256*)_ps256_cephes_log_p6);
148
+ y = _mm256_mul_ps(y, x);
149
+ y = _mm256_add_ps(y, *(__m256*)_ps256_cephes_log_p7);
150
+ y = _mm256_mul_ps(y, x);
151
+ y = _mm256_add_ps(y, *(__m256*)_ps256_cephes_log_p8);
152
+ y = _mm256_mul_ps(y, x);
153
+
154
+ y = _mm256_mul_ps(y, z);
155
+
156
+ tmp = _mm256_mul_ps(e, *(__m256*)_ps256_cephes_log_q1);
157
+ y = _mm256_add_ps(y, tmp);
158
+
159
+
160
+ tmp = _mm256_mul_ps(z, *(__m256*)_ps256_0p5);
161
+ y = _mm256_sub_ps(y, tmp);
162
+
163
+ tmp = _mm256_mul_ps(e, *(__m256*)_ps256_cephes_log_q2);
164
+ x = _mm256_add_ps(x, y);
165
+ x = _mm256_add_ps(x, tmp);
166
+ x = _mm256_or_ps(x, invalid_mask); // negative arg will be NAN
167
+ return x;
168
+ }
169
+
170
+ _PS256_CONST(exp_hi, 88.3762626647949f);
171
+ _PS256_CONST(exp_lo, -88.3762626647949f);
172
+
173
+ _PS256_CONST(cephes_LOG2EF, 1.44269504088896341);
174
+ _PS256_CONST(cephes_exp_C1, 0.693359375);
175
+ _PS256_CONST(cephes_exp_C2, -2.12194440e-4);
176
+
177
+ _PS256_CONST(cephes_exp_p0, 1.9875691500E-4);
178
+ _PS256_CONST(cephes_exp_p1, 1.3981999507E-3);
179
+ _PS256_CONST(cephes_exp_p2, 8.3334519073E-3);
180
+ _PS256_CONST(cephes_exp_p3, 4.1665795894E-2);
181
+ _PS256_CONST(cephes_exp_p4, 1.6666665459E-1);
182
+ _PS256_CONST(cephes_exp_p5, 5.0000001201E-1);
183
+
184
+ __m256 exp256_ps(__m256 x) {
185
+ __m256 tmp = _mm256_setzero_ps(), fx;
186
+ __m256i imm0;
187
+ __m256 one = *(__m256*)_ps256_1;
188
+
189
+ x = _mm256_min_ps(x, *(__m256*)_ps256_exp_hi);
190
+ x = _mm256_max_ps(x, *(__m256*)_ps256_exp_lo);
191
+
192
+ /* express exp(x) as exp(g + n*log(2)) */
193
+ fx = _mm256_mul_ps(x, *(__m256*)_ps256_cephes_LOG2EF);
194
+ fx = _mm256_add_ps(fx, *(__m256*)_ps256_0p5);
195
+
196
+ /* how to perform a floorf with SSE: just below */
197
+ //imm0 = _mm256_cvttps_epi32(fx);
198
+ //tmp = _mm256_cvtepi32_ps(imm0);
199
+
200
+ tmp = _mm256_floor_ps(fx);
201
+
202
+ /* if greater, substract 1 */
203
+ //__m256 mask = _mm256_cmpgt_ps(tmp, fx);
204
+ __m256 mask = _mm256_cmp_ps(tmp, fx, _CMP_GT_OS);
205
+ mask = _mm256_and_ps(mask, one);
206
+ fx = _mm256_sub_ps(tmp, mask);
207
+
208
+ tmp = _mm256_mul_ps(fx, *(__m256*)_ps256_cephes_exp_C1);
209
+ __m256 z = _mm256_mul_ps(fx, *(__m256*)_ps256_cephes_exp_C2);
210
+ x = _mm256_sub_ps(x, tmp);
211
+ x = _mm256_sub_ps(x, z);
212
+
213
+ z = _mm256_mul_ps(x,x);
214
+
215
+ __m256 y = *(__m256*)_ps256_cephes_exp_p0;
216
+ y = _mm256_mul_ps(y, x);
217
+ y = _mm256_add_ps(y, *(__m256*)_ps256_cephes_exp_p1);
218
+ y = _mm256_mul_ps(y, x);
219
+ y = _mm256_add_ps(y, *(__m256*)_ps256_cephes_exp_p2);
220
+ y = _mm256_mul_ps(y, x);
221
+ y = _mm256_add_ps(y, *(__m256*)_ps256_cephes_exp_p3);
222
+ y = _mm256_mul_ps(y, x);
223
+ y = _mm256_add_ps(y, *(__m256*)_ps256_cephes_exp_p4);
224
+ y = _mm256_mul_ps(y, x);
225
+ y = _mm256_add_ps(y, *(__m256*)_ps256_cephes_exp_p5);
226
+ y = _mm256_mul_ps(y, z);
227
+ y = _mm256_add_ps(y, x);
228
+ y = _mm256_add_ps(y, one);
229
+
230
+ /* build 2^n */
231
+ imm0 = _mm256_cvttps_epi32(fx);
232
+ // another two AVX2 instructions
233
+ imm0 = _mm256_add_epi32(imm0, *(__m256i*)_pi32_256_0x7f);
234
+ imm0 = _mm256_slli_epi32(imm0, 23);
235
+ __m256 pow2n = _mm256_castsi256_ps(imm0);
236
+ y = _mm256_mul_ps(y, pow2n);
237
+ return y;
238
+ }
239
+
240
+ _PS256_CONST(minus_cephes_DP1, -0.78515625);
241
+ _PS256_CONST(minus_cephes_DP2, -2.4187564849853515625e-4);
242
+ _PS256_CONST(minus_cephes_DP3, -3.77489497744594108e-8);
243
+ _PS256_CONST(sincof_p0, -1.9515295891E-4);
244
+ _PS256_CONST(sincof_p1, 8.3321608736E-3);
245
+ _PS256_CONST(sincof_p2, -1.6666654611E-1);
246
+ _PS256_CONST(coscof_p0, 2.443315711809948E-005);
247
+ _PS256_CONST(coscof_p1, -1.388731625493765E-003);
248
+ _PS256_CONST(coscof_p2, 4.166664568298827E-002);
249
+ _PS256_CONST(cephes_FOPI, 1.27323954473516); // 4 / M_PI
250
+
251
+
252
+ /* evaluation of 8 sines at onces using AVX intrisics
253
+
254
+ The code is the exact rewriting of the cephes sinf function.
255
+ Precision is excellent as long as x < 8192 (I did not bother to
256
+ take into account the special handling they have for greater values
257
+ -- it does not return garbage for arguments over 8192, though, but
258
+ the extra precision is missing).
259
+
260
+ Note that it is such that sinf((float)M_PI) = 8.74e-8, which is the
261
+ surprising but correct result.
262
+
263
+ */
264
+ __m256 sin256_ps(__m256 x) { // any x
265
+ __m256 xmm1, xmm2 = _mm256_setzero_ps(), xmm3, sign_bit, y;
266
+ __m256i imm0, imm2;
267
+
268
+ sign_bit = x;
269
+ /* take the absolute value */
270
+ x = _mm256_and_ps(x, *(__m256*)_ps256_inv_sign_mask);
271
+ /* extract the sign bit (upper one) */
272
+ sign_bit = _mm256_and_ps(sign_bit, *(__m256*)_ps256_sign_mask);
273
+
274
+ /* scale by 4/Pi */
275
+ y = _mm256_mul_ps(x, *(__m256*)_ps256_cephes_FOPI);
276
+
277
+ /*
278
+ Here we start a series of integer operations, which are in the
279
+ realm of AVX2.
280
+ If we don't have AVX, let's perform them using SSE2 directives
281
+ */
282
+
283
+ /* store the integer part of y in mm0 */
284
+ imm2 = _mm256_cvttps_epi32(y);
285
+ /* j=(j+1) & (~1) (see the cephes sources) */
286
+ // another two AVX2 instruction
287
+ imm2 = _mm256_add_epi32(imm2, *(__m256i*)_pi32_256_1);
288
+ imm2 = _mm256_and_si256(imm2, *(__m256i*)_pi32_256_inv1);
289
+ y = _mm256_cvtepi32_ps(imm2);
290
+
291
+ /* get the swap sign flag */
292
+ imm0 = _mm256_and_si256(imm2, *(__m256i*)_pi32_256_4);
293
+ imm0 = _mm256_slli_epi32(imm0, 29);
294
+ /* get the polynom selection mask
295
+ there is one polynom for 0 <= x <= Pi/4
296
+ and another one for Pi/4<x<=Pi/2
297
+
298
+ Both branches will be computed.
299
+ */
300
+ imm2 = _mm256_and_si256(imm2, *(__m256i*)_pi32_256_2);
301
+ imm2 = _mm256_cmpeq_epi32(imm2,*(__m256i*)_pi32_256_0);
302
+
303
+ __m256 swap_sign_bit = _mm256_castsi256_ps(imm0);
304
+ __m256 poly_mask = _mm256_castsi256_ps(imm2);
305
+ sign_bit = _mm256_xor_ps(sign_bit, swap_sign_bit);
306
+
307
+ /* The magic pass: "Extended precision modular arithmetic"
308
+ x = ((x - y * DP1) - y * DP2) - y * DP3; */
309
+ xmm1 = *(__m256*)_ps256_minus_cephes_DP1;
310
+ xmm2 = *(__m256*)_ps256_minus_cephes_DP2;
311
+ xmm3 = *(__m256*)_ps256_minus_cephes_DP3;
312
+ xmm1 = _mm256_mul_ps(y, xmm1);
313
+ xmm2 = _mm256_mul_ps(y, xmm2);
314
+ xmm3 = _mm256_mul_ps(y, xmm3);
315
+ x = _mm256_add_ps(x, xmm1);
316
+ x = _mm256_add_ps(x, xmm2);
317
+ x = _mm256_add_ps(x, xmm3);
318
+
319
+ /* Evaluate the first polynom (0 <= x <= Pi/4) */
320
+ y = *(__m256*)_ps256_coscof_p0;
321
+ __m256 z = _mm256_mul_ps(x,x);
322
+
323
+ y = _mm256_mul_ps(y, z);
324
+ y = _mm256_add_ps(y, *(__m256*)_ps256_coscof_p1);
325
+ y = _mm256_mul_ps(y, z);
326
+ y = _mm256_add_ps(y, *(__m256*)_ps256_coscof_p2);
327
+ y = _mm256_mul_ps(y, z);
328
+ y = _mm256_mul_ps(y, z);
329
+ __m256 tmp = _mm256_mul_ps(z, *(__m256*)_ps256_0p5);
330
+ y = _mm256_sub_ps(y, tmp);
331
+ y = _mm256_add_ps(y, *(__m256*)_ps256_1);
332
+
333
+ /* Evaluate the second polynom (Pi/4 <= x <= 0) */
334
+
335
+ __m256 y2 = *(__m256*)_ps256_sincof_p0;
336
+ y2 = _mm256_mul_ps(y2, z);
337
+ y2 = _mm256_add_ps(y2, *(__m256*)_ps256_sincof_p1);
338
+ y2 = _mm256_mul_ps(y2, z);
339
+ y2 = _mm256_add_ps(y2, *(__m256*)_ps256_sincof_p2);
340
+ y2 = _mm256_mul_ps(y2, z);
341
+ y2 = _mm256_mul_ps(y2, x);
342
+ y2 = _mm256_add_ps(y2, x);
343
+
344
+ /* select the correct result from the two polynoms */
345
+ xmm3 = poly_mask;
346
+ y2 = _mm256_and_ps(xmm3, y2); //, xmm3);
347
+ y = _mm256_andnot_ps(xmm3, y);
348
+ y = _mm256_add_ps(y,y2);
349
+ /* update the sign */
350
+ y = _mm256_xor_ps(y, sign_bit);
351
+
352
+ return y;
353
+ }
354
+
355
+ /* almost the same as sin_ps */
356
+ __m256 cos256_ps(__m256 x) { // any x
357
+ __m256 xmm1, xmm2 = _mm256_setzero_ps(), xmm3, y;
358
+ __m256i imm0, imm2;
359
+
360
+ /* take the absolute value */
361
+ x = _mm256_and_ps(x, *(__m256*)_ps256_inv_sign_mask);
362
+
363
+ /* scale by 4/Pi */
364
+ y = _mm256_mul_ps(x, *(__m256*)_ps256_cephes_FOPI);
365
+
366
+ /* store the integer part of y in mm0 */
367
+ imm2 = _mm256_cvttps_epi32(y);
368
+ /* j=(j+1) & (~1) (see the cephes sources) */
369
+ imm2 = _mm256_add_epi32(imm2, *(__m256i*)_pi32_256_1);
370
+ imm2 = _mm256_and_si256(imm2, *(__m256i*)_pi32_256_inv1);
371
+ y = _mm256_cvtepi32_ps(imm2);
372
+ imm2 = _mm256_sub_epi32(imm2, *(__m256i*)_pi32_256_2);
373
+
374
+ /* get the swap sign flag */
375
+ imm0 = _mm256_andnot_si256(imm2, *(__m256i*)_pi32_256_4);
376
+ imm0 = _mm256_slli_epi32(imm0, 29);
377
+ /* get the polynom selection mask */
378
+ imm2 = _mm256_and_si256(imm2, *(__m256i*)_pi32_256_2);
379
+ imm2 = _mm256_cmpeq_epi32(imm2, *(__m256i*)_pi32_256_0);
380
+
381
+ __m256 sign_bit = _mm256_castsi256_ps(imm0);
382
+ __m256 poly_mask = _mm256_castsi256_ps(imm2);
383
+
384
+ /* The magic pass: "Extended precision modular arithmetic"
385
+ x = ((x - y * DP1) - y * DP2) - y * DP3; */
386
+ xmm1 = *(__m256*)_ps256_minus_cephes_DP1;
387
+ xmm2 = *(__m256*)_ps256_minus_cephes_DP2;
388
+ xmm3 = *(__m256*)_ps256_minus_cephes_DP3;
389
+ xmm1 = _mm256_mul_ps(y, xmm1);
390
+ xmm2 = _mm256_mul_ps(y, xmm2);
391
+ xmm3 = _mm256_mul_ps(y, xmm3);
392
+ x = _mm256_add_ps(x, xmm1);
393
+ x = _mm256_add_ps(x, xmm2);
394
+ x = _mm256_add_ps(x, xmm3);
395
+
396
+ /* Evaluate the first polynom (0 <= x <= Pi/4) */
397
+ y = *(__m256*)_ps256_coscof_p0;
398
+ __m256 z = _mm256_mul_ps(x,x);
399
+
400
+ y = _mm256_mul_ps(y, z);
401
+ y = _mm256_add_ps(y, *(__m256*)_ps256_coscof_p1);
402
+ y = _mm256_mul_ps(y, z);
403
+ y = _mm256_add_ps(y, *(__m256*)_ps256_coscof_p2);
404
+ y = _mm256_mul_ps(y, z);
405
+ y = _mm256_mul_ps(y, z);
406
+ __m256 tmp = _mm256_mul_ps(z, *(__m256*)_ps256_0p5);
407
+ y = _mm256_sub_ps(y, tmp);
408
+ y = _mm256_add_ps(y, *(__m256*)_ps256_1);
409
+
410
+ /* Evaluate the second polynom (Pi/4 <= x <= 0) */
411
+
412
+ __m256 y2 = *(__m256*)_ps256_sincof_p0;
413
+ y2 = _mm256_mul_ps(y2, z);
414
+ y2 = _mm256_add_ps(y2, *(__m256*)_ps256_sincof_p1);
415
+ y2 = _mm256_mul_ps(y2, z);
416
+ y2 = _mm256_add_ps(y2, *(__m256*)_ps256_sincof_p2);
417
+ y2 = _mm256_mul_ps(y2, z);
418
+ y2 = _mm256_mul_ps(y2, x);
419
+ y2 = _mm256_add_ps(y2, x);
420
+
421
+ /* select the correct result from the two polynoms */
422
+ xmm3 = poly_mask;
423
+ y2 = _mm256_and_ps(xmm3, y2); //, xmm3);
424
+ y = _mm256_andnot_ps(xmm3, y);
425
+ y = _mm256_add_ps(y,y2);
426
+ /* update the sign */
427
+ y = _mm256_xor_ps(y, sign_bit);
428
+
429
+ return y;
430
+ }
431
+
432
+ /* since sin256_ps and cos256_ps are almost identical, sincos256_ps could replace both of them..
433
+ it is almost as fast, and gives you a free cosine with your sine */
434
+ void sincos256_ps(__m256 x, __m256 *s, __m256 *c) {
435
+
436
+ __m256 xmm1, xmm2, xmm3 = _mm256_setzero_ps(), sign_bit_sin, y;
437
+ __m256i imm0, imm2, imm4;
438
+
439
+ sign_bit_sin = x;
440
+ /* take the absolute value */
441
+ x = _mm256_and_ps(x, *(__m256*)_ps256_inv_sign_mask);
442
+ /* extract the sign bit (upper one) */
443
+ sign_bit_sin = _mm256_and_ps(sign_bit_sin, *(__m256*)_ps256_sign_mask);
444
+
445
+ /* scale by 4/Pi */
446
+ y = _mm256_mul_ps(x, *(__m256*)_ps256_cephes_FOPI);
447
+
448
+ /* store the integer part of y in imm2 */
449
+ imm2 = _mm256_cvttps_epi32(y);
450
+
451
+ /* j=(j+1) & (~1) (see the cephes sources) */
452
+ imm2 = _mm256_add_epi32(imm2, *(__m256i*)_pi32_256_1);
453
+ imm2 = _mm256_and_si256(imm2, *(__m256i*)_pi32_256_inv1);
454
+
455
+ y = _mm256_cvtepi32_ps(imm2);
456
+ imm4 = imm2;
457
+
458
+ /* get the swap sign flag for the sine */
459
+ imm0 = _mm256_and_si256(imm2, *(__m256i*)_pi32_256_4);
460
+ imm0 = _mm256_slli_epi32(imm0, 29);
461
+ //__m256 swap_sign_bit_sin = _mm256_castsi256_ps(imm0);
462
+
463
+ /* get the polynom selection mask for the sine*/
464
+ imm2 = _mm256_and_si256(imm2, *(__m256i*)_pi32_256_2);
465
+ imm2 = _mm256_cmpeq_epi32(imm2, *(__m256i*)_pi32_256_0);
466
+ //__m256 poly_mask = _mm256_castsi256_ps(imm2);
467
+
468
+ __m256 swap_sign_bit_sin = _mm256_castsi256_ps(imm0);
469
+ __m256 poly_mask = _mm256_castsi256_ps(imm2);
470
+
471
+ /* The magic pass: "Extended precision modular arithmetic"
472
+ x = ((x - y * DP1) - y * DP2) - y * DP3; */
473
+ xmm1 = *(__m256*)_ps256_minus_cephes_DP1;
474
+ xmm2 = *(__m256*)_ps256_minus_cephes_DP2;
475
+ xmm3 = *(__m256*)_ps256_minus_cephes_DP3;
476
+ xmm1 = _mm256_mul_ps(y, xmm1);
477
+ xmm2 = _mm256_mul_ps(y, xmm2);
478
+ xmm3 = _mm256_mul_ps(y, xmm3);
479
+ x = _mm256_add_ps(x, xmm1);
480
+ x = _mm256_add_ps(x, xmm2);
481
+ x = _mm256_add_ps(x, xmm3);
482
+
483
+ imm4 = _mm256_sub_epi32(imm4, *(__m256i*)_pi32_256_2);
484
+ imm4 = _mm256_andnot_si256(imm4, *(__m256i*)_pi32_256_4);
485
+ imm4 = _mm256_slli_epi32(imm4, 29);
486
+
487
+ __m256 sign_bit_cos = _mm256_castsi256_ps(imm4);
488
+
489
+ sign_bit_sin = _mm256_xor_ps(sign_bit_sin, swap_sign_bit_sin);
490
+
491
+ /* Evaluate the first polynom (0 <= x <= Pi/4) */
492
+ __m256 z = _mm256_mul_ps(x,x);
493
+ y = *(__m256*)_ps256_coscof_p0;
494
+
495
+ y = _mm256_mul_ps(y, z);
496
+ y = _mm256_add_ps(y, *(__m256*)_ps256_coscof_p1);
497
+ y = _mm256_mul_ps(y, z);
498
+ y = _mm256_add_ps(y, *(__m256*)_ps256_coscof_p2);
499
+ y = _mm256_mul_ps(y, z);
500
+ y = _mm256_mul_ps(y, z);
501
+ __m256 tmp = _mm256_mul_ps(z, *(__m256*)_ps256_0p5);
502
+ y = _mm256_sub_ps(y, tmp);
503
+ y = _mm256_add_ps(y, *(__m256*)_ps256_1);
504
+
505
+ /* Evaluate the second polynom (Pi/4 <= x <= 0) */
506
+
507
+ __m256 y2 = *(__m256*)_ps256_sincof_p0;
508
+ y2 = _mm256_mul_ps(y2, z);
509
+ y2 = _mm256_add_ps(y2, *(__m256*)_ps256_sincof_p1);
510
+ y2 = _mm256_mul_ps(y2, z);
511
+ y2 = _mm256_add_ps(y2, *(__m256*)_ps256_sincof_p2);
512
+ y2 = _mm256_mul_ps(y2, z);
513
+ y2 = _mm256_mul_ps(y2, x);
514
+ y2 = _mm256_add_ps(y2, x);
515
+
516
+ /* select the correct result from the two polynoms */
517
+ xmm3 = poly_mask;
518
+ __m256 ysin2 = _mm256_and_ps(xmm3, y2);
519
+ __m256 ysin1 = _mm256_andnot_ps(xmm3, y);
520
+ y2 = _mm256_sub_ps(y2,ysin2);
521
+ y = _mm256_sub_ps(y, ysin1);
522
+
523
+ xmm1 = _mm256_add_ps(ysin1,ysin2);
524
+ xmm2 = _mm256_add_ps(y,y2);
525
+
526
+ /* update the sign */
527
+ *s = _mm256_xor_ps(xmm1, sign_bit_sin);
528
+ *c = _mm256_xor_ps(xmm2, sign_bit_cos);
529
+ }
530
+
531
+ __m256 fabs256_ps(__m256 x) {
532
+ return _mm256_and_ps(x, *(__m256*)_pi32_256_signbit);
533
+ }
534
+
535
+ // I did not find any implementation
536
+ // that is as exact as sequential execution.
537
+ // Furthermore, there is none under a free
538
+ // license:
539
+ //
540
+ // http://jrfonseca.blogspot.de/2008/09/fast-sse2-pow-tables-or-polynomials.html
541
+ // http://www.dctsystems.co.uk/Software/power.html
542
+ //
543
+ // This implementation is the trivial
544
+ // reformulation a = x^y -> a = exp(y * ln(x))
545
+ __m256 pow256_ps(__m256 x, __m256 y)
546
+ {
547
+ const __m256 l = log256_ps(x);
548
+ const __m256 f = _mm256_mul_ps(l, y);
549
+ return exp256_ps(f);
550
+ }
551
+ }
552
+
553
+ #endif
third-party/DPVO/Pangolin/components/pango_core/src/dummy.cpp ADDED
File without changes
third-party/DPVO/Pangolin/components/pango_core/src/factory/factory_help.cpp ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <iomanip>
2
+ #include <numeric>
3
+ #include <limits>
4
+ #include <pangolin/factory/factory_help.h>
5
+ #include <pangolin/factory/factory_registry.h>
6
+
7
+ namespace pangolin {
8
+
9
+ void PrintSchemeHelp(std::ostream& out, bool color)
10
+ {
11
+ const std::string c_normal = color ? "\033[0m" : "";
12
+ const std::string c_bold = color ? "\033[1m" : "";
13
+ const std::string c_scheme = color ? "\033[36m" : "";
14
+ const std::string c_alias = color ? "\033[32m" : "";
15
+ const std::string c_params = color ? "\033[34m" : "";
16
+ const std::string c_param = color ? "\033[31m" : "";
17
+
18
+ out << c_bold << "Using Factory Schemes" << c_normal << std::endl << std::endl;
19
+
20
+ out << "The factory to use is specified in the 'scheme' portion of the URL. Any parameters the factory takes will be reset to default values." << std::endl;
21
+ out << " e.g. \"" << c_scheme << "scheme" << c_normal << "://" << c_normal << "\"" << std::endl;
22
+ out << std::endl;
23
+
24
+ out << "When a factory needs to choose a unique resource, it can be specified using the URI portion of the URL." << std::endl;
25
+ out << " e.g. \"" << c_scheme << "scheme" << c_normal << "://" << c_param << "uri" << c_normal << "\"" << std::endl;
26
+ out << std::endl;
27
+
28
+ out << "Parameters can be specified within square brackets to override defaults." << std::endl;
29
+ out << " e.g. \"" << c_scheme << "scheme" << c_normal << ":[";
30
+ out << c_param << "param1" << c_normal << "=" << c_alias << "value1" << c_normal << ",";
31
+ out << c_param << "param2" << c_normal << "=" << c_alias << "value2" << c_normal << ",...";
32
+ out << "]//" << c_param << "uri" << c_normal << "\"" << std::endl;
33
+ out << std::endl;
34
+ }
35
+
36
+ // assumes schemes is not empty
37
+ std::string HighestPriScheme(const std::map<FactoryInterface::Name,FactoryInterface::Precedence>& schemes)
38
+ {
39
+ FactoryInterface::Name best_name;
40
+ FactoryInterface::Precedence best_pri = std::numeric_limits<FactoryInterface::Precedence>::max();
41
+ for(const auto& scheme : schemes) {
42
+ if(scheme.second < best_pri) {
43
+ best_name = scheme.first;
44
+ best_pri = scheme.second;
45
+ }
46
+ }
47
+ return best_name;
48
+ }
49
+
50
+ void PrintFactoryDetails(std::ostream& out, const std::string name, const pangolin::FactoryInterface& f, HelpVerbosity level, size_t indent, bool color)
51
+ {
52
+ const std::string c_normal = color ? "\033[0m" : "";
53
+ const std::string c_scheme = color ? "\033[36m" : "";
54
+ const std::string c_alias = color ? "\033[32m" : "";
55
+ const std::string c_params = color ? "\033[34m" : "";
56
+ const std::string c_param = color ? "\033[31m" : "";
57
+
58
+ indent = std::max(indent, name.size());
59
+
60
+ out << c_scheme;
61
+ out << std::setw(indent);
62
+ out << name << c_normal;
63
+ out << "| " << f.Description() << std::endl;
64
+ if(level >= HelpVerbosity::SYNOPSIS) {
65
+ if(f.Schemes().size() > 1) {
66
+ out << std::setw(indent) << " " << "| ";
67
+ out << c_alias << "aliases: " << c_normal << "{";
68
+ for(const auto& s : f.Schemes()) {
69
+ out << c_scheme << s.first << c_normal << " (" << s.second << "); ";
70
+ }
71
+ out << "}" << std::endl;
72
+ }
73
+ }
74
+ if(level >= HelpVerbosity::PARAMS) {
75
+ if(f.Params().params.size()) {
76
+ out << std::setw(indent) << " " << "| ";
77
+ out << c_alias << "params: " << c_normal << std::endl;
78
+ for(auto& param : f.Params().params) {
79
+ out << std::setw(indent) << " " << "| ";
80
+ out << c_param << param.name_regex << c_normal << ":";
81
+ if(!param.default_value.empty()) {
82
+ out << " (default='" << param.default_value << "')";
83
+ }
84
+ out << std::endl;
85
+ out << std::setw(indent) << " " << "| ";
86
+ out << param.description << std::endl;
87
+ }
88
+ }
89
+ }
90
+ if(level >= HelpVerbosity::SYNOPSIS) {
91
+ std::cout << std::endl;
92
+ }
93
+ }
94
+
95
+ void PrintFactoryRegistryDetails(
96
+ std::ostream& out, const pangolin::FactoryRegistry& registry, std::type_index factory_type,
97
+ const std::string& scheme_filter, HelpVerbosity level, bool color
98
+ ) {
99
+ const std::string c_normal = color ? "\033[0m" : "";
100
+ const std::string c_bold = color ? "\033[1m" : "";
101
+
102
+ auto& factories = registry.GetFactories(factory_type);
103
+ std::vector<std::string> high_pri_names;
104
+ size_t longest_scheme = 0;
105
+ for(const auto& f : factories) {
106
+ const std::string scheme = HighestPriScheme(f->Schemes());
107
+ high_pri_names.push_back(scheme);
108
+ longest_scheme = std::max(longest_scheme, scheme.size());
109
+ }
110
+
111
+ // Create vector of indices which we will use to store alphabetical order
112
+ std::vector<size_t> order(factories.size());
113
+ std::iota(order.begin(), order.end(), 0);
114
+
115
+ std::sort(order.begin(), order.end(), [&](size_t lhs, size_t rhs){
116
+ return high_pri_names[lhs] < high_pri_names[rhs];
117
+ });
118
+
119
+ const std::string post = ":// ";
120
+ longest_scheme += post.size();
121
+
122
+ out << c_bold << "Factory Scheme List" << c_normal << std::endl << std::endl;
123
+
124
+ if(level >= HelpVerbosity::SYNOPSIS) {
125
+ out << "Factory schemes can be accessed through any of their named aliases (shown below). If multiple factories support the same scheme, the factory having the lowest scheme precedence (shown in brackets) will be used." << std::endl;
126
+ }
127
+ if(level >= HelpVerbosity::PARAMS) {
128
+ out << "Available parameters and their default values for the factories are also shown. Regular expressions may be used if the parameter itself can vary (see the examples)."<< std::endl;
129
+ }
130
+ out << "The following is a list of factory provided schemes:" << std::endl;
131
+
132
+ out << std::endl;
133
+
134
+ for(size_t idx : order) {
135
+ if(scheme_filter.empty() || factories[idx]->Schemes().count(scheme_filter) > 0) {
136
+ PrintFactoryDetails(out, high_pri_names[idx] + post, *factories[idx], level, longest_scheme, color);
137
+ }
138
+ }
139
+
140
+ if(level == 0) {
141
+ out << std::endl;
142
+ }
143
+ }
144
+
145
+ }
third-party/DPVO/Pangolin/components/pango_core/src/factory/factory_registry.cpp ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include "pangolin/factory/factory_registry.h"
2
+
3
+ namespace pangolin {
4
+
5
+ std::shared_ptr<FactoryRegistry> FactoryRegistry::I()
6
+ {
7
+ static std::shared_ptr<FactoryRegistry> registry(new FactoryRegistry());
8
+ return registry;
9
+ }
10
+
11
+ }
third-party/DPVO/Pangolin/components/pango_core/src/file_extension.cpp ADDED
@@ -0,0 +1,247 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2013 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include <pangolin/utils/file_extension.h>
29
+
30
+ #include <algorithm>
31
+ #include <fstream>
32
+ #include <string.h>
33
+
34
+ namespace pangolin
35
+ {
36
+
37
+ std::string ImageFileTypeToName(ImageFileType t)
38
+ {
39
+ switch(t)
40
+ {
41
+ case ImageFileTypePpm:
42
+ return "ppm";
43
+ case ImageFileTypeTga:
44
+ return "tga";
45
+ case ImageFileTypePng:
46
+ return "png";
47
+ case ImageFileTypeJpg:
48
+ return "jpg";
49
+ case ImageFileTypeTiff:
50
+ return "tiff";
51
+ case ImageFileTypeGif:
52
+ return "gif";
53
+ case ImageFileTypeExr:
54
+ return "exr";
55
+ case ImageFileTypeBmp:
56
+ return "bmp";
57
+ case ImageFileTypePango:
58
+ return "pango";
59
+ case ImageFileTypePvn:
60
+ return "pvn";
61
+ case ImageFileTypeVrs:
62
+ return "vrs";
63
+ case ImageFileTypePly:
64
+ return "ply";
65
+ case ImageFileTypeObj:
66
+ return "obj";
67
+ case ImageFileTypeArw:
68
+ return "arw";
69
+ case ImageFileTypeUnknown:
70
+ default:
71
+ return "unknown";
72
+ }
73
+ }
74
+
75
+ ImageFileType NameToImageFileType(const std::string& name)
76
+ {
77
+ if ("ppm" == name)
78
+ return ImageFileTypePpm;
79
+ else if ("pgm" == name)
80
+ return ImageFileTypePpm;
81
+ else if ("tga" == name)
82
+ return ImageFileTypeTga;
83
+ else if ("png" == name)
84
+ return ImageFileTypePng;
85
+ else if ("jpg" == name)
86
+ return ImageFileTypeJpg;
87
+ else if ("jpeg" == name)
88
+ return ImageFileTypeJpg;
89
+ else if ("tiff" == name)
90
+ return ImageFileTypeTiff;
91
+ else if ("gif" == name)
92
+ return ImageFileTypeGif;
93
+ else if ("exr" == name)
94
+ return ImageFileTypeExr;
95
+ else if ("bmp" == name)
96
+ return ImageFileTypeBmp;
97
+ else if ("pango" == name)
98
+ return ImageFileTypePango;
99
+ else if ("pvn" == name)
100
+ return ImageFileTypePvn;
101
+ else if ("vrs" == name)
102
+ return ImageFileTypeVrs;
103
+ else if ("zstd" == name)
104
+ return ImageFileTypeZstd;
105
+ else if ("lzf" == name)
106
+ return ImageFileTypeLz4;
107
+ else if ("p12b" == name)
108
+ return ImageFileTypeP12b;
109
+ else if ("ply" == name)
110
+ return ImageFileTypePly;
111
+ else if ("obj" == name)
112
+ return ImageFileTypeObj;
113
+ else if ("arw" == name)
114
+ return ImageFileTypeArw;
115
+
116
+ return ImageFileTypeUnknown;
117
+ }
118
+
119
+ ImageFileType FileTypeExtension(const std::string& ext)
120
+ {
121
+ if( ext == ".png" ) {
122
+ return ImageFileTypePng;
123
+ } else if( ext == ".tga" || ext == ".targa") {
124
+ return ImageFileTypeTga;
125
+ } else if( ext == ".jpg" || ext == ".jpeg" ) {
126
+ return ImageFileTypeJpg;
127
+ } else if( ext == ".gif" ) {
128
+ return ImageFileTypeGif;
129
+ } else if( ext == ".tif" || ext == ".tiff" ) {
130
+ return ImageFileTypeTiff;
131
+ } else if( ext == ".exr" ) {
132
+ return ImageFileTypeExr;
133
+ } else if( ext == ".bmp" ) {
134
+ return ImageFileTypeBmp;
135
+ } else if( ext == ".ppm" || ext == ".pgm" || ext == ".pbm" || ext == ".pxm" || ext == ".pdm" ) {
136
+ return ImageFileTypePpm;
137
+ } else if( ext == ".pvn" ) {
138
+ return ImageFileTypePvn;
139
+ } else if( ext == ".vrs" ) {
140
+ return ImageFileTypeVrs;
141
+ } else if( ext == ".pango" ) {
142
+ return ImageFileTypePango;
143
+ } else if( ext == ".zstd" ) {
144
+ return ImageFileTypeZstd;
145
+ } else if( ext == ".lzf" ) {
146
+ return ImageFileTypeLz4;
147
+ } else if( ext == ".p12b" ) {
148
+ return ImageFileTypeP12b;
149
+ } else if( ext == ".ply" ) {
150
+ return ImageFileTypePly;
151
+ } else if( ext == ".obj" ) {
152
+ return ImageFileTypeObj;
153
+ } else if( ext == ".ARW" ) {
154
+ return ImageFileTypeArw;
155
+ } else {
156
+ return ImageFileTypeUnknown;
157
+ }
158
+ }
159
+
160
+ std::string FileLowercaseExtention(const std::string& filename)
161
+ {
162
+ size_t pos = filename.find_last_of('.');
163
+ if(pos != std::string::npos) {
164
+ std::string ext = filename.substr(pos);
165
+ std::transform( ext.begin(), ext.end(), ext.begin(), tolower );
166
+ return ext;
167
+ }else{
168
+ return "";
169
+ }
170
+ }
171
+
172
+ ImageFileType FileTypeMagic(const unsigned char data[], size_t bytes)
173
+ {
174
+ // Check we wont go over bounds when comparing.
175
+ if(bytes >= 8) {
176
+ const unsigned char magic_png[] = "\211PNG\r\n\032\n";
177
+ const unsigned char magic_jpg1[] = "\xFF\xD8";
178
+ const unsigned char magic_jpg2[] = "\xFF\xD9";
179
+ const unsigned char magic_gif1[] = "GIF87a";
180
+ const unsigned char magic_gif2[] = "GIF89a";
181
+ const unsigned char magic_tiff1[] = "\x49\x49\x2A\x00";
182
+ const unsigned char magic_tiff2[] = "\x4D\x4D\x00\x2A";
183
+ const unsigned char magic_exr[] = "\x76\x2F\x31\x01";
184
+ const unsigned char magic_bmp[] = "BM";
185
+ const unsigned char magic_pango[] = "PANGO";
186
+ const unsigned char magic_pango_zstd[] = "ZSTD";
187
+ const unsigned char magic_pango_lz4[] = "LZ4";
188
+ const unsigned char magic_pango_p12b[] = "P12B";
189
+ const unsigned char magic_vrs[] = "VisionR";
190
+ const unsigned char magic_ply[] = "ply";
191
+
192
+ if( !strncmp((char*)data, (char*)magic_png, 8) ) {
193
+ return ImageFileTypePng;
194
+ }else if( !strncmp( (char*)data, (char*)magic_jpg1, 2)
195
+ || !strncmp( (char*)data, (char*)magic_jpg2, 2) ) {
196
+ return ImageFileTypeJpg;
197
+ }else if( !strncmp((char*)data, (char*)magic_gif1,6)
198
+ || !strncmp((char*)data, (char*)magic_gif2,6) ) {
199
+ return ImageFileTypeGif;
200
+ }else if( !strncmp((char*)data, (char*)magic_tiff1,4)
201
+ || !strncmp((char*)data, (char*)magic_tiff2,4) ) {
202
+ return ImageFileTypeTiff;
203
+ }else if( !strncmp((char*)data, (char*)magic_exr,4) ) {
204
+ return ImageFileTypeExr;
205
+ }else if( !strncmp((char*)data, (char*)magic_bmp,2) ) {
206
+ return ImageFileTypeBmp;
207
+ }else if( !strncmp((char*)data, (char*)magic_pango,5) ) {
208
+ return ImageFileTypePango;
209
+ }else if( !strncmp((char*)data, (char*)magic_vrs,7) ) {
210
+ return ImageFileTypeVrs;
211
+ }else if( !strncmp((char*)data, (char*)magic_pango_zstd,4) ) {
212
+ return ImageFileTypeZstd;
213
+ }else if( !strncmp((char*)data, (char*)magic_pango_lz4,3) ) {
214
+ return ImageFileTypeLz4;
215
+ }else if( !strncmp((char*)data, (char*)magic_pango_p12b,4) ) {
216
+ return ImageFileTypeP12b;
217
+ }else if( !strncmp((char*)data, (char*)magic_ply, 3) ) {
218
+ return ImageFileTypePly;
219
+ }else if( data[0] == 'P' && '0' < data[1] && data[1] < '9') {
220
+ return ImageFileTypePpm;
221
+ }
222
+ }
223
+ return ImageFileTypeUnknown;
224
+ }
225
+
226
+ ImageFileType FileType(const std::string& filename)
227
+ {
228
+ // Check magic number of file...
229
+ std::ifstream f(filename.c_str(), std::ios::binary );
230
+ if(f.is_open()) {
231
+ const size_t magic_bytes = 8;
232
+ unsigned char magic[magic_bytes];
233
+ f.read((char*)magic, magic_bytes);
234
+ if(f.good()) {
235
+ ImageFileType magic_type = FileTypeMagic(magic, magic_bytes);
236
+ if(magic_type != ImageFileTypeUnknown) {
237
+ return magic_type;
238
+ }
239
+ }
240
+ }
241
+
242
+ // Fallback on using extension...
243
+ const std::string ext = FileLowercaseExtention(filename);
244
+ return FileTypeExtension(ext);
245
+ }
246
+
247
+ }
third-party/DPVO/Pangolin/components/pango_core/src/file_utils.cpp ADDED
@@ -0,0 +1,544 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2013 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include <pangolin/platform.h>
29
+
30
+ #include <pangolin/utils/file_utils.h>
31
+
32
+ #ifdef _WIN_
33
+ # ifndef WIN32_LEAN_AND_MEAN
34
+ # define WIN32_LEAN_AND_MEAN
35
+ # endif
36
+ # include <Windows.h>
37
+ # include <Shlobj.h>
38
+ # ifdef UNICODE
39
+ # include <codecvt>
40
+ # endif
41
+ #else
42
+ # include <dirent.h>
43
+ # include <sys/types.h>
44
+ # include <sys/stat.h>
45
+ # include <sys/signal.h>
46
+ # include <stdio.h>
47
+ # include <string.h>
48
+ # include <unistd.h>
49
+ # include <fcntl.h>
50
+ # include <errno.h>
51
+ # include <poll.h>
52
+ #endif // _WIN_
53
+
54
+ #include <algorithm>
55
+ #include <sstream>
56
+ #include <fstream>
57
+ #include <list>
58
+ #include <NaturalSort/natural_sort.hpp>
59
+
60
+ namespace pangolin
61
+ {
62
+
63
+ std::vector<std::string>& Split(const std::string& s, char delim, std::vector<std::string>& elements) {
64
+ std::stringstream ss(s);
65
+ std::string item;
66
+ while (std::getline(ss, item, delim)) {
67
+ elements.push_back(item);
68
+ }
69
+ return elements;
70
+ }
71
+
72
+ std::vector<std::string> Split(const std::string &s, char delim) {
73
+ std::vector<std::string> elems;
74
+ return Split(s, delim, elems);
75
+ }
76
+
77
+ std::vector<std::string> Expand(const std::string &s, char open, char close, char delim)
78
+ {
79
+ const size_t no = s.find_first_of(open);
80
+ if(no != std::string::npos) {
81
+ const size_t nc = s.find_first_of(close, no);
82
+ if(no != std::string::npos) {
83
+ const std::string pre = s.substr(0, no);
84
+ const std::string mid = s.substr(no+1, nc-no-1);
85
+ const std::string post = s.substr(nc+1, std::string::npos);
86
+ const std::vector<std::string> options = Split(mid, delim);
87
+ std::vector<std::string> expansion;
88
+
89
+ for(std::vector<std::string>::const_iterator iop = options.begin(); iop != options.end(); ++iop)
90
+ {
91
+ std::string full = pre + *iop + post;
92
+ expansion.push_back(full);
93
+ }
94
+ return expansion;
95
+ }
96
+ // Open but no close is unusual. Leave it for caller to see if valid
97
+ }
98
+
99
+ std::vector<std::string> ret;
100
+ ret.push_back(s);
101
+ return ret;
102
+ }
103
+
104
+ // Make path seperator consistent for OS.
105
+ void PathOsNormaliseInplace(std::string& path)
106
+ {
107
+ #ifdef _WIN_
108
+ std::replace(path.begin(), path.end(), '/', '\\');
109
+ #else
110
+ std::replace(path.begin(), path.end(), '\\', '/');
111
+ #endif
112
+ }
113
+
114
+ std::string SanitizePath(const std::string& path)
115
+ {
116
+ std::string path_copy(path.length(), '\0');
117
+
118
+ int p_slash1 = -1;
119
+ int p_slash0 = -1;
120
+ int n_dots = 0;
121
+
122
+ int dst = 0;
123
+ for(int src=0; src < (int)path.length(); ++src) {
124
+ if(path[src] == '/') {
125
+ if(n_dots==1 && p_slash0 >=0) {
126
+ dst = p_slash0;
127
+ for(p_slash1=p_slash0-1; p_slash1>=0 && path_copy[p_slash1] != '/'; --p_slash1);
128
+ }else if(n_dots==2) {
129
+ if(p_slash1 >=0) {
130
+ dst = p_slash1;
131
+ p_slash0 = dst;
132
+ for(p_slash1=p_slash0-1; p_slash1>=0 && path_copy[p_slash1] != '/'; --p_slash1) {
133
+ if( path_copy[p_slash1] == '.' ) {
134
+ p_slash1=-1;
135
+ break;
136
+ }
137
+ }
138
+ }else{
139
+ p_slash1 = -1;
140
+ p_slash0 = dst;
141
+ }
142
+ }else{
143
+ p_slash1 = p_slash0;
144
+ p_slash0 = dst;
145
+ }
146
+ n_dots = 0;
147
+ }else if(path[src] == '.' ){
148
+ if((dst-p_slash0) == n_dots+1) {
149
+ ++n_dots;
150
+ }
151
+ }else{
152
+ n_dots = 0;
153
+ }
154
+ path_copy[dst++] = path[src];
155
+ }
156
+
157
+ return path_copy.substr(0,dst);
158
+ }
159
+
160
+ // Return path 'levels' directories above 'path'
161
+ std::string PathParent(const std::string& path, int levels)
162
+ {
163
+ std::string res = path;
164
+
165
+ while (levels > 0) {
166
+ if (res.length() == 0) {
167
+ res = std::string();
168
+ for (int l = 0; l < levels; ++l) {
169
+ #ifdef _WIN_
170
+ res += std::string("..\\");
171
+ #else
172
+ res += std::string("../");
173
+ #endif
174
+ }
175
+ return res;
176
+ }else{
177
+ const size_t nLastSlash = res.find_last_of("/\\");
178
+
179
+ if (nLastSlash != std::string::npos) {
180
+ res = path.substr(0, nLastSlash);
181
+ } else{
182
+ res = std::string();
183
+ }
184
+
185
+ --levels;
186
+ }
187
+ }
188
+
189
+ return res;
190
+ }
191
+
192
+ std::string FindPath(const std::string& child_path, const std::string& signature_path)
193
+ {
194
+ std::string path = PathExpand(child_path);
195
+ #ifdef _UNIX_
196
+ char abs_path[PATH_MAX];
197
+ if (realpath(path.c_str(), abs_path)) {
198
+ path = abs_path;
199
+ }
200
+ #endif
201
+ std::string signature = signature_path;
202
+ PathOsNormaliseInplace(path);
203
+ PathOsNormaliseInplace(signature);
204
+
205
+ while(!FileExists(path + signature)) {
206
+ if (path.empty()) {
207
+ return std::string();
208
+ } else {
209
+ path = PathParent(path);
210
+ }
211
+ }
212
+
213
+ return path + signature;
214
+ }
215
+
216
+ std::string PathExpand(const std::string& sPath)
217
+ {
218
+ if(sPath.length() >0 && sPath[0] == '~') {
219
+ #ifdef _WIN_
220
+ std::string sHomeDir;
221
+ WCHAR path[MAX_PATH];
222
+ if (SUCCEEDED(SHGetFolderPathW(NULL, CSIDL_PROFILE, NULL, 0, path))) {
223
+ std::wstring ws(path);
224
+ sHomeDir = std::string(ws.begin(), ws.end());
225
+ }
226
+ #else
227
+ std::string sHomeDir = std::string(getenv("HOME"));
228
+ #endif
229
+ return sHomeDir + sPath.substr(1,std::string::npos);
230
+ }else{
231
+ return sPath;
232
+ }
233
+ }
234
+
235
+ // Based on http://www.codeproject.com/Articles/188256/A-Simple-Wildcard-Matching-Function
236
+ bool MatchesWildcard(const std::string& str, const std::string& wildcard)
237
+ {
238
+ const char* psQuery = str.c_str();
239
+ const char* psWildcard = wildcard.c_str();
240
+
241
+ while(*psWildcard)
242
+ {
243
+ if(*psWildcard=='?')
244
+ {
245
+ if(!*psQuery)
246
+ return false;
247
+
248
+ ++psQuery;
249
+ ++psWildcard;
250
+ }
251
+ else if(*psWildcard=='*')
252
+ {
253
+ if(MatchesWildcard(psQuery,psWildcard+1))
254
+ return true;
255
+
256
+ if(*psQuery && MatchesWildcard(psQuery+1,psWildcard))
257
+ return true;
258
+
259
+ return false;
260
+ }
261
+ else
262
+ {
263
+ if(*psQuery++ != *psWildcard++ )
264
+ return false;
265
+ }
266
+ }
267
+
268
+ return !*psQuery && !*psWildcard;
269
+ }
270
+
271
+ std::string MakeUniqueFilename(const std::string& filename)
272
+ {
273
+ if( FileExists(filename) ) {
274
+ const size_t dot = filename.find_last_of('.');
275
+
276
+ std::string fn;
277
+ std::string ext;
278
+
279
+ if(dot == filename.npos) {
280
+ fn = filename;
281
+ ext = "";
282
+ }else{
283
+ fn = filename.substr(0, dot);
284
+ ext = filename.substr(dot);
285
+ }
286
+
287
+ int id = 1;
288
+ std::string new_file;
289
+ do {
290
+ id++;
291
+ std::stringstream ss;
292
+ ss << fn << "_" << id << ext;
293
+ new_file = ss.str();
294
+ }while( FileExists(new_file) );
295
+
296
+ return new_file;
297
+ }else{
298
+ return filename;
299
+ }
300
+ }
301
+
302
+ // Based on https://insanecoding.blogspot.com/2011/11/how-to-read-in-file-in-c.html
303
+ std::string GetFileContents(const std::string& filename)
304
+ {
305
+ std::ifstream in(filename.c_str(), std::ios::in | std::ios::binary);
306
+ if (in)
307
+ {
308
+ std::string contents;
309
+ in.seekg(0, std::ios::end);
310
+ contents.resize(in.tellg());
311
+ in.seekg(0, std::ios::beg);
312
+ in.read(&contents[0], contents.size());
313
+ in.close();
314
+ return(contents);
315
+ }else{
316
+ throw std::runtime_error(std::string("Unable to open file: ") + filename);
317
+ }
318
+ }
319
+
320
+ bool IsPipe(const std::string& file)
321
+ {
322
+ #ifdef _WIN_
323
+ return false;
324
+ #else
325
+ struct stat st;
326
+ int err = stat(file.c_str(), &st);
327
+ return (err == 0) && ((st.st_mode & S_IFMT) == S_IFIFO);
328
+ #endif // _WIN_
329
+ }
330
+
331
+ bool IsPipe(int fd)
332
+ {
333
+ #ifdef _WIN_
334
+ return false;
335
+ #else
336
+ struct stat st;
337
+ int err = fstat(fd, &st);
338
+ return (err == 0) && ((st.st_mode & S_IFMT) == S_IFIFO);
339
+ #endif
340
+ }
341
+
342
+ int WritablePipeFileDescriptor(const std::string& file)
343
+ {
344
+ #ifdef _WIN_
345
+ return false;
346
+ #else
347
+ // open(2) will return ENXIO when there is no reader on the other
348
+ // side of the pipe, but only if O_WRONLY|O_NONBLOCK is specified.
349
+ // The file descriptor can be adjusted to be a blocking file
350
+ // descriptor if it is valid.
351
+ return open(file.c_str(), O_WRONLY | O_NONBLOCK);
352
+ #endif // _WIN_
353
+ }
354
+
355
+ int ReadablePipeFileDescriptor(const std::string& file)
356
+ {
357
+ #ifdef _WIN_
358
+ return -1;
359
+ #else
360
+ return open(file.c_str(), O_RDONLY | O_NONBLOCK);
361
+ #endif
362
+ }
363
+
364
+ bool PipeHasDataToRead(int fd)
365
+ {
366
+ #ifdef _WIN_
367
+ return false;
368
+ #else
369
+ struct pollfd pfd;
370
+ memset(&pfd, 0, sizeof(pfd));
371
+ pfd.fd = fd;
372
+ pfd.events = POLLIN;
373
+
374
+ int err = poll(&pfd, 1, 0);
375
+
376
+ // If err is 0, the file has no data. If err is negative, an error
377
+ // occurred.
378
+ return err == 1 && pfd.revents & POLLIN;
379
+ #endif
380
+ }
381
+
382
+ void FlushPipe(const std::string& file)
383
+ {
384
+ #ifndef _WIN_
385
+ int fd = open(file.c_str(), O_RDONLY | O_NONBLOCK);
386
+ char buf[65535];
387
+ int n = 0;
388
+ do
389
+ {
390
+ n = read(fd, buf, sizeof(buf));
391
+ } while(n > 0);
392
+ close(fd);
393
+ #endif
394
+ }
395
+
396
+ #ifdef _WIN_
397
+
398
+ #ifdef UNICODE
399
+ typedef std::codecvt_utf8<wchar_t> WinStringConvert;
400
+ typedef std::wstring WinString;
401
+
402
+ WinString s2ws(const std::string& str) {
403
+ std::wstring_convert<WinStringConvert, wchar_t> converter;
404
+ return converter.from_bytes(str);
405
+ }
406
+ std::string ws2s(const WinString& wstr) {
407
+ std::wstring_convert<WinStringConvert, wchar_t> converter;
408
+ return converter.to_bytes(wstr);
409
+ }
410
+ #else
411
+ typedef std::string WinString;
412
+ // No conversions necessary
413
+ # define s2ws(X) (X)
414
+ # define ws2s(X) (X)
415
+ #endif // UNICODE
416
+
417
+ bool FilesMatchingWildcard(const std::string& wildcard, std::vector<std::string>& file_vec,
418
+ SortMethod sort_method )
419
+ {
420
+ size_t nLastSlash = wildcard.find_last_of("/\\");
421
+
422
+ std::string sPath;
423
+ std::string sFileWc;
424
+
425
+ if(nLastSlash != std::string::npos) {
426
+ sPath = wildcard.substr(0, nLastSlash);
427
+ sFileWc = wildcard.substr(nLastSlash+1, std::string::npos);
428
+ }else{
429
+ sPath = ".";
430
+ sFileWc = wildcard;
431
+ }
432
+
433
+ sPath = PathExpand(sPath);
434
+
435
+ WIN32_FIND_DATA wfd;
436
+ HANDLE fh = FindFirstFile( s2ws(sPath + "\\" + sFileWc).c_str(), &wfd);
437
+
438
+ std::vector<std::string> files;
439
+
440
+ if (fh != INVALID_HANDLE_VALUE) {
441
+ do {
442
+ if (!(wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
443
+ files.push_back( sPath + "\\" + ws2s(wfd.cFileName) );
444
+ }
445
+ } while (FindNextFile (fh, &wfd));
446
+ FindClose(fh);
447
+ }
448
+
449
+ // TOOD: Use different comparison to achieve better ordering.
450
+ switch(sort_method) {
451
+ case SortMethod::NATURAL:
452
+ SI::natural::sort(files.begin(), files.end());
453
+ break;
454
+ case SortMethod::STANDARD:
455
+ default:
456
+ std::sort(files.begin(), files.end() );
457
+ }
458
+
459
+ // Put file list at end of file_vec
460
+ file_vec.insert(file_vec.end(), files.begin(), files.end() );
461
+
462
+ return files.size() > 0;
463
+ }
464
+
465
+ bool FileExists(const std::string& filename)
466
+ {
467
+ std::string search_filename = filename;
468
+ if(filename.length() > 0 &&
469
+ (filename[filename.length()-1] == '\\' || filename[filename.length() - 1] == '/')) {
470
+ search_filename.resize(filename.length()-1);
471
+ }
472
+ WIN32_FIND_DATA wfd;
473
+ HANDLE fh = FindFirstFile( s2ws(search_filename).c_str(), &wfd);
474
+ const bool exists = fh != INVALID_HANDLE_VALUE;
475
+ FindClose(fh);
476
+ return exists;
477
+ }
478
+
479
+ #else // _WIN_
480
+
481
+ bool FilesMatchingWildcard_(const std::string& in_wildcard, std::vector<std::string>& file_vec)
482
+ {
483
+ const std::string wildcard = PathExpand(in_wildcard);
484
+ const size_t first_wildcard = wildcard.find_first_of("?*");
485
+ if(first_wildcard != std::string::npos) {
486
+ const std::string root = PathParent(wildcard.substr(0,first_wildcard));
487
+ struct dirent **namelist;
488
+ int n = scandir(root.c_str(), &namelist, 0, alphasort);
489
+ if (n >= 0) {
490
+ const size_t next_slash = wildcard.find_first_of("/\\",first_wildcard+1);
491
+ std::string dir_wildcard, rest;
492
+ if(next_slash != std::string::npos) {
493
+ dir_wildcard = wildcard.substr(root.size()+1, next_slash-root.size()-1);
494
+ rest = wildcard.substr(next_slash);
495
+ }else{
496
+ dir_wildcard = wildcard.substr(root.size()+1);
497
+ }
498
+
499
+ while(n--) {
500
+ const std::string file_name(namelist[n]->d_name);
501
+ if( file_name != "." && file_name != ".." && MatchesWildcard(file_name, dir_wildcard) ) {
502
+ const std::string sub_wildcard = root + "/" + file_name + rest;
503
+ FilesMatchingWildcard_(sub_wildcard, file_vec);
504
+ if(dir_wildcard == "**") {
505
+ const std::string sub_wildcard2 = root + "/" + file_name + "/**" + rest;
506
+ FilesMatchingWildcard_(sub_wildcard2, file_vec);
507
+ }
508
+ }
509
+ }
510
+ }
511
+ } else if(FileExists(wildcard)) {
512
+ file_vec.push_back(wildcard);
513
+ }
514
+ return file_vec.size() > 0;
515
+ }
516
+
517
+ bool FilesMatchingWildcard(const std::string& in_wildcard, std::vector<std::string>& file_vec, SortMethod sort_method)
518
+ {
519
+ if (FilesMatchingWildcard_(in_wildcard, file_vec)) {
520
+ // sort all file entries in file_vec to make sure anything that was
521
+ // added is sorted in properly.
522
+ switch (sort_method) {
523
+ case SortMethod::NATURAL:
524
+ SI::natural::sort(file_vec.begin(), file_vec.end());
525
+ break;
526
+ case SortMethod::STANDARD:
527
+ default:
528
+ std::sort(file_vec.begin(), file_vec.end() );
529
+ }
530
+ return true;
531
+ }
532
+ return false;
533
+ }
534
+
535
+
536
+ bool FileExists(const std::string& filename)
537
+ {
538
+ struct stat buf;
539
+ return stat(filename.c_str(), &buf) != -1;
540
+ }
541
+
542
+ #endif //_WIN_
543
+
544
+ }
third-party/DPVO/Pangolin/components/pango_core/src/param_set.cpp ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <pangolin/utils/param_set.h>
2
+
3
+ namespace pangolin
4
+ {
5
+
6
+ bool ParamReader::Contains( const std::string& param_name )
7
+ {
8
+ const ParamSet::Param* param = GetMatchingParamFromParamSet( param_name );
9
+ if( param ){
10
+ return uri_.Contains( param_name );
11
+ }
12
+ throw ParamReaderException( param_name );
13
+ }
14
+
15
+ std::unordered_set<std::string> ParamReader::FindUnrecognizedUriParams()
16
+ {
17
+ std::unordered_set<std::string> result;
18
+ for(const auto& param_pair: uri_.params){
19
+ if(GetMatchingParamFromParamSet( param_pair.first ) == nullptr ){
20
+ result.insert( param_pair.first );
21
+ }
22
+ }
23
+ return result;
24
+ }
25
+
26
+ const ParamSet::Param* ParamReader::GetMatchingParamFromParamSet( const std::string& param_name ) const
27
+ {
28
+ for(const auto& param : param_set_.params){
29
+ std::regex name_regex( param.name_regex );
30
+ if (std::regex_match ( param_name, name_regex )){
31
+ return &param;
32
+ }
33
+ }
34
+ return nullptr;
35
+ }
36
+
37
+ std::string ParamSet::str() const
38
+ {
39
+ std::stringstream ss;
40
+ if( params.size() > 0){
41
+ ss << "[";
42
+ size_t count = 0;
43
+ for(const auto& param : params){
44
+ ss << param.name_regex;
45
+ if(!param.default_value.empty()){
46
+ ss << "=" << param.default_value;
47
+ }
48
+ if(count < (params.size()-1)){
49
+ ss << ",";
50
+ }
51
+ count++;
52
+ }
53
+ ss << "]";
54
+ }
55
+ return ss.str();
56
+ }
57
+
58
+ }
third-party/DPVO/Pangolin/components/pango_core/src/posix/condition_variable.cpp ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <pangolin/utils/posix/condition_variable.h>
2
+
3
+ #include <pangolin/utils/posix/shared_memory_buffer.h>
4
+
5
+ #include <pthread.h>
6
+
7
+ using namespace std;
8
+
9
+ namespace pangolin {
10
+
11
+ struct PThreadSharedData {
12
+ pthread_mutex_t lock;
13
+ pthread_cond_t cond;
14
+ };
15
+
16
+ class PThreadConditionVariable : public ConditionVariableInterface {
17
+ public:
18
+ PThreadConditionVariable(std::shared_ptr<SharedMemoryBufferInterface> &shmem)
19
+ : _shmem(shmem),
20
+ _pthread_data(reinterpret_cast<PThreadSharedData *>(_shmem->ptr())) {}
21
+
22
+ ~PThreadConditionVariable() override {}
23
+
24
+ void wait() override {
25
+ _lock();
26
+ pthread_cond_wait(&_pthread_data->cond, &_pthread_data->lock);
27
+ _unlock();
28
+ }
29
+
30
+ bool wait(timespec abstime) override {
31
+ _lock();
32
+ int err = pthread_cond_timedwait(&_pthread_data->cond, &_pthread_data->lock,
33
+ &abstime);
34
+ _unlock();
35
+
36
+ return 0 == err;
37
+ }
38
+
39
+ void signal() override { pthread_cond_signal(&_pthread_data->cond); }
40
+
41
+ void broadcast() override { pthread_cond_broadcast(&_pthread_data->cond); }
42
+
43
+ private:
44
+ void _lock() { pthread_mutex_lock(&_pthread_data->lock); }
45
+
46
+ void _unlock() { pthread_mutex_unlock(&_pthread_data->lock); }
47
+
48
+ std::shared_ptr<SharedMemoryBufferInterface> _shmem;
49
+ PThreadSharedData *_pthread_data;
50
+ };
51
+
52
+ std::shared_ptr<ConditionVariableInterface>
53
+ create_named_condition_variable(const string &name) {
54
+ std::shared_ptr<SharedMemoryBufferInterface> shmem =
55
+ create_named_shared_memory_buffer(name, sizeof(PThreadSharedData));
56
+ std::shared_ptr<ConditionVariableInterface> ptr;
57
+
58
+ PThreadSharedData *pthread_data =
59
+ reinterpret_cast<PThreadSharedData *>(shmem->ptr());
60
+
61
+ pthread_mutexattr_t mattr;
62
+ pthread_mutexattr_init(&mattr);
63
+ pthread_mutexattr_setpshared(&mattr, PTHREAD_PROCESS_SHARED);
64
+
65
+ pthread_condattr_t cattr;
66
+ pthread_condattr_init(&cattr);
67
+ pthread_condattr_setpshared(&cattr, PTHREAD_PROCESS_SHARED);
68
+
69
+ pthread_mutex_init(&pthread_data->lock, &mattr);
70
+ pthread_cond_init(&pthread_data->cond, &cattr);
71
+
72
+ ptr.reset(static_cast<ConditionVariableInterface *>(
73
+ new PThreadConditionVariable(shmem)));
74
+ return ptr;
75
+ }
76
+
77
+ std::shared_ptr<ConditionVariableInterface>
78
+ open_named_condition_variable(const string &name) {
79
+ std::shared_ptr<SharedMemoryBufferInterface> shmem =
80
+ open_named_shared_memory_buffer(name, true);
81
+ std::shared_ptr<ConditionVariableInterface> ptr;
82
+
83
+ if(shmem) {
84
+ ptr.reset(new PThreadConditionVariable(shmem));
85
+ }
86
+ return ptr;
87
+ }
88
+
89
+ }
third-party/DPVO/Pangolin/components/pango_core/src/posix/semaphore.cpp ADDED
@@ -0,0 +1,83 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <pangolin/utils/posix/semaphore.h>
2
+
3
+ #include <fcntl.h>
4
+ #include <semaphore.h>
5
+ #include <sys/stat.h>
6
+
7
+ #include <string>
8
+
9
+ using namespace std;
10
+
11
+ namespace pangolin
12
+ {
13
+
14
+ // TODO(shaheen) register a signal handler for SIGTERM and unlink shared
15
+ // semaphores.
16
+ class PosixSemaphore : public SemaphoreInterface
17
+ {
18
+ public:
19
+ PosixSemaphore(sem_t *semaphore, bool ownership, const string& name) :
20
+ _semaphore(semaphore),
21
+ _ownership(ownership),
22
+ _name(name)
23
+ {
24
+ }
25
+
26
+ ~PosixSemaphore() override
27
+ {
28
+ if (_ownership) {
29
+ sem_unlink(_name.c_str());
30
+ } else {
31
+ sem_close(_semaphore);
32
+ }
33
+ }
34
+
35
+ bool tryAcquire() override
36
+ {
37
+ int err = sem_trywait(_semaphore);
38
+ return err == 0;
39
+ }
40
+
41
+ void acquire() override
42
+ {
43
+ sem_wait(_semaphore);
44
+ }
45
+
46
+ void release() override
47
+ {
48
+ sem_post(_semaphore);
49
+ }
50
+
51
+ private:
52
+ sem_t *_semaphore;
53
+ bool _ownership;
54
+ string _name;
55
+ };
56
+
57
+ std::shared_ptr<SemaphoreInterface> create_named_semaphore(const string& name, unsigned int value)
58
+ {
59
+ std::shared_ptr<SemaphoreInterface> ptr;
60
+ sem_t *semaphore = sem_open(name.c_str(), O_CREAT | O_EXCL,
61
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP, value);
62
+ if (NULL == semaphore) {
63
+ return ptr;
64
+ }
65
+
66
+ ptr.reset(new PosixSemaphore(semaphore, true, name));
67
+ return ptr;
68
+ }
69
+
70
+ std::shared_ptr<SemaphoreInterface> open_named_semaphore(const string& name)
71
+ {
72
+ std::shared_ptr<SemaphoreInterface> ptr;
73
+ sem_t *semaphore = sem_open(name.c_str(), 0);
74
+
75
+ if (NULL == semaphore) {
76
+ return ptr;
77
+ }
78
+
79
+ ptr.reset(new PosixSemaphore(semaphore, false, name));
80
+ return ptr;
81
+ }
82
+
83
+ }
third-party/DPVO/Pangolin/components/pango_core/src/posix/shared_memory_buffer.cpp ADDED
@@ -0,0 +1,134 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <pangolin/utils/posix/shared_memory_buffer.h>
2
+
3
+ #include <fcntl.h>
4
+ #include <limits.h>
5
+ #include <sys/file.h>
6
+ #include <sys/mman.h>
7
+ #include <sys/stat.h>
8
+ #include <unistd.h>
9
+
10
+ using namespace std;
11
+
12
+ namespace pangolin
13
+ {
14
+
15
+ // TODO(shaheen) register a signal handler for SIGTERM and unlink shared memory
16
+ // objects.
17
+ class PosixSharedMemoryBuffer : public SharedMemoryBufferInterface
18
+ {
19
+ public:
20
+ PosixSharedMemoryBuffer(int fd, unsigned char *ptr, size_t size, bool ownership, const std::string& name) :
21
+ _fd(fd),
22
+ _ptr(ptr),
23
+ _size(size),
24
+ _ownership(ownership),
25
+ _name(name),
26
+ _lockCount(0)
27
+ {
28
+ }
29
+
30
+ ~PosixSharedMemoryBuffer() override
31
+ {
32
+ close(_fd);
33
+ munmap(_ptr, _size);
34
+
35
+ if (_ownership) {
36
+ shm_unlink(_name.c_str());
37
+ }
38
+ }
39
+
40
+ bool tryLock() override
41
+ {
42
+ if (_lockCount == 0) {
43
+ int err = flock(_fd, LOCK_EX|LOCK_NB);
44
+ if (0 == err) {
45
+ _lockCount++;
46
+ }
47
+ }
48
+ return _lockCount != 0;
49
+ }
50
+
51
+ void lock() override
52
+ {
53
+ if (_lockCount == 0) {
54
+ flock(_fd, LOCK_EX);
55
+ }
56
+ _lockCount++;
57
+ }
58
+
59
+ void unlock() override
60
+ {
61
+ if (_lockCount != 0) {
62
+ flock(_fd, LOCK_UN);
63
+ }
64
+ _lockCount--;
65
+ }
66
+
67
+ unsigned char *ptr() override
68
+ {
69
+ return _ptr;
70
+ }
71
+
72
+ std::string name() override
73
+ {
74
+ return _name;
75
+ }
76
+
77
+ private:
78
+ int _fd;
79
+ unsigned char *_ptr;
80
+ size_t _size;
81
+ bool _ownership;
82
+ string _name;
83
+ unsigned int _lockCount;
84
+ };
85
+
86
+ std::shared_ptr<SharedMemoryBufferInterface> create_named_shared_memory_buffer(const
87
+ string& name, size_t size)
88
+ {
89
+ std::shared_ptr<SharedMemoryBufferInterface> ptr;
90
+
91
+ int fd = shm_open(name.c_str(), O_RDWR | O_RDONLY | O_CREAT,
92
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP);
93
+ if (-1 == fd) {
94
+ return ptr;
95
+ }
96
+
97
+ int err = ftruncate(fd, size);
98
+ if (-1 == err) {
99
+ shm_unlink(name.c_str());
100
+ return ptr;
101
+ }
102
+
103
+ unsigned char *buffer = reinterpret_cast<unsigned char *>(mmap(NULL, size,
104
+ PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0));
105
+
106
+ ptr.reset(new PosixSharedMemoryBuffer(fd, buffer, size, true, name));
107
+ return ptr;
108
+ }
109
+
110
+ std::shared_ptr<SharedMemoryBufferInterface> open_named_shared_memory_buffer(const
111
+ string& name, bool readwrite)
112
+ {
113
+ std::shared_ptr<SharedMemoryBufferInterface> ptr;
114
+
115
+ int fd = shm_open(name.c_str(), readwrite ? O_RDWR | O_RDONLY : O_RDONLY, 0);
116
+ if (-1 == fd) {
117
+ return ptr;
118
+ }
119
+
120
+ struct stat sbuf;
121
+ int err = fstat(fd, &sbuf);
122
+ if (-1 == err) {
123
+ return ptr;
124
+ }
125
+
126
+ size_t size = sbuf.st_size;
127
+ unsigned char *buffer = reinterpret_cast<unsigned char *>(mmap(NULL, size,
128
+ PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0));
129
+
130
+ ptr.reset(new PosixSharedMemoryBuffer(fd, buffer, size, false, name));
131
+ return ptr;
132
+ }
133
+
134
+ }
third-party/DPVO/Pangolin/components/pango_core/src/sigstate.cpp ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include <pangolin/utils/sigstate.h>
29
+ #include <iostream>
30
+ #include <fstream>
31
+ #include <sstream>
32
+
33
+ using namespace std;
34
+
35
+ namespace pangolin
36
+ {
37
+
38
+ SigState& SigState::I() {
39
+ static SigState singleton;
40
+ return singleton;
41
+ }
42
+
43
+ SigState::SigState()
44
+ {
45
+ }
46
+
47
+ SigState::~SigState() {
48
+ Clear();
49
+ }
50
+
51
+ void SigState::Clear() {
52
+ sig_callbacks.clear();
53
+ }
54
+
55
+ void RegisterNewSigCallback(SigCallbackFn callback, void* data, const int signal)
56
+ {
57
+ SigState::I().sig_callbacks.insert(std::pair<int, SigCallback>(signal, SigCallback(signal, callback, data)));
58
+ }
59
+
60
+ }
third-party/DPVO/Pangolin/components/pango_core/src/threadedfilebuf.cpp ADDED
@@ -0,0 +1,353 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include <pangolin/utils/threadedfilebuf.h>
29
+ #include <pangolin/utils/file_utils.h>
30
+ #include <pangolin/utils/sigstate.h>
31
+
32
+ #include <cstring>
33
+ #include <stdexcept>
34
+
35
+ #ifdef USE_POSIX_FILE_IO
36
+ #include <unistd.h>
37
+ #include <fcntl.h>
38
+
39
+ // Optionally use direct file i/o to avoid the cache.
40
+ #define USE_DIRECT_FILE_IO
41
+ #define POSIX_BLOCK_SIZE 4096
42
+ #endif
43
+
44
+ using namespace std;
45
+
46
+ namespace pangolin
47
+ {
48
+
49
+ namespace
50
+ {
51
+ char* allocate_buffer(size_t mem_max_size)
52
+ {
53
+ #ifdef USE_DIRECT_FILE_IO
54
+ void *mem_alloc;
55
+ int result = posix_memalign(&mem_alloc, POSIX_BLOCK_SIZE, mem_max_size);
56
+ if(result)
57
+ {
58
+ throw std::runtime_error("posix_memalign failed with result: " + std::to_string(result));
59
+ }
60
+ return static_cast<char*>(mem_alloc);
61
+ #else
62
+ return new char[static_cast<size_t>(mem_max_size)];
63
+ #endif
64
+ }
65
+
66
+ void free_buffer(char* mem_buffer)
67
+ {
68
+ #ifdef USE_DIRECT_FILE_IO
69
+ free(mem_buffer);
70
+ #else
71
+ delete mem_buffer;
72
+ #endif
73
+ }
74
+ }
75
+
76
+ threadedfilebuf::threadedfilebuf()
77
+ : mem_buffer(0), mem_size(0), mem_max_size(0), mem_start(0), mem_end(0), should_run(false), is_pipe(false)
78
+ {
79
+ }
80
+
81
+ threadedfilebuf::threadedfilebuf(const std::string& filename, size_t buffer_size_bytes )
82
+ : mem_buffer(0), mem_size(0), mem_max_size(0), mem_start(0), mem_end(0), should_run(false), is_pipe(pangolin::IsPipe(filename))
83
+ {
84
+ open(filename, buffer_size_bytes);
85
+ }
86
+
87
+ void threadedfilebuf::open(const std::string& filename, size_t buffer_size_bytes)
88
+ {
89
+ is_pipe = pangolin::IsPipe(filename);
90
+
91
+ #ifdef USE_POSIX_FILE_IO
92
+ if (filenum != -1) {
93
+ #else
94
+ if (file.is_open()) {
95
+ #endif
96
+ close();
97
+ }
98
+
99
+ #ifdef USE_POSIX_FILE_IO
100
+
101
+ // File is read/write for user and group, read only for other.
102
+ mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH;
103
+ #ifdef USE_DIRECT_FILE_IO
104
+ filenum = ::open(filename.c_str(), O_CREAT | O_TRUNC | O_WRONLY | O_DIRECT | O_SYNC, mode);
105
+ #else
106
+ filenum = ::open(filename.c_str(), O_CREAT | O_TRUNC | O_WRONLY | O_SYNC, mode);
107
+ #endif
108
+
109
+ #else
110
+ file.open(filename.c_str(), ios::out | ios::binary);
111
+ #endif
112
+
113
+ #ifdef USE_POSIX_FILE_IO
114
+ if (filenum == -1) {
115
+ #else
116
+ if(!file.is_open()) {
117
+ #endif
118
+ throw std::runtime_error("Unable to open '" + filename + "' for writing.");
119
+ }
120
+
121
+ mem_buffer = 0;
122
+ mem_size = 0;
123
+ mem_start = 0;
124
+ mem_end = 0;
125
+ mem_max_size = static_cast<std::streamsize>(buffer_size_bytes);
126
+ mem_buffer = allocate_buffer(mem_max_size);
127
+ should_run = true;
128
+ write_thread = std::thread(std::ref(*this));
129
+ }
130
+
131
+ void threadedfilebuf::close()
132
+ {
133
+ should_run = false;
134
+
135
+ cond_queued.notify_all();
136
+
137
+ if(write_thread.joinable())
138
+ {
139
+ write_thread.join();
140
+ }
141
+
142
+ if(mem_buffer)
143
+ {
144
+ free_buffer(mem_buffer);
145
+ mem_buffer = 0;
146
+ }
147
+
148
+ #ifdef USE_POSIX_FILE_IO
149
+ ::close(filenum);
150
+ filenum = -1;
151
+ #else
152
+ file.close();
153
+ #endif
154
+ }
155
+
156
+ void threadedfilebuf::soft_close()
157
+ {
158
+ // Forces sputn to write no bytes and exit early, results in lost data
159
+ mem_size = 0;
160
+ }
161
+
162
+ void threadedfilebuf::force_close()
163
+ {
164
+ soft_close();
165
+ close();
166
+ }
167
+
168
+ threadedfilebuf::~threadedfilebuf()
169
+ {
170
+ close();
171
+ }
172
+
173
+ std::streamsize threadedfilebuf::xsputn(const char* data, std::streamsize num_bytes)
174
+ {
175
+ if( num_bytes > mem_max_size ) {
176
+ std::unique_lock<std::mutex> lock(update_mutex);
177
+ // Wait until queue is empty
178
+ while( mem_size > 0 ) {
179
+ cond_dequeued.wait(lock);
180
+ }
181
+
182
+ // Allocate bigger buffer
183
+ free_buffer(mem_buffer);
184
+ mem_start = 0;
185
+ mem_end = 0;
186
+ mem_max_size = num_bytes * 4;
187
+ mem_buffer = allocate_buffer(mem_max_size);
188
+ }
189
+
190
+ {
191
+ std::unique_lock<std::mutex> lock(update_mutex);
192
+
193
+ // wait until there is space to write into buffer
194
+ while( mem_size + num_bytes > mem_max_size ) {
195
+ cond_dequeued.wait(lock);
196
+ }
197
+
198
+ // add image to end of mem_buffer
199
+ const std::streamsize array_a_size =
200
+ (mem_start <= mem_end) ? (mem_max_size - mem_end) : (mem_start - mem_end);
201
+
202
+ if( num_bytes <= array_a_size )
203
+ {
204
+ // copy in one
205
+ memcpy(mem_buffer + mem_end, data, static_cast<size_t>(num_bytes));
206
+ mem_end += num_bytes;
207
+ mem_size += num_bytes;
208
+ }else{
209
+ const std::streamsize array_b_size = num_bytes - array_a_size;
210
+ memcpy(mem_buffer + mem_end, data, (size_t)array_a_size);
211
+ memcpy(mem_buffer, data+array_a_size, (size_t)array_b_size);
212
+ mem_end = array_b_size;
213
+ mem_size += num_bytes;
214
+ }
215
+
216
+ if(mem_end == mem_max_size)
217
+ mem_end = 0;
218
+ }
219
+
220
+ cond_queued.notify_one();
221
+
222
+ input_pos += num_bytes;
223
+ return num_bytes;
224
+ }
225
+
226
+ int threadedfilebuf::overflow(int c)
227
+ {
228
+ const std::streamsize num_bytes = 1;
229
+
230
+ {
231
+ std::unique_lock<std::mutex> lock(update_mutex);
232
+
233
+ // wait until there is space to write into buffer
234
+ while( mem_size + num_bytes > mem_max_size ) {
235
+ cond_dequeued.wait(lock);
236
+ }
237
+
238
+ // add image to end of mem_buffer
239
+ mem_buffer[mem_end] = c;
240
+ mem_end += num_bytes;
241
+ mem_size += num_bytes;
242
+
243
+ if(mem_end == mem_max_size)
244
+ mem_end = 0;
245
+ }
246
+
247
+ cond_queued.notify_one();
248
+
249
+ input_pos += num_bytes;
250
+ return num_bytes;
251
+ }
252
+
253
+ std::streampos threadedfilebuf::seekoff(
254
+ std::streamoff off, std::ios_base::seekdir way,
255
+ std::ios_base::openmode /*which*/
256
+ ) {
257
+ if(off == 0 && way == ios_base::cur) {
258
+ return input_pos;
259
+ }else{
260
+ return -1;
261
+ }
262
+ }
263
+
264
+ void threadedfilebuf::operator()()
265
+ {
266
+ std::streamsize data_to_write = 0;
267
+
268
+ while(true)
269
+ {
270
+ if(is_pipe)
271
+ {
272
+ try
273
+ {
274
+ if(SigState::I().sig_callbacks.at(SIGPIPE).value)
275
+ {
276
+ soft_close();
277
+ return;
278
+ }
279
+ } catch(std::out_of_range&)
280
+ {
281
+ // std::cout << "Please register a SIGPIPE handler for your writer" << std::endl;
282
+ }
283
+ }
284
+
285
+ {
286
+ std::unique_lock<std::mutex> lock(update_mutex);
287
+
288
+ // Wait until there is data to write or we are stopping the write thread.
289
+ #ifdef USE_DIRECT_FILE_IO
290
+ while(mem_size < POSIX_BLOCK_SIZE && should_run) {
291
+ #else
292
+ while(mem_size == 0 && should_run) {
293
+ #endif
294
+ cond_queued.wait(lock);
295
+ }
296
+
297
+ if (mem_size == 0 && !should_run)
298
+ {
299
+ return;
300
+ }
301
+
302
+ data_to_write =
303
+ (mem_start < mem_end) ?
304
+ mem_end - mem_start :
305
+ mem_max_size - mem_start;
306
+ }
307
+
308
+ // Adjust write size if appropriate.
309
+ #ifdef USE_DIRECT_FILE_IO
310
+ if (!should_run && data_to_write < POSIX_BLOCK_SIZE)
311
+ {
312
+ // Stopping the write thread - allow non-direct write of final block.
313
+ int fopts = fcntl(filenum, F_GETFL);
314
+ int result = fcntl(filenum, F_SETFL, fopts & ~O_DIRECT);
315
+ if (result == -1)
316
+ {
317
+ throw std::runtime_error("fcntl failed with result: " + std::to_string(result));
318
+ }
319
+ }
320
+ else
321
+ {
322
+ // Direct writes are limited to block size boundaries
323
+ data_to_write = data_to_write - (data_to_write%POSIX_BLOCK_SIZE);
324
+ }
325
+ #endif
326
+
327
+ // Write data through to disk.
328
+ #ifdef USE_POSIX_FILE_IO
329
+ int bytes_written = ::write(filenum, mem_buffer + mem_start, data_to_write);
330
+ if(bytes_written == -1)
331
+ {
332
+ throw std::runtime_error("Unable to write data.");
333
+ }
334
+ #else
335
+ std::streamsize bytes_written =
336
+ file.sputn(mem_buffer + mem_start, data_to_write );
337
+ #endif
338
+
339
+ {
340
+ std::unique_lock<std::mutex> lock(update_mutex);
341
+
342
+ mem_size -= bytes_written;
343
+ mem_start += bytes_written;
344
+
345
+ if(mem_start == mem_max_size)
346
+ mem_start = 0;
347
+ }
348
+
349
+ cond_dequeued.notify_all();
350
+ }
351
+ }
352
+
353
+ }
third-party/DPVO/Pangolin/components/pango_core/src/uri.cpp ADDED
@@ -0,0 +1,105 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include <pangolin/utils/file_utils.h>
29
+ #include <pangolin/utils/uri.h>
30
+
31
+ #include <stdexcept>
32
+ #include <vector>
33
+ #include <string>
34
+
35
+ namespace pangolin
36
+ {
37
+
38
+ Uri ParseUri(const std::string &str_uri)
39
+ {
40
+ Uri uri;
41
+ uri.full_uri = str_uri;
42
+
43
+ // Find Scheme delimiter
44
+ size_t npos = 0;
45
+ const size_t ns = str_uri.find(':', npos);
46
+ if( ns != std::string::npos )
47
+ {
48
+ uri.scheme = str_uri.substr(0,ns);
49
+ npos = ns+1;
50
+ }else{
51
+ uri.scheme = "file";
52
+ uri.url = str_uri;
53
+ return uri;
54
+ }
55
+
56
+ // Find Options delimiters
57
+ if( str_uri.size() > npos && str_uri[npos] == '[' )
58
+ {
59
+ const size_t nob = npos;
60
+ const size_t ncb = str_uri.find(']', nob+1);
61
+ if(ncb != std::string::npos)
62
+ {
63
+ const std::string queries = str_uri.substr(nob+1, ncb - (ns+2) );
64
+ std::vector<std::string> params;
65
+ Split(queries, ',', params);
66
+ for(size_t i=0; i< params.size(); ++i)
67
+ {
68
+ std::vector<std::string> args;
69
+ Split(params[i], '=', args );
70
+ std::string key = Trim(args[0]);
71
+ std::string val = args.size() > 1 ? Trim(args[1]) : "";
72
+ uri.Set(key,val);
73
+ }
74
+ }else{
75
+ throw std::runtime_error("Unable to parse URI: '" + str_uri + "'");
76
+ }
77
+ npos = ncb + 1;
78
+ }
79
+
80
+ // Find url delimiter
81
+ size_t nurl = str_uri.find("//", npos);
82
+ if(nurl != std::string::npos)
83
+ {
84
+ uri.url = str_uri.substr(nurl+2);
85
+ }
86
+
87
+ return uri;
88
+ }
89
+
90
+ std::ostream& operator<< (std::ostream &out, Uri &uri)
91
+ {
92
+ out << "scheme: " << uri.scheme << std::endl;
93
+ out << "url: " << uri.url << std::endl;
94
+ out << "params:" << std::endl;
95
+
96
+ for( Uri::ParamMap::const_iterator ip = uri.params.begin();
97
+ ip != uri.params.end(); ++ip)
98
+ {
99
+ out << "\t" << ip->first << " = " << ip->second << std::endl;
100
+ }
101
+
102
+ return out;
103
+ }
104
+
105
+ } // pangolin
third-party/DPVO/Pangolin/components/pango_core/tests/tests_uri.cpp ADDED
@@ -0,0 +1,87 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #define CATCH_CONFIG_MAIN
2
+ #include <catch2/catch.hpp>
3
+
4
+ #include <string>
5
+ #include <limits>
6
+ #include <functional>
7
+ #include <pangolin/factory/factory_registry.h>
8
+
9
+ template<typename T>
10
+ inline void ExpectExceptionWithMessageFromAction(
11
+ std::function<void()> action,
12
+ const std::string& exceptionMessageBegin
13
+ ) {
14
+ try
15
+ {
16
+ action();
17
+
18
+ FAIL("The action succeeded when it should have failed.");
19
+ }
20
+ catch(const T& ex)
21
+ {
22
+ std::string exceptionMessage = std::string(ex.what());
23
+ std::string exceptionMessageRelevantPortion
24
+ = exceptionMessage.substr(0, exceptionMessageBegin.size());
25
+ REQUIRE(exceptionMessageRelevantPortion.compare(exceptionMessageBegin) == 0);
26
+ }
27
+ catch(...)
28
+ {
29
+ FAIL("Another kind of exception was thrown to the one expected");
30
+ }
31
+ }
32
+
33
+ TEST_CASE("Missing Closing Bracket Causes Exception")
34
+ {
35
+ const std::string rawUri = "abc:[...";
36
+ auto testAction = [&](){pangolin::ParseUri(rawUri);};
37
+ ExpectExceptionWithMessageFromAction<std::runtime_error>(testAction,
38
+ "Unable to parse URI: '" + rawUri + "'");
39
+ }
40
+
41
+ TEST_CASE("Uri Equals Sign Character In Value Truncates The Rest")
42
+ {
43
+ const std::string fullUri = "abc:[key=value=notfound,key2=value2]";
44
+ const pangolin::Uri pangoUri = pangolin::ParseUri(fullUri);
45
+
46
+ // parsing option list should have precendence over parsing individual option
47
+ REQUIRE(pangoUri.params.size() == 2);
48
+
49
+ REQUIRE( pangoUri.params[0].first == std::string("key"));
50
+ REQUIRE( pangoUri.params[1].first == std::string("key2"));
51
+
52
+ const std::string truncated = pangoUri.Get<std::string>("key", "");
53
+ REQUIRE( truncated == std::string("value"));
54
+
55
+ const std::string otherValue = pangoUri.Get<std::string>("key2", "");
56
+ REQUIRE( otherValue == std::string("value2"));
57
+ }
58
+
59
+ TEST_CASE("Uri Multiple Occurrences Of Option Overrides Previous")
60
+ {
61
+ const std::string fullUri = "abc:[key=value,key=value2]";
62
+ const pangolin::Uri pangoUri = pangolin::ParseUri(fullUri);
63
+
64
+ REQUIRE(pangoUri.params.size() == 2);
65
+ REQUIRE( pangoUri.params[0].first == std::string("key"));
66
+ REQUIRE( pangoUri.params[1].first == std::string("key"));
67
+
68
+ const std::string truncated = pangoUri.Get<std::string>("key", "");
69
+ REQUIRE( truncated == std::string("value2"));
70
+ }
71
+
72
+
73
+ TEST_CASE("Uri Url Contains Everything After Separator")
74
+ {
75
+ const std::string expectedUrl = "abc:123[],=";
76
+ const std::string fullUri = "abc:[key=value,key=value2]//" + expectedUrl;
77
+ const pangolin::Uri pangoUri = pangolin::ParseUri(fullUri);
78
+ REQUIRE( pangoUri.url == expectedUrl);
79
+ }
80
+
81
+ TEST_CASE("Uri Invalid Characters After Closed Bracket Are Ignored")
82
+ {
83
+ const std::string expectedUrl = "abc:123[],=";
84
+ const std::string fullUri = "abc:[key=value,key=value2]xyz//" + expectedUrl;
85
+ const pangolin::Uri pangoUri = pangolin::ParseUri(fullUri);
86
+ REQUIRE( pangoUri.url == expectedUrl);
87
+ }
third-party/DPVO/Pangolin/components/pango_display/CMakeLists.txt ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ get_filename_component(COMPONENT ${CMAKE_CURRENT_LIST_DIR} NAME)
2
+
3
+ target_sources( ${COMPONENT}
4
+ PRIVATE
5
+ ${CMAKE_CURRENT_LIST_DIR}/src/display.cpp
6
+ ${CMAKE_CURRENT_LIST_DIR}/src/process.cpp
7
+ ${CMAKE_CURRENT_LIST_DIR}/src/pangolin_gl.cpp
8
+ ${CMAKE_CURRENT_LIST_DIR}/src/handler.cpp
9
+ ${CMAKE_CURRENT_LIST_DIR}/src/handler_image.cpp
10
+ ${CMAKE_CURRENT_LIST_DIR}/src/handler_glbuffer.cpp
11
+ ${CMAKE_CURRENT_LIST_DIR}/src/view.cpp
12
+ ${CMAKE_CURRENT_LIST_DIR}/src/widgets.cpp
13
+ ${CMAKE_CURRENT_LIST_DIR}/src/image_view.cpp
14
+ ${CMAKE_CURRENT_LIST_DIR}/src/ConsoleView.cpp
15
+ ${CMAKE_CURRENT_LIST_DIR}/src/default_font.cpp
16
+ )
17
+
18
+ target_link_libraries(${COMPONENT} PUBLIC pango_core pango_opengl pango_windowing pango_vars )
19
+
20
+ target_include_directories(${COMPONENT} PUBLIC
21
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
22
+ $<INSTALL_INTERFACE:include>
23
+ )
24
+ install(DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/include"
25
+ DESTINATION ${CMAKE_INSTALL_PREFIX}
26
+ )
third-party/DPVO/Pangolin/components/pango_display/include/pangolin/console/ConsoleView.h ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #pragma once
29
+
30
+ #include <deque>
31
+
32
+ #include <pangolin/gl/glfont.h>
33
+ #include <pangolin/gl/colour.h>
34
+ #include <pangolin/var/var.h>
35
+ #include <pangolin/display/view.h>
36
+ #include <pangolin/handler/handler.h>
37
+
38
+ #include <pangolin/console/InterpreterInterface.h>
39
+
40
+ namespace pangolin
41
+ {
42
+
43
+ class ConsoleView : public pangolin::View, pangolin::Handler
44
+ {
45
+ public:
46
+ struct Line
47
+ {
48
+ Line()
49
+ : linetype(ConsoleLineTypeCmd)
50
+ {
51
+ }
52
+
53
+ Line(const GlText& text, InterpreterLineType linetype = ConsoleLineTypeCmd )
54
+ : text(text), linetype(linetype)
55
+ {
56
+ }
57
+
58
+ GlText text;
59
+ InterpreterLineType linetype;
60
+ };
61
+
62
+
63
+ // Construct with interpreter (and take ownership)
64
+ ConsoleView(const std::shared_ptr<InterpreterInterface>& interpreter);
65
+
66
+ ~ConsoleView();
67
+
68
+ View& ShowWithoutAnimation(bool show=true);
69
+
70
+ // Replace implementation in View to account for hiding animation
71
+ View& Show(bool show=true);
72
+
73
+ // Replace implementation in View to account for hiding animation
74
+ void ToggleShow();
75
+
76
+ // Replace implementation in View to account for hiding animation
77
+ bool IsShown() const;
78
+
79
+ void Render() override;
80
+
81
+ void Keyboard(View&, unsigned char key, int x, int y, bool pressed) override;
82
+
83
+ private:
84
+ void DrawLine(const ConsoleView::Line& l, int carat);
85
+
86
+ void ProcessOutputLines();
87
+
88
+ void AddLine(const std::string& text, InterpreterLineType linetype = ConsoleLineTypeCmd);
89
+
90
+ Line* GetLine(int id, InterpreterLineType line_type, const std::string& prefix = "");
91
+
92
+ std::shared_ptr<InterpreterInterface> interpreter;
93
+
94
+ GlFont& font;
95
+
96
+ int carat;
97
+ Line current_line;
98
+ std::deque<Line> line_buffer;
99
+
100
+ bool hiding;
101
+ GLfloat bottom;
102
+
103
+ Colour background_colour;
104
+ std::map<InterpreterLineType,pangolin::Colour> line_colours;
105
+ float animation_speed;
106
+ };
107
+
108
+ }
third-party/DPVO/Pangolin/components/pango_display/include/pangolin/console/InterpreterInterface.h ADDED
@@ -0,0 +1,80 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #pragma once
29
+
30
+ #include <vector>
31
+ #include <string>
32
+
33
+ namespace pangolin
34
+ {
35
+
36
+ enum InterpreterLineType
37
+ {
38
+ ConsoleLineTypeCmd,
39
+ ConsoleLineTypeCmdOptions,
40
+ ConsoleLineTypeStdout,
41
+ ConsoleLineTypeStderr,
42
+ ConsoleLineTypeOutput,
43
+ ConsoleLineTypeHelp,
44
+ };
45
+
46
+ class InterpreterLine
47
+ {
48
+ public:
49
+ inline InterpreterLine()
50
+ : linetype(ConsoleLineTypeCmd)
51
+ {
52
+ }
53
+
54
+ inline InterpreterLine(std::string text, InterpreterLineType linetype = ConsoleLineTypeOutput)
55
+ : text(text), linetype(linetype)
56
+ {
57
+ }
58
+
59
+ std::string text;
60
+ InterpreterLineType linetype;
61
+ };
62
+
63
+ class InterpreterInterface
64
+ {
65
+ public:
66
+ inline virtual ~InterpreterInterface()
67
+ {
68
+ }
69
+
70
+ virtual void PushCommand(const std::string& cmd) = 0;
71
+
72
+ virtual bool PullLine(InterpreterLine& line) = 0;
73
+
74
+ virtual std::vector<std::string> Complete(
75
+ const std::string& cmd, int max_options = 20
76
+ ) = 0;
77
+
78
+ };
79
+
80
+ }
third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/attach.h ADDED
@@ -0,0 +1,86 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2013 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #pragma once
29
+
30
+ #include <iostream>
31
+ #include <string>
32
+ #include <cmath>
33
+
34
+ namespace pangolin
35
+ {
36
+
37
+ /// Units for measuring screen distances.
38
+ enum Unit {
39
+ Fraction,
40
+ Pixel,
41
+ ReversePixel
42
+ };
43
+
44
+ /// Defines absolute or relative position from parent viewport edge.
45
+ /// Constructors distinguised by whole pixels, or floating
46
+ /// fraction in interval [0,1]
47
+ struct PANGOLIN_EXPORT Attach {
48
+ /// Attach to Left/Bottom edge
49
+ Attach() : unit(Fraction), p(0) {}
50
+
51
+ /// General constructor
52
+ Attach(Unit unit, GLfloat p) : unit(unit), p(p) {}
53
+
54
+ /// Specify relative position in range [0,1].
55
+ /// 0 represents leftmost / bottom-most edge,
56
+ /// 1 represents rightmost / topmost edge
57
+ Attach(GLfloat p) : unit(Fraction), p(p) {
58
+ // Allow for numerical imprecision when checking usage.
59
+ if( p < -1E-3 || 1.001 < p ) {
60
+ std::cerr << "Pangolin API Change: Display::SetBounds must be used with Attach::Pix or Attach::ReversePix to specify pixel bounds relative to an edge. See the code samples for details." << std::endl;
61
+ throw std::exception();
62
+ }
63
+ }
64
+
65
+ /// Specify absolute position from leftmost / bottom-most edge.
66
+ static Attach Pix(int p) {
67
+ return Attach(p >=0 ? Pixel : ReversePixel, std::abs((float)p));
68
+ }
69
+
70
+ /// Specify absolute position from rightmost / topmost edge.
71
+ static Attach ReversePix(int p) {
72
+ return Attach(ReversePixel, (GLfloat)p);
73
+ }
74
+
75
+ /// Specify relative position in range [0,1].
76
+ /// 0 represents leftmost / bottom-most edge,
77
+ /// 1 represents rightmost / topmost edge
78
+ static Attach Frac(float frac) {
79
+ return Attach(frac);
80
+ }
81
+
82
+ Unit unit;
83
+ GLfloat p;
84
+ };
85
+
86
+ } // namespace pangolin
third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/default_font.h ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <pangolin/gl/glfont.h>
4
+
5
+ namespace pangolin {
6
+ GlFont& default_font();
7
+ }
third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/display.h ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove, Richard Newcombe
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #pragma once
29
+
30
+ #include <pangolin/platform.h>
31
+ #include <pangolin/gl/glinclude.h>
32
+ #include <pangolin/gl/viewport.h>
33
+ #include <pangolin/utils/params.h>
34
+ #include <pangolin/windowing/window.h>
35
+
36
+ #include <functional>
37
+ #include <string>
38
+ #include <memory>
39
+
40
+ /*! \file display.h
41
+ * This file contains a number of global methods for creating and
42
+ * querying window state as well as handling user input.
43
+ */
44
+
45
+ namespace pangolin
46
+ {
47
+
48
+ // Forward Declarations
49
+ struct View;
50
+ class UserApp;
51
+
52
+ /// Give this OpenGL context a name or switch contexts.
53
+ /// This is required to initialise Pangolin for use with an
54
+ /// externally defined OpenGL context. You needn't call it
55
+ /// if you have used CreateWindowAndBind() to create a window
56
+ /// or launched a pangolin::UserApp
57
+ PANGOLIN_EXPORT
58
+ void BindToContext(std::string name);
59
+
60
+ /// Initialise OpenGL window (determined by platform) and bind context.
61
+ /// This method will choose an available windowing system if one is present.
62
+ PANGOLIN_EXPORT
63
+ WindowInterface& CreateWindowAndBind(std::string window_title, int w = 640, int h = 480, const Params& params = Params());
64
+
65
+ /// Return pointer to current Pangolin Window context, or nullptr if none bound.
66
+ PANGOLIN_EXPORT
67
+ WindowInterface* GetBoundWindow();
68
+
69
+ PANGOLIN_EXPORT
70
+ void DestroyWindow(const std::string& window_title);
71
+
72
+ /// Launch users derived UserApp, controlling OpenGL event loop.
73
+ /// This method will block until the application exits, calling app's
74
+ /// Init() method to start and Render() method subsequently to draw each frame.
75
+ /// @return exit code for use when returning from main. Currently always 0.
76
+ PANGOLIN_EXPORT
77
+ int LaunchUserApp(UserApp& app);
78
+
79
+ /// Perform any post rendering, event processing and frame swapping.
80
+ PANGOLIN_EXPORT
81
+ void FinishFrame();
82
+
83
+ /// Request that the window close.
84
+ PANGOLIN_EXPORT
85
+ void Quit();
86
+
87
+ /// Request that all windows close.
88
+ PANGOLIN_EXPORT
89
+ void QuitAll();
90
+
91
+ /// Returns true if user has requested to close OpenGL window.
92
+ PANGOLIN_EXPORT
93
+ bool ShouldQuit();
94
+
95
+ /// Renders any views with default draw methods.
96
+ PANGOLIN_EXPORT
97
+ void RenderViews();
98
+
99
+ /// Perform any post render events, such as screen recording.
100
+ PANGOLIN_EXPORT
101
+ void PostRender();
102
+
103
+ /// Request to be notified via functor when key is pressed.
104
+ PANGOLIN_EXPORT
105
+ void RegisterKeyPressCallback(int key, std::function<void(void)> func);
106
+
107
+ /// Request to be notified via functor when key is pressed.
108
+ /// Functor may take one parameter which will equal the key pressed
109
+ PANGOLIN_EXPORT
110
+ void RegisterKeyPressCallback(int key, std::function<void(int)> func);
111
+
112
+ /// Save the contents of current window within the specified viewport (whole window by default).
113
+ /// This will be called during pangolin::FinishFrame().
114
+ /// \param filename_hint can be a complete filename (absolute or relative to working directory).
115
+ /// \param the portion of the window to save. Default construction will save entire window.
116
+ PANGOLIN_EXPORT
117
+ void SaveWindowOnRender(const std::string& filename_hint, const Viewport& v = Viewport());
118
+
119
+ /// Save the contents of current window within the specified viewport (whole window by default).
120
+ /// This will block whilst waiting for pending draw calls to complete and then save the current contents.
121
+ /// \param filename_hint can be a complete filename (absolute or relative to working directory).
122
+ /// \param the portion of the window to save. Default construction will save entire window.
123
+ PANGOLIN_EXPORT
124
+ void SaveWindowNow(const std::string& filename_hint, const Viewport& v = Viewport());
125
+
126
+ /// Retrieve 'base' display, corresponding to entire window.
127
+ PANGOLIN_EXPORT
128
+ View& DisplayBase();
129
+
130
+ /// Create or retrieve named display managed by pangolin (automatically deleted).
131
+ PANGOLIN_EXPORT
132
+ View& Display(const std::string& name);
133
+
134
+ /// Create unnamed display managed by pangolin (automatically deleted).
135
+ PANGOLIN_EXPORT
136
+ View& CreateDisplay();
137
+
138
+ /// Switch windows/fullscreenmode = fullscreen.
139
+ PANGOLIN_EXPORT
140
+ void ShowFullscreen(TrueFalseToggle on_off);
141
+
142
+ /// Toggle display of Pangolin console
143
+ PANGOLIN_EXPORT
144
+ void ShowConsole(TrueFalseToggle on_off);
145
+ }
146
+
147
+ #include <pangolin/display/display.hpp>
third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/display.hpp ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove, Richard Newcombe
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #pragma once
29
+
30
+ namespace pangolin
31
+ {
32
+
33
+ PANGOLIN_DEPRECATED("Use ShowFullscreen(...) instead")
34
+ inline void ToggleFullscreen() {
35
+ ShowFullscreen(TrueFalseToggle::Toggle);
36
+ }
37
+ PANGOLIN_DEPRECATED("Use ShowFullscreen(...) instead")
38
+ inline void SetFullscreen(bool fullscreen = true) {
39
+ ShowFullscreen( (TrueFalseToggle)fullscreen);
40
+ }
41
+ PANGOLIN_DEPRECATED("Use ShowConsole(...) instead")
42
+ inline void ToggleConsole()
43
+ {
44
+ ShowConsole(TrueFalseToggle::Toggle);
45
+ }
46
+
47
+ }
third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/image_view.h ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #pragma once
2
+
3
+ #include <pangolin/display/display.h>
4
+ #include <pangolin/gl/glpixformat.h>
5
+ #include <pangolin/gl/glformattraits.h>
6
+ #include <pangolin/gl/glsl.h>
7
+ #include <pangolin/handler/handler_image.h>
8
+ #include <pangolin/image/image_utils.h>
9
+
10
+ #include <mutex>
11
+
12
+ namespace pangolin
13
+ {
14
+
15
+ class PANGOLIN_EXPORT ImageView : public pangolin::View, public pangolin::ImageViewHandler
16
+ {
17
+ public:
18
+ ImageView(const std::string & title ="");
19
+
20
+ ~ImageView();
21
+
22
+ void Render() override;
23
+
24
+ void Mouse(View& view, pangolin::MouseButton button, int x, int y, bool pressed, int button_state) override;
25
+
26
+ void Keyboard(View& view, unsigned char key, int x, int y, bool pressed) override;
27
+
28
+ pangolin::GlTexture& Tex();
29
+
30
+ ImageView& SetImage(void* ptr, size_t w, size_t h, size_t pitch, pangolin::GlPixFormat img_fmt, bool delayed_upload = false);
31
+
32
+ ImageView& SetImage(const pangolin::Image<unsigned char>& img, const pangolin::GlPixFormat& glfmt, bool delayed_upload = false);
33
+
34
+ template<typename T> inline
35
+ ImageView& SetImage(const pangolin::Image<T>& img, bool delayed_upload = false)
36
+ {
37
+ return SetImage(img.template UnsafeReinterpret<unsigned char>(), GlPixFormat::FromType<T>(), delayed_upload);
38
+ }
39
+
40
+ ImageView& SetImage(const pangolin::TypedImage& img, bool delayed_upload = false);
41
+
42
+ ImageView& SetImage(const pangolin::GlTexture& texture);
43
+
44
+ void LoadPending();
45
+
46
+ ImageView& Clear();
47
+
48
+ std::pair<float, float>& GetOffsetScale();
49
+
50
+ bool MouseReleased() const;
51
+
52
+ bool MousePressed() const;
53
+
54
+ void SetRenderOverlay(const bool& val);
55
+
56
+ // private:
57
+ // img_to_load contains image data that should be uploaded to the texture on
58
+ // the next render cycle. The data is owned by this object and should be
59
+ // freed after use.
60
+ pangolin::ManagedImage<unsigned char> img_to_load;
61
+ pangolin::GlPixFormat img_fmt_to_load;
62
+
63
+ std::pair<float, float> offset_scale;
64
+ pangolin::GlPixFormat fmt;
65
+ pangolin::GlTexture tex;
66
+ bool lastPressed;
67
+ bool mouseReleased;
68
+ bool mousePressed;
69
+ bool overlayRender;
70
+
71
+ std::mutex texlock;
72
+ };
73
+
74
+ }
third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/process.h ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove, Richard Newcombe
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #pragma once
29
+
30
+ #include <pangolin/platform.h>
31
+ #include <pangolin/windowing/handler_bitsets.h>
32
+
33
+ namespace pangolin
34
+ {
35
+
36
+ /// You can use these methods to drive Pangolin events when it
37
+ /// doesn't own the OpenGL Context. You can probably ignore these.
38
+ namespace process
39
+ {
40
+ PANGOLIN_EXPORT
41
+ void Resize(int width, int height);
42
+
43
+ PANGOLIN_EXPORT
44
+ void Keyboard(unsigned char key, int x, int y, bool pressed, KeyModifierBitmask key_modifiers);
45
+
46
+ PANGOLIN_EXPORT
47
+ void Mouse(int button, bool pressed, int x, int y, KeyModifierBitmask key_modifiers);
48
+
49
+ PANGOLIN_EXPORT
50
+ void MouseMotion( int x, int y, KeyModifierBitmask key_modifiers);
51
+
52
+ PANGOLIN_EXPORT
53
+ void PassiveMouseMotion(int x, int y, KeyModifierBitmask key_modifiers);
54
+
55
+ PANGOLIN_EXPORT
56
+ void SpecialInput(InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, KeyModifierBitmask key_modifiers);
57
+ }
58
+
59
+ }
third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/user_app.h ADDED
@@ -0,0 +1,43 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2014 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #pragma once
29
+
30
+ #include <pangolin/platform.h>
31
+
32
+ namespace pangolin
33
+ {
34
+
35
+ class PANGOLIN_EXPORT UserApp
36
+ {
37
+ public:
38
+ virtual ~UserApp() {}
39
+ virtual void Init() {}
40
+ virtual void Render() = 0;
41
+ };
42
+
43
+ }
third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/view.h ADDED
@@ -0,0 +1,231 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2013 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #pragma once
29
+
30
+ #include <functional>
31
+ #include <vector>
32
+
33
+ #include <pangolin/gl/viewport.h>
34
+ #include <pangolin/display/attach.h>
35
+
36
+ namespace pangolin
37
+ {
38
+
39
+ enum Layout
40
+ {
41
+ LayoutOverlay,
42
+ LayoutVertical,
43
+ LayoutHorizontal,
44
+ LayoutEqual,
45
+ LayoutEqualVertical,
46
+ LayoutEqualHorizontal
47
+ };
48
+
49
+ enum Lock {
50
+ LockLeft = 0,
51
+ LockBottom = 0,
52
+ LockCenter = 1,
53
+ LockRight = 2,
54
+ LockTop = 2
55
+ };
56
+
57
+ // Forward declarations
58
+ struct Handler;
59
+
60
+ class OpenGlRenderState;
61
+
62
+ /// A Display manages the location and resizing of an OpenGl viewport.
63
+ struct PANGOLIN_EXPORT View
64
+ {
65
+ View(double aspect=0.0)
66
+ : aspect(aspect), top(1.0),left(0.0),right(1.0),bottom(0.0), hlock(LockCenter),vlock(LockCenter),
67
+ layout(LayoutOverlay), scroll_offset(0), show(1), zorder(0), handler(0), scroll_show(1) {}
68
+
69
+ virtual ~View() {}
70
+
71
+ //! Activate Displays viewport for drawing within this area
72
+ void Activate() const;
73
+
74
+ //! Activate Displays and set State Matrices
75
+ void Activate(const OpenGlRenderState& state ) const;
76
+
77
+ //! Activate Displays viewport and Scissor for drawing within this area
78
+ void ActivateAndScissor() const;
79
+
80
+ //! Activate Displays viewport and Scissor for drawing within this area
81
+ void ActivateScissorAndClear() const;
82
+
83
+ //! Activate Display and set State Matrices
84
+ void ActivateAndScissor(const OpenGlRenderState& state ) const;
85
+
86
+ //! Activate Display and set State Matrices
87
+ void ActivateScissorAndClear(const OpenGlRenderState& state ) const;
88
+
89
+ //! Activate Display and setup coordinate system for 2d pixel View coordinates
90
+ void ActivatePixelOrthographic() const;
91
+
92
+ //! Activate Display and reset coordinate system to OpenGL default
93
+ void ActivateIdentity() const;
94
+
95
+ //! Return closest depth buffer value within radius of window (winx,winy)
96
+ GLfloat GetClosestDepth(int winx, int winy, int radius) const;
97
+
98
+ //! Obtain camera space coordinates of scene at pixel (winx, winy, winzdepth)
99
+ //! winzdepth can be obtained from GetClosestDepth
100
+ void GetCamCoordinates(const OpenGlRenderState& cam_state, double winx, double winy, double winzdepth, GLdouble& x, GLdouble& y, GLdouble& z) const;
101
+
102
+ //! Obtain object space coordinates of scene at pixel (winx, winy, winzdepth)
103
+ //! winzdepth can be obtained from GetClosestDepth
104
+ void GetObjectCoordinates(const OpenGlRenderState& cam_state, double winx, double winy, double winzdepth, GLdouble& x, GLdouble& y, GLdouble& z) const;
105
+
106
+ //! Given the specification of Display, compute viewport
107
+ virtual void Resize(const Viewport& parent);
108
+
109
+ //! Instruct all children to resize
110
+ virtual void ResizeChildren();
111
+
112
+ //! Perform any automatic rendering for this View.
113
+ //! Default implementation simply instructs children to render themselves.
114
+ virtual void Render();
115
+
116
+ //! Instruct all children to render themselves if appropriate
117
+ virtual void RenderChildren();
118
+
119
+ //! Set this view as the active View to receive input
120
+ View& SetFocus();
121
+
122
+ //! Returns true iff this view currently has focus and will receive user input
123
+ bool HasFocus() const;
124
+
125
+ //! Set bounds for the View using mixed fractional / pixel coordinates (OpenGl view coordinates)
126
+ View& SetBounds(Attach bottom, Attach top, Attach left, Attach right);
127
+
128
+ //! Set bounds for the View using mixed fractional / pixel coordinates (OpenGl view coordinates)
129
+ View& SetBounds(Attach bottom, Attach top, Attach left, Attach right, bool keep_aspect);
130
+
131
+ //! Set bounds for the View using mixed fractional / pixel coordinates (OpenGl view coordinates)
132
+ View& SetBounds(Attach bottom, Attach top, Attach left, Attach right, double aspect);
133
+
134
+ //! Designate handler for accepting mouse / keyboard input.
135
+ View& SetHandler(Handler* handler);
136
+
137
+ //! Set drawFunc as the drawing function for this view
138
+ View& SetDrawFunction(const std::function<void(View&)>& drawFunc);
139
+
140
+ //! Force this view to have the given aspect, whilst fitting snuggly
141
+ //! within the parent. A negative value with 'over-draw', fitting the
142
+ //! smaller side of the parent.
143
+ View& SetAspect(double aspect);
144
+
145
+ //! Set how this view should be positioned relative to its parent
146
+ View& SetLock(Lock horizontal, Lock vertical );
147
+
148
+ //! Set layout policy for this view
149
+ View& SetLayout(Layout layout);
150
+
151
+ //! Add view as child
152
+ View& AddDisplay(View& view);
153
+
154
+ //! Show / hide this view
155
+ View& Show(bool show=true);
156
+
157
+ //! Toggle this views visibility
158
+ void ToggleShow();
159
+
160
+ //! Return whether this view should be shown.
161
+ //! This method should be checked if drawing manually
162
+ bool IsShown() const;
163
+
164
+ //! Returns viewport reflecting space that will actually get drawn
165
+ //! The minimum of vp and v
166
+ Viewport GetBounds() const;
167
+
168
+ //! Return number of child views attached to this view
169
+ size_t NumChildren() const;
170
+
171
+ //! Return (i)th child of this view
172
+ View& operator[](size_t i);
173
+
174
+ //! Return number of visible child views attached to this view.
175
+ size_t NumVisibleChildren() const;
176
+
177
+ //! Return visible child by index.
178
+ View& VisibleChild(size_t i);
179
+
180
+ //! Return visible child at window coords x,y
181
+ View* FindChild(int x, int y);
182
+
183
+ // Desired width / height aspect (0 if dynamic)
184
+ double aspect;
185
+
186
+ // Bounds to fit display within
187
+ Attach top, left, right, bottom;
188
+ Lock hlock;
189
+ Lock vlock;
190
+ Layout layout;
191
+
192
+ int scroll_offset;
193
+
194
+ // Cached client area (space allocated from parent)
195
+ Viewport vp;
196
+
197
+ // Cached absolute viewport (recomputed on resize - respects aspect)
198
+ Viewport v;
199
+
200
+ // Should this view be displayed?
201
+ bool show;
202
+
203
+ // Child views are rendered in order of low to high z-order
204
+ // Views default to 0 z-order
205
+ int zorder;
206
+
207
+ // Input event handler (if any)
208
+ Handler* handler;
209
+
210
+ // Map for sub-displays (if any)
211
+ std::vector<View*> views;
212
+
213
+ // External draw function
214
+ std::function<void(View&)> extern_draw_function;
215
+
216
+ ////////////////////////////////////////////////
217
+
218
+ PANGOLIN_DEPRECATED("Use pangolin::SaveWindowOnRender(...) instead.")
219
+ void SaveOnRender(const std::string& filename_hint);
220
+
221
+ PANGOLIN_DEPRECATED("Use pangolin::SaveWindowNow(...) instead.")
222
+ void SaveRenderNow(const std::string& filename_hint);
223
+
224
+ private:
225
+ // Private copy constructor
226
+ View(View&) { /* Do Not copy - take reference instead*/ }
227
+
228
+ bool scroll_show;
229
+ };
230
+
231
+ }
third-party/DPVO/Pangolin/components/pango_display/include/pangolin/display/widgets.h ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #pragma once
29
+
30
+ #include <pangolin/display/view.h>
31
+ #include <pangolin/var/var.h>
32
+ #include <pangolin/handler/handler.h>
33
+ #include <pangolin/gl/glfont.h>
34
+
35
+ #include <functional>
36
+
37
+ namespace pangolin
38
+ {
39
+
40
+ PANGOLIN_EXPORT
41
+ View& CreatePanel(const std::string& name);
42
+
43
+ struct PANGOLIN_EXPORT Panel : public View
44
+ {
45
+ Panel();
46
+ Panel(const std::string& auto_register_var_prefix);
47
+ void Render();
48
+ void ResizeChildren();
49
+
50
+ private:
51
+ void NewVarCallback(const VarState::Event& e);
52
+ void AddVariable(const std::string& name, const std::shared_ptr<VarValueGeneric> &var);
53
+ void RemoveVariable(const std::string& name);
54
+
55
+ sigslot::scoped_connection var_added_connection;
56
+ std::string auto_register_var_prefix;
57
+ };
58
+
59
+ template<typename T>
60
+ struct Widget : public View, Handler, Var<T>
61
+ {
62
+ Widget(std::string title, const std::shared_ptr<VarValueGeneric>& tv)
63
+ : Var<T>(tv), title(title)
64
+ {
65
+ handler = this;
66
+ }
67
+
68
+ std::string title;
69
+ };
70
+
71
+ struct PANGOLIN_EXPORT Button : public Widget<bool>
72
+ {
73
+ Button(std::string title, const std::shared_ptr<VarValueGeneric> &tv);
74
+ void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
75
+ void Render();
76
+
77
+ //Cache params on resize
78
+ void ResizeChildren();
79
+ GlText gltext;
80
+ GLfloat raster[2];
81
+ bool down;
82
+ };
83
+
84
+ struct PANGOLIN_EXPORT FunctionButton : public Widget<std::function<void(void)> >
85
+ {
86
+ FunctionButton(std::string title, const std::shared_ptr<VarValueGeneric> &tv);
87
+ void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
88
+ void Render();
89
+
90
+ //Cache params on resize
91
+ void ResizeChildren();
92
+ GlText gltext;
93
+ GLfloat raster[2];
94
+ bool down;
95
+ };
96
+
97
+ struct PANGOLIN_EXPORT Checkbox : public Widget<bool>
98
+ {
99
+ Checkbox(std::string title, const std::shared_ptr<VarValueGeneric>& tv);
100
+ void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
101
+ void Render();
102
+
103
+ //Cache params on resize
104
+ void ResizeChildren();
105
+ GlText gltext;
106
+ GLfloat raster[2];
107
+ Viewport vcb;
108
+ };
109
+
110
+ struct PANGOLIN_EXPORT Slider : public Widget<double>
111
+ {
112
+ Slider(std::string title, const std::shared_ptr<VarValueGeneric>& tv);
113
+ void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
114
+ void MouseMotion(View&, int x, int y, int mouse_state);
115
+ void Keyboard(View&, unsigned char key, int x, int y, bool pressed);
116
+ void Render();
117
+
118
+ //Cache params on resize
119
+ void ResizeChildren();
120
+ GlText gltext;
121
+ GLfloat raster[2];
122
+ bool lock_bounds;
123
+ bool logscale;
124
+ bool is_integral_type;
125
+ };
126
+
127
+ struct PANGOLIN_EXPORT TextInput : public Widget<std::string>
128
+ {
129
+ TextInput(std::string title, const std::shared_ptr<VarValueGeneric>& tv);
130
+ void Mouse(View&, MouseButton button, int x, int y, bool pressed, int mouse_state);
131
+ void MouseMotion(View&, int x, int y, int mouse_state);
132
+ void Keyboard(View&, unsigned char key, int x, int y, bool pressed);
133
+ void Render();
134
+
135
+ std::string edit;
136
+ GlText gledit;
137
+
138
+ //Cache params on resize
139
+ void ResizeChildren();
140
+ void CalcVisibleEditPart();
141
+ GlText gltext;
142
+ bool can_edit;
143
+ bool do_edit;
144
+ int sel[2];
145
+ GLfloat vertical_margin;
146
+ GLfloat horizontal_margin = 2.f;
147
+ int input_width;
148
+ int edit_visible_part[2] = {0,1};
149
+ };
150
+
151
+
152
+ inline bool GuiVarHasChanged() {
153
+ Var<bool> changed("pango.widgets.gui_changed");
154
+ return bool(changed) && !(changed = false);
155
+ }
156
+
157
+ inline void FlagVarChanged() {
158
+ Var<bool>("pango.widgets.gui_changed") = true;
159
+ }
160
+
161
+ }
third-party/DPVO/Pangolin/components/pango_display/include/pangolin/handler/handler.h ADDED
@@ -0,0 +1,139 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2013 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #pragma once
29
+
30
+ #include <pangolin/gl/opengl_render_state.h>
31
+ #include <pangolin/gl/gl.h>
32
+ #include <pangolin/windowing/handler_enums.h>
33
+
34
+ #if defined(HAVE_EIGEN) && !defined(__CUDACC__) //prevent including Eigen in cuda files
35
+ #define USE_EIGEN
36
+ #endif
37
+
38
+ #ifdef USE_EIGEN
39
+ #include <Eigen/Core>
40
+ #endif
41
+
42
+ #ifdef _OSX_
43
+ #define PANGO_DFLT_HANDLER3D_ZF (1.0f/50.0f)
44
+ #else
45
+ #define PANGO_DFLT_HANDLER3D_ZF (1.0f/10.0f)
46
+ #endif
47
+
48
+ namespace pangolin
49
+ {
50
+
51
+ // Forward declarations
52
+ struct View;
53
+
54
+ /// Input Handler base class.
55
+ /// Virtual methods which recurse into sub-displays.
56
+ struct PANGOLIN_EXPORT Handler
57
+ {
58
+ virtual ~Handler() {}
59
+ virtual void Keyboard(View&, unsigned char key, int x, int y, bool pressed);
60
+ virtual void Mouse(View&, MouseButton button, int x, int y, bool pressed, int button_state);
61
+ virtual void MouseMotion(View&, int x, int y, int button_state);
62
+ virtual void PassiveMouseMotion(View&, int x, int y, int button_state);
63
+ virtual void Special(View&, InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state);
64
+ };
65
+
66
+ struct PANGOLIN_EXPORT HandlerScroll : Handler
67
+ {
68
+ void Mouse(View&, MouseButton button, int x, int y, bool pressed, int button_state);
69
+ void Special(View&, InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state);
70
+ };
71
+
72
+ struct PANGOLIN_EXPORT HandlerBase3D : Handler
73
+ {
74
+ HandlerBase3D(OpenGlRenderState& cam_state, AxisDirection enforce_up=AxisNone, float trans_scale=0.01f, float zoom_fraction= PANGO_DFLT_HANDLER3D_ZF);
75
+
76
+ virtual bool ValidWinDepth(GLprecision depth);
77
+ virtual void PixelUnproject( View& view, GLprecision winx, GLprecision winy, GLprecision winz, GLprecision Pc[3]);
78
+ virtual void GetPosNormal(View& view, int x, int y, GLprecision p[3], GLprecision Pw[3], GLprecision Pc[3], GLprecision nw[3], GLprecision default_z = 1.0);
79
+ virtual void GetPosNormalImpl(View& view, int x, int y, GLprecision p[3], GLprecision Pw[3], GLprecision Pc[3], GLprecision nw[3], GLprecision default_z, float *zs);
80
+
81
+ void Keyboard(View&, unsigned char key, int x, int y, bool pressed);
82
+ void Mouse(View&, MouseButton button, int x, int y, bool pressed, int button_state);
83
+ void MouseMotion(View&, int x, int y, int button_state);
84
+ void Special(View&, InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state);
85
+
86
+ #ifdef USE_EIGEN
87
+ // Return selected point in world coordinates
88
+ inline Eigen::Vector3d Selected_P_w() const {
89
+ return Eigen::Map<const Eigen::Matrix<GLprecision,3,1>>(Pw).cast<double>();
90
+ }
91
+ #endif
92
+ inline int KeyState() const{
93
+ return funcKeyState;
94
+ }
95
+
96
+ protected:
97
+ OpenGlRenderState* cam_state;
98
+ const static int hwin = 8;
99
+ AxisDirection enforce_up;
100
+ float tf; // translation factor
101
+ float zf; // zoom fraction
102
+ CameraSpec cameraspec;
103
+ GLprecision last_z;
104
+ float last_pos[2];
105
+ GLprecision rot_center[3];
106
+
107
+ GLprecision p[3];
108
+ GLprecision Pw[3];
109
+ GLprecision Pc[3];
110
+ GLprecision n[3];
111
+
112
+ int funcKeyState;
113
+ };
114
+
115
+ #ifndef HAVE_GLES
116
+ using Handler3D = HandlerBase3D;
117
+ #else
118
+ struct PANGOLIN_EXPORT Handler3DBlitCopy : public pangolin::HandlerBase3D
119
+ {
120
+ Handler3DBlitCopy(pangolin::OpenGlRenderState& cam_state, pangolin::AxisDirection enforce_up=pangolin::AxisNone, float trans_scale=0.01f);
121
+ void GetPosNormal(pangolin::View& view, int x, int y, GLprecision p[3], GLprecision Pw[3], GLprecision Pc[3], GLprecision /*n*/[3], GLprecision default_z = 1.0);
122
+
123
+ protected:
124
+ GlTexture rgb_blit;
125
+ GlTexture depth_blit;
126
+ GlFramebuffer fb_blit;
127
+
128
+ GlTexture rgb;
129
+ GlTexture depth;
130
+ GlFramebuffer fb;
131
+ };
132
+ using Handler3D = Handler3DBlitCopy;
133
+ #endif
134
+
135
+
136
+ static Handler StaticHandler;
137
+ static HandlerScroll StaticHandlerScroll;
138
+
139
+ }
third-party/DPVO/Pangolin/components/pango_display/include/pangolin/handler/handler_glbuffer.h ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2014 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #ifndef HANDLER_GLBUFFER_H
29
+ #define HANDLER_GLBUFFER_H
30
+
31
+ #include <pangolin/handler/handler.h>
32
+ #include <pangolin/gl/gl.h>
33
+
34
+ namespace pangolin
35
+ {
36
+
37
+ struct PANGOLIN_EXPORT Handler3DFramebuffer : public pangolin::HandlerBase3D
38
+ {
39
+ Handler3DFramebuffer(GlFramebuffer& fb, pangolin::OpenGlRenderState& cam_state, pangolin::AxisDirection enforce_up=pangolin::AxisNone, float trans_scale=0.01f);
40
+ void GetPosNormal(pangolin::View& view, int x, int y, GLprecision p[3], GLprecision Pw[3], GLprecision Pc[3], GLprecision /*n*/[3], GLprecision default_z);
41
+
42
+ protected:
43
+ GlFramebuffer& fb;
44
+ };
45
+
46
+ }
47
+
48
+ #endif // HANDLER_GLBUFFER_H
third-party/DPVO/Pangolin/components/pango_display/include/pangolin/handler/handler_image.h ADDED
@@ -0,0 +1,166 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2013 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #pragma once
29
+
30
+ #include <pangolin/image/image_utils.h>
31
+ #include <pangolin/display/view.h>
32
+ #include <pangolin/handler/handler.h>
33
+ #include <pangolin/gl/viewport.h>
34
+ #include <pangolin/gl/gl.h>
35
+ #include <pangolin/utils/range.h>
36
+
37
+ #include <functional>
38
+
39
+ namespace pangolin
40
+ {
41
+
42
+ class PANGOLIN_EXPORT ImageViewHandler : public Handler
43
+ {
44
+ public:
45
+ struct EventData {
46
+ EventData(View& v, ImageViewHandler& h) : view(v), handler(h) {}
47
+ View& view;
48
+ ImageViewHandler& handler;
49
+ };
50
+
51
+ struct OnSelectionEventData : public EventData {
52
+ OnSelectionEventData(View& v, ImageViewHandler& h, bool dragging)
53
+ : EventData(v,h), dragging(dragging) {}
54
+ bool dragging;
55
+ };
56
+
57
+ typedef std::function<void(OnSelectionEventData)> OnSelectionCallbackFn;
58
+
59
+ // Default constructor: User must call SetDimensions() once image dimensions are known.
60
+ // Default range is [0,1] in x and y.
61
+ ImageViewHandler(const std::string & title = "");
62
+
63
+ // View ranges store extremes of image (boundary of pixels)
64
+ // in 'discrete' coords, where 0,0 is center of top-left pixel.
65
+ ImageViewHandler(size_t w, size_t h);
66
+
67
+ void SetDimensions(size_t w, size_t h);
68
+
69
+ void UpdateView();
70
+
71
+ void glSetViewOrtho();
72
+
73
+ void glRenderTexture(pangolin::GlTexture& tex);
74
+ void glRenderTexture(GLuint tex, GLint width, GLint height);
75
+ void glRenderTexture(GLuint tex, GLint width, GLint height, XYRangef tex_region);
76
+
77
+
78
+ void glRenderOverlay();
79
+
80
+ void ScreenToImage(Viewport& v, float xpix, float ypix, float& ximg, float& yimg);
81
+
82
+ void ImageToScreen(Viewport& v, float ximg, float yimg, float& xpix, float& ypix);
83
+
84
+ bool UseNN() const;
85
+
86
+ bool& UseNN();
87
+
88
+ bool& FlipTextureX();
89
+
90
+ bool& FlipTextureY();
91
+
92
+ pangolin::XYRangef& GetViewToRender();
93
+
94
+ float GetViewScale();
95
+
96
+ pangolin::XYRangef& GetView();
97
+
98
+ pangolin::XYRangef& GetDefaultView();
99
+
100
+ pangolin::XYRangef& GetSelection();
101
+
102
+ void GetHover(float& x, float& y);
103
+
104
+ void SetView(const pangolin::XYRangef& range);
105
+
106
+ void SetViewSmooth(const pangolin::XYRangef& range);
107
+
108
+ void ScrollView(float x, float y);
109
+
110
+ void ScrollViewSmooth(float x, float y);
111
+
112
+ void ScaleView(float x, float y, float cx, float cy);
113
+
114
+ void ScaleViewSmooth(float x, float y, float cx, float cy);
115
+
116
+ void ResetView();
117
+
118
+ ///////////////////////////////////////////////////////
119
+ /// pangolin::Handler
120
+ ///////////////////////////////////////////////////////
121
+
122
+ void Keyboard(View&, unsigned char key, int /*x*/, int /*y*/, bool pressed) override;
123
+
124
+ void Mouse(View& view, pangolin::MouseButton button, int x, int y, bool pressed, int button_state) override;
125
+
126
+ void MouseMotion(View& view, int x, int y, int button_state) override;
127
+
128
+ void PassiveMouseMotion(View&, int /*x*/, int /*y*/, int /*button_state*/) override;
129
+
130
+ void Special(View& view, pangolin::InputSpecial inType, float x, float y, float p1, float p2, float /*p3*/, float /*p4*/, int /*button_state*/) override;
131
+
132
+ ///////////////////////////////////////////////////////
133
+ /// Callbacks
134
+ ///////////////////////////////////////////////////////
135
+
136
+ OnSelectionCallbackFn OnSelectionCallback;
137
+
138
+ protected:
139
+ void FixSelection(XYRangef& sel);
140
+
141
+ void AdjustScale();
142
+
143
+ void AdjustTranslation();
144
+
145
+ static ImageViewHandler* to_link;
146
+ static float animate_factor;
147
+
148
+ ImageViewHandler* linked_view_handler;
149
+
150
+ pangolin::XYRangef rview_default;
151
+ pangolin::XYRangef rview_max;
152
+ pangolin::XYRangef rview;
153
+ pangolin::XYRangef target;
154
+ pangolin::XYRangef selection;
155
+
156
+ float hover_img[2];
157
+ int last_mouse_pos[2];
158
+
159
+ bool use_nn;
160
+ bool flipTextureX;
161
+ bool flipTextureY;
162
+ std::string title;
163
+
164
+ };
165
+
166
+ }
third-party/DPVO/Pangolin/components/pango_display/src/ConsoleView.cpp ADDED
@@ -0,0 +1,327 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <iterator>
2
+ #include <pangolin/console/ConsoleView.h>
3
+ #include <pangolin/utils/picojson.h>
4
+ #include <pangolin/gl/gldraw.h>
5
+ #include <pangolin/display/default_font.h>
6
+
7
+ namespace pangolin
8
+ {
9
+
10
+ inline Colour ParseJson(const picojson::value& val)
11
+ {
12
+ return Colour(
13
+ val.contains("r") ? val["r"].get<double>() : 0.0,
14
+ val.contains("g") ? val["g"].get<double>() : 0.0,
15
+ val.contains("b") ? val["b"].get<double>() : 0.0,
16
+ val.contains("a") ? val["a"].get<double>() : 1.0
17
+ );
18
+ }
19
+
20
+ inline picojson::value toJson(const Colour& colour)
21
+ {
22
+ picojson::value ret(picojson::object_type,true);
23
+ ret["r"] = colour.r;
24
+ ret["g"] = colour.g;
25
+ ret["b"] = colour.b;
26
+ ret["a"] = colour.a;
27
+ return ret;
28
+ }
29
+
30
+ inline std::ostream& operator<<(std::ostream& os, const Colour& colour)
31
+ {
32
+ os << toJson(colour).serialize();
33
+ return os;
34
+ }
35
+
36
+ inline std::istream& operator>>(std::istream& is, Colour& colour)
37
+ {
38
+ picojson::value val;
39
+ picojson::parse(val,is);
40
+ colour = ParseJson(val);
41
+ return is;
42
+ }
43
+
44
+ inline void glColour(const Colour& c)
45
+ {
46
+ glColor4f(c.r,c.g,c.b,c.a);
47
+ }
48
+
49
+ ConsoleView::ConsoleView(const std::shared_ptr<InterpreterInterface> &interpreter)
50
+ : interpreter(interpreter),
51
+ font(default_font()),
52
+ carat(0),
53
+ hiding(false),
54
+ bottom(1.0f),
55
+ background_colour(0.2f, 0.0f, 0.0f, 0.6f),
56
+ animation_speed(0.2)
57
+ {
58
+ SetHandler(this);
59
+
60
+ line_colours[ConsoleLineTypeCmd] = Colour(1.0f,1.0f,1.0f,1.0f);
61
+ line_colours[ConsoleLineTypeCmdOptions] = Colour(0.9f,0.9f,0.9f,1.0f);
62
+ line_colours[ConsoleLineTypeOutput] = Colour(0.0f,1.0f,1.0f,1.0f);
63
+ line_colours[ConsoleLineTypeHelp] = Colour(1.0f,0.8f,1.0f,1.0f);
64
+ line_colours[ConsoleLineTypeStdout] = Colour(0.0f,0.0f,1.0f,1.0f);
65
+ line_colours[ConsoleLineTypeStderr] = Colour(1.0f,0.8f,0.8f,1.0f);
66
+
67
+ Var<Colour>::Attach("pango.console.colours.Background", background_colour);
68
+ Var<Colour>::Attach("pango.console.colours.Cmd", line_colours[ConsoleLineTypeCmd]);
69
+ Var<Colour>::Attach("pango.console.colours.CmdOptions", line_colours[ConsoleLineTypeCmdOptions]);
70
+ Var<Colour>::Attach("pango.console.colours.Stdout", line_colours[ConsoleLineTypeStdout]);
71
+ Var<Colour>::Attach("pango.console.colours.Stderr", line_colours[ConsoleLineTypeStderr]);
72
+ Var<Colour>::Attach("pango.console.colours.Output", line_colours[ConsoleLineTypeOutput]);
73
+ Var<Colour>::Attach("pango.console.colours.Help", line_colours[ConsoleLineTypeHelp]);
74
+
75
+ Var<float>::Attach("pango.console.animation_speed", animation_speed);
76
+
77
+ AddLine("Pangolin Console:", ConsoleLineTypeHelp);
78
+ AddLine("===============================", ConsoleLineTypeHelp);
79
+ }
80
+
81
+ ConsoleView::~ConsoleView() {
82
+ }
83
+
84
+ void ConsoleView::ProcessOutputLines()
85
+ {
86
+ // empty output queue
87
+ InterpreterLine line_in;
88
+ while(interpreter->PullLine(line_in))
89
+ {
90
+ AddLine(line_in.text, line_in.linetype);
91
+ }
92
+ }
93
+
94
+ View& ConsoleView::ShowWithoutAnimation(bool should_show){
95
+ Show(should_show);
96
+ bottom = show ? 1.0 : 0.0;
97
+ return *this;
98
+ }
99
+
100
+ View& ConsoleView::Show(bool should_show)
101
+ {
102
+ if(should_show) {
103
+ hiding = false;
104
+ show = true;
105
+ }else{
106
+ hiding = true;
107
+ }
108
+ return *this;
109
+ }
110
+
111
+ void ConsoleView::ToggleShow()
112
+ {
113
+ Show(!IsShown());
114
+ }
115
+
116
+ bool ConsoleView::IsShown() const
117
+ {
118
+ return show && !hiding;
119
+ }
120
+
121
+ void ConsoleView::DrawLine(const ConsoleView::Line& l, int carat=-1)
122
+ {
123
+ glColour(line_colours[l.linetype]);
124
+ l.text.Draw();
125
+ if(carat >= 0) {
126
+ const double w = font.Text(l.text.str.substr(0,carat)).Width();
127
+ glDrawLine(w,-2,w,font.Height()-4);
128
+ }
129
+ }
130
+
131
+ void ConsoleView::Render()
132
+ {
133
+ if(hiding) {
134
+ bottom += (1.0f - bottom) * animation_speed;
135
+ if(1.0 - bottom < 0.01) {
136
+ bottom = 1.0;
137
+ show = false;
138
+ hiding = false;
139
+ return;
140
+ }
141
+ }else{
142
+ if(bottom > 0.01f) {
143
+ bottom -= bottom*animation_speed;
144
+ }else{
145
+ bottom = 0.0f;
146
+ }
147
+ }
148
+
149
+ ProcessOutputLines();
150
+
151
+ #ifndef HAVE_GLES
152
+ glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT | GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
153
+ #endif
154
+
155
+ this->ActivatePixelOrthographic();
156
+ glDisable(GL_DEPTH_TEST );
157
+ glDisable(GL_LIGHTING);
158
+ glDisable(GL_SCISSOR_TEST);
159
+ glDisable(GL_LINE_SMOOTH);
160
+ glDisable( GL_COLOR_MATERIAL );
161
+ glLineWidth(1.0);
162
+
163
+ glEnable(GL_BLEND);
164
+ glBlendFunc( GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA );
165
+
166
+ glColour(background_colour);
167
+
168
+ GLfloat verts[] = { 0.0f, (GLfloat)v.h,
169
+ (GLfloat)v.w, (GLfloat)v.h,
170
+ (GLfloat)v.w, bottom*v.h,
171
+ 0.0f, bottom*v.h };
172
+ glEnableClientState(GL_VERTEX_ARRAY);
173
+ glVertexPointer(2, GL_FLOAT, 0, verts);
174
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
175
+ glDisableClientState(GL_VERTEX_ARRAY);
176
+
177
+
178
+ const GLfloat line_space = font.Height();
179
+ glTranslatef(10.0f, 10.0f + bottom*v.h, 0.0f );
180
+ DrawLine(current_line, carat);
181
+ glTranslatef(0.0f, line_space, 0.0f);
182
+ for(size_t l=0; l < line_buffer.size(); ++l) {
183
+ DrawLine(line_buffer[l]);
184
+ glTranslatef(0.0f, line_space, 0.0f);
185
+ }
186
+
187
+ #ifndef HAVE_GLES
188
+ glPopAttrib();
189
+ #endif
190
+ }
191
+
192
+ inline std::string CommonPrefix(const std::vector<std::string>& vec)
193
+ {
194
+ if(!vec.size()) return "";
195
+
196
+ size_t cmn = vec[0].size();
197
+ for(size_t i=1; i<vec.size(); ++i) {
198
+ cmn = std::min(vec[i].size(), cmn);
199
+ for(size_t p=0; p < cmn; ++p) {
200
+ if(vec[i][p] != vec[0][p]) {
201
+ cmn = p;
202
+ break;
203
+ }
204
+ }
205
+ }
206
+
207
+ return vec[0].substr(0,cmn);
208
+ }
209
+
210
+ void ConsoleView::Keyboard(View&, unsigned char key, int /*x*/, int /*y*/, bool pressed)
211
+ {
212
+ static int hist_id = -1;
213
+ static std::string prefix;
214
+ static bool edited = true;
215
+
216
+ if(pressed) {
217
+ if(key=='\r') key = '\n';
218
+
219
+ GlText& txt = current_line.text;
220
+ const std::string cmd = txt.Text();
221
+
222
+ if(key=='`') {
223
+ ToggleShow();
224
+ } else if(key=='\n') {
225
+ interpreter->PushCommand(cmd);
226
+ line_buffer.push_front(current_line);
227
+ hist_id = -1;
228
+ prefix = "";
229
+ edited = true;
230
+ carat = 0;
231
+ txt.Clear();
232
+ }else if(key=='\t') {
233
+ std::vector<std::string> options = interpreter->Complete(cmd,100);
234
+ if(options.size()) {
235
+ const std::string common = CommonPrefix(options);
236
+ if(common.size() > cmd.size()) {
237
+ current_line = font.Text("%s", common.c_str());
238
+ carat = common.size();
239
+ }else{
240
+ std::stringstream s;
241
+ std::copy(options.begin(), options.end(), std::ostream_iterator<std::string>(s,", "));
242
+ AddLine(s.str(), ConsoleLineTypeCmdOptions);
243
+ }
244
+ }
245
+ }else if(key==PANGO_SPECIAL + PANGO_KEY_UP) {
246
+ if(edited) {
247
+ prefix = cmd;
248
+ edited = false;
249
+ }
250
+ Line* hist_line = GetLine(hist_id+1, ConsoleLineTypeCmd, prefix);
251
+ if(hist_line) {
252
+ current_line = *hist_line;
253
+ hist_id++;
254
+ }
255
+ }else if(key==PANGO_SPECIAL + PANGO_KEY_DOWN) {
256
+ if(edited) {
257
+ prefix = cmd;
258
+ edited = false;
259
+ }
260
+ Line* hist_line = GetLine(hist_id-1, ConsoleLineTypeCmd, prefix);
261
+ if(hist_line) {
262
+ current_line = *hist_line;
263
+ hist_id--;
264
+ }
265
+ }else if(key==PANGO_SPECIAL + PANGO_KEY_LEFT) {
266
+ if(carat > 0) carat--;
267
+ }else if(key==PANGO_SPECIAL + PANGO_KEY_RIGHT) {
268
+ if(carat < (int)txt.str.size()) carat++;
269
+ }else if(key==PANGO_SPECIAL + PANGO_KEY_HOME) {
270
+ carat = 0;
271
+ }else if(key==PANGO_SPECIAL + PANGO_KEY_END) {
272
+ carat = txt.Text().size();
273
+ }else if(key=='\b') {
274
+ if(carat > 0) {
275
+ std::string newstr = txt.Text();
276
+ newstr.erase(newstr.begin()+carat-1);
277
+ txt = font.Text("%s", newstr.c_str() );
278
+ carat--;
279
+ edited = true;
280
+ }
281
+ }else if(key==127) { // delete
282
+ if(carat < (int)txt.Text().size() ) {
283
+ std::string newstr = txt.Text();
284
+ newstr.erase(newstr.begin()+carat);
285
+ txt = font.Text("%s", newstr.c_str() );
286
+ edited = true;
287
+ }
288
+ }else if(key==PANGO_CTRL + 'c') {
289
+ txt = font.Text("");
290
+ carat = 0;
291
+ edited = true;
292
+ }else if(key < PANGO_SPECIAL){
293
+ std::string newstr = txt.Text();
294
+ newstr.insert(carat, 1, key);
295
+ txt = font.Text("%s", newstr.c_str());
296
+ ++carat;
297
+ edited = true;
298
+ }
299
+ }
300
+ }
301
+
302
+ void ConsoleView::AddLine(const std::string& text, InterpreterLineType linetype )
303
+ {
304
+ line_buffer.push_front( Line( font.Text("%s",text.c_str()), linetype) );
305
+ }
306
+
307
+ ConsoleView::Line* ConsoleView::GetLine(int id, InterpreterLineType line_type, const std::string& prefix )
308
+ {
309
+ int match = 0;
310
+ for(Line& l : line_buffer)
311
+ {
312
+ if(l.linetype == line_type) {
313
+ const std::string substr = l.text.Text().substr(0,prefix.size());
314
+ if(substr == prefix ) {
315
+ if(id == match) {
316
+ return &l;
317
+ }else{
318
+ ++match;
319
+ }
320
+ }
321
+ }
322
+ }
323
+
324
+ return nullptr;
325
+ }
326
+
327
+ }
third-party/DPVO/Pangolin/components/pango_display/src/default_font.cpp ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <pangolin/display/default_font.h>
2
+
3
+ #include "pangolin_gl.h"
4
+
5
+ extern const unsigned char AnonymousPro_ttf[];
6
+
7
+ namespace pangolin {
8
+
9
+ GlFont& default_font()
10
+ {
11
+ PangolinGl* context = GetCurrentContext();
12
+ PANGO_ASSERT(context);
13
+ if(!context->font) {
14
+ context->font = std::make_shared<GlFont>(AnonymousPro_ttf, 18);
15
+ }
16
+ return *(context->font.get());
17
+ }
18
+
19
+ }
third-party/DPVO/Pangolin/components/pango_display/src/display.cpp ADDED
@@ -0,0 +1,347 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove, Richard Newcombe
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include <pangolin/platform.h>
29
+
30
+
31
+ #include <iostream>
32
+ #include <sstream>
33
+ #include <string>
34
+ #include <map>
35
+ #include <mutex>
36
+ #include <cstdlib>
37
+ #include <memory>
38
+
39
+ #include <pangolin/gl/gl.h>
40
+ #include <pangolin/gl/gldraw.h>
41
+ #include <pangolin/factory/factory_registry.h>
42
+ #include <pangolin/display/display.h>
43
+ #include <pangolin/display/process.h>
44
+ #include <pangolin/console/ConsoleView.h>
45
+ #include <pangolin/utils/simple_math.h>
46
+ #include <pangolin/utils/timer.h>
47
+ #include <pangolin/utils/type_convert.h>
48
+ #include <pangolin/image/image_io.h>
49
+ #include <pangolin/var/var.h>
50
+
51
+ #include "pangolin_gl.h"
52
+
53
+ extern const unsigned char AnonymousPro_ttf[];
54
+
55
+ namespace pangolin
56
+ {
57
+
58
+ typedef std::map<std::string,std::shared_ptr<PangolinGl> > ContextMap;
59
+
60
+ // Map of active contexts
61
+ ContextMap contexts;
62
+ std::recursive_mutex contexts_mutex;
63
+
64
+ // Context active for current thread
65
+ __thread PangolinGl* context = 0;
66
+
67
+ void SetCurrentContext(PangolinGl* newcontext) {
68
+ context = newcontext;
69
+ }
70
+
71
+ PangolinGl* GetCurrentContext()
72
+ {
73
+ return context;
74
+ }
75
+
76
+ PangolinGl *FindContext(const std::string& name)
77
+ {
78
+ contexts_mutex.lock();
79
+ ContextMap::iterator ic = contexts.find(name);
80
+ PangolinGl* context = (ic == contexts.end()) ? 0 : ic->second.get();
81
+ contexts_mutex.unlock();
82
+ return context;
83
+ }
84
+
85
+ WindowInterface& CreateWindowAndBind(std::string window_title, int w, int h, const Params& params)
86
+ {
87
+ std::unique_lock<std::recursive_mutex> l(contexts_mutex);
88
+
89
+ pangolin::Uri win_uri;
90
+
91
+ if(const char* extra_params = std::getenv("PANGOLIN_WINDOW_URI"))
92
+ {
93
+ // Take any defaults from the environment
94
+ win_uri = pangolin::ParseUri(extra_params);
95
+ }else{
96
+ // Otherwise revert to 'default' scheme.
97
+ win_uri.scheme = "default";
98
+ }
99
+
100
+ // Override with anything the program specified
101
+ for(const auto& param : params.params) {
102
+ if(param.first != "scheme") win_uri.params.push_back(param);
103
+ }
104
+
105
+ // Special params that shouldn't get passed to window factory
106
+ win_uri.scheme = win_uri.Get("scheme", win_uri.scheme);
107
+ const std::string default_font = win_uri.Get<std::string>("default_font","");
108
+ const int default_font_size = win_uri.Get("default_font_size", 18);
109
+ win_uri.Remove("scheme");
110
+ win_uri.Remove("default_font");
111
+ win_uri.Remove("default_font_size");
112
+
113
+ // Additional arguments we will send to factory
114
+ win_uri.Set("w", w);
115
+ win_uri.Set("h", h);
116
+ win_uri.Set("window_title", window_title);
117
+
118
+ auto context = std::make_shared<PangolinGl>();
119
+ context->window = ConstructWindow(win_uri);
120
+ assert(context->window);
121
+
122
+ RegisterNewContext(window_title, context);
123
+
124
+ context->window->CloseSignal.connect( [](){
125
+ pangolin::Quit();
126
+ });
127
+ context->window->ResizeSignal.connect( [](WindowResizeEvent event){
128
+ process::Resize(event.width, event.height);
129
+ });
130
+ context->window->KeyboardSignal.connect( [](KeyboardEvent event) {
131
+ process::Keyboard(event.key, event.x, event.y, event.pressed, event.key_modifiers);
132
+ });
133
+ context->window->MouseSignal.connect( [](MouseEvent event){
134
+ process::Mouse(event.button, event.pressed, event.x, event.y, event.key_modifiers);
135
+ });
136
+ context->window->MouseMotionSignal.connect( [](MouseMotionEvent event){
137
+ process::MouseMotion(event.x, event.y, event.key_modifiers);
138
+ });
139
+ context->window->PassiveMouseMotionSignal.connect( [](MouseMotionEvent event){
140
+ process::PassiveMouseMotion(event.x, event.y, event.key_modifiers);
141
+ });
142
+ context->window->SpecialInputSignal.connect( [](SpecialInputEvent event){
143
+ process::SpecialInput(event.inType, event.x, event.y, event.p[0], event.p[1], event.p[2], event.p[3], event.key_modifiers);
144
+ });
145
+
146
+ // If there is a special font request
147
+ if( !default_font.empty() ) {
148
+ const std::string font_filename = PathExpand(default_font);
149
+ context->font = std::make_shared<GlFont>(font_filename, default_font_size);
150
+ }else{
151
+ context->font = std::make_shared<GlFont>(AnonymousPro_ttf, default_font_size);
152
+ }
153
+
154
+ context->MakeCurrent();
155
+ glewInit();
156
+
157
+ // And finally process pending window events (such as resize) now that we've setup our callbacks.
158
+ context->window->ProcessEvents();
159
+
160
+ return *context->window;
161
+ }
162
+
163
+ // Assumption: unique lock is held on contexts_mutex for multi-threaded operation
164
+ void RegisterNewContext(const std::string& name, std::shared_ptr<PangolinGl> newcontext)
165
+ {
166
+ // Set defaults
167
+ newcontext->base.left = 0.0;
168
+ newcontext->base.bottom = 0.0;
169
+ newcontext->base.top = 1.0;
170
+ newcontext->base.right = 1.0;
171
+ newcontext->base.aspect = 0;
172
+ newcontext->base.handler = &StaticHandler;
173
+
174
+ // Create and add
175
+ if( contexts.find(name) != contexts.end() ) {
176
+ throw std::runtime_error("Context already exists.");
177
+ }
178
+ contexts[name] = newcontext;
179
+
180
+ // Process the following as if this context is now current.
181
+ PangolinGl *oldContext = context;
182
+ context = newcontext.get();
183
+
184
+ // Default key bindings can be overridden
185
+ RegisterKeyPressCallback(PANGO_KEY_ESCAPE, Quit );
186
+ RegisterKeyPressCallback('\t', [](){ShowFullscreen(TrueFalseToggle::Toggle);} );
187
+ RegisterKeyPressCallback('`', [](){ShowConsole(TrueFalseToggle::Toggle);} );
188
+
189
+ context = oldContext;
190
+ }
191
+
192
+ WindowInterface* GetBoundWindow()
193
+ {
194
+ return context->window.get();
195
+ }
196
+
197
+ void DestroyWindow(const std::string& name)
198
+ {
199
+ contexts_mutex.lock();
200
+ ContextMap::iterator ic = contexts.find(name);
201
+ PangolinGl *context_to_destroy = (ic == contexts.end()) ? 0 : ic->second.get();
202
+ if (context_to_destroy == context) {
203
+ context = nullptr;
204
+ }
205
+ size_t erased = contexts.erase(name);
206
+ if(erased == 0) {
207
+ pango_print_warn("Context '%s' doesn't exist for deletion.\n", name.c_str());
208
+ }
209
+ contexts_mutex.unlock();
210
+ }
211
+
212
+ void BindToContext(std::string name)
213
+ {
214
+ std::unique_lock<std::recursive_mutex> l(contexts_mutex);
215
+
216
+ // N.B. context is modified prior to invoking MakeCurrent so that
217
+ // state management callbacks (such as Resize()) can be correctly
218
+ // processed.
219
+ PangolinGl *context_to_bind = FindContext(name);
220
+ if( !context_to_bind )
221
+ {
222
+ std::shared_ptr<PangolinGl> newcontext(new PangolinGl());
223
+ RegisterNewContext(name, newcontext);
224
+ }else{
225
+ context_to_bind->MakeCurrent();
226
+ }
227
+ }
228
+
229
+ void Quit()
230
+ {
231
+ context->quit = true;
232
+ }
233
+
234
+ void QuitAll()
235
+ {
236
+ for(auto& nc : contexts) {
237
+ nc.second->quit = true;
238
+ }
239
+ }
240
+
241
+ bool ShouldQuit()
242
+ {
243
+ return !context || context->quit;
244
+ }
245
+
246
+ void ShowFullscreen(TrueFalseToggle on_off)
247
+ {
248
+ if(context && context->window)
249
+ context->window->ShowFullscreen(on_off);
250
+ }
251
+
252
+
253
+ void FinishFrame()
254
+ {
255
+ if(context) context->FinishFrame();
256
+ }
257
+
258
+ View& DisplayBase()
259
+ {
260
+ return context->base;
261
+ }
262
+
263
+ View& CreateDisplay()
264
+ {
265
+ int iguid = rand();
266
+ std::stringstream ssguid;
267
+ ssguid << iguid;
268
+ return Display(ssguid.str());
269
+ }
270
+
271
+ void ShowConsole(TrueFalseToggle on_off)
272
+ {
273
+ if( !context->console_view) {
274
+ Uri interpreter_uri = ParseUri("python://");
275
+
276
+ try {
277
+ // Instantiate interpreter
278
+ std::shared_ptr<InterpreterInterface> interpreter
279
+ = FactoryRegistry::I()->Construct<InterpreterInterface>(interpreter_uri);
280
+ assert(interpreter);
281
+
282
+ // Create console and let the pangolin context take ownership
283
+ context->console_view = std::make_unique<ConsoleView>(interpreter);
284
+ context->console_view->zorder = std::numeric_limits<int>::max();
285
+ DisplayBase().AddDisplay(*context->console_view);
286
+ context->console_view->SetFocus();
287
+ } catch (std::exception&) {
288
+ }
289
+ }else{
290
+ context->console_view->Show(
291
+ to_bool(on_off, context->console_view->IsShown())
292
+ );
293
+
294
+ if(context->console_view->IsShown()) {
295
+ context->console_view->SetFocus();
296
+ }
297
+ }
298
+
299
+ }
300
+
301
+ View& Display(const std::string& name)
302
+ {
303
+ // Get / Create View
304
+ ViewMap::iterator vi = context->named_managed_views.find(name);
305
+ if( vi != context->named_managed_views.end() )
306
+ {
307
+ return *(vi->second);
308
+ }else{
309
+ View * v = new View();
310
+ context->named_managed_views[name] = v;
311
+ v->handler = &StaticHandler;
312
+ context->base.views.push_back(v);
313
+ return *v;
314
+ }
315
+ }
316
+
317
+ void RegisterKeyPressCallback(int key, std::function<void(int)> func)
318
+ {
319
+ context->keypress_hooks[key] = func;
320
+ }
321
+
322
+ void RegisterKeyPressCallback(int key, std::function<void(void)> func)
323
+ {
324
+ context->keypress_hooks[key] = [=](int){func();};
325
+ }
326
+
327
+ void SaveWindowOnRender(const std::string& filename, const Viewport& v)
328
+ {
329
+ context->screen_capture.push(std::pair<std::string,Viewport>(filename, v) );
330
+ }
331
+
332
+ void SaveWindowNow(const std::string& filename_hint, const Viewport& v)
333
+ {
334
+ const Viewport to_save = v.area() ? v.Intersect(DisplayBase().v) : DisplayBase().v;
335
+ std::string filename = filename_hint;
336
+ if(FileLowercaseExtention(filename) == "") filename += ".png";
337
+
338
+ try {
339
+ glFlush();
340
+ TypedImage buffer = ReadFramebuffer(to_save, "RGBA32");
341
+ SaveImage(buffer, filename, false);
342
+ } catch (std::exception& e) {
343
+ std::cerr << e.what() << std::endl;
344
+ }
345
+ }
346
+
347
+ }
third-party/DPVO/Pangolin/components/pango_display/src/handler.cpp ADDED
@@ -0,0 +1,472 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2013 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include <pangolin/display/view.h>
29
+ #include <pangolin/handler/handler.h>
30
+ #include <pangolin/display/display.h>
31
+
32
+ #include "pangolin_gl.h"
33
+
34
+ namespace pangolin
35
+ {
36
+
37
+ void Handler::Keyboard(View& d, unsigned char key, int x, int y, bool pressed)
38
+ {
39
+ View* child = d.FindChild(x,y);
40
+ if( child)
41
+ {
42
+ GetCurrentContext()->activeDisplay = child;
43
+ if( child->handler)
44
+ child->handler->Keyboard(*child,key,x,y,pressed);
45
+ }
46
+ }
47
+
48
+ void Handler::Mouse(View& d, MouseButton button, int x, int y, bool pressed, int button_state)
49
+ {
50
+ View* child = d.FindChild(x,y);
51
+ if( child )
52
+ {
53
+ GetCurrentContext()->activeDisplay = child;
54
+ if( child->handler)
55
+ child->handler->Mouse(*child,button,x,y,pressed,button_state);
56
+ }
57
+ }
58
+
59
+ void Handler::MouseMotion(View& d, int x, int y, int button_state)
60
+ {
61
+ View* child = d.FindChild(x,y);
62
+ if( child )
63
+ {
64
+ GetCurrentContext()->activeDisplay = child;
65
+ if( child->handler)
66
+ child->handler->MouseMotion(*child,x,y,button_state);
67
+ }
68
+ }
69
+
70
+ void Handler::PassiveMouseMotion(View& d, int x, int y, int button_state)
71
+ {
72
+ View* child = d.FindChild(x,y);
73
+ if( child )
74
+ {
75
+ if( child->handler)
76
+ child->handler->PassiveMouseMotion(*child,x,y,button_state);
77
+ }
78
+ }
79
+
80
+ void Handler::Special(View& d, InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state)
81
+ {
82
+ View* child = d.FindChild( (int)x, (int)y);
83
+ if( child )
84
+ {
85
+ GetCurrentContext()->activeDisplay = child;
86
+ if( child->handler)
87
+ child->handler->Special(*child,inType, x,y, p1, p2, p3, p4, button_state);
88
+ }
89
+ }
90
+
91
+ void HandlerScroll::Mouse(View& d, MouseButton button, int x, int y, bool pressed, int button_state)
92
+ {
93
+ if( pressed && (button == MouseWheelUp || button == MouseWheelDown) )
94
+ {
95
+ if( button == MouseWheelUp) d.scroll_offset -= 1;
96
+ if( button == MouseWheelDown) d.scroll_offset += 1;
97
+ d.scroll_offset = std::max(0, std::min(d.scroll_offset, (int)d.NumVisibleChildren()-1) );
98
+ d.ResizeChildren();
99
+ }else{
100
+ Handler::Mouse(d,button,x,y,pressed,button_state);
101
+ }
102
+ }
103
+
104
+ void HandlerScroll::Special(View& d, InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, int button_state)
105
+ {
106
+ if( inType == InputSpecialScroll )
107
+ {
108
+ d.scroll_offset -= (int)(p2 / fabs(p2));
109
+ d.scroll_offset = std::max(0, std::min(d.scroll_offset, (int)d.NumVisibleChildren()-1) );
110
+ d.ResizeChildren();
111
+ }else{
112
+ Handler::Special(d,inType,x,y,p1,p2,p3,p4,button_state);
113
+ }
114
+ }
115
+
116
+ HandlerBase3D::HandlerBase3D(OpenGlRenderState& cam_state, AxisDirection enforce_up, float trans_scale, float zoom_fraction)
117
+ : cam_state(&cam_state), enforce_up(enforce_up), tf(trans_scale), zf(zoom_fraction), cameraspec(CameraSpecOpenGl), last_z(0.8)
118
+ {
119
+ SetZero<3,1>(rot_center);
120
+ }
121
+
122
+ void HandlerBase3D::Keyboard(View&, unsigned char /*key*/, int /*x*/, int /*y*/, bool /*pressed*/)
123
+ {
124
+ // TODO: hooks for reset / changing mode (perspective / ortho etc)
125
+ }
126
+
127
+ bool HandlerBase3D::ValidWinDepth(GLprecision depth)
128
+ {
129
+ return depth != 1;
130
+ }
131
+
132
+ void HandlerBase3D::PixelUnproject( View& view, GLprecision winx, GLprecision winy, GLprecision winz, GLprecision Pc[3])
133
+ {
134
+ const GLint viewport[4] = {view.v.l,view.v.b,view.v.w,view.v.h};
135
+ const pangolin::OpenGlMatrix proj = cam_state->GetProjectionMatrix();
136
+ glUnProject(winx, winy, winz, IdentityMatrix().m, proj.m, viewport, &Pc[0], &Pc[1], &Pc[2]);
137
+ }
138
+
139
+ void HandlerBase3D::GetPosNormalImpl(pangolin::View& view, int winx, int winy, GLprecision p[3], GLprecision Pw[3], GLprecision Pc[3], GLprecision nw[3], GLprecision default_z, float* zs)
140
+ {
141
+ const int zl = (hwin*2+1);
142
+ const int zsize = zl*zl;
143
+
144
+ GLfloat mindepth = *(std::min_element(zs,zs+zsize));
145
+ if(mindepth == 1) mindepth = (GLfloat)default_z;
146
+
147
+ p[0] = winx; p[1] = winy; p[2] = mindepth;
148
+ PixelUnproject(view, winx, winy, mindepth, Pc);
149
+
150
+ const pangolin::OpenGlMatrix mv = cam_state->GetModelViewMatrix();
151
+
152
+ GLprecision T_wc[3*4];
153
+ LieSE3from4x4(T_wc, mv.Inverse().m );
154
+ LieApplySE3vec(Pw, T_wc, Pc);
155
+
156
+ // Neighboring points in camera coordinates
157
+ GLprecision Pl[3]; GLprecision Pr[3]; GLprecision Pb[3]; GLprecision Pt[3];
158
+ PixelUnproject(view, winx-hwin, winy, zs[hwin*zl + 0], Pl );
159
+ PixelUnproject(view, winx+hwin, winy, zs[hwin*zl + zl-1], Pr );
160
+ PixelUnproject(view, winx, winy-hwin, zs[hwin+1], Pb );
161
+ PixelUnproject(view, winx, winy+hwin, zs[zsize-(hwin+1)], Pt );
162
+
163
+ // n = ((Pr-Pl).cross(Pt-Pb)).normalized();
164
+ GLprecision PrmPl[3]; GLprecision PtmPb[3];
165
+ MatSub<3,1>(PrmPl,Pr,Pl);
166
+ MatSub<3,1>(PtmPb,Pt,Pb);
167
+
168
+ GLprecision nc[3];
169
+ CrossProduct(nc, PrmPl, PtmPb);
170
+ Normalise<3>(nc);
171
+
172
+ // T_wc is col major, so the rotation component is first.
173
+ LieApplySO3(nw,T_wc,nc);
174
+ }
175
+
176
+ void HandlerBase3D::GetPosNormal(pangolin::View& view, int winx, int winy, GLprecision p[3], GLprecision Pw[3], GLprecision Pc[3], GLprecision nw[3], GLprecision default_z)
177
+ {
178
+ const int zl = (hwin*2+1);
179
+ const int zsize = zl*zl;
180
+ GLfloat zs[zsize];
181
+
182
+ GLint readid = 0;
183
+ glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &readid);
184
+ // Choose attachment based on the bound framebuffer since GL_FRONT doesn't exist for FBOs
185
+ glReadBuffer(readid == 0 ? GL_FRONT : GL_COLOR_ATTACHMENT0);
186
+ glReadPixels(winx-hwin,winy-hwin,zl,zl,GL_DEPTH_COMPONENT,GL_FLOAT,zs);
187
+ GetPosNormalImpl(view, winx, winy, p, Pw, Pc, nw, default_z, zs);
188
+ }
189
+
190
+ void HandlerBase3D::Mouse(View& display, MouseButton button, int x, int y, bool pressed, int button_state)
191
+ {
192
+ // mouse down
193
+ last_pos[0] = (float)x;
194
+ last_pos[1] = (float)y;
195
+
196
+ GLprecision T_nc[3*4];
197
+ LieSetIdentity(T_nc);
198
+
199
+ funcKeyState = 0;
200
+ if( pressed )
201
+ {
202
+ GetPosNormal(display,x,y,p,Pw,Pc,n,last_z);
203
+ if( ValidWinDepth(p[2]) )
204
+ {
205
+ last_z = p[2];
206
+ std::copy(Pc,Pc+3,rot_center);
207
+ }
208
+
209
+ if( button == MouseWheelUp || button == MouseWheelDown)
210
+ {
211
+ LieSetIdentity(T_nc);
212
+ const GLprecision t[3] = { 0,0,(button==MouseWheelUp?1:-1)*100*tf};
213
+ LieSetTranslation<>(T_nc,t);
214
+ if( !(button_state & MouseButtonRight) && !(rot_center[0]==0 && rot_center[1]==0 && rot_center[2]==0) )
215
+ {
216
+ LieSetTranslation<>(T_nc,rot_center);
217
+ const GLprecision s = (button==MouseWheelUp?-1.0:1.0) * zf;
218
+ MatMul<3,1>(T_nc+(3*3), s);
219
+ }
220
+ OpenGlMatrix& spec = cam_state->GetModelViewMatrix();
221
+ LieMul4x4bySE3<>(spec.m,T_nc,spec.m);
222
+ }
223
+
224
+ funcKeyState = button_state;
225
+ }
226
+ }
227
+
228
+ void HandlerBase3D::MouseMotion(View& display, int x, int y, int button_state)
229
+ {
230
+ const GLprecision rf = 0.01;
231
+ const float delta[2] = { (float)x - last_pos[0], (float)y - last_pos[1] };
232
+ const float mag = delta[0]*delta[0] + delta[1]*delta[1];
233
+
234
+ if((button_state & KeyModifierCtrl) && (button_state & KeyModifierShift))
235
+ {
236
+ GLprecision T_nc[3 * 4];
237
+ LieSetIdentity(T_nc);
238
+
239
+ GetPosNormal(display, x, y, p, Pw, Pc, n, last_z);
240
+ if(ValidWinDepth(p[2]))
241
+ {
242
+ last_z = p[2];
243
+ std::copy(Pc, Pc + 3, rot_center);
244
+ }
245
+
246
+ funcKeyState = button_state;
247
+ }
248
+ else
249
+ {
250
+ funcKeyState = 0;
251
+ }
252
+
253
+ // TODO: convert delta to degrees based of fov
254
+ // TODO: make transformation with respect to cam spec
255
+ if( mag < 50.0f*50.0f )
256
+ {
257
+ OpenGlMatrix& mv = cam_state->GetModelViewMatrix();
258
+ const GLprecision* up = AxisDirectionVector[enforce_up];
259
+ GLprecision T_nc[3*4];
260
+ LieSetIdentity(T_nc);
261
+ bool rotation_changed = false;
262
+
263
+ if( button_state == MouseButtonMiddle )
264
+ {
265
+ // Middle Drag: Rotate around view
266
+
267
+ // Try to correct for different coordinate conventions.
268
+ GLprecision aboutx = -rf * delta[1];
269
+ GLprecision abouty = rf * delta[0];
270
+ OpenGlMatrix& pm = cam_state->GetProjectionMatrix();
271
+ abouty *= -pm.m[2 * 4 + 3];
272
+
273
+ Rotation<>(T_nc, aboutx, abouty, (GLprecision)0.0);
274
+ }else if( button_state == MouseButtonLeft )
275
+ {
276
+ // Left Drag: in plane translate
277
+ if( ValidWinDepth(last_z) )
278
+ {
279
+ GLprecision np[3];
280
+ PixelUnproject(display, x, y, last_z, np);
281
+ const GLprecision t[] = { np[0] - rot_center[0], np[1] - rot_center[1], 0};
282
+ LieSetTranslation<>(T_nc,t);
283
+ std::copy(np,np+3,rot_center);
284
+ }else{
285
+ const GLprecision t[] = { -10*delta[0]*tf, 10*delta[1]*tf, 0};
286
+ LieSetTranslation<>(T_nc,t);
287
+ }
288
+ }else if( button_state == (MouseButtonLeft | MouseButtonRight) )
289
+ {
290
+ // Left and Right Drag: in plane rotate about object
291
+ // Rotation<>(T_nc,0.0,0.0, delta[0]*0.01);
292
+
293
+ GLprecision T_2c[3*4];
294
+ Rotation<>(T_2c, (GLprecision)0.0, (GLprecision)0.0, delta[0]*rf);
295
+ GLprecision mrotc[3];
296
+ MatMul<3,1>(mrotc, rot_center, (GLprecision)-1.0);
297
+ LieApplySO3<>(T_2c+(3*3),T_2c,mrotc);
298
+ GLprecision T_n2[3*4];
299
+ LieSetIdentity<>(T_n2);
300
+ LieSetTranslation<>(T_n2,rot_center);
301
+ LieMulSE3(T_nc, T_n2, T_2c );
302
+ rotation_changed = true;
303
+ }else if( button_state == MouseButtonRight)
304
+ {
305
+ GLprecision aboutx = -rf * delta[1];
306
+ GLprecision abouty = -rf * delta[0];
307
+
308
+ // Try to correct for different coordinate conventions.
309
+ if(cam_state->GetProjectionMatrix().m[2*4+3] <= 0) {
310
+ abouty *= -1;
311
+ }
312
+
313
+ if(enforce_up) {
314
+ // Special case if view direction is parallel to up vector
315
+ const GLprecision updotz = mv.m[2]*up[0] + mv.m[6]*up[1] + mv.m[10]*up[2];
316
+ if(updotz > 0.98) aboutx = std::min(aboutx, (GLprecision)0.0);
317
+ if(updotz <-0.98) aboutx = std::max(aboutx, (GLprecision)0.0);
318
+ // Module rotation around y so we don't spin too fast!
319
+ abouty *= (1-0.6*fabs(updotz));
320
+ }
321
+
322
+ // Right Drag: object centric rotation
323
+ GLprecision T_2c[3*4];
324
+ Rotation<>(T_2c, aboutx, abouty, (GLprecision)0.0);
325
+ GLprecision mrotc[3];
326
+ MatMul<3,1>(mrotc, rot_center, (GLprecision)-1.0);
327
+ LieApplySO3<>(T_2c+(3*3),T_2c,mrotc);
328
+ GLprecision T_n2[3*4];
329
+ LieSetIdentity<>(T_n2);
330
+ LieSetTranslation<>(T_n2,rot_center);
331
+ LieMulSE3(T_nc, T_n2, T_2c );
332
+ rotation_changed = true;
333
+ }
334
+
335
+ LieMul4x4bySE3<>(mv.m,T_nc,mv.m);
336
+
337
+ if(enforce_up != AxisNone && rotation_changed) {
338
+ EnforceUpT_cw(mv.m, up);
339
+ }
340
+ }
341
+
342
+ last_pos[0] = (float)x;
343
+ last_pos[1] = (float)y;
344
+ }
345
+
346
+ void HandlerBase3D::Special(View& display, InputSpecial inType, float x, float y, float p1, float p2, float /*p3*/, float /*p4*/, int button_state)
347
+ {
348
+ if( !(inType == InputSpecialScroll || inType == InputSpecialRotate) )
349
+ return;
350
+
351
+ // mouse down
352
+ last_pos[0] = x;
353
+ last_pos[1] = y;
354
+
355
+ GLprecision T_nc[3*4];
356
+ LieSetIdentity(T_nc);
357
+
358
+ GetPosNormal(display, (int)x, (int)y, p, Pw, Pc, n, last_z);
359
+ if(p[2] < 1.0) {
360
+ last_z = p[2];
361
+ std::copy(Pc,Pc+3,rot_center);
362
+ }
363
+
364
+ if( inType == InputSpecialScroll ) {
365
+ if(button_state & KeyModifierCmd) {
366
+ const GLprecision rx = -p2 / 1000;
367
+ const GLprecision ry = -p1 / 1000;
368
+
369
+ Rotation<>(T_nc,rx, ry, (GLprecision)0.0);
370
+ OpenGlMatrix& spec = cam_state->GetModelViewMatrix();
371
+ LieMul4x4bySE3<>(spec.m,T_nc,spec.m);
372
+ }else{
373
+ const GLprecision scrolly = p2/10;
374
+
375
+ LieSetIdentity(T_nc);
376
+ const GLprecision t[] = { 0,0, -scrolly*100*tf};
377
+ LieSetTranslation<>(T_nc,t);
378
+ if( !(button_state & MouseButtonRight) && !(rot_center[0]==0 && rot_center[1]==0 && rot_center[2]==0) )
379
+ {
380
+ LieSetTranslation<>(T_nc,rot_center);
381
+ MatMul<3,1>(T_nc+(3*3), -scrolly * zf);
382
+ }
383
+ OpenGlMatrix& spec = cam_state->GetModelViewMatrix();
384
+ LieMul4x4bySE3<>(spec.m,T_nc,spec.m);
385
+ }
386
+ }else if(inType == InputSpecialRotate) {
387
+ const GLprecision r = p1 / 20;
388
+
389
+ GLprecision T_2c[3*4];
390
+ Rotation<>(T_2c, (GLprecision)0.0, (GLprecision)0.0, r);
391
+ GLprecision mrotc[3];
392
+ MatMul<3,1>(mrotc, rot_center, (GLprecision)-1.0);
393
+ LieApplySO3<>(T_2c+(3*3),T_2c,mrotc);
394
+ GLprecision T_n2[3*4];
395
+ LieSetIdentity<>(T_n2);
396
+ LieSetTranslation<>(T_n2,rot_center);
397
+ LieMulSE3(T_nc, T_n2, T_2c );
398
+ OpenGlMatrix& spec = cam_state->GetModelViewMatrix();
399
+ LieMul4x4bySE3<>(spec.m,T_nc,spec.m);
400
+ }
401
+
402
+ }
403
+
404
+ #ifdef HAVE_GLES
405
+ Handler3DBlitCopy::Handler3DBlitCopy(pangolin::OpenGlRenderState& cam_state, pangolin::AxisDirection enforce_up, float trans_scale)
406
+ : pangolin::HandlerBase3D(cam_state,enforce_up, trans_scale)
407
+ {
408
+ }
409
+
410
+ void Handler3DBlitCopy::GetPosNormal(pangolin::View& view, int winx, int winy, GLprecision p[3], GLprecision Pw[3], GLprecision Pc[3], GLprecision n[3], GLprecision default_z)
411
+ {
412
+ // Go around the houses so we can get depth data...
413
+ // With GLES3 / WebGL 2.0, we can't read from the depth buffer or download ROI's of GL textures
414
+ // The process below is the simplest I could make work that avoids a large GPU -> CPU download.
415
+
416
+ const int w = pangolin::DisplayBase().v.w;
417
+ const int h = pangolin::DisplayBase().v.h;
418
+
419
+ GLint num_bits;
420
+ glGetIntegerv(GL_DEPTH_BITS, &num_bits);
421
+
422
+ // Make sure our buffers are the right size for the current screen buffer
423
+ if(!depth_blit.IsValid() || depth_blit.width != w || depth_blit.height != h)
424
+ {
425
+ // Reinitialize all buffers
426
+ fb_blit.Reinitialise();
427
+ rgb_blit.Reinitialise(w,h,GL_RGB, true, 0, GL_RGB, GL_UNSIGNED_BYTE);
428
+ depth_blit.Reinitialise(w,h,GL_DEPTH24_STENCIL8, false, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
429
+ fb_blit.AttachColour(rgb_blit);
430
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb_blit.fbid);
431
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, depth_blit.tid, 0);
432
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
433
+
434
+ fb.Reinitialise();
435
+ rgb.Reinitialise(w,h,GL_R32F, true, 0, GL_RED, GL_FLOAT);
436
+ depth.Reinitialise(w,h,GL_DEPTH24_STENCIL8, false, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8);
437
+ fb.AttachColour(rgb);
438
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fb.fbid);
439
+ glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_TEXTURE_2D, depth.tid, 0);
440
+ glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
441
+ }
442
+
443
+ // Copy screens depth buffer to our blit framebuffer
444
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
445
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, fb_blit.fbid);
446
+ glBlitFramebuffer(0,0,w,h, 0,0,w,h, GL_DEPTH_BUFFER_BIT, GL_NEAREST);
447
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
448
+
449
+ // Render the depth buffer to our regular buffer (so depth ends up in color buffer)
450
+ fb.Bind();
451
+ glViewport(0,0,w,h);
452
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
453
+ glColor4f(1.0,1.0,1.0,1.0);
454
+ depth_blit.RenderToViewport();
455
+ depth_blit.Unbind();
456
+
457
+ const int zl = (hwin*2+1);
458
+ const int zsize = zl*zl;
459
+ GLfloat zs[4*zsize];
460
+ GLfloat zsr[zsize];
461
+
462
+ // GLES3 only supports ReadPixels with GL_RGBA
463
+ glReadBuffer(GL_COLOR_ATTACHMENT0);
464
+ glReadPixels(winx-hwin,winy-hwin,zl,zl,GL_RGBA,GL_FLOAT,zs);
465
+ for(size_t i=0; i < zsize; ++i) zsr[i] = zs[4*i];
466
+ fb.Unbind();
467
+
468
+ HandlerBase3D::GetPosNormalImpl(view,winx,winy,p,Pw,Pc,n,default_z,zsr);
469
+ }
470
+ #endif
471
+
472
+ }
third-party/DPVO/Pangolin/components/pango_display/src/handler_glbuffer.cpp ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2013 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include <pangolin/handler/handler_glbuffer.h>
29
+ #include <pangolin/display/view.h>
30
+
31
+ namespace pangolin {
32
+
33
+ Handler3DFramebuffer::Handler3DFramebuffer(GlFramebuffer& fb, pangolin::OpenGlRenderState& cam_state, pangolin::AxisDirection enforce_up, float trans_scale)
34
+ : pangolin::HandlerBase3D(cam_state,enforce_up, trans_scale), fb(fb)
35
+ {
36
+ }
37
+
38
+ void Handler3DFramebuffer::GetPosNormal(pangolin::View& view, int x, int y, GLprecision p[3], GLprecision Pw[3], GLprecision Pc[3], GLprecision n[3], GLprecision default_z)
39
+ {
40
+ fb.Bind();
41
+ HandlerBase3D::GetPosNormal(view,x,y,p,Pw,Pc,n,default_z);
42
+ fb.Unbind();
43
+ }
44
+
45
+ }
third-party/DPVO/Pangolin/components/pango_display/src/handler_image.cpp ADDED
@@ -0,0 +1,526 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <pangolin/handler/handler_image.h>
2
+ #include <pangolin/display/default_font.h>
3
+
4
+ namespace pangolin
5
+ {
6
+
7
+ ImageViewHandler::ImageViewHandler(const std::string & title)
8
+ : linked_view_handler(0), use_nn(false), flipTextureX(false), flipTextureY(false), title(title)
9
+ {
10
+ SetDimensions(1, 1);
11
+ }
12
+
13
+ ImageViewHandler::ImageViewHandler(size_t w, size_t h)
14
+ : linked_view_handler(0),
15
+ use_nn(false), flipTextureX(false), flipTextureY(false)
16
+ {
17
+ SetDimensions(w,h);
18
+ }
19
+
20
+ void ImageViewHandler::SetDimensions(size_t w, size_t h)
21
+ {
22
+ rview_default = pangolin::XYRangef(-0.5f, w-0.5f, -0.5f, h-0.5f),
23
+ rview_max = pangolin::XYRangef(-0.5f, w-0.5f, -0.5f, h-0.5f),
24
+ rview = rview_default;
25
+ target = rview;
26
+ }
27
+
28
+ void ImageViewHandler::UpdateView()
29
+ {
30
+ // TODO: Base this on current framerate.
31
+ const float animate_factor = 1.0f / 5.0f;
32
+
33
+ if( linked_view_handler ) {
34
+ // Synchronise rview and target with linked plotter
35
+ rview = linked_view_handler->rview;
36
+ target = linked_view_handler->target;
37
+ selection = linked_view_handler->selection;
38
+ }else{
39
+ // Clamp target to image dimensions.
40
+ AdjustScale();
41
+ AdjustTranslation();
42
+
43
+ // Animate view window toward target
44
+ pangolin::XYRangef d = target - rview;
45
+ rview += d * animate_factor;
46
+ }
47
+ }
48
+
49
+ void ImageViewHandler::glSetViewOrtho()
50
+ {
51
+ const pangolin::XYRangef& xy = GetViewToRender();
52
+
53
+ glMatrixMode(GL_PROJECTION);
54
+ ProjectionMatrixOrthographic(xy.x.min, xy.x.max, xy.y.max, xy.y.min, -1.0f, 1.0f).Load();
55
+ glMatrixMode(GL_MODELVIEW);
56
+ glLoadIdentity();
57
+ }
58
+
59
+ void ImageViewHandler::glRenderTexture(pangolin::GlTexture& tex)
60
+ {
61
+ glRenderTexture(tex.tid, tex.width, tex.height);
62
+ }
63
+
64
+ void ImageViewHandler::glRenderTexture(GLuint tex, GLint width, GLint height)
65
+ {
66
+ if(tex != 0) {
67
+ const pangolin::XYRangef& xy = GetViewToRender();
68
+ const float w = (float)width;
69
+ const float h = (float)height;
70
+
71
+ // discrete coords, (-0.5, -0.5) - (w-0.5, h-0.5)
72
+ const GLfloat l = xy.x.min;
73
+ const GLfloat r = xy.x.max;
74
+ const GLfloat b = xy.y.max;
75
+ const GLfloat t = xy.y.min;
76
+
77
+ // continuous coords, (0,0) - (1,1)
78
+ GLfloat ln = (l + 0.5f) / w;
79
+ GLfloat rn = (r + 0.5f) / w;
80
+ GLfloat bn = (b + 0.5f) / h;
81
+ GLfloat tn = (t + 0.5f) / h;
82
+
83
+ if(flipTextureX) {
84
+ ln = 1-ln;
85
+ rn = 1-rn;
86
+ }
87
+
88
+ if(flipTextureY) {
89
+ bn = 1-bn;
90
+ tn = 1-tn;
91
+ }
92
+
93
+ const GLfloat sq_vert[] = { l,t, r,t, r,b, l,b };
94
+ const GLfloat sq_tex[] = { ln,tn, rn,tn, rn,bn, ln,bn };
95
+
96
+ glBindTexture(GL_TEXTURE_2D, tex);
97
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, UseNN() ? GL_NEAREST : GL_LINEAR);
98
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, UseNN() ? GL_NEAREST : GL_LINEAR);
99
+
100
+ glEnable(GL_TEXTURE_2D);
101
+ glEnableClientState(GL_VERTEX_ARRAY);
102
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
103
+ glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
104
+ glVertexPointer(2, GL_FLOAT, 0, sq_vert);
105
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
106
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
107
+ glDisableClientState(GL_VERTEX_ARRAY);
108
+ glDisable(GL_TEXTURE_2D);
109
+ glBindTexture(GL_TEXTURE_2D, 0);
110
+ }
111
+ }
112
+
113
+ void ImageViewHandler::glRenderTexture(GLuint tex, GLint width, GLint height, XYRangef tex_region)
114
+ {
115
+ if(tex != 0) {
116
+ const pangolin::XYRangef& xy = tex_region;
117
+ const float w = (float)width;
118
+ const float h = (float)height;
119
+
120
+ // discrete coords, (-0.5, -0.5) - (w-0.5, h-0.5)
121
+ const GLfloat l = xy.x.min;
122
+ const GLfloat r = xy.x.max;
123
+ const GLfloat b = xy.y.max;
124
+ const GLfloat t = xy.y.min;
125
+
126
+ // continuous coords, (0,0) - (1,1)
127
+ GLfloat ln = 0.0;
128
+ GLfloat rn = 1.0;
129
+ GLfloat bn = 0.0;
130
+ GLfloat tn = 1.0;
131
+
132
+ if(flipTextureX) {
133
+ ln = 1-ln;
134
+ rn = 1-rn;
135
+ }
136
+
137
+ if(flipTextureY) {
138
+ bn = 1-bn;
139
+ tn = 1-tn;
140
+ }
141
+
142
+ const GLfloat sq_vert[] = { l,t, r,t, r,b, l,b };
143
+ const GLfloat sq_tex[] = { ln,tn, rn,tn, rn,bn, ln,bn };
144
+
145
+ glBindTexture(GL_TEXTURE_2D, tex);
146
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, UseNN() ? GL_NEAREST : GL_LINEAR);
147
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, UseNN() ? GL_NEAREST : GL_LINEAR);
148
+
149
+ glEnable(GL_TEXTURE_2D);
150
+ glEnableClientState(GL_VERTEX_ARRAY);
151
+ glEnableClientState(GL_TEXTURE_COORD_ARRAY);
152
+ glTexCoordPointer(2, GL_FLOAT, 0, sq_tex);
153
+ glVertexPointer(2, GL_FLOAT, 0, sq_vert);
154
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
155
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
156
+ glDisableClientState(GL_VERTEX_ARRAY);
157
+ glDisable(GL_TEXTURE_2D);
158
+ glBindTexture(GL_TEXTURE_2D, 0);
159
+ }
160
+ }
161
+
162
+ void ImageViewHandler::glRenderOverlay()
163
+ {
164
+ const pangolin::XYRangef& selxy = GetSelection();
165
+ const GLfloat sq_select[] = {
166
+ selxy.x.min, selxy.y.min,
167
+ selxy.x.max, selxy.y.min,
168
+ selxy.x.max, selxy.y.max,
169
+ selxy.x.min, selxy.y.max
170
+ };
171
+ glColor4f(1.0,0.0,0.0,1.0);
172
+ glEnableClientState(GL_VERTEX_ARRAY);
173
+ glVertexPointer(2, GL_FLOAT, 0, sq_select);
174
+ glDrawArrays(GL_LINE_LOOP, 0, 4);
175
+ glDisableClientState(GL_TEXTURE_COORD_ARRAY);
176
+ glColor4f(1.0,1.0,1.0,1.0);
177
+
178
+ const bool have_text = std::abs(selxy.Area()) > 0 || !title.empty();
179
+
180
+ GLboolean gl_blend_enabled;
181
+ pangolin::Viewport v;
182
+
183
+ if( have_text ) {
184
+
185
+ glGetIntegerv( GL_VIEWPORT, &v.l );
186
+
187
+ // Save previous value
188
+ glGetBooleanv(GL_BLEND, &gl_blend_enabled);
189
+
190
+ // Ensure that blending is enabled for rendering text.
191
+ glEnable(GL_BLEND);
192
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
193
+
194
+ }
195
+
196
+ if( std::abs(selxy.Area()) > 0) {
197
+ // Render text
198
+ float xpix, ypix;
199
+ ImageToScreen(v, selxy.x.max, selxy.y.max, xpix, ypix);
200
+
201
+ auto& font = pangolin::default_font();
202
+
203
+ font.Text(
204
+ "%.2f x %.2f",
205
+ selxy.x.Size(), selxy.y.Size()
206
+ ).DrawWindow(xpix,ypix);
207
+
208
+ font.Text(
209
+ "(%.1f,%.1f)->(%.1f,%.1f)",
210
+ selxy.x.min, selxy.y.min,
211
+ selxy.x.max, selxy.y.max
212
+ ).DrawWindow(xpix, ypix - 1.0f * font.Height());
213
+ }
214
+
215
+ if (!title.empty()) {
216
+ auto& font = pangolin::default_font();
217
+ font.Text(title).DrawWindow(v.l + 8, v.t() - 4 - font.Height());
218
+ }
219
+
220
+ if (have_text) {
221
+ // Restore previous value
222
+ if(!gl_blend_enabled) glDisable(GL_BLEND);
223
+ }
224
+ }
225
+
226
+ void ImageViewHandler::ScreenToImage(Viewport& v, float xpix, float ypix, float& ximg, float& yimg)
227
+ {
228
+ ximg = rview.x.min + rview.x.Size() * (xpix - v.l) / (float)v.w;
229
+ yimg = rview.y.min + rview.y.Size() * ( 1.0f - (ypix - v.b) / (float)v.h);
230
+ }
231
+
232
+ void ImageViewHandler::ImageToScreen(Viewport& v, float ximg, float yimg, float& xpix, float& ypix)
233
+ {
234
+ xpix = (ximg -rview.x.min) * (float)v.w / rview.x.Size() + v.l;
235
+ ypix = v.b - (float)v.h * ((yimg - rview.y.min) / rview.y.Size() - 1.0f);
236
+ }
237
+
238
+ bool ImageViewHandler::UseNN() const
239
+ {
240
+ return use_nn;
241
+ }
242
+
243
+ bool& ImageViewHandler::UseNN()
244
+ {
245
+ return use_nn;
246
+ }
247
+
248
+ bool& ImageViewHandler::FlipTextureX()
249
+ {
250
+ return flipTextureX;
251
+ }
252
+
253
+ bool& ImageViewHandler::FlipTextureY()
254
+ {
255
+ return flipTextureY;
256
+ }
257
+
258
+ pangolin::XYRangef& ImageViewHandler::GetViewToRender()
259
+ {
260
+ return rview;
261
+ }
262
+
263
+ float ImageViewHandler::GetViewScale()
264
+ {
265
+ return rview_max.x.Size() / rview.x.Size();
266
+ }
267
+
268
+ pangolin::XYRangef& ImageViewHandler::GetView()
269
+ {
270
+ return target;
271
+ }
272
+
273
+ pangolin::XYRangef& ImageViewHandler::GetDefaultView()
274
+ {
275
+ return rview_default;
276
+ }
277
+
278
+ pangolin::XYRangef& ImageViewHandler::GetSelection()
279
+ {
280
+ return selection;
281
+ }
282
+
283
+ void ImageViewHandler::GetHover(float& x, float& y)
284
+ {
285
+ ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
286
+ x = tv.hover_img[0];
287
+ y = tv.hover_img[1];
288
+ }
289
+
290
+ void ImageViewHandler::SetView(const pangolin::XYRangef& range)
291
+ {
292
+ ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
293
+ tv.rview = range;
294
+ tv.target = range;
295
+ }
296
+
297
+ void ImageViewHandler::SetViewSmooth(const pangolin::XYRangef& range)
298
+ {
299
+ ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
300
+ tv.target = range;
301
+ }
302
+
303
+ void ImageViewHandler::ScrollView(float x, float y)
304
+ {
305
+ ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
306
+ ScrollViewSmooth(x,y);
307
+ tv.rview.x += x;
308
+ tv.rview.y += y;
309
+ }
310
+
311
+ void ImageViewHandler::ScrollViewSmooth(float x, float y)
312
+ {
313
+ ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
314
+ tv.target.x += x;
315
+ tv.target.y += y;
316
+ }
317
+
318
+ void ImageViewHandler::ScaleView(float x, float y, float cx, float cy)
319
+ {
320
+ ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
321
+ ScaleViewSmooth(x,y,cx,cy);
322
+ tv.rview.x.Scale(x,cx);
323
+ tv.rview.y.Scale(y,cy);
324
+ }
325
+
326
+ void ImageViewHandler::ScaleViewSmooth(float x, float y, float cx, float cy)
327
+ {
328
+ ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
329
+ tv.target.x.Scale(x,cx);
330
+ tv.target.y.Scale(y,cy);
331
+ }
332
+
333
+ void ImageViewHandler::ResetView()
334
+ {
335
+ ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
336
+ tv.target = tv.rview_default;
337
+ }
338
+
339
+ ///////////////////////////////////////////////////////
340
+ /// pangolin::Handler
341
+ ///////////////////////////////////////////////////////
342
+
343
+ void ImageViewHandler::Keyboard(View&, unsigned char key, int /*x*/, int /*y*/, bool pressed)
344
+ {
345
+ XYRangef& sel = linked_view_handler ? linked_view_handler->selection : selection;
346
+ const float mvfactor = 1.0f / 10.0f;
347
+ const float c[2] = { rview.x.Mid(), rview.y.Mid() };
348
+
349
+
350
+ if(pressed) {
351
+ if(key == '\r') {
352
+ if( sel.Area() != 0.0f && std::isfinite(sel.Area()) ) {
353
+ // Set view to equal selection
354
+ SetViewSmooth(sel);
355
+
356
+ // Reset selection
357
+ sel.x.max = sel.x.min;
358
+ sel.y.max = sel.y.min;
359
+ }
360
+ }else if(key == 'n') {
361
+ use_nn = !use_nn;
362
+ }else if(key == 'l') {
363
+ if(to_link) {
364
+ linked_view_handler = to_link;
365
+ to_link = 0;
366
+ }else{
367
+ to_link = this;
368
+ }
369
+ }else if(key == PANGO_SPECIAL + PANGO_KEY_LEFT) {
370
+ const float w = target.x.Size();
371
+ const float dx = mvfactor*w;
372
+ ScrollViewSmooth(-dx, 0);
373
+ }else if(key == PANGO_SPECIAL + PANGO_KEY_RIGHT) {
374
+ const float w = target.x.Size();
375
+ const float dx = mvfactor*w;
376
+ ScrollViewSmooth(+dx, 0);
377
+ }else if(key == PANGO_SPECIAL + PANGO_KEY_DOWN) {
378
+ const float h = target.y.Size();
379
+ const float dy = mvfactor*h;
380
+ ScrollViewSmooth(0, -dy);
381
+ }else if(key == PANGO_SPECIAL + PANGO_KEY_UP) {
382
+ const float h = target.y.Size();
383
+ const float dy = mvfactor*h;
384
+ ScrollViewSmooth(0, +dy);
385
+ }else if(key == '=') {
386
+ ScaleViewSmooth(0.5, 0.5, c[0], c[1]);
387
+ }else if(key == '-') {
388
+ ScaleViewSmooth(2.0, 2.0, c[0], c[1]);
389
+ }else if(key == '#') {
390
+ ResetView();
391
+ }else if(key == 1) {
392
+ // ctrl-a: select all.
393
+ sel = rview;
394
+ }else{
395
+ pango_print_debug("Unhandled ImageViewHandler::Keyboard. Key: %u\n", (unsigned int)key);
396
+ }
397
+ }
398
+ }
399
+
400
+ void ImageViewHandler::Mouse(View& view, pangolin::MouseButton button, int x, int y, bool pressed, int button_state)
401
+ {
402
+ XYRangef& sel = linked_view_handler ? linked_view_handler->selection : selection;
403
+ ScreenToImage(view.v, (float)x, (float)y, hover_img[0], hover_img[1]);
404
+
405
+ const float scinc = 1.05f;
406
+ const float scdec = 1.0f/scinc;
407
+
408
+ if(button_state & KeyModifierCtrl) {
409
+ const float mvfactor = 1.0f/20.0f;
410
+
411
+ if(button == MouseWheelUp) {
412
+ ScrollViewSmooth(0.0f, +mvfactor*rview.y.Size() );
413
+ }else if(button == MouseWheelDown) {
414
+ ScrollViewSmooth(0.0f, -mvfactor*rview.y.Size() );
415
+ }else if(button == MouseWheelLeft) {
416
+ ScrollViewSmooth(+mvfactor*rview.x.Size(), 0.0f );
417
+ }else if(button == MouseWheelRight) {
418
+ ScrollViewSmooth(-mvfactor*rview.x.Size(), 0.0f );
419
+ }
420
+ }else{
421
+ if(button == MouseButtonLeft) {
422
+ // Update selected range
423
+ if(pressed) {
424
+ sel.x.min = hover_img[0];
425
+ sel.y.min = hover_img[1];
426
+ }
427
+ sel.x.max = hover_img[0];
428
+ sel.y.max = hover_img[1];
429
+ }else if(button == MouseWheelUp) {
430
+ ScaleViewSmooth(scdec, scdec, hover_img[0], hover_img[1]);
431
+ }else if(button == MouseWheelDown) {
432
+ ScaleViewSmooth(scinc, scinc, hover_img[0], hover_img[1]);
433
+ }
434
+ }
435
+
436
+ FixSelection(sel);
437
+ last_mouse_pos[0] = x;
438
+ last_mouse_pos[1] = y;
439
+
440
+ if(OnSelectionCallback) {
441
+ OnSelectionCallback( OnSelectionEventData(view,*this,pressed) );
442
+ }
443
+ }
444
+
445
+ void ImageViewHandler::MouseMotion(View& view, int x, int y, int button_state)
446
+ {
447
+ XYRangef& sel = linked_view_handler ? linked_view_handler->selection : selection;
448
+ const int d[2] = {x-last_mouse_pos[0], y-last_mouse_pos[1]};
449
+
450
+ // Update hover status (after potential resizing)
451
+ ScreenToImage(view.v, (float)x, (float)y, hover_img[0], hover_img[1]);
452
+
453
+ if( button_state == MouseButtonLeft )
454
+ {
455
+ // Update selected range
456
+ sel.x.max = hover_img[0];
457
+ sel.y.max = hover_img[1];
458
+ }else if(button_state == MouseButtonRight )
459
+ {
460
+ Special(view, InputSpecialScroll, (float)x, (float)y, (float)d[0], (float)d[1], 0.0f, 0.0f, button_state);
461
+ }
462
+
463
+ last_mouse_pos[0] = x;
464
+ last_mouse_pos[1] = y;
465
+
466
+ if( button_state == MouseButtonLeft && OnSelectionCallback) {
467
+ OnSelectionCallback( OnSelectionEventData(view,*this,true) );
468
+ }
469
+ }
470
+
471
+ void ImageViewHandler::PassiveMouseMotion(View&, int /*x*/, int /*y*/, int /*button_state*/)
472
+ {
473
+ }
474
+
475
+ void ImageViewHandler::Special(View& view, pangolin::InputSpecial inType, float x, float y, float p1, float p2, float /*p3*/, float /*p4*/, int /*button_state*/)
476
+ {
477
+ ScreenToImage(view.v, x, y, hover_img[0], hover_img[1]);
478
+
479
+ if(inType == InputSpecialScroll) {
480
+ const float d[2] = {p1,p2};
481
+ const float is[2] = {rview.x.Size(),rview.y.Size() };
482
+ const float df[2] = {is[0]*d[0]/(float)view.v.w, is[1]*d[1]/(float)view.v.h};
483
+ ScrollView(-df[0], -df[1]);
484
+ } else if(inType == InputSpecialZoom) {
485
+ float scale = 1.0f - p1;
486
+ ScaleView(scale, scale, hover_img[0], hover_img[1]);
487
+ }
488
+
489
+ // Update hover status (after potential resizing)
490
+ ScreenToImage( view.v, x, y, hover_img[0], hover_img[1]);
491
+ }
492
+
493
+ void ImageViewHandler::FixSelection(XYRangef& sel)
494
+ {
495
+ // Make sure selection matches sign of current viewport
496
+ if( (sel.x.min<sel.x.max) != (rview.x.min<rview.x.max) ) {
497
+ std::swap(sel.x.min, sel.x.max);
498
+ }
499
+ if( (sel.y.min<sel.y.max) != (rview.y.min<rview.y.max) ) {
500
+ std::swap(sel.y.min, sel.y.max);
501
+ }
502
+ }
503
+
504
+ void ImageViewHandler::AdjustScale()
505
+ {
506
+ ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
507
+ if(tv.target.x.AbsSize() > tv.rview_max.x.AbsSize())
508
+ tv.target.x.Scale(tv.rview_max.x.AbsSize() / tv.target.x.AbsSize(), tv.target.x.Mid());
509
+ if(tv.target.y.AbsSize() > tv.rview_max.y.AbsSize())
510
+ tv.target.y.Scale(tv.rview_max.y.AbsSize() / tv.target.y.AbsSize(), tv.target.y.Mid());
511
+ }
512
+
513
+ void ImageViewHandler::AdjustTranslation()
514
+ {
515
+ ImageViewHandler& tv = linked_view_handler ? *linked_view_handler : *this;
516
+ if( tv.target.x.max > tv.rview_max.x.max) tv.target.x -= tv.target.x.max - tv.rview_max.x.max;
517
+ if( tv.target.x.min < tv.rview_max.x.min) tv.target.x -= tv.target.x.min - tv.rview_max.x.min;
518
+
519
+ if( tv.target.y.max > tv.rview_max.y.max) tv.target.y -= tv.target.y.max - tv.rview_max.y.max;
520
+ if( tv.target.y.min < tv.rview_max.y.min) tv.target.y -= tv.target.y.min - tv.rview_max.y.min;
521
+ }
522
+
523
+ float ImageViewHandler::animate_factor = 1.0f / 2.0f;
524
+ ImageViewHandler* ImageViewHandler::to_link = 0;
525
+
526
+ }
third-party/DPVO/Pangolin/components/pango_display/src/image_view.cpp ADDED
@@ -0,0 +1,227 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #include <pangolin/display/image_view.h>
2
+ #include <pangolin/image/image_utils.h>
3
+ #include <pangolin/image/image_convert.h>
4
+
5
+ namespace pangolin
6
+ {
7
+
8
+ ImageView::ImageView(const std::string & title)
9
+ : pangolin::ImageViewHandler(title), offset_scale(0.0f, 1.0f), lastPressed(false), mouseReleased(false), mousePressed(false), overlayRender(true)
10
+ {
11
+ SetHandler(this);
12
+ }
13
+
14
+ ImageView::~ImageView()
15
+ {
16
+ }
17
+
18
+ void ImageView::Render()
19
+ {
20
+ LoadPending();
21
+
22
+ #ifndef HAVE_GLES
23
+ glPushAttrib(GL_DEPTH_BITS);
24
+ #endif
25
+ glDisable(GL_DEPTH_TEST);
26
+
27
+ Activate();
28
+ this->UpdateView();
29
+ this->glSetViewOrtho();
30
+
31
+ if(tex.IsValid())
32
+ {
33
+ if(offset_scale.first != 0.0 || offset_scale.second != 1.0)
34
+ {
35
+ pangolin::GlSlUtilities::OffsetAndScale(offset_scale.first, offset_scale.second);
36
+ }
37
+ else
38
+ {
39
+ glColor4f(1, 1, 1, 1);
40
+ }
41
+
42
+ this->glRenderTexture(tex);
43
+ pangolin::GlSlUtilities::UseNone();
44
+ }
45
+
46
+ if(overlayRender)
47
+ {
48
+ this->glRenderOverlay();
49
+ }
50
+
51
+ if(extern_draw_function)
52
+ {
53
+ extern_draw_function(*this);
54
+ }
55
+
56
+ #ifndef HAVE_GLES
57
+ glPopAttrib();
58
+ #endif
59
+ }
60
+
61
+ void ImageView::Mouse(View& view, pangolin::MouseButton button, int x, int y, bool pressed, int button_state)
62
+ {
63
+ ImageViewHandler::Mouse(view, button, x, y, pressed, button_state);
64
+
65
+ mouseReleased = (!pressed && lastPressed);
66
+
67
+ mousePressed = lastPressed = (pressed && button == pangolin::MouseButtonLeft);
68
+ }
69
+
70
+ void ImageView::Keyboard(View& view, unsigned char key, int x, int y, bool pressed)
71
+ {
72
+ if(key == 'a')
73
+ {
74
+ if(!tex.IsValid())
75
+ {
76
+ std::cerr << "ImageViewHandler does not contain valid texture." << std::endl;
77
+ return;
78
+ }
79
+
80
+ // compute scale
81
+ const bool have_selection = std::isfinite(GetSelection().Area()) && std::abs(GetSelection().Area()) >= 4;
82
+ const pangolin::XYRangef froi = have_selection ? GetSelection() : GetViewToRender();
83
+
84
+ // Download texture so that we can take min / max
85
+ pangolin::TypedImage img;
86
+ tex.Download(img);
87
+ offset_scale = pangolin::GetOffsetScale(img, pangolin::Round(froi), img.fmt);
88
+ }
89
+ else if(key == 'b')
90
+ {
91
+ if(!tex.IsValid())
92
+ {
93
+ std::cerr << "ImageViewHandler does not contain valid texture." << std::endl;
94
+ return;
95
+ }
96
+
97
+ // compute scale
98
+ const bool have_selection = std::isfinite(GetSelection().Area()) && std::abs(GetSelection().Area()) >= 4;
99
+ const pangolin::XYRangef froi = have_selection ? GetSelection() : GetViewToRender();
100
+
101
+ // Download texture so that we can take min / max
102
+ pangolin::TypedImage img;
103
+ tex.Download(img);
104
+ std::pair<float, float> mm = pangolin::GetMinMax(img, pangolin::Round(froi), img.fmt);
105
+
106
+ printf("Min / Max in Region: %f / %f\n", mm.first, mm.second);
107
+ }
108
+ else
109
+ {
110
+ pangolin::ImageViewHandler::Keyboard(view, key, x, y, pressed);
111
+ }
112
+ }
113
+
114
+ pangolin::GlTexture& ImageView::Tex() {
115
+ return tex;
116
+ }
117
+
118
+ ImageView& ImageView::SetImage(void* ptr, size_t w, size_t h, size_t pitch, pangolin::GlPixFormat img_fmt, bool delayed_upload )
119
+ {
120
+ const size_t pix_bytes =
121
+ pangolin::GlFormatChannels(img_fmt.glformat) * pangolin::GlDataTypeBytes(img_fmt.gltype);
122
+
123
+ const bool convert_first = (img_fmt.gltype == GL_DOUBLE);
124
+
125
+ if(delayed_upload || !pangolin::GetBoundWindow() || IsDevicePtr(ptr) || convert_first )
126
+ {
127
+ texlock.lock();
128
+ if(!convert_first) {
129
+ img_to_load = ManagedImage<unsigned char>(w,h,w*pix_bytes);
130
+ PitchedCopy((char*)img_to_load.ptr, img_to_load.pitch, (char*)ptr, pitch, w * pix_bytes, h);
131
+ img_fmt_to_load = img_fmt;
132
+ }else if(img_fmt.gltype == GL_DOUBLE) {
133
+ Image<double> double_image( (double*)ptr, w, h, pitch);
134
+ img_to_load.OwnAndReinterpret(ImageConvert<float>(double_image));
135
+ img_fmt_to_load = GlPixFormat::FromType<float>();
136
+ }else{
137
+ pango_print_warn("TextureView: Unable to display image.\n");
138
+ }
139
+ texlock.unlock();
140
+ return *this;
141
+ }
142
+
143
+ PANGO_ASSERT(pitch % pix_bytes == 0);
144
+ const size_t stride = pitch / pix_bytes;
145
+ glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
146
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
147
+
148
+ // Initialise if it didn't already exist or the size was too small
149
+ if(!tex.tid || tex.width != (int)w || tex.height != (int)h ||
150
+ tex.internal_format != img_fmt.scalable_internal_format)
151
+ {
152
+ fmt = img_fmt;
153
+ SetDimensions(w, h);
154
+ SetAspect((float)w / (float)h);
155
+ tex.Reinitialise(w, h, img_fmt.scalable_internal_format, true, 0, img_fmt.glformat, img_fmt.gltype, ptr);
156
+ }
157
+ else
158
+ {
159
+ tex.Upload(ptr, img_fmt.glformat, img_fmt.gltype);
160
+ }
161
+
162
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
163
+ return *this;
164
+ }
165
+
166
+ ImageView& ImageView::SetImage(const pangolin::Image<unsigned char>& img, const pangolin::GlPixFormat& glfmt, bool delayed_upload )
167
+ {
168
+ return SetImage(img.ptr, img.w, img.h, img.pitch, glfmt, delayed_upload);
169
+ }
170
+
171
+ ImageView& ImageView::SetImage(const pangolin::TypedImage& img, bool delayed_upload )
172
+ {
173
+ return SetImage(img.ptr, img.w, img.h, img.pitch, pangolin::GlPixFormat(img.fmt), delayed_upload);
174
+ }
175
+
176
+ ImageView& ImageView::SetImage(const pangolin::GlTexture& texture)
177
+ {
178
+ // Initialise if it didn't already exist or the size was too small
179
+ if(!tex.tid || tex.width != texture.width || tex.height != texture.height ||
180
+ tex.internal_format != texture.internal_format)
181
+ {
182
+ SetDimensions(texture.width, texture.height);
183
+ SetAspect((float)texture.width / (float)texture.height);
184
+ tex.Reinitialise(texture.width, texture.height, texture.internal_format, true);
185
+ }
186
+
187
+ glCopyImageSubData(
188
+ texture.tid, GL_TEXTURE_2D, 0, 0, 0, 0, tex.tid, GL_TEXTURE_2D, 0, 0, 0, 0, tex.width, tex.height, 1);
189
+
190
+ return *this;
191
+ }
192
+
193
+ void ImageView::LoadPending()
194
+ {
195
+ if(img_to_load.ptr)
196
+ {
197
+ // Scoped lock
198
+ texlock.lock();
199
+ SetImage(img_to_load, img_fmt_to_load, false);
200
+ img_to_load.Deallocate();
201
+ texlock.unlock();
202
+ }
203
+ }
204
+
205
+ ImageView& ImageView::Clear()
206
+ {
207
+ tex.Delete();
208
+ return *this;
209
+ }
210
+
211
+ std::pair<float, float>& ImageView::GetOffsetScale() {
212
+ return offset_scale;
213
+ }
214
+
215
+ bool ImageView::MouseReleased() const {
216
+ return mouseReleased;
217
+ }
218
+
219
+ bool ImageView::MousePressed() const {
220
+ return mousePressed;
221
+ }
222
+
223
+ void ImageView::SetRenderOverlay(const bool& val) {
224
+ overlayRender = val;
225
+ }
226
+
227
+ }
third-party/DPVO/Pangolin/components/pango_display/src/pangolin_gl.cpp ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove, Richard Newcombe
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include "pangolin_gl.h"
29
+ #include <pangolin/display/display.h>
30
+ #include <pangolin/console/ConsoleView.h>
31
+
32
+ namespace pangolin
33
+ {
34
+
35
+ PangolinGl::PangolinGl()
36
+ : user_app(0), quit(false), mouse_state(0),activeDisplay(0)
37
+ {
38
+ }
39
+
40
+ PangolinGl::~PangolinGl()
41
+ {
42
+ // Free displays owned by named_managed_views
43
+ for(ViewMap::iterator iv = named_managed_views.begin(); iv != named_managed_views.end(); ++iv) {
44
+ delete iv->second;
45
+ }
46
+ named_managed_views.clear();
47
+ }
48
+
49
+ void PangolinGl::MakeCurrent()
50
+ {
51
+ SetCurrentContext(this);
52
+ if(window) {
53
+ window->MakeCurrent();
54
+ }
55
+ }
56
+
57
+ void PangolinGl::RenderViews()
58
+ {
59
+ Viewport::DisableScissor();
60
+ base.Render();
61
+ }
62
+
63
+ void PangolinGl::FinishFrame()
64
+ {
65
+ RenderViews();
66
+
67
+ while(screen_capture.size()) {
68
+ std::pair<std::string,Viewport> fv = screen_capture.front();
69
+ screen_capture.pop();
70
+ SaveWindowNow(fv.first, fv.second);
71
+ }
72
+
73
+ if(window) {
74
+ window->SwapBuffers();
75
+ window->ProcessEvents();
76
+ }
77
+
78
+ Viewport::DisableScissor();
79
+ }
80
+
81
+ void PangolinGl::SetOnRender(std::function<void ()> on_render) {
82
+ this->on_render = on_render;
83
+ }
84
+
85
+ void PangolinGl::Run() {
86
+ while (!quit) {
87
+ if (on_render) {
88
+ on_render();
89
+ }
90
+ FinishFrame();
91
+ }
92
+ }
93
+
94
+ }
third-party/DPVO/Pangolin/components/pango_display/src/pangolin_gl.h ADDED
@@ -0,0 +1,102 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #pragma once
29
+
30
+ #include <pangolin/platform.h>
31
+ #include <pangolin/windowing/window.h>
32
+
33
+ #include <pangolin/display/view.h>
34
+ #include <pangolin/display/user_app.h>
35
+ #include <functional>
36
+ #include <memory>
37
+
38
+ #include <map>
39
+ #include <queue>
40
+
41
+ namespace pangolin
42
+ {
43
+
44
+ // Forward Declarations
45
+ class ConsoleView;
46
+ class GlFont;
47
+
48
+ typedef std::map<const std::string,View*> ViewMap;
49
+ typedef std::map<int,std::function<void(int)> > KeyhookMap;
50
+
51
+ struct PANGOLIN_EXPORT PangolinGl
52
+ {
53
+ PangolinGl();
54
+ ~PangolinGl();
55
+
56
+ void Run();
57
+
58
+ void MakeCurrent();
59
+ void FinishFrame();
60
+
61
+ void RenderViews();
62
+ void PostRender();
63
+
64
+ void SetOnRender(std::function<void()> on_render);
65
+
66
+ // Callback for render loop
67
+ std::function<void()> on_render;
68
+
69
+ // Base container for displays
70
+ View base;
71
+
72
+ // Named views which are managed by pangolin (i.e. created / deleted by pangolin)
73
+ ViewMap named_managed_views;
74
+
75
+ // Optional user app
76
+ UserApp* user_app;
77
+
78
+ // Global keypress hooks
79
+ KeyhookMap keypress_hooks;
80
+
81
+ // State relating to interactivity
82
+ bool quit;
83
+ int mouse_state;
84
+ View* activeDisplay;
85
+
86
+ std::queue<std::pair<std::string,Viewport> > screen_capture;
87
+
88
+ std::shared_ptr<WindowInterface> window;
89
+ std::shared_ptr<GlFont> font;
90
+
91
+ std::unique_ptr<ConsoleView> console_view;
92
+ };
93
+
94
+ PangolinGl* GetCurrentContext();
95
+ void SetCurrentContext(PangolinGl* context);
96
+ void RegisterNewContext(const std::string& name, std::shared_ptr<PangolinGl> newcontext);
97
+ void DeleteContext(const std::string& name);
98
+ PangolinGl *FindContext(const std::string& name);
99
+ void SetCurrentContext(PangolinGl* newcontext);
100
+
101
+ }
102
+
third-party/DPVO/Pangolin/components/pango_display/src/process.cpp ADDED
@@ -0,0 +1,161 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove, Richard Newcombe
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include <pangolin/display/process.h>
29
+ #include <pangolin/console/ConsoleView.h>
30
+ #include <pangolin/handler/handler.h>
31
+ #include "pangolin_gl.h"
32
+
33
+ namespace pangolin
34
+ {
35
+ namespace process
36
+ {
37
+ float last_x = 0;
38
+ float last_y = 0;
39
+
40
+ void Resize( int width, int height )
41
+ {
42
+ PangolinGl* context = GetCurrentContext();
43
+
44
+ Viewport win(0,0,width,height);
45
+ context->base.Resize(win);
46
+ }
47
+
48
+ void Keyboard(unsigned char key, int x, int y, bool pressed, KeyModifierBitmask /*key_modifiers*/)
49
+ {
50
+ PangolinGl* context = GetCurrentContext();
51
+
52
+ // Force coords to match OpenGl Window Coords
53
+ y = context->base.v.h - y;
54
+
55
+ if(pressed) {
56
+ // Check if global key hook exists
57
+ const KeyhookMap::iterator hook = context->keypress_hooks.find(key);
58
+
59
+ // Console receives all input when it is open
60
+ if( context->console_view && context->console_view->IsShown() ) {
61
+ context->console_view->Keyboard(*(context->console_view),key,x,y,true);
62
+ }else if(hook != context->keypress_hooks.end() ) {
63
+ hook->second(key);
64
+ } else if(context->activeDisplay && context->activeDisplay->handler) {
65
+ context->activeDisplay->handler->Keyboard(*(context->activeDisplay),key,x,y,true);
66
+ }
67
+ }else{
68
+ if(context->activeDisplay && context->activeDisplay->handler)
69
+ {
70
+ context->activeDisplay->handler->Keyboard(*(context->activeDisplay),key,x,y,false);
71
+ }
72
+ }
73
+ }
74
+
75
+ void Mouse( int button_raw, bool pressed, int x, int y, KeyModifierBitmask key_modifiers)
76
+ {
77
+ PangolinGl* context = GetCurrentContext();
78
+
79
+ // Force coords to match OpenGl Window Coords
80
+ y = context->base.v.h - y;
81
+
82
+ last_x = (float)x;
83
+ last_y = (float)y;
84
+
85
+ const MouseButton button = (MouseButton)(1 << (button_raw & 0xf) );
86
+
87
+ const bool fresh_input = ( (context->mouse_state & 7) == 0);
88
+
89
+ if( pressed ) {
90
+ context->mouse_state |= (button&7);
91
+ }else{
92
+ context->mouse_state &= ~(button&7);
93
+ }
94
+
95
+ #if defined(_WIN_)
96
+ context->mouse_state &= 0x0000ffff;
97
+ context->mouse_state |= (button_raw >> 4) << 16;
98
+ #endif
99
+
100
+ const int button_state = context->mouse_state | key_modifiers.mask();
101
+
102
+ if(fresh_input) {
103
+ context->base.handler->Mouse(context->base,button,x,y,pressed,button_state);
104
+ }else if(context->activeDisplay && context->activeDisplay->handler) {
105
+ context->activeDisplay->handler->Mouse(*(context->activeDisplay),button,x,y,pressed,button_state);
106
+ }
107
+ }
108
+
109
+ void MouseMotion( int x, int y, KeyModifierBitmask key_modifiers)
110
+ {
111
+ PangolinGl* context = GetCurrentContext();
112
+
113
+ // Force coords to match OpenGl Window Coords
114
+ y = context->base.v.h - y;
115
+
116
+ last_x = (float)x;
117
+ last_y = (float)y;
118
+
119
+ const int button_state = context->mouse_state | key_modifiers.mask();
120
+
121
+ if( context->activeDisplay)
122
+ {
123
+ if( context->activeDisplay->handler )
124
+ context->activeDisplay->handler->MouseMotion(*(context->activeDisplay),x,y,button_state);
125
+ }else{
126
+ context->base.handler->MouseMotion(context->base,x,y,button_state);
127
+ }
128
+ }
129
+
130
+ void PassiveMouseMotion(int x, int y, KeyModifierBitmask key_modifiers)
131
+ {
132
+ PangolinGl* context = GetCurrentContext();
133
+
134
+ // Force coords to match OpenGl Window Coords
135
+ y = context->base.v.h - y;
136
+
137
+ const int button_state = context->mouse_state | key_modifiers.mask();
138
+ context->base.handler->PassiveMouseMotion(context->base,x,y,button_state);
139
+
140
+ last_x = (float)x;
141
+ last_y = (float)y;
142
+ }
143
+
144
+ void SpecialInput(InputSpecial inType, float x, float y, float p1, float p2, float p3, float p4, KeyModifierBitmask key_modifiers)
145
+ {
146
+ PangolinGl* context = GetCurrentContext();
147
+
148
+ // Force coords to match OpenGl Window Coords
149
+ y = context->base.v.h - y;
150
+
151
+ const bool fresh_input = (context->mouse_state == 0);
152
+ const int button_state = context->mouse_state | key_modifiers.mask();
153
+
154
+ if(fresh_input) {
155
+ context->base.handler->Special(context->base,inType,x,y,p1,p2,p3,p4,button_state);
156
+ }else if(context->activeDisplay && context->activeDisplay->handler) {
157
+ context->activeDisplay->handler->Special(*(context->activeDisplay),inType,x,y,p1,p2,p3,p4,button_state);
158
+ }
159
+ }
160
+ }
161
+ }
third-party/DPVO/Pangolin/components/pango_display/src/view.cpp ADDED
@@ -0,0 +1,508 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include <stdexcept>
29
+ #include <pangolin/display/display.h>
30
+ #include <pangolin/display/view.h>
31
+ #include <pangolin/gl/gl.h>
32
+ #include <pangolin/gl/viewport.h>
33
+ #include <pangolin/gl/opengl_render_state.h>
34
+ #include <pangolin/platform.h>
35
+
36
+ #include "pangolin_gl.h"
37
+
38
+ namespace pangolin
39
+ {
40
+
41
+ const int panal_v_margin = 6;
42
+
43
+ int AttachAbs( int low, int high, Attach a)
44
+ {
45
+ if( a.unit == Pixel ) return low + (int)a.p;
46
+ if( a.unit == ReversePixel ) return high - (int)a.p;
47
+ return (int)(low + a.p * (high - low));
48
+ }
49
+
50
+ double AspectAreaWithinTarget(double target, double test)
51
+ {
52
+ if( test < target )
53
+ return test / target;
54
+ else
55
+ return target / test;
56
+ }
57
+
58
+ void View::Resize(const Viewport& p)
59
+ {
60
+ // Compute Bounds based on specification
61
+ v.l = AttachAbs(p.l,p.r(),left);
62
+ v.b = AttachAbs(p.b,p.t(),bottom);
63
+ int r = AttachAbs(p.l,p.r(),right);
64
+ int t = AttachAbs(p.b,p.t(),top);
65
+
66
+ // Make sure left and right, top and bottom are correct order
67
+ if( t < v.b ) std::swap(t,v.b);
68
+ if( r < v.l ) std::swap(r,v.l);
69
+
70
+ v.w = r - v.l;
71
+ v.h = t - v.b;
72
+
73
+ vp = v;
74
+
75
+ // Adjust based on aspect requirements
76
+ if( aspect != 0 )
77
+ {
78
+ const float current_aspect = (float)v.w / (float)v.h;
79
+ if( aspect > 0 )
80
+ {
81
+ // Fit to space
82
+ if( current_aspect < aspect )
83
+ {
84
+ //Adjust height
85
+ const int nh = (int)(v.w / aspect);
86
+ v.b += vlock == LockBottom ? 0 : (vlock == LockCenter ? (v.h-nh)/2 : (v.h-nh) );
87
+ v.h = nh;
88
+ }else if( current_aspect > aspect )
89
+ {
90
+ //Adjust width
91
+ const int nw = (int)(v.h * aspect);
92
+ v.l += hlock == LockLeft? 0 : (hlock == LockCenter ? (v.w-nw)/2 : (v.w-nw) );
93
+ v.w = nw;
94
+ }
95
+ }else{
96
+ // Overfit
97
+ double true_aspect = -aspect;
98
+ if( current_aspect < true_aspect )
99
+ {
100
+ //Adjust width
101
+ const int nw = (int)(v.h * true_aspect);
102
+ v.l += hlock == LockLeft? 0 : (hlock == LockCenter ? (v.w-nw)/2 : (v.w-nw) );
103
+ v.w = nw;
104
+ }else if( current_aspect > true_aspect )
105
+ {
106
+ //Adjust height
107
+ const int nh = (int)(v.w / true_aspect);
108
+ v.b += vlock == LockBottom ? 0 : (vlock == LockCenter ? (v.h-nh)/2 : (v.h-nh) );
109
+ v.h = nh;
110
+ }
111
+ }
112
+ }
113
+
114
+ ResizeChildren();
115
+ }
116
+
117
+ inline int zcompare(const View* lhs, const View* rhs)
118
+ {
119
+ return lhs->zorder < rhs->zorder;
120
+ }
121
+
122
+ void View::ResizeChildren()
123
+ {
124
+ if( layout == LayoutOverlay )
125
+ {
126
+ // Sort children into z-order
127
+ std::sort(views.begin(), views.end(), zcompare);
128
+
129
+ for(std::vector<View*>::iterator iv = views.begin(); iv != views.end(); ++iv ) {
130
+ (*iv)->Resize(v);
131
+ }
132
+ }else if( layout == LayoutVertical )
133
+ {
134
+ // Allocate space incrementally
135
+ Viewport space = v.Inset(panal_v_margin);
136
+ int num_children = 0;
137
+ for(std::vector<View*>::iterator iv = views.begin(); iv != views.end(); ++iv )
138
+ {
139
+ if (!(*iv)->show) continue;
140
+ num_children++;
141
+ if(scroll_offset >= num_children ) {
142
+ (*iv)->scroll_show = false;
143
+ }else{
144
+ (*iv)->scroll_show = true;
145
+ (*iv)->Resize(space);
146
+ space.h = (*iv)->v.b - panal_v_margin - space.b;
147
+ }
148
+ }
149
+ }else if(layout == LayoutHorizontal )
150
+ {
151
+ // Allocate space incrementally
152
+ const int margin = 8;
153
+ Viewport space = v.Inset(margin);
154
+ for(std::vector<View*>::iterator iv = views.begin(); iv != views.end(); ++iv )
155
+ {
156
+ (*iv)->Resize(space);
157
+ space.w = (*iv)->v.l + margin + space.l;
158
+ }
159
+ }else if(layout == LayoutEqualVertical )
160
+ {
161
+ // Allocate vertical space equally
162
+ const size_t visiblechildren = NumVisibleChildren();
163
+ const float height = (float)v.h / (float)visiblechildren;
164
+
165
+ for( size_t i=0; i < visiblechildren; ++i) {
166
+ Viewport space(v.l, (GLint)(v.b+(visiblechildren-1-i)*height), v.w, (GLint)(height) );
167
+ VisibleChild(i).Resize(space);
168
+ }
169
+ }else if(layout == LayoutEqualHorizontal )
170
+ {
171
+ // Allocate vertical space equally
172
+ const size_t visiblechildren = NumVisibleChildren();
173
+ const float width = (float)v.w / (float)visiblechildren;
174
+
175
+ for( size_t i=0; i < visiblechildren; ++i) {
176
+ Viewport space( (GLint)(v.l+i*width), v.b, (GLint)width, v.h);
177
+ VisibleChild(i).Resize(space);
178
+ }
179
+ }else if(layout == LayoutEqual )
180
+ {
181
+ const size_t visiblechildren = NumVisibleChildren();
182
+ // TODO: Make this neater, and make fewer assumptions!
183
+ if( visiblechildren > 0 )
184
+ {
185
+ // This containers aspect
186
+ const double this_a = std::fabs(v.aspect());
187
+
188
+ // Use first child with fixed aspect for all children
189
+ double child_a = std::fabs(VisibleChild(0).aspect);
190
+ for(size_t i=1; (child_a==0) && i < visiblechildren; ++i ) {
191
+ child_a = std::fabs(VisibleChild(i).aspect);
192
+ }
193
+
194
+ if(child_a == 0) {
195
+ child_a = 1;
196
+ }
197
+
198
+ double a = visiblechildren*child_a;
199
+ double area = AspectAreaWithinTarget(this_a, a);
200
+
201
+ size_t cols = visiblechildren-1;
202
+ for(; cols > 0; --cols)
203
+ {
204
+ const size_t rows = visiblechildren / cols + (visiblechildren % cols == 0 ? 0 : 1);
205
+ const double na = cols * child_a / rows;
206
+ const double new_area = visiblechildren*AspectAreaWithinTarget(this_a,na)/(rows*cols);
207
+ if( new_area <= area )
208
+ break;
209
+ area = new_area;
210
+ a = na;
211
+ }
212
+
213
+ cols++;
214
+ const size_t rows = visiblechildren / cols + (visiblechildren % cols == 0 ? 0 : 1);
215
+ size_t cw, ch;
216
+ if( a > this_a )
217
+ {
218
+ cw = v.w / cols;
219
+ ch = (int)(cw / child_a); //v.h / rows;
220
+ }else{
221
+ ch = v.h / rows;
222
+ cw = (int)(ch * child_a);
223
+ }
224
+
225
+ for(size_t i=0; i< visiblechildren; ++i )
226
+ {
227
+ size_t c = i % cols;
228
+ size_t r = i / cols;
229
+ Viewport space( GLint(v.l + c*cw), GLint(v.t() - (r+1)*ch), GLint(cw), GLint(ch) );
230
+ VisibleChild(i).Resize(space);
231
+ }
232
+ }
233
+ }
234
+
235
+ }
236
+
237
+ void View::Render()
238
+ {
239
+ if(extern_draw_function && show && scroll_show) {
240
+ extern_draw_function(*this);
241
+ }
242
+ RenderChildren();
243
+ }
244
+
245
+ void View::RenderChildren()
246
+ {
247
+ for(std::vector<View*>::iterator iv = views.begin(); iv != views.end(); ++iv )
248
+ {
249
+ if((*iv)->show && (*iv)->scroll_show) (*iv)->Render();
250
+ }
251
+ }
252
+
253
+ void View::Activate() const
254
+ {
255
+ v.Activate();
256
+ }
257
+
258
+ void View::ActivateAndScissor() const
259
+ {
260
+ vp.Scissor();
261
+ v.Activate();
262
+ }
263
+
264
+ void View::ActivateScissorAndClear() const
265
+ {
266
+ vp.Scissor();
267
+ v.Activate();
268
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
269
+ }
270
+
271
+ void View::Activate(const OpenGlRenderState& state ) const
272
+ {
273
+ v.Activate();
274
+ state.Apply();
275
+ }
276
+
277
+ void View::ActivateAndScissor(const OpenGlRenderState& state) const
278
+ {
279
+ vp.Scissor();
280
+ v.Activate();
281
+ state.Apply();
282
+ }
283
+
284
+ void View::ActivateScissorAndClear(const OpenGlRenderState& state ) const
285
+ {
286
+ vp.Scissor();
287
+ v.Activate();
288
+ state.Apply();
289
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
290
+ }
291
+
292
+ void View::ActivatePixelOrthographic() const
293
+ {
294
+ v.ActivatePixelOrthographic();
295
+ }
296
+
297
+ void View::ActivateIdentity() const
298
+ {
299
+ v.ActivateIdentity();
300
+ }
301
+
302
+ GLfloat View::GetClosestDepth(int x, int y, int radius) const
303
+ {
304
+ // TODO: Get to work on android
305
+
306
+ #ifdef _MSC_VER
307
+ // MSVC Requires fixed sized arrays on stack
308
+ radius = 5;
309
+ const int zl = (5*2+1);
310
+ #else
311
+ const int zl = (radius*2+1);
312
+ #endif
313
+
314
+ const int zsize = zl*zl;
315
+ GLfloat zs[zsize];
316
+
317
+ #ifndef HAVE_GLES
318
+ glReadBuffer(GL_FRONT);
319
+ glReadPixels(x-radius,y-radius,zl,zl,GL_DEPTH_COMPONENT,GL_FLOAT,zs);
320
+ #else
321
+ std::fill(zs,zs+zsize, 0.8);
322
+ #endif
323
+
324
+ const GLfloat mindepth = *(std::min_element(zs,zs+zsize));
325
+ return mindepth;
326
+ }
327
+
328
+ void View::GetObjectCoordinates(const OpenGlRenderState& cam_state, double winx, double winy, double winzdepth, GLdouble& x, GLdouble& y, GLdouble& z) const
329
+ {
330
+ const GLint viewport[4] = {v.l,v.b,v.w,v.h};
331
+ const OpenGlMatrix proj = cam_state.GetProjectionMatrix();
332
+ const OpenGlMatrix mv = cam_state.GetModelViewMatrix();
333
+ glUnProject(winx, winy, winzdepth, mv.m, proj.m, viewport, &x, &y, &z);
334
+ }
335
+
336
+ void View::GetCamCoordinates(const OpenGlRenderState& cam_state, double winx, double winy, double winzdepth, GLdouble& x, GLdouble& y, GLdouble& z) const
337
+ {
338
+ const GLint viewport[4] = {v.l, v.b, v.w, v.h};
339
+ const OpenGlMatrix proj = cam_state.GetProjectionMatrix();
340
+ #ifndef HAVE_GLES
341
+ glUnProject(winx, winy, winzdepth, Identity4d, proj.m, viewport, &x, &y, &z);
342
+ #else
343
+ glUnProject(winx, winy, winzdepth, Identity4f, proj.m, viewport, &x, &y, &z);
344
+ #endif
345
+ }
346
+
347
+ View& View::SetFocus()
348
+ {
349
+ GetCurrentContext()->activeDisplay = this;
350
+ return *this;
351
+ }
352
+
353
+ bool View::HasFocus() const
354
+ {
355
+ return GetCurrentContext()->activeDisplay == this;
356
+ }
357
+
358
+ View& View::SetBounds(Attach bottom, Attach top, Attach left, Attach right)
359
+ {
360
+ this->left = left;
361
+ this->top = top;
362
+ this->right = right;
363
+ this->bottom = bottom;
364
+ GetCurrentContext()->base.ResizeChildren();
365
+ return *this;
366
+ }
367
+
368
+ View& View::SetBounds(Attach bottom, Attach top, Attach left, Attach right, bool keep_aspect)
369
+ {
370
+ aspect = keep_aspect ? v.aspect() : 0;
371
+ SetBounds(top,bottom,left,right);
372
+ return *this;
373
+ }
374
+
375
+ View& View::SetBounds(Attach bottom, Attach top, Attach left, Attach right, double aspect)
376
+ {
377
+ this->aspect = aspect;
378
+ SetBounds(top,bottom,left,right);
379
+ return *this;
380
+ }
381
+
382
+ View& View::SetAspect(double aspect)
383
+ {
384
+ this->aspect = aspect;
385
+ GetCurrentContext()->base.ResizeChildren();
386
+ return *this;
387
+ }
388
+
389
+ View& View::SetLock(Lock horizontal, Lock vertical )
390
+ {
391
+ vlock = vertical;
392
+ hlock = horizontal;
393
+ return *this;
394
+ }
395
+
396
+ View& View::SetLayout(Layout l)
397
+ {
398
+ layout = l;
399
+ return *this;
400
+ }
401
+
402
+
403
+ View& View::AddDisplay(View& child)
404
+ {
405
+ // detach child from any other view, and add to this
406
+ std::vector<View*>::iterator f = std::find(
407
+ GetCurrentContext()->base.views.begin(), GetCurrentContext()->base.views.end(), &child
408
+ );
409
+
410
+ if( f != GetCurrentContext()->base.views.end() )
411
+ GetCurrentContext()->base.views.erase(f);
412
+
413
+ views.push_back(&child);
414
+ GetCurrentContext()->base.ResizeChildren();
415
+ return *this;
416
+ }
417
+
418
+ View& View::Show(bool show)
419
+ {
420
+ this->show = show;
421
+ GetCurrentContext()->base.ResizeChildren();
422
+ return *this;
423
+ }
424
+
425
+ void View::ToggleShow()
426
+ {
427
+ Show(!show);
428
+ }
429
+
430
+ bool View::IsShown() const
431
+ {
432
+ return show;
433
+ }
434
+
435
+ Viewport View::GetBounds() const
436
+ {
437
+ return Viewport( std::max(v.l, vp.l), std::max(v.b, vp.b), std::min(v.w, vp.w), std::min(v.h, vp.h) );
438
+ }
439
+
440
+ void View::SaveOnRender(const std::string& filename_hint)
441
+ {
442
+ SaveWindowOnRender(filename_hint, this->v.Intersect(this->vp));
443
+ }
444
+
445
+ void View::SaveRenderNow(const std::string& filename_hint)
446
+ {
447
+ SaveWindowNow(filename_hint, this->v);
448
+ }
449
+
450
+ View& View::operator[](size_t i)
451
+ {
452
+ return *views[i];
453
+ }
454
+
455
+ size_t View::NumChildren() const
456
+ {
457
+ return views.size();
458
+ }
459
+
460
+ size_t View::NumVisibleChildren() const
461
+ {
462
+ int numvis = 0;
463
+ for(std::vector<View*>::const_iterator i=views.begin(); i!=views.end(); ++i)
464
+ {
465
+ if((*i)->show) {
466
+ numvis++;
467
+ }
468
+ }
469
+ return numvis;
470
+ }
471
+
472
+ View& View::VisibleChild(size_t i)
473
+ {
474
+ size_t numvis = 0;
475
+ for(size_t v=0; v < views.size(); ++v ) {
476
+ if(views[v]->show) {
477
+ if( i == numvis ) {
478
+ return *views[v];
479
+ }
480
+ numvis++;
481
+ }
482
+ }
483
+ // Shouldn't get here
484
+ throw std::out_of_range("No such child.");
485
+ }
486
+
487
+ View* View::FindChild(int x, int y)
488
+ {
489
+ // Find in reverse order to mirror draw order
490
+ for( std::vector<View*>::const_reverse_iterator i = views.rbegin(); i != views.rend(); ++i )
491
+ if( (*i)->show && (*i)->GetBounds().Contains(x,y) )
492
+ return (*i);
493
+ return 0;
494
+ }
495
+
496
+ View& View::SetHandler(Handler* h)
497
+ {
498
+ handler = h;
499
+ return *this;
500
+ }
501
+
502
+ View& View::SetDrawFunction(const std::function<void(View&)>& drawFunc)
503
+ {
504
+ extern_draw_function = drawFunc;
505
+ return *this;
506
+ }
507
+
508
+ }
third-party/DPVO/Pangolin/components/pango_display/src/widgets.cpp ADDED
@@ -0,0 +1,787 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include <thread>
29
+ #include <mutex>
30
+ #include <iostream>
31
+ #include <iomanip>
32
+
33
+ #include <pangolin/display/widgets.h>
34
+ #include <pangolin/display/display.h>
35
+ #include <pangolin/display/default_font.h>
36
+ #include <pangolin/gl/gldraw.h>
37
+ #include <pangolin/var/varextra.h>
38
+ #include <pangolin/utils/file_utils.h>
39
+
40
+ #include "pangolin_gl.h"
41
+
42
+
43
+ using namespace std;
44
+
45
+ namespace pangolin
46
+ {
47
+
48
+ const static GLfloat colour_s1[4] = {0.2f, 0.2f, 0.2f, 1.0f};
49
+ const static GLfloat colour_s2[4] = {0.6f, 0.6f, 0.6f, 1.0f};
50
+ const static GLfloat colour_bg[4] = {0.9f, 0.9f, 0.9f, 1.0f};
51
+ const static GLfloat colour_fg[4] = {1.0f, 1.0f, 1.0f, 1.0f};
52
+ const static GLfloat colour_tx[4] = {0.0f, 0.0f, 0.0f, 1.0f};
53
+ const static GLfloat colour_dn[4] = {1.0f, 0.7f, 0.7f, 1.0f};
54
+
55
+ // TODO: It doesn't look like this is doing anything meaningful right now...
56
+ std::mutex display_mutex;
57
+
58
+ // Render at (x,y) in window coordinates.
59
+ inline void DrawWindow(GlText& text, GLfloat x, GLfloat y, GLfloat z = 0.0)
60
+ {
61
+ // Backup viewport
62
+ GLint view[4];
63
+ glGetIntegerv(GL_VIEWPORT, view );
64
+
65
+ glMatrixMode(GL_PROJECTION);
66
+ glPushMatrix();
67
+ glMatrixMode(GL_MODELVIEW);
68
+ glPushMatrix();
69
+
70
+ DisplayBase().ActivatePixelOrthographic();
71
+
72
+ glTranslatef( std::floor(x), std::floor(y), z);
73
+ text.Draw();
74
+
75
+ // Restore viewport
76
+ glViewport(view[0],view[1],view[2],view[3]);
77
+
78
+ // Restore modelview / project matrices
79
+ glMatrixMode(GL_PROJECTION);
80
+ glPopMatrix();
81
+ glMatrixMode(GL_MODELVIEW);
82
+ glPopMatrix();
83
+ }
84
+
85
+ static inline int cb_height()
86
+ {
87
+ return (int)(default_font().Height() * 1.0);
88
+ }
89
+
90
+ static inline int tab_h()
91
+ {
92
+ return (int)(default_font().Height() * 1.4);
93
+ }
94
+
95
+ static inline float x_width()
96
+ {
97
+ return default_font().Text("x").Width();
98
+ }
99
+
100
+ template<typename T>
101
+ inline void MarkVarChangedByGui(VarValueT<T>& var)
102
+ {
103
+ var.Meta().gui_changed = true;
104
+ FlagVarChanged();
105
+ }
106
+
107
+ void glLine(GLfloat vs[4])
108
+ {
109
+ glEnableClientState(GL_VERTEX_ARRAY);
110
+ glVertexPointer(2, GL_FLOAT, 0, vs);
111
+ glDrawArrays( GL_LINE_STRIP, 0, 2);
112
+ glDisableClientState(GL_VERTEX_ARRAY);
113
+ }
114
+
115
+ void glRect(Viewport v)
116
+ {
117
+ GLfloat vs[] = { (float)v.l,(float)v.b,
118
+ (float)v.l,(float)v.t(),
119
+ (float)v.r(),(float)v.t(),
120
+ (float)v.r(),(float)v.b };
121
+
122
+ glEnableClientState(GL_VERTEX_ARRAY);
123
+ glVertexPointer(2, GL_FLOAT, 0, vs);
124
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
125
+ glDisableClientState(GL_VERTEX_ARRAY);
126
+ }
127
+
128
+ void glRect(Viewport v, int inset)
129
+ {
130
+ glRect(v.Inset(inset));
131
+ }
132
+
133
+ void DrawShadowRect(Viewport& v)
134
+ {
135
+ glColor4fv(colour_s2);
136
+ glDrawRectPerimeter((GLfloat)v.l, (GLfloat)v.b, (GLfloat)v.r(), (GLfloat)v.t());
137
+ }
138
+
139
+ void DrawShadowRect(Viewport& v, bool pushed)
140
+ {
141
+ const GLfloat* c1 = pushed ? colour_s1 : colour_s2;
142
+ const GLfloat* c2 = pushed ? colour_s2 : colour_s1;
143
+
144
+ GLfloat vs[] = { (float)v.l,(float)v.b,
145
+ (float)v.l,(float)v.t(),
146
+ (float)v.r(),(float)v.t(),
147
+ (float)v.r(),(float)v.b,
148
+ (float)v.l,(float)v.b };
149
+
150
+ glEnableClientState(GL_VERTEX_ARRAY);
151
+ glVertexPointer(2, GL_FLOAT, 0, vs);
152
+ glColor4fv(c1);
153
+ glDrawArrays(GL_LINE_STRIP, 0, 3);
154
+
155
+ glColor4fv(c2);
156
+ glDrawArrays(GL_LINE_STRIP, 2, 3);
157
+ glDisableClientState(GL_VERTEX_ARRAY);
158
+
159
+ }
160
+
161
+ Panel::Panel()
162
+ {
163
+ handler = &StaticHandlerScroll;
164
+ layout = LayoutVertical;
165
+ }
166
+
167
+ Panel::Panel(const std::string& auto_register_var_prefix)
168
+ : auto_register_var_prefix(auto_register_var_prefix)
169
+ {
170
+ handler = &StaticHandlerScroll;
171
+ layout = LayoutVertical;
172
+
173
+ // Register for notifications on var additions
174
+ var_added_connection = VarState::I().RegisterForVarEvents(
175
+ std::bind(&Panel::NewVarCallback,this,std::placeholders::_1),
176
+ true
177
+ );
178
+ }
179
+
180
+ void Panel::NewVarCallback(const VarState::Event& e)
181
+ {
182
+ const std::string name = e.var->Meta().full_name;
183
+ if(!StartsWith(name, auto_register_var_prefix))
184
+ return;
185
+
186
+ switch(e.action) {
187
+ case VarState::Event::Action::Added:
188
+ AddVariable(name, e.var);
189
+ break;
190
+ case VarState::Event::Action::Removed:
191
+ RemoveVariable(name);
192
+ break;
193
+ }
194
+ }
195
+
196
+ void Panel::AddVariable(const std::string& name, const std::shared_ptr<VarValueGeneric>& var)
197
+ {
198
+ const string& title = var->Meta().friendly;
199
+
200
+ display_mutex.lock();
201
+
202
+ ViewMap::iterator pnl = GetCurrentContext()->named_managed_views.find(name);
203
+
204
+ // Only add if a widget by the same name doesn't already exist
205
+ if( pnl == GetCurrentContext()->named_managed_views.end() )
206
+ {
207
+ View* nv = NULL;
208
+ if( !strcmp(var->TypeId(), typeid(bool).name()) ) {
209
+ nv = (var->Meta().flags & META_FLAG_TOGGLE) ? (View*)new Checkbox(title,var) : (View*)new Button(title,var);
210
+ } else if (!strcmp(var->TypeId(), typeid(double).name()) ||
211
+ !strcmp(var->TypeId(), typeid(float).name()) ||
212
+ !strcmp(var->TypeId(), typeid(int8_t).name()) ||
213
+ !strcmp(var->TypeId(), typeid(uint8_t).name()) ||
214
+ !strcmp(var->TypeId(), typeid(int16_t).name()) ||
215
+ !strcmp(var->TypeId(), typeid(uint16_t).name()) ||
216
+ !strcmp(var->TypeId(), typeid(int32_t).name()) ||
217
+ !strcmp(var->TypeId(), typeid(uint32_t).name()) ||
218
+ !strcmp(var->TypeId(), typeid(int64_t).name()) ||
219
+ !strcmp(var->TypeId(), typeid(uint64_t).name())
220
+ )
221
+ {
222
+ nv = new Slider(title, var);
223
+ } else if (!strcmp(var->TypeId(), typeid(std::function<void(void)>).name() ) ) {
224
+ nv = (View*)new FunctionButton(title, var);
225
+ }else if(var->str){
226
+ nv = new TextInput(title,var);
227
+ }
228
+ if(nv) {
229
+ GetCurrentContext()->named_managed_views[name] = nv;
230
+ views.push_back( nv );
231
+ ResizeChildren();
232
+ }
233
+ }
234
+
235
+ display_mutex.unlock();
236
+ }
237
+
238
+ void Panel::RemoveVariable(const std::string& name)
239
+ {
240
+ display_mutex.lock();
241
+
242
+ ViewMap::iterator pnl = GetCurrentContext()->named_managed_views.find(name);
243
+
244
+ if( pnl != GetCurrentContext()->named_managed_views.end() ) {
245
+ views.erase(std::remove(views.begin(), views.end(), pnl->second), views.end());
246
+ ResizeChildren();
247
+
248
+ delete pnl->second;
249
+ GetCurrentContext()->named_managed_views.erase(pnl);
250
+ }
251
+
252
+ display_mutex.unlock();
253
+ }
254
+
255
+ void Panel::Render()
256
+ {
257
+ #ifndef HAVE_GLES
258
+ glPushAttrib(GL_CURRENT_BIT | GL_ENABLE_BIT | GL_DEPTH_BUFFER_BIT | GL_SCISSOR_BIT | GL_VIEWPORT_BIT | GL_COLOR_BUFFER_BIT | GL_TRANSFORM_BIT);
259
+ #endif
260
+ glEnable (GL_BLEND);
261
+ glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
262
+
263
+ DisplayBase().ActivatePixelOrthographic();
264
+ glDisable(GL_DEPTH_TEST);
265
+ glDisable(GL_LIGHTING);
266
+ glDisable(GL_SCISSOR_TEST);
267
+ glDisable(GL_LINE_SMOOTH);
268
+ glDisable( GL_COLOR_MATERIAL );
269
+ glLineWidth(1.0);
270
+
271
+ glColor4fv(colour_bg);
272
+ glRect(v);
273
+ DrawShadowRect(v);
274
+
275
+ RenderChildren();
276
+
277
+ #ifndef HAVE_GLES
278
+ glPopAttrib();
279
+ #else
280
+ glEnable(GL_LINE_SMOOTH);
281
+ glEnable(GL_DEPTH_TEST);
282
+ #endif
283
+ }
284
+
285
+ void Panel::ResizeChildren()
286
+ {
287
+ View::ResizeChildren();
288
+ }
289
+
290
+
291
+ View& CreatePanel(const std::string& name)
292
+ {
293
+ if(GetCurrentContext()->named_managed_views.find(name) != GetCurrentContext()->named_managed_views.end()) {
294
+ throw std::runtime_error("Panel already registered with this name.");
295
+ }
296
+ Panel * p = new Panel(name);
297
+ GetCurrentContext()->named_managed_views[name] = p;
298
+ GetCurrentContext()->base.views.push_back(p);
299
+ return *p;
300
+ }
301
+
302
+ Button::Button(string title, const std::shared_ptr<VarValueGeneric>& tv)
303
+ : Widget<bool>(title,tv), down(false)
304
+ {
305
+ top = 1.0; bottom = Attach::Pix(-tab_h());
306
+ left = 0.0; right = 1.0;
307
+ hlock = LockLeft;
308
+ vlock = LockBottom;
309
+ gltext = default_font().Text(title);
310
+ }
311
+
312
+ void Button::Mouse(View&, MouseButton button, int /*x*/, int /*y*/, bool pressed, int /*mouse_state*/)
313
+ {
314
+ if(button == MouseButtonLeft )
315
+ {
316
+ down = pressed;
317
+ if( !pressed ) {
318
+ var->Set(!var->Get());
319
+ MarkVarChangedByGui(*var);
320
+ }
321
+ }
322
+ }
323
+
324
+ void Button::Render()
325
+ {
326
+ glColor4fv(colour_fg );
327
+ glRect(v);
328
+ glColor4fv(colour_tx);
329
+ if(gltext.Text() != var->Meta().friendly) {
330
+ gltext = default_font().Text(var->Meta().friendly);
331
+ }
332
+ DrawWindow(gltext, raster[0],raster[1]-down);
333
+ DrawShadowRect(v, down);
334
+ }
335
+
336
+ void Button::ResizeChildren()
337
+ {
338
+ raster[0] = floor(v.l + (v.w-gltext.Width())/2.0f);
339
+ raster[1] = floor(v.b + (v.h-gltext.Height())/2.0f);
340
+ }
341
+
342
+ FunctionButton::FunctionButton(string title, const std::shared_ptr<VarValueGeneric> &tv)
343
+ : Widget<std::function<void(void)> >(title, tv), down(false)
344
+ {
345
+ top = 1.0; bottom = Attach::Pix(-tab_h());
346
+ left = 0.0; right = 1.0;
347
+ hlock = LockLeft;
348
+ vlock = LockBottom;
349
+ gltext = default_font().Text(title);
350
+ }
351
+
352
+ void FunctionButton::Mouse(View&, MouseButton button, int /*x*/, int /*y*/, bool pressed, int /*mouse_state*/)
353
+ {
354
+ if (button == MouseButtonLeft)
355
+ {
356
+ down = pressed;
357
+ if (!pressed) {
358
+ var->Get()();
359
+ MarkVarChangedByGui(*var);
360
+ }
361
+ }
362
+ }
363
+
364
+ void FunctionButton::Render()
365
+ {
366
+ glColor4fv(colour_fg);
367
+ glRect(v);
368
+ glColor4fv(colour_tx);
369
+ if(gltext.Text() != var->Meta().friendly) {
370
+ gltext = default_font().Text(var->Meta().friendly);
371
+ }
372
+ DrawWindow(gltext, raster[0],raster[1]-down);
373
+ DrawShadowRect(v, down);
374
+ }
375
+
376
+ void FunctionButton::ResizeChildren()
377
+ {
378
+ raster[0] = v.l + (v.w - gltext.Width()) / 2.0f;
379
+ raster[1] = v.b + (v.h - gltext.Height()) / 2.0f;
380
+ }
381
+
382
+ Checkbox::Checkbox(std::string title, const std::shared_ptr<VarValueGeneric> &tv)
383
+ : Widget<bool>(title,tv)
384
+ {
385
+ top = 1.0; bottom = Attach::Pix(-tab_h());
386
+ left = 0.0; right = 1.0;
387
+ hlock = LockLeft;
388
+ vlock = LockBottom;
389
+ handler = this;
390
+ gltext = default_font().Text(title);
391
+ }
392
+
393
+ void Checkbox::Mouse(View&, MouseButton button, int /*x*/, int /*y*/, bool pressed, int /*mouse_state*/)
394
+ {
395
+ if( button == MouseButtonLeft && pressed ) {
396
+ var->Set(!var->Get());
397
+ MarkVarChangedByGui(*var);
398
+ }
399
+ }
400
+
401
+ void Checkbox::ResizeChildren()
402
+ {
403
+ raster[0] = v.l + cb_height() + 4.0f;
404
+ raster[1] = v.b + (v.h-gltext.Height())/2.0f;
405
+ const int h = v.h;
406
+ const int t = (int)((h-cb_height()) / 2.0f);
407
+ vcb = Viewport(v.l,v.b+t,cb_height(),cb_height());
408
+ }
409
+
410
+ void Checkbox::Render()
411
+ {
412
+ const bool val = var->Get();
413
+
414
+ if( val )
415
+ {
416
+ glColor4fv(colour_dn);
417
+ glRect(vcb);
418
+ }
419
+ glColor4fv(colour_tx);
420
+ if(gltext.Text() != var->Meta().friendly) {
421
+ gltext = default_font().Text(var->Meta().friendly);
422
+ }
423
+ DrawWindow(gltext, raster[0], raster[1]);
424
+ DrawShadowRect(vcb, val);
425
+ }
426
+
427
+ inline bool IsIntegral(const char* typeidname)
428
+ {
429
+ // TODO: There must be a better way of doing this...
430
+ return !strcmp(typeidname, typeid(char).name()) ||
431
+ !strcmp(typeidname, typeid(short).name()) ||
432
+ !strcmp(typeidname, typeid(int).name()) ||
433
+ !strcmp(typeidname, typeid(long).name()) ||
434
+ !strcmp(typeidname, typeid(unsigned char).name()) ||
435
+ !strcmp(typeidname, typeid(unsigned short).name()) ||
436
+ !strcmp(typeidname, typeid(unsigned int).name()) ||
437
+ !strcmp(typeidname, typeid(unsigned long).name());
438
+ }
439
+
440
+ Slider::Slider(std::string title, const std::shared_ptr<VarValueGeneric> &tv)
441
+ : Widget<double>(title+":", tv), lock_bounds(true)
442
+ {
443
+ top = 1.0; bottom = Attach::Pix(-tab_h());
444
+ left = 0.0; right = 1.0;
445
+ hlock = LockLeft;
446
+ vlock = LockBottom;
447
+ handler = this;
448
+ logscale = (int)tv->Meta().logscale;
449
+ gltext = default_font().Text(title);
450
+ is_integral_type = IsIntegral(tv->TypeId());
451
+ }
452
+
453
+ void Slider::Keyboard(View&, unsigned char key, int /*x*/, int /*y*/, bool pressed)
454
+ {
455
+ if( pressed && var->Meta().range[0] < var->Meta().range[1] )
456
+ {
457
+ double val = !logscale ? var->Get() : log(var->Get());
458
+
459
+ if(key=='-' || key=='_' || key=='=' || key=='+') {
460
+ double inc = var->Meta().increment;
461
+ if (key == '-') inc *= -1.0;
462
+ if (key == '_') inc *= -0.1;
463
+ if (key == '+') inc *= 0.1;
464
+ const double newval = max(var->Meta().range[0], min(var->Meta().range[1], val + inc));
465
+ var->Set( logscale ? exp(newval) : newval );
466
+ MarkVarChangedByGui(*var);
467
+ }else if(key == 'r'){
468
+ Reset();
469
+ MarkVarChangedByGui(*var);
470
+ }else{
471
+ return;
472
+ }
473
+ }
474
+ }
475
+
476
+ void Slider::Mouse(View& view, MouseButton button, int x, int y, bool pressed, int mouse_state)
477
+ {
478
+ if(pressed)
479
+ {
480
+ // Wheel
481
+ if( button == MouseWheelUp || button == MouseWheelDown )
482
+ {
483
+ // Change scale around current value
484
+ const double frac = max(0.0,min(1.0,(double)(x - v.l)/(double)v.w));
485
+ double val = frac * (var->Meta().range[1] - var->Meta().range[0]) + var->Meta().range[0];
486
+
487
+ if (logscale)
488
+ {
489
+ if (val<=0)
490
+ val = std::numeric_limits<double>::min();
491
+ else
492
+ val = log(val);
493
+ }
494
+
495
+ const double scale = (button == MouseWheelUp ? 1.2 : 1.0 / 1.2 );
496
+ var->Meta().range[1] = val + (var->Meta().range[1] - val)*scale;
497
+ var->Meta().range[0] = val - (val - var->Meta().range[0])*scale;
498
+ }else{
499
+ lock_bounds = (button == MouseButtonLeft);
500
+ MouseMotion(view,x,y,mouse_state);
501
+ }
502
+ }else{
503
+ if(!lock_bounds)
504
+ {
505
+ double val = !logscale ? var->Get() : log(var->Get());
506
+
507
+ var->Meta().range[0] = min(var->Meta().range[0], val);
508
+ var->Meta().range[1] = max(var->Meta().range[1], val);
509
+ }
510
+ }
511
+ }
512
+
513
+ void Slider::MouseMotion(View&, int x, int /*y*/, int /*mouse_state*/)
514
+ {
515
+ if( var->Meta().range[0] != var->Meta().range[1] )
516
+ {
517
+ const double range = (var->Meta().range[1] - var->Meta().range[0]);
518
+ const double frac = (double)(x - v.l)/(double)v.w;
519
+ double val;
520
+
521
+ if( lock_bounds )
522
+ {
523
+ const double bfrac = max(0.0,min(1.0,frac));
524
+ val = bfrac * range + var->Meta().range[0] ;
525
+ }else{
526
+ val = frac * range + var->Meta().range[0];
527
+ }
528
+
529
+ if (logscale) {
530
+ val = exp(val);
531
+ }
532
+
533
+ if( is_integral_type ) {
534
+ val = std::round(val);
535
+ }
536
+
537
+ var->Set(val);
538
+ MarkVarChangedByGui(*var);
539
+ }
540
+ }
541
+
542
+
543
+ void Slider::ResizeChildren()
544
+ {
545
+ raster[0] = v.l + 2.0f;
546
+ raster[1] = v.b + (v.h-gltext.Height())/2.0f;
547
+ }
548
+
549
+ void Slider::Render()
550
+ {
551
+ const double val = var->Get();
552
+
553
+ if( var->Meta().range[0] != var->Meta().range[1] )
554
+ {
555
+ double rval = val;
556
+ if (logscale)
557
+ {
558
+ rval = log(val);
559
+ }
560
+ glColor4fv(colour_fg);
561
+ glRect(v);
562
+ glColor4fv(colour_dn);
563
+ const double norm_val = max(0.0,min(1.0,(rval - var->Meta().range[0]) / (var->Meta().range[1] - var->Meta().range[0])));
564
+ glRect(Viewport(v.l,v.b, (int)(v.w*norm_val),v.h));
565
+ DrawShadowRect(v);
566
+ }
567
+
568
+ glColor4fv(colour_tx);
569
+ if(gltext.Text() != var->Meta().friendly) {
570
+ gltext = default_font().Text(var->Meta().friendly);
571
+ }
572
+ DrawWindow(gltext, raster[0], raster[1]);
573
+
574
+ std::ostringstream oss;
575
+ oss << setprecision(4) << val;
576
+ string str = oss.str();
577
+ GlText glval = default_font().Text(str);
578
+ const float l = glval.Width() + 2.0f;
579
+ DrawWindow(glval, v.l + v.w - l, raster[1] );
580
+ }
581
+
582
+
583
+ TextInput::TextInput(std::string title, const std::shared_ptr<VarValueGeneric> &tv)
584
+ : Widget<std::string>(title+":", tv), can_edit(!(tv->Meta().flags & META_FLAG_READONLY)), do_edit(false)
585
+ {
586
+ top = 1.0; bottom = Attach::Pix(-2 * tab_h());
587
+ left = 0.0; right = 1.0;
588
+ hlock = LockLeft;
589
+ vlock = LockBottom;
590
+ handler = this;
591
+ sel[0] = -1;
592
+ sel[1] = -1;
593
+ gltext = default_font().Text(title);
594
+ }
595
+
596
+ void TextInput::Keyboard(View&, unsigned char key, int /*x*/, int /*y*/, bool pressed)
597
+ {
598
+ if(can_edit && pressed && do_edit)
599
+ {
600
+ const bool selection = sel[1] > sel[0] && sel[0] >= 0;
601
+
602
+ if(key == 13)
603
+ {
604
+ var->Set(edit);
605
+ MarkVarChangedByGui(*var);
606
+
607
+ do_edit = false;
608
+ sel[0] = sel[1] = -1;
609
+ }else if(key == 8) {
610
+ // backspace
611
+ if(selection)
612
+ {
613
+ edit = edit.substr(0,sel[0]) + edit.substr(sel[1],edit.length()-sel[1]);
614
+ sel[1] = sel[0];
615
+ }else{
616
+ if(sel[0] >0)
617
+ {
618
+ edit = edit.substr(0,sel[0]-1) + edit.substr(sel[0],edit.length()-sel[0]);
619
+ sel[0]--;
620
+ sel[1]--;
621
+ }
622
+ }
623
+ }else if(key == 127){
624
+ // delete
625
+ if(selection)
626
+ {
627
+ edit = edit.substr(0,sel[0]) + edit.substr(sel[1],edit.length()-sel[1]);
628
+ sel[1] = sel[0];
629
+ }else{
630
+ if(sel[0] < (int)edit.length())
631
+ {
632
+ edit = edit.substr(0,sel[0]) + edit.substr(sel[0]+1,edit.length()-sel[0]+1);
633
+ }
634
+ }
635
+ }else if(key == 230){
636
+ // right
637
+ sel[0] = min((int)edit.length(),sel[0]+1);
638
+ sel[1] = sel[0];
639
+ }else if(key == 228){
640
+ // left
641
+ sel[0] = max(0,sel[0]-1);
642
+ sel[1] = sel[0];
643
+ }else if(key == 234){
644
+ // home
645
+ sel[0] = sel[1] = 0;
646
+ }else if(key == 235){
647
+ // end
648
+ sel[0] = sel[1] = (int)edit.length();
649
+ }else if(key < PANGO_SPECIAL){
650
+ edit = edit.substr(0,sel[0]).append(1,key) + edit.substr(sel[1],edit.length()-sel[1]);
651
+ sel[1] = sel[0];
652
+ sel[0]++;
653
+ sel[1]++;
654
+ }
655
+ CalcVisibleEditPart();
656
+ }
657
+ }
658
+
659
+ void TextInput::Mouse(View& /*view*/, MouseButton button, int x, int /*y*/, bool pressed, int /*mouse_state*/)
660
+ {
661
+ if(can_edit && button != MouseWheelUp && button != MouseWheelDown )
662
+ {
663
+
664
+ if(do_edit)
665
+ {
666
+ const int sl = (int)gledit.Width() + vertical_margin;
667
+ const int rl = v.l + v.w - sl;
668
+ std::string edit_visible = edit.substr(edit_visible_part[0], edit_visible_part[1]);
669
+ int ep = (int)edit_visible.length();
670
+
671
+ if( x < rl )
672
+ {
673
+ ep = 0;
674
+ }else{
675
+ for( unsigned i=0; i<edit_visible.length(); ++i )
676
+ {
677
+ const int tl = (int)(rl + default_font().Text(edit_visible.substr(0,i)).Width());
678
+ if(x < tl+2)
679
+ {
680
+ ep = i;
681
+ break;
682
+ }
683
+ }
684
+ }
685
+ if(pressed)
686
+ {
687
+ sel[0] = sel[1] = ep + edit_visible_part[0];
688
+ }else{
689
+ sel[1] = ep + edit_visible_part[0];
690
+ }
691
+
692
+ if(sel[0] > sel[1])
693
+ std::swap(sel[0],sel[1]);
694
+ }else{
695
+ do_edit = !pressed;
696
+ sel[0] = 0;
697
+ sel[1] = (int)edit.length();
698
+ }
699
+ }
700
+ }
701
+
702
+ void TextInput::MouseMotion(View&, int x, int /*y*/, int /*mouse_state*/)
703
+ {
704
+ if(can_edit && do_edit)
705
+ {
706
+ const int sl = (int)gledit.Width() + 2;
707
+ const int rl = v.l + v.w - sl;
708
+ std::string edit_visible = edit.substr(edit_visible_part[0], edit_visible_part[1]);
709
+ int ep = (int)edit_visible.length();
710
+
711
+ if( x < rl )
712
+ {
713
+ ep = 0;
714
+ }else{
715
+ for( unsigned i=0; i<edit.length(); ++i )
716
+ {
717
+ const int tl = (int)(rl + default_font().Text(edit_visible.substr(0,i)).Width());
718
+ if(x < tl+2)
719
+ {
720
+ ep = i;
721
+ break;
722
+ }
723
+ }
724
+ }
725
+
726
+ sel[1] = ep + edit_visible_part[0];
727
+ }
728
+ }
729
+
730
+
731
+ void TextInput::ResizeChildren()
732
+ {
733
+ vertical_margin = (v.h-2.f*gltext.Height()) / 4.0f;
734
+ input_width = v.w - 2 * horizontal_margin;
735
+ int max_possible_chars = floor(input_width / x_width());
736
+ edit_visible_part[1] = max_possible_chars;
737
+ CalcVisibleEditPart();
738
+ }
739
+
740
+ void TextInput::CalcVisibleEditPart()
741
+ {
742
+ edit_visible_part[0] = 0;
743
+
744
+ if(default_font().Text(edit).Width() > input_width)
745
+ {
746
+ if(sel[1] >= 0 )
747
+ {
748
+ edit_visible_part[0] = max(0, sel[1] - edit_visible_part[1]);
749
+ }
750
+ }
751
+ };
752
+
753
+ void TextInput::Render()
754
+ {
755
+ if(!do_edit) edit = var->Get();
756
+
757
+ Viewport input_v(v.l,v.b,v.w,v.h / 2);
758
+
759
+ glColor4fv(colour_fg);
760
+ if(can_edit) glRect(input_v);
761
+
762
+ std::string edit_visible = edit.substr(edit_visible_part[0], edit_visible_part[1]);
763
+ gledit = default_font().Text(edit_visible);
764
+
765
+ const int sl = (int)gledit.Width() + horizontal_margin;
766
+ const int rl = v.l + v.w - sl;
767
+
768
+ if( do_edit && sel[0] >= 0)
769
+ {
770
+ const int tl = (int)(rl + default_font().Text(edit_visible.substr(0,sel[0] - edit_visible_part[0])).Width());
771
+ const int tr = (int)(rl + default_font().Text(edit_visible.substr(0,sel[1] - edit_visible_part[0])).Width());
772
+ glColor4fv(colour_dn);
773
+ glRect(Viewport(tl,input_v.b,tr-tl,input_v.h));
774
+
775
+ glColor4fv(colour_tx);
776
+ GLfloat caret[4] = {(float) tr, (float) input_v.b, (float) tr, (float) input_v.b + input_v.h};
777
+ glLine(caret);
778
+ }
779
+
780
+ glColor4fv(colour_tx);
781
+ DrawWindow(gltext, v.l + horizontal_margin, v.b + gltext.Height() + 3.f * vertical_margin);
782
+
783
+ DrawWindow(gledit, (GLfloat)(rl), input_v.b + vertical_margin);
784
+ if(can_edit) DrawShadowRect(input_v);
785
+ }
786
+
787
+ }
third-party/DPVO/Pangolin/components/pango_geometry/CMakeLists.txt ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ get_filename_component(COMPONENT ${CMAKE_CURRENT_LIST_DIR} NAME)
2
+
3
+ find_package (Eigen3 REQUIRED QUIET)
4
+ message(STATUS "Found Eigen: '${EIGEN3_INCLUDE_DIRS}'")
5
+ target_compile_definitions(${COMPONENT} PUBLIC HAVE_EIGEN)
6
+
7
+ target_sources( ${COMPONENT}
8
+ PRIVATE
9
+ ${CMAKE_CURRENT_LIST_DIR}/src/geometry.cpp
10
+ ${CMAKE_CURRENT_LIST_DIR}/src/geometry_obj.cpp
11
+ ${CMAKE_CURRENT_LIST_DIR}/src/geometry_ply.cpp
12
+ )
13
+
14
+ target_link_libraries(${COMPONENT} pango_core pango_image tinyobj Eigen3::Eigen)
15
+ target_include_directories(${COMPONENT} PUBLIC
16
+ $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
17
+ $<INSTALL_INTERFACE:include>
18
+ )
19
+ install(DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/include"
20
+ DESTINATION ${CMAKE_INSTALL_PREFIX}
21
+ )
third-party/DPVO/Pangolin/components/pango_geometry/include/pangolin/geometry/geometry.h ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2014 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #ifndef PANGOLIN_GEOMETRY_H
29
+ #define PANGOLIN_GEOMETRY_H
30
+
31
+ #include <map>
32
+ #include <unordered_map>
33
+ #include <vector>
34
+ #include <variant>
35
+ #include <pangolin/image/typed_image.h>
36
+
37
+ #ifdef HAVE_EIGEN
38
+ #include <Eigen/Geometry>
39
+ #endif
40
+
41
+ namespace pangolin
42
+ {
43
+
44
+ struct Geometry
45
+ {
46
+ struct Element : public ManagedImage<uint8_t> {
47
+ Element() = default;
48
+ Element(Element&&) = default;
49
+ Element& operator=(Element&&) = default;
50
+
51
+ Element(size_t stride_bytes, size_t num_elements)
52
+ : ManagedImage<uint8_t>(stride_bytes, num_elements)
53
+ {}
54
+
55
+ using Attribute = std::variant<Image<float>,Image<uint32_t>,Image<uint16_t>,Image<uint8_t>>;
56
+ // "vertex", "rgb", "normal", "uv", "tris", "quads", ...
57
+ std::map<std::string, Attribute> attributes;
58
+ };
59
+
60
+ // Store vertices and attributes
61
+ std::map<std::string, Element> buffers;
62
+ // Stores index buffers for each sub-object
63
+ std::multimap<std::string, Element> objects;
64
+ // Stores pixmaps
65
+ std::map<std::string, TypedImage> textures;
66
+ };
67
+
68
+ pangolin::Geometry LoadGeometry(const std::string& filename);
69
+
70
+ #ifdef HAVE_EIGEN
71
+ inline Eigen::AlignedBox3f GetAxisAlignedBox(const Geometry& geom)
72
+ {
73
+ Eigen::AlignedBox3f box;
74
+ box.setEmpty();
75
+
76
+ for(const auto& b : geom.buffers) {
77
+ const auto& it_vert = b.second.attributes.find("vertex");
78
+ if(it_vert != b.second.attributes.end()) {
79
+ const Image<float>& vs = std::get<Image<float>>(it_vert->second);
80
+ for(size_t i=0; i < vs.h; ++i) {
81
+ const Eigen::Map<const Eigen::Vector3f> v(vs.RowPtr(i));
82
+ box.extend(v);
83
+ }
84
+ }
85
+ }
86
+
87
+ return box;
88
+ }
89
+ #endif
90
+
91
+ }
92
+
93
+ #endif // PANGOLIN_GEOMETRY_H
third-party/DPVO/Pangolin/components/pango_geometry/include/pangolin/geometry/geometry_obj.h ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2011 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include <pangolin/geometry/geometry.h>
29
+
30
+ namespace pangolin {
31
+
32
+ pangolin::Geometry LoadGeometryObj(const std::string& filename);
33
+
34
+ }
third-party/DPVO/Pangolin/components/pango_geometry/include/pangolin/geometry/geometry_ply.h ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ /* This file is part of the Pangolin Project.
2
+ * http://github.com/stevenlovegrove/Pangolin
3
+ *
4
+ * Copyright (c) 2014 Steven Lovegrove
5
+ *
6
+ * Permission is hereby granted, free of charge, to any person
7
+ * obtaining a copy of this software and associated documentation
8
+ * files (the "Software"), to deal in the Software without
9
+ * restriction, including without limitation the rights to use,
10
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell
11
+ * copies of the Software, and to permit persons to whom the
12
+ * Software is furnished to do so, subject to the following
13
+ * conditions:
14
+ *
15
+ * The above copyright notice and this permission notice shall be
16
+ * included in all copies or substantial portions of the Software.
17
+ *
18
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
20
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
22
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
23
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
24
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25
+ * OTHER DEALINGS IN THE SOFTWARE.
26
+ */
27
+
28
+ #include <variant>
29
+ #include <pangolin/platform.h>
30
+ #include <pangolin/geometry/geometry.h>
31
+ #include <pangolin/geometry/geometry.h>
32
+
33
+ #include <fstream>
34
+ #include <vector>
35
+ #include <algorithm>
36
+
37
+ namespace pangolin
38
+ {
39
+
40
+ #define PLY_GROUP_LIST(m) m(PlyHeader) m(PlyFormat) m(PlyType)
41
+ #define PLY_HEADER_LIST(m) m(ply) m(format) m(comment) m(property) m(element) m(end_header)
42
+ #define PLY_FORMAT_LIST(m) m(ascii) m(binary_big_endian) m(binary_little_endian)
43
+ #define PLY_TYPE_LIST(m) m(char) m(uchar) m(short) m(ushort) m(int) m(uint) m(float) m(double) m(list) m(none)
44
+ #define PLY_CTYPE_LIST(m) m(int8_t) m(uint8_t) m(int16_t) m(uint16_t) m(int32_t) m(uint32_t) m(float) m(double) m(void*) m(void*)
45
+
46
+ // Define Enums / strings
47
+ enum PlyHeader {
48
+ #define FORMAT_ENUM(x) PlyHeader_##x,
49
+ PLY_HEADER_LIST(FORMAT_ENUM)
50
+ PlyHeaderSize
51
+ #undef FORMAT_ENUM
52
+ };
53
+
54
+ enum PlyFormat {
55
+ #define FORMAT_ENUM(x) PlyFormat_##x,
56
+ PLY_FORMAT_LIST(FORMAT_ENUM)
57
+ PlyFormatSize
58
+ #undef FORMAT_ENUM
59
+ };
60
+
61
+ enum PlyType {
62
+ #define FORMAT_ENUM(x) PlyType_##x,
63
+ PLY_TYPE_LIST(FORMAT_ENUM)
64
+ PlyTypeSize
65
+ #undef FORMAT_ENUM
66
+ };
67
+ const size_t PlyTypeSizeBytes[] = {
68
+ #define FORMAT_ENUM(x) sizeof(x),
69
+ PLY_CTYPE_LIST(FORMAT_ENUM)
70
+ #undef FORMAT_ENUM
71
+ };
72
+
73
+ struct PlyPropertyDetails
74
+ {
75
+ std::string name;
76
+
77
+ // Type of property
78
+ PlyType type;
79
+
80
+ // Type of list index if a list, or 0 otherwise.
81
+ PlyType list_index_type;
82
+
83
+ // Offset from element start
84
+ size_t offset_bytes;
85
+
86
+ // Number of items in the list. 1 if not a list. -1 if unknown.
87
+ int num_items;
88
+
89
+ bool isList() const {
90
+ return list_index_type > 0;
91
+ }
92
+ };
93
+
94
+ struct PlyElementDetails
95
+ {
96
+ std::string name;
97
+ int num_items;
98
+ int stride_bytes;
99
+ std::vector<PlyPropertyDetails> properties;
100
+
101
+ inline std::vector<PlyPropertyDetails>::iterator FindProperty(const std::string& name)
102
+ {
103
+ return std::find_if(properties.begin(), properties.end(),
104
+ [&name](const PlyPropertyDetails& p){ return p.name == name;}
105
+ );
106
+ }
107
+ };
108
+
109
+ struct PlyHeaderDetails
110
+ {
111
+ PlyFormat format;
112
+ std::string version;
113
+ std::vector<PlyElementDetails> elements;
114
+
115
+ inline std::vector<PlyElementDetails>::iterator FindElement(const std::string& name)
116
+ {
117
+ return std::find_if(elements.begin(), elements.end(),
118
+ [&name](const PlyElementDetails& el){ return el.name == name;}
119
+ );
120
+ }
121
+ };
122
+
123
+ void ParsePlyHeader(PlyHeaderDetails& ply, std::istream& is);
124
+
125
+ struct PlyBuffer
126
+ {
127
+ size_t index_size_bytes;
128
+ size_t element_item_size_bytes;
129
+ std::vector<unsigned char> data;
130
+ };
131
+
132
+ void ParsePlyAscii(pangolin::Geometry& /*geom*/, const PlyHeaderDetails& /*ply*/, std::istream& /*is*/);
133
+
134
+ // Convert Seperate "x","y","z" attributes into a single "vertex" attribute
135
+ void StandardizeXyzToVertex(pangolin::Geometry& geom);
136
+
137
+ // The Artec scanner saves with these attributes, for example
138
+ void StandardizeMultiTextureFaceToXyzuv(pangolin::Geometry& geom);
139
+
140
+ void Standardize(pangolin::Geometry& geom);
141
+
142
+ void ParsePlyLE(pangolin::Geometry& geom, PlyHeaderDetails& ply, std::istream& is);
143
+
144
+ void ParsePlyBE(pangolin::Geometry& /*geom*/, const PlyHeaderDetails& /*ply*/, std::istream& /*is*/);
145
+
146
+ void AttachAssociatedTexturesPly(pangolin::Geometry& geom, const std::string& filename);
147
+
148
+ pangolin::Geometry LoadGeometryPly(const std::string& filename);
149
+
150
+ }