using Autodesk.Revit.ApplicationServices; using Autodesk.Revit.DB; using Autodesk.Revit.DB.Visual; using System.Diagnostics; using System.IO; using System.Text; namespace ShrlAlgoToolkit.Revit.Extensions; public static class MaterialExtensions { /// /// 获取材质外观 /// /// /// public static StringBuilder GetMaterialAppearanceInfo(this Material material) { var assetElem = material.Document.GetElement(material.AppearanceAssetId) as AppearanceAssetElement; var asset = assetElem.GetRenderingAsset(); StringBuilder sb = new(); for (var i = 0; i < asset.Size; i++) { var prop = asset[i]; sb.Append($"属性名:{prop.Name};值类型:{prop.Type};值:"); switch (prop.Type) { case AssetPropertyType.Unknown: break; case AssetPropertyType.Properties: break; case AssetPropertyType.Boolean: var propBool = prop as AssetPropertyBoolean; sb.Append(propBool?.Value); break; case AssetPropertyType.Enumeration: var propEnum = prop as AssetPropertyEnum; sb.Append(propEnum?.Value); break; case AssetPropertyType.Integer: var propInt = prop as AssetPropertyInteger; sb.Append(propInt?.Value); break; case AssetPropertyType.Float: break; case AssetPropertyType.Double1: var propDouble = prop as AssetPropertyDouble; sb.Append(propDouble?.Value); break; case AssetPropertyType.Double2: var propDouble2 = prop as AssetPropertyDoubleArray2d; foreach (var d in propDouble2.Value) { sb.Append($"{d},"); } break; case AssetPropertyType.Double3: var propDouble3 = prop as AssetPropertyDoubleArray3d; foreach (var d in propDouble3?.GetValueAsDoubles()) { sb.Append($"{d},"); } break; case AssetPropertyType.Double4: var propDouble4 = prop as AssetPropertyDoubleArray4d; foreach (var d in propDouble4?.GetValueAsDoubles()) { sb.Append($"{d},"); } break; case AssetPropertyType.Double44: break; case AssetPropertyType.String: var propStr = prop as AssetPropertyString; sb.Append(propStr?.Value); break; case AssetPropertyType.Time: break; case AssetPropertyType.Distance: break; case AssetPropertyType.Asset: break; case AssetPropertyType.Reference: break; case AssetPropertyType.Longlong: break; case AssetPropertyType.ULonglong: break; case AssetPropertyType.List: break; case AssetPropertyType.Float3: break; } sb.AppendLine(); } return sb; } /// /// 获取资产属性 /// /// /// /// public static AssetProperty FindByName(this Asset asset, string name) { #if REVIT2018 return asset[name]; #else return asset.FindByName(name); #endif } public static AssetProperty Get(this Asset asset, int index) { #if REVIT2018 return asset[index]; #else return asset.Get(index); #endif } #if REVIT2019 || REVIT2020 public static void ModifyAppearanceBitMap(this Material material, string bitmapPath) { using AppearanceAssetEditScope editScope = new(material.Document); Asset editableAsset = editScope.Start(material.AppearanceAssetId); AssetProperty assetProperty = editableAsset.FindByName("generic_diffuse"); Asset connectedAsset = assetProperty.GetConnectedProperty(0) as Asset; if (connectedAsset?.Name == "UnifiedBitmapSchema") { AssetPropertyString path = connectedAsset.FindByName(UnifiedBitmap.UnifiedbitmapBitmap) as AssetPropertyString; Debug.Assert(path != null, nameof(path) + " != null"); path.Value = bitmapPath; } editScope.Commit(true); } public static void ModifyAppearanceColor(Material material, string bitmapPath) { if (material != null) { Document doc = material.Document; ElementId appearanceAssetId = material.AppearanceAssetId; AppearanceAssetElement assetElem = doc.GetElement(appearanceAssetId) as AppearanceAssetElement; using Transaction t2 = new(doc); t2.Start("修改外观颜色"); using (AppearanceAssetEditScope editScope = new(assetElem.Document)) { // returns an editable copy of the appearance asset Asset editableAsset = editScope.Start(assetElem.Id); // Diffuse image AssetPropertyDoubleArray4d genericDiffuseProperty = editableAsset.FindByName("generic_diffuse") as AssetPropertyDoubleArray4d; genericDiffuseProperty.SetValueAsColor(new Color(100, 100, 100)); editScope.Commit(true); } t2.Commit(); } } #endif #if REVIT2019 || REVIT2020 public static void ChangeRenderingTexturePath(this Material mat, string texturePath) { using AppearanceAssetEditScope editScope = new(mat.Document); Asset editableAsset = editScope.Start(mat.AppearanceAssetId); //AssetProperty assetProperty = editableAsset["generic_diffuse"]; AssetProperty assetProperty = editableAsset.FindByName("generic_diffuse"); Asset connectedAsset = assetProperty.GetConnectedProperty(0) as Asset; if (connectedAsset.Name == "UnifiedBitmapSchema") { AssetPropertyString path = connectedAsset.FindByName(UnifiedBitmap.UnifiedbitmapBitmap) as AssetPropertyString; if (path.IsValidValue(texturePath)) { path.Value = texturePath; } } editScope.Commit(true); } #endif /// /// 读取标准外观库 /// /// /// public static StringBuilder GetAssetsInfo(this Application app) { #if REVIT2018 var assets = app.get_Assets(AssetType.Appearance); #else var assets = app.GetAssets(AssetType.Appearance); #endif StringBuilder sb = new(); foreach (Asset asset in assets) { ReadAsset(asset, sb); } return sb; } /// /// 读取资产 /// /// /// public static void ReadAsset(this Asset asset, StringBuilder objWriter) { //string libName = "assetlibrary_base.fbx"; //string name = asset.Name; objWriter.AppendLine($"{asset.Name}----{asset.LibraryName}"); for (var idx = 0; idx < asset.Size; idx++) { var prop = asset[idx]; ReadAssetProperty(prop, objWriter); } objWriter.AppendLine(); } /// /// 读取资产属性 /// /// /// private static void ReadAssetProperty(this AssetProperty prop, StringBuilder objWriter) { switch (prop.Type) { // Retrieve the value from simple type property is easy. // for example, retrieve bool property value. case AssetPropertyType.Integer: objWriter.Append(Enum.GetName(typeof(AssetPropertyType), prop.Type)); objWriter.Append(','); var assetPropertyInt = prop as AssetPropertyInteger; objWriter.AppendLine(assetPropertyInt.Name + "," + assetPropertyInt.Value); break; case AssetPropertyType.Distance: objWriter.Append(Enum.GetName(typeof(AssetPropertyType), prop.Type)); objWriter.Append(','); var assetPropertyDistance = prop as AssetPropertyDistance; objWriter.AppendLine(assetPropertyDistance.Name + "," + assetPropertyDistance.Value); break; case AssetPropertyType.Double1: objWriter.Append(Enum.GetName(typeof(AssetPropertyType), prop.Type)); objWriter.Append(','); var assetPropertyDouble = prop as AssetPropertyDouble; objWriter.AppendLine(assetPropertyDouble.Name + "," + assetPropertyDouble.Value); break; case AssetPropertyType.Double2: objWriter.Append(Enum.GetName(typeof(AssetPropertyType), prop.Type)); objWriter.Append(','); var assetPropertyDoubleArray2d = prop as AssetPropertyDoubleArray2d; objWriter.AppendLine(" : " + assetPropertyDoubleArray2d.Name + "," + assetPropertyDoubleArray2d.Value); break; case AssetPropertyType.Double4: objWriter.Append(Enum.GetName(typeof(AssetPropertyType), prop.Type)); objWriter.Append(','); var assetPropertyDoubleArray4d = prop as AssetPropertyDoubleArray4d; objWriter.AppendLine(assetPropertyDoubleArray4d.Name + "," + assetPropertyDoubleArray4d.GetValueAsDoubles()); break; case AssetPropertyType.String: objWriter.Append(Enum.GetName(typeof(AssetPropertyType), prop.Type)); objWriter.Append(','); var val = prop as AssetPropertyString; objWriter.AppendLine(val.Name + "," + val.Value); break; case AssetPropertyType.Boolean: objWriter.Append(Enum.GetName(typeof(AssetPropertyType), prop.Type)); objWriter.Append(','); var boolProp = prop as AssetPropertyBoolean; objWriter.AppendLine(boolProp.Name + "," + boolProp.Value); break; // When you retrieve the value from the data array property, // you may need to get which value the property stands for. // for example, the APT_Double44 may be a transform data. case AssetPropertyType.Double44: objWriter.Append(Enum.GetName(typeof(AssetPropertyType), prop.Type)); objWriter.Append(','); var transformProp = prop as AssetPropertyDoubleArray4d; objWriter.AppendLine(transformProp.Name + "," + transformProp.GetValueAsDoubles()); break; // The APT_List contains a list of sub asset properties with same type. case AssetPropertyType.List: objWriter.Append(Enum.GetName(typeof(AssetPropertyType), prop.Type)); objWriter.Append(','); var propList = prop as AssetPropertyList; var subProps = propList.GetValue(); if (subProps.Count == 0) { break; } switch (subProps[0].Type) { case (AssetPropertyType)4: foreach (var subProp in subProps) { objWriter.Append("子属性集---"); objWriter.Append(','); objWriter.Append(Enum.GetName(typeof(AssetPropertyType), subProps[0].Type)); objWriter.Append(','); var intProp = subProp as AssetPropertyInteger; objWriter.AppendLine(intProp.Name + "," + intProp.Value); } break; } break; case AssetPropertyType.Asset: objWriter.Append(Enum.GetName(typeof(AssetPropertyType), prop.Type)); objWriter.Append(','); var propAsset = prop as Asset; ReadAsset(propAsset, objWriter); break; case AssetPropertyType.Reference: objWriter.Append(Enum.GetName(typeof(AssetPropertyType), prop.Type)); objWriter.Append(','); break; default: objWriter.Append(Enum.GetName(typeof(AssetPropertyType), prop.Type)); objWriter.Append(','); objWriter.AppendLine("无类型" + prop.Type); break; } // Get the connected properties. // please notice that the information of many texture stores here. if (prop.NumberOfConnectedProperties == 0) { return; } foreach (var connectedProp in prop.GetAllConnectedProperties()) { // Note: Usually, the connected property is an Asset. ReadAssetProperty(connectedProp, objWriter); } } /// /// 获取材质贴图 /// /// /// 材质目录 public static void GetTexture(this Material material, FileInfo[] files) { var doc = material.Document; var appearance = doc.GetElement(material.AppearanceAssetId) as AppearanceAssetElement; var asset = appearance.GetRenderingAsset(); #if REVIT2018 var p = asset["unifiedbitmap_Bitmap"] as AssetPropertyString; //p.Value #elif REVIT2019 || REVIT2020 AssetPropertyString val = asset.FindByName("unifiedbitmap_Bitmap") as AssetPropertyString; if (val.Name == "unifiedbitmap_Bitmap" && val.Value.Contains("\\") && !File.Exists(val.Value)) { FileInfo originalFile = new(val.Value); foreach (var info in files) { if (info.Name == originalFile.Name) { val.Value = info.Name; } } } #endif for (var i = 0; i < asset.Size; i++) { #if REVIT2018 //using (StreamWriter writer = new StreamWriter("F:\\纤维板.txt")) //{ // ReadAsset(asset, writer); //} #elif REVIT2019 || REVIT2020 var prop = asset.Get(i); #endif } } }