//----------------------------------------------------------------------------- // Think for all entities that need it //----------------------------------------------------------------------------- void CClientThinkList::PerformThinkFunctions() { VPROF_("Client Thinks", 1, VPROF_BUDGETGROUP_CLIENT_SIM, false, BUDGETFLAG_CLIENT); int nMaxList = m_ThinkEntries.Count(); if ( nMaxList == 0 ) return; ++m_nIterEnum; // Build a list of entities to think this frame, in order of hierarchy. // Do this because the list may be modified during the thinking and also to // prevent bad situations where an entity can think more than once in a frame. ThinkEntry_t **ppThinkEntryList = (ThinkEntry_t**)stackalloc( nMaxList * sizeof(ThinkEntry_t*) ); int nThinkCount = 0; for ( unsigned short iCur=m_ThinkEntries.Head(); iCur != m_ThinkEntries.InvalidIndex(); iCur = m_ThinkEntries.Next( iCur ) ) { AddEntityToFrameThinkList( &m_ThinkEntries[iCur], false, nThinkCount, ppThinkEntryList ); Assert( nThinkCount <= nMaxList ); } // While we're in the loop, no changes to the think list are allowed m_bInThinkLoop = true; // Perform thinks on all entities that need it int i; for ( i = 0; i < nThinkCount; ++i ) { PerformThinkFunction( ppThinkEntryList[i], gpGlobals->curtime ); } m_bInThinkLoop = false; // Apply changes to the think list int nCount = m_aChangeList.Count(); for ( i = 0; i < nCount; ++i ) { ClientThinkHandle_t hThink = m_aChangeList[i].m_hThink; if ( hThink != INVALID_THINK_HANDLE ) { // This can happen if the same think handle was removed twice if ( !m_ThinkEntries.IsInList( (unsigned long)hThink ) ) continue; // NOTE: This is necessary for the case where the client entity handle // is slammed to NULL during a think interval; the hThink will get stuck // in the list and can never leave. SetNextClientThink( hThink, m_aChangeList[i].m_flNextTime ); } else { SetNextClientThink( m_aChangeList[i].m_hEnt, m_aChangeList[i].m_flNextTime ); } } m_aChangeList.RemoveAll(); // Clear out the client-side entity deletion list. CleanUpDeleteList(); }
// This is called by cdll_client_int to setup view model origins. This has to be done before // simulation so entities can access attachment points on view models during simulation. void CViewRender::OnRenderStart() { VPROF_("CViewRender::OnRenderStart", 2, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, false, 0); SetUpViews(); // Adjust mouse sensitivity based upon the current FOV C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); if ( player ) { default_fov.SetValue( player->m_iDefaultFOV ); //Update our FOV, including any zooms going on int iDefaultFOV = default_fov.GetInt(); int localFOV = player->GetFOV(); int min_fov = player->GetMinFOV(); // Don't let it go too low localFOV = MAX( min_fov, localFOV ); gHUD.m_flFOVSensitivityAdjust = 1.0f; #ifndef _XBOX if ( gHUD.m_flMouseSensitivityFactor ) { gHUD.m_flMouseSensitivity = sensitivity.GetFloat() * gHUD.m_flMouseSensitivityFactor; } else #endif { // No override, don't use huge sensitivity if ( localFOV == iDefaultFOV ) { #ifndef _XBOX // reset to saved sensitivity gHUD.m_flMouseSensitivity = 0; #endif } else { // Set a new sensitivity that is proportional to the change from the FOV default and scaled // by a separate compensating factor if ( iDefaultFOV == 0 ) { Assert(0); // would divide by zero, something is broken with iDefatulFOV iDefaultFOV = 1; } gHUD.m_flFOVSensitivityAdjust = ((float)localFOV / (float)iDefaultFOV) * // linear fov downscale zoom_sensitivity_ratio.GetFloat(); // sensitivity scale factor #ifndef _XBOX gHUD.m_flMouseSensitivity = gHUD.m_flFOVSensitivityAdjust * sensitivity.GetFloat(); // regular sensitivity #endif } } } }
void CColorCorrectionMgr::ResetColorCorrectionWeights() { VPROF_("ResetColorCorrectionWeights", 2, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, false, 0); // FIXME: Where should I put this? It needs to happen prior to SimulateEntities() // which is where the client thinks for c_colorcorrection + c_colorcorrectionvolumes // update the color correction weights. CMatRenderContextPtr pRenderContext( g_pMaterialSystem ); pRenderContext->ResetLookupWeights(); m_nActiveWeightCount = 0; m_bHaveExclusiveWeight = false; m_flExclusiveWeight = 0.0f; m_colorCorrectionWeights.RemoveAll(); }
//----------------------------------------------------------------------------- int CAudioMixerWave::MixDataToDevice_( IAudioDevice *pDevice, channel_t *pChannel, int sampleCount, int outputRate, int outputOffset, bool bSkipAllMixing ) { // shouldn't be playing this if finished, but return if we are if ( m_finished ) return 0; // save this to compute total output int startingOffset = outputOffset; double inputRate = (pChannel->pitch * m_pData->Source().SampleRate()); double rate_max = inputRate / outputRate; // If we are terminating this wave prematurely, then make sure we detect the limit if ( m_forcedEndSample ) { // How many total input samples will we need? int samplesRequired = (int)(sampleCount * rate_max); // will this hit the end? if ( m_fsample_index + samplesRequired >= m_forcedEndSample ) { // yes, mark finished and truncate the sample request m_finished = true; sampleCount = (int)( (m_forcedEndSample - m_fsample_index) / rate_max ); } } /* Example: rate = 1.2, sampleCount = 3 (ie: # of samples to return ) ______load 4 samples_____ ________load 4 samples____ ___load 3 samples__ 0 1 2 3 4 5 6 7 8 9 10 sample_index (whole samples) ^ ^ ^ ^ ^ ^ ^ ^ ^ | | | | | | | | | 0 1.2 2.4 3.6 4.8 6.0 7.2 8.4 9.6 m_fsample_index (rate*sample) _______return 3_______ _______return 3_______ _______return 3__________ ^ ^ | | m_sample_loaded_index----- | (after first load 4 samples, this is where pointers are) m_fsample_index--------- */ while ( sampleCount > 0 ) { bool advanceSample = true; int samples_loaded, outputSampleCount; char *pData = NULL; double fsample_index_prev = m_fsample_index; // save so we can modify in LoadMixBuffer bool bInterpolated_pitch = FUseHighQualityPitch( pChannel ); double rate; VPROF_( bInterpolated_pitch ? "CAudioMixerWave::MixData innerloop interpolated" : "CAudioMixerWave::MixData innerloop not interpolated", 2, VPROF_BUDGETGROUP_OTHER_SOUND, false, BUDGETFLAG_OTHER ); // process samples in paintbuffer-sized batches int sampleCountOut = min( sampleCount, PAINTBUFFER_SIZE ); // cap rate so that we never overflow the input copy buffer. rate = MIX_GetMaxRate( rate_max, sampleCountOut ); if ( m_delaySamples > 0 ) { // If we are preceding sample playback with a delay, // just fill data buffer with 0 value samples. // Because there is no pitch shift applied, outputSampleCount == sampleCountOut. int num_zero_samples = min( m_delaySamples, sampleCountOut ); // Decrement delay counter m_delaySamples -= num_zero_samples; int sampleSize = GetMixSampleSize(); int readBytes = sampleSize * num_zero_samples; // make sure we don't overflow temp copy buffer (g_temppaintbuffer) Assert ( (TEMP_COPY_BUFFER_SIZE * sizeof(portable_samplepair_t)) > readBytes ); pData = (char *)g_temppaintbuffer; // Now copy in some zeroes memset( pData, 0, readBytes ); // we don't pitch shift these samples, so outputSampleCount == samples_loaded samples_loaded = num_zero_samples; outputSampleCount = num_zero_samples; advanceSample = false; // the zero samples are at the output rate, so set the input/output ratio to 1.0 rate = 1.0f; } else { // ask the source for the data... // temp buffer req'd by some data loaders char copyBuf[AUDIOSOURCE_COPYBUF_SIZE]; // compute number of new samples to load at 'rate' so we can // output 'sampleCount' samples, from m_fsample_index to fsample_index_end (inclusive) int sample_load_request = GetSampleLoadRequest( rate, sampleCountOut, bInterpolated_pitch ); // return pointer to a new copy buffer (g_temppaintbuffer) loaded with sample_load_request samples + // first sample(s), which are always the last sample(s) from the previous load. // Always returns sample_load_request samples. Updates m_sample_max_loaded, m_sample_loaded_index. pData = LoadMixBuffer( pChannel, sample_load_request, &samples_loaded, copyBuf ); // LoadMixBuffer should always return requested samples. Assert ( !pData || ( samples_loaded == sample_load_request ) ); outputSampleCount = sampleCountOut; } // no samples available if ( !pData ) { break; } // get sample fraction from 0th sample in copy buffer double sampleFraction = m_fsample_index - floor( m_fsample_index ); // if just skipping samples in source, don't mix, just keep reading if ( !bSkipAllMixing ) { // mix this data to all active paintbuffers // Verify that we won't get a buffer overrun. Assert( floor( sampleFraction + RoundToFixedPoint(rate, (outputSampleCount-1), bInterpolated_pitch) ) <= samples_loaded ); int saveIndex = MIX_GetCurrentPaintbufferIndex(); for ( int i = 0 ; i < CPAINTBUFFERS; i++ ) { if ( g_paintBuffers[i].factive ) { // mix channel into all active paintbuffers MIX_SetCurrentPaintbuffer( i ); Mix( pDevice, // Device. pChannel, // Channel. pData, // Input buffer. outputOffset, // Output position. FIX_FLOAT( sampleFraction ), // Iterators. FIX_FLOAT( rate ), outputSampleCount, 0 ); } } MIX_SetCurrentPaintbuffer( saveIndex ); } if ( advanceSample ) { // update sample index to point to the next sample to output // if we're not delaying // Use fixed point math to make sure we exactly match results of mix // iterators. m_fsample_index = fsample_index_prev + RoundToFixedPoint( rate, outputSampleCount, bInterpolated_pitch ); } outputOffset += outputSampleCount; sampleCount -= outputSampleCount; } // Did we run out of samples? if so, mark finished if ( sampleCount > 0 ) { m_finished = true; } // total number of samples mixed !!! at the output clock rate !!! return outputOffset - startingOffset; }
// This is called by cdll_client_int to setup view model origins. This has to be done before // simulation so entities can access attachment points on view models during simulation. void CViewRender::OnRenderStart() { VPROF_("CViewRender::OnRenderStart", 2, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, false, 0); IterateRemoteSplitScreenViewSlots_Push( true ); FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh ) { ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( hh ); // This will fill in one of the m_UserView[ hh ] slots SetUpView(); // Adjust mouse sensitivity based upon the current FOV C_BasePlayer *player = C_BasePlayer::GetLocalPlayer(); if ( player ) { default_fov.SetValue( player->m_iDefaultFOV ); //Update our FOV, including any zooms going on int iDefaultFOV = default_fov.GetInt(); int localFOV = player->GetFOV(); int min_fov = player->GetMinFOV(); // Don't let it go too low localFOV = MAX( min_fov, localFOV ); GetHud().m_flFOVSensitivityAdjust = 1.0f; #ifndef _XBOX if ( GetHud().m_flMouseSensitivityFactor ) { GetHud().m_flMouseSensitivity = sensitivity.GetFloat() * GetHud().m_flMouseSensitivityFactor; } else #endif { // No override, don't use huge sensitivity if ( localFOV == iDefaultFOV ) { #ifndef _XBOX // reset to saved sensitivity GetHud().m_flMouseSensitivity = 0; #endif } else { // Set a new sensitivity that is proportional to the change from the FOV default and scaled // by a separate compensating factor if ( iDefaultFOV == 0 ) { Assert(0); // would divide by zero, something is broken with iDefatulFOV iDefaultFOV = 1; } GetHud().m_flFOVSensitivityAdjust = ((float)localFOV / (float)iDefaultFOV) * // linear fov downscale zoom_sensitivity_ratio.GetFloat(); // sensitivity scale factor #ifndef _XBOX GetHud().m_flMouseSensitivity = GetHud().m_flFOVSensitivityAdjust * sensitivity.GetFloat(); // regular sensitivity #endif } } } } // Setup the frustum cache for this frame. m_bAllowViewAccess = true; FOR_EACH_VALID_SPLITSCREEN_PLAYER( iSlot ) { const CViewSetup &view = GetView( iSlot ); FrustumCache()->Add( &view, iSlot ); } FrustumCache()->SetUpdated(); m_bAllowViewAccess = false; IterateRemoteSplitScreenViewSlots_Pop(); }