three-cad-viewer 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "three-cad-viewer",
3
- "version": "4.2.0",
3
+ "version": "4.3.0",
4
4
  "type": "module",
5
5
  "description": "WebGL-based CAD viewer built on Three.js with clipping planes, measurement tools, and tree navigation",
6
6
  "repository": {
package/src/_version.ts CHANGED
@@ -1 +1 @@
1
- export const version: string = "4.2.0";
1
+ export const version: string = "4.3.0";
@@ -69,11 +69,6 @@ class StudioManager {
69
69
  private _composer: StudioComposer | null = null;
70
70
  private _active: boolean = false;
71
71
  private _savedClippingState: ClippingState | null = null;
72
- private _savedViewState: {
73
- ortho: boolean;
74
- axes: boolean;
75
- grid: [boolean, boolean, boolean];
76
- } | null = null;
77
72
  private _shadowLights: THREE.DirectionalLight[] = [];
78
73
  private _ctx: StudioManagerContext;
79
74
 
@@ -162,15 +157,7 @@ class StudioManager {
162
157
  clipping.planeHelpers.visible = false;
163
158
  }
164
159
 
165
- // 2. Save view state (applied after env is loaded to avoid
166
- // subscriber side-effects before the texture is ready)
167
- this._savedViewState = {
168
- ortho: state.get("ortho"),
169
- axes: state.get("axes"),
170
- grid: [...state.get("grid")] as [boolean, boolean, boolean],
171
- };
172
-
173
- // 3. Build/swap studio materials (async due to textures)
160
+ // 2. Build/swap studio materials (async due to textures)
174
161
  const nestedGroup = this._ctx.getNestedGroup();
175
162
  const unresolvedTags = await nestedGroup.enterStudioMode(state.get("studioTextureMapping"));
176
163
  if (!this._active) return;
@@ -182,12 +169,12 @@ class StudioManager {
182
169
  );
183
170
  }
184
171
 
185
- // 4. Load environment map
172
+ // 3. Load environment map
186
173
  const envName = state.get("studioEnvironment");
187
174
  await this.envManager.loadEnvironment(envName, renderer);
188
175
  if (!this._active) return;
189
176
 
190
- // 5. Apply ALL rendering changes atomically
177
+ // 4. Apply ALL rendering changes atomically
191
178
  const scene = this._ctx.getScene();
192
179
  const camera = this._ctx.getCamera();
193
180
  this.envManager.apply(
@@ -199,12 +186,6 @@ class StudioManager {
199
186
  state.get("studioEnvRotation"),
200
187
  );
201
188
 
202
- // 6. Override camera, axes, grid (after env is loaded so
203
- // ortho subscriber doesn't trigger reapplyEnv with null texture)
204
- if (this._savedViewState?.ortho) this._ctx.setOrtho(false);
205
- if (this._savedViewState?.axes) this._ctx.setAxes(false);
206
- if (state.get("grid").some(Boolean)) this._ctx.setGrids([false, false, false]);
207
-
208
189
  // Lighting: disable CAD lights; environment IBL provides all illumination
209
190
  this._ctx.getAmbientLight().intensity = 0;
210
191
  this._ctx.getDirectLight().intensity = 0;
@@ -292,20 +273,9 @@ class StudioManager {
292
273
  this._savedClippingState = null;
293
274
  }
294
275
 
295
- // 7. Clear active flag (before restoring view state, so subscribers don't re-apply studio)
276
+ // 7. Clear active flag; edges restored by ObjectGroup.leaveStudioMode()
296
277
  this._active = false;
297
278
 
298
- // 8. Restore camera, axes, grid
299
- if (this._savedViewState) {
300
- const { ortho, axes, grid } = this._savedViewState;
301
- if (ortho) this._ctx.setOrtho(true);
302
- if (axes) this._ctx.setAxes(true);
303
- if (grid.some(Boolean)) this._ctx.setGrids(grid);
304
- this._savedViewState = null;
305
- }
306
-
307
- // 9. Edges restored by ObjectGroup.leaveStudioMode()
308
-
309
279
  this._ctx.update(true, false);
310
280
  };
311
281
 
package/src/core/types.ts CHANGED
@@ -490,8 +490,7 @@ export type StateKey = keyof ViewerStateShape;
490
490
  * which the shader skips at near-zero cost.
491
491
  *
492
492
  * This is a data-format interface (describes JSON input), not a Three.js material.
493
- * Texture string fields reference either a key in the root-level `textures` table,
494
- * a data URI, or a URL resolved against the HTML page.
493
+ * Texture string fields are either a data URI or a URL resolved against the HTML page.
495
494
  */
496
495
  export interface MaterialAppearance {
497
496
  /** Display name */
@@ -649,28 +648,6 @@ export function isMaterialXMaterial(m: unknown): m is MaterialXMaterial {
649
648
  return typeof m === "object" && m !== null && "properties" in m;
650
649
  }
651
650
 
652
- // =============================================================================
653
- // Texture Entry (Studio Mode)
654
- // =============================================================================
655
-
656
- /**
657
- * Entry in the root-level `textures` table.
658
- *
659
- * Each entry is either embedded (base64-encoded image data) or a URL reference
660
- * loaded on demand. At least one of `data`+`format` or `url` must be provided.
661
- * An empty TextureEntry is invalid and will be ignored at runtime.
662
- * Multiple builtin preset texture fields can reference the same key for
663
- * deduplication. threejs-materials carry their own textures as inline data URIs.
664
- */
665
- export interface TextureEntry {
666
- /** Base64-encoded image data (for embedded textures) */
667
- data?: string;
668
- /** Image format, e.g., "png", "jpg", "webp" (required when data is provided) */
669
- format?: string;
670
- /** URL to load the texture from (for URL-referenced textures) */
671
- url?: string;
672
- }
673
-
674
651
  // =============================================================================
675
652
  // Studio Options
676
653
  // =============================================================================
@@ -881,9 +858,6 @@ export interface Shapes {
881
858
  * - MaterialAppearance: preset with overrides (e.g., { builtin: "acrylic-clear", color: "#55a0e3" })
882
859
  */
883
860
  materials?: Record<string, string | MaterialXMaterial | MaterialAppearance> | undefined;
884
- /** Shared texture table for builtin preset materials (root node).
885
- * threejs-materials carry their own textures inline. */
886
- textures?: Record<string, TextureEntry> | undefined;
887
861
  }
888
862
 
889
863
  // =============================================================================
package/src/index.ts CHANGED
@@ -133,7 +133,6 @@ export type { ColoredMaterial } from "./core/types.js";
133
133
  export type {
134
134
  MaterialAppearance,
135
135
  MaterialXMaterial,
136
- TextureEntry,
137
136
  StudioOptions,
138
137
  StudioBackground,
139
138
  StudioModeOptions,
@@ -540,6 +540,8 @@ class MaterialFactory {
540
540
  if (COLOR_ARRAY_KEYS.has(key) && Array.isArray(prop.value)) {
541
541
  const [r, g, b] = prop.value as number[];
542
542
  matOptions[key] = new THREE.Color(r, g, b);
543
+ } else if ((key === "normalScale" || key === "clearcoatNormalScale") && Array.isArray(prop.value)) {
544
+ matOptions[key] = new THREE.Vector2(prop.value[0], prop.value[1]);
543
545
  } else if (key === "iridescenceThicknessRange" && Array.isArray(prop.value)) {
544
546
  matOptions[key] = prop.value;
545
547
  } else {
@@ -253,20 +253,6 @@ export const MATERIAL_PRESETS: Record<string, MaterialAppearance> = {
253
253
  // Natural / Other
254
254
  // ---------------------------------------------------------------------------
255
255
 
256
- "wood-light": {
257
- name: "Wood (Light)",
258
- color: [0.89, 0.8, 0.68, 1],
259
- metalness: 0.0,
260
- roughness: 0.6,
261
- },
262
-
263
- "wood-dark": {
264
- name: "Wood (Dark)",
265
- color: [0.63, 0.51, 0.38, 1],
266
- metalness: 0.0,
267
- roughness: 0.55,
268
- },
269
-
270
256
  "ceramic-white": {
271
257
  name: "Ceramic (White)",
272
258
  color: [0.98, 0.98, 0.97, 1],