[转]使用 AcDbMultiModesGripPE 夹点上下文菜单

篇一:使用 AcDbMultiModesGripPE 夹点上下文菜单

作者 Balaji Ramamoorthy

原链接 http://adndevblog.typepad.com/autocad/2013/12/grip-context-menu-using-acdbmultimodesgrippe.html

这是一个使用 AcDbMultiModesGripPE 为自定义实体实现夹点上下文菜单的示例项目。它演示了使用多模式夹点来获取与自定义实体相关的输入。

为了让它变得有趣,我创建了一个类似于树的自定义实体。它的夹点上下文菜单显示两种模式 - “春季”和“冬季”。创建树自定义实体后,当夹点变热时将出现上下文菜单。选择“春天”将确保树有叶子,选择“冬天”将使树脱落叶子。

在这种情况下,模式与夹点编辑无关,并且由于我们不希望夹点在单击时开始拖动,因此将模式的动作类型设置为命令。选择模式后,AutoCAD 将调用该命令。在命令实现中,我们确保树根据选择的模式更新其显示。我希望在当前模式旁边有一个复选标记,但 API 目前没有办法做到这一点,我们的工程团队为它创建了一个愿望清单项目。

这是相关代码,完整的示例项目可以从下面的链接下载:

示例项目下载 multimodegrip_simplesample

图片展示

// Header
// TreeMultiModesGripPE.h
 
#pragma once
 
#include "dbMultiModesGrip.h"
 
class AdskTreeMultiModesGripPE : public AcDbMultiModesGripPE
{
private:
    static AcDbMultiModesGripPE::GripMode _currentGripMode;
    static AcDbObjectId _lastModifiedEntId;
 
public:
    ACRX_DECLARE_MEMBERS(AdskTreeMultiModesGripPE);
 
    AdskTreeMultiModesGripPE();
    ~AdskTreeMultiModesGripPE();
    static AcDbObjectId getLastModifiedEntId();
 
    virtual bool getGripModes(AcDbEntity* pThis, 
                              AcDbGripData* pGripData, 
                              AcArray<GripMode>& modes, 
                              unsigned int& curMode) const;
 
    virtual unsigned int mode(AcDbEntity* pThis, 
                              AcDbGripData* pGripData) const;
 
    virtual AcDbMultiModesGripPE::GripMode modeEx(
                AcDbEntity* pThis, 
                AcDbGripData* pGripData) const;
 
    virtual bool setMode(
                AcDbEntity* pThis, 
                AcDbGripData* pGripData, 
                unsigned int newMode);
 
    virtual AcDbMultiModesGripPE::GripType gripType(
            AcDbEntity* pThis, AcDbGripData* pGripData) const;
 
    virtual void reset(AcDbEntity* pThis);
};
 
 
// Implementation
// TreeMultiModesGripPE.cpp
 
#include "StdAfx.h"
#include "dbMultiModesGrip.h"
#include "TreeMultiModesGripPE.h"
#include "AdskTree.h"
 
ACRX_CONS_DEFINE_MEMBERS(AdskTreeMultiModesGripPE, 
                         AcDbMultiModesGripPE, 1);
 
AcDbMultiModesGripPE::GripMode 
                    AdskTreeMultiModesGripPE::_currentGripMode;
 
AcDbObjectId AdskTreeMultiModesGripPE::_lastModifiedEntId 
                                        = AcDbObjectId::kNull;
 
AdskTreeMultiModesGripPE::AdskTreeMultiModesGripPE()
{
    // Default grip mode
    _currentGripMode.Mode = 0;
    _currentGripMode.DisplayString = AcString("Spring");
}
 
AdskTreeMultiModesGripPE::~AdskTreeMultiModesGripPE()
{
}
 
// Returns the possible grip modes
bool AdskTreeMultiModesGripPE::getGripModes(
                                AcDbEntity* pThis, 
                                AcDbGripData* pGripData, 
                                AcArray<GripMode>& modes, 
                                unsigned int& curMode) const 
{
    GripMode gripMode1;
    gripMode1.Mode = 0;
    gripMode1.DisplayString = AcString("Spring");
    gripMode1.ActionType = GripActionType::kCommand;
    gripMode1.CommandString = AcString("ModeSwitchCmd ");
 
    modes.append(gripMode1);
 
    GripMode gripMode2;
    gripMode2.Mode = 1;
    gripMode2.DisplayString = AcString("Winter");
    gripMode2.ActionType = GripActionType::kCommand;
    gripMode2.CommandString = AcString("ModeSwitchCmd ");
 
    modes.append(gripMode2);
 
    curMode = 0;
 
    return true;
}
 
// Gets the current mode identifier.
unsigned int AdskTreeMultiModesGripPE::mode(
                                AcDbEntity* pThis, 
                                AcDbGripData* pGripData) const
{
    return _currentGripMode.Mode; 
}
 
// Return the current mode.
AcDbMultiModesGripPE::GripMode 
    AdskTreeMultiModesGripPE::modeEx(
            AcDbEntity* pThis, AcDbGripData* pGripData) const 
{
    return _currentGripMode;
}
 
