Commit Graph

703 Commits

Author SHA1 Message Date
6b8bae2afc fix: clear all IsSelected flags after export to prevent stale selections
- Added finally block to reset IsSelected on all PathRoutes
- Prevents multi-select state from leaking into subsequent single exports
2026-06-04 21:36:52 +08:00
897280bb3f fix: show concatenated path names as dialog filename for multi-select export
- Single: path name as default filename (unchanged)
- Multi: semicolon-separated names as hint, each file still saved individually
2026-06-03 21:16:52 +08:00
1beaa7b24d Revert "fix: use folder dialog for multi-select export, file dialog for single"
This reverts commit 6d14d1d26f.
2026-06-03 21:16:28 +08:00
6d14d1d26f fix: use folder dialog for multi-select export, file dialog for single
- Single selection: SaveFileDialog with path name as default filename
- Multi selection: FolderBrowserDialog to pick output directory
- Export format: XML for multi (simpler UX), selectable for single
2026-06-03 21:11:41 +08:00
ac2de23e32 feat: support multi-select and batch export in path list
- DataGrid: SelectionMode Extended with RowStyle IsSelected binding
- PathRouteViewModel: add IsSelected property
- Export: iterates selected paths, saves each to separate file
- Ctrl/Shift+click to multi-select, then Export button batches them
2026-06-03 21:06:32 +08:00
c0714a5180 fix: regenerate path point IDs and rebuild edges on import rename
- Also regenerate all PathPoint.Id to avoid UNIQUE constraint on PathPoints.Id
- Call RecalculateRoute() to rebuild edges with new point references
- Edge constructor auto-generates new Id, so edges are fresh too
2026-06-03 20:58:49 +08:00
c6afef13de fix: generate new GUID when renaming imported path to avoid DB conflict
- Imported routes with same Id would overwrite each other in DB
- Now assign route.Id = Guid.NewGuid() on rename, ensuring unique DB entry
2026-06-03 20:54:08 +08:00
0cff495331 fix: prevent duplicate database save during XML import deserialization
- ParseRouteElement used route.AddPoint() which called RecalculateAndSaveRoute
- This saved the path to DB with original name before ImportPathCommand could rename it
- Changed to route.Points.Add() + route.RecalculateRoute() to skip DB save
- Only ImportPathCommand → AddRoute → SavePathToDatabase now persists renamed path
2026-06-03 20:44:52 +08:00
c2a37fe007 fix: only count rename when name actually changed during import
- Capture original name before GenerateUniqueName
- Skip RenamedCount increment if names are identical
- Fix misleading log showing same name twice
2026-06-03 20:34:49 +08:00
0967f7a9bc feat: show renamed count in import result dialog
- Add RenamedCount to ImportPathResult
- Track per-file and aggregate across multi-file imports
- Dialog now shows '重名自动重命名: N 个路径' when applicable
2026-06-03 20:29:28 +08:00
27ab485558 fix: use DialogHelper.ShowAutoClosingMessageBox for import result dialog
- 5s auto-close, test automation mode skips dialog
- Consistent with existing project patterns
2026-06-03 20:25:15 +08:00
ab0b5760d8 feat: show import result dialog after multi-file import 2026-06-03 20:22:58 +08:00
5692fde956 feat: rename export button, support multi-file import
- Rename '导出选中路径' to '导出', move before '导出全部'
- Import dialog: enable MultiSelect, loop through all selected files
- Aggregate import results across files
2026-06-03 20:17:19 +08:00
b3a8364e7e tweak: remove redundant '路径' from path creation button labels 2026-06-03 20:11:09 +08:00
a8a786d807 refactor: rename and reorder path creation buttons
- Rename '手动创建' to '地面路径'
- Rename '传统空轨路径' to '空轨路径'
- Move 空轨路径 after 吊装路径 (Ground → Hoisting → Rail order)
2026-06-03 20:07:33 +08:00
469f529fa0 tweak: increase path list DataGrid height from 200 to 340 (7→12 rows) 2026-06-03 20:02:51 +08:00
750559a560 refactor: collapsible test section with Grid layout in SystemManagement
- Wrap test buttons in Expander (default collapsed)
- Replace horizontal StackPanel with 3-column Grid layout
- Simplify button labels by removing redundant 'test' wording
2026-06-03 20:00:00 +08:00
6bc77672e9 fix: prevent crash when invalid characters typed in coordinate editor
EditableNumberConverter.ConvertBack was throwing FormatException
when users typed '=' or other non-numeric characters, causing
WPF binding validation to crash the application on focus change.
Changed to return Binding.DoNothing to silently reject invalid input.
2026-06-03 19:49:44 +08:00
0ed24b21a2 refactor: change virtual object RadioButton to CheckBox in AnimationControlView 2026-06-03 19:45:07 +08:00
c7a1eeebb8 feat: add FaceInferToolPlugin - single-click face normal inference tool
- New FaceInferToolPlugin: pixel-neighborhood method with {2,5,10}px offsets
- New FaceInferResult data class
- Test button in SystemManagement page
- Cursor: MarkupAutoPoly (arrow + dashed box)
- Uses project-standard tools: FindNamedParentContainer, viewpoint.Position
- Design doc at doc/design/2026/face-infer-tool-design.md
2026-06-02 23:11:11 +08:00
922864ce4f style: 别名树字体 SemiBold → Bold 2026-06-02 13:02:16 +08:00
337ccbb43b fix: OnTreeViewSelected NRE + 日志清理
- _isInternalSelection 为 true 时 OnTreeViewSelected 直接 return,阻断 NW→树→NW 循环
- 调试日志降为 Debug 级别
- doc.CurrentSelection 加空检查
2026-06-02 12:58:38 +08:00
8a8153dba0 fix: use ShouldUseReferenceBasedRealObjectPlanarPose to guard reference rotation capture
Ground and Hoisting paths don't consume fragment reference rotation, only Rail does.
Replace manual PathType checks with the existing semantic utility method.

