ObjectARX自定义实体 My Custom Entity Embedded AcDb3dSolid not displaying after save and reopen in AutoCAD 2013

作者: admin 分类: C++,CAD,ObjectARX 发布时间: 2020-06-28 23:31

My Custom Entity Embedded AcDb3dSolid not displaying after save and reopen in AutoCAD 2013

by Fenton Webb

In AutoCAD 2013 and RealDWG 2013 based applications, ASM based entities (AcDb3dSolid, AcDbRegion, AcDbBody, AcDbSurface and classes derived from it) have their ASM data stored separately from the entity.  ASM based entities without an ObjectId were not saving their ASM data to a file.  For entities added to a BlockTableRecord this isn't a problem since they have ObjectIds.

The problem is with entities embedded within other custom entities; embedded entities do not have ObjectIds.

To address this, we have added a new protocol extension class:

class AcDbEmbeddedASMEntPropsPE : public AcRxObject

{

public:

  ACRX_DECLARE_MEMBERS(AcDbEmbeddedASMEntPropsPE);

  ACDB_PORT virtual void setIsEmbeddedEnt(AcDbObjectpObjbool bIsEmbedded = true);

};

 

This new protocol extension class is only present on the ASM based entity classes.  Custom entities that embed ASM based entities, should use this new protocol extension class to set a flag in the embedded ASM based entities indicating that they are embedded.  During a save, when this flag is set, the ASM data will be saved as part of the ASM based entity as was done prior to the 2013 release.

That takes care of the saving part.  BUT, for reading in, some additional checking must be done to determine if the host application's acdb19.dll has the new protocol extension class.  If it does not, then that host application cannot properly read in the saved data of the embedded ASM based entity, so the custom entity should return an ErrorStatus of Acad::eMakeMeAProxy from its dwgInFields() instead of calling dwgInFields() on the embedded ASM based entity.  This will cause the custom entity to become a proxy and the ASM based entity will remain as an unprocessed data blob within the proxy.

For dxfInFields(), there is no way to force the custom entity to be made a proxy, so the custom entity should return any non-eOk ErrorStatus instead of calling dxfInFields() on the embedded ASM based entity.  This will abort the dxfin operation. Here's a very simple example of a custom entity class with an embedded AcDb3dSolid that has the necessary changes to make use of the new protocol extension:

class EmbeddedSolidWrapper : public AcDbEntity

{

public:

  ACRX_DECLARE_MEMBERS(EmbeddedSolidWrapper);

  EmbeddedSolidWrapper();

  virtual ~EmbeddedSolidWrapper();

  virtual Acad::ErrorStatus   dwgInFields(AcDbDwgFilerfiler);

