Hi Everyone,
I got few queries. I’m having a Revit family (.rfa) that I need to use in sketchup (Version 2023). in other wors I need to create a skp file out of the rfa file with all the visible properties (Material/ transparency/ color etc.) preserved.
I can’t directly import the rfa file into sketchup. Hence I’m first exporting a dwg from rfa file and then to import the dwg in SketchUp model. In this process it then loses the properties like material and transparency etc. which is required to remain same. Though I’ve successfully imported the dwg file using ruby API.
Now I’m trying to assign a material for imported family (dwg) in SketchUp but I’m not getting how to access all different entities available in the imported component (dwg) like different faces, or solids (entities) maybe.
Can anyone please suggest something here or maybe if you can tell me an alternative and preferable approach?
In the attached drawing of a door I have multiple glass panels and Metallic frame for the door and for the multiple glass panels. All I want is to assign different materials to frame and glass panels here using ruby API.
I missed to communicate that I’m able to import the dwg file using ruby API but I’m not sure how can I assign different materials to the entities existing in the component instance (imported dwg). Now I’ve edited the question as well for avoiding such confusion further.
I see. You can assign materials of the faces of the component definition entities.
You need to define some criteria’s to be able to decide which faces are the panel and which one is the frame.
My idea below is to get the faces in a component definition in a question (here the name of the component “Family_Test - Family_Test-67707-3D”) , check the area of faces, determine the maximum.
Then iterate all faces and set different material ( here is “red” & “black” ) if its area is above or below of the 90% of the max area.
You need to know the definition name
def color_my_componet( name, panel_material, frame_material )
model = Sketchup.active_model
definitions = model.definitions
my_defi = definitions.find{|d|
#d.name = name edited:
d.name == name
}
faces = my_defi.entities.grep(Sketchup::Face)
max_area = faces.map(&:area).max
model.start_operation('Color my component', true)
faces.each{|f|
if f.area > 0.9 * max_area
f.material = panel_material
f.back_material = panel_material
else
f.material = frame_material
f.back_material = frame_material
end
}
model.commit_operation
end
color_my_componet( "Family_Test - Family_Test-67707-_3D_", "red", "black" )
Hi,
This code works fine only if I close sketchup after importing the dwg and saving the file. I’m not able to do import and material assignment task in one go without closing and reopening the file again.
Any guess, What’s I’m missing? I’ve use “model.commit_operation” after both the tasks.
I guess you imported the same dwg second time which will give an unique name for newly implored definition : “Family_Test - Family_Test-67707-3D#1”), because there is a definition there with a same name already.
Since you are calling again the color_my_componet method with the original name it will color the original component definition entities, not the newly imported one.
To avoid it, you can rename the definition after colored, so the new definition can get its original name.
E.g:
def color_my_componet( name, panel_material, frame_material )
model = Sketchup.active_model
definitions = model.definitions
my_defi = definitions.find{|d|
d.name == name
}
faces = my_defi.entities.grep(Sketchup::Face)
max_area = faces.map(&:area).max
model.start_operation('Color my component', true)
faces.each{|f|
if f.area > 0.9 * max_area
f.material = panel_material
f.back_material = panel_material
else
f.material = frame_material
f.back_material = frame_material
end
}
my_defi.name = name + "-colored"
model.commit_operation
end
color_my_componet( "Family_Test - Family_Test-67707-_3D_", "red", "black" )
I’ve found the issue. Actually, when I print the available definitions, it shows that the definition “Test_Project - 3D View - {3D}.dwg” is available, but the code says that available faces for the definition is zero. It happens when the code is run for first time.
If the script is run further (after doing undo the operation of this material assignment), it shows that there’s no definition for “Test_Project - 3D View - {3D}.dwg”. How is it possible that the entity is available in model, has a definition but has no faces at all?
As I’m not getting how I can setup a debug functioning for the code with SU, I’m getting nowhere. Below is the code I’m using as per your suggestion. Though there are a few changes to track the execution as I’m unable to debug it.
def color_my_componet( name, panel_material, frame_material )
model = Sketchup.active_model
puts "\n************* \navailable definitions are:"
definitions = model.definitions
definitions.each{|definition|
puts definition.name
}
my_defi = definitions.find{|d|
d.name == name
}
if my_defi == nil
puts "Nil definition"
else
faces = my_defi.entities.grep(Sketchup::Face)
# puts my_defi.name + "has a total faces => "
puts faces.length
max_area = faces.map(&:area).max
model.start_operation('Color my component', true)
materials = model.materials
number = materials.length
puts number
materials.each{|mat|
puts mat.name
}
areaInStr = max_area.to_s()
puts "Max area is "+areaInStr
if faces.length > 0
faces.each{|f|
if f.area > 0.1 * max_area
f.material = panel_material
f.back_material = panel_material
puts "Face color updated"
else
f.material = frame_material
f.back_material = frame_material
end
}
else
puts "Zero faces are available for definition"
end
end
model.commit_operation
end
entityName = "Test_Project - 3D View - {3D}.dwg"
color_my_componet( entityName, "red", "black")
model.commit_operation
Output for 1st attempt:
*************
available definitions are:
Family_Test - Family_Test-67707-_3D_
Heather
Test_Project - 3D View - {3D}.dwg
0
21
Heather_Hair2
Heather_Shirt
Heather_PantShadow
Heather_Band
Heather_Stripe1
Heather_Stripe2
Heather_ShirtShadow
Heather_Hair
Heather_Soles
Heather_Jeans
Heather_Hat
Heather_Cuffs
Heather_Shoes
Heather_Brim
Heather_Skin
Lily_Dark
Lily_Blonde
Lily_Light
Heather_Brim1
<auto>
Translucent Glass Tinted
Max area is
Zero faces are available for definition
Output in next attempts:
*************
available definitions are:
Family_Test - Family_Test-67707-_3D_
Heather
Test_Project - 3D View - {3D}.dwg
Nil definition
The “debug functioning” you are using here - writing a puts inside the code to some “critical” place - is totally fine. I’m using that too and never ever used VScode or any other debugger…
Back to topic:
No.
It is modified code!
Also I do not see how did you called (witch parameters you used for) the def color_my_componet method.
I guess you used “Test_Project - 3D View - {3D}.dwg” as a first parameter.
Therefore, certainly there are no faces, because that definition does contains only a instance of the “Family_Test - Family_Test-67707-3D” definition. The faces are in the second (nested) one.
I’ve used both as parameter. When passing “Family_Test - Family_Test-67707-3D” as parameter faces are available but when I pass “Test_Project - 3D View - {3D}.dwg” as first parameter of color_my_component function I get zero faces. So, I understood the point that DWG will not contain the faces but the exported family from rfa to dwg.
Now the function works well when the code is run for first time.
Still, If the script is run further (after doing undo the operation of this material assignment), it shows that there’s no definition for “Family_Test - Family_Test-67707-3D”. How is it possible that the entity is available in model, but not the definition?
Below is the code I’m using as per your suggestion. Though there are a few changes to track the execution as I’m unable to debug it.
def color_my_componet( name, panel_material, frame_material )
model = Sketchup.active_model
puts "\n************* \navailable definitions are:"
definitions = model.definitions
definitions.each{|definition|
puts definition.name
}
my_defi = definitions.find{|d|
d.name == name
}
if my_defi == nil
puts "Nil definition"
else
faces = my_defi.entities.grep(Sketchup::Face)
# puts my_defi.name + "has a total faces => "
puts faces.length
max_area = faces.map(&:area).max
model.start_operation('Color my component', true)
materials = model.materials
number = materials.length
puts number
materials.each{|mat|
puts mat.name
}
areaInStr = max_area.to_s()
puts "Max area is "+areaInStr
if faces.length > 0
faces.each{|f|
if f.area > 0.1 * max_area
f.material = panel_material
f.back_material = panel_material
puts "Face color updated"
else
f.material = frame_material
f.back_material = frame_material
end
}
else
puts "Zero faces are available for definition"
end
end
model.commit_operation
end
entityName = "Family_Test - Family_Test-67707-_3D_"
color_my_componet( entityName, "red", "black")
model.commit_operation
Output for 1st attempt:
*************
available definitions are:
Family_Test - Family_Test-67707-_3D_
Heather
Test_Project - 3D View - {3D}.dwg
8302
21
Heather_Hair2
Heather_Shirt
Heather_PantShadow
Heather_Band
Heather_Stripe1
Heather_Stripe2
Heather_ShirtShadow
Heather_Hair
Heather_Soles
Heather_Jeans
Heather_Hat
Heather_Cuffs
Heather_Shoes
Heather_Brim
Heather_Skin
Lily_Dark
Lily_Blonde
Lily_Light
Heather_Brim1
<auto>
Translucent Glass Tinted
Max area is 3867.792825117733
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Face color updated
Output in next attempts:
*************
available definitions are:
Family_Test - Family_Test-67707-_3D_
Heather
Test_Project - 3D View - {3D}.dwg
Nil definition
Always code defensively. And always check to be sure that you have objects or entities to operate upon before your code starts an undo operation.
This means that following the grep for faces, your code should “bail out” from the method if faces.empty? and then an operation would not be started (because there would be nothing to undo.)
Instead, your code above, does not check the number of faces until after the operation is started.
Also, a bit of coding style.
faces.each{|f|
… should be typed as … faces.each { |f|
Ie, the spacing of { should be the same as if you used do … end.
faces.each do |f|
puts face.material.name
end
faces.each { |f|
puts face.material.name
}
You are not gaining speed and are suffering readability by running everything together.
Lastly, all statements within the block should be indented.
Lets examine your model. (You posted above)
Open the Entity Info and Outliner Tray. And don’t lose sight of what it shows. (Never)
Your dwg file imported as a component. The component definition name is Test_Project - 3D View - {3D}.dwg Select its instance and double click on it to go to its editing context. (You are editing now the instance definition, and can see its entities).
If you select all (e.g. Ctrl + A) you will be realized the selection is contains only one entity (or its superclass: drawingelment) which is an instance of the component named: Family_Test - Family_Test-67707-_3D_. There is no other entities , like face or edge there.
You need to double click on it to go to its editing context to be able to access the faces to paint.
The definition list of the model (Sketchup.active_model.definitions) contains all the definition of the model, independently how deeply nested their instances in a model. Even (can) contain the definitions which don’t have its instance in a model. So if you are deleting the component (instance) from the model the definition still can be there. You need to purge it (most of the case).