virtual int handleEvent( mxEvent *event )
	{
		int iret = 0;
		switch ( event->event )
		{
		default:
			break;
		case mxEvent::Action:
			{
				iret = 1;
				switch ( event->action )
				{
				default:
					iret = 0;
					break;
				case IDC_MODELTAB_SHOWALL:
				case IDC_MODELTAB_HIDEALL:
					{
						bool show = ( event->action == IDC_MODELTAB_SHOWALL ) ? true : false;
						int c = models->Count();
						for ( int i = 0; i < c ; i++ )
						{
							models->ShowModelIn3DView( i, show );
						}
					}
					break;
				case IDC_MODELTAB_LOAD:
					{
						const char *ptr = mxGetOpenFileName(
							this, 
							FacePoser_MakeWindowsSlashes( va( "%s/models/", GetGameDirectory() ) ), 
							"*.mdl" );

						if (ptr)
						{
							g_MDLViewer->LoadModelFile( ptr );
						}
					}
					break;
				case IDC_MODELTAB_CLOSE:
					{
						int idx = getSelectedIndex();
						if ( idx >= 0 )
						{
							models->FreeModel( idx );
						}
					}
					break;
				case IDC_MODELTAB_CLOSEALL:
					{
						models->CloseAllModels();
					}
					break;
				case IDC_MODELTAB_CENTERONFACE:
					{
						g_pControlPanel->CenterOnFace();
					}
					break;
				case IDC_MODELTAB_TOGGLE3DVIEW:
					{
						int idx = getSelectedIndex();
						if ( idx >= 0 )
						{
							bool visible = models->IsModelShownIn3DView( idx );
							models->ShowModelIn3DView( idx, !visible );
						}
					}
					break;
				case IDC_MODELTAB_ASSOCIATEACTOR:
					{
						int idx = getSelectedIndex();
						if ( idx >= 0 )
						{
							char const *modelname = models->GetModelFileName( idx );

							CChoreoScene *scene = g_pChoreoView->GetScene();
							if ( scene )
							{
								CChoiceParams params;
								strcpy( params.m_szDialogTitle, "Associate Actor" );

								params.m_bPositionDialog = false;
								params.m_nLeft = 0;
								params.m_nTop = 0;
								strcpy( params.m_szPrompt, "Choose actor:" );

								params.m_Choices.RemoveAll();

								params.m_nSelected = -1;
								int oldsel = -1;

								int c = scene->GetNumActors();
								ChoiceText text;
								for ( int i = 0; i < c; i++ )
								{
									CChoreoActor *a = scene->GetActor( i );
									Assert( a );

									
									strcpy( text.choice, a->GetName() );

									if ( !stricmp( a->GetFacePoserModelName(), modelname ) )
									{
										params.m_nSelected = i;
										oldsel = -1;
									}

									params.m_Choices.AddToTail( text );
								}
		
								if ( ChoiceProperties( &params ) && 
									params.m_nSelected != oldsel )
								{
									
									// Chose something new...
									CChoreoActor *a = scene->GetActor( params.m_nSelected );
									
									g_pChoreoView->AssociateModelToActor( a, idx );
								}
							}
						}

					}
				}
			}
			break;
		}
		if ( iret )
			return iret;
		return BaseClass::handleEvent( event );
	}
