#include "externals.hh" #include "common.hh" #include "ui.hh" #include "ui-colorgrading.hh" #include "ui-overrides.hh" #include "ui-sync.hh" #include "ui-utilities.hh" #include namespace sov { namespace { char const* BuildLabel_( uint32_t& counter , T_StringBuilder& sb ) noexcept { sb.clear( ) << "##temp label " << counter << '\0'; counter ++; return sb.data( ); } } // namespace /*= FLOAT OVERRIDES ==========================================================*/ M_DECL_SOVUI( Float ) { using namespace ImGui; auto& ov{ dynamic_cast< T_Float& >( ovp ) }; float v[ 1 ] = { Common::Sync( ).inputs( )[ ov.inputPositions( )[ 0 ] ] }; char const* const label( BuildLabel_( counter , sb ) ); const bool changed( ov.slider( ) ? SliderFloat( label , v , ov.min( ) , ov.max( ) , ov.decimals( ) , ov.power( ) ) : DragFloat( label , v , ov.step( ) , ov.min( ) , ov.max( ) , ov.decimals( ) , ov.power( ) ) ); if ( changed ) { Common::Sync( ).inputs( )[ ov.inputPositions( )[ 0 ] ] = v[ 0 ]; } } M_DECL_SOVUI( Float2 ) { using namespace ImGui; auto& ov{ dynamic_cast< T_Float2& >( ovp ) }; auto& sinp( Common::Sync( ).inputs( ) ); auto const& ovip{ ov.inputPositions( ) }; float v[ 2 ]; for ( auto i = 0 ; i < 2 ; i ++ ) { v[ i ] = sinp[ ovip[ i ] ]; } char const* const label( BuildLabel_( counter , sb ) ); const bool changed( ov.slider( ) ? SliderFloat2( label , v , ov.min( ) , ov.max( ) , ov.decimals( ) , ov.power( ) ) : DragFloat2( label , v , ov.step( ) , ov.min( ) , ov.max( ) , ov.decimals( ) , ov.power( ) ) ); if ( changed ) { for ( auto i = 0 ; i < 2 ; i ++ ) { sinp[ ovip[ i ] ] = v[ i ]; } } } M_DECL_SOVUI( Float3 ) { using namespace ImGui; auto& ov{ dynamic_cast< T_Float3& >( ovp ) }; auto& sinp( Common::Sync( ).inputs( ) ); auto const& ovip{ ov.inputPositions( ) }; float v[ 3 ]; for ( auto i = 0 ; i < 3 ; i ++ ) { v[ i ] = sinp[ ovip[ i ] ]; } char const* const label( BuildLabel_( counter , sb ) ); const bool changed( ov.slider( ) ? SliderFloat3( label , v , ov.min( ) , ov.max( ) , ov.decimals( ) , ov.power( ) ) : DragFloat3( label , v , ov.step( ) , ov.min( ) , ov.max( ) , ov.decimals( ) , ov.power( ) ) ); if ( changed ) { for ( auto i = 0 ; i < 3 ; i ++ ) { sinp[ ovip[ i ] ] = v[ i ]; } } } M_DECL_SOVUI( Float4 ) { using namespace ImGui; auto& ov{ dynamic_cast< T_Float4& >( ovp ) }; auto& sinp( Common::Sync( ).inputs( ) ); auto const& ovip{ ov.inputPositions( ) }; float v[ 4 ]; for ( auto i = 0 ; i < 4 ; i ++ ) { v[ i ] = sinp[ ovip[ i ] ]; } char const* const label( BuildLabel_( counter , sb ) ); const bool changed( ov.slider( ) ? SliderFloat4( label , v , ov.min( ) , ov.max( ) , ov.decimals( ) , ov.power( ) ) : DragFloat4( label , v , ov.step( ) , ov.min( ) , ov.max( ) , ov.decimals( ) , ov.power( ) ) ); if ( changed ) { for ( auto i = 0 ; i < 4 ; i ++ ) { sinp[ ovip[ i ] ] = v[ i ]; } } } /*= INTEGER OVERRIDES ========================================================*/ M_DECL_SOVUI( Integer ) { using namespace ImGui; auto& ov{ dynamic_cast< T_Integer& >( ovp ) }; auto& sinp( Common::Sync( ).inputs( ) ); auto const& ovip{ ov.inputPositions( ) }; int32_t v[ 1 ] = { int32_t( sinp[ ovip[ 0 ] ] ) }; char const* const label( BuildLabel_( counter , sb ) ); const bool changed( ov.slider( ) ? SliderInt( label , v , ov.min( ) , ov.max( ) ) : DragInt( label , v , ov.step( ) , ov.min( ) , ov.max( ) ) ); if ( changed ) { sinp[ ovip[ 0 ] ] = v[ 0 ]; } } M_DECL_SOVUI( Integer2 ) { using namespace ImGui; auto& ov{ dynamic_cast< T_Integer2& >( ovp ) }; auto& sinp( Common::Sync( ).inputs( ) ); auto const& ovip{ ov.inputPositions( ) }; int32_t v[ 2 ]; for ( auto i = 0 ; i < 2 ; i ++ ) { v[ i ] = sinp[ ovip[ i ] ]; } char const* const label( BuildLabel_( counter , sb ) ); const bool changed( ov.slider( ) ? SliderInt2( label , v , ov.min( ) , ov.max( ) ) : DragInt2( label , v , ov.step( ) , ov.min( ) , ov.max( ) ) ); if ( changed ) { for ( auto i = 0 ; i < 2 ; i ++ ) { sinp[ ovip[ i ] ] = v[ i ]; } } } M_DECL_SOVUI( Integer3 ) { using namespace ImGui; auto& ov{ dynamic_cast< T_Integer3& >( ovp ) }; auto& sinp( Common::Sync( ).inputs( ) ); auto const& ovip{ ov.inputPositions( ) }; int32_t v[ 3 ]; for ( auto i = 0 ; i < 3 ; i ++ ) { v[ i ] = sinp[ ovip[ i ] ]; } char const* const label( BuildLabel_( counter , sb ) ); const bool changed( ov.slider( ) ? SliderInt3( label , v , ov.min( ) , ov.max( ) ) : DragInt3( label , v , ov.step( ) , ov.min( ) , ov.max( ) ) ); if ( changed ) { for ( auto i = 0 ; i < 3 ; i ++ ) { sinp[ ovip[ i ] ] = v[ i ]; } } } M_DECL_SOVUI( Integer4 ) { using namespace ImGui; auto& ov{ dynamic_cast< T_Integer4& >( ovp ) }; auto& sinp( Common::Sync( ).inputs( ) ); auto const& ovip{ ov.inputPositions( ) }; int32_t v[ 4 ]; for ( auto i = 0 ; i < 4 ; i ++ ) { v[ i ] = sinp[ ovip[ i ] ]; } char const* const label( BuildLabel_( counter , sb ) ); const bool changed( ov.slider( ) ? SliderInt4( label , v , ov.min( ) , ov.max( ) ) : DragInt4( label , v , ov.step( ) , ov.min( ) , ov.max( ) ) ); if ( changed ) { for ( auto i = 0 ; i < 4 ; i ++ ) { sinp[ ovip[ i ] ] = v[ i ]; } } } /*= COLOR GRADING OVERRIDES ==================================================*/ M_DECL_SOVUI( ColorGrading ) { using namespace ImGui; auto& ov{ dynamic_cast< T_ColorGrading& >( ovp ) }; auto& sinp{ Common::Sync( ).inputs( ) }; auto const& ovip{ ov.inputPositions( ) }; float v[ 3 ]; for ( auto i = 0 ; i < 3 ; i ++ ) { v[ i ] = sinp[ ovip[ i ] ]; } char const* const label{ BuildLabel_( counter , sb ) }; const bool changed{ ColorGradingControls( label , &v[ 0 ] , &v[ 1 ] , &v[ 2 ] , ov.base( ) , ov.unit( ) ) }; if ( changed ) { for ( auto i = 0 ; i < 3 ; i ++ ) { sinp[ ovip[ i ] ] = v[ i ]; } } } /*= CAMERA OVERRIDES =========================================================*/ namespace { glm::vec3 VectorFromInputs_( T_CamOverride::T_VectorConfig const& vc , T_AutoArray< uint32_t , 8 > const& ovip ) noexcept { auto& sinp( Common::Sync( ).inputs( ) ); return glm::vec3{ sinp[ ovip[ vc.x ] ] , sinp[ ovip[ vc.y ] ] , sinp[ ovip[ vc.z ] ] }; } void InputsFromVector_( T_CamOverride::T_VectorConfig const& vc , T_AutoArray< uint32_t , 8 > const& ovip , glm::vec3 const& v ) noexcept { auto& sinp( Common::Sync( ).inputs( ) ); sinp[ ovip[ vc.x ] ] = v.x; sinp[ ovip[ vc.y ] ] = v.y; sinp[ ovip[ vc.z ] ] = v.z; } /*------------------------------------------------------------------------------*/ struct T_MouseCam_ : public virtual A_MouseCtrl { T_CameraMouseControl camera; T_CamOverride& ov; T_MouseCam_( T_Camera& cam , T_CamOverride& ov ) noexcept : camera( cam ) , ov( ov ) { } void handleDragAndDrop( ImVec2 const& move , T_KbdMods modifiers , T_MouseButtons buttons ) noexcept override; void handleWheel( float wheel , T_KbdMods modifiers , T_MouseButtons buttons ) noexcept override; }; /*------------------------------------------------------------------------------*/ void T_MouseCam_::handleDragAndDrop( ImVec2 const& move , T_KbdMods modifiers , T_MouseButtons buttons ) noexcept { auto& sync( Common::Sync( ) ); if ( !ov.enabled( ) ) { UI::Sync( ).clearMouseDelegate( ); return; } camera.handleDragAndDrop( move , modifiers , buttons ); auto& sinp( sync.inputs( ) ); auto const& ovip{ ov.inputPositions( ) }; auto& cam{ camera.camera }; InputsFromVector_( ov.target( ) , ovip , cam.lookAt( ) ); if ( ov.mode( ) == T_CamOverride::CM_ANGLES ) { InputsFromVector_( ov.angles( ) , ovip , cam.angles( ) ); sinp[ ovip[ ov.distance( ) ] ] = cam.distance( ); } else { InputsFromVector_( ov.position( ) , ovip , cam.position( ) ); InputsFromVector_( ov.up( ) , ovip , cam.upVector( ) ); } } void T_MouseCam_::handleWheel( const float wheel , T_KbdMods modifiers , T_MouseButtons buttons ) noexcept { auto& sync( Common::Sync( ) ); if ( !ov.enabled( ) ) { UI::Sync( ).clearMouseDelegate( ); return; } camera.handleWheel( wheel , modifiers , buttons ); auto& sinp( sync.inputs( ) ); auto& cam{ camera.camera }; auto const& ovip{ ov.inputPositions( ) }; if ( modifiers & E_KbdMod::SHIFT ) { auto const& fc( ov.fovConfig( ) ); if ( fc.mode == T_CamOverride::FM_FOV ) { sinp[ ovip[ fc.inputIndex ] ] = cam.fieldOfView( ); } else { sinp[ ovip[ fc.inputIndex ] ] = cam.nearPlane( ); } } else { InputsFromVector_( ov.target( ) , ovip , cam.lookAt( ) ); if ( ov.mode( ) == T_CamOverride::CM_ANGLES ) { InputsFromVector_( ov.angles( ) , ovip , cam.angles( ) ); sinp[ ovip[ ov.distance( ) ] ] = cam.distance( ); } else { InputsFromVector_( ov.position( ) , ovip , cam.position( ) ); InputsFromVector_( ov.up( ) , ovip , cam.upVector( ) ); } } } } // namespace M_DECL_SOVUI( Camera ) { auto& ov{ dynamic_cast< T_CamOverride& >( ovp ) }; auto& sync{ Common::Sync( ) }; auto& sinp{ sync.inputs( ) }; auto& camera{ ov.camData( ) }; auto const& ovip{ ov.inputPositions( ) }; auto const& fc{ ov.fovConfig( ) }; if ( !ov.enabled( ) || !ov.prevEnabled( ) ) { // Set field of view / near plane if ( fc.mode == T_CamOverride::FM_FOV ) { camera.fieldOfView( sinp[ ovip[ fc.inputIndex ] ] ); } else { camera.nearPlane( sinp[ ovip[ fc.inputIndex ] ] ); } // Set camera parameters const glm::vec3 lookAt{ VectorFromInputs_( ov.target( ) , ovip ) }; if ( ov.mode( ) == T_CamOverride::CM_ANGLES ) { const glm::vec3 angles{ VectorFromInputs_( ov.angles( ) , ovip ) }; const float distance{ sinp[ ovip[ ov.distance( ) ] ] }; camera.camera( lookAt , angles , distance ); } else { const glm::vec3 position{ VectorFromInputs_( ov.position( ) , ovip ) }; const glm::vec3 up{ VectorFromInputs_( ov.up( ) , ovip ) }; camera.camera( lookAt , position , up ); } } ov.prevEnabled( ) = ov.enabled( ); // Draw UI char const* const name( BuildLabel_( counter , sb ) ); auto& sui{ UI::Sync( ) }; bool mouseHandler{ sui.isCurrentDelegate( ov.id( ) ) }; using namespace ImGui; PushItemWidth( 0 ); // Compensate for -1 PushID( GetCurrentWindow( )->GetID( name ) ); const bool handlerChanged{ Checkbox( "Mouse control" , &mouseHandler ) }; Separator( ); const auto changes{ CameraUI( camera ) }; PopID( ); PopItemWidth( ); if ( handlerChanged ) { if ( mouseHandler ) { sui.delegateMouse( ov.id( ) , NewOwned< T_MouseCam_ >( camera , ov ) ); } else { sui.clearMouseDelegate( ); } } // Update values if ( changes & E_CameraChange::FOV ) { if ( fc.mode == T_CamOverride::FM_FOV ) { sinp[ ovip[ fc.inputIndex ] ] = camera.fieldOfView( ); } else { sinp[ ovip[ fc.inputIndex ] ] = camera.nearPlane( ); } } if ( changes & E_CameraChange::MATRIX ) { InputsFromVector_( ov.target( ) , ovip , camera.lookAt( ) ); if ( ov.mode( ) == T_CamOverride::CM_ANGLES ) { InputsFromVector_( ov.angles( ) , ovip , camera.angles( ) ); sinp[ ovip[ ov.distance( ) ] ] = camera.distance( ); } else { InputsFromVector_( ov.position( ) , ovip , camera.position( ) ); InputsFromVector_( ov.up( ) , ovip , camera.upVector( ) ); } } } } // namespace sov