//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // // $NoKeywords: $ //=============================================================================// #include "cbase.h" #include #include #include "hlfaceposer.h" #include "choreochannelwidget.h" #include "choreoeventwidget.h" #include "choreoactorwidget.h" #include "choreochannel.h" #include "choreowidgetdrawhelper.h" #include "choreoview.h" #include "choreoevent.h" #include "choreoviewcolors.h" #include "utlrbtree.h" #include "utllinkedlist.h" #include "iclosecaptionmanager.h" #include "PhonemeEditor.h" #include "SoundEmitterSystem/isoundemittersystembase.h" #include "filesystem.h" #define AUDIO_HEIGHT 18 #define STREAM_FONT "Tahoma" //----------------------------------------------------------------------------- // Purpose: // Input : *parent - //----------------------------------------------------------------------------- CChoreoChannelWidget::CChoreoChannelWidget( CChoreoActorWidget *parent ) : CChoreoWidget( parent ) { m_pChannel = NULL; m_pParent = parent; m_bHasAudio = false; m_nBaseHeight = 0; m_nSelectorEventIndex = -1; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- CChoreoChannelWidget::~CChoreoChannelWidget( void ) { for ( int i = 0 ; i < m_Events.Size(); i++ ) { CChoreoEventWidget *e = m_Events[ i ]; delete e; } m_Events.RemoveAll(); } //----------------------------------------------------------------------------- // Purpose: Create child windows //----------------------------------------------------------------------------- void CChoreoChannelWidget::Create( void ) { Assert( m_pChannel ); // Create objects for children for ( int i = 0; i < m_pChannel->GetNumEvents(); i++ ) { CChoreoEvent *e = m_pChannel->GetEvent( i ); Assert( e ); if ( !e ) { continue; } CChoreoEventWidget *eventWidget = new CChoreoEventWidget( this ); eventWidget->SetEvent( e ); eventWidget->Create(); AddEvent( eventWidget ); } } //----------------------------------------------------------------------------- // Purpose: // Input : mx - // Output : float //----------------------------------------------------------------------------- float CChoreoChannelWidget::GetTimeForMousePosition( int mx ) { int dx = mx - m_pView->GetLabelWidth(); float windowfrac = ( float ) dx / ( float ) ( w() - m_pView->GetLabelWidth() ); float time = m_pView->GetStartTime() + windowfrac * ( m_pView->GetEndTime() - m_pView->GetStartTime() ); return time; } static bool EventStartTimeLessFunc( CChoreoEventWidget * const &p1, CChoreoEventWidget * const &p2 ) { CChoreoEventWidget *w1; CChoreoEventWidget *w2; w1 = const_cast< CChoreoEventWidget * >( p1 ); w2 = const_cast< CChoreoEventWidget * >( p2 ); CChoreoEvent *e1; CChoreoEvent *e2; e1 = w1->GetEvent(); e2 = w2->GetEvent(); return e1->GetStartTime() < e2->GetStartTime(); } void CChoreoChannelWidget::LayoutEventInRow( CChoreoEventWidget *event, int row, RECT& rc ) { int itemHeight = BaseClass::GetItemHeight(); RECT rcEvent; rcEvent.left = m_pView->GetPixelForTimeValue( event->GetEvent()->GetStartTime() ); if ( event->GetEvent()->HasEndTime() ) { rcEvent.right = m_pView->GetPixelForTimeValue( event->GetEvent()->GetEndTime() ); } else { rcEvent.right = rcEvent.left + 8; } rcEvent.top = rc.top + ( row ) * itemHeight + 2; rcEvent.bottom = rc.top + ( row + 1 ) * itemHeight - 2; event->Layout( rcEvent ); } static bool EventCollidesWithRows( CUtlLinkedList< CChoreoEventWidget *, int >& list, CChoreoEventWidget *event ) { float st = event->GetEvent()->GetStartTime(); float ed = event->GetEvent()->HasEndTime() ? event->GetEvent()->GetEndTime() : event->GetEvent()->GetStartTime(); for ( int i = list.Head(); i != list.InvalidIndex(); i = list.Next( i ) ) { CChoreoEvent *test = list[ i ]->GetEvent(); float teststart = test->GetStartTime(); float testend = test->HasEndTime() ? test->GetEndTime() : test->GetStartTime(); // See if spans overlap if ( teststart >= ed ) continue; if ( testend <= st ) continue; return true; } return false; } int CChoreoChannelWidget::GetVerticalStackingCount( bool layout, RECT *rc ) { CUtlRBTree< CChoreoEventWidget * > sorted( 0, 0, EventStartTimeLessFunc ); CUtlVector< CUtlLinkedList< CChoreoEventWidget *, int > > rows; int i; // Sort items int c = m_Events.Size(); for ( i = 0; i < c; i++ ) { sorted.Insert( m_Events[ i ] ); } for ( i = sorted.FirstInorder(); i != sorted.InvalidIndex(); i = sorted.NextInorder( i ) ) { CChoreoEventWidget *event = sorted[ i ]; Assert( event ); if ( !rows.Count() ) { rows.AddToTail(); CUtlLinkedList< CChoreoEventWidget *, int >& list = rows[ 0 ]; list.AddToHead( event ); if ( layout ) { LayoutEventInRow( event, 0, *rc ); } 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< CChoreoEventWidget *, int >& list = rows[ j ]; if ( !EventCollidesWithRows( list, event ) ) { // Update row event list list.AddToHead( event ); addrow = false; if ( layout ) { LayoutEventInRow( event, j, *rc ); } break; } } if ( addrow ) { // Add a new row int idx = rows.AddToTail(); CUtlLinkedList< CChoreoEventWidget *, int >& list = rows[ idx ]; list.AddToHead( event ); if ( layout ) { LayoutEventInRow( event, rows.Count() - 1, *rc ); } } } return max( 1, rows.Count() ); } int CChoreoChannelWidget::GetItemHeight( void ) { int itemHeight = BaseClass::GetItemHeight(); int stackCount = GetVerticalStackingCount( false, NULL ); CheckHasAudio(); int h = stackCount * itemHeight; // Remember the base height m_nBaseHeight = h; if ( m_bHasAudio && m_pView->GetShowCloseCaptionData() ) { h += 2 * AUDIO_HEIGHT; } return h; } bool CChoreoChannelWidget::CheckHasAudio() { m_bHasAudio = false; // Create objects for children for ( int i = 0; i < m_Events.Size(); i++ ) { CChoreoEventWidget *event = m_Events[ i ]; if ( event->GetEvent()->GetType() == CChoreoEvent::SPEAK ) { m_bHasAudio = true; break; } } return m_bHasAudio; } //----------------------------------------------------------------------------- // Purpose: // Input : rc - //----------------------------------------------------------------------------- void CChoreoChannelWidget::Layout( RECT& rc ) { setBounds( rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top ); GetVerticalStackingCount( true, &rc ); CheckHasAudio(); /* // Create objects for children for ( int i = 0; i < m_Events.Size(); i++ ) { CChoreoEventWidget *event = m_Events[ i ]; Assert( event ); if ( !event ) { continue; } RECT rcEvent; rcEvent.left = m_pView->GetPixelForTimeValue( event->GetEvent()->GetStartTime() ); if ( event->GetEvent()->HasEndTime() ) { rcEvent.right = m_pView->GetPixelForTimeValue( event->GetEvent()->GetEndTime() ); } else { rcEvent.right = rcEvent.left + 8; } rcEvent.top = rc.top + 2; rcEvent.bottom = rc.bottom - 2; event->Layout( rcEvent ); } */ } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CChoreoChannelWidget::redraw( CChoreoWidgetDrawHelper& drawHelper ) { if ( !getVisible() ) return; CChoreoChannel *channel = GetChannel(); if ( !channel ) return; RECT rcText; rcText = getBounds(); rcText.right = m_pView->GetLabelWidth(); if ( !channel->GetActive() ) { RECT rcBg = rcText; InflateRect( &rcBg, -5, -5 ); drawHelper.DrawFilledRect( RGB( 210, 210, 210 ), rcBg ); } RECT rcName = rcText; rcName.left += 20; char n[ 512 ]; V_strcpy_safe( n, channel->GetName() ); drawHelper.DrawColoredText( "Arial", m_pView->GetFontSize() + 2, FW_HEAVY, channel->GetActive() ? COLOR_CHOREO_CHANNELNAME : COLOR_CHOREO_ACTORNAME_INACTIVE, rcName, n ); if ( !channel->GetActive() ) { strcpy( n, "(inactive)" ); RECT rcInactive = rcName; int len = drawHelper.CalcTextWidth( "Arial", m_pView->GetFontSize(), 500, n ); rcInactive.left = rcInactive.right - len; //rcInactive.top += 3; //rcInactive.bottom = rcInactive.top + m_pView->GetFontSize() - 2; drawHelper.DrawColoredText( "Arial", m_pView->GetFontSize() - 2, 500, COLOR_CHOREO_ACTORNAME_INACTIVE, rcInactive, n ); } rcName.left -= 20; RECT rcEventArea = getBounds(); rcEventArea.left = m_pView->GetLabelWidth() + 1; rcEventArea.top -= 20; drawHelper.StartClipping( rcEventArea ); if ( m_bHasAudio ) { RenderCloseCaptionExpandCollapseRect( drawHelper, rcEventArea ); if ( m_pView->GetShowCloseCaptionData() ) { RenderCloseCaptionExpandCollapseRect( drawHelper, rcEventArea ); RenderCloseCaptionInfo( drawHelper, rcEventArea ); RenderCloseCaptions( drawHelper, rcEventArea ); RenderCloseCaptionSelectors( drawHelper, rcEventArea ); } } for ( int j = GetNumEvents()-1; j >= 0; j-- ) { CChoreoEventWidget *event = GetEvent( j ); if ( event ) { event->redraw( drawHelper ); } } drawHelper.StopClipping(); } //----------------------------------------------------------------------------- // Purpose: // Input : drawHelper - // rcEventArea - //----------------------------------------------------------------------------- void CChoreoChannelWidget::RenderCloseCaptionInfo( CChoreoWidgetDrawHelper& drawHelper, RECT& rcEventArea ) { wchar_t wstr[ 1024 ]; COLORREF barColor = RGB( 100, 200, 255 ); { RECT rcText = rcEventArea; rcText.left += 2; rcText.top = rcEventArea.bottom - 15; rcText.bottom = rcText.top + 12; drawHelper.DrawColoredText( "Arial", m_pView->GetFontSize() - 2, 500, COLOR_CHOREO_TEXT, rcText, "token/data:" ); } // Walk the events looking for SPEAK events (esp if marked as MASTER with >= 1 slave) for ( int j = GetNumEvents()-1; j >= 0; j-- ) { CChoreoEventWidget *event = GetEvent( j ); CChoreoEvent *e = event->GetEvent(); if ( e->GetType() != CChoreoEvent::SPEAK ) continue; if ( e->GetCloseCaptionType() == CChoreoEvent::CC_SLAVE ) continue; char const *label = ""; bool showState = false; bool stateValid = false; if ( e->GetCloseCaptionType() == CChoreoEvent::CC_MASTER ) { showState = true; if ( e->GetNumSlaves() >= 1 ) { barColor = RGB( 100, 200, 255 ); label = e->GetCloseCaptionToken(); } else { barColor = RGB( 100, 150, 100 ); label = e->GetParameters(); } char cctoken[ CChoreoEvent::MAX_CCTOKEN_STRING ]; if ( e->GetPlaybackCloseCaptionToken( cctoken, sizeof( cctoken ) ) ) { stateValid = closecaptionmanager->LookupUnicodeText( GetCloseCaptionLanguageId(), cctoken, wstr, sizeof( wstr ) / sizeof( wchar_t ) ); } } else { barColor = RGB( 150, 150, 150 ); label = "-disabled-"; } // Found one!!! RECT rcEvent = event->getBounds(); float bestEndTime = max( e->GetEndTime(), e->GetLastSlaveEndTime() ); int pixeloffset = (int)( ( bestEndTime - e->GetStartTime() ) * m_pView->GetPixelsPerSecond() + 0.5f ); rcEvent.right = rcEvent.left + pixeloffset; rcEvent.top = rcEventArea.bottom - 3; rcEvent.bottom = rcEventArea.bottom; drawHelper.DrawFilledRect( barColor, rcEvent ); RECT rcTriangle; rcTriangle = rcEvent; rcTriangle.right = rcTriangle.left + 3; rcTriangle.left -= 3; OffsetRect( &rcTriangle, 0, -6 ); rcTriangle.bottom += 6; drawHelper.DrawTriangleMarker( rcTriangle, barColor, true ); rcTriangle.left = rcEvent.right - 3; rcTriangle.right = rcEvent.right + 3; drawHelper.DrawTriangleMarker( rcTriangle, barColor, true ); RECT rcText = rcEvent; rcText.bottom = rcText.top + 12; OffsetRect( &rcText, 5, -12 ); if ( showState ) { int stateMarkWidth = 12; RECT rcState = rcText; rcState.right = rcState.left + stateMarkWidth; rcText.left += stateMarkWidth; COLORREF symColor = stateValid ? RGB( 40, 100, 40 ) : RGB( 200, 40, 40 ); drawHelper.DrawColoredTextCharset( "Marlett", m_pView->GetFontSize() - 2, 500, SYMBOL_CHARSET, symColor, rcState, stateValid ? "a" : "r" ); } if ( e->IsSuppressingCaptionAttenuation() ) { drawHelper.DrawColoredText( "Arial", m_pView->GetFontSize() - 2, 500, RGB( 80, 80, 100 ), rcText, "%s [no attenuate]", label ); } else { drawHelper.DrawColoredText( "Arial", m_pView->GetFontSize() - 2, 500, RGB( 80, 80, 100 ), rcText, label ); } } } //----------------------------------------------------------------------------- // Purpose: // Input : drawHelper - // rcEventArea - //----------------------------------------------------------------------------- void CChoreoChannelWidget::RenderCloseCaptions( CChoreoWidgetDrawHelper& drawHelper, RECT& rcEventArea ) { { RECT rcText = rcEventArea; rcText.top = rcEventArea.top + m_nBaseHeight + AUDIO_HEIGHT + 5; rcText.bottom = rcText.top + 12; rcText.left += 12; drawHelper.DrawColoredText( "Arial", m_pView->GetFontSize() - 2, 500, COLOR_CHOREO_TEXT, rcText, "%s", CSentence::NameForLanguage( GetCloseCaptionLanguageId() ) ); // Previous GetCloseCaptionLanguageRect( rcText, true ); drawHelper.DrawColoredTextCharset( "Marlett", m_pView->GetFontSize(), 500, SYMBOL_CHARSET, COLOR_CHOREO_TEXT, rcText, "3" ); // Next GetCloseCaptionLanguageRect( rcText, false ); drawHelper.DrawColoredTextCharset( "Marlett", m_pView->GetFontSize(), 500, SYMBOL_CHARSET, COLOR_CHOREO_TEXT, rcText, "4" ); } // Walk the events looking for SPEAK events (esp if marked as MASTER with >= 1 slave) for ( int j = GetNumEvents()-1; j >= 0; j-- ) { CChoreoEventWidget *event = GetEvent( j ); CChoreoEvent *e = event->GetEvent(); if ( e->GetType() != CChoreoEvent::SPEAK ) continue; if ( e->GetCloseCaptionType() == CChoreoEvent::CC_SLAVE || e->GetCloseCaptionType() == CChoreoEvent::CC_DISABLED ) continue; char cctoken[ CChoreoEvent::MAX_CCTOKEN_STRING ]; bool valid = e->GetPlaybackCloseCaptionToken( cctoken, sizeof( cctoken ) ); if ( !valid ) continue; wchar_t wstr[ 1024 ]; valid = closecaptionmanager->LookupStrippedUnicodeText( GetCloseCaptionLanguageId(), cctoken, wstr, sizeof( wstr ) / sizeof( wchar_t ) ); // Found one!!! RECT rcEvent = event->getBounds(); float bestEndTime = max( e->GetEndTime(), e->GetLastSlaveEndTime() ); int pixeloffset = (int)( ( bestEndTime - e->GetStartTime() ) * m_pView->GetPixelsPerSecond() + 0.5f ); rcEvent.right = rcEvent.left + pixeloffset; rcEvent.top = rcEventArea.top + m_nBaseHeight + AUDIO_HEIGHT + 5; rcEvent.bottom = rcEvent.top + 12; rcEvent.left += 5; COLORREF textColor = valid ? RGB( 80, 80, 100 ) : RGB( 225, 40, 40 ); drawHelper.DrawColoredTextW( STREAM_FONT, m_pView->GetFontSize() - 2, 500, textColor, rcEvent, wstr ); } } //----------------------------------------------------------------------------- // Purpose: // Output : CChoreoChannel //----------------------------------------------------------------------------- CChoreoChannel *CChoreoChannelWidget::GetChannel( void ) { return m_pChannel; } //----------------------------------------------------------------------------- // Purpose: // Input : *channel - //----------------------------------------------------------------------------- void CChoreoChannelWidget::SetChannel( CChoreoChannel *channel ) { m_pChannel = channel; } //----------------------------------------------------------------------------- // Purpose: // Input : *event - //----------------------------------------------------------------------------- void CChoreoChannelWidget::AddEvent( CChoreoEventWidget *event ) { m_Events.AddToTail( event ); } //----------------------------------------------------------------------------- // Purpose: // Input : *event - //----------------------------------------------------------------------------- void CChoreoChannelWidget::RemoveEvent( CChoreoEventWidget *event ) { m_Events.FindAndRemove( event ); } //----------------------------------------------------------------------------- // Purpose: // Input : num - // Output : CChoreoEventWidget //----------------------------------------------------------------------------- CChoreoEventWidget *CChoreoChannelWidget::GetEvent( int num ) { return m_Events[ num ]; } //----------------------------------------------------------------------------- // Purpose: // Output : int //----------------------------------------------------------------------------- int CChoreoChannelWidget::GetNumEvents( void ) { return m_Events.Size(); } //----------------------------------------------------------------------------- // Purpose: // Input : *event - //----------------------------------------------------------------------------- void CChoreoChannelWidget::MoveEventToTail( CChoreoEventWidget *event ) { for ( int i = 0; i < GetNumEvents(); i++ ) { CChoreoEventWidget *ew = GetEvent( i ); if ( ew == event ) { m_Events.Remove( i ); m_Events.AddToTail( ew ); break; } } } int CChoreoChannelWidget::GetChannelItemUnderMouse( int mx, int my ) { m_nSelectorEventIndex = -1; if ( !m_bHasAudio ) return CLOSECAPTION_NONE; RECT rcCCArea; GetCloseCaptionExpandCollapseRect( rcCCArea ); POINT pt; pt.x = mx; pt.y = my; if ( PtInRect( &rcCCArea, pt ) ) { return CLOSECAPTION_EXPANDCOLLAPSE; } // previous GetCloseCaptionLanguageRect( rcCCArea, true ); if ( PtInRect( &rcCCArea, pt ) ) { return CLOSECAPTION_PREVLANGUAGE; } // next language GetCloseCaptionLanguageRect( rcCCArea, false ); if ( PtInRect( &rcCCArea, pt ) ) { return CLOSECAPTION_NEXTLANGUAGE; } CUtlVector< CloseCaptionInfo > vecSelectors; GetCloseCaptions( vecSelectors ); int c = vecSelectors.Count(); if ( vecSelectors.Count() > 0 ) { int i; for ( i = 0; i < c; ++i ) { CloseCaptionInfo& check = vecSelectors[ i ]; if ( check.isSelector && PtInRect( &check.rcSelector, pt ) ) { m_nSelectorEventIndex = check.eventindex; return CLOSECAPTION_SELECTOR; } } for ( i = 0; i < c; ++i ) { CloseCaptionInfo& check = vecSelectors[ i ]; if ( PtInRect( &check.rcCaption, pt ) ) { m_nSelectorEventIndex = check.eventindex; return CLOSECAPTION_CAPTION; } } } return CLOSECAPTION_NONE; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CChoreoChannelWidget::HandleSelectorClicked() { if ( m_nSelectorEventIndex < 0 ) return; if ( m_nSelectorEventIndex >= m_Events.Count() ) return; CChoreoEvent *event = GetEvent( m_nSelectorEventIndex )->GetEvent(); SetUsingCombinedFieldByTokenName( event->GetCloseCaptionToken(), !event->IsUsingCombinedFile() ); } void CChoreoChannelWidget::SetUsingCombinedFieldByTokenName( char const *token, bool usingcombinedfile ) { int c = GetNumEvents(); for ( int i = 0; i < c; ++i ) { CChoreoEvent *e = GetEvent( i )->GetEvent(); if ( !Q_stricmp( e->GetCloseCaptionToken(), token ) ) { e->SetUsingCombinedFile( usingcombinedfile ); } } } //----------------------------------------------------------------------------- // Purpose: // Output : CChoreoEvent //----------------------------------------------------------------------------- CChoreoEvent *CChoreoChannelWidget::GetCaptionClickedEvent() { if ( m_nSelectorEventIndex < 0 ) return NULL; if ( m_nSelectorEventIndex >= m_Events.Count() ) return NULL; CChoreoEvent *event = GetEvent( m_nSelectorEventIndex )->GetEvent(); return event; } void CChoreoChannelWidget::GetCloseCaptionExpandCollapseRect( RECT& rc ) { Assert( m_bHasAudio ); rc = getBounds(); rc.left = m_pView->GetLabelWidth() + 2; rc.right = rc.left + 12; rc.top += 2; rc.bottom = rc.top + 12; } void CChoreoChannelWidget::GetCloseCaptionLanguageRect( RECT& rc, bool previous ) { Assert( m_bHasAudio ); RECT rcEventArea = getBounds(); rcEventArea.left = m_pView->GetLabelWidth() + 1; rcEventArea.top -= 20; rc = rcEventArea; rc.top = rcEventArea.top + m_nBaseHeight + AUDIO_HEIGHT + 5; rc.bottom = rc.top + 12; rc.left += 2; rc.right = rc.left + 12; if ( !previous ) { int textlen = CChoreoWidgetDrawHelper::CalcTextWidth ( "Arial", m_pView->GetFontSize()-2, 500, CSentence::NameForLanguage( GetCloseCaptionLanguageId() ) ); OffsetRect( &rc, textlen + 10, 0 ); } } void CChoreoChannelWidget::RenderCloseCaptionSelectors( CChoreoWidgetDrawHelper& drawHelper, RECT& rcEventArea ) { CUtlVector< CloseCaptionInfo > vecSelectors; GetCloseCaptions( vecSelectors ); int c = vecSelectors.Count(); if ( vecSelectors.Count() > 0 ) { for ( int i = 0; i < c; ++i ) { CloseCaptionInfo& check = vecSelectors[ i ]; if ( !check.isSelector ) continue; CChoreoEventWidget *e = GetEvent( check.eventindex ); if ( !e ) continue; CChoreoEvent *event = e->GetEvent(); bool upArrow = !event->IsUsingCombinedFile(); COLORREF clr = RGB( 63, 63, 63 ); // upArrow ? RGB( 255, 0, 0 ) : RGB( 0, 0, 255 ); RECT rc = check.rcSelector; POINT endpt; endpt.x = rc.right - 2; if ( upArrow ) { endpt.y = rc.top - 9; } else { endpt.y = rc.bottom + 9; } POINT startpt; startpt.x = ( rc.left + rc.right ) * 0.5; startpt.y = ( rc.top + rc.bottom ) * 0.5; drawHelper.DrawCircle( clr, endpt.x, endpt.y, 3 , true ); drawHelper.DrawColoredLine( clr, PS_SOLID, 1, startpt.x, startpt.y, endpt.x, endpt.y ); drawHelper.DrawCircle( clr, startpt.x, startpt.y, 7, true ); } } } void CChoreoChannelWidget::GetCloseCaptions( CUtlVector< CloseCaptionInfo >& selectors ) { selectors.RemoveAll(); // Walk the events looking for SPEAK events (esp if marked as MASTER with >= 1 slave) for ( int j = GetNumEvents()-1; j >= 0; j-- ) { CChoreoEventWidget *event = GetEvent( j ); CChoreoEvent *e = event->GetEvent(); if ( e->GetType() != CChoreoEvent::SPEAK ) continue; CChoreoEvent::CLOSECAPTION capType = e->GetCloseCaptionType(); if ( capType == CChoreoEvent::CC_SLAVE ) continue; bool isSelector = ( e->GetNumSlaves() >= 1 ) && capType == CChoreoEvent::CC_MASTER; // Found one!!! RECT rcEvent = event->getBounds(); RECT rcCaption = rcEvent; rcEvent.right = rcEvent.left + 16; OffsetRect( &rcEvent, -16, rcEvent.bottom - rcEvent.top ); rcEvent.bottom = rcEvent.top + 16; CloseCaptionInfo ccs; ccs.rcSelector = rcEvent; ccs.isSelector = isSelector; rcCaption.top += rcEvent.bottom - rcEvent.top; RECT rcEventArea = getBounds(); rcCaption.bottom = rcEventArea.bottom; // Now compute true right edge float bestEndTime = max( e->GetEndTime(), e->GetLastSlaveEndTime() ); int pixeloffset = (int)( ( bestEndTime - e->GetStartTime() ) * m_pView->GetPixelsPerSecond() + 0.5f ); rcCaption.right = rcCaption.left + pixeloffset; ccs.rcCaption = rcCaption; ccs.eventindex = j; selectors.AddToTail( ccs ); } } void CChoreoChannelWidget::RenderCloseCaptionExpandCollapseRect( CChoreoWidgetDrawHelper& drawHelper, RECT& rcEventArea ) { if ( !m_bHasAudio ) return; RECT rcCCArea; GetCloseCaptionExpandCollapseRect( rcCCArea ); COLORREF symColor = RGB( 100, 100, 100 ); drawHelper.DrawColoredTextCharset( "Marlett", m_pView->GetFontSize(), 900, SYMBOL_CHARSET, symColor, rcCCArea, m_pView->GetShowCloseCaptionData() ? "6" : "4" ); } void CChoreoChannelWidget::GetMasterAndSlaves( CChoreoEvent *master, CUtlVector< CChoreoEvent * >& fulllist ) { // Old int c = GetNumEvents(); int i; for ( i = 0; i < c; ++i ) { CChoreoEvent *e = GetEvent( i )->GetEvent(); if ( !Q_stricmp( master->GetCloseCaptionToken(), e->GetCloseCaptionToken() ) ) { if ( fulllist.Find( e ) == fulllist.InvalidIndex() ) { fulllist.AddToTail( e ); } } } } //----------------------------------------------------------------------------- // Purpose: // Input : drawHelper - // rcBounds - //----------------------------------------------------------------------------- void CChoreoChannelWidget::redrawStatus( CChoreoWidgetDrawHelper& drawHelper, RECT& rcClient, int areaUnderMouse ) { if ( !getVisible() ) return; if ( areaUnderMouse != CLOSECAPTION_CAPTION ) return; CChoreoEvent *e = GetCaptionClickedEvent(); if ( !e ) return; int deflateborder = 1; int fontsize = 9; // Now draw the label RECT rcEventLabel; rcEventLabel = rcClient; InflateRect( &rcEventLabel, 0, -deflateborder ); // rcEventLabel.top += 2; rcEventLabel.left += 2; //rcEventLabel.top = rcEventLabel.bottom - 2 * ( fontsize + 2 ) - 1; //rcEventLabel.bottom = rcEventLabel.top + fontsize + 2; /* HDC dc = drawHelper.GrabDC(); int leftAdd = 16; if ( CChoreoEventWidget::GetImage( event->GetType() ) ) { mxbitmapdata_t *image = CChoreoEventWidget::GetImage( event->GetType() ); if ( image ) { RECT rcFixed = rcEventLabel; drawHelper.OffsetSubRect( rcFixed ); DrawBitmapToDC( dc, rcFixed.left, rcFixed.top, leftAdd, leftAdd, *image ); } } // Draw Type Name: //rcEventLabel.top -= 4; rcEventLabel.left = rcClient.left + 32; rcEventLabel.bottom = rcEventLabel.top + fontsize + 2; // OffsetRect( &rcEventLabel, 0, 2 ); int len = drawHelper.CalcTextWidth( "Arial", fontsize, FW_NORMAL, "%s event \"%s\"", event->NameForType( event->GetType() ), event->GetName() ); drawHelper.DrawColoredText( "Arial", fontsize, FW_NORMAL, COLOR_INFO_TEXT, rcEventLabel, "%s event \"%s\"", event->NameForType( event->GetType() ), event->GetName() ); OffsetRect( &rcEventLabel, 0, fontsize + 2 ); drawHelper.DrawColoredText( "Arial", fontsize, FW_NORMAL, COLOR_INFO_TEXT, rcEventLabel, "parameters \"%s\"", GetLabelText() ); */ char const *label = ""; bool showState = false; bool stateValid = false; wchar_t wstr[ 1024 ]; COLORREF labelColor = COLOR_INFO_TEXT; if ( e->GetCloseCaptionType() == CChoreoEvent::CC_MASTER ) { showState = true; if ( e->GetNumSlaves() >= 1 ) { label = e->GetCloseCaptionToken(); } else { label = e->GetParameters(); } } else if ( e->GetCloseCaptionType() == CChoreoEvent::CC_SLAVE ) { showState = true; label = e->GetCloseCaptionToken(); } else { label = "-disabled-"; } char cctoken[ CChoreoEvent::MAX_CCTOKEN_STRING ]; if ( showState && e->GetPlaybackCloseCaptionToken( cctoken, sizeof( cctoken ) ) ) { stateValid = closecaptionmanager->LookupUnicodeText( GetCloseCaptionLanguageId(), cctoken, wstr, sizeof( wstr ) / sizeof( wchar_t ) ); } RECT rcText = rcEventLabel; rcText.left += 250; rcText.bottom = rcText.top + fontsize + 1; if ( showState ) { int stateMarkWidth = 12; RECT rcState = rcText; rcState.right = rcState.left + stateMarkWidth; rcText.left += stateMarkWidth; COLORREF symColor = stateValid ? RGB( 40, 100, 40 ) : RGB( 200, 40, 40 ); drawHelper.DrawColoredTextCharset( "Marlett", fontsize+2, 500, SYMBOL_CHARSET, symColor, rcState, stateValid ? "a" : "r" ); } drawHelper.DrawColoredText( "Arial", fontsize, 500, labelColor, rcText, "closecaption token: %s", label ); RECT saveText = rcText; COLORREF statusClr = RGB( 20, 150, 20 ); if ( e->GetCloseCaptionType() != CChoreoEvent::CC_DISABLED ) { if ( e->GetNumSlaves() >= 1 || e->GetCloseCaptionType() == CChoreoEvent::CC_SLAVE ) { bool combinedValid = m_pView->ValidateCombinedSoundCheckSum( e ); OffsetRect( &rcText, 0, fontsize + 3 ); char cf[ 256 ]; Q_strncpy( cf, "(no file)", sizeof( cf ) ); // Get the filename, including expansion for gender e->ComputeCombinedBaseFileName( cf, sizeof( cf ), e->IsCombinedUsingGenderToken() ); bool gendermacro = Q_stristr( cf, SOUNDGENDER_MACRO ) ? true : false; char exist[ 256 ]; if ( gendermacro ) { bool valid[2]; char actualfile[ 256 ]; soundemitter->GenderExpandString( GENDER_MALE, cf, actualfile, sizeof( actualfile ) ); valid[ 0 ] = filesystem->FileExists( actualfile ); soundemitter->GenderExpandString( GENDER_FEMALE, cf, actualfile, sizeof( actualfile ) ); valid[ 1 ] = filesystem->FileExists( actualfile ); if ( !valid[ 0 ] || !valid[ 1 ] ) { statusClr = RGB( 255, 0, 0 ); } Q_snprintf( exist, sizeof( exist ), "%s", valid ? "exist" : "missing!" ); } else { bool valid = filesystem->FileExists( cf ); if ( !valid ) { statusClr = RGB( 255, 0, 0 ); } Q_snprintf( exist, sizeof( exist ), "%s", valid ? "exists" : "missing!" ); } RECT rcPartial = rcText; char sz[ 256 ]; Q_snprintf( sz, sizeof( sz ), "combined file active [ %s ] gender[ %s ] up-to-date[ ", e->IsUsingCombinedFile() ? "yes" : "no", e->IsCombinedUsingGenderToken() ? "yes" : "no" ); int len = drawHelper.CalcTextWidth( "Arial", fontsize, 500, sz ); drawHelper.DrawColoredText( "Arial", fontsize, 500, labelColor, rcPartial, sz ); rcPartial.left += len; Q_snprintf( sz, sizeof( sz ), "%s", combinedValid ? "yes" : "no" ); len = drawHelper.CalcTextWidth( "Arial", fontsize, 500, sz ); drawHelper.DrawColoredText( "Arial", fontsize, 500, combinedValid ? RGB( 20, 150, 20 ) : RGB( 255, 0, 0 ), rcPartial, sz ); rcPartial.left += len; Q_snprintf( sz, sizeof( sz ), " ]: %s, %s ", cf, gendermacro ? "files" : "file" ); len = drawHelper.CalcTextWidth( "Arial", fontsize, 500, sz ); drawHelper.DrawColoredText( "Arial", fontsize, 500, labelColor, rcPartial, sz ); rcPartial.left += len; drawHelper.DrawColoredText( "Arial", fontsize, 500, statusClr, rcPartial, exist ); } rcText = saveText; OffsetRect( &rcText, 400, 0 ); // Print out script file for sound int soundindex = soundemitter->GetSoundIndex( cctoken ); if ( soundindex >= 0 ) { char const *scriptfile = soundemitter->GetSourceFileForSound( soundindex ); Assert( scriptfile ); if ( scriptfile ) { drawHelper.DrawColoredText( "Arial", fontsize, 500, labelColor, rcText, "sound script: %s", scriptfile ); } } else { drawHelper.DrawColoredText( "Arial", fontsize, 500, RGB( 255, 0, 0 ), rcText, "sound not in game_sounds script files!" ); } } }