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!
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.
Set the active_path to an instance path of [..., group_a]
Thanks @DanRathbun , I tried your advice to change the code and got what I wanted.
# This method searches for a group by its name within a collection of entities.
def find_group_by_name(entities, name)
entities.each do |entity|
# Returns the entity if it is a group and its name matches the given name.
return entity if entity.is_a?(Sketchup::Group) && entity.name == name
# If the entity is a group or component instance, recursively search its definition's entities.
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
# Return nil if no matching group is found.
nil
end
# This method finds the instance path to a target entity within a collection of entities.
def find_instance_path(entities, target, path = [])
entities.each do |entity|
new_path = path + [entity] # Append the current entity to the path.
# Returns the new path if the current entity is the target.
if entity == target
return new_path
# If the entity is a group or component, recursively search its definition's entities.
elsif entity.is_a?(Sketchup::Group) || entity.is_a?(Sketchup::ComponentInstance)
found_path = find_instance_path(entity.definition.entities, target, new_path)
return found_path unless found_path.nil?
end
end
# Return nil if no path to the target is found.
nil
end
model = Sketchup.active_model
# Find groups by their names.
group1 = find_group_by_name(model.entities, "1")
group2 = find_group_by_name(model.entities, "2")
# If either group does not exist, print a message and exit.
if group1.nil? || group2.nil?
puts "One of the groups does not exist"
return
end
# Find the instance paths to each group.
path_to_group1 = find_instance_path(model.entities, group1)
path_to_group2 = find_instance_path(model.entities, group2)
if path_to_group1 && path_to_group2
# Calculate the transformation from group1 to group2 using their instance paths.
transformation_to_group1 = Sketchup::InstancePath.new(path_to_group1).transformation
transformation_to_group2 = Sketchup::InstancePath.new(path_to_group2).transformation
combined_transformation = transformation_to_group1.inverse * transformation_to_group2
# Add an instance of group2 to group1 with the calculated transformation.
new_group2 = group1.entities.add_instance(group2.definition, combined_transformation)
# Copy properties from the original group2 to the new instance.
new_group2.name = group2.name
new_group2.layer = group2.layer
new_group2.material = group2.material
# Copy attribute dictionaries from the original group2 to the new instance.
group2.attribute_dictionaries.each do |dict|
new_group2.attribute_dictionaries[dict.name].update(dict)
end if group2.attribute_dictionaries
# Erase the original group2.
group2.erase!
else
puts "Failed to find paths to the groups"
end