KDint KD_APIENTRY ThreadOnce(KDThreadOnce *once_control, void (*init_routine)(void)) { EVENT("(KDThreadOnce *once_control = 0x%0.8p, void (*init_routine)(void) = 0x%0.8p)", once_control, init_routine); ExecuteOnce(once_control, init_routine); return 0; }
static void AddNeighbor( const CCoreDispInfo *pListBase, CCoreDispInfo *pMain, int iEdge, // Which of pMain's sides this is on. int iSub, // Which sub neighbor this takes up in pSide. NeighborSpan span, // What span this fills in pMain. CCoreDispInfo *pOther, int iNeighborEdge, NeighborSpan nbSpan ) { // The edge iteration before coming in here goes 0-1, 1-2, 2-3, 3-4. // This flips the sense of CORNER_TO_MIDPOINT/MIDPOINT_TO_CORNER on the right and // bottom edges and is undone here. span = NeighborSpanFlip( iEdge, span ); nbSpan = NeighborSpanFlip( iNeighborEdge, nbSpan ); // Get the subspan this fills on our displacement. CDispSubNeighbor *pSub = &pMain->GetEdgeNeighbor(iEdge)->m_SubNeighbors[iSub]; // Which subspan does this use in the neighbor? CDispSubNeighbor *pNeighborSub; if ( nbSpan == MIDPOINT_TO_CORNER ) pNeighborSub = &pOther->GetEdgeNeighbor(iNeighborEdge)->m_SubNeighbors[1]; else pNeighborSub = &pOther->GetEdgeNeighbor(iNeighborEdge)->m_SubNeighbors[0]; // Make sure this slot isn't used on either displacement. if ( pSub->IsValid() || pNeighborSub->IsValid() ) { ExecuteOnce( Warning( "Found a displacement edge abutting multiple other edges.\n" ) ); return; } // Now just copy the data into each displacement. pSub->m_iNeighbor = pOther - pListBase; pSub->m_NeighborOrientation = g_CoreDispNeighborOrientationMap[iEdge][iNeighborEdge]; pSub->m_Span = span; pSub->m_NeighborSpan = nbSpan; pNeighborSub->m_iNeighbor = pMain - pListBase; pNeighborSub->m_NeighborOrientation = g_CoreDispNeighborOrientationMap[iNeighborEdge][iEdge]; pNeighborSub->m_Span = nbSpan; pNeighborSub->m_NeighborSpan = span; #if defined( _DEBUG ) // Walk an iterator over the new connection to make sure it works. CDispSubEdgeIterator it; it.Start( pMain, iEdge, iSub ); while ( it.Next() ) { CVertIndex nbIndex; TransformIntoNeighbor( pMain, iEdge, it.GetVertIndex(), nbIndex ); } #endif }
// Pick a sequence for the given activity. If the current sequence is appropriate for the // current activity, and its stored weight is negative (whatever that means), always select // it. Otherwise perform a weighted selection -- imagine a large roulette wheel, with each // sequence having a number of spaces corresponding to its weight. int CStudioHdr::CActivityToSequenceMapping::SelectWeightedSequence( CStudioHdr *pstudiohdr, int activity, int curSequence ) { if (!ValidateAgainst(pstudiohdr)) { AssertMsg1(false, "CStudioHdr %s has changed its vmodel pointer without reinitializing its activity mapping! Now performing emergency reinitialization.", pstudiohdr->pszName()); ExecuteOnce(DebuggerBreakIfDebugging()); Reinitialize(pstudiohdr); } // a null m_pSequenceTuples just means that this studio header has no activities. if (!m_pSequenceTuples) return ACTIVITY_NOT_AVAILABLE; // is the current sequence appropriate? if (curSequence >= 0) { mstudioseqdesc_t &seqdesc = pstudiohdr->pSeqdesc( curSequence ); if (seqdesc.activity == activity && seqdesc.actweight < 0) return curSequence; } // get the data for the given activity HashValueType dummy( activity, 0, 0, 0 ); UtlHashHandle_t handle = m_ActToSeqHash.Find(dummy); if (!m_ActToSeqHash.IsValidHandle(handle)) { return ACTIVITY_NOT_AVAILABLE; } const HashValueType * __restrict actData = &m_ActToSeqHash[handle]; int weighttotal = actData->totalWeight; // generate a random number from 0 to the total weight int randomValue; if ( IsInPrediction() ) { randomValue = SharedRandomInt( "SelectWeightedSequence", 0, weighttotal - 1 ); } else { randomValue = RandomInt( 0, weighttotal - 1 ); } // chug through the entries in the list (they are sequential therefore cache-coherent) // until we run out of random juice SequenceTuple * __restrict sequenceInfo = m_pSequenceTuples + actData->startingIdx; const SequenceTuple *const stopHere = sequenceInfo + actData->count; // this is a backup // in case the weights are somehow miscalculated -- we don't read or write through // it (because it aliases the restricted pointer above); it's only here for // the comparison. while (randomValue >= sequenceInfo->weight && sequenceInfo < stopHere) { randomValue -= sequenceInfo->weight; ++sequenceInfo; } return sequenceInfo->seqnum; }
void CPoseDebuggerImpl::StartBlending( IClientNetworkable *pEntity, const CStudioHdr *pStudioHdr ) { // virtualmodel_t const *pVMdl = pStudioHdr->GetVirtualModel(); // if ( !pVMdl ) // return; if ( !ThreadInMainThread() ) { ExecuteOnce( "Turn of threading when using pose debugger\n" ); return; } // If we are starting a new model then finalize the previous one if ( pStudioHdr != m_pLastModel && m_pLastModel ) { MapModel::IndexType_t idx = m_mapModel.Find( m_pLastModel ); if ( idx != m_mapModel.InvalidIndex() ) { ModelPoseDebugInfo &mpi = m_mapModel.Element( idx ); ModelPoseDebugInfo *pMpiOld = NULL; MapModel::IndexType_t idxMapModelOld = m_mapModelOld.Find( m_pLastModel ); if ( idxMapModelOld != m_mapModelOld.InvalidIndex() ) { pMpiOld = &m_mapModelOld.Element( idxMapModelOld ); } mpi.AddInfoText( NULL, pMpiOld ); mpi.PrintPendingInfoText( m_nPosPrint ); } } m_pLastModel = pStudioHdr; // Go ahead with the new model studiohdr_t const *pRMdl = pStudioHdr->GetRenderHdr(); if ( !pRMdl || !pRMdl->numincludemodels ) return; // Entity number int iEntNum = pEntity->entindex(); if ( !IsModelShown( iEntNum ) ) return; // Check if we saw the model if ( m_mapModel.Find( pStudioHdr ) != m_mapModel.InvalidIndex() ) { // Initialize the printing position m_nPosPrint = 9; // Swap the maps m_mapModelOld.RemoveAll(); m_mapModelOld.Swap( m_mapModel ); // Zero out the text on the old map for ( int k = m_mapModelOld.FirstInorder(); k != m_mapModelOld.InvalidIndex(); k = m_mapModelOld.NextInorder( k ) ) { ModelPoseDebugInfo &mpi = m_mapModelOld[k]; mpi.m_iCurrentText = 0; } } else { // Next model m_nPosPrint += 3; } ModelPoseDebugInfo mpi; mpi.m_iEntNum = iEntNum; m_mapModel.Insert( pStudioHdr, mpi ); con_nprint_s nxPrn = { 0 }; nxPrn.index = m_nPosPrint; nxPrn.time_to_live = -1; nxPrn.color[0] = 0.9f, nxPrn.color[1] = 1.0f, nxPrn.color[2] = 0.9f; nxPrn.fixed_width_font = false; engine->Con_NXPrintf( &nxPrn, "[ %2d ] Model: %s", iEntNum, pRMdl->pszName() ); m_nPosPrint += 3; }
int CStudioHdr::CActivityToSequenceMapping::SelectWeightedSequenceFromModifiers( CStudioHdr *pstudiohdr, int activity, CUtlSymbol *pActivityModifiers, int iModifierCount ) { if ( !pstudiohdr->SequencesAvailable() ) { return ACTIVITY_NOT_AVAILABLE; } VerifySequenceIndex( pstudiohdr ); if ( pstudiohdr->GetNumSeq() == 1 ) { return ( ::GetSequenceActivity( pstudiohdr, 0, NULL ) == activity ) ? 0 : ACTIVITY_NOT_AVAILABLE; } if (!ValidateAgainst(pstudiohdr)) { AssertMsg1(false, "CStudioHdr %s has changed its vmodel pointer without reinitializing its activity mapping! Now performing emergency reinitialization.", pstudiohdr->pszName()); ExecuteOnce(DebuggerBreakIfDebugging()); Reinitialize(pstudiohdr); } // a null m_pSequenceTuples just means that this studio header has no activities. if (!m_pSequenceTuples) return ACTIVITY_NOT_AVAILABLE; // get the data for the given activity HashValueType dummy( activity, 0, 0, 0 ); UtlHashHandle_t handle = m_ActToSeqHash.Find(dummy); if (!m_ActToSeqHash.IsValidHandle(handle)) { return ACTIVITY_NOT_AVAILABLE; } const HashValueType * __restrict actData = &m_ActToSeqHash[handle]; // go through each sequence and give it a score int top_score = -1; CUtlVector<int> topScoring( actData->count, actData->count ); for ( int i = 0; i < actData->count; i++ ) { SequenceTuple * __restrict sequenceInfo = m_pSequenceTuples + actData->startingIdx + i; int score = 0; // count matching activity modifiers for ( int m = 0; m < iModifierCount; m++ ) { int num_modifiers = sequenceInfo->iNumActivityModifiers; for ( int k = 0; k < num_modifiers; k++ ) { if ( sequenceInfo->pActivityModifiers[ k ] == pActivityModifiers[ m ] ) { score++; break; } } } if ( score > top_score ) { topScoring.RemoveAll(); topScoring.AddToTail( sequenceInfo->seqnum ); top_score = score; } } // randomly pick between the highest scoring sequences ( NOTE: this method of selecting a sequence ignores activity weights ) if ( IsInPrediction() ) { return topScoring[ SharedRandomInt( "SelectWeightedSequence", 0, topScoring.Count() - 1 ) ]; } return topScoring[ RandomInt( 0, topScoring.Count() - 1 ) ]; }