Perhaps I'm missing something in the UI about assigning materials to categories but...

Perhaps I'm missing something in the UI about assigning materials to categories but...

GaryOrrMBI
Collaborator Collaborator
443 Views
4 Replies
Message 1 of 5

Perhaps I'm missing something in the UI about assigning materials to categories but...

GaryOrrMBI
Collaborator
Collaborator

While I was looking at some stuff concerning wall layers I ran across this code sample in the API help:

 

Public Sub GetWallLayerMaterial(document As Autodesk.Revit.DB.Document, wall As Wall)
    ' get WallType of wall
    Dim aWallType As WallType = wall.WallType
    ' Only Basic Wall has compoundStructure
    If WallKind.Basic = aWallType.Kind Then
        ' Get CompoundStructure
        Dim comStruct As CompoundStructure = aWallType.GetCompoundStructure()
        Dim allCategories As Categories = document.Settings.Categories

        ' Get the category OST_Walls default Material; 
        ' use if that layer's default Material is <By Category>
        Dim wallCategory As Category = allCategories.Item(BuiltInCategory.OST_Walls)
        Dim wallMaterial As Autodesk.Revit.DB.Material = wallCategory.Material

        For Each structLayer As CompoundStructureLayer In comStruct.GetLayers()
            Dim layerMaterial As Autodesk.Revit.DB.Material = TryCast(document.GetElement(structLayer.MaterialId), Material)

            ' If CompoundStructureLayer's Material is specified, use default
            ' Material of its Category
            If layerMaterial Is Nothing Then
                Select Case structLayer.[Function]
                    Case MaterialFunctionAssignment.Finish1
                        layerMaterial = allCategories.Item(BuiltInCategory.OST_WallsFinish1).Material
                        Exit Select
                    Case MaterialFunctionAssignment.Finish2
                        layerMaterial = allCategories.Item(BuiltInCategory.OST_WallsFinish2).Material
                        Exit Select
                    Case MaterialFunctionAssignment.Membrane
                        layerMaterial = allCategories.Item(BuiltInCategory.OST_WallsMembrane).Material
                        Exit Select
                    Case MaterialFunctionAssignment.[Structure]
                        layerMaterial = allCategories.Item(BuiltInCategory.OST_WallsStructure).Material
                        Exit Select
                    Case MaterialFunctionAssignment.Substrate
                        layerMaterial = allCategories.Item(BuiltInCategory.OST_WallsSubstrate).Material
                        Exit Select
                    Case MaterialFunctionAssignment.Insulation
                        layerMaterial = allCategories.Item(BuiltInCategory.OST_WallsInsulation).Material
                        Exit Select
                    Case Else
                        ' It is impossible to reach here
                        Exit Select
                End Select
                If layerMaterial Is Nothing Then
                    ' CompoundStructureLayer's default Material is its SubCategory
                    layerMaterial = wallMaterial
                End If
            End If
            TaskDialog.Show("Revit", "Layer Material: " & layerMaterial.ToString())
        Next
    End If
End Sub

 

According to that sample a person should be able to assign default materials to the function sub-categories of walls.

 

The UI has no such ability:

 

GaryOrrMBI_0-1710517499598.png

 

So the code sample always returns the material assigned to the main Walls category for each layer if the layer does not have a material assignment (it never returns any material assigned to the wall function subcategories because there isn't any way to assign a material to them).

 

What am I missing?

 

-G

Gary J. Orr
GaryOrrMBI (MBI Companies 2014-Current)
aka (past user names):
Gary_J_Orr (GOMO Stuff 2008-2014);
OrrG (Forum Studio 2005-2008);
Gary J. Orr (LHB Inc 2002-2005);
Orr, Gary J. (Gossen Livingston 1997-2002)
0 Likes
444 Views
4 Replies
Replies (4)
Message 2 of 5

ctm_mka
Collaborator
Collaborator

You can assign the subcats material in the wall definition, but as you noted, not as a default object style.

ctm_mka_1-1710539826320.png

 

0 Likes
Message 3 of 5

RPTHOMAS108
Mentor
Mentor

It is a strange sample yes, then again it is strange to have a 'Exit Select' statement after each case and show a task dialogue separately for every wall layer (hopefully there aren't many wall layers).

0 Likes
Message 4 of 5

GaryOrrMBI
Collaborator
Collaborator

OK, so it isn't just me 🙂

The Revit API is hard enough to navigate and figure out even when the samples are viable, then you run across things like this that simply can't ever work (well, technically this works because it doesn't error out, but it leads you down an incorrect path to do it)...

 

And yeah, @RPTHOMAS108 , there are several examples in the help that use an Exit Select in a Select Case statement... tons of other oddities as well, especially in the VB samples, that makes me think that most are being translated from another code language and getting a bit scrambled along the way. I always try to compare the VB samples to the C# samples, thinking that it might help me along the way in trying to learn C# but... it often just confuses me more since I don't know if those samples are composed any better than the VB versions 🙂

 

Thanks for the comments,

-G

Gary J. Orr
GaryOrrMBI (MBI Companies 2014-Current)
aka (past user names):
Gary_J_Orr (GOMO Stuff 2008-2014);
OrrG (Forum Studio 2005-2008);
Gary J. Orr (LHB Inc 2002-2005);
Orr, Gary J. (Gossen Livingston 1997-2002)
0 Likes
Message 5 of 5

TripleM-Dev.net
Advisor
Advisor

Hi,

 

The internal categories for layers have never been assigned a material.

The user can't add/edit those so a app should first assign the materials to these categories.

 

I've just tried to assign them materials (by a wall type with all functions defined with a material) and assigned the materials to the internal categories by function. Apparently this is possible, the materials are saved with the internal categories (something that can't be done in the UI!)

 

