EntitiesObserver and attributes
-
Hi,
Im working with
EntitiesObserver
, and having trouble understanding the method
def onElementModified(entities, entity)
.For instance, if you add an
EntitiesObserver
to a group consisting of a face, theEntitiesObserver
will fire when you doubleclick the group and alter the face.(Eg. moving one of the edges so that the area of the face will increase.) In that case it will fire 3 times because 2 edges will get longer, and the face itself will increase in size.
If you have set an attribute to the face it is then possible to retrieve the value by saying
myFaceAttr = entity.get_attribute "rsdict", "face_attr"
, and you can set a new value withset_attribute "rsdict", "face_attr", "new value"
.But now my question is: what if I have an attribute set to the group, and I want to alter that when the
EntitiesObserver
fires. Is it possible to see name of the parent of the entity? (The face is a child of the group)Hope the question is understandable...
-Rasmus
-
@rvs1977 said:
But now my question is: what if I have an attribute set to the group, and I want to alter that when the
EntitiesObserver
fires. Is it possible to see name of the parent of the entity? (The face is a child of the group)Get the group instance's name from inside the observer callback:
editpath = entities.model.active_path grp =( editpath.size > 0 ? editpath.last ; nil ) name =( grp ? grp.name ; "" )
Get the group definition's name from inside the observer callback:
entities.parent.name
A
Group
is a special flavourComponentInstance
, so it therefor has aComponentDefinition
, which is the real owner of theEntities
collection. -
Thank you Dan, but I try to explain it again:
My goal is to set an attribute to the group when a face has been modified. As you can see in the code below Im able to set an attribute to the face inside the group, but not the group containing the face. Do you have any ideas how to work around this problem?
If the group is called rsgroup:
yv_face_height = rsgroup.entities.add_face pts[0..3]
rsgroup.set_attribute "rsdict","area", yv_area
yv_face_height.set_attribute "rsdict", "yv_face_area", yv_areaclass MyEntitiesObserver < Sketchup;;EntitiesObserver def onElementModified(entities, entity) attr_area = entity.get_attribute "rsdict", "yv_face_area" if attr_area yv_area_new = i.area.to_m.to_m entity.set_attribute "rsdict", "yv_face_area", yv_area_new #(HERE I WOULD LIKE TO SET THE ATTRIBUTE OF THE GROUP-something like;) entity.parent.set_attribute "rsdict","area", yv_area_new end #attr_area end #onElementModified_end end #class
-
I showed you how to get a reference to the group (named
grp
in my example, above.)
Just ignore the calls to get thename
... BUT ...... you have a vicious circle situation.
Changing attributes fires observers on
Entities
collections.In SketchUp:
I made a box and grouped it. And left it selected.
I made a ref to the group:
grp = Sketchup.active_model.selection[0]
At the Ruby Console, I defined a quick checker class:
class Spy; attr_accessor(;name); def initialize(spy); @name = spy.to_s; end; alias_method(;has_method?,;respond_to?); # override respond_to? method; def respond_to?(meth); puts("\nSpy '#{self.name}' method '#{meth.to_s}' was called by Sketchup."); has_method?(meth); end; end
Then made two spy instances:
mspy = Spy.new("Model Entities Spy") gspy = Spy.new("Group Entities Spy")
And attached them:
Sketchup.active_model.entities.add_observer(mspy) grp.entities.add_observer(gspy)
Then added a dummy attribute:
grp.set_attribute "rsdict","area", (1.23).to_l.to_m.to_m
This was the output to the console:
[pre:gsyu95n9]Spy 'Model Entities Spy' method 'onElementAdded' was called by Sketchup.Spy 'Model Entities Spy' method 'onElementRemoved' was called by Sketchup.
Spy 'Model Entities Spy' method 'onElementModified' was called by Sketchup.
Spy 'Group Entities Spy' method 'onElementAdded' was called by Sketchup.
Spy 'Group Entities Spy' method 'onElementRemoved' was called by Sketchup.
Spy 'Group Entities Spy' method 'onElementModified' was called by Sketchup.[/pre:gsyu95n9]
Problem is you are already within the
EntitiesObserver
instance attached to the Group'sEntities
collection !
You must be careful not to set up an infinite loop !Changing the model from within observer callbacks can crash SketchUp !
-
@dan rathbun said:
Problem is you are already within the
EntitiesObserver
instance attached to the Group'sEntities
collection !
You must be careful not to set up an infinite loop !Changing the model from within observer callbacks can crash SketchUp !
Ok, for now I will abandon this approach.
Please consider this example:
mod = Sketchup.active_model ent = mod.entities i = 0 h= {} ent.each do |o| attr = o.get_attribute "rsdict","area" if attr h[i] = {'structid' => 201, 'area' => attr} i += 1; end end
Here it scans the entire model for groups with the attribute_dictionary "rsdict", "area".
Lets say it finds a group with the "rsdict" attribute. Inside the group there are a face
with an attribute attached to it.Is it possible to scan that group for all its entities? Something like this:
mod = Sketchup.active_model ent = mod.entities i = 0 h= {} ent.each do |o| attr = o.get_attribute "rsdict","area" if attr o.entites.each do |u| yv_face_area = u.get_attribute "rsdict", "yv_face_area" if yv_face_area h[i] = {'structid' => 201, 'area' => yv_face_area} i += 1; end end end
-
Something more like:
mod = Sketchup.active_model ent = mod.entities h = {} ent.each_with_index do |o,i| next unless o.is_a?(Sketchup;;Group) attr = o.get_attribute("rsdict","area") if attr o.entities.each do |u| next unless o.is_a?(Sketchup;;Face) yv_face_area = u.get_attribute("rsdict", "yv_face_area") if yv_face_area h[i] = {'structid' => 201, 'area' => yv_face_area} end end end end
I wonder why you are using ordinal integers as hash keys ??
You might as well just use an array:mod = Sketchup.active_model ent = mod.entities h = [] ent.each do |o| next unless o.is_a?(Sketchup;;Group) attr = o.get_attribute("rsdict","area") if attr o.entities.each do |u| next unless o.is_a?(Sketchup;;Face) yv_face_area = u.get_attribute("rsdict", "yv_face_area") if yv_face_area h << {'structid' => 201, 'area' => yv_face_area} end end end end
-
Great, this solved my problem! Thank you very much Dan!
Advertisement