// Sets the current mode.
bool AdskTreeMultiModesGripPE::setMode(
            AcDbEntity* pThis, 
            AcDbGripData* pGripData, 
            unsigned int newMode)
{
    _currentGripMode.Mode = newMode;
 
    AcDbObjectId entId = pThis->id();
    AdskTree *pTree = AdskTree::cast(pThis);
 
    switch(newMode)
    {
        case 0:
            acutPrintf(ACRX_T("\nSpring season, growing leaves !"));
 
            _currentGripMode.DisplayString = AcString("Spring"); 
            pTree->setSeason(AcString("Spring"));
            // For graphics update
            _lastModifiedEntId = pTree->id();
 
            break;
 
        case 1:
            acutPrintf(ACRX_T("\nWinter season, shedding leaves !"));
 
            _currentGripMode.DisplayString = AcString("Winter");
            pTree->setSeason(AcString("Winter"));
            // For graphics update
            _lastModifiedEntId = pTree->id();
 
            break;
    }
    return true;
}
 
// Gets the grip type of a given grip.
AcDbMultiModesGripPE::GripType 
AdskTreeMultiModesGripPE::gripType(
            AcDbEntity* pThis, AcDbGripData* pGripData) const 
{
    return AcDbMultiModesGripPE::GripType::kPrimary;  
}
 
// To retrieve the objectId of the tree entity 
// for graphics update
AcDbObjectId AdskTreeMultiModesGripPE::getLastModifiedEntId()
{
    return _lastModifiedEntId;
}
 
// resets current mode to default 
void AdskTreeMultiModesGripPE::reset(AcDbEntity* pThis)
{
    _currentGripMode.Mode = 0;
    _currentGripMode.DisplayString = AcString("Spring");
}
 
 
 
// Header for custom entity
// AsdkTree.h
 
#pragma once
 
#ifdef MULTIMODEGRIPSIMPLESAMPLE_MODULE
#define DLLIMPEXP __declspec(dllexport)
#else
#define DLLIMPEXP
#endif
 
//-----------------------------------------------------------------------------
#include "dbmain.h"
 
//-----------------------------------------------------------------------------
class DLLIMPEXP AdskTree : public AcDbEntity 
{
 
public:
    ACRX_DECLARE_MEMBERS(AdskTree) ;
 
protected:
    static Adesk::UInt32 kCurrentVersionNumber ;
 
private:
    AcGePoint3d _basePoint;
    AcString _season;
 
    void BuildSubTree(
        AcGeLineSeg3d *pMainBranch, 
        int level, 
        AcGiWorldDraw *mode, 
        Adesk::Boolean flower = Adesk::kFalse);
 
public:
    AdskTree () ;
    virtual ~AdskTree () ;
 
    // Sets the season status
    void setSeason(AcString season);
 
    // Sets the insertion point
    void setBasePoint(AcGePoint3d basePoint);
 
    //----- AcDbObject protocols
    //- Dwg Filing protocol
    virtual Acad::ErrorStatus 
                    dwgOutFields (AcDbDwgFiler *pFiler) const ;
    virtual Acad::ErrorStatus 
                        dwgInFields (AcDbDwgFiler *pFiler) ;
 
    //----- AcDbEntity protocols
    //- Graphics protocol
protected:
    virtual Adesk::Boolean subWorldDraw (AcGiWorldDraw *mode) ;
    virtual Acad::ErrorStatus 
                    subTransformBy(const AcGeMatrix3d& xform);
 
    //- Grip points protocol
    virtual Acad::ErrorStatus subGetGripPoints (
                                AcDbGripDataPtrArray &grips, 
                                const double curViewUnitSize, 
                                const int gripSize, 
                                const AcGeVector3d &curViewDir, 
                                const int bitflags) const ;
 
    virtual Acad::ErrorStatus subMoveGripPointsAt (
        const AcDbVoidPtrArray &gripAppData, 
        const AcGeVector3d &offset, const int bitflags) ;
};
 
#ifdef MULTIMODEGRIPSIMPLESAMPLE_MODULE
ACDB_REGISTER_OBJECT_ENTRY_AUTO(AdskTree)
#endif
 
 
// Implementation of the custom entity
// AdskTree.cpp 
 
#include "StdAfx.h"
#include "AdskTree.h"
 
Adesk::UInt32 AdskTree::kCurrentVersionNumber =1 ;
 
ACRX_DXF_DEFINE_MEMBERS (
    AdskTree, AcDbEntity,
    AcDb::kDHL_CURRENT, AcDb::kMReleaseCurrent, 
    AcDbProxyEntity::kNoOperation, ADSKTREE,
ADSKMULTIMODEGRIPSIMPLESAMPLEAPP
|Product Desc:     A description for your object
|Company:          Your company name
|WEB Address:      Your company WEB site address
)
 
AdskTree::AdskTree () : AcDbEntity () 
{
    _basePoint = AcGePoint3d::kOrigin; 
    _season = AcString("Spring");
}
 
AdskTree::~AdskTree () 
{
}
 
//----- AcDbObject protocols
//- Dwg Filing protocol
Acad::ErrorStatus AdskTree::dwgOutFields(AcDbDwgFiler *pFiler) 
                                                    const {
    assertReadEnabled () ;
    //----- Save parent class information first.
    Acad::ErrorStatus es =AcDbEntity::dwgOutFields (pFiler) ;
    if ( es != Acad::eOk )
        return (es) ;
    //----- Object version number needs to be saved first
    if ( (es =pFiler->writeUInt32 
            (AdskTree::kCurrentVersionNumber)) != Acad::eOk )
        return (es) ;
 
    //----- Output params
    pFiler->writePoint3d(_basePoint);
 
    return (pFiler->filerStatus ()) ;
}
 
