UI - Refactoring progress

(see previous log message)
This commit is contained in:
Emmanuel BENOîT 2017-11-24 07:26:02 +01:00
parent c465a38306
commit 30699ee8df
5 changed files with 201 additions and 166 deletions

121
camera.cc
View file

@ -78,124 +78,3 @@ void T_Camera::cvtVectorsToAngles( ) noexcept
angles_ = nAngles * 180.f / float( M_PI ); angles_ = nAngles * 180.f / float( M_PI );
} }
/*------------------------------------------------------------------------------*/
void T_Camera::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( glm::normalize( glm::cross( up_ , dir_ ) ) );
lookAt_ += .1f * ( side * fdx + up_ * fdy );
} else if ( buttons & E_MouseButton::LEFT ) {
// Left mouse button, no shift - change yaw/pitch
updateAngle( angles_.y , fdx );
updateAngle( angles_.x , fdy );
} else if ( buttons & E_MouseButton::RIGHT ) {
// Right mouse button - change roll
updateAngle( angles_.z , fdx );
}
cvtAnglesToVectors( );
}
void T_Camera::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 ) {
fov_ = std::max( 1.f , std::min( 179.f , fov_ + delta ) );
cvtFov2Np( );
} else {
distance_ = std::max( .01f , distance_ - delta );
cvtAnglesToVectors( );
}
}
/*----------------------------------------------------------------------------*/
T_Camera::T_Changes T_Camera::makeUI( ) noexcept
{
using namespace ImGui;
// What gets changed
static const T_Changes changeFlags[] = {
E_Changes::MATRIX ,
{} ,
E_Changes::MATRIX ,
E_Changes::MATRIX ,
{} ,
E_Changes::MATRIX ,
E_Changes::MATRIX ,
{} ,
E_Changes::FOV ,
E_Changes::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( sizeof( changeFlags ) / sizeof( T_Changes ) == sizeof( changeCalls ) / sizeof( E_ChangeCall_ ) ,
"invalid configuration" );
// Changes (also draws the fields)
const bool changed[] = {
DragFloat3( "Target" , &lookAt_.x ) ,
( Separator( ) , false ) ,
DragFloat( "Distance" , &distance_ , .1f , .1f , 1e8 , "%.1f" ) ,
DragFloat3( "Angles" , &angles_.x , .01f , -180 , 180 ) ,
( Separator( ) , false ) ,
DragFloat3( "Position" , &pos_.x ) ,
DragFloat3( "Up vector" , &up_.x ) ,
( Separator( ) , false ) ,
DragFloat( "FoV" , &fov_ , .01f , .01f , 179.9f ) ,
DragFloat( "Near plane" , &np_ , .00001f , .001f , 1e6f ) ,
};
static_assert( sizeof( changeFlags ) / sizeof( T_Changes ) == sizeof( changed ) / sizeof( bool ) ,
"invalid configuration" );
T_Changes changes;
for ( unsigned i = 0 ; i < sizeof( changed ) / sizeof( bool ) ; i ++ ) {
if ( changed[ i ] ) {
switch ( changeCalls[ i ] ) {
case CC_NONE: break;
case CC_FROM_VECTORS: cvtVectorsToAngles( ); break;
case CC_FROM_ANGLES: cvtAnglesToVectors( ); break;
case CC_FROM_FOV: cvtFov2Np( ); break;
case CC_FROM_NP: cvtNp2Fov( ); break;
}
changes = changes | changeFlags[ i ];
}
}
return changes;
}

View file

@ -15,7 +15,7 @@
* - position, direction and up vectors * - position, direction and up vectors
* Modifying one of the sets updates the other. * Modifying one of the sets updates the other.
*/ */
struct T_Camera : public virtual A_MouseCtrl struct T_Camera
{ {
T_Camera( ) noexcept; T_Camera( ) noexcept;
@ -40,18 +40,17 @@ struct T_Camera : public virtual A_MouseCtrl
float fieldOfView( ) const noexcept float fieldOfView( ) const noexcept
{ return fov_; } { return fov_; }
float& fieldOfView( ) noexcept
{ return fov_; }
float nearPlane( ) const noexcept float nearPlane( ) const noexcept
{ return np_; } { return np_; }
float& nearPlane( ) noexcept
{ return np_; }
private: private:
float fov_ = 90.f; float fov_ = 90.f;
float np_; float np_;
void cvtFov2Np( ) noexcept
{ np_ = 2 * tanf( M_PI * ( 180.f - fov_ ) / 360.f ); }
void cvtNp2Fov( ) noexcept
{ fov_ = 180.f - atanf( .5 * np_ ) * 360.f / M_PI; }
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// POSITION AND ORIENTATION // POSITION AND ORIENTATION
@ -66,16 +65,31 @@ struct T_Camera : public virtual A_MouseCtrl
glm::vec3 const& lookAt( ) const noexcept glm::vec3 const& lookAt( ) const noexcept
{ return lookAt_; } { return lookAt_; }
glm::vec3& lookAt( ) noexcept
{ return lookAt_; }
glm::vec3 const& angles( ) const noexcept glm::vec3 const& angles( ) const noexcept
{ return angles_; } { return angles_; }
glm::vec3& angles( ) noexcept
{ return angles_; }
float distance( ) const noexcept float distance( ) const noexcept
{ return distance_; } { return distance_; }
float& distance( ) noexcept
{ return distance_; }
glm::vec3 const& position( ) const noexcept glm::vec3 const& position( ) const noexcept
{ return pos_; } { return pos_; }
glm::vec3& position( ) noexcept
{ return pos_; }
glm::vec3 const& upVector( ) const noexcept glm::vec3 const& upVector( ) const noexcept
{ return up_; } { return up_; }
glm::vec3& upVector( ) noexcept
{ return up_; }
glm::vec3 const& direction( ) const noexcept
{ return dir_; }
glm::vec3& direction( ) noexcept
{ return dir_; }
private: private:
glm::vec3 lookAt_ = glm::vec3( 0 ); glm::vec3 lookAt_ = glm::vec3( 0 );
@ -88,28 +102,15 @@ struct T_Camera : public virtual A_MouseCtrl
glm::mat3x3 rotMat_; glm::mat3x3 rotMat_;
void cvtAnglesToVectors( ) noexcept;
void cvtVectorsToAngles( ) noexcept;
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// UI & MOUSE CONTROLS // CONVERSION
public: public:
enum class E_Changes { void cvtFov2Np( ) noexcept
FOV , { np_ = 2 * tanf( M_PI * ( 180.f - fov_ ) / 360.f ); }
MATRIX void cvtNp2Fov( ) noexcept
}; { fov_ = 180.f - atanf( .5 * np_ ) * 360.f / M_PI; }
using T_Changes = T_Flags< E_Changes >;
T_Changes makeUI( ) noexcept;
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;
void cvtAnglesToVectors( ) noexcept;
void cvtVectorsToAngles( ) noexcept;
}; };

View file

@ -4,6 +4,7 @@
#include "ui-colorgrading.hh" #include "ui-colorgrading.hh"
#include "ui-overrides.hh" #include "ui-overrides.hh"
#include "ui-sync.hh" #include "ui-sync.hh"
#include "ui-utilities.hh"
#include <imgui_internal.h> #include <imgui_internal.h>
@ -263,7 +264,7 @@ void InputsFromVector_(
struct T_MouseCam_ : public virtual A_MouseCtrl struct T_MouseCam_ : public virtual A_MouseCtrl
{ {
T_Camera& camera; T_CameraMouseControl camera;
T_CamOverride& ov; T_CamOverride& ov;
T_MouseCam_( T_Camera& cam , T_MouseCam_( T_Camera& cam ,
@ -299,13 +300,14 @@ void T_MouseCam_::handleDragAndDrop(
auto& sinp( sync.inputs( ) ); auto& sinp( sync.inputs( ) );
auto const& ovip{ ov.inputPositions( ) }; auto const& ovip{ ov.inputPositions( ) };
InputsFromVector_( ov.target( ) , ovip , camera.lookAt( ) ); auto& cam{ camera.camera };
InputsFromVector_( ov.target( ) , ovip , cam.lookAt( ) );
if ( ov.mode( ) == T_CamOverride::CM_ANGLES ) { if ( ov.mode( ) == T_CamOverride::CM_ANGLES ) {
InputsFromVector_( ov.angles( ) , ovip , camera.angles( ) ); InputsFromVector_( ov.angles( ) , ovip , cam.angles( ) );
sinp[ ovip[ ov.distance( ) ] ] = camera.distance( ); sinp[ ovip[ ov.distance( ) ] ] = cam.distance( );
} else { } else {
InputsFromVector_( ov.position( ) , ovip , camera.position( ) ); InputsFromVector_( ov.position( ) , ovip , cam.position( ) );
InputsFromVector_( ov.up( ) , ovip , camera.upVector( ) ); InputsFromVector_( ov.up( ) , ovip , cam.upVector( ) );
} }
} }
@ -323,22 +325,23 @@ void T_MouseCam_::handleWheel(
camera.handleWheel( wheel , modifiers , buttons ); camera.handleWheel( wheel , modifiers , buttons );
auto& sinp( sync.inputs( ) ); auto& sinp( sync.inputs( ) );
auto& cam{ camera.camera };
auto const& ovip{ ov.inputPositions( ) }; auto const& ovip{ ov.inputPositions( ) };
if ( modifiers & E_KeyboardModifier::SHIFT ) { if ( modifiers & E_KeyboardModifier::SHIFT ) {
auto const& fc( ov.fovConfig( ) ); auto const& fc( ov.fovConfig( ) );
if ( fc.mode == T_CamOverride::FM_FOV ) { if ( fc.mode == T_CamOverride::FM_FOV ) {
sinp[ ovip[ fc.inputIndex ] ] = camera.fieldOfView( ); sinp[ ovip[ fc.inputIndex ] ] = cam.fieldOfView( );
} else { } else {
sinp[ ovip[ fc.inputIndex ] ] = camera.nearPlane( ); sinp[ ovip[ fc.inputIndex ] ] = cam.nearPlane( );
} }
} else { } else {
InputsFromVector_( ov.target( ) , ovip , camera.lookAt( ) ); InputsFromVector_( ov.target( ) , ovip , cam.lookAt( ) );
if ( ov.mode( ) == T_CamOverride::CM_ANGLES ) { if ( ov.mode( ) == T_CamOverride::CM_ANGLES ) {
InputsFromVector_( ov.angles( ) , ovip , camera.angles( ) ); InputsFromVector_( ov.angles( ) , ovip , cam.angles( ) );
sinp[ ovip[ ov.distance( ) ] ] = camera.distance( ); sinp[ ovip[ ov.distance( ) ] ] = cam.distance( );
} else { } else {
InputsFromVector_( ov.position( ) , ovip , camera.position( ) ); InputsFromVector_( ov.position( ) , ovip , cam.position( ) );
InputsFromVector_( ov.up( ) , ovip , camera.upVector( ) ); InputsFromVector_( ov.up( ) , ovip , cam.upVector( ) );
} }
} }
} }
@ -389,7 +392,7 @@ M_DECL_SOVUI( Camera )
PushID( GetCurrentWindow( )->GetID( name ) ); PushID( GetCurrentWindow( )->GetID( name ) );
const bool handlerChanged{ Checkbox( "Mouse control" , &mouseHandler ) }; const bool handlerChanged{ Checkbox( "Mouse control" , &mouseHandler ) };
Separator( ); Separator( );
const auto changes{ camera.makeUI( ) }; const auto changes{ CameraUI( camera ) };
PopID( ); PopID( );
PopItemWidth( ); PopItemWidth( );
@ -403,14 +406,14 @@ M_DECL_SOVUI( Camera )
} }
// Update values // Update values
if ( changes & T_Camera::E_Changes::FOV ) { if ( changes & E_CameraChange::FOV ) {
if ( fc.mode == T_CamOverride::FM_FOV ) { if ( fc.mode == T_CamOverride::FM_FOV ) {
sinp[ ovip[ fc.inputIndex ] ] = camera.fieldOfView( ); sinp[ ovip[ fc.inputIndex ] ] = camera.fieldOfView( );
} else { } else {
sinp[ ovip[ fc.inputIndex ] ] = camera.nearPlane( ); sinp[ ovip[ fc.inputIndex ] ] = camera.nearPlane( );
} }
} }
if ( changes & T_Camera::E_Changes::MATRIX ) { if ( changes & E_CameraChange::MATRIX ) {
InputsFromVector_( ov.target( ) , ovip , camera.lookAt( ) ); InputsFromVector_( ov.target( ) , ovip , camera.lookAt( ) );
if ( ov.mode( ) == T_CamOverride::CM_ANGLES ) { if ( ov.mode( ) == T_CamOverride::CM_ANGLES ) {
InputsFromVector_( ov.angles( ) , ovip , camera.angles( ) ); InputsFromVector_( ov.angles( ) , ovip , camera.angles( ) );

View file

@ -1,4 +1,6 @@
#include "externals.hh" #include "externals.hh"
#include "c-utilities.hh"
#include "camera.hh"
#include "ui-utilities.hh" #include "ui-utilities.hh"
#include <imgui_internal.h> #include <imgui_internal.h>
@ -57,3 +59,125 @@ void ImGui::ToolbarSeparator( ) noexcept
VerticalSeparator( ); VerticalSeparator( );
SameLine( ); 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;
}

View file

@ -1,7 +1,6 @@
#pragma once #pragma once
#ifndef REAL_BUILD #include "ui-mousectrl.hh"
# include "externals.hh"
#endif
/*= UI UTILITIES =============================================================*/ /*= UI UTILITIES =============================================================*/
@ -47,3 +46,32 @@ namespace ImGui {
err_ , __FILE__ , __LINE__ ); \ err_ , __FILE__ , __LINE__ ); \
abort( ); \ abort( ); \
}) })
/*= CAMERA ===================================================================*/
struct T_Camera;
struct T_CameraMouseControl : public A_MouseCtrl
{
T_Camera& camera;
explicit T_CameraMouseControl( T_Camera& cam ) : camera( cam ) {}
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;
};
enum class E_CameraChange {
FOV ,
MATRIX
};
using T_CameraChanges = T_Flags< E_CameraChange >;
T_CameraChanges CameraUI( T_Camera& camera ) noexcept;