#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( __rw__ float& initial , __rd__ const float delta ); // Make a rotation matrix from three YPR angles (in degrees) void anglesToMatrix( __rd__ float const* angles , __wr__ float* matrix ); /*----------------------------------------------------------------------------*/ // Helpers for finding entries in collections template< typename T , typename I > inline auto find( __rd__ T const& collection , __rd__ I const& item ) { return std::find( collection.begin( ) , collection.end( ) , item ); } template< typename T , typename I > inline auto find( __rw__ T& collection , __rd__ I const& item ) { return std::find( collection.begin( ) , collection.end( ) , item ); } /*= JSON utilities ===========================================================*/ // Convert a vector to a JSON array picojson::value jsonVector( __rd__ float const* vector , __rd__ const int nComponents ); // Convert a GLM vec3 to a JSON array inline picojson::value jsonVector( __rd__ glm::vec3 const& vector ) { return jsonVector( &vector.x , 3 ); } // Add an entry to a JSON object template< typename T > inline void jsonAdd( __rw__ picojson::value::object& object , __rd__ std::string const& key , __rd__ 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 >( __rw__ picojson::value::object& object , __rd__ std::string const& key , __rd__ double const& v ); extern template void jsonAdd< picojson::value::object >( __rw__ picojson::value::object& object , __rd__ std::string const& key , __rd__ picojson::value::object const& v ); extern template void jsonAdd< picojson::value::array >( __rw__ picojson::value::object& object , __rd__ std::string const& key , __rd__ picojson::value::array const& v ); extern template void jsonAdd< std::string >( __rw__ picojson::value::object& object , __rd__ std::string const& key , __rd__ std::string const& v ); template< > void jsonAdd< picojson::value >( __rw__ picojson::value::object& object , __rd__ std::string const& key , __rd__ picojson::value const& v ); template< > void jsonAdd< int >( __rw__ picojson::value::object& object , __rd__ std::string const& key , __rd__ int const& v ); template< > void jsonAdd< unsigned >( __rw__ picojson::value::object& object , __rd__ std::string const& key , __rd__ unsigned const& v ); /*----------------------------------------------------------------------------*/ // JSON read type error class X_JsonGetFailed : public std::exception { }; // 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( __rd__ picojson::value::object const& object , __rd__ 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( __wr__ T& out , __rd__ picojson::value::object const& object , __rd__ 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 >( __wr__ int& out , __rd__ picojson::value::object const& object , __rd__ 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 >( __wr__ unsigned& out , __rd__ picojson::value::object const& object , __rd__ 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 >( __wr__ float& out , __rd__ picojson::value::object const& object , __rd__ 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( __wr__ float* vector , __rd__ const size_t size , __rd__ picojson::value::object const& object , __rd__ char const* key ); // Read a GLM vec3 from a JSON array of numbers inline void jsonGetVectorOpt( __wr__ glm::vec3& vector , __rd__ picojson::value::object const& object , __rd__ 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( __rw__ T& out , __rd__ picojson::value::object const& object , __rd__ char const* key ) { using T_Obj = picojson::value::object; try { auto const* sub( jsonGetOpt< T_Obj >( object , key ) ); if ( sub ) { return out.load( *sub ); } return true; } catch ( X_JsonGetFailed const& ) { return false; } }