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.