315 lines
7.5 KiB
C++
315 lines
7.5 KiB
C++
// TrackViewKeyList.cpp : implementation file
|
|
//
|
|
|
|
#include "stdafx.h"
|
|
#include "TrackViewKeyList.h"
|
|
#include "Controls\MemDC.h"
|
|
|
|
#include "TrackViewDialog.h"
|
|
#include "AnimationContext.h"
|
|
|
|
//#include "IMovieSystem.h"
|
|
|
|
enum ETVMouseMode
|
|
{
|
|
MOUSE_MODE_NONE = 0,
|
|
MOUSE_MODE_SELECT = 1,
|
|
MOUSE_MODE_MOVE,
|
|
MOUSE_MODE_CLONE,
|
|
MOUSE_MODE_DRAGTIME
|
|
};
|
|
|
|
#define KEY_TEXT_COLOR RGB(255,255,255)
|
|
|
|
// CTrackViewKeyList
|
|
|
|
IMPLEMENT_DYNAMIC(CTrackViewKeyList, CTrackViewKeys)
|
|
CTrackViewKeyList::CTrackViewKeyList()
|
|
{
|
|
m_leftOffset = 30;
|
|
|
|
m_itemWidth = 1000;
|
|
m_itemHeight = 16;
|
|
}
|
|
|
|
CTrackViewKeyList::~CTrackViewKeyList()
|
|
{
|
|
}
|
|
|
|
BEGIN_MESSAGE_MAP(CTrackViewKeyList, CTrackViewKeys)
|
|
END_MESSAGE_MAP()
|
|
|
|
// CTrackViewKeyList message handlers
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeyList::DrawTrack( int item,CDC *dc,CRect &rcItem )
|
|
{
|
|
CPen pen(PS_SOLID,1,RGB(120,120,120));
|
|
CPen *prevPen = dc->SelectObject( &pen );
|
|
dc->MoveTo( rcItem.left,rcItem.bottom );
|
|
dc->LineTo( rcItem.right,rcItem.bottom );
|
|
dc->SelectObject( prevPen );
|
|
|
|
IAnimTrack *track = GetTrack(item);
|
|
if (!track)
|
|
return;
|
|
|
|
//dc->Draw3dRect( rcItem,GetSysColor(COLOR_3DHILIGHT),GetSysColor(COLOR_3DDKSHADOW) );
|
|
//int minx = m_leftOffset;
|
|
//int maxx = min( TimeToClient(
|
|
|
|
CRect rcInner = rcItem;
|
|
//rcInner.DeflateRect(m_leftOffset,0,m_leftOffset,0);
|
|
rcInner.left = max( rcItem.left,m_leftOffset - m_scrollOffset.x );
|
|
rcInner.right = min( rcItem.right,(m_scrollMax + m_scrollMin) - m_scrollOffset.x + m_leftOffset*3 );
|
|
|
|
CRect rcInnerDraw( rcInner.left-6,rcInner.top,rcInner.right+6,rcInner.bottom );
|
|
if (m_selected == item)
|
|
{
|
|
CRect rc = rcInnerDraw;
|
|
rc.DeflateRect(1,1,1,1);
|
|
dc->FillRect( rc,&m_selectedBrush );
|
|
}
|
|
dc->Draw3dRect( rcInnerDraw,GetSysColor(COLOR_3DDKSHADOW),GetSysColor(COLOR_3DHILIGHT) );
|
|
|
|
// Left outside
|
|
CRect rcOutside = rcItem;
|
|
rcOutside.right = rcInnerDraw.left-1;
|
|
rcOutside.DeflateRect(1,1,1,1);
|
|
dc->SelectObject( m_bkgrBrushEmpty );
|
|
dc->Rectangle( rcOutside );
|
|
|
|
// Right outside.
|
|
rcOutside = rcItem;
|
|
rcOutside.left = rcInnerDraw.right+1;
|
|
rcOutside.DeflateRect(1,1,1,1);
|
|
dc->Rectangle( rcOutside );
|
|
|
|
// Get time range of update rectangle.
|
|
Range timeRange = GetTimeRange(rcItem);
|
|
// Draw tick marks in time range.
|
|
DrawTicks( dc,rcInner,timeRange );
|
|
// Draw keys in time range.
|
|
DrawKeys( track,dc,rcInner,timeRange );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeyList::DrawKeys( IAnimTrack *track,CDC *dc,CRect &rc,Range &timeRange )
|
|
{
|
|
CPen selPen( PS_SOLID,1,RGB(255,255,0) );
|
|
|
|
char keydesc[1024];
|
|
int numKeys = track->GetNumKeys();
|
|
|
|
// If this track is boolean draw bars to show true value.
|
|
if (track->GetValueType() == ATRACK_BOOL)
|
|
{
|
|
int x0 = TimeToClient(timeRange.start);
|
|
float t0 = timeRange.start;
|
|
CRect itemrc;
|
|
|
|
CBrush *prevBrush = dc->SelectObject( &m_visibilityBrush );
|
|
for (int i = 0; i < numKeys; i++)
|
|
{
|
|
float time = track->GetKeyTime(i);
|
|
if (time < timeRange.start)
|
|
continue;
|
|
if (time > timeRange.end)
|
|
break;
|
|
|
|
int x = TimeToClient(time);
|
|
bool val = false;
|
|
track->GetValue( time-0.001f,val );
|
|
if (val)
|
|
{
|
|
dc->Rectangle( x0,rc.top+5,x,rc.bottom-5 );
|
|
}
|
|
|
|
t0 = time;
|
|
x0 = x;
|
|
}
|
|
int x = TimeToClient(timeRange.end);
|
|
bool val = false;
|
|
track->GetValue( timeRange.end-0.001f,val );
|
|
if (val)
|
|
{
|
|
dc->Rectangle( x0,rc.top+5,x,rc.bottom-5 );
|
|
}
|
|
dc->SelectObject( &prevBrush );
|
|
}
|
|
|
|
CFont *prevFont = dc->SelectObject( m_descriptionFont );
|
|
|
|
dc->SetTextColor(KEY_TEXT_COLOR);
|
|
dc->SetBkMode(TRANSPARENT);
|
|
|
|
int prevKeyPixel = -10000;
|
|
float time0 = FLT_MIN;
|
|
// Draw keys.
|
|
for (int i = 0; i < numKeys; i++)
|
|
{
|
|
float time = track->GetKeyTime(i);
|
|
|
|
// Get info about that key.
|
|
const char *description = NULL;
|
|
float duration = 0;
|
|
track->GetKeyInfo(i,description,duration);
|
|
|
|
if (time+duration < timeRange.start)
|
|
continue;
|
|
if (time > timeRange.end)
|
|
break;
|
|
|
|
int x = TimeToClient(time);
|
|
if (duration > 0)
|
|
{
|
|
// Draw key duration.
|
|
int x1 = TimeToClient(time+duration);
|
|
if (x1 < 0)
|
|
{
|
|
if (x > 0)
|
|
x1 = rc.right;
|
|
}
|
|
CBrush *prevBrush = dc->SelectObject( &m_visibilityBrush );
|
|
dc->Rectangle( x,rc.top+3,x1+1,rc.bottom-3 );
|
|
dc->SelectObject( &prevBrush );
|
|
dc->MoveTo(x1,rc.top);
|
|
dc->LineTo(x1,rc.bottom);
|
|
}
|
|
|
|
if (description)
|
|
{
|
|
strcpy(keydesc,"{");
|
|
strcat(keydesc,description);
|
|
strcat(keydesc,"}");
|
|
// Draw key description text.
|
|
// Find next key.
|
|
int x1 = x + 200;
|
|
if (x < 0)
|
|
x1 = rc.right;
|
|
if (i+1 < numKeys)
|
|
{
|
|
x1 = TimeToClient( track->GetKeyTime(i+1) ) - 10;
|
|
}
|
|
CRect textRect(x+5,rc.top,x1,rc.bottom );
|
|
textRect &= rc;
|
|
dc->DrawText( keydesc,strlen(keydesc),textRect,DT_LEFT|DT_END_ELLIPSIS|DT_VCENTER|DT_SINGLELINE );
|
|
}
|
|
|
|
if (x < 0)
|
|
continue;
|
|
|
|
if (abs(x-prevKeyPixel) < 2)
|
|
{
|
|
// If two keys on the same time.
|
|
m_imageList.Draw( dc,2,CPoint(x-6,rc.top+2),ILD_TRANSPARENT );
|
|
}
|
|
else
|
|
{
|
|
if (track->GetKeyFlags(i) & AKEY_SELECTED)
|
|
{
|
|
CPen *prevPen = dc->SelectObject( &selPen );
|
|
dc->MoveTo(x,m_rcClient.top);
|
|
dc->LineTo(x,m_rcClient.bottom);
|
|
dc->SelectObject(prevPen);
|
|
m_imageList.Draw( dc,1,CPoint(x-6,rc.top+2),ILD_TRANSPARENT );
|
|
}
|
|
else
|
|
{
|
|
m_imageList.Draw( dc,0,CPoint(x-6,rc.top+2),ILD_TRANSPARENT );
|
|
}
|
|
}
|
|
|
|
prevKeyPixel = x;
|
|
time0 = time;
|
|
}
|
|
dc->SelectObject( prevFont );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
int CTrackViewKeyList::KeyFromPoint( CPoint point )
|
|
{
|
|
int item = ItemFromPoint(point);
|
|
if (item < 0)
|
|
return -1;
|
|
|
|
float t1 = TimeFromPointUnsnapped( CPoint(point.x-4,point.y) );
|
|
float t2 = TimeFromPointUnsnapped( CPoint(point.x+4,point.y) );
|
|
|
|
IAnimTrack *track = GetTrack(item);
|
|
if (!track)
|
|
return -1;
|
|
|
|
int numKeys = track->GetNumKeys();
|
|
for (int i = 0; i < numKeys; i++)
|
|
{
|
|
float time = track->GetKeyTime(i);
|
|
if (time >= t1 && time <= t2)
|
|
{
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeyList::SelectKeys( const CRect &rc )
|
|
{
|
|
// put selection rectangle from client to item space.
|
|
CRect rci = rc;
|
|
rci.OffsetRect( m_scrollOffset );
|
|
|
|
Range selTime = GetTimeRange( rci );
|
|
|
|
CRect rcItem;
|
|
for (int i = 0; i < GetCount(); i++)
|
|
{
|
|
GetItemRect(i,rcItem);
|
|
// Decrease item rectangle a bit.
|
|
rcItem.DeflateRect(4,4,4,4);
|
|
// Check if item rectanle intersects with selection rectangle in y axis.
|
|
if ((rcItem.top >= rc.top && rcItem.top <= rc.bottom) ||
|
|
(rcItem.bottom >= rc.top && rcItem.bottom <= rc.bottom) ||
|
|
(rc.top >= rcItem.top && rc.top <= rcItem.bottom) ||
|
|
(rc.bottom >= rcItem.top && rc.bottom <= rcItem.bottom))
|
|
{
|
|
IAnimTrack *track = GetTrack(i);
|
|
if (!track)
|
|
continue;
|
|
|
|
// Check which keys we intersect.
|
|
for (int j = 0; j < track->GetNumKeys(); j++)
|
|
{
|
|
float time = track->GetKeyTime(j);
|
|
if (selTime.IsInside(time))
|
|
{
|
|
RecordTrackUndo( GetItem(i) );
|
|
break;
|
|
m_bAnySelected = true;
|
|
}
|
|
}
|
|
|
|
// Check which keys we intersect.
|
|
for (int j = 0; j < track->GetNumKeys(); j++)
|
|
{
|
|
float time = track->GetKeyTime(j);
|
|
if (selTime.IsInside(time))
|
|
{
|
|
track->SetKeyFlags( j,track->GetKeyFlags(j)|AKEY_SELECTED );
|
|
m_bAnySelected = true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
int CTrackViewKeyList::GetItemRect( int item,CRect &rect )
|
|
{
|
|
if (item < 0 || item >= GetCount())
|
|
return -1;
|
|
int x = 0;
|
|
int y = item*m_itemHeight - m_scrollOffset.y;
|
|
rect.SetRect( x,y,x+m_rcClient.Width(),y+m_itemHeight );
|
|
return 0;
|
|
} |