#include "externals.hh" #include "c-camera.hh" #include "c-utilities.hh" #include "ui-utilities.hh" #include void ImGui::PushDisabled( ) noexcept { PushItemFlag( ImGuiItemFlags_Disabled , true ); PushStyleVar( ImGuiStyleVar_Alpha , GetStyle( ).Alpha * .5f ); } void ImGui::PopDisabled( ) noexcept { PopItemFlag( ); PopStyleVar( ); } /*------------------------------------------------------------------------------*/ bool ImGui::MenuItemCheckbox( char const* name , bool* checked ) noexcept { bool rv{ MenuItem( name , "" , *checked , true ) }; if ( rv ) { *checked = !*checked; } return rv; } /*------------------------------------------------------------------------------*/ bool ImGui::ToolbarButton( char const* const string , ImVec2 const& size , char const* const tooltip , bool enabled ) noexcept { if ( !enabled ) { PushDisabled( ); } const bool rv{ Button( string , size ) }; if ( !enabled ) { PopDisabled( ); } else if ( tooltip && IsItemHovered( ) ) { BeginTooltip( ); Text( tooltip ); EndTooltip( ); } return rv; } void ImGui::ToolbarSeparator( ) noexcept { SameLine( ); VerticalSeparator( ); SameLine( ); } /*= T_CameraMouseControl =======================================================*/ void T_CameraMouseControl::handleDragAndDrop( ImVec2 const& move , T_KeyboardModifiers modifiers , T_MouseButtons buttons ) noexcept { if ( move.x == 0 || move.y == 0 ) { return; } const float fdx( move.x * .1f * ( ( modifiers & E_KeyboardModifier::CTRL ) ? 1.f : .1f ) ); const float fdy( move.y * .1f * ( ( modifiers & E_KeyboardModifier::CTRL ) ? 1.f : .1f ) ); if ( ( buttons & E_MouseButton::LEFT ) && ( modifiers & E_KeyboardModifier::SHIFT ) ) { // Left mouse button, shift - move camera const auto side( normalize( cross( camera.upVector( ) , camera.direction( ) ) ) ); camera.lookAt( ) += .1f * ( side * fdx + camera.upVector( ) * fdy ); } else if ( buttons & E_MouseButton::LEFT ) { // Left mouse button, no shift - change yaw/pitch updateAngle( camera.angles( ).y , fdx ); updateAngle( camera.angles( ).x , fdy ); } else if ( buttons & E_MouseButton::RIGHT ) { // Right mouse button - change roll updateAngle( camera.angles( ).z , fdx ); } camera.cvtAnglesToVectors( ); } void T_CameraMouseControl::handleWheel( const float wheel , T_KeyboardModifiers modifiers , T_MouseButtons /* buttons */ ) noexcept { const float delta( wheel * ( ( modifiers & E_KeyboardModifier::CTRL ) ? 1.f : .1f) ); if ( modifiers & E_KeyboardModifier::SHIFT ) { camera.fieldOfView( ) = ImClamp( camera.fieldOfView( ) + delta , 1.f , 179.f ); camera.cvtFov2Np( ); } else { camera.distance( ) = std::max( .01f , camera.distance( ) - delta ); camera.cvtAnglesToVectors( ); } } /*----------------------------------------------------------------------------*/ T_CameraChanges CameraUI( T_Camera& camera ) noexcept { using namespace ImGui; // What gets changed static const T_CameraChanges changeFlags[] = { E_CameraChange::MATRIX , {} , E_CameraChange::MATRIX , E_CameraChange::MATRIX , {} , E_CameraChange::MATRIX , E_CameraChange::MATRIX , {} , E_CameraChange::FOV , E_CameraChange::FOV , }; // Which update gets called. enum E_ChangeCall_ { CC_NONE , CC_FROM_VECTORS , CC_FROM_ANGLES , CC_FROM_FOV , CC_FROM_NP , }; static const E_ChangeCall_ changeCalls[] = { CC_FROM_ANGLES , CC_NONE , CC_FROM_ANGLES , CC_FROM_ANGLES , CC_NONE , CC_FROM_VECTORS , CC_FROM_VECTORS , CC_NONE , CC_FROM_FOV , CC_FROM_NP , }; static_assert( IM_ARRAYSIZE( changeFlags ) == IM_ARRAYSIZE( changeCalls ) , "invalid configuration" ); // Changes (also draws the fields) const bool changed[] = { DragFloat3( "Target" , &camera.lookAt( ).x ) , ( Separator( ) , false ) , DragFloat( "Distance" , &camera.distance( ) , .1f , .1f , 1e8 , "%.1f" ) , DragFloat3( "Angles" , &camera.angles( ).x , .01f , -180 , 180 ) , ( Separator( ) , false ) , DragFloat3( "Position" , &camera.position( ).x ) , DragFloat3( "Up vector" , &camera.upVector( ).x ) , ( Separator( ) , false ) , DragFloat( "FoV" , &camera.fieldOfView( ) , .01f , .01f , 179.9f ) , DragFloat( "Near plane" , &camera.nearPlane( ) , .00001f , .001f , 1e6f ) , }; static_assert( IM_ARRAYSIZE( changeFlags ) == IM_ARRAYSIZE( changed ) , "invalid configuration" ); T_CameraChanges changes; for ( unsigned i = 0 ; i < IM_ARRAYSIZE( changed ) ; i ++ ) { if ( changed[ i ] ) { switch ( changeCalls[ i ] ) { case CC_NONE: break; case CC_FROM_VECTORS: camera.cvtVectorsToAngles( ); break; case CC_FROM_ANGLES: camera.cvtAnglesToVectors( ); break; case CC_FROM_FOV: camera.cvtFov2Np( ); break; case CC_FROM_NP: camera.cvtNp2Fov( ); break; } changes = changes | changeFlags[ i ]; } } return changes; }