How to prevent explode on a block reference?

By Gopinath Taget

The EXPLODE command works on a Block reference by deepcloning the contents of the referenced block in kDcExplode context, and finally erasing the block reference itself. So, one solution to prevent explode is to exclude the block’s contents from deepClone operation and un-erase the block reference after the explode command ends. A similar approach could be found in this blog post. By modifying the code in that blog post, we can disable EXPLODE command for block references (sample attached). The sample code below works as follows:

1. Issue DISABLEEXPLODE command. This will ask you to select block references you want to prevent exploding. The referenced blocks are then iterated, and the IDs of contents of the block are remembered in a list.

2. In the editor reactor’s beginDeepClone() notification, the above collected ids are placed in the objectId map. This will trick AutoCAD into thinking they have already been copied, and so will not clone them. These fake ids are removed during beginDeepCloneXlation().

3. At the commandEnded() notification for explode command, we un-erase the block reference.

You can enable exploding with ENABLEEXPLODE command. Here is the relevant code:

Header of the reactor:

/////////////////////////////////////////////

// AcEditorReactor reactors.

 

#if !defined(ARX__REDITORREACTOR_H__20020123_132949)

#define ARX__REDITORREACTOR_H__20020123_132949

 

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

 

#include "dbidmap.h"

#include "aced.h"

 

 

class ADCGEditorRctr : public AcEditorReactor

{

public:

 

 // Constructor / Destructor

ADCGEditorRctr(const bool autoInitAndRelease = true);

 virtual ~ADCGEditorRctr();

 

 //{{AFX_ARX_METHODS(ADCGEditorRctr)

 virtual void commandEnded(const TCHAR* cmdStr);

 virtual void beginDeepCloneXlation(AcDbIdMapping& x0,

  Acad::ErrorStatus* x1);

 virtual void beginDeepClone(AcDbDatabase* pTo,

  AcDbIdMapping& x0);

 //}}AFX_ARX_METHODS

 

  // other

 

public:

 

  Adesk::Boolean addObject(const AcDbObjectId& id);

  Adesk::Boolean removeObject(const AcDbObjectId& id);

  Adesk::Boolean addBlRefId(const AcDbObjectId& id);

  Adesk::Boolean removeBlRefId(const AcDbObjectId& id);

 

private:

 // Auto initialization and release flag.

 bool m_autoInitAndRelease;

AcDbObjectIdArray m_ids;

AcDbObjectIdArray m_blRefIds;

 bool dcActiveDuringExplode;

};

 

#endif // !defined(ARX__REDITORREACTOR_H__20020123_132949)

 

Implementation of the reactor:

/////////////////////////////////////////////    // AcEditorReactor reactors.         #include "StdAfx.h"    
#include "rEditorReactor.h"         ADCGEditorRctr::ADCGEditorRctr(const bool autoInitAndRelease)    {     m_autoInitAndRelease = autoInitAndRelease;     if (m_autoInitAndRelease)      if (NULL != acedEditor)       acedEditor->addReactor(this);      else       m_autoInitAndRelease = false;          dcActiveDuringExplode = false;    }         ADCGEditorRctr::~ADCGEditorRctr()    {     if (m_autoInitAndRelease)      if (NULL != acedEditor)       acedEditor->removeReactor(this);    }         //    // Overrides    //         void ADCGEditorRctr::beginDeepClone(AcDbDatabase* pTo,      AcDbIdMapping& x0)    {           // Only for Explode Context      if(  AcDb::kDcExplode != x0.deepCloneContext() )        return;           // Mock up a fake clone: place our ids in the map      for(int i=0; iclose();       }      }     }          dcActiveDuringExplode = false;    }

Implementation of commands:

//-------------------------------------------------------------------    //----- acrxEntryPoint.h    //-------------------------------------------------------------------    #include "StdAfx.h"    #include "resource.h"    #include "rEditorReactor.h"         //-------------------------------------------------------------------    #define szRDS _RXST("asdk")         //-------------------------------------------------------------------    //----- ObjectARX EntryPoint              class CDisableExplodeApp : public AcRxArxApp     {          static ADCGEditorRctr gEditorRctr;              public:     CDisableExplodeApp () : 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) ;           // TODO: Add your initialization code here           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           return (retCode) ;     }          virtual void RegisterServerComponents () {     }         public:          // - asdkDisableExplode._DISABLECOPY command (do not rename)     static void asdkDisableExplode_DISABLECOPY(void)     {       ads_name ss;            if(acedSSGet(NULL,NULL,NULL,NULL,ss)==RTNORM) {      ads_name ent;      AcDbObjectId id;      long length;      if(acedSSLength(ss, &length)==RTNORM) {        for(int i=0; inewIterator(pIter))            {            for(; !pIter->done(); pIter->step())            {             AcDbObjectId entId;             pIter->getEntityId(entId);             gEditorRctr.addObject(entId);            }            delete pIter;            }           pBTR->close();            }            pObj->close();           }          }        }         }       }      }            acedSSFree(ss);          }                   public:          // - asdkDisableExplode._ENABLEEXPLODE command (do not rename)     static void asdkDisableExplode_ENABLEEXPLODE(void)     {      ads_name ss;           //Select block references      if(acedSSGet(NULL,NULL,NULL,NULL,ss)==RTNORM)       {       ads_name ent;       AcDbObjectId id;       long length;       if(acedSSLength(ss, &length)==RTNORM) {         for(int i=0; iobjectId());                 AcDbObjectId blockId =              pBlRef->blockTableRecord();            //Open the blockId for read            AcDbBlockTableRecordPointer pBTR(             blockId, AcDb::kForRead);            AcDbBlockTableRecordIterator *pIter;            if(Acad::eOk == pBTR->newIterator(pIter))            {            for(; !pIter->done(); pIter->step())            {             AcDbObjectId entId;             pIter->getEntityId(entId);             gEditorRctr.removeObject(entId);                 }            delete pIter;            }           pBTR->close();            }            pObj->close();           }          }        }         }       }      }            acedSSFree(ss);      }              } ;              ADCGEditorRctr CDisableExplodeApp::gEditorRctr;              //-----------------------------------------------------------------------------    IMPLEMENT_ARX_ENTRYPOINT(CDisableExplodeApp)         ACED_ARXCOMMAND_ENTRY_AUTO(CDisableExplodeApp, asdkDisableExplode,     _DISABLECOPY, DISABLECOPY, ACRX_CMD_TRANSPARENT, NULL)    ACED_ARXCOMMAND_ENTRY_AUTO(CDisableExplodeApp, asdkDisableExplode,     _ENABLECOPY, ENABLECOPY, ACRX_CMD_TRANSPARENT, NULL)    ACED_ARXCOMMAND_ENTRY_AUTO(CDisableExplodeApp, asdkDisableExplode,     _DISABLEEXPLODE, DISABLEEXPLODE, ACRX_CMD_TRANSPARENT, NULL)    ACED_ARXCOMMAND_ENTRY_AUTO(CDisableExplodeApp, asdkDisableExplode,     _ENABLEEXPLODE, ENABLEEXPLODE, ACRX_CMD_TRANSPARENT, NULL)

Comments

One response to “How to prevent explode on a block reference?”

  1. Hi Gopinath,
    Is this possible with the .Net API?

Leave a Reply

Discover more from Autodesk Developer Blog

Subscribe now to keep reading and get access to the full archive.

Continue reading