  virtual Acad::ErrorStatus   dwgOutFields(AcDbDwgFilerfilerconst;

  virtual Adesk::Boolean subWorldDraw(AcGiWorldDrawpWd);

  virtual Acad::ErrorStatus dxfInFields (AcDbDxfFilerpFiler);

  virtual Acad::ErrorStatus dxfOutFields(AcDbDxfFilerpFilerconst;

  void initializeSolid()

  {

    if (mpSolid) {

      mpSolid->setDatabaseDefaults();

      mpSolid->createSphere(400);

    }

  }

  static AcDbEmbeddedASMEntPropsPEgetEmbedPE();

private:

  AcDb3dSolidmpSolid;

};

AcDbEmbeddedASMEntPropsPEEmbeddedSolidWrapper::getEmbedPE()

{

  static AcDbEmbeddedASMEntPropsPEpPE = NULL;

  static bool bInit = true;

  // We only need to do this once per session because the protocol extension

  // is loaded at AcDb initialization, so if it isn't already present, it won't

  // be for the rest of the session.

  //

  if (bInit) {

    bInit = false;

    AcRxClasspCls = AcDb3dSolid::desc();

    // We get the AcDbEmbeddedASMEntityPropsPE AcRxClass object pointer from the

    // dictionary instead of using AcDbEmbeddedASMEntityPropsPE::desc() so that we

    // don't have a dependency on AcDbEmbeddedASMEntityPropsPE::desc() that would

    // prevent loading our app into a host application that does not have the

    // fixed acdb19.dll.

    //

    AcRxClasspPECls = AcRxClass::cast(acrxClassDictionary->at(L"AcDbEmbeddedASMEntPropsPE"));

    if (pCls && pPECls) {

      pPE = (AcDbEmbeddedASMEntPropsPE*)pCls->queryX(pPECls);

    }

  }

  return pPE;

}

ACRX_DXF_DEFINE_MEMBERS (EmbeddedSolidWrapper,

  AcDbEntity,

  AcDb::kDHL_CURRENT,

  AcDb::kMReleaseCurrent,

  AcDbProxyEntity::kNoOperation,

  EmbeddedSolidWrapper,

  EmbeddedSolidTest);

EmbeddedSolidWrapper::EmbeddedSolidWrapper()

{

  mpSolid = new AcDb3dSolid();

  AcDbEmbeddedASMEntPropsPEpPE = getEmbedPE();

  if (pPE && mpSolid)

    pPE->setIsEmbeddedEnt(mpSolid);

}

EmbeddedSolidWrapper::~EmbeddedSolidWrapper()

{

  if(mpSolid)

    delete mpSolid;

}

Acad::ErrorStatus EmbeddedSolidWrapper::dwgInFields(AcDbDwgFilerfiler)

{

  if (!mpSolid)

    return Acad::eOutOfMemory;

  // If the embeddedASM protocol extension is not present, then we cannot

  // read in from file because the necessary code is not present in acdb.

  // So, we return the error eMakeMeAProxy to force acdb to make us a proxy

  // and not require reading in the data on a per-class basis.

  //

  if (!getEmbedPE() && filer->filerType() == AcDb::kFileFiler)

    return Acad::eMakeMeProxy;

  assertWriteEnabled();

  Acad::ErrorStatus es = AcDbEntity::dwgInFields(filer);

  if (es != Acad::eOk)

    return es;

  es = mpSolid->dwgInFields(filer);

  return es;

}

Acad::ErrorStatus EmbeddedSolidWrapper::dwgOutFields(AcDbDwgFilerfilerconst

{

  if (!mpSolid)

    return Acad::eOutOfMemory;

  assertReadEnabled();

  Acad::ErrorStatus es = AcDbEntity::dwgOutFields(filer);

  if (es != Acad::eOk)

    return es;

  es = mpSolid->dwgOutFields(filer);

  return es;

}

Acad::ErrorStatus EmbeddedSolidWrapper::dxfInFields (AcDbDxfFilerfiler)\

{

  if (!mpSolid)

    return Acad::eOutOfMemory;

  // If the embeddedASM protocol extension is not present, then we cannot

  // read in from file because the necessary code is not present in acdb.

  // So, we return an error.  Unfortunately, we can't get dxf to turn us

  // into a proxy – any return other than eOk will just cause the dxf to

  // be aborted.

  //

  if (!getEmbedPE()) {

    filer->setError(Acad::eMissingDxfFieldL"Missing necessary ASM protocol extension");

    return Acad::eInvalidContext;

  }

  assertWriteEnabled();

  Acad::ErrorStatus es = AcDbEntity::dxfInFields(filer);

  if (es != Acad::eOk)

    return es;

  if (filer->atEmbeddedObjectStart())

    mpSolid->dxfInFields(filer);

  else

    filer->setError(Acad::eMissingDxfFieldL"Missing expected embeddedObject marker");

  return filer->filerStatus();

}

Acad::ErrorStatus EmbeddedSolidWrapper::dxfOutFields(AcDbDxfFilerfilerconst

{

  if (!mpSolid)

    return Acad::eOutOfMemory;

  assertReadEnabled();

  Acad::ErrorStatus es = AcDbEntity::dxfOutFields(filer);

  if (es != Acad::eOk)

    return es;

  filer->writeEmbeddedObjectStart();

  return mpSolid->dxfOutFields(filer);

}

Adesk::Boolean EmbeddedSolidWrapper::subWorldDraw(AcGiWorldDrawpWd)

{

  pWd->geometry().draw(mpSolid);

  return Adesk::kTrue;

}

void creatCustomEnt()

{

  // If we don't have the necessary support to save the ASM data,

  // then don't allow creatining one of our entities.

  //

  if (!EmbeddedSolidWrapper::getEmbedPE())

    return;

  EmbeddedSolidWrapperpTestSolid = new EmbeddedSolidWrapper();

  pTestSolid->initializeSolid();

  AcDbBlockTablepBlockTable = NULL;

  Acad::ErrorStatus es = acdbHostApplicationServices()->workingDatabase()->getBlockTable(pBlockTableAcDb::kForRead);

  if (es != Acad::eOk)

    return;

  AcDbBlockTableRecordpRecord = NULL;

  es = pBlockTable->getAt(ACDB_MODEL_SPACEpRecordAcDb::kForWrite);

  if (es != Acad::eOk)

    return;

  pBlockTable->close();

  AcDbObjectId retId;

  es = pRecord->appendAcDbEntity(retIdpTestSolid);

  pRecord->close();

  if (es != Acad::eOk) {

    return;

}

  pTestSolid->close();

}

Posted at 02:19 PM in 2013, AutoCAD, Fenton Webb, ObjectARX | Permalink

转载自:https://adndevblog.typepad.com/autocad/2012/08/my-custom-entity-embedded-acdb3dsolid-not-displaying-after-save-and-reopen-in-autocad-2013.html

如果觉得我的文章对您有用,请随意赞赏。您的支持将鼓励我继续创作!

发表评论

标签云