GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/gepetto/viewer/node-property.h Lines: 62 134 46.3 %
Date: 2024-04-14 11:13:22 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
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

1
    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

1
    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
    return create(name, Getter_t(boost::bind(mem_get, obj)),
326

2
                  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
    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
    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

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
        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
    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
    return create(name, Getter_t(boost::bind(mem_get, obj)),
447

1
                  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

6
    bool c(callback_ && value != v);
508
6
    value = v;
509
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
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 */