# Navisworks 插件类型详解

## 插件基类对比

| 基类 | 继承关系 | 主要用途 | 触发方式 |
|------|---------|---------|---------|
| `DockPanePlugin` | ← `Plugin` | 停靠面板 UI | 用户点击 Ribbon 按钮 |
| `ToolPlugin` | ← `Plugin` | 鼠标 3D 交互工具 | 用户点击后进入工具模式 |
| `RenderPlugin` | ← `Plugin` | 自定义 3D 渲染 | 自动在渲染时调用 |
| `AddInPlugin` | ← `Plugin` | 简单命令 | 用户点击 Ribbon 按钮 |
| `EventWatcherPlugin` | ← `Plugin` | 监听文档事件 | 自动注册，事件触发 |
| `CommandHandlerPlugin` | - | 自定义命令处理器 | 命令调用时触发 |

## 1. DockPanePlugin

用于创建停靠在 Navisworks 窗口中的面板。

```csharp
[DockPanePlugin(400, 600, FixedSize = false)]
[Plugin("PluginName", "DeveloperID", DisplayName = "Display Name")]
[RibbonLayout("RibbonTabName")]
[RibbonTab("Home", DisplayName = "Home")]
[Command("CommandName", DisplayName = "Open Panel", Icon = "icon.png")]
public class MyDockPanePlugin : DockPanePlugin
{
    public override Control CreateControlPane()
    {
        // 返回 Windows Forms 或 WPF 控件
        var host = new ElementHost();
        host.Child = new MyWpfUserControl();
        host.Dock = DockStyle.Fill;
        return host;
    }

    public override void DestroyControlPane(Control control)
    {
        control?.Dispose();
    }
}
```

## 2. ToolPlugin

用于创建需要与 3D 视图交互的工具。

```csharp
[ToolPlugin("ToolName", "DeveloperID", DisplayName = "Tool Display Name")]
[Plugin("PluginName", "DeveloperID")]
[RibbonLayout("RibbonTabName")]
[RibbonTab("Home", DisplayName = "Home")]
[Command("CommandName", DisplayName = "Activate Tool", Icon = "icon.png")]
public class MyToolPlugin : ToolPlugin
{
    public override bool MouseDown(MouseButton button, int x, int y)
    {
        // 处理鼠标按下
        // 返回 true 表示已处理事件
        return true;
    }

    public override bool MouseMove(int x, int y)
    {
        // 处理鼠标移动
        return true;
    }

    public override bool MouseUp(MouseButton button, int x, int y)
    {
        // 处理鼠标释放
        return true;
    }

    public override void OnActivate()
    {
        // 工具激活时调用
        base.OnActivate();
    }

    public override void OnDeactivate()
    {
        // 工具停用时调用
        base.OnDeactivate();
    }
}
```

### 获取 3D 点击坐标

```csharp
public override bool MouseDown(MouseButton button, int x, int y)
{
    if (button == MouseButton.Left)
    {
        // 将屏幕坐标转换为 3D 射线
        var view = Application.ActiveDocument.CurrentViewpoint;
        var pickResult = view.PickItemFromPoint(x, y);
        
        if (pickResult != null)
        {
            Point3D point = pickResult.Point;
            // 使用点击的 3D 坐标
        }
    }
    return true;
}
```

## 3. RenderPlugin

用于在 3D 视图中渲染自定义图形。

```csharp
[RenderPlugin("RenderPluginName", "DeveloperID")]
[Plugin("PluginName", "DeveloperID")]
public class MyRenderPlugin : RenderPlugin
{
    public override void Render(View view, RenderContext context)
    {
        // 在这里进行自定义渲染
        // 使用 context 绘制线条、点、文本等
        
        // 示例：绘制一条红线
        var points = new List<Point3D>
        {
            new Point3D(0, 0, 0),
            new Point3D(10, 10, 10)
        };
        
        context.DrawLines(points, new Color(1, 0, 0), 2.0f);
    }
}
```

## 4. AddInPlugin

最简单的插件类型，用于执行一次性命令。

