Files
SzmediTools/Szmedi.RvKits/ModelManager/MaterialBatchViewModel.cs
2025-09-16 16:06:41 +08:00

507 lines
18 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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<Material>();
materials = new ObservableCollection<Material>(mats);
this.uiapp = uiapp;
materialHandler = new();
}
private readonly ActionEventHandler materialHandler;
private readonly Document doc;
private readonly ObservableCollection<Material> 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<Material> 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<Material> GetEmissiveMat(Document doc)
{
var materials = new FilteredElementCollector(doc).OfClass(typeof(Material)).ToElements().Cast<Material>();
List<Material> 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;
}
/// <summary>
/// 设置材质颜色
/// </summary>
/// <param name="uiapp"></param>
/// <param name="materialName"></param>
/// <param name="materialCategoryClass"></param>
/// <param name="appearanceAssetName"></param>
/// <param name="assetPropertyVersionGuid"></param>
/// <param name="shading">着色颜色</param>
/// <param name="color"></param>
/// <param name="cutPatternName"></param>
/// <param name="surfacePatternName"></param>
/// <returns></returns>
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<Material>()
.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<Material>()
.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<Floor>().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<Wall>().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);
// }
//}
}