With my plugin I am grabbing a components instances and getting those points.
instances = comp.instances
# Create a points array to hold all the coordinates for each instance
pts = []
# Loop through each instances and save the coordinates
instances.each { |inst|
point = inst.transformation.origin
px = point.x
py = point.y
pz = point.z
pts.push (point)
}#instances.each
Then I am using those points to swap that component with another. Everything works well and the components swap at the correct point. The only issue I am having is if I save out the component. Then I open a new sketchup file and I drag my saved skp file into my new model. Say the original saved component was placed at the origin, and I drag it into the new model and place it anywhere but the origin. When I am going to get the point, I do not get the new point, I get the origin.
Once I explode the imported component it picks up the new point, but still remembers the origin point. So when I go to swap the component it swaps at the new point and the origin.
How can I work around this behavior?
I am placing components in the model like the picture above. It is in a “model” mode. Then I have a button the user can press to preview what that “model” looks like(It’s just a simple billboarding model, basically a rectangle with a texture on it). Which is the second picture. I am hiding the components in the top picture and placing their matching “texture” mode components where they are in the scene.
The user can not move or edit the “texture” mode component. But they can move the “model” mode. If they edit the “model” mode, like move the guy on the right forward some, and then go back to the preview “texture” mode, it updates the position accordingly.
Everything works great when they are placing the components in the model. Its when I save out the guys and then try to import the model into a new model that I lose this ability.
So I saved the model in the images above, and below is after I dragged that model into a new skp file. I drop them away from the origin.
# Create array to hold Model Mesh components
m_components = []
# Create array to hold Preview Texture components
p_components = []
#Go through each component checking the attributes
definitions.each { |d|
if d.attribute_dictionaries
mValue = d.get_attribute("A", "PreviewMode")
preValue = d.get_attribute("A", "PreviewId")
#If the model component has a PreviewMode attached add it to the m_component array
if (mValue != nil)
m_components.push(d)
end#if
#If the component is a preview component, add it to the p_component array
if (preValue != nil)
p_components.push(d)
end#if
end#if
}# definitions.each
When I create my components I add a “PreviewMode” attribute to the “model” components(They also have an ID that I give them, but I don’t need that at this part). When I create the “model” component, I also create a matching preview component that goes with it, but I do not use it until the mode is toggled. I loop through the definitions and find all the components I need to perform the toggle. I then loop through all the m_components and get each position in the model.
m_components.each { |comp|
instances = comp.instances
pts = []
instances.each { |inst|
inst.layer = rpcLayer
point = inst.transformation.origin
px = point.x
py = point.y
pz = point.z
pts.push (point)
}#instances.each
# Set the index location for the array to the beginning
indexLocation = 0
savedIndex = nil
#Get the ID and store it in "tempID"
if comp.attribute_dictionaries
v = comp.get_attribute("A", "ID")
tempID = v
end#if
#Loop through the Preview Components to find the ID that
# matches the model component "tempID"
p_components.each {|preComp|
if preComp.attribute_dictionaries
pID = preComp.get_attribute("A", "PreviewId")
if (pID == tempID)
# When a match is found save the location in the p_components array to
# grab that component for the swap
savedIndex = indexLocation
end#if
end#if
indexLocation = indexLocation + 1
}#preview_components.each
# Grab the matching component
swapComp = p_components[savedIndex]
#Swap the preview component for the model component at each
# matching instance coordinate.
pts.each { |pt|
new_instance = entities.add_instance(swapComp, pt)
#Lock the preview component instance so that the original
# geometry of the model component cannot be changed.
status = new_instance.locked = true
}#pts.each
}#m_components.each
FYI, the attribute_dictionaries collection is shared by all extensions. It may not be good to use simple dictionary names that other extensions might also use. (Name clash)
It is good practice to prefix your dictionary name with author name and plugin name. Often you can use the qualification of the encapsulating modules. DICT = ECW_Peoplifier_A
or more plyable (allowing outer modules to be renamed at will): DICT = Module::nesting[0].name.gsub('::','_')
Using a constant in your get_attribute calls is better, more easily maintained, and uses less string memory space. (You’re using multiple literal string objects that could share a single string object.)