1442 lines
34 KiB
C++
1442 lines
34 KiB
C++
////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Crytek Engine Source File.
|
|
// Copyright (C), Crytek Studios, 2002.
|
|
// -------------------------------------------------------------------------
|
|
// File name: TrackViewKeys.cpp
|
|
// Version: v1.00
|
|
// Created: 23/8/2002 by Timur.
|
|
// Compilers: Visual Studio.NET
|
|
// Description:
|
|
// -------------------------------------------------------------------------
|
|
// History:
|
|
//
|
|
////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#include "stdafx.h"
|
|
#include "TrackViewKeys.h"
|
|
#include "Controls\MemDC.h"
|
|
|
|
#include "TrackViewDialog.h"
|
|
#include "AnimationContext.h"
|
|
#include "TrackViewUndo.h"
|
|
|
|
//#include "IMovieSystem.h"
|
|
|
|
enum ETVMouseMode
|
|
{
|
|
MOUSE_MODE_NONE = 0,
|
|
MOUSE_MODE_SELECT = 1,
|
|
MOUSE_MODE_MOVE,
|
|
MOUSE_MODE_CLONE,
|
|
MOUSE_MODE_DRAGTIME,
|
|
MOUSE_MODE_DRAGSTARTMARKER,
|
|
MOUSE_MODE_DRAGENDMARKER
|
|
};
|
|
|
|
#define KEY_TEXT_COLOR RGB(255,255,255)
|
|
|
|
// CTrackViewKeys
|
|
|
|
IMPLEMENT_DYNAMIC(CTrackViewKeys, CWnd)
|
|
|
|
CTrackViewKeys::CTrackViewKeys()
|
|
{
|
|
m_wndTrack = NULL;
|
|
m_bkgrBrush.CreateSolidBrush( GetSysColor(COLOR_3DFACE) );
|
|
//m_bkgrBrushEmpty.CreateHatchBrush( HS_BDIAGONAL,GetSysColor(COLOR_3DFACE) );
|
|
m_bkgrBrushEmpty.CreateSolidBrush( RGB(180,180,180) );
|
|
m_timeBkgBrush.CreateSolidBrush(RGB(0xE0,0xE0,0xE0));
|
|
m_timeHighlightBrush.CreateSolidBrush(RGB(0xFF,0x0,0x0));
|
|
m_selectedBrush.CreateSolidBrush(RGB(200,200,200));
|
|
//m_visibilityBrush.CreateSolidBrush( RGB(0,150,255) );
|
|
m_visibilityBrush.CreateSolidBrush( RGB(100,100,255) );
|
|
|
|
m_timeScale = 1;
|
|
m_ticksStep = 10;
|
|
|
|
m_bZoomDrag=false;
|
|
m_bMoveDrag=false;
|
|
|
|
m_leftOffset = 0;
|
|
m_scrollOffset = CPoint(0,0);
|
|
m_bAnySelected = 0;
|
|
m_mouseMode = MOUSE_MODE_NONE;
|
|
m_currentTime = 40;
|
|
m_rcSelect = CRect(0,0,0,0);
|
|
m_keyTimeOffset = 0;
|
|
m_currCursor = NULL;
|
|
m_mouseActionMode = TVMODE_MOVEKEY;
|
|
|
|
m_itemWidth = 1000;
|
|
m_scrollMin = 0;
|
|
m_scrollMax = 1000;
|
|
m_itemHeight = 16;
|
|
|
|
m_descriptionFont = new CFont();
|
|
m_descriptionFont->CreateFont( 8,0,0,0,FW_NORMAL,FALSE,FALSE,FALSE,
|
|
DEFAULT_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,DEFAULT_PITCH,"MS Sans Serif" );
|
|
}
|
|
|
|
CTrackViewKeys::~CTrackViewKeys()
|
|
{
|
|
m_descriptionFont->DeleteObject();
|
|
delete m_descriptionFont;
|
|
}
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CTrackViewKeys, CWnd)
|
|
ON_WM_CREATE()
|
|
ON_WM_MEASUREITEM_REFLECT()
|
|
ON_WM_CTLCOLOR_REFLECT()
|
|
ON_WM_SIZE()
|
|
ON_WM_MOUSEWHEEL()
|
|
ON_WM_HSCROLL()
|
|
ON_WM_LBUTTONDOWN()
|
|
ON_WM_RBUTTONDOWN()
|
|
ON_WM_LBUTTONUP()
|
|
ON_WM_MOUSEMOVE()
|
|
ON_WM_PAINT()
|
|
ON_WM_SETCURSOR()
|
|
ON_WM_ERASEBKGND()
|
|
ON_WM_RBUTTONDOWN()
|
|
ON_WM_KEYDOWN()
|
|
ON_WM_RBUTTONUP()
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
|
|
// CTrackViewKeys message handlers
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
int CTrackViewKeys::OnCreate(LPCREATESTRUCT lpCreateStruct)
|
|
{
|
|
if (CWnd::OnCreate(lpCreateStruct) == -1)
|
|
return -1;
|
|
|
|
m_imageList.Create( MAKEINTRESOURCE(IDB_TRACKVIEW_KEYS),14,0,RGB(255,0,255) );
|
|
m_imgMarker.Create( MAKEINTRESOURCE(IDB_MARKER),8,0,RGB(255,0,255) );
|
|
m_crsLeftRight = AfxGetApp()->LoadStandardCursor(IDC_SIZEWE);
|
|
m_crsAddKey = AfxGetApp()->LoadCursor(IDC_ARROW_ADDKEY);
|
|
|
|
//InitializeFlatSB(GetSafeHwnd());
|
|
|
|
return 0;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::DrawTimeline( CDC *dc,const CRect &rcUpdate )
|
|
{
|
|
CRect rc,temprc;
|
|
|
|
bool recording = GetIEditor()->GetAnimation()->IsRecording();
|
|
|
|
COLORREF lineCol = RGB(255,0,255);
|
|
COLORREF textCol = RGB(0,0,0);
|
|
if (recording)
|
|
{
|
|
lineCol = RGB(255,0,0);
|
|
//textCol = RGB(255,255,255);
|
|
}
|
|
|
|
// Draw vertical line showing current time.
|
|
{
|
|
int x = TimeToClient(m_currentTime);
|
|
if (x > m_rcClient.left && x < m_rcClient.right)
|
|
{
|
|
CPen pen( PS_SOLID,1,lineCol );
|
|
CPen *prevPen = dc->SelectObject(&pen);
|
|
dc->MoveTo( x,0 );
|
|
dc->LineTo( x,m_rcClient.bottom );
|
|
dc->SelectObject( prevPen );
|
|
}
|
|
}
|
|
|
|
|
|
rc = m_rcTimeline;
|
|
if (temprc.IntersectRect(rc,rcUpdate) == 0)
|
|
return;
|
|
|
|
/*
|
|
if (recording)
|
|
{
|
|
dc->FillRect( rc,&m_timeHighlightBrush );
|
|
}
|
|
else
|
|
*/
|
|
{
|
|
dc->FillRect( rc,&m_timeBkgBrush );
|
|
}
|
|
dc->Draw3dRect( rc,GetSysColor(COLOR_3DHILIGHT),GetSysColor(COLOR_3DDKSHADOW) );
|
|
|
|
CPen *prevPen;
|
|
CPen ltgray(PS_SOLID,1,RGB(90,90,90));
|
|
CPen black(PS_SOLID,1,textCol);
|
|
CPen redpen(PS_SOLID,1,lineCol );
|
|
// Draw time ticks every tick step seconds.
|
|
Range timeRange = m_timeRange;
|
|
CString str;
|
|
|
|
dc->SetTextColor( textCol );
|
|
dc->SetBkMode( TRANSPARENT );
|
|
dc->SelectObject( GetStockObject(DEFAULT_GUI_FONT) );
|
|
|
|
dc->SelectObject(ltgray);
|
|
|
|
Range VisRange=GetVisibleRange();
|
|
int nNumberTicks=10;
|
|
double step = (double)1.0 / (double)m_ticksStep;
|
|
for (double t = SnapTime(timeRange.start); t <= timeRange.end+step; t += step)
|
|
{
|
|
double st = SnapTime(t);
|
|
if (st > timeRange.end)
|
|
st = timeRange.end;
|
|
if (st < VisRange.start)
|
|
continue;
|
|
if (st > VisRange.end)
|
|
break;
|
|
int x = TimeToClient(st);
|
|
if (x < 0)
|
|
continue;
|
|
dc->MoveTo(x,rc.bottom-2);
|
|
|
|
int k = st * (float)m_ticksStep;
|
|
if (k % nNumberTicks == 0)
|
|
{
|
|
dc->SelectObject(black);
|
|
dc->LineTo(x,rc.bottom-14);
|
|
char str[32];
|
|
sprintf( str,"%g",st );
|
|
dc->TextOut( x+2,rc.top,str );
|
|
dc->SelectObject(ltgray);
|
|
}
|
|
else
|
|
dc->LineTo(x,rc.bottom-6);
|
|
}
|
|
|
|
// Draw time markers.
|
|
int x;
|
|
|
|
x=TimeToClient(m_timeMarked.start);
|
|
m_imgMarker.Draw(dc, 1, CPoint(x, m_rcTimeline.bottom-9), ILD_TRANSPARENT);
|
|
x=TimeToClient(m_timeMarked.end);
|
|
m_imgMarker.Draw(dc, 0, CPoint(x-7, m_rcTimeline.bottom-9), ILD_TRANSPARENT);
|
|
|
|
prevPen = dc->SelectObject(&redpen);
|
|
x=TimeToClient(m_currentTime);
|
|
dc->SelectObject( GetStockObject(NULL_BRUSH) );
|
|
dc->Rectangle( x-3,rc.top,x+4,rc.bottom );
|
|
|
|
dc->SelectObject(redpen);
|
|
dc->MoveTo( x,rc.top ); dc->LineTo( x,rc.bottom );
|
|
dc->SelectObject( GetStockObject(NULL_BRUSH) );
|
|
// dc->Rectangle( x-3,rc.top,x+4,rc.bottom );
|
|
|
|
dc->SelectObject(prevPen);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
int CTrackViewKeys::TimeToClient( float time )
|
|
{
|
|
if (time < m_timeRange.start || time > m_timeRange.end)
|
|
return -1;
|
|
|
|
int x = m_leftOffset - m_scrollOffset.x + time*m_timeScale;
|
|
return x;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
Range CTrackViewKeys::GetVisibleRange()
|
|
{
|
|
Range r;
|
|
r.start = (m_scrollOffset.x - m_leftOffset)/m_timeScale;
|
|
r.end = r.start + (m_rcClient.Width())/m_timeScale;
|
|
// Intersect range with global time range.
|
|
r = m_timeRange & r;
|
|
return r;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
Range CTrackViewKeys::GetTimeRange( CRect &rc )
|
|
{
|
|
Range r;
|
|
r.start = (rc.left-m_leftOffset+m_scrollOffset.x)/m_timeScale;
|
|
r.end = r.start + (rc.Width())/m_timeScale;
|
|
|
|
r.start = SnapTime(r.start);
|
|
r.end = SnapTime(r.end);
|
|
// Intersect range with global time range.
|
|
r = m_timeRange & r;
|
|
return r;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::DrawTicks( CDC *dc,CRect &rc,Range &timeRange )
|
|
{
|
|
// Draw time ticks every tick step seconds.
|
|
CPen ltgray(PS_SOLID,1,RGB(90,90,90));
|
|
CPen *prevPen = dc->SelectObject( <gray );
|
|
Range VisRange=GetVisibleRange();
|
|
int nNumberTicks=10;
|
|
double step = 1.0 / (double)m_ticksStep;
|
|
for (double t = SnapTime(timeRange.start); t <= timeRange.end+step; t += step)
|
|
{
|
|
double st = SnapTime(t);
|
|
if (st > timeRange.end)
|
|
st = timeRange.end;
|
|
if (st < VisRange.start)
|
|
continue;
|
|
if (st > VisRange.end)
|
|
break;
|
|
int x = TimeToClient(st);
|
|
if (x < 0)
|
|
continue;
|
|
dc->MoveTo(x,rc.bottom-2);
|
|
|
|
int k = st * (float)m_ticksStep;
|
|
if (k % nNumberTicks == 0)
|
|
{
|
|
dc->SelectObject( GetStockObject(BLACK_PEN) );
|
|
dc->LineTo(x,rc.bottom-6);
|
|
dc->SelectObject( ltgray );
|
|
}
|
|
else
|
|
dc->LineTo(x,rc.bottom-4);
|
|
}
|
|
dc->SelectObject( prevPen );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::DrawKeys( IAnimTrack *track,CDC *dc,CRect &rc,Range &timeRange )
|
|
{
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::RedrawItem( int item )
|
|
{
|
|
CRect rc;
|
|
if (GetItemRect( item,rc ) != LB_ERR)
|
|
{
|
|
RedrawWindow( rc,NULL,RDW_INVALIDATE|RDW_ERASE );
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::MeasureItem(LPMEASUREITEMSTRUCT lpMIS)
|
|
{
|
|
lpMIS->itemWidth = 1000;
|
|
lpMIS->itemHeight = 16;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
HBRUSH CTrackViewKeys::CtlColor(CDC* pDC, UINT nCtlColor)
|
|
{
|
|
return m_bkgrBrush;
|
|
|
|
// TODO: Return a non-NULL brush if the parent's handler should not be called
|
|
return NULL;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::SetTimeRange( float start,float end )
|
|
{
|
|
/*
|
|
if (m_timeMarked.start==m_timeRange.start)
|
|
m_timeMarked.start=start;
|
|
if (m_timeMarked.end==m_timeRange.end)
|
|
m_timeMarked.end=end;
|
|
if (m_timeMarked.end>end)
|
|
m_timeMarked.end=end;
|
|
*/
|
|
if (m_timeMarked.start < start)
|
|
m_timeMarked.start = start;
|
|
if (m_timeMarked.end > end)
|
|
m_timeMarked.end = end;
|
|
|
|
m_realTimeRange.Set(start,end);
|
|
m_timeRange.Set( start-1,end+1 );
|
|
//SetHorizontalExtent( m_timeRange.Length() *m_timeScale + 2*m_leftOffset );
|
|
|
|
SetHorizontalExtent( m_timeRange.start*m_timeScale-m_leftOffset,m_timeRange.end*m_timeScale-m_leftOffset );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::SetTimeScale( float timeScale )
|
|
{
|
|
float fOldScale=m_timeScale;
|
|
if (timeScale < 0.5f)
|
|
timeScale = 0.5f;
|
|
if (timeScale > 10000.0f)
|
|
timeScale = 10000.0f;
|
|
m_timeScale = timeScale;
|
|
double fPixelsPerTick=(1.0/(double)m_ticksStep)*(double)m_timeScale;
|
|
if (fPixelsPerTick<6.0)
|
|
{
|
|
if (m_ticksStep>=10)
|
|
m_ticksStep>>=1;
|
|
}
|
|
if (fPixelsPerTick>=12.0)
|
|
{
|
|
m_ticksStep<<=1;
|
|
}
|
|
m_scrollOffset.x*=timeScale/fOldScale;
|
|
Invalidate();
|
|
|
|
//SetHorizontalExtent( m_timeRange.Length()*m_timeScale + 2*m_leftOffset );
|
|
SetHorizontalExtent( m_timeRange.start*m_timeScale-m_leftOffset,m_timeRange.end*m_timeScale-m_leftOffset );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::OnSize(UINT nType, int cx, int cy)
|
|
{
|
|
CWnd::OnSize(nType, cx, cy);
|
|
|
|
GetClientRect(m_rcClient);
|
|
|
|
if (m_offscreenBitmap.GetSafeHandle() != NULL)
|
|
m_offscreenBitmap.DeleteObject();
|
|
|
|
CDC *dc = GetDC();
|
|
m_offscreenBitmap.CreateCompatibleBitmap( dc,m_rcClient.Width(),m_rcClient.Height() );
|
|
ReleaseDC(dc);
|
|
|
|
GetClientRect(m_rcTimeline);
|
|
//m_rcTimeline.top = m_rcTimeline.bottom - m_itemHeight;
|
|
m_rcTimeline.bottom = m_rcTimeline.top + m_itemHeight;
|
|
|
|
SetHorizontalExtent( m_scrollMin,m_scrollMax );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
BOOL CTrackViewKeys::OnMouseWheel(UINT nFlags, short zDelta, CPoint pt)
|
|
{
|
|
//float z = m_timeScale + (zDelta/120.0f) * 1.0f;
|
|
float z;
|
|
if (zDelta>0)
|
|
z = m_timeScale * 1.25f;
|
|
else
|
|
z = m_timeScale * 0.8f;
|
|
SetTimeScale(z);
|
|
return 1;
|
|
//return CWnd::OnMouseWheel(nFlags, zDelta, pt);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
|
|
{
|
|
SCROLLINFO si;
|
|
GetScrollInfo( SB_HORZ,&si );
|
|
|
|
// Get the minimum and maximum scroll-bar positions.
|
|
int minpos = si.nMin;
|
|
int maxpos = si.nMax;
|
|
int nPage = si.nPage;
|
|
|
|
// Get the current position of scroll box.
|
|
int curpos = si.nPos;
|
|
|
|
// Determine the new position of scroll box.
|
|
switch (nSBCode)
|
|
{
|
|
case SB_LEFT: // Scroll to far left.
|
|
curpos = minpos;
|
|
break;
|
|
|
|
case SB_RIGHT: // Scroll to far right.
|
|
curpos = maxpos;
|
|
break;
|
|
|
|
case SB_ENDSCROLL: // End scroll.
|
|
break;
|
|
|
|
case SB_LINELEFT: // Scroll left.
|
|
if (curpos > minpos)
|
|
curpos--;
|
|
break;
|
|
|
|
case SB_LINERIGHT: // Scroll right.
|
|
if (curpos < maxpos)
|
|
curpos++;
|
|
break;
|
|
|
|
case SB_PAGELEFT: // Scroll one page left.
|
|
if (curpos > minpos)
|
|
curpos = max(minpos, curpos - (int)nPage);
|
|
break;
|
|
|
|
case SB_PAGERIGHT: // Scroll one page right.
|
|
if (curpos < maxpos)
|
|
curpos = min(maxpos, curpos + (int)nPage);
|
|
break;
|
|
|
|
case SB_THUMBPOSITION: // Scroll to absolute position. nPos is the position
|
|
curpos = nPos; // of the scroll box at the end of the drag operation.
|
|
break;
|
|
|
|
case SB_THUMBTRACK: // Drag scroll box to specified position. nPos is the
|
|
curpos = nPos; // position that the scroll box has been dragged to.
|
|
break;
|
|
}
|
|
|
|
// Set the new position of the thumb (scroll box).
|
|
SetScrollPos( SB_HORZ,curpos );
|
|
|
|
m_scrollOffset.x = curpos;
|
|
Invalidate();
|
|
|
|
CWnd::OnHScroll(nSBCode, nPos, pScrollBar);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
float CTrackViewKeys::SnapTime( float time )
|
|
{
|
|
double t = floor( (double)time*(double)m_ticksStep + 0.5f);
|
|
t = t / (double)m_ticksStep;
|
|
return t;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
float CTrackViewKeys::TimeFromPoint( CPoint point )
|
|
{
|
|
int x = point.x - m_leftOffset + m_scrollOffset.x;
|
|
double t = (double)x / m_timeScale;
|
|
return (float)SnapTime(t);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
float CTrackViewKeys::TimeFromPointUnsnapped( CPoint point )
|
|
{
|
|
int x = point.x - m_leftOffset + m_scrollOffset.x;
|
|
double t = (double)x / m_timeScale;
|
|
return t;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::AddItem( const Item &item )
|
|
{
|
|
m_tracks.push_back(item);
|
|
m_selected = -1;
|
|
Invalidate();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
const CTrackViewKeys::Item& CTrackViewKeys::GetItem( int item )
|
|
{
|
|
return m_tracks[item];
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
IAnimTrack* CTrackViewKeys::GetTrack( int item )
|
|
{
|
|
if (item < 0 || item >= GetCount())
|
|
return 0;
|
|
IAnimTrack *track = m_tracks[item].track;
|
|
return track;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
int CTrackViewKeys::KeyFromPoint( CPoint point )
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::OnLButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
CWnd::OnLButtonDown(nFlags, point);
|
|
|
|
SetFocus();
|
|
|
|
m_mouseDownPos = point;
|
|
|
|
//int item = ItemFromPoint(point);
|
|
//SetCurSel(item);
|
|
|
|
if (m_rcTimeline.PtInRect(point))
|
|
{
|
|
// Clicked inside timeline.
|
|
m_mouseMode = MOUSE_MODE_DRAGTIME;
|
|
// If mouse over selected key, change cursor to left-right arrows.
|
|
SetMouseCursor( m_crsLeftRight );
|
|
SetCapture();
|
|
|
|
SetCurrTime( TimeFromPoint(point) );
|
|
return;
|
|
}
|
|
|
|
int key = KeyFromPoint(point);
|
|
if (key >= 0)
|
|
{
|
|
int item = ItemFromPoint(point);
|
|
IAnimTrack *track = GetTrack(item);
|
|
|
|
// Store track undo.
|
|
RecordTrackUndo( GetItem(item) );
|
|
|
|
if ((track->GetKeyFlags(key) & AKEY_SELECTED) == 0 && !(nFlags&MK_CONTROL))
|
|
{
|
|
UnselectAllKeys();
|
|
}
|
|
m_bAnySelected = true;
|
|
m_keyTimeOffset = 0;
|
|
track->SetKeyFlags( key,track->GetKeyFlags(key) | AKEY_SELECTED );
|
|
if (nFlags & MK_SHIFT)
|
|
{
|
|
m_mouseMode = MOUSE_MODE_CLONE;
|
|
SetMouseCursor( m_crsLeftRight );
|
|
}
|
|
else
|
|
{
|
|
m_mouseMode = MOUSE_MODE_MOVE;
|
|
SetMouseCursor( m_crsLeftRight );
|
|
}
|
|
Invalidate();
|
|
SetKeyInfo( track,key );
|
|
return;
|
|
}
|
|
|
|
if (m_mouseActionMode == TVMODE_ADDKEY)
|
|
{
|
|
// Add key here.
|
|
int item = ItemFromPoint(point);
|
|
IAnimTrack *track = GetTrack(item);
|
|
if (track)
|
|
{
|
|
RecordTrackUndo( GetItem(item) );
|
|
track->CreateKey( TimeFromPoint(point) );
|
|
Invalidate();
|
|
UpdateAnimation();
|
|
}
|
|
return;
|
|
}
|
|
|
|
m_mouseMode = MOUSE_MODE_SELECT;
|
|
SetCapture();
|
|
if (m_bAnySelected && !(nFlags & MK_CONTROL))
|
|
{
|
|
// First unselect all buttons.
|
|
UnselectAllKeys();
|
|
Invalidate();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::OnRButtonDown(UINT nFlags, CPoint point)
|
|
{
|
|
//CWnd::OnRButtonDown(nFlags, point);
|
|
|
|
SetFocus();
|
|
|
|
if (m_rcTimeline.PtInRect(point))
|
|
{
|
|
// Clicked inside timeline.
|
|
// adjust markers.
|
|
int nMarkerStart=TimeToClient(m_timeMarked.start);
|
|
int nMarkerEnd=TimeToClient(m_timeMarked.end);
|
|
if ((abs(point.x-nMarkerStart))<(abs(point.x-nMarkerEnd)))
|
|
{
|
|
SetStartMarker(TimeFromPoint(point));
|
|
m_mouseMode = MOUSE_MODE_DRAGSTARTMARKER;
|
|
}else
|
|
{
|
|
SetEndMarker(TimeFromPoint(point));
|
|
m_mouseMode = MOUSE_MODE_DRAGENDMARKER;
|
|
}
|
|
SetCapture();
|
|
return;
|
|
}
|
|
|
|
//int item = ItemFromPoint(point);
|
|
//SetCurSel(item);
|
|
|
|
m_mouseDownPos = point;
|
|
|
|
if (nFlags & MK_SHIFT) // alternative zoom
|
|
{
|
|
m_bZoomDrag=true;
|
|
SetCapture();
|
|
return;
|
|
}
|
|
|
|
int key = KeyFromPoint(point);
|
|
if (key >= 0)
|
|
{
|
|
|
|
int item = ItemFromPoint(point);
|
|
IAnimTrack *track = GetTrack(item);
|
|
UnselectAllKeys();
|
|
track->SetKeyFlags( key,track->GetKeyFlags(key) | AKEY_SELECTED );
|
|
m_bAnySelected = true;
|
|
m_keyTimeOffset = 0;
|
|
Invalidate();
|
|
|
|
SetKeyInfo( track,key,true );
|
|
}else
|
|
{
|
|
m_bMoveDrag=true;
|
|
SetCapture();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::OnLButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
if (m_mouseMode == MOUSE_MODE_SELECT)
|
|
{
|
|
bool prevSelected = m_bAnySelected;
|
|
// Check if any key are selected.
|
|
m_rcSelect-=m_scrollOffset;
|
|
SelectKeys( m_rcSelect );
|
|
/*
|
|
if (prevSelected == m_bAnySelected)
|
|
Invalidate();
|
|
else
|
|
{
|
|
CDC *dc = GetDC();
|
|
dc->DrawDragRect( CRect(0,0,0,0),CSize(0,0),m_rcSelect,CSize(1,1) );
|
|
ReleaseDC(dc);
|
|
}
|
|
*/
|
|
Invalidate();
|
|
m_rcSelect = CRect(0,0,0,0);
|
|
}
|
|
else if (m_mouseMode == MOUSE_MODE_DRAGTIME)
|
|
{
|
|
SetMouseCursor(NULL);
|
|
}
|
|
|
|
if (GetCapture() == this)
|
|
{
|
|
ReleaseCapture();
|
|
}
|
|
|
|
if (m_bAnySelected)
|
|
{
|
|
IAnimTrack *track = 0;
|
|
int key = 0;
|
|
if (FindSingleSelectedKey(track,key))
|
|
{
|
|
SetKeyInfo(track,key);
|
|
}
|
|
}
|
|
m_keyTimeOffset = 0;
|
|
|
|
//if (GetIEditor()->IsUndoRecording())
|
|
//GetIEditor()->AcceptUndo( "Track Modify" );
|
|
|
|
m_mouseMode = MOUSE_MODE_NONE;
|
|
CWnd::OnLButtonUp(nFlags, point);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::OnMouseMove(UINT nFlags, CPoint point)
|
|
{
|
|
if (m_bZoomDrag && (nFlags & MK_SHIFT))
|
|
{
|
|
SetTimeScale(m_timeScale*(1.0f+(point.x-m_mouseDownPos.x)*0.0025f));
|
|
m_mouseDownPos=point;
|
|
return;
|
|
}else
|
|
m_bZoomDrag=false;
|
|
if (m_bMoveDrag)
|
|
{
|
|
m_scrollOffset.x+= m_mouseDownPos.x-point.x;
|
|
if (m_scrollOffset.x < m_scrollMin)
|
|
m_scrollOffset.x = m_scrollMin;
|
|
if (m_scrollOffset.x > m_scrollMax)
|
|
m_scrollOffset.x = m_scrollMax;
|
|
m_mouseDownPos = point;
|
|
// Set the new position of the thumb (scroll box).
|
|
SetScrollPos( SB_HORZ,m_scrollOffset.x );
|
|
Invalidate();
|
|
return;
|
|
}
|
|
if (m_mouseMode == MOUSE_MODE_SELECT)
|
|
{
|
|
SetMouseCursor(NULL);
|
|
CRect rc( m_mouseDownPos.x,m_mouseDownPos.y,point.x,point.y );
|
|
rc.NormalizeRect();
|
|
CRect rcClient;
|
|
GetClientRect(rcClient);
|
|
rc.IntersectRect(rc,rcClient);
|
|
|
|
CDC *dc = GetDC();
|
|
dc->DrawDragRect( rc,CSize(1,1),m_rcSelect,CSize(1,1) );
|
|
ReleaseDC(dc);
|
|
m_rcSelect = rc;
|
|
}
|
|
else if (m_mouseMode == MOUSE_MODE_MOVE)
|
|
{
|
|
SetMouseCursor(m_crsLeftRight);
|
|
if (point.x < m_rcClient.left)
|
|
point.x = m_rcClient.left;
|
|
if (point.x > m_rcClient.right)
|
|
point.x = m_rcClient.right;
|
|
CPoint ofs = point - m_mouseDownPos;
|
|
|
|
bool bSnapKeys = (nFlags & MK_CONTROL) != 0;
|
|
|
|
float newTime;
|
|
float oldTime;
|
|
if (bSnapKeys)
|
|
{
|
|
newTime = TimeFromPointUnsnapped(point);
|
|
oldTime = TimeFromPointUnsnapped(m_mouseDownPos);
|
|
}
|
|
else
|
|
{
|
|
newTime = TimeFromPoint(point);
|
|
oldTime = TimeFromPoint(m_mouseDownPos);
|
|
}
|
|
m_realTimeRange.ClipValue( newTime );
|
|
|
|
float timeOffset = newTime - oldTime;
|
|
|
|
if (m_mouseActionMode == TVMODE_SCALEKEY)
|
|
{
|
|
float tscale = 0.005f;
|
|
float tofs = ofs.x * tscale;
|
|
// Offset all selected keys back by previous offset.
|
|
if (m_keyTimeOffset != 0)
|
|
ScaleSelectedKeys( 1.0f/(1+m_keyTimeOffset),bSnapKeys );
|
|
// Offset all selected keys by this offset.
|
|
ScaleSelectedKeys( 1+tofs,bSnapKeys );
|
|
m_keyTimeOffset = tofs;
|
|
}
|
|
else
|
|
{
|
|
bool bSlide = false;
|
|
if (m_mouseActionMode == TVMODE_SLIDEKEY)
|
|
bSlide = true;
|
|
|
|
// Offset all selected keys back by previous offset.
|
|
if (m_keyTimeOffset != 0)
|
|
OffsetSelectedKeys( -m_keyTimeOffset,bSlide,bSnapKeys );
|
|
// Offset all selected keys by this offset.
|
|
OffsetSelectedKeys( timeOffset,bSlide,bSnapKeys );
|
|
m_keyTimeOffset = timeOffset;
|
|
}
|
|
Invalidate();
|
|
}
|
|
else if (m_mouseMode == MOUSE_MODE_CLONE)
|
|
{
|
|
CloneSelectedKeys();
|
|
m_mouseMode = MOUSE_MODE_MOVE;
|
|
}
|
|
else if (m_mouseMode == MOUSE_MODE_DRAGTIME)
|
|
{
|
|
CPoint p = point;
|
|
if (p.x < m_rcClient.left)
|
|
p.x = m_rcClient.left;
|
|
if (p.x > m_rcClient.right)
|
|
p.x = m_rcClient.right;
|
|
if (p.y < m_rcClient.top)
|
|
p.y = m_rcClient.top;
|
|
if (p.y > m_rcClient.bottom)
|
|
p.y = m_rcClient.bottom;
|
|
|
|
bool bNoSnap = (nFlags & MK_CONTROL) != 0;
|
|
float time = TimeFromPointUnsnapped(p);
|
|
m_realTimeRange.ClipValue( time );
|
|
if (!bNoSnap)
|
|
time = SnapTime(time);
|
|
SetCurrTime( time );
|
|
}
|
|
else if (m_mouseMode == MOUSE_MODE_DRAGSTARTMARKER)
|
|
{
|
|
CPoint p = point;
|
|
if (p.x < m_rcClient.left)
|
|
p.x = m_rcClient.left;
|
|
if (p.x > m_rcClient.right)
|
|
p.x = m_rcClient.right;
|
|
if (p.y < m_rcClient.top)
|
|
p.y = m_rcClient.top;
|
|
if (p.y > m_rcClient.bottom)
|
|
p.y = m_rcClient.bottom;
|
|
|
|
bool bNoSnap = (nFlags & MK_CONTROL) != 0;
|
|
float time = TimeFromPointUnsnapped(p);
|
|
m_realTimeRange.ClipValue( time );
|
|
if (!bNoSnap)
|
|
time = SnapTime(time);
|
|
SetStartMarker( time );
|
|
}
|
|
else if (m_mouseMode == MOUSE_MODE_DRAGENDMARKER)
|
|
{
|
|
CPoint p = point;
|
|
if (p.x < m_rcClient.left)
|
|
p.x = m_rcClient.left;
|
|
if (p.x > m_rcClient.right)
|
|
p.x = m_rcClient.right;
|
|
if (p.y < m_rcClient.top)
|
|
p.y = m_rcClient.top;
|
|
if (p.y > m_rcClient.bottom)
|
|
p.y = m_rcClient.bottom;
|
|
|
|
bool bNoSnap = (nFlags & MK_CONTROL) != 0;
|
|
float time = TimeFromPointUnsnapped(p);
|
|
m_realTimeRange.ClipValue( time );
|
|
if (!bNoSnap)
|
|
time = SnapTime(time);
|
|
SetEndMarker( time );
|
|
}
|
|
else
|
|
{
|
|
if (m_mouseActionMode == TVMODE_ADDKEY)
|
|
{
|
|
SetMouseCursor(m_crsAddKey);
|
|
}
|
|
else
|
|
{
|
|
// No mouse mode.
|
|
SetMouseCursor(NULL);
|
|
int key = KeyFromPoint(point);
|
|
if (key >= 0)
|
|
{
|
|
int item = ItemFromPoint(point);
|
|
IAnimTrack *track = GetTrack(item);
|
|
if (track && track->GetKeyFlags(key) & AKEY_SELECTED)
|
|
{
|
|
// If mouse over selected key, change cursor to left-right arrows.
|
|
SetMouseCursor(m_crsLeftRight);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CWnd::OnMouseMove(nFlags, point);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::OnPaint()
|
|
{
|
|
// CPaintDC dc(this); // device context for painting
|
|
// TODO: Add your message handler code here
|
|
// CWnd::OnPaint();
|
|
|
|
CPaintDC PaintDC(this);
|
|
CMemDC dc( PaintDC,&m_offscreenBitmap );
|
|
|
|
dc->FillRect( &PaintDC.m_ps.rcPaint,&m_bkgrBrush );
|
|
DrawControl( dc,PaintDC.m_ps.rcPaint );
|
|
|
|
/*
|
|
CRect rc = m_rcClient;
|
|
for (int i = 0; i < GetCount(); i++)
|
|
{
|
|
IAnimTrack *track = GetTrack(i);
|
|
if (!track)
|
|
continue;
|
|
|
|
float xoffset = 0;
|
|
int y = (m_rcClient.bottom+m_rcClient.top)/2;
|
|
dc->MoveTo( m_rcClient.left,y );
|
|
// Draw first track spline.
|
|
for (int x = m_rcClient.left; x < m_rcClient.right; x++)
|
|
{
|
|
float time = TimeFromPointUnsnapped(CPoint(x,y));
|
|
Vec3 val;
|
|
track->GetValue( time,val );
|
|
if (x == m_rcClient.left)
|
|
xoffset = val.x;
|
|
dc->LineTo(x,y + val.x - xoffset);
|
|
}
|
|
}
|
|
*/
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::DrawTrack( int item,CDC *dc,CRect &rcItem )
|
|
{
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::DrawControl( CDC *dc,const CRect &rcUpdate )
|
|
{
|
|
CRect rc;
|
|
CRect rcTemp;
|
|
|
|
// Draw all items.
|
|
int count = GetCount();
|
|
for (int i = 0; i < count; i++)
|
|
{
|
|
GetItemRect( i,rc );
|
|
//if (rcTemp.IntersectRect(rc,rcUpdate) != 0)
|
|
{
|
|
DrawTrack( i,dc,rc );
|
|
}
|
|
}
|
|
|
|
DrawTimeline( dc,rcUpdate );
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::UnselectAllKeys()
|
|
{
|
|
for (int i = 0; i < GetCount(); i++)
|
|
{
|
|
IAnimTrack *track = GetTrack(i);
|
|
if (!track)
|
|
continue;
|
|
|
|
for (int j = 0; j < track->GetNumKeys(); j++)
|
|
{
|
|
track->SetKeyFlags( j,track->GetKeyFlags(j) & ~AKEY_SELECTED );
|
|
}
|
|
}
|
|
m_bAnySelected = false;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::SelectKeys( const CRect &rc )
|
|
{}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::DelSelectedKeys()
|
|
{
|
|
// Cofirm.
|
|
if (AfxMessageBox("Delete selected keys?",MB_OKCANCEL|MB_ICONQUESTION ) != IDOK)
|
|
return;
|
|
|
|
for (int i = 0; i < GetCount(); i++)
|
|
{
|
|
IAnimTrack *track = GetTrack(i);
|
|
if (!track)
|
|
continue;
|
|
int j = 0;
|
|
while (j < track->GetNumKeys())
|
|
{
|
|
if (track->GetKeyFlags(j)&AKEY_SELECTED)
|
|
{
|
|
track->RemoveKey(j);
|
|
}
|
|
else
|
|
j++;
|
|
}
|
|
}
|
|
Invalidate();
|
|
UpdateAnimation();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::OffsetSelectedKeys( float timeOffset,bool bSlide,bool bSnap )
|
|
{
|
|
for (int i = 0; i < GetCount(); i++)
|
|
{
|
|
IAnimTrack *track = GetTrack(i);
|
|
if (!track)
|
|
continue;
|
|
|
|
int numKeys = track->GetNumKeys();
|
|
|
|
if (bSlide)
|
|
{
|
|
bool move = false;
|
|
for (int j = 0; j < numKeys; j++)
|
|
{
|
|
if (track->GetKeyFlags(j)&AKEY_SELECTED)
|
|
move = true;
|
|
if (move)
|
|
{
|
|
//float keyt = SnapTime(track->GetKeyTime(j) + timeOffset);
|
|
float keyt = track->GetKeyTime(j) + timeOffset;
|
|
if (bSnap)
|
|
keyt = SnapTime(keyt);
|
|
|
|
track->SetKeyTime( j,keyt );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int j = 0; j < numKeys; j++)
|
|
{
|
|
if (track->GetKeyFlags(j)&AKEY_SELECTED)
|
|
{
|
|
//float keyt = SnapTime(track->GetKeyTime(j) + timeOffset);
|
|
float keyt = track->GetKeyTime(j) + timeOffset;
|
|
if (bSnap)
|
|
keyt = SnapTime(keyt);
|
|
track->SetKeyTime( j,keyt );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
UpdateAnimation();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::ScaleSelectedKeys( float timeOffset,bool bSnapKeys )
|
|
{
|
|
if (timeOffset <= 0)
|
|
return;
|
|
for (int i = 0; i < GetCount(); i++)
|
|
{
|
|
IAnimTrack *track = GetTrack(i);
|
|
if (!track)
|
|
continue;
|
|
int numKeys = track->GetNumKeys();
|
|
bool move = false;
|
|
for (int j = 0; j < numKeys; j++)
|
|
{
|
|
if (track->GetKeyFlags(j)&AKEY_SELECTED)
|
|
move = true;
|
|
if (move)
|
|
{
|
|
float keyt = track->GetKeyTime(j) * timeOffset;
|
|
if (bSnapKeys)
|
|
keyt = SnapTime(keyt);
|
|
track->SetKeyTime( j,keyt );
|
|
}
|
|
}
|
|
}
|
|
UpdateAnimation();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::CloneSelectedKeys()
|
|
{
|
|
for (int i = 0; i < GetCount(); i++)
|
|
{
|
|
IAnimTrack *track = GetTrack(i);
|
|
if (!track)
|
|
continue;
|
|
int numKeys = track->GetNumKeys();
|
|
for (int j = 0; j < numKeys; j++)
|
|
{
|
|
int keyFlags = track->GetKeyFlags(j);
|
|
if (!(keyFlags&AKEY_SELECTED))
|
|
continue;
|
|
|
|
int newKey = track->CloneKey(j);
|
|
// Select new key.
|
|
track->SetKeyFlags(newKey,keyFlags|AKEY_SELECTED );
|
|
// Unselect cloned key.
|
|
track->SetKeyFlags(j,keyFlags&(~AKEY_SELECTED) );
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
BOOL CTrackViewKeys::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
|
|
{
|
|
if (m_currCursor != NULL)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
return CWnd::OnSetCursor(pWnd, nHitTest, message);
|
|
}
|
|
|
|
void CTrackViewKeys::SetMouseCursor( HCURSOR crs )
|
|
{
|
|
m_currCursor = crs;
|
|
if (m_currCursor != NULL)
|
|
SetCursor(crs);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
BOOL CTrackViewKeys::OnEraseBkgnd(CDC* pDC)
|
|
{
|
|
//return CWnd::OnEraseBkgnd(pDC);
|
|
return FALSE;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::SetCurrTime( float time )
|
|
{
|
|
if (time < m_timeRange.start)
|
|
time = m_timeRange.start;
|
|
if (time > m_timeRange.end)
|
|
time = m_timeRange.end;
|
|
|
|
//bool bChange = fabs(time-m_currentTime) >= (1.0f/m_ticksStep);
|
|
bool bChange = fabs(time-m_currentTime) >= 0.001f;
|
|
|
|
if (bChange)
|
|
{
|
|
int x1 = TimeToClient(m_currentTime);
|
|
int x2 = TimeToClient(time);
|
|
m_currentTime = time;
|
|
//Invalidate();
|
|
|
|
|
|
CRect rc(x1-3,m_rcClient.top,x1+4,m_rcClient.bottom);
|
|
RedrawWindow( rc,NULL,RDW_INVALIDATE );
|
|
CRect rc1(x2-3,m_rcClient.top,x2+4,m_rcClient.bottom);
|
|
RedrawWindow( rc1,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ERASE );
|
|
GetIEditor()->GetAnimation()->SetTime( m_currentTime );
|
|
}
|
|
}
|
|
|
|
void CTrackViewKeys::SetStartMarker(float fTime)
|
|
{
|
|
m_timeMarked.start=fTime;
|
|
if (m_timeMarked.start<m_timeRange.start)
|
|
m_timeMarked.start=m_timeRange.start;
|
|
if (m_timeMarked.start>m_timeRange.end)
|
|
m_timeMarked.start=m_timeRange.end;
|
|
if (m_timeMarked.start>m_timeMarked.end)
|
|
m_timeMarked.end=m_timeMarked.start;
|
|
GetIEditor()->GetAnimation()->SetMarkers(m_timeMarked);
|
|
Invalidate();
|
|
}
|
|
|
|
void CTrackViewKeys::SetEndMarker(float fTime)
|
|
{
|
|
m_timeMarked.end=fTime;
|
|
if (m_timeMarked.end<m_timeRange.start)
|
|
m_timeMarked.end=m_timeRange.start;
|
|
if (m_timeMarked.end>m_timeRange.end)
|
|
m_timeMarked.end=m_timeRange.end;
|
|
if (m_timeMarked.start>m_timeMarked.end)
|
|
m_timeMarked.start=m_timeMarked.end;
|
|
GetIEditor()->GetAnimation()->SetMarkers(m_timeMarked);
|
|
Invalidate();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::SetMouseActionMode( ETVActionMode mode )
|
|
{
|
|
m_mouseActionMode = mode;
|
|
if (mode == TVMODE_ADDKEY)
|
|
{
|
|
SetMouseCursor( m_crsAddKey );
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CTrackViewKeys::CanCopyPasteKeys()
|
|
{
|
|
IAnimTrack *pCopyFromTrack=NULL;
|
|
// are all selected keys from the same source track ?
|
|
if (!m_bAnySelected)
|
|
return false;
|
|
for (int i=0;i<GetCount();i++)
|
|
{
|
|
IAnimTrack *pCurrTrack=GetTrack(i);
|
|
if (!pCurrTrack)
|
|
continue;
|
|
for (int nKey=0;nKey<pCurrTrack->GetNumKeys();nKey++)
|
|
{
|
|
if (pCurrTrack->GetKeyFlags(nKey) & AKEY_SELECTED)
|
|
{
|
|
if (!pCopyFromTrack)
|
|
{
|
|
pCopyFromTrack=pCurrTrack;
|
|
}else
|
|
{
|
|
if (pCopyFromTrack!=pCurrTrack)
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!pCopyFromTrack)
|
|
return false;
|
|
// is a destination-track selected ?
|
|
if (m_selected==-1)
|
|
return false;
|
|
IAnimTrack *pCurrTrack=GetTrack(m_selected);
|
|
if (!pCurrTrack)
|
|
return false;
|
|
if (pCurrTrack->GetType()!=pCopyFromTrack->GetType())
|
|
return false;
|
|
return (pCopyFromTrack!=pCurrTrack);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CTrackViewKeys::CopyPasteKeys()
|
|
{
|
|
IAnimTrack *pCopyFromTrack=NULL;
|
|
std::vector<int> vecKeysToCopy;
|
|
if (!CanCopyPasteKeys())
|
|
return false;
|
|
if (!m_bAnySelected)
|
|
return false;
|
|
for (int i=0;i<GetCount();i++)
|
|
{
|
|
IAnimTrack *pCurrTrack=GetTrack(i);
|
|
if (!pCurrTrack)
|
|
continue;
|
|
for (int nKey=0;nKey<pCurrTrack->GetNumKeys();nKey++)
|
|
{
|
|
if (pCurrTrack->GetKeyFlags(nKey) & AKEY_SELECTED)
|
|
{
|
|
pCopyFromTrack=pCurrTrack;
|
|
vecKeysToCopy.push_back(nKey);
|
|
}
|
|
}
|
|
if (pCopyFromTrack)
|
|
break;
|
|
}
|
|
if (!pCopyFromTrack)
|
|
return false;
|
|
IAnimTrack *pCurrTrack=GetTrack(m_selected);
|
|
if (!pCurrTrack)
|
|
return false;
|
|
for (int i=0;i<(int)vecKeysToCopy.size();i++)
|
|
{
|
|
pCurrTrack->CopyKey(pCopyFromTrack, vecKeysToCopy[i]);
|
|
}
|
|
Invalidate();
|
|
return true;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::SetKeyInfo( IAnimTrack *track,int key,bool openWindow )
|
|
{
|
|
EAnimTrackType trackType = track->GetType();
|
|
|
|
if (openWindow && m_wndTrack != 0 && !::IsWindow(m_wndTrack->m_hWnd))
|
|
{
|
|
m_wndTrack->Create( CTVTrackPropsDialog::IDD,GetParent() );
|
|
}
|
|
if (m_wndTrack && m_wndTrack->m_hWnd != 0 && ::IsWindow(m_wndTrack->m_hWnd))
|
|
{
|
|
int paramId;
|
|
IAnimNode *node = 0;
|
|
for (int i = 0; i < GetCount(); i++)
|
|
{
|
|
if (m_tracks[i].track == track)
|
|
{
|
|
node = m_tracks[i].node;
|
|
paramId = m_tracks[i].paramId;
|
|
break;
|
|
}
|
|
}
|
|
if (node)
|
|
m_wndTrack->SetKey( node,paramId,track,key );
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
bool CTrackViewKeys::FindSingleSelectedKey( IAnimTrack* &selTrack,int &selKey )
|
|
{
|
|
selTrack = 0;
|
|
selKey = 0;
|
|
for (int i = 0; i < GetCount(); i++)
|
|
{
|
|
IAnimTrack *track = GetTrack(i);
|
|
if (!track)
|
|
continue;
|
|
int numKeys = track->GetNumKeys();
|
|
for (int j = 0; j < numKeys; j++)
|
|
{
|
|
if (track->GetKeyFlags(j)&AKEY_SELECTED)
|
|
{
|
|
// Check if already different key selected.
|
|
if (selTrack != 0)
|
|
{
|
|
return false;
|
|
}
|
|
selTrack = track;
|
|
selKey = j;
|
|
}
|
|
}
|
|
}
|
|
if (selTrack)
|
|
return true;
|
|
|
|
return false;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
int CTrackViewKeys::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;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
int CTrackViewKeys::ItemFromPoint( CPoint pnt )
|
|
{
|
|
CRect rc;
|
|
int num = GetCount();
|
|
for (int i = 0; i < num; i++)
|
|
{
|
|
GetItemRect(i,rc);
|
|
if (rc.PtInRect(pnt))
|
|
return i;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::SetHorizontalExtent( int min,int max )
|
|
{
|
|
m_scrollMin = min;
|
|
m_scrollMax = max;
|
|
m_itemWidth = max - min;
|
|
int nPage = m_rcClient.Width()/2;
|
|
int sx = m_itemWidth - nPage + m_leftOffset;
|
|
|
|
SCROLLINFO si;
|
|
ZeroStruct(si);
|
|
si.cbSize = sizeof(si);
|
|
si.fMask = SIF_ALL;
|
|
si.nMin = m_scrollMin;
|
|
si.nMax = m_scrollMax - nPage + m_leftOffset;
|
|
si.nPage = m_rcClient.Width()/2;
|
|
si.nPos = m_scrollOffset.x;
|
|
//si.nPage = max(0,m_rcClient.Width() - m_leftOffset*2);
|
|
//si.nPage = 1;
|
|
//si.nPage = 1;
|
|
SetScrollInfo( SB_HORZ,&si,TRUE );
|
|
};
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::UpdateAnimation()
|
|
{
|
|
GetIEditor()->GetAnimation()->ForceAnimation();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::SetCurSel( int sel )
|
|
{
|
|
if (sel != m_selected)
|
|
{
|
|
m_selected = sel;
|
|
Invalidate();
|
|
}
|
|
}
|
|
|
|
void CTrackViewKeys::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
{
|
|
if (nChar == VK_DELETE)
|
|
{
|
|
DelSelectedKeys();
|
|
}
|
|
|
|
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
|
|
}
|
|
|
|
void CTrackViewKeys::OnRButtonUp(UINT nFlags, CPoint point)
|
|
{
|
|
m_bZoomDrag=false;
|
|
m_bMoveDrag=false;
|
|
|
|
if (GetCapture() == this)
|
|
{
|
|
ReleaseCapture();
|
|
}
|
|
m_mouseMode = MOUSE_MODE_NONE;
|
|
// CWnd::OnRButtonUp(nFlags, point);
|
|
}
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CTrackViewKeys::RecordTrackUndo( const Item &item )
|
|
{
|
|
if (item.track != 0)
|
|
{
|
|
CUndo undo("Track Modify");
|
|
CUndo::Record( new CUndoTrackObject(item.track) );
|
|
}
|
|
} |