// Copyright (C) 2012-2015 ChaosForge Ltd // http://chaosforge.org/ // // This file is part of Nova libraries. // For conditions of distribution and use, see copying.txt file in root folder. #ifndef NV_INTERFACE_DATA_CHANNEL_HH #define NV_INTERFACE_DATA_CHANNEL_HH #include #include #include namespace nv { struct raw_data_channel { raw_data_channel( raw_data_channel&& other ) { m_data = other.m_data; m_size = other.m_size; m_desc = other.m_desc; other.m_data = nullptr; other.m_size = 0; } raw_data_channel& operator=( raw_data_channel&& other ) { if ( this != &other ) { if ( m_data != nullptr ) delete[] m_data; m_data = other.m_data; m_size = other.m_size; m_desc = other.m_desc; other.m_data = nullptr; other.m_size = 0; } return *this; } const data_descriptor& descriptor() const { return m_desc; } uint32 element_size() const { return m_desc.element_size(); } uint32 size() const { return m_size; } uint32 raw_size() const { return m_size * m_desc.element_size(); } const uint8* raw_data() const { return m_data; } // TODO: constexpr compile-time cast check? template < typename Struct > const Struct* data_cast() const { return reinterpret_cast( m_data ); } bool has_slot( slot vslot ) const { return m_desc.has_slot( vslot ); } ~raw_data_channel() { if ( m_data != nullptr ) delete[] m_data; } protected: template < typename Struct > friend class data_channel_access; friend class raw_data_channel_access; friend class data_channel_creator; friend class data_channel_set; raw_data_channel() : m_data( nullptr ), m_size( 0 ) {} raw_data_channel( const raw_data_channel& ) = delete; raw_data_channel& operator=( const raw_data_channel& ) = delete; uint8* m_data; uint32 m_size; data_descriptor m_desc; }; class data_channel_set { public: friend class data_channel_set_creator; friend class raw_data_channel_access; typedef const raw_data_channel* const_iterator; data_channel_set( data_channel_set&& other ) { for ( uint32 c = 0; c < other.m_size; ++c ) m_channels[c] = move( other.m_channels[c] ); m_size = other.m_size; other.m_size = 0; } data_channel_set& operator=( data_channel_set&& other ) { if ( this != &other ) { for ( uint32 c = 0; c < other.m_size; ++c ) m_channels[c] = move( other.m_channels[c] ); m_size = other.m_size; other.m_size = 0; } return *this; } size_t size() const { return m_size; } const raw_data_channel* get_channel( size_t index ) const { if ( m_size > index ) return &m_channels[index]; return nullptr; } const raw_data_channel* get_channel( slot s ) const { for ( uint32 c = 0; c < m_size; ++c ) if ( m_channels[c].has_slot( s ) ) return &m_channels[c]; return nullptr; } template < typename Struct > const raw_data_channel* get_channel() const { data_descriptor compare; compare.initialize(); for ( uint32 c = 0; c < m_size; ++c ) { if ( m_channels[c].descriptor() == compare ) { return &m_channels[c]; } } return nullptr; } size_t get_channel_size( slot s ) const { const raw_data_channel* channel = get_channel( s ); return channel ? channel->size() : 0; } size_t get_channel_size( size_t channel ) const { if ( m_size > channel ) return m_channels[channel].size(); return 0; } template < typename Struct > size_t get_channel_size() const { data_descriptor compare; compare.initialize(); for ( uint32 c = 0; c < m_size; ++c ) { if ( m_channels[c].descriptor() == compare ) { return m_channels[c].size(); } } return 0; } template < typename VTX > const VTX* get_channel_data() const { data_descriptor compare; compare.initialize(); for ( uint32 c = 0; c < m_size; ++c ) { if ( m_channels[c].descriptor() == compare ) { return m_channels[c].data_cast( ); } } return nullptr; } int get_channel_index( slot s ) const { for ( uint32 c = 0; c < m_size; ++c ) if ( m_channels[c].has_slot( s ) ) return int( c ); return -1; } data_descriptor get_interpolation_key() const { data_descriptor result; for ( uint32 c = 0; c < m_size; ++c ) { for ( const auto& cslot : m_channels[c].descriptor() ) if ( cslot.vslot != slot::TIME ) result.push_slot( cslot.etype, cslot.vslot ); } return result; } const_iterator begin() const { return &m_channels[0]; } const_iterator end() const { return &m_channels[ m_size ]; } protected: data_channel_set() { m_size = 0; } raw_data_channel m_channels[4]; uint32 m_size; }; } #endif // NV_INTERFACE_DATA_CHANNEL_HH