//----------------------------------------------------------------------------- // Purpose: Clears all the memory queues and free's their memory //----------------------------------------------------------------------------- void CVGui::ClearMessageQueues() { Assert(!m_InDispatcher); {FOR_EACH_LL( m_MessageQueue, i ) { if (m_MessageQueue[i]._params) { m_MessageQueue[i]._params->deleteThis(); } }} m_MessageQueue.RemoveAll(); // secondary message queue, holds all vgui messages generated by vgui {FOR_EACH_LL( m_SecondaryQueue, i ) { if (m_SecondaryQueue[i]._params) { m_SecondaryQueue[i]._params->deleteThis(); } }} m_SecondaryQueue.RemoveAll(); // timing queue, holds all the messages that have to arrive at a specified time while (m_DelayedMessageQueue.Count() > 0) { if (m_DelayedMessageQueue.ElementAtHead()._params) { m_DelayedMessageQueue.ElementAtHead()._params->deleteThis(); } m_DelayedMessageQueue.RemoveAtHead(); } }
// Remove any envelope commands from the list (dynamically changing envelope) void CSoundControllerImp::CommandClear( CSoundPatch *pSound ) { for ( int i = m_commandList.Count()-1; i >= 0; i-- ) { SoundCommand_t *pCmd = m_commandList.Element( i ); if ( pCmd->m_pPatch == pSound ) { m_commandList.RemoveAt(i); delete pCmd; } } }
//----------------------------------------------------------------------------- // Purpose: Update the active sounds, dequeue any events and move the ramps //----------------------------------------------------------------------------- void CSoundControllerImp::SystemUpdate( void ) { float time = g_pEffects->Time(); float deltaTime = time - m_flLastTime; // handle clock resets if ( deltaTime < 0 ) deltaTime = 0; m_flLastTime = time; while ( m_commandList.Count() ) { SoundCommand_t *pCmd = m_commandList.ElementAtHead(); // Commands are sorted by time. // process any that should occur by the current time if ( time >= pCmd->m_time ) { m_commandList.RemoveAtHead(); ProcessCommand( pCmd ); delete pCmd; } else { break; } } // NOTE: Because this loop goes from the end to the beginning // we can fast remove inside it without breaking the indexing for ( int i = m_soundList.Count()-1; i >=0; i-- ) { CSoundPatch *pNode = m_soundList[i]; if ( !pNode->Update( time, deltaTime ) ) { pNode->Reset(); m_soundList.FastRemove( i ); } } }
//----------------------------------------------------------------------------- // Purpose: Adds a message to the queue to be sent to a user //----------------------------------------------------------------------------- void CVGui::PostMessage(VPANEL target, KeyValues *params, VPANEL from, float delay) { // Ignore all messages in re-entrant mode if ( IsReentrant() ) { Assert( 0 ); if (params) { params->deleteThis(); } return; } if (!target) { if (params) { params->deleteThis(); } return; } MessageItem_t messageItem; messageItem._messageTo = (target != (VPANEL)-1) ? g_pIVgui->PanelToHandle(target) : 0xFFFFFFFF; messageItem._params = params; Assert(params->GetName()); messageItem._from = g_pIVgui->PanelToHandle(from); messageItem._arrivalTime = 0; messageItem._messageID = m_iCurrentMessageID++; /* message debug code //if ( stricmp(messageItem._params->GetName(),"CursorMoved") && stricmp(messageItem._params->GetName(),"KeyFocusTicked")) { g_pIVgui->DPrintf2( "posting( %s -- %i )\n", messageItem._params->GetName(), messageItem._messageID ); } */ // add the message to the correct message queue if (delay > 0.0f) { messageItem._arrivalTime = g_pSystem->GetTimeMillis() + (delay * 1000); m_DelayedMessageQueue.Insert(messageItem); } else if (m_InDispatcher) { m_SecondaryQueue.AddToTail(messageItem); } else { m_MessageQueue.AddToTail(messageItem); } }
//----------------------------------------------------------------------------- // Saves the sound patch + associated commands //----------------------------------------------------------------------------- void CSoundControllerImp::SaveSoundPatch( CSoundPatch *pSoundPatch, ISave *pSave ) { int i; // Write out the sound patch pSave->StartBlock(); pSave->WriteAll( pSoundPatch ); pSave->EndBlock(); // Count the number of commands that refer to the sound patch int nCount = 0; for ( i = m_commandList.Count()-1; i >= 0; i-- ) { SoundCommand_t *pCmd = m_commandList.Element( i ); if ( pCmd->m_pPatch == pSoundPatch ) { nCount++; } } // Write out the number of commands, followed by each command itself pSave->StartBlock(); pSave->WriteInt( &nCount ); for ( i = m_commandList.Count()-1; i >= 0; i-- ) { SoundCommand_t *pCmd = m_commandList.Element( i ); if ( pCmd->m_pPatch == pSoundPatch ) { pSave->StartBlock(); pSave->WriteAll( pCmd ); pSave->EndBlock(); } } pSave->EndBlock(); }
// Reset the whole system (level change, etc.) void CSoundControllerImp::SystemReset( void ) { for ( int i = m_soundList.Count()-1; i >=0; i-- ) { CSoundPatch *pNode = m_soundList[i]; // shutdown all active sounds pNode->Shutdown(); } // clear the list m_soundList.Purge(); // clear the command queue m_commandList.RemoveAll(); }
//----------------------------------------------------------------------------- // Inserts the command into the list, sorted by time //----------------------------------------------------------------------------- void CSoundControllerImp::CommandInsert( SoundCommand_t *pCommand ) { m_commandList.Insert( pCommand ); }
//----------------------------------------------------------------------------- // Purpose: message pump // loops through and sends all active messages // note that more messages may be posted during the process //----------------------------------------------------------------------------- bool CVGui::DispatchMessages() { int time = g_pSystem->GetTimeMillis(); m_InDispatcher = true; bool doneWork = (m_MessageQueue.Count() > 12); bool bUsingDelayedQueue = (m_DelayedMessageQueue.Count() > 0); // Need two passes because we send the mouse move message after all // other messages are done, but the mouse move message may itself generate // some more messages int nPassCount = 0; while ( nPassCount < 2 ) { while (m_MessageQueue.Count() > 0 || (m_SecondaryQueue.Count() > 0) || bUsingDelayedQueue) { // get the first message MessageItem_t *messageItem = NULL; int messageIndex = 0; // use the secondary queue until it empties. empty it after each message in the // primary queue. this makes primary messages completely resolve bool bUsingSecondaryQueue = (m_SecondaryQueue.Count() > 0); if (bUsingSecondaryQueue) { doneWork = true; messageIndex = m_SecondaryQueue.Head(); messageItem = &m_SecondaryQueue[messageIndex]; } else if (bUsingDelayedQueue) { if (m_DelayedMessageQueue.Count() >0) { messageItem = (MessageItem_t*)&m_DelayedMessageQueue.ElementAtHead(); } if (!messageItem || messageItem->_arrivalTime > time) { // no more items in the delayed message queue, move to the system queue bUsingDelayedQueue = false; continue; } } else { messageIndex = m_MessageQueue.Head(); messageItem = &m_MessageQueue[messageIndex]; } // message debug code if ( m_bDebugMessages ) { char *qname = bUsingSecondaryQueue ? "Secondary" : "Primary"; if (strcmp(messageItem->_params->GetName(), "Tick") && strcmp(messageItem->_params->GetName(), "MouseFocusTicked") && strcmp(messageItem->_params->GetName(), "KeyFocusTicked") && strcmp(messageItem->_params->GetName(), "CursorMoved")) { if (!stricmp(messageItem->_params->GetName(), "command")) { g_pIVgui->DPrintf2( "%s Queue dispatching command( %s, %s -- %i )\n", qname, messageItem->_params->GetName(), messageItem->_params->GetString("command"), messageItem->_messageID ); } else { g_pIVgui->DPrintf2( "%s Queue dispatching( %s -- %i )\n", qname ,messageItem->_params->GetName(), messageItem->_messageID ); } } } // send it KeyValues *params = messageItem->_params; // Deal with special internal cursor movement messages if ( messageItem->_messageTo == 0xFFFFFFFF ) { if ( !Q_stricmp( params->GetName(), "SetCursorPosInternal" ) ) { int nXPos = params->GetInt( "xpos", 0 ); int nYPos = params->GetInt( "ypos", 0 ); g_pInput->UpdateCursorPosInternal( nXPos, nYPos ); } } else { VPanel *vto = (VPanel *)g_pIVgui->HandleToPanel(messageItem->_messageTo); if (vto) { // Msg("Sending message: %s to %s\n", params ? params->GetName() : "\"\"", vto->GetName() ? vto->GetName() : "\"\""); vto->SendMessage(params, g_pIVgui->HandleToPanel(messageItem->_from)); } } // free the keyvalues memory // we can't reference the messageItem pointer anymore since the queue might have moved in memory if (params) { params->deleteThis(); } // remove it from the queue if (bUsingSecondaryQueue) { m_SecondaryQueue.Remove(messageIndex); } else if (bUsingDelayedQueue) { m_DelayedMessageQueue.RemoveAtHead(); } else { m_MessageQueue.Remove(messageIndex); } } ++nPassCount; if ( nPassCount == 1 ) { // Specifically post the current mouse position as a message g_pInput->PostCursorMessage(); } } // Make sure the windows cursor is in the right place after processing input // Needs to be done here because a message provoked by the cursor moved // message may move the cursor also g_pInput->HandleExplicitSetCursor( ); m_InDispatcher = false; return doneWork; }