Also fix GetPathRouteSync SELECT missing IsTwoPointVertical column.
2026-06-02 12:41:31 +08:00
93c143f75b docs: CHANGELOG 添加别名树功能 2026-06-02 00:13:58 +08:00
2ff4cb1678 fix: 2-point vertical path point modification no longer constrained by hoisting height limits
- Skip height constraints, orthogonalization, and intermediate point insertion
- Auto-recalculate LiftHeight from elevation difference between the two points
2026-06-01 23:55:04 +08:00
be5867f2a3 chore: bump version to 0.15.4 2026-06-01 23:32:05 +08:00
a8c5681dfb feat: separate 2-point vertical hoisting path from regular hoisting
- Add IsTwoPointVertical flag on PathRoute to distinguish pure vertical paths
- 2-point paths skip hoisting-specific logic: ResolveHoistingTrackedCenter,
  TryCreatePlanarPathRotationForFrame, ground-contact segment classification
- Endpoint semantics: center reaches endpoint (not top-face constrained)
- Frame interpolation applies same ResolveGroundTrackedCenter as move-to-start
- Add database migration for IsTwoPointVertical column
- Update CHANGELOG for v0.15.4
2026-06-01 23:31:00 +08:00
64a27f4c29 feat: add 2-point vertical hoisting path support
- Add '2点路径' button in AerialHeightDialog for pure vertical lift
- Handle IsTwoPointMode on first click to create 2-point path directly
- Fix PathTargetFrameResolver to accept 2-point Hoisting paths
- Fix animation yaw for 2-point vertical paths (use _currentYaw)
- Fix TryApplyPlanarRealObjectStartIncrementalTransform to translate even
  when no rotation change (was skipping translation for pure vertical)
