[转]使用 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);
}