|
|
|
|
|
#pragma once
|
|
|
|
|
|
#include "CurveEditorBase.h"
|
|
|
|
|
|
#include "HandleDrawer.h"
|
|
|
|
|
|
#include "SplineCurveModel.h"
|
|
|
|
|
|
#include "SplineDragPipeline.h"
|
|
|
|
|
|
#include "SplineEditorRenderer.h"
|
|
|
|
|
|
#include <memory>
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 三次样条曲线编辑模式
|
|
|
|
|
|
*
|
|
|
|
|
|
* 使用 Centripetal Catmull-Rom 算法,以控制点为唯一数据源,
|
|
|
|
|
|
* 支持拖拽控制点、点击曲线添加节点、双击删除节点。
|
|
|
|
|
|
*/
|
|
|
|
|
|
class CurveEditorSpline : public CurveEditorBase, public ISplineDragPipelineContext
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
CurveEditorSpline(CSigmaDoc* pDoc);
|
|
|
|
|
|
|
|
|
|
|
|
virtual ~CurveEditorSpline(void);
|
|
|
|
|
|
|
|
|
|
|
|
// Mouse event handlers
|
|
|
|
|
|
void OnDraw(CXyDC* pDC) override;
|
|
|
|
|
|
void OnLButtonDblClk(UINT nFlags, CPoint point) override;
|
|
|
|
|
|
void OnLButtonDown(CDC* pDC, UINT nFlags, CPoint point, int vk) override;
|
|
|
|
|
|
int OnMouseMove(CDC* pDC, UINT nFlags, CPoint point) override;
|
|
|
|
|
|
void OnLButtonUp(CDC* pDC, UINT nFlags, CPoint point, int vk) override;
|
|
|
|
|
|
BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) override;
|
|
|
|
|
|
BOOL OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) override;
|
|
|
|
|
|
BOOL OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) override;
|
|
|
|
|
|
int GetSubMenu() override;
|
|
|
|
|
|
void SetPos(POSITION pos) override;
|
|
|
|
|
|
void Clear(void) override;
|
|
|
|
|
|
|
|
|
|
|
|
void Draw(CDC* pDC) override;
|
|
|
|
|
|
void DrawAssistant(CDC* pDC, int mouseX, int mouseY) override;
|
|
|
|
|
|
int GetNumberOfNode() override;
|
|
|
|
|
|
void EreaseHandles(CDC* pDC) override;
|
|
|
|
|
|
|
|
|
|
|
|
void EndEdit(void) override;
|
|
|
|
|
|
void CancelAll(void) override;
|
|
|
|
|
|
BOOL IsCanCancelAll(void) override;
|
|
|
|
|
|
|
|
|
|
|
|
// =========================
|
|
|
|
|
|
// 核心操作:控制点管理
|
|
|
|
|
|
// =========================
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 初始化控制点
|
|
|
|
|
|
*/
|
|
|
|
|
|
void InitializeHandles(CCurveEx* pCurve);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 测试是否是控制点
|
|
|
|
|
|
*/
|
|
|
|
|
|
int HitTestHandle(CPoint point) override;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 删除控制点
|
|
|
|
|
|
*/
|
|
|
|
|
|
void DeleteHandle(int nIndex) override;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 添加控制点
|
|
|
|
|
|
*/
|
|
|
|
|
|
int AddHandle(CPoint point) override;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 判断是否可以添加控制点
|
|
|
|
|
|
*/
|
|
|
|
|
|
BOOL IsCanAddHandle(CPoint point, double* pl0 = nullptr) override;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 获取当前控制点曲线,指针仅在本次调用链内有效
|
|
|
|
|
|
*/
|
|
|
|
|
|
CCurveEx* GetControlCurve(void) override;
|
|
|
|
|
|
void GetXY(CCurveEx* pValue, int nIndex, dfPoint& point) override;
|
|
|
|
|
|
|
|
|
|
|
|
void AttachProcess(CPointList& oldPoints, CPointList& newPoints) override;
|
|
|
|
|
|
void DrawMoveLine(void) override;
|
|
|
|
|
|
void GetMarkCurve(void) override;
|
|
|
|
|
|
CPoint2D GetCDown() const override;
|
|
|
|
|
|
CPoint2D GetCLast() const override;
|
|
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
void OnDrawDragPreview();
|
|
|
|
|
|
void OnCalculateDragEffect(CPointList* pList);
|
|
|
|
|
|
void OnDragMove(int nIndex, CPoint2D pt);
|
|
|
|
|
|
int AddHandle(double l0);
|
|
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
|
SplineCurveModel m_splineCurveModel;
|
|
|
|
|
|
SplineDragState m_dragState;
|
|
|
|
|
|
std::unique_ptr<SplineDragPipeline> m_dragPipeline;
|
|
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<COne> m_pBakOne;
|
|
|
|
|
|
std::unique_ptr<HandleDrawer> m_handleDrawer;
|
|
|
|
|
|
std::unique_ptr<SplineEditorRenderer> m_renderer;
|
|
|
|
|
|
DWORD m_nHandleDrawMode;
|
|
|
|
|
|
std::unique_ptr<CCurveEx> m_tempControlCurve;
|
|
|
|
|
|
|
|
|
|
|
|
void DrawHandle(CXyDC* pDC, CCurveEx* pCurve);
|
|
|
|
|
|
void DrawHandlesByCDC(CDC* pDC, CCurveEx* pCurve);
|
|
|
|
|
|
void DrawSelectHandle(int nHandle);
|
|
|
|
|
|
CRect GetRangeWidthIndex(int nIndex);
|
|
|
|
|
|
CRect GetFirstNodeHandleRectFocus(CPoint point);
|
|
|
|
|
|
int HitTestHandle(CCurveEx* pValue, CPoint point);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// =========================
|
|
|
|
|
|
// 核心操作:鼠标交互
|
|
|
|
|
|
// =========================
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 是否是拖动状态
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool IsDragging(int nFlags) const;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 处理拖动
|
|
|
|
|
|
*/
|
|
|
|
|
|
int HandleMouseDrag(CXyDC* pXyDC, CPoint point);
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 处理 Hover
|
|
|
|
|
|
*/
|
|
|
|
|
|
int HandleMouseHover(CXyDC* pXyDC, CPoint point);
|
|
|
|
|
|
|
|
|
|
|
|
int AcquireDragHandle(CPoint point);
|
|
|
|
|
|
void ApplyDragAndRelease();
|
|
|
|
|
|
void RemoveCurrentHandle();
|
|
|
|
|
|
|
|
|
|
|
|
CSigmaDoc* GetDoc() override;
|
|
|
|
|
|
POSITION GetPos() override;
|
|
|
|
|
|
int GetHandleIndex() override;
|
|
|
|
|
|
void WriteModelToDocCurve() override;
|
|
|
|
|
|
void Invalidate() override;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* @brief 在渲染点中找与屏幕点最近的点,返回段索引,可选输出世界坐标
|
|
|
|
|
|
*/
|
|
|
|
|
|
int FindSegmentIndexAtScreenPoint(CPoint screenPoint, dfPoint* pOutWorldPoint);
|
|
|
|
|
|
};
|