Hello.
I'm trying to use function deepClone() to copy some elements on my drawing. Fragment of wrong code is:
if(AcTxtSize != DefaultTSSize) { // setting layer of the improper text entities to ERROR
AcDbObjectPointer<AcDbText> pText2;
AcDbIdMapping idMap;
idMap.setDestDb(pAC_DB);
pText->deepClone(pText, pText2, idMap, true);
pText->setLayer(_T("_ERROR"), true);
++acc;
}
How I should write this fragment of code to work properly (make second text entity visible on the drawing)?
Solved! Go to Solution.
Hi,
Please refer to object arx documentation "Deep clone basics":
"
The AcDbObject::deepClone() and AcDbObject::wblockClone() functions should not be called directly on a custom object in application code. They are only called as part of a chain from a higher-level cloning operation.
"
I suppose (I may be wrong) this is true for native AutoCAD objects too.
you should use AcDbDatabase::deepCloneObjects() instead.
this should give something like:
if(AcTxtSize != DefaultTSSize) { AcDbIdMapping idmap; AcDbObjectIdArray oids; objectIds.append(mytextid); //mytextid is pText object Id if (mytextid.database()->deepCloneObjects(oids, pText->ownerId(), idMap) == Acad::eOk) { AcDbIdPair idPair; idPair.setKey(mytextid); if (idMap.compute(idPair)){ AcDbSmartObjectPointer<AcDbText> myclone(idPair.value(),AcDb::kForWrite);//requires including dbobjptr2.h if (myclone.openStatus()==Acad::eOk){ //modify your cloned text here } } } }
I haven't tested it (event not compiled) but event if it does not work as is, it should gives you a clue on how to do.
I hope this helps.
I have one another question: when I'm trying to do as you wrote, function don't create a copy and I have an error:
eWasOpenForRead = 82
I think all pointers are closed - before addition of this command everything worked properly. I have no idea what is problem here.
Hi,
I guess the AcDbText you're trying to clone is opened for read while deepCloneObjects is called. In the sample code I've posted, I see [...]deepCloneObjects(oids, pText->ownerId(), idMap)[...] which, in my mind, means the pText object is still opened for read (at least).
Have you tried to get the owner id in a separate variable then close the pText object and finally call deepCloneObjects with the stored owner id as second argument?
(sorry if the code I've posted did not work, as I said, I haven't tested it)
I tried do it as it is in this fragment of code:
AcDbObjectId pTextOwnerId = pText->ownerId();
pObj->close();
pText->close();
pActualStRcd->close();
if(AcTxtSize != DefaultTSSize) { // setting layer of the improper text entities to ERROR
AcDbIdMapping idMap;
AcDbObjectIdArray oIds;
oIds.append(TextId);
Acad::ErrorStatus CopyError = pAC_DB->deepCloneObjects(oIds, pTextOwnerId, idMap, true);
if(CopyError == Acad::eOk) {
AcDbIdPair idPair;
idPair.setKey(TextId);
if(idMap.compute(idPair)){
AcDbObjectPointer<AcDbText> pClonedText(idPair.value(), AcDb::kForWrite);
if(pClonedText.openStatus() == Acad::eOk){
pClonedText->setLayer(_T("_ERROR"), true);
}
pClonedText->downgradeOpen();
pClonedText->close();
}
} else {
ads_printf(_T("\nERROR: %d\n"), CopyError);
}
oIds.removeLast();
++acc;
}
I have this error (82 = eWasOpenForRead) also when I try to copy all text objects to AcDbObjectIdArray oIds and then copy all of them by one function call.
Hi,
I see that you passed true as last argument of deepCloneObjects, which means you defer oid xlation.
you have to ask this method to process xlation right now, meaning you have to set deferXlation parameter to false.
I'm not sure this cause the issue but it's wrong anyway.
you might defer oid xlation in some cases where you have to call deepCloneObjects multiple times but xlation has to be done at least once at the end, (see `AcDbDatabase::deepCloneObjects` documentation for further information).
In your case, if you want to clone several text objects in model space, you have to call deepCloneObjects once, filling the oid array with all text oids and passing deferXlation to false.
If you don't process xlation, your clone objects will be in a weird state where their references to owned or pointed objects still reference their source object reference.
If this not fix the issue, you'll have to figure out which object in the database remains opened for read while calling deepCloneObjects...