Great resources on this forum, and I want to thank everyone in advance, and apologize as I’m coming from python and thus learning Ruby and the SKUP API all at once.
My goal is to open a Layout document, get all the existing Dimension, and set their Layout::Style to Metric.
UPDATE:
So I’ve got this far in editing dimension style. Now I’m just looking for help turning this into a for loop and iterating over the dimensions.
This just gets the first page and the first entity on that page. I’m guessing I need to get all pages as an [array] and loop over each page, with a nested for loop getting all entities.
Will it throw an error if I don’t specify Dimensions?
Major difference is Ruby uses 2 space indents and has an end statement to close blocks (of all kinds. It does not have specific end keywords for each type of block like Pascal has for example.)
Second, major difference is that modules and class definitions are not tied to any specific file nor filename. (Ie, the name of a file has no bearing upon what the identifier names are of module or class definitions within the file.)
Ruby is a dynamic language and so any (unfrozen) class or module can be reopened for changes during runtime, by any number of files. When you use the interpreter syntax of a line beginning with module, the interpreter will call the Module class constructor if it hasn’t yet been defined, or it it has, then the interpreter will call the #module_eval upon the module object passing in the code block.
This all means you’ll be modifying your toplevel namespace module each time you load one of your plugins. Each extension / plugin should be wrapped in a submodule of your namespace module, so it will not clash with your other plugins, and the namespace module protects it from other coder’s code (as well as the Ruby core classes and modules.) The opposite is also true.
This also means that your plugin submodule can span any number of .rb files. This can make it much easier to write and maintain if you use a code editor that has tabbed mutil-doc interface and more so if it supports side by side or one above another editing panes.
Take advantage of the wiki lists I’ve compiled here …
… and especially the Python migration primer listed on …
It will (raise an NoMethodError) if you call a method that the iterator entity does not respond to.
The most beneficial thing new SketchUp Ruby API coders need to learn is that most SketchUp API collection classes mixin in the Ruby Core Enumerable module. From this module we get the very fast #grep method. Ie …
module Sertfas
module MyThang
extend self
def set_dim_units_mm(doc)
doc.pages.each do |page|
dims = page.entities.grep(Layout::LinearDimension)
dims.each do |dim|
style = dim.style
style.set_dimension_units(Layout::Style::DECIMAL_MILLIMETERS, 1)
dim.style= style
end
end
end
def do_my_thang()
filepath = UI.openpanel(
'Choose filepath', File.expand_path('~'), 'Test.layout'
)
return false unless filepath
begin
doc = Layout::Document.open(filepath)
rescue => err
puts err.inspect
return false
else
set_dim_units_mm(doc)
doc.save
end
end
if !@loaded
UI.menu('Extensions').add_item('Do My Thang...') { do_my_thang() }
@loaded = true
end
end
end
EDIT: Fixed the method set_dim_units_mm that was setting the units upon the dimension’s text object instead of the dimension itself. (See @sertfas’ post below.)
Wow, thank you very much for the clear and thorough explanation. Really grateful for you to take the time. It would’ve taken me a loooong time to get to this point.
For the benefit of posterity, please note commented lines below. While I’m sure Dan’s code works as intended on his machine, I had to change the following lines to achieve the desired result.
module Sertfas
module MyThang
extend self
def set_dim_units_mm(doc)
doc.pages.each do |page|
dims = page.entities.grep(Layout::LinearDimension)
dims.each do |dim|
style = dim.style #Replaced dim.text.style with dim.style
style.set_dimension_units(Layout::Style::DECIMAL_MILLIMETERS, 1)
dim.style = style #Replaced dim.text.style with dim.style
end
end
end
def do_my_thang()
filepath = UI.openpanel(
'Choose filepath', File.expand_path('~'), 'Test.layout'
)
return false unless filepath
begin
doc = Layout::Document.open(filepath)
rescue => err
puts err.inspect
return false
else
set_dim_units_mm(doc)
doc.save
end
end
if !@loaded
UI.menu('Extensions').add_item('Do My Thang...') { do_my_thang() }
@loaded = true
end
end
end
Thank you again Dan, hope this little script can help someone else’s workflow.
I looked for the #style getter method under the Layout::LinearDimension class, didn’t see it, and saw the #text getter, and looked that up and saw it did have a #style getter. I made an assumption.
The Layout::LinearDimension class actually inherits it’s #style getter and #style= setter methods from it’s superclass Layout::Entity.