//====== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======= // // Purpose: // //============================================================================= #include "matsys_controls/potterywheelpanel.h" #include "matsys_controls/manipulator.h" #include "vgui/ISystem.h" #include "vgui/Cursor.h" #include "vgui/IVGui.h" #include "vgui/ISurface.h" #include "vgui/IInput.h" #include "VGuiMatSurface/IMatSystemSurface.h" #include "dmxloader/dmxelement.h" #include "vgui_controls/Frame.h" #include "convar.h" #include "tier0/dbg.h" #include "matsys_controls/matsyscontrols.h" #include "materialsystem/imaterial.h" #include "materialsystem/imaterialsystem.h" #include "istudiorender.h" #include "materialsystem/imaterialsystemhardwareconfig.h" #include "tier2/renderutils.h" #include "tier1/keyvalues.h" #include "materialsystem/imesh.h" #include "shaderapi/ishaderapi.h" #include "view_shared.h" #include "ivrenderview.h" #include "game/client/irendercaptureconfiguration.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" using namespace vgui; //----------------------------------------------------------------------------- // Translation manipulator //----------------------------------------------------------------------------- class CTranslationManipulator : public CTransformManipulator { public: CTranslationManipulator( matrix3x4_t *pTransform ); // Methods of IManipulator virtual void OnMousePressed( vgui::MouseCode code, int x, int y ); virtual void OnCursorMoved( int x, int y ); protected: int m_lastx, m_lasty; }; CTranslationManipulator::CTranslationManipulator( matrix3x4_t *pTransform ) : CTransformManipulator( pTransform ) { m_lastx = m_lasty = 0; } void CTranslationManipulator::OnMousePressed( vgui::MouseCode code, int x, int y ) { m_lasty = y; m_lastx = x; } void CTranslationManipulator::OnCursorMoved( int x, int y ) { if ( !m_pTransform ) return; Vector vPosition; QAngle quakeEuler; MatrixAngles( *m_pTransform, quakeEuler, vPosition ); Vector forward, right, up; AngleVectors( quakeEuler, &forward, &right, &up ); int dy = y - m_lasty; int dx = x - m_lastx; right *= -0.2f * dx; up *= 0.2f * dy; vPosition += up + right; m_lastx = x; m_lasty = y; PositionMatrix( vPosition, *m_pTransform ); } //----------------------------------------------------------------------------- // Zoom manipulator //----------------------------------------------------------------------------- class CZoomManipulator : public CBaseManipulator { public: CZoomManipulator( float *pDistance ); // Methods of IManipulator virtual void OnMousePressed( vgui::MouseCode code, int x, int y ); virtual void OnCursorMoved( int x, int y ); protected: int m_lasty; float *m_pDistance; }; CZoomManipulator::CZoomManipulator( float *pDistance ) { m_lasty = 0; m_pDistance = pDistance; } void CZoomManipulator::OnMousePressed( vgui::MouseCode code, int x, int y ) { m_lasty = y; } void CZoomManipulator::OnCursorMoved( int x, int y ) { float delta = 0.2f * ( y - m_lasty ); m_lasty = y; *m_pDistance *= pow( 1.01f, delta ); } //----------------------------------------------------------------------------- // Rotation manipulator //----------------------------------------------------------------------------- class CRotationManipulator : public CTransformManipulator { public: CRotationManipulator( matrix3x4_t *pTransform ); // Inherited from IManipulator virtual void OnMousePressed( vgui::MouseCode code, int x, int y ); virtual void OnCursorMoved( int x, int y ); virtual void UpdateTransform(); void SetDefaultValues(); private: int m_lastx, m_lasty; float m_altitude, m_azimuth; }; CRotationManipulator::CRotationManipulator( matrix3x4_t *pTransform ) : CTransformManipulator( pTransform ) { SetDefaultValues(); } void CRotationManipulator::SetDefaultValues() { m_lastx = m_lasty = 0; m_altitude = M_PI/6; m_azimuth = -3*M_PI/4; UpdateTransform(); } void CRotationManipulator::OnMousePressed( vgui::MouseCode code, int x, int y ) { m_lasty = y; m_lastx = x; } void CRotationManipulator::OnCursorMoved( int x, int y ) { m_azimuth += 0.002f * ( m_lastx - x ); m_altitude -= 0.002f * ( m_lasty - y ); m_altitude = MAX( -M_PI/2, MIN( M_PI/2, m_altitude ) ); m_lastx = x; m_lasty = y; UpdateTransform(); } void CRotationManipulator::UpdateTransform() { if ( !m_pTransform ) return; QAngle angles( RAD2DEG( m_altitude ), RAD2DEG( m_azimuth ), 0 ); Vector vecPosition; MatrixGetColumn( *m_pTransform, 3, vecPosition ); AngleMatrix( angles, vecPosition, *m_pTransform ); } //----------------------------------------------------------------------------- // Constructor, destructor //----------------------------------------------------------------------------- CPotteryWheelPanel::CPotteryWheelPanel( vgui::Panel *pParent, const char *pName ) : BaseClass( pParent, pName ), m_pCameraRotate( NULL ), m_pCameraTranslate( NULL ), m_pCameraZoom( NULL ), m_pLightManip( NULL ), m_pCurrentManip( NULL ), m_nCaptureMouseCode( vgui::MouseCode( -1 ) ), m_xoffset( 0 ), m_yoffset( 0 ), m_bParentMouseNotify( false ) { m_bHasLightProbe = false; m_bSetupRenderStateDelayed = false; m_bRender3DSupersampled = false; m_bInRender3dForRenderCapture = false; m_pvRenderingWithFlashlightConfiguration = NULL; SetPaintBackgroundEnabled( false ); SetPaintBorderEnabled( false ); m_ClearColor.SetColor( 76, 88, 68, 255 ); m_GridColor.SetColor( 255, 255, 255, 255 ); SetIdentityMatrix( m_CameraPivot ); CreateDefaultLights(); m_nManipStartX = m_nManipStartY = 0; m_vecCameraOffset.Init( 100.0f, 0.0f, 0.0f ); m_Camera.Init( Vector( 0, 0, 0 ), QAngle( 0, 0, 0 ), 3.0f, 16384.0f * 1.73205080757f, 30.0f, 1.0f ); m_pCameraRotate = new CRotationManipulator( &m_CameraPivot ); m_pCameraRotate->SetDefaultValues(); m_pCameraTranslate = new CTranslationManipulator( &m_CameraPivot ); m_pCameraZoom = new CZoomManipulator( &m_vecCameraOffset.x ); SetKeyBoardInputEnabled( true ); UpdateCameraTransform(); // Used to poll input vgui::ivgui()->AddTickSignal( GetVPanel() ); } CPotteryWheelPanel::~CPotteryWheelPanel() { delete m_pCameraRotate; delete m_pCameraZoom; delete m_pCameraTranslate; DestroyLights(); } void CPotteryWheelPanel::CreateDefaultLights() { memset( &m_LightingState, 0, sizeof(MaterialLightingState_t) ); for ( int i = 0; i < 6; ++i ) { m_LightingState.m_vecAmbientCube[i].Init( 0.4f, 0.4f, 0.4f ); } SetIdentityMatrix( m_LightToWorld[0] ); m_LightingState.m_pLocalLightDesc[0].m_Type = MATERIAL_LIGHT_DIRECTIONAL; m_LightingState.m_pLocalLightDesc[0].m_Color.Init( 1.0f, 1.0f, 1.0f ); m_LightingState.m_pLocalLightDesc[0].m_Direction.Init( 0.0f, 0.0f, -1.0f ); m_LightingState.m_pLocalLightDesc[0].m_Range=0.0; m_LightingState.m_pLocalLightDesc[0].m_Attenuation0 = 1.0; m_LightingState.m_pLocalLightDesc[0].m_Attenuation1 = 0; m_LightingState.m_pLocalLightDesc[0].m_Attenuation2 = 0; m_LightingState.m_pLocalLightDesc[0].RecalculateDerivedValues(); m_LightingState.m_nLocalLightCount = 1; m_pLightManip = new CPotteryWheelManip( &m_LightToWorld[0] ); } void CPotteryWheelPanel::UpdateDirectionalLight( int idx, const Color& color, const Vector& direction ) { if ( idx >= 0 && idx < m_LightingState.m_nLocalLightCount ) { // Update the existing light SetIdentityMatrix( m_LightToWorld[idx] ); m_LightingState.m_pLocalLightDesc[idx].m_Type = MATERIAL_LIGHT_DIRECTIONAL; m_LightingState.m_pLocalLightDesc[idx].m_Color.Init( color.r() / 255.0f, color.g() / 255.0f, color.b() / 255.0f ); m_LightingState.m_pLocalLightDesc[idx].m_Direction.Init( direction.x, direction.y, direction.z ); m_LightingState.m_pLocalLightDesc[idx].m_Range=0.0; m_LightingState.m_pLocalLightDesc[idx].m_Attenuation0 = 1.0; m_LightingState.m_pLocalLightDesc[idx].m_Attenuation1 = 0; m_LightingState.m_pLocalLightDesc[idx].m_Attenuation2 = 0; m_LightingState.m_pLocalLightDesc[idx].RecalculateDerivedValues(); } else { AddDirectionalLight( color, direction ); } } void CPotteryWheelPanel::ClearDirectionalLights() { m_LightingState.m_nLocalLightCount = 0; } void CPotteryWheelPanel::AddDirectionalLight( const Color& color, const Vector& direction ) { if ( m_LightingState.m_nLocalLightCount < MATERIAL_MAX_LIGHT_COUNT ) { SetIdentityMatrix( m_LightToWorld[m_LightingState.m_nLocalLightCount] ); m_LightingState.m_pLocalLightDesc[m_LightingState.m_nLocalLightCount].m_Type = MATERIAL_LIGHT_DIRECTIONAL; m_LightingState.m_pLocalLightDesc[m_LightingState.m_nLocalLightCount].m_Color.Init( color.r() / 255.0f, color.g() / 255.0f, color.b() / 255.0f ); m_LightingState.m_pLocalLightDesc[m_LightingState.m_nLocalLightCount].m_Direction.Init( direction.x, direction.y, direction.z ); m_LightingState.m_pLocalLightDesc[m_LightingState.m_nLocalLightCount].m_Range=0.0; m_LightingState.m_pLocalLightDesc[m_LightingState.m_nLocalLightCount].m_Attenuation0 = 1.0; m_LightingState.m_pLocalLightDesc[m_LightingState.m_nLocalLightCount].m_Attenuation1 = 0; m_LightingState.m_pLocalLightDesc[m_LightingState.m_nLocalLightCount].m_Attenuation2 = 0; m_LightingState.m_pLocalLightDesc[m_LightingState.m_nLocalLightCount].RecalculateDerivedValues(); m_LightingState.m_nLocalLightCount++; } } void CPotteryWheelPanel::SetLightAmbient( const Vector& ambient ) { for ( int i = 0; i < 6; ++i ) { m_LightingState.m_vecAmbientCube[i].Init( ambient.x, ambient.y, ambient.z ); } } void CPotteryWheelPanel::DestroyLights() { if ( m_pLightManip ) { delete m_pLightManip; m_pLightManip = NULL; } m_LightingState.m_nLocalLightCount = 0; } //----------------------------------------------------------------------------- // Sets the background color //----------------------------------------------------------------------------- void CPotteryWheelPanel::SetBackgroundColor( int r, int g, int b ) { m_ClearColor.SetColor( r, g, b, 255 ); } void CPotteryWheelPanel::SetBackgroundColor( const Color& c ) { m_ClearColor = c; } const Color& CPotteryWheelPanel::GetBackgroundColor() const { return m_ClearColor; } void CPotteryWheelPanel::SetGridColor( int r, int g, int b ) { m_GridColor.SetColor( r, g, b, 255 ); } //----------------------------------------------------------------------------- // Light probe //----------------------------------------------------------------------------- void CPotteryWheelPanel::SetLightProbe( CDmxElement *pLightProbe ) { m_LightProbeBackground.Shutdown(); m_LightProbeHDRBackground.Shutdown(); m_LightProbeCubemap.Shutdown(); m_LightProbeHDRCubemap.Shutdown(); DestroyLights(); m_bHasLightProbe = ( pLightProbe != NULL ); if ( !m_bHasLightProbe ) { CreateDefaultLights(); return; } const char *pCubemap = pLightProbe->GetValueString( "cubemap" ); m_LightProbeCubemap.Init( pCubemap, TEXTURE_GROUP_OTHER ); const char *pCubemapHDR = pLightProbe->HasAttribute( "cubemapHdr" ) ? pLightProbe->GetValueString( "cubemapHdr" ) : pCubemap; m_LightProbeHDRCubemap.Init( pCubemapHDR, TEXTURE_GROUP_OTHER ); KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" ); pVMTKeyValues->SetInt( "$ignorez", 1 ); pVMTKeyValues->SetString( "$envmap", pCubemap ); pVMTKeyValues->SetInt( "$no_fullbright", 1 ); pVMTKeyValues->SetInt( "$nocull", 1 ); m_LightProbeBackground.Init( "SPWP_LightProbeBackground", pVMTKeyValues ); m_LightProbeBackground->Refresh(); pVMTKeyValues = new KeyValues( "UnlitGeneric" ); pVMTKeyValues->SetInt( "$ignorez", 1 ); pVMTKeyValues->SetString( "$envmap", pCubemapHDR ); pVMTKeyValues->SetInt( "$no_fullbright", 1 ); pVMTKeyValues->SetInt( "$nocull", 1 ); m_LightProbeHDRBackground.Init( "SPWP_LightProbeBackground_HDR", pVMTKeyValues ); m_LightProbeHDRBackground->Refresh(); const CUtlVector< Vector >& ambientCube = pLightProbe->GetArray( "ambientCube" ); if ( ambientCube.Count() == 6 ) { for ( int i = 0; i < 6; ++i ) { m_LightingState.m_vecAmbientCube[i].Init( ambientCube[i].x, ambientCube[i].y, ambientCube[i].z ); } } const CUtlVector< CDmxElement* >& localLights = pLightProbe->GetArray< CDmxElement* >( "localLights" ); int nLightCount = localLights.Count(); for ( int i = 0; i < nLightCount; ++i ) { if ( m_LightingState.m_nLocalLightCount == MATERIAL_MAX_LIGHT_COUNT ) break; LightDesc_t *pDesc = &m_LightingState.m_pLocalLightDesc[m_LightingState.m_nLocalLightCount]; CDmxElement *pLocalLight = localLights[ i ]; const char *pType = pLocalLight->GetValueString( "name" ); const Vector& vecColor = pLocalLight->GetValue( "color" ); if ( !Q_stricmp( pType, "directional" ) ) { pDesc->InitDirectional( pLocalLight->GetValue( "direction" ), vecColor ); ++m_LightingState.m_nLocalLightCount; continue; } if ( !Q_stricmp( pType, "point" ) ) { const Vector& vecAtten = pLocalLight->GetValue( "attenuation" ); pDesc->InitPoint( pLocalLight->GetValue( "origin" ), vecColor ); pDesc->m_Attenuation0 = vecAtten.x; pDesc->m_Attenuation1 = vecAtten.y; pDesc->m_Attenuation2 = vecAtten.z; pDesc->m_Range = pLocalLight->GetValue( "maxDistance" ); pDesc->RecalculateDerivedValues(); ++m_LightingState.m_nLocalLightCount; continue; } if ( !Q_stricmp( pType, "spot" ) ) { const Vector& vecAtten = pLocalLight->GetValue( "attenuation" ); pDesc->InitSpot( pLocalLight->GetValue( "origin" ), vecColor, vec3_origin, 0.5f * RAD2DEG ( pLocalLight->GetValue( "theta" ) ), 0.5f * RAD2DEG ( pLocalLight->GetValue( "phi" ) ) ); pDesc->m_Direction = pLocalLight->GetValue( "direction" ); pDesc->m_Attenuation0 = vecAtten.x; pDesc->m_Attenuation1 = vecAtten.y; pDesc->m_Attenuation2 = vecAtten.z; pDesc->m_Range = pLocalLight->GetValue( "maxDistance" ); pDesc->m_Falloff = pLocalLight->GetValue( "exponent" ); pDesc->RecalculateDerivedValues(); ++m_LightingState.m_nLocalLightCount; continue; } } if ( nLightCount > 0 ) { m_pLightManip = new CPotteryWheelManip( &m_LightToWorld[0] ); } } bool CPotteryWheelPanel::HasLightProbe() const { return m_bHasLightProbe; } ITexture *CPotteryWheelPanel::GetLightProbeCubemap( bool bHDR ) { if ( !m_bHasLightProbe ) return NULL; return bHDR ? m_LightProbeHDRCubemap : m_LightProbeCubemap; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- int CPotteryWheelPanel::GetCameraFOV( void ) { return m_Camera.m_flFOVX; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CPotteryWheelPanel::SetCameraFOV( float flFOV ) { m_Camera.m_flFOVX = flFOV; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CPotteryWheelPanel::SetCameraOffset( const Vector &vecOffset ) { m_vecCameraOffset = vecOffset; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CPotteryWheelPanel::GetCameraOffset( Vector &vecOffset ) { vecOffset = m_vecCameraOffset; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CPotteryWheelPanel::SetCameraPositionAndAngles( const Vector &vecPos, const QAngle &angDir ) { m_Camera.m_origin = vecPos; m_Camera.m_angles = angDir; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CPotteryWheelPanel::GetCameraPositionAndAngles( Vector &vecPos, QAngle &angDir ) { MatrixAngles( m_CameraPivot, angDir, vecPos ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CPotteryWheelPanel::ResetCameraPivot( void ) { SetIdentityMatrix( m_CameraPivot ); } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CPotteryWheelPanel::ResetView( void ) { SetIdentityMatrix( m_CameraPivot ); m_vecCameraOffset.Init( 100.0f, 0.0f, 0.0f ); m_pCameraRotate->SetDefaultValues(); UpdateCameraTransform(); } //----------------------------------------------------------------------------- // Sets the camera to look at the the thing we're spinning around //----------------------------------------------------------------------------- void CPotteryWheelPanel::LookAt( float flRadius ) { // Compute the distance to the camera for the object based on its // radius and fov. // since tan( fov/2 ) = f/d // cos( fov/2 ) = r / r' where r = sphere radius, r' = perp distance from sphere center to max extent of camera // d/f = r'/d' where d' is distance of camera to sphere // d' = r' / tan( fov/2 ) * r' = r / ( cos (fov/2) * tan( fov/2 ) ) = r / sin( fov/2 ) float flFOVx = m_Camera.m_flFOVX; // Compute fov/2 in radians flFOVx *= M_PI / 360.0f; // Compute an effective fov based on the aspect ratio // if the height is smaller than the width int w, h; GetSize( w, h ); if ( h < w ) { flFOVx = atan( h * tan( flFOVx ) / w ); } m_vecCameraOffset.x = -( flRadius / sin( flFOVx ) ); UpdateCameraTransform(); } void CPotteryWheelPanel::LookAt( const Vector &vecCenter, float flRadius ) { MatrixSetColumn( vecCenter, 3, m_CameraPivot ); LookAt( flRadius ); } //----------------------------------------------------------------------------- // Sets up render state in the material system for rendering //----------------------------------------------------------------------------- void CPotteryWheelPanel::SetupRenderState( int nDisplayWidth, int nDisplayHeight ) { CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); VMatrix view, projection; ComputeViewMatrix( &view, m_Camera ); ComputeProjectionMatrix( &projection, m_Camera, nDisplayWidth, nDisplayHeight ); pRenderContext->MatrixMode( MATERIAL_MODEL ); pRenderContext->LoadIdentity( ); pRenderContext->MatrixMode( MATERIAL_VIEW ); pRenderContext->LoadMatrix( view ); pRenderContext->MatrixMode( MATERIAL_PROJECTION ); pRenderContext->LoadMatrix( projection ); // Transform light based on manipulator MaterialLightingState_t state = m_LightingState; for ( int i = 0; i < state.m_nLocalLightCount; ++i ) { const LightDesc_t &srcDesc = m_LightingState.m_pLocalLightDesc[ i ]; LightDesc_t &destDesc = state.m_pLocalLightDesc[ i ]; VectorTransform( srcDesc.m_Position, m_LightToWorld[i], destDesc.m_Position ); VectorRotate( srcDesc.m_Direction, m_LightToWorld[i], destDesc.m_Direction ); VectorNormalize( destDesc.m_Direction ); } pRenderContext->SetLightingState( state ); // FIXME: Remove this! This should automatically happen in DrawModel // in studiorender. if ( !g_pStudioRender ) return; VMatrix worldToCamera; MatrixInverseTR( view, worldToCamera ); Vector vecOrigin, vecRight, vecUp, vecForward; MatrixGetColumn( worldToCamera, 0, &vecRight ); MatrixGetColumn( worldToCamera, 1, &vecUp ); MatrixGetColumn( worldToCamera, 2, &vecForward ); MatrixGetColumn( worldToCamera, 3, &vecOrigin ); g_pStudioRender->SetViewState( vecOrigin, vecRight, vecUp, vecForward ); g_pStudioRender->SetLocalLights( state.m_nLocalLightCount, state.m_pLocalLightDesc ); g_pStudioRender->SetAmbientLightColors( state.m_vecAmbientCube ); } //----------------------------------------------------------------------------- // Compute the camera world position //----------------------------------------------------------------------------- void CPotteryWheelPanel::UpdateCameraTransform( ) { // Set up the render state for the camera + light matrix3x4_t offset, worldToCamera; SetIdentityMatrix( offset ); MatrixSetColumn( m_vecCameraOffset, 3, offset ); ConcatTransforms( m_CameraPivot, offset, worldToCamera ); MatrixAngles( worldToCamera, m_Camera.m_angles, m_Camera.m_origin ); } void CPotteryWheelPanel::ComputeCameraTransform( matrix3x4_t *pWorldToCamera ) { AngleMatrix( m_Camera.m_angles, m_Camera.m_origin, *pWorldToCamera ); } //----------------------------------------------------------------------------- // Computes the position in the panel of a particular 3D point //----------------------------------------------------------------------------- void CPotteryWheelPanel::ComputePanelPosition( const Vector &vecPosition, Vector2D *pPanelPos ) { int w, h; GetSize( w, h ); matrix3x4_t worldToCamera; ComputeCameraTransform( &worldToCamera ); MatrixAngles( worldToCamera, m_Camera.m_angles, m_Camera.m_origin ); ComputeScreenSpacePosition( pPanelPos, vecPosition, m_Camera, w, h ); } IMaterial * CPotteryWheelPanel::GetWireframeMaterial() { if ( !m_Wireframe.IsValid() ) { KeyValues *pMaterialKeys = new KeyValues( "Wireframe", "$model", "1" ); pMaterialKeys->SetString( "$vertexcolor", "1" ); m_Wireframe.Init( "potterywheelpanelwireframe", pMaterialKeys ); } return m_Wireframe; } //----------------------------------------------------------------------------- // Utility method to draw a grid at the 'ground' //----------------------------------------------------------------------------- void CPotteryWheelPanel::DrawGrid() { matrix3x4_t transform; CMatRenderContextPtr pRenderContext( MaterialSystem() ); pRenderContext->MatrixMode( MATERIAL_MODEL ); pRenderContext->LoadIdentity( ); pRenderContext->Bind( GetWireframeMaterial() ); IMesh *pMesh = pRenderContext->GetDynamicMesh(); int nGridDim = 10; CMeshBuilder meshBuilder; meshBuilder.Begin( pMesh, MATERIAL_LINES, 2 * nGridDim + 2 ); float bounds = 100.0f; float delta = 2 * bounds / nGridDim; for ( int i = 0; i < nGridDim + 1; ++i ) { float xy = -bounds + delta * i; meshBuilder.Position3f( xy, -bounds, 0 ); meshBuilder.Color4ub( m_GridColor.r(), m_GridColor.g(), m_GridColor.b(), m_GridColor.a()); meshBuilder.AdvanceVertex(); meshBuilder.Position3f( xy, bounds, 0 ); meshBuilder.Color4ub( m_GridColor.r(), m_GridColor.g(), m_GridColor.b(), m_GridColor.a()); meshBuilder.AdvanceVertex(); meshBuilder.Position3f( -bounds, xy, 0 ); meshBuilder.Color4ub( m_GridColor.r(), m_GridColor.g(), m_GridColor.b(), m_GridColor.a()); meshBuilder.AdvanceVertex(); meshBuilder.Position3f( bounds, xy, 0 ); meshBuilder.Color4ub( m_GridColor.r(), m_GridColor.g(), m_GridColor.b(), m_GridColor.a()); meshBuilder.AdvanceVertex(); } meshBuilder.End(); pMesh->Draw(); } //----------------------------------------------------------------------------- // paint it! //----------------------------------------------------------------------------- void CPotteryWheelPanel::Paint() { int iWidth, iHeight; GetSize( iWidth, iHeight ); int screenw, screenh; vgui::surface()->GetScreenSize( screenw, screenh ); int windowposx = 0, windowposy = 0; GetPos( windowposx, windowposy ); int windowposright = windowposx + iWidth; int windowposbottom = windowposy + iHeight; if ( windowposright >= screenw ) { iWidth -= ( windowposright - screenw ); } if ( windowposbottom >= screenh ) { iHeight -= ( windowposbottom - screenh ); } int startx = 0, starty = 0; if( windowposx < 0 ) { startx = -windowposx; iWidth -= startx; } if ( windowposy < 0 ) { starty = -windowposy; iHeight -= starty; } if( iWidth < 0 || iHeight < 0 ) { return; } if ( GetRenderingWithFlashlightConfiguration() ) { RenderCapture(); } int w, h; GetSize( w, h ); vgui::MatSystemSurface()->Begin3DPaint( 0, 0, w, h, m_bRender3DSupersampled ); if ( m_pCurrentManip ) { m_pCurrentManip->SetViewportSize( iWidth, iHeight ); } // Set up the render state for the camera + light m_nRenderWidth = iWidth; m_nRenderHeight = iHeight; if ( !m_bSetupRenderStateDelayed ) SetupRenderState( iWidth, iHeight ); CMatRenderContextPtr pRenderContext( vgui::MaterialSystem() ); PIXEVENT( pRenderContext, "CPotteryWheelPanel::Paint" ); if ( m_bUseParentBG && GetParent() ) { Color bgCol = GetParent()->GetBgColor(); pRenderContext->ClearColor4ub( bgCol.r(), bgCol.g(), bgCol.b(), bgCol.a() ); } else { pRenderContext->ClearColor4ub( m_ClearColor.r(), m_ClearColor.g(), m_ClearColor.b(), m_ClearColor.a() ); } pRenderContext->ClearBuffers( true, true ); pRenderContext->CullMode( MATERIAL_CULLMODE_CCW ); if ( HasLightProbe() ) { IMaterial *pMaterial = ( vgui::MaterialSystemHardwareConfig()->GetHDRType() == HDR_TYPE_NONE ) ? m_LightProbeBackground : m_LightProbeHDRBackground; RenderBox( m_Camera.m_origin, vec3_angle, Vector( -100, -100, -100 ), Vector( 100, 100, 100 ), Color( 255, 255, 255, 255 ), pMaterial, true ); } OnPaint3D(); pRenderContext->CullMode( MATERIAL_CULLMODE_CW ); vgui::MatSystemSurface()->End3DPaint( ); } void CPotteryWheelPanel::EnableRenderingWithFlashlight( void *pvConfiguration ) { m_pvRenderingWithFlashlightConfiguration = pvConfiguration; } void CPotteryWheelPanel::RenderCapture() { if ( !GetRenderingWithFlashlightConfiguration() ) return; CRenderCaptureConfigurationState *pCfg = reinterpret_cast< CRenderCaptureConfigurationState * >( GetRenderingWithFlashlightConfiguration() ); m_nRenderWidth = pCfg->m_pFlashlightDepthTexture->GetActualWidth(); m_nRenderHeight = pCfg->m_pFlashlightDepthTexture->GetActualHeight(); if ( !m_bSetupRenderStateDelayed ) SetupRenderState( m_nRenderWidth, m_nRenderHeight ); CMatRenderContextPtr pRenderContext( vgui::MaterialSystem() ); PIXEVENT( pRenderContext, "CPotteryWheelPanel::RenderCapture" ); CViewSetup view2d; view2d.x = 0; view2d.y = 0; view2d.width = m_nRenderWidth; view2d.height = m_nRenderHeight; pCfg->m_pIVRenderView->Push3DView( pRenderContext, view2d, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH, pCfg->m_pDummyColorBufferTexture, NULL, pCfg->m_pFlashlightDepthTexture ); pRenderContext->ClearColor4ub( 0, 0, 0, 0 ); pRenderContext->ClearBuffers( true, true, false ); m_bInRender3dForRenderCapture = true; pRenderContext->CullMode(MATERIAL_CULLMODE_CW); g_pStudioRender->ForcedMaterialOverride( NULL, OVERRIDE_DEPTH_WRITE ); // Don't draw the 3D scene w/ stencil ShaderStencilState_t state; pRenderContext->SetStencilState( state ); OnPaint3D(); g_pStudioRender->ForcedMaterialOverride( NULL ); pRenderContext->CullMode(MATERIAL_CULLMODE_CCW); m_bInRender3dForRenderCapture = false; pCfg->m_pIVRenderView->PopView( pRenderContext, NULL ); pRenderContext->Flush(); } //----------------------------------------------------------------------------- // called when we're ticked... //----------------------------------------------------------------------------- void CPotteryWheelPanel::OnTick() { BaseClass::OnTick(); if ( m_pCurrentManip ) { m_pCurrentManip->OnTick(); UpdateCameraTransform(); } } //----------------------------------------------------------------------------- // input //----------------------------------------------------------------------------- void CPotteryWheelPanel::OnKeyCodePressed(KeyCode code) { if ( m_pCurrentManip ) { switch( code ) { case KEY_RSHIFT: case KEY_LSHIFT: // start translate mode AcceptManipulation( false ); EnterManipulationMode( CAMERA_TRANSLATE, false ); break; case KEY_RCONTROL: case KEY_LCONTROL: // start light mode AcceptManipulation( false ); EnterManipulationMode( LIGHT_MODE, false ); break; } } BaseClass::OnKeyCodePressed( code ); } //----------------------------------------------------------------------------- // Set whether the parent panel should be notified of mouse actions //----------------------------------------------------------------------------- void CPotteryWheelPanel::SetParentMouseNotify( bool bParentMouseNotify ) { m_bParentMouseNotify = bParentMouseNotify; } //----------------------------------------------------------------------------- // Purpose: soaks up any remaining messages //----------------------------------------------------------------------------- void CPotteryWheelPanel::OnKeyCodeReleased(KeyCode code) { if ( m_pCurrentManip ) { switch( code ) { case KEY_RSHIFT: case KEY_LSHIFT: case KEY_RCONTROL: case KEY_LCONTROL: { // stop manipulation mode AcceptManipulation( false ); switch ( m_nCaptureMouseCode ) { default: case MOUSE_LEFT: EnterManipulationMode( CAMERA_ROTATE, false ); break; case MOUSE_MIDDLE: EnterManipulationMode( CAMERA_TRANSLATE, false ); break; case MOUSE_RIGHT: EnterManipulationMode( CAMERA_ZOOM, false ); break; } } break; } } BaseClass::OnKeyCodeReleased( code ); } void CPotteryWheelPanel::OnMouseDoublePressed( vgui::MouseCode code ) { BaseClass::OnMouseDoublePressed( code ); if( m_bParentMouseNotify && GetParent() ) { GetParent()->OnMouseDoublePressed(code); } } void CPotteryWheelPanel::OnMousePressed( vgui::MouseCode code ) { if ( m_pCurrentManip ) return; RequestFocus(); if ( input()->IsKeyDown( KEY_RSHIFT ) || input()->IsKeyDown( KEY_LSHIFT ) ) { EnterManipulationMode( CAMERA_TRANSLATE, true, code ); } else if ( input()->IsKeyDown( KEY_RCONTROL ) || input()->IsKeyDown( KEY_LCONTROL ) ) { EnterManipulationMode( LIGHT_MODE, true, code ); } else { switch ( code ) { case MOUSE_LEFT: EnterManipulationMode( CAMERA_ROTATE, true, code ); break; case MOUSE_MIDDLE: EnterManipulationMode( CAMERA_TRANSLATE, true, code ); break; case MOUSE_RIGHT: EnterManipulationMode( CAMERA_ZOOM, true, code ); break; } } BaseClass::OnMousePressed( code ); if( m_bParentMouseNotify && GetParent() ) { GetParent()->OnMousePressed(code); } } void CPotteryWheelPanel::OnMouseReleased( vgui::MouseCode code ) { int x, y; input()->GetCursorPos( x, y ); ScreenToLocal( x, y ); AcceptManipulation(); BaseClass::OnMouseReleased( code ); if( m_bParentMouseNotify && GetParent() ) { GetParent()->OnMouseReleased(code); } } void CPotteryWheelPanel::OnCursorMoved( int x, int y ) { if ( m_pCurrentManip ) { if ( WarpMouse( x, y ) ) { m_pCurrentManip->OnCursorMoved( x, y ); } } BaseClass::OnCursorMoved( x, y ); if( m_bParentMouseNotify && GetParent() ) { GetParent()->OnCursorMoved(x,y); } } void CPotteryWheelPanel::OnMouseWheeled( int delta ) { if ( m_pCurrentManip ) { m_pCurrentManip->OnMouseWheeled( delta ); } BaseClass::OnMouseWheeled( delta ); if( m_bParentMouseNotify && GetParent() ) { GetParent()->OnMouseWheeled(delta); } } void CPotteryWheelPanel::EnterManipulationMode( ManipulationMode_t manipMode, bool bMouseCapture, vgui::MouseCode mouseCode /* = -1 */ ) { switch ( manipMode ) { case CAMERA_ROTATE: m_pCurrentManip = m_pCameraRotate; break; case CAMERA_TRANSLATE: m_pCurrentManip = m_pCameraTranslate; break; case CAMERA_ZOOM: m_pCurrentManip = m_pCameraZoom; break; case LIGHT_MODE: m_pCurrentManip = m_pLightManip; break; } if ( !m_pCurrentManip ) return; m_pCurrentManip->OnBeginManipulation(); m_xoffset = m_yoffset = 0; // Warp the mouse to the center of the screen int width, height; GetSize( width, height ); int x = width / 2; int y = height / 2; if ( bMouseCapture ) { input()->GetCursorPos( m_nManipStartX, m_nManipStartY ); EnableMouseCapture( true, mouseCode ); int xpos = x; int ypos = y; LocalToScreen( xpos, ypos ); input()->SetCursorPos( xpos, ypos ); } m_pCurrentManip->OnMousePressed( mouseCode, x, y ); } void CPotteryWheelPanel::AcceptManipulation( bool bReleaseMouseCapture ) { if ( m_pCurrentManip ) { m_pCurrentManip->OnAcceptManipulation(); if ( bReleaseMouseCapture ) { EnableMouseCapture( false ); input()->SetCursorPos( m_nManipStartX, m_nManipStartY ); } m_pCurrentManip = NULL; } } void CPotteryWheelPanel::CancelManipulation() { if ( m_pCurrentManip ) { m_pCurrentManip->OnCancelManipulation(); EnableMouseCapture( false ); input()->SetCursorPos( m_nManipStartX, m_nManipStartY ); m_pCurrentManip = NULL; } } void CPotteryWheelPanel::OnMouseCaptureLost() { SetCursor( vgui::dc_arrow ); m_nCaptureMouseCode = vgui::MouseCode( -1 ); } void CPotteryWheelPanel::EnableMouseCapture( bool enable, vgui::MouseCode mouseCode /* = -1 */ ) { if ( enable ) { m_nCaptureMouseCode = mouseCode; SetCursor( vgui::dc_none ); input()->SetMouseCaptureEx( GetVPanel(), m_nCaptureMouseCode ); } else { m_nCaptureMouseCode = vgui::MouseCode( -1 ); input()->SetMouseCapture( NULL ); SetCursor( vgui::dc_arrow ); } } bool CPotteryWheelPanel::WarpMouse( int &x, int &y ) { // Re-force capture if it was lost... if ( input()->GetMouseCapture() != GetVPanel() ) { input()->GetCursorPos( m_nManipStartX, m_nManipStartY ); EnableMouseCapture( true, m_nCaptureMouseCode ); } int width, height; GetSize( width, height ); int centerx = width / 2; int centery = height / 2; // skip this event if ( x == centerx && y == centery ) return false; int xpos = centerx; int ypos = centery; LocalToScreen( xpos, ypos ); input()->SetCursorPos( xpos, ypos ); int dx = x - centerx; int dy = y - centery; x += m_xoffset; y += m_yoffset; m_xoffset += dx; m_yoffset += dy; return true; }