diff --git a/TODO b/TODO index 0909ab5..cc239de 100644 --- a/TODO +++ b/TODO @@ -26,10 +26,6 @@ Scripting: * (Output only) Texture / framebuffer re-use Sync / inputs: -* Support for overrides - * Camera controls - * FoV vs near plane - * Target/angles/distance vs dir/up/left * Curve / timeline display * Display selected input values * Display selected overrides @@ -40,3 +36,6 @@ Misc: * Color grading controls: * White balance control in components tab * Don't reset when hitting value or saturation 0 +* Camera + * Control for up vector - check if something more appropriate exists? + * Vector controls are too sensitive diff --git a/camera.cc b/camera.cc index 940ff75..5580734 100644 --- a/camera.cc +++ b/camera.cc @@ -81,28 +81,27 @@ void T_Camera::cvtVectorsToAngles( ) noexcept /*------------------------------------------------------------------------------*/ -void T_Camera::handleDND( +void T_Camera::handleDragAndDrop( ImVec2 const& move , - const bool hasCtrl , - const bool hasShift , - const bool lmb ) noexcept + T_KeyboardModifiers modifiers , + T_MouseButtons buttons ) noexcept { if ( move.x == 0 || move.y == 0 ) { return; } - const float fdx( move.x * .1f * ( hasCtrl ? 1.f : .1f ) ); - const float fdy( move.y * .1f * ( hasCtrl ? 1.f : .1f ) ); + 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 ( lmb && hasShift ) { + if ( ( buttons & E_MouseButton::LEFT ) && ( modifiers & E_KeyboardModifier::SHIFT ) ) { // Left mouse button, shift - move camera const auto side( glm::normalize( glm::cross( up_ , dir_ ) ) ); lookAt_ += .1f * ( side * fdx + up_ * fdy ); - } else if ( lmb ) { + } else if ( buttons & E_MouseButton::LEFT ) { // Left mouse button, no shift - change yaw/pitch updateAngle( angles_.y , fdx ); updateAngle( angles_.x , fdy ); - } else { + } else if ( buttons & E_MouseButton::RIGHT ) { // Right mouse button - change roll updateAngle( angles_.z , fdx ); } @@ -111,11 +110,11 @@ void T_Camera::handleDND( void T_Camera::handleWheel( const float wheel , - const bool hasCtrl , - const bool hasShift ) noexcept + T_KeyboardModifiers modifiers , + T_MouseButtons /* buttons */ ) noexcept { - const float delta( wheel * ( hasCtrl ? 1.f : .1f) ); - if ( hasShift ) { + const float delta( wheel * ( ( modifiers & E_KeyboardModifier::CTRL ) ? 1.f : .1f) ); + if ( modifiers & E_KeyboardModifier::SHIFT ) { fov_ = std::max( 1.f , std::min( 179.f , fov_ + delta ) ); cvtFov2Np( ); } else { diff --git a/camera.hh b/camera.hh index d447f7f..53f345a 100644 --- a/camera.hh +++ b/camera.hh @@ -1,7 +1,5 @@ #pragma once -#ifndef REAL_BUILD -# include "externals.hh" -#endif +#include "imousectrl.hh" /*= T_Camera =================================================================*/ @@ -17,7 +15,7 @@ * - position, direction and up vectors * Modifying one of the sets updates the other. */ -struct T_Camera +struct T_Camera : public virtual A_MouseCtrl { T_Camera( ) noexcept; @@ -105,16 +103,13 @@ struct T_Camera T_Changes makeUI( ) noexcept; - void handleDND( + void handleDragAndDrop( ImVec2 const& move , - const bool hasCtrl , - const bool hasShift , - const bool lmb // Left mouse button - ) noexcept; + T_KeyboardModifiers modifiers , + T_MouseButtons buttons ) noexcept override; void handleWheel( - const float wheel , - const bool hasCtrl , - const bool hasShift - ) noexcept; + float wheel , + T_KeyboardModifiers modifiers , + T_MouseButtons buttons ) noexcept override; }; diff --git a/demo.cc b/demo.cc index 4b0c0dd..5af075d 100644 --- a/demo.cc +++ b/demo.cc @@ -40,24 +40,6 @@ void T_Demo::render( ) } } -void T_Demo::handleDND( - ImVec2 const& move , - const bool hasCtrl , - const bool hasShift , - const bool lmb // Left mouse button - ) -{ -} - -void T_Demo::handleWheel( - const float wheel , - const bool hasCtrl , - const bool hasShift - ) -{ -} - - bool T_Demo::runInit( ops::T_OpProgram& p ) { diff --git a/demo.hh b/demo.hh index c9c8bd2..e193d3f 100644 --- a/demo.hh +++ b/demo.hh @@ -18,18 +18,6 @@ struct T_Demo const uint32_t height ); void render( ); - void handleDND( - ImVec2 const& move , - const bool hasCtrl , - const bool hasShift , - const bool lmb // Left mouse button - ); - void handleWheel( - const float wheel , - const bool hasCtrl , - const bool hasShift - ); - // --------------------------------------------------------------------- private: diff --git a/imousectrl.hh b/imousectrl.hh new file mode 100644 index 0000000..ab27629 --- /dev/null +++ b/imousectrl.hh @@ -0,0 +1,46 @@ +#pragma once +#ifndef REAL_BUILD +# include "externals.hh" +#endif + + +/*= MOUSE CONTROLS INTERFACE ===================================================*/ + +enum class E_MouseButton { + LEFT , + MIDDLE , + RIGHT , +}; +using T_MouseButtons = T_Flags< E_MouseButton >; + +/*------------------------------------------------------------------------------*/ + +enum class E_KeyboardModifier +{ + CTRL , + SHIFT , + ALT , +}; +using T_KeyboardModifiers = T_Flags< E_KeyboardModifier >; + +/*------------------------------------------------------------------------------*/ + +class A_MouseCtrl +{ + public: + virtual ~A_MouseCtrl( ) = 0; + + virtual void handleDragAndDrop( + ImVec2 const& move , + T_KeyboardModifiers modifiers , + T_MouseButtons buttons + ) noexcept = 0; + + virtual void handleWheel( + float wheel , + T_KeyboardModifiers modifiers , + T_MouseButtons buttons + ) noexcept = 0; +}; + +inline A_MouseCtrl::~A_MouseCtrl() {} diff --git a/main.cc b/main.cc index fc76468..46cbbaf 100644 --- a/main.cc +++ b/main.cc @@ -142,36 +142,57 @@ void T_Main::startIteration( ) void T_Main::handleCapture( ) { - auto const& io( ImGui::GetIO( ) ); - const bool lmb( ImGui::IsMouseDown( 0 ) ); - const bool mb( lmb || ImGui::IsMouseDown( 1 ) ); + using namespace ImGui; + auto const& io( GetIO( ) ); + const T_MouseButtons mb( ([]() {; + T_MouseButtons mb; + if ( IsMouseDown( 0 ) ) { + mb |= E_MouseButton::LEFT; + } + if ( IsMouseDown( 1 ) ) { + mb |= E_MouseButton::RIGHT; + } + if ( IsMouseDown( 2 ) ) { + mb |= E_MouseButton::MIDDLE; + } + return mb; + })() ); + const T_KeyboardModifiers kb( ([&io]() { + T_KeyboardModifiers kb; + if ( io.KeyCtrl ) { + kb |= E_KeyboardModifier::CTRL; + } + if ( io.KeyShift ) { + kb |= E_KeyboardModifier::SHIFT; + } + if ( io.KeyAlt ) { + kb |= E_KeyboardModifier::ALT; + } + return kb; + })() ); const bool appCanGrab( !( ImGui::IsMouseHoveringAnyWindow( ) || io.WantCaptureMouse || io.WantCaptureKeyboard ) ); - const bool shift( io.KeyShift ); - const bool ctrl( io.KeyCtrl ); if ( capture && !mb ) { capture = false; - ImGui::CaptureMouseFromApp( false ); + CaptureMouseFromApp( false ); SDL_SetRelativeMouseMode( SDL_FALSE ); Globals::Window( ).warpMouse( mouseInitial ); - ImGui::SetMouseCursor( ImGuiMouseCursor_Arrow ); + SetMouseCursor( ImGuiMouseCursor_Arrow ); } else if ( capture ) { - ImGui::SetMouseCursor( ImGuiMouseCursor_Move ); - if ( demo ) { - demo->handleDND( mouseMove , ctrl , shift , lmb ); - } + SetMouseCursor( ImGuiMouseCursor_Move ); + Globals::Sync( ).handleDragAndDrop( mouseMove , kb , mb ); } else if ( appCanGrab && mb ) { capture = true; - mouseInitial = ImGui::GetMousePos( ); - ImGui::CaptureMouseFromApp( true ); + mouseInitial = GetMousePos( ); + CaptureMouseFromApp( true ); SDL_SetRelativeMouseMode( SDL_TRUE ); - ImGui::SetMouseCursor( ImGuiMouseCursor_Move ); + SetMouseCursor( ImGuiMouseCursor_Move ); } - if ( ( appCanGrab || capture ) && io.MouseWheel && demo ) { - demo->handleWheel( io.MouseWheel , ctrl , shift ); + if ( ( appCanGrab || capture ) && io.MouseWheel ) { + Globals::Sync( ).handleWheel( io.MouseWheel , kb , mb ); } } diff --git a/sync.cc b/sync.cc index 85abb2f..47052aa 100644 --- a/sync.cc +++ b/sync.cc @@ -2,6 +2,7 @@ #include "sync.hh" #include "globals.hh" +#include #include #include #include @@ -555,6 +556,14 @@ void T_SyncManager::updateTime( ) noexcept /*----------------------------------------------------------------------------*/ +void T_SyncManager::clearInputs( ) noexcept +{ + clearOverrides( ); + values_.clear( ); +} + +/*----------------------------------------------------------------------------*/ + void T_SyncManager::checkCurveFile( ) { if ( watcher_ ) { @@ -664,6 +673,7 @@ void T_SyncManager::updateValues( ) void T_SyncManager::clearOverrides( ) noexcept { + mouseDelegate_ = nullptr; soRoot_.subsections.clear( ); soRoot_.overrides.clear( ); } @@ -765,3 +775,25 @@ void T_SyncManager::makeOverridesWindow( ) } End( ); } + +/*------------------------------------------------------------------------------*/ + +void T_SyncManager::handleDragAndDrop( + ImVec2 const& move , + T_KeyboardModifiers modifiers , + T_MouseButtons buttons ) noexcept +{ + if ( mouseDelegate_ ) { + mouseDelegate_->handleDragAndDrop( move , modifiers , buttons ); + } +} + +void T_SyncManager::handleWheel( + const float wheel , + T_KeyboardModifiers modifiers , + T_MouseButtons buttons ) noexcept +{ + if ( mouseDelegate_ ) { + mouseDelegate_->handleWheel( wheel , modifiers , buttons ); + } +} diff --git a/sync.hh b/sync.hh index b509fbf..5a5658e 100644 --- a/sync.hh +++ b/sync.hh @@ -1,7 +1,7 @@ #pragma once #include "filewatcher.hh" #include "utilities.hh" -#include "imgui_internal.h" +#include "imousectrl.hh" #include #include @@ -272,10 +272,11 @@ struct T_SyncOverrideVisitor // Synchronisation manager; handles all the synchronization data and makes it // work together. -struct T_SyncManager +struct T_SyncManager : public virtual A_MouseCtrl { T_SyncManager( ); + // --------------------------------------------------------------------- // Duration & time controls @@ -297,11 +298,11 @@ struct T_SyncManager { return time_.time >= time_.duration( ); } void updateTime( ) noexcept; + // --------------------------------------------------------------------- // Value access - void clearInputs( ) - { values_.clear( ); } + void clearInputs( ) noexcept; bool addInput( T_String const& name , const float initial = 0.f ) noexcept { return values_.addValue( name , initial ); } @@ -313,6 +314,7 @@ struct T_SyncManager T_Array< float >& inputs( ) noexcept { return values_.values; } + // --------------------------------------------------------------------- // Curves @@ -324,6 +326,7 @@ struct T_SyncManager void curvesChanged_( ); bool loadCurves_( bool& missing ); + // --------------------------------------------------------------------- // Overrides @@ -342,6 +345,7 @@ struct T_SyncManager void updateCurveCaches( ); void updateValues( ); + // --------------------------------------------------------------------- // User interface @@ -353,6 +357,26 @@ struct T_SyncManager { return ovWindow_; } void makeOverridesWindow( ); + void delegateMouse( A_MouseCtrl& delegate ) noexcept + { mouseDelegate_ = &delegate; } + void clearMouseDelegate( ) noexcept + { mouseDelegate_ = nullptr; } + bool isCurrentDelegate( A_MouseCtrl const& delegate ) noexcept + { return mouseDelegate_ == &delegate; } + + void handleDragAndDrop( + ImVec2 const& move , + T_KeyboardModifiers modifiers , + T_MouseButtons buttons ) noexcept override; + void handleWheel( + float wheel , + T_KeyboardModifiers modifiers , + T_MouseButtons buttons ) noexcept override; + + + // --------------------------------------------------------------------- + // Private data + private: ebcl::T_SRDParserConfig pConfig_; // Parser config for curves P_WatchedFiles watcher_; // Curves file watcher @@ -366,4 +390,5 @@ struct T_SyncManager T_Array< P_SyncCurveCache > curveCaches_; // Cache for curve segments bool ovWindow_{ false }; // Overrides window T_SyncOverrideSection soRoot_; // Root for overrides + A_MouseCtrl* mouseDelegate_{ nullptr }; // Delegate for mouse actions }; diff --git a/syncoverrides.cc b/syncoverrides.cc index 47fa7a1..b532da4 100644 --- a/syncoverrides.cc +++ b/syncoverrides.cc @@ -3,6 +3,7 @@ #include "syncoverrides.hh" #include "colorgrading.hh" +#include #include using namespace sov; @@ -1124,7 +1125,8 @@ void T_CamOverride::makeEditWidgets( uint32_t& counter , T_StringBuilder& sb ) noexcept { - auto& sinp( Globals::Sync( ).inputs( ) ); + auto& sync( Globals::Sync( ) ); + auto& sinp( sync.inputs( ) ); auto const& fc( *fovConfig_ ); if ( !enabled( ) || !prevEnabled_ ) { @@ -1151,13 +1153,24 @@ void T_CamOverride::makeEditWidgets( // Draw UI char const* const name( buildLabel( counter , sb ) ); + bool mouseHandler{ sync.isCurrentDelegate( *this ) }; using namespace ImGui; PushItemWidth( 0 ); // Compensate for -1 PushID( GetCurrentWindow( )->GetID( name ) ); + const bool handlerChanged{ Checkbox( "Mouse control" , &mouseHandler ) }; + Separator( ); const auto changes{ camera_.makeUI( ) }; PopID( ); PopItemWidth( ); + if ( handlerChanged ) { + if ( mouseHandler ) { + sync.delegateMouse( *this ); + } else { + sync.clearMouseDelegate( ); + } + } + if ( changes & T_Camera::E_Changes::FOV ) { if ( fc.mode == FM_FOV ) { sinp[ inputPos_[ fc.inputIndex ] ] = camera_.fieldOfView( ); @@ -1196,3 +1209,60 @@ void T_CamOverride::inputsFromVector( sinp[ inputPos_[ vc.y ] ] = v.y; sinp[ inputPos_[ vc.z ] ] = v.z; } + +/*------------------------------------------------------------------------------*/ + +void T_CamOverride::handleDragAndDrop( + ImVec2 const& move , + T_KeyboardModifiers modifiers , + T_MouseButtons buttons ) noexcept +{ + auto& sync( Globals::Sync( ) ); + if ( !enabled( ) ) { + sync.clearMouseDelegate( ); + return; + } + camera_.handleDragAndDrop( move , modifiers , buttons ); + + auto& sinp( sync.inputs( ) ); + inputsFromVector( *target_ , camera_.lookAt( ) ); + if ( camMode_ == CM_ANGLES ) { + inputsFromVector( *angles_ , camera_.angles( ) ); + sinp[ inputPos_[ *distance_ ] ] = camera_.distance( ); + } else { + inputsFromVector( *position_ , camera_.position( ) ); + inputsFromVector( *upVector_ , camera_.upVector( ) ); + } +} + +void T_CamOverride::handleWheel( + const float wheel , + T_KeyboardModifiers modifiers , + T_MouseButtons buttons ) noexcept +{ + auto& sync( Globals::Sync( ) ); + if ( !enabled( ) ) { + sync.clearMouseDelegate( ); + return; + } + camera_.handleWheel( wheel , modifiers , buttons ); + + auto& sinp( sync.inputs( ) ); + if ( modifiers & E_KeyboardModifier::SHIFT ) { + auto const& fc( *fovConfig_ ); + if ( fc.mode == FM_FOV ) { + sinp[ inputPos_[ fc.inputIndex ] ] = camera_.fieldOfView( ); + } else { + sinp[ inputPos_[ fc.inputIndex ] ] = camera_.nearPlane( ); + } + } else { + inputsFromVector( *target_ , camera_.lookAt( ) ); + if ( camMode_ == CM_ANGLES ) { + inputsFromVector( *angles_ , camera_.angles( ) ); + sinp[ inputPos_[ *distance_ ] ] = camera_.distance( ); + } else { + inputsFromVector( *position_ , camera_.position( ) ); + inputsFromVector( *upVector_ , camera_.upVector( ) ); + } + } +} diff --git a/syncoverrides.hh b/syncoverrides.hh index 0674cad..27c6095 100644 --- a/syncoverrides.hh +++ b/syncoverrides.hh @@ -214,7 +214,7 @@ class T_ColorGrading : public A_SyncOverride /*= CAMERA CONTROLS ============================================================*/ -class T_CamOverride : public A_SyncOverride +class T_CamOverride : public A_SyncOverride , public virtual A_MouseCtrl { public: enum E_SetState { @@ -309,6 +309,15 @@ class T_CamOverride : public A_SyncOverride T_Camera const& camData( ) const noexcept { return camera_; } + void handleDragAndDrop( + ImVec2 const& move , + T_KeyboardModifiers modifiers , + T_MouseButtons buttons ) noexcept override; + void handleWheel( + float wheel , + T_KeyboardModifiers modifiers , + T_MouseButtons buttons ) noexcept override; + private: E_SetState setVector( T_Optional< T_VectorConfig_ >& vector ,