It’s not a mistake in the code, but in your expectation: In your model, the model.entities collection contains only a single entity, so the code only outputs one line of the attributes of this entity.
If you want to traverse also entities nested in groups/components, you need to call your function again with the entities contained in the group/component. You can do this with recursion (see the code below). But there is one conceptional problem: when a component has multiple instances (n), you would visit the contained entities n times. If you don’t want that, you either have to keep track of all component definitions that you have already visited, or you traverse over model.definitions (linearly instead of recursion).
def infos_piece(entities)
lines = []
entities.each{ |entity|
dicts = entity.attribute_dictionaries()
next if dicts == nil
# Read attributes from this entity
infos = []
dicts.each{ |dict|
next if dict.name != 'dynamic_attributes'
puts '', "dictionary: #{dict.name}, definition #{entity.name}"
dict.each_pair{ |key, value|
infos << sprintf("%s=%s",key,value)
}
}
lines << infos.join(", ") unless infos.empty?
# If the entity can contain other entities, recurse over the contained entities
if entity.is_a?(Sketchup::ComponentInstance) || entity.is_a?(Sketchup::Group)
lines.concat( infos_piece(entity.definition.entities) )
end
}
return lines
end
iPiece[0] = '' #Supprimer premier caractère (,)
Don’t do that! You are assuming a comma was added at the beginning of the string, but the comma was not added at the beginning, but after iPiece. Instead of adding and removing characters, it is safer not to add the comma unless you need it.
iPiece += "," if iPiece.length != 0
iPiece += sprintf("%s=%s",key,value)
or much better by joining a list with the character you want only to appear inbetween elements list.join(","). In programming you should never use assumptions, you must be able to prove that what you do is correct.