- Show hidden pins immediately when camera moves (not just on occlusion frames)
- Throttle scene.pick occlusion checks from every 3 to every 6 frames
- Guard against disposed scene in projection loop
- Replace preview! with preview?. in slider/axis closures
- Use scene.forceWireframe for PBR material support
- Click-to-pin: click on 3D model to add labeled bookmarks with color
- Edit existing pins: click pin to edit label/color, or delete
- Camera focus: click pin label in panel to animate camera to pin position
- Depth occlusion: pins behind geometry show blurred/dimmed; fully hidden when camera idle
- Workbench integration: Annotations panel with toggle, pin list, edit/delete/focus actions
- DirectView integration: annotation toolbar button with pin count badge
- Code-block readonly: display saved annotations in inline previews
- ESC to exit annotation mode
- Semi-transparent mode overlay when annotation active
- Coordinate fix: engine render → CSS pixel scaling for accurate pin positioning
- Relative occlusion epsilon for large model compatibility
The build_xde_color_lookup function used BRepAdaptor_Surface without
importing it, causing a silent NameError that left the color lookup
table empty. All STEP faces fell back to default gray [180,180,180].
- Add en/zh-CN translation dictionaries for all settings strings
- Add t() translation function with locale state management
- Add locale field to PluginSettings with auto-detect on first run
- Replace all hardcoded English strings in settings.ts with t() calls
- Add language selector dropdown at top of settings page
- orientation-gizmo: set viewport directly on camera instead of manual
engine.setViewport (which was overridden by scene.render)
- scene: include rootMesh in wireframe iteration for STL/PLY single-mesh models
- direct-view: remove height:100% that caused excessive blank space
- code-block: remove defaultCanvasHeight from min-height, use CSS only;
grid uses height instead of min-height so CSS max-height can cap it
- styles.css: reduce preview-host min-height, add grid-host max-height
- Rewrite README.md with table of contents and clear sections
- Add README.zh-CN.md with full Chinese translation
- Add language switch links at top of both files
- Organize: Quick Start, Installation, Format Support, Usage, Settings, Technical Details, Deployment
- Reorganize README.md with cleaner structure
- Add README.zh-CN.md with full Chinese translation
- Add language switch links between EN/CN versions
- Streamline sections: Features, Usage, Settings, Pipeline, Architecture, Deployment
- Add loadPLYBuffer() to bypass SceneLoader for PLY files (same Babylon v9 data-URL fix as STL)
- Update scene.ts to use direct loading for PLY format
- Add Model Import Pipeline section to README with architecture principles
- Add Format Parsing Details (STL/PLY/OBJ/GLB/SPLAT/FBX binary structures)
- Add Complete Format Support Matrix (15 formats)
- Add Format Feature Details comparison table
- Add Known Limitations section
New features:
- Add SLDPRT (SolidWorks) converter via FreeCAD + OpenCASCADE pipeline
- Add IGES/IGS and BREP format support via format-aware Python scripts
- Add 3MF and DAE format support via trimesh/Assimp converter
- Add loading overlay component with progress bar and phase text
- Enable STP files by default in format registry
Portability:
- Remove all hardcoded user paths, use process.env.LOCALAPPDATA for discovery
- Fix .split("/") path separator issues (scene.ts, app.ts, helper-buttons.ts)
- Add macOS Apple Silicon Homebrew paths (/opt/homebrew/bin/)
- Fix escapePyStr + raw string double-escaping (pyPath normalizes to forward slashes)
- Add maxBuffer to all execFileAsync calls (50MB)
Bug fixes:
- Fix OBJ load errors silently swallowed (now re-throw after logging)
- Fix explode position drift on repeated set/reset cycles (store original center)
- Fix explode uses world-space position (switch to local position)
- Fix picking highlight material leak when mesh disposed externally
- Fix grid layerMask collision in compose presets (one cell = one bit)
- Fix renderScale/quality inconsistency (track currentQuality)
- Fix stale loading flag drops model path changes (pendingPath mechanism)
- Fix persist() unhandled rejection on save failure
- Fix Python injection via double-quote in paths (reject quotes in pyPath)
- Fix PLY face indices parsed as floats (Math.round)
- Fix PLY face indices no bounds checking (skip out-of-range)
- Fix ASCII STL produces confusing error (detect and warn)
- Fix WebGL engine leak on live-preview load error
- Fix DirectView race condition on rapid file loads (generation counter)
- Fix MutationObserver not disconnected on code-block load error
- Fix auto-save timer fires after plugin unload (add dispose)
- Fix duplicate conversions on concurrent requests (in-flight dedup)
Other:
- Rewrite README with comprehensive usage, third-party setup, and demo page
- Add docs/demo.md with 11 feature walkthrough sections
- Remove dead code (freecad-stub.ts)
Per FORMAT_SUPPORT_DESIGN.md, FBX should have both direct channel
(babylonjs-fbx-loader) and convert channel (FBX2glTF CLI).
Bundle size 7.7MB is within design doc's expected 8.2-10MB range.
- Added console.log in STL parser (triangle count, buffer size)
- Added console.log in DirectModelView (file path, size, success/failure)
- Wired renderScale through all call sites
- Created 3D Diagnostic Test.md for debugging
- Add renderScale setting (0.25x–2.0x) in PluginSettings
- Settings UI: resolution scale slider with 0.25 step
- Toolbar: quick cycle button (0.5x → 0.75x → 1.0x → 1.5x → 2.0x)
- setRenderScale() on both BabylonModelPreview and GridRenderer
- Integrated with existing renderQuality preset and mobile boost
- Applied in code-block processor and workbench after model load
- Deduplicate generateNote() in main.ts, reuse app.ts version
- Remove unused formatFileSize() and escapeObsidianMarkup()
- Wire up isMobile() for automatic resolution scaling on mobile
- Replace hardcoded #1e1e22 with CSS variable for theme compat
- R: reset view
- W: toggle wireframe
- G: toggle orientation gizmo
- B: toggle bounding box
- Space: play/pause animation
- Canvas must have focus (click on it first)
- Works in both 3d and 3dgrid code blocks
- XYZ axis indicator rendered in bottom-left corner of preview
- Separate Babylon scene with its own camera tracking main rotation
- Toggle via toolbar button (compass icon)
- Added to SnapshotProvider interface
- Serialize generateKnowledgeNote to prevent TOCTOU and duplicates (Fix #33/34)
- Destroy preview on load failure to prevent Engine/Scene leak (Fix#38)
- Clean up stale error messages on model retry
- Pass getSettings to DirectModelView for snapshot save settings
- OBJ monkey-patch concurrency lock to prevent clobbering (Fix#1)
- ShadowGenerator: type guard for light instead of as any (Fix#9)
- instanceof TFile instead of "extension" in file / as any (Fix#10)
- Static Color3 import in grid.ts, remove dynamic import (Fix#13)
- detachControl cameras in destroy() for scene.ts and grid.ts (Fix#35)
- Replace rootMesh! assertions with null guards (Fix#36)
- BabylonModelPreview: hasAnimations(), toggleAnimation(), setAnimationSpeed()
- Helper toolbar: play/pause button appears when model has animations,
toggles between play triangle and pause bars icons
- Workbench sidebar: Play/Pause button in actions when animations detected
- Animation button auto-shows in code-block after model load
- BabylonModelPreview.toggleWireframe() tracks state and toggles
all mesh materials
- GridRenderer.toggleWireframe() toggles wireframe across all cells
- Helper toolbar gets a grid icon button with visual active state
(accent color when wireframe is on)
- BabylonModelPreview.exportModelInfo() generates Markdown with summary
table, per-mesh breakdown (name/triangles/vertices/material), material list
- GridRenderer.exportModelInfo() generates per-cell summary table
- Helper toolbar: info button copies Markdown to clipboard
- Workbench: "Insert Info" inserts Markdown at cursor in active note
- BabylonModelPreview.resetView() restores initial camera alpha/beta/
radius/target and resets explosion
- GridRenderer.resetView() resets all cell cameras to initial state
- Helper toolbar gets a refresh-arrow button (first position)
- Workbench sidebar gets "Reset View" action button when preview is active