覆盖 deepClone() 函数
本节中的示例代码是 的默认行为的近似值。深度克隆操作有两个主要阶段:deepClone()
在此示例的克隆阶段,使用特定类型的文件管理器将有关旧对象的信息复制到新对象,以写出对象并将其读回。文件管理器跟踪主对象拥有的对象,以便也可以复制它们。 完成克隆阶段
以下示例代码演示了这些步骤:
Acad::ErrorStatus
AsdkPoly::subDeepClone(AcDbObject* pOwner,
AcDbObject*& pClonedObject,
AcDbIdMapping& idMap,
Adesk::Boolean isPrimary) const
{
// You should always pass back pClonedObject == NULL
// if, for any reason, you do not actually clone it
// during this call. The caller should pass it in
// as NULL, but to be safe, we set it here as well.
//
pClonedObject = NULL;
// If this object is in the idMap and is already
// cloned, then return.
//
bool isPrim = false;
if (isPrimary)
isPrim = true;
AcDbIdPair idPair(objectId(), (AcDbObjectId)NULL,
false, isPrim);
if (idMap.compute(idPair) && (idPair.value() != NULL))
return Acad::eOk;
// Create the clone
//
AsdkPoly *pClone = (AsdkPoly*)isA()->create();
if (pClone != NULL)
pClonedObject = pClone; // set the return value
else
return Acad::eOutOfMemory;
AcDbDeepCloneFiler filer;
dwgOut(&filer);
filer.seek(0L, AcDb::kSeekFromStart);
pClone->dwgIn(&filer);
bool bOwnerXlated = false;
if (isPrimary)
{
AcDbBlockTableRecord *pBTR =
AcDbBlockTableRecord::cast(pOwner);
if (pBTR != NULL)
{
pBTR->appendAcDbEntity(pClone);
bOwnerXlated = true;
}
else
{
pOwner->database()->addAcDbObject(pClone);
}
} else {
pOwner->database()->addAcDbObject(pClone);
pClone->setOwnerId(pOwner->objectId());
bOwnerXlated = true;
}
// This must be called for all newly created objects
// in deepClone. It is turned off by endDeepClone()
// after it has translated the references to their
// new values.
//
pClone->setAcDbObjectIdsInFlux();
pClone->disableUndoRecording(true);
// Add the new information to the idMap. We can use
// the idPair started above.
//
idPair.setValue(pClonedObject->objectId());
idPair.setIsCloned(Adesk::kTrue);
idPair.setIsOwnerXlated(bOwnerXlated);
idMap.assign(idPair);
// Using the filer list created above, find and clone
// any owned objects.
//
AcDbObjectId id;
while (filer.getNextOwnedObject(id)) {
AcDbObject *pSubObject;
AcDbObject *pClonedSubObject;
// Some object's references may be set to NULL,
// so don't try to clone them.
//
if (id == NULL)
continue;
// Open the object and clone it. Note that we now
// set "isPrimary" to kFalse here because the object
// is being cloned, not as part of the primary set,
// but because it is owned by something in the
// primary set.
//
acdbOpenAcDbObject(pSubObject, id, AcDb::kForRead);
pClonedSubObject = NULL;
pSubObject->deepClone(pClonedObject,
pClonedSubObject,
idMap, Adesk::kFalse);
// If this is a kDcInsert context, the objects
// may be "cheapCloned". In this case, they are
// "moved" instead of cloned. The result is that
// pSubObject and pClonedSubObject will point to
// the same object. So, we only want to close
// pSubObject if it really is a different object
// than its clone.
//
if (pSubObject != pClonedSubObject)
pSubObject->close();
// The pSubObject may either already have been
// cloned, or for some reason has chosen not to be
// cloned. In that case, the returned pointer will
// be NULL. Otherwise, since we have no immediate
// use for it now, we can close the clone.
//
if (pClonedSubObject != NULL)
pClonedSubObject->close();
}
// Leave pClonedObject open for the caller
//
return Acad::eOk;
}
父主题: |
|Archiver|CAD开发者社区
( 苏ICP备2022047690号-1 苏公网安备32011402011833)
GMT+8, 2025-11-1 10:02
Powered by Discuz! X3.4
Copyright © 2001-2021, Tencent Cloud.