# Change log

## v4.3.9

- Support texture rotation for triplanar and parametric uv texture mapping
- Properly support viewer reuse and direct-to-tab rendering without CAD flash
- Implement policy to keep/reset clip slider and normal values in three-cad-viewer, based on bbox/gridsize
- Fix env rotation in Z-up scenes (use ZYX Euler order) which was changed by three.js r184
- Fix to keep state.theme in sync with the DOM

## v4.3.8

- Support 4K HDR env maps
- Exclude backMaterial from casting shadow
- Bump some dev package versions, and remove ^ from versions (pinning version to minimize supply-chain-attacks)
- Fix an inconsistency of studio's 4k env map checkbox with shown env map
- Fix bug that restore material editor settings across viewing sessions
- Fix a state bug between explode tool and measurement tools

## v4.3.7

- Fixed triplanar shader ignoring `textureRepeat` for materials without a color texture (e.g. roughness+normal only)

## v4.3.6

- Fixed `textureRepeat` being shared across materials using the same texture — textures are now cloned when repeat differs
- Removed `src/` from published npm package (source maps are self-contained)

## v4.3.5

- Fixed `CenteredPlane.clone()` crash during shadow map generation with clipping planes active
- Fixed builtin preset color override: leaf node CAD color is now used as fallback when no explicit color is provided
- Updated examples (toycar, shader_ball, profile4040, boxes) to new material format

## v4.3.3, v4.3.4

- Re-enabled anisotropy support for both builtin and MaterialX materials — tangent vectors are now computed automatically for geometries with UVs
- Refactored `MaterialXMaterial` interface: split `properties` dict into separate `values` and `textures` fields
- Increased shadow camera frustum and floor plane size to prevent shadow clipping with low-angle IBL lights
- Added `README.md` to published package files

## v4.3.1, v4.3.2

- Disabled anisotropic reflections in Studio mode — CAD meshes lack tangent vectors, causing facet artifacts
- Enabled 16x anisotropic texture filtering for sharper textures at oblique angles

## v4.3.0

- Fixed `normalScale` and `clearcoatNormalScale` handling in `createStudioMaterialFromMaterialX` — array values are now correctly converted to `THREE.Vector2`
- Removed automatic save/restore of grid, axes, and ortho mode when entering/leaving Studio mode — these are now user-controlled
- Removed procedural builtin textures (brushed, knurled, sandblasted, hammered, checker, wood-dark, leather, fabric-weave) and the `builtin:` texture resolution path
- Removed shared `textures` table support (`TextureEntry` type, `setTexturesTable`, `textures` field on `Shapes`) — threejs-materials carry textures inline as data URIs
- Removed `wood-light` and `wood-dark` material presets (29 presets, down from 31)
- Fixed examples to use correct color value ranges and consistent material definitions

## v4.2.0

**Studio Mode** (new, beta)

A new **Studio** tab provides physically-based rendering with per-object materials, environment-based lighting, shadows, ambient occlusion, and tone mapping — turning the CAD viewer into a product visualization tool.