Acad::ErrorStatus AdskTree::dwgInFields(AcDbDwgFiler *pFiler)
{
    assertWriteEnabled () ;
    //----- Read parent class information first.
    Acad::ErrorStatus es =AcDbEntity::dwgInFields (pFiler) ;
    if ( es != Acad::eOk )
        return (es) ;
    //----- Object version number needs to be read first
    Adesk::UInt32 version =0 ;
    if ( (es =pFiler->readUInt32 (&version)) != Acad::eOk )
        return (es) ;
    if ( version > AdskTree::kCurrentVersionNumber )
        return (Acad::eMakeMeProxy) ;
 
    //----- Read params
    pFiler->readPoint3d(&_basePoint);
 
    return (pFiler->filerStatus ()) ;
}
 
 
//----- AcDbEntity protocols
Adesk::Boolean AdskTree::subWorldDraw (AcGiWorldDraw *mode) 
{
    assertReadEnabled () ;
 
    AcGeLineSeg3d mainBranch(
        _basePoint, 
        AcGePoint3d(_basePoint.x,_basePoint.y+10.0,_basePoint.z));
 
    AcDbLine *pLine1 = new AcDbLine(
            mainBranch.startPoint(), mainBranch.endPoint());
    mode->geometry().draw(pLine1);
    delete pLine1;
 
    int level = 0;
    BuildSubTree(&mainBranch, level, mode);
 
    return (AcDbEntity::subWorldDraw (mode)) ;
}
 
void AdskTree::setBasePoint(AcGePoint3d basePoint)
{
    _basePoint = basePoint;
}
 
void AdskTree::setSeason(AcString season)
{
    _season = season;
}
 
void AdskTree::BuildSubTree(AcGeLineSeg3d *pMainBranch, 
                            int level, 
                            AcGiWorldDraw *mode, 
                            Adesk::Boolean flower)
{
    if(mode->isDragging() && level >= 2)
        return; // Light weight for dragging
 
    if(level >= 3)
    {
        if(_season == AcString("Spring"))
        {
            AcDbCircle *pLeaf = new AcDbCircle(
                pMainBranch->endPoint(), 
                AcGeVector3d::kZAxis, 
                pMainBranch->length() * 0.2); 
 
            if(flower)
                pLeaf->setColorIndex(1);
            else
                pLeaf->setColorIndex(2); 
            mode->geometry().draw(pLeaf);
            delete pLeaf;
        }
        return;
    }
 
    int subLevel = level + 1;
    AcGePoint3d sp = AcGePoint3d::kOrigin;
    AcGePoint3d ep = AcGePoint3d::kOrigin;
    AcGeInterval intrvl;
    pMainBranch->getInterval(intrvl, sp, ep);
    double len = pMainBranch->length();
 
    AcGePoint3dArray pts;
    pMainBranch->getSamplePoints(5, pts);
 
    const double PI = 3.1415926535897932385;
    int cnt = 1;
    if(level == 0)
        cnt = 2;
    for(;cnt < 5; cnt++)
    {
        AcGeVector3d dir = pMainBranch->direction().normalize(); 
        AcGePoint3d refPt1 = pts[cnt];
 
        if(cnt == 4)
        {
            AcGePoint3d refPt2 = refPt1 + (len * 0.5) * dir;
 
            AcGeLineSeg3d branch1(refPt1, refPt2);
            AcDbLine *pBranchLine1 = new AcDbLine(refPt1, refPt2);
            mode->geometry().draw(pBranchLine1);
            delete pBranchLine1;
            BuildSubTree(&branch1, subLevel, mode, Adesk::kTrue);
        }
        else
        {
            AcGePoint3d refPt2 = refPt1 + 
                (len * 0.5) * dir.transformBy(
                AcGeMatrix3d::rotation(    PI * 0.25, 
                                        AcGeVector3d::kZAxis, 
                                        refPt1
                                       ));
 
            AcGeLineSeg3d branch1(refPt1, refPt2);
            AcDbLine *pBranchLine1 = new AcDbLine(refPt1, refPt2);
            mode->geometry().draw(pBranchLine1);
            delete pBranchLine1;
            BuildSubTree(&branch1, subLevel, mode);
 
            dir = pMainBranch->direction().normalize(); 
            refPt2 = refPt1 + (len * 0.5) * 
                dir.transformBy(AcGeMatrix3d::rotation(
                -PI * 0.25, AcGeVector3d::kZAxis, refPt1));
 
            AcGeLineSeg3d branch2(refPt1, refPt2);
            AcDbLine *pBranchLine2 = new AcDbLine(refPt1, refPt2);
            mode->geometry().draw(pBranchLine2);
            delete pBranchLine2;
            BuildSubTree(&branch2, subLevel, mode);
        }
    }
}
 
