Copy/Paste on custom entity

Copy/Paste on custom entity

alex_b
Advocate Advocate
1,422 Views
24 Replies
Message 1 of 25

Copy/Paste on custom entity

alex_b
Advocate
Advocate
Hi
class XEl public AcDbEntity {
.....
AcGePoint3d ;
AcDbHandle;//handle to another custom entity (another class)
......
}

Now, when we perform a Copy/Paste sequence to another drawing, the XEl::worldDraw() is called, it tries to open the entity pointed to by the member handle and of course errors out.
The curious part is that the error is Acad::eWasErased when in fact the entity is nonexistent.
Any good explanation?
BTW, the solution would be the same (create a new entity and point the handle at it) but I'd like to know if there is a way do distinguish between an erased entity and a nonexistent one.

TIA

alex
0 Likes
1,423 Views
24 Replies
Replies (24)
Message 2 of 25

Anonymous
Not applicable
It's also possible that the handle might be valid in the target drawing, but
it isn't for the same object that it was in the source drawing. So, even if
you do determine that the handle is valid, you still might not be getting
what you expect.

You're better off using an ObjectId since they are not database specific as
handles are.

wrote in message news:5934071@discussion.autodesk.com...
Hi
class XEl public AcDbEntity {
.....
AcGePoint3d ;
AcDbHandle;//handle to another custom entity (another class)
......
}

Now, when we perform a Copy/Paste sequence to another drawing, the
XEl::worldDraw() is called, it tries to open the entity pointed to by the
member handle and of course errors out.
The curious part is that the error is Acad::eWasErased when in fact the
entity is nonexistent.
Any good explanation?
BTW, the solution would be the same (create a new entity and point the
handle at it) but I'd like to know if there is a way do distinguish between
an erased entity and a nonexistent one.

TIA

alex
0 Likes
Message 3 of 25

alex_b
Advocate
Advocate
Art
The question was, why did we get Acad::eWasErased. The database pasted to was new and clean, so the handle was not valid and surely not erased.
About using ObjectId, good suggestion, will implement.

BTW, how do we append an entity to the current space (model or paper). I mean w/o explicitly using ACDB_MODEL_SPACE etc.?

I see I am flooding the group with questions, we are in the middle of the prog writing and questions arise faster than the answers. Sorry.

Thanks

alex
0 Likes
Message 4 of 25

Anonymous
Not applicable
Are you sure it was eWasErased and not eWasPermanentlyErased? It should
return eWasPermanentlyErased which indicates that the object does not exist.

There is no shortcut to append to the current space. You must figure out
what BlockTableRecord is the current space and then append to it. If the
drawing is the current drawing in the editor, then you should be able to use
the AcDbLayoutManager::getActiveLayoutBTRId() to get the objectId of the
current layout's BlockTableRecord.

wrote in message news:5934122@discussion.autodesk.com...
Art
The question was, why did we get Acad::eWasErased. The database pasted to
was new and clean, so the handle was not valid and surely not erased.
About using ObjectId, good suggestion, will implement.

BTW, how do we append an entity to the current space (model or paper). I
mean w/o explicitly using ACDB_MODEL_SPACE etc.?

I see I am flooding the group with questions, we are in the middle of the
prog writing and questions arise faster than the answers. Sorry.

Thanks

alex
0 Likes
Message 5 of 25

alex_b
Advocate
Advocate
Art
I double checked, and it indeed is eWasErased.
code from helper routine:
//try to open the entity from handle and get data from it
pCurDb = acdbHostApplicationServices()->workingDatabase();
es = pCurDb->getAcDbObjectId(objId, Adesk::kFalse, handle, 0);//ObjectId from handle
if (es == Acad::eWasErased)//it errors here
{
MSG("getBaselineEnt():getAcDbObjectId: eWasErased\n");
return NULL;
}
....

Now this is strange and I agree that it should have been eWasPermanentlyErased. The problem now is that if we could know the pasting was ocurring in another drawing (not the one the Copy was performed in) ,we could find a sollution, but if we are getting the wrong error code.....
As the secondary entity, the one whose handle is missing - rased or nonexistent - is vital, we have to create a valid one anyway, which raises another problem:
The above attempt to open the secondary entity is made in the main entity's worldDraw() method. Now, if the secondary entity is missing, creating it involves user input. The question is, is it possible and/or advisable to remain in worldDraw long enough to get user's response? I seem to have read somewhere that worldDraw has to return as fast as possible.

