ObjectARX
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

deepClone() function

9 REPLIES 9
SOLVED
Reply
Message 1 of 10
julie7
2362 Views, 9 Replies

deepClone() function

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)?

Tags (1)
9 REPLIES 9
Message 2 of 10
loic.jourdan
in reply to: julie7

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.

 

----
20-20 CAD / 20-20 Technologies
Message 3 of 10
julie7
in reply to: loic.jourdan

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.

Message 4 of 10
loic.jourdan
in reply to: julie7

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)

----
20-20 CAD / 20-20 Technologies
Message 5 of 10
julie7
in reply to: loic.jourdan

I understood a idea, so your post was very helpful. Thanks.

Message 6 of 10
julie7
in reply to: loic.jourdan

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;

}

Message 7 of 10
loic.jourdan
in reply to: julie7

You still have the same issue with this code? CopyError variable still get eWasOpenForRead value?

----
20-20 CAD / 20-20 Technologies
Message 8 of 10
julie7
in reply to: loic.jourdan

I still have this problem. I'm searching what's wrong in this code but I don't understand this now.

Message 9 of 10
julie7
in reply to: julie7

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.

Message 10 of 10
loic.jourdan
in reply to: julie7

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...

----
20-20 CAD / 20-20 Technologies

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report

”Boost