How to access the attributes for the dynamic component?

I’m just learning Ruby API, so do not judge strictly! I am wondering how to get data for embedded attributes:

I tried several options, but did not get the result, for example:

  model = Sketchup.active_model
  entities = model.entities

  for entity in entities
        UI.messagebox(entity.get_attribute('Size', 'LenX'))
  end

This implementation returns an empty dialogue. But I do not find suitable examples in the documentation Ruby API.

Any ideas are welcome, thank you.

You will understand better how things are set up, if you use an attribute viewer plugin, like Aerilius’ Attribute Inspector.

It is often misleading to use UI.messagebox() for testing, because it silently fails. Instead open the Ruby Console, and use puts statements to sent output to the console.
ie:
puts entity.get_attribute('dictionary_name','Size', 'LenX')

What is ‘dictionary_name’?

attribute = entity.get_attribute('Component_1', 'Size', 'lenx')
UI.messagebox(attribute.to_s)

I get the name ‘LenX’ instead of a value.

I am sorry, but it is not my place to publish specifications about the Dynamic Components extension. This extension is a Trimble extension, and the code is proprietary.

Possibly others have mentioned the dictionary name in the Dynamic Components category posts. It is likely not that much of a secret, but still, I do not feel comfortable stating the name publically.

Perhaps one of the staff can weigh in?
@tt_su or @ChrisFullmer

And yet I do not understand how to use the method of ‘get_attribute’ for the attribute value ‘LenX’. It’s funny, if you enter an empty string parameter ‘dictionary_name’ I get the same thing.

LenXIS a String value of attribute “_lenx_label

Attribute name that begin with “_” are hidden attributes. (The DC dialogs do not display them because they are not something the user changes.)

The attribute “_lenx_label” is used in association with the value stored in attribute “lenx”, ie:

xs = ent.get_attribute(DICTNAME,"lenx")
x = xs.to_f.to_l # a Length class object

I get the value ‘0.00mm’, must define the parameter ‘dictionary_name’ is not correct.

attribute = entity.get_attribute('Component_1', 'lenx')
UI.messagebox(attribute.to_s.to_l)

‘Component_1’ is the definition name, not the dictionary name.

The attribute is already stored in the dictionary as a String object.

I think it needs to be converted to a Float before conversion to Length.

See this post by Scott Lininger the author of Dynamic Components for SketchUp.

http://sketchucation.com/forums/viewtopic.php?p=208211#p208211

There is also some good information at the old api group:

http://groups.google.com/forum/#!searchin/sketchupruby/dynamic

Here is the code from the first link:

UI.menu("Plugins").add_item('Make Sang Red') {

  # Assumes that sang is the 1st entity in model.
  sang = Sketchup.active_model.entities[0]
  sang_def = sang.definition

  # Override sang's shirt color to red. ("material"
  # is a special attribute that requires
  # you to set a formula to "take control" 
  # over the default material the user has painted.)
  sang_def.set_attribute 'dynamic_attributes', 'material', 'red'
  sang_def.set_attribute 'dynamic_attributes', '_material_formula', '"red"'

  # Add a new configurable option to Sang.
  # (Any attribute that starts with an underscore
  # is a "meta attribute" that describes behavior.)
  sang_def.set_attribute 'dynamic_attributes', 'weight', '145'
  sang_def.set_attribute 'dynamic_attributes', '_weight_label', 'weight'
  sang_def.set_attribute 'dynamic_attributes', '_weight_formlabel', 'My Weight'
  sang_def.set_attribute 'dynamic_attributes', '_weight_units', 'STRING'
  sang_def.set_attribute 'dynamic_attributes', '_weight_access', 'TEXTBOX'

  # Change the description that shows
  # up in the configure box with a custom
  # formula.
  sang_def.set_attribute 'dynamic_attributes',  '_description_formula', '"Sang is now red and weighs " & weight'

  # There is a global handle into the plugin that
  # allows you to make the same calls that the
  # plugin does, like so...
  dcs = $dc_observers.get_latest_class
  dcs.redraw_with_undo(sang)

}

I need to get the value of the attributes of a dynamic component. I created a simple component ‘Component_1’ and added three attributes ‘LenX, LenY, LenZ’. Which method should I use to get the values of attributes?

I tried to change the setting to ‘lenz’, is the same.

Here’s a working example:

model = Sketchup.active_model
entities = model.entities
@dictionary_name = "dynamic_attributes"

for entity in entities
      attribute = entity.definition.get_attribute(@dictionary_name, 'lenx').to_f
      UI.messagebox(attribute.to_cm)
end

Source: Attribute Reporting

1 Like

Just beware that the structure of the Dynamic Component’s attributes is not part of an API contract and might change at any time. You want to code defensibly if interacting with them.

I’m striving to access the the attributes of nested dynamic components.
This is my original question: Component reporter - mining nested attributes
anyone that can help?

Well… I guess you can just do a each into DC component to access nested ones… Like:

my_dc_component.definition.entities do |dc_entity|
  dc_entity.definition.get_attribute('dynamic_components', '_lenx_nominal')
  dc_entity.definition.entities do |more_child|
     #perhaps faces and edges or even a group, instance, etc..
  end
end

There are two type of attributes:

instance.get_attribute('dynamic_attributes', 'my_att')

and

instance.definition.get_attribute('dynamic_atrributes', 'my_att')

note the definition method, maybe this is causing some issues.

Dynamic Components present a problem for any developer wanting to perform any general purpose copy function. (eg: creating arrays of existing objects based on a spacing algorithm, or simply creating a copy in a different location/orientation.).

Since the API has no “copy” function" for any entity type, the developer has to query the attributes of each entity to be copied in order to create clones. This is fairly easy for most element types including normal groups or component instances. But not for dynamic components.

I believe it is the responsibility of the developer of such specialized objects to publish at least these simple methods: (given a component instance “cinst”)::
cinst.is_dynamic?
cinst.copy(point3d)

This would turn dynamic components into good citizens of the community of entities.

Who do we ask?

3 Likes

@barry_milliken_droid, good point.

It would be nice if the copy at point method was added to Components of all types and included copying their attributes, since a DC is just a Component with some special attribute dictionaries.

That’;s even better. I’ve never looked into the area of attribute dictionaries. Is there someone on this forum who knows enough to create a copy function at point3d for component instances?
And since attributes dictionaries can be used for any kind of drawing element, a generic copydrawingelement(point3d) method would be best. For a line the point would be the start, for a face the start of the first edges, etc ,etc.

I changed my mind. A function simply to copy attribute dictionary content from one entity to another would suffice.
Given 2 entities ent1 and ent2.
ent1.copy_attributes(ent2)
I can take responsibilty to ensure that the entities are of correct types(s).

I’m thinking that this should be a fairly simple method to write.
However, I’m having a problem understanding Attribute Dictionaries. I don’t see a method in the API to create a dictionary in the first place(?) .
Maybe the “dictionaries” are just what ever “dictionary names” happen to be attached to individual entities. But this contradicts normal understanding of what a “dictionary” is.
I must be missing something fundamental.