GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: include/gepetto/viewer/node-property.h Lines: 49 102 48.0 %
Date: 2020-05-14 11:23:33 Branches: 32 156 20.5 %

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 <map>
21
#include <iostream>
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 <QObject>
30
31
#include <gepetto/viewer/fwd.h>
32
#include <gepetto/viewer/config-osg.h>
33
34
class QWidget;
35
36
namespace gepetto {
37
namespace viewer {
38
39
    class Property;
40
    template <typename T> class PropertyTpl;
41
    template <typename T, typename RangeT = T> class RangedPropertyTpl;
42
43
    /// \cond
44
    namespace details {
45
      template <typename T> struct property_type {};
46
      template <typename T> struct property_type <const T > : property_type<T> {};
47
      template <typename T> struct property_type <     T& > : property_type<T> {};
48
      template <> struct property_type<void         > { static inline std::string to_string () { return "void"         ; } };
49
      template <> struct property_type<bool         > { static inline std::string to_string () { return "bool"         ; } };
50
      template <> struct property_type<int          > { static inline std::string to_string () { return "int"          ; } };
51
      template <> struct property_type<float        > { static inline std::string to_string () { return "float"        ; } };
52
      template <> struct property_type<std::string  > { static inline std::string to_string () { return "string"       ; } };
53
      template <> struct property_type<osgVector2   > { static inline std::string to_string () { return "osgVector2"   ; } };
54
      template <> struct property_type<osgVector3   > { static inline std::string to_string () { return "osgVector3"   ; } };
55
      template <> struct property_type<osgVector4   > { static inline std::string to_string () { return "osgVector4"   ; } };
56
      template <> struct property_type<Configuration> { static inline std::string to_string () { return "Configuration"; } };
57
58
      template <typename T> QWidget* buildEditor (Property* property) { return NULL; }
59
      template <> QWidget* buildEditor<bool         > (Property* property);
60
      template <> QWidget* buildEditor<int          > (Property* property);
61
      template <> QWidget* buildEditor<float        > (Property* property);
62
      template <> QWidget* buildEditor<std::string  > (Property* property);
63
      template <> QWidget* buildEditor<osgVector2   > (Property* property);
64
      template <> QWidget* buildEditor<osgVector3   > (Property* property);
65
      template <> QWidget* buildEditor<osgVector4   > (Property* property);
66
      template <> QWidget* buildEditor<Configuration> (Property* property);
67
    }
68
    /// \endcond
69
70
    /// Abstract base class for runtime properties of Node.
71
    class Property : public QObject {
72
      Q_OBJECT
73
74
      public slots:
75
        bool set(      void             );
76
        bool set(const bool          & v);
77
        bool set(const int           & v);
78
        bool set(const float         & v);
79
        bool set(const std::string   & v);
80
        bool set(const osgVector2    & v);
81
        bool set(const osgVector3    & v);
82
        bool set(const osgVector4    & v);
83
        bool set(const Configuration & v);
84
85
        // Provide slots to convert from double to float.
86
        bool set(const double& v);
87
88
        // Provide slots to convert from QString to std::string.
89
        bool set(const QString& v);
90
91
        // Provide slots to convert from QColor to osgVector4.
92
        bool set(const QColor& v);
93
94
      public:
95
        bool get(void             );
96
        bool get(bool          & v);
97
        bool get(int           & v);
98
        bool get(float         & v);
99
        bool get(std::string   & v);
100
        bool get(osgVector2    & v);
101
        bool get(osgVector3    & v);
102
        bool get(osgVector4    & v);
103
        bool get(Configuration & v);
104
105
        // Provide slots to convert from double to float.
106
        bool get(double      & v);
107
        // Provide slots to convert from QString to std::string.
108
        bool get(QString      & v);
109
        // Provide slots to convert from QColor to osgVector4.
110
        bool get(QColor      & v);
111
112
      signals:
113
        void valueChanged(      void             );
114
        void valueChanged(const bool          & v);
115
        void valueChanged(const int           & v);
116
        void valueChanged(const float         & v);
117
        void valueChanged(const std::string   & v);
118
        void valueChanged(const osgVector2    & v);
119
        void valueChanged(const osgVector3    & v);
120
        void valueChanged(const osgVector4    & v);
121
        void valueChanged(const Configuration & v);
122
123
        // Provide slots to convert from double to float.
124
        void valueChanged(const double& v);
125
        // Provide slots to convert from QString to std::string
126
        void valueChanged(const QString& v);
127
        // Provide slots to convert from QColor to osgVector4
128
        void valueChanged(const QColor& v);
129
130
      public:
131
        virtual bool hasReadAccess () const = 0;
132
        virtual bool hasWriteAccess() const = 0;
133
134
        virtual std::string type() = 0;
135
136
13
        const std::string& name () const { return name_; }
137
138
        /// \return NULL is this property is not editable, otherwise it returns
139
        ///         a valid new QWidget.
140
        virtual QWidget* guiEditor ()
141
        {
142
          return NULL;
143
        }
144
145
      protected:
146
        virtual bool impl_set(      void             );
147
        virtual bool impl_set(const bool          & v);
148
        virtual bool impl_set(const int           & v);
149
        virtual bool impl_set(const float         & v);
150
        virtual bool impl_set(const std::string   & v);
151
        virtual bool impl_set(const osgVector2    & v);
152
        virtual bool impl_set(const osgVector3    & v);
153
        virtual bool impl_set(const osgVector4    & v);
154
        virtual bool impl_set(const Configuration & v);
155
156
        virtual bool impl_get(void             );
157
        virtual bool impl_get(bool          & v);
158
        virtual bool impl_get(int           & v);
159
        virtual bool impl_get(float         & v);
160
        virtual bool impl_get(std::string   & v);
161
        virtual bool impl_get(osgVector2    & v);
162
        virtual bool impl_get(osgVector3    & v);
163
        virtual bool impl_get(osgVector4    & v);
164
        virtual bool impl_get(Configuration & v);
165
166
      protected:
167
        Property(const std::string& name);
168
169
13
        virtual ~Property() {}
170
171
        const std::string name_;
172
173
        inline void invalidGet() const { throw std::logic_error ("Cannot read property "  + name_ + "."); }
174
        inline void invalidSet() const { throw std::logic_error ("Cannot write property " + name_ + "."); }
175
    };
176
177
    class VoidProperty : public Property {
178
      public:
179
        typedef boost::function<void (void)> Function_t;
180
        typedef shared_ptr<VoidProperty> Ptr_t;
181
182
        static Ptr_t create (const std::string& name, const Function_t& f) { return Ptr_t(new VoidProperty(name, f)); }
183
        virtual std::string type() { return details::property_type<void>::to_string(); }
184
185
        template <typename Obj, typename ReturnType>
186
        static inline Function_t memberFunction(Obj* obj, ReturnType (Obj::*mem_func)()      ) { return boost::bind(mem_func, obj); }
187
        template <typename Obj, typename ReturnType>
188
        static inline Function_t memberFunction(Obj* obj, ReturnType (Obj::*mem_func)() const) { return boost::bind(mem_func, obj); }
189
190
        VoidProperty(const std::string& name, const Function_t& f)
191
          : Property(name), function_(f) {}
192
193
        virtual ~VoidProperty() {}
194
195
        bool hasReadAccess  () const { return (bool)function_; }
196
        bool hasWriteAccess () const { return hasReadAccess(); }
197
198
        const Function_t& function () const { return function_; }
199
        void function (const Function_t& f) { function_ = f; }
200
201
        QWidget* guiEditor ();
202
203
      protected:
204
        bool impl_get(void) { if (!hasReadAccess ()) { invalidGet(); return false; } function_(); return true; }
205
        bool impl_set(void) { return get(); }
206
207
      private:
208
        Function_t function_;
209
    };
210
211
    template <typename T>
212
    class PropertyTpl : public Property {
213
      public:
214
        typedef boost::function<void(const T&)> Setter_t;
215
        typedef boost::function<  T (void)> Getter_t;
216
        typedef shared_ptr<PropertyTpl> Ptr_t;
217
218

4
        static Ptr_t create (const std::string& name, const Getter_t& g, const Setter_t& s) { return Ptr_t(new PropertyTpl(name, g, s)); }
219

1
        static Ptr_t create (const std::string& name, const Getter_t& g) { return Ptr_t(new PropertyTpl(name, g, Setter_t())); }
220

1
        static Ptr_t create (const std::string& name, const Setter_t& s) { return Ptr_t(new PropertyTpl(name, Getter_t(), s)); }
221
222
        virtual std::string type() { return details::property_type<T>::to_string(); }
223
224
        template <typename Obj>
225
1
        static inline Getter_t getterFromMemberFunction(Obj* obj, const T& (Obj::*mem_func)() const) { return boost::bind(mem_func, obj); }
226
        template <typename Obj>
227
2
        static inline Getter_t getterFromMemberFunction(Obj* obj, T (Obj::*mem_func)() const) { return boost::bind(mem_func, obj); }
228
        template <typename Obj>
229
2
        static inline Setter_t setterFromMemberFunction(Obj* obj, void (Obj::*mem_func)(const T&)) { return boost::bind(mem_func, obj, _1); }
230
        template <typename Obj>
231
        static inline Setter_t setterFromMemberFunction(Obj* obj, void (Obj::*mem_func)(T)) { return boost::bind(mem_func, obj, _1); }
232
233
        template <typename Obj, typename RetType>
234
        static Ptr_t create (const std::string& name, Obj* obj,
235
            RetType (Obj::*mem_get)() const,
236
            void (Obj::*mem_set)(const T&))
237
        {
238
          return create (name, Getter_t(boost::bind(mem_get, obj)),
239
              Setter_t(boost::bind(mem_set, obj, _1)));
240
        }
241
        template <typename Obj, typename RetType>
242
1
        static Ptr_t create (const std::string& name, Obj* obj,
243
            RetType (Obj::*mem_get)() const,
244
            void (Obj::*mem_set)(T))
245
        {
246
          return create (name, Getter_t(boost::bind(mem_get, obj)),
247

1
              Setter_t(boost::bind(mem_set, obj, _1)));
248
        }
249
        template <typename Obj, typename RetType>
250
1
        static Ptr_t createRO (const std::string& name, Obj* obj,
251
            RetType (Obj::*mem_get)() const)
252
        {
253
1
          return create (name, Getter_t(boost::bind(mem_get, obj)));
254
        }
255
        template <typename Obj>
256
1
        static Ptr_t createWO (const std::string& name, Obj* obj,
257
            void (Obj::*mem_set)(const T&))
258
        {
259
1
          return create (name, Setter_t(boost::bind(mem_set, obj, _1)));
260
        }
261
        template <typename Obj, typename RetType>
262
        static Ptr_t createWO (const std::string& name, Obj* obj,
263
            void (Obj::*mem_set)(T))
264
        {
265
          return create (name, Setter_t(boost::bind(mem_set, obj, _1)));
266
        }
267
268
269
11
        PropertyTpl(const std::string& name, const Getter_t& g, const Setter_t& s)
270





11
          : Property(name), getter_(g), setter_(s) {}
271
272
17
        virtual ~PropertyTpl() {}
273
274
        bool hasReadAccess  () const { return (bool)getter_; }
275
        bool hasWriteAccess () const { return (bool)setter_; }
276
277
        const Getter_t& getter () const { return getter_; }
278
        void getter (const Getter_t& g) { getter_ = g; }
279
280
        const Setter_t& setter () const { return setter_; }
281
        void setter (const Setter_t& s) { setter_ = s; }
282
283
        virtual QWidget* guiEditor ()
284
        {
285
          return details::buildEditor<T>(this);
286
        }
287
288
      protected:
289
        virtual bool impl_set(const T& value) { if (!hasWriteAccess()) { invalidSet(); return false; } setter_(value)   ; return true; }
290
        virtual bool impl_get(      T& value) { if (!hasReadAccess ()) { invalidGet(); return false; } value = getter_(); return true; }
291
292
      private:
293
        Getter_t getter_;
294
        Setter_t setter_;
295
    };
296
297
    template<typename Scalar>
298
    struct Range {
299
      Scalar min, max, step;
300
      bool adaptiveDecimal;
301
302
2
      Range () :
303
#if __cplusplus >= 201103L
304
2
        min(std::numeric_limits<Scalar>::lowest()),
305
#else
306
        min(std::numeric_limits<Scalar>::quiet_NaN()),
307
#endif
308
2
        max(std::numeric_limits<Scalar>::max()),
309
        step (static_cast<Scalar>(1)),
310
4
        adaptiveDecimal (false)
311
2
      {}
312
313
#if __cplusplus >= 201103L
314
      inline bool hasMin () const { return min > std::numeric_limits<Scalar>::lowest(); }
315
#else
316
      inline bool hasMin () const { return min == min; }
317
#endif
318
      inline bool hasMax () const { return max < std::numeric_limits<Scalar>::max(); }
319
      inline bool hasRange() const { return hasMin() && hasMax(); }
320
321
      void setRange(const Scalar& minimum, const Scalar& maximum)
322
      { min = minimum; max = maximum; }
323
1
      void setRange(const Scalar& minimum, const Scalar& maximum, const Scalar& _step)
324
1
      { min = minimum; max = maximum; step = _step;}
325
    };
326
327
    template <typename T, typename RangeT>
328
    class RangedPropertyTpl : public PropertyTpl<T>, public Range<RangeT> {
329
      public:
330
        typedef boost::function<void(const T&)> Setter_t;
331
        typedef boost::function<  T (void)> Getter_t;
332
        typedef shared_ptr<RangedPropertyTpl> Ptr_t;
333
334
1
        static Ptr_t create (const std::string& name, const Getter_t& g, const Setter_t& s) { return Ptr_t(new RangedPropertyTpl(name, g, s)); }
335
        static Ptr_t create (const std::string& name, const Getter_t& g) { return Ptr_t(new RangedPropertyTpl(name, g, Setter_t())); }
336
        static Ptr_t create (const std::string& name, const Setter_t& s) { return Ptr_t(new RangedPropertyTpl(name, Getter_t(), s)); }
337
338
        template <typename Obj, typename RetType>
339
1
        static Ptr_t create (const std::string& name, Obj* obj,
340
            RetType (Obj::*mem_get)() const,
341
            void (Obj::*mem_set)(const T&))
342
        {
343
          return create (name, Getter_t(boost::bind(mem_get, obj)),
344

1
              Setter_t(boost::bind(mem_set, obj, _1)));
345
        }
346
        template <typename Obj, typename RetType>
347
        static Ptr_t create (const std::string& name, Obj* obj,
348
            RetType (Obj::*mem_get)() const,
349
            void (Obj::*mem_set)(T))
350
        {
351
          return create (name, Getter_t(boost::bind(mem_get, obj)),
352
              Setter_t(boost::bind(mem_set, obj, _1)));
353
        }
354
        template <typename Obj, typename RetType>
355
        static Ptr_t createRO (const std::string& name, Obj* obj,
356
            RetType (Obj::*mem_get)() const)
357
        {
358
          return create (name, Getter_t(boost::bind(mem_get, obj)));
359
        }
360
        template <typename Obj>
361
        static Ptr_t createWO (const std::string& name, Obj* obj,
362
            void (Obj::*mem_set)(const T&))
363
        {
364
          return create (name, Setter_t(boost::bind(mem_set, obj, _1)));
365
        }
366
        template <typename Obj, typename RetType>
367
        static Ptr_t createWO (const std::string& name, Obj* obj,
368
            void (Obj::*mem_set)(T))
369
        {
370
          return create (name, Setter_t(boost::bind(mem_set, obj, _1)));
371
        }
372
373
374
1
        RangedPropertyTpl(const std::string& name, const Getter_t& g, const Setter_t& s)
375
1
          : PropertyTpl<T>(name, g, s) {}
376
377
2
        virtual ~RangedPropertyTpl() {}
378
    };
379
380
    template <typename T>
381
    class StoredPropertyTpl : public Property {
382
      public:
383
        typedef boost::function<void()> Callback_t;
384
        typedef shared_ptr<StoredPropertyTpl> Ptr_t;
385
386
        static Ptr_t create (const std::string& name) { return Ptr_t(new StoredPropertyTpl(name)); }
387
388
        virtual std::string type() { return details::property_type<T>::to_string(); }
389
390

2
        StoredPropertyTpl(const std::string& name) : Property(name) {}
391
392
2
        virtual ~StoredPropertyTpl() {}
393
394
4
        bool hasReadAccess  () const { return true; }
395
        bool hasWriteAccess () const { return true; }
396
397
        virtual QWidget* guiEditor ()
398
        {
399
          return details::buildEditor<T>(this);
400
        }
401
402
1
        const Callback_t& callback () const { return callback_; }
403
2
        void callback (const Callback_t& s) { callback_ = s; }
404
405
        T value;
406
407
      protected:
408



3
        bool impl_set(const T& v) { bool c (callback_ && value != v); value = v; if (c) callback_(); return true; }
409
4
        bool impl_get(      T& v) { v = value; return true; }
410
411
        Callback_t callback_;
412
    };
413
414
    template <typename T, typename RangeT>
415
    class RangedStoredPropertyTpl : public StoredPropertyTpl<T>, public Range<RangeT> {
416
      public:
417
        typedef shared_ptr<RangedStoredPropertyTpl> Ptr_t;
418
419
        static Ptr_t create (const std::string& name) { return Ptr_t(new RangedStoredPropertyTpl(name)); }
420
421
1
        RangedStoredPropertyTpl(const std::string& name)
422
1
          : StoredPropertyTpl<T>(name) {}
423
424
1
        virtual ~RangedStoredPropertyTpl() {}
425
    };
426
427
    typedef PropertyTpl<bool         > BoolProperty;
428
    typedef PropertyTpl<int          > IntProperty;
429
    typedef PropertyTpl<float        > FloatProperty;
430
    typedef PropertyTpl<std::string  > StringProperty;
431
    typedef PropertyTpl<osgVector2   > Vector2Property;
432
    typedef PropertyTpl<osgVector3   > Vector3Property;
433
    typedef PropertyTpl<osgVector4   > Vector4Property;
434
    typedef PropertyTpl<Configuration> ConfigurationProperty;
435
436
    typedef RangedPropertyTpl<int          > RangedIntProperty;
437
    typedef RangedPropertyTpl<float        > RangedFloatProperty;
438
    typedef RangedPropertyTpl<osgVector2   , float> RangedVector2Property;
439
    typedef RangedPropertyTpl<osgVector3   , float> RangedVector3Property;
440
    typedef RangedPropertyTpl<osgVector4   , float> RangedVector4Property;
441
    typedef RangedPropertyTpl<Configuration, float> RangedConfigurationProperty;
442
443
    /// Conversion between integer and enum name at runtime.
444
8
    struct MetaEnum {
445
      std::string type;
446
      std::vector<std::string> names;
447
      std::vector<        int> values;
448
449
      int from_string (const std::string& s);
450
      std::string to_string (const int& v);
451
    };
452
453
    MetaEnum* visibilityModeEnum ();
454
    MetaEnum* wireFrameModeEnum  ();
455
    MetaEnum* lightingModeEnum  ();
456
    MetaEnum* glImmediateModeEnum  ();
457
458
8
    class EnumProperty : public IntProperty {
459
      public:
460
        using IntProperty::Getter_t;
461
        using IntProperty::Setter_t;
462
        typedef shared_ptr<EnumProperty> Ptr_t;
463
464
4
        static Ptr_t create (const std::string& name, const MetaEnum* type, const Getter_t& g, const Setter_t& s) { return Ptr_t(new EnumProperty(name, type, g, s)); }
465
        virtual std::string type() { return "enum"; }
466
        const MetaEnum* metaEnum () const { return metaEnum_; }
467
468
4
        EnumProperty(const std::string& name, const MetaEnum* type, const Getter_t& g, const Setter_t& s)
469
4
          : IntProperty(name, g, s), metaEnum_ (type) {}
470
471
        virtual QWidget* guiEditor ();
472
473
      protected:
474
        /// Set the enum property.
475
        /// It also checks that \c value is a valid enum.
476
        bool impl_set(const int& value);
477
478
        /// Set the enum property from a string.
479
        /// It also checks that \c value is a valid enum.
480
        bool impl_set(const std::string& value);
481
482
        /// Get the enum property as an integer
483
        bool impl_get(int   & v);
484
485
        /// Get the enum property as a string
486
        bool impl_get(std::string   & v);
487
488
      private:
489
        const MetaEnum* metaEnum_;
490
    };
491
492
2
    class Properties
493
    {
494
      public:
495
65
        struct Wrapper
496
        {
497
          Property* p;
498
          PropertyPtr_t lock;
499
2
          Wrapper (Property* p) : p(p) {}
500
11
          Wrapper (PropertyPtr_t p) : p(p.get()), lock(p) {}
501
          Property* operator->() const { return p; }
502
        };
503
        typedef std::map<std::string, Wrapper> PropertyMap_t;
504
505
      protected:
506
        PropertyMap_t properties_;
507
508
        /// Called when a property is modified.
509
        virtual void setDirty (bool dirty=true) = 0;
510
511
      public:
512
        /// Access a property
513
        /// \note do not use this to set the property value as it won't set
514
        /// the current node as dirty.
515
        Property* property(const std::string& name) const;
516
517
        bool callVoidProperty(const std::string& name) const
518
        {
519
          return property(name)->get();
520
        }
521
522
        template <typename T>
523
        bool getProperty(const std::string& name, T& value) const
524
        {
525
          return property(name)->get(value);
526
        }
527
528
        /// Set a property and set this object as dirty.
529
        template <typename T>
530
        bool setProperty(const std::string& name, const T& value)
531
        {
532
          bool res = property(name)->set(value);
533
          if (res) this->setDirty();
534
          return res;
535
        }
536
537
        bool hasProperty(const std::string& name) const;
538
539
        const PropertyMap_t& properties () const
540
        {
541
          return properties_;
542
        }
543
544
        /// Add a property and take ownership.
545
        void addProperty(const PropertyPtr_t& prop);
546
547
        /// Add a property and take ownership.
548
        void addProperty(const std::string& name, const PropertyPtr_t& prop);
549
550
        /// Add a property and leave ownership.
551
        void addProperty(Property* prop);
552
553
        /// Add a property and leave ownership.
554
        void addProperty(const std::string& name, Property* prop);
555
556
        QWidget* guiEditor ();
557
    };
558
559
} /* namespace viewer */
560
} /* namespace gepetto */
561
562
#endif /* GEPETTO_VIEWER_NODE_PROPERTY_HH */