Radium Engine  1.5.0
Attribs.hpp
1 #pragma once
2 #include <map>
3 
4 #include <Core/Containers/VectorArray.hpp>
5 #include <Core/RaCore.hpp>
6 #include <Core/Utils/ContainerIntrospectionInterface.hpp>
7 #include <Core/Utils/Index.hpp>
8 #include <Core/Utils/Observable.hpp>
9 
10 namespace Ra {
11 namespace Core {
12 
13 namespace Geometry {
14 // need forward declarations for friend classes outside of Utils namespace
15 class TopologicalMesh;
16 } // namespace Geometry
17 
18 namespace Utils {
19 
20 template <typename T>
21 class Attrib;
22 
26 class RA_CORE_API AttribBase : public ObservableVoid, public ContainerIntrospectionInterface
27 {
28  public:
29  inline explicit AttribBase( const std::string& name );
30  virtual ~AttribBase();
31  AttribBase( const AttribBase& ) = delete;
32  AttribBase& operator=( const AttribBase& ) = delete;
33 
35  inline std::string getName() const;
36 
38  inline void setName( const std::string& name );
39 
41  virtual void resize( size_t s ) = 0;
42 
44  bool inline operator==( const AttribBase& rhs );
45 
47  template <typename T>
48  inline Attrib<T>& cast();
49 
51  template <typename T>
52  inline const Attrib<T>& cast() const;
53 
55  virtual bool isFloat() const = 0;
56 
58  virtual bool isVector2() const = 0;
59 
61  virtual bool isVector3() const = 0;
62 
64  virtual bool isVector4() const = 0;
65 
69  bool inline isLocked() const;
70 
72  void inline unlock();
73 
74  virtual std::unique_ptr<AttribBase> clone() = 0;
75 
76  protected:
77  void inline lock( bool isLocked = true );
78 
79  private:
81  std::string m_name;
82 
84  bool m_isLocked { false };
85 };
86 
90 template <typename T>
91 class Attrib : public AttribBase
92 {
93  public:
94  using value_type = T;
95  using Container = VectorArray<T>;
96 
97  explicit Attrib( const std::string& name );
98  virtual ~Attrib();
99 
101  void resize( size_t s ) override;
102 
105  inline Container& getDataWithLock();
106 
109  size_t getSize() const override;
110  size_t getNumberOfComponents() const override;
111  int getStride() const override;
112  size_t getBufferSize() const override;
113  const void* dataPtr() const override;
115 
118  void setData( const Container& data );
119  void setData( Container&& data );
121 
123  inline const Container& data() const;
124  bool isFloat() const override;
125  bool isVector2() const override;
126  bool isVector3() const override;
127  bool isVector4() const override;
128 
130  template <typename U>
131  bool isType();
132 
133  std::unique_ptr<AttribBase> clone() override {
134  auto ptr = std::make_unique<Attrib<T>>( getName() );
135  ptr->m_data = m_data;
136  return ptr;
137  }
138 
139  private:
140  Container m_data;
141 };
142 
144 template <typename T>
146 {
147  public:
148  using value_type = T;
149  using AttribType = Attrib<T>;
150  using Container = typename Attrib<T>::Container;
153  template <typename U>
154  bool operator==( const AttribHandle<U>& lhs ) const {
155  return std::is_same<T, U>::value && m_idx == lhs.idx();
156  }
157 
159  Index idx() const { return m_idx; }
160 
163  std::string attribName() const { return m_name; }
164 
165  private:
166  Index m_idx = Index::Invalid();
167  std::string m_name = "";
168 
169  friend class AttribManager;
170 };
171 
203 class RA_CORE_API AttribManager : public Observable<const std::string&>
204 {
205  public:
206  using value_type = AttribBase;
207  using pointer_type = value_type*;
208  using smart_pointer_type = std::unique_ptr<value_type>;
209  using Container = std::vector<smart_pointer_type>;
210 
211  inline AttribManager();
212 
214  AttribManager( const AttribManager& m ) = delete;
215  AttribManager& operator=( const AttribManager& m ) = delete;
216 
217  inline AttribManager( AttribManager&& m );
218 
219  inline AttribManager& operator=( AttribManager&& m );
220  ~AttribManager() override;
221 
223  inline void copyAttributes( const AttribManager& m );
224 
228  template <class T, class... Handle>
229  void copyAttributes( const AttribManager& m, const AttribHandle<T>& attr, Handle... attribs );
230 
234  void copyAllAttributes( const AttribManager& m );
235 
237  void clear();
238 
240  template <typename T>
241  bool isValid( const AttribHandle<T>& h ) const;
242 
249  inline bool contains( const std::string& name ) const;
250 
258  template <typename T>
259  inline AttribHandle<T> findAttrib( const std::string& name ) const;
260 
267  template <typename T>
268  typename Attrib<T>::Container& getDataWithLock( const AttribHandle<T>& h );
269 
276  template <typename T>
277  const typename Attrib<T>::Container& getData( const AttribHandle<T>& h );
278 
285  template <typename T>
286  void unlock( const AttribHandle<T>& h );
287 
294  template <typename T>
295  inline Attrib<T>& getAttrib( const AttribHandle<T>& h );
296  template <typename T>
297  inline const Attrib<T>& getAttrib( const AttribHandle<T>& h ) const;
298  template <typename T>
299  inline Attrib<T>* getAttribPtr( const AttribHandle<T>& h );
300  template <typename T>
301  inline const Attrib<T>* getAttribPtr( const AttribHandle<T>& h ) const;
303 
309  template <typename T>
310  inline Attrib<T>& getAttrib( const std::string& name );
311  template <typename T>
312  inline const Attrib<T>& getAttrib( const std::string& name ) const;
314 
319  inline AttribBase* getAttribBase( const std::string& name );
320  inline const AttribBase* getAttribBase( const std::string& name ) const;
321  inline AttribBase* getAttribBase( const Index& idx );
322  inline const AttribBase* getAttribBase( const Index& idx ) const;
324 
328  template <typename T>
329  inline void setAttrib( const AttribHandle<T>& h,
330  const typename AttribHandle<T>::Container& data );
331 
333  template <typename T>
334  inline void setAttrib( const AttribHandle<T>& h, typename AttribHandle<T>::Container&& data );
336 
342  template <typename T>
343  AttribHandle<T> addAttrib( const std::string& name );
344 
350  template <typename T>
351  void removeAttrib( AttribHandle<T>& h );
355  bool hasSameAttribs( const AttribManager& other );
356 
359  // This is needed by the user to avoid caring about removed attributes (nullptr)
360  // \todo reimplement as range for
361  template <typename F>
362  void for_each_attrib( const F& func ) const;
363 
364  // \todo keep non const version private
365  template <typename F>
366  void for_each_attrib( const F& func );
368 
370  inline int getNumAttribs() const;
371 
404  {
405  public:
411  a->for_each_attrib( [this]( const auto& attr ) {
412  return ( v.push_back( std::make_pair( attr, attr->isLocked() ) ) );
413  } );
414  }
420  for ( auto& p : v ) {
421  if ( !p.second && p.first->isLocked() ) { p.first->unlock(); }
422  }
423  }
424 
425  private:
426  std::vector<std::pair<AttribBase*, bool>> v;
427  };
428 
431 
432  private:
434  Container m_attribs;
435 
438  std::map<std::string, Index> m_attribsIndex;
439 
440  // Ease wrapper
441  friend class ::Ra::Core::Geometry::TopologicalMesh;
442 
444  int m_numAttribs { 0 };
445 };
446 
447 AttribBase::AttribBase( const std::string& name ) : m_name { name } {}
448 
449 std::string AttribBase::getName() const {
450  return m_name;
451 }
452 
453 void AttribBase::setName( const std::string& name ) {
454  m_name = name;
455 }
456 
457 bool inline AttribBase::operator==( const AttribBase& rhs ) {
458  return m_name == rhs.getName();
459 }
460 
461 template <typename T>
463  return static_cast<Attrib<T>&>( *this );
464 }
465 
466 template <typename T>
467 const Attrib<T>& AttribBase::cast() const {
468  return static_cast<const Attrib<T>&>( *this );
469 }
470 
471 bool AttribBase::isLocked() const {
472  return m_isLocked;
473 }
474 
476  lock( false );
477 }
478 
479 void AttribBase::lock( bool isLocked ) {
480  CORE_ASSERT( isLocked != m_isLocked, "double (un)lock" );
481  m_isLocked = isLocked;
482  if ( !m_isLocked ) notify();
483 }
484 
486 
487 template <typename T>
488 Attrib<T>::Attrib( const std::string& name ) : AttribBase( name ) {}
489 
490 template <typename T>
491 
493  m_data.clear();
494 }
495 template <typename T>
496 void Attrib<T>::resize( size_t s ) {
497  m_data.resize( s );
498 }
499 template <typename T>
501  lock();
502  return m_data;
503 }
504 
505 template <typename T>
506 const void* Attrib<T>::dataPtr() const {
507  return m_data.dataPtr();
508 }
509 
510 template <typename T>
511 void Attrib<T>::setData( const Container& data ) {
512  CORE_ASSERT( !isLocked(), "try to set onto locked data" );
513  m_data = data;
514  notify();
515 }
516 
517 template <typename T>
518 void Attrib<T>::setData( Container&& data ) {
519  CORE_ASSERT( !isLocked(), "try to set onto locked data" );
520  m_data = std::move( data );
521  notify();
522 }
523 
524 template <typename T>
525 const typename Attrib<T>::Container& Attrib<T>::data() const {
526  return m_data;
527 }
528 
529 template <typename T>
530 size_t Attrib<T>::getSize() const {
531  return m_data.getSize();
532 }
533 
534 template <typename T>
535 int Attrib<T>::getStride() const {
536  return m_data.getStride();
537 }
538 
539 template <typename T>
540 size_t Attrib<T>::getBufferSize() const {
541  return m_data.getBufferSize();
542 }
543 
544 template <typename T>
545 bool Attrib<T>::isFloat() const {
546  return std::is_same<Scalar, T>::value;
547 }
548 
549 template <typename T>
550 bool Attrib<T>::isVector2() const {
551  return std::is_same<Eigen::Matrix<Scalar, 2, 1>, T>::value;
552 }
553 
554 template <typename T>
555 bool Attrib<T>::isVector3() const {
556  return std::is_same<Eigen::Matrix<Scalar, 3, 1>, T>::value;
557 }
558 
559 template <typename T>
560 bool Attrib<T>::isVector4() const {
561  return std::is_same<Eigen::Matrix<Scalar, 4, 1>, T>::value;
562 }
563 
564 template <typename T>
565 template <typename U>
567  return std::is_same<U, T>::value;
568 }
569 
570 // Defer computation to VectorArrayTypeHelper
571 template <typename T>
573  return m_data.getNumberOfComponents();
574 }
575 
577 
578 AttribManager::AttribManager() {}
579 
580 AttribManager::AttribManager( AttribManager&& m ) :
581  m_attribs( std::move( m.m_attribs ) ),
582  m_attribsIndex( std::move( m.m_attribsIndex ) ),
583  m_numAttribs( std::move( m.m_numAttribs ) ) {}
584 
585 AttribManager& AttribManager::operator=( AttribManager&& m ) {
586  m_attribs = std::move( m.m_attribs );
587  m_attribsIndex = std::move( m.m_attribsIndex );
588  m_numAttribs = std::move( m.m_numAttribs );
589  return *this;
590 }
591 
593  m_numAttribs = m.m_numAttribs;
594 }
595 
596 template <class T, class... Handle>
598  const AttribHandle<T>& attr,
599  Handle... attribs ) {
600  if ( m.isValid( attr ) ) {
601  // get attrib to copy
602  auto& a = m.getAttrib( attr );
603  // add new attrib
604  auto h = addAttrib<T>( a.getName() );
605  // copy attrib data
606  getAttrib( h ).setData( a.data() );
607  }
608  // deal with other attribs
609  copyAttributes( m, attribs... );
610 }
611 
612 template <typename T>
613 bool AttribManager::isValid( const AttribHandle<T>& h ) const {
614  auto itr = m_attribsIndex.find( h.attribName() );
615  return h.m_idx != Index::Invalid() && itr != m_attribsIndex.end() && itr->second == h.m_idx;
616 }
617 
618 inline bool AttribManager::contains( const std::string& name ) const {
619  return m_attribsIndex.find( name ) != m_attribsIndex.end();
620 }
621 
622 template <typename T>
623 inline AttribHandle<T> AttribManager::findAttrib( const std::string& name ) const {
624  auto c = m_attribsIndex.find( name );
625  AttribHandle<T> handle;
626  if ( c != m_attribsIndex.end() ) {
627  handle.m_idx = c->second;
628  handle.m_name = c->first;
629  }
630  return handle;
631 }
632 
633 template <typename T>
635  return static_cast<Attrib<T>*>( m_attribs.at( h.m_idx ).get() )->getDataWithLock();
636 }
637 
638 template <typename T>
640  return static_cast<Attrib<T>*>( m_attribs.at( h.m_idx ).get() )->data();
641 }
642 
643 template <typename T>
645  static_cast<Attrib<T>*>( m_attribs.at( h.m_idx ).get() )->unlock();
646 }
647 
648 template <typename T>
650  return *static_cast<Attrib<T>*>( m_attribs.at( h.m_idx ).get() );
651 }
652 
653 template <typename T>
654 inline const Attrib<T>& AttribManager::getAttrib( const AttribHandle<T>& h ) const {
655  return *static_cast<Attrib<T>*>( m_attribs.at( h.m_idx ).get() );
656 }
657 template <typename T>
658 inline Attrib<T>& AttribManager::getAttrib( const std::string& name ) {
659  return getAttrib( findAttrib<T>( name ) );
660 }
661 
662 template <typename T>
663 inline const Attrib<T>& AttribManager::getAttrib( const std::string& name ) const {
664  return getAttrib( findAttrib<T>( name ) );
665 }
666 
667 template <typename T>
668 inline Attrib<T>* AttribManager::getAttribPtr( const AttribHandle<T>& h ) {
669  return static_cast<Attrib<T>*>( m_attribs.at( h.m_idx ).get() );
670 }
671 
672 template <typename T>
673 inline const Attrib<T>* AttribManager::getAttribPtr( const AttribHandle<T>& h ) const {
674  return static_cast<Attrib<T>*>( m_attribs.at( h.m_idx ).get() );
675 }
676 
677 template <typename T>
679  const typename AttribHandle<T>::Container& data ) {
680  static_cast<Attrib<T>*>( m_attribs.at( h.m_idx ).get() )->setData( data );
681 }
682 
683 template <typename T>
685  typename AttribHandle<T>::Container&& data ) {
686  static_cast<Attrib<T>*>( m_attribs.at( h.m_idx ).get() )->setData( data );
687 }
688 
689 inline AttribBase* AttribManager::getAttribBase( const std::string& name ) {
690  auto c = m_attribsIndex.find( name );
691  if ( c != m_attribsIndex.end() ) return m_attribs[c->second].get();
692  return nullptr;
693 }
694 
695 inline const AttribBase* AttribManager::getAttribBase( const std::string& name ) const {
696  auto c = m_attribsIndex.find( name );
697  if ( c != m_attribsIndex.end() ) return m_attribs[c->second].get();
698  return nullptr;
699 }
700 
701 inline AttribBase* AttribManager::getAttribBase( const Index& idx ) {
702  if ( idx.isValid() ) return m_attribs[idx].get();
703  return nullptr;
704 }
705 
706 inline const AttribBase* AttribManager::getAttribBase( const Index& idx ) const {
707  if ( idx.isValid() ) return m_attribs[idx].get();
708  return nullptr;
709 }
710 
711 template <typename T>
712 AttribHandle<T> AttribManager::addAttrib( const std::string& name ) {
713  // does the attrib already exist?
714  AttribHandle<T> h = findAttrib<T>( name );
715  if ( isValid( h ) ) return h;
716 
717  // create the attrib
718  smart_pointer_type attrib = std::make_unique<Attrib<T>>( name );
719 
720  // look for a free slot
721  auto it = std::find_if(
722  m_attribs.begin(), m_attribs.end(), []( const auto& attr ) { return !attr; } );
723  if ( it != m_attribs.end() ) {
724  it->swap( attrib );
725  h.m_idx = std::distance( m_attribs.begin(), it );
726  }
727  else {
728  m_attribs.push_back( std::move( attrib ) );
729  h.m_idx = m_attribs.size() - 1;
730  }
731  m_attribsIndex[name] = h.m_idx;
732  h.m_name = name;
733  ++m_numAttribs;
734 
735  notify( name );
736  return h;
737 }
738 
739 template <typename T>
741  auto c = m_attribsIndex.find( h.m_name );
742  if ( c != m_attribsIndex.end() ) {
743  Index idx = c->second;
744  m_attribs[idx].reset( nullptr );
745  m_attribsIndex.erase( c );
746  }
747  h.m_idx = Index::Invalid(); // invalidate whatever!
748  auto name = h.m_name;
749  h.m_name = ""; // invalidate whatever!
750  --m_numAttribs;
751  notify( name );
752 }
753 
754 template <typename F>
755 void AttribManager::for_each_attrib( const F& func ) const {
756  for ( const auto& attr : m_attribs )
757  if ( attr != nullptr ) func( attr.get() );
758 }
759 
760 template <typename F>
761 void AttribManager::for_each_attrib( const F& func ) {
762  for ( auto& attr : m_attribs )
763  if ( attr != nullptr ) func( attr.get() );
764 }
765 
767  return m_numAttribs;
768 }
769 
770 } // namespace Utils
771 } // namespace Core
772 } // namespace Ra
virtual bool isFloat() const =0
Return true if the attribute content is of Scalar type, false otherwise.
virtual bool isVector3() const =0
Return true if the attribute content is of Vector3 type, false otherwise.
virtual bool isVector4() const =0
Return true if the attribute content is of Vector4 type, false otherwise.
virtual bool isVector2() const =0
Return true if the attribute content is of Vector2 type, false otherwise.
virtual void resize(size_t s)=0
Resize the attribute's array.
void unlock()
Unlock data so another one can gain write access.
Definition: Attribs.hpp:475
Attrib< T > & cast()
Downcast from AttribBase to Attrib<T>.
Definition: Attribs.hpp:462
bool operator==(const AttribBase &rhs)
Return true if *this and rhs have the same name.
Definition: Attribs.hpp:457
std::string getName() const
Return the attribute's name.
Definition: Attribs.hpp:449
void setName(const std::string &name)
Set the attribute's name.
Definition: Attribs.hpp:453
An attrib handle basically store an Index and a name.
Definition: Attribs.hpp:146
std::string attribName() const
Definition: Attribs.hpp:163
bool operator==(const AttribHandle< U > &lhs) const
Definition: Attribs.hpp:154
Index idx() const
return the index of the attrib.
Definition: Attribs.hpp:159
Scope lock state management for attributes.
Definition: Attribs.hpp:404
ScopedLockState(AttribManager *a)
Constructor, save lock state of all attribs from attribManager.
Definition: Attribs.hpp:410
~ScopedLockState()
Destructor, unlock all attribs whose have been locked after the initialization of the Unlocker.
Definition: Attribs.hpp:419
The AttribManager provides attributes management by handles.
Definition: Attribs.hpp:204
void setAttrib(const AttribHandle< T > &h, const typename AttribHandle< T >::Container &data)
Definition: Attribs.hpp:678
AttribBase * getAttribBase(const std::string &name)
Definition: Attribs.hpp:689
int getNumAttribs() const
Return the number of attributes.
Definition: Attribs.hpp:766
ScopedLockState getScopedLockState()
Returns a scope unlocker for managed attribs.
Definition: Attribs.hpp:430
AttribManager(const AttribManager &m)=delete
Copy constructor and assignment operator are forbidden.
Attrib< T >::Container & getDataWithLock(const AttribHandle< T > &h)
Get the locked data container from the attrib handle.
Definition: Attribs.hpp:634
void unlock(const AttribHandle< T > &h)
Unlock the handle data.
Definition: Attribs.hpp:644
AttribHandle< T > addAttrib(const std::string &name)
Definition: Attribs.hpp:712
void copyAttributes(const AttribManager &m)
Base copy, does nothing.
Definition: Attribs.hpp:592
bool contains(const std::string &name) const
contains Check if an attribute with the given name exists.
Definition: Attribs.hpp:618
Attrib< T > & getAttrib(const AttribHandle< T > &h)
Definition: Attribs.hpp:649
bool isValid(const AttribHandle< T > &h) const
Return true if h correspond to an existing attribute in *this.
Definition: Attribs.hpp:613
void removeAttrib(AttribHandle< T > &h)
Definition: Attribs.hpp:740
void for_each_attrib(const F &func) const
Definition: Attribs.hpp:755
const Attrib< T >::Container & getData(const AttribHandle< T > &h)
Get read access to the data container from the attrib handle.
Definition: Attribs.hpp:639
AttribHandle< T > findAttrib(const std::string &name) const
findAttrib Grab an attribute handler by name.
Definition: Attribs.hpp:623
size_t getSize() const override
Definition: Attribs.hpp:530
void setData(const Container &data)
Definition: Attribs.hpp:511
size_t getNumberOfComponents() const override
Definition: Attribs.hpp:572
bool isType()
check if attrib is a given type, as in attr.isType<MyMatrix>()
Definition: Attribs.hpp:566
bool isVector4() const override
Return true if the attribute content is of Vector4 type, false otherwise.
Definition: Attribs.hpp:560
const void * dataPtr() const override
Definition: Attribs.hpp:506
Container & getDataWithLock()
Definition: Attribs.hpp:500
const Container & data() const
Read-only acccess to the attribute content.
Definition: Attribs.hpp:525
bool isVector2() const override
Return true if the attribute content is of Vector2 type, false otherwise.
Definition: Attribs.hpp:550
bool isVector3() const override
Return true if the attribute content is of Vector3 type, false otherwise.
Definition: Attribs.hpp:555
size_t getBufferSize() const override
Definition: Attribs.hpp:540
int getStride() const override
Definition: Attribs.hpp:535
void resize(size_t s) override
Resize the container (value_type must have a default ctor).
Definition: Attribs.hpp:496
bool isFloat() const override
Return true if the attribute content is of Scalar type, false otherwise.
Definition: Attribs.hpp:545
This class defines the introspection interface a container need to implement.
void notify(Args... p) const
Notify (i.e. call) each attached observer with argument p.
Definition: Observable.hpp:67
Definition: Cage.cpp:3