Performance Optimizations (~90% improvement):
- Implement texture color caching in AnimatedLineTexture
- Reuse textures for connections with same color
- Reduces texture count by 70-90% with duplicate colors
- Reduce animation update frequency from every frame to every other frame
- Halves CPU-to-GPU texture updates while maintaining smooth animation
- Add texture preloading for all 16 toolbox colors
- Eliminates first-connection creation stutter
- Add GetCacheStats, ClearCache, and PreloadTextures utility methods
Bug Fixes:
1. Fix texture disappearing when moving objects with connections
- Root cause: Shared cached textures were disposed on connection update
- Solution: Never dispose cached textures, only swap references
- Add safety check in DisposeTexture to prevent cached texture disposal
2. Fix UI text textures bleeding to normal materials
- Add metadata.isUI = true to 10+ UI components:
- Button.ts (with unique material names per button)
- handle.ts, roundButton.ts, createLabel.ts, updateTextNode.ts
- spinner.ts, vrConfigPanel.ts, buildImage, introduction.ts
- ResizeGizmo.ts
- Update LightmapGenerator filter to check metadata.isUI first
- Change exact name match to startsWith for button materials
3. Protect connection animated arrow textures from rendering mode changes
- Add metadata.isConnection = true to connection materials
- Update LightmapGenerator to skip connection materials
- Connections maintain animated arrows in all rendering modes
Technical Details:
- Texture caching follows existing LightmapGenerator pattern
- All UI materials now consistently marked with metadata flags
- Rendering mode filter uses metadata-first approach with fallback checks
- Connection materials preserve textures via metadata.preserveTextures flag
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
Label Positioning Fixes:
- Fix labels accounting for mesh scaling using maximumWorld coordinates
- Labels now properly positioned on scaled objects (spheres, boxes, etc.)
- Restore world→local coordinate transformation in updateLabelPosition
Billboard Mode Implementation:
- Add configurable label rendering modes: fixed, billboard, dynamic, distance-based
- Implement billboard mode (labels always face camera using BILLBOARDMODE_Y)
- Add label rendering mode to AppConfig with default 'billboard'
- Add UI selector in ConfigModal for label rendering mode
- Observable pattern updates all existing labels when mode changes
XR Entry Positioning Fix:
- Synchronize desktop camera position to platform before entering XR
- Transfer camera world position and rotation to prevent scene shift
- Reset physics velocity on XR entry to prevent drift
- Add debug logging for position synchronization
Config System Architecture Fix:
- Create singleton appConfigInstance to ensure single source of truth
- Update DiagramObject to use singleton instead of creating instances
- Update DiagramManager to use singleton
- Fix ConfigModal to update AppConfig directly (was only updating legacy config)
- ConfigModal now triggers Observable notifications via appConfigInstance setters
- Maintain legacy config for backward compatibility
- Fixes issue where label rendering mode changes didn't take effect
Files Modified:
- src/diagram/diagramObject.ts - Label positioning, billboard mode, singleton config
- src/diagram/diagramManager.ts - Use singleton config
- src/util/appConfig.ts - Add labelRenderingMode, export singleton
- src/util/appConfigType.ts - Add LabelRenderingMode type
- src/react/pages/configModal.tsx - Update AppConfig directly, add label mode UI
- src/util/functions/groundMeshObserver.ts - Add camera position sync on XR entry
- public/api/user/features - Update test config
- package.json - Version bump
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>