Hi, Dezmo,
Sorry about that I did not describe the function clear but thank you for mentioning AttributeDictionaries and your overall suggestion that I should have done before.
This time I tried to include AttributeDictionaries in my code to store the information of the selected face. There are two functions: âbim_wallâ for creating the wall and âedit_parametersâ for editing the wall. In process, the user selects the âstartâ face and then use âbim_wallâ with its setting for thickness as well as material to create a wall. Then the user can select and edit the wall, created by âbim_wallâ related to the âstartâ face, with âedit_parametersâ.
To simply in this case, the wall created has just one layer (one component), but ideally, the wall can have more layers (components) as one component (a nested component) for both âbim_wallâ and âedit_parametersâ. I have done them separately. Here is the full code (I deleted the material application part), you could try it directly. I promise that I tested it countless timesâŚ
and it seems âlegalâ (but I am not 100% sure
):
def bim_wall
mod = Sketchup.active_model # Open model
ent = mod.entities # All entities in model
sel = mod.selection # Current selection
# Default values
material_1 = "CLT"
thickness_1_prompt = 100.mm
prompt = ["Material_1", "Thickness_1"]
values = [material_1, thickness_1_prompt]
list = ["Woodpanel|CLT|Timber frame with mineral wool", ""]
results = UI.inputbox(prompt, values, list, "Set Wall Parameters")
unless results == false # Check if user clicked "Cancel" or "Close"
material_1 = results[0]
thickness_1_prompt = results[1].to_l # Convert input value to length
# Create a new group for the face(s) selected by the user
only_faces = sel.grep(Sketchup::Face)
only_faces.each do |f|
group = ent.add_group(f)
# Extrude the face to create a wall with the specified thickness
f.pushpull(thickness_1_prompt)
# Convert the group to a component and set its name and attributes
inst = group.to_component
inst.definition.name = "#{material_1}"
inst.name = thickness_1_prompt.to_s
# Create an attribute dictionary for the component
attribute_dict = inst.attribute_dictionary("MyComponentParams", true)
attribute_dict["material_1"] = material_1
attribute_dict["thickness_1_prompt"] = thickness_1_prompt
attribute_dict["selected_face"] = f.persistent_id.to_s
end
end
end
def edit_parameters
mod = Sketchup.active_model # Open model
sel = mod.selection # Current selection
# Retrieve the selected component
selected_component = sel.grep(Sketchup::ComponentInstance).first
# Check if a component is selected
if selected_component
# Retrieve the attribute dictionary of the component
attribute_dict = selected_component.attribute_dictionary("MyComponentParams")
# Check if the attribute dictionary exists
if attribute_dict
# Retrieve the existing values for material_1 and thickness_1_prompt
material_1 = attribute_dict["material_1"]
thickness_1_prompt = attribute_dict["thickness_1_prompt"]
# Default values for the input box
default_values = [material_1, thickness_1_prompt.to_s]
# List of options for the material selection
list = ["Woodpanel|CLT|Timber frame with mineral wool", ""]
# Prompt the user to edit the values
prompt = ["Material_1", "Thickness_1"]
results = UI.inputbox(prompt, default_values, list, "Edit Parameters")
# Update the attribute values and component properties
unless results == false # Check if user clicked "Cancel" or "Close"
material_1 = results[0]
thickness_1_prompt = results[1].to_l # Convert input value to length
attribute_dict["material_1"] = material_1
attribute_dict["thickness_1_prompt"] = thickness_1_prompt
# Set the material for the face
# Retrieve the selected face
selected_face_id = attribute_dict["selected_face"]
selected_face = selected_component.definition.entities.find { |entity| entity.is_a?(Sketchup::Face) && entity.persistent_id.to_s == selected_face_id }
# Create a new group for the copied face
group_selected_face = mod.entities.add_group(selected_face)
copied_face_group = group_selected_face.copy
# Select the face inside the copied group
copied_face = copied_face_group.entities.grep(Sketchup::Face).first
# Set the material for the face
# Extrude the face to create a wall with the specified thickness (LenY)
copied_face.reverse!.pushpull(thickness_1_prompt)
# Convert the group to a component and set its name and attributes
inst = copied_face_group.to_component
inst.definition.name = "#{material_1}"
inst.name = thickness_1_prompt.to_s
# Create an attribute dictionary for the component
new_attribute_dict = inst.attribute_dictionary("MyComponentParams", true)
new_attribute_dict["material_1"] = material_1
new_attribute_dict["thickness_1_prompt"] = thickness_1_prompt
new_attribute_dict["selected_face"] = selected_face.persistent_id.to_s
# Erase the original selected component
selected_component.erase!
end
end
end
end
# Add a menu item for the plugin
UI.menu("Plugins").add_item("BimWall") do
bim_wall
end
# Add a menu item for editing parameters
UI.menu("Plugins").add_item("Edit Parameters") do
edit_parameters
end
The key is to store the information of the selected face âfâ in âbim_wallâ by âf.persistent_idâ and to reuse it when run âedit_parametersâ.
When I run the function âbim_wallâ to create the wall and, after that, modify the wall with the function âedit_parametersâ, no errors showed in Ruby Console, but the wallâs coordination after âeditâ is based on origin (0, 0, 0) again rather than the previous wall. (Please see image and yes, you mentioned it for me but here it is little bit more complex to fix).
And when I âeditâ the wall after âeditâ, Ruby Console shows âError: #<TypeError: wrong argument type (expected Sketchup::Entity)>â. These have exceeded the ceiling of my knowledge in Ruby. Help!!
I have a vision that if the wall, created with âbim_wallâ, has more layers (components) as one component (a nested component) and the âstart faceâ information is stored in AttributeDictionaries, âedit_parametersâ can also retrieve the âstart faceâ in that nested component for further edit (create).
Thank you very much for your time and patience!