2026-02-20 16:47:26 +08:00
|
|
|
|
using System.Collections.ObjectModel;
|
2026-01-01 10:02:59 +08:00
|
|
|
|
using System.Reflection;
|
2025-12-23 21:35:54 +08:00
|
|
|
|
using System.Windows;
|
|
|
|
|
|
using Autodesk.Revit.DB;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
using Autodesk.Windows;
|
2025-04-24 20:56:44 +08:00
|
|
|
|
using ShrlAlgoToolkit.RevitAddins.Properties;
|
|
|
|
|
|
using ShrlAlgoToolkit.RevitAddins.RvFamily.FamilyLibrary;
|
2026-02-21 16:31:24 +08:00
|
|
|
|
using ShrlAlgoToolkit.RevitAddins.Common.Extensions;
|
|
|
|
|
|
|
2026-02-22 20:03:42 +08:00
|
|
|
|
namespace ShrlAlgoToolkit.RevitAddins.Entry;
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
|
|
|
|
|
public class FamilyApp
|
|
|
|
|
|
{
|
2024-12-22 10:26:12 +08:00
|
|
|
|
public FamilyApp(UIControlledApplication application, UIApplication uiapp)
|
|
|
|
|
|
{
|
|
|
|
|
|
Items = new ObservableCollection<FamilyModel>();
|
|
|
|
|
|
uiapp.Application.DocumentChanged += Application_DocumentChanged;
|
|
|
|
|
|
uiapp.Application.DocumentClosed += Application_DocumentClosed;
|
|
|
|
|
|
//uiapp.Application.FamilyLoadedIntoDocument += Application_FamilyLoadedIntoDocument;
|
|
|
|
|
|
CreateFamilyUI(application);
|
|
|
|
|
|
|
|
|
|
|
|
CreateRecentPanel();
|
|
|
|
|
|
BindingData();
|
|
|
|
|
|
this.uiapp = uiapp;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//private void Application_FamilyLoadedIntoDocument(object sender, Autodesk.Revit.DB.Events.FamilyLoadedIntoDocumentEventArgs e)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// Document doc = e.Document;
|
|
|
|
|
|
// var existedFamilyIds = Items.Select(i => i.ReferenceFamily).Cast<Family>().Select(f => f.Id).ToList();
|
|
|
|
|
|
// var i = existedFamilyIds.IndexOf(e.OriginalFamilyId);
|
|
|
|
|
|
// if (i == -1)
|
|
|
|
|
|
// {
|
|
|
|
|
|
// var family = doc.GetElement(e.NewFamilyId) as Family;
|
|
|
|
|
|
// var symbol = doc.GetElement(family.GetFamilySymbolIds().FirstOrDefault()) as FamilySymbol;
|
|
|
|
|
|
// var bitmapsymbol?.GetPreviewImage(new System.Drawing.Size(56, 56)).ToBitmapImage();
|
|
|
|
|
|
// Items.Insert(0, new FamilyModel
|
|
|
|
|
|
// {
|
|
|
|
|
|
// Title = e.FamilyName,
|
|
|
|
|
|
// ReferenceFamily = family,
|
|
|
|
|
|
// $"布置 {e.FamilyName}",
|
|
|
|
|
|
// uiApplication = uiapp,
|
|
|
|
|
|
// BitmapbitmapImage
|
|
|
|
|
|
// });
|
|
|
|
|
|
// }
|
|
|
|
|
|
// else
|
|
|
|
|
|
// {
|
|
|
|
|
|
// Items.Move(i, 0);
|
|
|
|
|
|
// }
|
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
|
|
private const string VbPanelName = "族工具";
|
|
|
|
|
|
private const string VbRecentPanelName = "最近使用";
|
|
|
|
|
|
|
|
|
|
|
|
//获取Ribbon类所在的通用类库目录
|
2026-02-24 11:34:18 +08:00
|
|
|
|
private static readonly string TabName = Properties.Settings.Default.TabName;
|
2024-12-22 10:26:12 +08:00
|
|
|
|
private readonly UIApplication uiapp;
|
|
|
|
|
|
|
|
|
|
|
|
public ObservableCollection<FamilyModel> Items { get; set; }
|
|
|
|
|
|
|
|
|
|
|
|
private static bool IsFitting(FamilyInstance instance)
|
|
|
|
|
|
{
|
|
|
|
|
|
var category = instance.Category;
|
|
|
|
|
|
if (category != null)
|
|
|
|
|
|
{
|
2024-09-22 11:05:41 +08:00
|
|
|
|
#if REVIT2018 || REVIT2020
|
|
|
|
|
|
var builtIncategory = (BuiltInCategory)category.Id.IntegerValue;
|
|
|
|
|
|
#elif REVIT2025
|
|
|
|
|
|
var builtIncategory = (BuiltInCategory)category.Id.Value;
|
|
|
|
|
|
#endif
|
|
|
|
|
|
//var name = Enum.Parse(typeof(BuiltInCategory), .ToString());
|
|
|
|
|
|
|
|
|
|
|
|
var name = Enum.GetName(typeof(BuiltInCategory), builtIncategory);
|
2024-12-22 10:26:12 +08:00
|
|
|
|
if (name.Contains("Fitting"))
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void Application_DocumentChanged(object sender, Autodesk.Revit.DB.Events.DocumentChangedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
var doc = e.GetDocument();
|
|
|
|
|
|
ElementClassFilter instanceClass = new(typeof(FamilyInstance));
|
|
|
|
|
|
var elementIds = e.GetAddedElementIds(instanceClass);
|
2024-09-22 11:05:41 +08:00
|
|
|
|
//e.GetTransactionNames()
|
|
|
|
|
|
//elementIds.AddRange(e.GetModifiedElementIds());
|
2024-12-22 10:26:12 +08:00
|
|
|
|
if (elementIds.Count > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
var elems = elementIds.Select(doc.GetElement).OfType<FamilyInstance>();
|
|
|
|
|
|
var instances = elems.Where(instance => !IsFitting(instance));
|
|
|
|
|
|
var existedFamilyIds = Items.Select(i => i.ReferenceFamily).Select(f => f.Id).ToList();
|
|
|
|
|
|
var instanceGroups = instances.GroupBy(ins => ins.Symbol.Family.Id);
|
|
|
|
|
|
foreach (var grouping in instanceGroups)
|
|
|
|
|
|
{
|
|
|
|
|
|
var familyId = grouping.Key;
|
|
|
|
|
|
var i = existedFamilyIds.IndexOf(familyId);
|
|
|
|
|
|
if (i == -1)
|
|
|
|
|
|
{
|
|
|
|
|
|
NewGalleryItem(doc, familyId);
|
|
|
|
|
|
}
|
|
|
|
|
|
//不在第一位则新建到第一位
|
|
|
|
|
|
else if (i > 0)
|
|
|
|
|
|
{
|
|
|
|
|
|
Items.RemoveAt(i);
|
|
|
|
|
|
NewGalleryItem(doc, familyId);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//foreach (var elementFunc in instances)
|
|
|
|
|
|
//{
|
|
|
|
|
|
// if (!(elementFunc is FamilyInstance instance)) continue;
|
|
|
|
|
|
// var family = instance.Symbol.Family;
|
|
|
|
|
|
// var symbolId = family?.GetFamilySymbolIds().FirstOrDefault();
|
|
|
|
|
|
// var symbol = doc.GetElement(symbolId) as FamilySymbol;
|
|
|
|
|
|
// var bitmapsymbol?.GetPreviewImage(new System.Drawing.Size(56, 56)).ConvertBitmapToBitmapImage();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Items.Insert(0, new FamilyModel
|
|
|
|
|
|
// {
|
|
|
|
|
|
// Title = family?.Name,
|
|
|
|
|
|
// ReferenceFamily = family,
|
|
|
|
|
|
// $"布置{family?.Name}",
|
|
|
|
|
|
// uiApplication = uiApplication,
|
|
|
|
|
|
// BitmapbitmapImage
|
|
|
|
|
|
// });
|
|
|
|
|
|
//}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void Application_DocumentClosed(object sender, Autodesk.Revit.DB.Events.DocumentClosedEventArgs e)
|
|
|
|
|
|
{
|
|
|
|
|
|
Items.Clear();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void BindingData()
|
|
|
|
|
|
{
|
|
|
|
|
|
var adTab = ComponentManager.Ribbon.Tabs.First(o => o.Title == TabName);
|
|
|
|
|
|
var adPanel = adTab.Panels.First(o => o.Source.Title == VbRecentPanelName);
|
|
|
|
|
|
var gallery = adPanel.Source.Items.First() as RibbonGallery;
|
|
|
|
|
|
gallery!.ItemWidth = 56;
|
|
|
|
|
|
gallery.ItemHeight = 56;
|
|
|
|
|
|
gallery.ResizeStyle = RibbonItemResizeStyles.ChangeSize;
|
|
|
|
|
|
gallery.DisplayMode = GalleryDisplayMode.Window;
|
|
|
|
|
|
gallery.ResizableBoxWidth = 0.0;
|
|
|
|
|
|
gallery.IsVirtualizing = true;
|
|
|
|
|
|
gallery.RowsInWindowMode = 1;
|
|
|
|
|
|
gallery.ShowImage = true;
|
|
|
|
|
|
gallery.MinWidth = 400;
|
|
|
|
|
|
|
2026-01-01 10:02:59 +08:00
|
|
|
|
// 1. 获取当前程序集的短名称 (例如 "ShrlAlgoToolkit.RevitAddins")
|
|
|
|
|
|
string assemblyName = Assembly.GetExecutingAssembly().GetName().Name;
|
|
|
|
|
|
// 2. 拼接 Pack URI
|
|
|
|
|
|
// 注意:格式通常是 "/{程序集名称};component/{路径}"
|
|
|
|
|
|
var resourceLocator = new Uri($"/{assemblyName};component/WPFUI.xaml", UriKind.Relative);
|
|
|
|
|
|
|
|
|
|
|
|
var dictionary = (ResourceDictionary)Application.LoadComponent(resourceLocator);
|
2024-12-22 10:26:12 +08:00
|
|
|
|
gallery.ItemTemplate = (DataTemplate)dictionary["FamilyGalleryItemTemplate"];
|
|
|
|
|
|
//绑定数据
|
|
|
|
|
|
gallery.ItemsBinding = new System.Windows.Data.Binding
|
|
|
|
|
|
{
|
|
|
|
|
|
Source = this,
|
|
|
|
|
|
Path = new PropertyPath(nameof(Items)),
|
|
|
|
|
|
//Source = Items,
|
|
|
|
|
|
Mode = System.Windows.Data.BindingMode.OneWay
|
|
|
|
|
|
};
|
|
|
|
|
|
//绑定样式
|
|
|
|
|
|
}
|
|
|
|
|
|
public void CreateFamilyUI(UIControlledApplication application)
|
|
|
|
|
|
{
|
|
|
|
|
|
//AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
|
|
|
|
|
|
//application.CreateRibbonTab(TabName);
|
|
|
|
|
|
|
|
|
|
|
|
//UserPanel.AddAwItem(_loginPBData);
|
|
|
|
|
|
//".\\*.*"中的“.”表示通用类库文件所在的目录(Debug),“..”表示的是上级的目录(bin),“..”\\..,引号表示再上一级目录
|
|
|
|
|
|
//ContextualHelp contextualHelp = new ContextualHelp(ContextualHelpType.Url, "https://www.szmedi.com.cn");
|
|
|
|
|
|
//_loginPBData.CreateContextualHelp(contextualHelp);
|
|
|
|
|
|
|
|
|
|
|
|
var familyManagePanel = application.CreateRibbonPanel(TabName, VbPanelName);
|
|
|
|
|
|
|
|
|
|
|
|
//在面板上添加添加浏览族库按钮
|
2026-02-22 20:03:42 +08:00
|
|
|
|
var localFamilyPbd = UIAssist.NewPushButtonData<FamMaster.FamilyLibraryCmd>(
|
2024-12-22 10:26:12 +08:00
|
|
|
|
"本地族库",
|
|
|
|
|
|
Resources.library_32px,
|
|
|
|
|
|
Resources.library_16px
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-02-22 20:03:42 +08:00
|
|
|
|
var familyMassSave = UIAssist.NewPushButtonData<FamMaster.FamilyProcessorCmd>(
|
2024-12-22 10:26:12 +08:00
|
|
|
|
"族复用",
|
|
|
|
|
|
Resources.family_processor_32px,
|
|
|
|
|
|
Resources.family_processor_16px
|
|
|
|
|
|
);
|
2026-02-22 20:03:42 +08:00
|
|
|
|
var replaceInstance = UIAssist.NewPushButtonData<Modeling.ReplaceInstanceCmd>(
|
2024-12-22 10:26:12 +08:00
|
|
|
|
"替换族",
|
|
|
|
|
|
Resources.replace_32px,
|
|
|
|
|
|
Resources.replace_16px
|
|
|
|
|
|
);
|
|
|
|
|
|
|
2026-02-22 20:03:42 +08:00
|
|
|
|
var updateFamilyFile = UIAssist.NewPushButtonData<General.UpgradeFamilyCmd>(
|
2024-12-22 10:26:12 +08:00
|
|
|
|
"更新族",
|
|
|
|
|
|
Resources.available_updates_32px,
|
|
|
|
|
|
Resources.available_updates_16px,
|
|
|
|
|
|
"更新族文件缩略图及升级至当前版本"
|
|
|
|
|
|
);
|
2024-09-22 11:05:41 +08:00
|
|
|
|
|
2026-02-22 20:03:42 +08:00
|
|
|
|
var renameFamily = UIAssist.NewPushButtonData<Standardizer.RenameFamilyNameCmd>(
|
2024-09-22 11:05:41 +08:00
|
|
|
|
"重命名族",
|
|
|
|
|
|
Resources.rename_family_32px,
|
|
|
|
|
|
Resources.rename_family_16px
|
|
|
|
|
|
);
|
2026-02-22 20:03:42 +08:00
|
|
|
|
var renameType = UIAssist.NewPushButtonData<Standardizer.RenameTypeNameCmd>(
|
2024-09-22 11:05:41 +08:00
|
|
|
|
"重命名类型",
|
|
|
|
|
|
Resources.rename_type_32px,
|
|
|
|
|
|
Resources.rename_type_16px
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
familyManagePanel.AddItem(localFamilyPbd);
|
|
|
|
|
|
familyManagePanel.AddStackedItems(familyMassSave, replaceInstance, updateFamilyFile);
|
|
|
|
|
|
familyManagePanel.AddStackedItems(renameFamily, renameType);
|
2024-12-22 10:26:12 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private static void CreateRecentPanel()
|
|
|
|
|
|
{
|
|
|
|
|
|
var adTab = ComponentManager.Ribbon.Tabs.First(o => o.Title == TabName);
|
|
|
|
|
|
var recentPanel = new Autodesk.Windows.RibbonPanel
|
|
|
|
|
|
{
|
|
|
|
|
|
Source = new RibbonPanelSource { Title = VbRecentPanelName }
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
adTab.Panels.Insert(adTab.Panels.Count, recentPanel);
|
|
|
|
|
|
|
|
|
|
|
|
recentPanel.Source.Items.Add(new RibbonGallery { Name = "_ribbonGallery_recent" });
|
|
|
|
|
|
recentPanel.IsVisible = true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private void NewGalleryItem(Document doc, ElementId familyId)
|
|
|
|
|
|
{
|
|
|
|
|
|
var family = doc.GetElement(familyId) as Family;
|
|
|
|
|
|
var symbol = doc.GetElement(family!.GetFamilySymbolIds().FirstOrDefault()) as FamilySymbol;
|
|
|
|
|
|
var bitmap = symbol?.GetPreviewImage(new System.Drawing.Size(50, 50)).ToBitmapImage();
|
|
|
|
|
|
Items.Insert(
|
|
|
|
|
|
0,
|
|
|
|
|
|
new FamilyModel
|
|
|
|
|
|
{
|
|
|
|
|
|
ReferenceFamily = family,
|
|
|
|
|
|
Title = family.Name,
|
|
|
|
|
|
UiApplication = uiapp,
|
|
|
|
|
|
BitmapImage = bitmap,
|
|
|
|
|
|
ToolTip = $"布置:{family.Name}\n\r所属文档:{family.Document.Title}",
|
|
|
|
|
|
}
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
2024-09-22 11:05:41 +08:00
|
|
|
|
}
|