//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #include #include #include #include #include #include #include #include #include #include "mathlib/mathlib.h" // memdbgon must be the last include file in a .cpp file!!! #include using namespace vgui; DECLARE_BUILD_FACTORY( RotatingProgressBar ); //----------------------------------------------------------------------------- // Purpose: Constructor //----------------------------------------------------------------------------- RotatingProgressBar::RotatingProgressBar(Panel *parent, const char *panelName) : ProgressBar(parent, panelName) { m_flStartRadians = 0; m_flEndRadians = 0; m_flLastAngle = 0; m_nTextureId = -1; m_pszImageName = NULL; m_flTickDelay = 30; ivgui()->AddTickSignal(GetVPanel(), m_flTickDelay ); SetPaintBorderEnabled(false); } //----------------------------------------------------------------------------- // Purpose: Destructor //----------------------------------------------------------------------------- RotatingProgressBar::~RotatingProgressBar() { if ( vgui::surface() && m_nTextureId != -1 ) { vgui::surface()->DestroyTextureID( m_nTextureId ); m_nTextureId = -1; } delete [] m_pszImageName; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void RotatingProgressBar::ApplySettings(KeyValues *inResourceData) { const char *imageName = inResourceData->GetString("image", ""); if (*imageName) { SetImage( imageName ); } // Find min and max rotations in radians m_flStartRadians = DEG2RAD(inResourceData->GetFloat( "start_degrees", 0 ) ); m_flEndRadians = DEG2RAD( inResourceData->GetFloat( "end_degrees", 0 ) ); // Start at 0 progress m_flLastAngle = m_flStartRadians; // approach speed is specified in degrees per second. // convert to radians per 1/30th of a second float flDegressPerSecond = DEG2RAD( inResourceData->GetFloat( "approach_speed", 360.0 ) ); // default is super fast m_flApproachSpeed = flDegressPerSecond * ( m_flTickDelay / 1000.0f ); // divide by number of frames in a second m_flRotOriginX = inResourceData->GetFloat( "rot_origin_x_percent", 0.5f ); m_flRotOriginY = inResourceData->GetFloat( "rot_origin_y_percent", 0.5f ); m_flRotatingX = inResourceData->GetFloat( "rotating_x", 0 ); m_flRotatingY = inResourceData->GetFloat( "rotating_y", 0 ); m_flRotatingWide = inResourceData->GetFloat( "rotating_wide", 0 ); m_flRotatingTall = inResourceData->GetFloat( "rotating_tall", 0 ); BaseClass::ApplySettings( inResourceData ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void RotatingProgressBar::ApplySchemeSettings(IScheme *pScheme) { BaseClass::ApplySchemeSettings(pScheme); if ( m_pszImageName && strlen( m_pszImageName ) > 0 ) { if ( m_nTextureId == -1 ) { m_nTextureId = surface()->CreateNewTextureID(); } surface()->DrawSetTextureFile( m_nTextureId, m_pszImageName, true, false); } } //----------------------------------------------------------------------------- // Purpose: sets an image by file name //----------------------------------------------------------------------------- void RotatingProgressBar::SetImage(const char *imageName) { if ( m_pszImageName ) { delete [] m_pszImageName; m_pszImageName = NULL; } const char *pszDir = "vgui/"; int len = Q_strlen(imageName) + 1; len += strlen(pszDir); m_pszImageName = new char[ len ]; Q_snprintf( m_pszImageName, len, "%s%s", pszDir, imageName ); InvalidateLayout(false, true); // force applyschemesettings to run } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void RotatingProgressBar::PaintBackground() { // No background } //----------------------------------------------------------------------------- // Purpose: Update event when we aren't drawing so we don't get huge sweeps // when we start drawing it //----------------------------------------------------------------------------- void RotatingProgressBar::OnTick( void ) { float flDesiredAngle = RemapVal( GetProgress(), 0.0, 1.0, m_flStartRadians, m_flEndRadians ); m_flLastAngle = Approach( flDesiredAngle, m_flLastAngle, m_flApproachSpeed ); BaseClass::OnTick(); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void RotatingProgressBar::Paint() { // we have an image that we rotate based on the progress, // where '0' is not rotated,'90' is rotated 90 degrees to the right. // Image is rotated around its center. // desired rotation is GetProgress() ( 0.0 -> 1.0 ) mapped into // ( m_flStartDegrees -> m_flEndDegrees ) vgui::surface()->DrawSetTexture( m_nTextureId ); vgui::surface()->DrawSetColor( Color(255,255,255,255) ); int wide, tall; GetSize( wide, tall ); float mid_x = m_flRotatingX + m_flRotOriginX * m_flRotatingWide; float mid_y = m_flRotatingY + m_flRotOriginY * m_flRotatingTall; Vertex_t vert[4]; vert[0].Init( Vector2D( m_flRotatingX, m_flRotatingY ), Vector2D(0,0) ); vert[1].Init( Vector2D( m_flRotatingX+m_flRotatingWide, m_flRotatingY ), Vector2D(1,0) ); vert[2].Init( Vector2D( m_flRotatingX+m_flRotatingWide, m_flRotatingY+m_flRotatingTall ), Vector2D(1,1) ); vert[3].Init( Vector2D( m_flRotatingX, m_flRotatingY+m_flRotatingTall ), Vector2D(0,1) ); float flCosA = cos(m_flLastAngle); float flSinA = sin(m_flLastAngle); // rotate each point around (mid_x, mid_y) by flAngle radians for ( int i=0;i<4;i++ ) { Vector2D result; // subtract the (x,y) we're rotating around, we'll add it on at the end. vert[i].m_Position.x -= mid_x; vert[i].m_Position.y -= mid_y; result.x = ( vert[i].m_Position.x * flCosA - vert[i].m_Position.y * flSinA ) + mid_x; result.y = ( vert[i].m_Position.x * flSinA + vert[i].m_Position.y * flCosA ) + mid_y; vert[i].m_Position = result; } vgui::surface()->DrawTexturedPolygon( 4, vert ); }