You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

315 lines
8.0 KiB
C++

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#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);
}
}