diff --git a/TransportPlugin.csproj b/TransportPlugin.csproj index 4bbb6e9..a41f577 100644 --- a/TransportPlugin.csproj +++ b/TransportPlugin.csproj @@ -165,6 +165,7 @@ + @@ -522,6 +523,18 @@ PreserveNewest resources\TransportPlugin.name.txt + + PreserveNewest + TransportRibbon.xaml + + + PreserveNewest + TransportRibbon_16.png + + + PreserveNewest + TransportRibbon_32.png + PreserveNewest diff --git a/deploy-plugin.bat b/deploy-plugin.bat index 0c5a3cd..789d687 100644 --- a/deploy-plugin.bat +++ b/deploy-plugin.bat @@ -16,6 +16,11 @@ powershell -NoProfile -ExecutionPolicy Bypass -Command ^ " 'System.Data.SQLite.dll'," ^ " 'Tomlyn.dll'" ^ ");" ^ + "$deployRootFiles = @(" ^ + " 'TransportRibbon.xaml'," ^ + " 'TransportRibbon_16.png'," ^ + " 'TransportRibbon_32.png'" ^ + ");" ^ "$stalePluginFiles = @(" ^ " 'Autodesk.Navisworks.Api.dll'," ^ " 'NavisworksTransport.UnitTests.dll'," ^ @@ -63,6 +68,17 @@ powershell -NoProfile -ExecutionPolicy Bypass -Command ^ " if (-not (Test-Path $sourceDll)) { throw ('Deployment source file missing: ' + $sourceDll) }" ^ " Copy-Item $sourceDll $targetDir -Force;" ^ "}" ^ + "foreach ($rootFileName in $deployRootFiles) {" ^ + " $sourceRootFile = Join-Path $buildDir $rootFileName;" ^ + " if (Test-Path $sourceRootFile) {" ^ + " Copy-Item $sourceRootFile $targetDir -Force;" ^ + " foreach ($locale in @('en-US','zh-CN')) {" ^ + " $localeDir = Join-Path $targetDir $locale;" ^ + " New-Item -ItemType Directory -Force -Path $localeDir | Out-Null;" ^ + " Copy-Item $sourceRootFile $localeDir -Force;" ^ + " }" ^ + " }" ^ + "}" ^ "if (Test-Path (Join-Path $buildDir 'resources')) {" ^ " New-Item -ItemType Directory -Force -Path (Join-Path $targetDir 'resources') | Out-Null;" ^ " Copy-Item (Join-Path $buildDir 'resources\\*') (Join-Path $targetDir 'resources') -Recurse -Force;" ^ @@ -70,6 +86,10 @@ powershell -NoProfile -ExecutionPolicy Bypass -Command ^ "" ^ "$sourceFiles = @();" ^ "foreach ($dllName in $deployDllNames) { $sourceFiles += Get-Item (Join-Path $buildDir $dllName) }" ^ + "foreach ($rootFileName in $deployRootFiles) {" ^ + " $sourceRootFile = Join-Path $buildDir $rootFileName;" ^ + " if (Test-Path $sourceRootFile) { $sourceFiles += Get-Item $sourceRootFile }" ^ + "}" ^ "if (Test-Path (Join-Path $buildDir 'resources')) {" ^ " $sourceFiles += Get-ChildItem (Join-Path $buildDir 'resources') -File;" ^ "}" ^ @@ -82,6 +102,17 @@ powershell -NoProfile -ExecutionPolicy Bypass -Command ^ " throw ('Deployment verification failed for ' + $sourceFile.Name + ': source=' + $sourceFile.LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss.fff') + ' (' + $sourceFile.Length + '), target=' + $targetInfo.LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss.fff') + ' (' + $targetInfo.Length + ')');" ^ " }" ^ " Write-Host ('Verified ' + $sourceFile.Name + ': ' + $targetInfo.LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss.fff'));" ^ + " if ($deployRootFiles -contains $sourceFile.Name) {" ^ + " foreach ($locale in @('en-US','zh-CN')) {" ^ + " $localeTargetFile = Join-Path (Join-Path $targetDir $locale) $sourceFile.Name;" ^ + " if (-not (Test-Path $localeTargetFile)) { throw ('Deployment verification failed: missing locale target file ' + $localeTargetFile) }" ^ + " $localeTargetInfo = Get-Item $localeTargetFile;" ^ + " if ($sourceFile.Length -ne $localeTargetInfo.Length -or $sourceFile.LastWriteTime -ne $localeTargetInfo.LastWriteTime) {" ^ + " throw ('Deployment verification failed for locale copy ' + $localeTargetFile);" ^ + " }" ^ + " Write-Host ('Verified ' + $locale + '\\' + $sourceFile.Name + ': ' + $localeTargetInfo.LastWriteTime.ToString('yyyy-MM-dd HH:mm:ss.fff'));" ^ + " }" ^ + " }" ^ "}" ^ "" ^ "Write-Host 'Plugin deployed successfully!';" diff --git a/resources/TransportRibbon.xaml b/resources/TransportRibbon.xaml new file mode 100644 index 0000000..d0188d7 --- /dev/null +++ b/resources/TransportRibbon.xaml @@ -0,0 +1,23 @@ + + + + + + + + + + diff --git a/resources/TransportRibbon_16.png b/resources/TransportRibbon_16.png new file mode 100644 index 0000000..7d75f30 Binary files /dev/null and b/resources/TransportRibbon_16.png differ diff --git a/resources/TransportRibbon_32.png b/resources/TransportRibbon_32.png new file mode 100644 index 0000000..5118b17 Binary files /dev/null and b/resources/TransportRibbon_32.png differ diff --git a/src/Commands/TransportRibbonHandler.cs b/src/Commands/TransportRibbonHandler.cs new file mode 100644 index 0000000..95278f6 --- /dev/null +++ b/src/Commands/TransportRibbonHandler.cs @@ -0,0 +1,79 @@ +using System; +using Autodesk.Navisworks.Api.Plugins; +using NavisworksTransport.Utils; + +namespace NavisworksTransport.Commands +{ + [Plugin("TransportRibbonHandler", "NavisworksTransport", + DisplayName = "物流路径规划工具栏", + ToolTip = "物流路径规划工具栏命令")] + [RibbonLayout("TransportRibbon.xaml")] + [RibbonTab("ID_TransportTab", DisplayName = "物流路径规划")] + [Command("OpenLogisticsPanel", + DisplayName = "物流路径规划", + ToolTip = "打开物流路径规划面板", + LoadForCanExecute = true)] + public class TransportRibbonHandler : CommandHandlerPlugin + { + private const string MainDockPanePluginKey = "NavisworksTransport.Main.Tian"; + private const string OpenLogisticsPanelCommandId = "OpenLogisticsPanel"; + private const string TransportRibbonTabId = "ID_TransportTab"; + + public override int ExecuteCommand(string commandId, params string[] parameters) + { + try + { + if (!string.Equals(commandId, OpenLogisticsPanelCommandId, StringComparison.OrdinalIgnoreCase)) + { + LogManager.Warning($"[Ribbon] 未知命令: {commandId}"); + return 1; + } + + var pluginRecord = Autodesk.Navisworks.Api.Application.Plugins.FindPlugin(MainDockPanePluginKey) as DockPanePluginRecord; + if (pluginRecord == null) + { + throw new InvalidOperationException($"未找到物流路径规划面板插件: {MainDockPanePluginKey}"); + } + + var dockPane = pluginRecord.LoadPlugin() as DockPanePlugin; + if (dockPane == null) + { + throw new InvalidOperationException("物流路径规划面板加载失败"); + } + + dockPane.Visible = true; + dockPane.ActivatePane(); + LogManager.Info("[Ribbon] 已通过正式工具栏打开物流路径规划面板"); + return 0; + } + catch (Exception ex) + { + LogManager.Error($"[Ribbon] 执行命令失败: {ex.Message}", ex); + return 1; + } + } + + public override CommandState CanExecuteCommand(string commandId) + { + if (string.Equals(commandId, OpenLogisticsPanelCommandId, StringComparison.OrdinalIgnoreCase)) + { + return new CommandState + { + IsEnabled = true, + IsVisible = true + }; + } + + return new CommandState + { + IsEnabled = false, + IsVisible = false + }; + } + + public override bool CanExecuteRibbonTab(string ribbonTabId) + { + return string.Equals(ribbonTabId, TransportRibbonTabId, StringComparison.OrdinalIgnoreCase); + } + } +}