#pragma once #ifndef REAL_BUILD # include "externals.hh" #endif /*= Utilities ================================================================*/ // Disable next ImGui button(s) void disableButton( ); // Re-enable ImGui buttons inline void reenableButtons( ) { ImGui::PopStyleColor( 3 ); } /*----------------------------------------------------------------------------*/ #define GL_CHECK( FAIL ) \ do { \ auto err_( glGetError( ) ); \ if ( err_ != GL_NO_ERROR ) FAIL; \ } while ( 0 ) #define GL_ASSERT( ) \ GL_CHECK({ \ fprintf( stderr , "GL error %x in %s:%d\n" , \ err_ , __FILE__ , __LINE__ ); \ abort( ); \ }) /*----------------------------------------------------------------------------*/ // Add some value to an angle, keeping it in [-180;180] void updateAngle( float& initial , const float delta ); // Make a rotation matrix from three YPR angles (in degrees) void anglesToMatrix( float const* angles , float* matrix ); /*----------------------------------------------------------------------------*/ // Helpers for finding entries in collections template< typename T , typename I > inline auto find( T const& collection , I const& item ) { return std::find( collection.begin( ) , collection.end( ) , item ); } template< typename T , typename I > inline auto find( T& collection , I const& item ) { return std::find( collection.begin( ) , collection.end( ) , item ); } template< typename T , typename I > inline bool Contains( T const& collection , I const& item ) { return std::find( collection.begin( ) , collection.end( ) , item ) != collection.end( ); } /*----------------------------------------------------------------------------*/ // Get the absolute path std::string GetAbsolutePath( std::string const& path ); // Get the absolute parent path for a (possibly relative) path std::string GetParentPath( std::string const& path ); /*= JSON utilities ===========================================================*/ using T_JSONObject = picojson::value::object; using T_JSONArray = picojson::value::array; // Convert a vector to a JSON array picojson::value jsonVector( float const* vector , const int nComponents ); // Convert a GLM vec3 to a JSON array inline picojson::value jsonVector( glm::vec3 const& vector ) { return jsonVector( &vector.x , 3 ); } // Add an entry to a JSON object template< typename T > inline void jsonAdd( T_JSONObject& object , std::string const& key , T const& v ) { using T_Entry = std::pair< std::string , picojson::value >; object.insert( T_Entry( key , picojson::value( v ) ) ); } extern template void jsonAdd< double >( T_JSONObject& object , std::string const& key , double const& v ); extern template void jsonAdd< T_JSONObject >( T_JSONObject& object , std::string const& key , T_JSONObject const& v ); extern template void jsonAdd< T_JSONArray >( T_JSONObject& object , std::string const& key , T_JSONArray const& v ); extern template void jsonAdd< std::string >( T_JSONObject& object , std::string const& key , std::string const& v ); template< > void jsonAdd< picojson::value >( T_JSONObject& object , std::string const& key , picojson::value const& v ); template< > void jsonAdd< int >( T_JSONObject& object , std::string const& key , int const& v ); template< > void jsonAdd< unsigned >( T_JSONObject& object , std::string const& key , unsigned const& v ); /*----------------------------------------------------------------------------*/ // JSON read type error class X_JsonGetFailed : public std::exception { }; // Get a JSON object field; throws X_JsonGetFailed if the type is incorrect or // if the field is missing. template< typename T > inline T const& jsonGet( T_JSONObject const& object , char const* const key ) { const std::string k( key ); if ( object.find( k ) == object.end( ) ) { throw X_JsonGetFailed( ); } picojson::value const& v( object.at( k ) ); if ( !v.is< T >( ) ) { throw X_JsonGetFailed( ); } return v.get< T >( ); } // Get a pointer to a JSON object field, or nullptr if the field doesn't exist. // Throws X_JsonGetFailed if the type is incorrect. template< typename T > inline T const* jsonGetOpt( T_JSONObject const& object , char const* const key ) { const std::string k( key ); if ( object.find( k ) == object.end( ) ) { return nullptr; } picojson::value const& v( object.at( k ) ); if ( !v.is< T >( ) ) { throw X_JsonGetFailed( ); } return &v.get< T >( ); } // Read a value from a JSON object, if the value actually exists. Fails with // X_JsonGetFailed if the type is wrong template< typename T > inline bool jsonSetFromOpt( T& out , T_JSONObject const& object , char const* const key ) { T const* ptr( jsonGetOpt< T >( object , key ) ); if ( ptr ) { out = *ptr; } return ptr; } // Integer specialization of the above template< > inline bool jsonSetFromOpt< int >( int& out , T_JSONObject const& object , char const* const key ) { double const* ptr( jsonGetOpt< double >( object , key ) ); if ( ptr ) { out = int( *ptr ); } return ptr; } // Unsigned integer specialization of the above template< > inline bool jsonSetFromOpt< unsigned >( unsigned& out , T_JSONObject const& object , char const* const key ) { double const* ptr( jsonGetOpt< double >( object , key ) ); if ( ptr ) { out = unsigned( *ptr ); } return ptr; } // 32-bit float specialization of the above template< > inline bool jsonSetFromOpt< float >( float& out , T_JSONObject const& object , char const* const key ) { double const* ptr( jsonGetOpt< double >( object , key ) ); if ( ptr ) { out = float( *ptr ); } return ptr; } // Read a vector from a JSON array of numbers void jsonGetVectorOpt( float* vector , const size_t size , T_JSONObject const& object , char const* key ); // Read a GLM vec3 from a JSON array of numbers inline void jsonGetVectorOpt( glm::vec3& vector , T_JSONObject const& object , char const* key ) { jsonGetVectorOpt( &vector.x , 3 , object , key ); } // Try to load some object using its "bool load( jsonobject )" method. template< typename T > inline bool jsonLoadOpt( T& out , T_JSONObject const& object , char const* key ) { try { auto const* sub( jsonGetOpt< T_JSONObject >( object , key ) ); if ( sub ) { return out.load( *sub ); } return true; } catch ( X_JsonGetFailed const& ) { return false; } }