void CClientLeafSystem::RemoveRenderable( ClientRenderHandle_t handle ) { // This can happen upon level shutdown if (!m_Renderables.IsValidIndex(handle)) return; // Reset the render handle in the entity. IClientRenderable *pRenderable = m_Renderables[handle].m_pRenderable; Assert( handle == pRenderable->RenderHandle() ); pRenderable->RenderHandle() = INVALID_CLIENT_RENDER_HANDLE; // Reemove the renderable from the dirty list if ( m_Renderables[handle].m_Flags & RENDER_FLAGS_HASCHANGED ) { // NOTE: This isn't particularly fast (linear search), // but I'm assuming it's an unusual case where we remove // renderables that are changing or that m_DirtyRenderables usually // only has a couple entries int i = m_DirtyRenderables.Find( handle ); Assert( i != m_DirtyRenderables.InvalidIndex() ); m_DirtyRenderables.FastRemove( i ); } if ( IsViewModelRenderGroup( (RenderGroup_t)m_Renderables[handle].m_RenderGroup ) ) { RemoveFromViewModelList( handle ); } RemoveFromTree( handle ); m_Renderables.Remove( handle ); }
void CMaterialModifyProxy::OnBind( void *pEntity ) { // Get the modified material vars from the entity input IClientRenderable *pRend = (IClientRenderable *)pEntity; if ( pRend ) { C_BaseEntity *pBaseEntity = pRend->GetIClientUnknown()->GetBaseEntity(); if ( pBaseEntity ) { if( debug_materialmodifycontrol_client.GetBool() ) { // DevMsg( 1, "%s\n", pBaseEntity->GetDebugName() ); } int numChildren = 0; bool gotOne = false; for ( C_BaseEntity *pChild = pBaseEntity->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() ) { numChildren++; C_MaterialModifyControl *pControl = dynamic_cast<C_MaterialModifyControl*>( pChild ); if ( !pControl ) continue; if( debug_materialmodifycontrol_client.GetBool() ) { // DevMsg( 1, "pControl: 0x%p\n", pControl ); } switch( pControl->GetModifyMode() ) { case MATERIAL_MODIFY_MODE_NONE: break; case MATERIAL_MODIFY_MODE_SETVAR: gotOne = true; OnBindSetVar( pControl ); break; case MATERIAL_MODIFY_MODE_ANIM_SEQUENCE: OnBindAnimatedTexture( pControl ); break; case MATERIAL_MODIFY_MODE_FLOAT_LERP: OnBindFloatLerp( pControl ); break; default: Assert( 0 ); break; } } if( gotOne ) { // DevMsg( 1, "numChildren: %d\n", numChildren ); } } } if ( ToolsEnabled() ) { ToolFramework_RecordMaterialParams( GetMaterial() ); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void ShotgunShellEjectCallback( const CEffectData &data ) { // Use the gun angles to orient the shell IClientRenderable *pRenderable = data.GetRenderable(); if ( pRenderable ) { tempents->EjectBrass( data.m_vOrigin, data.m_vAngles, pRenderable->GetRenderAngles(), 2 ); } }
void CShieldPowerLevelProxy::OnBind( void *pRenderable ) { IClientRenderable *pRend = (IClientRenderable *)pRenderable; C_BaseEntity *pEntity = pRend->GetIClientUnknown()->GetBaseEntity(); C_Shield *pShield = dynamic_cast<C_Shield*>(pEntity); if (!pShield) return; SetFloatResult( pShield->GetPowerLevel() ); }
void CreateSpurtParticles( void ) { SimpleParticle *pParticle; // PMaterialHandle hMaterial = GetPMaterial( "particle/particle_smokegrenade" ); Vector vecOrigin = m_vSortOrigin; IClientRenderable *pRenderable = ClientEntityList().GetClientRenderableFromHandle(m_hEntity); if ( pRenderable && m_nAttachmentIndex ) { QAngle tmp; pRenderable->GetAttachment( m_nAttachmentIndex, vecOrigin, tmp ); SetSortOrigin( vecOrigin ); } // Smoke int numParticles = RandomInt( 1,2 ); for ( int i = 0; i < numParticles; i++ ) { pParticle = (SimpleParticle *) AddParticle( sizeof( SimpleParticle ), g_Mat_DustPuff[0], vecOrigin ); if ( pParticle == NULL ) break; pParticle->m_flLifetime = 0.0f; pParticle->m_flDieTime = RandomFloat( 0.5, 1.0 ); // Random velocity around the angles forward Vector vecVelocity; vecVelocity.Random( -0.1f, 0.1f ); vecVelocity += m_vecSpurtForward; VectorNormalize( vecVelocity ); vecVelocity *= RandomFloat( 160.0f, 640.0f ); pParticle->m_vecVelocity = vecVelocity; // Randomize the color a little int color[3][2]; for( int i = 0; i < 3; ++i ) { color[i][0] = MAX( 0, m_SpurtColor[i] - 64 ); color[i][1] = MIN( 255, m_SpurtColor[i] + 64 ); } pParticle->m_uchColor[0] = random->RandomInt( color[0][0], color[0][1] ); pParticle->m_uchColor[1] = random->RandomInt( color[1][0], color[1][1] ); pParticle->m_uchColor[2] = random->RandomInt( color[2][0], color[2][1] ); pParticle->m_uchStartAlpha = m_SpurtColor[3]; pParticle->m_uchEndAlpha = 0; pParticle->m_uchStartSize = RandomInt( 50, 60 ); pParticle->m_uchEndSize = pParticle->m_uchStartSize*3; pParticle->m_flRoll = RandomFloat( 0, 360 ); pParticle->m_flRollDelta = RandomFloat( -4.0f, 4.0f ); } m_flLastParticleSpawnTime = gpGlobals->curtime + m_flSpawnRate; }
//----------------------------------------------------------------------------- // Helper class to deal with floating point inputs //----------------------------------------------------------------------------- void CEntityMaterialProxy::OnBind( void *pRenderable ) { if( !pRenderable ) return; IClientRenderable *pRend = (IClientRenderable *)pRenderable; C_BaseEntity *pEnt = pRend->GetIClientUnknown()->GetBaseEntity(); if (pEnt) { OnBind(pEnt); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CMaterialModifyAnimatedProxy::AnimationWrapped( void* pArg ) { IClientRenderable *pRend = (IClientRenderable *)pArg; if (!pRend) return; C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity(); if (pEntity) { pEntity->TextureAnimationWrapped(); } }
void CCoreOriginProxy::OnBind( void *pRenderable ) { if( !pRenderable || !m_pSphereOriginTextureVar ) return; IClientRenderable *pRend = ( IClientRenderable* )pRenderable; if ( !pRend ) return; const Vector &origin = pRend->GetRenderOrigin(); m_pSphereOriginTextureVar->SetVecValue(origin[0], origin[1], origin[2], 1); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- float CMaterialModifyAnimatedProxy::GetAnimationStartTime( void* pArg ) { IClientRenderable *pRend = (IClientRenderable *)pArg; if (!pRend) return 0.0f; C_BaseEntity* pEntity = pRend->GetIClientUnknown()->GetBaseEntity(); if (pEntity) { return pEntity->GetTextureAnimationStartTime(); } return 0.0f; }
void CTeamColorProxy::OnBind( void *pRenderable ) { if( !pRenderable || !m_pColorTextureVar ) return; IClientRenderable *pRend = ( IClientRenderable* )pRenderable; C_BaseEntity *pEnt = pRend->GetIClientUnknown()->GetBaseEntity(); if ( !pEnt ) return; Vector &teamcolor = pEnt->GetTeamColor(); m_pColorTextureVar->SetVecValue(teamcolor[0], teamcolor[1], teamcolor[2], 1); }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- Vector GetTracerOrigin( const CEffectData &data ) { Vector vecStart = data.m_vStart; QAngle vecAngles; int iAttachment = data.m_nAttachmentIndex;; // Attachment? if ( data.m_fFlags & TRACER_FLAG_USEATTACHMENT ) { C_BaseViewModel *pViewModel = NULL; // If the entity specified is a weapon being carried by this player, use the viewmodel instead IClientRenderable *pRenderable = data.GetRenderable(); if ( !pRenderable ) return vecStart; C_BaseEntity *pEnt = data.GetEntity(); FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh ) { ACTIVE_SPLITSCREEN_PLAYER_GUARD( hh ); C_BaseCombatWeapon *pWpn = ToBaseCombatWeapon( pEnt ); if ( pWpn && pWpn->IsCarriedByLocalPlayer() ) { C_BasePlayer *player = ToBasePlayer( pWpn->GetOwner() ); if( !player && pWpn->GetOwner() && pWpn->GetOwner()->IsUnit() ) { player = pWpn->GetOwner()->MyUnitPointer()->GetCommander(); } pViewModel = player ? player->GetViewModel( 0 ) : NULL; if ( pViewModel ) { // Get the viewmodel and use it instead pRenderable = pViewModel; break; } } } // Get the attachment origin if ( !pRenderable->GetAttachment( iAttachment, vecStart, vecAngles ) ) { DevMsg( "GetTracerOrigin: Couldn't find attachment %d on model %s\n", iAttachment, modelinfo->GetModelName( pRenderable->GetModel() ) ); } }
//----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- Vector GetTracerOrigin( const CEffectData &data ) { Vector vecStart = data.m_vStart; QAngle vecAngles; int iAttachment = data.m_nAttachmentIndex;; // Attachment? if ( data.m_fFlags & TRACER_FLAG_USEATTACHMENT ) { C_BaseViewModel *pViewModel = NULL; // If the entity specified is a weapon being carried by this player, use the viewmodel instead IClientRenderable *pRenderable = data.GetRenderable(); if ( !pRenderable ) return vecStart; C_BaseEntity *pEnt = data.GetEntity(); // This check should probably be for all multiplayer games, investigate later #if defined( HL2MP ) || defined( TF_CLIENT_DLL ) || defined( TF_CLASSIC_CLIENT ) if ( pEnt && pEnt->IsDormant() ) return vecStart; #endif C_BaseCombatWeapon *pWpn = dynamic_cast<C_BaseCombatWeapon *>( pEnt ); if ( pWpn && pWpn->ShouldDrawUsingViewModel() ) { C_BasePlayer *player = ToBasePlayer( pWpn->GetOwner() ); // Use GetRenderedWeaponModel() instead? pViewModel = player ? player->GetViewModel( 0 ) : NULL; if ( pViewModel ) { // Get the viewmodel and use it instead pRenderable = pViewModel; } } // Get the attachment origin if ( !pRenderable->GetAttachment( iAttachment, vecStart, vecAngles ) ) { DevMsg( "GetTracerOrigin: Couldn't find attachment %d on model %s\n", iAttachment, modelinfo->GetModelName( pRenderable->GetModel() ) ); } } return vecStart; }
//----------------------------------------------------------------------------- // Purpose: // Input : &data - //----------------------------------------------------------------------------- void CrosshairLoadCallback2( const CEffectData &data ) { IClientRenderable *pRenderable = data.GetRenderable( ); if ( !pRenderable ) return; Vector position; QAngle angles; // If we found the attachment, emit sparks there if ( pRenderable->GetAttachment( data.m_nAttachmentIndex, position, angles ) ) { FX_ElectricSpark( position, 1.0f, 1.0f, NULL ); } }
void CObjectPowerProxy::OnBind( void *pRenderable ) { // Find the view angle between the player and this entity.... IClientRenderable *pRend = (IClientRenderable *)pRenderable; C_BaseEntity *pEntity = pRend->GetIClientUnknown()->GetBaseEntity(); C_BaseObject *pObject = dynamic_cast<C_BaseObject*>(pEntity); if (!pObject) return; SetFloatResult( m_Factor.GetFloat() ); if ( ToolsEnabled() ) { ToolFramework_RecordMaterialParams( GetMaterial() ); } }
//----------------------------------------------------------------------------- // Helper class to deal with floating point inputs //----------------------------------------------------------------------------- void CEntityMaterialProxy::OnBind( void *pRenderable ) { if( !pRenderable ) return; IClientRenderable *pRend = ( IClientRenderable* )pRenderable; C_BaseEntity *pEnt = pRend->GetIClientUnknown()->GetBaseEntity(); if ( pEnt ) { OnBind( pEnt ); if ( ToolsEnabled() ) { ToolFramework_RecordMaterialParams( GetMaterial() ); } } }
//----------------------------------------------------------------------------- // Purpose: // Input : entityIndex - // attachmentIndex - // *origin - // *angles - // Output : Returns true on success, false on failure. //----------------------------------------------------------------------------- bool FX_GetAttachmentTransform( ClientEntityHandle_t hEntity, int attachmentIndex, Vector *origin, QAngle *angles ) { // Validate our input if ( ( hEntity == INVALID_EHANDLE_INDEX ) || ( attachmentIndex < 1 ) ) { if ( origin != NULL ) { *origin = vec3_origin; } if ( angles != NULL ) { *angles = QAngle(0,0,0); } return false; } // Get the actual entity IClientRenderable *pRenderable = ClientEntityList().GetClientRenderableFromHandle( hEntity ); if ( pRenderable ) { Vector attachOrigin; QAngle attachAngles; // Find the attachment's matrix pRenderable->GetAttachment( attachmentIndex, attachOrigin, attachAngles ); if ( origin != NULL ) { *origin = attachOrigin; } if ( angles != NULL ) { *angles = attachAngles; } return true; } return false; }
//----------------------------------------------------------------------------- // Old-style muzzle flashes //----------------------------------------------------------------------------- void MuzzleFlashCallback( const CEffectData &data ) { Vector vecOrigin = data.m_vOrigin; QAngle vecAngles = data.m_vAngles; if ( data.entindex() > 0 ) { IClientRenderable *pRenderable = data.GetRenderable(); if ( !pRenderable ) return; if ( data.m_nAttachmentIndex ) { //FIXME: We also need to allocate these particles into an attachment space setup pRenderable->GetAttachment( data.m_nAttachmentIndex, vecOrigin, vecAngles ); } else { vecOrigin = pRenderable->GetRenderOrigin(); vecAngles = pRenderable->GetRenderAngles(); } } tempents->MuzzleFlash( vecOrigin, vecAngles, data.m_fFlags & (~MUZZLEFLASH_FIRSTPERSON), data.m_hEntity, (data.m_fFlags & MUZZLEFLASH_FIRSTPERSON) != 0 ); }
//----------------------------------------------------------------------------- // Purpose: Create the matrix by which we'll transform the particle's local // space into world space, via the attachment's transform //----------------------------------------------------------------------------- void CLocalSpaceEmitter::SetupTransformMatrix( void ) { IClientRenderable *pRenderable = ClientEntityList().GetClientRenderableFromHandle( m_hEntity ); if ( pRenderable ) { matrix3x4_t mat; if ( pRenderable->GetAttachment( m_nAttachment, mat ) == false ) { // This attachment is bogus! Assert(0); } // Tell the particle effect so it knows Vector origin; MatrixGetColumn( mat, 3, origin ); m_ParticleEffect.SetLocalSpaceTransform( mat ); SetSortOrigin( origin ); C_BaseEntity *pEnt = pRenderable->GetIClientUnknown()->GetBaseEntity(); if ( pEnt ) { Vector vWorldMins, vWorldMaxs; float scale = pEnt->CollisionProp()->BoundingRadius(); vWorldMins[0] = origin[0] - scale; vWorldMins[1] = origin[1] - scale; vWorldMins[2] = origin[2] - scale; vWorldMaxs[0] = origin[0] + scale; vWorldMaxs[1] = origin[1] + scale; vWorldMaxs[2] = origin[2] + scale; GetBinding().SetBBox( vWorldMins, vWorldMaxs, true ); } } // We preapply the local transform because we need to squash it for viewmodel FOV. m_ParticleEffect.SetAutoApplyLocalTransform( false ); }
C_BaseEntity *C_BloodyTextureProxy::BindArgToEntity(void *pArg) { IClientRenderable *pRend = (IClientRenderable *)pArg; return pRend ? pRend->GetIClientUnknown()->GetBaseEntity() : NULL; }
int SEditModelRender::MaterialPicker( char ***szMat ) { int mx, my; #ifdef SOURCE_2006 vgui::input()->GetCursorPos( mx, my ); #else vgui::input()->GetCursorPosition( mx, my ); #endif Vector ray; const CViewSetup *pViewSetup = view->GetPlayerViewSetup(); float ratio =engine->GetScreenAspectRatio( #ifdef SWARM_DLL pViewSetup->width, pViewSetup->height #endif ); ratio = ( 1.0f / ratio ) * (4.0f/3.0f); float flFov = ScaleFOVByWidthRatio( pViewSetup->fov, ratio ); ScreenToWorld( mx, my, flFov, pViewSetup->origin, pViewSetup->angles, ray ); Vector start = pViewSetup->origin; Vector end = start + ray * MAX_TRACE_LENGTH; trace_t tr; C_BaseEntity *pIgnore = input->CAM_IsThirdPerson() ? NULL : C_BasePlayer::GetLocalPlayer(); UTIL_TraceLine( start, end, MASK_SOLID, pIgnore, COLLISION_GROUP_NONE, &tr ); if ( !tr.DidHit() ) return 0; int numMaterials = 0; IMaterial **MatList = NULL; studiohdr_t *pSHdr = NULL; if ( tr.DidHitWorld() ) { if ( tr.hitbox == 0 ) { Vector dummy; IMaterial *pMat = engine->TraceLineMaterialAndLighting( start, end, dummy, dummy ); if ( pMat ) { numMaterials = 1; MatList = new IMaterial*[1]; MatList[0] = pMat; } } else { ICollideable *prop = staticpropmgr->GetStaticPropByIndex( tr.hitbox - 1 ); if ( prop ) { IClientRenderable *pRenderProp = prop->GetIClientUnknown()->GetClientRenderable(); if ( pRenderProp ) { const model_t *pModel = pRenderProp->GetModel(); if ( pModel ) pSHdr = modelinfo->GetStudiomodel( pModel ); } } } } else if ( tr.m_pEnt ) { const model_t *pModel = tr.m_pEnt->GetModel(); if ( pModel ) pSHdr = modelinfo->GetStudiomodel( pModel ); } if ( pSHdr ) { Assert( !numMaterials && !MatList ); numMaterials = pSHdr->numtextures; const int numPaths = pSHdr->numcdtextures; if ( numMaterials ) { CUtlVector< IMaterial* >hValidMaterials; for ( int i = 0; i < numMaterials; i++ ) { mstudiotexture_t *pStudioTex = pSHdr->pTexture( i ); const char *matName = pStudioTex->pszName(); for ( int p = 0; p < numPaths; p++ ) { char tmpPath[MAX_PATH]; Q_snprintf( tmpPath, MAX_PATH, "%s%s\0", pSHdr->pCdtexture( p ), matName ); Q_FixSlashes( tmpPath ); IMaterial *pTempMat = materials->FindMaterial( tmpPath, TEXTURE_GROUP_MODEL ); if ( !IsErrorMaterial( pTempMat ) ) { hValidMaterials.AddToTail( pTempMat ); break; } } } numMaterials = hValidMaterials.Count(); if ( numMaterials ) { MatList = new IMaterial*[ numMaterials ]; for ( int i = 0; i < numMaterials; i++ ) MatList[i] = hValidMaterials[i]; } hValidMaterials.Purge(); } } *szMat = new char*[ numMaterials ]; int iTotalLength = 0; for ( int i = 0; i < numMaterials; i++ ) iTotalLength += Q_strlen( MatList[i]->GetName() ) + 1; **szMat = new char[ iTotalLength ]; int curpos = 0; for ( int i = 0; i < numMaterials; i++ ) { const char *pszName = MatList[i]->GetName(); int curLength = Q_strlen( pszName ) + 1; (*szMat)[ i ] = **szMat + curpos; Q_strcpy( (*szMat)[ i ], pszName ); curpos += curLength; } if ( MatList ) delete [] MatList; return numMaterials; }
void CClientLeafSystem::CollateRenderablesInLeaf( int leaf, int worldListLeafIndex, SetupRenderInfo_t &info ) { bool portalTestEnts = r_PortalTestEnts.GetBool() && !r_portalsopenall.GetBool(); // Collate everything. unsigned short idx = m_RenderablesInLeaf.FirstElement(leaf); for ( ;idx != m_RenderablesInLeaf.InvalidIndex(); idx = m_RenderablesInLeaf.NextElement(idx) ) { ClientRenderHandle_t handle = m_RenderablesInLeaf.Element(idx); RenderableInfo_t& renderable = m_Renderables[handle]; // Early out on static props if we don't want to render them if ((!m_DrawStaticProps) && (renderable.m_Flags & RENDER_FLAGS_STATIC_PROP)) continue; // Early out if we're told to not draw small objects (top view only, /* that's why we don't check the z component). if (!m_DrawSmallObjects) { CCachedRenderInfo& cachedInfo = m_CachedRenderInfos[renderable.m_CachedRenderInfo]; float sizeX = cachedInfo.m_Maxs.x - cachedInfo.m_Mins.x; float sizeY = cachedInfo.m_Maxs.y - cachedInfo.m_Mins.y; if ((sizeX < 50.f) && (sizeY < 50.f)) continue; }*/ Assert( m_DrawSmallObjects ); // MOTODO // Don't hit the same ent in multiple leaves twice. if ( renderable.m_RenderGroup != RENDER_GROUP_TRANSLUCENT_ENTITY ) { if ( renderable.m_RenderFrame2 == info.m_nRenderFrame ) continue; renderable.m_RenderFrame2 = info.m_nRenderFrame; } else { // Translucent entities already have had ComputeTranslucentRenderLeaf called on them // so m_RenderLeaf should be set to the nearest leaf, so that's what we want here. if ( renderable.m_RenderLeaf != leaf ) continue; } // Prevent culling if the renderable is invisible // NOTE: OPAQUE objects can have alpha == 0. // They are made to be opaque because they don't have to be sorted. unsigned char nAlpha = renderable.m_pRenderable->GetFxBlend(); if ( nAlpha == 0 ) continue; Vector absMins, absMaxs; CalcRenderableWorldSpaceAABB( renderable.m_pRenderable, absMins, absMaxs ); // If the renderable is inside an area, cull it using the frustum for that area. if ( portalTestEnts && renderable.m_Area != -1 ) { VPROF( "r_PortalTestEnts" ); if ( !engine->DoesBoxTouchAreaFrustum( absMins, absMaxs, renderable.m_Area ) ) continue; } else { // cull with main frustum if ( engine->CullBox( absMins, absMaxs ) ) continue; } // UNDONE: Investigate speed tradeoffs of occlusion culling brush models too? if ( renderable.m_Flags & RENDER_FLAGS_STUDIO_MODEL ) { // test to see if this renderable is occluded by the engine's occlusion system if ( engine->IsOccluded( absMins, absMaxs ) ) continue; } if( renderable.m_RenderGroup != RENDER_GROUP_TRANSLUCENT_ENTITY ) { RenderGroup_t group = (RenderGroup_t)renderable.m_RenderGroup; AddRenderableToRenderList( *info.m_pRenderList, renderable.m_pRenderable, worldListLeafIndex, group, handle); } else { bool bTwoPass = ((renderable.m_Flags & RENDER_FLAGS_TWOPASS) != 0) && ( nAlpha == 255 ); AddRenderableToRenderList( *info.m_pRenderList, renderable.m_pRenderable, worldListLeafIndex, (RenderGroup_t)renderable.m_RenderGroup, handle, bTwoPass ); // Add to both lists if it's a two-pass model... if (bTwoPass) { AddRenderableToRenderList( *info.m_pRenderList, renderable.m_pRenderable, worldListLeafIndex, RENDER_GROUP_OPAQUE_ENTITY, handle, bTwoPass ); } } } // Do detail objects. // These don't have render handles! if ( IsPC() && info.m_bDrawDetailObjects && ShouldDrawDetailObjectsInLeaf( leaf, info.m_nDetailBuildFrame ) ) { idx = m_Leaf[leaf].m_FirstDetailProp; int count = m_Leaf[leaf].m_DetailPropCount; while( --count >= 0 ) { IClientRenderable* pRenderable = DetailObjectSystem()->GetDetailModel(idx); // FIXME: This if check here is necessary because the detail object system also maintains // lists of sprites... if (pRenderable) { if( pRenderable->IsTransparent() ) { // Lots of the detail entities are invsible so avoid sorting them and all that. if( pRenderable->GetFxBlend() > 0 ) { AddRenderableToRenderList( *info.m_pRenderList, pRenderable, worldListLeafIndex, RENDER_GROUP_TRANSLUCENT_ENTITY, DETAIL_PROP_RENDER_HANDLE ); } } else { AddRenderableToRenderList( *info.m_pRenderList, pRenderable, worldListLeafIndex, RENDER_GROUP_OPAQUE_ENTITY, DETAIL_PROP_RENDER_HANDLE ); } } ++idx; } } }
C_BaseEntity *CResultProxy::BindArgToEntity( void *pArg ) { IClientRenderable *pRend = (IClientRenderable *)pArg; return pRend->GetIClientUnknown()->GetBaseEntity(); }
C_BaseEntity *CConveyorMaterialProxy::BindArgToEntity( void *pArg ) { IClientRenderable *pRend = (IClientRenderable *)pArg; return pRend->GetIClientUnknown()->GetBaseEntity(); }
//----------------------------------------------------------------------------- // Does the dirty deed //----------------------------------------------------------------------------- void CMaterialModifyAnimatedProxy::OnBind( void *pEntity ) { assert ( m_AnimatedTextureVar ); if( m_AnimatedTextureVar->GetType() != MATERIAL_VAR_TYPE_TEXTURE ) return; ITexture *pTexture; pTexture = m_AnimatedTextureVar->GetTextureValue(); // Get the modified material vars from the entity input IClientRenderable *pRend = (IClientRenderable *)pEntity; if ( pRend ) { C_BaseEntity *pBaseEntity = pRend->GetIClientUnknown()->GetBaseEntity(); if ( pBaseEntity ) { for ( C_BaseEntity *pChild = pBaseEntity->FirstMoveChild(); pChild; pChild = pChild->NextMovePeer() ) { C_MaterialModifyControl *pControl = dynamic_cast<C_MaterialModifyControl*>( pChild ); if ( !pControl ) continue; if ( !pControl->HasNewAnimationCommands() ) continue; // Read the data from the modify entity materialanimcommands_t sCommands; pControl->GetAnimationCommands( &sCommands ); m_iFrameStart = sCommands.iFrameStart; m_iFrameEnd = sCommands.iFrameEnd; m_bCustomWrap = sCommands.bWrap; m_flCustomFramerate = sCommands.flFrameRate; m_bReachedEnd = false; m_flStartTime = gpGlobals->curtime; pControl->ClearAnimationCommands(); } } } // Init all the vars based on whether we're using the base material settings, // or the custom ones from the entity input. int numFrames; bool bWrapAnimation; float flFrameRate; int iLastFrame; // Do we have a custom frame section from the server? if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET ) { if ( m_iFrameEnd == MATERIAL_MODIFY_ANIMATION_UNSET ) { m_iFrameEnd = pTexture->GetNumAnimationFrames(); } numFrames = (m_iFrameEnd - m_iFrameStart) + 1; bWrapAnimation = m_bCustomWrap; flFrameRate = m_flCustomFramerate; iLastFrame = (m_iFrameEnd - 1); } else { numFrames = pTexture->GetNumAnimationFrames(); bWrapAnimation = m_WrapAnimation; flFrameRate = m_FrameRate; iLastFrame = (numFrames - 1); } // Have we already reached the end? If so, stay there. if ( m_bReachedEnd && !bWrapAnimation ) { m_AnimatedTextureFrameNumVar->SetIntValue( iLastFrame ); return; } // NOTE: Must not use relative time based methods here // because the bind proxy can be called many times per frame. // Prevent multiple Wrap callbacks to be sent for no wrap mode float startTime; if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET ) { startTime = m_flStartTime; } else { startTime = GetAnimationStartTime(pEntity); } float deltaTime = gpGlobals->curtime - startTime; float prevTime = deltaTime - gpGlobals->frametime; // Clamp.. if (deltaTime < 0.0f) deltaTime = 0.0f; if (prevTime < 0.0f) prevTime = 0.0f; float frame = flFrameRate * deltaTime; float prevFrame = flFrameRate * prevTime; int intFrame = ((int)frame) % numFrames; int intPrevFrame = ((int)prevFrame) % numFrames; if ( m_iFrameStart != MATERIAL_MODIFY_ANIMATION_UNSET ) { intFrame += m_iFrameStart; intPrevFrame += m_iFrameStart; } // Report wrap situation... if (intPrevFrame > intFrame) { m_bReachedEnd = true; if (bWrapAnimation) { AnimationWrapped( pEntity ); } else { // Only sent the wrapped message once. // when we're in non-wrapping mode if (prevFrame < numFrames) AnimationWrapped( pEntity ); intFrame = numFrames - 1; } } m_AnimatedTextureFrameNumVar->SetIntValue( intFrame ); if ( ToolsEnabled() ) { ToolFramework_RecordMaterialParams( GetMaterial() ); } }