|
|
//====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#include "dme_controls/attributeslider.h"
#include "dme_controls/dmecontrols_utils.h"
#include "materialsystem/imesh.h"
#include "movieobjects/dmeanimationset.h"
#include "movieobjects/dmeexpressionoperator.h"
#include "vgui/IInput.h"
#include "vgui/ISurface.h"
#include "vgui_controls/TextImage.h"
#include "vgui_controls/subrectimage.h"
#include "vgui_controls/CheckButton.h"
#include "vgui_controls/Menu.h"
#include "dme_controls/BaseAnimSetAttributeSliderPanel.h"
#include "dme_controls/BaseAnimSetPresetFaderPanel.h"
#include "dme_controls/BaseAnimationSetEditor.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
using namespace vgui;
//-----------------------------------------------------------------------------
// Enums
//-----------------------------------------------------------------------------
#define SLIDER_PIXEL_SPACING 3
#define UNDO_CHAIN_MOUSEWHEEL_ATTRIBUTE_SLIDER 9876
#define FRAC_PER_PIXEL 0.0025f
static ConVar ifm_attributeslider_sensitivity( "ifm_attributeslider_sensitivity", "3.0", 0 ); static ConVar ifm_attributeslider_legacy( "ifm_attributeslider_legacy", "0", 0, "Uses old style slider dragging." );
//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------
static Color s_TextColor( 200, 200, 200, 192 ); static Color s_TextColorFocus( 208, 143, 40, 192 ); static Color s_TextColorDependent( 240, 50, 50, 192 );
static Color s_BarColor[2] = { Color( 45, 45, 45, 255 ), Color( 30, 255, 255, 80 ) };
static Color s_ZeroColor[2] = { Color( 33, 33, 33, 255 ), Color( 100, 80, 0, 255 ) };
static Color s_DraggingBarColor( 142, 142, 142, 255 ); static Color s_PreviewTickColor( 255, 164, 8, 255 ); static Color s_OldValueTickColor( 100, 100, 100, 63 );
static Color s_MidpointColor( 115, 115, 115, 255 );
//-----------------------------------------------------------------------------
// Blends flex values in left-right space instead of balance/value space
//-----------------------------------------------------------------------------
static void BlendFlexValues( AttributeValue_t *pResult, const AttributeValue_t &src, const AttributeValue_t &dest, float flBlend, float flBalanceFilter = 0.5f ) { float flLeftFilter, flRightFilter; ValueBalanceToLeftRight( &flLeftFilter, &flRightFilter, flBlend, flBalanceFilter, 0.0f );
pResult->m_pValue[ANIM_CONTROL_VALUE ] = src.m_pValue[ANIM_CONTROL_VALUE ] + ( dest.m_pValue[ANIM_CONTROL_VALUE ] - src.m_pValue[ANIM_CONTROL_VALUE ] ) * flBlend; pResult->m_pValue[ANIM_CONTROL_VALUE_LEFT ] = src.m_pValue[ANIM_CONTROL_VALUE_LEFT ] + ( dest.m_pValue[ANIM_CONTROL_VALUE_LEFT ] - src.m_pValue[ANIM_CONTROL_VALUE_LEFT ] ) * flLeftFilter; pResult->m_pValue[ANIM_CONTROL_VALUE_RIGHT] = src.m_pValue[ANIM_CONTROL_VALUE_RIGHT] + ( dest.m_pValue[ANIM_CONTROL_VALUE_RIGHT] - src.m_pValue[ANIM_CONTROL_VALUE_RIGHT] ) * flRightFilter; }
static void BlendTransformValues( AttributeValue_t *pResult, const AttributeValue_t &src, const AttributeValue_t &dest, float flBlend ) { pResult->m_Vector = Lerp( flBlend, src.m_Vector, dest.m_Vector ); // TODO: SHould this be a Slerp or a simple blend or some other op?
QuaternionSlerp( src.m_Quaternion, dest.m_Quaternion, flBlend, pResult->m_Quaternion ); }
void BlendValues( bool bTransform, AttributeValue_t *pResult, const AttributeValue_t &src, const AttributeValue_t &dest, float flBlend, float flBalanceFilter = 0.5f ) { if ( bTransform ) { BlendTransformValues( pResult, src, dest, flBlend ); } else { BlendFlexValues( pResult, src, dest, flBlend, flBalanceFilter ); } } //-----------------------------------------------------------------------------
// The panel used to do text entry when double-clicking in the slider
//-----------------------------------------------------------------------------
class CAttributeSliderTextEntry : public TextEntry { DECLARE_CLASS_SIMPLE( CAttributeSliderTextEntry, TextEntry );
public: CAttributeSliderTextEntry( CAttributeSlider *slider, const char *panelName ) : BaseClass( (Panel *)slider, panelName ), m_pSlider( slider ) { Assert( m_pSlider ); }
MESSAGE_FUNC_PARAMS( OnKillFocus, "KillFocus", kv ); virtual void OnMouseWheeled( int delta );
private: CAttributeSlider *m_pSlider; };
//-----------------------------------------------------------------------------
//
// CAttributeSlider begins here
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CAttributeSlider::CAttributeSlider( CBaseAnimSetAttributeSliderPanel *parent ) : BaseClass( (Panel *)parent, "" ), m_pParent( parent ), m_flFaderAmount( 1.0f ), m_bDependent( false ), m_pTextField( 0 ), m_pRightTextField( 0 ), m_nVisibleComponents( LOG_COMPONENTS_ALL ) { SetPaintBackgroundEnabled( true ); SetPaintBorderEnabled( false ); SetBgColor( Color( 42, 42, 42, 255 ) );
m_pName = new TextImage( "" ); m_pValues[ 0 ] = new TextImage( "" ); m_pValues[ 1 ] = new TextImage( "" ); m_pValues[ 2 ] = new TextImage( "" ); m_pValues[ 3 ] = new TextImage( "" );
SetSize( 100, 20 ); }
void CAttributeSlider::Init( CDmElement *control, bool bOrientation ) { SetName( control->GetName() );
m_SliderMode = SLIDER_MODE_NONE; m_hControl = control; m_bTransform = false; m_bOrientation = false; // Cache off control information since this state should never change
// NOTE: If it ever does, just change the implementations of
// IsTransform + GetMidpoint to always read these values from the attributes
CDmeTransformControl *pTransformControl = CastElement< CDmeTransformControl >( control ); if ( pTransformControl ) { m_bTransform = true; m_bOrientation = bOrientation; }
m_bStereo = IsStereoControl( control );
m_nDragStartPosition[ 0 ] = m_nDragStartPosition[ 1 ] = 0; m_nAccum[ 0 ] = m_nAccum[ 1 ] = 0; m_dragStartValues = GetValue();
SetPaintBackgroundEnabled( true );
if ( m_bTransform ) { m_pName->SetText( CFmtStr( m_bOrientation ? "%s - rot" : "%s - pos", control->GetName() ) ); } else { m_pName->SetText( control->GetName() ); } m_pName->ResizeImageToContent();
InitControls(); }
CAttributeSlider::~CAttributeSlider() { delete m_pName; delete m_pValues[ 0 ]; delete m_pValues[ 1 ]; delete m_pValues[ 2 ]; delete m_pValues[ 3 ]; }
//-----------------------------------------------------------------------------
// Scheme
//-----------------------------------------------------------------------------
void CAttributeSlider::ApplySchemeSettings( IScheme *scheme ) { BaseClass::ApplySchemeSettings( scheme );
m_pName->SetFont( scheme->GetFont( "Default" ) ); m_pName->SetColor( s_TextColor ); m_pName->ResizeImageToContent();
m_pValues[ 0 ]->SetColor( s_TextColor ); m_pValues[ 0 ]->SetFont( scheme->GetFont( "Default" ) ); m_pValues[ 1 ]->SetColor( s_TextColorFocus ); m_pValues[ 1 ]->SetFont( scheme->GetFont( "Default" ) ); m_pValues[ 2 ]->SetColor( s_TextColor ); m_pValues[ 2 ]->SetFont( scheme->GetFont( "Default" ) ); m_pValues[ 3 ]->SetColor( s_TextColor ); m_pValues[ 3 ]->SetFont( scheme->GetFont( "Default" ) );
SetBgColor( Color( 42, 42, 42, 255 ) ); SetFgColor( Color( 194, 120, 0, 255 ) ); }
void CAttributeSlider::InitControls() { if ( m_bTransform ) { CDmeTransformControl *pTransformControl = CastElement< CDmeTransformControl >( m_hControl ); if ( pTransformControl ) { if ( m_bOrientation ) { SetValue( ANIM_CONTROL_TXFORM_ORIENTATION, pTransformControl->GetOrientation() ); } else { SetValue( ANIM_CONTROL_TXFORM_POSITION, pTransformControl->GetPosition() ); } } } else { if ( m_bStereo ) { SetValue( ANIM_CONTROL_VALUE_LEFT, m_hControl->GetValue< float >( "leftValue" ) ); SetValue( ANIM_CONTROL_VALUE_RIGHT, m_hControl->GetValue< float >( "rightValue" ) ); } else { SetValue( ANIM_CONTROL_VALUE, m_hControl->GetValue< float >( "value" ) ); } } }
void CAttributeSlider::SetValue( AnimationControlType_t type, float flValue ) { Assert( type < ANIM_CONTROL_COUNT ); if ( m_Control.m_pValue[type] != flValue ) { m_Control.m_pValue[type] = flValue; } }
void CAttributeSlider::SetValue( const AttributeValue_t& value ) { for ( int i = 0; i < ANIM_CONTROL_COUNT; ++i ) { SetValue( (AnimationControlType_t)i, value.m_pValue[i] ); } SetValue( ANIM_CONTROL_TXFORM_POSITION, value.m_Vector ); SetValue( ANIM_CONTROL_TXFORM_ORIENTATION, value.m_Quaternion ); }
void CAttributeSlider::SetValue( AnimationControlType_t type, const Vector &vec ) { Assert( type == ANIM_CONTROL_TXFORM_POSITION ); if ( m_Control.m_Vector != vec ) { m_Control.m_Vector = vec; } }
void CAttributeSlider::SetValue( AnimationControlType_t type, const Quaternion &quat ) { Assert( type == ANIM_CONTROL_TXFORM_ORIENTATION ); if ( m_Control.m_Quaternion != quat ) { m_Control.m_Quaternion = quat; } }
const AttributeValue_t& CAttributeSlider::GetValue() const { return m_Control; }
float CAttributeSlider::GetValue( AnimationControlType_t type ) const { Assert( type < ANIM_CONTROL_COUNT ); return m_Control.m_pValue[type]; }
void CAttributeSlider::GetValue( AnimationControlType_t type, Vector &out ) const { Assert( type == ANIM_CONTROL_TXFORM_POSITION ); out = m_Control.m_Vector; }
void CAttributeSlider::GetValue( AnimationControlType_t type, Quaternion &out ) const { Assert( type == ANIM_CONTROL_TXFORM_ORIENTATION ); out = m_Control.m_Quaternion; }
float CAttributeSlider::GetPreview( AnimationControlType_t type ) const { Assert( type < ANIM_CONTROL_COUNT ); return m_PreviewCurrent.m_pValue[type]; }
void CAttributeSlider::GetPreview( AnimationControlType_t type, Vector &out ) const { Assert( type == ANIM_CONTROL_TXFORM_POSITION ); out = m_PreviewCurrent.m_Vector; }
void CAttributeSlider::GetPreview( AnimationControlType_t type, Quaternion &out ) const { Assert( type == ANIM_CONTROL_TXFORM_ORIENTATION ); out = m_PreviewCurrent.m_Quaternion; }
//-----------------------------------------------------------------------------
// Purpose: Set the flags controlling which specific components of the slider
// are visible.
//-----------------------------------------------------------------------------
void CAttributeSlider::SetVisibleComponents( LogComponents_t componentFlags ) { m_nVisibleComponents = componentFlags; }
//-----------------------------------------------------------------------------
// Purpose: Get the set of flags specifying which components of the slider are
// visible.
//-----------------------------------------------------------------------------
LogComponents_t CAttributeSlider::VisibleComponents() const { return m_nVisibleComponents; }
void CAttributeSlider::OnCursorEntered() { if ( IsDragging() ) return;
BaseClass::OnCursorEntered(); m_pParent->GetController()->SetActiveAttributeSlider( this ); } void CAttributeSlider::OnCursorExited() { if ( IsDragging() ) return;
BaseClass::OnCursorExited(); m_pParent->GetController()->SetActiveAttributeSlider( NULL ); }
void CAttributeSlider::SetToDefault() { if ( m_bTransform ) { if ( m_bOrientation ) { const Quaternion &quat = m_hControl->GetValue< Quaternion >( DEFAULT_ORIENTATION_ATTR ); SetValue( ANIM_CONTROL_TXFORM_ORIENTATION, quat );
CUndoScopeGuard guard( "Set Slider Value To Default" );
StampValueIntoLogs( ANIM_CONTROL_TXFORM_ORIENTATION, quat ); } else { const Vector &vec = m_hControl->GetValue< Vector >( DEFAULT_POSITION_ATTR ); SetValue( ANIM_CONTROL_TXFORM_POSITION, vec );
CUndoScopeGuard guard( "Set Slider Value To Default" );
StampValueIntoLogs( ANIM_CONTROL_TXFORM_POSITION, vec ); } } else { float flDefaultValue = m_hControl->GetValue< float >( DEFAULT_FLOAT_ATTR ); if ( m_bStereo ) { SetValue( ANIM_CONTROL_VALUE_LEFT, flDefaultValue ); SetValue( ANIM_CONTROL_VALUE_RIGHT, flDefaultValue );
CUndoScopeGuard guard( "Set Slider Value To Default" );
StampValueIntoLogs( ANIM_CONTROL_VALUE_LEFT, flDefaultValue ); StampValueIntoLogs( ANIM_CONTROL_VALUE_RIGHT, flDefaultValue ); } else { SetValue( ANIM_CONTROL_VALUE, flDefaultValue );
CUndoScopeGuard guard( "Set Slider Value To Default" );
StampValueIntoLogs( ANIM_CONTROL_VALUE, flDefaultValue ); } } }
void CAttributeSlider::OnSetToDefault() { SetToDefault(); }
void CAttributeSlider::OnEditMinMaxDefault() { CDmeChannel *pChannel = m_hControl->GetValueElement< CDmeChannel >( "channel" ); if ( !pChannel ) return;
CDmeExpressionOperator *pExpr = CastElement< CDmeExpressionOperator >( pChannel->GetToElement() ); if ( !pExpr ) return;
if ( m_bStereo ) return;
float flMin = pExpr->GetValue< float >( "lo" ); float flMax = pExpr->GetValue< float >( "hi" ); float flDefault = m_hControl->GetValue< float >( "defaultValue" ); flDefault = flMin + flDefault * ( flMax - flMin );
MultiInputDialog *pDialog = new MultiInputDialog( this, "Edit Min/Max/Default" ); pDialog->AddEntry( "min", "Min:", flMin ); pDialog->AddEntry( "max", "Max:", flMax ); pDialog->AddEntry( "default", "Default:", flDefault ); pDialog->DoModal(); }
void CAttributeSlider::OnInputCompleted( KeyValues *params ) { CDmeChannel *pChannel = m_hControl->GetValueElement< CDmeChannel >( "channel" ); if ( !pChannel ) return;
CDmeExpressionOperator *pExpr = CastElement< CDmeExpressionOperator >( pChannel->GetToElement() ); if ( !pExpr ) return;
m_pParent->GetController()->OnSliderRangeRemapped();
float flOldMin = pExpr->GetValue< float >( "lo" ); float flOldMax = pExpr->GetValue< float >( "hi" ); float flOldValue = m_hControl->GetValue< float >( "value" ); flOldValue = flOldMin + flOldValue * ( flOldMax - flOldMin );
float flMin = params->GetFloat( "min" ); float flMax = params->GetFloat( "max" ); float flDefault = params->GetFloat( "default" ); flDefault = ( flDefault - flMin ) / ( flMax - flMin ); flOldValue = ( flOldValue - flMin ) / ( flMax - flMin );
CUndoScopeGuard sg( "Set Control Min/Max/Default" );
pExpr->SetValue( "lo", flMin ); pExpr->SetValue( "hi", flMax ); m_hControl->SetValue( "defaultValue", clamp( flDefault, 0.0f, 1.0f ) ); m_hControl->SetValue( "value", clamp( flOldValue, 0.0f, 1.0f ) );
float flBias = ( flOldMin - flMin ) / ( flMax - flMin ); float flScale = ( flOldMax - flOldMin ) / ( flMax - flMin ); RemapFloatLogValues( pChannel, flBias, flScale ); }
//-----------------------------------------------------------------------------
// Mouse event handlers
//-----------------------------------------------------------------------------
void CAttributeSlider::OnMousePressed( MouseCode code ) { if ( !IsEnabled() || IsInTextEntry() || IsDragging() ) return;
if ( code != MOUSE_LEFT ) return;
// Cache off the value at the click point
// in case we end up receiving a double-click
m_pParent->GetTypeInValueForControl( m_hControl, m_bOrientation, m_InitialTextEntryValue, m_Control );
if ( m_bTransform ) return;
// Determine which control we clicked on
int x,y; input()->GetCursorPosition( x, y ); ScreenToLocal( x, y );
// Enter drag mode
m_SliderMode = SLIDER_MODE_DRAG_VALUE; m_nDragStartPosition[ 0 ] = x; m_nDragStartPosition[ 1 ] = y; m_nAccum[ 0 ] = m_nAccum[ 1 ] = 0; m_dragStartValues = GetValue(); input()->SetMouseCapture( GetVPanel() ); SetCursor( dc_blank ); }
void CAttributeSlider::OnCursorMoved( int x, int y ) { if ( !IsEnabled() || !IsDragging() || m_bTransform ) return;
// NOTE: This works because we always slam the mouse to be back at the start position
// at the end of this function
// Accumulate the total mouse movement
int dx = x - m_nDragStartPosition[ 0 ]; m_nAccum[ 0 ] += dx;
float flFactor = 1.0f; if ( ifm_attributeslider_legacy.GetBool() ) { flFactor = FRAC_PER_PIXEL * ifm_attributeslider_sensitivity.GetFloat(); } else { Rect_t rect; GetControlRect( &rect ); // assumes controls are same width
if ( rect.width > 0 ) { flFactor = 1.0f / (float)rect.width; } }
bool bInRecordMode = m_pParent->GetEditor()->GetController()->GetRecordingState() == AS_RECORD; float flMinVal = bInRecordMode ? -1.0f : 0.0f; float flMaxVal = bInRecordMode ? 2.0f : 1.0f;
if ( m_bStereo ) { float flBalance = m_pParent->GetBalanceSliderValue();
float flLeftValue = m_dragStartValues.m_pValue[ ANIM_CONTROL_VALUE_LEFT ]; float flRightValue = m_dragStartValues.m_pValue[ ANIM_CONTROL_VALUE_RIGHT ];
int nMinVal = floor( ( flMinVal - MAX( flLeftValue, flRightValue ) ) / flFactor ); int nMaxVal = ceil ( ( flMaxVal - MIN( flLeftValue, flRightValue ) ) / flFactor ); m_nAccum[ 0 ] = clamp( m_nAccum[ 0 ], nMinVal, nMaxVal ); float flDelta = flFactor * m_nAccum[ 0 ];
float flLeftDelta, flRightDelta; ValueBalanceToLeftRight( &flLeftDelta, &flRightDelta, flDelta, flBalance, 0.0f );
flLeftValue = clamp( flLeftValue + flLeftDelta, flMinVal, flMaxVal ); flRightValue = clamp( flRightValue + flRightDelta, flMinVal, flMaxVal );
SetValue( ANIM_CONTROL_VALUE_LEFT, flLeftValue ); SetValue( ANIM_CONTROL_VALUE_RIGHT, flRightValue ); } else { AnimationControlType_t type = ANIM_CONTROL_VALUE;
float flValue = m_dragStartValues.m_pValue[ type ]; int nMinVal = floor( ( flMinVal - flValue ) / flFactor ); int nMaxVal = ceil ( ( flMaxVal - flValue ) / flFactor ); m_nAccum[ 0 ] = clamp( m_nAccum[ 0 ], nMinVal, nMaxVal ); float flDelta = flFactor * m_nAccum[ 0 ];
flValue = clamp( flValue + flDelta, flMinVal, flMaxVal ); SetValue( type, flValue ); }
// Slam the cursor back to the drag start point
if ( x != m_nDragStartPosition[ 0 ] || y != m_nDragStartPosition[ 1 ] ) { x = m_nDragStartPosition[ 0 ]; y = m_nDragStartPosition[ 1 ]; LocalToScreen( x, y ); input()->SetCursorPos( x, y ); } }
void CAttributeSlider::OnMouseReleased( MouseCode code ) { if ( !IsEnabled() || m_bTransform ) return;
if ( code == MOUSE_RIGHT ) { if ( m_hContextMenu.Get() ) { delete m_hContextMenu.Get(); m_hContextMenu = NULL; }
m_hContextMenu = new Menu( this, "ActionMenu" );
int x,y; input()->GetCursorPosition( x, y ); ScreenToLocal( x, y ); m_hContextMenu->AddMenuItem( "Set To Default", new KeyValues( "SetToDefault" ), this );
if ( CDmeChannel *pChannel = m_hControl->GetValueElement< CDmeChannel >( "channel" ) ) { CDmElement *pToElement = pChannel->GetToElement(); if ( pToElement && pToElement->IsA< CDmeExpressionOperator >() ) { m_hContextMenu->AddMenuItem( "Edit Min/Max/Default...", new KeyValues( "EditMinMaxDefault" ), this ); } }
Menu::PlaceContextMenu( this, m_hContextMenu.Get() ); return; }
if ( !IsDragging() ) return;
m_SliderMode = SLIDER_MODE_NONE; input()->SetMouseCapture( NULL ); SetCursor( dc_arrow );
m_pParent->UpdatePreview( "Attribute Slider Released" ); }
//-----------------------------------------------------------------------------
//
// Methods related to text entry mode
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Called by the text entry code to enter the value into the logs
//-----------------------------------------------------------------------------
void CAttributeSlider::StampValueIntoLogs( AnimationControlType_t type, float flValue ) { Assert( !m_bTransform ); Assert( type < ANIM_CONTROL_COUNT ); m_pParent->StampValueIntoLogs( m_hControl, type, flValue ); }
void CAttributeSlider::StampValueIntoLogs( AnimationControlType_t type, const Vector &vecValue ) { Assert( m_bTransform ); Assert( type == ANIM_CONTROL_TXFORM_POSITION || type == ANIM_CONTROL_TXFORM_ORIENTATION ); m_pParent->StampValueIntoLogs( m_hControl, type, vecValue ); }
void CAttributeSlider::StampValueIntoLogs( AnimationControlType_t type, const Quaternion &qValue ) { Assert( m_bTransform ); Assert( type == ANIM_CONTROL_TXFORM_ORIENTATION ); m_pParent->StampValueIntoLogs( m_hControl, type, qValue ); }
//-----------------------------------------------------------------------------
// Key typed key handler
//-----------------------------------------------------------------------------
void CAttributeSlider::OnKeyCodeTyped( KeyCode code ) { if ( !IsInTextEntry() ) { BaseClass::OnKeyCodeTyped( code ); return; }
switch ( code ) { default: BaseClass::OnKeyCodeTyped( code ); break;
case KEY_ESCAPE: DiscardTextEntryValue(); break;
case KEY_ENTER: AcceptTextEntryValue(); break; } }
void CAttributeSlider::SetupTextFieldForTextEntryMode( CAttributeSliderTextEntry *&pTextField, const char *pText, bool bRequestFocus ) { if ( !pTextField ) { pTextField = new CAttributeSliderTextEntry( this, GetName() ); pTextField->SetVisible( false ); pTextField->SetEnabled( false ); pTextField->SelectAllOnFocusAlways( true ); InvalidateLayout(); }
pTextField->SetVisible( true ); pTextField->SetEnabled( true );
pTextField->SetText( pText );
pTextField->GotoTextEnd(); if ( bRequestFocus ) { pTextField->RequestFocus(); } }
//-----------------------------------------------------------------------------
// Methods to entry text entry mode
//-----------------------------------------------------------------------------
void CAttributeSlider::EnterTextEntryMode( bool bRelatchValues ) { m_SliderMode = SLIDER_MODE_TEXT;
// For double-clicking, ignore the value set by the first single mouse click
if ( !bRelatchValues ) { SetValue( m_InitialTextEntryValue ); }
if ( !IsTransform() ) { if ( m_bStereo ) { char val[ 64 ]; V_snprintf( val, sizeof( val ), "%f", m_InitialTextEntryValue.m_pValue[ ANIM_CONTROL_VALUE_LEFT ] ); SetupTextFieldForTextEntryMode( m_pTextField, val, true );
V_snprintf( val, sizeof( val ), "%f", m_InitialTextEntryValue.m_pValue[ ANIM_CONTROL_VALUE_RIGHT ] ); SetupTextFieldForTextEntryMode( m_pRightTextField, val, false ); } else { char val[ 64 ]; Q_snprintf( val, sizeof( val ), "%f", m_InitialTextEntryValue.m_pValue[ ANIM_CONTROL_VALUE ] ); SetupTextFieldForTextEntryMode( m_pTextField, val, true ); } } else { char val[ 128 ]; Q_snprintf( val, sizeof( val ), "%f %f %f", VectorExpand( m_InitialTextEntryValue.m_Vector ) ); SetupTextFieldForTextEntryMode( m_pTextField, val, true ); } }
//-----------------------------------------------------------------------------
// Methods to accept or discard the value in the text entry field
//-----------------------------------------------------------------------------
void CAttributeSlider::AcceptTextEntryValue() { if ( !IsInTextEntry() ) return;
// Get the value in the text entry field
char buf[ 64 ]; m_pTextField->GetText( buf, sizeof( buf ) ); // Hide the text entry
m_pTextField->SetVisible( false ); m_pTextField->SetEnabled( false );
CDmeTransformControl *pTransformControl = CastElement< CDmeTransformControl >( m_hControl );
if ( !IsTransform() ) { float flValue = Q_atof( buf );
if ( m_bStereo ) { float flLeftValue = flValue; SetValue( ANIM_CONTROL_VALUE_LEFT, flLeftValue ); StampValueIntoLogs( ANIM_CONTROL_VALUE_LEFT, flLeftValue );
// Get the value in the text entry field
char buf[ 64 ]; m_pRightTextField->GetText( buf, sizeof( buf ) ); float flRightValue = Q_atof( buf );
// Hide the text entry
m_pRightTextField->SetVisible( false ); m_pRightTextField->SetEnabled( false );
SetValue( ANIM_CONTROL_VALUE_RIGHT, flRightValue ); StampValueIntoLogs( ANIM_CONTROL_VALUE_RIGHT, flRightValue ); } else { SetValue( ANIM_CONTROL_VALUE, flValue ); StampValueIntoLogs( ANIM_CONTROL_VALUE, flValue ); } } else if ( pTransformControl ) { Vector vecValue; if ( 3 == sscanf( buf, "%f %f %f", &vecValue.x, &vecValue.y, &vecValue.z ) ) { if ( !m_bOrientation ) { SetValue( ANIM_CONTROL_TXFORM_POSITION, vecValue ); StampValueIntoLogs( ANIM_CONTROL_TXFORM_POSITION, vecValue ); } else { StampValueIntoLogs( ANIM_CONTROL_TXFORM_ORIENTATION, vecValue ); SetValue( ANIM_CONTROL_TXFORM_ORIENTATION, pTransformControl->GetOrientation() );
/*
QAngle angValue; if ( 3 == sscanf( buf, "%f %f %f", &angValue.x, &angValue.y, &angValue.z ) ) { // Convert back to a quat
Quaternion qValue; AngleQuaternion( angValue, qValue );
SetValue( ANIM_CONTROL_TXFORM_ORIENTATION, qValue ); StampValueIntoLogs( ANIM_CONTROL_TXFORM_ORIENTATION, qValue ); } */ } }
m_pParent->UpdatePreview( "AcceptTextEntryValue\n" ); }
m_SliderMode = SLIDER_MODE_NONE; RequestFocus(); }
void CAttributeSlider::DiscardTextEntryValue() { if ( !IsInTextEntry() ) return;
// Hide the text entry
m_pTextField->SetVisible( false ); m_pTextField->SetEnabled( false );
if ( m_bStereo ) { m_pRightTextField->SetVisible( false ); m_pRightTextField->SetEnabled( false ); }
m_SliderMode = SLIDER_MODE_NONE; RequestFocus(); }
//-----------------------------------------------------------------------------
// Methods of the text entry widget
//-----------------------------------------------------------------------------
void CAttributeSliderTextEntry::OnKillFocus( KeyValues *pParams ) { Assert( m_pSlider );
SelectNone();
VPANEL hPanel = (VPANEL)pParams->GetPtr( "newPanel" ); if ( hPanel != INVALID_PANEL && vgui::ipanel()->GetParent( hPanel ) == m_pSlider->GetVPanel() ) return;
m_pSlider->AcceptTextEntryValue(); }
void CAttributeSliderTextEntry::OnMouseWheeled( int delta ) { if ( m_pSlider->IsTransform() ) return;
if ( m_pSlider->IsStereo() ) return;
float deltaFactor; if ( input()->IsKeyDown(KEY_LSHIFT) ) { deltaFactor = ((float)delta) * 10.0f; } else if ( input()->IsKeyDown(KEY_LCONTROL) ) { deltaFactor = ((float)delta) / 100.0; } else { deltaFactor = ((float)delta) / 10.0; }
char sz[ 64 ]; GetText( sz, sizeof( sz ) );
float val = Q_atof( sz ) + deltaFactor; if ( input()->IsKeyDown(KEY_LALT) ) { val = clamp( val, 0.0f, 1.0f ); }
Q_snprintf( sz, sizeof( sz ), "%f", val );
SetText( sz ); m_pSlider->SetValue( ANIM_CONTROL_VALUE, val );
CUndoScopeGuard guard( UNDO_CHAIN_MOUSEWHEEL_ATTRIBUTE_SLIDER, "Set Slider Value" );
m_pSlider->StampValueIntoLogs( ANIM_CONTROL_VALUE, val ); }
void CAttributeSlider::OnMouseDoublePressed( MouseCode code ) { if ( !IsEnabled() || IsDragging() ) return;
if ( code != MOUSE_LEFT ) return;
int x,y; input()->GetCursorPosition( x, y ); ScreenToLocal( x, y ); EnterTextEntryMode( false ); }
//-----------------------------------------------------------------------------
//
// Methods related to preview
//
//-----------------------------------------------------------------------------
void CAttributeSlider::UpdateFaderAmount( float flAmount ) { m_flFaderAmount = flAmount; BlendValues( m_bTransform, &m_PreviewCurrent, GetValue(), m_PreviewFull, flAmount ); }
void CAttributeSlider::SetPreview( const AttributeValue_t &value, const AttributeValue_t &full ) { m_PreviewCurrent = value; m_PreviewFull = full; }
const AttributeValue_t &CAttributeSlider::GetPreview() const { return m_PreviewCurrent; }
const AttributeValue_t &CAttributeSlider::GetPreviewFull() const { return m_PreviewFull; }
// Estimates the value of the control given a local coordinate
float CAttributeSlider::EstimateValueAtPos( int nLocalX, int nLocalY ) const { Rect_t rect; GetControlRect( &rect ); // assumes controls are same width
float flFactor = rect.width > 1 ? (float)( nLocalX - rect.x ) / (float)( rect.width - 1 ) : 0.5f; flFactor = clamp( flFactor, 0.0f, 1.0f ); return flFactor; }
//-----------------------------------------------------------------------------
// Layout
//-----------------------------------------------------------------------------
void CAttributeSlider::PerformLayout() { BaseClass::PerformLayout();
if ( !m_pTextField ) return;
Rect_t rect; GetControlRect( &rect );
// Place the text entry along the main attribute track rectangle
if ( m_bStereo ) { m_pTextField ->SetBounds( rect.x, rect.y, rect.width / 2, rect.height ); m_pRightTextField->SetBounds( rect.x + rect.width / 2, rect.y, rect.width / 2, rect.height ); } else { m_pTextField->SetBounds( rect.x, rect.y, rect.width, rect.height ); } }
void CAttributeSlider::GetControlRect( Rect_t *pRect ) const { int sw, sh; const_cast<CAttributeSlider*>( this )->GetSize( sw, sh );
pRect->x = 2 * SLIDER_PIXEL_SPACING; pRect->y = SLIDER_PIXEL_SPACING; pRect->width = sw - pRect->x * 2; pRect->height = MAX( 0, sh - SLIDER_PIXEL_SPACING * 2 ); }
//-----------------------------------------------------------------------------
//
// Methods related to painting start here
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Used to control how fader-driven ticks look
//-----------------------------------------------------------------------------
float CAttributeSlider::GetPreviewAlphaScale() const { return MAX( m_flFaderAmount, 0.1f ); }
//-----------------------------------------------------------------------------
// Draws a tick on the main control
//-----------------------------------------------------------------------------
void DrawTick( float flValue, int xbase, int nTotalWidth, int nTickWidth, int y, int nHeight ) { int x = xbase + (int)( flValue * (float)nTotalWidth + 0.5f ) - nTickWidth / 2; x = clamp( x, xbase, xbase + nTotalWidth - nTickWidth ); surface()->DrawFilledRect( x, y, x + nTickWidth, y + nHeight ); }
void CAttributeSlider::DrawTick( const Color& clr, const AttributeValue_t &value, int width, int inset ) { surface()->DrawSetColor( clr );
// Get the control position
Rect_t rect; GetControlRect( &rect );
// Inset by 1 pixel
rect.x++; rect.y++; rect.width -= 2; rect.height -= 2;
int previewtall = rect.height - 2 * inset; int ypos = rect.y + ( rect.height - previewtall ) / 2;
if ( m_bStereo ) { previewtall /= 2; ::DrawTick( value.m_pValue[ ANIM_CONTROL_VALUE_LEFT ], rect.x, rect.width, width, ypos, previewtall ); ::DrawTick( value.m_pValue[ ANIM_CONTROL_VALUE_RIGHT ], rect.x, rect.width, width, ypos + previewtall, previewtall ); } else { ::DrawTick( value.m_pValue[ ANIM_CONTROL_VALUE ], rect.x, rect.width, width, ypos + previewtall, previewtall ); } }
//-----------------------------------------------------------------------------
// Paints ticks
//-----------------------------------------------------------------------------
void CAttributeSlider::Paint() { if ( IsTransform() ) return;
DrawTick( s_OldValueTickColor, GetValue(), 1, 0 );
bool shiftDown = input()->IsKeyDown( KEY_LSHIFT ) || input()->IsKeyDown( KEY_RSHIFT ); bool bPreviewingAttributeSlider = m_pParent->GetController()->GetActiveAttributeSlider() == this && !IsDragging() && shiftDown; bool bMouseOverPreviewSlider = m_pParent->GetEditor()->GetPresetFader()->GetActivePresetSlider() ? true : false; if ( bPreviewingAttributeSlider || bMouseOverPreviewSlider ) { Color col = s_PreviewTickColor; col[ 3 ] *= GetPreviewAlphaScale();
DrawTick( col, m_PreviewFull, 2, 2 ); } }
//-----------------------------------------------------------------------------
// Draws the min, current, and max values for the slider
//-----------------------------------------------------------------------------
void CAttributeSlider::DrawValueLabel() { if ( IsTransform() ) return;
float flMinVal = 0.0f; float flMaxVal = 1.0f;
Rect_t rect; GetControlRect( &rect );
int cw, ch; char sz[ 32 ]; Q_snprintf( sz, sizeof( sz ), "%.1f", flMinVal ); m_pValues[ 0 ]->SetText( sz ); m_pValues[ 0 ]->ResizeImageToContent(); m_pValues[ 0 ]->GetContentSize( cw, ch ); m_pValues[ 0 ]->SetPos( rect.x + 5, rect.y + ( rect.height - ch ) * 0.5f ); m_pValues[ 0 ]->Paint();
Q_snprintf( sz, sizeof( sz ), "%.1f", flMaxVal ); m_pValues[ 1 ]->SetText( sz ); m_pValues[ 1 ]->ResizeImageToContent(); m_pValues[ 1 ]->GetContentSize( cw, ch ); m_pValues[ 1 ]->SetPos( rect.x + rect.width - cw - 5, rect.y + ( rect.height - ch ) * 0.5f ); m_pValues[ 1 ]->Paint();
if ( m_bStereo ) { float flLeftValue = clamp( GetValue().m_pValue[ ANIM_CONTROL_VALUE_LEFT ], flMinVal, flMaxVal ); Q_snprintf( sz, sizeof( sz ), "%.3f", flLeftValue ); m_pValues[ 2 ]->SetText( sz ); m_pValues[ 2 ]->ResizeImageToContent(); m_pValues[ 2 ]->GetContentSize( cw, ch ); m_pValues[ 2 ]->SetPos( rect.x + ( rect.width - cw ) * 0.4f, rect.y + ( rect.height - ch ) * 0.5f ); m_pValues[ 2 ]->Paint();
float flRightValue = clamp( GetValue().m_pValue[ ANIM_CONTROL_VALUE_RIGHT ], flMinVal, flMaxVal ); Q_snprintf( sz, sizeof( sz ), "%.3f", flRightValue ); m_pValues[ 3 ]->SetText( sz ); m_pValues[ 3 ]->ResizeImageToContent(); m_pValues[ 3 ]->GetContentSize( cw, ch ); m_pValues[ 3 ]->SetPos( rect.x + ( rect.width - cw ) * 0.6f, rect.y + ( rect.height - ch ) * 0.5f ); m_pValues[ 3 ]->Paint(); } else { float flValue = clamp( GetValue().m_pValue[ ANIM_CONTROL_VALUE ], flMinVal, flMaxVal ); Q_snprintf( sz, sizeof( sz ), "%.3f", flValue ); m_pValues[ 2 ]->SetText( sz ); m_pValues[ 2 ]->ResizeImageToContent(); m_pValues[ 2 ]->GetContentSize( cw, ch ); m_pValues[ 2 ]->SetPos( rect.x + ( rect.width - cw ) * 0.5f, rect.y + ( rect.height - ch ) * 0.5f ); m_pValues[ 2 ]->Paint(); } }
//-----------------------------------------------------------------------------
// Draws the text for the slider. It's either the slider name, or its value if dragging is happening
//-----------------------------------------------------------------------------
void CAttributeSlider::DrawNameLabel() { if ( IsDragging() ) { DrawValueLabel(); return; }
if ( IsInTextEntry() ) return;
if ( !m_pName ) return;
int cw, ch;
Color clr = s_TextColor; if ( m_pParent->GetController()->GetActiveAttributeSlider() == this ) { clr = s_TextColorFocus; } else if ( m_bDependent ) { clr = s_TextColorDependent; }
m_pName->SetColor( clr ); m_pName->GetContentSize( cw, ch );
Rect_t rect; GetControlRect( &rect );
m_pName->SetPos( rect.x + ( rect.width - cw ) * 0.5f, rect.y + ( rect.height - ch ) * 0.5f ); m_pName->Paint(); }
//-----------------------------------------------------------------------------
// Draws the midpoint value for the slider
//-----------------------------------------------------------------------------
void CAttributeSlider::DrawMidpoint( int x, int ty, int ttall ) { if ( IsTransform() ) return; surface()->DrawSetColor( s_MidpointColor ); surface()->DrawFilledRect( x, ty, x + 1, ty + ttall ); }
//-----------------------------------------------------------------------------
// Paints the slider
//-----------------------------------------------------------------------------
void CAttributeSlider::PaintBackground() { Rect_t rect; GetControlRect( &rect );
// Paint the border
surface()->DrawSetColor( Color( 24, 24, 24, 255 ) ); // top and left
surface()->DrawOutlinedRect( rect.x, rect.y, rect.x + rect.width, rect.y + 1 ); surface()->DrawOutlinedRect( rect.x, rect.y, rect.x + 1, rect.y + rect.height ); // right
surface()->DrawSetColor( Color( 33, 33, 33, 255 ) ); surface()->DrawOutlinedRect( rect.x + rect.width - 1, rect.y, rect.x + rect.width, rect.y + rect.height ); // bottom
surface()->DrawSetColor( Color( 56, 56, 56, 255 ) ); surface()->DrawOutlinedRect( rect.x, rect.y + rect.height - 1, rect.x + rect.width, rect.y + rect.height );
// Inset the rect by 1 pixel
++rect.x; ++rect.y; rect.width -= 2; rect.height -= 2;
int y0 = rect.y; int y1 = rect.y + rect.height / 2; int y2 = rect.y + rect.height;
bool bIsLogPreviewControl = ( m_pParent->GetController()->GetActiveAttributeSlider() == this );
// Draw the main bar background
surface()->DrawSetColor( s_ZeroColor[ bIsLogPreviewControl ] ); surface()->DrawFilledRect( rect.x, y0, rect.x + rect.width, y2 );
if ( IsInTextEntry() ) return;
if ( !IsTransform() ) { CBaseAnimationSetControl *pController = m_pParent->GetController(); bool shiftDown = input()->IsKeyDown( KEY_LSHIFT ) || input()->IsKeyDown( KEY_RSHIFT ); bool bPreviewingAttributeSlider = pController->GetActiveAttributeSlider() == this && !IsDragging() && shiftDown;
bool bDraggingPreviewSlider = pController->IsPresetFaderBeingDragged(); bool bPreviewingPreset = pController->WasPreviouslyHoldingPresetPreviewKey();
bool bUsePreview = bPreviewingAttributeSlider || bDraggingPreviewSlider || bPreviewingPreset;
float flDefaultValue = m_hControl->GetValue< float >( DEFAULT_FLOAT_ATTR ); int nMidPoint = (int)( (float)rect.width * clamp( flDefaultValue, 0.0f, 1.0f ) + 0.5f );
if ( m_bStereo ) { const AttributeValue_t &value = bUsePreview ? m_PreviewCurrent : GetValue(); float flLeftValue = value.m_pValue[ ANIM_CONTROL_VALUE_LEFT ]; float flRightValue = value.m_pValue[ ANIM_CONTROL_VALUE_RIGHT ];
int nLeftValue = (int)( (float)rect.width * clamp( flLeftValue, 0.0f, 1.0f ) + 0.5f ); int nRightValue = (int)( (float)rect.width * clamp( flRightValue, 0.0f, 1.0f ) + 0.5f );
// Draw the current value as a bar from the midpoint
surface()->DrawSetColor( IsDragging() ? s_DraggingBarColor : s_BarColor[ bIsLogPreviewControl ] ); surface()->DrawFilledRect( rect.x + MIN( nLeftValue, nMidPoint ), y0, rect.x + MAX( nLeftValue, nMidPoint ), y1 ); surface()->DrawFilledRect( rect.x + MIN( nRightValue, nMidPoint ), y1, rect.x + MAX( nRightValue, nMidPoint ), y2 ); } else { const AttributeValue_t &value = bUsePreview ? m_PreviewCurrent : GetValue(); float flValue = value.m_pValue[ ANIM_CONTROL_VALUE ]; int nValue = (int)( (float)rect.width * clamp( flValue, 0.0f, 1.0f ) + 0.5f );
// Draw the current value as a bar from the midpoint
surface()->DrawSetColor( IsDragging() ? s_DraggingBarColor : s_BarColor[ bIsLogPreviewControl ] ); surface()->DrawFilledRect( rect.x + MIN( nValue, nMidPoint ), y0, rect.x + MAX( nValue, nMidPoint ), y2 ); }
// Draw the midpoint over the top of the current value
DrawMidpoint( rect.x + nMidPoint, rect.y, rect.height ); }
// Draw the name or value over the top of that
DrawNameLabel(); }
//-----------------------------------------------------------------------------
// Manipulate in/out curve types
//-----------------------------------------------------------------------------
void CAttributeSlider::OnCurve1() { m_pParent->DispatchCurve( 1 ); }
void CAttributeSlider::OnCurve2() { m_pParent->DispatchCurve( 2 ); }
void CAttributeSlider::OnCurve3() { m_pParent->DispatchCurve( 3 ); }
void CAttributeSlider::OnCurve4() { m_pParent->DispatchCurve( 4 ); }
//-----------------------------------------------------------------------------
//
// Slider dependency functions, provide management and information about the
// other sliders on which the function of this slider depends.
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Purpose: Clear the list of sliders that this slider is dependent on
//-----------------------------------------------------------------------------
void CAttributeSlider::ClearDependencies() { m_Dependenices.RemoveAll(); }
//-----------------------------------------------------------------------------
// Purpose: Add a slider to the list of sliders this slider is dependent on
//-----------------------------------------------------------------------------
bool CAttributeSlider::AddDependency( const CAttributeSlider* pSlider ) { if ( pSlider == NULL ) return false;
// Make sure the slider is not already in the dependency list
if ( m_Dependenices.Find( pSlider ) != m_Dependenices.InvalidIndex() ) return false;
m_Dependenices.AddToTail( pSlider ); return true; }
//-----------------------------------------------------------------------------
// Purpose: Check the dependency list to see the operation of this slider is
// dependent of the specified slider.
//-----------------------------------------------------------------------------
bool CAttributeSlider::IsDependent( const CAttributeSlider* pSlider ) const { return ( m_Dependenices.Find( pSlider) != m_Dependenices.InvalidIndex() ); }
//-----------------------------------------------------------------------------
// Purpose: Set the flag indicating that the operation of the slider is
// dependent on the currently selected slider.
//-----------------------------------------------------------------------------
void CAttributeSlider::SetDependent( bool dependent ) { m_bDependent = dependent; }
|