DC volume attribute with update script

This bit of Ruby adds a volume attribute to a DC as expected. However the new attribute will not update on redraw and if you try to reference it in a new attribute by clicking on it, this error message appears. Any thoughts on how to correct or workaround either of these issues?

Thanks!

Sketchup.active_model.selection.grep(Sketchup::ComponentInstance).each do |s|
      s.set_attribute "dynamic_attributes","vol_inch", s.volume 
       $dc_observers.get_latest_class.redraw_with_undo(s)
 end

Edit: If you manually enter =vol_inch the new attribute works as expected.

Related topic.

Almost all dynamic attributes are attached to a DC’s definition. Any of those that have values that differ from the definition are also attached to the DC instance. The last different value is also saved into the definition for use as the default value for the next instance of that DC. (Note that nested dynamic groups always have the dynamic attributes attached to the instance.)

So it not surprising that all a dynamic property’s supporting attributes get properly added to the definition and the instance (as required) when you use the manual interface.

2 Likes

Use Aerilius attribute inspector. to see what attributes are created with each addition to a DC.

By adding the _“some new attribute” _label to the list of created attributes first, assures its defined

Sketchup.active_model.selection.grep(Sketchup::ComponentInstance).each do |s|
      s.set_attribute "dynamic_attributes","_vol_inch_label", "vol_inch"
      s.set_attribute "dynamic_attributes","vol_inch", s.volume 
       $dc_observers.get_latest_class.redraw_with_undo(s)
 end

probably best to add to the definition rather than the instance

1 Like

Yep that fixes the click to add problem, thanks Philip. Any idea on making it update on the redraw? It would be SUPER cool to add that functionality.

Add Volume to component definition:

Sketchup.active_model.selection.grep(Sketchup::ComponentInstance).each do |s|
  s.definition.set_attribute "dynamic_attributes","_vol_inch_label","volume_inches"   
  s.definition.set_attribute "dynamic_attributes","vol_inch", s.volume 
  $dc_observers.get_latest_class.redraw_with_undo(s)
end

Code should always check groups and instances if they are actually dynamic before setting attributes as Entity#set_attribute will create a new AttributeDictionary if none exists.

Ie, dynamic groups must have a “dynamic_attributes” AttributeDictionary … and dynamic instances must have an AttributeDictionary at the least attached to their definition. (They might also have one attached at the instance level depending upon whether they can have attribute values that differ from those in the definition’s dictionary.)

1 Like

Add Volume script a la @DanRathbun

model = Sketchup.active_model
dco = $dc_observers.get_latest_class
model.selection.grep(Sketchup::ComponentInstance).each do |inst|
  dco.set_attribute(inst,"_volume_label","volume")
  dco.set_attribute(inst,"volume",inst.volume)
  dco.redraw_with_undo(inst)
end

This script updates all of the volume attributes in the model, created with the above script.

model = Sketchup.active_model
dict = "dynamic_attributes"
model.start_operation("Update Volume")

def select_children(instance)
  children = instance.definition.entities.select { |e| e.respond_to?(:definition) }
  instance.model.selection.add(children)
  children.each { |c| select_children(c) }
end

model.entities.each do |d|
  select_children(d)
  model.selection.add(d)
end

model.selection.each do |v|
  if v.get_attribute dict,"_volume_label","volume" == true
    v.set_attribute dict,"volume",v.volume
  end
end

model.selection.clear
model.commit_operation

… except that such code, I always wrap in a submodule within an author namespace module.

Ie, it is not nice to define global methods or global references other than a toplevel namespace module.

1 Like

Care to show me what that looks like? I always like to do my best to be nice…

Maybe like this?

module Build_Vitruvian
  module DC_volume #adds a volume in cubic inches attribute to a DC

    model = Sketchup.active_model.selection
    dco = $dc_observers.get_latest_class
    model.grep(Sketchup::ComponentInstance).each do |inst|
      dco.set_attribute(inst,"_volume_label","volume")
      dco.set_attribute(inst,"volume",inst.volume)
      dco.redraw_with_undo(inst)
    end

  end
end

And the rest…

module Build_Vitruvian
  module Update_DC_volume #updates all volume attributes created with DC_volume

    model = Sketchup.active_model
    dict = "dynamic_attributes"
    def select_children(instance)
      children = instance.definition.entities.select { |e| e.respond_to?(:definition) }
      instance.model.selection.add(children)
      children.each { |c| select_children(c) }
    end
    model.entities.each do |d|
     select_children(d)
     model.selection.add(d)
    end
    model.selection.each do |v|
      if v.get_attribute dict,"_volume_label","volume" == true
        v.set_attribute dict,"volume",v.volume
      end
    end
    model.selection.clear

  end
end