diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /vgui2/dme_controls/ChannelGraphPanel.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'vgui2/dme_controls/ChannelGraphPanel.cpp')
| -rw-r--r-- | vgui2/dme_controls/ChannelGraphPanel.cpp | 368 |
1 files changed, 368 insertions, 0 deletions
diff --git a/vgui2/dme_controls/ChannelGraphPanel.cpp b/vgui2/dme_controls/ChannelGraphPanel.cpp new file mode 100644 index 0000000..b7b1ed9 --- /dev/null +++ b/vgui2/dme_controls/ChannelGraphPanel.cpp @@ -0,0 +1,368 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +//=============================================================================// + +#include <math.h> + +#include <dme_controls/ChannelGraphPanel.h> +#include <vgui/IScheme.h> +#include <vgui/ISurface.h> +#include <vgui/IVGui.h> +#include "vgui/IInput.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + +using namespace vgui; + +DECLARE_BUILD_FACTORY( CChannelGraphPanel ); + +//----------------------------------------------------------------------------- +// Purpose: Constructor +//----------------------------------------------------------------------------- +CChannelGraphPanel::CChannelGraphPanel( Panel *parent, const char *name ) + : BaseClass( parent, name ), m_font( 0 ), + m_graphMinTime( 0 ), m_graphMaxTime( 0 ), + m_graphMinValue( 0.0f ), m_graphMaxValue( 0.0f ), + m_nMouseStartX( -1 ), m_nMouseStartY( -1 ), + m_nMouseLastX( -1 ), m_nMouseLastY( -1 ), + m_nTextBorder( 2 ), m_nGraphOriginX( 40 ), m_nGraphOriginY( 10 ) +{ +} + + +void CChannelGraphPanel::SetChannel( CDmeChannel *pChannel ) +{ + m_hChannel = pChannel; + CDmeLog *pLog = m_hChannel->GetLog(); + m_graphMinTime = pLog->GetBeginTime(); + m_graphMaxTime = pLog->GetEndTime(); + + m_graphMinValue = FLT_MAX; + m_graphMaxValue = -FLT_MAX; + + int nComponents = NumComponents( pLog->GetDataType() ); + int nKeys = pLog->GetKeyCount(); + for ( int k = 0; k < nKeys; ++k ) + { + DmeTime_t t = pLog->GetKeyTime( k ); + for ( int i = 0; i < nComponents; ++i ) + { + float f = pLog->GetComponent( t, i ); + m_graphMinValue = min( m_graphMinValue, f ); + m_graphMaxValue = max( m_graphMaxValue, f ); + } + } +} + +//----------------------------------------------------------------------------- +// input methods +//----------------------------------------------------------------------------- +void CChannelGraphPanel::OnSizeChanged( int newWide, int newTall ) // called after the size of a panel has been changed +{ + int wide = newWide - m_nGraphOriginX; + int tall = newTall - m_nGraphOriginY; + m_flTimeToPixel = wide / ( m_graphMaxTime - m_graphMinTime ).GetSeconds(); + m_flValueToPixel = tall / ( m_graphMaxValue - m_graphMinValue ); +} + +void CChannelGraphPanel::OnMousePressed( MouseCode code ) +{ + BaseClass::OnMousePressed( code ); + if ( code != MOUSE_LEFT ) + return; + + vgui::input()->GetCursorPos( m_nMouseStartX, m_nMouseStartY ); + ScreenToLocal( m_nMouseStartX, m_nMouseStartY ); + m_nMouseLastX = m_nMouseStartX; + m_nMouseLastY = m_nMouseStartY; + + input()->SetMouseCapture( GetVPanel() ); +} + +void CChannelGraphPanel::OnMouseReleased( MouseCode code ) +{ + BaseClass::OnMouseReleased( code ); + if ( code != MOUSE_LEFT ) + return; + + m_nMouseStartX = m_nMouseStartY = -1; + m_nMouseLastX = m_nMouseLastY = -1; + + input()->SetMouseCapture( NULL ); +} + +void CChannelGraphPanel::OnCursorMoved( int mx, int my ) +{ + BaseClass::OnCursorMoved( mx, my ); + if ( !vgui::input()->IsMouseDown( MOUSE_LEFT ) ) + return; + + bool bInValueLegend = m_nMouseStartX < m_nGraphOriginX; + bool bInTimeLegend = m_nMouseStartY > GetTall() - m_nGraphOriginY - 1; + if ( bInTimeLegend && bInValueLegend ) + { + bInTimeLegend = bInValueLegend = false; + } + + int dx = mx - m_nMouseLastX; + int dy = my - m_nMouseLastY; + + if ( bInTimeLegend ) + { + if ( abs( dy ) > abs( dx ) ) + { + m_graphMinTime -= DmeTime_t( dy / m_flTimeToPixel ); + m_graphMaxTime += DmeTime_t( dy / m_flTimeToPixel ); + m_flTimeToPixel = ( GetWide() - m_nGraphOriginX ) / ( m_graphMaxTime - m_graphMinTime ).GetSeconds(); + + int x = mx = m_nMouseLastX; + int y = my = m_nMouseLastY; + LocalToScreen( x, y ); + vgui::input()->SetCursorPos( x, y ); + } + else + { + m_graphMinTime -= DmeTime_t( dx / m_flTimeToPixel ); + m_graphMaxTime -= DmeTime_t( dx / m_flTimeToPixel ); + } + } + else if ( bInValueLegend ) + { + if ( abs( dx ) > abs( dy ) ) + { + m_graphMinValue += dx / m_flValueToPixel; + m_graphMaxValue -= dx / m_flValueToPixel; + m_flValueToPixel = ( GetTall() - m_nGraphOriginY ) / ( m_graphMaxValue - m_graphMinValue ); + + int x = mx = m_nMouseLastX; + int y = my = m_nMouseLastY; + LocalToScreen( x, y ); + vgui::input()->SetCursorPos( x, y ); + } + else + { + m_graphMinValue += dy / m_flValueToPixel; + m_graphMaxValue += dy / m_flValueToPixel; + } + } + + m_nMouseLastX = mx; + m_nMouseLastY = my; +} + +void CChannelGraphPanel::OnMouseWheeled( int delta ) +{ + // TODO - zoom in around current time? +} + +//----------------------------------------------------------------------------- +// Purpose: lays out the graph +//----------------------------------------------------------------------------- +void CChannelGraphPanel::PerformLayout() +{ + BaseClass::PerformLayout(); +} + + +float GetDisplayIncrement( int windowpixels, int fontpixels, float valuerange, int *pDecimalPlaces = NULL ) +{ + float ratio = valuerange * fontpixels / ( windowpixels ); + int nPower = ( int )ceil( log10( ratio ) ); + if ( pDecimalPlaces ) + { + *pDecimalPlaces = max( 0, -nPower ); + } + return pow( 10.0f, nPower ); +} + +int CChannelGraphPanel::TimeToPixel( DmeTime_t time ) +{ + return m_nGraphOriginX + ( int )floor( m_flTimeToPixel * ( time - m_graphMinTime ).GetSeconds() + 0.5f ); +} + +int CChannelGraphPanel::ValueToPixel( float flValue ) +{ + return m_nGraphOriginY + ( int )floor( m_flValueToPixel * ( flValue - m_graphMinValue ) + 0.5f ); +} + +//----------------------------------------------------------------------------- +// Purpose: draws the graph +//----------------------------------------------------------------------------- +void CChannelGraphPanel::Paint() +{ + // estimate the size of the graph marker text + int wide = GetWide() - m_nGraphOriginX; + int tall = GetTall() - m_nGraphOriginY; + + int textwidth = 40, textheight = 10; + surface()->GetTextSize( m_font, L"999.9", textwidth, textheight ); + + // draw current time marker + DmeTime_t curtime = m_hChannel->GetCurrentTime(); + if ( curtime >= m_graphMinTime && curtime <= m_graphMaxTime ) + { + Color cyan( 0, 255, 255, 255 ); + surface()->DrawSetColor( cyan ); + int x = TimeToPixel( curtime ); + surface()->DrawLine( x, 0, x, GetTall() - m_nGraphOriginY - 1 ); + } + + // draw left/bottom graph border + Color black( 0, 0, 0, 255 ); + surface()->DrawSetColor( black ); + surface()->DrawLine( m_nGraphOriginX, GetTall() - m_nGraphOriginY - 1, GetWide(), GetTall() - m_nGraphOriginY - 1 ); + surface()->DrawLine( m_nGraphOriginX, GetTall() - m_nGraphOriginY - 1, m_nGraphOriginX, 0 ); + + surface()->DrawSetTextColor( black ); + surface()->DrawSetTextFont( m_font ); + + // draw graph tickmarks and values along the left border + int nDecimalPlaces = 0; + float flValueIncrement = GetDisplayIncrement( tall, ( int )( 1.5f * textheight ), m_graphMaxValue - m_graphMinValue, &nDecimalPlaces ); + int nMinValueIndex = ( int )ceil ( m_graphMinValue / flValueIncrement ); + int nMaxValueIndex = ( int )floor( m_graphMaxValue / flValueIncrement ); + float flValue = nMinValueIndex * flValueIncrement; + for ( int i = nMinValueIndex; i <= nMaxValueIndex; ++i, flValue += flValueIncrement ) + { + wchar_t pFormat[ 32 ]; + V_swprintf_safe( pFormat, L"%%.%df", nDecimalPlaces ); + + wchar_t wstring[ 32 ]; + V_swprintf_safe( wstring, pFormat, flValue ); + + int tw = 0, th = 0; + surface()->GetTextSize( m_font, wstring, tw, th ); + + int y = GetTall() - ValueToPixel( flValue ) - 1; + surface()->DrawSetTextPos( m_nGraphOriginX - m_nTextBorder - tw, y - textheight / 2 ); + surface()->DrawPrintText( wstring, wcslen( wstring ) ); + + surface()->DrawLine( m_nGraphOriginX - m_nTextBorder, y, m_nGraphOriginX, y ); + } + + // draw graph tickmarks and times along the bottom border + float flTimeIncrement = GetDisplayIncrement( wide, textwidth, ( m_graphMaxTime - m_graphMinTime ).GetSeconds(), &nDecimalPlaces ); + int nMinTimeIndex = ( int )ceil ( m_graphMinTime.GetSeconds() / flTimeIncrement ); + int nMaxTimeIndex = ( int )floor( m_graphMaxTime.GetSeconds() / flTimeIncrement ); + float flTime = nMinTimeIndex * flTimeIncrement; + for ( int i = nMinTimeIndex; i <= nMaxTimeIndex; ++i, flTime += flTimeIncrement ) + { + wchar_t pFormat[ 32 ]; + V_swprintf_safe( pFormat, L"%%.%df", nDecimalPlaces ); + + wchar_t wstring[ 32 ]; + V_swprintf_safe( wstring, pFormat, flTime ); + + int tw = 0, th = 0; + surface()->GetTextSize( m_font, wstring, tw, th ); + + int x = TimeToPixel( DmeTime_t( flTime ) ); + surface()->DrawSetTextPos( x - tw / 2, GetTall() - m_nGraphOriginY + m_nTextBorder - 1 ); + surface()->DrawPrintText( wstring, wcslen( wstring ) ); + + surface()->DrawLine( x, GetTall() - m_nGraphOriginY + m_nTextBorder - 1, x, GetTall() - m_nGraphOriginY - 1 ); + } + + static Color s_componentColors[] = + { + Color( 255, 0, 0, 255 ), + Color( 0, 255, 0, 255 ), + Color( 0, 0, 255, 255 ), + Color( 0, 0, 0, 255 ), + }; + + CDmeLog *pLog = m_hChannel->GetLog(); + int nComponents = NumComponents( pLog->GetDataType() ); + int nKeys = pLog->GetKeyCount(); + + // draw plotted graph + for ( int i = 0; i < nComponents; ++i ) + { + Color &color = s_componentColors[ i % ARRAYSIZE( s_componentColors ) ]; + surface()->DrawSetColor( color ); + + int lastx = -1; + int lasty = -1; + for ( int k = 0; k < nKeys; ++k ) + { + DmeTime_t t = pLog->GetKeyTime( k ); + float f = pLog->GetComponent( t, i ); + int x = TimeToPixel( t ); + int y = GetTall() - ValueToPixel( f ) - 1; + if ( k ) + { + surface()->DrawLine( lastx, lasty, x, y ); + } + lastx = x; + lasty = y; + } + } +} + +//----------------------------------------------------------------------------- +// Purpose: sets up colors +//----------------------------------------------------------------------------- +void CChannelGraphPanel::ApplySchemeSettings(IScheme *pScheme) +{ + BaseClass::ApplySchemeSettings(pScheme); + + m_font = pScheme->GetFont( "DefaultVerySmall" ); + + surface()->GetTextSize( m_font, L"999.9", m_nGraphOriginX, m_nGraphOriginY ); + m_nGraphOriginX += 2 * m_nTextBorder; + m_nGraphOriginY += 2 * m_nTextBorder; + + SetFgColor(GetSchemeColor("CChannelGraphPanel.FgColor", pScheme)); + SetBgColor(GetSchemeColor("CChannelGraphPanel.BgColor", pScheme)); + SetBorder(pScheme->GetBorder("ButtonDepressedBorder")); +} + + +//----------------------------------------------------------------------------- +// +// CChannelGraphFrame methods +// +//----------------------------------------------------------------------------- +CChannelGraphFrame::CChannelGraphFrame( Panel *parent, const char *pTitle ) +: BaseClass( parent, "CChannelGraphFrame" ) +{ + SetTitle( pTitle, true ); + + SetSizeable( true ); + SetCloseButtonVisible( true ); + SetMinimumSize( 200, 100 ); + + SetVisible( true ); + + SetSize( 400, 200 ); + SetPos( 100, 100 ); + + m_pChannelGraph = new CChannelGraphPanel( this, "ChannelGraph" ); + + SetScheme( vgui::scheme()->LoadSchemeFromFile( "Resource/BoxRocket.res", "BoxRocket" ) ); +} + +void CChannelGraphFrame::SetChannel( CDmeChannel *pChannel ) +{ + m_pChannelGraph->SetChannel( pChannel ); +} + +void CChannelGraphFrame::OnCommand( const char *cmd ) +{ + BaseClass::OnCommand( cmd ); + m_pChannelGraph->OnCommand( cmd ); +} + +void CChannelGraphFrame::PerformLayout() +{ + BaseClass::PerformLayout(); + + int border = 5; + int iWidth, iHeight; + GetSize( iWidth, iHeight ); + m_pChannelGraph->SetPos( border, GetCaptionHeight() + border ); + m_pChannelGraph->SetSize( iWidth - 2 * border, iHeight - GetCaptionHeight() - 2 * border ); +} |