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
}
}
}