And then do the reverse (something like the posted code) and set those materials to a walltype without materials defined in the layers.

 

Below a quick sample code, variables needed the Id of the WallType + LayerFromWall or not.

Doesn't check if there's already a material attached etc...

 

			Dim UiApp As UIApplication = commandData.Application
			Dim doc As Document = UiApp.ActiveUIDocument.Document

			Dim SetLayersFromWall As Boolean = True
			Dim GetLayeredMaterialsOfWallTypeId As Integer = 348734

			Dim WallTypeObj As WallType = CType(doc.GetElement(New ElementId(GetLayeredMaterialsOfWallTypeId)), WallType)

			Dim WallCompStr As CompoundStructure = WallTypeObj.GetCompoundStructure()
			Dim AllCats As Categories = doc.Settings.Categories

			Dim edits As Integer = 0
			Using myt As Transaction = New Transaction(doc, "Set Default LayerFunctions")
				myt.Start()
				Try
					Dim index As Integer = 0
					For Each matlayer As CompoundStructureLayer In WallCompStr.GetLayers

						If SetLayersFromWall Then

							'Retrieve materials of a WallType and save the materials to the matching internal function category
							If matlayer.MaterialId <> ElementId.InvalidElementId Then
								Dim layerMatObj As Material = CType(doc.GetElement(matlayer.MaterialId), Material)

								Select Case matlayer.Function
									Case MaterialFunctionAssignment.Finish1
										AllCats.Item(BuiltInCategory.OST_WallsFinish1).Material = layerMatObj
									Case MaterialFunctionAssignment.Finish2
										AllCats.Item(BuiltInCategory.OST_WallsFinish2).Material = layerMatObj
									Case MaterialFunctionAssignment.Insulation
										AllCats.Item(BuiltInCategory.OST_WallsInsulation).Material = layerMatObj
									Case MaterialFunctionAssignment.Structure
										AllCats.Item(BuiltInCategory.OST_WallsStructure).Material = layerMatObj
									Case MaterialFunctionAssignment.Substrate
										AllCats.Item(BuiltInCategory.OST_WallsSubstrate).Material = layerMatObj
								End Select
							End If
						Else

							'Reverse, get the material from the internal function category and set it to the Function layer
							Dim GetMaterialOfCategory As Category = Nothing
							Select Case matlayer.Function
								Case MaterialFunctionAssignment.Finish1
									GetMaterialOfCategory = AllCats.Item(BuiltInCategory.OST_WallsFinish1)
								Case MaterialFunctionAssignment.Finish2
									GetMaterialOfCategory = AllCats.Item(BuiltInCategory.OST_WallsFinish2)
								Case MaterialFunctionAssignment.Insulation
									GetMaterialOfCategory = AllCats.Item(BuiltInCategory.OST_WallsInsulation)
								Case MaterialFunctionAssignment.Structure
									GetMaterialOfCategory = AllCats.Item(BuiltInCategory.OST_WallsStructure)
								Case MaterialFunctionAssignment.Substrate
									GetMaterialOfCategory = AllCats.Item(BuiltInCategory.OST_WallsSubstrate)
							End Select

							If Not (IsNothing(GetMaterialOfCategory)) Then
								WallCompStr.SetMaterialId(index, GetMaterialOfCategory.Material.Id)
							End If

							index += 1
						End If
					Next

					If Not (SetLayersFromWall) Then WallTypeObj.SetCompoundStructure(WallCompStr)

				Catch ex As Exception
					'MessageException(ex,, "Error layer materials")
				End Try

				myt.Commit()
			End Using

 

 

- Michel

0 Likes