summaryrefslogtreecommitdiff
path: root/vgui2/dme_controls/ChannelGraphPanel.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /vgui2/dme_controls/ChannelGraphPanel.cpp
downloadarchived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.tar.xz
archived-source-engine-2018-hl2-src-3bf9df6b2785fa6d951086978a3e66f49427166a.zip
Diffstat (limited to 'vgui2/dme_controls/ChannelGraphPanel.cpp')
-rw-r--r--vgui2/dme_controls/ChannelGraphPanel.cpp368
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 );
+}