Save initial group transformation when moving between contexts (add_instance)

How does it work)?. For example, we have a parent group A that hosts group 1 and a parent group B that hosts group 2. I want to move group 2 to group 1. My code works fine if group 1 and group 2 are in the same context. If they are in different contexts (as in the example), then the placement of group 2 changes after the move. How to preserve group 2 transformation when moving it between contexts? Like how we just move groups between contexts in the outliner tray.
Here is the code:

ruby

def find_group_by_name(entities, name)
  entities.each do |entity|
    return entity if entity.is_a?(Sketchup::Group) && entity.name == name
    if entity.is_a?(Sketchup::Group) || entity.is_a?(Sketchup::ComponentInstance)
      result = find_group_by_name(entity.definition.entities, name)
      return result if result
    end
  end
  nil
end

model = Sketchup.active_model

group2 = find_group_by_name(model.entities, "2")

group1 = find_group_by_name(model.entities, "1")

if group1.nil? || group2.nil?
  puts "Одна з груп не існує"
  return
end

name = group2.name
layer = group2.layer
material = group2.material
attributes = group2.attribute_dictionaries

original_transformation = group1.transformation.inverse * group2.transformation

new_group2 = group1.entities.add_instance(group2.definition, original_transformation)

new_group2.name = name
new_group2.layer = layer
new_group2.material = material
attributes.each { |dict| new_group2.set_attribute(dict.name, dict.each_pair.to_h) } if attributes

group2.erase!

The simplest solution is to explode group B.

Thank you. And what is the more difficult solution?

Likely using InstancePath class and it’s #transformation method.

It also will depend upon whether the source context and the target context are on the same branch of the nesting hierarchy.


One possible way to do this is to take advantage of the fact that when in an editing context, the paste in place will use the transformation in world coordinates.

  1. Set the active_path to an instance path of [..., group_a]
  2. Select group_1: model.selection.clear; model.selection.add(group_1)
  3. Call Sketchup.send_action("cut:")
  4. Set the active_path to an instance path of [..., group_b]
  5. Call
    if Sketchup.platform == :platform_win
      Sketchup.send_action(21939)
    else
      Sketchup.send_action("pasteInPlace:")
    end
    

You might need to wait before step 5, until you verify that the active path has been changed to the target context.

1 Like

Thank you. Will have to try this)