|
|
|
|
|
#include "StdAfx.h"
|
|
|
|
|
|
#include "CurveEditorSpline.h"
|
|
|
|
|
|
#include "SigmaDoc.h"
|
|
|
|
|
|
#include "SigmaView.h"
|
|
|
|
|
|
#include "ActionModifiedItem.h"
|
|
|
|
|
|
#include "ActionBackupItem.h"
|
|
|
|
|
|
#include "DrawOperator/TypeDefine.h"
|
|
|
|
|
|
#include "ActionCurveEdit.h"
|
|
|
|
|
|
#include "ActionCurveEditAddPoint.h"
|
|
|
|
|
|
#include "ActionCurveEditDeletePoint.h"
|
|
|
|
|
|
#include "HandleDrawer.h"
|
|
|
|
|
|
#include "Util.h"
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
constexpr double RECT_INFINITE = 1e100;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CurveEditorSpline::CurveEditorSpline(CSigmaDoc* pDoc)
|
|
|
|
|
|
: CurveEditorBase(pDoc)
|
|
|
|
|
|
, m_handleDrawer(std::make_unique<HandleDrawer>(pDoc))
|
|
|
|
|
|
, m_nHandleDrawMode(TRACKER_CIRCLE)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_renderer = std::make_unique<SplineEditorRenderer>(GetDoc(), m_handleDrawer.get());
|
|
|
|
|
|
m_dragPipeline = std::make_unique<SplineDragPipeline>(m_splineCurveModel, m_dragState, this);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CurveEditorSpline::~CurveEditorSpline(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::OnDraw(CXyDC* pDC)
|
|
|
|
|
|
{
|
|
|
|
|
|
POSITION pos = GetPos();
|
|
|
|
|
|
if (!pos)
|
|
|
|
|
|
return;
|
|
|
|
|
|
(void)pDC;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::DrawAssistant(CDC* pDC, int mouseX, int mouseY)
|
|
|
|
|
|
{
|
|
|
|
|
|
CCurveEx* pControlCurve = GetControlCurve();
|
|
|
|
|
|
if (pControlCurve == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_handleDrawer->Init(pControlCurve);
|
|
|
|
|
|
m_handleDrawer->DrawAll(pDC);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::OnLButtonDown(CDC* pDC, UINT nFlags, CPoint point, int vk)
|
|
|
|
|
|
{
|
|
|
|
|
|
SetScreenDC(pDC);
|
|
|
|
|
|
|
|
|
|
|
|
int hitIndex = HitTestHandle(point);
|
|
|
|
|
|
|
|
|
|
|
|
// 场景1:点击到了handle,选中并开始拖拽
|
|
|
|
|
|
if (hitIndex >= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
SetHandleIndex(hitIndex);
|
|
|
|
|
|
m_dragState.StartDrag(point, GetDC()->GetReal(point));
|
|
|
|
|
|
OnDrawDragPreview();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 场景2:没点到handle,检查是否在曲线上(可延迟创建handle)
|
|
|
|
|
|
if (IsCanAddHandle(point))
|
|
|
|
|
|
{
|
|
|
|
|
|
SetHandleIndex(-1);
|
|
|
|
|
|
m_dragState.StartDrag(point, GetDC()->GetReal(point));
|
|
|
|
|
|
OnDrawDragPreview();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 场景3:既没点到handle也没点到曲线,取消选中
|
|
|
|
|
|
SetHandleIndex(-1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorSpline::OnMouseMove(CDC* dc, UINT nFlags, CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
SetScreenDC(dc);
|
|
|
|
|
|
|
|
|
|
|
|
POSITION pos = GetPos();
|
|
|
|
|
|
if (!pos)
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
|
|
CXyDC* pDC = GetDC();
|
|
|
|
|
|
|
|
|
|
|
|
if (IsDragging(nFlags))
|
|
|
|
|
|
{
|
|
|
|
|
|
HandleMouseDrag(pDC, point);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
HandleMouseHover(pDC, point);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_handleDrawer->DrawFocusHandle(dc, GetHandleIndex());
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::ApplyDragAndRelease()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (!m_dragState.HasMoved())
|
|
|
|
|
|
{
|
|
|
|
|
|
SetHandleIndex(-1);
|
|
|
|
|
|
ReleaseCapture();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
OnDrawDragPreview();
|
|
|
|
|
|
m_dragPipeline->ProcessDragStep(false, nullptr);
|
|
|
|
|
|
SetModifiedFlag(TRUE);
|
|
|
|
|
|
GetDoc()->Modified();
|
|
|
|
|
|
SetHandleIndex(-1);
|
|
|
|
|
|
ReleaseCapture();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::OnLButtonUp(CDC* pDC, UINT nFlags, CPoint point, int vk)
|
|
|
|
|
|
{
|
|
|
|
|
|
SetScreenDC(pDC);
|
|
|
|
|
|
|
|
|
|
|
|
if (!m_dragState.isLeftButtonDownDuringMove)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
m_dragState.isLeftButtonDownDuringMove = false;
|
|
|
|
|
|
|
|
|
|
|
|
if (GetHandleIndex() < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
CPoint2D pt = GetDC()->GetReal(point);
|
|
|
|
|
|
POSITION pos = GetDoc()->GetSelectedItem(pt);
|
|
|
|
|
|
if (pos == GetPos())
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
EndEdit();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_dragState.UpdateLast(GetDC()->GetReal(point));
|
|
|
|
|
|
ApplyDragAndRelease();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::RemoveCurrentHandle()
|
|
|
|
|
|
{
|
|
|
|
|
|
if (IsCaptureState())
|
|
|
|
|
|
ReleaseCapture();
|
|
|
|
|
|
CCurveEx* pCurve = GetControlCurve();
|
|
|
|
|
|
if (pCurve == nullptr)
|
|
|
|
|
|
return;
|
|
|
|
|
|
DeleteHandle(GetHandleIndex());
|
|
|
|
|
|
SetHandleIndex(-1);
|
|
|
|
|
|
Invalidate();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::OnLButtonDblClk(UINT nFlags, CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
POSITION pos = GetPos();
|
|
|
|
|
|
if (!pos)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
COne* pOne = GetDoc()->GetDraw()->GetAt(pos);
|
|
|
|
|
|
if (pOne == nullptr)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<CActionModifiedItem> pAction = std::make_unique<CActionModifiedItem>(GetDoc(), 0);
|
|
|
|
|
|
pAction->BackupOldItem(pos, pOne);
|
|
|
|
|
|
|
|
|
|
|
|
if (GetHandleIndex() >= 0) // 如果当前存在控制点,删除它
|
|
|
|
|
|
{
|
|
|
|
|
|
RemoveCurrentHandle();
|
|
|
|
|
|
}
|
|
|
|
|
|
else // 否则尝试添加控制点
|
|
|
|
|
|
{
|
|
|
|
|
|
int ret = AddHandle(point);
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
pAction->BackupNewItem();
|
|
|
|
|
|
GetDoc()->SetActionItem(pAction.release());
|
|
|
|
|
|
GetDoc()->Modified();
|
|
|
|
|
|
|
|
|
|
|
|
if (GetDoc()->GetItem()->GetType() == ITEM_CURVE_EDIT)
|
|
|
|
|
|
EndEdit();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CurveEditorSpline::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
|
|
|
|
|
|
{
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CurveEditorSpline::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (nChar)
|
|
|
|
|
|
{
|
|
|
|
|
|
case VK_ESCAPE:
|
|
|
|
|
|
if (!IsCaptureState()) break;
|
|
|
|
|
|
OnDrawDragPreview();
|
|
|
|
|
|
DrawSelectHandle(GetHandleIndex());
|
|
|
|
|
|
SetHandleIndex(-1);
|
|
|
|
|
|
ReleaseCapture();
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
}
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CurveEditorSpline::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags)
|
|
|
|
|
|
{
|
|
|
|
|
|
switch (nChar)
|
|
|
|
|
|
{
|
|
|
|
|
|
case VK_ESCAPE:
|
|
|
|
|
|
EndEdit();
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
}
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorSpline::GetSubMenu()
|
|
|
|
|
|
{
|
|
|
|
|
|
return 6;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::SetPos(POSITION pos)
|
|
|
|
|
|
{
|
|
|
|
|
|
CItem::SetPos(pos);
|
|
|
|
|
|
m_pBakOne.reset();
|
|
|
|
|
|
m_dragState.Reset();
|
|
|
|
|
|
|
|
|
|
|
|
if (pos)
|
|
|
|
|
|
{
|
|
|
|
|
|
COne* pOne = GetDoc()->GetDraw()->GetAt(GetPos());
|
|
|
|
|
|
m_pBakOne = std::make_unique<COne>();
|
|
|
|
|
|
*m_pBakOne = *pOne;
|
|
|
|
|
|
|
|
|
|
|
|
CCurveEx* pCurve = (CCurveEx*)pOne->GetValue();
|
|
|
|
|
|
InitializeHandles(pCurve);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::Clear(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pBakOne.reset(); // 清除备份
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::Draw(CDC* pDC)
|
|
|
|
|
|
{
|
|
|
|
|
|
POSITION pos = GetPos();
|
|
|
|
|
|
if (!pos)
|
|
|
|
|
|
return;
|
|
|
|
|
|
CCurveEx* pValue = GetControlCurve();
|
|
|
|
|
|
DrawHandlesByCDC(pDC, pValue);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorSpline::GetNumberOfNode()
|
|
|
|
|
|
{
|
|
|
|
|
|
CCurveEx* pc = GetControlCurve();
|
|
|
|
|
|
if (pc == nullptr)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
return pc->num;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::EreaseHandles(CDC* pDC)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_handleDrawer->ClearAll(pDC);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::EndEdit(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (GetPos() == nullptr)
|
|
|
|
|
|
return;
|
|
|
|
|
|
COne* pOne = GetDoc()->GetDraw()->GetAt(GetPos());
|
|
|
|
|
|
|
|
|
|
|
|
CRect8 range(RECT_INFINITE, -RECT_INFINITE, -RECT_INFINITE, RECT_INFINITE);
|
|
|
|
|
|
pOne->GetRange(range);
|
|
|
|
|
|
CRect rt = GetDC()->GetScreen(range);
|
|
|
|
|
|
rt.NormalizeRect();
|
|
|
|
|
|
rt.InflateRect(GetDoc()->GetHandleSize());
|
|
|
|
|
|
rt.InflateRect(1, 1);
|
|
|
|
|
|
|
|
|
|
|
|
if (((CCurveEx*)pOne->GetValue())->num < 2)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (::AfxMessageBox(IDS_STRING_CURVE_ONLY_ONE_POINT, MB_YESNO | MB_ICONQUESTION) == IDYES)
|
|
|
|
|
|
{
|
|
|
|
|
|
*pOne = *m_pBakOne;
|
|
|
|
|
|
CPositionList list;
|
|
|
|
|
|
list.AddTail(GetPos());
|
|
|
|
|
|
CItem::SetPos(nullptr);
|
|
|
|
|
|
GetDoc()->InvalidateDelete(list);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (IsModified())
|
|
|
|
|
|
{
|
|
|
|
|
|
CActionItem* pAction = new CActionModifiedItem(GetDoc(), IDS_STRING_TOOLBAR_EDIT);
|
|
|
|
|
|
((CActionModifiedItem*)pAction)->BackupOldItem(GetPos(), m_pBakOne.get());
|
|
|
|
|
|
GetDoc()->SetActionItem(pAction);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::CancelAll(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_pBakOne)
|
|
|
|
|
|
{
|
|
|
|
|
|
COne* pOne = GetDoc()->GetDraw()->GetAt(GetPos());
|
|
|
|
|
|
*pOne = *m_pBakOne;
|
|
|
|
|
|
CCurveEx* pCurve = (CCurveEx*)pOne->GetValue();
|
|
|
|
|
|
InitializeHandles(pCurve);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CurveEditorSpline::IsCanCancelAll(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
return (m_pBakOne != nullptr);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::GetXY(CCurveEx* pValue, int nIndex, dfPoint& point)
|
|
|
|
|
|
{
|
|
|
|
|
|
pValue->GetPoint(nIndex, point);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CCurveEx* CurveEditorSpline::GetControlCurve(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
const auto& controlPoints = m_splineCurveModel.GetControlPoints();
|
|
|
|
|
|
if (controlPoints.empty())
|
|
|
|
|
|
return nullptr;
|
|
|
|
|
|
|
|
|
|
|
|
m_tempControlCurve = std::make_unique<CCurveEx>();
|
|
|
|
|
|
int num = static_cast<int>(controlPoints.size());
|
|
|
|
|
|
m_tempControlCurve->Create(num);
|
|
|
|
|
|
for (int i = 0; i < num; ++i)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_tempControlCurve->x[i] = controlPoints[i].x0;
|
|
|
|
|
|
m_tempControlCurve->y[i] = controlPoints[i].y0;
|
|
|
|
|
|
}
|
|
|
|
|
|
return m_tempControlCurve.get();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorSpline::HitTestHandle(CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
return HitTestHandle(GetControlCurve(), point);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorSpline::HitTestHandle(CCurveEx* pValue, CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (pValue == nullptr)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
CRect rt;
|
|
|
|
|
|
for (int i = 0; i < pValue->num; i++)
|
|
|
|
|
|
{
|
|
|
|
|
|
CPoint ptScreen(GetDC()->GetSX(pValue->x[i]), GetDC()->GetSY(pValue->y[i]));
|
|
|
|
|
|
if (i == 0 || i == pValue->num - 1)
|
|
|
|
|
|
rt = GetFirstNodeHandleRectFocus(ptScreen);
|
|
|
|
|
|
else
|
|
|
|
|
|
rt = GetDoc()->m_itemTracker.GetHandleRect(ptScreen);
|
|
|
|
|
|
if (rt.PtInRect(point))
|
|
|
|
|
|
return i;
|
|
|
|
|
|
}
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool CurveEditorSpline::IsDragging(int nFlags) const
|
|
|
|
|
|
{
|
|
|
|
|
|
return (nFlags & MK_LBUTTON) != 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorSpline::AcquireDragHandle(CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
int i = GetHandleIndex();
|
|
|
|
|
|
if (i >= 0)
|
|
|
|
|
|
return i;
|
|
|
|
|
|
|
|
|
|
|
|
CSize8 selectSize = GetDoc()->GetSelectSize();
|
|
|
|
|
|
if (AfxGetPublicFunction()->Distance(m_dragState.screenDownPoint.x, m_dragState.screenDownPoint.y, point.x, point.y) <= selectSize.cx)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
i = AddHandle(m_dragState.screenDownPoint);
|
|
|
|
|
|
if (i < 0)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
SetHandleIndex(i);
|
|
|
|
|
|
m_dragState.StartDrag(m_dragState.screenDownPoint, GetDC()->GetReal(m_dragState.screenDownPoint));
|
|
|
|
|
|
OnDrawDragPreview();
|
|
|
|
|
|
return i;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorSpline::HandleMouseDrag(CXyDC* pXyDC, CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_dragState.isLeftButtonDownDuringMove = true;
|
|
|
|
|
|
|
|
|
|
|
|
int i = AcquireDragHandle(point);
|
|
|
|
|
|
if (i < 0)
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
|
|
OnDrawDragPreview();
|
|
|
|
|
|
m_dragState.UpdateLast(pXyDC->GetReal(point));
|
|
|
|
|
|
|
|
|
|
|
|
CPointList list;
|
|
|
|
|
|
m_dragPipeline->ProcessDragStep(true, &list);
|
|
|
|
|
|
|
|
|
|
|
|
OnDrawDragPreview();
|
|
|
|
|
|
OnDragMove(GetHandleIndex(), m_dragState.worldLastPoint);
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorSpline::HandleMouseHover(CXyDC* pXyDC, CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
CDC* dc = pXyDC->GetDC();
|
|
|
|
|
|
|
|
|
|
|
|
CCurveEx* pValue = GetControlCurve();
|
|
|
|
|
|
if (pValue == nullptr)
|
|
|
|
|
|
{
|
|
|
|
|
|
SetHandleIndex(-1);
|
|
|
|
|
|
int handleIndex = m_handleDrawer->EreaseFocusHandle(dc);
|
|
|
|
|
|
m_handleDrawer->DrawOneHandle(dc, handleIndex);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
int i = HitTestHandle(pValue, point);
|
|
|
|
|
|
if (i >= 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
SetHandleIndex(i);
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
SetHandleIndex(-1);
|
|
|
|
|
|
int handleIndex = m_handleDrawer->EreaseFocusHandle(dc);
|
|
|
|
|
|
m_handleDrawer->DrawOneHandle(dc, handleIndex);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::DeleteHandle(int nIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (nIndex < 0 || nIndex >= m_splineCurveModel.GetControlPointCount())
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
if (!m_splineCurveModel.RemoveControlPoint(nIndex))
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
WriteModelToDocCurve();
|
|
|
|
|
|
SetModifiedFlag(TRUE);
|
|
|
|
|
|
SetHandleIndex(-1);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorSpline::AddHandle(double l0)
|
|
|
|
|
|
{
|
|
|
|
|
|
(void)l0;
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorSpline::AddHandle(CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
dfPoint worldPoint;
|
|
|
|
|
|
int segmentIndex = FindSegmentIndexAtScreenPoint(point, &worldPoint);
|
|
|
|
|
|
if (segmentIndex < 0)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
int insertIndex = segmentIndex + 1;
|
|
|
|
|
|
int ret = m_splineCurveModel.InsertControlPoint(insertIndex, worldPoint);
|
|
|
|
|
|
if (ret < 0)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
WriteModelToDocCurve();
|
|
|
|
|
|
GetDoc()->Modified();
|
|
|
|
|
|
SetModifiedFlag(TRUE);
|
|
|
|
|
|
return ret;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CurveEditorSpline::IsCanAddHandle(CPoint point, double* pl0)
|
|
|
|
|
|
{
|
|
|
|
|
|
dfPoint worldPoint;
|
|
|
|
|
|
int segmentIndex = FindSegmentIndexAtScreenPoint(point, &worldPoint);
|
|
|
|
|
|
if (pl0)
|
|
|
|
|
|
*pl0 = worldPoint.l;
|
|
|
|
|
|
return segmentIndex >= 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorSpline::FindSegmentIndexAtScreenPoint(CPoint screenPoint, dfPoint* pOutWorldPoint)
|
|
|
|
|
|
{
|
|
|
|
|
|
const auto& renderPoints = m_splineCurveModel.GetRenderPoints();
|
|
|
|
|
|
if (renderPoints.empty())
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
|
|
|
|
CXyDC* pDC = GetDC();
|
|
|
|
|
|
CSize8 selectSize = GetDoc()->GetSelectSize();
|
|
|
|
|
|
int maxDistSq = (int)(selectSize.cx * selectSize.cx + selectSize.cy * selectSize.cy);
|
|
|
|
|
|
int bestSegmentIndex = -1;
|
|
|
|
|
|
double bestDistSq = static_cast<double>(maxDistSq) + 1;
|
|
|
|
|
|
|
|
|
|
|
|
for (const auto& renderPoint : renderPoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
CPoint ptScreen(pDC->GetSX(renderPoint.point.x0), pDC->GetSY(renderPoint.point.y0));
|
|
|
|
|
|
int dx = ptScreen.x - screenPoint.x;
|
|
|
|
|
|
int dy = ptScreen.y - screenPoint.y;
|
|
|
|
|
|
double distSq = static_cast<double>(dx) * dx + static_cast<double>(dy) * dy;
|
|
|
|
|
|
if (distSq < bestDistSq)
|
|
|
|
|
|
{
|
|
|
|
|
|
bestDistSq = distSq;
|
|
|
|
|
|
bestSegmentIndex = renderPoint.segIndex;
|
|
|
|
|
|
if (pOutWorldPoint)
|
|
|
|
|
|
*pOutWorldPoint = renderPoint.point;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
if (bestSegmentIndex < 0 || bestDistSq > maxDistSq)
|
|
|
|
|
|
return -1;
|
|
|
|
|
|
return bestSegmentIndex;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::AttachProcess(CPointList& oldPoints, CPointList& newPoints)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::DrawMoveLine(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
OnDrawDragPreview();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::GetMarkCurve(void)
|
|
|
|
|
|
{
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CPoint2D CurveEditorSpline::GetCDown() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_dragState.worldDownPoint;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CPoint2D CurveEditorSpline::GetCLast() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_dragState.worldLastPoint;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::DrawHandle(CXyDC* pDC, CCurveEx* pCurve)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_renderer->DrawHandle(pDC, m_pScreenDC, pCurve, GetHandleIndex());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::DrawHandlesByCDC(CDC* pDC, CCurveEx* pCurve)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_renderer->DrawHandlesByCDC(pDC, pCurve);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::DrawSelectHandle(int nHandle)
|
|
|
|
|
|
{
|
|
|
|
|
|
CCurveEx* pValue = GetControlCurve();
|
|
|
|
|
|
if (pValue == nullptr)
|
|
|
|
|
|
return;
|
|
|
|
|
|
m_renderer->DrawSelectHandle(m_pScreenDC, GetDC(), pValue, nHandle, m_nHandleDrawMode);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CRect CurveEditorSpline::GetRangeWidthIndex(int nIndex)
|
|
|
|
|
|
{
|
|
|
|
|
|
CCurveEx* pValue = GetControlCurve();
|
|
|
|
|
|
if (pValue == nullptr)
|
|
|
|
|
|
return CRect(0, 0, 0, 0);
|
|
|
|
|
|
return m_renderer->GetRangeWidthIndex(pValue, nIndex, GetDC(), GetDoc()->GetHandleSize());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CRect CurveEditorSpline::GetFirstNodeHandleRectFocus(CPoint point)
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_renderer->GetFirstNodeHandleRectFocus(point);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::OnDragMove(int nIndex, CPoint2D pt)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_splineCurveModel.UpdateControlPoint(nIndex, pt.x0, pt.y0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::OnDrawDragPreview()
|
|
|
|
|
|
{
|
|
|
|
|
|
m_renderer->DrawDragPreview(m_pScreenDC, GetDC(), m_dragState.previewPoints);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CSigmaDoc* CurveEditorSpline::GetDoc()
|
|
|
|
|
|
{
|
|
|
|
|
|
return CItemCurve::GetDoc();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
POSITION CurveEditorSpline::GetPos()
|
|
|
|
|
|
{
|
|
|
|
|
|
return CItemCurve::GetPos();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int CurveEditorSpline::GetHandleIndex()
|
|
|
|
|
|
{
|
|
|
|
|
|
return CItemCurve::GetHandleIndex();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::Invalidate()
|
|
|
|
|
|
{
|
|
|
|
|
|
CItemCurve::Invalidate();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::WriteModelToDocCurve()
|
|
|
|
|
|
{
|
|
|
|
|
|
CCurveEx* pDocCurve = (CCurveEx*)GetDoc()->GetDraw()->GetAtValue(GetPos());
|
|
|
|
|
|
if (pDocCurve == nullptr)
|
|
|
|
|
|
return;
|
|
|
|
|
|
m_splineCurveModel.ToCCurveEx(*pDocCurve);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::InitializeHandles(CCurveEx* pCurve)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (pCurve == nullptr || pCurve->num < 2)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
double splineStep = GetDC()->GetMiniSmoothStep() * 3;
|
|
|
|
|
|
m_splineCurveModel.InitFromCCurveEx(*pCurve, splineStep);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CurveEditorSpline::OnCalculateDragEffect(CPointList* pList)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_dragPipeline->ProcessDragStep(pList != nullptr, pList);
|
|
|
|
|
|
}
|