|
|
#include "stdafx.h"
|
|
|
#include "HTracker.h"
|
|
|
#include "SigmaDoc.h"
|
|
|
#include "ScaleMotionGraphDrawer.h"
|
|
|
#include "PanMotionGraphDrawer.h"
|
|
|
#include "RotationMotionGraphDrawer.h"
|
|
|
#include "ShearMotionGraphDrawer.h"
|
|
|
#include "SelectedItemMotionGraphDrawer.h"
|
|
|
|
|
|
bool GraphItemTransform(Gdiplus::Matrix * pMat, CPositionList & selectionSet, CSigmaDoc * pDoc);
|
|
|
|
|
|
//Tracker的状态
|
|
|
//未拖拽状态
|
|
|
//拖拽状态
|
|
|
|
|
|
//未拖拽状态的条件:用户刚选中图元
|
|
|
//拖拽状态:
|
|
|
//进入拖拽状态的条件:[鼠标左键单击]且[选择集不空]且[击中Handle],简化为:[鼠标左键单击]且[击中Handle]
|
|
|
//退出拖拽状态的条件:[鼠标左键松开]/[鼠标移动]且[未击中Handle]
|
|
|
//隐藏状态的条件:[鼠标左键下按或抬起]且[未击中Handle]
|
|
|
|
|
|
HTracker::HTracker()
|
|
|
:m_status(HTRACKER_STATUS_HIDE),
|
|
|
m_HandleSize(12),
|
|
|
m_pDoc(NULL),
|
|
|
m_motionCount(0),
|
|
|
m_transformKind(HTRACKER_TRANSFORM_KIND_SCALE)
|
|
|
{
|
|
|
m_pScaleMotionGraphDrawer = new ScaleMotionGraphDrawer();
|
|
|
m_pPanMotionGraphDrawer = new PanMotionGraphDrawer();
|
|
|
m_pRotationMotionGraphDrawer = new RotationMotionGraphDrawer() ;
|
|
|
m_pShearMotionGraphDrawer = new ShearMotionGraphDrawer();
|
|
|
m_pTMGDrawer = m_pScaleMotionGraphDrawer;
|
|
|
|
|
|
m_pSIMGDrawer = new SelectedItemMotionGraphDrawer();
|
|
|
}
|
|
|
|
|
|
HTracker::~HTracker()
|
|
|
{
|
|
|
delete m_pSIMGDrawer;
|
|
|
m_pSIMGDrawer = NULL;
|
|
|
|
|
|
delete m_pScaleMotionGraphDrawer;
|
|
|
m_pScaleMotionGraphDrawer = NULL;
|
|
|
delete m_pPanMotionGraphDrawer;
|
|
|
m_pPanMotionGraphDrawer = NULL;
|
|
|
delete m_pRotationMotionGraphDrawer;
|
|
|
m_pRotationMotionGraphDrawer = NULL;
|
|
|
delete m_pShearMotionGraphDrawer;
|
|
|
m_pShearMotionGraphDrawer = NULL;
|
|
|
}
|
|
|
|
|
|
bool HTracker::Create(CSigmaDoc * pDoc, CPositionList & selectionSet)
|
|
|
{
|
|
|
if (selectionSet.IsEmpty() || pDoc == NULL)
|
|
|
return false;
|
|
|
|
|
|
m_boundRect.SetRectEmpty();
|
|
|
m_pDoc = pDoc;
|
|
|
m_motionCount = 0;
|
|
|
m_switch.Reset();
|
|
|
m_drawer.Reset();
|
|
|
m_transformKind = HTRACKER_TRANSFORM_KIND_SCALE;
|
|
|
|
|
|
CopySelectionSet(selectionSet);
|
|
|
|
|
|
m_pSIMGDrawer->Init(pDoc, &selectionSet);
|
|
|
m_pTMGDrawer = m_pScaleMotionGraphDrawer;
|
|
|
m_pTMGDrawer->SetSIMGDrawer(m_pSIMGDrawer);
|
|
|
m_pTMGDrawer->CopyMatrix(m_trackerTransform.GetMatrix());
|
|
|
|
|
|
if (m_bound.CreateBoundRect(pDoc, selectionSet, m_boundRect) == false)
|
|
|
return false;
|
|
|
|
|
|
m_handleCalctor.Calculate(m_boundRect);
|
|
|
return true;
|
|
|
}
|
|
|
|
|
|
void HTracker::LButtonDown(int mouseX, int mouseY)
|
|
|
{
|
|
|
HTRACKER_HANDLE_KIND handleKind = HitTest(mouseX, mouseY);
|
|
|
m_motionCount = 0;
|
|
|
if (handleKind == HTRACKER_HANDLE_KIND_INVALID)
|
|
|
{
|
|
|
m_status = HTRACKER_STATUS_HIDE;
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
m_pTMGDrawer->LButtonDown(mouseX, mouseY);
|
|
|
m_switch.HitHandle();
|
|
|
|
|
|
//击中Handle,进入拖拽状态
|
|
|
m_status = HTRACKER_STATUS_DRAGING;
|
|
|
|
|
|
CPoint mousePt(mouseX, mouseY);
|
|
|
|
|
|
m_trackerTransform.Init((int)handleKind, m_boundRect, mousePt); //缩放或平移变换
|
|
|
m_transformKind = JudgeTransformKind(handleKind);
|
|
|
ChangeGraphDrawer();
|
|
|
ChangeHtrackerDrawerState();
|
|
|
}
|
|
|
|
|
|
void HTracker::MouseMove(CDC * pDC, int mouseX, int mouseY)
|
|
|
{
|
|
|
if (m_status == HTRACKER_STATUS_HIDE)
|
|
|
return;
|
|
|
|
|
|
if (m_status == HTRACKER_STATUS_NOT_DRAG)
|
|
|
return;
|
|
|
|
|
|
CPoint mousePt(mouseX, mouseY);
|
|
|
m_switch.MouseMove();
|
|
|
m_trackerTransform.SetKind(this->m_transformKind);
|
|
|
m_trackerTransform.Draging(mousePt);
|
|
|
|
|
|
//之前处于拖拽状态
|
|
|
//判断退出拖拽状态的条件
|
|
|
//1、鼠标左键处于释放状态
|
|
|
//2、鼠标点不在Handle上
|
|
|
//一旦判断出不在拖拽状态,则说明刚推出拖拽状态
|
|
|
|
|
|
HTRACKER_HANDLE_KIND handleKind = HitTest(mouseX, mouseY);
|
|
|
|
|
|
SHORT lbttonStatus = ::GetAsyncKeyState(VK_LBUTTON);
|
|
|
if (handleKind == HTRACKER_HANDLE_KIND_INVALID && lbttonStatus == 0)
|
|
|
{
|
|
|
m_status = HTRACKER_STATUS_NOT_DRAG; //保持未拖拽状态的原因是,程序要继续绘制出tracker.
|
|
|
GraphItemTransform(m_trackerTransform.GetMatrix(), m_selectionSet, m_pDoc);
|
|
|
m_trackerTransform.EndDrag();
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
m_motionCount++;
|
|
|
if (m_motionCount == 1)
|
|
|
{
|
|
|
m_drawer.Draw(pDC, m_boundRect); //擦掉tracker
|
|
|
m_pTMGDrawer->FirstDraw(pDC, m_trackerTransform.GetMatrix(), mouseX, mouseY);
|
|
|
}
|
|
|
else
|
|
|
m_pTMGDrawer->Draw(pDC, m_trackerTransform.GetMatrix(), mouseX, mouseY);
|
|
|
}
|
|
|
|
|
|
void HTracker::LButtonUp(int mouseX, int mouseY)
|
|
|
{
|
|
|
//进入旋转切错状态的条件:
|
|
|
//在Handle上先按左键.在鼠标抬起时,鼠标没有移动.
|
|
|
HTRACKER_HANDLE_KIND handleKind = HitTest(mouseX, mouseY);
|
|
|
if (m_motionCount == 0)
|
|
|
{
|
|
|
m_switch.ButtonUp(handleKind);
|
|
|
m_transformKind = JudgeTransformKind(handleKind);
|
|
|
}
|
|
|
|
|
|
ChangeGraphDrawer();
|
|
|
ChangeHtrackerDrawerState();
|
|
|
|
|
|
m_status = HTRACKER_STATUS_NOT_DRAG;
|
|
|
m_motionCount = 0;
|
|
|
GraphItemTransform(m_trackerTransform.GetMatrix(), m_selectionSet, m_pDoc);
|
|
|
m_pSIMGDrawer->Init(m_pDoc, &m_selectionSet);
|
|
|
|
|
|
m_bound.CreateBoundRect(m_pDoc, m_selectionSet, m_boundRect);
|
|
|
m_trackerTransform.EndDrag();
|
|
|
}
|
|
|
|
|
|
void HTracker::Draw(CDC * pDC)
|
|
|
{
|
|
|
if (m_boundRect.IsRectEmpty())
|
|
|
return;
|
|
|
|
|
|
CRect boundRect;
|
|
|
TranslateBoundRect(boundRect);
|
|
|
|
|
|
m_drawer.Draw(pDC, boundRect);
|
|
|
m_handleCalctor.Calculate(boundRect);
|
|
|
}
|
|
|
|
|
|
bool HTracker::IsDraging()
|
|
|
{
|
|
|
return m_status == HTRACKER_STATUS_DRAGING;
|
|
|
}
|
|
|
|
|
|
void HTracker::Reset()
|
|
|
{
|
|
|
m_status = HTRACKER_STATUS_HIDE;
|
|
|
m_selectionSet.RemoveAll();
|
|
|
m_boundRect.SetRectEmpty();
|
|
|
m_handleCalctor.Reset();
|
|
|
m_trackerTransform.EndDrag();
|
|
|
m_motionCount = 0;
|
|
|
m_switch.Reset();
|
|
|
}
|
|
|
|
|
|
HTRACKER_HANDLE_KIND HTracker::HitTest(int mouseX, int mouseY)
|
|
|
{
|
|
|
if (m_selectionSet.IsEmpty())
|
|
|
return HTRACKER_HANDLE_KIND_INVALID;
|
|
|
|
|
|
CPoint point(mouseX, mouseY);
|
|
|
int i = -1;
|
|
|
for (i = 0; i < 9; i++)
|
|
|
{
|
|
|
if (m_handleCalctor.GetHandleRect(i).PtInRect(point))
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
if (i == -1)
|
|
|
return HTRACKER_HANDLE_KIND_INVALID;
|
|
|
|
|
|
//i的取值范围:[0,8]
|
|
|
return HTRACKER_HANDLE_KIND(i);
|
|
|
}
|
|
|
|
|
|
bool HTracker::IsRotateAndShearState()
|
|
|
{
|
|
|
return m_switch.IsRotationAndShear();
|
|
|
}
|
|
|
|
|
|
void HTracker::CopySelectionSet(CPositionList & selectionSet)
|
|
|
{
|
|
|
m_selectionSet.RemoveAll();
|
|
|
m_selectionSet.AddTail(&selectionSet);
|
|
|
}
|
|
|
|
|
|
void HTracker::TranslateBoundRect(CRect & boundRectOut)
|
|
|
{
|
|
|
//角点与索引的对应关系
|
|
|
// 0----------1
|
|
|
// | |
|
|
|
// | |
|
|
|
// 3----------2
|
|
|
Gdiplus::Point cornerPts[4];
|
|
|
cornerPts[0].X = cornerPts[3].X = m_boundRect.left;
|
|
|
cornerPts[0].Y = cornerPts[1].Y = m_boundRect.top;
|
|
|
cornerPts[1].X = cornerPts[2].X = m_boundRect.right;
|
|
|
cornerPts[2].Y = cornerPts[3].Y = m_boundRect.bottom;
|
|
|
|
|
|
Gdiplus::Matrix * matrix = m_trackerTransform.GetMatrix();
|
|
|
matrix->TransformPoints(cornerPts, 4);
|
|
|
|
|
|
boundRectOut.SetRect(cornerPts[0].X, cornerPts[0].Y, cornerPts[2].X, cornerPts[2].Y);
|
|
|
}
|
|
|
|
|
|
//只有在LButtonDown和LButtonUp中有效
|
|
|
HTRACKER_TRANSFORM_KIND HTracker::JudgeTransformKind(HTRACKER_HANDLE_KIND kind)
|
|
|
{
|
|
|
if (kind == HTRACKER_HANDLE_KIND_INVALID)
|
|
|
return HTRACKER_TRANSFORM_KIND_SCALE;
|
|
|
|
|
|
if (kind == HTRACKER_HANDLE_KIND_CENTER)
|
|
|
return HTRACKER_TRANSFORM_KIND_MOVE;
|
|
|
|
|
|
if (m_switch.IsRotationAndShear())
|
|
|
{
|
|
|
switch (kind)
|
|
|
{
|
|
|
case HTRACKER_HANDLE_KIND_TOP_LEFT:
|
|
|
case HTRACKER_HANDLE_KIND_TOP_RIGHT:
|
|
|
case HTRACKER_HANDLE_KIND_BOTTOM_RIGHT:
|
|
|
case HTRACKER_HANDLE_KIND_BOTTOM_LEFT:
|
|
|
return HTRACKER_TRANSFORM_KIND_ROTATION;
|
|
|
case HTRACKER_HANDLE_KIND_TOP:
|
|
|
case HTRACKER_HANDLE_KIND_RIGTH:
|
|
|
case HTRACKER_HANDLE_KIND_BOTTOM:
|
|
|
case HTRACKER_HANDLE_KIND_LEFT:
|
|
|
return HTRACKER_TRANSFORM_KIND_SHEAR;
|
|
|
}
|
|
|
|
|
|
return HTRACKER_TRANSFORM_KIND_SHEAR;
|
|
|
}
|
|
|
|
|
|
return HTRACKER_TRANSFORM_KIND_SCALE;
|
|
|
}
|
|
|
|
|
|
void HTracker::ChangeGraphDrawer()
|
|
|
{
|
|
|
switch (m_transformKind)
|
|
|
{
|
|
|
case HTRACKER_TRANSFORM_KIND_SCALE:
|
|
|
m_pTMGDrawer = m_pScaleMotionGraphDrawer;
|
|
|
break;
|
|
|
case HTRACKER_TRANSFORM_KIND_MOVE:
|
|
|
m_pTMGDrawer = m_pPanMotionGraphDrawer;
|
|
|
break;
|
|
|
case HTRACKER_TRANSFORM_KIND_ROTATION:
|
|
|
m_pTMGDrawer = m_pRotationMotionGraphDrawer;
|
|
|
break;
|
|
|
case HTRACKER_TRANSFORM_KIND_SHEAR:
|
|
|
m_pTMGDrawer = m_pShearMotionGraphDrawer;
|
|
|
break;
|
|
|
default:
|
|
|
m_pTMGDrawer = m_pScaleMotionGraphDrawer;
|
|
|
}
|
|
|
|
|
|
m_pTMGDrawer->SetSIMGDrawer(m_pSIMGDrawer);
|
|
|
m_pTMGDrawer->CopyMatrix(m_trackerTransform.GetMatrix());
|
|
|
m_pTMGDrawer->SetBoundRect(m_boundRect);
|
|
|
}
|
|
|
|
|
|
void HTracker::ChangeHtrackerDrawerState()
|
|
|
{
|
|
|
//如果是平移状态,则不改变drawer的旋转状态。
|
|
|
//因为在旋转和非旋转状态中,都可以平移图元。
|
|
|
//这么做修复了这个Bug:Tracker图形在旋转切错状态中,执行平移操作。
|
|
|
//之后,tracker图形变成平移图形。
|
|
|
if (m_transformKind == HTRACKER_TRANSFORM_KIND_SCALE)
|
|
|
{
|
|
|
m_drawer.SetRotateAndShearState(false);
|
|
|
}
|
|
|
else if (m_transformKind == HTRACKER_TRANSFORM_KIND_ROTATION
|
|
|
|| m_transformKind == HTRACKER_TRANSFORM_KIND_SHEAR)
|
|
|
{
|
|
|
m_drawer.SetRotateAndShearState(true);
|
|
|
}
|
|
|
} |