Acad::ErrorStatus AdskTree::subGetGripPoints ( 
    AcDbGripDataPtrArray &grips, 
    const double curViewUnitSize, 
    const int gripSize,  
    const AcGeVector3d &curViewDir, 
    const int bitflags ) const 
{
    assertReadEnabled () ;
 
    AcDbGripData *pGripData = new AcDbGripData();
    pGripData->setGripPoint(_basePoint);
    grips.append(pGripData);
 
    return Acad::eOk;
}
 
Acad::ErrorStatus AdskTree::subMoveGripPointsAt (
    const AcDbVoidPtrArray &gripAppData, 
    const AcGeVector3d &offset,
    const int bitflags) 
{
    assertWriteEnabled () ;
 
    _basePoint += offset;
 
    return Acad::eOk;
}
 
Acad::ErrorStatus AdskTree::subTransformBy(
                                    const AcGeMatrix3d& xform)
{
    assertWriteEnabled();
    _basePoint.transformBy(xform);
    return (AcDbEntity::subTransformBy(xform));
}
 
 
 
// acrxEntryPoint.cpp
// Usage 
 
#include "resource.h"
#include "AdskTree.h"
 
#include "stdafx.h"
#include "dbMultiModesGrip.h"
#include "TreeMultiModesGripPE.h"
 
static AdskTreeMultiModesGripPE *pMyMultiModeGrips = NULL;
 
#define szRDS _RXST("Adsk")
 
//----- ObjectARX EntryPoint
class CMultiModeGripSimpleSampleApp : public AcRxArxApp {
 
public:
    CMultiModeGripSimpleSampleApp () : AcRxArxApp () {}
 
    virtual AcRx::AppRetCode On_kInitAppMsg (void *pkt) {
        // TODO: Load dependencies here
 
        // You *must* call On_kInitAppMsg here
        AcRx::AppRetCode retCode 
                            =AcRxArxApp::On_kInitAppMsg(pkt) ;
 
        AdskTreeMultiModesGripPE::rxInit();
        AdskTree::rxInit();
        acrxBuildClassHierarchy();
 
        // TODO: Add your initialization code here
        if(pMyMultiModeGrips == NULL)
        {
            pMyMultiModeGrips = new AdskTreeMultiModesGripPE();
            AdskTree::desc()->addX(
                                AcDbMultiModesGripPE::desc(), 
                                pMyMultiModeGrips);
        }
 
        return (retCode) ;
    }
 
    virtual AcRx::AppRetCode On_kUnloadAppMsg (void *pkt) {
        // TODO: Add your code here
 
        // You *must* call On_kUnloadAppMsg here
        AcRx::AppRetCode retCode 
                        = AcRxArxApp::On_kUnloadAppMsg (pkt) ;
 
        // TODO: Unload dependencies here
        if(pMyMultiModeGrips != NULL)
        {
            delete pMyMultiModeGrips;
            pMyMultiModeGrips = NULL;
        }
        return (retCode) ;
    }
 
    virtual void RegisterServerComponents () {
    }
 
 
    // "Tree" command to create a tree
    static void AdskMultiModeGripSimpleSampleTREE(void)
    {
        ads_point pt;
        if (RTNORM != acedGetPoint(
                    NULL, L"\nSelect tree base point: ", pt))
            return;
 
        AcGePoint3d insertionPt = asPnt3d( pt );
 
        AdskTree *pTree = new AdskTree();
        pTree->setDatabaseDefaults();
        pTree->setBasePoint(insertionPt);
        PostToDb(pTree);
    }
 
    // Add the entity to DB
    static Acad::ErrorStatus PostToDb(AcDbEntity* pEnt)
    {
        AcDbDatabase *pDb 
            = acdbHostApplicationServices()->workingDatabase();
        AcDbObjectId objId;
 
        Acad::ErrorStatus      es;
        AcDbBlockTable*        pBlockTable;
        AcDbBlockTableRecord*  pSpaceRecord;
 
        pDb->getBlockTable(pBlockTable, AcDb::kForRead);
        pBlockTable->getAt( ACDB_MODEL_SPACE, 
                            pSpaceRecord, 
                            AcDb::kForWrite);
        es = pSpaceRecord->appendAcDbEntity(objId, pEnt);
        es = pEnt->close();
        es = pSpaceRecord->close();
        es = pBlockTable->close();
 
        return es;
    }
 
    // Command to update the graphics after the 
    // grip mode was changed. 
    // This will ensure a graphics is in sync with the
    // mode selected 
    static void AdskMultiModeGripSimpleSampleModeSwitchCmd(void)
    {
        AcDbObjectId entId 
            = AdskTreeMultiModesGripPE::getLastModifiedEntId(); 
 
        AcApDocument *pActiveDoc 
                        = acDocManager->mdiActiveDocument();
        AcDbDatabase *pDb = pActiveDoc->database();
 
        if(entId.isNull())
            return;
 
        AcDbEntity* pEnt = NULL;
        acdbOpenAcDbEntity(pEnt, entId, AcDb::kForWrite);
        pEnt->recordGraphicsModified();
        pEnt->close();
        acedUpdateDisplay();
    }
} ;
 
//-----------------------------------------------------------------------------
IMPLEMENT_ARX_ENTRYPOINT(CMultiModeGripSimpleSampleApp)
 
ACED_ARXCOMMAND_ENTRY_AUTO(CMultiModeGripSimpleSampleApp, 
                           AdskMultiModeGripSimpleSample, 
                           TREE, 
                           TREE, 
                           ACRX_CMD_TRANSPARENT, 
                           NULL)
