three-cad-viewer 4.1.2 → 4.2.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/Readme.md +12 -5
- package/dist/camera/camera.d.ts +14 -2
- package/dist/core/studio-manager.d.ts +91 -0
- package/dist/core/types.d.ts +260 -9
- package/dist/core/viewer-state.d.ts +28 -2
- package/dist/core/viewer.d.ts +200 -6
- package/dist/index.d.ts +7 -2
- package/dist/rendering/environment.d.ts +239 -0
- package/dist/rendering/light-detection.d.ts +44 -0
- package/dist/rendering/material-factory.d.ts +77 -2
- package/dist/rendering/material-presets.d.ts +32 -0
- package/dist/rendering/room-environment.d.ts +13 -0
- package/dist/rendering/studio-composer.d.ts +130 -0
- package/dist/rendering/studio-floor.d.ts +53 -0
- package/dist/rendering/texture-cache.d.ts +142 -0
- package/dist/rendering/triplanar.d.ts +37 -0
- package/dist/scene/animation.d.ts +1 -1
- package/dist/scene/clipping.d.ts +31 -0
- package/dist/scene/nestedgroup.d.ts +64 -27
- package/dist/scene/objectgroup.d.ts +47 -0
- package/dist/three-cad-viewer.css +339 -29
- package/dist/three-cad-viewer.esm.js +27567 -11874
- package/dist/three-cad-viewer.esm.js.map +1 -1
- package/dist/three-cad-viewer.esm.min.js +10 -4
- package/dist/three-cad-viewer.js +27486 -11787
- package/dist/three-cad-viewer.min.js +10 -4
- package/dist/ui/display.d.ts +147 -0
- package/dist/utils/decode-instances.d.ts +60 -0
- package/dist/utils/utils.d.ts +10 -0
- package/package.json +4 -2
- package/src/_version.ts +1 -1
- package/src/camera/camera.ts +27 -10
- package/src/core/studio-manager.ts +682 -0
- package/src/core/types.ts +328 -9
- package/src/core/viewer-state.ts +84 -4
- package/src/core/viewer.ts +453 -22
- package/src/index.ts +25 -1
- package/src/rendering/environment.ts +840 -0
- package/src/rendering/light-detection.ts +327 -0
- package/src/rendering/material-factory.ts +456 -2
- package/src/rendering/material-presets.ts +303 -0
- package/src/rendering/raycast.ts +2 -2
- package/src/rendering/room-environment.ts +192 -0
- package/src/rendering/studio-composer.ts +577 -0
- package/src/rendering/studio-floor.ts +108 -0
- package/src/rendering/texture-cache.ts +1020 -0
- package/src/rendering/triplanar.ts +329 -0
- package/src/scene/animation.ts +3 -2
- package/src/scene/clipping.ts +59 -0
- package/src/scene/nestedgroup.ts +399 -0
- package/src/scene/objectgroup.ts +186 -11
- package/src/scene/orientation.ts +12 -0
- package/src/scene/render-shape.ts +55 -21
- package/src/types/n8ao.d.ts +28 -0
- package/src/ui/display.ts +1032 -27
- package/src/ui/index.html +181 -44
- package/src/utils/decode-instances.ts +233 -0
- package/src/utils/utils.ts +33 -20
|
@@ -2,12 +2,13 @@ import * as THREE from "three";
|
|
|
2
2
|
import { BoundingBox } from "./bbox.js";
|
|
3
3
|
import { ObjectGroup, isObjectGroup } from "./objectgroup.js";
|
|
4
4
|
import { MaterialFactory } from "../rendering/material-factory.js";
|
|
5
|
-
import type { ZebraColorScheme, ZebraMappingMode, Shapes, ColorValue } from "../core/types";
|
|
5
|
+
import type { ZebraColorScheme, ZebraMappingMode, StudioTextureMapping, Shapes, ColorValue, MaterialAppearance, MaterialXMaterial, TextureEntry } from "../core/types";
|
|
6
6
|
interface ShapeData {
|
|
7
7
|
vertices: Float32Array | number[][];
|
|
8
8
|
normals: Float32Array | number[][];
|
|
9
9
|
triangles: Uint32Array | number[][];
|
|
10
10
|
edges?: Float32Array | number[][];
|
|
11
|
+
uvs?: Float32Array | number[];
|
|
11
12
|
}
|
|
12
13
|
interface EdgeData {
|
|
13
14
|
edges: Float32Array | number[][];
|
|
@@ -44,6 +45,7 @@ interface ShapeEntry {
|
|
|
44
45
|
width: number;
|
|
45
46
|
height: number;
|
|
46
47
|
};
|
|
48
|
+
material?: string;
|
|
47
49
|
}
|
|
48
50
|
type GroupsMap = Record<string, ObjectGroup | CompoundGroup>;
|
|
49
51
|
/**
|
|
@@ -56,32 +58,6 @@ declare class CompoundGroup extends THREE.Group {
|
|
|
56
58
|
/** Type guard property following Three.js convention */
|
|
57
59
|
readonly isCompoundGroup = true;
|
|
58
60
|
}
|
|
59
|
-
/**
|
|
60
|
-
* Manages hierarchical 3D geometry rendering from tessellated CAD data.
|
|
61
|
-
*
|
|
62
|
-
* NestedGroup is the central scene graph manager that:
|
|
63
|
-
* - Parses Shapes data into Three.js geometry
|
|
64
|
-
* - Creates ObjectGroup instances for individual shapes, edges, and vertices
|
|
65
|
-
* - Maintains a flat `groups` map for path-based access
|
|
66
|
-
* - Handles materials, transparency, and clipping planes
|
|
67
|
-
*
|
|
68
|
-
* ## Architecture
|
|
69
|
-
* ```
|
|
70
|
-
* NestedGroup (manager)
|
|
71
|
-
* └── rootGroup (THREE.Group)
|
|
72
|
-
* └── CompoundGroup (per assembly)
|
|
73
|
-
* └── ObjectGroup (per shape/edge/vertex)
|
|
74
|
-
* └── THREE.Mesh / LineSegments2
|
|
75
|
-
* ```
|
|
76
|
-
*
|
|
77
|
-
* ## Key Methods
|
|
78
|
-
* - `render()`: Build geometry from Shapes data
|
|
79
|
-
* - `setTransparent()`: Toggle transparency mode
|
|
80
|
-
* - `setClipPlanes()`: Apply clipping planes
|
|
81
|
-
* - `groups[path]`: Access ObjectGroup by path
|
|
82
|
-
*
|
|
83
|
-
* @internal - This is an internal class used by Viewer
|
|
84
|
-
*/
|
|
85
61
|
declare class NestedGroup {
|
|
86
62
|
shapes: Shapes;
|
|
87
63
|
width: number;
|
|
@@ -103,6 +79,16 @@ declare class NestedGroup {
|
|
|
103
79
|
groups: GroupsMap;
|
|
104
80
|
clipPlanes: THREE.Plane[] | null;
|
|
105
81
|
materialFactory: MaterialFactory;
|
|
82
|
+
texturesTable: Record<string, TextureEntry> | null;
|
|
83
|
+
materialsTable: Record<string, string | MaterialXMaterial | MaterialAppearance> | null;
|
|
84
|
+
resolvedMaterials: Map<string, MaterialAppearance>;
|
|
85
|
+
/** Cache for threejs-materials entries resolved from the materials table */
|
|
86
|
+
resolvedMaterialX: Map<string, MaterialXMaterial>;
|
|
87
|
+
private _textureCache;
|
|
88
|
+
private _studioMaterialCache;
|
|
89
|
+
/** Sharing keys of materials that have textures (for UV generation on cache hits) */
|
|
90
|
+
private _texturedMaterialKeys;
|
|
91
|
+
private _isStudioMode;
|
|
106
92
|
/**
|
|
107
93
|
* Create a NestedGroup for rendering CAD geometry.
|
|
108
94
|
* @param shapes - The tessellated shape data to render.
|
|
@@ -121,6 +107,26 @@ declare class NestedGroup {
|
|
|
121
107
|
* Dispose of all resources and clean up memory.
|
|
122
108
|
*/
|
|
123
109
|
dispose(): void;
|
|
110
|
+
/**
|
|
111
|
+
* Resolve a material tag to its definition.
|
|
112
|
+
*
|
|
113
|
+
* Returns either a MaterialAppearance (for builtin presets) or a
|
|
114
|
+
* MaterialXMaterial (for threejs-materials entries). The caller must check the
|
|
115
|
+
* return type to determine which factory method to use.
|
|
116
|
+
*
|
|
117
|
+
* Resolution order:
|
|
118
|
+
* 1. Check caches (resolvedMaterials / resolvedMaterialX)
|
|
119
|
+
* 2. Look up in root-level `materials` table:
|
|
120
|
+
* - string starting with "builtin:" → MATERIAL_PRESETS lookup
|
|
121
|
+
* - object with `properties` key → threejs-materials entry
|
|
122
|
+
* 3. Direct lookup in MATERIAL_PRESETS by tag name
|
|
123
|
+
* 4. No match → warning, return null
|
|
124
|
+
*
|
|
125
|
+
* @param tag - The material tag from a leaf node
|
|
126
|
+
* @param objectPath - The object path (for warning messages)
|
|
127
|
+
* @returns Resolved material definition or null if not found
|
|
128
|
+
*/
|
|
129
|
+
resolveMaterialTag(tag: string, objectPath: string): MaterialAppearance | MaterialXMaterial | null;
|
|
124
130
|
/**
|
|
125
131
|
* Check if array is nested (number[][]).
|
|
126
132
|
*/
|
|
@@ -272,6 +278,37 @@ declare class NestedGroup {
|
|
|
272
278
|
* Set the mapping mode for zebra stripes.
|
|
273
279
|
*/
|
|
274
280
|
setZebraMappingMode(flag: ZebraMappingMode): void;
|
|
281
|
+
/**
|
|
282
|
+
* Enter Studio mode: build and apply studio materials to all ObjectGroups.
|
|
283
|
+
*
|
|
284
|
+
* Material resolution per ObjectGroup:
|
|
285
|
+
* 1. Resolve the material tag via `resolveMaterialTag()`
|
|
286
|
+
* - MaterialXMaterial → `createStudioMaterialFromMaterialX`
|
|
287
|
+
* - MaterialAppearance → `createStudioMaterial` (builtin presets)
|
|
288
|
+
* - null (no tag) → fallback plastic-glossy preset tinted with CAD color
|
|
289
|
+
* 2. Cache by sharing key for reuse across objects with the same tag+color
|
|
290
|
+
* 3. Clone BackSide variant for renderback objects
|
|
291
|
+
* 4. Auto-generate box-projected UVs when textured but geometry has no UVs
|
|
292
|
+
*/
|
|
293
|
+
enterStudioMode(textureMapping?: StudioTextureMapping): Promise<string[]>;
|
|
294
|
+
/**
|
|
295
|
+
* Leave Studio mode: restore CAD materials on all ObjectGroups.
|
|
296
|
+
* Does NOT clear the material cache (allows fast re-entry).
|
|
297
|
+
*/
|
|
298
|
+
leaveStudioMode(): void;
|
|
299
|
+
/**
|
|
300
|
+
* Clear cached Studio materials so they are rebuilt on next enterStudioMode.
|
|
301
|
+
*/
|
|
302
|
+
clearStudioMaterialCache(): void;
|
|
303
|
+
/**
|
|
304
|
+
* Set edge visibility across all ObjectGroups while in Studio mode.
|
|
305
|
+
* @param visible - Whether edges should be visible
|
|
306
|
+
*/
|
|
307
|
+
setStudioShowEdges(visible: boolean): void;
|
|
308
|
+
/**
|
|
309
|
+
* Dispose all Studio mode resources (material cache + texture cache).
|
|
310
|
+
*/
|
|
311
|
+
private _disposeStudioResources;
|
|
275
312
|
}
|
|
276
313
|
/**
|
|
277
314
|
* Type guard to check if an object is a CompoundGroup instance.
|
|
@@ -69,9 +69,17 @@ declare class ObjectGroup extends THREE.Group {
|
|
|
69
69
|
vertexFocusSize: number;
|
|
70
70
|
edgeFocusWidth: number;
|
|
71
71
|
shapeGeometry?: THREE.BufferGeometry | null;
|
|
72
|
+
/** Material tag from shapes data, used for Studio mode material lookup */
|
|
73
|
+
materialTag: string;
|
|
72
74
|
minZ?: number;
|
|
73
75
|
height?: number;
|
|
74
76
|
private _zebra;
|
|
77
|
+
private _cadFrontMaterial;
|
|
78
|
+
private _cadBackMaterial;
|
|
79
|
+
private _cadOriginalColor;
|
|
80
|
+
private _cadOriginalBackColor;
|
|
81
|
+
private _isStudioMode;
|
|
82
|
+
private _cadEdgesVisible;
|
|
75
83
|
/**
|
|
76
84
|
* Create an ObjectGroup for managing a CAD object's visual representation.
|
|
77
85
|
* @param opacity - Default opacity value (0.0 to 1.0).
|
|
@@ -86,6 +94,10 @@ declare class ObjectGroup extends THREE.Group {
|
|
|
86
94
|
* Get the zebra tool, creating it on first access.
|
|
87
95
|
*/
|
|
88
96
|
get zebra(): ZebraTool;
|
|
97
|
+
/**
|
|
98
|
+
* Whether this ObjectGroup is currently in Studio mode.
|
|
99
|
+
*/
|
|
100
|
+
get isStudioMode(): boolean;
|
|
89
101
|
/**
|
|
90
102
|
* Dispose of all resources and clean up memory.
|
|
91
103
|
* Releases geometry, materials, children, and zebra tool.
|
|
@@ -252,6 +264,41 @@ declare class ObjectGroup extends THREE.Group {
|
|
|
252
264
|
* Set the mapping mode for zebra stripes.
|
|
253
265
|
*/
|
|
254
266
|
setZebraMappingMode(value: ZebraMappingMode): void;
|
|
267
|
+
/**
|
|
268
|
+
* Enter Studio mode: swap CAD materials for pre-built Studio materials.
|
|
269
|
+
*
|
|
270
|
+
* The caller (NestedGroup) is responsible for resolving material tags and
|
|
271
|
+
* building MeshPhysicalMaterial instances via MaterialFactory. ObjectGroup
|
|
272
|
+
* just receives the finished materials and performs the swap.
|
|
273
|
+
*
|
|
274
|
+
* On first call, saves the current CAD material references so they can be
|
|
275
|
+
* restored by `leaveStudioMode()`. Copies the `material.visible` flag from
|
|
276
|
+
* CAD to Studio material to preserve tree-view hide/show state. Updates
|
|
277
|
+
* `originalColor` / `originalBackColor` so highlight/unhighlight works
|
|
278
|
+
* correctly in Studio mode.
|
|
279
|
+
*
|
|
280
|
+
* @param studioFront - Studio material for front face, or null if this object has no front mesh
|
|
281
|
+
* @param studioBack - Studio material for back face, or null if back face should not be swapped
|
|
282
|
+
*/
|
|
283
|
+
enterStudioMode(studioFront: THREE.MeshPhysicalMaterial | null, studioBack: THREE.MeshPhysicalMaterial | null): void;
|
|
284
|
+
/**
|
|
285
|
+
* Leave Studio mode: restore CAD materials.
|
|
286
|
+
*
|
|
287
|
+
* Copies `material.visible` from Studio back to CAD material to preserve
|
|
288
|
+
* any visibility changes made while in Studio mode (e.g., tree-view toggle).
|
|
289
|
+
* Restores `originalColor` / `originalBackColor` to CAD material colors.
|
|
290
|
+
* Restores edge visibility to the state saved when entering Studio mode.
|
|
291
|
+
*/
|
|
292
|
+
leaveStudioMode(): void;
|
|
293
|
+
/**
|
|
294
|
+
* Toggle edge visibility while in Studio mode.
|
|
295
|
+
*
|
|
296
|
+
* Only affects edges (not vertices). Should only be called while in
|
|
297
|
+
* Studio mode; the saved CAD edge visibility is not affected.
|
|
298
|
+
*
|
|
299
|
+
* @param visible - Whether edges should be visible
|
|
300
|
+
*/
|
|
301
|
+
setStudioShowEdges(visible: boolean): void;
|
|
255
302
|
}
|
|
256
303
|
/**
|
|
257
304
|
* Type guard to check if an object is an ObjectGroup instance.
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
--tcv-font-color: #333;
|
|
5
5
|
--tcv-bg-color: #fff;
|
|
6
6
|
--tcv-bg-overlay-color: rgba(255, 255, 255, 0.7);
|
|
7
|
+
--tcv-bg-overlay-rest-color: rgba(255, 255, 255, 0.14);
|
|
7
8
|
--tcv-bg-highlight-color: #ddd;
|
|
8
9
|
--tcv-bg-pressed-color: #eee;
|
|
9
10
|
--tcv-bg-pressed-border-color: #bbb;
|
|
@@ -63,6 +64,7 @@
|
|
|
63
64
|
--tcv-font-color: #ddd;
|
|
64
65
|
--tcv-bg-color: #444;
|
|
65
66
|
--tcv-bg-overlay-color: rgba(68, 68, 68, 0.7);
|
|
67
|
+
--tcv-bg-overlay-rest-color: rgba(68, 68, 68, 0.14);
|
|
66
68
|
--tcv-bg-highlight-color: rgb(104, 104, 104);
|
|
67
69
|
--tcv-bg-pressed-color: rgb(94, 94, 94);
|
|
68
70
|
--tcv-bg-pressed-border-color: #999;
|
|
@@ -258,6 +260,7 @@ input[type="radio"] {
|
|
|
258
260
|
|
|
259
261
|
|
|
260
262
|
.tcv_cad_viewer {
|
|
263
|
+
--tcv-ui-row-gap: 8px;
|
|
261
264
|
margin: 0;
|
|
262
265
|
display: flex;
|
|
263
266
|
flex-direction: column;
|
|
@@ -292,7 +295,7 @@ input[type="radio"] {
|
|
|
292
295
|
|
|
293
296
|
.tcv_cad_tree_toggles {
|
|
294
297
|
text-align: right;
|
|
295
|
-
|
|
298
|
+
padding: 0 4px;
|
|
296
299
|
margin-bottom: 3px;
|
|
297
300
|
}
|
|
298
301
|
|
|
@@ -310,6 +313,7 @@ input[type="radio"] {
|
|
|
310
313
|
.tcv_cad_tree_glass {
|
|
311
314
|
border: none !important;
|
|
312
315
|
height: fit-content;
|
|
316
|
+
background-color: var(--tcv-bg-overlay-rest-color);
|
|
313
317
|
}
|
|
314
318
|
|
|
315
319
|
.tcv_cad_tree_glass:hover {
|
|
@@ -321,8 +325,6 @@ input[type="radio"] {
|
|
|
321
325
|
height: 146px;
|
|
322
326
|
font-family: sans-serif;
|
|
323
327
|
font-size: 12px;
|
|
324
|
-
border-style: solid;
|
|
325
|
-
border-width: 1px;
|
|
326
328
|
overflow: hidden;
|
|
327
329
|
user-select:text;
|
|
328
330
|
}
|
|
@@ -353,12 +355,38 @@ input[type="radio"] {
|
|
|
353
355
|
font-weight: bold;
|
|
354
356
|
margin-left: 4px;
|
|
355
357
|
padding-bottom: 4px;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
.tcv_toggle_tools {
|
|
361
|
+
vertical-align: middle;
|
|
362
|
+
display: inline-block;
|
|
363
|
+
width: 0.8rem;
|
|
364
|
+
cursor: pointer;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
.tcv_toggle_tools_wrapper {
|
|
368
|
+
display: none;
|
|
369
|
+
margin-left: 4px;
|
|
370
|
+
cursor: pointer;
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
.tcv_tools_label {
|
|
374
|
+
font-size: 12px;
|
|
375
|
+
font-family: sans-serif;
|
|
376
|
+
font-weight: bold;
|
|
377
|
+
margin-left: 4px;
|
|
378
|
+
padding-bottom: 4px;
|
|
356
379
|
vertical-align: middle;
|
|
357
380
|
user-select: none;
|
|
358
381
|
}
|
|
359
382
|
|
|
360
383
|
.tcv_cad_info_glass {
|
|
361
384
|
display: none;
|
|
385
|
+
border: none !important;
|
|
386
|
+
background: var(--tcv-bg-overlay-rest-color);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
.tcv_cad_info_glass:hover {
|
|
362
390
|
background: var(--tcv-bg-overlay-color);
|
|
363
391
|
}
|
|
364
392
|
|
|
@@ -474,7 +502,7 @@ th {
|
|
|
474
502
|
|
|
475
503
|
.tcv_cad_animation {
|
|
476
504
|
height: 36px;
|
|
477
|
-
background-color: var(--tcv-bg-overlay-color);
|
|
505
|
+
background-color: var(--tcv-bg-overlay-rest-color);
|
|
478
506
|
border: none;
|
|
479
507
|
margin: 0;
|
|
480
508
|
padding: 0px;
|
|
@@ -484,9 +512,13 @@ th {
|
|
|
484
512
|
z-index: 100;
|
|
485
513
|
}
|
|
486
514
|
|
|
515
|
+
.tcv_cad_animation:hover {
|
|
516
|
+
background-color: var(--tcv-bg-overlay-color);
|
|
517
|
+
}
|
|
518
|
+
|
|
487
519
|
.tcv_cad_zscale {
|
|
488
520
|
height: 36px;
|
|
489
|
-
background-color: var(--tcv-bg-overlay-color);
|
|
521
|
+
background-color: var(--tcv-bg-overlay-rest-color);
|
|
490
522
|
border: none;
|
|
491
523
|
margin: 0;
|
|
492
524
|
padding: 0px;
|
|
@@ -497,6 +529,10 @@ th {
|
|
|
497
529
|
align-content: center;
|
|
498
530
|
}
|
|
499
531
|
|
|
532
|
+
.tcv_cad_zscale:hover {
|
|
533
|
+
background-color: var(--tcv-bg-overlay-color);
|
|
534
|
+
}
|
|
535
|
+
|
|
500
536
|
.tcv_cad_tools {
|
|
501
537
|
height: 38px;
|
|
502
538
|
background-color: var(--tcv-bg-overlay-color);
|
|
@@ -552,7 +588,7 @@ th {
|
|
|
552
588
|
}
|
|
553
589
|
|
|
554
590
|
.tcv_box_content {
|
|
555
|
-
overflow:
|
|
591
|
+
overflow: auto;
|
|
556
592
|
height: 100%;
|
|
557
593
|
/* margin: 0px 0px 0px 4px; */
|
|
558
594
|
padding-top: 2px;
|
|
@@ -658,7 +694,10 @@ input[type="button"] {
|
|
|
658
694
|
/* margin-bottom: 6px; */
|
|
659
695
|
background-color: transparent;
|
|
660
696
|
color: var(--tcv-font-color);
|
|
661
|
-
font-size:
|
|
697
|
+
font-size: 12px;
|
|
698
|
+
overflow: hidden;
|
|
699
|
+
text-overflow: ellipsis;
|
|
700
|
+
white-space: nowrap;
|
|
662
701
|
}
|
|
663
702
|
|
|
664
703
|
.tcv_tab:hover {
|
|
@@ -776,47 +815,60 @@ input[type="button"] {
|
|
|
776
815
|
}
|
|
777
816
|
|
|
778
817
|
.tcv_slider_group {
|
|
779
|
-
margin-bottom:
|
|
818
|
+
margin-bottom: var(--tcv-ui-row-gap);
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
.tcv_slider_group > div {
|
|
822
|
+
display: flex;
|
|
823
|
+
align-items: center;
|
|
824
|
+
gap: 4px;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
.tcv_slider_group > div:first-child {
|
|
828
|
+
align-items: flex-end;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
.tcv_slider_group .tcv_label {
|
|
832
|
+
margin-bottom: 0;
|
|
780
833
|
}
|
|
781
834
|
|
|
782
835
|
.tcv_material_ambientlight {
|
|
783
836
|
margin-top: 4px;
|
|
784
837
|
}
|
|
785
838
|
|
|
786
|
-
.
|
|
787
|
-
|
|
788
|
-
overflow: hidden;
|
|
839
|
+
.tcv_cad_material_container .tcv_studio_slider_group {
|
|
840
|
+
width: 60%;
|
|
789
841
|
}
|
|
790
842
|
|
|
791
|
-
.
|
|
843
|
+
.tcv_cad_clip_container,
|
|
844
|
+
.tcv_cad_material_container,
|
|
845
|
+
.tcv_cad_zebra_container,
|
|
846
|
+
.tcv_cad_studio_container {
|
|
792
847
|
overflow: hidden;
|
|
848
|
+
padding: 0 4px;
|
|
793
849
|
}
|
|
794
850
|
|
|
795
|
-
.
|
|
796
|
-
|
|
851
|
+
.tcv_cad_clip_container .tcv_label,
|
|
852
|
+
.tcv_cad_material_container .tcv_label,
|
|
853
|
+
.tcv_cad_zebra_container .tcv_label,
|
|
854
|
+
.tcv_cad_studio_container .tcv_label {
|
|
855
|
+
margin-left: 0;
|
|
856
|
+
margin-right: 0;
|
|
797
857
|
}
|
|
798
858
|
|
|
799
|
-
.tcv_zebra_stripe_count {
|
|
800
|
-
margin-top: 20px;
|
|
801
|
-
}
|
|
802
859
|
|
|
803
860
|
.tcv_zebra_radio {
|
|
804
|
-
margin-
|
|
805
|
-
margin-bottom: 4px;
|
|
861
|
+
margin-bottom: var(--tcv-ui-row-gap);
|
|
806
862
|
margin-left: -3px;
|
|
807
863
|
}
|
|
808
864
|
|
|
809
|
-
.tcv_zebra_mapping {
|
|
810
|
-
margin-top: 8px;
|
|
811
|
-
margin-bottom: 4px;
|
|
812
|
-
}
|
|
813
|
-
|
|
814
865
|
.tcv_clip_checks {
|
|
815
|
-
margin-top:
|
|
866
|
+
margin-top: var(--tcv-ui-row-gap);
|
|
816
867
|
}
|
|
817
868
|
|
|
818
869
|
.tcv_clip_input {
|
|
819
|
-
width:
|
|
870
|
+
width: 36px;
|
|
871
|
+
flex-shrink: 0;
|
|
820
872
|
border: 1px solid #d3d3d3;
|
|
821
873
|
background-color: var(--tcv-bg-overlay-color);
|
|
822
874
|
color: var(--tcv-font-color);
|
|
@@ -825,10 +877,11 @@ input[type="button"] {
|
|
|
825
877
|
.tcv_clip_slider {
|
|
826
878
|
-webkit-appearance: none;
|
|
827
879
|
appearance: none;
|
|
828
|
-
|
|
880
|
+
flex: 1;
|
|
881
|
+
min-width: 0;
|
|
829
882
|
height: 5px;
|
|
830
883
|
border-radius: 2px;
|
|
831
|
-
background: #
|
|
884
|
+
background: #a0a0a0;
|
|
832
885
|
outline: none;
|
|
833
886
|
opacity: 0.7;
|
|
834
887
|
-webkit-transition: 0.2s;
|
|
@@ -860,7 +913,6 @@ input[type="button"] {
|
|
|
860
913
|
}
|
|
861
914
|
|
|
862
915
|
.tcv_lbl_norm_plane1 {
|
|
863
|
-
margin-top: 20px;
|
|
864
916
|
color: var(--tcv-x-color);
|
|
865
917
|
}
|
|
866
918
|
|
|
@@ -955,6 +1007,126 @@ input[type="button"] {
|
|
|
955
1007
|
font-size: 12px;
|
|
956
1008
|
}
|
|
957
1009
|
|
|
1010
|
+
.tcv_studio_select {
|
|
1011
|
+
font-family: sans-serif;
|
|
1012
|
+
font-size: 13px;
|
|
1013
|
+
padding: 2px 4px;
|
|
1014
|
+
border: 1px solid #d3d3d3;
|
|
1015
|
+
border-radius: 3px;
|
|
1016
|
+
background-color: var(--tcv-bg-overlay-color);
|
|
1017
|
+
color: var(--tcv-font-color);
|
|
1018
|
+
width: 55%;
|
|
1019
|
+
flex-shrink: 0;
|
|
1020
|
+
margin-left: auto;
|
|
1021
|
+
outline: none;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
.tcv_studio_texture_mapping {
|
|
1025
|
+
width: auto;
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
.tcv_studio_select:hover {
|
|
1029
|
+
opacity: 1;
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
.tcv_studio_select option {
|
|
1033
|
+
background-color: var(--tcv-bg-color);
|
|
1034
|
+
color: var(--tcv-font-color);
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
.tcv_studio_row {
|
|
1038
|
+
display: flex;
|
|
1039
|
+
align-items: center;
|
|
1040
|
+
justify-content: space-between;
|
|
1041
|
+
margin-bottom: var(--tcv-ui-row-gap);
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
.tcv_studio_row > .tcv_label {
|
|
1045
|
+
margin-left: 0;
|
|
1046
|
+
padding-bottom: 0;
|
|
1047
|
+
flex-shrink: 0;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
.tcv_studio_slider_group {
|
|
1051
|
+
display: flex;
|
|
1052
|
+
align-items: center;
|
|
1053
|
+
width: 55%;
|
|
1054
|
+
flex-shrink: 0;
|
|
1055
|
+
margin-left: auto;
|
|
1056
|
+
gap: 4px;
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
.tcv_studio_slider_group > .tcv_clip_slider {
|
|
1060
|
+
flex: 1;
|
|
1061
|
+
width: auto;
|
|
1062
|
+
min-width: 0;
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
.tcv_studio_slider_group > .tcv_clip_input {
|
|
1066
|
+
width: 36px;
|
|
1067
|
+
flex-shrink: 0;
|
|
1068
|
+
}
|
|
1069
|
+
|
|
1070
|
+
.tcv_studio_checks {
|
|
1071
|
+
display: flex;
|
|
1072
|
+
gap: 16px;
|
|
1073
|
+
margin-top: var(--tcv-ui-row-gap);
|
|
1074
|
+
margin-bottom: var(--tcv-ui-row-gap);
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
.tcv_studio_4k_row {
|
|
1078
|
+
/* Align checkbox with the slider/dropdown column (45% label + 55% control) */
|
|
1079
|
+
margin-left: 45%;
|
|
1080
|
+
gap: 4px;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
.tcv_studio_group_spacer {
|
|
1084
|
+
height: calc(var(--tcv-ui-row-gap) * 0.6);
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
.tcv_studio_info {
|
|
1088
|
+
font-size: 12px;
|
|
1089
|
+
margin-top: 8px;
|
|
1090
|
+
color: var(--tcv-font-color);
|
|
1091
|
+
opacity: 0.7;
|
|
1092
|
+
font-style: italic;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
.tcv_warning_banner {
|
|
1096
|
+
position: absolute;
|
|
1097
|
+
top: 4px;
|
|
1098
|
+
left: 50%;
|
|
1099
|
+
transform: translateX(-50%);
|
|
1100
|
+
z-index: 100;
|
|
1101
|
+
background: #e8a735;
|
|
1102
|
+
color: #000;
|
|
1103
|
+
padding: 4px 12px;
|
|
1104
|
+
border-radius: 4px;
|
|
1105
|
+
font-size: 12px;
|
|
1106
|
+
line-height: 1.4;
|
|
1107
|
+
max-width: 80%;
|
|
1108
|
+
text-align: center;
|
|
1109
|
+
pointer-events: auto;
|
|
1110
|
+
box-shadow: 0 1px 4px rgba(0,0,0,0.3);
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
.tcv_studio_spinner {
|
|
1114
|
+
display: none;
|
|
1115
|
+
width: 8px;
|
|
1116
|
+
height: 8px;
|
|
1117
|
+
border: 2px solid var(--tcv-font-color);
|
|
1118
|
+
border-top-color: transparent;
|
|
1119
|
+
border-radius: 50%;
|
|
1120
|
+
animation: tcv_spin 0.7s linear infinite;
|
|
1121
|
+
opacity: 0.6;
|
|
1122
|
+
float: left;
|
|
1123
|
+
margin-top: 5px;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
@keyframes tcv_spin {
|
|
1127
|
+
to { transform: rotate(360deg); }
|
|
1128
|
+
}
|
|
1129
|
+
|
|
958
1130
|
.tcv_filter_menu {
|
|
959
1131
|
position: relative;
|
|
960
1132
|
}
|
|
@@ -1253,4 +1425,142 @@ input[type="button"] {
|
|
|
1253
1425
|
|
|
1254
1426
|
.tcv_angle_val {
|
|
1255
1427
|
text-align: right;
|
|
1428
|
+
}
|
|
1429
|
+
|
|
1430
|
+
/* MATERIAL EDITOR PANEL */
|
|
1431
|
+
|
|
1432
|
+
.tcv_mat_editor {
|
|
1433
|
+
position: absolute;
|
|
1434
|
+
top: 8px;
|
|
1435
|
+
right: 8px;
|
|
1436
|
+
width: 250px;
|
|
1437
|
+
max-height: calc(100% - 16px);
|
|
1438
|
+
display: flex;
|
|
1439
|
+
flex-direction: column;
|
|
1440
|
+
background-color: var(--tcv-bg-overlay-rest-color);
|
|
1441
|
+
border: 1px solid lightgray;
|
|
1442
|
+
border-radius: 6px;
|
|
1443
|
+
font-family: sans-serif;
|
|
1444
|
+
font-size: 13px;
|
|
1445
|
+
color: var(--tcv-font-color);
|
|
1446
|
+
user-select: none;
|
|
1447
|
+
z-index: 10;
|
|
1448
|
+
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
.tcv_mat_editor:hover {
|
|
1452
|
+
background-color: var(--tcv-bg-overlay-color);
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
.tcv_mat_editor_titlebar {
|
|
1456
|
+
display: flex;
|
|
1457
|
+
align-items: center;
|
|
1458
|
+
justify-content: space-between;
|
|
1459
|
+
padding: 4px 6px;
|
|
1460
|
+
border-bottom: 1px solid lightgray;
|
|
1461
|
+
background-color: var(--tcv-bg-overlay-color);
|
|
1462
|
+
border-radius: 5px 5px 0 0;
|
|
1463
|
+
flex-shrink: 0;
|
|
1464
|
+
cursor: move;
|
|
1465
|
+
}
|
|
1466
|
+
|
|
1467
|
+
.tcv_mat_editor_titlebar_btns {
|
|
1468
|
+
display: flex;
|
|
1469
|
+
gap: 2px;
|
|
1470
|
+
flex-shrink: 0;
|
|
1471
|
+
}
|
|
1472
|
+
|
|
1473
|
+
.tcv_mat_editor_title {
|
|
1474
|
+
font-weight: bold;
|
|
1475
|
+
font-size: 12px;
|
|
1476
|
+
}
|
|
1477
|
+
|
|
1478
|
+
.tcv_mat_editor_close {
|
|
1479
|
+
cursor: pointer;
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
.tcv_mat_editor_path {
|
|
1483
|
+
padding: 3px 6px;
|
|
1484
|
+
font-size: 11px;
|
|
1485
|
+
color: var(--tcv-font-color);
|
|
1486
|
+
opacity: 0.7;
|
|
1487
|
+
border-bottom: 1px solid lightgray;
|
|
1488
|
+
white-space: nowrap;
|
|
1489
|
+
overflow: hidden;
|
|
1490
|
+
text-overflow: ellipsis;
|
|
1491
|
+
flex-shrink: 0;
|
|
1492
|
+
user-select: text;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
.tcv_mat_editor_content {
|
|
1496
|
+
padding: 6px;
|
|
1497
|
+
overflow-y: auto;
|
|
1498
|
+
flex: 1;
|
|
1499
|
+
min-height: 0;
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
.tcv_mat_editor_section {
|
|
1503
|
+
font-size: 11px;
|
|
1504
|
+
font-weight: bold;
|
|
1505
|
+
text-transform: uppercase;
|
|
1506
|
+
letter-spacing: 0.5px;
|
|
1507
|
+
color: var(--tcv-font-color);
|
|
1508
|
+
opacity: 0.6;
|
|
1509
|
+
margin-top: 8px;
|
|
1510
|
+
margin-bottom: 4px;
|
|
1511
|
+
padding-bottom: 2px;
|
|
1512
|
+
border-bottom: 1px solid var(--tcv-bg-overlay-color);
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
.tcv_mat_editor_section:first-child {
|
|
1516
|
+
margin-top: 0;
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
.tcv_mat_editor_row {
|
|
1520
|
+
display: flex;
|
|
1521
|
+
align-items: center;
|
|
1522
|
+
justify-content: space-between;
|
|
1523
|
+
margin-bottom: 5px;
|
|
1524
|
+
}
|
|
1525
|
+
|
|
1526
|
+
.tcv_mat_editor_label {
|
|
1527
|
+
font-size: 12px;
|
|
1528
|
+
color: var(--tcv-font-color);
|
|
1529
|
+
flex-shrink: 0;
|
|
1530
|
+
max-width: 45%;
|
|
1531
|
+
overflow: hidden;
|
|
1532
|
+
text-overflow: ellipsis;
|
|
1533
|
+
white-space: nowrap;
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
/* Reuse tcv_studio_slider_group layout for slider + value */
|
|
1537
|
+
.tcv_mat_editor_slider_group {
|
|
1538
|
+
display: flex;
|
|
1539
|
+
align-items: center;
|
|
1540
|
+
width: 52%;
|
|
1541
|
+
flex-shrink: 0;
|
|
1542
|
+
margin-left: auto;
|
|
1543
|
+
gap: 4px;
|
|
1544
|
+
}
|
|
1545
|
+
|
|
1546
|
+
/* Sliders reuse tcv_clip_slider class (set in JS) */
|
|
1547
|
+
.tcv_mat_editor_slider_group > .tcv_clip_slider {
|
|
1548
|
+
flex: 1;
|
|
1549
|
+
width: auto;
|
|
1550
|
+
min-width: 0;
|
|
1551
|
+
}
|
|
1552
|
+
|
|
1553
|
+
/* Value inputs reuse tcv_clip_input class (set in JS) */
|
|
1554
|
+
.tcv_mat_editor_slider_group > .tcv_clip_input {
|
|
1555
|
+
width: 36px;
|
|
1556
|
+
flex-shrink: 0;
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
.tcv_mat_editor_changed {
|
|
1560
|
+
color: #cc3333 !important;
|
|
1561
|
+
}
|
|
1562
|
+
|
|
1563
|
+
.tcv_mat_editor_toggle.tcv_active {
|
|
1564
|
+
background-color: var(--tcv-bg-overlay-color);
|
|
1565
|
+
border-radius: 6px;
|
|
1256
1566
|
}
|