- Guard _pathPoints[2] access in animation code for <3 points
2026-06-01 22:56:50 +08:00
a375e977d4 style: 别名树面板统一白色背景 + TreeView MinWidth=300 2026-06-01 11:04:18 +08:00
f8319438e9 fix: 无 DisplayName 的几何体节点显示为「几何对象」而非空字符 2026-06-01 10:39:57 +08:00
a5f9e4da24 feat: MaxFullDisplayDepth 改为从配置文件读取,支持实时生效
- SystemConfig 新增 AliasTreeConfig,含 MaxFullDisplayDepth 属性(默认 2)
- ConfigManager 添加 [alias_tree] 段的 TOML 解析和写入
- default_config.toml 添加 [alias_tree] 配置项
- AliasTreeControl 构造时读取配置 + 订阅 CategoryConfigurationChanged 实时重建
2026-06-01 10:30:21 +08:00
d670ae5c3c perf: BuildNode 延迟 CreatePathId + DisplayPath 同名去重修复
- BuildNode 不再调 FromModelItem/CreatePathId,改用父节点 DisplayPath 拼接
- CreatePathId 只在保存别名时通过 EnsureFullNodeKey 触发
- LazyLoadChildren 用 nameCount 字典计算 siblingIndex,BuildNode 追加 #N 去重
- 子节点 DisplayPath 拼接时剥离父路径中的 ||前缀和#N后缀,与 FromModelItem 一致
- LazyLoadChildren 直接用 parentNode.ModelItem,不再调 FindModelItemByNodeKey
- 别名匹配去掉 fallback,精确到#N
- _dataStore.LoadAll() 提升到循环外
2026-06-01 10:21:02 +08:00
61318b450d chore: DockPane 标题「别名导航树」→「别名树」 2026-06-01 09:12:28 +08:00
fddefde1ed docs: 更新别名树实施方案 — 新增显示原则 + 修正标识/定位/联动描述
- 新增第7节「别名树显示原则」:二条件OR逻辑、深度限制、别名特殊规则、按需加载生命周期
- 第4节:标识改为 CreatePathId格式,定位改为 Models.ResolvePathId
- 第10节:JSON导出格式改为 key 字段
- 第11节:双向联动改为 ModelItem.Parent链 + ExpandAndSelect
- 清理 CleanupOnDemandNodes 逻辑文档化
2026-06-01 09:10:47 +08:00
6260c175d4 fix: 别名树 IndexPath 改用 Navisworks 官方 API CreatePathId/ResolvePathId
- AliasNodeIdentity.FromModelItem: 用 doc.Models.CreatePathId 替代 GetModelItemIndexPaths
- 存储格式统一为 'modelIndex:PathId'(冒号分隔,PathId 为斜杠分隔)
- FindModelItemByNodeKey: 用 Models.ResolvePathId 替代手写 LocateByIndexPath
- 删除 LocateByIndexPath、LocateByDisplayPath、LoadPathChild、EnsureChildLoaded
- 与 PathAnimationManager/BatchQueueManager 使用完全一致的 PathId 格式
2026-05-31 23:26:54 +08:00
f7544a2095 fix: 别名树深度超限节点导航 — 改用 ModelItem.Parent 链替代 IndexPath
- 移除 IndexPath 解析/偏移量等易错逻辑
- ExpandAndSelect 改为沿 ModelItem.Parent 链回溯,ModelItem.Equals 匹配
- 深层节点通过 BuildNode 直接创建,不依赖占位/懒加载通道
- 删除 LoadPathChild、EnsureChildLoaded 等废弃方法
- 清理约 10 行净代码
2026-05-31 22:30:54 +08:00
ea49774f39 fix: no silent catch - log all exceptions 2026-05-31 18:14:09 +08:00
6a3be184a6 fix: crash from VisualTreeHelper.GetParent during rapid clicks
- OnTreeViewItemLeftClick: use e.OriginalSource.DataContext directly,
  not visual tree traversal (FindAncestor)
- _isProgrammaticExpand prevents Expanded event from triggering bulk
  LazyLoadChildren during ExpandAndSelect
- OnNavisSelectionChanged: synchronous processing with _isInternalSelection
  guard prevents feedback loop