ACED_ARXCOMMAND_ENTRY_AUTO(CMultiModeGripSimpleSampleApp, 
                           AdskMultiModeGripSimpleSample, 
                           ModeSwitchCmd, 
                           ModeSwitchCmd, 
                           ACRX_CMD_TRANSPARENT,
                           NULL) 

篇二:使自定义实体 GripMode 感知

作者 Balaji Ramamoorthy

原链接 http://adndevblog.typepad.com/autocad/2014/02/making-custom-entity-gripmode-aware.html

这是一个实现嵌入式多段线的自定义实体的示例项目。 自定义实体通过实现“subMoveGripPointsAt”方法 GripMode 来启用对嵌入式实体进行操作的 GripMode。 在附件项目中,自定义实体的夹点模式与嵌入式多段线的夹点模式相同,但如果您的自定义实体有多个嵌入式实体,您可以扩展实现以在相似的线上为自定义实体公开更多的 GripModes。

这是相关代码的一部分,示例项目可以从这里下载:

示例项目下载 multimodegrip_embeddedpolyline

//ContainerEntity.h 
 
// Custom grip app data to identify the grips 
class MyGripAppData : public AcDbObject
{
public:
   ACRX_DECLARE_MEMBERS(MyGripAppData) ;
 
   Adesk::UInt32 m_GripNumber;
 
   MyGripAppData(){ m_GripNumber = 0; }
 
   MyGripAppData(int gripNumber){ m_GripNumber = gripNumber; }
};
 
// Container custom entity that embeds a polyline
class DLLIMPEXP AdskContainerEntity : public AcDbEntity 
{
 
public:
    ACRX_DECLARE_MEMBERS(AdskContainerEntity) ;
 
protected:
    static Adesk::UInt32 kCurrentVersionNumber ;
 
public:
    AdskContainerEntity () ;
    virtual ~AdskContainerEntity () ;
 
    AcDbPolyline *m_pPolyline; // Embedded Polyline
 
    // GripMode for use in "subMoveGripPointsAt" 
    // which is GripMode aware. 
    Adesk::UInt32 m_pCurrentGripMode; 
 
    // To remove or to add after depending on the GripMode
    Adesk::UInt32 m_iVertexNumber;    
 
    // Coordinates of the new vertex point to 
    // add if the GripMode is "Add Vertex"
    AcGePoint2d m_NewVertexCoord;     
 
protected:
    virtual Adesk::Boolean subWorldDraw (AcGiWorldDraw *mode) ;
    virtual Acad::ErrorStatus subTransformBy
                                (const AcGeMatrix3d& xform);
 
    Acad::ErrorStatus dwgInFields (AcDbDwgFiler *pFiler);
    Acad::ErrorStatus dwgOutFields (AcDbDwgFiler *pFiler) const;
 
    //- Grip points protocol
    virtual Acad::ErrorStatus subGetGripPoints (
                                AcDbGripDataPtrArray &grips, 
                                const double curViewUnitSize, 
                                const int gripSize, 
                                const AcGeVector3d &curViewDir, 
                                const int bitflags) const ;
 
    virtual Acad::ErrorStatus subMoveGripPointsAt(
                            const AcDbVoidPtrArray& gripAppData, 
                            const AcGeVector3d& offset, 
                            const int bitflags);
};
 
 
// ContainerEntity.cpp : Implementation of AdskContainerEntity
 
AdskContainerEntity::AdskContainerEntity () : AcDbEntity () 
{
    m_pPolyline = NULL;
    m_pCurrentGripMode = 0;
    m_iVertexNumber = 0;
}
 
AdskContainerEntity::~AdskContainerEntity () 
{
    if (m_pPolyline)
    {
        delete m_pPolyline;
        m_pPolyline = 0;
    }
}
 
Acad::ErrorStatus AdskContainerEntity::dwgInFields
                                        (AcDbDwgFiler *pFiler) 
{
    assertWriteEnabled () ;
 
    Acad::ErrorStatus es = AcDbEntity::dwgInFields (pFiler) ;
    if ( es != Acad::eOk )
        return (es) ;
 
    Adesk::UInt32 version =0 ;
    if ( (es =pFiler->readUInt32 (&version)) != Acad::eOk )
        return (es) ;
 
    if ( version > AdskContainerEntity::kCurrentVersionNumber)
        return (Acad::eMakeMeProxy) ;
 
    // Read params
    Adesk::UInt32 numVerts = 0;
    pFiler->readUInt32(&numVerts);
 
    AcGePoint3dArray points;
    for(int i = 0; i < numVerts; i++)
    {
        AcGePoint3d pt;
        pFiler->readPoint3d(&pt);
        points.append(pt);
    }
 
    if (m_pPolyline)
    {
        delete m_pPolyline;
        m_pPolyline = 0;
    }
 
    m_pPolyline = new AcDbPolyline(numVerts);         
    m_pPolyline->setDatabaseDefaults();
 
    for(int i = 0; i < numVerts; i++)
    {
        AcGePoint3d pt(points[i]);
        m_pPolyline->addVertexAt(i, AcGePoint2d(pt.x, pt.y));
    }
 
    return (pFiler->filerStatus ()) ;
}
 
 
Acad::ErrorStatus AdskContainerEntity::dwgOutFields 
                                (AcDbDwgFiler *pFiler) const 
{
    assertReadEnabled () ;
 
    Acad::ErrorStatus es = AcDbEntity::dwgOutFields (pFiler) ;
    if ( es != Acad::eOk )
        return (es) ;
 
    if ( (es =pFiler->writeUInt32 
        (AdskContainerEntity::kCurrentVersionNumber)) 
                                                != Acad::eOk )
        return (es) ;
 
    // Output params
    if(m_pPolyline)
    {
        Adesk::UInt32 numVerts = m_pPolyline->numVerts();
 
        pFiler->writeUInt32(numVerts);
 
        for(int i = 0; i < numVerts; i++)
        {
            AcGePoint3d pt;
            m_pPolyline->getPointAt(i, pt);
            pFiler->writePoint3d(pt); 
        }
    }
 
    return (pFiler->filerStatus ()) ;
}
 
