onElementModified not triggered when push/pulling a face of a Group or a Component

I’d like to know when the dimensions of a component or a group have changed so I tried with this simple script:

class MyEntitiesObserver < Sketchup::EntitiesObserver
  def onElementAdded(entities, entity)
    puts "onElementAdded: #{entity}"
  end
  def onElementModified(entities, entity)
    puts "onElementModified: #{entity}"
  end
  def onElementRemoved(entities, entity_id)
    puts "onElementRemoved: #{entity_id}"
  end
  def onEraseEntities(entities)
    puts "onEraseEntities: #{entities}"
  end
end

Sketchup.active_model.entities.add_observer(MyEntitiesObserver.new)

If I draw a flat rectangle and pull that to a cube I get the change events:

onElementModified: #Sketchup::Edge:0x00000001704c5d80

onElementModified: #Sketchup::Face:0x00000001704c5c40

However, if after creating the cube, I select all of it and group it, then pull/pushing the faces does not trigger onElementModified events anymore. Same thing if I make it a Component.

But scaling the cube does trigger onElementModified:

onElementModified: #Sketchup::Group:0x00000001704c4070
onElementModified: #Sketchup::AttributeDictionary:0x000000017002f028

So how can I monitor size changes of Groups and Components in case of push/pull?

I suppose you have to use a Entity Observer because Entities Observer react to Entities collection events.

This is because you only have done this …

… which attached your observer instance to the model’s entities collection, … but the face and edge are no longer members of the model’s entities collection as you’ve grouped them.

They are now members of the group instance’s definition’s entities collection. So you will need to attach the observer to the group.definition.entities also.

* Note that a group is a special kind of component instance whose definition does not appear in the “In Model” definition list in the Components inspector panel. So therefore they (groups) also have a parent definition object.

1 Like

Thanks Dan. I’m new to both Ruby and the Sketchup API so it takes a little time for me to understand what’s in these collections and what is the right way to use these observers. I’m sure you are right, just need to play around a bit :+1:

OK, so I managed to update the code in such way that each time a Group is added to the model.entities collection, an observer is also added to the group’s definition.entities collection. This now triggers the observer’s onElementModified callback when a Face in a Group is pushed/pulled with the Face as the entity callback argument.

Since my original goal was to monitor when the overall dimensions of a Group or ComponentInstance change, I tried to navigate to the parent of that Face, expecting to end into the Group or ComponentInstance -object but this does not seem to be how this object tree is organized.

So how do I find the Group that a Face is part of - if any? Or, is there a more elegant way to monitor dimensional changes for a Group or ComponentInstance than monitoring changes in it’s “child elements”? Thanks!

use parent method

Same group may have different sizes in global coordinates. Because there may be different instance paths

A Face entity is part of the definition entities, not “part of the” instance. (Instance does not have an entities method.)
The Entities class is a collection of Entity objects, either in a ComponentDefinition or directly in the Model. A Entities object corresponds to a drawing context in the GUI. This is a collection of groups (group instances), component instances (and edges, faces etc…).

The only way if user pushed/pulled the Face is to go to the instance definition editing context and edit the definition by “moving” the Face . It is irrelevant which instance is chosen to edit the definition, it will change the same Face and a same definition.

If the user make unique the instance in a question before editing, he is creating a new definition which will contain a new face.

However if the user move, rotate or scale one of the instance the GUI representation of that face will change. So you need to check how the instance transformation changed.

__
About the groups:
If the user copies a group in UI, SketchUp will create a group that shares the same definition.

Groups in SketchUp are very similar to components, but can from a user point of view be thought of as unique objects. Groups can be instanced when copied but are silently made unique when edited through the GUI. To honor this behavior, make sure to call #make_unique before modifying a group through the API.

2 Likes