Directory: | ./ |
---|---|
File: | include/gepetto/viewer/node-property.h |
Date: | 2024-12-20 15:53:58 |
Exec | Total | Coverage | |
---|---|---|---|
Lines: | 65 | 138 | 47.1% |
Branches: | 22 | 95 | 23.2% |
Line | Branch | Exec | Source |
---|---|---|---|
1 | // Copyright (c) 2017, LAAS-CNRS | ||
2 | // Authors: Joseph Mirabel (joseph.mirabel@laas.fr) | ||
3 | // | ||
4 | // This file is part of hpp-core. | ||
5 | // hpp-core is free software: you can redistribute it | ||
6 | // and/or modify it under the terms of the GNU Lesser General Public | ||
7 | // License as published by the Free Software Foundation, either version | ||
8 | // 3 of the License, or (at your option) any later version. | ||
9 | // | ||
10 | // hpp-core is distributed in the hope that it will be | ||
11 | // useful, but WITHOUT ANY WARRANTY; without even the implied warranty | ||
12 | // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
13 | // General Lesser Public License for more details. You should have | ||
14 | // received a copy of the GNU Lesser General Public License along with | ||
15 | // hpp-core. If not, see <http://www.gnu.org/licenses/>. | ||
16 | |||
17 | #ifndef GEPETTO_VIEWER_NODE_PROPERTY_HH | ||
18 | #define GEPETTO_VIEWER_NODE_PROPERTY_HH | ||
19 | |||
20 | #include <iostream> | ||
21 | #include <map> | ||
22 | |||
23 | #ifndef Q_MOC_RUN | ||
24 | #include <boost/bind.hpp> | ||
25 | #include <boost/function.hpp> | ||
26 | #include <boost/mpl/if.hpp> | ||
27 | #endif | ||
28 | |||
29 | #include <gepetto/viewer/config-osg.h> | ||
30 | #include <gepetto/viewer/fwd.h> | ||
31 | |||
32 | #include <QObject> | ||
33 | |||
34 | class QWidget; | ||
35 | |||
36 | namespace gepetto { | ||
37 | namespace viewer { | ||
38 | |||
39 | class Property; | ||
40 | template <typename T> | ||
41 | class PropertyTpl; | ||
42 | template <typename T, typename RangeT = T> | ||
43 | class RangedPropertyTpl; | ||
44 | |||
45 | /// \cond | ||
46 | namespace details { | ||
47 | template <typename T> | ||
48 | struct property_type {}; | ||
49 | template <typename T> | ||
50 | struct property_type<const T> : property_type<T> {}; | ||
51 | template <typename T> | ||
52 | struct property_type<T&> : property_type<T> {}; | ||
53 | template <> | ||
54 | struct property_type<void> { | ||
55 | ✗ | static inline std::string to_string() { return "void"; } | |
56 | }; | ||
57 | template <> | ||
58 | struct property_type<bool> { | ||
59 | ✗ | static inline std::string to_string() { return "bool"; } | |
60 | }; | ||
61 | template <> | ||
62 | struct property_type<int> { | ||
63 | ✗ | static inline std::string to_string() { return "int"; } | |
64 | }; | ||
65 | template <> | ||
66 | struct property_type<float> { | ||
67 | ✗ | static inline std::string to_string() { return "float"; } | |
68 | }; | ||
69 | template <> | ||
70 | struct property_type<std::string> { | ||
71 | ✗ | static inline std::string to_string() { return "string"; } | |
72 | }; | ||
73 | template <> | ||
74 | struct property_type<osgVector2> { | ||
75 | ✗ | static inline std::string to_string() { return "osgVector2"; } | |
76 | }; | ||
77 | template <> | ||
78 | struct property_type<osgVector3> { | ||
79 | ✗ | static inline std::string to_string() { return "osgVector3"; } | |
80 | }; | ||
81 | template <> | ||
82 | struct property_type<osgVector4> { | ||
83 | ✗ | static inline std::string to_string() { return "osgVector4"; } | |
84 | }; | ||
85 | template <> | ||
86 | struct property_type<Configuration> { | ||
87 | ✗ | static inline std::string to_string() { return "Configuration"; } | |
88 | }; | ||
89 | |||
90 | template <typename T> | ||
91 | QWidget* buildEditor(Property* /*property*/) { | ||
92 | return NULL; | ||
93 | } | ||
94 | template <> | ||
95 | QWidget* buildEditor<bool>(Property* property); | ||
96 | template <> | ||
97 | QWidget* buildEditor<int>(Property* property); | ||
98 | template <> | ||
99 | QWidget* buildEditor<float>(Property* property); | ||
100 | template <> | ||
101 | QWidget* buildEditor<std::string>(Property* property); | ||
102 | template <> | ||
103 | QWidget* buildEditor<osgVector2>(Property* property); | ||
104 | template <> | ||
105 | QWidget* buildEditor<osgVector3>(Property* property); | ||
106 | template <> | ||
107 | QWidget* buildEditor<osgVector4>(Property* property); | ||
108 | template <> | ||
109 | QWidget* buildEditor<Configuration>(Property* property); | ||
110 | } // namespace details | ||
111 | /// \endcond | ||
112 | |||
113 | /// Abstract base class for runtime properties of Node. | ||
114 | class Property : public QObject { | ||
115 | Q_OBJECT | ||
116 | |||
117 | public slots: | ||
118 | bool set(void); | ||
119 | bool set(const bool& v); | ||
120 | bool set(const int& v); | ||
121 | bool set(const float& v); | ||
122 | bool set(const std::string& v); | ||
123 | bool set(const osgVector2& v); | ||
124 | bool set(const osgVector3& v); | ||
125 | bool set(const osgVector4& v); | ||
126 | bool set(const Configuration& v); | ||
127 | |||
128 | // Provide slots to convert from double to float. | ||
129 | bool set(const double& v); | ||
130 | |||
131 | // Provide slots to convert from QString to std::string. | ||
132 | bool set(const QString& v); | ||
133 | |||
134 | // Provide slots to convert from QColor to osgVector4. | ||
135 | bool set(const QColor& v); | ||
136 | |||
137 | public: | ||
138 | bool get(void); | ||
139 | bool get(bool& v); | ||
140 | bool get(int& v); | ||
141 | bool get(float& v); | ||
142 | bool get(std::string& v); | ||
143 | bool get(osgVector2& v); | ||
144 | bool get(osgVector3& v); | ||
145 | bool get(osgVector4& v); | ||
146 | bool get(Configuration& v); | ||
147 | |||
148 | // Provide slots to convert from double to float. | ||
149 | bool get(double& v); | ||
150 | // Provide slots to convert from QString to std::string. | ||
151 | bool get(QString& v); | ||
152 | // Provide slots to convert from QColor to osgVector4. | ||
153 | bool get(QColor& v); | ||
154 | |||
155 | signals: | ||
156 | void valueChanged(void); | ||
157 | void valueChanged(const bool& v); | ||
158 | void valueChanged(const int& v); | ||
159 | void valueChanged(const float& v); | ||
160 | void valueChanged(const std::string& v); | ||
161 | void valueChanged(const osgVector2& v); | ||
162 | void valueChanged(const osgVector3& v); | ||
163 | void valueChanged(const osgVector4& v); | ||
164 | void valueChanged(const Configuration& v); | ||
165 | |||
166 | // Provide slots to convert from double to float. | ||
167 | void valueChanged(const double& v); | ||
168 | // Provide slots to convert from QString to std::string | ||
169 | void valueChanged(const QString& v); | ||
170 | // Provide slots to convert from QColor to osgVector4 | ||
171 | void valueChanged(const QColor& v); | ||
172 | |||
173 | public: | ||
174 | virtual bool hasReadAccess() const = 0; | ||
175 | virtual bool hasWriteAccess() const = 0; | ||
176 | |||
177 | virtual std::string type() = 0; | ||
178 | |||
179 | 14 | const std::string& name() const { return name_; } | |
180 | |||
181 | /// \return NULL is this property is not editable, otherwise it returns | ||
182 | /// a valid new QWidget. | ||
183 | ✗ | virtual QWidget* guiEditor() { return NULL; } | |
184 | |||
185 | protected: | ||
186 | virtual bool impl_set(void); | ||
187 | virtual bool impl_set(const bool& v); | ||
188 | virtual bool impl_set(const int& v); | ||
189 | virtual bool impl_set(const float& v); | ||
190 | virtual bool impl_set(const std::string& v); | ||
191 | virtual bool impl_set(const osgVector2& v); | ||
192 | virtual bool impl_set(const osgVector3& v); | ||
193 | virtual bool impl_set(const osgVector4& v); | ||
194 | virtual bool impl_set(const Configuration& v); | ||
195 | |||
196 | virtual bool impl_get(void); | ||
197 | virtual bool impl_get(bool& v); | ||
198 | virtual bool impl_get(int& v); | ||
199 | virtual bool impl_get(float& v); | ||
200 | virtual bool impl_get(std::string& v); | ||
201 | virtual bool impl_get(osgVector2& v); | ||
202 | virtual bool impl_get(osgVector3& v); | ||
203 | virtual bool impl_get(osgVector4& v); | ||
204 | virtual bool impl_get(Configuration& v); | ||
205 | |||
206 | protected: | ||
207 | Property(const std::string& name); | ||
208 | |||
209 | 28 | virtual ~Property() {} | |
210 | |||
211 | const std::string name_; | ||
212 | |||
213 | ✗ | inline void invalidGet() const { | |
214 | ✗ | throw std::logic_error("Cannot read property " + name_ + "."); | |
215 | } | ||
216 | ✗ | inline void invalidSet() const { | |
217 | ✗ | throw std::logic_error("Cannot write property " + name_ + "."); | |
218 | } | ||
219 | }; | ||
220 | |||
221 | class VoidProperty : public Property { | ||
222 | public: | ||
223 | typedef boost::function<void(void)> Function_t; | ||
224 | typedef shared_ptr<VoidProperty> Ptr_t; | ||
225 | |||
226 | ✗ | static Ptr_t create(const std::string& name, const Function_t& f) { | |
227 | ✗ | return Ptr_t(new VoidProperty(name, f)); | |
228 | } | ||
229 | ✗ | virtual std::string type() { | |
230 | ✗ | return details::property_type<void>::to_string(); | |
231 | } | ||
232 | |||
233 | template <typename Obj, typename ReturnType> | ||
234 | ✗ | static inline Function_t memberFunction(Obj* obj, | |
235 | ReturnType (Obj::*mem_func)()) { | ||
236 | ✗ | return boost::bind(mem_func, obj); | |
237 | } | ||
238 | template <typename Obj, typename ReturnType> | ||
239 | static inline Function_t memberFunction(Obj* obj, | ||
240 | ReturnType (Obj::*mem_func)() const) { | ||
241 | return boost::bind(mem_func, obj); | ||
242 | } | ||
243 | |||
244 | ✗ | VoidProperty(const std::string& name, const Function_t& f) | |
245 | ✗ | : Property(name), function_(f) {} | |
246 | |||
247 | ✗ | virtual ~VoidProperty() {} | |
248 | |||
249 | ✗ | bool hasReadAccess() const { return (bool)function_; } | |
250 | ✗ | bool hasWriteAccess() const { return hasReadAccess(); } | |
251 | |||
252 | const Function_t& function() const { return function_; } | ||
253 | void function(const Function_t& f) { function_ = f; } | ||
254 | |||
255 | QWidget* guiEditor(); | ||
256 | |||
257 | protected: | ||
258 | ✗ | bool impl_get(void) { | |
259 | ✗ | if (!hasReadAccess()) { | |
260 | ✗ | invalidGet(); | |
261 | ✗ | return false; | |
262 | } | ||
263 | ✗ | function_(); | |
264 | ✗ | return true; | |
265 | } | ||
266 | ✗ | bool impl_set(void) { return get(); } | |
267 | |||
268 | private: | ||
269 | Function_t function_; | ||
270 | }; | ||
271 | |||
272 | template <typename T> | ||
273 | class PropertyTpl : public Property { | ||
274 | public: | ||
275 | typedef boost::function<void(const T&)> Setter_t; | ||
276 | typedef boost::function<T(void)> Getter_t; | ||
277 | typedef shared_ptr<PropertyTpl> Ptr_t; | ||
278 | |||
279 | 5 | static Ptr_t create(const std::string& name, const Getter_t& g, | |
280 | const Setter_t& s) { | ||
281 |
1/2✓ Branch 2 taken 5 times.
✗ Branch 3 not taken.
|
5 | return Ptr_t(new PropertyTpl(name, g, s)); |
282 | } | ||
283 | 1 | static Ptr_t create(const std::string& name, const Getter_t& g) { | |
284 |
3/6✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
2 | return Ptr_t(new PropertyTpl(name, g, Setter_t())); |
285 | } | ||
286 | 1 | static Ptr_t create(const std::string& name, const Setter_t& s) { | |
287 |
3/6✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 1 times.
✗ Branch 6 not taken.
✓ Branch 8 taken 1 times.
✗ Branch 9 not taken.
|
2 | return Ptr_t(new PropertyTpl(name, Getter_t(), s)); |
288 | } | ||
289 | |||
290 | ✗ | virtual std::string type() { return details::property_type<T>::to_string(); } | |
291 | |||
292 | template <typename Obj> | ||
293 | 1 | static inline Getter_t getterFromMemberFunction(Obj* obj, | |
294 | const T& (Obj::*mem_func)() | ||
295 | const) { | ||
296 | 1 | return boost::bind(mem_func, obj); | |
297 | } | ||
298 | template <typename Obj> | ||
299 | 2 | static inline Getter_t getterFromMemberFunction(Obj* obj, | |
300 | T (Obj::*mem_func)() const) { | ||
301 | 2 | return boost::bind(mem_func, obj); | |
302 | } | ||
303 | template <typename Obj> | ||
304 | 2 | static inline Setter_t setterFromMemberFunction( | |
305 | Obj* obj, void (Obj::*mem_func)(const T&)) { | ||
306 | 2 | return boost::bind(mem_func, obj, _1); | |
307 | } | ||
308 | template <typename Obj> | ||
309 | ✗ | static inline Setter_t setterFromMemberFunction(Obj* obj, | |
310 | void (Obj::*mem_func)(T)) { | ||
311 | ✗ | return boost::bind(mem_func, obj, _1); | |
312 | } | ||
313 | |||
314 | template <typename Obj, typename RetType> | ||
315 | ✗ | static Ptr_t create(const std::string& name, Obj* obj, | |
316 | RetType (Obj::*mem_get)() const, | ||
317 | void (Obj::*mem_set)(const T&)) { | ||
318 | ✗ | return create(name, Getter_t(boost::bind(mem_get, obj)), | |
319 | ✗ | Setter_t(boost::bind(mem_set, obj, _1))); | |
320 | } | ||
321 | template <typename Obj, typename RetType> | ||
322 | 2 | static Ptr_t create(const std::string& name, Obj* obj, | |
323 | RetType (Obj::*mem_get)() const, | ||
324 | void (Obj::*mem_set)(T)) { | ||
325 |
2/4✓ Branch 1 taken 2 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 2 times.
✗ Branch 5 not taken.
|
4 | return create(name, Getter_t(boost::bind(mem_get, obj)), |
326 |
1/2✓ Branch 3 taken 2 times.
✗ Branch 4 not taken.
|
6 | Setter_t(boost::bind(mem_set, obj, _1))); |
327 | } | ||
328 | template <typename Obj, typename RetType> | ||
329 | 1 | static Ptr_t createRO(const std::string& name, Obj* obj, | |
330 | RetType (Obj::*mem_get)() const) { | ||
331 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | return create(name, Getter_t(boost::bind(mem_get, obj))); |
332 | } | ||
333 | template <typename Obj> | ||
334 | 1 | static Ptr_t createWO(const std::string& name, Obj* obj, | |
335 | void (Obj::*mem_set)(const T&)) { | ||
336 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
2 | return create(name, Setter_t(boost::bind(mem_set, obj, _1))); |
337 | } | ||
338 | template <typename Obj, typename RetType> | ||
339 | static Ptr_t createWO(const std::string& name, Obj* obj, | ||
340 | void (Obj::*mem_set)(T)) { | ||
341 | return create(name, Setter_t(boost::bind(mem_set, obj, _1))); | ||
342 | } | ||
343 | |||
344 | 23 | PropertyTpl(const std::string& name, const Getter_t& g, const Setter_t& s) | |
345 |
2/4✓ Branch 2 taken 12 times.
✗ Branch 3 not taken.
✓ Branch 5 taken 12 times.
✗ Branch 6 not taken.
|
23 | : Property(name), getter_(g), setter_(s) {} |
346 | |||
347 | 38 | virtual ~PropertyTpl() {} | |
348 | |||
349 | ✗ | bool hasReadAccess() const { return (bool)getter_; } | |
350 | ✗ | bool hasWriteAccess() const { return (bool)setter_; } | |
351 | |||
352 | const Getter_t& getter() const { return getter_; } | ||
353 | void getter(const Getter_t& g) { getter_ = g; } | ||
354 | |||
355 | const Setter_t& setter() const { return setter_; } | ||
356 | ✗ | void setter(const Setter_t& s) { setter_ = s; } | |
357 | |||
358 | ✗ | virtual QWidget* guiEditor() { return details::buildEditor<T>(this); } | |
359 | |||
360 | protected: | ||
361 | ✗ | virtual bool impl_set(const T& value) { | |
362 | ✗ | if (!hasWriteAccess()) { | |
363 | ✗ | invalidSet(); | |
364 | ✗ | return false; | |
365 | } | ||
366 | ✗ | setter_(value); | |
367 | ✗ | return true; | |
368 | } | ||
369 | ✗ | virtual bool impl_get(T& value) { | |
370 | ✗ | if (!hasReadAccess()) { | |
371 | ✗ | invalidGet(); | |
372 | ✗ | return false; | |
373 | } | ||
374 | ✗ | value = getter_(); | |
375 | ✗ | return true; | |
376 | } | ||
377 | |||
378 | private: | ||
379 | Getter_t getter_; | ||
380 | Setter_t setter_; | ||
381 | }; | ||
382 | |||
383 | template <typename Scalar> | ||
384 | struct Range { | ||
385 | Scalar min, max, step; | ||
386 | bool adaptiveDecimal; | ||
387 | |||
388 | 2 | Range() | |
389 | : | ||
390 | #if __cplusplus >= 201103L | ||
391 | 2 | min(std::numeric_limits<Scalar>::lowest()), | |
392 | #else | ||
393 | min(std::numeric_limits<Scalar>::quiet_NaN()), | ||
394 | #endif | ||
395 | 2 | max(std::numeric_limits<Scalar>::max()), | |
396 | 2 | step(static_cast<Scalar>(1)), | |
397 | 2 | adaptiveDecimal(false) { | |
398 | 2 | } | |
399 | |||
400 | #if __cplusplus >= 201103L | ||
401 | ✗ | inline bool hasMin() const { | |
402 | ✗ | return min > std::numeric_limits<Scalar>::lowest(); | |
403 | } | ||
404 | #else | ||
405 | inline bool hasMin() const { return min == min; } | ||
406 | #endif | ||
407 | ✗ | inline bool hasMax() const { | |
408 | ✗ | return max < std::numeric_limits<Scalar>::max(); | |
409 | } | ||
410 | inline bool hasRange() const { return hasMin() && hasMax(); } | ||
411 | |||
412 | void setRange(const Scalar& minimum, const Scalar& maximum) { | ||
413 | min = minimum; | ||
414 | max = maximum; | ||
415 | } | ||
416 | 1 | void setRange(const Scalar& minimum, const Scalar& maximum, | |
417 | const Scalar& _step) { | ||
418 | 1 | min = minimum; | |
419 | 1 | max = maximum; | |
420 | 1 | step = _step; | |
421 | 1 | } | |
422 | }; | ||
423 | |||
424 | template <typename T, typename RangeT> | ||
425 | class RangedPropertyTpl : public PropertyTpl<T>, public Range<RangeT> { | ||
426 | public: | ||
427 | typedef boost::function<void(const T&)> Setter_t; | ||
428 | typedef boost::function<T(void)> Getter_t; | ||
429 | typedef shared_ptr<RangedPropertyTpl> Ptr_t; | ||
430 | |||
431 | 1 | static Ptr_t create(const std::string& name, const Getter_t& g, | |
432 | const Setter_t& s) { | ||
433 |
1/2✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
|
1 | return Ptr_t(new RangedPropertyTpl(name, g, s)); |
434 | } | ||
435 | static Ptr_t create(const std::string& name, const Getter_t& g) { | ||
436 | return Ptr_t(new RangedPropertyTpl(name, g, Setter_t())); | ||
437 | } | ||
438 | static Ptr_t create(const std::string& name, const Setter_t& s) { | ||
439 | return Ptr_t(new RangedPropertyTpl(name, Getter_t(), s)); | ||
440 | } | ||
441 | |||
442 | template <typename Obj, typename RetType> | ||
443 | 1 | static Ptr_t create(const std::string& name, Obj* obj, | |
444 | RetType (Obj::*mem_get)() const, | ||
445 | void (Obj::*mem_set)(const T&)) { | ||
446 |
2/4✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 4 taken 1 times.
✗ Branch 5 not taken.
|
2 | return create(name, Getter_t(boost::bind(mem_get, obj)), |
447 |
1/2✓ Branch 3 taken 1 times.
✗ Branch 4 not taken.
|
3 | Setter_t(boost::bind(mem_set, obj, _1))); |
448 | } | ||
449 | template <typename Obj, typename RetType> | ||
450 | static Ptr_t create(const std::string& name, Obj* obj, | ||
451 | RetType (Obj::*mem_get)() const, | ||
452 | void (Obj::*mem_set)(T)) { | ||
453 | return create(name, Getter_t(boost::bind(mem_get, obj)), | ||
454 | Setter_t(boost::bind(mem_set, obj, _1))); | ||
455 | } | ||
456 | template <typename Obj, typename RetType> | ||
457 | static Ptr_t createRO(const std::string& name, Obj* obj, | ||
458 | RetType (Obj::*mem_get)() const) { | ||
459 | return create(name, Getter_t(boost::bind(mem_get, obj))); | ||
460 | } | ||
461 | template <typename Obj> | ||
462 | static Ptr_t createWO(const std::string& name, Obj* obj, | ||
463 | void (Obj::*mem_set)(const T&)) { | ||
464 | return create(name, Setter_t(boost::bind(mem_set, obj, _1))); | ||
465 | } | ||
466 | template <typename Obj, typename RetType> | ||
467 | static Ptr_t createWO(const std::string& name, Obj* obj, | ||
468 | void (Obj::*mem_set)(T)) { | ||
469 | return create(name, Setter_t(boost::bind(mem_set, obj, _1))); | ||
470 | } | ||
471 | |||
472 | 1 | RangedPropertyTpl(const std::string& name, const Getter_t& g, | |
473 | const Setter_t& s) | ||
474 | 1 | : PropertyTpl<T>(name, g, s) {} | |
475 | |||
476 | 4 | virtual ~RangedPropertyTpl() {} | |
477 | }; | ||
478 | |||
479 | template <typename T> | ||
480 | class StoredPropertyTpl : public Property { | ||
481 | public: | ||
482 | typedef boost::function<void()> Callback_t; | ||
483 | typedef shared_ptr<StoredPropertyTpl> Ptr_t; | ||
484 | |||
485 | static Ptr_t create(const std::string& name) { | ||
486 | return Ptr_t(new StoredPropertyTpl(name)); | ||
487 | } | ||
488 | |||
489 | ✗ | virtual std::string type() { return details::property_type<T>::to_string(); } | |
490 | |||
491 | 4 | StoredPropertyTpl(const std::string& name) : Property(name) {} | |
492 | |||
493 | 4 | virtual ~StoredPropertyTpl() {} | |
494 | |||
495 | 8 | bool hasReadAccess() const { return true; } | |
496 | ✗ | bool hasWriteAccess() const { return true; } | |
497 | |||
498 | ✗ | virtual QWidget* guiEditor() { return details::buildEditor<T>(this); } | |
499 | |||
500 | 1 | const Callback_t& callback() const { return callback_; } | |
501 | 4 | void callback(const Callback_t& s) { callback_ = s; } | |
502 | |||
503 | T value; | ||
504 | |||
505 | protected: | ||
506 | 6 | bool impl_set(const T& v) { | |
507 |
2/5✓ Branch 1 taken 3 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✓ Branch 4 taken 3 times.
✗ Branch 5 not taken.
|
6 | bool c(callback_ && value != v); |
508 | 6 | value = v; | |
509 |
1/2✓ Branch 0 taken 3 times.
✗ Branch 1 not taken.
|
6 | if (c) callback_(); |
510 | 6 | return true; | |
511 | } | ||
512 | 4 | bool impl_get(T& v) { | |
513 | 8 | v = value; | |
514 | 8 | return true; | |
515 | } | ||
516 | |||
517 | Callback_t callback_; | ||
518 | }; | ||
519 | |||
520 | template <typename T, typename RangeT> | ||
521 | class RangedStoredPropertyTpl : public StoredPropertyTpl<T>, | ||
522 | public Range<RangeT> { | ||
523 | public: | ||
524 | typedef shared_ptr<RangedStoredPropertyTpl> Ptr_t; | ||
525 | |||
526 | static Ptr_t create(const std::string& name) { | ||
527 | return Ptr_t(new RangedStoredPropertyTpl(name)); | ||
528 | } | ||
529 | |||
530 | 1 | RangedStoredPropertyTpl(const std::string& name) | |
531 | 1 | : StoredPropertyTpl<T>(name) {} | |
532 | |||
533 | 2 | virtual ~RangedStoredPropertyTpl() {} | |
534 | }; | ||
535 | |||
536 | typedef PropertyTpl<bool> BoolProperty; | ||
537 | typedef PropertyTpl<int> IntProperty; | ||
538 | typedef PropertyTpl<float> FloatProperty; | ||
539 | typedef PropertyTpl<std::string> StringProperty; | ||
540 | typedef PropertyTpl<osgVector2> Vector2Property; | ||
541 | typedef PropertyTpl<osgVector3> Vector3Property; | ||
542 | typedef PropertyTpl<osgVector4> Vector4Property; | ||
543 | typedef PropertyTpl<Configuration> ConfigurationProperty; | ||
544 | |||
545 | typedef RangedPropertyTpl<int> RangedIntProperty; | ||
546 | typedef RangedPropertyTpl<float> RangedFloatProperty; | ||
547 | typedef RangedPropertyTpl<osgVector2, float> RangedVector2Property; | ||
548 | typedef RangedPropertyTpl<osgVector3, float> RangedVector3Property; | ||
549 | typedef RangedPropertyTpl<osgVector4, float> RangedVector4Property; | ||
550 | typedef RangedPropertyTpl<Configuration, float> RangedConfigurationProperty; | ||
551 | |||
552 | /// Conversion between integer and enum name at runtime. | ||
553 | struct MetaEnum { | ||
554 | std::string type; | ||
555 | std::vector<std::string> names; | ||
556 | std::vector<int> values; | ||
557 | |||
558 | int from_string(const std::string& s); | ||
559 | std::string to_string(const int& v); | ||
560 | }; | ||
561 | |||
562 | MetaEnum* visibilityModeEnum(); | ||
563 | MetaEnum* wireFrameModeEnum(); | ||
564 | MetaEnum* lightingModeEnum(); | ||
565 | MetaEnum* glImmediateModeEnum(); | ||
566 | |||
567 | class EnumProperty : public IntProperty { | ||
568 | public: | ||
569 | using IntProperty::Getter_t; | ||
570 | using IntProperty::Setter_t; | ||
571 | typedef shared_ptr<EnumProperty> Ptr_t; | ||
572 | |||
573 | 4 | static Ptr_t create(const std::string& name, const MetaEnum* type, | |
574 | const Getter_t& g, const Setter_t& s) { | ||
575 |
1/2✓ Branch 2 taken 4 times.
✗ Branch 3 not taken.
|
4 | return Ptr_t(new EnumProperty(name, type, g, s)); |
576 | } | ||
577 | ✗ | virtual std::string type() { return "enum"; } | |
578 | ✗ | const MetaEnum* metaEnum() const { return metaEnum_; } | |
579 | |||
580 | 4 | EnumProperty(const std::string& name, const MetaEnum* type, const Getter_t& g, | |
581 | const Setter_t& s) | ||
582 | 4 | : IntProperty(name, g, s), metaEnum_(type) {} | |
583 | |||
584 | virtual QWidget* guiEditor(); | ||
585 | |||
586 | protected: | ||
587 | /// Set the enum property. | ||
588 | /// It also checks that \c value is a valid enum. | ||
589 | bool impl_set(const int& value); | ||
590 | |||
591 | /// Set the enum property from a string. | ||
592 | /// It also checks that \c value is a valid enum. | ||
593 | bool impl_set(const std::string& value); | ||
594 | |||
595 | /// Get the enum property as an integer | ||
596 | bool impl_get(int& v); | ||
597 | |||
598 | /// Get the enum property as a string | ||
599 | bool impl_get(std::string& v); | ||
600 | |||
601 | private: | ||
602 | const MetaEnum* metaEnum_; | ||
603 | }; | ||
604 | |||
605 | class Properties { | ||
606 | public: | ||
607 | struct Wrapper { | ||
608 | Property* p; | ||
609 | PropertyPtr_t lock; | ||
610 | 4 | Wrapper(Property* p) : p(p) {} | |
611 | 25 | Wrapper(PropertyPtr_t p) : p(p.get()), lock(p) {} | |
612 | ✗ | Property* operator->() const { return p; } | |
613 | }; | ||
614 | typedef std::map<std::string, Wrapper> PropertyMap_t; | ||
615 | |||
616 | protected: | ||
617 | PropertyMap_t properties_; | ||
618 | |||
619 | /// Called when a property is modified. | ||
620 | virtual void setDirty(bool dirty = true) = 0; | ||
621 | |||
622 | public: | ||
623 | /// Access a property | ||
624 | /// \note do not use this to set the property value as it won't set | ||
625 | /// the current node as dirty. | ||
626 | Property* property(const std::string& name) const; | ||
627 | |||
628 | ✗ | bool callVoidProperty(const std::string& name) const { | |
629 | ✗ | return property(name)->get(); | |
630 | } | ||
631 | |||
632 | template <typename T> | ||
633 | ✗ | bool getProperty(const std::string& name, T& value) const { | |
634 | ✗ | return property(name)->get(value); | |
635 | } | ||
636 | |||
637 | /// Set a property and set this object as dirty. | ||
638 | template <typename T> | ||
639 | ✗ | bool setProperty(const std::string& name, const T& value) { | |
640 | ✗ | bool res = property(name)->set(value); | |
641 | ✗ | if (res) this->setDirty(); | |
642 | ✗ | return res; | |
643 | } | ||
644 | |||
645 | bool hasProperty(const std::string& name) const; | ||
646 | |||
647 | ✗ | const PropertyMap_t& properties() const { return properties_; } | |
648 | |||
649 | /// Add a property and take ownership. | ||
650 | void addProperty(const PropertyPtr_t& prop); | ||
651 | |||
652 | /// Add a property and take ownership. | ||
653 | void addProperty(const std::string& name, const PropertyPtr_t& prop); | ||
654 | |||
655 | /// Add a property and leave ownership. | ||
656 | void addProperty(Property* prop); | ||
657 | |||
658 | /// Add a property and leave ownership. | ||
659 | void addProperty(const std::string& name, Property* prop); | ||
660 | |||
661 | QWidget* guiEditor(); | ||
662 | }; | ||
663 | |||
664 | } /* namespace viewer */ | ||
665 | } /* namespace gepetto */ | ||
666 | |||
667 | #endif /* GEPETTO_VIEWER_NODE_PROPERTY_HH */ | ||
668 |