Manipulate atribute ScaleTool of Dynamic Component

How can I control the active handles of the scaletool attribute?
I want to leave only the handles: x, y and z

    module Scale
      def self.wrap_selection(entities)
        return if entities.empty?

          mod = Sketchup.active_model
          sel = mod.selection
          sel.grep(Sketchup::ComponentInstance).each do |s|
            s.set_attribute "dynamic_attributes", "scaletool", "LMO"

            $dc_observers.get_latest_class.redraw_with_undo(s)
          end
        end
    end

Are you looking for this Class: Sketchup::Behavior — SketchUp Ruby API Documentation?

@Cabarsa wants to control the scale handles via the dynamic dictionary, but the linked API method does give the clue to integer value that must be set in the "dynamic_attributes" dictionary for dynamic definitions.

First of all, again, control attributes such as this are set upon the definition, not the instance.

Also, you should not be brute force setting attributes on selected objects unless you have verified that they actually are dynamic objects (ie, dynamic components or groups.)

Here is a simple method to test whether an object is a dynamic component or group:

def is_dynamic?(obj)
  return false unless obj.respond_to?(:definition)
  return true if obj.attribute_dictionary('dynamic_attributes')
  obj.definition.attribute_dictionary('dynamic_attributes') ? true : false
end

Referring to the #no_scale_mask= method that @curic4su linked above, you will see that the “switch” to turn off a certain scale handle is a bit in the mask of the integer 127.

  • Bit0: 1 disable scale along red (X)

  • Bit1: 2 disable scale along green (Y)

  • Bit2: 4 disable scale along blue (Z)

  • Bit3: 8 disable scale in red/blue plane (X+Z)

  • Bit4: 16 disable scale in green/blue plane (Y+Z)

  • Bit5: 32 disable scale in red/green plane (X+Y)

  • Bit6: 64 disable scale uniform (from corners) (XYZ)

If the value of the scaletool attribute is 0 then all handles are active and available to the user.

The sum of all bits is 127, so if the value was 127 then all scale handles would be switched off.

Since you want only x (1), y (2) and z (4), then subtract the sum of their bit values from 127 and you get 120.

    module Scale

      DISABLE_ALL_SCALING ||= 127
      DISABLE_SCALE_X ||= 1
      DISABLE_SCALE_Y ||= 2
      DISABLE_SCALE_Z ||= 4
      DISABLE_SCALE_XZ ||= 8
      DISABLE_SCALE_YZ ||= 16
      DISABLE_SCALE_XY ||= 32
      DISABLE_SCALE_UNIFORM ||= 64

      def self.is_dynamic?(obj)
        return false unless obj.respond_to?(:definition)
        return true if obj.attribute_dictionary('dynamic_attributes')
        obj.definition.attribute_dictionary('dynamic_attributes') ? true : false
      end # is_dynamic?()

      def self.wrap_selection(entities)
        return if entities.empty?
        allow_scaling = DISABLE_SCALE_X + DISABLE_SCALE_Y + DISABLE_SCALE_Z
        scaling = DISABLE_ALL_SCALING - allow_scaling
        entities.grep(Sketchup::ComponentInstance).each do |obj|
          next unless is_dynamic?(obj)
          dc = obj.definition
          dc.set_attribute('dynamic_attributes', 'scaletool', scaling.to_s)
          $dc_observers.get_latest_class.redraw_with_undo(obj)
        end
      end # wrap_selection()

    end # submodule
6 Likes

NOTE: Changing the scaling handle behaviors causes the DC extension to make that definition unique.

1 Like

Perfect. Thks again Dan.

1 Like