As about appending to the current layout, I'm not sure I understood you. Is there some code snippet, maybe in the samples?
Thanks

alex
0 Likes
Message 6 of 25

Anonymous
Not applicable
Alex:

Your dependent entity needs to be referenced via object ID, and filed
during filing operations using the appropriate reference type to avoid this
whole problem. You can use AcDbDatabase::currentSpaceId() to get the
current BTR. 🙂
--
Owen Wengerd
President, ManuSoft <>
VP Americas, CADLock, Inc. <>
0 Likes
Message 7 of 25

alex_b
Advocate
Advocate
Owen

The secondary object is referenced by many instances of the main object. It should be cloned only when pasting an instance of the main object to another db. Except this, the new copy, if made in the same db, is quite happy with the current handle (or object ID).

Thanks

alex
0 Likes
Message 8 of 25

Anonymous
Not applicable
There's also acedGetCurrentSpaceId()

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm

"Art Cooney" wrote in message news:5934132@discussion.autodesk.com...
Are you sure it was eWasErased and not eWasPermanentlyErased? It should
return eWasPermanentlyErased which indicates that the object does not exist.

There is no shortcut to append to the current space. You must figure out
what BlockTableRecord is the current space and then append to it. If the
drawing is the current drawing in the editor, then you should be able to use
the AcDbLayoutManager::getActiveLayoutBTRId() to get the objectId of the
current layout's BlockTableRecord.

wrote in message news:5934122@discussion.autodesk.com...
Art
The question was, why did we get Acad::eWasErased. The database pasted to
was new and clean, so the handle was not valid and surely not erased.
About using ObjectId, good suggestion, will implement.

BTW, how do we append an entity to the current space (model or paper). I
mean w/o explicitly using ACDB_MODEL_SPACE etc.?

I see I am flooding the group with questions, we are in the middle of the
prog writing and questions arise faster than the answers. Sorry.

Thanks

alex
0 Likes
Message 9 of 25

Anonymous
Not applicable
"Owen Wengerd" wrote

>> You can use AcDbDatabase::currentSpaceId() to get the
current BTR. 🙂 <<

Owen - You might want to see this recent post here:

BUG: AcDbDatabase::currentSpaceId() returns incorrect value


--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm

"Owen Wengerd" wrote in message news:5934180@discussion.autodesk.com...
Alex:

Your dependent entity needs to be referenced via object ID, and filed
during filing operations using the appropriate reference type to avoid this
whole problem. You can use AcDbDatabase::currentSpaceId() to get the
current BTR. 🙂
--
Owen Wengerd
President, ManuSoft <>
VP Americas, CADLock, Inc. <>
0 Likes
Message 10 of 25

Anonymous
Not applicable
Just a note about appending to the 'current' space, do not rely on
AcDbDatabase::currentSpaceId() returning the correct value, if the
AcDbDatabase is not the current working database.

--
http://www.caddzone.com

AcadXTabs: MDI Document Tabs for AutoCAD 2009
Supporting AutoCAD 2000 through 2009

http://www.acadxtabs.com

Introducing AcadXTabs 2010:
http://www.caddzone.com/acadxtabs/AcadXTabs2010.htm

wrote in message news:5934122@discussion.autodesk.com...
Art
The question was, why did we get Acad::eWasErased. The database pasted to was new and clean, so the handle was not valid and surely not erased.
About using ObjectId, good suggestion, will implement.

BTW, how do we append an entity to the current space (model or paper). I mean w/o explicitly using ACDB_MODEL_SPACE etc.?

I see I am flooding the group with questions, we are in the middle of the prog writing and questions arise faster than the answers. Sorry.

Thanks

alex
0 Likes
Message 11 of 25

Anonymous
Not applicable
Alex:

> The secondary object is referenced by many instances of the main object.

Then it should be either a SoftPointerId or a HardPointerId, depending on
whether the referencing object works correctly with a non-existent
reference. 🙂
--
Owen Wengerd
President, ManuSoft <>
VP Americas, CADLock, Inc. <>
0 Likes
Message 12 of 25

Anonymous
Not applicable
Tony:

I do recall that post. Thanks for the reminder. 🙂
--
Owen Wengerd
President, ManuSoft <>
VP Americas, CADLock, Inc. <>
0 Likes
Message 13 of 25

alex_b
Advocate
Advocate
Owen

