using Autodesk.Revit.DB; using Autodesk.Revit.DB.Visual; using Autodesk.Revit.UI; using CommunityToolkit.Mvvm.ComponentModel; using CommunityToolkit.Mvvm.Input; using Nice3point.Revit.Toolkit.External.Handlers; using System; using System.Collections.ObjectModel; using System.Linq; using System.Runtime.InteropServices; using System.Windows.Controls; using Szmedi.RvKits.Assists; namespace Szmedi.RvKits.ModelManager; public partial class MaterialBatchViewModel : ObservableObject { public MaterialBatchViewModel(UIApplication uiapp) { doc = uiapp.ActiveUIDocument.Document; var mats = new FilteredElementCollector(doc).OfClass(typeof(Material)).Cast(); materials = new ObservableCollection(mats); this.uiapp = uiapp; materialHandler = new(); } private readonly ActionEventHandler materialHandler; private readonly Document doc; private readonly ObservableCollection materials; private readonly UIApplication uiapp; [ObservableProperty] private bool isFloor = true; [ObservableProperty] private bool isStructuralColumn = true; [ObservableProperty] private bool isStructuralFraming = true; [ObservableProperty] private bool isWall = true; [ObservableProperty] [NotifyPropertyChangedFor(nameof(FilteredList))] private string searchText; [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(ApplyCustomMaterialCommand))] private Material selectedMaterial; //[RelayCommand] //private void MaterialEdit() //{ // RevitCommandId commandId = RevitCommandId.LookupPostableCommandId(PostableCommand.Materials); // // var ptr = WinIntPtr.FindWindow(null, "材质浏览器"); // var mainWindowHandle = System.Diagnostics.Process.GetCurrentProcess().MainWindowHandle; // if (mainWindowHandle != IntPtr.Zero) // { // IntPtr materialDialog = WinIntPtr.FindWindowEx(mainWindowHandle, IntPtr.Zero, null, null); // if (materialDialog != IntPtr.Zero) // { // if (uiapp.CanPostCommand(commandId)) // { // Revit.Async.RevitTask.RunAsync(() => // { // uiapp.PostCommand(commandId); // } // ); // } // } // } //} public IEnumerable FilteredList => IsIllumMaterial == true ? GetEmissiveMat(doc) : string.IsNullOrEmpty(SearchText) ? materials : materials.Where(x => x.Name.Contains(SearchText)); [ObservableProperty] [NotifyPropertyChangedFor(nameof(FilteredList))] private bool? isIllumMaterial = false; [RelayCommand(CanExecute = nameof(StandardCanRun))] private void ApplyStandardMaterial(ComboBoxItem item) { var materialName = item.Content.ToString(); materialHandler.Raise(uiapp => { try { #if REVIT2018 var assetPropertyConcreteVersionGuid = "ACADGen-006"; var assetPropertyMetalVersionGuid = "Metal-047"; //缎光 // string assetPropertyMetalVersionGuid = "InvGen-028";//钢板 #elif REVIT2019 || REVIT2020 string assetPropertyConcreteVersionGuid = "Prism-1100"; //如果有贴图,前缀加上t_就是贴图的文件名 string assetPropertyMetalVersionGuid = "Metal-047"; #endif Material material = null; StandardCanRun = false; using (var tg = new TransactionGroup(doc, $"应用标准{materialName}材质")) { tg.Start(); using (Transaction ts = new(doc, $"{materialName}材质创建")) { ts.Start(); if (materialName == "混凝土") { material = CreateConcreteMaterial( uiapp, "混凝土,现场浇注", "混凝土", "混凝土 - 现场浇注", assetPropertyConcreteVersionGuid, new Color(192, 192, 192) ); } else if (materialName == "钢") { material = CreateConcreteMaterial(uiapp, "金属,钢", "金属", "钢材", assetPropertyMetalVersionGuid, new Color(247, 247, 247)); } else { ts.RollBack(); } ts.Commit(); } ApplyMaterial(material); tg.Assimilate(); } } catch (Exception) { } StandardCanRun = true; }); } [RelayCommand(CanExecute = nameof(CanApplyCustomMaterial))] private void ApplyCustomMaterial(Material material) { materialHandler.Raise(_ => { CustomCanRun = false; try { ApplyMaterial(material); } catch (Exception) { } CustomCanRun = true; }); } private void ApplyMaterial(Material material) { var framingCatId = Category.GetCategory(doc, BuiltInCategory.OST_StructuralFraming).Id; var columnCatId = Category.GetCategory(doc, BuiltInCategory.OST_StructuralColumns).Id; try { var elements = uiapp.ActiveUIDocument.Selection .PickElementsByRectangle( new FuncFilter( elem => { var flag1 = IsFloor && elem is Floor; var flag2 = IsWall && elem is Wall wall && wall.WallType.Kind == WallKind.Basic; var flag3 = IsStructuralColumn && elem is FamilyInstance && elem.Category.Id == columnCatId; var flag4 = IsStructuralFraming && elem is FamilyInstance && elem.Category.Id == framingCatId; return flag1 || flag2 || flag3 || flag4; }, (_, _) => true), "请框选元素"); using Transaction ts = new(doc, $"应用{material.Name}材质"); ts.Start(); foreach (var elem in elements) { if (elem is FamilyInstance framing && elem.Category.Id == framingCatId) { var param = framing.get_Parameter(BuiltInParameter.STRUCTURAL_MATERIAL_PARAM); param?.Set(material.Id); } else if (elem is Wall wall) { var structure = wall.WallType.GetCompoundStructure(); structure.SetMaterialId(structure.StructuralMaterialIndex, material.Id); wall.WallType.SetCompoundStructure(structure); } else if (elem is Floor floor) { var structure = floor.FloorType.GetCompoundStructure(); structure.SetMaterialId(structure.StructuralMaterialIndex, material.Id); floor.FloorType.SetCompoundStructure(structure); } else if (elem is FamilyInstance column && elem.Category.Id == columnCatId) { var param = column.get_Parameter(BuiltInParameter.STRUCTURAL_MATERIAL_PARAM); param?.Set(material.Id); } } ts.Commit(); } catch (Autodesk.Revit.Exceptions.OperationCanceledException) { } } [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(ApplyStandardMaterialCommand))] private bool standardCanRun = true; [ObservableProperty] [NotifyCanExecuteChangedFor(nameof(ApplyCustomMaterialCommand))] private bool customCanRun = true; private bool CanApplyCustomMaterial(Material material) { return material is not null && CustomCanRun; } private static List GetEmissiveMat(Document doc) { var materials = new FilteredElementCollector(doc).OfClass(typeof(Material)).ToElements().Cast(); List emissiveMat = []; foreach (var material in materials) { if (doc.GetElement(material.AppearanceAssetId) is AppearanceAssetElement assetElem) { var asset = assetElem.GetRenderingAsset(); #if REVIT2018 var prop = asset["generic_self_illum_luminance"]; #elif REVIT2020 || REVIT2019 var prop = asset.FindByName("generic_self_illum_luminance"); #endif var d = prop as AssetPropertyDouble; if (d?.Value > 0) { emissiveMat.Add(material); } } } return emissiveMat; } /// /// 设置材质颜色 /// /// /// /// /// /// /// 着色颜色 /// /// /// /// private static Material CreateConcreteMaterial( UIApplication uiapp, string materialName, string materialCategoryClass, string appearanceAssetName, string assetPropertyVersionGuid, Color shading, Color color, string cutPatternName, string surfacePatternName ) { Material material; var doc = uiapp.ActiveUIDocument.Document; var materials = new FilteredElementCollector(doc) .OfClass(typeof(Material)) .Cast() .Where(m => m.Name == materialName); var assets = uiapp.Application.GetAssets(AssetType.Appearance); if (materials.Any()) { material = materials.FirstOrDefault(); } else { using Transaction ts = new(doc, $"新建{materialName}材质"); ts.Start(); var matId = Material.Create(doc, materialName); material = doc.GetElement(matId) as Material; ts.Commit(); } using (Transaction name = new(doc, $"定义{materialCategoryClass}材质")) { name.Start(); if (material != null) { material.Color = shading; material.MaterialClass = materialCategoryClass; material.MaterialCategory = materialCategoryClass; var asset = assets.FirstOrDefault(a => { var propStr = a.FindByName("VersionGUID") as AssetPropertyString; return propStr?.Value == assetPropertyVersionGuid; }); AppearanceAssetElement appearanceAssetElement = null; for (var i = 0; i < 100; i++) { appearanceAssetName = $"{appearanceAssetName}({i})"; if (AppearanceAssetElement.GetAppearanceAssetElementByName(doc, appearanceAssetName) == null) { appearanceAssetElement = AppearanceAssetElement.Create(doc, appearanceAssetName, asset); break; } } if (appearanceAssetElement != null) { material.AppearanceAssetId = appearanceAssetElement.Id; } var pattern1 = FillPatternElement.GetFillPatternElementByName( doc, FillPatternTarget.Drafting, cutPatternName ); var pattern2 = FillPatternElement.GetFillPatternElementByName( doc, FillPatternTarget.Drafting, surfacePatternName ); #if REVIT2018 material.CutPatternColor = color; material.SurfacePatternColor = color; if (pattern1 != null) { material.CutPatternId = pattern1.Id; } if (pattern2 != null) { material.SurfacePatternId = pattern2.Id; } #else material.CutBackgroundPatternColor = color; material.CutForegroundPatternColor = color; material.SurfaceBackgroundPatternColor = color; material.SurfaceForegroundPatternColor = color; if (pattern1 != null) { material.CutBackgroundPatternId = pattern1.Id; material.CutForegroundPatternId = pattern1.Id; } if (pattern2 != null) { material.SurfaceBackgroundPatternId = pattern2.Id; material.SurfaceForegroundPatternId = pattern2.Id; } #endif material.UseRenderAppearanceForShading = false; } name.Commit(); } return material; } private static Material CreateConcreteMaterial( UIApplication uiapp, string materialName, string materialCategoryClass, string appearanceAssetName, string assetPropertyVersionGuid, Color shadingColor ) { Material material; var doc = uiapp.ActiveUIDocument.Document; var materials = new FilteredElementCollector(doc) .OfClass(typeof(Material)) .Cast() .Where(m => m.Name == materialName); var assets = uiapp.Application.GetAssets(AssetType.Appearance); //获取或创建材质 if (materials.Any()) { material = materials.FirstOrDefault(); } else { using SubTransaction ts = new(doc); ts.Start(); var matId = Material.Create(doc, materialName); material = doc.GetElement(matId) as Material; ts.Commit(); } //应用外观 using (SubTransaction name = new(doc)) { name.Start(); if (material != null) { material.Color = shadingColor; material.MaterialClass = materialCategoryClass; material.MaterialCategory = materialCategoryClass; var asset = assets.FirstOrDefault(a => { var propStr = a.FindByName("VersionGUID") as AssetPropertyString; return propStr?.Value == assetPropertyVersionGuid; }); AppearanceAssetElement appearanceAssetElement = null; for (var i = 0; i < 100; i++) { appearanceAssetName = $"{appearanceAssetName}({i})"; if (AppearanceAssetElement.GetAppearanceAssetElementByName(doc, appearanceAssetName) == null) { appearanceAssetElement = AppearanceAssetElement.Create(doc, appearanceAssetName, asset); break; } } if (appearanceAssetElement != null) { material.AppearanceAssetId = appearanceAssetElement.Id; } material.UseRenderAppearanceForShading = false; } name.Commit(); } return material; } [RelayCommand] private void CloseWin() { SendESCToRevit(); } private static void SendKeyToRevit(byte bVk, byte dwFlags) { var Revit = Autodesk.Windows.ComponentManager.ApplicationWindow; WinIntPtr.SetForegroundWindow(Revit); keybd_event(bVk, 0, dwFlags, 0); } [DllImport("user32.dll")] public static extern void keybd_event(byte bVk, byte bScan, uint dwFlags, uint dwExtraInfo); public static void SendESCToRevit() { SendKeyToRevit(0x1B, 0); SendKeyToRevit(0x1B, 2); } //private static void SetStructuralComponents(Material material) //{ // var doc = material.doc; // var columns = new FilteredElementCollector(doc).QueryElementsByType(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_StructuralColumns); // var floors = new FilteredElementCollector(doc).QueryElementsByType(typeof(Floor)).OfCategory(BuiltInCategory.OST_Floors).Cast().GroupBy(floor => floor.FloorType); // var framings = new FilteredElementCollector(doc).QueryElementsByType(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_StructuralFraming); // var walls = new FilteredElementCollector(doc).QueryElementsByType(typeof(Wall)).OfCategory(BuiltInCategory.OST_Walls).Cast().Where(wall => wall.WallType.Kind == WallKind.Basic).GroupBy(wall => wall.WallType); // foreach (var column in columns) // { // var param = column.get_Parameter(BuiltInParameter.STRUCTURAL_MATERIAL_PARAM); // param?.Set(material.Id); // } // foreach (var framing in framings) // { // var param = framing.get_Parameter(BuiltInParameter.STRUCTURAL_MATERIAL_PARAM); // param?.Set(material.Id); // } // foreach (var wall in walls) // { // var structure = wall.Key.GetCompoundStructure(); // structure.SetMaterialId(structure.StructuralMaterialIndex, material.Id); // wall.Key.SetCompoundStructure(structure); // } // foreach (var floor in floors) // { // var structure = floor.Key.GetCompoundStructure(); // structure.SetMaterialId(structure.StructuralMaterialIndex, material.Id); // floor.Key.SetCompoundStructure(structure); // } //} }