Hi,
I'm developing an application which process a block diagram built with lines and blocks.
Blocks are inserted as AcDbBlockReference.
For each block I need to define, easily, an input point and an output point.
When the block is inserted as an AcdbBlockReference, I need to set also the scale factor to scale the insertion.
So, for each block, using the block editor I had defined 2 attributes "IN" and "OUT"
During the processing of the enities I can build the structure fast, using ssget.
Now I need to extend the acdbBlockreference class to implement:
-the deepclone for copy & paste
-the override for the snappoints
When I derive the class AcDbBlockReference, I can't use Attributes on the block, thus I need to put something else on the block definition to represent these two points.
(I can't use fixed points because I have to resize the block. The user, who create blocks must be able to add these points easily)
How can I do? Have I to add subentities on the block like a litte circle?
Thank you for your help.
Have a good day.
Massimo
You haven't explained why you are deriving a new class from AcDbBlockReference, but doing so is almost certainly a bad idea and very likely the wrong way to solve the problem.
I need to derive from AcDbBlockReference, in order to:
-manage copy and paste overriding the deepclone method of the acdbblockreference.
-manage the snap point of the block overriding the getosnappoint method.
I've already implemented the copy paste using the deepCloneObjects function, but I need to implement this feature with CTRL+C and CTRL+V and with the possibility to copy from one layer and paste to another layer.
Now I can't override the snap points of the blockreference, because I can't override the method getsnappoint without deriving from the acdbblockreference.
Someone adviced me to use the snappointoverrule, but I think it's a workaround and the need to implement the copy & paste push me to derive my custom class fromacdbblockreference..
Thank you for your time.
Regards
Massimo
Sorry, I don't understand what you mean by "manage copy and paste" and "manage the snap point". In any case, it sounds like you have decided to create a derived class despite advice to the contrary.
I have something similar (block digram for wiring), so comments :).
1. use pure AcDbBlockReference
2. create data for in\out points in block coordinates (for block "name". i hope you have unique blocks with their own in\out points)
AcGeMatrix3d mat(pBlock->blockTransform()); mat.invert(); ... acedGetPoint(NULL,_T("\nSet point: "),asDblArray(pt)); acdbUcs2Wcs(asDblArray(pt), asDblArray(pt), false); pt.transformBy(mat); // now point is in block coordinates ...
3. create your own snap (my piece of getOsnapInfo)
getOsnapInfo(...) { ... assert( pickedObject->isKindOf( AcDbBlockReference::desc() )); AcDbBlockReference * pBlock = (AcDbBlockReference*)pickedObject; ACHAR *BlockName; AcDbDynBlockReference dynBlk(pBlock->objectId()); if (dynBlk.isDynamicBlock()) { AcDbBlockTableRecordPointer pBTR(dynBlk.dynamicBlockTableRecord(),AcDb::kForRead); if (pBTR.openStatus() == Acad::eOk) { pBTR->getName(BlockName); pBTR->close(); } } else { AcDbBlockTableRecordPointer pBTR(pBlock->blockTableRecord(),AcDb::kForRead); pBTR->getName(BlockName); pBTR->close(); } BLOCKPOINTS_DATA pCurData = ptsData->getDataForBlock(BlockName); // my way to get points for needed block AcGeMatrix3d mat(pBlock->blockTransform()); ... onePoint.transformBy(mat); // now my snap point is in WCS coords
snapPoints.append(onePoint); // add ALL in\out points to snapPoints array
}
that's enough if you don't want stretch "lines" when block moves. )))
but if you want stetch "lines", you have to use great quantity of different reactors.
Hi,
thank you for your accurate answer.
I'm looking at the snap point..
I found this
http://adndevblog.typepad.com/autocad/2012/12/how-to-implement-extension-osnap-for-an-entity.html
but I added the registration of my CustomOsnapInfo in this way
//Register protocol extension object (customOsnapInfo)
BlockOSnapInfo::rxInit();
acrxBuildClassHierarchy();
AcDbEntity::desc()->addX(BlockOSnapInfo::desc(), &_BlockOSnapInfo);
acdbCustomOsnapManager()->addCustomOsnapMode(&_CustomOsnapMode);
in the AcRx::AppRetCode On_kInitAppMsg (void *pkt) of the ARX acrxEntryPoint..
I put a break point on the getOsnapInfo() function and I moved with the mouse curson on some of my objects, but the execution doesn't pass through the breakpoint.
Could I have put the osnap registration in the wrong module?
Thank you for your time.
Massimo
Hi, I finally figured out with the custom osnap mode, but I have a question.
I decided to use the osnap point on my block references to force the user to pick only input or output point fo a block.
But, to use the custom osnap the user has to activate this mode with an input string everytime.. this is annoying.
How can I force to turn on this snap mode everytime a user is drawing an acdbline and snap to a blockreference?
Thank you for your help.
Best regards
Massimo
i use this code inside MY command
{ int osmod = acdbHostApplicationServices()->workingAppSysvars()->osmode(); acdbHostApplicationServices()->workingAppSysvars()->setOsmode(0); Acad::ErrorStatus es = acdbCustomOsnapManager()->activateOsnapMode(_T("MY_OSMODE")); // drawing "line" acdbHostApplicationServices()->workingAppSysvars()->setOsmode(osmod); }
IMHO, it's not a good idea to turn off all of users snaps when hi just want to create a line or polyline. but you can use AcEditorReactor.
commandWillStart - check if command is "line", if true, turn off all snaps and turn on yours
commandFailed, commandCancelled, commandEnded - if you modified snaps, set em back to previous state