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

Object reactor firing repeatedly during undo

6 REPLIES 6
SOLVED
Reply
Message 1 of 7
oliver253m
674 Views, 6 Replies

Object reactor firing repeatedly during undo

Greetings!

 

I was noticing that the overriden methods of an object reactor were being called several times for each object during the undo command. I thought there was an error in my code, but I did a very simple test and got the same results.

 

First of all, I created a plain lightweight polyline in AutoCAD. Secondly, I added an object reactor to my application with print statements inside the interesting functions. Then I added a command, which opens the last created entity and assuming it's a polyline, attaches the reactor, changes all of the points and some other properties.


Now, when I run the command in AutoCAD and then do an undo, I get the openedForModify, modifyUndone, modified and objectClosed notifications called once for every set* function that my command called, or the assertWriteEnabled behind these functions. If I create a polyline with two points, I get two sets of notifications, if I create a polyline with four points and add a setColorIndex to my command, I get five sets of notifications. It doesn't matter if I use manual open-close or transactions.

 

Have I missed something big or is this how undo works?

6 REPLIES 6
Message 2 of 7
Balaji_Ram
in reply to: oliver253m

Hi Oliver,

 

Sorry for the delay.

 

I did a quick test using the ArxDbg Snoop tool on a LWPolyline and the object reactors did seem to get fired only once regardless of the number of points the polyline had.

 

Here is the recording of what i tried in AutoCAD 2013.

https://www.dropbox.com/s/xhnznxp14ddrv39/Demo.zip

 

 

Can you please try with ArxDbg to see if the behavior is reproducible and if so, let me know the steps ?



Balaji
Developer Technical Services
Autodesk Developer Network

Message 3 of 7
oliver253m
in reply to: Balaji_Ram

Hello and thank you for replying.

 

The behaviour doesn't seem to be related to polylines or the number of points, but the number of set* functions called from code.

 

I created a lwpolyline with 5 points, attached the ArxDbg reactors and created the following test code without any error checking:

 

ads_name entlast;
acdbEntLast( entlast );

AcDbObjectId oId;
acdbGetObjectId ( oId, entlast );

AcDbPolyline * pPl = nullptr;
acdbOpenObject( pPl, oId, AcDb::kForWrite );

 

pPl->close();

 

Running the command showed the following messages:

{OBJ T-REACTOR} : {Object Closed     : }

Undo did nothing, as the code didn't modify anything.

 

Next I added the following line:

pPl->setColorIndex( 1 );

 

Running this command shows:

{OBJ T-REACTOR} : {Open For Modify   : AcDbPolyline, 1F2}
{OBJ T-REACTOR} : {Modified          : AcDbPolyline, 1F2}
{OBJ T-REACTOR} : {Object Closed     : }

 

And undo, as expected:

{OBJ T-REACTOR} : {Open For Modify   : AcDbPolyline, 1F2}
{OBJ T-REACTOR} : {Modify Undone     : AcDbPolyline, 1F2}
{OBJ T-REACTOR} : {Modified          : AcDbPolyline, 1F2}
{OBJ T-REACTOR} : {Object Closed     : }

 

Now, I add another function call:

pPl->setLineWeight( AcDb::kLnWt015 );

 

Running it shows the same result, but the following undo shows this:

{OBJ T-REACTOR} : {Open For Modify   : AcDbPolyline, 1F2}
{OBJ T-REACTOR} : {Modify Undone     : AcDbPolyline, 1F2}
{OBJ T-REACTOR} : {Modified          : AcDbPolyline, 1F2}
{OBJ T-REACTOR} : {Object Closed     : }
{OBJ T-REACTOR} : {Open For Modify   : AcDbPolyline, 1F2}
{OBJ T-REACTOR} : {Modify Undone     : AcDbPolyline, 1F2}
{OBJ T-REACTOR} : {Modified          : AcDbPolyline, 1F2}
{OBJ T-REACTOR} : {Object Closed     : }

 

If I add code to change each of the 5 points, then I get 7 sets of notifications during undo.

 

I'm not sure what goes on behind the scenes, but it seems like each set* function is stored as a separate state.

 

It's not really a big deal, just curious and may need to check existing values before modifying them in my entity wrapper classes.

Message 4 of 7
owenwengerd
in reply to: oliver253m

I'm curious whether you see the same behavior for e.g. AcDbLine, or is this peculiar to AcDbPolyline?

--
Owen Wengerd
ManuSoft
Message 5 of 7
oliver253m
in reply to: owenwengerd

Did the test, there is a difference, as set* functions specific to AcDbLine seem to work as one. The same with circle and text entities.

 

Setting the following properties results in one set of notifications after undo:

pLine->setStartPoint( AcGePoint3d( 1.0, 0.0 ,0.0 ) );
pLine->setEndPoint( AcGePoint3d( 2.0, 0.0, 0.0 ) );
pLine->setNormal( AcGeVector3d::kZAxis );
pLine->setThickness( 1.0 );

 

However, adding AcDbEntity-specific functions, for example

pLine->setColorIndex( 1 );
pLine->setLineWeight( AcDb::kLnWt015 );
pLine->setLinetypeScale( 1.0 );
pLine->setLayer( _T( "0" ) );

produces 5 sets of notifications during undo.

 

Back to lwpolyline, I don't see a difference between functions specific to points or the polyline itself.

 

This code results in 3 sets:

pPl->setPointAt( 0, AcGePoint2d() );
pPl->setBulgeAt( 0, 0.0 );
pPl->setWidthsAt( 0, 1.0, 1.0 );

 

And adding this gives 6 sets:

pPl->setNormal( AcGeVector3d::kZAxis );
pPl->setElevation( 0.0 );
pPl->setThickness( 1.0 );

Message 6 of 7
artc2
in reply to: oliver253m

The AcDbEntity level functions you are using all do partial undo recording, so each function has its own independent undo recording.  The AcDbLine setStartPoint, setEndPoint, etc. all use the full undo recording mechanism which uses the object's dwgOutFields to get a record of all of the object's state the first time one of those functions is called and then no more undo recording is needed for that open of the object, so all of those operations are treated as one by undo.

Message 7 of 7
oliver253m
in reply to: artc2

Thank you for the explanation, good to have an understanding of the implications.

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

Post to forums  

Autodesk Design & Make Report

”Boost