source-engine/utils/hlfaceposer/choreochannelwidget.cpp

1207 lines
30 KiB
C++
Raw Normal View History

2020-04-22 16:56:21 +00:00
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include <stdio.h>
#include <mxtk/mxPopupMenu.h>
#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!" );
}
}
}