I’m starting to study programming with Ruby. The first goal I set myself is to add an attribute to a component.
For example, I want to define the maximum size of a component. Now I do it manually by defining:
“Lenght” defined as = LARGEST (LenX, LenY, LenZ).
I wish I could do it with a button via Ruby code, I select the component then I click on the button and the code is added.
How can I do it? Can you give me some advice on the best way to deal with this step?
[bounds.height, bounds.width, bounds.depth].max is how you get the longest side of a Geom::BoundingBox with Ruby.
Not sure what you mean by adding code with a button.
Thanks for your reply,
I would like to add an attribute to a given component by selecting it and clicking on a button.
This is not Ruby code. It is a Dynamic Components extension formula using a DC function that references dynamic attributes.
The Dynamic Components extension is closed source at this time, and hacking it with Ruby is a very advanced concept in programming. It is also not advised to “hack” Dynamic Components as it’s proprietary extension engine could be modified at any time by the SketchUp Team.
Please choose a simpler feature to use to learn SketchUp Ruby programming.
You should at least read the Ruby Core primers & guides before attempting to program for SketchUp using it’s API.
I’ll go ahead and give you a general answer for adding an attribute to any
Sketchup::Entity subclass object. Ruby can use inheritance to pass down behavior to subclasses, so the methods to create and access attributes (and the dictionaries they belong to,) are defined upon the
So say that we have a reference to a selected component instance, and you want to attach an attribute to this object.
# We assume the first and only object selected is the instance: selset = Sketchup.active_model.selection obj = selset.first obj.set_attribute( "MPS", "Created", "Massimiliano Pratelli" )
NOTE: The modelspace is a shared space among all extensions. Therefore extension authors need to use unique attribute dictionary names. A good “rule of thumb” is to always prefix your dictionary names with your unique toplevel company/author module name, and then the name of the extension that will use this dictionary.
"MPS_NiftyPlugin"(This can follow the required file naming for extensions.)
This keeps them separate from all other author’s dictionaries as well as your other extension’s dictionaries.
But this attaches the attribute and it’s “MPS” dictionary to only 1 instance of the component.
It would make much more sense to attach it to the definition of the component, like so …
# We assume the first and only object selected is the instance: selset = Sketchup.active_model.selection obj = selset.first if obj.respond_to?(:definition) # duck typing obj.definition.set_attribute( "MPS", "Created", "Massimiliano Pratelli" ) else obj.set_attribute( "MPS", "Created", "Massimiliano Pratelli" ) end
Then we can wrap it up within a Ruby method that can be called from elsewhere.
NOTE: It is assumed whenever example methods are posted in the forum, that they need to be wrapped within your company/author namespace module and within it, a specific sub-module for an extension.
def set_mps_created_by # We assume the first and only object selected is the instance: selset = Sketchup.active_model.selection obj = selset.first if obj.respond_to?(:definition) # duck typing obj.definition.set_attribute( "MPS", "Created", "Massimiliano Pratelli" ) else obj.set_attribute( "MPS", "Created", "Massimiliano Pratelli" ) end end
For a complete example with YARD documentation comments and a method argument allowing the “creator” to be passed into the method (but having a default value,) along with type checking and a couple of “bailout” conditions …
# Set the "creator" attribute in a "MPS" dictionary attached to a definition # (if possible) otherwise on the selected Drawingelement object. # # @param creator [String] A text string or an object coercible into a string. # # @return [String] the string value as set in the dictionary. # @return [nil] if the selection set is empty. # @return [false] if the first object does not respond to a :set_attribute call. # def set_mps_created(creator = "Massimiliano Pratelli") # Be sure the passed argument is a String or coercible object: unless creator.respond_to?(:to_s) fail(TypeError,"String or coercible object expected.",caller) end creator = creator.to_s if !creator.is_a?(String) # selset = Sketchup.active_model.selection return nil if selset.empty? # We assume the first and only object selected is the target object: obj = selset.first return false unless obj.respond_to?(:set_attribute) # if obj.respond_to?(:definition) # duck typing # It walks and talks like an instance (component, image or group.) obj.definition.set_attribute( "MPS", "Created", creator ) else # It is some other kind of Sketchup::Drawingelement. obj.set_attribute( "MPS", "Created", creator ) end end
Whaaw! Many thanks!
I know the difference between the dynamic component formula and the Ruby code. I said that badly. I would really like to get the same effect of adding that formula into the component via code.
eneroth3 (thank you!) suggested the expression
[bounds.height, bounds.width, bounds.depth] .max
My aim is to take advantage of that attribute in LayOut.
I will practice to do this:
I select the component;
I press the button with the command that I have to define in the toolbar;
the attribute is added;
Many thanks again