- **Per-object PBR materials**: Assign materials to shapes via a `material` string tag on leaf nodes and a root-level `materials` dictionary
  - Supports two formats: `"builtin:preset-name"` strings (31 built-in presets) and `MaterialXMaterial` objects (from the [threejs-materials](https://github.com/bernhard-42/threejs-materials) Python library, 3,200+ PBR materials)
  - `MeshPhysicalMaterial` for all objects in Studio mode (clearcoat, transmission, sheen, IOR, anisotropy, etc.)
  - Transparent objects auto-converted: `alpha < 1` → `acrylic-clear` preset with `transmission = 1 - alpha`
- **Texture mapping**: Triplanar shader injection for UV-less CAD geometry (default), with parametric fallback toggle
  - 8 procedural builtins (brushed, knurled, sandblasted, hammered, checker, wood-dark, leather, fabric-weave)
  - `TextureCache` with 4-tier resolution (builtin procedural, textures table, data URI, URL) and promise deduplication
- **Environment maps**: Image-based lighting (IBL) via Poly Haven HDR presets (CC0 license)
  - 15+ curated presets (studio, workshop, outdoor, architectural), loaded on demand from Poly Haven CDN
  - Procedural `RoomEnvironment` bundled as zero-network fallback
  - Custom HDR URL support via API
  - 2K default resolution with runtime **4K toggle**
  - Environment rotation slider with synchronized shadow light positioning
- **Background modes**: gradient grey, gradient dark grey (default), white, environment, or transparent
  - Environment background rendered via fixed-FOV virtual camera for consistent appearance across ortho/perspective
  - Solid-color backgrounds excluded from tone mapping via alpha compositing
- **Shadows**: Two-pass blurred shadow system with depth masking
  - Automatic shadow light placement from HDR environment analysis (light detection)
  - PCF shadow maps at 4096×4096, Kawase blur with continuous softness control
  - Floor-only + objects-only mask passes to avoid depth-discontinuity glow halos
  - Shadow intensity and softness sliders
- **Ambient Occlusion**: N8AO screen-space AO with depth-aware upsampling and user-controlled intensity
- **Tone mapping**: PBR Neutral (default), ACES Filmic, or none — with exposure control
- **Anti-aliasing**: SMAA via postprocessing library EffectComposer
- **Material Editor**: Interactive PBR parameter tweaker for selected objects in Studio mode
  - 14 slider parameters (metalness, roughness, clearcoat, transmission, IOR, sheen, anisotropy, emissive, specular)
  - Per-object material cloning with triplanar mapping preservation
  - Changed-value highlighting, draggable panel, auto-reopen on selection change
  - Material editor changes persist across tab switches
- **Material presets**: 31 built-in presets (polished/matte metals, plastics, glass, rubber, painted, natural) — usable as `"builtin:preset-name"` in the materials dictionary
- **Data format**: New fields on shapes root node: `materials`, `textures`, `studioOptions`
- **Studio tab controls**: Environment selector, env intensity/rotation sliders, background mode, tone mapping, exposure, shadow intensity/softness, AO intensity, texture mapping toggle, 4K env maps toggle, reset button
- **API**: `setStudioEnvironment()`, `setStudioEnvIntensity()`, `setStudioBackground()`, `setStudioToneMapping()`, `setStudioExposure()`, `setStudio4kEnvMaps()`, `setStudioEnvRotation()`, `setStudioTextureMapping()`, `setStudioShadowIntensity()`, `setStudioShadowSoftness()`, `setStudioAOIntensity()`, `enterStudioMode()`, `leaveStudioMode()`, `resetStudio()`, `isStudioActive`, `getSelectedObjectGroup()`
- **Keyboard shortcut**: `s` to switch to Studio tab
- **Architecture**: `StudioManager` class encapsulates Studio orchestration (subscriptions, enter/leave, shadows, floor, tone mapping) — extracted from viewer.ts for maintainability

**UI Improvements**

- Reordered tabs: Tree | Clip | Zebra | Material | Studio
- Added reset buttons for Clip and Zebra tabs
- 4 visual groups in Studio tab: Environment | Appearance | Shadows & AO | Textures
- Collapsible Tools and Info panels in glass mode with arrow toggle indicators
- Tools panel toggle also hides/shows orientation marker and animation/explode slider
- Animation and Z-scale bars use same rest/hover transparency as tools and info panels
- Semi-transparent overlay backgrounds in glass mode (rest vs hover states)
- Inline label+control layout for Studio, Material, and Zebra sliders

**Fixes**

- Fixed z-fighting on large models by scaling near plane with scene size (`near = max(0.1, 0.01 * boundingRadius)`)
- Fixed environment map background appearing as tiny rectangle with orthographic cameras
- Fixed raycaster not filtering hidden objects in Studio mode (Three.js `intersectObjects` does not check `Object3D.visible`)
- Fixed shift-double-click (isolate) showing edges in Studio mode
- Fixed staircase artifacts in procedural studio environment background
- Fixed release script to include type declaration files and source maps

**New Dependencies**

- `three` upgraded from r180 to r183 (WebGL 1.0 removed, `Clock` deprecated → migrated to `Timer`)
- `postprocessing` 6.38.3 — EffectComposer, ToneMappingEffect, SMAA, KawaseBlur
- `n8ao` 1.10.1 — screen-space ambient occlusion

**Tests**

- 67 Studio-specific tests across 5 test files (decode-instances, mode switching, light detection, material presets, material factory, studio floor)
- Full suite: 1332 passed, 0 failed

## v4.1.2

**Fixes**

- Make default zoom faster again (regression from 4.1.1)
- Fix boundary color of colorful zebra for odd stripe count

## v4.1.1

**Fixes**

- Fix the zoom state residual issue beacuse of TrackballControls using dynamic damping

## v4.1.0

**Features**

- Added `addPart(parentPath, partData)` to dynamically add a leaf shape or subtree to the scene after `render()`, and `removePart(path)` to remove a part or entire subtree by absolute path
  - Leaf parts use a plain `name` (no leading slash); the viewer constructs the absolute path from the parent
  - Subtree parts use slash-prefixed relative ids; `addPart` prefixes every id with the parent path before rendering
  - Both methods validate uniqueness at the insertion level and update the bounding box, clipping, and tree view
- Added `updatePart(path, updates)` for in-place buffer updates on existing parts without rebuilding the scene graph, and `updateParts(updates[])` for batched updates
- Added keyboard shortcuts for toolbar buttons, camera presets, tab navigation, and animation control
  - When the viewer container has focus (via click), single-key presses trigger actions
  - Modifier-key mappings (shift/ctrl/meta/alt) continue to work as before
  - The `keymap` option is fully configurable; user overrides merge with defaults
  - Button tooltips show `[key]` suffixes; tab elements get title attributes with their shortcut
  - Default bindings:
    - Toggle: `a`/`A` axes, `g`/`G` grid, `p` perspective, `t` transparent, `b` blackedges, `x` explode, `L` zscale, `D` distance, `P` properties, `S` select
    - Views: `0` iso, `1`–`6` front/rear/top/bottom/left/right, `r` resize, `R` reset
    - Tabs: `T` tree, `C` clip, `M` material, `Z` zebra
    - Other: `h` help, `Space` play/pause, `Escape` stop/close-help
- Measurement improvements
  - Measurement arrows adapt to point proximity: cones flip outward when points are close, and are hidden when coincident — preventing visual overlap
  - Measurement panels now render grouped backend responses with horizontal separators between groups

**Build & Tooling**

- Switched documentation generator from JSDoc to TypeDoc for native TypeScript support

## v4.0.0

**TypeScript Migration**

- Complete migration from JavaScript to TypeScript with full strict mode
- All 24 source files converted with comprehensive type definitions
- Created `src/core/types.ts` with shared interfaces and type guards
- Added Three.js module augmentation for internal API usage
- Enabled all strict compiler options: `strict`, `noUnusedLocals`, `noUnusedParameters`, `exactOptionalPropertyTypes`
- Reduced explicit `any` usage to 2 documented cases
- Exported all public API types from index.ts for library consumers

**Architecture**

- Major refactoring to decouple components and modernize the codebase
- Reorganized filesystem into logical folders: `core/`, `scene/`, `camera/`, `rendering/`, `tools/`, `ui/`, `utils/`
- Introduced centralized `ViewerState` class for state management with subscription support
- Decoupled `Viewer` from `Display` - Display now receives Viewer instance via dependency injection
- Controls architecture rewritten with separate `CADOrbitControls` and `CADTrackballControls` classes
- New `Controls` wrapper class providing unified API with normalized speed factors
- Added `MaterialFactory` for centralized material creation and management
- Improved memory management with consistent `dispose()` methods across all components

**Features**

- Added `holroyd` parameter to control non-tumbling trackball rotation mode
- Exposed `getHolroyd()` and `setHolroyd()` methods on Viewer
- Normalized control speed settings (pan, rotate, zoom) - 1.0 now means consistent default experience across control types
- Added `logger` utility for configurable log levels (debug, info, warn, error, silent)
- Added `gpuTracker` utility to detect GPU memory leaks with optional debug mode for stack traces
- Added `CollapseState` enum replacing numeric collapse values with named constants (`LEAVES`, `COLLAPSED`, `ROOT`, `EXPANDED`)
- Centralized state notification system with `STATE_TO_NOTIFICATION_KEY` mapping
- Added `syncMaterialSlidersFromState()`, `syncZebraSlidersFromState()`, and `syncClipSlidersFromState()` for proper UI initialization
- Export getters for `cadWidth`, `treeWidth`, `height` dimensions
- Added `isCompoundGroup` type guard
- Added comprehensive unit and integration test suite (1200+ tests, 90% coverage)

**Build & Tooling**

- Added `"type": "module"` to package.json for native ES modules
- Added `exports` field for modern package resolution
- Added `sideEffects` field for better tree-shaking
- Updated vitest coverage configuration for TypeScript sources
- Removed obsolete `.eslintrc.json` (using flat config)

**Fixes**

- Fixed trackball panning speed to be more responsive
- Fixed holroyd (non-tumbling) trackball rotation
- Ensured proper disposal of all Three.js objects to prevent memory leaks
- Cleaned up debug console.log statements (now behind logger)

**Migration from 3.6 to 4.0**

_Import Changes_

```javascript
// Before (3.x)
import { Viewer, Display } from "three-cad-viewer";

// After (4.0) - same, but internal structure changed
import { Viewer, Display } from "three-cad-viewer";

// New exports available
import { CollapseState, logger, gpuTracker } from "three-cad-viewer";
```

_CollapseState Enum_

```javascript
// Before (3.x)
viewer.collapse = 0; // collapsed
viewer.collapse = 1; // root only
viewer.collapse = 2; // expanded
viewer.collapse = -1; // leaves

// After (4.0)
import { CollapseState } from "three-cad-viewer";
viewer.collapseNodes(CollapseState.COLLAPSED);
viewer.collapseNodes(CollapseState.ROOT);
viewer.collapseNodes(CollapseState.EXPANDED);
viewer.collapseNodes(CollapseState.LEAVES);
```

_State Access_

```javascript
// Before (3.x) - direct property access
const isOrtho = viewer.ortho;
viewer.ortho = false;

// After (4.0) - use getters/setters
const isOrtho = viewer.getOrtho();
viewer.setOrtho(false);

// Or via state (for TypeScript users)
const isOrtho = viewer.state.get("ortho");
viewer.state.set("ortho", false);
```

_Notification Key Changes_

```javascript
// Before (3.x)
callback({ edge_color: { new: 0x707070, old: 0x000000 } });

// After (4.0)
callback({ default_edgecolor: { new: 0x707070, old: 0x000000 } });
```

_Control Speed Normalization_

Control speed values (pan, rotate, zoom) are now normalized. A value of `1.0` provides consistent default behavior across both OrbitControls and TrackballControls.

```javascript
// Before (3.x) - different scales for different control types
viewer.rotateSpeed = 2.0;

// After (4.0) - normalized, 1.0 is default
viewer.setRotateSpeed(1.0);
```

_Logger Usage_

```javascript
// Before (3.x) - console.log scattered through code
console.log("debug info");

// After (4.0) - centralized logger
import { logger } from "three-cad-viewer";
logger.setLevel("debug"); // "debug" | "info" | "warn" | "error" | "silent"
logger.debug("debug info");
```

## v3.6.3

**Fixes**

- Fix typos in the properties selectTool and explodeTool in toolbar.js preventing the tools being visible

## v3.6.2

**Features**

- Dynamic theme support
  - Grid now scales dynamically based on zoom level
  - Beautified grid with dashes and different colors for better visual clarity
  - Enhanced grid font rendering with improved axis label readability
  - New paramter "gridFontSize" with default 12
- Viewer now automatically reacts to theme changes from the browser or OS
- Add viewer version to ready message for better debugging
- Introduced EventListenerManager for better event disposal
- Allow clicking on canvas to close help dialog
- Settle on FOV 22 and improve perspective camera settings

**Fixes**

- Theme handling
  - Remove wrong theme setting and 'dark' property
  - Set initial theme properly on viewer initialization
  - Ensure body background is theme sensitive
- Remove context menu from help dialog
- Make keymap routine more robust
- Improve heuristics for various viewer operations
- Add overflow hidden to body tag to prevent scrolling issues
- Bump version of three.js to 0.180.0

## v3.6.1

**Features**

- Add polygon renderer for GDS files (will be part of gdsfactoryplus)
- Add a z-scale tool for GDS files
- Add GDS chip design examples (photonic and classic)

**Fixes**

- Change memory management to a new paradigm using a global function deepDispose which works recursively
- Fix setCameraTarget
- Fix keymapping regression where keymaps were not used any more
- Reduce far plane distance to improve transparent rendering

## v3.5.0

**Features**

- The viewer now supports widths of < 815px with shrunken toolbar (using ellipsis). From 815px width the toolbar is fully visible
- The view preset buttons in the toolbar now respect shift and will center the to all visible objects only

For the following features you need a measure backend, e.g. as in [VS Code OCP Viewer](https://github.com/bernhard-42/vscode-ocp-cad-viewer)

- Removed angle measure button, it is integrated in distance measure
- Simplified filter management in measure mode since angle tool vanished
- Changed shift modifier in distance measure mode to distinguish between min and center distance
- Changed the hard coded DEBUG flag in measure mode to a display options parameter measurementDebug

**Fixes**

- Move measurement toggle to display options

## v3.4.3

**Fixes**

- Make measure debug mode asynchronous and fix delay-by-one-step regression

## v3.4.2

**Fixes**

- Ensure that lines and arrows for measurement are initialized once only to remove memory leaks [#29](https://github.com/bernhard-42/three-cad-viewer/issues/29)
- Clean up disableTools, disableContext and dispose
- Ensure tools get properly disabled

## v3.4.1

**Features**

- Clicking on a tree label with shift+meta hides all others without change of location

**Fixes**

- Fix isolate mode when there are only 1-dim objects in the viewer
- Fix parameters whan calling handlepick

## v3.4.0

**Features**

- Add select shapes mode for OCP CAD Viewer

**Fixes**

- Add \_ in vertex enumeration for the expanded mode

## v3.3.5

**Fixes**

- Move disposing of shapes and groups to clear()
- Fix wrong order of parameters in the Viewer.render function
- Add a color indicator to the objects in the navigation tree

## v3.3.4

**Fixes**

- Move packages "cross-spawn" and "html-minifier" to dev dependencies

## v3.3.3

**Fixes**

- Fix center_grid parameter name

## v3.3.2

**Fixes**

- Ensure theme is only set for container and not for document
- Replace scrollIntoView for the navigation tree with own logic to avoid page jumps in Jupyter
- Fix clip setting via API

## v3.3.1

**Fixes**

- Fix top level bounding box

## v3.3.0

**Features**

- Change measure panel to be stable

**Fixes**

- Fix top and bottom skew for up=Z
- Add dispose methods to measure classes
- Fix switching object while measurement is active

## v3.2.3

- Fix toggleTab after dispose is called

## v3.2.2

- Fix updating orientation marker after changes in treeview

## v3.2.1

- Fix removing orientation marker from screenshot

## v3.2.0

**Features**

- Add a function to set the center of the grid interactively
- Restrict help box to viewer size, use scrolling and enable Escape everywhere
- Add setVisible to orientationMarker and hide the marker during screenshots
- Move display out of viewer and setup ui before showing cad objects

**Fixes**

- Fix glass/no tools mode
- Fix double clicking edges leading to crash
- Fix some security alerts
- Add dispose method to fix memory leaks

## v3.1.8

**Features**

- Allow to deselect all selected objects via right click

**Fixes**

- Fix mouse up position comparison
- Change resize button to always zoom to factor 1
- Fix center to point on double click

## v3.1.6

**Features**

- Add KeyMapper to measure click event handler
- Introduce new file format
- Introduce a new lazy tree component
- Highlight back side of faces in measure mode
- Enable radius2 for measuring ellipses
- Open first level on start

**Fixes**

- Ensure STLs are handled properly
- Fix regression around click handling in measure mode
- Remove unused code
- Add measure mode to help
- Support longer names in the tree
- Updated all examples to new data format
- Support image faces for expanded faces
- Fix interworking of explode and measurements
- Hide animation control in measure mode
- Remove double render
- Fix top level bounding box
- Fix label color on second click
- Fix selecting full solids
- Enable animation loop for taking screenshots
- Prevent model toggling when switching between tools
- Disable clipping tab instead of hiding it
- Add a function to show/hide clipping tab

## v2.2.5

**Fixes**

- Handle protocol v3 and ensure protocol v2 and v1 are still rendered

## v2.2.4

**Fixes**

- Do not handle clipping planes in raycaster

## v2.2.3

**Fixes**

- Check a front exists before changing its material

## v2.2.2

**Fixes**

- Add a function to retrieve objectgroup's state
- Ensure all for all deselected objects the stencil planes are invisible

## v2.2.1

**Fixes**

- Fix brightening backcolor via lerp()
- Hide stencil plane together with faces for better clipping

## v2.2.0

**Features**

- Introduce stencil for clipping
- Add reset button to material configurator
- Ensure clipping object color check box gets checked when set per api
- Implement centered grid and numbers on the grid

**Fixes**

- Fix input value of sliders
- Make plane helper material double sided
- Made glass mode the default
- Make background color a bit brigther to distinguish from edge color
- Show image texture on both side
- Wrap color value into THREE.Color class
- Fix toolbar checkboxes not working, fix dropdown hiding

## v2.1.2

**Features**

- Changed to protocol 2
- Introduce measurement mode

## v1.8.7

**Features**

- Key mapping can be changed (viewer.setKeyMap({"shift": "ctrlKey", "ctrl": "shiftKey", "meta": "altKey"}) or as parameter to the viewer

**Fixes**

- Switched to threejs r155 and fixed for the breaking change for light intensity
- "clean" and "build" steps in package,json are Windows friendly (note, docs and release aren't, but you might not need them)

## v1.8.6

**Fixes**

- Fixed root collapse mode

## v1.8.5

**Fixes**

- Ensure center is set as target for preset buttons
- Added Vector3 and Quaternion creator

## v1.8.4

**Fixes**

- Fixed trihedron panning for panned objects

## v1.8.3

**Fixes**

- Ensure notifications for material properties are sent
- Add setters for material properties

## v1.8.2

**Fixes**

- Integrate helvetiker font into code

## v1.8.1

**Fixes**

- Removal of environment maps and new defaults

## v1.8.0

**Features**

- XYZ labels for orientation marker
- Support for metalness and roughness
- Material configurator tab

## v1.7.12

**Fixes**

- Ensure no exceptions are thrown when the view is cleared and resized

## v1.7.11

**Fixes**

- Check properly whether animation is active

## v1.7.10

**Features**

- Add expand root only for treeview
- Add recenterCamera method

**Fixes**

- Ensure center is shown for object far away from center

## v1.7.9

**Features**

- Add example for single edges and vertices
- Enable explode for edges and vertices

## v1.7.8

**Features**

- Add build123d examples

## v1.7.7

**Features**

- Add build123d assembly

**Fixes**

- Fix explode

## v1.7.4

**Fixes**

- Fixed resize cad view problem

## v1.7.3

**Fixes**

- Bump version of three and dev depenedencies

## v1.7.2

- Ensure one element trees are not collapsed

## v1.7.0

**Features**

- Change trihedron orientation in the orientation marker to CAD standard

## v1.6.4

**Features**

- Add support for color alpha channel

## v1.6.3

**Features**

- Introduce mode where Y is camera up

**Fixes**

- Fixed grid menu selection issue

## v1.6.2

**Fixes**

- Fixed bbox.max_dist_from_center

## v1.6.1

**Features**

- Allow resizing after view is created

**Fixes**

- Increase minimum width to 970
- Handle more button in glassMode function
- Check bbox exist before updating it

## v1.6.0

**Features**

- Added treview highlighting
- A new bounding box (AABB) algorithm

**Fixes**

- Ensure bbox update will be triggered when animation starts
- Fix remove bbox on second click in tree
- Disable jupyter cell select on shift mousedown in cad tree
- Flexible "More" menu handling
- No bounding box for isolate mode
- Center isolated objects around bbox center and look at bbox center
- Clearer help text around AABB
- Extend help for picking/hiding/isolating
- Improve center info output