```csharp
[AddInPlugin("AddInName", "DeveloperID", DisplayName = "Command Name")]
[RibbonTab("Home", DisplayName = "Home")]
[Command("CommandName", DisplayName = "Run Command", Icon = "icon.png")]
public class MyAddInPlugin : AddInPlugin
{
    public override int Execute(params string[] parameters)
    {
        // 执行命令逻辑
        MessageBox.Show("Hello from AddIn!");
        return 0; // 返回 0 表示成功
    }
}
```

## 5. EventWatcherPlugin

用于监听文档事件。

```csharp
[EventWatcherPlugin("EventWatcherName", "DeveloperID")]
[Plugin("PluginName", "DeveloperID")]
public class MyEventWatcher : EventWatcherPlugin
{
    public override void OnDocumentChanged(object sender, DocumentEventArgs e)
    {
        // 文档变更时触发
    }

    public override void OnSelectionChanged(object sender, EventArgs e)
    {
        // 选择变更时触发
    }

    public override void OnViewChanged(object sender, ViewEventArgs e)
    {
        // 视图变更时触发
    }
}
```

## 插件属性详解

### Plugin 属性

```csharp
[Plugin("PluginName", "DeveloperID", 
    DisplayName = "显示名称",
    ToolTip = "鼠标悬停提示",
    LoadForCanExecute = true)]
```

### RibbonTab 属性

```csharp
[RibbonTab("TabName", DisplayName = "Tab 显示名称")]
```

### RibbonLayout 属性

```csharp
[RibbonLayout("LayoutName")]
```

### Command 属性

```csharp
[Command("CommandName", 
    DisplayName = "命令显示名称",
    ToolTip = "命令提示",
    Icon = "icon.png",
    LargeIcon = "icon_large.png",
    Shortcut = "Ctrl+Shift+X")]
```

### DockPanePlugin 属性

```csharp
[DockPanePlugin(width, height,
    FixedSize = false,              // 是否固定大小
    MinimumWidth = 200,             // 最小宽度
    MinimumHeight = 300,            // 最小高度
    HasDockingFrames = true)]       // 是否有停靠框架
```

## COM 插件注册

COM 插件需要注册到系统注册表。

### 1. 为程序集添加 GUID

```csharp
// 在 AssemblyInfo.cs 中
[assembly: Guid("YOUR-GUID-HERE")]

// 在插件类上添加 ProgId
[ProgId("YourCompany.YourPlugin")]
public class YourPlugin : DockPanePlugin { }
```

### 2. 注册插件

```bash
# 使用 Visual Studio 自动注册（开发时）
# 或在注册表中手动添加：
# HKLM\SOFTWARE\Autodesk\Navisworks Manage\23.0\COM Plugins
# 创建字符串值，名称为 ProgId，值为空

# 或使用 nwregasm.bat
nwregasm.bat "path\to\your\plugin.dll"
```

## 项目文件配置

### 必要的引用

```xml
<!-- Navisworks API -->
<Reference Include="Autodesk.Navisworks.Api" />
<Reference Include="Autodesk.Navisworks.ComApi" />
<Reference Include="Autodesk.Navisworks.Interop.ComApi" />
<Reference Include="Autodesk.Navisworks.Timeliner" />
<Reference Include="Autodesk.Navisworks.Clash" />
<Reference Include="Autodesk.Navisworks.Controls" />
```

### 输出路径

插件应该输出到 Navisworks 插件目录：

```
C:\ProgramData\Autodesk\Navisworks Manage 2026\plugins\YourPluginName\
```

## 调试插件

1. 设置启动外部程序：
   - 路径：`C:\Program Files\Autodesk\Navisworks Manage 2026\Roamer.exe`

2. 附加到进程调试：
   - 在 Visual Studio 中选择 "附加到进程"
   - 选择 `Roamer.exe`

3. 日志输出：

   ```csharp
   // 使用 System.Diagnostics.Debug
   System.Diagnostics.Debug.WriteLine("Debug message");
   ```