void CheckForOverlappingFlexTracks( CChoreoScene *scene )
{
    for ( int a = 0; a < scene->GetNumActors(); ++a )
    {
        CChoreoActor *actor = scene->GetActor( a );

        CUtlRBTree< CChoreoEvent * >  actorFlexEvents( 0, 0, ChoreEventStartTimeLessFunc );

        for ( int c = 0; c < actor->GetNumChannels(); ++c )
        {
            CChoreoChannel *channel = actor->GetChannel( c );

            for ( int e = 0 ; e < channel->GetNumEvents(); ++e )
            {
                CChoreoEvent *event = channel->GetEvent( e );

                if ( event->GetType() != CChoreoEvent::FLEXANIMATION )
                    continue;

                actorFlexEvents.Insert( event );
            }
        }

        CUtlVector< CUtlLinkedList< CChoreoEvent*, int > >	rows;

        bool done = false;
        int i;
        // Now check for overlaps
        for ( i = actorFlexEvents.FirstInorder(); i != actorFlexEvents.InvalidIndex() && !done; i = actorFlexEvents.NextInorder( i ) )
        {
            CChoreoEvent *e = actorFlexEvents[ i ];
            if ( !rows.Count() )
            {
                rows.AddToTail();

                CUtlLinkedList< CChoreoEvent*, int >& list = rows[ 0 ];
                list.AddToHead( e );
                continue;
            }

            // Does it come totally after what's in rows[0]?
            int rowCount = rows.Count();
            bool addrow = true;

            for ( int j = 0; j < rowCount; j++ )
            {
                CUtlLinkedList< CChoreoEvent*, int >& list = rows[ j ];

                char offender[ 256 ];
                if ( !EventCollidesWithRows( list, e, offender, sizeof( offender ) ) )
                {
                    // Update row event list
                    list.AddToHead( e );
                    addrow = false;
                    break;
                }
                else
                {
                    Msg( "[%s] has overlapping events for actor [%s] [%s] [flex: %s]\n",
                         scene->GetFilename(), actor->GetName(), e->GetName(), offender );
                    done = true;
                }
            }

            if ( addrow )
            {
                // Add a new row
                int idx = rows.AddToTail();
                CUtlLinkedList< CChoreoEvent *, int >& list = rows[ idx ];
                list.AddToHead( e );
            }
        }

        // Assert( rows.Count() <= 1 );
    }
}
void CBaseEventPropertiesDialog::PopulateNamedActorList( HWND wnd, CEventParams *params )
{
	int i;

	char const *mapname = NULL;
	if ( params->m_pScene )
	{
		mapname = params->m_pScene->GetMapname();
	}

	CUtlRBTree< char const *, int >		m_SortedNames( 0, 0, NameLessFunc );

	if ( mapname )
	{
		g_MapEntities.CheckUpdateMap( mapname );

		for ( i = 0; i < g_MapEntities.Count(); i++ )
		{
			char const *name = g_MapEntities.GetName( i );
			if ( name && name[ 0 ] )
			{
				m_SortedNames.Insert( name );
			}
		}
	}

	for ( i = 0 ; i < params->m_pScene->GetNumActors() ; i++ )
	{
		CChoreoActor *actor = params->m_pScene->GetActor( i );
		if ( actor && actor->GetName() && actor->GetName()[0] )
		{
			if ( m_SortedNames.Find( actor->GetName() ) == m_SortedNames.InvalidIndex() )
			{
				m_SortedNames.Insert( actor->GetName() );
			}
		}
	}

	i = m_SortedNames.FirstInorder();
	while ( i != m_SortedNames.InvalidIndex() )
	{
		char const *name = m_SortedNames[ i ];
		if ( name && name[ 0 ] )
		{
			SendMessage( wnd, CB_ADDSTRING, 0, (LPARAM)name ); 
		}

		i = m_SortedNames.NextInorder( i );
	}

	/*
	// Note have to do this here, after posting data to the control, since we are storing a raw string pointer in m_SortedNames!!!
	if ( allActors )
	{
		allActors->deleteThis();
	}
	*/

	// These events can also be directed at another player or named target, too
	SendMessage( wnd, CB_ADDSTRING, 0, (LPARAM)"!player" );
	SendMessage( wnd, CB_ADDSTRING, 0, (LPARAM)"!enemy" );
	SendMessage( wnd, CB_ADDSTRING, 0, (LPARAM)"!self" );
	SendMessage( wnd, CB_ADDSTRING, 0, (LPARAM)"!friend" );
	SendMessage( wnd, CB_ADDSTRING, 0, (LPARAM)"!speechtarget" );
	SendMessage( wnd, CB_ADDSTRING, 0, (LPARAM)"!target1" );
	SendMessage( wnd, CB_ADDSTRING, 0, (LPARAM)"!target2" );
	SendMessage( wnd, CB_ADDSTRING, 0, (LPARAM)"!target3" );
	SendMessage( wnd, CB_ADDSTRING, 0, (LPARAM)"!target4" );
	SendMessage( wnd, CB_ADDSTRING, 0, (LPARAM)"!target5" );
	SendMessage( wnd, CB_ADDSTRING, 0, (LPARAM)"!target6" );
	SendMessage( wnd, CB_ADDSTRING, 0, (LPARAM)"!target7" );
	SendMessage( wnd, CB_ADDSTRING, 0, (LPARAM)"!target8" );
}
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : hwndDlg - 
//			uMsg - 
//			wParam - 
//			lParam - 
// Output : static BOOL CALLBACK ChannelPropertiesDialogProc
//-----------------------------------------------------------------------------
static BOOL CALLBACK ChannelPropertiesDialogProc ( HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ) 
{
	switch(uMsg)
	{
    case WM_INITDIALOG:
		// Insert code here to put the string (to find and replace with)
		// into the edit controls.
		// ...
		{
			g_Params.PositionSelf( hwndDlg );

			SetDlgItemText( hwndDlg, IDC_CHANNELNAME, g_Params.m_szName );

			HWND control = GetDlgItem( hwndDlg, IDC_ACTORCHOICE );

			if ( !g_Params.m_bShowActors )
			{
				// Hide the combo box
				if ( control )
				{
					ShowWindow( control, SW_HIDE );
				}
				control = GetDlgItem( hwndDlg, IDC_STATIC_ACTOR );
				if ( control )
				{
					ShowWindow( control, SW_HIDE );
				}
			}
			else
			{
				SendMessage( control, CB_RESETCONTENT, 0, 0 ); 

				if ( g_Params.m_pScene )
				{
					for ( int i = 0 ; i < g_Params.m_pScene->GetNumActors() ; i++ )
					{
						CChoreoActor *actor = g_Params.m_pScene->GetActor( i );
						if ( actor )
						{
							// add text to combo box
							SendMessage( control, CB_ADDSTRING, 0, (LPARAM)actor->GetName() ); 
						}
					}
				}
				
				SendMessage( control, CB_SETCURSEL, (WPARAM)0, (LPARAM)0 );
			}

			SetWindowText( hwndDlg, g_Params.m_szDialogTitle );

			SetFocus( GetDlgItem( hwndDlg, IDC_CHANNELNAME ) );
		}
		return FALSE;  
		
    case WM_COMMAND:
		switch (LOWORD(wParam))
		{
		case IDOK:
			g_Params.m_szName[ 0 ] = 0;
			GetDlgItemText( hwndDlg, IDC_CHANNELNAME, g_Params.m_szName, 256 );

			if ( g_Params.m_bShowActors )
			{
				HWND control = GetDlgItem( hwndDlg, IDC_ACTORCHOICE );
				if ( control )
				{
					SendMessage( control, WM_GETTEXT, (WPARAM)sizeof( g_Params.m_szSelectedActor ), (LPARAM)g_Params.m_szSelectedActor );
				}
			}

			EndDialog( hwndDlg, 1 );
			break;
        case IDCANCEL:
			EndDialog( hwndDlg, 0 );
			break;
		}
		return TRUE;
	}
	return FALSE;
}