Setting units in Component Definition DC


#1

How to set units for ComponentDefinition via ruby?
I create CD dynamically and I need to have cm instead Inches.
Units for Model are set as cm.


#2

SketchUp uses inches internally, and DCs usually do also.

However, you can set the formula units for your of attributes to be in any units. But this may (or may not,) make them harder to use.

Where DC_DICT is "dynamic_attributes"

To get the user’s model units (as a DC unit string name):

EDIT: This example has been edited to use constants to avoid errors using the wrong integer id literals.

def get_model_units()
  opts = Sketchup.active_model.options["UnitsOptions"]
  unit_format = opts["LengthFormat"]
  if unit_format != Length::Decimal
    if unit_format == Length::Fractional ||
    unit_format == Length::Architectural
      "INCHES" # Architectural or Fractional
    elsif unit_format == Length::Engineering
      "FEET"   # Engineering
    else
      "DEFAULT"
    end
  else # Decimal ( unit_format == 0 )
    case opts["LengthUnit"]
    when Length::Inches
      "INCHES"
    when Length::Feet
      "FEET"
    when Length::Centimeter
      "CENTIMETERS"
    when Length::Millimeter
      "MILLIMETERS"
    when Length::Meter
      "METERS"
    else
      "DEFAULT"
    end
  end
end

[details=(For the record: the previous code using erroneous integer literals…)]

def get_model_units()
  opts = Sketchup.active_model.options["UnitsOptions"]
  unit_format = opts["LengthFormat"]
  if unit_format != 0
    if unit_format == 1 || unit_format == 3
      "INCHES" # Architectural or Fractional
    elsif unit_format == 2
      "FEET"   # Engineering
    else
      "DEFAULT"
    end
  else # Decimal ( unit_format == 0 )
    case opts["LengthUnit"]
    when 0
      "INCHES"
    when 1
      "FEET"
    when 2 # ERROR! --> should be 3
      "CENTIMETERS"
    when 3 # ERROR! --> should be 2
      "MILLIMETERS"
    when 4
      "METERS"
    else
      "DEFAULT"
    end
  end
end
```[/details]

To set a DC's length units:

_NOTE: This is the attribute that toggles between `"INCHES"` and `"CENTIMETERS"` when you click the ruler icon in the **Component Options** dialog._
```ruby
def set_dc_length_units(
  dc, # the dynamic component's definition
  units = get_model_units() # "DEFAULT" is to use model units
)
  dc.set_attribute( DC_DICT, "_lengthunits", units )
end

To set an individual attribute’s formula units:

def set_dc_attribute_units(
  dc, # the dynamic component's definition
  attr_name, # the name of the dc attribute
  units = get_model_units() # "DEFAULT" is to use model units
)
  dc.set_attribute( DC_DICT, "_#{attr_name}_formulaunits", units )
end

#3

I don’t know about Ruby but the plain vanilla version of Dynamic Components has only inches or centimeters as internal unit options. The Componnet OPtions window can be made to display any units to the user or select the current unit type automatically.

The worst bug in DCs is that the whole thing falls apart if the user has unchecked the “Display units format” box in Model Info, and everything reverts to using inches.

Anssi


#4

To be precise, it is the Component Attributes dialog’s choices that are restricted to "INCHES" and "CENTIMETERS" (for what reason I am not sure.)

But, testing a little bit, by directly using "FEET" as a value for "_z_formulaunits", seems to work just fine.

This is the value for: "_#{attr_name}_units", so an appropriate method to set display units for a particular attribute, would be:

def set_dc_attribute_display_units(
  dc, # the dynamic component's definition
  attr_name, # the name of the dc attribute
  units = get_model_units() # "DEFAULT" is to use model units
)
  dc.set_attribute( DC_DICT, "_#{attr_name}_units", units )
end

But, I believe if not set explicitly (ie, a particular attribute has no corresponding "_#{attr_name}_units" attribute,) then it should most likely use the "_lengthunits" value.


#5

Thank you - just what I was looking for. Just 1 small correction,
CENTIMETERS and MILLIMETERS are swaped for [LengthUnit], the should be:

return value 2 = MILLIMETERS
return value 3 = CENTIMETERS


#6

Whoops! Good catch.

The above example has been edited to use API constants to avoid errors using the wrong integer id literals.

I always forget to use them because they are in a weird place. I go looking within the Sketchup::Model class for these constants but don’t find them there. Then I go searching through the Sketchup::OptionsManager and Sketchup::OptionsProvider classes, with no luck. etc. etc. (It took me more than an hour of poking around in the API documentation until I found them, in the Length class.)