Update Dynamic Components Instance values using Ruby API

Hi all,

I’m facing dynamic component instance values update problems using Ruby API. That ok if I want to update dynamic component definition, for example like this below :

  def cuDraw(argView)
    #Ensure the dynamic component is imported
    wallDivDCpath = "#{File.dirname(__FILE__)}/../DYN_WallDiv.skp"
    newDefinition = Sketchup.active_model.definitions.load(wallDivDCpath)

    #Place the dynamic component
    newInstance = Sketchup.active_model.entities.add_instance(newDefinition, Geom::Transformation.translation(@pickedPositions[0]))
    newInstance.make_unique
    newDefinitionAD = newInstance.definition.attribute_dictionaries["dynamic_attributes"]
    newInstanceAD = newInstance.attribute_dictionary("dynamic_attributes", true)

    #Adjust height [Z]
    #newInstanceAD["lenz"] = @height.mm.to_f
    newDefinitionAD["_lenz_nominal"] = @@heights[@heightSel].mm.to_f.to_s

    #Adjust Thickness [Y]
    #newInstanceAD["leny"] = @thickness.mm.to_f
    #newDefinitionAD["_leny_nominal"] = @thickness.mm.to_f.to_s
    newDefinitionAD["_leny_nominal"] = @@thickness[@thicknessSel].mm.to_f.to_s

    #Adjust Length [X]
    targetLength = @pickedPositions[0].distance(@pickedPositions[1])
    #newInstanceAD["lenx"] = targetLength.to_f.to_s
    newDefinitionAD["_lenx_nominal"] = targetLength.to_f.to_s

    #Orient it
    instanceVecor = newInstance.bounds.corner(0).vector_to(newInstance.bounds.corner(1)).normalize
    targetVector = @pickedPositions[0].vector_to(@pickedPositions[1]).normalize
    diagVector = @pickedPositions[0].vector_to(@pickedPositions[2]).normalize
    angleSign = instanceVecor.cross(diagVector).normalize.to_a.sum(0).round(0)
    angle = instanceVecor.angle_between(targetVector).round(3)
    rotationAxis = Geom::Vector3d.new(0,0,1)

    newInstance.transform!(Geom::Transformation.rotation(@pickedPositions[0], rotationAxis, angle * angleSign))

    #Mirror if matching conditions
    thickDir = @pickedPositions[1].vector_to(@pickedPositions[2]).normalize.to_a.round(0)
    lengthDir = @pickedPositions[0].vector_to(@pickedPositions[1]).normalize.to_a.round(0)
    mirror = [1,1,1]

    ##On Y axis
    if (lengthDir[0] > 0 and thickDir[1] < 0) or \
      (lengthDir[0] < 0 and thickDir[1] > 0)
      mirror[1] = -1

      ##On X axis
    elsif (lengthDir[1] > 0 and thickDir[0] > 0) or \
      (lengthDir[1] < 0 and thickDir[0] < 0)
      mirror[0] = -1
    end

    ##Apply mirror
    if mirror[0] < 0 or mirror[1] < 0
      newInstance.transform!(Geom::Transformation.scaling(@pickedPositions[0], mirror[0], mirror[1], mirror[2]))
    end

    #Apply component options dimensions
    newDefinitionAD["height"] = @@heights[@heightSel].mm.to_f.to_s
    newDefinitionAD["thickness"] = @@thickness[@thicknessSel].mm.to_f.to_s

    #Redraw the instance
    $dc_observers.get_latest_class.redraw_with_undo(newInstance)

    #Reset tool for a next usage
    cuResetTool(argView)
  end

But my problem is related todynamic component instance. I’ll show you a simple slope dynamic component that I tried to create :

Here is the code I tries to execute in the example video (some part of code related to the definition is mute, but the instance is activated):

#GET DYNAMIC COMPONENT INSTANCE
instance = Sketchup.active_model.selection[0]
instanceAD = instance.attribute_dictionaries["dynamic_attributes"]
#definition = instance.definition
#defintionAD = definition.attribute_dictionaries["dynamic_attributes"]

#DISPLAY DYNAMIC ATTRIBUTES
instanceAD.to_h

#SET DYNAMIC COMPONENT INSTANCE VALUES
#instanceAD["lenx"] = 2000.mm
instance.set_attribute("dynamic_attributes", "lenx", 2000.mm)
instanceAD.to_h["lenx"]

#REDRAW DYNAMIC COMPONENT
$dc_observers.get_latest_class.redraw_with_undo(instance)

You’ll see on the video that the redraw is done but visually nothing is updated…
0.0005521 seconds to redraw

What is wrong in my approch ?

Thank for your appreciated help :wink:

For info, I’m using Sketchup 2023 Pro 64-bit :

After a lot of time off research, I finaly found a solution without explicit explantions. But it’s related to the fact that I observed : Definition modification more than Instance modification, which is strange because the Instance has the positions and settings…

ONLY if the instance attributes DIFFER from the default attribute values defined in the definition’s "dynamic_attributes" dictionary. (Does not apply to dynamic subgroups whose attributes are always on the instance dictionary.)

So you always check the instance dictionary first for the existence of an attribute, and if it does not exist and is a component, then you check the definition’s dictionary.

2 Likes