Adesk::Boolean AdskContainerEntity::subWorldDraw 
                                        (AcGiWorldDraw *mode) 
{
    assertReadEnabled () ;
 
    // Draw the polyline
    if(m_pPolyline)
        mode->geometry().pline (*m_pPolyline);
 
    return (AcDbEntity::subWorldDraw (mode)) ;
}
 
Acad::ErrorStatus AdskContainerEntity::subGetGripPoints(
                     AcDbGripDataPtrArray &grips, 
                     const double curViewUnitSize, 
                     const int gripSize,  
                     const AcGeVector3d &curViewDir, 
                     const int bitflags ) const 
{
    assertReadEnabled () ;
 
    // Return the vertices of the embedded polyline as 
    // grip points
    if(m_pPolyline)
    {
        Adesk::UInt32 numVerts = m_pPolyline->numVerts();
        for(int i = 0; i < numVerts; i++)
        {
            AcGePoint3d pt;
            m_pPolyline->getPointAt(i, pt);
 
            AcDbGripData * pGripData = new AcDbGripData();
            pGripData->setAppData(new MyGripAppData(i));
            pGripData->setGripPoint(pt); 
            grips.append(pGripData);
        }
    }
    return Acad::eOk;
}
 
// Grip mode aware implementation of subMoveGripPointsAt
// Depending on the current grip mode, it stretches / adds or
// removes vertices from the embedded polyline
 Acad::ErrorStatus AdskContainerEntity::subMoveGripPointsAt(
                         const AcDbVoidPtrArray& gripAppData, 
                         const AcGeVector3d& offset, 
                         const int bitflags)
 {
    assertWriteEnabled () ;
 
    if(m_pPolyline)
    {
        switch(m_pCurrentGripMode)
        {
            case 0: // Stretch 
            {
                for (int i = 0; i < gripAppData.length(); i++)
                {
                    MyGripAppData *pMyGripAppData 
                        = static_cast<MyGripAppData *>
                                        (gripAppData.at(i));
                    if(pMyGripAppData != NULL)
                    {
                        int num = pMyGripAppData->m_GripNumber;
 
                        AcGePoint3d pt;
                        m_pPolyline->getPointAt(num, pt);
 
                        AcGeMatrix3d mat 
                                    = AcGeMatrix3d::kIdentity;
                        mat = mat.translation(offset);
 
                        pt = pt.transformBy(mat);
 
                        m_pPolyline->setPointAt(
                                num, AcGePoint2d(pt.x, pt.y));
                    }
                }
                break;
            }
 
            case 1: // Add Vertex
            {
                m_pPolyline->addVertexAt(
                    m_iVertexNumber+1, 
                    AcGePoint2d(m_NewVertexCoord.x, 
                                m_NewVertexCoord.y)
                                        );
 
                // Reset to default GripMode
                m_pCurrentGripMode = 0; 
                break;
            }
 
            case 2: // Remove Vertex
            {
                if(m_iVertexNumber < m_pPolyline->numVerts())
                    m_pPolyline->removeVertexAt(m_iVertexNumber); 
 
                // Reset to default GripMode
                m_pCurrentGripMode = 0; 
                break;
            }
        }
    }
    return Acad::eOk;
 }
 
Acad::ErrorStatus AdskContainerEntity::subTransformBy(const AcGeMatrix3d& xform)
{
    assertWriteEnabled();
 
    // Transform the polyline
    if(m_pPolyline)
        m_pPolyline->transformBy(xform);
 
    return (AcDbEntity::subTransformBy(xform));
}
 
 
// ContainerEntityMultiModesGripPE.h
 
#include "dbMultiModesGrip.h"
 
// GripModePE implementation for the custom entity
// This exposes 3 gripmodes. 
// Stretch vertex
// Add Vertex
// Remove Vertex
class AdskContainerEntityMultiModesGripPE : public AcDbMultiModesGripPE
{
private:
    static AcDbMultiModesGripPE::GripMode _currentGripMode;
 
public:
    ACRX_DECLARE_MEMBERS(AdskContainerEntityMultiModesGripPE);
 
    AdskContainerEntityMultiModesGripPE();
    ~AdskContainerEntityMultiModesGripPE();
 
    static AcDbObjectId getLastModifiedEntId();
    static Adesk::UInt32 getVertexNumberToAdd();
 
