diff options
Diffstat (limited to 'vgui2/matsys_controls/manipulator.cpp')
| -rw-r--r-- | vgui2/matsys_controls/manipulator.cpp | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/vgui2/matsys_controls/manipulator.cpp b/vgui2/matsys_controls/manipulator.cpp new file mode 100644 index 0000000..b582b11 --- /dev/null +++ b/vgui2/matsys_controls/manipulator.cpp @@ -0,0 +1,201 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//============================================================================= + +#include "matsys_controls/manipulator.h" + +#include "materialsystem/imaterialsystem.h" + +#include "vgui/IVGui.h" +#include "vgui/IInput.h" +#include "vgui/ISystem.h" +#include "vgui/MouseCode.h" + +#include "mathlib/vector.h" +#include "mathlib/vmatrix.h" +#include "mathlib/mathlib.h" + +#include <float.h> + +using namespace vgui; + + +//----------------------------------------------------------------------------- +// local helper functions +//----------------------------------------------------------------------------- +static float UpdateTime( float &flLastTime ) +{ + float flTime = vgui::system()->GetFrameTime(); + float dt = flTime - flLastTime; + flLastTime = flTime; + return dt; +} + + +//----------------------------------------------------------------------------- +// Base class for manipulators which operate on transforms +//----------------------------------------------------------------------------- +CTransformManipulator::CTransformManipulator( matrix3x4_t *pTransform ) : + m_pTransform( pTransform ) +{ +} + +void CTransformManipulator::SetTransform( matrix3x4_t *pTransform ) +{ + m_pTransform = pTransform; +} + +matrix3x4_t *CTransformManipulator::GetTransform( void ) +{ + return m_pTransform; +} + + +//----------------------------------------------------------------------------- +// CPotteryWheelManip - nendo-style camera manipulator +//----------------------------------------------------------------------------- +CPotteryWheelManip::CPotteryWheelManip( matrix3x4_t *pTransform ) : + CTransformManipulator( pTransform ), + m_lastx( -1 ), m_lasty( -1 ), + m_zoom( 100.0f ), m_altitude( 0.0f ), m_azimuth( 0.0f ), + m_prevZoom( 100.0f ), m_prevAltitude( 0.0f ), m_prevAzimuth( 0.0f ), + m_flLastMouseTime( 0.0f ), m_flLastTickTime( 0.0f ), + m_flSpin( 0.0f ), m_bSpin( false ) +{ +} + +void CPotteryWheelManip::OnBeginManipulation( void ) +{ + m_prevZoom = m_zoom; + m_prevAltitude = m_altitude; + m_prevAzimuth = m_azimuth; + m_flLastMouseTime = m_flLastTickTime = vgui::system()->GetFrameTime(); + m_flSpin = 0.0f; + m_bSpin = false; +} + +// Sets the zoom level +void CPotteryWheelManip::SetZoom( float flZoom ) +{ + m_prevZoom = m_zoom = flZoom; +} + + +void CPotteryWheelManip::OnAcceptManipulation( void ) +{ + m_flSpin = 0.0f; + m_bSpin = false; +} + +void CPotteryWheelManip::OnCancelManipulation( void ) +{ + m_zoom = m_prevZoom; + m_altitude = m_prevAltitude; + m_azimuth = m_prevAzimuth; + m_flSpin = 0.0f; + m_bSpin = false; + UpdateTransform(); +} + + +void CPotteryWheelManip::OnTick( void ) +{ + float dt = UpdateTime( m_flLastTickTime ); + + if ( m_bSpin ) + { + m_azimuth += dt * m_flSpin; + UpdateTransform(); + } +} + +void CPotteryWheelManip::OnCursorMoved( int x, int y ) +{ + float dt = UpdateTime( m_flLastMouseTime ); + + if ( m_bSpin ) + { + m_lastx = x; + m_lasty = y; + return; + } + + if ( input()->IsMouseDown( MOUSE_MIDDLE ) ) + { + int dy = y - m_lasty; + int dx = x - m_lastx; + + if ( abs( dx ) < 2 * abs( dy ) ) + { + UpdateZoom( 0.2f * dy ); + } + else + { + m_flSpin = (dt != 0.0f) ? 0.002f * dx / dt : 0.0f; + m_azimuth += 0.002f * dx; + } + } + else + { + m_azimuth += 0.002f * ( x - m_lastx ); + m_altitude -= 0.002f * ( y - m_lasty ); + m_altitude = max( (float)-M_PI/2, min( (float)M_PI/2, m_altitude ) ); + } + m_lastx = x; + m_lasty = y; + + UpdateTransform(); +} + +void CPotteryWheelManip::OnMousePressed( vgui::MouseCode code, int x, int y ) +{ + UpdateTime( m_flLastMouseTime ); + m_lastx = x; + m_lasty = y; + m_bSpin = false; + m_flSpin = 0.0f; +} + +void CPotteryWheelManip::OnMouseReleased( vgui::MouseCode code, int x, int y ) +{ + UpdateTime( m_flLastMouseTime ); + + if ( code == MOUSE_MIDDLE ) + { + m_bSpin = ( fabs( m_flSpin ) > 1.0f ); + } + + m_lastx = x; + m_lasty = y; +} + +void CPotteryWheelManip::OnMouseWheeled( int delta ) +{ + UpdateTime( m_flLastMouseTime ); + + UpdateZoom( -10.0f * delta ); + UpdateTransform(); +} + +void CPotteryWheelManip::UpdateTransform() +{ + if ( !m_pTransform ) + return; + + float y = m_zoom * sin( m_altitude ); + float xz = m_zoom * cos( m_altitude ); + float x = xz * sin( m_azimuth ); + float z = xz * cos( m_azimuth ); + + Vector position(x, y, z); + AngleMatrix( RadianEuler( -m_altitude, m_azimuth, 0 ), position, *m_pTransform ); +} + + +void CPotteryWheelManip::UpdateZoom( float delta ) +{ + m_zoom *= pow( 1.01f, delta ); +} |