Entity.set_attribute infinite loop
-
Hi,
Just wondering if anyone can help me with a problem I've been struggling with all day
I'm trying to assign a unique id attribute to each face entity that is created when the plugin is running. I've set up a model observer so that every time that onElementAdded is fired it checks whether the new entity is a face and if it is it does the following:
entity.set_attribute('test', 'id', id)
The problem is that when this happens I start to get an infinite loop and eventually sketchup crashes. I've whittled the cause of this down to the attribute being set, this seems to create the face over and over again.
The following is the code I've got to do this:
def onElementAdded(entities, entity) puts entity.typename if entity.kind_of? Sketchup;;Face if entity.get_attribute('test', 'id') == nil puts "setting attribute" entity.set_attribute('test', 'id', 'blah') end end end
In the above code I've just put 'blah' as the id to make sure that it wasn't the unique id that was causing the problem. BTW, the unique id is just a timestamp.
Any help or suggestions would be greatly appreciated.
-
I came to conclusion the set_attribute stuff and observers really don't get along. They are, in my experience, at best very flakey when used together. I gave up setting attributes from within observers all together...quite annoying.
I'd love to hear of any toptips to make it work though..
Adam
-
Unfortunately, you can't change an entity inside an observer that tells you that entity is being created. When your observer gets called, it is inside SketchUp's internal commit scope of the entity creation. Anything you change about the entity will cause a new commit scope, and that breaks things. That's my understanding of it.
Todd
-
@adamb said:
I came to conclusion the set_attribute stuff and observers really don't get along. They are, in my experience, at best very flakey when used together. I gave up setting attributes from within observers all together...quite annoying.
I'd love to hear of any toptips to make it work though..
Adam
I just did this by starting a timer to defer the execution of the block.
UI.start_time(0.1) { entity.set_attribute('test', 'id', 'blah') }
I don't like it, but it worked.
-
Yeah, my solution was just as nasty. I add a reference to a global list and flush the list outside the observer context. Horrid.
BTW I understand Todd's explanation wrt recursive invokation but I found I had problems if I set_attribute in an InstanceObserver too which to me is pretty unreasonable.
Adam
-
Hi Thanks for that solution, I've tried it and it works a treat.
Its a bit hackish but it works so it'll do.
Thanks again.
Advertisement