- Try-catch wrappers on all COM API call sites (FromModelItem, BuildNode)
2026-05-31 18:12:34 +08:00
cba8e3f3b7 feat: depth-limited tree display for performance
- MaxFullDisplayDepth=2: only show full tree up to level 2
- Beyond max depth, nodes only expand if they have an alias
- AliasNodeViewModel.Depth tracks tree depth
- Reduces loaded nodes for large models with deep unaliased branches
2026-05-31 17:28:05 +08:00
7418fe28aa feat: JSON import/export for aliases + crash protection
- Export: JavaScriptSerializer, .alias.json format matching path data pattern
- Import: merge mode (overwrites existing keys, adds new)
- Try-catch wraps on SetAlias, RefreshAliases, NW selection operations
- Prevents crashes from database inconsistency or API exceptions
2026-05-31 17:10:32 +08:00
4da6669707 refactor: lazy database creation - match path planning pattern
- TryConnectToDatabase: createIfMissing=false (only connect, don't create)
- New BeforeSaveAlias event + EnsureDatabaseCreated: creates DB on first save
- Matches MainPlugin.TryConnectPathDatabase pattern
2026-05-31 16:56:57 +08:00
af7099d682 fix: alias persistence - trigger DatabaseInitialize on connect
- TryConnectToDatabase calls DatabaseInitialize(createIfMissing:true)
- Alias saving now creates .db file if it doesn't exist
- Removed delayed retry code (no longer needed)
- Added diagnostic logging for SetDataStore/RefreshAliases
2026-05-31 16:40:54 +08:00
903ed856e3 feat: display alias with [original name] suffix, fix false alias detection
- Two stacked TextBlocks: alias (red, bold) + [原文] (black, bold)
- [原文] suffix only visible when HasAlias=true
- CommitEdit/toolbar: treat unchanged text as no alias (set to null)
- Fixes: nodes edited without actual changes no longer show false [原文] suffix
2026-05-31 16:29:17 +08:00
d358c31a7d feat: inline editing with click-to-edit, TextBox overlay, Focus+SelectAll
- Grid overlay: TextBox covers TextBlock when editing (no more dual display)
- EditValue property: auto-initialized to DisplayName on edit start
- Click on already-selected node enters inline edit (PreviewMouseLeftButtonDown)
- Right-click auto-selects node before context menu
- TextBox IsVisibleChanged: Focus + SelectAll on Loaded priority
- XAML Visibility moved to Style setter (fix DataTrigger precedence)
- Light yellow background (#FFFFFDE6)
2026-05-31 15:52:03 +08:00
ad398652a7 feat: alias persistence via PathDatabase SQLite
- AliasTreePlugin 监听文档生命周期,连接 PathDatabase
- AliasDataStore 写入 PathDatabase.SQLiteConnection
- 编辑别名实时持久化,重启后自动恢复
- 修复 _isInternalSelection 阻塞 _currentSelectionItem 更新导致编辑写错节点
2026-05-31 14:59:54 +08:00
9a6859cdb5 style: match Navisworks Selection Tree font/color
- 别名用暗红色字体 (#C62828),原名用黑色
- 选中态:浅灰蓝底色 (#3A6EA5) + 白色字体,无焦点时也保持
- 字体加粗 SemiBold,字号 12px
- 移除斜体灰色样式和方块标记
2026-05-31 14:47:01 +08:00
b42cf02710 fix: bidirectional sync working for deep nodes + scroll-into-view
- 关掉 VirtualizingPanel 虚拟化(树是懒加载,虚拟化收益小但导致 ContainerFromItem 失败)
- ExpandAndSelect 重写为 IndexPath 纯 ViewModel 导航,不依赖 TreeViewItem
- 新增 GetTreeViewItemForNode:从 TreeView 根沿 parent 链找 Tvi
- IndexPath -1 修正(COM 路径从 1 开始计数,.NET Children 从 0)
- BringIntoView 延迟到 Dispatcher.Background
- 清理无用代码(ExpandAndSelectRecursive)
2026-05-31 14:21:50 +08:00
c002feee51 fix: ExpandAndSelect uses ModelItem.Equals for precise sibling matching
- 新增 AliasNodeViewModel.ModelItem 属性(持有 Navisworks 原生引用)
- BuildNode 中存储 ModelItem
- ExpandAndSelect 重写为 DFS 递归,用 ModelItem.Equals 精确匹配
  (同 ModelItemAnalysisHelper.ModelItemEquals 逻辑,底层原生对象比较)
- 不再依赖 IndexPath 或 _nodeMap 做选中同步
2026-05-31 13:17:52 +08:00
4feb12f6b9 refactor: AliasNodeIdentity dual-field + reuse ModelItemAnalysisHelper
- 新增 IndexPath(COM 树索引路径),复用 ModelItemAnalysisHelper.GetModelItemIndexPaths
- 保留 DisplayPath(父链 DisplayName 拼接)作为降级匹配
- 序列化格式:"IndexPath||DisplayPath",向后兼容纯 DisplayPath
- FindModelItemByNodeKey: IndexPath 优先定位,DisplayPath 降级
- BuildNode: 新增旧格式兼容查找
- 单元测试全面更新覆盖新/旧格式、双字段解析、前缀匹配
2026-05-31 12:52:26 +08:00
56d18c696c phase 2b: add AliasTreePlugin DockPanePlugin entry + wiring
- AliasTreePlugin.cs: DockPanePlugin with ElementHost wrapper
- XAML: wire Expanded/Selected event handlers via TreeViewItem
- Both projects compile, plugin deployed to Navisworks
2026-05-31 12:49:50 +08:00