Why creating dictionary triggers onSelectionBulkChange?
-
Creating a dictionary on a selected object in my onSelectionBulkChange implementation will trigger onSelectionBulkChange recursively (code and output below).
Why does it happen? Do I have to detach the observer while editing the object?Thanks for your help!
klap.. def onSelectionBulkChange( selection ) puts("SelectionObserver.onSelectionBulkChange") puts "xxx" selection[0].attribute_dictionary( "test_dictionary", true ) puts "yyy" end ..
If I select an object once I get the following output in the Ruby-Console
SelectionObserver.onSelectionBulkChange xxx SelectionObserver.onSelectionBulkChange xxx yyy yyy
-
@klap said:
Do I have to detach the observer while editing the object?
Well first of all.. it is generally dangerous to make changes to the model inside observer callbacks.
This behavior is mild... sometimes we get BugSplats! (crashes.)
-
@klap said:
Why does it happen?
Sounds like a bug to me.
Ie.. Ruby-wise,
Sketchup::AttributeDictionary
is a subclass ofSketchup::Entity
.. meaning that EntityObservers apply toSketchup::AttributeDictionary
instances.... and then you ADD another entity to the model, which is attached to the selected entity.
The weirdness here is that a dictionary does not increase the number of members in the selection set.
-
I reported this as a Ruby bug.
-
@dan rathbun said:
@klap said:
Do I have to detach the observer while editing the object?
Well first of all.. it is generally dangerous to make changes to the model inside observer callbacks.
This behavior is mild... sometimes we get BugSplats! (crashes.)
I second this. It causes lots of problems. It breaks native operations and other plugin's operations. Adding an attribute will also add an item to the undo stack - interfering with Undo and Redo. User's will hit undo - but see no change because what's being undone is the attribute.
-
thanks for the quick reply
what is the best/save practice in such cases: e.g. creating a attribute dictionary at an entity if the user select the entity:- detaching the observer (unsave because it changes the model from inside the callback)
- using a flag to simulate (1)
- possibly skip the code in the callback if the selected Entity has not changed
- ?
I am not sure what the intended behaviour after the bug fix is:
Is the AttributeDictionary going to appear in the selection set (increasing its number)?
Currently I assume that active_model.selection[0] is one of the Entities selected by the user, is it unsave to assume that.
.. -
Can you describe roughly what you're doing?
-
regarding my last post: ok, changing AttributeDictionary from inside the callback is also unsave, because it is a part of the model, so (1)(2)(3) are no options.
So I have to create the AttributeDictionary asynchronously..
What I am going to do is to add properties to groups to describe event triggered behaviour. E.g. to make a group being a door I annotate the group with a start and a target location. The SketchUp model is linked with a VR application which plays the game then.For editing the properties and interacting with the goup I use a non modal web dialog, which updates if the user changes the selection. The AttributeDictionary will be lazy created if the user press the save button in the webdialog. This works fine if I have one group per behaviour (e.g. the animation).
Now I want to add a behaviour which switches between groups. The user interaction causes creation and associatiation of new groups. To store the associations I need a further dictionary per group which stores an "id", a "parent" and a "children" property.
This directory must be available if the user can interact with the group via the web dialog, that means directly after the dialog has been updated caused by selecting an object by the user.
..Possibly I could work around by lazy creation triggered by certain user interactions via web dialog but would like to avoid this.
-
Yea - it's best to collect info/data from observer events and then react to that on safe points. Be extremely defensive with observers. Also try to do as little as possible as some events triggers a lot.
-
thanks, that is clear now.
About save points: are there other save points, beside user interaction events from javascript in the web dialog or possibly timer events.Is it right, that:
- calling javascript from ruby is syncroniously
- calling ruby from javascript is syncroniously too
so that the following is unsave:
rb.onSelChanged() calls js.selChanged()
js.selChanged() calls rb.modifyModel()Dan, just another question regarding your former post: is it save to assume that iff the user select one entity in the 3d view, active_model.selection[0] is always this entity?
.. -
@klap said:
Is it right, that:
- calling javascript from ruby is syncroniously
- calling ruby from javascript is syncroniously too
so that the following is unsave:
..
Under OSX the communication from JavaScript to Ruby is async. Everything else is syncronious.
Read more in the Lost Manual:
https://github.com/thomthom/sketchup-webdialogs-the-lost-manual/wiki/Asynchronous-versus-Synchronous-Communication -
Thanks thomthom!
An other question regarding SelectionObserver.onSelectionBulkChange:
The notification seems to depend on whether I change the selection in the 3d-view or via ruby with (selection.add):
The method onSelectionBulkChange is called only when the selection is changed in the 3d view, changing via ruby will not trigger it
The method onSelectionCleared is triggered from the 3d-view and ruby (as expected)
Is there a intention for thatIs it possible to notify all registered observers via ruby (as a workaround?)?
-
attaching #<ObserverTests;;SelectionObserver;0xd0f8c0c> to #<Sketchup;;Selection;0xe565be0> onSelectionBulkChange;[#<Sketchup;;Selection;0xe565be0>] onSelectionCleared;[#<Sketchup;;Selection;0xe565be0>] onSelectionBulkChange;[#<Sketchup;;Selection;0xe565be0>] x=Sketchup.active_model.selection[0] #<Sketchup;;ComponentInstance;0xe68e1c0> sel=Sketchup.active_model.selection #<Sketchup;;Selection;0xe565be0> sel.clear onSelectionCleared;[#<Sketchup;;Selection;0xe565be0>] nil sel.add(x) onSelectionAdded;[#<Sketchup;;Selection;0xe565be0>, #<Sketchup;;ComponentInstance;0xe68e1c0>] 1
It seems that Ruby will trigger the old methods...
-
@thomthom said:
It seems that Ruby will trigger the old methods...
And for some selection events using the Outliner... the engine triggers MISSPELLED callbacks.
I never did get around to logging those bugs !
-
@dan rathbun said:
... the engine triggers MISSPELLED
dan, I truly thought you had misspelt that and had to Google it...
best explanation I could find was this...@unknownuser said:
British English shows a preference for retaining strong verb forms (burnt, learnt, spelt, dreamt, spoilt etc). American English shows a preference for ignora... I'm mean simplification (burned, learned etc).
john
Advertisement