    virtual bool getGripModes(    AcDbEntity* pThis, 
                                AcDbGripData* pGripData, 
                                AcArray<GripMode>& modes, 
                                unsigned int& curMode
                             ) const;
 
    virtual unsigned int mode(    AcDbEntity* pThis, 
                                AcDbGripData* pGripData
                             ) const;
 
    virtual AcDbMultiModesGripPE::GripMode modeEx(
            AcDbEntity* pThis, AcDbGripData* pGripData) const;
 
    virtual bool setMode(    AcDbEntity* pThis, 
                            AcDbGripData* pGripData, 
                            unsigned int newMode);
 
    virtual AcDbMultiModesGripPE::GripType gripType(
            AcDbEntity* pThis, AcDbGripData* pGripData) const;
 
    virtual void reset(AcDbEntity* pThis);
};
 
// ContainerEntityMultiModesGripPE.cpp
// GripModePE implementation for the custom entity
// This exposes 3 gripmodes. 
// Stretch vertex
// Add Vertex
// Remove Vertex
 
AdskContainerEntityMultiModesGripPE::
                        AdskContainerEntityMultiModesGripPE()
{
    // Default grip mode : Stretch Vertex
    _currentGripMode.Mode = 0;
    _currentGripMode.DisplayString = AcString("Stretch Vertex");
}
 
AdskContainerEntityMultiModesGripPE::
                        ~AdskContainerEntityMultiModesGripPE()
{
}
 
// Returns the possible grip modes
// Stretch vertex
// Add Vertex
// Remove Vertex
bool AdskContainerEntityMultiModesGripPE::getGripModes(
                                AcDbEntity* pThis, 
                                AcDbGripData* pGripData, 
                                AcArray<GripMode>& modes, 
                                unsigned int& curMode) const 
{
    // "Stretch Vertex" mode
    GripMode gripMode1;
    gripMode1.Mode = 0;
    gripMode1.DisplayString = AcString("Stretch Vertex");
    gripMode1.ActionType = AcDbMultiModesGripPE::kDragOn;
 
    modes.append(gripMode1);
 
    // "Add Vertex" mode
    GripMode gripMode2;
    gripMode2.Mode = 1;
    gripMode2.DisplayString = AcString("Add Vertex");
    gripMode2.ActionType = AcDbMultiModesGripPE::kImmediate;
 
    modes.append(gripMode2);
 
    // "Remove Vertex" mode to be available only if there are 
    // more than 2 vertices in the polyline.
    AdskContainerEntity *pContEnt 
                           = AdskContainerEntity::cast(pThis);
    if(pContEnt->m_pPolyline != NULL)
    {
        if(pContEnt->m_pPolyline->numVerts() > 2)
        {
            GripMode gripMode3;
            gripMode3.Mode = 2;
            gripMode3.DisplayString = AcString("Remove Vertex");
            gripMode3.ActionType 
                        = AcDbMultiModesGripPE::kImmediate;
 
            modes.append(gripMode3);
        }
    }
 
    // "Stretch Vertex" is the current mode
    curMode = 0;
 
    return true;
}
 
// Gets the current mode identifier.
unsigned int AdskContainerEntityMultiModesGripPE::mode(
            AcDbEntity* pThis, AcDbGripData* pGripData) const
{
    return _currentGripMode.Mode; 
}
 
// Return the current mode.
AcDbMultiModesGripPE::GripMode 
AdskContainerEntityMultiModesGripPE::modeEx(
            AcDbEntity* pThis, AcDbGripData* pGripData) const 
{
    return _currentGripMode;
}
 
// Sets the current mode.
bool AdskContainerEntityMultiModesGripPE::setMode(
                AcDbEntity* pThis, 
                AcDbGripData* pGripData, unsigned int newMode)
{
    bool retStatus = true;
 
    _currentGripMode.Mode = newMode;
 
    AcDbObjectId entId = pThis->id();
    AdskContainerEntity *pContEnt 
                            = AdskContainerEntity::cast(pThis);
    pContEnt->m_pCurrentGripMode = newMode;
 
    switch(newMode)
    {
        case 0:
        {
            _currentGripMode.DisplayString 
                                 = AcString("Stretch Vertex"); 
            break;
        }
 
        case 1:
        {
            _currentGripMode.DisplayString 
                                     = AcString("Add Vertex");
 
            // Create a temporary copy of the embedded Polyline for jigging purposes
            AcDbPolyline *pPolyTemp = AcDbPolyline::cast(pContEnt->m_pPolyline->clone());
 
            MyGripAppData *pMyGripAppData = static_cast<MyGripAppData *>(pGripData->appData());
            if(pMyGripAppData != NULL)
            {
                // Adding vertex requires a Jig
                PolyLineVertexAddJig *pPolyAddVertedJig 
                    = new PolyLineVertexAddJig(
                      pPolyTemp, pMyGripAppData->m_GripNumber);
                AcEdJig::DragStatus status = pPolyAddVertedJig->doIt();
                if(status != AcEdJig::kCancel)
                {
                    pContEnt->m_iVertexNumber 
                                = pMyGripAppData->m_GripNumber;
                    pContEnt->m_NewVertexCoord 
                           = pPolyAddVertedJig->AddedVertex();
                }
                else
                {
                    // Cancel setting the GripMode as the 
                    // Jig was canceled 
                    retStatus = false; 
                }
 
                delete pPolyAddVertedJig;
            }
 
            break;
        }
 
        case 2:
        {
            _currentGripMode.DisplayString 
                                  = AcString("Remove Vertex");
 
            MyGripAppData *pMyGripAppData 
                = static_cast<MyGripAppData *>(
                                        pGripData->appData());
            if(pMyGripAppData != NULL)
            {
                pContEnt->m_iVertexNumber 
                               = pMyGripAppData->m_GripNumber;
            }
            break;
        }
    }
 
    return retStatus;
}
 