I don't see the connection to the kind of ptr used, so I think I explained badly the whole thing. I'll try again:
We have 2 custom entitties, Main and Secondary. The Main ent has a data member pointing to an instance of the Secondary ent.
The reference has to be valid for the Main ent to work, although an invalid ref won't cause a crash.
The Main ent uses the reference only during worldDraw().

Now, the user opens 2 new clean dwgs, A and B, and in A creates an instance of the Main ent. She will be asked to create a Secondary ent also, and a pointer to it will be stored in the Main ent data member.
Now Copy the Main ent, move over to B dwg and Paste it there.
The Main ent gets copied there, bad handle and all. When it tries to worldDraw() itself, it errors out on an invalid handle.
OK thus far.
The problems:
1. why is the error eWasErased (there never were any ents in this dwg)? If we are to find a solution we have to know if it was indeed erased and we can unerase it, or it never existed and we have to create a new one.
2. Supposing we solve 1. above: in order to create a new Secondary ent we need user input, and the question was : can we stay in worldDraw() indefinitely (until the user makes up her mind)?

Regardless, using AcDbDatabase::currentSpaceId() is not a problem here, as we append only to the current working db.

Thanks

alex

null
0 Likes
Message 14 of 25

Anonymous
Not applicable
Alex:

> I don't see the connection to the kind of ptr used...

From your description, it sounds like the "data member" should be an
AcDbHardPointerId. If you fix the flawed design of your entity class in the
way that I suggested, all these other problems will no longer exist. 🙂
--
Owen Wengerd
President, ManuSoft <>
VP Americas, CADLock, Inc. <>
0 Likes
Message 15 of 25

alex_b
Advocate
Advocate
Owen
You are probably right in principle about using pointers instead of handles.
But, in this particular case I don't think a hard pointer will do, as it will cause the cloning of the pointed-to entity for every Copy command, which I specifically don't want.
Moreover, are you saying that using pointers will solve the problem of Autocad returning the wrong error code?
What I need is a way of knowing for sure if the entity pointed-to by the handle/pointer was erased (and can be resuscitated) or never existed.
In any case, could you refer to my question about waiting for user input inside worldDraw()?

Thanks

alex
0 Likes
Message 16 of 25

Anonymous
Not applicable
You can't safely solicit user input during a worldDraw(). The various user
input functions should error out, but I'm not sure that they will do so.

wrote in message news:5934816@discussion.autodesk.com...
Owen
You are probably right in principle about using pointers instead of handles.
But, in this particular case I don't think a hard pointer will do, as it
will cause the cloning of the pointed-to entity for every Copy command,
which I specifically don't want.
Moreover, are you saying that using pointers will solve the problem of
Autocad returning the wrong error code?
What I need is a way of knowing for sure if the entity pointed-to by the
handle/pointer was erased (and can be resuscitated) or never existed.
In any case, could you refer to my question about waiting for user input
inside worldDraw()?

Thanks

alex
0 Likes
Message 17 of 25

alex_b
Advocate
Advocate
Art
Thank you for the clarification. Now I have a big problem :).
About getting eWasErased instead of eWasPermanentlyErased, could you comment?
Thanks

alex
0 Likes
Message 18 of 25

Anonymous
Not applicable
Alex:

> But, in this particular case I don't think a hard pointer will do,
> as it will cause the cloning of the pointed-to entity for every
> Copy command, which I specifically don't want.

Have you tried it?


> Moreover, are you saying that using pointers will solve the
> problem of Autocad returning the wrong error code?

Yes, that is what I am saying. 🙂
--
Owen Wengerd
President, ManuSoft <>
VP Americas, CADLock, Inc. <>
0 Likes
Message 19 of 25

Anonymous
Not applicable
As Owen and I have both said, you should use an objectId not a handle. That
will eliminate this problem. If you don't the referenced entity to be
cloned by wblock, then use a softPointerId. A soft pointer id will be set to
null in the target drawing if the object it refers to was not part of the
cloning operation. So, you could simply use the AcDbObjectId::isNull()
method to determine if the referenced entity was copied to the target
drawing or not.

wrote in message news:5935247@discussion.autodesk.com...
Art
Thank you for the clarification. Now I have a big problem :).
About getting eWasErased instead of eWasPermanentlyErased, could you
comment?
Thanks

alex
0 Likes
Message 20 of 25

alex_b
Advocate
Advocate
OK, I will try doing it with object ID's, and post here the results.
Thank you, Art and Owen.

alex
0 Likes