You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1207 lines
30 KiB
1207 lines
30 KiB
//========= 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!" ); |
|
} |
|
} |
|
} |