// Gets the grip type of a given grip.
AcDbMultiModesGripPE::GripType 
    AdskContainerEntityMultiModesGripPE::gripType(
            AcDbEntity* pThis, AcDbGripData* pGripData) const 
{
    return AcDbMultiModesGripPE::kPrimary;  
}
 
// resets current mode to default 
void AdskContainerEntityMultiModesGripPE::reset(AcDbEntity* pThis)
{
    _currentGripMode.Mode = 0;
    _currentGripMode.DisplayString = AcString("Stretch Vertex");
}
 
 
// PolyLineVertexAddJig.h
// Polyline jig for adding a new vertex
 
class PolyLineVertexAddJig : public AcEdJig
{
public:
    PolyLineVertexAddJig();
    ~PolyLineVertexAddJig();
    PolyLineVertexAddJig(
              AcDbPolyline *pPoly, Adesk::UInt32 vertexToAdd);
 
    AcEdJig::DragStatus doIt();
    virtual DragStatus sampler();
    virtual Adesk::Boolean update();
 
    AcGePoint2d AddedVertex();
 
    virtual AcDbEntity* entity() const;
 
private:
    AcDbPolyline *m_pPoly;
    Adesk::UInt32 m_nVertexToAdd;
 
    AcGePoint3d vertexPointTemp;
    AcGePoint3d vertexPoint;
 
    Adesk::Boolean addNew;
};
 
// PolyLineVertexAddJig.cpp
 
#include "StdAfx.h"
#include "PolyLineVertexAddJig.h"
 
PolyLineVertexAddJig::PolyLineVertexAddJig()
{
    m_pPoly = NULL;
    vertexPointTemp = AcGePoint3d::kOrigin;
    vertexPoint = AcGePoint3d::kOrigin;
    addNew = Adesk::kTrue;
}
 
PolyLineVertexAddJig::PolyLineVertexAddJig(
               AcDbPolyline *pPoly, Adesk::UInt32 vertexToAdd)
{
    // Polyline to jig
    m_pPoly = pPoly;
 
    // Index to mark the position of the new vertex
    m_nVertexToAdd = vertexToAdd;
 
    // To keep track of the coordinates during jigging
    vertexPointTemp = AcGePoint3d::kOrigin;
    vertexPoint = AcGePoint3d::kOrigin;
 
    // To know if we already added a vertex during jigging
    addNew = Adesk::kTrue;
}
 
PolyLineVertexAddJig::~PolyLineVertexAddJig()
{
    // Cleanup
    if(m_pPoly)
    {
        delete m_pPoly;
        m_pPoly = NULL;
    }
}
 
// Start the jig
AcEdJig::DragStatus PolyLineVertexAddJig::doIt()
{
    AcEdJig::DragStatus stat = AcEdJig::kCancel;
 
    if(m_pPoly)
    {
        setDispPrompt(ACRX_T("\n Select vertex point : "));
        stat = drag();
    }
 
    return stat;
}
 
AcEdJig::DragStatus PolyLineVertexAddJig::sampler()
{
    DragStatus stat;
    setUserInputControls((UserInputControls)
        (AcEdJig::kAccept3dCoordinates
         | AcEdJig::kNoNegativeResponseAccepted
         | AcEdJig::kNoZeroResponseAccepted));
 
    // Get a point input for the coordinates
    stat = acquirePoint(vertexPoint);
    if (vertexPointTemp != vertexPoint)
        vertexPointTemp = vertexPoint;
    else if (stat == AcEdJig::kNormal)
        return AcEdJig::kNoChange;
 
    return stat;
}
 
Adesk::Boolean PolyLineVertexAddJig::update()
{
    if(m_pPoly)
    {
        if(addNew)
        {// First time, add a new vertex
            m_pPoly->addVertexAt(
                m_nVertexToAdd+1, 
                AcGePoint2d(vertexPoint.x, vertexPoint.y));
        }
        else
        { // Update the coordinates of the 
          // previously added vertex
            if(m_nVertexToAdd < m_pPoly->numVerts())
            {
                m_pPoly->setPointAt(
                    m_nVertexToAdd+1, 
                    AcGePoint2d(vertexPoint.x, vertexPoint.y));
            }
        }
    }
 
    if(addNew)
        addNew = Adesk::kFalse;
 
    return Adesk::kTrue;
}
 
AcDbEntity* PolyLineVertexAddJig::entity() const
{
    return m_pPoly;
}
 
// To get the coordinates of the vertex added by this jig
AcGePoint2d PolyLineVertexAddJig::AddedVertex()
{
    return AcGePoint2d(vertexPoint.x, vertexPoint.y);
}
posted @ 2022-03-27 12:29  edata  阅读(361)  评论(0编辑  收藏  举报