1207 lines
30 KiB
C++
1207 lines
30 KiB
C++
//========= 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!" );
|
|
}
|
|
}
|
|
} |