demotool/ui-overrides.cc
2017-11-23 23:05:14 +01:00

426 lines
11 KiB
C++

#include "externals.hh"
#include "common.hh"
#include "ui.hh"
#include "ui-colorgrading.hh"
#include "ui-overrides.hh"
#include "ui-sync.hh"
#include <imgui_internal.h>
namespace sov {
namespace {
char const* BuildLabel_(
uint32_t& counter ,
T_StringBuilder& sb ) noexcept
{
sb.clear( ) << "##temp label " << counter << '\0';
counter ++;
return sb.data( );
}
} // namespace <anon>
/*= 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_Camera& camera;
T_CamOverride& ov;
T_MouseCam_( T_Camera& cam ,
T_CamOverride& ov ) noexcept
: camera( cam ) , ov( ov )
{ }
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 T_MouseCam_::handleDragAndDrop(
ImVec2 const& move ,
T_KeyboardModifiers 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( ) };
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( ) );
}
}
void T_MouseCam_::handleWheel(
const float wheel ,
T_KeyboardModifiers 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 const& ovip{ ov.inputPositions( ) };
if ( modifiers & E_KeyboardModifier::SHIFT ) {
auto const& fc( ov.fovConfig( ) );
if ( fc.mode == T_CamOverride::FM_FOV ) {
sinp[ ovip[ fc.inputIndex ] ] = camera.fieldOfView( );
} else {
sinp[ ovip[ fc.inputIndex ] ] = camera.nearPlane( );
}
} else {
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 <anon>
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{ camera.makeUI( ) };
PopID( );
PopItemWidth( );
if ( handlerChanged ) {
if ( mouseHandler ) {
sui.delegateMouse( ov.id( ) ,
NewOwned< T_MouseCam_ >( camera , ov ) );
} else {
sui.clearMouseDelegate( );
}
}
// Update values
if ( changes & T_Camera::E_Changes::FOV ) {
if ( fc.mode == T_CamOverride::FM_FOV ) {
sinp[ ovip[ fc.inputIndex ] ] = camera.fieldOfView( );
} else {
sinp[ ovip[ fc.inputIndex ] ] = camera.nearPlane( );
}
}
if ( changes & T_Camera::E_Changes::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